GitLab: include nested subgroup projects when enumerating group repositories

This commit is contained in:
Mick Grove 2025-08-08 21:43:01 -07:00
commit 3c487de38e

113
f1.patch
View file

@ -1,113 +0,0 @@
diff --git a/src/gitlab.rs b/src/gitlab.rs
index c7b0549eee0cf1b6ef4772efc955647e3da00cac..e7df15e102cdac3e4017cbab97fab5dc52940b97 100644
--- a/src/gitlab.rs
+++ b/src/gitlab.rs
@@ -66,77 +66,101 @@ fn create_gitlab_client(gitlab_url: &Url, ignore_certs: bool) -> Result<Gitlab>
let mut builder = GitlabBuilder::new_unauthenticated(host);
if ignore_certs {
builder.insecure();
}
Ok(builder.build()?)
}
pub async fn enumerate_repo_urls(
repo_specifiers: &RepoSpecifiers,
gitlab_url: Url,
ignore_certs: bool,
mut progress: Option<&mut ProgressBar>,
) -> Result<Vec<String>> {
let client = create_gitlab_client(&gitlab_url, ignore_certs)?;
let mut repo_urls = Vec::new();
// 1) Process each GitLab username
for username in &repo_specifiers.user {
// a) Look up the user by username, deserializing only `id`
let users_ep = Users::builder().username(username).build()?;
let hits: Vec<SimpleUser> = users_ep.query(&client)?;
let user =
hits.into_iter().next().context(format!("GitLab user `{}` not found", username))?;
let user_id = user.id;
- // b) List that users projects by ID
- let projects_ep = UserProjects::builder().user(user_id).build()?;
+ // b) List that user's projects applying the requested filter
+ let mut builder = UserProjects::builder();
+ builder.user(user_id);
+
+ match repo_specifiers.repo_filter {
+ RepoType::Owner => {
+ builder.owned(true);
+ }
+ RepoType::Member => {
+ builder.membership(true);
+ }
+ RepoType::All => {
+ // default: list all visible repositories
+ }
+ }
+
+ let projects_ep = builder.build()?;
let projects: Vec<SimpleProject> = projects_ep.query(&client)?;
for proj in projects {
repo_urls.push(proj.http_url_to_repo);
}
if let Some(pb) = progress.as_mut() {
pb.inc(1);
}
}
// all groups
let groups: Vec<SimpleGroup> = if repo_specifiers.all_groups {
- gitlab::api::groups::Groups::builder().build()?.query(&client.clone())?
+ gitlab::api::groups::Groups::builder()
+ .all_available(true)
+ .build()?
+ .query(&client.clone())?
} else {
let mut found: Vec<SimpleGroup> = Vec::new();
for grp in &repo_specifiers.group {
- let ep = gitlab::api::groups::Groups::builder().search(grp).build()?;
- let page: Vec<SimpleGroup> = ep.query(&client.clone())?;
- found.extend(page);
+ let ep = gitlab::api::groups::Group::builder().group(grp).build()?;
+ let group: SimpleGroup = ep.query(&client.clone())?;
+ found.push(group);
}
found
};
for group in groups {
- let gp_ep = GroupProjects::builder().group(group.id).build()?;
+ let mut gp_builder = GroupProjects::builder();
+ gp_builder.group(group.id);
+ if matches!(repo_specifiers.repo_filter, RepoType::Owner) {
+ gp_builder.owned(true);
+ }
+
+ let gp_ep = gp_builder.build()?;
let projects: Vec<SimpleProject> = gp_ep.query(&client)?;
for proj in projects {
repo_urls.push(proj.http_url_to_repo);
}
if let Some(pb) = progress.as_mut() {
pb.inc(1);
}
}
// 3) Sort & dedupe
repo_urls.sort_unstable();
repo_urls.dedup();
Ok(repo_urls)
}
pub async fn list_repositories(
api_url: Url,
ignore_certs: bool,
progress_enabled: bool,
users: &[String],
groups: &[String],
all_groups: bool,
repo_filter: RepoType,
) -> Result<()> {