|
1 | | -{ version }: |
| 1 | +{ |
| 2 | + version, |
| 3 | + lib, |
| 4 | + writeText, |
| 5 | +}: |
2 | 6 |
|
3 | 7 | { |
4 | 8 | inherit version; |
|
15 | 19 | .${stdenv'.hostPlatform.parsed.cpu.name} or stdenv'.hostPlatform.parsed.cpu.name; |
16 | 20 |
|
17 | 21 | install-wrapper = builtins.readFile ../../lib/install-wrapper.sh; |
| 22 | + |
| 23 | + # this function takes a list of patches and a list of paths and returns a list of derivations, |
| 24 | + # one per file that is patched, containing the actual patch contents. This allows us to have |
| 25 | + # extract only the patches that are relevant for a given subset of the source tree. |
| 26 | + # note: the "list of patches" input can be a directory containing patch files, a path or a list of valid inputs to this argument, recursively. |
| 27 | + filterPatches = |
| 28 | + patches: paths: |
| 29 | + let |
| 30 | + isDir = |
| 31 | + file: |
| 32 | + let |
| 33 | + base = baseNameOf file; |
| 34 | + type = (builtins.readDir (dirOf file)).${base} or null; |
| 35 | + in |
| 36 | + file == /. || type == "directory"; |
| 37 | + consolidatePatches = |
| 38 | + patches: |
| 39 | + if (lib.isDerivation patches) then |
| 40 | + [ patches ] |
| 41 | + else if (builtins.isPath patches) then |
| 42 | + (if (isDir patches) then (lib.filesystem.listFilesRecursive patches) else [ patches ]) |
| 43 | + else if (builtins.isList patches) then |
| 44 | + (lib.flatten (builtins.map consolidatePatches patches)) |
| 45 | + else |
| 46 | + throw "Bad patches - must be path or derivation or list thereof"; |
| 47 | + consolidated = consolidatePatches patches; |
| 48 | + splitPatch = |
| 49 | + patchFile: |
| 50 | + let |
| 51 | + allLines' = lib.strings.splitString "\n" (builtins.readFile patchFile); |
| 52 | + allLines = builtins.filter ( |
| 53 | + line: !((lib.strings.hasPrefix "diff --git" line) || (lib.strings.hasPrefix "index " line)) |
| 54 | + ) allLines'; |
| 55 | + foldFunc = |
| 56 | + a: b: |
| 57 | + if ((lib.strings.hasPrefix "--- " b) || (lib.strings.hasPrefix "diff --git " b)) then |
| 58 | + (a ++ [ [ b ] ]) |
| 59 | + else |
| 60 | + ((lib.lists.init a) ++ (lib.lists.singleton ((lib.lists.last a) ++ [ b ]))); |
| 61 | + partitionedPatches' = lib.lists.foldl foldFunc [ [ ] ] allLines; |
| 62 | + partitionedPatches = |
| 63 | + if (builtins.length partitionedPatches' > 1) then |
| 64 | + (lib.lists.drop 1 partitionedPatches') |
| 65 | + else |
| 66 | + (throw "${patchFile} does not seem to be a unified patch (diff -u). this is required for FreeBSD."); |
| 67 | + filterFunc = |
| 68 | + patchLines: |
| 69 | + let |
| 70 | + prefixedPath = builtins.elemAt (builtins.split " |\t" (builtins.elemAt patchLines 1)) 2; |
| 71 | + unfixedPath = lib.path.subpath.join (lib.lists.drop 1 (lib.path.subpath.components prefixedPath)); |
| 72 | + in |
| 73 | + lib.lists.any (included: lib.path.hasPrefix (/. + ("/" + included)) (/. + ("/" + unfixedPath))) ( |
| 74 | + paths |
| 75 | + ); |
| 76 | + filteredLines = builtins.filter filterFunc partitionedPatches; |
| 77 | + derive = patchLines: writeText "freebsd-patch" (lib.concatLines patchLines); |
| 78 | + derivedPatches = builtins.map derive filteredLines; |
| 79 | + in |
| 80 | + derivedPatches; |
| 81 | + in |
| 82 | + lib.lists.concatMap splitPatch consolidated; |
18 | 83 | } |
0 commit comments