From 3dab03fc454877e20555d74e6e8f0965f9c9c1f1 Mon Sep 17 00:00:00 2001 From: Psionik K <73710933+psionic-k@users.noreply.github.com> Date: Mon, 16 Oct 2023 01:30:55 -0500 Subject: [PATCH] automatically update the lockfile and support --locked There is a problem because cargo2nix is not using the cargo binary here, which could result in the lockfile being different than the project's lock file. We want the behavior that cargo implements privately, to see that the lockfile is out of date and to ask if the user wants to update it. Cargo2nix could offload the work via metadata and json parsing, which may make more sense as a cargo plugin. Cargo2nix will be limited in its capability to work seemlessly with newer or older projects if they generate lockfiles that clash with the output of cargo2nix. The use of the cargo library further cements the potential for disparity. --- src/main.rs | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 4ed35863..14f1497d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,13 +12,14 @@ use cargo::{ core::{ compiler::{CompileKind, RustcTargetData}, dependency::DepKind, + registry::PackageRegistry, resolver::{ features::{ForceAllTargets, HasDevUnits}, CliFeatures, Resolve, }, Package, PackageId, PackageIdSpec, Workspace, }, - ops::{resolve_ws_with_opts, Packages}, + ops::{resolve_with_previous, resolve_ws_with_opts, Packages}, util::important_paths::find_root_manifest_for_wd, }; use cargo_platform::Platform; @@ -59,6 +60,9 @@ struct Opt { /// Overwrite existing output filepath without prompting #[arg(action, long, short)] overwrite: bool, + /// Don't attempt to update the lockfile + #[arg(action, long, short, value_name = "LOCKED")] + locked: bool, /// Output to stdout #[arg(conflicts_with = "file", action, long, short)] stdout: bool, @@ -77,7 +81,8 @@ fn main() -> std::io::Result<()> { let workspace_directory = opt.workspace_directory.unwrap_or(std::env::current_dir()?).canonicalize()?; let file = opt.file.unwrap_or(PathBuf::from("./Cargo.nix")); - let rendered = generate_cargo_nix(&workspace_directory).expect("Error generating nix expressions"); + let rendered = generate_cargo_nix(&workspace_directory, opt.locked) + .expect("Error generating nix expressions"); if opt.stdout { write_to_stdout(&rendered).expect("Error writing to stdout"); } else { write_to_file(&file, &rendered, &opt.overwrite).expect("Error writing to file"); } @@ -187,10 +192,10 @@ fn write_to_stdout(rendered: &str) -> Result<()> { Ok(()) } -fn generate_cargo_nix(workspace_directory: &PathBuf) -> Result { +fn generate_cargo_nix(workspace_directory: &PathBuf, locked: bool) -> Result { let config = { let mut config = cargo::Config::default()?; - config.configure(0, true, None, false, true, false, &None, &[], &[])?; + config.configure(0, false, None, false, locked, false, &None, &[], &[])?; config }; @@ -204,6 +209,21 @@ fn generate_cargo_nix(workspace_directory: &PathBuf) -> Result { let cargo_lock_hash: String = format!("{:x}", hasher.finalize()); let ws = Workspace::new(&root_manifest_path, &config)?; + if !locked { + let mut registry = PackageRegistry::new(ws.config())?; + let mut resolve = resolve_with_previous( + &mut registry, + &ws, + &CliFeatures::new_all(true), + HasDevUnits::Yes, + None, + None, + &[], + true, + )?; + cargo::ops::write_pkg_lockfile(&ws, &mut resolve)?; + } + // To get a list of all packages with all features and dependencies that // might be enabled present, we first resolve with all features turned on let requested_kinds = CompileKind::from_requested_targets(ws.config(), &[])?;