aboutsummaryrefslogtreecommitdiffstats
path: root/lib/default.nix
blob: 4eb643832428627d5bcbe16982b616c99ef38fda (plain)
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
let {

  body = lib;

  lib = nixpkgs.lib // builtins // {

    # What populate's Nix library defines.
    inherit (populate.lib) evalSource flakeFollows hasGeneratedFlake derivesFlake;

    maybeHostName = default: let
      # We're parsing /etc/hostname here because reading
      # /proc/sys/kernel/hostname yields ""
      path = "/etc/hostname";
      lines = lib.splitString "\n" (lib.readFile path);
      hostNames = lib.filter lib.types.label.check lines;
    in
      if lib.pathExists path then
        if lib.length hostNames == 1 then
          lib.head hostNames
        else
          lib.trace "malformed ${path}" default
      else
        default;

    firstWord = s:
      lib.head (lib.match "^([^[:space:]]*).*" s);

    isLocalTarget = let
      origin = lib.mkTarget "";
    in target:
      target.user == origin.user &&
      lib.elem target.host [origin.host "localhost"];

    mkTarget = s: let
      parse = lib.match "(([^@]*)@)?(([^:/]+))?(:([^/]+))?(/.*)?" s;
      elemAt' = xs: i: if lib.length xs > i then lib.elemAt xs i else null;
      filterNull = lib.filterAttrs (n: v: v != null);
    in {
      user = lib.maybeEnv "LOGNAME" null;
      host = lib.maybeEnv "HOSTNAME" (lib.maybeHostName "localhost");
      port = null;
      path = "/var/src";
      sudo = false;
      extraOptions = [];
    } // (if lib.isString s then filterNull {
      user = elemAt' parse 1;
      host = elemAt' parse 3;
      port = elemAt' parse 5;
      path = elemAt' parse 6;
    } else s);

    mkUserPortSSHOpts = target:
      (lib.optionals (target.user != null) ["-l" target.user]) ++
      (lib.optionals (target.port != null) ["-p" target.port]);

    shell = let
      isSafeChar = lib.testString "[-+./0-9:=A-Z_a-z]";
      quoteChar = c:
        if isSafeChar c then c
        else if c == "\n" then "'\n'"
        else "\\${c}";
    in {
      quote = x: if x == "" then "''" else lib.stringAsChars quoteChar x;

      # Shell code defining the function url_path, which prints the path $1
      # as it goes into a URL: with every byte percent-encoded that isn't a
      # letter, a digit, or one of -._~/.  Nix decodes that, and otherwise
      # takes, e.g., ? and # for delimiters, and refuses blanks.
      urlPath = /* sh */ ''
        url_path() {
          printf %s "$1" | od -An -v -tx1 | tr -s ' ' '\n' |
          while read -r url_byte; do
            case $url_byte in
              "") ;;
              2[d-f]|3[0-9]|4[1-9a-f]|5[0-9a]|5f|6[1-9a-f]|7[0-9a]|7e)
                printf "\\$(printf %o "0x$url_byte")"
                ;;
              *)
                printf '%%%s' "$url_byte"
                ;;
            esac
          done
        }
      '';

      # Shell code that enables flakes for the Nix commands following it, and
      # fails unless Nix supports them, i.e. is version 2.4 or later.  `what`
      # names what needs flakes, for the error message.
      requireFlakes = what: /* sh */ ''
        NIX_CONFIG=$(printf '%s\n%s' "''${NIX_CONFIG-}" \
            'extra-experimental-features = nix-command flakes')
        export NIX_CONFIG
        if ! nix flake --help >/dev/null 2>&1; then
          >&2 printf 'error: %s needs Nix 2.4 or later on %s, found: %s\n' \
              ${lib.shell.quote what} "$(uname -n)" "$(nix --version 2>&1 || :)"
          exit 1
        fi
      '';
    };

    test = re: x: lib.isString x && lib.testString re x;
    testString = re: x: lib.match re x != null;

    types = nixpkgs.lib.types // populate.lib.types;
  };

  nixpkgs.lib = import <nixpkgs/lib>;

  populate.lib = import ../pkgs/populate/lib { lib = nixpkgs.lib; };

}