//! `repo-create [--description ] [--private] [--default-branch ] //! [--org ] [--auto-init]` — create a forge repository under the current //! user (or under `--org`). Prints the new repo's web URL (or the full repo //! object under `--json`). //! //! Wraps `POST /api/v1/user/repos` (or `/orgs/{org}/repos`) so agents don't //! reach for raw API calls when the operator greenlights a new repo — the //! instance has push-to-create disabled, so `git push` to a non-existent //! repo 403s. Pairs with `clone` (then push your content) and //! `repo-add-collaborator` (add peers to a fresh agent-namespace repo). use anyhow::Result; use clap::Args as ClapArgs; use serde_json::{Value, json}; use crate::client::Client; use crate::verbs::print_json; #[derive(ClapArgs)] pub struct Args { /// Repository name (required). Created under the authenticated user /// unless `--org` is given. name: String, /// Repository description. #[arg(long)] description: Option, /// Create the repo as private (default: public). #[arg(long)] private: bool, /// Default branch name (e.g. `main`). Forgejo applies it to the /// initial commit, so it only takes effect alongside `--auto-init`. #[arg(long = "default-branch")] default_branch: Option, /// Create under this organisation (`POST /orgs//repos`) instead /// of the authenticated user's namespace. #[arg(long)] org: Option, /// Seed an initial commit (README) so the repo is non-empty and can /// be cloned immediately. Omit to create a bare repo you push into. #[arg(long = "auto-init")] auto_init: bool, } /// # Errors /// /// Propagates any transport error from the Forgejo REST call (network /// unreachable, 4xx/5xx response such as a name clash or insufficient /// permission on the target namespace, token missing/invalid) and any /// I/O error from writing the result to stdout. pub fn run(client: &Client, args: Args) -> Result<()> { let mut payload = json!({ "name": args.name, "private": args.private, "auto_init": args.auto_init, }); if let Some(d) = args.description { payload["description"] = json!(d); } if let Some(b) = args.default_branch { payload["default_branch"] = json!(b); } let path = match args.org.as_deref() { Some(org) => format!("/orgs/{org}/repos"), None => "/user/repos".to_owned(), }; let resp = client.post_json(&path, &payload)?; if client.json_mode() { return print_json(&resp); } // Default human path: print the web URL, like issue-create / pr-create. if let Some(url) = resp.get("html_url").and_then(Value::as_str) { println!("{url}"); } Ok(()) }