diff --git a/docs/reference/cli.md b/docs/reference/cli.md index ff073bd7f..75343df13 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -28,10 +28,11 @@ It also supports the [`pyproject.toml`](../advanced/pyproject_toml.md) file, if ##### Options -- `--channel (-c)`: specify a channel that the project uses. Defaults to `conda-forge`. (Allowed to be used more than once) -- `--platform (-p)`: specify a platform that the project supports. (Allowed to be used more than once) +- `--channel (-c)`: Specify a channel that the project uses. Defaults to `conda-forge`. (Allowed to be used more than once) +- `--platform (-p)`: Specify a platform that the project supports. (Allowed to be used more than once) - `--import (-i)`: Import an existing conda environment file, e.g. `environment.yml`. - `--format `: Specify the format of the project file, either `pyproject` or `pixi`. [default: `pixi`] +- `--scm `: Specify the SCM used to manage the project with. Possible values: github, gitlab, codeberg. [default: `github`] !!! info "Importing an environment.yml" When importing an environment, the `pixi.toml` will be created with the dependencies from the environment file. @@ -46,7 +47,7 @@ pixi init --channel conda-forge --channel bioconda myproject pixi init --platform osx-64 --platform linux-64 myproject pixi init --import environment.yml pixi init --format pyproject -pixi init --format pixi +pixi init --format pixi --scm gitlab ``` ## `add` diff --git a/src/cli/init.rs b/src/cli/init.rs index 5a8b30d96..296da842b 100644 --- a/src/cli/init.rs +++ b/src/cli/init.rs @@ -46,13 +46,17 @@ pub struct Args { pub env_file: Option, /// The manifest format to create. - #[arg(long, conflicts_with_all = ["env_file", "pyproject_toml"],)] + #[arg(long, conflicts_with_all = ["env_file", "pyproject_toml"], ignore_case = true)] pub format: Option, /// Create a pyproject.toml manifest instead of a pixi.toml manifest // BREAK (0.27.0): Remove this option from the cli in favor of the `format` option. #[arg(long, conflicts_with_all = ["env_file", "format"], alias = "pyproject", hide = true)] pub pyproject_toml: bool, + + /// Source Control Management used for this project + #[arg(short = 's', long = "scm", ignore_case = true)] + pub scm: Option, } /// The pixi.toml template @@ -149,9 +153,29 @@ const GITIGNORE_TEMPLATE: &str = r#" *.egg-info "#; -const GITATTRIBUTES_TEMPLATE: &str = r#"# GitHub syntax highlighting +#[derive(Parser, Debug, Clone, PartialEq, ValueEnum)] +pub enum GitAttributes { + Github, + Gitlab, + Codeberg, +} + +impl GitAttributes { + fn template(&self) -> &'static str { + match self { + GitAttributes::Github | GitAttributes::Codeberg => { + r#"# SCM syntax highlighting pixi.lock linguist-language=YAML linguist-generated=true -"#; +"# + } + GitAttributes::Gitlab => { + r#"# GitLab syntax highlighting +pixi.lock gitlab-language=yaml gitlab-generated=true +"# + } + } + } +} pub async fn execute(args: Args) -> miette::Result<()> { let env = Environment::new(); @@ -412,8 +436,10 @@ pub async fn execute(args: Args) -> miette::Result<()> { ); } + let git_attributes = args.scm.unwrap_or(GitAttributes::Github); + // create a .gitattributes if one is missing - if let Err(e) = create_or_append_file(&gitattributes_path, GITATTRIBUTES_TEMPLATE) { + if let Err(e) = create_or_append_file(&gitattributes_path, git_attributes.template()) { tracing::warn!( "Warning, couldn't update '{}' because of: {}", gitattributes_path.to_string_lossy(), @@ -579,4 +605,56 @@ mod tests { dir.close().unwrap(); } + + #[test] + fn test_multiple_format_values() { + let test_cases = vec![ + ("pixi", ManifestFormat::Pixi), + ("PiXi", ManifestFormat::Pixi), + ("PIXI", ManifestFormat::Pixi), + ("pyproject", ManifestFormat::Pyproject), + ("PyPrOjEcT", ManifestFormat::Pyproject), + ("PYPROJECT", ManifestFormat::Pyproject), + ]; + + for (input, expected) in test_cases { + let args = Args::try_parse_from(["init", "--format", input]).unwrap(); + assert_eq!(args.format, Some(expected)); + } + } + + #[test] + fn test_multiple_scm_values() { + let test_cases = vec![ + ("github", GitAttributes::Github), + ("GiThUb", GitAttributes::Github), + ("GITHUB", GitAttributes::Github), + ("Github", GitAttributes::Github), + ("gitlab", GitAttributes::Gitlab), + ("GiTlAb", GitAttributes::Gitlab), + ("GITLAB", GitAttributes::Gitlab), + ("codeberg", GitAttributes::Codeberg), + ("CoDeBeRg", GitAttributes::Codeberg), + ("CODEBERG", GitAttributes::Codeberg), + ]; + + for (input, expected) in test_cases { + let args = Args::try_parse_from(["init", "--scm", input]).unwrap(); + assert_eq!(args.scm, Some(expected)); + } + } + + #[test] + fn test_invalid_scm_values() { + let invalid_values = vec!["invalid", "", "git", "bitbucket", "mercurial", "svn"]; + + for value in invalid_values { + let result = Args::try_parse_from(["init", "--scm", value]); + assert!( + result.is_err(), + "Expected error for invalid SCM value '{}', but got success", + value + ); + } + } } diff --git a/tests/common/mod.rs b/tests/common/mod.rs index c4b1e5486..bcf635412 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -16,7 +16,7 @@ use pixi::{ cli::{ add, cli_config::{PrefixUpdateConfig, ProjectConfig}, - init, + init::{self, GitAttributes}, install::Args, project, remove, run, task::{self, AddArgs, AliasArgs}, @@ -261,6 +261,7 @@ impl PixiControl { env_file: None, format: None, pyproject_toml: false, + scm: Some(GitAttributes::Github), }, } } @@ -278,6 +279,7 @@ impl PixiControl { env_file: None, format: None, pyproject_toml: false, + scm: Some(GitAttributes::Github), }, } }