about summary refs log tree commit diff
path: root/pkgs/os-specific/bsd/freebsd/lib/default.nix
blob: 3fea3bc3e7f226b0b409f6f47cae15523d382328 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
{
  version,
  lib,
  writeText,
}:

{
  inherit version;

  mkBsdArch =
    stdenv':
    {
      x86_64 = "amd64";
      aarch64 = "arm64";
      i486 = "i386";
      i586 = "i386";
      i686 = "i386";
    }
    .${stdenv'.hostPlatform.parsed.cpu.name} or stdenv'.hostPlatform.parsed.cpu.name;

  install-wrapper = builtins.readFile ../../lib/install-wrapper.sh;

  # this function takes a list of patches and a list of paths and returns a list of derivations,
  # one per file that is patched, containing the actual patch contents. This allows us to have
  # extract only the patches that are relevant for a given subset of the source tree.
  # 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.
  filterPatches =
    patches: paths:
    let
      isDir =
        file:
        let
          base = baseNameOf file;
          type = (builtins.readDir (dirOf file)).${base} or null;
        in
        file == /. || type == "directory";
      consolidatePatches =
        patches:
        if (lib.isDerivation patches) then
          [ patches ]
        else if (builtins.isPath patches) then
          (if (isDir patches) then (lib.filesystem.listFilesRecursive patches) else [ patches ])
        else if (builtins.isList patches) then
          (lib.flatten (builtins.map consolidatePatches patches))
        else
          throw "Bad patches - must be path or derivation or list thereof";
      consolidated = consolidatePatches patches;
      splitPatch =
        patchFile:
        let
          allLines' = lib.strings.splitString "\n" (builtins.readFile patchFile);
          allLines = builtins.filter (
            line: !((lib.strings.hasPrefix "diff --git" line) || (lib.strings.hasPrefix "index " line))
          ) allLines';
          foldFunc =
            a: b:
            if ((lib.strings.hasPrefix "--- " b) || (lib.strings.hasPrefix "diff --git " b)) then
              (a ++ [ [ b ] ])
            else
              ((lib.lists.init a) ++ (lib.lists.singleton ((lib.lists.last a) ++ [ b ])));
          partitionedPatches' = lib.lists.foldl foldFunc [ [ ] ] allLines;
          partitionedPatches =
            if (builtins.length partitionedPatches' > 1) then
              (lib.lists.drop 1 partitionedPatches')
            else
              (throw "${patchFile} does not seem to be a unified patch (diff -u). this is required for FreeBSD.");
          filterFunc =
            patchLines:
            let
              prefixedPath = builtins.elemAt (builtins.split " |\t" (builtins.elemAt patchLines 1)) 2;
              unfixedPath = lib.path.subpath.join (lib.lists.drop 1 (lib.path.subpath.components prefixedPath));
            in
            lib.lists.any (included: lib.path.hasPrefix (/. + ("/" + included)) (/. + ("/" + unfixedPath))) (
              paths
            );
          filteredLines = builtins.filter filterFunc partitionedPatches;
          derive = patchLines: writeText "freebsd-patch" (lib.concatLines patchLines);
          derivedPatches = builtins.map derive filteredLines;
        in
        derivedPatches;
    in
    lib.lists.concatMap splitPatch consolidated;
}