Separate config structs from internal structs

This commit is contained in:
2022-05-26 16:30:11 +02:00
parent 10e02c20a1
commit 6ef759a14e
7 changed files with 217 additions and 115 deletions

View File

@@ -3,27 +3,32 @@ use std::process;
use crate::output::*;
use super::repo::RepoConfig;
use std::path::Path;
use crate::get_token_from_command;
use crate::{get_token_from_command, Remote, Repo, Tree};
use crate::provider;
use crate::provider::Filter;
use crate::provider::Provider;
pub type RemoteProvider = crate::provider::RemoteProvider;
pub type RemoteType = crate::repo::RemoteType;
fn worktree_setup_default() -> bool {
false
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Config {
ConfigTree(ConfigTree),
ConfigTrees(ConfigTrees),
ConfigProvider(ConfigProvider),
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigTree {
pub trees: Trees,
pub struct ConfigTrees {
pub trees: Vec<ConfigTree>,
}
#[derive(Debug, Serialize, Deserialize)]
@@ -50,30 +55,100 @@ pub struct ConfigProvider {
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Trees(Vec<Tree>);
#[serde(deny_unknown_fields)]
pub struct RemoteConfig {
pub name: String,
pub url: String,
#[serde(rename = "type")]
pub remote_type: RemoteType,
}
impl Trees {
impl RemoteConfig {
pub fn from_remote(remote: Remote) -> Self {
Self {
name: remote.name,
url: remote.url,
remote_type: remote.remote_type,
}
}
pub fn into_remote(self) -> Remote {
Remote {
name: self.name,
url: self.url,
remote_type: self.remote_type,
}
}
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct RepoConfig {
pub name: String,
#[serde(default = "worktree_setup_default")]
pub worktree_setup: bool,
pub remotes: Option<Vec<RemoteConfig>>,
}
impl RepoConfig {
pub fn from_repo(repo: Repo) -> Self {
Self {
name: repo.name,
worktree_setup: repo.worktree_setup,
remotes: repo
.remotes
.map(|remotes| remotes.into_iter().map(RemoteConfig::from_remote).collect()),
}
}
pub fn into_repo(self) -> Repo {
Repo {
name: self.name,
worktree_setup: self.worktree_setup,
remotes: self.remotes.map(|remotes| {
remotes
.into_iter()
.map(|remote| remote.into_remote())
.collect()
}),
}
}
}
impl ConfigTrees {
pub fn to_config(self) -> Config {
Config::ConfigTree(ConfigTree { trees: self })
Config::ConfigTrees(self)
}
pub fn from_vec(vec: Vec<Tree>) -> Self {
Trees(vec)
pub fn from_vec(vec: Vec<ConfigTree>) -> Self {
ConfigTrees { trees: vec }
}
pub fn as_vec(self) -> Vec<Tree> {
self.0
pub fn from_trees(vec: Vec<Tree>) -> Self {
ConfigTrees {
trees: vec.into_iter().map(ConfigTree::from_tree).collect(),
}
}
pub fn as_vec_ref(&self) -> &Vec<Tree> {
self.0.as_ref()
pub fn trees(self) -> Vec<ConfigTree> {
self.trees
}
pub fn trees_mut(&mut self) -> &mut Vec<ConfigTree> {
&mut self.trees
}
pub fn trees_ref(&self) -> &Vec<ConfigTree> {
self.trees.as_ref()
}
}
impl Config {
pub fn trees(self) -> Result<Trees, String> {
pub fn trees(self) -> Result<Vec<ConfigTree>, String> {
match self {
Config::ConfigTree(config) => Ok(config.trees),
Config::ConfigTrees(config) => Ok(config.trees),
Config::ConfigProvider(config) => {
let token = match get_token_from_command(&config.token_command) {
Ok(token) => token,
@@ -129,27 +204,29 @@ impl Config {
let mut trees = vec![];
for (namespace, namespace_repos) in repos {
let tree = Tree {
let repos = namespace_repos
.into_iter()
.map(RepoConfig::from_repo)
.collect();
let tree = ConfigTree {
root: crate::path_as_string(&Path::new(&config.root).join(namespace)),
repos: Some(namespace_repos),
repos: Some(repos),
};
trees.push(tree);
}
Ok(Trees(trees))
Ok(trees)
}
}
}
pub fn from_trees(trees: Vec<Tree>) -> Self {
Config::ConfigTree(ConfigTree {
trees: Trees::from_vec(trees),
})
pub fn from_trees(trees: Vec<ConfigTree>) -> Self {
Config::ConfigTrees(ConfigTrees { trees })
}
pub fn normalize(&mut self) {
if let Config::ConfigTree(config) = self {
if let Config::ConfigTrees(config) = self {
let home = super::env_home().display().to_string();
for tree in &mut config.trees.0 {
for tree in &mut config.trees_mut().iter_mut() {
if tree.root.starts_with(&home) {
// The tilde is not handled differently, it's just a normal path component for `Path`.
// Therefore we can treat it like that during **output**.
@@ -181,11 +258,27 @@ impl Config {
#[derive(Debug, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Tree {
pub struct ConfigTree {
pub root: String,
pub repos: Option<Vec<RepoConfig>>,
}
impl ConfigTree {
pub fn from_repos(root: String, repos: Vec<Repo>) -> Self {
Self {
root,
repos: Some(repos.into_iter().map(RepoConfig::from_repo).collect()),
}
}
pub fn from_tree(tree: Tree) -> Self {
Self {
root: tree.root,
repos: Some(tree.repos.into_iter().map(RepoConfig::from_repo).collect()),
}
}
}
pub fn read_config<'a, T>(path: &str) -> Result<T, String>
where
T: for<'de> serde::Deserialize<'de>,