Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ pytest-temp
/vendor
*.conda
*.local.*
.history
/__*
179 changes: 115 additions & 64 deletions src/cli/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ pub struct Args {
pub env_file: Option<PathBuf>,

/// The manifest format to create.
#[arg(long, conflicts_with_all = ["ENVIRONMENT_FILE", "pyproject_toml"], ignore_case = true)]
#[arg(long, conflicts_with_all = ["pyproject_toml"], ignore_case = true)]
pub format: Option<ManifestFormat>,

/// Create a pyproject.toml manifest instead of a pixi.toml manifest
Expand Down Expand Up @@ -301,15 +301,37 @@ pub async fn execute(args: Args) -> miette::Result<()> {
args.platforms.clone()
};

// Dialog with user to create a 'pyproject.toml' or 'pixi.toml' manifest
// If nothing is defined but there is a `pyproject.toml` file, ask the user.
let pyproject = if !pixi_manifest_path.is_file()
&& args.format.is_none()
&& !args.pyproject_toml
&& pyproject_manifest_path.is_file()
{
eprintln!(
"\nA '{}' file already exists.\n",
console::style(consts::PYPROJECT_MANIFEST).bold()
);

dialoguer::Confirm::new()
.with_prompt(format!(
"Do you want to extend it with the '{}' configuration?",
console::style("[tool.pixi]").bold().green()
))
.default(false)
.show_default(true)
.interact()
.into_diagnostic()?
} else {
args.format == Some(ManifestFormat::Pyproject) || args.pyproject_toml
};

let index_url = &(config.pypi_config.index_url);
let extra_index_urls = &(config.pypi_config.extra_index_urls);

// Create a 'pixi.toml' manifest and populate it by importing a conda
// environment file
if let Some(env_file_path) = args.env_file {
// Check if the 'pixi.toml' file doesn't already exist. We don't want to
// overwrite it.
if pixi_manifest_path.is_file() {
miette::bail!("{} already exists", consts::WORKSPACE_MANIFEST);
}

let env_file = CondaEnvFile::from_path(&env_file_path)?;
let name = env_file
.name()
Expand All @@ -320,68 +342,97 @@ pub async fn execute(args: Args) -> miette::Result<()> {
// TODO: Improve this:
// - Use .condarc as channel config
let (conda_deps, pypi_deps, channels) = env_file.to_manifest(&config)?;
let rendered_workspace_template = render_workspace(
&env,
name,
version,
author.as_ref(),
channels,
&platforms,
None,
&vec![],
config.s3_options,
Some(&env_vars),
);
let mut workspace =
WorkspaceMut::from_template(pixi_manifest_path, rendered_workspace_template)?;
workspace.add_specs(
conda_deps,
pypi_deps,
&[] as &[Platform],
&FeatureName::default(),
)?;
let workspace = workspace.save().await.into_diagnostic()?;

eprintln!(
"{}Created {}",
console::style(console::Emoji("✔ ", "")).green(),
// Canonicalize the path to make it more readable, but if it fails just use the path as
// is.
workspace.workspace.provenance.path.display()
);
} else {
let channels = if let Some(channels) = args.channels {
channels
if pyproject {
// Python package names cannot contain '-', so we replace them with '_'
let pypi_package_name = PackageName::from_str(&name)
.map(|name| name.as_dist_info_name().to_string())
.unwrap_or_else(|_| name.clone());

let rv = env
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does rv stand for?

.render_named_str(
consts::PYPROJECT_MANIFEST,
NEW_PYROJECT_TEMPLATE,
context! {
name,
pypi_package_name,
version,
author,
channels,
platforms,
index_url => index_url.as_ref(),
extra_index_urls => &extra_index_urls,
s3 => relevant_s3_options(config.s3_options, channels),
},
)
.expect("should be able to render the template");
save_manifest_file(&pyproject_manifest_path, rv)?;

let src_dir = dir.join("src").join(pypi_package_name);
tokio::fs::create_dir_all(&src_dir)
.await
.into_diagnostic()
.wrap_err_with(|| format!("Could not create directory {}.", src_dir.display()))?;

let init_file = src_dir.join("__init__.py");
match OpenOptions::new()
.write(true)
.create_new(true)
.open(&init_file)
.await
{
Ok(_) => (),
Err(e) if e.kind() == ErrorKind::AlreadyExists => {
// If the file already exists, do nothing
}
Err(e) => {
return Err(e).into_diagnostic().wrap_err_with(|| {
format!("Could not create file {}.", init_file.display())
});
}
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have I missed something, or does the pyproject path not use (conda_deps, pypi_deps) from above? If so, I think import will not work properly.

} else {
config.default_channels().to_vec()
};
// Check if the 'pixi.toml' file doesn't already exist. We don't want to
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Check if the 'pixi.toml' file doesn't already exist. We don't want to
// Check that the 'pixi.toml' file doesn't already exist. We don't want to

// overwrite it.
if pixi_manifest_path.is_file() {
miette::bail!("{} already exists", consts::WORKSPACE_MANIFEST);
}

let index_url = config.pypi_config.index_url;
let extra_index_urls = config.pypi_config.extra_index_urls;
let rendered_workspace_template = render_workspace(
&env,
name,
version,
author.as_ref(),
channels,
&platforms,
None,
&vec![],
config.s3_options,
Some(&env_vars),
);
let mut workspace =
WorkspaceMut::from_template(pixi_manifest_path, rendered_workspace_template)?;
workspace.add_specs(
conda_deps,
pypi_deps,
&[] as &[Platform],
&FeatureName::default(),
)?;
let workspace = workspace.save().await.into_diagnostic()?;

// Dialog with user to create a 'pyproject.toml' or 'pixi.toml' manifest
// If nothing is defined but there is a `pyproject.toml` file, ask the user.
let pyproject = if !pixi_manifest_path.is_file()
&& args.format.is_none()
&& !args.pyproject_toml
&& pyproject_manifest_path.is_file()
{
eprintln!(
"\nA '{}' file already exists.\n",
console::style(consts::PYPROJECT_MANIFEST).bold()
"{}Created {}",
console::style(console::Emoji("✔ ", "")).green(),
// Canonicalize the path to make it more readable, but if it fails just use the path as
// is.
workspace.workspace.provenance.path.display()
Comment on lines 423 to +428
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to include this in the pyproject path also?

);

dialoguer::Confirm::new()
.with_prompt(format!(
"Do you want to extend it with the '{}' configuration?",
console::style("[tool.pixi]").bold().green()
))
.default(false)
.show_default(true)
.interact()
.into_diagnostic()?
}
} else {
let channels = if let Some(channels) = args.channels {
channels
} else {
args.format == Some(ManifestFormat::Pyproject) || args.pyproject_toml
config.default_channels().to_vec()
};

// Inject a tool.pixi.workspace section into an existing pyproject.toml file if
Expand Down Expand Up @@ -449,7 +500,7 @@ pub async fn execute(args: Args) -> miette::Result<()> {
}
}

// Create a 'pyproject.toml' manifest
// Create a 'pyproject.toml' manifest
} else if pyproject {
// Python package names cannot contain '-', so we replace them with '_'
let pypi_package_name = PackageName::from_str(&default_name)
Expand Down Expand Up @@ -521,7 +572,7 @@ pub async fn execute(args: Args) -> miette::Result<()> {
channels,
&platforms,
index_url.as_ref(),
&extra_index_urls,
extra_index_urls,
config.s3_options,
None,
);
Expand Down
Loading