Skip to content

Commit 52542db

Browse files
committed
Keep commented path.system from reviving a path
A `BUNDLE_PATH__SYSTEM: true # note` line makes Bundler 2.5.6+ ignore the recorded BUNDLE_PATH and load system gems. The era fallback added for #951 could still pick the recorded path when a leftover directory existed there, so apply would patch a copy Bundler never loads. The legacy reading now only competes with another directory reading; an unset current reading always stands. Assisted-by: Claude Code:claude-opus-5-5
1 parent 3f8e1c1 commit 52542db

1 file changed

Lines changed: 35 additions & 7 deletions

File tree

‎crates/socket-patch-core/src/crawlers/ruby_crawler.rs‎

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,25 +1600,29 @@ fn strip_bundle_config_comment(v: &str) -> &str {
16001600
/// is not known here. Bundler creates the directory it uses, so take the
16011601
/// current reading unless only the legacy reading's directory exists.
16021602
/// Values without a comment read the same in both eras.
1603+
///
1604+
/// Only two directory readings are weighed against each other. When the
1605+
/// current reading is unset — e.g. a commented `path.system: true` that
1606+
/// only the current loader honours — the legacy path's directory is no
1607+
/// evidence of the era (it may be a leftover install, the #915 shape), so
1608+
/// the current reading stands.
16031609
async fn bundle_config_dir_reading(
16041610
current: Option<String>,
16051611
legacy: Option<String>,
16061612
resolve: impl Fn(&str) -> PathBuf,
16071613
) -> Option<String> {
1608-
let Some(legacy) = legacy.filter(|legacy| current.as_ref() != Some(legacy)) else {
1614+
let (Some(value), Some(legacy)) = (current.as_deref(), legacy) else {
16091615
return current;
16101616
};
1617+
if value == legacy {
1618+
return current;
1619+
}
16111620
let is_dir = |path: PathBuf| async move {
16121621
tokio::fs::metadata(path)
16131622
.await
16141623
.is_ok_and(|meta| meta.is_dir())
16151624
};
1616-
if let Some(value) = &current {
1617-
if is_dir(resolve(value)).await {
1618-
return current;
1619-
}
1620-
}
1621-
if is_dir(resolve(&legacy)).await {
1625+
if !is_dir(resolve(value)).await && is_dir(resolve(&legacy)).await {
16221626
Some(legacy)
16231627
} else {
16241628
current
@@ -4280,4 +4284,28 @@ mod tests {
42804284
legacy_cache
42814285
);
42824286
}
4287+
4288+
/// Bugbot on #953: a commented `path.system: true` drops the recorded
4289+
/// path under the current loader. A leftover directory at that
4290+
/// recorded path must not bring it back through the legacy reading.
4291+
#[tokio::test]
4292+
async fn commented_path_system_true_ignores_a_leftover_recorded_path() {
4293+
let dir = tempfile::tempdir().unwrap();
4294+
std::fs::write(dir.path().join("Gemfile"), b"gem \"foo\"\n").unwrap();
4295+
std::fs::create_dir_all(dir.path().join(".bundle")).unwrap();
4296+
std::fs::write(
4297+
dir.path().join(".bundle").join("config"),
4298+
"---\nBUNDLE_PATH: vendor/mygems\nBUNDLE_PATH__SYSTEM: true # use system gems\n",
4299+
)
4300+
.unwrap();
4301+
let root = dir.path().join("vendor").join("mygems");
4302+
std::fs::create_dir_all(root.join("gems").join("foo-1.0.0").join("lib")).unwrap();
4303+
std::fs::create_dir_all(root.join("specifications")).unwrap();
4304+
4305+
let paths = RubyCrawler::get_vendor_bundle_paths_with_env(dir.path(), None, None).await;
4306+
assert!(
4307+
paths.is_empty(),
4308+
"a commented path.system=true must still drop the config root: {paths:?}"
4309+
);
4310+
}
42834311
}

0 commit comments

Comments
 (0)