nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{
2 lib,
3 runCommand,
4 transmission_4,
5 rqbit,
6 writeShellScript,
7 formats,
8 cacert,
9 rsync,
10}:
11let
12 urlRegexp = ".*xt=urn:bt[im]h:([^&]{64}|[^&]{40}).*";
13in
14{
15 url,
16 name ?
17 if (builtins.match urlRegexp url) == null then
18 "bittorrent"
19 else
20 "bittorrent-" + builtins.head (builtins.match urlRegexp url),
21 config ? { },
22 hash,
23 backend ? "transmission",
24 recursiveHash ? true,
25 flatten ? null,
26 postFetch ? "",
27 postUnpack ? "",
28 meta ? { },
29}:
30let
31 # Default to flattening if no flatten argument was specified.
32 flatten' = if flatten == null then true else flatten;
33
34 transmissionFinishScript = writeShellScript "fetch-bittorrent-done.sh" ''
35 ${postUnpack}
36 # Flatten the directory, so that only the torrent contents are in $out, not
37 # the folder name
38 shopt -s dotglob
39 mv -v $downloadedDirectory/*/* $out
40 rm -v -rf $downloadedDirectory
41 unset downloadedDirectory
42 ${postFetch}
43 kill $PPID
44 '';
45 jsonConfig = (formats.json { }).generate "jsonConfig" config;
46
47 # https://github.com/NixOS/nixpkgs/issues/432001
48 #
49 # For a while, the transmission backend would put the downloaded torrent in
50 # the output directory, but whether the rqbit backend would put the output in
51 # the output directory or a subdirectory depended on the version of rqbit.
52 # We want to standardise on a single behaviour, but give users of
53 # fetchtorrent with the rqbit backend some warning that the behaviour might
54 # be unexpected, particularly since we can't know what behaviour users might
55 # be expecting at this point, and they probably wouldn't notice a change
56 # straight away because the results are fixed-output derivations.
57 #
58 # This warning was introduced for 25.11, so we can remove handling of the
59 # `flatten` argument once that release is no longer supported.
60 warnings =
61 if backend == "rqbit" && flatten == null then
62 [
63 ''
64 `fetchtorrent` with the rqbit backend may or may not have the
65 downloaded files stored in a subdirectory of the output directory.
66 Verify which behaviour you need, and set the `flatten` argument to
67 `fetchtorrent` accordingly.
68
69 The `flatten = false` behaviour will still produce a warning, as this
70 behaviour is deprecated. It is only available with the "rqbit" backend
71 to provide temporary support for users who are relying on the
72 previous incorrect behaviour. For a warning-free evaluation, use
73 `flatten = true`.
74 ''
75 ]
76 else if flatten == false then
77 [
78 ''
79 `fetchtorrent` with `flatten = false` is deprecated and will be
80 removed in a future release.
81 ''
82 ]
83 else
84 [ ];
85in
86assert lib.assertMsg (config != { } -> backend == "transmission") ''
87 json config for configuring fetchtorrent only works with the transmission backend
88'';
89assert lib.assertMsg (backend == "transmission" -> flatten') ''
90 `flatten = false` is only supported by the rqbit backend for fetchtorrent
91'';
92runCommand name
93 {
94 inherit meta;
95 nativeBuildInputs = [
96 cacert
97 ]
98 ++ (
99 if (backend == "transmission") then
100 [ transmission_4 ]
101 else if (backend == "rqbit") then
102 [ rqbit ]
103 else
104 throw "rqbit or transmission are the only available backends for fetchtorrent"
105 );
106 outputHashAlgo = if hash != "" then null else "sha256";
107 outputHash = hash;
108 outputHashMode = if recursiveHash then "recursive" else "flat";
109
110 # url will be written to the derivation, meaning it can be parsed and utilized
111 # by external tools, such as tools that may want to seed fetchtorrent calls
112 # in nixpkgs
113 inherit url;
114 }
115 (
116 if (backend == "transmission") then
117 ''
118 export HOME=$TMP
119 export downloadedDirectory=$out/downloadedDirectory
120 mkdir -p $downloadedDirectory
121 mkdir -p $HOME/.config/transmission
122 cp ${jsonConfig} $HOME/.config/transmission/settings.json
123 port="$(shuf -n 1 -i 49152-65535)"
124 function handleChild {
125 # This detects failures and logs the contents of the transmission fetch
126 find $out
127 exit 0
128 }
129 trap handleChild CHLD
130 transmission-cli \
131 --port "$port" \
132 --portmap \
133 --finish ${transmissionFinishScript} \
134 --download-dir "$downloadedDirectory" \
135 "$url"
136 ''
137 else
138 ''
139 export HOME=$TMP
140 ''
141 + lib.optionalString flatten' ''
142 downloadedDirectory=$out/downloadedDirectory
143 mkdir -p $downloadedDirectory
144 ''
145 + lib.optionalString (!flatten') ''
146 downloadedDirectory=$out
147 ''
148 + ''
149 port="$(shuf -n 1 -i 49152-65535)"
150
151 rqbit \
152 --disable-dht-persistence \
153 --http-api-listen-addr "127.0.0.1:$port" \
154 download \
155 -o "$downloadedDirectory" \
156 --exit-on-finish \
157 "$url"
158
159 ${postUnpack}
160 ''
161 + lib.optionalString flatten' ''
162 # Flatten the directory, so that only the torrent contents are in $out,
163 # not the folder name
164 shopt -s dotglob
165 mv -v $downloadedDirectory/*/* $out
166 rm -v -rf $downloadedDirectory
167 unset downloadedDirectory
168 ''
169 + ''
170 ${postFetch}
171 ''
172 )