Skip to content

Commit 2d067cc

Browse files
Fix git lfs for github fetcher
According to https://github.com/git-lfs/git-lfs/blob/main/docs/api/server-discovery.md LFS endpoints must end in `.git`. Resolves #15285 Signed-off-by: Lisanna Dettwyler <lisanna.dettwyler@gmail.com>
1 parent bc385bc commit 2d067cc

4 files changed

Lines changed: 56 additions & 12 deletions

File tree

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include "nix/fetchers/git-lfs-fetch.hh"
2+
#include "nix/util/url.hh"
3+
4+
#include <gtest/gtest.h>
5+
6+
namespace nix::lfs {
7+
8+
struct GitLFSTest : public ::testing::Test
9+
{
10+
void test(std::string input, std::string expected)
11+
{
12+
ASSERT_EQ(getLfsApi(parseURL(input)).endpoint, expected);
13+
}
14+
};
15+
16+
TEST_F(GitLFSTest, get_lfs_api)
17+
{
18+
test("https://git-server.com/foo/bar", "https://git-server.com/foo/bar.git/info/lfs");
19+
test("https://git-server.com/foo/bar.git", "https://git-server.com/foo/bar.git/info/lfs");
20+
test("https://git-server.com", "https://git-server.com/.git/info/lfs");
21+
test("https://git-server.com/foo/bar/", "https://git-server.com/foo/bar.git//info/lfs");
22+
};
23+
24+
} // namespace nix::lfs

src/libfetchers-tests/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ subdir('nix-meson-build-support/common')
4141
sources = files(
4242
'access-tokens.cc',
4343
'attrs.cc',
44+
'git-lfs-fetch.cc',
4445
'git-utils.cc',
4546
'git.cc',
4647
'input.cc',

src/libfetchers/git-lfs-fetch.cc

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,7 @@ static void downloadToSink(
4646
"hash mismatch while fetching %s: expected sha256:%s but got sha256:%s", url, sha256Expected, sha256Actual);
4747
}
4848

49-
namespace {
50-
51-
struct LfsApiInfo
52-
{
53-
std::string endpoint;
54-
std::optional<std::string> authHeader;
55-
};
56-
57-
} // namespace
58-
59-
static LfsApiInfo getLfsApi(const ParsedURL & url)
49+
LfsApiInfo getLfsApi(ParsedURL url)
6050
{
6151
assert(url.authority.has_value());
6252
if (url.scheme == "ssh") {
@@ -96,7 +86,28 @@ static LfsApiInfo getLfsApi(const ParsedURL & url)
9686
return {queryResp.at("href").get<std::string>(), authIt->get<std::string>()};
9787
}
9888

99-
return {url.to_string() + "/info/lfs", std::nullopt};
89+
// Try to mimic what git-lfs will do to plain remotes
90+
// https://github.com/git-lfs/git-lfs/blob/main/docs/api/server-discovery.md
91+
bool hasDotGit = false;
92+
for (auto it = url.path.rbegin(); it != url.path.rend(); ++it) {
93+
if (it->empty())
94+
continue;
95+
if (it->ends_with(".git")) {
96+
hasDotGit = true;
97+
break;
98+
} else {
99+
*it += ".git";
100+
hasDotGit = true;
101+
break;
102+
}
103+
}
104+
if (!hasDotGit)
105+
url.path.push_back(".git");
106+
107+
url.path.push_back("info");
108+
url.path.push_back("lfs");
109+
110+
return {url.to_string(), std::nullopt};
100111
}
101112

102113
typedef std::unique_ptr<git_config, Deleter<git_config_free>> GitConfig;

src/libfetchers/include/nix/fetchers/git-lfs-fetch.hh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,12 @@ struct Fetch
4343
std::vector<nlohmann::json> fetchUrls(const std::vector<Pointer> & pointers) const;
4444
};
4545

46+
struct LfsApiInfo
47+
{
48+
std::string endpoint;
49+
std::optional<std::string> authHeader;
50+
};
51+
52+
LfsApiInfo getLfsApi(ParsedURL url);
53+
4654
} // namespace nix::lfs

0 commit comments

Comments
 (0)