@@ -17,6 +17,21 @@
/// Repository (org/repo), or detected from git remote
repo: Option<String>,
},
/// Create a new repository
Create {
/// Repository name
#[arg(long)]
name: String,
/// Organization slug (defaults to org from default repo)
#[arg(long)]
org: Option<String>,
/// Description
#[arg(long, default_value = "")]
description: String,
/// Visibility: private or public
#[arg(long, default_value = "private")]
visibility: String,
},
/// Clone a repository via SSH
Clone {
/// Repository (org/repo)
@@ -46,6 +61,12 @@
pub async fn run(args: RepoArgs) -> Result<(), Box<dyn std::error::Error>> {
match args.command {
RepoCommand::View { repo } => view(repo.as_deref()).await,
RepoCommand::Create {
name,
org,
description,
visibility,
} => create(&name, org.as_deref(), &description, &visibility).await,
RepoCommand::Clone { repo, dir } => clone(&repo, dir.as_deref()).await,
RepoCommand::SetDefault { repo } => set_default(&repo).await,
}
@@ -74,6 +95,50 @@
}
if let Some(ref ts) = repo.inserted_at {
output::detail("Created", &output::format_time(ts));
}
Ok(())
}
async fn create(
name: &str,
org: Option<&str>,
description: &str,
visibility: &str,
) -> Result<(), Box<dyn std::error::Error>> {
let client = Client::from_config()?;
// Resolve org: explicit flag, or first part of default repo
let org_slug = match org {
Some(o) => o.to_string(),
None => {
let (resolved_org, _) = config::resolve_repo(None)?;
resolved_org
}
};
let resp: serde_json::Value = client
.post(
&format!("/{org_slug}/repos"),
&serde_json::json!({
"name": name,
"description": description,
"visibility": visibility,
}),
)
.await?;
let slug = resp
.pointer("/slug")
.or_else(|| resp.pointer("/data/slug"))
.and_then(|v| v.as_str())
.unwrap_or(name);
output::success(&format!("Created repository {org_slug}/{slug}"));
let config = Config::load()?;
if let Some(ref url) = config.server_url {
println!("\n {url}/{org_slug}/{slug}");
}
Ok(())