Skip to content

Commit 3add9b2

Browse files
committed
Mirror the vendor gate in the service preflight
The download plan has to name exactly the modules vendor asks the service for, so it now skips a version the build doesn't select, as vendor itself does. Adds a regression test for vendoring an unselected version in a go 1.16 graph. Assisted-by: Claude Code:claude-opus-5-5
1 parent 4a759f2 commit 3add9b2

1 file changed

Lines changed: 48 additions & 0 deletions

File tree

‎crates/socket-patch-core/src/vendor/golang.rs‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,18 @@ pub(crate) async fn service_preflight(
181181
.await
182182
.ok()
183183
.filter(|p| !p.copy_was_ok)?;
184+
// `vendor_go_module` refuses a version the build doesn't select before
185+
// it asks the service for anything (#392).
186+
if crate::patch::redirect::golang_local::selection_refusal(
187+
project_root,
188+
&prelude.module,
189+
&prelude.version,
190+
)
191+
.await
192+
.is_some()
193+
{
194+
return None;
195+
}
184196
// `go_service_redirect` extracts the module zip (its literal
185197
// `{module}@{version}/` prefix stripped) into the copy dir's stage.
186198
let prefix = format!("{}@{}/", prelude.module, prelude.version);
@@ -817,6 +829,11 @@ mod tests {
817829
};
818830
let (dir, blobs, pristine, record) = fixture().await;
819831
let root = dir.path();
832+
// A go 1.16 go.mod listing no version of the module: neither
833+
// version is shown unselected, so both ask for a grant.
834+
tokio::fs::write(root.join("go.mod"), "module example.com/app\n\ngo 1.16\n")
835+
.await
836+
.unwrap();
820837
let server = wiremock::MockServer::start().await;
821838
mount_no_results(&server).await;
822839
let cfg = service_cfg(&server.uri(), crate::vendor::VendorSource::Service, false);
@@ -911,6 +928,37 @@ mod tests {
911928
}
912929
}
913930

931+
/// #392 (vendored variant): in the go 1.16 graph where go.sum shows the
932+
/// build selects v1.5.0, vendoring a v1.4.2 patch would commit a replace
933+
/// go ignores. Refuse before fetching or writing anything.
934+
#[tokio::test]
935+
async fn test_vendor_refuses_a_version_the_build_does_not_select() {
936+
let (dir, blobs, pristine, record) = fixture().await;
937+
let root = dir.path();
938+
let go_mod = "module example.com/app\n\ngo 1.16\n\nrequire example.com/mid v1.0.0\n";
939+
tokio::fs::write(root.join("go.mod"), go_mod).await.unwrap();
940+
tokio::fs::write(
941+
root.join("go.sum"),
942+
"github.com/foo/bar v1.4.2/go.mod h1:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\n\
943+
github.com/foo/bar v1.5.0 h1:BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=\n",
944+
)
945+
.await
946+
.unwrap();
947+
let outcome = run_vendor(PURL, root, &blobs, &pristine, &record, false).await;
948+
let detail = expect_refused(outcome, "vendor_go_version_not_selected");
949+
assert!(
950+
detail.contains("the build selects github.com/foo/bar v1.5.0"),
951+
"{detail}"
952+
);
953+
assert_eq!(
954+
tokio::fs::read_to_string(root.join("go.mod"))
955+
.await
956+
.unwrap(),
957+
go_mod
958+
);
959+
assert!(!root.join(".socket/vendor").exists());
960+
}
961+
914962
#[tokio::test]
915963
async fn test_happy_path_wires_copy_replace_and_marker() {
916964
let (dir, blobs, pristine, record) = fixture().await;

0 commit comments

Comments
 (0)