diff --git a/hive-forge/src/main.rs b/hive-forge/src/main.rs index 795176bd..d03afb8d 100644 --- a/hive-forge/src/main.rs +++ b/hive-forge/src/main.rs @@ -113,10 +113,6 @@ enum Verb { /// the valid names + descriptions for triage / labelling. `--json` /// emits the full label objects (id, name, color, description). RepoLabels(verbs::repo_labels::Args), - /// Search for repositories on the forge instance by keyword, topic, or - /// description. Not repo-scoped — queries the instance-wide explore - /// endpoint. `--json` emits the full repository objects. - RepoSearch(verbs::repo_search::Args), /// Triage lint queries (unassigned / no-reviewer / stale-branches / assignments). Lint(verbs::lint::Args), /// List issues / PRs with filters (`--kind`, `--state`, `--assignee`, @@ -202,7 +198,6 @@ fn main() -> Result<()> { Verb::RepoCreate(a) => verbs::repo_create::run(&client, a), Verb::RepoAddCollaborator(a) => verbs::repo_add_collaborator::run(&client, a), Verb::RepoLabels(a) => verbs::repo_labels::run(&client, a), - Verb::RepoSearch(a) => verbs::repo_search::run(&client, a), Verb::Lint(a) => verbs::lint::run(&client, a), Verb::List(a) => verbs::list::run(&client, a), Verb::Milestone(a) => verbs::milestone::run(&client, a), diff --git a/hive-forge/src/verbs/mod.rs b/hive-forge/src/verbs/mod.rs index 784df9e1..2a438aa4 100644 --- a/hive-forge/src/verbs/mod.rs +++ b/hive-forge/src/verbs/mod.rs @@ -37,7 +37,6 @@ pub mod reopen; pub mod repo_add_collaborator; pub mod repo_create; pub mod repo_labels; -pub mod repo_search; pub mod subscription; pub mod timeline; pub mod tree_sha; diff --git a/hive-forge/src/verbs/repo_search.rs b/hive-forge/src/verbs/repo_search.rs deleted file mode 100644 index 382d1076..00000000 --- a/hive-forge/src/verbs/repo_search.rs +++ /dev/null @@ -1,85 +0,0 @@ -//! `repo-search [--query ] [--topic] [--include-desc] [--limit N]` — -//! search for repositories on the forge instance. -//! -//! Wraps `GET /repos/search` (Forgejo explore endpoint). Useful for agents -//! that need to find a repo by keyword rather than knowing the exact -//! `owner/repo` slug upfront. Not repo-scoped — the `-r` flag is ignored. -//! -//! Human output: one `owner/repo description` line per hit. `--json` -//! emits the full `SearchResults.data` array as raw JSON. - -use anyhow::Result; -use clap::Args as ClapArgs; -use forgejo_api::structs::RepoSearchQuery; - -use crate::client::Client; -use crate::verbs::print_json; - -#[derive(ClapArgs)] -pub struct Args { - /// Keyword to search for (matches repo name by default; combine with - /// `--include-desc` to also match description text). - #[arg(short = 'q', long)] - query: Option, - /// Restrict matches to repositories that have the keyword as a **topic** - /// tag rather than in the name. - #[arg(long)] - topic: bool, - /// Extend the keyword search to repository descriptions (in addition to - /// names, or topics when `--topic` is set). - #[arg(long = "include-desc")] - include_desc: bool, - /// Maximum number of results to return (default: 30). - #[arg(long, default_value_t = 30, value_parser = clap::value_parser!(u64).range(1..))] - limit: u64, -} - -/// # Errors -/// -/// Propagates transport errors from the Forgejo search call or JSON -/// serialisation errors when emitting `--json` output. -pub fn run(client: &Client, args: Args) -> Result<()> { - let limit = u32::try_from(args.limit.min(u64::from(u32::MAX))).unwrap_or(u32::MAX); - let results = client - .api() - .repo_search(RepoSearchQuery { - q: args.query, - topic: args.topic.then_some(true), - include_desc: args.include_desc.then_some(true), - // All other filters left at defaults — callers who need them - // can drop to `--json` and post-filter. - uid: None, - priority_owner_id: None, - team_id: None, - starred_by: None, - private: None, - is_private: None, - template: None, - archived: None, - mode: None, - exclusive: None, - sort: None, - order: None, - }) - .page_size(limit) - .send()?; - - let repos = results.data.unwrap_or_default(); - if client.json_mode() { - return print_json(&serde_json::to_value(&repos)?); - } - if repos.is_empty() { - eprintln!("(no results)"); - return Ok(()); - } - for repo in &repos { - let full_name = repo.full_name.as_deref().unwrap_or("?/?"); - let desc = repo.description.as_deref().unwrap_or(""); - if desc.is_empty() { - println!("{full_name}"); - } else { - println!("{full_name} {desc}"); - } - } - Ok(()) -}