Skip to content

Commit 45f12b1

Browse files
committed
Auto merge of #6434 - ehuss:fix-fix-concurrent, r=dwijnand
cargo fix: fix targets with shared sources. If `cargo fix` attempts to fix multiple targets concurrently that have shared source files, it would apply fixes multiple times causing corruption of the source code. Fix this by locking on the package path instead of the target filename, essentially serializing all targets within a package. Fixes #6415.
2 parents 79f962f + 41519fb commit 45f12b1

File tree

3 files changed

+20
-7
lines changed

3 files changed

+20
-7
lines changed

src/cargo/ops/fix.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ const FIX_ENV: &str = "__CARGO_FIX_PLZ";
2222
const BROKEN_CODE_ENV: &str = "__CARGO_FIX_BROKEN_CODE";
2323
const PREPARE_FOR_ENV: &str = "__CARGO_FIX_PREPARE_FOR";
2424
const EDITION_ENV: &str = "__CARGO_FIX_EDITION";
25-
2625
const IDIOMS_ENV: &str = "__CARGO_FIX_IDIOMS";
2726

2827
pub struct FixOptions<'a> {
@@ -258,9 +257,10 @@ fn rustfix_crate(
258257
// process at a time. If two invocations concurrently check a crate then
259258
// it's likely to corrupt it.
260259
//
261-
// Currently we do this by assigning the name on our lock to the first
262-
// argument that looks like a Rust file.
263-
let _lock = LockServerClient::lock(&lock_addr.parse()?, filename)?;
260+
// Currently we do this by assigning the name on our lock to the manifest
261+
// directory.
262+
let dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR is missing?");
263+
let _lock = LockServerClient::lock(&lock_addr.parse()?, dir)?;
264264

265265
// Next up this is a bit suspicious, but we *iteratively* execute rustc and
266266
// collect suggestions to feed to rustfix. Once we hit our limit of times to

src/cargo/util/lockserver.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
use std::collections::HashMap;
1515
use std::io::{BufRead, BufReader, Read, Write};
1616
use std::net::{SocketAddr, TcpListener, TcpStream};
17-
use std::path::Path;
1817
use std::sync::atomic::{AtomicBool, Ordering};
1918
use std::sync::{Arc, Mutex};
2019
use std::thread::{self, JoinHandle};
@@ -156,11 +155,11 @@ impl Drop for LockServerStarted {
156155
}
157156

158157
impl LockServerClient {
159-
pub fn lock(addr: &SocketAddr, name: &Path) -> Result<LockServerClient, Error> {
158+
pub fn lock(addr: &SocketAddr, name: impl AsRef<[u8]>) -> Result<LockServerClient, Error> {
160159
let mut client = TcpStream::connect(&addr)
161160
.with_context(|_| "failed to connect to parent lock server")?;
162161
client
163-
.write_all(name.display().to_string().as_bytes())
162+
.write_all(name.as_ref())
164163
.and_then(|_| client.write_all(b"\n"))
165164
.with_context(|_| "failed to write to lock server")?;
166165
let mut buf = [0];

tests/testsuite/fix.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,3 +1235,17 @@ fn fix_to_broken_code() {
12351235
"pub fn foo() { let x = 3; drop(x); }"
12361236
);
12371237
}
1238+
1239+
#[test]
1240+
fn fix_with_common() {
1241+
let p = project()
1242+
.file("src/lib.rs", "")
1243+
.file("tests/t1.rs", "mod common; #[test] fn t1() { common::try(); }")
1244+
.file("tests/t2.rs", "mod common; #[test] fn t2() { common::try(); }")
1245+
.file("tests/common/mod.rs", "pub fn try() {}")
1246+
.build();
1247+
1248+
p.cargo("fix --edition --allow-no-vcs").run();
1249+
1250+
assert_eq!(p.read_file("tests/common/mod.rs"), "pub fn r#try() {}");
1251+
}

0 commit comments

Comments
 (0)