diff --git a/Cargo.lock b/Cargo.lock index 0678af98d0..c5c7b3388f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6033,8 +6033,11 @@ dependencies = [ "pixi_uv_conversions", "rattler", "rattler_conda_types", + "rattler_index", "rattler_lock", "rattler_networking", + "rattler_package_streaming", + "rattler_s3", "rattler_shell", "rattler_solve", "rattler_upload", diff --git a/Cargo.toml b/Cargo.toml index 97b372fd9a..74e5466800 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -226,6 +226,9 @@ rattler_conda_types = { version = "0.44.0", default-features = false, features = "rayon", ] } rattler_digest = { version = "1.2.2", default-features = false } +rattler_index = { version = "0.27.17", default-features = false, features = [ + "s3", +] } rattler_lock = { version = "0.27.0", default-features = false } rattler_menuinst = { version = "0.2.49", default-features = false } rattler_networking = { version = "0.26.2", default-features = false, features = [ @@ -234,6 +237,7 @@ rattler_networking = { version = "0.26.2", default-features = false, features = ] } rattler_package_streaming = { version = "0.24.2", default-features = false } rattler_repodata_gateway = { version = "0.27.0", default-features = false } +rattler_s3 = { version = "0.1.26", default-features = false } rattler_shell = { version = "0.26.2", default-features = false } rattler_solve = { version = "5.0.0", default-features = false } rattler_upload = { version = "0.5.0", default-features = false, features = [ diff --git a/crates/pixi_cli/Cargo.toml b/crates/pixi_cli/Cargo.toml index 308fac2c11..ec33571278 100644 --- a/crates/pixi_cli/Cargo.toml +++ b/crates/pixi_cli/Cargo.toml @@ -67,6 +67,9 @@ rattler_lock = { workspace = true } rattler_networking = { workspace = true, default-features = false } rattler_shell = { workspace = true, features = ["sysinfo"] } rattler_solve = { workspace = true, features = ["resolvo", "serde"] } +rattler_index = { workspace = true } +rattler_package_streaming = { workspace = true } +rattler_s3 = { workspace = true } rattler_upload = { workspace = true } rattler_virtual_packages = { workspace = true } regex = { workspace = true } diff --git a/crates/pixi_cli/src/build.rs b/crates/pixi_cli/src/build.rs index b6a5a174ae..a3db45f103 100644 --- a/crates/pixi_cli/src/build.rs +++ b/crates/pixi_cli/src/build.rs @@ -71,7 +71,7 @@ pub struct Args { /// Validate that the full path of package manifest exists and is a supported format. /// Directories are allowed (for discovery), and specific manifest files must be supported formats. -async fn validate_package_manifest(path: &PathBuf) -> miette::Result<()> { +pub(crate) async fn validate_package_manifest(path: &PathBuf) -> miette::Result<()> { let supported_file_names: Vec<&str> = [ // backend-specific build files // that will be autodiscovered diff --git a/crates/pixi_cli/src/lib.rs b/crates/pixi_cli/src/lib.rs index 5999b8eedc..ce3b60216e 100644 --- a/crates/pixi_cli/src/lib.rs +++ b/crates/pixi_cli/src/lib.rs @@ -37,6 +37,7 @@ pub mod install; pub mod list; pub mod lock; pub(crate) mod match_spec_or_path; +pub mod publish; pub mod reinstall; pub mod remove; pub mod run; @@ -172,6 +173,7 @@ pub enum Command { List(list::Args), Lock(lock::Args), Reinstall(reinstall::Args), + Publish(publish::Args), #[clap(visible_alias = "rm")] Remove(remove::Args), #[clap(visible_alias = "r")] @@ -367,6 +369,7 @@ pub async fn execute_command( Command::Task(cmd) => task::execute(cmd).await, Command::Info(cmd) => info::execute(cmd).await, Command::Import(cmd) => import::execute(cmd).await, + Command::Publish(cmd) => publish::execute(cmd).await, Command::Upload(cmd) => upload::execute(cmd).await, Command::Search(cmd) => search::execute(cmd).await, Command::Workspace(cmd) => workspace::execute(cmd).await, diff --git a/crates/pixi_cli/src/publish.rs b/crates/pixi_cli/src/publish.rs new file mode 100644 index 0000000000..2c253c777f --- /dev/null +++ b/crates/pixi_cli/src/publish.rs @@ -0,0 +1,687 @@ +use std::path::PathBuf; + +use clap::Parser; +use indicatif::ProgressBar; +use miette::{Context, IntoDiagnostic}; +use pixi_auth::get_auth_store; +use pixi_build_frontend::BackendOverride; +use pixi_command_dispatcher::{ + BuildBackendMetadataSpec, BuildEnvironment, BuildProfile, CacheDirs, SourceBuildSpec, + build::PinnedSourceCodeLocation, +}; +use pixi_config::{Config, ConfigCli}; +use pixi_core::{WorkspaceLocator, environment::sanity_check_workspace}; +use pixi_manifest::FeaturesExt; +use pixi_path::AbsPathBuf; +use pixi_progress::global_multi_progress; +use pixi_record::{PinnedPathSpec, PinnedSourceSpec}; +use pixi_reporters::TopLevelProgress; +use pixi_utils::variants::VariantConfig; +use rattler_conda_types::{GenericVirtualPackage, Platform}; +use rattler_networking::AuthenticationStorage; +use rattler_package_streaming::seek::read_package_file; + +use crate::build::{determine_discovery_start, validate_package_manifest}; +use crate::cli_config::LockAndInstallConfig; + +/// Build a conda package and publish it to a channel. +/// +/// This is a convenience command that combines `pixi build` and `pixi upload`. +/// +/// Supported target channel URLs: +/// - prefix.dev: `https://prefix.dev/` +/// - anaconda.org: `https://anaconda.org//