mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-08-25 17:55:21 +00:00
fetchtorrent: fix single-file torrents (#497402)
This commit is contained in:
@@ -79,7 +79,7 @@ indent_size = unset
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
# binaries
|
||||
[*.nib]
|
||||
[*.{nib,torrent}]
|
||||
end_of_line = unset
|
||||
insert_final_newline = unset
|
||||
trim_trailing_whitespace = unset
|
||||
|
||||
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -62,3 +62,6 @@ ci/OWNERS linguist-language=CODEOWNERS
|
||||
# patching CRLF line endings from an upstream source package.
|
||||
*.diff !text !eol
|
||||
*.patch !text !eol
|
||||
|
||||
# Torrent files are binary files and should not be re-encoded.
|
||||
*.torrent !text !eol
|
||||
|
||||
@@ -31,57 +31,48 @@ let
|
||||
# Default to flattening if no flatten argument was specified.
|
||||
flatten' = if flatten == null then true else flatten;
|
||||
|
||||
transmissionFinishScript = writeShellScript "fetch-bittorrent-done.sh" ''
|
||||
setupScript = ''
|
||||
export HOME=$TMP
|
||||
mkdir -p $out
|
||||
downloadedDirectory=${
|
||||
if flatten' then "$(mktemp -d $out/downloadedDirectory.XXXXXXXXXX)" else "$out"
|
||||
}
|
||||
export downloadedDirectory # See https://www.shellcheck.net/wiki/SC2155
|
||||
port="$(shuf -n 1 -i 49152-65535)"
|
||||
'';
|
||||
|
||||
flattenScript = ''
|
||||
(
|
||||
shopt -s dotglob nullglob
|
||||
downloadedFiles=($downloadedDirectory/*)
|
||||
if [[ ''${#downloadedFiles[@]} -eq 0 ]]; then
|
||||
echo "Failed to download any files."
|
||||
exit 1
|
||||
elif [[ ''${#downloadedFiles[@]} -eq 1 ]] && [[ -d "$downloadedFiles" ]]; then
|
||||
# Flatten the directory, so that only the torrent contents are in $out,
|
||||
# not the folder name
|
||||
mv -v "$downloadedFiles"/* $out
|
||||
else
|
||||
# Either we downloaded a single (regular) file, or we downloaded
|
||||
# multiple files/directories. We can't flatten, so we move them to
|
||||
# $out.
|
||||
mv -v "''${downloadedFiles[@]}" $out
|
||||
fi
|
||||
rm -v -rf $downloadedDirectory
|
||||
)
|
||||
'';
|
||||
|
||||
finishScript = ''
|
||||
${postUnpack}
|
||||
# Flatten the directory, so that only the torrent contents are in $out, not
|
||||
# the folder name
|
||||
shopt -s dotglob
|
||||
mv -v $downloadedDirectory/*/* $out
|
||||
rm -v -rf $downloadedDirectory
|
||||
unset downloadedDirectory
|
||||
${lib.optionalString flatten' flattenScript}
|
||||
${postFetch}
|
||||
'';
|
||||
|
||||
transmissionFinishScript = writeShellScript "fetch-bittorrent-done.sh" ''
|
||||
${finishScript}
|
||||
kill $PPID
|
||||
'';
|
||||
jsonConfig = (formats.json { }).generate "jsonConfig" config;
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/issues/432001
|
||||
#
|
||||
# For a while, the transmission backend would put the downloaded torrent in
|
||||
# the output directory, but whether the rqbit backend would put the output in
|
||||
# the output directory or a subdirectory depended on the version of rqbit.
|
||||
# We want to standardise on a single behaviour, but give users of
|
||||
# fetchtorrent with the rqbit backend some warning that the behaviour might
|
||||
# be unexpected, particularly since we can't know what behaviour users might
|
||||
# be expecting at this point, and they probably wouldn't notice a change
|
||||
# straight away because the results are fixed-output derivations.
|
||||
#
|
||||
# This warning was introduced for 25.11, so we can remove handling of the
|
||||
# `flatten` argument once that release is no longer supported.
|
||||
warnings =
|
||||
if backend == "rqbit" && flatten == null then
|
||||
[
|
||||
''
|
||||
`fetchtorrent` with the rqbit backend may or may not have the
|
||||
downloaded files stored in a subdirectory of the output directory.
|
||||
Verify which behaviour you need, and set the `flatten` argument to
|
||||
`fetchtorrent` accordingly.
|
||||
|
||||
The `flatten = false` behaviour will still produce a warning, as this
|
||||
behaviour is deprecated. It is only available with the "rqbit" backend
|
||||
to provide temporary support for users who are relying on the
|
||||
previous incorrect behaviour. For a warning-free evaluation, use
|
||||
`flatten = true`.
|
||||
''
|
||||
]
|
||||
else if flatten == false then
|
||||
[
|
||||
''
|
||||
`fetchtorrent` with `flatten = false` is deprecated and will be
|
||||
removed in a future release.
|
||||
''
|
||||
]
|
||||
else
|
||||
[ ];
|
||||
in
|
||||
assert
|
||||
(config != { } -> backend == "transmission")
|
||||
@@ -103,7 +94,41 @@ runCommand name
|
||||
if (backend == "transmission") then
|
||||
[ transmission_4 ]
|
||||
else if (backend == "rqbit") then
|
||||
[ rqbit ]
|
||||
lib.warnIf (flatten != true) (
|
||||
# https://github.com/NixOS/nixpkgs/issues/432001
|
||||
#
|
||||
# For a while, the transmission backend would put the downloaded torrent in
|
||||
# the output directory, but whether the rqbit backend would put the output in
|
||||
# the output directory or a subdirectory depended on the version of rqbit.
|
||||
# We want to standardise on a single behaviour, but give users of
|
||||
# fetchtorrent with the rqbit backend some warning that the behaviour might
|
||||
# be unexpected, particularly since we can't know what behaviour users might
|
||||
# be expecting at this point, and they probably wouldn't notice a change
|
||||
# straight away because the results are fixed-output derivations.
|
||||
#
|
||||
# This warning was introduced for 25.11, so we can remove handling of the
|
||||
# `flatten` argument once that release is no longer supported.
|
||||
if flatten == null then
|
||||
''
|
||||
`fetchtorrent` with the rqbit backend may or may not have the
|
||||
downloaded files stored in a subdirectory of the output directory.
|
||||
Verify which behaviour you need, and set the `flatten` argument to
|
||||
`fetchtorrent` accordingly.
|
||||
|
||||
The `flatten = false` behaviour will still produce a warning, as this
|
||||
behaviour is deprecated. It is only available with the "rqbit" backend
|
||||
to provide temporary support for users who are relying on the
|
||||
previous incorrect behaviour. For a warning-free evaluation, use
|
||||
`flatten = true`.
|
||||
''
|
||||
else if flatten == false then
|
||||
''
|
||||
`fetchtorrent` with `flatten = false` is deprecated and will be
|
||||
removed in a future release.
|
||||
''
|
||||
else
|
||||
throw "invalid value for flatten: must be true, false, or null"
|
||||
) [ rqbit ]
|
||||
else
|
||||
throw "rqbit or transmission are the only available backends for fetchtorrent"
|
||||
);
|
||||
@@ -119,12 +144,9 @@ runCommand name
|
||||
(
|
||||
if (backend == "transmission") then
|
||||
''
|
||||
export HOME=$TMP
|
||||
export downloadedDirectory=$out/downloadedDirectory
|
||||
mkdir -p $downloadedDirectory
|
||||
${setupScript}
|
||||
mkdir -p $HOME/.config/transmission
|
||||
cp ${jsonConfig} $HOME/.config/transmission/settings.json
|
||||
port="$(shuf -n 1 -i 49152-65535)"
|
||||
function handleChild {
|
||||
# This detects failures and logs the contents of the transmission fetch
|
||||
find $out
|
||||
@@ -140,18 +162,7 @@ runCommand name
|
||||
''
|
||||
else
|
||||
''
|
||||
export HOME=$TMP
|
||||
''
|
||||
+ lib.optionalString flatten' ''
|
||||
downloadedDirectory=$out/downloadedDirectory
|
||||
mkdir -p $downloadedDirectory
|
||||
''
|
||||
+ lib.optionalString (!flatten') ''
|
||||
downloadedDirectory=$out
|
||||
''
|
||||
+ ''
|
||||
port="$(shuf -n 1 -i 49152-65535)"
|
||||
|
||||
${setupScript}
|
||||
rqbit \
|
||||
--disable-dht-persistence \
|
||||
--http-api-listen-addr "127.0.0.1:$port" \
|
||||
@@ -159,18 +170,6 @@ runCommand name
|
||||
-o "$downloadedDirectory" \
|
||||
--exit-on-finish \
|
||||
"$url"
|
||||
|
||||
${postUnpack}
|
||||
''
|
||||
+ lib.optionalString flatten' ''
|
||||
# Flatten the directory, so that only the torrent contents are in $out,
|
||||
# not the folder name
|
||||
shopt -s dotglob
|
||||
mv -v $downloadedDirectory/*/* $out
|
||||
rm -v -rf $downloadedDirectory
|
||||
unset downloadedDirectory
|
||||
''
|
||||
+ ''
|
||||
${postFetch}
|
||||
${finishScript}
|
||||
''
|
||||
)
|
||||
|
||||
1
pkgs/build-support/fetchtorrent/test-single-file.torrent
Normal file
1
pkgs/build-support/fetchtorrent/test-single-file.torrent
Normal file
@@ -0,0 +1 @@
|
||||
d10:created by13:mktorrent 1.113:creation datei1772926249e4:infod6:lengthi1097e4:name7:COPYING12:piece lengthi262144e6:pieces20:€åÏÊ\c™èçæÉ\Q3Ní-e8:url-list96:https://raw.githubusercontent.com/NixOS/nixpkgs/3d82431ec4b51262989559b821b83abe4a9f6dbd/COPYINGe
|
||||
@@ -47,7 +47,7 @@ let
|
||||
pushd "$out" &&
|
||||
sha512sum --check --strict ${./test-hashes.sha512sum} &&
|
||||
sed 's/.* //' ${./test-hashes.sha512sum} | xargs rm --verbose &&
|
||||
popd
|
||||
popd || exit 1
|
||||
'';
|
||||
unflattened.postFetch = ''
|
||||
pushd "$out" &&
|
||||
@@ -56,7 +56,7 @@ let
|
||||
sed 's/.* //' ${./test-hashes.sha512sum} | xargs rm --verbose &&
|
||||
popd &&
|
||||
rm --dir --verbose Sintel &&
|
||||
popd
|
||||
popd || exit 1
|
||||
'';
|
||||
|
||||
fetchtorrentWithHash =
|
||||
@@ -75,7 +75,7 @@ let
|
||||
);
|
||||
in
|
||||
# Seems almost but not quite worth using lib.mapCartesianProduct...
|
||||
builtins.mapAttrs (n: v: testers.invalidateFetcherByDrvHash fetchtorrentWithHash v) {
|
||||
(builtins.mapAttrs (n: v: testers.invalidateFetcherByDrvHash fetchtorrentWithHash v) {
|
||||
http-link = {
|
||||
inherit (http) url;
|
||||
inherit (flattened) postFetch;
|
||||
@@ -94,16 +94,22 @@ builtins.mapAttrs (n: v: testers.invalidateFetcherByDrvHash fetchtorrentWithHash
|
||||
backend = "transmission";
|
||||
inherit (flattened) postFetch;
|
||||
};
|
||||
http-link-rqbit = {
|
||||
inherit (http) url;
|
||||
backend = "rqbit";
|
||||
inherit (flattened) postFetch;
|
||||
};
|
||||
magnet-link-rqbit = {
|
||||
inherit (magnet) url;
|
||||
backend = "rqbit";
|
||||
inherit (flattened) postFetch;
|
||||
};
|
||||
#
|
||||
# Disabled because these warn that flatten hasn't been explicitly
|
||||
# set to true, and warnings are treated as failures in tests.
|
||||
#
|
||||
# Re-enable these tests when flatten defaults to true.
|
||||
#
|
||||
#http-link-rqbit = {
|
||||
# inherit (http) url;
|
||||
# backend = "rqbit";
|
||||
# inherit (flattened) postFetch;
|
||||
#};
|
||||
#magnet-link-rqbit = {
|
||||
# inherit (magnet) url;
|
||||
# backend = "rqbit";
|
||||
# inherit (flattened) postFetch;
|
||||
#};
|
||||
http-link-rqbit-flattened = {
|
||||
inherit (http) url;
|
||||
backend = "rqbit";
|
||||
@@ -116,16 +122,38 @@ builtins.mapAttrs (n: v: testers.invalidateFetcherByDrvHash fetchtorrentWithHash
|
||||
flatten = true;
|
||||
inherit (flattened) postFetch;
|
||||
};
|
||||
http-link-rqbit-unflattened = {
|
||||
inherit (http) url;
|
||||
backend = "rqbit";
|
||||
flatten = false;
|
||||
inherit (unflattened) postFetch;
|
||||
};
|
||||
magnet-link-rqbit-unflattened = {
|
||||
inherit (magnet) url;
|
||||
backend = "rqbit";
|
||||
flatten = false;
|
||||
inherit (unflattened) postFetch;
|
||||
#
|
||||
# Disabled because these warn that `flatten = false` is deprecated
|
||||
# and will be removed.
|
||||
#
|
||||
# Remove these when support for `flatten = false` is completely removed.
|
||||
#
|
||||
#http-link-rqbit-unflattened = {
|
||||
# inherit (http) url;
|
||||
# backend = "rqbit";
|
||||
# flatten = false;
|
||||
# inherit (unflattened) postFetch;
|
||||
#};
|
||||
#magnet-link-rqbit-unflattened = {
|
||||
# inherit (magnet) url;
|
||||
# backend = "rqbit";
|
||||
# flatten = false;
|
||||
# inherit (unflattened) postFetch;
|
||||
#};
|
||||
})
|
||||
// {
|
||||
# Make sure we can download and "flatten" single-file torrents.
|
||||
# We only test with transmission because we use a web-seed and rqbit
|
||||
# doesn't support web-seeds.
|
||||
single-file = fetchtorrent {
|
||||
hash = "sha256-u5c/ZN5V79Jg1aN6spbui4OdhExsXjofk1JpvUdW7Ro=";
|
||||
backend = "transmission";
|
||||
flatten = true;
|
||||
url = "${./test-single-file.torrent}";
|
||||
meta = {
|
||||
hydraPlatforms = [ ];
|
||||
license = lib.licenses.mit;
|
||||
description = "The license file for the Nixpkgs repository as of 7 March 2026";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user