1{ lib, stdenv
2, fetchFromGitLab
3, fetchpatch
4, python3
5, librsync
6, ncftp
7, gnupg
8, gnutar
9, par2cmdline
10, util-linux
11, rsync
12, makeWrapper
13, gettext
14}:
15let
16 pythonPackages = python3.pkgs;
17 inherit (lib.versions) majorMinor splitVersion;
18 majorMinorPatch = v: builtins.concatStringsSep "." (lib.take 3 (splitVersion v));
19in
20pythonPackages.buildPythonApplication rec {
21 pname = "duplicity";
22 version = "0.8.20";
23
24 src = fetchFromGitLab {
25 owner = "duplicity";
26 repo = "duplicity";
27 rev = "rel.${version}";
28 sha256 = "13ghra0myq6h6yx8qli55bh8dg91nf1hpd8l7d7xamgrw6b188sm";
29 };
30
31 patches = [
32 # We use the tar binary on all platforms.
33 ./gnutar-in-test.patch
34
35 # Our Python infrastructure runs test in installCheckPhase so we need
36 # to make the testing code stop assuming it is run from the source directory.
37 ./use-installed-scripts-in-test.patch
38
39 # https://gitlab.com/duplicity/duplicity/-/merge_requests/64
40 # remove on next release
41 (fetchpatch {
42 url = "https://gitlab.com/duplicity/duplicity/-/commit/5c229a9b42f67257c747fbc0022c698fec405bbc.patch";
43 sha256 = "05v931rnawfv11cyxj8gykmal8rj5vq2ksdysyr2mb4sl81mi7v0";
44 })
45 ] ++ lib.optionals stdenv.isLinux [
46 # Broken on Linux in Nix' build environment
47 ./linux-disable-timezone-test.patch
48 ];
49
50 SETUPTOOLS_SCM_PRETEND_VERSION = version;
51
52 preConfigure = ''
53 # fix version displayed by duplicity --version
54 # see SourceCopy in setup.py
55 ls
56 for i in bin/*.1 duplicity/__init__.py; do
57 substituteInPlace "$i" --replace '$version' "${version}"
58 done
59 '';
60
61 nativeBuildInputs = [
62 makeWrapper
63 gettext
64 pythonPackages.wrapPython
65 pythonPackages.setuptools-scm
66 ];
67 buildInputs = [
68 librsync
69 ];
70
71 pythonPath = with pythonPackages; [
72 b2sdk
73 boto3
74 cffi
75 cryptography
76 ecdsa
77 idna
78 pygobject3
79 fasteners
80 ipaddress
81 lockfile
82 paramiko
83 pyasn1
84 pycrypto
85 pydrive
86 future
87 ] ++ lib.optionals (!isPy3k) [
88 enum
89 ];
90
91 checkInputs = [
92 gnupg # Add 'gpg' to PATH.
93 gnutar # Add 'tar' to PATH.
94 librsync # Add 'rdiff' to PATH.
95 par2cmdline # Add 'par2' to PATH.
96 ] ++ lib.optionals stdenv.isLinux [
97 util-linux # Add 'setsid' to PATH.
98 ] ++ (with pythonPackages; [
99 lockfile
100 mock
101 pexpect
102 pytest
103 pytest-runner
104 ]);
105
106 postInstall = ''
107 wrapProgram $out/bin/duplicity \
108 --prefix PATH : "${lib.makeBinPath [ gnupg ncftp rsync ]}"
109 '';
110
111 preCheck = ''
112 wrapPythonProgramsIn "$PWD/testing/overrides/bin" "$pythonPath"
113
114 # Add 'duplicity' to PATH for tests.
115 # Normally, 'setup.py test' adds 'build/scripts-2.7/' to PATH before running
116 # tests. However, 'build/scripts-2.7/duplicity' is not wrapped, so its
117 # shebang is incorrect and it fails to run inside Nix' sandbox.
118 # In combination with use-installed-scripts-in-test.patch, make 'setup.py
119 # test' use the installed 'duplicity' instead.
120 PATH="$out/bin:$PATH"
121
122 # Don't run developer-only checks (pep8, etc.).
123 export RUN_CODE_TESTS=0
124
125 # check version string
126 duplicity --version | grep ${version}
127 '' + lib.optionalString stdenv.isDarwin ''
128 # Work around the following error when running tests:
129 # > Max open files of 256 is too low, should be >= 1024.
130 # > Use 'ulimit -n 1024' or higher to correct.
131 ulimit -n 1024
132 '';
133
134 # TODO: Fix test failures on macOS 10.13:
135 #
136 # > OSError: out of pty devices
137 doCheck = !stdenv.isDarwin;
138
139 meta = with lib; {
140 description = "Encrypted bandwidth-efficient backup using the rsync algorithm";
141 homepage = "https://duplicity.gitlab.io/duplicity-web/";
142 license = licenses.gpl2Plus;
143 platforms = platforms.unix;
144 };
145}