You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix FileLock path tracking after rename in package operation (#16036)
### What does this PR try to resolve?
Fixes#7863 - FileLock::rename bug where `cargo::ops::package()` returns
a FileLock pointing to a non-existent temporary file.
The issue occurs when using Cargo's programmatic API. The
`cargo::ops::package()` function creates a temporary file, locks it with
FileLock, then renames it to the final package location. However, it was
using `std::fs::rename()` directly, which only moves the file on the
filesystem but doesn't update the FileLock's internal path. This left
the FileLock pointing to the old temporary path that no longer exists.
**Root cause:** FileLock had no way to update its internal path after a
filesystem rename operation.
**Solution:**
1. Add a `FileLock::rename()` method that performs both the filesystem
rename AND updates the internal path
2. Update the package operation to use this new method instead of
`std::fs::rename()`
### How to test and review this PR?
**Manual testing approach:**
Since this bug only affects programmatic usage (not CLI), you can test
it by creating a simple test that uses `cargo::ops::package()`:
```rust
use std::env;
use crate::prelude::*;
use cargo::core::Workspace;
use cargo::core::Shell;
use cargo::util::GlobalContext;
use cargo_test_support::{basic_manifest, paths, project};
#[cargo_test]
fn filelock_path_after_rename_bug() {
// This test shows the bug where cargo::ops::package returns a FileLock
// pointing to a temporary file that no longer exists after the file is renamed.
let p = project()
.file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
.file("src/lib.rs", "")
.build();
let shell = Shell::from_write(Box::new(Vec::new()));
let gctx = GlobalContext::new(shell, env::current_dir().unwrap(), paths::home());
let ws = Workspace::new(&p.root().join("Cargo.toml"), &gctx).unwrap();
let package_opts = cargo::ops::PackageOpts {
gctx: &gctx,
list: false,
fmt: cargo::ops::PackageMessageFormat::Human,
check_metadata: false,
allow_dirty: true,
include_lockfile: false,
verify: false,
jobs: None,
keep_going: false,
to_package: cargo::ops::Packages::Default,
targets: Vec::new(),
cli_features: cargo::core::resolver::CliFeatures::new_all(false),
reg_or_index: None,
dry_run: false,
};
let file_locks = cargo::ops::package(&ws, &package_opts).unwrap();
let file_lock = &file_locks[0];
// Before fix: this fails because FileLock points to deleted temp file
// After fix: this succeeds because FileLock points to actual package
assert!(file_lock.path().exists());
}
0 commit comments