libfetchers/mercurial: handle "evil refs" gracefully
If a revision is specified in a way that looks like a commit hash, Lix expects that it actually is a commit hash. Unlike Git, Mercurial will fall back to bookmarks, tags and branches with the specified name when a commit with the specified hash does not exist. Previously, an assertion failure would be thrown due to the resulting commit hash mismatch. Tell Mercurial to only take commit hashes into account, whose non-existence is then handled gracefully. Change-Id: I98bf020187575f3cf8176831da85872d066c4d95
This commit is contained in:
@@ -246,7 +246,7 @@ struct MercurialInputScheme : InputScheme
|
||||
return makeResult(res->first, std::move(res->second));
|
||||
}
|
||||
|
||||
auto revOrRef = input.getRev() ? input.getRev()->gitRev() : *input.getRef();
|
||||
auto revOrRef = input.getRev() ? fmt("id(%s)", input.getRev()->gitRev()) : *input.getRef();
|
||||
|
||||
Attrs unlockedAttrs({
|
||||
{"type", "hg"},
|
||||
@@ -269,7 +269,7 @@ struct MercurialInputScheme : InputScheme
|
||||
have to pull again. */
|
||||
if (!(input.getRev()
|
||||
&& pathExists(cacheDir)
|
||||
&& runProgram(hgOptions({ "log", "-R", cacheDir, "-r", input.getRev()->gitRev(), "--template", "1" })).second == "1"))
|
||||
&& runProgram(hgOptions({ "identify", "-R", cacheDir, "-r", revOrRef, "--template", "1" })).second == "1"))
|
||||
{
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching Mercurial repository '%s'", actualUrl));
|
||||
|
||||
@@ -294,7 +294,7 @@ struct MercurialInputScheme : InputScheme
|
||||
}
|
||||
|
||||
auto tokens = tokenizeString<std::vector<std::string>>(
|
||||
runHg({ "log", "-R", cacheDir, "-r", revOrRef, "--template", "{node} {count(revset('::{rev}'))} {branch}" }));
|
||||
runHg({ "identify", "-R", cacheDir, "-r", revOrRef, "--template", "{node} {count(revset('::{rev}'))} {branch}" }));
|
||||
assert(tokens.size() == 3);
|
||||
|
||||
input.attrs.insert_or_assign("rev", Hash::parseAny(tokens[0], HashType::SHA1).gitRev());
|
||||
@@ -307,7 +307,7 @@ struct MercurialInputScheme : InputScheme
|
||||
Path tmpDir = createTempDir();
|
||||
AutoDelete delTmpDir(tmpDir, true);
|
||||
|
||||
runHg({ "archive", "-R", cacheDir, "-r", input.getRev()->gitRev(), tmpDir });
|
||||
runHg({ "archive", "-R", cacheDir, "-r", fmt("id(%s)", input.getRev()->gitRev()), tmpDir });
|
||||
|
||||
deletePath(tmpDir + "/.hg_archival.txt");
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ rev1=$(hg log --cwd $repo -r tip --template '{node}')
|
||||
echo world > $repo/hello
|
||||
hg commit --cwd $repo -m 'Bla2'
|
||||
rev2=$(hg log --cwd $repo -r tip --template '{node}')
|
||||
hg --cwd $repo bookmark aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
|
||||
# Fetch an unclean branch.
|
||||
echo unclean > $repo/hello
|
||||
@@ -45,6 +46,10 @@ path=$(nix eval --impure --raw --expr "(builtins.fetchMercurial \"file://$repo\"
|
||||
path2=$(nix eval --impure --raw --expr "(builtins.fetchMercurial { url = \"file://$repo\"; rev = \"$rev2\"; }).outPath")
|
||||
[[ $path = $path2 ]]
|
||||
|
||||
out=$(nix eval --impure --raw --expr "builtins.fetchMercurial { url = \"file://$repo\"; rev = \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"; }" 2>&1) || status=$?
|
||||
[[ $status == 1 ]]
|
||||
[[ $out =~ 'hg failed with exit code' ]]
|
||||
|
||||
# In pure eval mode, fetchMercurial with a revision should succeed.
|
||||
[[ $(nix eval --raw --expr "builtins.readFile (fetchMercurial { url = \"file://$repo\"; rev = \"$rev2\"; } + \"/hello\")") = world ]]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user