nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at haskell-updates 273 lines 9.4 kB view raw
1{ 2 config, 3 lib, 4 stdenvNoCC, 5 git, 6 git-lfs, 7 cacert, 8}: 9 10let 11 urlToName = 12 { 13 url, 14 rev, 15 append, 16 }: 17 let 18 shortRev = lib.sources.shortRev rev; 19 appendShort = lib.optionalString ((builtins.match "[a-f0-9]*" rev) != null) "-${shortRev}"; 20 in 21 "${lib.sources.urlToName url}${if append == "" then appendShort else append}"; 22 23 getRevWithTag = 24 { 25 rev ? null, 26 tag ? null, 27 }: 28 if tag != null && rev != null then 29 throw "fetchgit requires one of either `rev` or `tag` to be provided (not both)." 30 else if tag != null then 31 "refs/tags/${tag}" 32 else if rev != null then 33 rev 34 else 35 # FIXME fetching HEAD if no rev or tag is provided is problematic at best 36 "HEAD"; 37in 38 39lib.makeOverridable ( 40 lib.extendMkDerivation { 41 constructDrv = stdenvNoCC.mkDerivation; 42 43 excludeDrvArgNames = [ 44 # Additional stdenv.mkDerivation arguments from derived fetchers. 45 "derivationArgs" 46 47 # Hashes, handled by `lib.fetchers.withNormalizedHash` 48 # whose outputs contain outputHash* attributes. 49 # Use `hash` when overriding with `<pkg>.overrideAttrs`. 50 "sha256" 51 ]; 52 53 extendDrvArgs = 54 finalAttrs: 55 lib.fetchers.withNormalizedHash { } ( 56 # NOTE Please document parameter additions or changes in 57 # ../../../doc/build-helpers/fetchers.chapter.md 58 { 59 url, 60 tag ? null, 61 rev ? null, 62 name ? urlToName { 63 inherit url; 64 rev = lib.revOrTag finalAttrs.revCustom finalAttrs.tag; 65 # when rootDir is specified, avoid invalidating the result when rev changes 66 append = if rootDir != "" then "-${lib.strings.sanitizeDerivationName rootDir}" else ""; 67 }, 68 # When null, will default to: `deepClone || fetchTags` 69 leaveDotGit ? null, 70 outputHash ? lib.fakeHash, 71 outputHashAlgo ? null, 72 fetchSubmodules ? true, 73 deepClone ? false, 74 branchName ? null, 75 # When null, will default to: `lib.optional (rootdir != "") rootdir` 76 sparseCheckout ? null, 77 # When null, will default to: `rootDir != ""` 78 nonConeMode ? null, 79 nativeBuildInputs ? [ ], 80 # Shell code executed before the file has been fetched. This, in 81 # particular, can do things like set NIX_PREFETCH_GIT_CHECKOUT_HOOK to 82 # run operations between the checkout completing and deleting the .git 83 # directory. 84 preFetch ? "", 85 # Shell code executed after `git checkout` and before .git directory removal/sanitization. 86 postCheckout ? "", 87 # Shell code executed after the file has been fetched 88 # successfully. This can do things like check or transform the file. 89 postFetch ? "", 90 preferLocalBuild ? true, 91 fetchLFS ? false, 92 # Shell code to build a netrc file for BASIC auth 93 netrcPhase ? null, 94 # Impure env vars (https://nixos.org/nix/manual/#sec-advanced-attributes) 95 # needed for netrcPhase 96 netrcImpureEnvVars ? [ ], 97 passthru ? { }, 98 meta ? { }, 99 allowedRequisites ? null, 100 # fetch all tags after tree (useful for git describe) 101 fetchTags ? false, 102 # make this subdirectory the root of the result 103 rootDir ? "", 104 # GIT_CONFIG_GLOBAL (as a file) 105 gitConfigFile ? config.gitConfigFile, 106 # Additional stdenvNoCC.mkDerivation arguments. 107 # It is typically for derived fetchers to pass down additional arguments, 108 # and the specified arguments have lower precedence than other mkDerivation arguments. 109 derivationArgs ? { }, 110 }: 111 112 /* 113 NOTE: 114 fetchgit has one problem: git fetch only works for refs. 115 This is because fetching arbitrary (maybe dangling) commits creates garbage collection risks 116 and checking whether a commit belongs to a ref is expensive. This may 117 change in the future when some caching is added to git (?) 118 Usually refs are either tags (refs/tags/*) or branches (refs/heads/*) 119 Cloning branches will make the hash check fail when there is an update. 120 But not all patches we want can be accessed by tags. 121 122 The workaround is getting the last n commits so that it's likely that they 123 still contain the hash we want. 124 125 for now : increase depth iteratively (TODO) 126 127 real fix: ask git folks to add a 128 git fetch $HASH contained in $BRANCH 129 facility because checking that $HASH is contained in $BRANCH is less 130 expensive than fetching --depth $N. 131 Even if git folks implemented this feature soon it may take years until 132 server admins start using the new version? 133 */ 134 135 let 136 finalHashHasColon = lib.hasInfix ":" finalAttrs.hash; 137 finalHashColonMatch = lib.match "([^:]+)[:](.*)" finalAttrs.hash; 138 in 139 140 derivationArgs 141 // { 142 __structuredAttrs = true; 143 144 inherit name; 145 146 builder = ./builder.sh; 147 fetcher = ./nix-prefetch-git; 148 149 nativeBuildInputs = [ 150 git 151 cacert 152 ] 153 ++ lib.optionals fetchLFS [ git-lfs ] 154 ++ nativeBuildInputs; 155 156 hash = 157 if outputHashAlgo == null || outputHash == "" || lib.hasPrefix outputHashAlgo outputHash then 158 outputHash 159 else 160 "${outputHashAlgo}:${outputHash}"; 161 162 outputHash = 163 if finalAttrs.hash == "" then 164 lib.fakeHash 165 else if finalHashHasColon then 166 lib.elemAt finalHashColonMatch 1 167 else 168 finalAttrs.hash; 169 outputHashAlgo = if finalHashHasColon then lib.head finalHashColonMatch else null; 170 outputHashMode = "recursive"; 171 172 sparseCheckout = 173 let 174 default = lib.optional (finalAttrs.rootDir != "") finalAttrs.rootDir; 175 in 176 lib.defaultTo default sparseCheckout; 177 sparseCheckoutText = 178 # Changed to throw on 2023-06-04 179 assert ( 180 lib.assertMsg (lib.isList finalAttrs.sparseCheckout) "Please provide directories/patterns for sparse checkout as a list of strings. Passing a (multi-line) string is not supported any more." 181 ); 182 assert finalAttrs.nonConeMode -> (finalAttrs.sparseCheckout != [ ]); 183 # git-sparse-checkout(1) says: 184 # > When the --stdin option is provided, the directories or patterns are read 185 # > from standard in as a newline-delimited list instead of from the arguments. 186 builtins.concatStringsSep "\n" finalAttrs.sparseCheckout; 187 188 inherit 189 url 190 fetchLFS 191 fetchSubmodules 192 deepClone 193 branchName 194 preFetch 195 postCheckout 196 postFetch 197 fetchTags 198 rootDir 199 gitConfigFile 200 ; 201 leaveDotGit = 202 if leaveDotGit != null then 203 assert fetchTags -> leaveDotGit; 204 assert rootDir != "" -> !leaveDotGit; 205 leaveDotGit 206 else 207 deepClone || fetchTags; 208 nonConeMode = lib.defaultTo (finalAttrs.rootDir != "") nonConeMode; 209 inherit tag; 210 revCustom = rev; 211 rev = getRevWithTag { 212 inherit (finalAttrs) tag; 213 rev = finalAttrs.revCustom; 214 }; 215 216 postHook = 217 if netrcPhase == null then 218 null 219 else 220 '' 221 ${netrcPhase} 222 # required that git uses the netrc file 223 mv {,.}netrc 224 export NETRC=$PWD/.netrc 225 export HOME=$PWD 226 ''; 227 228 impureEnvVars = 229 lib.fetchers.proxyImpureEnvVars 230 ++ netrcImpureEnvVars 231 ++ [ 232 "GIT_PROXY_COMMAND" 233 "NIX_GIT_SSL_CAINFO" 234 "SOCKS_SERVER" 235 236 # This is a parameter intended to be set by setup hooks or preFetch 237 # scripts that want per-URL control over HTTP proxies used by Git 238 # (if per-URL control isn't needed, `http_proxy` etc. will 239 # suffice). It must be a whitespace-separated (with backslash as an 240 # escape character) list of pairs like this: 241 # 242 # http://domain1/path1 proxy1 https://domain2/path2 proxy2 243 # 244 # where the URLs are as documented in the `git-config` manual page 245 # under `http.<url>.*`, and the proxies are as documented on the 246 # same page under `http.proxy`. 247 "FETCHGIT_HTTP_PROXIES" 248 ]; 249 250 outputChecks.out = { 251 ${if allowedRequisites != null then "allowedRequisites" else null} = allowedRequisites; 252 }; 253 254 inherit preferLocalBuild meta; 255 256 env = { 257 NIX_PREFETCH_GIT_CHECKOUT_HOOK = finalAttrs.postCheckout; 258 }; 259 260 passthru = { 261 gitRepoUrl = url; 262 } 263 // passthru; 264 } 265 ); 266 267 # No ellipsis. 268 inheritFunctionArgs = false; 269 } 270) 271// { 272 inherit getRevWithTag; 273}