Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/libfetchers/fetch-settings.hh
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ struct FetchSettings : public Config
Setting<bool> warnDirty{this, true, "warn-dirty",
"Whether to warn about dirty Git/Mercurial trees."};

Setting<bool> includeUntrackedFiles{this, false, "include-untracked-files",
"Whether to include untracked files in Git/Mercurial trees."};

Setting<std::string> flakeRegistry{this, "https://channels.nixos.org/flake-registry.json", "flake-registry",
R"(
Path or URI of the global flake registry.
Expand Down
6 changes: 5 additions & 1 deletion src/libfetchers/git-utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
return (*((std::function<int(const char * path, unsigned int statusFlags)> *) payload))(path, statusFlags);
}

WorkdirInfo getWorkdirInfo() override
WorkdirInfo getWorkdirInfo(bool includeUntrackedFiles) override
{
WorkdirInfo info;

Expand All @@ -284,6 +284,10 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
git_status_options options = GIT_STATUS_OPTIONS_INIT;
options.flags |= GIT_STATUS_OPT_INCLUDE_UNMODIFIED;
options.flags |= GIT_STATUS_OPT_EXCLUDE_SUBMODULES;
if (includeUntrackedFiles) {
options.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED |
GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS;
}
if (git_status_foreach_ext(*this, &options, &statusCallbackTrampoline, &statusCallback))
throw Error("getting working directory status: %s", git_error_last()->message);

Expand Down
2 changes: 1 addition & 1 deletion src/libfetchers/git-utils.hh
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ struct GitRepo
std::vector<Submodule> submodules;
};

virtual WorkdirInfo getWorkdirInfo() = 0;
virtual WorkdirInfo getWorkdirInfo(bool includeUntrackedFiles) = 0;

/* Get the ref that HEAD points to. */
virtual std::optional<std::string> getWorkdirRef() = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/libfetchers/git.cc
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ struct GitInputScheme : InputScheme
// If this is a local directory and no ref or revision is
// given, then allow the use of an unclean working tree.
if (!input.getRef() && !input.getRev() && repoInfo.isLocal)
repoInfo.workdirInfo = GitRepo::openRepo(CanonPath(repoInfo.url))->getWorkdirInfo();
repoInfo.workdirInfo = GitRepo::openRepo(CanonPath(repoInfo.url))->getWorkdirInfo(fetchSettings.includeUntrackedFiles);

return repoInfo;
}
Expand Down
10 changes: 8 additions & 2 deletions src/libfetchers/mercurial.cc
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,10 @@ struct MercurialInputScheme : InputScheme

if (!input.getRef() && !input.getRev() && isLocal && pathExists(actualUrl + "/.hg")) {

bool clean = runHg({ "status", "-R", actualUrl, "--modified", "--added", "--removed" }) == "";
Strings hgStatusOptions = { "status", "-R", actualUrl, "--modified", "--added", "--removed" };
if (fetchSettings.includeUntrackedFiles)
hgStatusOptions.push_back("--unknown");
bool clean = runHg(hgStatusOptions) == "";

if (!clean) {

Expand All @@ -190,8 +193,11 @@ struct MercurialInputScheme : InputScheme

input.attrs.insert_or_assign("ref", chomp(runHg({ "branch", "-R", actualUrl })));

hgStatusOptions = { "status", "-R", actualUrl, "--clean", "--modified", "--added", "--no-status", "--print0" };
if (fetchSettings.includeUntrackedFiles)
hgStatusOptions.push_back("--unknown");
auto files = tokenizeString<std::set<std::string>>(
runHg({ "status", "-R", actualUrl, "--clean", "--modified", "--added", "--no-status", "--print0" }), "\0"s);
runHg(hgStatusOptions), "\0"s);

Path actualPath(absPath(actualUrl));

Expand Down
19 changes: 19 additions & 0 deletions tests/functional/fetchGit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,25 @@ path2=$(nix eval --impure --raw --expr "(builtins.fetchGit $repo).outPath")
[ ! -e $path2/.git ]
[[ $(cat $path2/dir1/foo) = foo ]]

# Using an unclean tree with --include-git-untracked-files option should yield the tracked and uncommitted changes
path21=$(nix eval --include-untracked-files --impure --raw --expr "(builtins.fetchGit $repo).outPath")
[ ! -e $path21/hello ]
[ -e $path21/bar ]
[ -e $path21/dir2/bar ]
[ ! -e $path21/.git ]
[[ $(cat $path21/dir1/foo) = foo ]]

# Using an unclean tree with --include-git-untracked-files option should take into account .gitignore files
echo "/bar" >> $repo/.gitignore
echo "bar" >> $repo/dir2/.gitignore
path22=$(nix eval --include-untracked-files --impure --raw --expr "(builtins.fetchGit $repo).outPath")
[ ! -e $path22/hello ]
[ ! -e $path22/bar ]
[ ! -e $path22/dir2/bar ]
[ ! -e $path22/.git ]
git -C $repo checkout -- $repo/.gitignore
git -C $repo clean -fd

[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).rev") = 0000000000000000000000000000000000000000 ]]
[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).dirtyRev") = "${rev2}-dirty" ]]
[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).dirtyShortRev") = "${rev2:0:7}-dirty" ]]
Expand Down
18 changes: 17 additions & 1 deletion tests/functional/fetchMercurial.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
source common.sh

[[ $(type -p hq) ]] || skipTest "Mercurial not installed"
[[ $(type -p hg) ]] || skipTest "Mercurial not installed"

clearStore

Expand Down Expand Up @@ -88,6 +88,22 @@ path2=$(nix eval --impure --raw --expr "(builtins.fetchMercurial $repo).outPath"
[ ! -e $path2/.hg ]
[[ $(cat $path2/dir1/foo) = foo ]]

path21=$(nix eval --include-untracked-files --impure --raw --expr "(builtins.fetchMercurial $repo).outPath")
[ ! -e $path21/hello ]
[ -e $path21/bar ]
[ -e $path21/dir2/bar ]
[ ! -e $path21/.hg ]
[[ $(cat $path21/dir1/foo) = foo ]]

echo "bar" >> $repo/.hgignore
path22=$(nix eval --include-untracked-files --impure --raw --expr "(builtins.fetchMercurial $repo).outPath")
[ ! -e $path22/hello ]
[ ! -e $path22/bar ]
[ ! -e $path22/dir2/bar ]
[ ! -e $path22/.git ]
sed -i '/bar/d' $repo/.hgignore
hg status --cwd $repo

[[ $(nix eval --impure --raw --expr "(builtins.fetchMercurial $repo).rev") = 0000000000000000000000000000000000000000 ]]

# ... unless we're using an explicit ref.
Expand Down
2 changes: 1 addition & 1 deletion tests/functional/flakes/mercurial.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
source ./common.sh

[[ $(type -p hq) ]] || skipTest "Mercurial not installed"
[[ $(type -p hg) ]] || skipTest "Mercurial not installed"

flake1Dir=$TEST_ROOT/flake-hg1
mkdir -p $flake1Dir
Expand Down