Something went wrong. Try again.
lol
Something went wrong. Try again.
9.4 kB · 273 lines
Nix
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274{ config, lib, stdenvNoCC, git, git-lfs, cacert,}:
let urlToName = { url, rev, append, }: let shortRev = lib.sources.shortRev rev; appendShort = lib.optionalString ((builtins.match "[a-f0-9]*" rev) != null) "-${shortRev}"; in "${lib.sources.urlToName url}${if append == "" then appendShort else append}";
getRevWithTag = { rev ? null, tag ? null, }: if tag != null && rev != null then throw "fetchgit requires one of either `rev` or `tag` to be provided (not both)." else if tag != null then "refs/tags/${tag}" else if rev != null then rev else # FIXME fetching HEAD if no rev or tag is provided is problematic at best "HEAD";in
lib.makeOverridable ( lib.extendMkDerivation { constructDrv = stdenvNoCC.mkDerivation;
excludeDrvArgNames = [ # Additional stdenv.mkDerivation arguments from derived fetchers. "derivationArgs"
# Hashes, handled by `lib.fetchers.withNormalizedHash` # whose outputs contain outputHash* attributes. # Use `hash` when overriding with `<pkg>.overrideAttrs`. "sha256" ];
extendDrvArgs = finalAttrs: lib.fetchers.withNormalizedHash { } ( # NOTE Please document parameter additions or changes in # ../../../doc/build-helpers/fetchers.chapter.md { url, tag ? null, rev ? null, name ? urlToName { inherit url; rev = lib.revOrTag finalAttrs.revCustom finalAttrs.tag; # when rootDir is specified, avoid invalidating the result when rev changes append = if rootDir != "" then "-${lib.strings.sanitizeDerivationName rootDir}" else ""; }, # When null, will default to: `deepClone || fetchTags` leaveDotGit ? null, outputHash ? lib.fakeHash, outputHashAlgo ? null, fetchSubmodules ? true, deepClone ? false, branchName ? null, # When null, will default to: `lib.optional (rootdir != "") rootdir` sparseCheckout ? null, # When null, will default to: `rootDir != ""` nonConeMode ? null, nativeBuildInputs ? [ ], # Shell code executed before the file has been fetched. This, in # particular, can do things like set NIX_PREFETCH_GIT_CHECKOUT_HOOK to # run operations between the checkout completing and deleting the .git # directory. preFetch ? "", # Shell code executed after `git checkout` and before .git directory removal/sanitization. postCheckout ? "", # Shell code executed after the file has been fetched # successfully. This can do things like check or transform the file. postFetch ? "", preferLocalBuild ? true, fetchLFS ? false, # Shell code to build a netrc file for BASIC auth netrcPhase ? null, # Impure env vars (https://nixos.org/nix/manual/#sec-advanced-attributes) # needed for netrcPhase netrcImpureEnvVars ? [ ], passthru ? { }, meta ? { }, allowedRequisites ? null, # fetch all tags after tree (useful for git describe) fetchTags ? false, # make this subdirectory the root of the result rootDir ? "", # GIT_CONFIG_GLOBAL (as a file) gitConfigFile ? config.gitConfigFile, # Additional stdenvNoCC.mkDerivation arguments. # It is typically for derived fetchers to pass down additional arguments, # and the specified arguments have lower precedence than other mkDerivation arguments. derivationArgs ? { }, }:
/* NOTE: fetchgit has one problem: git fetch only works for refs. This is because fetching arbitrary (maybe dangling) commits creates garbage collection risks and checking whether a commit belongs to a ref is expensive. This may change in the future when some caching is added to git (?) Usually refs are either tags (refs/tags/*) or branches (refs/heads/*) Cloning branches will make the hash check fail when there is an update. But not all patches we want can be accessed by tags.
The workaround is getting the last n commits so that it's likely that they still contain the hash we want.
for now : increase depth iteratively (TODO)
real fix: ask git folks to add a git fetch $HASH contained in $BRANCH facility because checking that $HASH is contained in $BRANCH is less expensive than fetching --depth $N. Even if git folks implemented this feature soon it may take years until server admins start using the new version? */
let finalHashHasColon = lib.hasInfix ":" finalAttrs.hash; finalHashColonMatch = lib.match "([^:]+)[:](.*)" finalAttrs.hash; in
derivationArgs // { __structuredAttrs = true;
inherit name;
builder = ./builder.sh; fetcher = ./nix-prefetch-git;
nativeBuildInputs = [ git cacert ] ++ lib.optionals fetchLFS [ git-lfs ] ++ nativeBuildInputs;
hash = if outputHashAlgo == null || outputHash == "" || lib.hasPrefix outputHashAlgo outputHash then outputHash else "${outputHashAlgo}:${outputHash}";
outputHash = if finalAttrs.hash == "" then lib.fakeHash else if finalHashHasColon then lib.elemAt finalHashColonMatch 1 else finalAttrs.hash; outputHashAlgo = if finalHashHasColon then lib.head finalHashColonMatch else null; outputHashMode = "recursive";
sparseCheckout = let default = lib.optional (finalAttrs.rootDir != "") finalAttrs.rootDir; in lib.defaultTo default sparseCheckout; sparseCheckoutText = # Changed to throw on 2023-06-04 assert ( 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." ); assert finalAttrs.nonConeMode -> (finalAttrs.sparseCheckout != [ ]); # git-sparse-checkout(1) says: # > When the --stdin option is provided, the directories or patterns are read # > from standard in as a newline-delimited list instead of from the arguments. builtins.concatStringsSep "\n" finalAttrs.sparseCheckout;
inherit url fetchLFS fetchSubmodules deepClone branchName preFetch postCheckout postFetch fetchTags rootDir gitConfigFile ; leaveDotGit = if leaveDotGit != null then assert fetchTags -> leaveDotGit; assert rootDir != "" -> !leaveDotGit; leaveDotGit else deepClone || fetchTags; nonConeMode = lib.defaultTo (finalAttrs.rootDir != "") nonConeMode; inherit tag; revCustom = rev; rev = getRevWithTag { inherit (finalAttrs) tag; rev = finalAttrs.revCustom; };
postHook = if netrcPhase == null then null else '' ${netrcPhase} # required that git uses the netrc file mv {,.}netrc export NETRC=$PWD/.netrc export HOME=$PWD '';
impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ netrcImpureEnvVars ++ [ "GIT_PROXY_COMMAND" "NIX_GIT_SSL_CAINFO" "SOCKS_SERVER"
# This is a parameter intended to be set by setup hooks or preFetch # scripts that want per-URL control over HTTP proxies used by Git # (if per-URL control isn't needed, `http_proxy` etc. will # suffice). It must be a whitespace-separated (with backslash as an # escape character) list of pairs like this: # # http://domain1/path1 proxy1 https://domain2/path2 proxy2 # # where the URLs are as documented in the `git-config` manual page # under `http.<url>.*`, and the proxies are as documented on the # same page under `http.proxy`. "FETCHGIT_HTTP_PROXIES" ];
outputChecks.out = { ${if allowedRequisites != null then "allowedRequisites" else null} = allowedRequisites; };
inherit preferLocalBuild meta;
env = { NIX_PREFETCH_GIT_CHECKOUT_HOOK = finalAttrs.postCheckout; };
passthru = { gitRepoUrl = url; } // passthru; } );
# No ellipsis. inheritFunctionArgs = false; })// { inherit getRevWithTag;}