Skip to content

Commit f22359b

Browse files
authored
Merge pull request #12287 from bryango/2.24-maintenance
Backport git+file:./ fixes to 2.24 (#12107 + #12277)
2 parents f366bea + 876d724 commit f22359b

File tree

10 files changed

+58
-12
lines changed

10 files changed

+58
-12
lines changed

src/libexpr/eval.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ void EvalState::checkURI(const std::string & uri)
438438

439439
/* If the URI is a path, then check it against allowedPaths as
440440
well. */
441-
if (hasPrefix(uri, "/")) {
441+
if (isAbsolute(uri)) {
442442
if (auto rootFS2 = rootFS.dynamic_pointer_cast<AllowListSourceAccessor>())
443443
rootFS2->checkAccess(CanonPath(uri));
444444
return;

src/libfetchers/git.cc

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,26 @@ struct GitInputScheme : InputScheme
425425
auto url = parseURL(getStrAttr(input.attrs, "url"));
426426
bool isBareRepository = url.scheme == "file" && !pathExists(url.path + "/.git");
427427
repoInfo.isLocal = url.scheme == "file" && !forceHttp && !isBareRepository;
428-
repoInfo.url = repoInfo.isLocal ? url.path : url.base;
428+
//
429+
// FIXME: here we turn a possibly relative path into an absolute path.
430+
// This allows relative git flake inputs to be resolved against the
431+
// **current working directory** (as in POSIX), which tends to work out
432+
// ok in the context of flakes, but is the wrong behavior,
433+
// as it should resolve against the flake.nix base directory instead.
434+
//
435+
// See: https://discourse.nixos.org/t/57783 and #9708
436+
//
437+
if (repoInfo.isLocal) {
438+
if (!isAbsolute(url.path)) {
439+
warn(
440+
"Fetching Git repository '%s', which uses a path relative to the current directory. "
441+
"This is not supported and will stop working in a future release. "
442+
"See https://github.com/NixOS/nix/issues/12281 for details.",
443+
url.to_string());
444+
}
445+
repoInfo.url = std::filesystem::absolute(url.path).string();
446+
} else
447+
repoInfo.url = url.to_string();
429448

430449
// If this is a local directory and no ref or revision is
431450
// given, then allow the use of an unclean working tree.

src/libfetchers/path.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ struct PathInputScheme : InputScheme
9696
std::optional<std::string> isRelative(const Input & input) const
9797
{
9898
auto path = getStrAttr(input.attrs, "path");
99-
if (hasPrefix(path, "/"))
99+
if (isAbsolute(path))
100100
return std::nullopt;
101101
else
102102
return path;

src/libfetchers/registry.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ static std::shared_ptr<Registry> getGlobalRegistry(const Settings & settings, re
156156
return std::make_shared<Registry>(settings, Registry::Global); // empty registry
157157
}
158158

159-
if (!hasPrefix(path, "/")) {
159+
if (!isAbsolute(path)) {
160160
auto storePath = downloadFile(store, path, "flake-registry.json").storePath;
161161
if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>())
162162
store2->addPermRoot(storePath, getCacheDir() + "/nix/flake-registry.json");

src/libflake/flake/flakeref.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ std::pair<FlakeRef, std::string> parsePathFlakeRefWithFragment(
175175
}
176176

177177
} else {
178-
if (!hasPrefix(path, "/"))
178+
if (!isAbsolute(path))
179179
throw BadURL("flake reference '%s' is not an absolute path", url);
180180
path = canonPath(path + "/" + getOr(query, "dir", ""));
181181
}

src/libutil/file-system.cc

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,7 @@ namespace fs = std::filesystem;
2929

3030
namespace nix {
3131

32-
/**
33-
* Treat the string as possibly an absolute path, by inspecting the
34-
* start of it. Return whether it was probably intended to be
35-
* absolute.
36-
*/
37-
static bool isAbsolute(PathView path)
32+
bool isAbsolute(PathView path)
3833
{
3934
return fs::path { path }.is_absolute();
4035
}

src/libutil/file-system.hh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ namespace nix {
4242
struct Sink;
4343
struct Source;
4444

45+
/**
46+
* Return whether the path denotes an absolute path.
47+
*/
48+
bool isAbsolute(PathView path);
49+
4550
/**
4651
* @return An absolutized path, resolving paths relative to the
4752
* specified directory, or the current directory otherwise. The path

src/libutil/source-accessor.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ CanonPath SourceAccessor::resolveSymlinks(
9494
throw Error("infinite symlink recursion in path '%s'", showPath(path));
9595
auto target = readLink(res);
9696
res.pop();
97-
if (hasPrefix(target, "/"))
97+
if (isAbsolute(target))
9898
res = CanonPath::root;
9999
todo.splice(todo.begin(), tokenizeString<std::list<std::string>>(target, "/"));
100100
}

tests/functional/flakes/flake-in-submodule.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,21 @@ flakeref=git+file://$rootRepo\?submodules=1\&dir=submodule
6363
echo '"foo"' > "$rootRepo"/submodule/sub.nix
6464
[[ $(nix eval --json "$flakeref#sub" ) = '"foo"' ]]
6565
[[ $(nix flake metadata --json "$flakeref" | jq -r .locked.rev) = null ]]
66+
67+
# The root repo may use the submodule repo as an input
68+
# through the relative path. This may change in the future;
69+
# see: https://discourse.nixos.org/t/57783 and #9708.
70+
cat > "$rootRepo"/flake.nix <<EOF
71+
{
72+
inputs.subRepo.url = "git+file:./submodule";
73+
outputs = { ... }: { };
74+
}
75+
EOF
76+
git -C "$rootRepo" add flake.nix
77+
git -C "$rootRepo" commit -m "Add subRepo input"
78+
(
79+
cd "$rootRepo"
80+
# The submodule must be locked to the relative path,
81+
# _not_ the absolute path:
82+
[[ $(nix flake metadata --json | jq -r .locks.nodes.subRepo.locked.url) = "file:./submodule" ]]
83+
)

tests/functional/flakes/flakes.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,15 @@ nix build -o "$TEST_ROOT/result" "git+file://$flake1Dir#default"
228228
nix build -o "$TEST_ROOT/result" "$flake1Dir?ref=HEAD#default"
229229
nix build -o "$TEST_ROOT/result" "git+file://$flake1Dir?ref=HEAD#default"
230230

231+
# Check that relative paths are allowed for git flakes.
232+
# This may change in the future once git submodule support is refined.
233+
# See: https://discourse.nixos.org/t/57783 and #9708.
234+
(
235+
# This `cd` should not be required and is indicative of aforementioned bug.
236+
cd "$flake1Dir/.."
237+
nix build -o "$TEST_ROOT/result" "git+file:./$(basename "$flake1Dir")"
238+
)
239+
231240
# Check that store symlinks inside a flake are not interpreted as flakes.
232241
nix build -o "$flake1Dir/result" "git+file://$flake1Dir"
233242
nix path-info "$flake1Dir/result"

0 commit comments

Comments
 (0)