-
-
Notifications
You must be signed in to change notification settings - Fork 15k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lib, treewide: introduce repoRevToName
and use it to cleanup most fetch*
functions
#316668
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -254,6 +254,62 @@ let | |
outPath = builtins.path { inherit filter name; path = origSrc; }; | ||
}; | ||
|
||
# urlToName : (URL | Path | String) -> String | ||
# | ||
# Transform a URL (or path, or string) into a clean package name. | ||
urlToName = url: | ||
let | ||
inherit (builtins) stringLength; | ||
base = baseNameOf (lib.removeSuffix "/" (lib.last (lib.splitString ":" (toString url)))); | ||
# chop away one git or archive-related extension | ||
removeExt = name: let | ||
matchExt = builtins.match "(.*)\\.(git|tar|zip|gz|tgz|bz|tbz|bz2|tbz2|lzma|txz|xz|zstd)" name; | ||
in if matchExt != null then lib.head matchExt else name; | ||
# apply function f to string x while the result shrinks | ||
shrink = f: x: let v = f x; in if stringLength v < stringLength x then shrink f v else x; | ||
in shrink removeExt base; | ||
|
||
# shortRev : (String | Integer) -> String | ||
# | ||
# Given a package revision (like "refs/tags/v12.0"), produce a short revision ("12.0"). | ||
shortRev = rev: | ||
let | ||
baseRev = baseNameOf (toString rev); | ||
matchHash = builtins.match "[a-f0-9]+" baseRev; | ||
matchVer = builtins.match "([A-Za-z]+[-_. ]?)*(v)?([0-9.]+.*)" baseRev; | ||
in | ||
if matchHash != null then builtins.substring 0 7 baseRev | ||
else if matchVer != null then lib.last matchVer | ||
else baseRev; | ||
|
||
# repoRevToNameFull : (URL | Path | String) -> (String | Integer | null) -> (String | null) -> String | ||
# | ||
# See `repoRevToName` below. | ||
repoRevToNameFull = repo_: rev_: suffix_: | ||
let | ||
repo = urlToName repo_; | ||
rev = if rev_ != null then "-${shortRev rev_}" else ""; | ||
suffix = if suffix_ != null then "-${suffix_}" else ""; | ||
in "${repo}${rev}${suffix}-source"; | ||
|
||
# repoRevToName : (Bool | String) -> (URL | Path | String) -> (String | Integer | null) -> String -> String | ||
# | ||
# Produce derivation.name attribute for a given repository URL/path/name and (optionally) its revision/version tag. | ||
# | ||
# This is used by fetch(zip|git|FromGitHub|hg|svn|etc) to generate discoverable | ||
# /nix/store paths. | ||
# | ||
# This uses a different implementation depending on the `pretty` argument: | ||
# false -> name everything as "source" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To be honest I do not like dual-type attributes. This is a serious footgun in a duck-typed language. And let's remember Nix is not stellar on the error report department: Either is everything a string, say There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But it is not checked by Nix but by the
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hum, less bad. Nonetheless, semantically it is a clear case for an enumeration with three possible states, instead of a weird Boolean-plus-an-extra. |
||
# true -> name everything as "${repo}-${rev}-source" | ||
# "full" -> name everything as "${repo}-${rev}-${fetcher}-source" | ||
repoRevToName = pretty: | ||
# match on `pretty` first to minimize the thunk | ||
if pretty == false then (repo: rev: suffix: "source") | ||
else if pretty == true then (repo: rev: suffix: repoRevToNameFull repo rev null) | ||
else if pretty == "full" then repoRevToNameFull | ||
else throw "invalid value of `pretty'"; | ||
|
||
in { | ||
|
||
pathType = lib.warnIf (lib.isInOldestRelease 2305) | ||
|
@@ -278,6 +334,10 @@ in { | |
pathHasContext | ||
canCleanSource | ||
|
||
urlToName | ||
shortRev | ||
repoRevToName | ||
|
||
sourceByRegex | ||
sourceFilesBySuffices | ||
|
||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -50,6 +50,39 @@ let | |||||
default = false; | ||||||
}; | ||||||
|
||||||
nameSourcesPrettily = mkOption { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, but why? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's shorter because it is more obscure. On the other hand, it depends on the previous tristate vs boolean-plus-state discussion. |
||||||
type = types.uniq (types.either types.bool (types.enum ["full"])); | ||||||
default = false; | ||||||
description = lib.mdDoc '' | ||||||
This controls the default derivation name attribute generated by the | ||||||
`fetch*` (like `fetchzip`, `fetchFromGitHub`, etc) functions. | ||||||
|
||||||
Possible values and the resulting `.name`: | ||||||
|
||||||
- `false` -> `"source"` | ||||||
- `true` -> `"''${repo}-''${rev}-source"` | ||||||
- `"full"` -> `"''${repo}-''${rev}-''${fetcherName}-source"` | ||||||
|
||||||
The default `false` is the best choice for minimal rebuilds, it will | ||||||
ignore any non-hash changes (like branches being renamed, source URLs | ||||||
changing, etc). | ||||||
|
||||||
Setting this to `true` greatly helps with discoverability of sources | ||||||
in `/nix/store` at the cost of a single mass-rebuild for all `src` | ||||||
derivations (but not their referrers, as all `src`s are fixed-output) | ||||||
and occasional rebuild when a source changes some of its non-hash | ||||||
attributes. | ||||||
|
||||||
Setting this to `"full"` is similar to setting it to `true`, but the | ||||||
use of `fetcherName` in the derivation name will force a rebuild when | ||||||
`src` switches between `fetch*` functions, thus forcing `nix` to check | ||||||
new derivation's `outputHash`, which is useful for debugging. | ||||||
|
||||||
Also, `"full"` is useful for easy collection and tracking of | ||||||
statistics of where the packages you use are hosted. | ||||||
''; | ||||||
}; | ||||||
|
||||||
doCheckByDefault = mkMassRebuild { | ||||||
feature = "run `checkPhase` by default"; | ||||||
}; | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I can be wrong, but the general term is URI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a thing more general than a URL? Yes. But here it is literally "a URL, or a path, or a string (a package name, usually)".