1{
2 lib,
3 repoRevToNameMaybe,
4 fetchgit,
5 fetchzip,
6}:
7
8lib.makeOverridable (
9 {
10 owner,
11 repo,
12 tag ? null,
13 rev ? null,
14 name ? repoRevToNameMaybe repo (lib.revOrTag rev tag) "github",
15 fetchSubmodules ? false,
16 leaveDotGit ? null,
17 deepClone ? false,
18 private ? false,
19 forceFetchGit ? false,
20 fetchLFS ? false,
21 sparseCheckout ? [ ],
22 githubBase ? "github.com",
23 varPrefix ? null,
24 meta ? { },
25 ... # For hash agility
26 }@args:
27
28 assert (
29 lib.assertMsg (lib.xor (tag == null) (
30 rev == null
31 )) "fetchFromGitHub requires one of either `rev` or `tag` to be provided (not both)."
32 );
33
34 let
35
36 position = (
37 if args.meta.description or null != null then
38 builtins.unsafeGetAttrPos "description" args.meta
39 else if tag != null then
40 builtins.unsafeGetAttrPos "tag" args
41 else
42 builtins.unsafeGetAttrPos "rev" args
43 );
44 baseUrl = "https://${githubBase}/${owner}/${repo}";
45 newMeta =
46 meta
47 // {
48 homepage = meta.homepage or baseUrl;
49 }
50 // lib.optionalAttrs (position != null) {
51 # to indicate where derivation originates, similar to make-derivation.nix's mkDerivation
52 position = "${position.file}:${toString position.line}";
53 };
54 passthruAttrs = removeAttrs args [
55 "owner"
56 "repo"
57 "tag"
58 "rev"
59 "fetchSubmodules"
60 "forceFetchGit"
61 "private"
62 "githubBase"
63 "varPrefix"
64 ];
65 varBase = "NIX${lib.optionalString (varPrefix != null) "_${varPrefix}"}_GITHUB_PRIVATE_";
66 useFetchGit =
67 fetchSubmodules
68 || (leaveDotGit == true)
69 || deepClone
70 || forceFetchGit
71 || fetchLFS
72 || (sparseCheckout != [ ]);
73 # We prefer fetchzip in cases we don't need submodules as the hash
74 # is more stable in that case.
75 fetcher =
76 if useFetchGit then
77 fetchgit
78 # fetchzip may not be overridable when using external tools, for example nix-prefetch
79 else if fetchzip ? override then
80 fetchzip.override { withUnzip = false; }
81 else
82 fetchzip;
83 privateAttrs = lib.optionalAttrs private {
84 netrcPhase =
85 # When using private repos:
86 # - Fetching with git works using https://github.com but not with the GitHub API endpoint
87 # - Fetching a tarball from a private repo requires to use the GitHub API endpoint
88 let
89 machineName = if githubBase == "github.com" && !useFetchGit then "api.github.com" else githubBase;
90 in
91 ''
92 if [ -z "''$${varBase}USERNAME" -o -z "''$${varBase}PASSWORD" ]; then
93 echo "Error: Private fetchFromGitHub requires the nix building process (nix-daemon in multi user mode) to have the ${varBase}USERNAME and ${varBase}PASSWORD env vars set." >&2
94 exit 1
95 fi
96 cat > netrc <<EOF
97 machine ${machineName}
98 login ''$${varBase}USERNAME
99 password ''$${varBase}PASSWORD
100 EOF
101 '';
102 netrcImpureEnvVars = [
103 "${varBase}USERNAME"
104 "${varBase}PASSWORD"
105 ];
106 };
107
108 gitRepoUrl = "${baseUrl}.git";
109
110 revWithTag = if tag != null then "refs/tags/${tag}" else rev;
111
112 fetcherArgs =
113 (
114 if useFetchGit then
115 {
116 inherit
117 tag
118 rev
119 deepClone
120 fetchSubmodules
121 sparseCheckout
122 fetchLFS
123 ;
124 url = gitRepoUrl;
125 }
126 // lib.optionalAttrs (leaveDotGit != null) { inherit leaveDotGit; }
127 else
128 {
129 # Use the API endpoint for private repos, as the archive URI doesn't
130 # support access with GitHub's fine-grained access tokens.
131 #
132 # Use the archive URI for non-private repos, as the API endpoint has
133 # relatively restrictive rate limits for unauthenticated users.
134 url =
135 if private then
136 let
137 endpoint = "/repos/${owner}/${repo}/tarball/${revWithTag}";
138 in
139 if githubBase == "github.com" then
140 "https://api.github.com${endpoint}"
141 else
142 "https://${githubBase}/api/v3${endpoint}"
143 else
144 "${baseUrl}/archive/${revWithTag}.tar.gz";
145 extension = "tar.gz";
146
147 passthru = {
148 inherit gitRepoUrl;
149 };
150 }
151 )
152 // privateAttrs
153 // passthruAttrs
154 // {
155 inherit name;
156 };
157 in
158
159 fetcher fetcherArgs
160 // {
161 meta = newMeta;
162 inherit owner repo tag;
163 rev = revWithTag;
164 }
165)