lib.sources: small performance improvements (#536129)

This commit is contained in:
Silvan Mosberger
2026-06-29 15:23:59 +00:00
committed by GitHub
+78 -50
View File
@@ -4,22 +4,31 @@
# Tested in lib/tests/sources.sh
let
inherit (lib.strings)
match
split
storeDir
escapeRegex
hasPrefix
hasSuffix
match
removePrefix
removeSuffix
split
splitString
storeDir
stringLength
substring
;
inherit (lib)
boolToString
filter
isString
readFile
concatStrings
length
elemAt
isList
any
boolToString
concatStrings
elemAt
fileContents
filter
head
isList
isString
last
length
readFile
;
inherit (lib.filesystem)
pathIsRegularFile
@@ -41,6 +50,12 @@ let
: 2\. Function argument
*/
cleanSourceFilter =
let
hasEmacsBackupFileSuffix = hasSuffix "~";
hasObjectSuffix = hasSuffix ".o";
hasSharedObjectSuffix = hasSuffix ".so";
hasResultPrefix = hasPrefix "result";
in
name: type:
let
baseName = baseNameOf name;
@@ -62,17 +77,15 @@ let
)
||
# Filter out editor backup / swap files.
lib.hasSuffix "~" baseName
hasEmacsBackupFileSuffix baseName
|| match "^\\.sw[a-z]$" baseName != null
|| match "^\\..*\\.sw[a-z]$" baseName != null
||
# Filter out generates files.
lib.hasSuffix ".o" baseName
|| lib.hasSuffix ".so" baseName
# Filter out generated files.
|| hasObjectSuffix baseName
|| hasSharedObjectSuffix baseName
||
# Filter out nix-build result symlinks
(type == "symlink" && lib.hasPrefix "result" baseName)
(type == "symlink" && hasResultPrefix baseName)
||
# Filter out sockets and other types of files we can't have in the store.
(type == "unknown")
@@ -133,13 +146,13 @@ let
{
# A path or cleanSourceWith result to filter and/or rename.
src,
# Optional with default value: constant true (include everything)
# Optional with default value of null (include everything)
# The function will be combined with the && operator such
# that src.filter is called lazily.
# For implementing a filter, see
# https://nixos.org/nix/manual/#builtin-filterSource
# Type: A function (Path -> Type -> Bool)
filter ? _path: _type: true,
filter ? null,
# Optional name to use as part of the store path.
# This defaults to `src.name` or otherwise `"source"`.
name ? null,
@@ -149,7 +162,13 @@ let
in
fromSourceAttributes {
inherit (orig) origSrc;
filter = path: type: filter path type && orig.filter path type;
filter =
if orig.filter == null then
filter
else if filter == null then
orig.filter
else
path: type: filter path type && orig.filter path type;
name = if name != null then name else orig.name;
};
@@ -178,11 +197,14 @@ let
attrs
// {
filter =
path: type:
let
r = attrs.filter path type;
in
builtins.trace "${attrs.name}.filter ${path} = ${boolToString r}" r;
if attrs.filter == null then
path: type: builtins.trace "${attrs.name}.filter ${path} = true" true
else
path: type:
let
r = attrs.filter path type;
in
builtins.trace "${attrs.name}.filter ${path} = ${boolToString r}" r;
}
)
// {
@@ -218,13 +240,13 @@ let
isFiltered = src ? _isLibCleanSourceWith;
origSrc = if isFiltered then src.origSrc else src;
in
lib.cleanSourceWith {
cleanSourceWith {
filter = (
path: type:
let
relPath = lib.removePrefix (toString origSrc + "/") (toString path);
relPath = removePrefix (toString origSrc + "/") (toString path);
in
lib.any (re: match re relPath != null) regexes
any (re: match re relPath != null) regexes
);
inherit src;
};
@@ -272,7 +294,7 @@ let
let
base = baseNameOf name;
in
type == "directory" || lib.any (ext: lib.hasSuffix ext base) exts;
type == "directory" || any (ext: hasSuffix ext base) exts;
in
cleanSourceWith { inherit filter src; };
@@ -319,9 +341,9 @@ let
packedRefsName = path + "/packed-refs";
absolutePath =
base: path:
if lib.hasPrefix "/" path then
if hasPrefix "/" path then
path
else if lib.hasPrefix "/" base then
else if hasPrefix "/" base then
"${base}/${path}"
else
"/${base}/${path}";
@@ -337,12 +359,12 @@ let
{ error = "File contains no gitdir reference: " + path; }
else
let
gitDir = absolutePath (dirOf path) (lib.head m);
gitDir = absolutePath (dirOf path) (head m);
commonDir'' =
if pathIsRegularFile "${gitDir}/commondir" then lib.fileContents "${gitDir}/commondir" else gitDir;
commonDir' = lib.removeSuffix "/" commonDir'';
if pathIsRegularFile "${gitDir}/commondir" then fileContents "${gitDir}/commondir" else gitDir;
commonDir' = removeSuffix "/" commonDir'';
commonDir = absolutePath gitDir commonDir';
refFile = lib.removePrefix "${commonDir}/" "${gitDir}/${file}";
refFile = removePrefix "${commonDir}/" "${gitDir}/${file}";
in
readCommitFromFile refFile commonDir
@@ -352,10 +374,10 @@ let
# sometimes it stores something like: «ref: refs/heads/branch-name»
then
let
fileContent = lib.fileContents fileName;
fileContent = fileContents fileName;
matchRef = match "^ref: (.*)$" fileContent;
in
if matchRef == null then { value = fileContent; } else readCommitFromFile (lib.head matchRef) path
if matchRef == null then { value = fileContent; } else readCommitFromFile (head matchRef) path
else if
pathIsRegularFile packedRefsName
@@ -373,14 +395,14 @@ let
if refs == [ ] then
{ error = "Could not find " + file + " in " + packedRefsName; }
else
{ value = lib.head (matchRef (lib.head refs)); }
{ value = head (matchRef (head refs)); }
else
{ error = "Not a .git directory: " + toString path; };
in
readCommitFromFile "HEAD";
pathHasContext = builtins.hasContext or (lib.hasPrefix storeDir);
pathHasContext = builtins.hasContext or (hasPrefix storeDir);
canCleanSource = src: src ? _isLibCleanSourceWith || !(pathHasContext (toString src));
@@ -403,7 +425,7 @@ let
{
# The original path
origSrc = if isFiltered then src.origSrc else src;
filter = if isFiltered then src.filter else _: _: true;
filter = if isFiltered then src.filter else null; # make sure to handle this!
name = if isFiltered then src.name else "source";
};
@@ -411,6 +433,9 @@ let
#
# Inverse of toSourceAttributes for Source objects.
fromSourceAttributes =
let
inherit (builtins) path;
in
{
origSrc,
filter,
@@ -418,9 +443,13 @@ let
}:
{
_isLibCleanSourceWith = true;
inherit origSrc filter name;
outPath = builtins.path {
inherit filter name;
inherit origSrc name;
# preserve outside checks, since a filter of null looks odd for
# comparisons
filter = if filter == null then _: _: true else filter;
outPath = path {
inherit name;
${if filter != null then "filter" else null} = filter;
path = origSrc;
};
};
@@ -431,15 +460,14 @@ let
urlToName =
url:
let
inherit (lib.strings) stringLength;
base = baseNameOf (lib.removeSuffix "/" (lib.last (lib.splitString ":" (toString url))));
base = baseNameOf (removeSuffix "/" (last (splitString ":" (toString url))));
# chop away one git or archive-related extension
removeExt =
name:
let
matchExt = 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;
if matchExt != null then head matchExt else name;
# apply function f to string x while the result shrinks
shrink =
f: x:
@@ -461,9 +489,9 @@ let
matchVer = match "([A-Za-z]+[-_. ]?)*(v)?([0-9.]+.*)" baseRev;
in
if matchHash != null then
builtins.substring 0 7 baseRev
substring 0 7 baseRev
else if matchVer != null then
lib.last matchVer
last matchVer
else
baseRev;
@@ -623,7 +651,7 @@ let
in
src: patterns:
lib.cleanSourceWith {
cleanSourceWith {
filter = mkSourceFilter src patterns;
inherit src;
};