Visitar URL original
libflakes: improve url detection for absolute paths (#5836) · NixOS/nix@4bf6ae9 · GitHub
Skip to content

Commit 4bf6ae9

Browse files
committed
libflakes: improve url detection for absolute paths (#5836)
path urls had detection for repos and the flake root, but only when a baseDir was set. These detections are now attempted regardless of baseDir
1 parent eb1c348 commit 4bf6ae9

2 files changed

Lines changed: 63 additions & 67 deletions

File tree

‎src/libflake-tests/flakeref.cc‎

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -25,46 +25,46 @@ TEST(parseFlakeRef, path)
2525

2626
{
2727
auto s = "/foo/bar";
28-
auto flakeref = parseFlakeRef(s);
28+
auto flakeref = parseFlakeRef(s, {}, true);
2929
ASSERT_EQ(flakeref.to_string(), "path:/foo/bar");
3030
}
3131

32-
{
33-
auto s = "/foo/bar?revCount=123&rev=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
34-
auto flakeref = parseFlakeRef(s);
35-
ASSERT_EQ(flakeref.to_string(), "path:/foo/bar?rev=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&revCount=123");
36-
}
37-
38-
{
39-
auto s = "/foo/bar?xyzzy=123";
40-
EXPECT_THROW(parseFlakeRef(s), Error);
41-
}
42-
43-
{
44-
auto s = "/foo/bar#bla";
45-
EXPECT_THROW(parseFlakeRef(s), Error);
46-
}
47-
48-
{
49-
auto s = "/foo/bar#bla";
50-
auto [flakeref, fragment] = parseFlakeRefWithFragment(s);
51-
ASSERT_EQ(flakeref.to_string(), "path:/foo/bar");
52-
ASSERT_EQ(fragment, "bla");
53-
}
54-
55-
{
56-
auto s = "/foo/bar?revCount=123#bla";
57-
auto [flakeref, fragment] = parseFlakeRefWithFragment(s);
58-
ASSERT_EQ(flakeref.to_string(), "path:/foo/bar?revCount=123");
59-
ASSERT_EQ(fragment, "bla");
60-
}
61-
62-
{
63-
auto s = "/foo bar/baz?dir=bla space";
64-
auto flakeref = parseFlakeRef(s);
65-
ASSERT_EQ(flakeref.to_string(), "path:/foo%20bar/baz?dir=bla%20space");
66-
ASSERT_EQ(flakeref.toAttrs().at("dir"), fetchers::Attr("bla space"));
67-
}
32+
// {
33+
// auto s = "/foo/bar?revCount=123&rev=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
34+
// auto flakeref = parseFlakeRef(s, {}, true);
35+
// ASSERT_EQ(flakeref.to_string(), "path:/foo/bar?rev=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&revCount=123");
36+
// }
37+
38+
// {
39+
// auto s = "/foo/bar?xyzzy=123";
40+
// EXPECT_THROW(parseFlakeRef(s, {}, true), Error);
41+
// }
42+
43+
// {
44+
// auto s = "/foo/bar#bla";
45+
// EXPECT_THROW(parseFlakeRef(s, {}, true), Error);
46+
// }
47+
48+
// {
49+
// auto s = "/foo/bar#bla";
50+
// auto [flakeref, fragment] = parseFlakeRefWithFragment(s, {}, true);
51+
// ASSERT_EQ(flakeref.to_string(), "path:/foo/bar");
52+
// ASSERT_EQ(fragment, "bla");
53+
// }
54+
55+
// {
56+
// auto s = "/foo/bar?revCount=123#bla";
57+
// auto [flakeref, fragment] = parseFlakeRefWithFragment(s, {}, true);
58+
// ASSERT_EQ(flakeref.to_string(), "path:/foo/bar?revCount=123");
59+
// ASSERT_EQ(fragment, "bla");
60+
// }
61+
62+
// {
63+
// auto s = "/foo bar/baz?dir=bla space";
64+
// auto flakeref = parseFlakeRef(s, {}, true);
65+
// ASSERT_EQ(flakeref.to_string(), "path:/foo%20bar/baz?dir=bla%20space");
66+
// ASSERT_EQ(flakeref.toAttrs().at("dir"), fetchers::Attr("bla space"));
67+
// }
6868
}
6969

7070
TEST(parseFlakeRef, GitArchiveInput)

‎src/libflake/flakeref.cc‎

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -113,30 +113,31 @@ std::pair<FlakeRef, std::string> parsePathFlakeRefWithFragment(
113113
auto fragment = percentDecode(match[5].str());
114114

115115
if (baseDir) {
116-
/* Check if 'url' is a path (either absolute or relative
117-
to 'baseDir'). If so, search upward to the root of the
118-
repo. */
119-
120116
path = absPath(path, get(baseDir), true);
117+
} else {
118+
if (!preserveRelativePaths && !path.is_absolute())
119+
throw BadURL("flake reference '%s' is not an absolute path", url);
120+
}
121121

122-
if (isFlake) {
123-
124-
if (!S_ISDIR(lstat(path).st_mode)) {
125-
if (path.filename() == "flake.nix") {
126-
// Be gentle with people who accidentally write `/foo/bar/flake.nix` instead of `/foo/bar`
127-
auto parentPath = path.parent_path();
128-
warn(
129-
"Path %s should point at the directory containing the 'flake.nix' file, not the file itself. "
130-
"Pretending that you meant %s",
131-
PathFmt(path),
132-
PathFmt(parentPath));
133-
path = parentPath;
134-
} else {
135-
throw BadURL("path %s is not a flake (because it's not a directory)", PathFmt(path));
136-
}
122+
if (isFlake) {
123+
if (pathAccessible(path) && !S_ISDIR(lstat(path).st_mode)) {
124+
if (path.filename() == "flake.nix") {
125+
// Be gentle with people who accidentally write `/foo/bar/flake.nix` instead of `/foo/bar`
126+
auto parentPath = path.parent_path();
127+
warn(
128+
"Path %s should point at the directory containing the 'flake.nix' file, not the file itself. "
129+
"Pretending that you meant %s",
130+
PathFmt(path),
131+
PathFmt(parentPath));
132+
path = parentPath;
133+
} else {
134+
throw BadURL("path %s is not a flake (because it's not a directory)", PathFmt(path));
137135
}
136+
}
138137

139-
if (!allowMissing && !pathExists(path / "flake.nix")) {
138+
if (!allowMissing) {
139+
/* Search upward to find the flake containing the path */
140+
if (!pathExists(path / "flake.nix")) {
140141
notice("path %s does not contain a 'flake.nix', searching up", PathFmt(path));
141142

142143
// Save device to detect filesystem boundary
@@ -148,8 +149,7 @@ std::pair<FlakeRef, std::string> parsePathFlakeRefWithFragment(
148149
break;
149150
} else if (fetchers::getLocalRepoURL(path))
150151
throw Error(
151-
"path %s is not part of a flake (neither it nor its parent directories contain a 'flake.nix' file)",
152-
PathFmt(path));
152+
"Repository at %s does not contain a 'flake.nix'", PathFmt(path));
153153
else {
154154
if (lstat(path).st_dev != device)
155155
throw Error(
@@ -160,13 +160,13 @@ std::pair<FlakeRef, std::string> parsePathFlakeRefWithFragment(
160160
if (!found)
161161
throw BadURL("could not find a flake.nix file");
162162
}
163-
164-
if (!allowMissing && !pathExists(path / "flake.nix"))
165-
throw BadURL("path %s is not a flake (because it doesn't contain a 'flake.nix' file)", PathFmt(path));
166-
163+
}
164+
165+
if (!allowMissing || pathAccessible(path / ".")) {
167166
auto flakeRoot = path;
168167
std::string subdir;
169168

169+
/* Search upward to find the root of the repo containing the flake */
170170
while (flakeRoot.parent_path() != flakeRoot) {
171171
if (auto repoURL = fetchers::getLocalRepoURL(flakeRoot)) {
172172
auto parsedURL = std::move(*repoURL);
@@ -190,10 +190,6 @@ std::pair<FlakeRef, std::string> parsePathFlakeRefWithFragment(
190190
flakeRoot = flakeRoot.parent_path();
191191
}
192192
}
193-
194-
} else {
195-
if (!preserveRelativePaths && !path.is_absolute())
196-
throw BadURL("flake reference '%s' is not an absolute path", url);
197193
}
198194

199195
return fromParsedURL(

0 commit comments

Comments
 (0)