duplicity 3.0.8.dev2__tar.gz → 3.0.8.dev4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/CHANGELOG.md +24 -2
- {duplicity-3.0.8.dev2/duplicity.egg-info → duplicity-3.0.8.dev4}/PKG-INFO +1 -1
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/__init__.py +2 -2
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/_librsyncmodule.c +4 -46
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/_cf_cloudfiles.py +2 -4
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/_cf_pyrax.py +2 -4
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/b2backend.py +2 -1
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/dpbxbackend.py +2 -4
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/gdrivebackend.py +2 -4
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/hubicbackend.py +2 -4
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/idrivedbackend.py +0 -1
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/imapbackend.py +6 -6
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/mediafirebackend.py +2 -4
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/onedrivebackend.py +0 -1
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/pcabackend.py +2 -4
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/pyrax_identity/hubic.py +2 -4
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/rclonebackend.py +4 -2
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/rsyncbackend.py +1 -1
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/s3_boto3_backend.py +3 -2
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/slatebackend.py +2 -4
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/ssh_paramiko_backend.py +2 -4
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/ssh_pexpect_backend.py +2 -4
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/swiftbackend.py +2 -4
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/webdavbackend.py +13 -23
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/cli_data.py +7 -4
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/cli_main.py +7 -21
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/cli_util.py +2 -8
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/config.py +4 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/diffdir.py +1 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/dup_main.py +47 -40
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/dup_time.py +4 -8
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/patchdir.py +1 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/path.py +0 -14
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/selection.py +12 -41
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/util.py +0 -89
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4/duplicity.egg-info}/PKG-INFO +1 -1
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/man/duplicity.1 +8 -1
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/pyproject.toml +1 -5
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/setup.py +1 -1
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/AUTHORS.md +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/COPYING +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/README-LOG.md +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/README-REPO.md +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/README-TESTING.md +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/README.md +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/__main__.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/argparse311.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backend_pool.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/__init__.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/_testbackend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/adbackend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/azurebackend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/boxbackend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/cfbackend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/gdocsbackend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/giobackend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/hsibackend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/jottacloudbackend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/lftpbackend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/localbackend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/megabackend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/megav2backend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/megav3backend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/multibackend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/ncftpbackend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/par2backend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/pydrivebackend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/pyrax_identity/__init__.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/sxbackend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/tahoebackend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/backends/xorrisobackend.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/cached_ops.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/dup_collections.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/dup_tarfile.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/dup_temp.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/errors.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/file_naming.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/filechunkio.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/globmatch.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/gpg.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/gpginterface.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/lazy.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/librsync.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/log.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/manifest.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/progress.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/robust.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/statistics.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity/tempdir.py +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity.egg-info/SOURCES.txt +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity.egg-info/dependency_links.txt +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity.egg-info/entry_points.txt +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity.egg-info/requires.txt +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/duplicity.egg-info/top_level.txt +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/af_ZA/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/ar_SA/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/ca_ES/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/cs_CZ/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/da_DK/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/de_AT/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/de_DE/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/el_GR/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/en_AU/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/en_GB/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/en_PR/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/en_US/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/es_EM/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/es_ES/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/es_MX/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/es_PR/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/es_US/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/fi_FI/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/fr_FR/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/he_IL/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/hu_HU/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/it_IT/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/ja_JP/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/ko_KR/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/nl_BE/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/nl_NL/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/nl_SR/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/no_NO/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/pl_PL/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/pt_BR/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/pt_PT/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/ro_RO/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/ru_BY/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/ru_MD/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/ru_RU/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/ru_UA/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/sr_SP/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/sv_SE/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/tr_TR/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/uk_UA/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/vi_VN/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/zh_CN/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/zh_HK/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/zh_MO/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/zh_SG/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/po/zh_TW/duplicity.mo +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/requirements.txt +0 -0
- {duplicity-3.0.8.dev2 → duplicity-3.0.8.dev4}/setup.cfg +0 -0
|
@@ -1,7 +1,29 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
rel.3.0.8.dev4 / 2026-03-31
|
|
3
|
+
===========================
|
|
4
|
+
|
|
5
|
+
* c17b03bc:fix: try/except block masking real S3UploadFailedError
|
|
6
|
+
* db127ce5:new: Add --full-if-n-inc flag for count-based full backup.
|
|
7
|
+
* dc977419:fix: Simplify swig module definition.
|
|
8
|
+
* 0de30e69:chg: Adjust to newer sphinx.
|
|
9
|
+
* c1883117:fix: Add templates for bug and feature requests.
|
|
10
|
+
* 39150d34:fix: delete unused Path.patch_with_attribs.
|
|
11
|
+
* 1a7c6790:fix: Remove support for Python 2.
|
|
12
|
+
* 564dd593:fix: fix flag name --gpg-agent -> --use-agent.
|
|
13
|
+
* 866680d0:chg: Multiple changes for 2026 are planned
|
|
14
|
+
* 29e00b55:fix: Fix incompatibility with Python 3.14.
|
|
15
|
+
* 50faabfc:chg: Partial fix for #924.
|
|
16
|
+
* 00ae7687:fix: webdav, always send warmup OPTIONS request, prevent loop
|
|
17
|
+
* 37841a0e:fix: Handle local version identifiers in b2backend
|
|
18
|
+
|
|
19
|
+
rel.3.0.8.dev3 / 2026-01-14
|
|
20
|
+
===========================
|
|
21
|
+
|
|
22
|
+
* 3475dd05:fix: Unnecessary passphrase prompt with --encrypt-key --no-check-remote.
|
|
23
|
+
* b8508f6d:chg: Remove slow marker from tests.
|
|
4
24
|
|
|
25
|
+
rel.3.0.8.dev2 / 2026-01-14
|
|
26
|
+
===========================
|
|
5
27
|
|
|
6
28
|
|
|
7
29
|
rel.3.0.7 / 2025-12-31
|
|
@@ -90,11 +90,7 @@ _librsync_sigmaker_cycle(_librsync_SigMakerObject *self, PyObject *args)
|
|
|
90
90
|
rs_buffers_t buf;
|
|
91
91
|
rs_result result;
|
|
92
92
|
|
|
93
|
-
#if PY_MAJOR_VERSION >= 3
|
|
94
93
|
if (!PyArg_ParseTuple(args, "y#:cycle", &inbuf, &inbuf_length))
|
|
95
|
-
#else
|
|
96
|
-
if (!PyArg_ParseTuple(args, "s#:cycle", &inbuf, &inbuf_length))
|
|
97
|
-
#endif
|
|
98
94
|
return NULL;
|
|
99
95
|
|
|
100
96
|
buf.next_in = inbuf;
|
|
@@ -110,11 +106,7 @@ _librsync_sigmaker_cycle(_librsync_SigMakerObject *self, PyObject *args)
|
|
|
110
106
|
return NULL;
|
|
111
107
|
}
|
|
112
108
|
|
|
113
|
-
#if PY_MAJOR_VERSION >= 3
|
|
114
109
|
return Py_BuildValue("(ily#)", (result == RS_DONE),
|
|
115
|
-
#else
|
|
116
|
-
return Py_BuildValue("(ils#)", (result == RS_DONE),
|
|
117
|
-
#endif
|
|
118
110
|
(long)inbuf_length - (long)buf.avail_in,
|
|
119
111
|
outbuf, RS_JOB_BLOCKSIZE - (long)buf.avail_out);
|
|
120
112
|
}
|
|
@@ -178,11 +170,7 @@ _librsync_new_deltamaker(PyObject* self, PyObject* args)
|
|
|
178
170
|
rs_buffers_t buf;
|
|
179
171
|
rs_result result;
|
|
180
172
|
|
|
181
|
-
#if PY_MAJOR_VERSION >= 3
|
|
182
173
|
if (!PyArg_ParseTuple(args,"y#:new_deltamaker", &sig_string, &sig_length))
|
|
183
|
-
#else
|
|
184
|
-
if (!PyArg_ParseTuple(args,"s#:new_deltamaker", &sig_string, &sig_length))
|
|
185
|
-
#endif
|
|
186
174
|
return NULL;
|
|
187
175
|
|
|
188
176
|
dm = PyObject_New(_librsync_DeltaMakerObject, &_librsync_DeltaMakerType);
|
|
@@ -237,11 +225,7 @@ _librsync_deltamaker_cycle(_librsync_DeltaMakerObject *self, PyObject *args)
|
|
|
237
225
|
rs_buffers_t buf;
|
|
238
226
|
rs_result result;
|
|
239
227
|
|
|
240
|
-
#if PY_MAJOR_VERSION >= 3
|
|
241
228
|
if (!PyArg_ParseTuple(args, "y#:cycle", &inbuf, &inbuf_length))
|
|
242
|
-
#else
|
|
243
|
-
if (!PyArg_ParseTuple(args, "s#:cycle", &inbuf, &inbuf_length))
|
|
244
|
-
#endif
|
|
245
229
|
return NULL;
|
|
246
230
|
|
|
247
231
|
buf.next_in = inbuf;
|
|
@@ -256,11 +240,7 @@ _librsync_deltamaker_cycle(_librsync_DeltaMakerObject *self, PyObject *args)
|
|
|
256
240
|
return NULL;
|
|
257
241
|
}
|
|
258
242
|
|
|
259
|
-
#if PY_MAJOR_VERSION >= 3
|
|
260
243
|
return Py_BuildValue("(ily#)", (result == RS_DONE),
|
|
261
|
-
#else
|
|
262
|
-
return Py_BuildValue("(ils#)", (result == RS_DONE),
|
|
263
|
-
#endif
|
|
264
244
|
(long)inbuf_length - (long)buf.avail_in,
|
|
265
245
|
outbuf, RS_JOB_BLOCKSIZE - (long)buf.avail_out);
|
|
266
246
|
}
|
|
@@ -374,11 +354,7 @@ _librsync_patchmaker_cycle(_librsync_PatchMakerObject *self, PyObject *args)
|
|
|
374
354
|
rs_buffers_t buf;
|
|
375
355
|
rs_result result;
|
|
376
356
|
|
|
377
|
-
#if PY_MAJOR_VERSION >= 3
|
|
378
357
|
if (!PyArg_ParseTuple(args, "y#:cycle", &inbuf, &inbuf_length))
|
|
379
|
-
#else
|
|
380
|
-
if (!PyArg_ParseTuple(args, "s#:cycle", &inbuf, &inbuf_length))
|
|
381
|
-
#endif
|
|
382
358
|
return NULL;
|
|
383
359
|
|
|
384
360
|
buf.next_in = inbuf;
|
|
@@ -393,11 +369,7 @@ _librsync_patchmaker_cycle(_librsync_PatchMakerObject *self, PyObject *args)
|
|
|
393
369
|
return NULL;
|
|
394
370
|
}
|
|
395
371
|
|
|
396
|
-
#if PY_MAJOR_VERSION >= 3
|
|
397
372
|
return Py_BuildValue("(ily#)", (result == RS_DONE),
|
|
398
|
-
#else
|
|
399
|
-
return Py_BuildValue("(ils#)", (result == RS_DONE),
|
|
400
|
-
#endif
|
|
401
373
|
(long)inbuf_length - (long)buf.avail_in,
|
|
402
374
|
outbuf, RS_JOB_BLOCKSIZE - (long)buf.avail_out);
|
|
403
375
|
}
|
|
@@ -441,16 +413,6 @@ static PyTypeObject _librsync_PatchMakerType = {
|
|
|
441
413
|
|
|
442
414
|
/* --------------- _librsync module definition */
|
|
443
415
|
|
|
444
|
-
#if PY_MAJOR_VERSION >= 3
|
|
445
|
-
#define MOD_DEF(ob, name, doc, methods) \
|
|
446
|
-
static struct PyModuleDef moduledef = { \
|
|
447
|
-
PyModuleDef_HEAD_INIT, name, doc, -1, methods, }; \
|
|
448
|
-
ob = PyModule_Create(&moduledef);
|
|
449
|
-
#else
|
|
450
|
-
#define MOD_DEF(ob, name, doc, methods) \
|
|
451
|
-
ob = Py_InitModule3(name, methods, doc);
|
|
452
|
-
#endif
|
|
453
|
-
|
|
454
416
|
static PyMethodDef _librsyncMethods[] = {
|
|
455
417
|
{"new_sigmaker", _librsync_new_sigmaker, METH_VARARGS,
|
|
456
418
|
"Return a sigmaker object, for finding the signature of an object"},
|
|
@@ -461,6 +423,9 @@ static PyMethodDef _librsyncMethods[] = {
|
|
|
461
423
|
{NULL, NULL, 0, NULL}
|
|
462
424
|
};
|
|
463
425
|
|
|
426
|
+
static struct PyModuleDef moduledef = {
|
|
427
|
+
PyModuleDef_HEAD_INIT, "_librsync", "", -1, _librsyncMethods, };
|
|
428
|
+
|
|
464
429
|
static PyObject *
|
|
465
430
|
moduleinit(void)
|
|
466
431
|
{
|
|
@@ -474,7 +439,7 @@ moduleinit(void)
|
|
|
474
439
|
Py_TYPE(&_librsync_DeltaMakerType) = &PyType_Type;
|
|
475
440
|
#endif
|
|
476
441
|
|
|
477
|
-
|
|
442
|
+
m = PyModule_Create(&moduledef);
|
|
478
443
|
if (m == NULL)
|
|
479
444
|
return NULL;
|
|
480
445
|
|
|
@@ -491,14 +456,7 @@ moduleinit(void)
|
|
|
491
456
|
return m;
|
|
492
457
|
}
|
|
493
458
|
|
|
494
|
-
#if PY_MAJOR_VERSION < 3
|
|
495
|
-
void init_librsync(void)
|
|
496
|
-
{
|
|
497
|
-
moduleinit();
|
|
498
|
-
}
|
|
499
|
-
#else
|
|
500
459
|
PyObject *PyInit__librsync(void)
|
|
501
460
|
{
|
|
502
461
|
return moduleinit();
|
|
503
462
|
}
|
|
504
|
-
#endif
|
|
@@ -39,10 +39,8 @@ class CloudFilesBackend(duplicity.backend.Backend):
|
|
|
39
39
|
from cloudfiles import consts
|
|
40
40
|
from cloudfiles.errors import NoSuchObject
|
|
41
41
|
except ImportError as e:
|
|
42
|
-
raise BackendException(
|
|
43
|
-
|
|
44
|
-
Exception: {str(e)}"""
|
|
45
|
-
)
|
|
42
|
+
raise BackendException(f"""Cloudfiles backend requires the cloudfiles library available from Rackspace.
|
|
43
|
+
Exception: {str(e)}""")
|
|
46
44
|
|
|
47
45
|
self.resp_exc = ResponseError
|
|
48
46
|
conn_kwargs = {}
|
|
@@ -37,10 +37,8 @@ class PyraxBackend(duplicity.backend.Backend):
|
|
|
37
37
|
try:
|
|
38
38
|
import pyrax
|
|
39
39
|
except ImportError as e:
|
|
40
|
-
raise BackendException(
|
|
41
|
-
|
|
42
|
-
Exception: {str(e)}"""
|
|
43
|
-
)
|
|
40
|
+
raise BackendException(f"""Pyrax backend requires the pyrax library available from Rackspace.
|
|
41
|
+
Exception: {str(e)}""")
|
|
44
42
|
|
|
45
43
|
# Inform Pyrax that we're talking to Rackspace
|
|
46
44
|
# per Jesus Monzon (gsusmonzon)
|
|
@@ -73,7 +73,8 @@ class B2Backend(duplicity.backend.Backend):
|
|
|
73
73
|
try: # figure out what version of b2sdk we have
|
|
74
74
|
from b2sdk import __version__ as VERSION # pylint: disable=import-error
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
v_public = VERSION.partition("+")[0] # ignore local version identifier if present
|
|
77
|
+
v_split = v_public.split(".")
|
|
77
78
|
self.v_num = [int(x) for x in v_split]
|
|
78
79
|
except Exception as e:
|
|
79
80
|
self.v_num = [0, 0, 0]
|
|
@@ -120,11 +120,9 @@ class DPBXBackend(duplicity.backend.Backend):
|
|
|
120
120
|
)
|
|
121
121
|
from dropbox.oauth import DropboxOAuth2FlowNoRedirect
|
|
122
122
|
except ImportError as e:
|
|
123
|
-
raise BackendException(
|
|
124
|
-
f"""This backend requires the dropbox package version 6.9.0
|
|
123
|
+
raise BackendException(f"""This backend requires the dropbox package version 6.9.0
|
|
125
124
|
To install use "sudo pip install dropbox==6.9.0"
|
|
126
|
-
Exception: {str(e)}"""
|
|
127
|
-
)
|
|
125
|
+
Exception: {str(e)}""")
|
|
128
126
|
|
|
129
127
|
self.api_account = None
|
|
130
128
|
self.api_client = None
|
|
@@ -38,11 +38,9 @@ class GDriveBackend(duplicity.backend.Backend):
|
|
|
38
38
|
from googleapiclient.discovery import build
|
|
39
39
|
from google.oauth2.service_account import Credentials
|
|
40
40
|
except ImportError as e:
|
|
41
|
-
raise BackendException(
|
|
42
|
-
f"""GDrive backend requires Google API client installation.
|
|
41
|
+
raise BackendException(f"""GDrive backend requires Google API client installation.
|
|
43
42
|
Please read the manpage for setup details.
|
|
44
|
-
Exception: {str(e)}"""
|
|
45
|
-
)
|
|
43
|
+
Exception: {str(e)}""")
|
|
46
44
|
|
|
47
45
|
# Note Google has 2 drive methods, `Shared(previously Team) Drives` and `My Drive`
|
|
48
46
|
# both can be shared but require different addressing
|
|
@@ -38,10 +38,8 @@ class HubicBackend(PyraxBackend):
|
|
|
38
38
|
try:
|
|
39
39
|
import pyrax
|
|
40
40
|
except ImportError as e:
|
|
41
|
-
raise BackendException(
|
|
42
|
-
|
|
43
|
-
Exception: {str(e)}"""
|
|
44
|
-
)
|
|
41
|
+
raise BackendException(f"""Hubic backend requires the pyrax library available from Rackspace.
|
|
42
|
+
Exception: {str(e)}""")
|
|
45
43
|
|
|
46
44
|
# Inform Pyrax that we're talking to Hubic
|
|
47
45
|
pyrax.set_setting("identity_type", "duplicity.backends.pyrax_identity.hubic.HubicIdentity")
|
|
@@ -168,7 +168,7 @@ class ImapBackend(duplicity.backend.Backend):
|
|
|
168
168
|
while allowedTimeout > 0:
|
|
169
169
|
try:
|
|
170
170
|
self.conn.select(config.imap_mailbox)
|
|
171
|
-
|
|
171
|
+
result, flist = self.conn.search(None, "Subject", remote_filename)
|
|
172
172
|
if result != "OK":
|
|
173
173
|
raise Exception(flist[0])
|
|
174
174
|
|
|
@@ -176,7 +176,7 @@ class ImapBackend(duplicity.backend.Backend):
|
|
|
176
176
|
if flist[0] == "":
|
|
177
177
|
raise Exception("no mail with subject %s")
|
|
178
178
|
|
|
179
|
-
|
|
179
|
+
result, flist = self.conn.fetch(flist[0], "(RFC822)")
|
|
180
180
|
|
|
181
181
|
if result != "OK":
|
|
182
182
|
raise Exception(flist[0])
|
|
@@ -211,7 +211,7 @@ class ImapBackend(duplicity.backend.Backend):
|
|
|
211
211
|
|
|
212
212
|
def _list(self):
|
|
213
213
|
ret = []
|
|
214
|
-
|
|
214
|
+
result, flist = self.conn.select(config.imap_mailbox)
|
|
215
215
|
if result != "OK":
|
|
216
216
|
raise BackendException(flist[0])
|
|
217
217
|
|
|
@@ -219,14 +219,14 @@ class ImapBackend(duplicity.backend.Backend):
|
|
|
219
219
|
# address
|
|
220
220
|
|
|
221
221
|
# Search returns an error if you haven't selected an IMAP folder.
|
|
222
|
-
|
|
222
|
+
result, flist = self.conn.search(None, "FROM", self.remote_dir)
|
|
223
223
|
if result != "OK":
|
|
224
224
|
raise Exception(flist[0])
|
|
225
225
|
if flist[0] == b"":
|
|
226
226
|
return ret
|
|
227
227
|
nums = flist[0].strip().split(b" ")
|
|
228
228
|
set = b"%s:%s" % (nums[0], nums[-1]) # pylint: disable=redefined-builtin
|
|
229
|
-
|
|
229
|
+
result, flist = self.conn.fetch(set, "(BODY[HEADER])")
|
|
230
230
|
if result != "OK":
|
|
231
231
|
raise Exception(flist[0])
|
|
232
232
|
|
|
@@ -247,7 +247,7 @@ class ImapBackend(duplicity.backend.Backend):
|
|
|
247
247
|
return ret
|
|
248
248
|
|
|
249
249
|
def imapf(self, fun, *args):
|
|
250
|
-
|
|
250
|
+
ret, flist = fun(*args)
|
|
251
251
|
if ret != "OK":
|
|
252
252
|
raise Exception(flist[0])
|
|
253
253
|
return flist
|
|
@@ -38,10 +38,8 @@ class MediafireBackend(duplicity.backend.Backend):
|
|
|
38
38
|
try:
|
|
39
39
|
import mediafire.client
|
|
40
40
|
except ImportError as e:
|
|
41
|
-
raise BackendException(
|
|
42
|
-
|
|
43
|
-
Exception: {str(e)}"""
|
|
44
|
-
)
|
|
41
|
+
raise BackendException(f"""Mediafire backend requires the mediafire library.
|
|
42
|
+
Exception: {str(e)}""")
|
|
45
43
|
|
|
46
44
|
duplicity.backend.Backend.__init__(self, parsed_url)
|
|
47
45
|
|
|
@@ -34,7 +34,6 @@ from duplicity import log
|
|
|
34
34
|
from duplicity import util
|
|
35
35
|
from duplicity.errors import BackendException
|
|
36
36
|
|
|
37
|
-
|
|
38
37
|
# For documentation on the API, see
|
|
39
38
|
# The previous Live SDK API required the use of opaque folder IDs to navigate paths, but the Microsoft Graph
|
|
40
39
|
# API allows the use of parent/child/grandchild pathnames.
|
|
@@ -39,10 +39,8 @@ class PCABackend(duplicity.backend.Backend):
|
|
|
39
39
|
from swiftclient import Connection
|
|
40
40
|
from swiftclient import ClientException
|
|
41
41
|
except ImportError as e:
|
|
42
|
-
raise BackendException(
|
|
43
|
-
|
|
44
|
-
Exception: {str(e)}"""
|
|
45
|
-
)
|
|
42
|
+
raise BackendException(f"""PCA backend requires the python-swiftclient library.
|
|
43
|
+
Exception: {str(e)}""")
|
|
46
44
|
|
|
47
45
|
self.resp_exc = ClientException
|
|
48
46
|
self.conn_cls = Connection
|
|
@@ -24,10 +24,8 @@ try:
|
|
|
24
24
|
)
|
|
25
25
|
import pyrax.exceptions as exc
|
|
26
26
|
except ImportError as e:
|
|
27
|
-
raise BackendException(
|
|
28
|
-
|
|
29
|
-
Exception: {str(e)}"""
|
|
30
|
-
)
|
|
27
|
+
raise BackendException(f"""Hubic backend requires the pyrax library available from Rackspace.
|
|
28
|
+
Exception: {str(e)}""")
|
|
31
29
|
|
|
32
30
|
OAUTH_ENDPOINT = "https://api.hubic.com/oauth/"
|
|
33
31
|
API_ENDPOINT = "https://api.hubic.com/1.0/"
|
|
@@ -95,8 +95,10 @@ class RcloneBackend(duplicity.backend.Backend):
|
|
|
95
95
|
size = -1
|
|
96
96
|
elif rc == 0:
|
|
97
97
|
size = int(o)
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
except Exception as e:
|
|
99
|
+
log.Debug(f"Failed to query file size for {remote_filename}: {e}")
|
|
100
|
+
return {"size": None}
|
|
101
|
+
return {"size": size}
|
|
100
102
|
|
|
101
103
|
def _delete(self, remote_filename):
|
|
102
104
|
remote_filename = os.fsdecode(remote_filename)
|
|
@@ -60,7 +60,7 @@ class RsyncBackend(duplicity.backend.Backend):
|
|
|
60
60
|
del os.environ["RSYNC_RSH"]
|
|
61
61
|
if self.over_rsyncd():
|
|
62
62
|
# its a module path
|
|
63
|
-
|
|
63
|
+
path, port = self.get_rsync_path()
|
|
64
64
|
self.url_string = f"{host}::{path.lstrip('/:')}"
|
|
65
65
|
if port:
|
|
66
66
|
port = f" --port={port}"
|
|
@@ -208,10 +208,11 @@ class S3Boto3Backend(duplicity.backend.Backend):
|
|
|
208
208
|
)
|
|
209
209
|
except S3UploadFailedError as e:
|
|
210
210
|
if boto3.__version__ > "1.36.0" or botocore.__version__ > "1.36.0":
|
|
211
|
-
|
|
211
|
+
raise FatalBackendException(
|
|
212
212
|
f"Failed to upload file {remote_filename}, got S3UploadFailedError\n"
|
|
213
213
|
f"See https://gitlab.com/duplicity/duplicity/-/issues/870 for details.\n"
|
|
214
|
-
f"Quick fix is: [sudo] pip3 install boto3<1.36.0 botocore<1.36.0"
|
|
214
|
+
f"Quick fix is: [sudo] pip3 install boto3<1.36.0 botocore<1.36.0\n"
|
|
215
|
+
f"API-Error: {e}"
|
|
215
216
|
)
|
|
216
217
|
else:
|
|
217
218
|
raise e
|
|
@@ -40,10 +40,8 @@ class SlateBackend(duplicity.backend.Backend):
|
|
|
40
40
|
duplicity.backend.Backend.__init__(self, parsed_url)
|
|
41
41
|
log.Debug("loading slate backend...")
|
|
42
42
|
if "SLATE_API_KEY" not in os.environ.keys():
|
|
43
|
-
raise BackendException(
|
|
44
|
-
|
|
45
|
-
as the value of your slate API key"""
|
|
46
|
-
)
|
|
43
|
+
raise BackendException("""You must set an environment variable SLATE_API_KEY
|
|
44
|
+
as the value of your slate API key""")
|
|
47
45
|
else:
|
|
48
46
|
self.key = os.environ["SLATE_API_KEY"]
|
|
49
47
|
|
|
@@ -104,13 +104,11 @@ class SSHParamikoBackend(duplicity.backend.Backend):
|
|
|
104
104
|
if hasattr(key, "fingerprint"):
|
|
105
105
|
fingerprints += f"\n {key.fingerprint}"
|
|
106
106
|
keyname = key.get_name().upper()
|
|
107
|
-
question = dedent(
|
|
108
|
-
"""
|
|
107
|
+
question = dedent("""
|
|
109
108
|
The authenticity of host '{hostname}' can't be established.
|
|
110
109
|
{keyname} fingerprint is
|
|
111
110
|
{fingerprints}.
|
|
112
|
-
Are you sure you want to continue connecting (yes/no)? """
|
|
113
|
-
).format(**locals())
|
|
111
|
+
Are you sure you want to continue connecting (yes/no)? """).format(**locals())
|
|
114
112
|
while True:
|
|
115
113
|
sys.stdout.write(question)
|
|
116
114
|
choice = input().lower()
|
|
@@ -49,14 +49,12 @@ class SSHPExpectBackend(duplicity.backend.Backend):
|
|
|
49
49
|
raise
|
|
50
50
|
|
|
51
51
|
if pexpect.__version__ < "4.5.0":
|
|
52
|
-
log.FatalError(
|
|
53
|
-
f"""
|
|
52
|
+
log.FatalError(f"""
|
|
54
53
|
The version of pexpect, '{pexexpect.__version__}`, is too old. We need version 4.5.0 or above to run.
|
|
55
54
|
See https://gitlab.com/duplicity/duplicity/-/issues/125 for the gory details.
|
|
56
55
|
|
|
57
56
|
Use "python3 -m pip install pexpect" to install the latest version.
|
|
58
|
-
"""
|
|
59
|
-
)
|
|
57
|
+
""")
|
|
60
58
|
|
|
61
59
|
self.retry_delay = 10
|
|
62
60
|
|
|
@@ -43,10 +43,8 @@ class SwiftBackend(duplicity.backend.Backend):
|
|
|
43
43
|
from swiftclient import Connection
|
|
44
44
|
from swiftclient import ClientException
|
|
45
45
|
except ImportError as e:
|
|
46
|
-
raise BackendException(
|
|
47
|
-
|
|
48
|
-
Exception: {str(e)}"""
|
|
49
|
-
)
|
|
46
|
+
raise BackendException(f"""Swift backend requires the python-swiftclient library.
|
|
47
|
+
Exception: {str(e)}""")
|
|
50
48
|
|
|
51
49
|
self.resp_exc = ClientException
|
|
52
50
|
conn_kwargs = {}
|
|
@@ -191,20 +191,18 @@ class WebDAVBackend(duplicity.backend.Backend):
|
|
|
191
191
|
else:
|
|
192
192
|
raise FatalBackendException(_("WebDAV Unknown URI scheme: %s") % self.parsed_url.scheme)
|
|
193
193
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
response = self.request("OPTIONS", self.directory, None)
|
|
201
|
-
response.close()
|
|
194
|
+
# Workaround cpython http.client issue
|
|
195
|
+
# https://github.com/python/cpython/issues/70107
|
|
196
|
+
# PUT may not return a proper error when ran as first request but throw SSL-EOF-Error or hang
|
|
197
|
+
# as a workaround we run an OPTIONS request to make sure that PUT is never the first request
|
|
198
|
+
response = self.request("OPTIONS", self.directory, None, connect=False)
|
|
199
|
+
response.close()
|
|
202
200
|
|
|
203
201
|
def _close(self):
|
|
204
202
|
if self.conn:
|
|
205
203
|
self.conn.close()
|
|
206
204
|
|
|
207
|
-
def request(self, method, path, data=None, redirected=0):
|
|
205
|
+
def request(self, method, path, data=None, redirected=0, connect=True):
|
|
208
206
|
"""
|
|
209
207
|
Wraps the connection.request method to retry once if authentication is
|
|
210
208
|
required
|
|
@@ -221,7 +219,8 @@ class WebDAVBackend(duplicity.backend.Backend):
|
|
|
221
219
|
return headers_copy
|
|
222
220
|
|
|
223
221
|
self._close() # or we get previous request's data or exception
|
|
224
|
-
|
|
222
|
+
if connect:
|
|
223
|
+
self.connect()
|
|
225
224
|
|
|
226
225
|
quoted_path = urllib.parse.quote(path, "/:~")
|
|
227
226
|
|
|
@@ -275,21 +274,12 @@ class WebDAVBackend(duplicity.backend.Backend):
|
|
|
275
274
|
try:
|
|
276
275
|
return self.get_kerberos_authorization()
|
|
277
276
|
except ImportError:
|
|
278
|
-
log.Warn(
|
|
279
|
-
|
|
280
|
-
"python-kerberos needed to use kerberos \
|
|
281
|
-
authorization, falling back to basic auth."
|
|
282
|
-
)
|
|
283
|
-
)
|
|
277
|
+
log.Warn(_("python-kerberos needed to use kerberos \
|
|
278
|
+
authorization, falling back to basic auth."))
|
|
284
279
|
return self.get_basic_authorization()
|
|
285
280
|
except Exception as e:
|
|
286
|
-
log.Warn(
|
|
287
|
-
|
|
288
|
-
"Kerberos authorization failed: %s.\
|
|
289
|
-
Falling back to basic auth."
|
|
290
|
-
)
|
|
291
|
-
% e
|
|
292
|
-
)
|
|
281
|
+
log.Warn(_("Kerberos authorization failed: %s.\
|
|
282
|
+
Falling back to basic auth.") % e)
|
|
293
283
|
return self.get_basic_authorization()
|
|
294
284
|
elif token.lower() == "basic":
|
|
295
285
|
return self.get_basic_authorization()
|
|
@@ -354,6 +354,12 @@ OptionKwargs = dict(
|
|
|
354
354
|
help="Perform full backup if last full is older than 'time'",
|
|
355
355
|
default=dflt(config.full_if_older_than),
|
|
356
356
|
),
|
|
357
|
+
full_if_n_inc=dict(
|
|
358
|
+
metavar=_("number"),
|
|
359
|
+
type=int,
|
|
360
|
+
help="Perform full backup if latest chain has N or more incremental backups",
|
|
361
|
+
default=dflt(config.full_if_n_inc),
|
|
362
|
+
),
|
|
357
363
|
gpg_binary=dict(
|
|
358
364
|
metavar=_("path"),
|
|
359
365
|
type=check_file,
|
|
@@ -996,9 +1002,7 @@ trans = {
|
|
|
996
1002
|
"remote": _("remote"),
|
|
997
1003
|
}
|
|
998
1004
|
|
|
999
|
-
help_url_formats = (
|
|
1000
|
-
_("Backends and their URL formats:")
|
|
1001
|
-
+ f"""
|
|
1005
|
+
help_url_formats = _("Backends and their URL formats:") + f"""
|
|
1002
1006
|
azure://{trans['container_name']}
|
|
1003
1007
|
b2://{trans['account_id']}[:{trans['application_key']}]@{trans['bucket_name']}/[{trans['some_dir']}/]
|
|
1004
1008
|
boto3+s3://{trans['bucket_name']}[/{trans['prefix']}]
|
|
@@ -1033,4 +1037,3 @@ help_url_formats = (
|
|
|
1033
1037
|
webdav://{trans['user']}[:{trans['password']}]@{trans['other_host']}/{trans['some_dir']}
|
|
1034
1038
|
webdavs://{trans['user']}[:{trans['password']}]@{trans['other_host']}/{trans['some_dir']}
|
|
1035
1039
|
"""
|
|
1036
|
-
)
|
|
@@ -173,37 +173,23 @@ def parse_cmdline_options(arglist):
|
|
|
173
173
|
for opt in remainder:
|
|
174
174
|
if opt.startswith("-"):
|
|
175
175
|
if opt in changed_options:
|
|
176
|
-
command_line_error(
|
|
177
|
-
dedent(
|
|
178
|
-
f"""\
|
|
176
|
+
command_line_error(dedent(f"""\
|
|
179
177
|
Option '{opt} was changed in 2.0.0.
|
|
180
178
|
--file-to-restore to --path-to-restore
|
|
181
179
|
--do-not-restore-ownership to --no-restore-ownership
|
|
182
|
-
"""
|
|
183
|
-
)
|
|
184
|
-
)
|
|
180
|
+
"""))
|
|
185
181
|
elif opt in removed_options:
|
|
186
182
|
removed_commands_string = "\n".join(f" {c}" for c in sorted(removed_options))
|
|
187
|
-
command_line_error(
|
|
188
|
-
dedent(
|
|
189
|
-
f"""\
|
|
183
|
+
command_line_error(dedent(f"""\
|
|
190
184
|
Option '{opt}' was removed in 2.0.0.
|
|
191
185
|
The following options were deprecated and removed in 2.0.0
|
|
192
|
-
"""
|
|
193
|
-
)
|
|
194
|
-
+ f"{removed_commands_string}"
|
|
195
|
-
)
|
|
186
|
+
""") + f"{removed_commands_string}")
|
|
196
187
|
elif opt in removed_backup_options and args.action in ("backup", "full", "incremental"):
|
|
197
188
|
removed_commands_string = "\n".join(f" {c}" for c in sorted(removed_backup_options))
|
|
198
|
-
command_line_error(
|
|
199
|
-
dedent(
|
|
200
|
-
f"""\
|
|
189
|
+
command_line_error(dedent(f"""\
|
|
201
190
|
Option '{opt}' was removed for backup actions in 2.0.0.
|
|
202
191
|
The following options were deprecated and removed in 2.0.0
|
|
203
|
-
"""
|
|
204
|
-
)
|
|
205
|
-
+ f"{removed_commands_string}"
|
|
206
|
-
)
|
|
192
|
+
""") + f"{removed_commands_string}")
|
|
207
193
|
|
|
208
194
|
# check for proper action
|
|
209
195
|
if remainder and remainder[0] in all_commands:
|
|
@@ -280,7 +266,7 @@ def process_command_line(cmdline_list):
|
|
|
280
266
|
and len(config.gpg_profile.hidden_recipients) == 0
|
|
281
267
|
):
|
|
282
268
|
log.Warn(
|
|
283
|
-
"Option --
|
|
269
|
+
"Option --use-agent is unsafe with symmetric encryption.\n"
|
|
284
270
|
"Refer to https://gitlab.com/duplicity/duplicity/-/issues/799 for more information."
|
|
285
271
|
)
|
|
286
272
|
|