forked from lix-project/lix
Merge pull request #4275 from lukegb/mercurialHGPLAIN
fetchMercurial: set HGPLAIN when invoking hg
This commit is contained in:
commit
eb6b9bd672
|
@ -11,6 +11,36 @@ using namespace std::string_literals;
|
||||||
|
|
||||||
namespace nix::fetchers {
|
namespace nix::fetchers {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
RunOptions hgOptions(const Strings & args) {
|
||||||
|
RunOptions opts("hg", args);
|
||||||
|
opts.searchPath = true;
|
||||||
|
|
||||||
|
auto env = getEnv();
|
||||||
|
// Set HGPLAIN: this means we get consistent output from hg and avoids leakage from a user or system .hgrc.
|
||||||
|
env["HGPLAIN"] = "";
|
||||||
|
opts.environment = env;
|
||||||
|
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
// runProgram wrapper that uses hgOptions instead of stock RunOptions.
|
||||||
|
string runHg(const Strings & args, const std::optional<std::string> & input = {})
|
||||||
|
{
|
||||||
|
RunOptions opts = hgOptions(args);
|
||||||
|
opts.input = input;
|
||||||
|
|
||||||
|
auto res = runProgram(opts);
|
||||||
|
|
||||||
|
if (!statusOk(res.first))
|
||||||
|
throw ExecError(res.first, fmt("hg %1%", statusToString(res.first)));
|
||||||
|
|
||||||
|
return res.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
struct MercurialInputScheme : InputScheme
|
struct MercurialInputScheme : InputScheme
|
||||||
{
|
{
|
||||||
std::optional<Input> inputFromURL(const ParsedURL & url) override
|
std::optional<Input> inputFromURL(const ParsedURL & url) override
|
||||||
|
@ -100,11 +130,11 @@ struct MercurialInputScheme : InputScheme
|
||||||
assert(sourcePath);
|
assert(sourcePath);
|
||||||
|
|
||||||
// FIXME: shut up if file is already tracked.
|
// FIXME: shut up if file is already tracked.
|
||||||
runProgram("hg", true,
|
runHg(
|
||||||
{ "add", *sourcePath + "/" + std::string(file) });
|
{ "add", *sourcePath + "/" + std::string(file) });
|
||||||
|
|
||||||
if (commitMsg)
|
if (commitMsg)
|
||||||
runProgram("hg", true,
|
runHg(
|
||||||
{ "commit", *sourcePath + "/" + std::string(file), "-m", *commitMsg });
|
{ "commit", *sourcePath + "/" + std::string(file), "-m", *commitMsg });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +160,7 @@ struct MercurialInputScheme : InputScheme
|
||||||
|
|
||||||
if (!input.getRef() && !input.getRev() && isLocal && pathExists(actualUrl + "/.hg")) {
|
if (!input.getRef() && !input.getRev() && isLocal && pathExists(actualUrl + "/.hg")) {
|
||||||
|
|
||||||
bool clean = runProgram("hg", true, { "status", "-R", actualUrl, "--modified", "--added", "--removed" }) == "";
|
bool clean = runHg({ "status", "-R", actualUrl, "--modified", "--added", "--removed" }) == "";
|
||||||
|
|
||||||
if (!clean) {
|
if (!clean) {
|
||||||
|
|
||||||
|
@ -143,10 +173,10 @@ struct MercurialInputScheme : InputScheme
|
||||||
if (settings.warnDirty)
|
if (settings.warnDirty)
|
||||||
warn("Mercurial tree '%s' is unclean", actualUrl);
|
warn("Mercurial tree '%s' is unclean", actualUrl);
|
||||||
|
|
||||||
input.attrs.insert_or_assign("ref", chomp(runProgram("hg", true, { "branch", "-R", actualUrl })));
|
input.attrs.insert_or_assign("ref", chomp(runHg({ "branch", "-R", actualUrl })));
|
||||||
|
|
||||||
auto files = tokenizeString<std::set<std::string>>(
|
auto files = tokenizeString<std::set<std::string>>(
|
||||||
runProgram("hg", true, { "status", "-R", actualUrl, "--clean", "--modified", "--added", "--no-status", "--print0" }), "\0"s);
|
runHg({ "status", "-R", actualUrl, "--clean", "--modified", "--added", "--no-status", "--print0" }), "\0"s);
|
||||||
|
|
||||||
PathFilter filter = [&](const Path & p) -> bool {
|
PathFilter filter = [&](const Path & p) -> bool {
|
||||||
assert(hasPrefix(p, actualUrl));
|
assert(hasPrefix(p, actualUrl));
|
||||||
|
@ -224,33 +254,33 @@ struct MercurialInputScheme : InputScheme
|
||||||
if (!(input.getRev()
|
if (!(input.getRev()
|
||||||
&& pathExists(cacheDir)
|
&& pathExists(cacheDir)
|
||||||
&& runProgram(
|
&& runProgram(
|
||||||
RunOptions("hg", { "log", "-R", cacheDir, "-r", input.getRev()->gitRev(), "--template", "1" })
|
hgOptions({ "log", "-R", cacheDir, "-r", input.getRev()->gitRev(), "--template", "1" })
|
||||||
.killStderr(true)).second == "1"))
|
.killStderr(true)).second == "1"))
|
||||||
{
|
{
|
||||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching Mercurial repository '%s'", actualUrl));
|
Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching Mercurial repository '%s'", actualUrl));
|
||||||
|
|
||||||
if (pathExists(cacheDir)) {
|
if (pathExists(cacheDir)) {
|
||||||
try {
|
try {
|
||||||
runProgram("hg", true, { "pull", "-R", cacheDir, "--", actualUrl });
|
runHg({ "pull", "-R", cacheDir, "--", actualUrl });
|
||||||
}
|
}
|
||||||
catch (ExecError & e) {
|
catch (ExecError & e) {
|
||||||
string transJournal = cacheDir + "/.hg/store/journal";
|
string transJournal = cacheDir + "/.hg/store/journal";
|
||||||
/* hg throws "abandoned transaction" error only if this file exists */
|
/* hg throws "abandoned transaction" error only if this file exists */
|
||||||
if (pathExists(transJournal)) {
|
if (pathExists(transJournal)) {
|
||||||
runProgram("hg", true, { "recover", "-R", cacheDir });
|
runHg({ "recover", "-R", cacheDir });
|
||||||
runProgram("hg", true, { "pull", "-R", cacheDir, "--", actualUrl });
|
runHg({ "pull", "-R", cacheDir, "--", actualUrl });
|
||||||
} else {
|
} else {
|
||||||
throw ExecError(e.status, fmt("'hg pull' %s", statusToString(e.status)));
|
throw ExecError(e.status, fmt("'hg pull' %s", statusToString(e.status)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
createDirs(dirOf(cacheDir));
|
createDirs(dirOf(cacheDir));
|
||||||
runProgram("hg", true, { "clone", "--noupdate", "--", actualUrl, cacheDir });
|
runHg({ "clone", "--noupdate", "--", actualUrl, cacheDir });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto tokens = tokenizeString<std::vector<std::string>>(
|
auto tokens = tokenizeString<std::vector<std::string>>(
|
||||||
runProgram("hg", true, { "log", "-R", cacheDir, "-r", revOrRef, "--template", "{node} {rev} {branch}" }));
|
runHg({ "log", "-R", cacheDir, "-r", revOrRef, "--template", "{node} {rev} {branch}" }));
|
||||||
assert(tokens.size() == 3);
|
assert(tokens.size() == 3);
|
||||||
|
|
||||||
input.attrs.insert_or_assign("rev", Hash::parseAny(tokens[0], htSHA1).gitRev());
|
input.attrs.insert_or_assign("rev", Hash::parseAny(tokens[0], htSHA1).gitRev());
|
||||||
|
@ -263,7 +293,7 @@ struct MercurialInputScheme : InputScheme
|
||||||
Path tmpDir = createTempDir();
|
Path tmpDir = createTempDir();
|
||||||
AutoDelete delTmpDir(tmpDir, true);
|
AutoDelete delTmpDir(tmpDir, true);
|
||||||
|
|
||||||
runProgram("hg", true, { "archive", "-R", cacheDir, "-r", input.getRev()->gitRev(), tmpDir });
|
runHg({ "archive", "-R", cacheDir, "-r", input.getRev()->gitRev(), tmpDir });
|
||||||
|
|
||||||
deletePath(tmpDir + "/.hg_archival.txt");
|
deletePath(tmpDir + "/.hg_archival.txt");
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,9 @@ hg init $repo
|
||||||
echo '[ui]' >> $repo/.hg/hgrc
|
echo '[ui]' >> $repo/.hg/hgrc
|
||||||
echo 'username = Foobar <foobar@example.org>' >> $repo/.hg/hgrc
|
echo 'username = Foobar <foobar@example.org>' >> $repo/.hg/hgrc
|
||||||
|
|
||||||
|
# Set ui.tweakdefaults to ensure HGPLAIN is being set.
|
||||||
|
echo 'tweakdefaults = True' >> $repo/.hg/hgrc
|
||||||
|
|
||||||
echo utrecht > $repo/hello
|
echo utrecht > $repo/hello
|
||||||
touch $repo/.hgignore
|
touch $repo/.hgignore
|
||||||
hg add --cwd $repo hello .hgignore
|
hg add --cwd $repo hello .hgignore
|
||||||
|
|
Loading…
Reference in a new issue