Give repos a namespace to allow subdirectories
This commit is contained in:
@@ -5,7 +5,7 @@ use crate::output::*;
|
|||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use crate::{get_token_from_command, Remote, Repo, Tree};
|
use crate::{get_token_from_command, path_as_string, Remote, Repo, Tree};
|
||||||
|
|
||||||
use crate::provider;
|
use crate::provider;
|
||||||
use crate::provider::Filter;
|
use crate::provider::Filter;
|
||||||
@@ -104,8 +104,15 @@ impl RepoConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_repo(self) -> Repo {
|
pub fn into_repo(self) -> Repo {
|
||||||
|
let (namespace, name) = if let Some((namespace, name)) = self.name.rsplit_once('/') {
|
||||||
|
(Some(namespace.to_string()), name.to_string())
|
||||||
|
} else {
|
||||||
|
(None, self.name)
|
||||||
|
};
|
||||||
|
|
||||||
Repo {
|
Repo {
|
||||||
name: self.name,
|
name,
|
||||||
|
namespace,
|
||||||
worktree_setup: self.worktree_setup,
|
worktree_setup: self.worktree_setup,
|
||||||
remotes: self.remotes.map(|remotes| {
|
remotes: self.remotes.map(|remotes| {
|
||||||
remotes
|
remotes
|
||||||
@@ -209,7 +216,11 @@ impl Config {
|
|||||||
.map(RepoConfig::from_repo)
|
.map(RepoConfig::from_repo)
|
||||||
.collect();
|
.collect();
|
||||||
let tree = ConfigTree {
|
let tree = ConfigTree {
|
||||||
root: crate::path_as_string(&Path::new(&config.root).join(namespace)),
|
root: if let Some(namespace) = namespace {
|
||||||
|
path_as_string(&Path::new(&config.root).join(namespace))
|
||||||
|
} else {
|
||||||
|
path_as_string(Path::new(&config.root))
|
||||||
|
},
|
||||||
repos: Some(repos),
|
repos: Some(repos),
|
||||||
};
|
};
|
||||||
trees.push(tree);
|
trees.push(tree);
|
||||||
|
|||||||
@@ -82,10 +82,13 @@ fn main() {
|
|||||||
let mut trees: Vec<config::ConfigTree> = vec![];
|
let mut trees: Vec<config::ConfigTree> = vec![];
|
||||||
|
|
||||||
for (namespace, repolist) in repos {
|
for (namespace, repolist) in repos {
|
||||||
let tree = config::ConfigTree::from_repos(
|
let root = if let Some(namespace) = namespace {
|
||||||
Path::new(&args.root).join(namespace).display().to_string(),
|
path_as_string(&Path::new(&args.root).join(namespace))
|
||||||
repolist,
|
} else {
|
||||||
);
|
path_as_string(Path::new(&args.root))
|
||||||
|
};
|
||||||
|
|
||||||
|
let tree = config::ConfigTree::from_repos(root, repolist);
|
||||||
trees.push(tree);
|
trees.push(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,7 +313,11 @@ fn main() {
|
|||||||
|
|
||||||
for (namespace, namespace_repos) in repos {
|
for (namespace, namespace_repos) in repos {
|
||||||
let tree = config::ConfigTree {
|
let tree = config::ConfigTree {
|
||||||
root: path_as_string(&Path::new(&config.root).join(namespace)),
|
root: if let Some(namespace) = namespace {
|
||||||
|
path_as_string(&Path::new(&config.root).join(namespace))
|
||||||
|
} else {
|
||||||
|
path_as_string(Path::new(&config.root))
|
||||||
|
},
|
||||||
repos: Some(
|
repos: Some(
|
||||||
namespace_repos
|
namespace_repos
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -402,7 +409,11 @@ fn main() {
|
|||||||
|
|
||||||
for (namespace, repolist) in repos {
|
for (namespace, repolist) in repos {
|
||||||
let tree = config::ConfigTree {
|
let tree = config::ConfigTree {
|
||||||
root: Path::new(&args.root).join(namespace).display().to_string(),
|
root: if let Some(namespace) = namespace {
|
||||||
|
path_as_string(&Path::new(&args.root).join(namespace))
|
||||||
|
} else {
|
||||||
|
path_as_string(Path::new(&args.root))
|
||||||
|
},
|
||||||
repos: Some(
|
repos: Some(
|
||||||
repolist
|
repolist
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|||||||
30
src/lib.rs
30
src/lib.rs
@@ -147,7 +147,7 @@ pub fn get_token_from_command(command: &str) -> Result<String, String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn sync_repo(root_path: &Path, repo: &Repo, init_worktree: bool) -> Result<(), String> {
|
fn sync_repo(root_path: &Path, repo: &Repo, init_worktree: bool) -> Result<(), String> {
|
||||||
let repo_path = root_path.join(&repo.name);
|
let repo_path = root_path.join(&repo.fullname());
|
||||||
let actual_git_directory = get_actual_git_directory(&repo_path, repo.worktree_setup);
|
let actual_git_directory = get_actual_git_directory(&repo_path, repo.worktree_setup);
|
||||||
|
|
||||||
let mut newly_created = false;
|
let mut newly_created = false;
|
||||||
@@ -460,17 +460,33 @@ fn find_repos(root: &Path) -> Result<Option<(Vec<Repo>, Vec<String>, bool)>, Str
|
|||||||
}
|
}
|
||||||
let remotes = results;
|
let remotes = results;
|
||||||
|
|
||||||
repos.push(Repo{
|
let (namespace, name) = if path == root {
|
||||||
name: match path == root {
|
(
|
||||||
true => match &root.parent() {
|
None,
|
||||||
|
match &root.parent() {
|
||||||
Some(parent) => path_as_string(path.strip_prefix(parent).unwrap()),
|
Some(parent) => path_as_string(path.strip_prefix(parent).unwrap()),
|
||||||
None => {
|
None => {
|
||||||
warnings.push(String::from("Getting name of the search root failed. Do you have a git repository in \"/\"?"));
|
warnings.push(String::from("Getting name of the search root failed. Do you have a git repository in \"/\"?"));
|
||||||
continue
|
continue;
|
||||||
},
|
|
||||||
}
|
}
|
||||||
false => path_as_string(path.strip_prefix(&root).unwrap()),
|
|
||||||
},
|
},
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
let name = path.strip_prefix(&root).unwrap();
|
||||||
|
let namespace = name.parent().unwrap();
|
||||||
|
(
|
||||||
|
if namespace != Path::new("") {
|
||||||
|
Some(path_as_string(namespace).to_string())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
path_as_string(name),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
repos.push(Repo {
|
||||||
|
name,
|
||||||
|
namespace,
|
||||||
remotes: Some(remotes),
|
remotes: Some(remotes),
|
||||||
worktree_setup: is_worktree,
|
worktree_setup: is_worktree,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ impl Project for GithubProject {
|
|||||||
self.name.clone()
|
self.name.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn namespace(&self) -> String {
|
fn namespace(&self) -> Option<String> {
|
||||||
self.full_name
|
if let Some((namespace, _name)) = self.full_name.rsplit_once('/') {
|
||||||
.rsplit_once('/')
|
Some(namespace.to_string())
|
||||||
.expect("Github project name did not include a namespace")
|
} else {
|
||||||
.0
|
None
|
||||||
.to_string()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ssh_url(&self) -> String {
|
fn ssh_url(&self) -> String {
|
||||||
|
|||||||
@@ -39,12 +39,12 @@ impl Project for GitlabProject {
|
|||||||
self.name.clone()
|
self.name.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn namespace(&self) -> String {
|
fn namespace(&self) -> Option<String> {
|
||||||
self.path_with_namespace
|
if let Some((namespace, _name)) = self.path_with_namespace.rsplit_once('/') {
|
||||||
.rsplit_once('/')
|
Some(namespace.to_string())
|
||||||
.expect("Gitlab project name did not include a namespace")
|
} else {
|
||||||
.0
|
None
|
||||||
.to_string()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ssh_url(&self) -> String {
|
fn ssh_url(&self) -> String {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ pub trait Project {
|
|||||||
{
|
{
|
||||||
Repo {
|
Repo {
|
||||||
name: self.name(),
|
name: self.name(),
|
||||||
|
namespace: self.namespace(),
|
||||||
worktree_setup,
|
worktree_setup,
|
||||||
remotes: Some(vec![Remote {
|
remotes: Some(vec![Remote {
|
||||||
name: String::from(provider_name),
|
name: String::from(provider_name),
|
||||||
@@ -53,7 +54,7 @@ pub trait Project {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn name(&self) -> String;
|
fn name(&self) -> String;
|
||||||
fn namespace(&self) -> String;
|
fn namespace(&self) -> Option<String>;
|
||||||
fn ssh_url(&self) -> String;
|
fn ssh_url(&self) -> String;
|
||||||
fn http_url(&self) -> String;
|
fn http_url(&self) -> String;
|
||||||
fn private(&self) -> bool;
|
fn private(&self) -> bool;
|
||||||
@@ -200,7 +201,7 @@ pub trait Provider {
|
|||||||
&self,
|
&self,
|
||||||
worktree_setup: bool,
|
worktree_setup: bool,
|
||||||
force_ssh: bool,
|
force_ssh: bool,
|
||||||
) -> Result<HashMap<String, Vec<Repo>>, String> {
|
) -> Result<HashMap<Option<String>, Vec<Repo>>, String> {
|
||||||
let mut repos = vec![];
|
let mut repos = vec![];
|
||||||
|
|
||||||
if self.filter().owner {
|
if self.filter().owner {
|
||||||
@@ -277,12 +278,16 @@ pub trait Provider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ret: HashMap<String, Vec<Repo>> = HashMap::new();
|
let mut ret: HashMap<Option<String>, Vec<Repo>> = HashMap::new();
|
||||||
|
|
||||||
for repo in repos {
|
for repo in repos {
|
||||||
let namespace = repo.namespace().clone();
|
let namespace = repo.namespace();
|
||||||
|
|
||||||
let repo = repo.into_repo_config(&self.name(), worktree_setup, force_ssh);
|
let mut repo = repo.into_repo_config(&self.name(), worktree_setup, force_ssh);
|
||||||
|
|
||||||
|
// Namespace is already part of the hashmap key. I'm not too happy
|
||||||
|
// about the data exchange format here.
|
||||||
|
repo.remove_namespace();
|
||||||
|
|
||||||
ret.entry(namespace).or_insert(vec![]).push(repo);
|
ret.entry(namespace).or_insert(vec![]).push(repo);
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/repo.rs
15
src/repo.rs
@@ -114,11 +114,24 @@ pub struct Remote {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Repo {
|
pub struct Repo {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub namespace: Option<String>,
|
||||||
pub worktree_setup: bool,
|
pub worktree_setup: bool,
|
||||||
pub remotes: Option<Vec<Remote>>,
|
pub remotes: Option<Vec<Remote>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Repo {
|
||||||
|
pub fn fullname(&self) -> String {
|
||||||
|
match &self.namespace {
|
||||||
|
Some(namespace) => format!("{}/{}", namespace, self.name),
|
||||||
|
None => self.name.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_namespace(&mut self) {
|
||||||
|
self.namespace = None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct RepoChanges {
|
pub struct RepoChanges {
|
||||||
pub files_new: usize,
|
pub files_new: usize,
|
||||||
pub files_modified: usize,
|
pub files_modified: usize,
|
||||||
|
|||||||
Reference in New Issue
Block a user