summaryrefslogtreecommitdiff
path: root/pkgs/build-support/fetchzip/default.nix
blob: 4376fef41085460a4af3db59bfc05ca931a795f4 (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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# This function downloads and unpacks an archive file, such as a zip
# or tar file. This is primarily useful for dynamically generated
# archives, such as GitHub's /archive URLs, where the unpacked content
# of the zip file doesn't change, but the zip file itself may
# (e.g. due to minor changes in the compression algorithm, or changes
# in timestamps).

{
  lib,
  repoRevToNameMaybe,
  fetchurl,
  withUnzip ? true,
  unzip,
  glibcLocalesUtf8,
}:

lib.extendMkDerivation {
  constructDrv = fetchurl;

  excludeDrvArgNames = [
    "extraPostFetch"

    # Pass via derivationArgs
    "extension"
    "stripRoot"
  ];

  extendDrvArgs =
    finalAttrs:
    {
      url ? "",
      urls ? [ ],
      name ? repoRevToNameMaybe (if url != "" then url else builtins.head urls) null "unpacked",
      nativeBuildInputs ? [ ],
      postFetch ? "",
      extraPostFetch ? "",

      # Optionally move the contents of the unpacked tree up one level.
      stripRoot ? true,
      # Allows to set the extension for the intermediate downloaded
      # file. This can be used as a hint for the unpackCmdHooks to select
      # an appropriate unpacking tool.
      extension ? null,

      # Additional stdenvNoCC.mkDerivation arguments.
      # It is typically for derived fetchers to pass down additional arguments,
      # and the specified arguments have lower precedence than other mkDerivation arguments.
      derivationArgs ? { },

      # the rest are given to fetchurl as is
      ...
    }@args:

    let
      tmpFilename =
        if finalAttrs.extension != null then
          "download.${finalAttrs.extension}"
        else
          baseNameOf (if url != "" then url else builtins.head urls);
    in

    {
      inherit name;
      recursiveHash = true;

      downloadToTemp = true;

      # Have to pull in glibcLocalesUtf8 for unzip in setup-hook.sh to handle
      # UTF-8 aware locale:
      #   https://github.com/NixOS/nixpkgs/issues/176225#issuecomment-1146617263
      nativeBuildInputs =
        lib.optionals withUnzip [
          unzip
          glibcLocalesUtf8
        ]
        ++ nativeBuildInputs;

      postFetch = ''
        unpackDir="$TMPDIR/unpack"
        mkdir "$unpackDir"
        cd "$unpackDir"

        renamed="$TMPDIR/${tmpFilename}"
        mv "$downloadedFile" "$renamed"
        unpackFile "$renamed"
        chmod -R +w "$unpackDir"
      ''
      + (
        if finalAttrs.stripRoot then
          ''
            if [ $(ls -A "$unpackDir" | wc -l) != 1 ]; then
              echo "error: zip file must contain a single file or directory."
              echo "hint: Pass stripRoot=false; to fetchzip to assume flat list of files."
              exit 1
            fi
            fn=$(cd "$unpackDir" && ls -A)
            if [ -f "$unpackDir/$fn" ]; then
              mkdir $out
            fi
            mv "$unpackDir/$fn" "$out"
          ''
        else
          ''
            mv "$unpackDir" "$out"
          ''
      )
      + ''
        ${postFetch}
        ${lib.warnIf (extraPostFetch != "")
          "use 'postFetch' instead of 'extraPostFetch' with 'fetchzip' and 'fetchFromGitHub' or 'fetchFromGitLab'."
          extraPostFetch
        }
        chmod 755 "$out"
      '';
      # ^ Remove non-owner write permissions
      # Fixes https://github.com/NixOS/nixpkgs/issues/38649

      derivationArgs = derivationArgs // {
        inherit
          extension
          stripRoot
          ;
      };
    };
}