Skip to content

Commit 4f9c962

Browse files
committed
In the legacy case if submodules = true, use git checkout
That's what Nix < 2.20 did (which means that it behaved differently from the `submodules = false`, by not applying `export-ignore`).
1 parent 90ca8c3 commit 4f9c962

File tree

1 file changed

+40
-18
lines changed

1 file changed

+40
-18
lines changed

src/libfetchers/git.cc

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -648,10 +648,10 @@ struct GitInputScheme : InputScheme
648648
}
649649

650650
/**
651-
* Get a `SourceAccessor` for the given Git revision by creating a git archive and unpacking it to the Nix store.
652-
* This is used for Nix < 2.20 compatibility.
651+
* Get a `SourceAccessor` for the given Git revision using Nix < 2.20 semantics, i.e. using `git archive` or `git
652+
* checkout`.
653653
*/
654-
ref<SourceAccessor> getGitArchiveAccessor(
654+
ref<SourceAccessor> getLegacyGitAccessor(
655655
Store & store,
656656
RepoInfo & repoInfo,
657657
const std::filesystem::path & repoDir,
@@ -661,27 +661,49 @@ struct GitInputScheme : InputScheme
661661
auto tmpDir = createTempDir();
662662
AutoDelete delTmpDir(tmpDir, true);
663663

664-
auto source = sinkToSource([&](Sink & sink) {
665-
runProgram2(
666-
{.program = "git",
667-
.args = {"-C", repoDir, "--git-dir", repoInfo.gitDir, "archive", rev.gitRev()},
668-
.standardOut = &sink});
669-
});
670-
671-
unpackTarfile(*source, tmpDir);
672-
673-
auto storePath = store.addToStore("source", {getFSSourceAccessor(), CanonPath(tmpDir)});
664+
auto storePath =
665+
options.submodules
666+
? [&]() {
667+
// Nix < 2.20 used `git checkout` for repos with submodules.
668+
runProgram2({.program = "git", .args = {"init", tmpDir}});
669+
runProgram2({.program = "git", .args = {"-C", tmpDir, "remote", "add", "origin", repoDir}});
670+
runProgram2({.program = "git", .args = {"-C", tmpDir, "fetch", "origin", rev.gitRev()}});
671+
runProgram2({.program = "git", .args = {"-C", tmpDir, "checkout", rev.gitRev()}});
672+
PathFilter filter = [&](const Path & path) { return baseNameOf(path) != ".git"; };
673+
return store.addToStore(
674+
"source",
675+
{getFSSourceAccessor(), CanonPath(tmpDir)},
676+
ContentAddressMethod::Raw::NixArchive,
677+
HashAlgorithm::SHA256,
678+
{},
679+
filter);
680+
}()
681+
: [&]() {
682+
// Nix < 2.20 used `git archive` for repos without submodules.
683+
options.exportIgnore = true;
684+
685+
auto source = sinkToSource([&](Sink & sink) {
686+
runProgram2(
687+
{.program = "git",
688+
.args = {"-C", repoDir, "--git-dir", repoInfo.gitDir, "archive", rev.gitRev()},
689+
.standardOut = &sink});
690+
});
691+
692+
unpackTarfile(*source, tmpDir);
693+
694+
return store.addToStore("source", {getFSSourceAccessor(), CanonPath(tmpDir)});
695+
}();
674696

675697
auto accessor = store.getFSAccessor(storePath);
676698

677-
options.exportIgnore = true;
678-
accessor->fingerprint = options.makeFingerprint(rev) + ";f";
699+
accessor->fingerprint = options.makeFingerprint(rev) + ";legacy";
679700

680701
return ref{accessor};
681702
}
682703

683704
std::pair<ref<SourceAccessor>, Input>
684705
getAccessorFromCommit(const Settings & settings, ref<Store> store, RepoInfo & repoInfo, Input && input) const
706+
685707
{
686708
assert(!repoInfo.workdirInfo.isDirty);
687709

@@ -833,7 +855,7 @@ struct GitInputScheme : InputScheme
833855
* as well. */
834856
warn("Using Nix 2.19 semantics to export Git repository '%s'.", input.to_string());
835857
auto accessorModern = accessor;
836-
accessor = getGitArchiveAccessor(*store, repoInfo, repoDir, rev, options);
858+
accessor = getLegacyGitAccessor(*store, repoInfo, repoDir, rev, options);
837859
if (expectedNarHash) {
838860
auto narHashLegacy =
839861
fetchToStore2(settings, *store, {accessor}, FetchMode::DryRun, input.getName()).second;
@@ -851,7 +873,7 @@ struct GitInputScheme : InputScheme
851873
auto narHashNew = fetchToStore2(settings, *store, {accessor}, FetchMode::DryRun, input.getName()).second;
852874
if (expectedNarHash && accessor->pathExists(CanonPath(".gitattributes"))) {
853875
if (expectedNarHash != narHashNew) {
854-
auto accessorLegacy = getGitArchiveAccessor(*store, repoInfo, repoDir, rev, options);
876+
auto accessorLegacy = getLegacyGitAccessor(*store, repoInfo, repoDir, rev, options);
855877
auto narHashLegacy =
856878
fetchToStore2(settings, *store, {accessorLegacy}, FetchMode::DryRun, input.getName()).second;
857879
if (expectedNarHash == narHashLegacy) {
@@ -1033,7 +1055,7 @@ struct GitInputScheme : InputScheme
10331055

10341056
if (auto rev = input.getRev())
10351057
// FIXME: this can return a wrong fingerprint for the legacy (`git archive`) case, since we don't know here
1036-
// whether to append the `;f` suffix or not.
1058+
// whether to append the `;legacy` suffix or not.
10371059
return options.makeFingerprint(*rev);
10381060
else {
10391061
auto repoInfo = getRepoInfo(input);

0 commit comments

Comments
 (0)