Skip to content

Commit 0f16114

Browse files
committed
fix(cargo): resolve relative build dirs against workspace root and use FIFO-safe file reads
- Relative build.target-dir and build.build-dir now resolve against the workspace root as Cargo does, not the config file's directory. Fixes invalidation when target-dir is set in ~/.cargo/config.toml (#387). - Replace std::fs::read_to_string with read_regular_to_string_sync for Cargo.toml and .cargo/config reads to prevent hangs on FIFO/device files.
1 parent 7d9f646 commit 0f16114

1 file changed

Lines changed: 15 additions & 17 deletions

File tree

‎crates/socket-patch-core/src/utils/cargo_build_cache.rs‎

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pub fn build_dirs_with(
6161
) -> BuildDirs {
6262
let env = |k: &str| env(k).filter(|v| !v.trim().is_empty());
6363
let ws_root = workspace_root(cwd);
64-
let config = ConfigDirs::read(cwd, cargo_home);
64+
let config = ConfigDirs::read(cwd, cargo_home, &ws_root);
6565

6666
let mut candidates: Vec<PathBuf> = Vec::new();
6767
let mut unresolved = Vec::new();
@@ -77,11 +77,10 @@ pub fn build_dirs_with(
7777
// build-dir (cargo 1.91+): where the fingerprints live; defaults to
7878
// the target dir.
7979
let build_dir = env("CARGO_BUILD_BUILD_DIR")
80-
.map(|v| (v, cwd.to_path_buf()))
8180
.or_else(|| config.build_dir.clone());
82-
if let Some((raw, base)) = build_dir {
81+
if let Some(raw) = build_dir {
8382
match expand_build_dir(&raw, &ws_root, cargo_home) {
84-
Some(p) => candidates.push(base.join(p)),
83+
Some(p) => candidates.push(ws_root.join(p)),
8584
None => unresolved.push(raw),
8685
}
8786
}
@@ -126,7 +125,7 @@ fn workspace_root(cwd: &Path) -> PathBuf {
126125
}
127126
for dir in cwd.ancestors() {
128127
let manifest = dir.join("Cargo.toml");
129-
if let Ok(text) = std::fs::read_to_string(&manifest) {
128+
if let Ok(text) = crate::utils::fs::read_regular_to_string_sync(&manifest) {
130129
if text
131130
.parse::<toml_edit::DocumentMut>()
132131
.is_ok_and(|d| d.contains_key("workspace"))
@@ -142,29 +141,28 @@ fn workspace_root(cwd: &Path) -> PathBuf {
142141
/// reads for `cwd`: `.cargo/config.toml` (or legacy `.cargo/config`) in
143142
/// `cwd` and every ancestor, then `$CARGO_HOME/config.toml`; the deepest
144143
/// file that sets a key wins. A relative value resolves against the
145-
/// directory holding the `.cargo` directory.
144+
/// workspace root.
146145
#[derive(Default)]
147146
struct ConfigDirs {
148147
target_dir: Option<PathBuf>,
149-
/// The raw value and the base its relative form resolves against.
150-
build_dir: Option<(String, PathBuf)>,
148+
/// The raw value.
149+
build_dir: Option<String>,
151150
}
152151

153152
impl ConfigDirs {
154-
fn read(cwd: &Path, cargo_home: Option<&Path>) -> Self {
155-
let mut files: Vec<(PathBuf, PathBuf)> = cwd
153+
fn read(cwd: &Path, cargo_home: Option<&Path>, ws_root: &Path) -> Self {
154+
let mut files: Vec<PathBuf> = cwd
156155
.ancestors()
157-
.map(|d| (d.join(".cargo"), d.to_path_buf()))
156+
.map(|d| d.join(".cargo"))
158157
.collect();
159158
if let Some(home) = cargo_home {
160-
let base = home.parent().map(Path::to_path_buf).unwrap_or_default();
161-
files.push((home.to_path_buf(), base));
159+
files.push(home.to_path_buf());
162160
}
163161
let mut out = ConfigDirs::default();
164-
for (dot_cargo, base) in files {
162+
for dot_cargo in files {
165163
let text = ["config.toml", "config"]
166164
.iter()
167-
.find_map(|f| std::fs::read_to_string(dot_cargo.join(f)).ok());
165+
.find_map(|f| crate::utils::fs::read_regular_to_string_sync(&dot_cargo.join(f)).ok());
168166
let Some(doc) = text.and_then(|t| t.parse::<toml_edit::DocumentMut>().ok()) else {
169167
continue;
170168
};
@@ -173,12 +171,12 @@ impl ConfigDirs {
173171
};
174172
if out.target_dir.is_none() {
175173
if let Some(v) = build.get("target-dir").and_then(|v| v.as_str()) {
176-
out.target_dir = Some(base.join(v));
174+
out.target_dir = Some(ws_root.join(v));
177175
}
178176
}
179177
if out.build_dir.is_none() {
180178
if let Some(v) = build.get("build-dir").and_then(|v| v.as_str()) {
181-
out.build_dir = Some((v.to_string(), base.clone()));
179+
out.build_dir = Some(v.to_string());
182180
}
183181
}
184182
}

0 commit comments

Comments
 (0)