mirror of
https://github.com/NixOS/nix
synced 2025-06-25 10:41:16 +02:00
Merge pull request #12283 from DeterminateSystems/type-safe-git-url
Git fetcher: Replace RepoInfo::url by a std::variant
This commit is contained in:
commit
4f0e352ef2
7 changed files with 80 additions and 59 deletions
|
@ -358,7 +358,7 @@ void Input::clone(const Path & destDir) const
|
||||||
scheme->clone(*this, destDir);
|
scheme->clone(*this, destDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Path> Input::getSourcePath() const
|
std::optional<std::filesystem::path> Input::getSourcePath() const
|
||||||
{
|
{
|
||||||
assert(scheme);
|
assert(scheme);
|
||||||
return scheme->getSourcePath(*this);
|
return scheme->getSourcePath(*this);
|
||||||
|
@ -461,7 +461,7 @@ Input InputScheme::applyOverrides(
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Path> InputScheme::getSourcePath(const Input & input) const
|
std::optional<std::filesystem::path> InputScheme::getSourcePath(const Input & input) const
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,7 +164,7 @@ public:
|
||||||
|
|
||||||
void clone(const Path & destDir) const;
|
void clone(const Path & destDir) const;
|
||||||
|
|
||||||
std::optional<Path> getSourcePath() const;
|
std::optional<std::filesystem::path> getSourcePath() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a file to this input, for input types that support
|
* Write a file to this input, for input types that support
|
||||||
|
@ -247,7 +247,7 @@ struct InputScheme
|
||||||
|
|
||||||
virtual void clone(const Input & input, const Path & destDir) const;
|
virtual void clone(const Input & input, const Path & destDir) const;
|
||||||
|
|
||||||
virtual std::optional<Path> getSourcePath(const Input & input) const;
|
virtual std::optional<std::filesystem::path> getSourcePath(const Input & input) const;
|
||||||
|
|
||||||
virtual void putFile(
|
virtual void putFile(
|
||||||
const Input & input,
|
const Input & input,
|
||||||
|
|
|
@ -297,7 +297,7 @@ struct GitInputScheme : InputScheme
|
||||||
|
|
||||||
Strings args = {"clone"};
|
Strings args = {"clone"};
|
||||||
|
|
||||||
args.push_back(repoInfo.url);
|
args.push_back(repoInfo.locationToArg());
|
||||||
|
|
||||||
if (auto ref = input.getRef()) {
|
if (auto ref = input.getRef()) {
|
||||||
args.push_back("--branch");
|
args.push_back("--branch");
|
||||||
|
@ -311,11 +311,9 @@ struct GitInputScheme : InputScheme
|
||||||
runProgram("git", true, args, {}, true);
|
runProgram("git", true, args, {}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Path> getSourcePath(const Input & input) const override
|
std::optional<std::filesystem::path> getSourcePath(const Input & input) const override
|
||||||
{
|
{
|
||||||
auto repoInfo = getRepoInfo(input);
|
return getRepoInfo(input).getPath();
|
||||||
if (repoInfo.isLocal) return repoInfo.url;
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void putFile(
|
void putFile(
|
||||||
|
@ -325,14 +323,15 @@ struct GitInputScheme : InputScheme
|
||||||
std::optional<std::string> commitMsg) const override
|
std::optional<std::string> commitMsg) const override
|
||||||
{
|
{
|
||||||
auto repoInfo = getRepoInfo(input);
|
auto repoInfo = getRepoInfo(input);
|
||||||
if (!repoInfo.isLocal)
|
auto repoPath = repoInfo.getPath();
|
||||||
|
if (!repoPath)
|
||||||
throw Error("cannot commit '%s' to Git repository '%s' because it's not a working tree", path, input.to_string());
|
throw Error("cannot commit '%s' to Git repository '%s' because it's not a working tree", path, input.to_string());
|
||||||
|
|
||||||
writeFile((CanonPath(repoInfo.url) / path).abs(), contents);
|
writeFile(*repoPath / path.rel(), contents);
|
||||||
|
|
||||||
auto result = runProgram(RunOptions {
|
auto result = runProgram(RunOptions {
|
||||||
.program = "git",
|
.program = "git",
|
||||||
.args = {"-C", repoInfo.url, "--git-dir", repoInfo.gitDir, "check-ignore", "--quiet", std::string(path.rel())},
|
.args = {"-C", *repoPath, "--git-dir", repoInfo.gitDir, "check-ignore", "--quiet", std::string(path.rel())},
|
||||||
});
|
});
|
||||||
auto exitCode =
|
auto exitCode =
|
||||||
#ifndef WIN32 // TODO abstract over exit status handling on Windows
|
#ifndef WIN32 // TODO abstract over exit status handling on Windows
|
||||||
|
@ -345,7 +344,7 @@ struct GitInputScheme : InputScheme
|
||||||
if (exitCode != 0) {
|
if (exitCode != 0) {
|
||||||
// The path is not `.gitignore`d, we can add the file.
|
// The path is not `.gitignore`d, we can add the file.
|
||||||
runProgram("git", true,
|
runProgram("git", true,
|
||||||
{ "-C", repoInfo.url, "--git-dir", repoInfo.gitDir, "add", "--intent-to-add", "--", std::string(path.rel()) });
|
{ "-C", *repoPath, "--git-dir", repoInfo.gitDir, "add", "--intent-to-add", "--", std::string(path.rel()) });
|
||||||
|
|
||||||
|
|
||||||
if (commitMsg) {
|
if (commitMsg) {
|
||||||
|
@ -353,7 +352,7 @@ struct GitInputScheme : InputScheme
|
||||||
logger->pause();
|
logger->pause();
|
||||||
Finally restoreLogger([]() { logger->resume(); });
|
Finally restoreLogger([]() { logger->resume(); });
|
||||||
runProgram("git", true,
|
runProgram("git", true,
|
||||||
{ "-C", repoInfo.url, "--git-dir", repoInfo.gitDir, "commit", std::string(path.rel()), "-F", "-" },
|
{ "-C", *repoPath, "--git-dir", repoInfo.gitDir, "commit", std::string(path.rel()), "-F", "-" },
|
||||||
*commitMsg);
|
*commitMsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -361,24 +360,41 @@ struct GitInputScheme : InputScheme
|
||||||
|
|
||||||
struct RepoInfo
|
struct RepoInfo
|
||||||
{
|
{
|
||||||
/* Whether this is a local, non-bare repository. */
|
/* Either the path of the repo (for local, non-bare repos), or
|
||||||
bool isLocal = false;
|
the URL (which is never a `file` URL). */
|
||||||
|
std::variant<std::filesystem::path, ParsedURL> location;
|
||||||
|
|
||||||
/* Working directory info: the complete list of files, and
|
/* Working directory info: the complete list of files, and
|
||||||
whether the working directory is dirty compared to HEAD. */
|
whether the working directory is dirty compared to HEAD. */
|
||||||
GitRepo::WorkdirInfo workdirInfo;
|
GitRepo::WorkdirInfo workdirInfo;
|
||||||
|
|
||||||
/* URL of the repo, or its path if isLocal. Never a `file` URL. */
|
std::string locationToArg() const
|
||||||
std::string url;
|
{
|
||||||
|
return std::visit(
|
||||||
|
overloaded {
|
||||||
|
[&](const std::filesystem::path & path)
|
||||||
|
{ return path.string(); },
|
||||||
|
[&](const ParsedURL & url)
|
||||||
|
{ return url.to_string(); }
|
||||||
|
}, location);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::filesystem::path> getPath() const
|
||||||
|
{
|
||||||
|
if (auto path = std::get_if<std::filesystem::path>(&location))
|
||||||
|
return *path;
|
||||||
|
else
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
void warnDirty(const Settings & settings) const
|
void warnDirty(const Settings & settings) const
|
||||||
{
|
{
|
||||||
if (workdirInfo.isDirty) {
|
if (workdirInfo.isDirty) {
|
||||||
if (!settings.allowDirty)
|
if (!settings.allowDirty)
|
||||||
throw Error("Git tree '%s' is dirty", url);
|
throw Error("Git tree '%s' is dirty", locationToArg());
|
||||||
|
|
||||||
if (settings.warnDirty)
|
if (settings.warnDirty)
|
||||||
warn("Git tree '%s' is dirty", url);
|
warn("Git tree '%s' is dirty", locationToArg());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,7 +441,6 @@ struct GitInputScheme : InputScheme
|
||||||
static bool forceHttp = getEnv("_NIX_FORCE_HTTP") == "1"; // for testing
|
static bool forceHttp = getEnv("_NIX_FORCE_HTTP") == "1"; // for testing
|
||||||
auto url = parseURL(getStrAttr(input.attrs, "url"));
|
auto url = parseURL(getStrAttr(input.attrs, "url"));
|
||||||
bool isBareRepository = url.scheme == "file" && !pathExists(url.path + "/.git");
|
bool isBareRepository = url.scheme == "file" && !pathExists(url.path + "/.git");
|
||||||
repoInfo.isLocal = url.scheme == "file" && !forceHttp && !isBareRepository;
|
|
||||||
//
|
//
|
||||||
// FIXME: here we turn a possibly relative path into an absolute path.
|
// FIXME: here we turn a possibly relative path into an absolute path.
|
||||||
// This allows relative git flake inputs to be resolved against the
|
// This allows relative git flake inputs to be resolved against the
|
||||||
|
@ -435,7 +450,7 @@ struct GitInputScheme : InputScheme
|
||||||
//
|
//
|
||||||
// See: https://discourse.nixos.org/t/57783 and #9708
|
// See: https://discourse.nixos.org/t/57783 and #9708
|
||||||
//
|
//
|
||||||
if (repoInfo.isLocal) {
|
if (url.scheme == "file" && !forceHttp && !isBareRepository) {
|
||||||
if (!isAbsolute(url.path)) {
|
if (!isAbsolute(url.path)) {
|
||||||
warn(
|
warn(
|
||||||
"Fetching Git repository '%s', which uses a path relative to the current directory. "
|
"Fetching Git repository '%s', which uses a path relative to the current directory. "
|
||||||
|
@ -443,14 +458,14 @@ struct GitInputScheme : InputScheme
|
||||||
"See https://github.com/NixOS/nix/issues/12281 for details.",
|
"See https://github.com/NixOS/nix/issues/12281 for details.",
|
||||||
url);
|
url);
|
||||||
}
|
}
|
||||||
repoInfo.url = std::filesystem::absolute(url.path).string();
|
repoInfo.location = std::filesystem::absolute(url.path);
|
||||||
} else
|
} else
|
||||||
repoInfo.url = url.to_string();
|
repoInfo.location = url;
|
||||||
|
|
||||||
// If this is a local directory and no ref or revision is
|
// If this is a local directory and no ref or revision is
|
||||||
// given, then allow the use of an unclean working tree.
|
// given, then allow the use of an unclean working tree.
|
||||||
if (!input.getRef() && !input.getRev() && repoInfo.isLocal)
|
if (auto repoPath = repoInfo.getPath(); !input.getRef() && !input.getRev() && repoPath)
|
||||||
repoInfo.workdirInfo = GitRepo::getCachedWorkdirInfo(repoInfo.url);
|
repoInfo.workdirInfo = GitRepo::getCachedWorkdirInfo(*repoPath);
|
||||||
|
|
||||||
return repoInfo;
|
return repoInfo;
|
||||||
}
|
}
|
||||||
|
@ -480,7 +495,7 @@ struct GitInputScheme : InputScheme
|
||||||
if (auto revCountAttrs = cache->lookup(key))
|
if (auto revCountAttrs = cache->lookup(key))
|
||||||
return getIntAttr(*revCountAttrs, "revCount");
|
return getIntAttr(*revCountAttrs, "revCount");
|
||||||
|
|
||||||
Activity act(*logger, lvlChatty, actUnknown, fmt("getting Git revision count of '%s'", repoInfo.url));
|
Activity act(*logger, lvlChatty, actUnknown, fmt("getting Git revision count of '%s'", repoInfo.locationToArg()));
|
||||||
|
|
||||||
auto revCount = GitRepo::openRepo(repoDir)->getRevCount(rev);
|
auto revCount = GitRepo::openRepo(repoDir)->getRevCount(rev);
|
||||||
|
|
||||||
|
@ -491,11 +506,15 @@ struct GitInputScheme : InputScheme
|
||||||
|
|
||||||
std::string getDefaultRef(const RepoInfo & repoInfo) const
|
std::string getDefaultRef(const RepoInfo & repoInfo) const
|
||||||
{
|
{
|
||||||
auto head = repoInfo.isLocal
|
auto head = std::visit(
|
||||||
? GitRepo::openRepo(repoInfo.url)->getWorkdirRef()
|
overloaded {
|
||||||
: readHeadCached(repoInfo.url);
|
[&](const std::filesystem::path & path)
|
||||||
|
{ return GitRepo::openRepo(path)->getWorkdirRef(); },
|
||||||
|
[&](const ParsedURL & url)
|
||||||
|
{ return readHeadCached(url.to_string()); }
|
||||||
|
}, repoInfo.location);
|
||||||
if (!head) {
|
if (!head) {
|
||||||
warn("could not read HEAD ref from repo at '%s', using 'master'", repoInfo.url);
|
warn("could not read HEAD ref from repo at '%s', using 'master'", repoInfo.locationToArg());
|
||||||
return "master";
|
return "master";
|
||||||
}
|
}
|
||||||
return *head;
|
return *head;
|
||||||
|
@ -540,12 +559,13 @@ struct GitInputScheme : InputScheme
|
||||||
|
|
||||||
Path repoDir;
|
Path repoDir;
|
||||||
|
|
||||||
if (repoInfo.isLocal) {
|
if (auto repoPath = repoInfo.getPath()) {
|
||||||
repoDir = repoInfo.url;
|
repoDir = *repoPath;
|
||||||
if (!input.getRev())
|
if (!input.getRev())
|
||||||
input.attrs.insert_or_assign("rev", GitRepo::openRepo(repoDir)->resolveRef(ref).gitRev());
|
input.attrs.insert_or_assign("rev", GitRepo::openRepo(repoDir)->resolveRef(ref).gitRev());
|
||||||
} else {
|
} else {
|
||||||
Path cacheDir = getCachePath(repoInfo.url, getShallowAttr(input));
|
auto repoUrl = std::get<ParsedURL>(repoInfo.location);
|
||||||
|
Path cacheDir = getCachePath(repoUrl.to_string(), getShallowAttr(input));
|
||||||
repoDir = cacheDir;
|
repoDir = cacheDir;
|
||||||
repoInfo.gitDir = ".";
|
repoInfo.gitDir = ".";
|
||||||
|
|
||||||
|
@ -555,7 +575,7 @@ struct GitInputScheme : InputScheme
|
||||||
auto repo = GitRepo::openRepo(cacheDir, true, true);
|
auto repo = GitRepo::openRepo(cacheDir, true, true);
|
||||||
|
|
||||||
// We need to set the origin so resolving submodule URLs works
|
// We need to set the origin so resolving submodule URLs works
|
||||||
repo->setRemote("origin", repoInfo.url);
|
repo->setRemote("origin", repoUrl.to_string());
|
||||||
|
|
||||||
Path localRefFile =
|
Path localRefFile =
|
||||||
ref.compare(0, 5, "refs/") == 0
|
ref.compare(0, 5, "refs/") == 0
|
||||||
|
@ -594,11 +614,11 @@ struct GitInputScheme : InputScheme
|
||||||
? ref
|
? ref
|
||||||
: "refs/heads/" + ref;
|
: "refs/heads/" + ref;
|
||||||
|
|
||||||
repo->fetch(repoInfo.url, fmt("%s:%s", fetchRef, fetchRef), getShallowAttr(input));
|
repo->fetch(repoUrl.to_string(), fmt("%s:%s", fetchRef, fetchRef), getShallowAttr(input));
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
if (!pathExists(localRefFile)) throw;
|
if (!pathExists(localRefFile)) throw;
|
||||||
logError(e.info());
|
logError(e.info());
|
||||||
warn("could not update local clone of Git repository '%s'; continuing with the most recent version", repoInfo.url);
|
warn("could not update local clone of Git repository '%s'; continuing with the most recent version", repoInfo.locationToArg());
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -607,8 +627,8 @@ struct GitInputScheme : InputScheme
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
warn("could not update mtime for file '%s': %s", localRefFile, e.info().msg);
|
warn("could not update mtime for file '%s': %s", localRefFile, e.info().msg);
|
||||||
}
|
}
|
||||||
if (!originalRef && !storeCachedHead(repoInfo.url, ref))
|
if (!originalRef && !storeCachedHead(repoUrl.to_string(), ref))
|
||||||
warn("could not update cached head '%s' for '%s'", ref, repoInfo.url);
|
warn("could not update cached head '%s' for '%s'", ref, repoInfo.locationToArg());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto rev = input.getRev()) {
|
if (auto rev = input.getRev()) {
|
||||||
|
@ -620,8 +640,7 @@ struct GitInputScheme : InputScheme
|
||||||
"allRefs = true;" ANSI_NORMAL " to " ANSI_BOLD "fetchGit" ANSI_NORMAL ".",
|
"allRefs = true;" ANSI_NORMAL " to " ANSI_BOLD "fetchGit" ANSI_NORMAL ".",
|
||||||
rev->gitRev(),
|
rev->gitRev(),
|
||||||
ref,
|
ref,
|
||||||
repoInfo.url
|
repoInfo.locationToArg());
|
||||||
);
|
|
||||||
} else
|
} else
|
||||||
input.attrs.insert_or_assign("rev", repo->resolveRef(ref).gitRev());
|
input.attrs.insert_or_assign("rev", repo->resolveRef(ref).gitRev());
|
||||||
|
|
||||||
|
@ -633,7 +652,7 @@ struct GitInputScheme : InputScheme
|
||||||
auto isShallow = repo->isShallow();
|
auto isShallow = repo->isShallow();
|
||||||
|
|
||||||
if (isShallow && !getShallowAttr(input))
|
if (isShallow && !getShallowAttr(input))
|
||||||
throw Error("'%s' is a shallow Git repository, but shallow repositories are only allowed when `shallow = true;` is specified", repoInfo.url);
|
throw Error("'%s' is a shallow Git repository, but shallow repositories are only allowed when `shallow = true;` is specified", repoInfo.locationToArg());
|
||||||
|
|
||||||
// FIXME: check whether rev is an ancestor of ref?
|
// FIXME: check whether rev is an ancestor of ref?
|
||||||
|
|
||||||
|
@ -648,7 +667,7 @@ struct GitInputScheme : InputScheme
|
||||||
infoAttrs.insert_or_assign("revCount",
|
infoAttrs.insert_or_assign("revCount",
|
||||||
getRevCount(repoInfo, repoDir, rev));
|
getRevCount(repoInfo, repoDir, rev));
|
||||||
|
|
||||||
printTalkative("using revision %s of repo '%s'", rev.gitRev(), repoInfo.url);
|
printTalkative("using revision %s of repo '%s'", rev.gitRev(), repoInfo.locationToArg());
|
||||||
|
|
||||||
verifyCommit(input, repo);
|
verifyCommit(input, repo);
|
||||||
|
|
||||||
|
@ -702,21 +721,23 @@ struct GitInputScheme : InputScheme
|
||||||
RepoInfo & repoInfo,
|
RepoInfo & repoInfo,
|
||||||
Input && input) const
|
Input && input) const
|
||||||
{
|
{
|
||||||
|
auto repoPath = repoInfo.getPath().value();
|
||||||
|
|
||||||
if (getSubmodulesAttr(input))
|
if (getSubmodulesAttr(input))
|
||||||
/* Create mountpoints for the submodules. */
|
/* Create mountpoints for the submodules. */
|
||||||
for (auto & submodule : repoInfo.workdirInfo.submodules)
|
for (auto & submodule : repoInfo.workdirInfo.submodules)
|
||||||
repoInfo.workdirInfo.files.insert(submodule.path);
|
repoInfo.workdirInfo.files.insert(submodule.path);
|
||||||
|
|
||||||
auto repo = GitRepo::openRepo(repoInfo.url, false, false);
|
auto repo = GitRepo::openRepo(repoPath, false, false);
|
||||||
|
|
||||||
auto exportIgnore = getExportIgnoreAttr(input);
|
auto exportIgnore = getExportIgnoreAttr(input);
|
||||||
|
|
||||||
ref<SourceAccessor> accessor =
|
ref<SourceAccessor> accessor =
|
||||||
repo->getAccessor(repoInfo.workdirInfo,
|
repo->getAccessor(repoInfo.workdirInfo,
|
||||||
exportIgnore,
|
exportIgnore,
|
||||||
makeNotAllowedError(repoInfo.url));
|
makeNotAllowedError(repoInfo.locationToArg()));
|
||||||
|
|
||||||
accessor->setPathDisplay(repoInfo.url);
|
accessor->setPathDisplay(repoInfo.locationToArg());
|
||||||
|
|
||||||
/* If the repo has submodules, return a mounted input accessor
|
/* If the repo has submodules, return a mounted input accessor
|
||||||
consisting of the accessor for the top-level repo and the
|
consisting of the accessor for the top-level repo and the
|
||||||
|
@ -725,10 +746,10 @@ struct GitInputScheme : InputScheme
|
||||||
std::map<CanonPath, nix::ref<SourceAccessor>> mounts;
|
std::map<CanonPath, nix::ref<SourceAccessor>> mounts;
|
||||||
|
|
||||||
for (auto & submodule : repoInfo.workdirInfo.submodules) {
|
for (auto & submodule : repoInfo.workdirInfo.submodules) {
|
||||||
auto submodulePath = CanonPath(repoInfo.url) / submodule.path;
|
auto submodulePath = repoPath / submodule.path.rel();
|
||||||
fetchers::Attrs attrs;
|
fetchers::Attrs attrs;
|
||||||
attrs.insert_or_assign("type", "git");
|
attrs.insert_or_assign("type", "git");
|
||||||
attrs.insert_or_assign("url", submodulePath.abs());
|
attrs.insert_or_assign("url", submodulePath.string());
|
||||||
attrs.insert_or_assign("exportIgnore", Explicit<bool>{ exportIgnore });
|
attrs.insert_or_assign("exportIgnore", Explicit<bool>{ exportIgnore });
|
||||||
attrs.insert_or_assign("submodules", Explicit<bool>{ true });
|
attrs.insert_or_assign("submodules", Explicit<bool>{ true });
|
||||||
// TODO: fall back to getAccessorFromCommit-like fetch when submodules aren't checked out
|
// TODO: fall back to getAccessorFromCommit-like fetch when submodules aren't checked out
|
||||||
|
@ -752,7 +773,7 @@ struct GitInputScheme : InputScheme
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!repoInfo.workdirInfo.isDirty) {
|
if (!repoInfo.workdirInfo.isDirty) {
|
||||||
auto repo = GitRepo::openRepo(repoInfo.url);
|
auto repo = GitRepo::openRepo(repoPath);
|
||||||
|
|
||||||
if (auto ref = repo->getWorkdirRef())
|
if (auto ref = repo->getWorkdirRef())
|
||||||
input.attrs.insert_or_assign("ref", *ref);
|
input.attrs.insert_or_assign("ref", *ref);
|
||||||
|
@ -762,7 +783,7 @@ struct GitInputScheme : InputScheme
|
||||||
|
|
||||||
input.attrs.insert_or_assign("rev", rev.gitRev());
|
input.attrs.insert_or_assign("rev", rev.gitRev());
|
||||||
input.attrs.insert_or_assign("revCount",
|
input.attrs.insert_or_assign("revCount",
|
||||||
rev == nullRev ? 0 : getRevCount(repoInfo, repoInfo.url, rev));
|
rev == nullRev ? 0 : getRevCount(repoInfo, repoPath, rev));
|
||||||
|
|
||||||
verifyCommit(input, repo);
|
verifyCommit(input, repo);
|
||||||
} else {
|
} else {
|
||||||
|
@ -781,7 +802,7 @@ struct GitInputScheme : InputScheme
|
||||||
input.attrs.insert_or_assign(
|
input.attrs.insert_or_assign(
|
||||||
"lastModified",
|
"lastModified",
|
||||||
repoInfo.workdirInfo.headRev
|
repoInfo.workdirInfo.headRev
|
||||||
? getLastModified(repoInfo, repoInfo.url, *repoInfo.workdirInfo.headRev)
|
? getLastModified(repoInfo, repoPath, *repoInfo.workdirInfo.headRev)
|
||||||
: 0);
|
: 0);
|
||||||
|
|
||||||
return {accessor, std::move(input)};
|
return {accessor, std::move(input)};
|
||||||
|
@ -804,7 +825,7 @@ struct GitInputScheme : InputScheme
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [accessor, final] =
|
auto [accessor, final] =
|
||||||
input.getRef() || input.getRev() || !repoInfo.isLocal
|
input.getRef() || input.getRev() || !repoInfo.getPath()
|
||||||
? getAccessorFromCommit(store, repoInfo, std::move(input))
|
? getAccessorFromCommit(store, repoInfo, std::move(input))
|
||||||
: getAccessorFromWorkdir(store, repoInfo, std::move(input));
|
: getAccessorFromWorkdir(store, repoInfo, std::move(input));
|
||||||
|
|
||||||
|
@ -822,14 +843,14 @@ struct GitInputScheme : InputScheme
|
||||||
return makeFingerprint(*rev);
|
return makeFingerprint(*rev);
|
||||||
else {
|
else {
|
||||||
auto repoInfo = getRepoInfo(input);
|
auto repoInfo = getRepoInfo(input);
|
||||||
if (repoInfo.isLocal && repoInfo.workdirInfo.headRev && repoInfo.workdirInfo.submodules.empty()) {
|
if (auto repoPath = repoInfo.getPath(); repoPath && repoInfo.workdirInfo.headRev && repoInfo.workdirInfo.submodules.empty()) {
|
||||||
/* Calculate a fingerprint that takes into account the
|
/* Calculate a fingerprint that takes into account the
|
||||||
deleted and modified/added files. */
|
deleted and modified/added files. */
|
||||||
HashSink hashSink{HashAlgorithm::SHA512};
|
HashSink hashSink{HashAlgorithm::SHA512};
|
||||||
for (auto & file : repoInfo.workdirInfo.dirtyFiles) {
|
for (auto & file : repoInfo.workdirInfo.dirtyFiles) {
|
||||||
writeString("modified:", hashSink);
|
writeString("modified:", hashSink);
|
||||||
writeString(file.abs(), hashSink);
|
writeString(file.abs(), hashSink);
|
||||||
dumpPath(repoInfo.url + "/" + file.abs(), hashSink);
|
dumpPath(*repoPath / file.rel(), hashSink);
|
||||||
}
|
}
|
||||||
for (auto & file : repoInfo.workdirInfo.deletedFiles) {
|
for (auto & file : repoInfo.workdirInfo.deletedFiles) {
|
||||||
writeString("deleted:", hashSink);
|
writeString("deleted:", hashSink);
|
||||||
|
|
|
@ -126,7 +126,7 @@ struct MercurialInputScheme : InputScheme
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Path> getSourcePath(const Input & input) const override
|
std::optional<std::filesystem::path> getSourcePath(const Input & input) const override
|
||||||
{
|
{
|
||||||
auto url = parseURL(getStrAttr(input.attrs, "url"));
|
auto url = parseURL(getStrAttr(input.attrs, "url"));
|
||||||
if (url.scheme == "file" && !input.getRef() && !input.getRev())
|
if (url.scheme == "file" && !input.getRef() && !input.getRev())
|
||||||
|
|
|
@ -80,9 +80,9 @@ struct PathInputScheme : InputScheme
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Path> getSourcePath(const Input & input) const override
|
std::optional<std::filesystem::path> getSourcePath(const Input & input) const override
|
||||||
{
|
{
|
||||||
return getStrAttr(input.attrs, "path");
|
return getAbsPath(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
void putFile(
|
void putFile(
|
||||||
|
|
|
@ -781,7 +781,7 @@ LockedFlake lockFlake(
|
||||||
writeFile(*lockFlags.outputLockFilePath, newLockFileS);
|
writeFile(*lockFlags.outputLockFilePath, newLockFileS);
|
||||||
} else {
|
} else {
|
||||||
auto relPath = (topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock";
|
auto relPath = (topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock";
|
||||||
auto outputLockFilePath = *sourcePath + "/" + relPath;
|
auto outputLockFilePath = *sourcePath / relPath;
|
||||||
|
|
||||||
bool lockFileExists = pathExists(outputLockFilePath);
|
bool lockFileExists = pathExists(outputLockFilePath);
|
||||||
|
|
||||||
|
|
|
@ -696,7 +696,7 @@ struct CmdDevelop : Common, MixEnvironment
|
||||||
auto sourcePath = installableFlake->getLockedFlake()->flake.resolvedRef.input.getSourcePath();
|
auto sourcePath = installableFlake->getLockedFlake()->flake.resolvedRef.input.getSourcePath();
|
||||||
if (sourcePath) {
|
if (sourcePath) {
|
||||||
if (chdir(sourcePath->c_str()) == -1) {
|
if (chdir(sourcePath->c_str()) == -1) {
|
||||||
throw SysError("chdir to '%s' failed", *sourcePath);
|
throw SysError("chdir to %s failed", *sourcePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue