mirror of
https://github.com/openai/codex.git
synced 2026-10-30 19:18:49 +00:00
## Summary Move `codex marketplace add` onto a shared core implementation so the CLI and app-server path can use one source of truth. This change: - adds shared marketplace-add orchestration in `codex-core` - switches the CLI command to call that shared implementation - removes duplicated CLI-only marketplace add helpers - preserves focused parser and add-path coverage while moving the shared behavior into core tests ## Why The new `marketplace/add` RPC should reuse the same underlying marketplace-add flow as the CLI. This refactor lands that consolidation first so the follow-up app-server PR can be mostly protocol and handler wiring. ## Validation - `cargo test -p codex-core marketplace_add` - `cargo test -p codex-cli marketplace_cmd` - `just fix -p codex-core` - `just fix -p codex-cli` - `just fmt`
135 lines
3.7 KiB
Rust
135 lines
3.7 KiB
Rust
use anyhow::Context;
|
|
use anyhow::Result;
|
|
use clap::Parser;
|
|
use codex_core::config::find_codex_home;
|
|
use codex_core::plugins::MarketplaceAddRequest;
|
|
use codex_core::plugins::add_marketplace;
|
|
use codex_utils_cli::CliConfigOverrides;
|
|
|
|
#[derive(Debug, Parser)]
|
|
pub struct MarketplaceCli {
|
|
#[clap(flatten)]
|
|
pub config_overrides: CliConfigOverrides,
|
|
|
|
#[command(subcommand)]
|
|
subcommand: MarketplaceSubcommand,
|
|
}
|
|
|
|
#[derive(Debug, clap::Subcommand)]
|
|
enum MarketplaceSubcommand {
|
|
/// Add a remote marketplace repository.
|
|
Add(AddMarketplaceArgs),
|
|
}
|
|
|
|
#[derive(Debug, Parser)]
|
|
struct AddMarketplaceArgs {
|
|
/// Marketplace source. Supports owner/repo[@ref], HTTP(S) Git URLs, or SSH URLs.
|
|
source: String,
|
|
|
|
/// Git ref to check out. Overrides any @ref or #ref suffix in SOURCE.
|
|
#[arg(long = "ref", value_name = "REF")]
|
|
ref_name: Option<String>,
|
|
|
|
/// Sparse-checkout path to use while cloning git sources. Repeat to include multiple paths.
|
|
#[arg(
|
|
long = "sparse",
|
|
value_name = "PATH",
|
|
action = clap::ArgAction::Append
|
|
)]
|
|
sparse_paths: Vec<String>,
|
|
}
|
|
|
|
impl MarketplaceCli {
|
|
pub async fn run(self) -> Result<()> {
|
|
let MarketplaceCli {
|
|
config_overrides,
|
|
subcommand,
|
|
} = self;
|
|
|
|
// Validate overrides now. This command writes to CODEX_HOME only; marketplace discovery
|
|
// happens from that cache root after the next plugin/list or app-server start.
|
|
config_overrides
|
|
.parse_overrides()
|
|
.map_err(anyhow::Error::msg)?;
|
|
|
|
match subcommand {
|
|
MarketplaceSubcommand::Add(args) => run_add(args).await?,
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
async fn run_add(args: AddMarketplaceArgs) -> Result<()> {
|
|
let AddMarketplaceArgs {
|
|
source,
|
|
ref_name,
|
|
sparse_paths,
|
|
} = args;
|
|
|
|
let codex_home = find_codex_home().context("failed to resolve CODEX_HOME")?;
|
|
let outcome = add_marketplace(
|
|
codex_home.to_path_buf(),
|
|
MarketplaceAddRequest {
|
|
source,
|
|
ref_name,
|
|
sparse_paths,
|
|
},
|
|
)
|
|
.await?;
|
|
|
|
if outcome.already_added {
|
|
println!(
|
|
"Marketplace `{}` is already added from {}.",
|
|
outcome.marketplace_name, outcome.source_display
|
|
);
|
|
} else {
|
|
println!(
|
|
"Added marketplace `{}` from {}.",
|
|
outcome.marketplace_name, outcome.source_display
|
|
);
|
|
}
|
|
println!(
|
|
"Installed marketplace root: {}",
|
|
outcome.installed_root.as_path().display()
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use pretty_assertions::assert_eq;
|
|
|
|
#[test]
|
|
fn sparse_paths_parse_before_or_after_source() {
|
|
let sparse_before_source =
|
|
AddMarketplaceArgs::try_parse_from(["add", "--sparse", "plugins/foo", "owner/repo"])
|
|
.unwrap();
|
|
assert_eq!(sparse_before_source.source, "owner/repo");
|
|
assert_eq!(sparse_before_source.sparse_paths, vec!["plugins/foo"]);
|
|
|
|
let sparse_after_source =
|
|
AddMarketplaceArgs::try_parse_from(["add", "owner/repo", "--sparse", "plugins/foo"])
|
|
.unwrap();
|
|
assert_eq!(sparse_after_source.source, "owner/repo");
|
|
assert_eq!(sparse_after_source.sparse_paths, vec!["plugins/foo"]);
|
|
|
|
let repeated_sparse = AddMarketplaceArgs::try_parse_from([
|
|
"add",
|
|
"--sparse",
|
|
"plugins/foo",
|
|
"--sparse",
|
|
"skills/bar",
|
|
"owner/repo",
|
|
])
|
|
.unwrap();
|
|
assert_eq!(repeated_sparse.source, "owner/repo");
|
|
assert_eq!(
|
|
repeated_sparse.sparse_paths,
|
|
vec!["plugins/foo", "skills/bar"]
|
|
);
|
|
}
|
|
}
|