Skip to content

Commit 709a73e

Browse files
authored
Merge pull request #14492 from NixOS/fix-14429
fetchGit: Drop `git+` from the `url` attribute
2 parents accb564 + d6fc64a commit 709a73e

File tree

6 files changed

+80
-15
lines changed

6 files changed

+80
-15
lines changed

src/libfetchers-tests/input.cc

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#include "nix/fetchers/fetch-settings.hh"
2+
#include "nix/fetchers/attrs.hh"
3+
#include "nix/fetchers/fetchers.hh"
4+
5+
#include <gtest/gtest.h>
6+
7+
#include <string>
8+
9+
namespace nix {
10+
11+
using fetchers::Attr;
12+
13+
struct InputFromAttrsTestCase
14+
{
15+
fetchers::Attrs attrs;
16+
std::string expectedUrl;
17+
std::string description;
18+
fetchers::Attrs expectedAttrs = attrs;
19+
};
20+
21+
class InputFromAttrsTest : public ::testing::WithParamInterface<InputFromAttrsTestCase>, public ::testing::Test
22+
{};
23+
24+
TEST_P(InputFromAttrsTest, attrsAreCorrectAndRoundTrips)
25+
{
26+
fetchers::Settings fetchSettings;
27+
28+
const auto & testCase = GetParam();
29+
30+
auto input = fetchers::Input::fromAttrs(fetchSettings, fetchers::Attrs(testCase.attrs));
31+
32+
EXPECT_EQ(input.toAttrs(), testCase.expectedAttrs);
33+
EXPECT_EQ(input.toURLString(), testCase.expectedUrl);
34+
35+
auto input2 = fetchers::Input::fromAttrs(fetchSettings, input.toAttrs());
36+
EXPECT_EQ(input, input2);
37+
EXPECT_EQ(input.toAttrs(), input2.toAttrs());
38+
}
39+
40+
INSTANTIATE_TEST_SUITE_P(
41+
InputFromAttrs,
42+
InputFromAttrsTest,
43+
::testing::Values(
44+
// Test for issue #14429.
45+
InputFromAttrsTestCase{
46+
.attrs =
47+
{
48+
{"url", Attr("git+ssh://[email protected]/NixOS/nixpkgs")},
49+
{"type", Attr("git")},
50+
},
51+
.expectedUrl = "git+ssh://[email protected]/NixOS/nixpkgs",
52+
.description = "strips_git_plus_prefix",
53+
.expectedAttrs =
54+
{
55+
{"url", Attr("ssh://[email protected]/NixOS/nixpkgs")},
56+
{"type", Attr("git")},
57+
},
58+
}),
59+
[](const ::testing::TestParamInfo<InputFromAttrsTestCase> & info) { return info.param.description; });
60+
61+
} // namespace nix

src/libfetchers-tests/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ sources = files(
4242
'access-tokens.cc',
4343
'git-utils.cc',
4444
'git.cc',
45+
'input.cc',
4546
'nix_api_fetchers.cc',
4647
'public-key.cc',
4748
)

src/libfetchers/git.cc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,6 @@ struct GitInputScheme : InputScheme
168168
return {};
169169

170170
auto url2(url);
171-
if (hasPrefix(url2.scheme, "git+"))
172-
url2.scheme = std::string(url2.scheme, 4);
173171
url2.query.clear();
174172

175173
Attrs attrs;

src/libutil-tests/url.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ INSTANTIATE_TEST_SUITE_P(
3535
// Already proper URL with git+ssh
3636
FixGitURLParam{
3737
.input = "git+ssh://user@domain:1234/path",
38-
.expected = "git+ssh://user@domain:1234/path",
38+
.expected = "ssh://user@domain:1234/path",
3939
.parsed =
4040
ParsedURL{
41-
.scheme = "git+ssh",
41+
.scheme = "ssh",
4242
.authority =
4343
ParsedURL::Authority{
4444
.host = "domain",

src/libutil/include/nix/util/url.hh

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -330,10 +330,13 @@ struct ParsedUrlScheme
330330

331331
ParsedUrlScheme parseUrlScheme(std::string_view scheme);
332332

333-
/* Detects scp-style uris (e.g. [email protected]:NixOS/nix) and fixes
334-
them by removing the `:` and assuming a scheme of `ssh://`. Also
335-
changes absolute paths into file:// URLs. */
336-
ParsedURL fixGitURL(const std::string & url);
333+
/**
334+
* Detects scp-style uris (e.g. `[email protected]:NixOS/nix`) and fixes
335+
* them by removing the `:` and assuming a scheme of `ssh://`. Also
336+
* drops `git+` from the scheme (e.g. `git+https://` to `https://`)
337+
* and changes absolute paths into `file://` URLs.
338+
*/
339+
ParsedURL fixGitURL(std::string url);
337340

338341
/**
339342
* Whether a string is valid as RFC 3986 scheme name.

src/libutil/url.cc

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -409,21 +409,23 @@ ParsedUrlScheme parseUrlScheme(std::string_view scheme)
409409
};
410410
}
411411

412-
ParsedURL fixGitURL(const std::string & url)
412+
ParsedURL fixGitURL(std::string url)
413413
{
414414
std::regex scpRegex("([^/]*)@(.*):(.*)");
415415
if (!hasPrefix(url, "/") && std::regex_match(url, scpRegex))
416-
return parseURL(std::regex_replace(url, scpRegex, "ssh://$1@$2/$3"));
417-
if (hasPrefix(url, "file:"))
418-
return parseURL(url);
419-
if (url.find("://") == std::string::npos) {
416+
url = std::regex_replace(url, scpRegex, "ssh://$1@$2/$3");
417+
if (!hasPrefix(url, "file:") && !hasPrefix(url, "git+file:") && url.find("://") == std::string::npos)
420418
return ParsedURL{
421419
.scheme = "file",
422420
.authority = ParsedURL::Authority{},
423421
.path = splitString<std::vector<std::string>>(url, "/"),
424422
};
425-
}
426-
return parseURL(url);
423+
auto parsed = parseURL(url);
424+
// Drop the superfluous "git+" from the scheme.
425+
auto scheme = parseUrlScheme(parsed.scheme);
426+
if (scheme.application == "git")
427+
parsed.scheme = scheme.transport;
428+
return parsed;
427429
}
428430

429431
// https://www.rfc-editor.org/rfc/rfc3986#section-3.1

0 commit comments

Comments
 (0)