Skip to content

Commit

Permalink
Merge pull request #12287 from bryango/2.24-maintenance
Browse files Browse the repository at this point in the history
Backport git+file:./ fixes to 2.24 (#12107 + #12277)
  • Loading branch information
roberth authored Jan 21, 2025
2 parents f366bea + 876d724 commit f22359b
Show file tree
Hide file tree
Showing 10 changed files with 58 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/libexpr/eval.cc
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ void EvalState::checkURI(const std::string & uri)

/* If the URI is a path, then check it against allowedPaths as
well. */
if (hasPrefix(uri, "/")) {
if (isAbsolute(uri)) {
if (auto rootFS2 = rootFS.dynamic_pointer_cast<AllowListSourceAccessor>())
rootFS2->checkAccess(CanonPath(uri));
return;
Expand Down
21 changes: 20 additions & 1 deletion src/libfetchers/git.cc
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,26 @@ struct GitInputScheme : InputScheme
auto url = parseURL(getStrAttr(input.attrs, "url"));
bool isBareRepository = url.scheme == "file" && !pathExists(url.path + "/.git");
repoInfo.isLocal = url.scheme == "file" && !forceHttp && !isBareRepository;
repoInfo.url = repoInfo.isLocal ? url.path : url.base;
//
// FIXME: here we turn a possibly relative path into an absolute path.
// This allows relative git flake inputs to be resolved against the
// **current working directory** (as in POSIX), which tends to work out
// ok in the context of flakes, but is the wrong behavior,
// as it should resolve against the flake.nix base directory instead.
//
// See: https://discourse.nixos.org/t/57783 and #9708
//
if (repoInfo.isLocal) {
if (!isAbsolute(url.path)) {
warn(
"Fetching Git repository '%s', which uses a path relative to the current directory. "
"This is not supported and will stop working in a future release. "
"See https://github.com/NixOS/nix/issues/12281 for details.",
url.to_string());
}
repoInfo.url = std::filesystem::absolute(url.path).string();
} else
repoInfo.url = url.to_string();

// If this is a local directory and no ref or revision is
// given, then allow the use of an unclean working tree.
Expand Down
2 changes: 1 addition & 1 deletion src/libfetchers/path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ struct PathInputScheme : InputScheme
std::optional<std::string> isRelative(const Input & input) const
{
auto path = getStrAttr(input.attrs, "path");
if (hasPrefix(path, "/"))
if (isAbsolute(path))
return std::nullopt;
else
return path;
Expand Down
2 changes: 1 addition & 1 deletion src/libfetchers/registry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ static std::shared_ptr<Registry> getGlobalRegistry(const Settings & settings, re
return std::make_shared<Registry>(settings, Registry::Global); // empty registry
}

if (!hasPrefix(path, "/")) {
if (!isAbsolute(path)) {
auto storePath = downloadFile(store, path, "flake-registry.json").storePath;
if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>())
store2->addPermRoot(storePath, getCacheDir() + "/nix/flake-registry.json");
Expand Down
2 changes: 1 addition & 1 deletion src/libflake/flake/flakeref.cc
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ std::pair<FlakeRef, std::string> parsePathFlakeRefWithFragment(
}

} else {
if (!hasPrefix(path, "/"))
if (!isAbsolute(path))
throw BadURL("flake reference '%s' is not an absolute path", url);
path = canonPath(path + "/" + getOr(query, "dir", ""));
}
Expand Down
7 changes: 1 addition & 6 deletions src/libutil/file-system.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,7 @@ namespace fs = std::filesystem;

namespace nix {

/**
* Treat the string as possibly an absolute path, by inspecting the
* start of it. Return whether it was probably intended to be
* absolute.
*/
static bool isAbsolute(PathView path)
bool isAbsolute(PathView path)
{
return fs::path { path }.is_absolute();
}
Expand Down
5 changes: 5 additions & 0 deletions src/libutil/file-system.hh
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ namespace nix {
struct Sink;
struct Source;

/**
* Return whether the path denotes an absolute path.
*/
bool isAbsolute(PathView path);

/**
* @return An absolutized path, resolving paths relative to the
* specified directory, or the current directory otherwise. The path
Expand Down
2 changes: 1 addition & 1 deletion src/libutil/source-accessor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ CanonPath SourceAccessor::resolveSymlinks(
throw Error("infinite symlink recursion in path '%s'", showPath(path));
auto target = readLink(res);
res.pop();
if (hasPrefix(target, "/"))
if (isAbsolute(target))
res = CanonPath::root;
todo.splice(todo.begin(), tokenizeString<std::list<std::string>>(target, "/"));
}
Expand Down
18 changes: 18 additions & 0 deletions tests/functional/flakes/flake-in-submodule.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,21 @@ flakeref=git+file://$rootRepo\?submodules=1\&dir=submodule
echo '"foo"' > "$rootRepo"/submodule/sub.nix
[[ $(nix eval --json "$flakeref#sub" ) = '"foo"' ]]
[[ $(nix flake metadata --json "$flakeref" | jq -r .locked.rev) = null ]]

# The root repo may use the submodule repo as an input
# through the relative path. This may change in the future;
# see: https://discourse.nixos.org/t/57783 and #9708.
cat > "$rootRepo"/flake.nix <<EOF
{
inputs.subRepo.url = "git+file:./submodule";
outputs = { ... }: { };
}
EOF
git -C "$rootRepo" add flake.nix
git -C "$rootRepo" commit -m "Add subRepo input"
(
cd "$rootRepo"
# The submodule must be locked to the relative path,
# _not_ the absolute path:
[[ $(nix flake metadata --json | jq -r .locks.nodes.subRepo.locked.url) = "file:./submodule" ]]
)
9 changes: 9 additions & 0 deletions tests/functional/flakes/flakes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,15 @@ nix build -o "$TEST_ROOT/result" "git+file://$flake1Dir#default"
nix build -o "$TEST_ROOT/result" "$flake1Dir?ref=HEAD#default"
nix build -o "$TEST_ROOT/result" "git+file://$flake1Dir?ref=HEAD#default"

# Check that relative paths are allowed for git flakes.
# This may change in the future once git submodule support is refined.
# See: https://discourse.nixos.org/t/57783 and #9708.
(
# This `cd` should not be required and is indicative of aforementioned bug.
cd "$flake1Dir/.."
nix build -o "$TEST_ROOT/result" "git+file:./$(basename "$flake1Dir")"
)

# Check that store symlinks inside a flake are not interpreted as flakes.
nix build -o "$flake1Dir/result" "git+file://$flake1Dir"
nix path-info "$flake1Dir/result"
Expand Down

0 comments on commit f22359b

Please sign in to comment.