Skip to content

Commit 693a38a

Browse files
authored
Merge pull request #10153 from b-camacho/lfs
git-lfs support
2 parents eb91014 + a902b84 commit 693a38a

File tree

13 files changed

+781
-46
lines changed

13 files changed

+781
-46
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
synopsis: "Git LFS support"
3+
prs: [10153]
4+
---
5+
6+
The Git fetcher now supports Large File Storage (LFS). This can be enabled by passing the attribute `lfs = true` to the fetcher, e.g.
7+
```console
8+
nix flake prefetch 'git+ssh://[email protected]/Apress/repo-with-large-file-storage.git?lfs=1'
9+
```
10+
11+
Author: [**@b-camacho**](https://github.com/b-camacho), [**@kip93**](https://github.com/kip93)

src/libexpr/primops/fetchTree.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,12 @@ static RegisterPrimOp primop_fetchTree({
367367
368368
Default: `false`
369369
370+
- `lfs` (Bool, optional)
371+
372+
Fetch any [Git LFS](https://git-lfs.com/) files.
373+
374+
Default: `false`
375+
370376
- `allRefs` (Bool, optional)
371377
372378
By default, this has no effect. This becomes relevant only once `shallow` cloning is disabled.
@@ -691,6 +697,13 @@ static RegisterPrimOp primop_fetchGit({
691697
692698
Make a shallow clone when fetching the Git tree.
693699
When this is enabled, the options `ref` and `allRefs` have no effect anymore.
700+
701+
- `lfs` (default: `false`)
702+
703+
A boolean that when `true` specifies that [Git LFS] files should be fetched.
704+
705+
[Git LFS]: https://git-lfs.com/
706+
694707
- `allRefs`
695708
696709
Whether to fetch all references (eg. branches and tags) of the repository.

src/libfetchers-tests/git-utils.cc

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <gtest/gtest.h>
88
#include "fs-sink.hh"
99
#include "serialise.hh"
10+
#include "git-lfs-fetch.hh"
1011

1112
namespace nix {
1213

@@ -109,4 +110,131 @@ TEST_F(GitUtilsTest, sink_hardlink)
109110
}
110111
};
111112

113+
namespace lfs {
114+
115+
TEST_F(GitUtilsTest, parseGitRemoteUrl)
116+
{
117+
{
118+
GitUrl result = parseGitUrl("[email protected]:path/repo.git");
119+
EXPECT_EQ(result.protocol, "ssh");
120+
EXPECT_EQ(result.user, "git");
121+
EXPECT_EQ(result.host, "example.com");
122+
EXPECT_EQ(result.port, "");
123+
EXPECT_EQ(result.path, "path/repo.git");
124+
}
125+
126+
{
127+
GitUrl result = parseGitUrl("example.com:/path/repo.git");
128+
EXPECT_EQ(result.protocol, "ssh");
129+
EXPECT_EQ(result.user, "");
130+
EXPECT_EQ(result.host, "example.com");
131+
EXPECT_EQ(result.port, "");
132+
EXPECT_EQ(result.path, "/path/repo.git");
133+
}
134+
135+
{
136+
GitUrl result = parseGitUrl("example.com:path/repo.git");
137+
EXPECT_EQ(result.protocol, "ssh");
138+
EXPECT_EQ(result.user, "");
139+
EXPECT_EQ(result.host, "example.com");
140+
EXPECT_EQ(result.port, "");
141+
EXPECT_EQ(result.path, "path/repo.git");
142+
}
143+
144+
{
145+
GitUrl result = parseGitUrl("https://example.com/path/repo.git");
146+
EXPECT_EQ(result.protocol, "https");
147+
EXPECT_EQ(result.user, "");
148+
EXPECT_EQ(result.host, "example.com");
149+
EXPECT_EQ(result.port, "");
150+
EXPECT_EQ(result.path, "path/repo.git");
151+
}
152+
153+
{
154+
GitUrl result = parseGitUrl("ssh://[email protected]/path/repo.git");
155+
EXPECT_EQ(result.protocol, "ssh");
156+
EXPECT_EQ(result.user, "git");
157+
EXPECT_EQ(result.host, "example.com");
158+
EXPECT_EQ(result.port, "");
159+
EXPECT_EQ(result.path, "path/repo.git");
160+
}
161+
162+
{
163+
GitUrl result = parseGitUrl("ssh://example/path/repo.git");
164+
EXPECT_EQ(result.protocol, "ssh");
165+
EXPECT_EQ(result.user, "");
166+
EXPECT_EQ(result.host, "example");
167+
EXPECT_EQ(result.port, "");
168+
EXPECT_EQ(result.path, "path/repo.git");
169+
}
170+
171+
{
172+
GitUrl result = parseGitUrl("http://example.com:8080/path/repo.git");
173+
EXPECT_EQ(result.protocol, "http");
174+
EXPECT_EQ(result.user, "");
175+
EXPECT_EQ(result.host, "example.com");
176+
EXPECT_EQ(result.port, "8080");
177+
EXPECT_EQ(result.path, "path/repo.git");
178+
}
179+
180+
{
181+
GitUrl result = parseGitUrl("invalid-url");
182+
EXPECT_EQ(result.protocol, "");
183+
EXPECT_EQ(result.user, "");
184+
EXPECT_EQ(result.host, "");
185+
EXPECT_EQ(result.port, "");
186+
EXPECT_EQ(result.path, "");
187+
}
188+
189+
{
190+
GitUrl result = parseGitUrl("");
191+
EXPECT_EQ(result.protocol, "");
192+
EXPECT_EQ(result.user, "");
193+
EXPECT_EQ(result.host, "");
194+
EXPECT_EQ(result.port, "");
195+
EXPECT_EQ(result.path, "");
196+
}
197+
}
198+
TEST_F(GitUtilsTest, gitUrlToHttp)
199+
{
200+
{
201+
const GitUrl url = parseGitUrl("[email protected]:user/repo.git");
202+
EXPECT_EQ(url.toHttp(), "https://github.com/user/repo.git");
203+
}
204+
{
205+
const GitUrl url = parseGitUrl("https://github.com/user/repo.git");
206+
EXPECT_EQ(url.toHttp(), "https://github.com/user/repo.git");
207+
}
208+
{
209+
const GitUrl url = parseGitUrl("http://github.com/user/repo.git");
210+
EXPECT_EQ(url.toHttp(), "http://github.com/user/repo.git");
211+
}
212+
{
213+
const GitUrl url = parseGitUrl("ssh://[email protected]:22/user/repo.git");
214+
EXPECT_EQ(url.toHttp(), "https://github.com:22/user/repo.git");
215+
}
216+
{
217+
const GitUrl url = parseGitUrl("invalid-url");
218+
EXPECT_EQ(url.toHttp(), "");
219+
}
220+
}
221+
222+
TEST_F(GitUtilsTest, gitUrlToSsh)
223+
{
224+
{
225+
const GitUrl url = parseGitUrl("https://example.com/user/repo.git");
226+
const auto [host, path] = url.toSsh();
227+
EXPECT_EQ(host, "example.com");
228+
EXPECT_EQ(path, "user/repo.git");
229+
}
230+
{
231+
const GitUrl url = parseGitUrl("[email protected]:user/repo.git");
232+
const auto [host, path] = url.toSsh();
233+
EXPECT_EQ(host, "[email protected]");
234+
EXPECT_EQ(path, "user/repo.git");
235+
}
236+
}
237+
238+
} // namespace lfs
239+
112240
} // namespace nix

0 commit comments

Comments
 (0)