duplicity 3.2.1.dev2__tar.gz → 3.2.1.dev3__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.2.1.dev2 → duplicity-3.2.1.dev3}/CHANGELOG.md +45 -16
- {duplicity-3.2.1.dev2/duplicity.egg-info → duplicity-3.2.1.dev3}/PKG-INFO +1 -3
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/README-INSTALL.md +1 -2
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/README-TESTING.md +2 -1
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/__init__.py +2 -2
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backend_pool.py +2 -1
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/_cf_cloudfiles.py +6 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/_cf_pyrax.py +6 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/b2backend.py +36 -11
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/hubicbackend.py +5 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/imapbackend.py +1 -1
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/par2backend.py +21 -4
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/rsyncbackend.py +25 -1
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/ssh_pexpect_backend.py +2 -2
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/cli_data.py +215 -36
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/cli_main.py +93 -14
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/cli_util.py +116 -1
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/config.py +2 -1
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/dup_collections.py +10 -8
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/dup_main.py +68 -61
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/file_naming.py +15 -1
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/gpg.py +217 -246
- duplicity-3.2.1.dev3/duplicity/gpginterface.py +702 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/selection.py +43 -119
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/tempdir.py +6 -5
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3/duplicity.egg-info}/PKG-INFO +1 -3
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity.egg-info/SOURCES.txt +1 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity.egg-info/requires.txt +0 -2
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/man/duplicity.1 +25 -1
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/pyproject.toml +17 -9
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/requirements.txt +0 -2
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/setup.py +2 -1
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/AUTHORS.md +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/COPYING +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/README-ARCH.md +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/README-LOG.md +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/README-RELEASE.md +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/README-REPO.md +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/README-SNAP.md +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/README.md +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/__main__.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/_librsync_ctypes.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/_librsyncmodule.c +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/argparse311.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/__init__.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/_testbackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/adbackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/azurebackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/boxbackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/cfbackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/dpbxbackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/gdocsbackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/gdrivebackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/giobackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/hsibackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/idrivedbackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/jottacloudbackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/lftpbackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/localbackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/mediafirebackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/megabackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/megav2backend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/megav3backend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/multibackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/ncftpbackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/onedrivebackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/pcabackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/pydrivebackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/pyrax_identity/__init__.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/pyrax_identity/hubic.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/rclonebackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/s3_boto3_backend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/slatebackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/ssh_paramiko_backend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/swiftbackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/sxbackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/tahoebackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/webdavbackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/backends/xorrisobackend.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/cached_ops.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/diffdir.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/dup_tarfile.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/dup_temp.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/dup_time.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/errors.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/globmatch.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/lazy.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/librsync.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/log.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/manifest.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/patchdir.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/path.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/progress.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/robust.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/statistics.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity/util.py +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity.egg-info/dependency_links.txt +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity.egg-info/entry_points.txt +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/duplicity.egg-info/top_level.txt +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/af_ZA/af_ZA.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/af_ZA.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ar_SA/ar_SA.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ar_SA.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ca_ES/ca_ES.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ca_ES.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/cs_CZ/cs_CZ.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/cs_CZ.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/da_DK/da_DK.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/da_DK.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/de_AT/de_AT.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/de_AT.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/de_DE/de_DE.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/de_DE.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/duplicity.pot +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/el_GR/el_GR.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/el_GR.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/en_AU/en_AU.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/en_AU.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/en_GB/en_GB.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/en_GB.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/en_PR/en_PR.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/en_PR.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/en_US/en_US.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/en_US.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/es_EM/es_EM.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/es_EM.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/es_ES/es_ES.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/es_ES.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/es_MX/es_MX.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/es_MX.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/es_PR/es_PR.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/es_PR.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/es_US/es_US.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/es_US.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/fi_FI/fi_FI.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/fi_FI.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/fr_FR/fr_FR.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/fr_FR.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/he_IL/he_IL.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/he_IL.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/hu_HU/hu_HU.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/hu_HU.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/it_IT/it_IT.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/it_IT.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ja_JP/ja_JP.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ja_JP.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ka_GE/ka_GE.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ka_GE.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ko_KR/ko_KR.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ko_KR.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/nl_BE/nl_BE.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/nl_BE.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/nl_NL/nl_NL.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/nl_NL.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/nl_SR/nl_SR.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/nl_SR.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/no_NO/no_NO.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/no_NO.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/pl_PL/pl_PL.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/pl_PL.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/pt_BR/pt_BR.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/pt_BR.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/pt_PT/pt_PT.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/pt_PT.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ro_RO/ro_RO.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ro_RO.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ru_BY/ru_BY.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ru_BY.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ru_MD/ru_MD.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ru_MD.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ru_RU/ru_RU.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ru_RU.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ru_UA/ru_UA.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/ru_UA.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/sr_SP/sr_SP.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/sr_SP.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/sv_SE/sv_SE.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/sv_SE.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/tr_TR/tr_TR.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/tr_TR.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/uk_UA/uk_UA.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/uk_UA.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/vi_VN/vi_VN.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/vi_VN.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/zh_CN/zh_CN.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/zh_CN.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/zh_HK/zh_HK.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/zh_HK.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/zh_MO/zh_MO.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/zh_MO.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/zh_SG/zh_SG.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/zh_SG.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/zh_TW/zh_TW.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/po/zh_TW.po +0 -0
- {duplicity-3.2.1.dev2 → duplicity-3.2.1.dev3}/setup.cfg +0 -0
|
@@ -1,15 +1,35 @@
|
|
|
1
1
|
|
|
2
|
-
(Unreleased) / 2026-
|
|
2
|
+
(Unreleased) / 2026-09-23
|
|
3
3
|
=========================
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
|
+
rel.3.2.1.dev3 / 2026-09-23
|
|
8
|
+
===========================
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
rel.3.3.1.dev3 / 2026-09-22
|
|
12
|
+
===========================
|
|
13
|
+
|
|
14
|
+
* [`d7da150b`](https://gitlab.com/duplicity/duplicity/-/commit/d7da150b):new: Create subpath in rsyncd.
|
|
15
|
+
* [`e181a9e9`](https://gitlab.com/duplicity/duplicity/-/commit/e181a9e9):chg: Improve error handling and signature file filtering logic; add unit tests for B2 and PAR2 backends
|
|
16
|
+
* [`58a54680`](https://gitlab.com/duplicity/duplicity/-/commit/58a54680):chg: Add regex cache invalidation for file prefix changes; update tests
|
|
17
|
+
* [`fcd6920a`](https://gitlab.com/duplicity/duplicity/-/commit/fcd6920a):chg: Add deprecation warnings for CloudFiles, Pyrax, and Hubic backends
|
|
18
|
+
* [`1842e4de`](https://gitlab.com/duplicity/duplicity/-/commit/1842e4de):chg: Remove `python3-gnupg` and restore `gpginterface` module and unit tests.
|
|
19
|
+
* [`a201453e`](https://gitlab.com/duplicity/duplicity/-/commit/a201453e):chg: Plan to remove obsolete Pyrax, CloudFiles, and Hubic backends; standardize on python-swiftclient
|
|
20
|
+
* [`abdf9a0e`](https://gitlab.com/duplicity/duplicity/-/commit/abdf9a0e):chg: Remove unused gnupg import from gpg.py for cleanup.
|
|
21
|
+
* [`bd649791`](https://gitlab.com/duplicity/duplicity/-/commit/bd649791):chg: Split wildcard and multiline imports into individual lines for improved clarity and compliance with coding standards
|
|
22
|
+
* [`993cc651`](https://gitlab.com/duplicity/duplicity/-/commit/993cc651):chg: Decouple selection parsing from core engine and refactor tests
|
|
23
|
+
* [`1af57ea4`](https://gitlab.com/duplicity/duplicity/-/commit/1af57ea4):chg: Add support and tests for new CLI options
|
|
24
|
+
* [`df643666`](https://gitlab.com/duplicity/duplicity/-/commit/df643666):chg: Update Python3 version and dependencies in `debian/control`
|
|
25
|
+
* [`7514a7e2`](https://gitlab.com/duplicity/duplicity/-/commit/7514a7e2):fix: Correct string formatting in help output and improve test stability
|
|
26
|
+
* [`c179caf1`](https://gitlab.com/duplicity/duplicity/-/commit/c179caf1):fix: Fix GPG sleep processes on verify, modernize tests, and update guidelines
|
|
27
|
+
* [`90f9137e`](https://gitlab.com/duplicity/duplicity/-/commit/90f9137e):fix: Fix subpath creation for rsync #943
|
|
28
|
+
* [`ed58fae5`](https://gitlab.com/duplicity/duplicity/-/commit/ed58fae5):fix: Restore Python versions, dependencies, and revert migration to 'python-gnupg'.
|
|
29
|
+
|
|
7
30
|
rel.3.2.1.dev2 / 2026-08-20
|
|
8
31
|
===========================
|
|
9
32
|
|
|
10
|
-
* [`77c5107e`](https://gitlab.com/duplicity/duplicity/-/commit/77c5107e):new: Add get_version() to librsync to retrieve underlying library version
|
|
11
|
-
* [`b839f2c8`](https://gitlab.com/duplicity/duplicity/-/commit/b839f2c8):new: Add pure Python librsync implementation using ctypes as fallback
|
|
12
|
-
* [`ba7957c3`](https://gitlab.com/duplicity/duplicity/-/commit/ba7957c3):new: Add coverage configuration and Makefile targets for testing.
|
|
13
33
|
* [`855c6f1c`](https://gitlab.com/duplicity/duplicity/-/commit/855c6f1c):chg: Remove outdated comment for `python3-gnupg` in `debian/control`
|
|
14
34
|
* [`22fae925`](https://gitlab.com/duplicity/duplicity/-/commit/22fae925):chg: Sync README files in `setup.py` and clean up verbosity flags
|
|
15
35
|
* [`978355b4`](https://gitlab.com/duplicity/duplicity/-/commit/978355b4):chg: Enable verbose mode in debian/rules
|
|
@@ -17,11 +37,23 @@ rel.3.2.1.dev2 / 2026-08-20
|
|
|
17
37
|
* [`ba71d094`](https://gitlab.com/duplicity/duplicity/-/commit/ba71d094):chg: Update setuptools to >=61.0.0 in dev dependencies and `debian/rules`
|
|
18
38
|
* [`2b55864a`](https://gitlab.com/duplicity/duplicity/-/commit/2b55864a):chg: Simplify `gnupg` import logic in `gpg.py`
|
|
19
39
|
* [`80abbd02`](https://gitlab.com/duplicity/duplicity/-/commit/80abbd02):chg: Adjust dependencies in `requirements.txt` and `debian/control`
|
|
40
|
+
|
|
41
|
+
rel.3.2.1.dev1 / 2026-08-15
|
|
42
|
+
===========================
|
|
43
|
+
|
|
20
44
|
* [`df52d45b`](https://gitlab.com/duplicity/duplicity/-/commit/df52d45b):chg: Add `python3-gnupg` as a build dependency in `debian/control`
|
|
21
45
|
* [`057c7d0a`](https://gitlab.com/duplicity/duplicity/-/commit/057c7d0a):chg: Update doc cleanup pattern in `debian/rules`
|
|
22
46
|
* [`4eaee861`](https://gitlab.com/duplicity/duplicity/-/commit/4eaee861):chg: Update doc cleanup to remove `duplicity-*` files in `debian/rules`
|
|
23
47
|
* [`7cd8ddb6`](https://gitlab.com/duplicity/duplicity/-/commit/7cd8ddb6):chg: Add `get_data_files` for dynamic data file handling in `setup.py`
|
|
24
48
|
* [`e9bf8843`](https://gitlab.com/duplicity/duplicity/-/commit/e9bf8843):chg: Simplify doc handling by removing outdated duplicity docs
|
|
49
|
+
* [`22da1a0d`](https://gitlab.com/duplicity/duplicity/-/commit/22da1a0d):fix: Resolve PEP8 style issues and whitespace in backend and main modules
|
|
50
|
+
|
|
51
|
+
rel.3.2.1.dev0 / 2026-08-11
|
|
52
|
+
===========================
|
|
53
|
+
|
|
54
|
+
* [`77c5107e`](https://gitlab.com/duplicity/duplicity/-/commit/77c5107e):new: Add get_version() to librsync to retrieve underlying library version
|
|
55
|
+
* [`b839f2c8`](https://gitlab.com/duplicity/duplicity/-/commit/b839f2c8):new: Add pure Python librsync implementation using ctypes as fallback
|
|
56
|
+
* [`ba7957c3`](https://gitlab.com/duplicity/duplicity/-/commit/ba7957c3):new: Add coverage configuration and Makefile targets for testing.
|
|
25
57
|
* [`4bc93712`](https://gitlab.com/duplicity/duplicity/-/commit/4bc93712):chg: Update dependencies, streamline configs, and refine CI
|
|
26
58
|
* [`ca78d6c5`](https://gitlab.com/duplicity/duplicity/-/commit/ca78d6c5):chg: Update release-prep script to use `check_tags`
|
|
27
59
|
* [`60ae51f3`](https://gitlab.com/duplicity/duplicity/-/commit/60ae51f3):chg: Update release-prep script to fix tag removal and file refs
|
|
@@ -34,7 +66,6 @@ rel.3.2.1.dev2 / 2026-08-20
|
|
|
34
66
|
* [`1dee9e31`](https://gitlab.com/duplicity/duplicity/-/commit/1dee9e31):chg: b2backend prefer b2sdk.v3
|
|
35
67
|
* [`4f4e052e`](https://gitlab.com/duplicity/duplicity/-/commit/4f4e052e):chg: Cleanup some minor issues
|
|
36
68
|
* [`1e0a97dc`](https://gitlab.com/duplicity/duplicity/-/commit/1e0a97dc):chg: Format with Black/PEP8 and ensure file flush before rename
|
|
37
|
-
* [`22da1a0d`](https://gitlab.com/duplicity/duplicity/-/commit/22da1a0d):fix: Resolve PEP8 style issues and whitespace in backend and main modules
|
|
38
69
|
* [`06858c9a`](https://gitlab.com/duplicity/duplicity/-/commit/06858c9a):fix: Replace `os.system` calls with safer Python alternatives.
|
|
39
70
|
* [`da745307`](https://gitlab.com/duplicity/duplicity/-/commit/da745307):fix: Add --ignore-installed flag for pip in Dockerfiles
|
|
40
71
|
* [`883cca1e`](https://gitlab.com/duplicity/duplicity/-/commit/883cca1e):fix: restore issue: AssertionError: (b'keys', [...]) not empty
|
|
@@ -50,6 +81,11 @@ rel.3.2.1.dev2 / 2026-08-20
|
|
|
50
81
|
* [`9819e4d4`](https://gitlab.com/duplicity/duplicity/-/commit/9819e4d4):fix: Add get_last_continuous_volume for reliable backup resumption
|
|
51
82
|
* [`5d737d07`](https://gitlab.com/duplicity/duplicity/-/commit/5d737d07):fix: Postpone metadata promotion to prevent orphaned cache files
|
|
52
83
|
|
|
84
|
+
rel.3.2.0.2 / 2026-08-22
|
|
85
|
+
========================
|
|
86
|
+
|
|
87
|
+
* [`f7ccc81b`](https://gitlab.com/duplicity/duplicity/-/commit/f7ccc81b):chg: Update Python3 version and dependencies in `debian/control`
|
|
88
|
+
|
|
53
89
|
rel.3.2.0.1 / 2026-08-15
|
|
54
90
|
========================
|
|
55
91
|
|
|
@@ -61,17 +97,6 @@ rel.3.2.0.1 / 2026-08-15
|
|
|
61
97
|
* [`f0fb534c`](https://gitlab.com/duplicity/duplicity/-/commit/f0fb534c):chg: Update dependencies, streamline configs, and refine CI
|
|
62
98
|
* [`6d719e1c`](https://gitlab.com/duplicity/duplicity/-/commit/6d719e1c):fix: Resolve PEP8 style issues and whitespace in backend and main modules
|
|
63
99
|
|
|
64
|
-
rel.3.2.1.dev1 / 2026-08-15
|
|
65
|
-
===========================
|
|
66
|
-
|
|
67
|
-
* [`29b7ca68`](https://gitlab.com/duplicity/duplicity/-/commit/29b7ca68):chg: Add `python3-gnupg` as a build dependency in `debian/control`
|
|
68
|
-
* [`d5ab54d3`](https://gitlab.com/duplicity/duplicity/-/commit/d5ab54d3):chg: Update doc cleanup pattern in `debian/rules`
|
|
69
|
-
* [`6fbffc54`](https://gitlab.com/duplicity/duplicity/-/commit/6fbffc54):chg: Update doc cleanup to remove `duplicity-*` files in `debian/rules`
|
|
70
|
-
* [`bf4b9c5d`](https://gitlab.com/duplicity/duplicity/-/commit/bf4b9c5d):chg: Add `get_data_files` for dynamic data file handling in `setup.py`
|
|
71
|
-
* [`c88e9239`](https://gitlab.com/duplicity/duplicity/-/commit/c88e9239):chg: Simplify doc handling by removing outdated duplicity docs
|
|
72
|
-
* [`e05cf2f2`](https://gitlab.com/duplicity/duplicity/-/commit/e05cf2f2):chg: Update dependencies, streamline configs, and refine CI
|
|
73
|
-
* [`3bced29a`](https://gitlab.com/duplicity/duplicity/-/commit/3bced29a):fix: Resolve PEP8 style issues and whitespace in backend and main modules
|
|
74
|
-
|
|
75
100
|
rel.3.2.0 / 2026-08-10
|
|
76
101
|
======================
|
|
77
102
|
|
|
@@ -105,6 +130,10 @@ rel.3.2.0 / 2026-08-10
|
|
|
105
130
|
* [`c823ed36`](https://gitlab.com/duplicity/duplicity/-/commit/c823ed36):fix: Could not release lockfile
|
|
106
131
|
* [`3d9eab94`](https://gitlab.com/duplicity/duplicity/-/commit/3d9eab94):fix: Comprehensive fix for backup, restart, and cleanup logic.
|
|
107
132
|
|
|
133
|
+
rel.3.1.1.dev0 / 2026-06-16
|
|
134
|
+
===========================
|
|
135
|
+
|
|
136
|
+
|
|
108
137
|
rel.3.1.0 / 2026-06-16
|
|
109
138
|
======================
|
|
110
139
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: duplicity
|
|
3
|
-
Version: 3.2.1.
|
|
3
|
+
Version: 3.2.1.dev3
|
|
4
4
|
Summary: Encrypted backup using rsync algorithm
|
|
5
5
|
Author-email: Kenneth Loafman <kenneth@loafman.com>
|
|
6
6
|
Maintainer: Edgar Soldin, Thomas Laubrock
|
|
@@ -27,11 +27,9 @@ Requires-Python: <3.15,>=3.10
|
|
|
27
27
|
Description-Content-Type: text/markdown
|
|
28
28
|
License-File: COPYING
|
|
29
29
|
License-File: AUTHORS.md
|
|
30
|
-
Requires-Dist: cryptography==43.0.3
|
|
31
30
|
Requires-Dist: fasteners>=0.19
|
|
32
31
|
Requires-Dist: httplib2
|
|
33
32
|
Requires-Dist: pysocks
|
|
34
|
-
Requires-Dist: python-gnupg
|
|
35
33
|
Requires-Dist: requests
|
|
36
34
|
Requires-Dist: requests-oauthlib
|
|
37
35
|
Requires-Dist: azure-storage-blob
|
|
@@ -22,6 +22,7 @@ sudo apt-get install -y \
|
|
|
22
22
|
par2 \
|
|
23
23
|
python3-dev \
|
|
24
24
|
python3-lxml \
|
|
25
|
+
python3-cryptography \
|
|
25
26
|
python3-pip \
|
|
26
27
|
python3-venv \
|
|
27
28
|
python3 \
|
|
@@ -85,7 +86,6 @@ sudo apt-get install -y \
|
|
|
85
86
|
python3-fasteners \
|
|
86
87
|
python3-httplib2 \
|
|
87
88
|
python3-socks \
|
|
88
|
-
python3-gnupg \
|
|
89
89
|
python3-requests \
|
|
90
90
|
python3-requests-oauthlib \
|
|
91
91
|
python3-azure-storage-blob \
|
|
@@ -130,7 +130,6 @@ sudo apt-get install -y \
|
|
|
130
130
|
python3-fasteners \
|
|
131
131
|
python3-httplib2 \
|
|
132
132
|
python3-socks \
|
|
133
|
-
python3-gnupg \
|
|
134
133
|
python3-requests \
|
|
135
134
|
python3-requests-oauthlib \
|
|
136
135
|
python3-azure-storage-blob \
|
|
@@ -16,7 +16,7 @@ environment. You can run tests on your branch as follows:
|
|
|
16
16
|
|
|
17
17
|
Please test your branch using this method and ensure all tests pass before submitting a merge request.
|
|
18
18
|
|
|
19
|
-
The decorator `@
|
|
19
|
+
The decorator `@pytest.mark.xfail` can be used to commit a known-failing test case without breaking the test
|
|
20
20
|
suite, for example to exhibit the behaviour in a bug report before it has been fixed.
|
|
21
21
|
|
|
22
22
|
## Manual testing and running individual tests
|
|
@@ -34,3 +34,4 @@ See _Dependencies for testing_ to setup your environment.
|
|
|
34
34
|
## Dependencies for testing
|
|
35
35
|
If you should prefer to execute the tests locally without using Docker, see [README-INSTALL.md](README-INSTALL.md) for
|
|
36
36
|
comprehensive `apt` commands to set up your environment (see "APT Only Installation (Development)").
|
|
37
|
+
Duplicity rely on some python packages provided by the system/distribution, to avoid compilations issues if installed via pip.
|
|
@@ -332,7 +332,8 @@ class BackendPool:
|
|
|
332
332
|
|
|
333
333
|
# code to run/test the pool independent, not relevant for duplicity
|
|
334
334
|
if __name__ == "__main__":
|
|
335
|
-
from duplicity import config
|
|
335
|
+
from duplicity import config
|
|
336
|
+
from duplicity import log
|
|
336
337
|
|
|
337
338
|
log.setup()
|
|
338
339
|
log.add_file("/tmp/tmp.log")
|
|
@@ -42,6 +42,12 @@ class CloudFilesBackend(duplicity.backend.Backend):
|
|
|
42
42
|
|
|
43
43
|
:param ParsedUrl parsed_url: The parsed URL.
|
|
44
44
|
"""
|
|
45
|
+
log.Warn(
|
|
46
|
+
"DEPRECATION NOTICE: The cloudfiles backend will be removed with the next major version release. "
|
|
47
|
+
"It is based on the outdated pyrax library that is no longer being developed or supported. "
|
|
48
|
+
"As instant replacement consider using either `swift://` or `rclone://` backend."
|
|
49
|
+
)
|
|
50
|
+
|
|
45
51
|
super().__init__(parsed_url)
|
|
46
52
|
try:
|
|
47
53
|
from cloudfiles import Connection
|
|
@@ -44,6 +44,12 @@ class PyraxBackend(duplicity.backend.Backend):
|
|
|
44
44
|
"""
|
|
45
45
|
duplicity.backend.Backend.__init__(self, parsed_url)
|
|
46
46
|
|
|
47
|
+
log.Warn(
|
|
48
|
+
"DEPRECATION NOTICE: The cloudfiles pyrax backend will be removed with the next major version release. "
|
|
49
|
+
"It is based on the outdated python-cloudfiles library that is no longer being developed or supported. "
|
|
50
|
+
"As instant replacement consider using either `swift://` or `rclone://` backend."
|
|
51
|
+
)
|
|
52
|
+
|
|
47
53
|
try:
|
|
48
54
|
import pyrax
|
|
49
55
|
except ImportError as e:
|
|
@@ -217,10 +217,24 @@ class B2Backend(duplicity.backend.Backend):
|
|
|
217
217
|
log.Log(f"Delete: {full_filename}", log.INFO)
|
|
218
218
|
|
|
219
219
|
if config.b2_hide_files:
|
|
220
|
-
|
|
220
|
+
try:
|
|
221
|
+
self.bucket.hide_file(full_filename)
|
|
222
|
+
except Exception as e:
|
|
223
|
+
code = self._error_code("delete", e)
|
|
224
|
+
if code == log.ErrorCode.backend_not_found:
|
|
225
|
+
log.Debug(f"B2Backend._delete: file {full_filename} not found, already deleted")
|
|
226
|
+
return
|
|
227
|
+
raise
|
|
221
228
|
else:
|
|
222
|
-
|
|
223
|
-
|
|
229
|
+
try:
|
|
230
|
+
file_version_info = self.file_info(quote_plus(full_filename, "/"))
|
|
231
|
+
self.bucket.delete_file_version(file_version_info.id_, file_version_info.file_name)
|
|
232
|
+
except Exception as e:
|
|
233
|
+
code = self._error_code("delete", e)
|
|
234
|
+
if code == log.ErrorCode.backend_not_found:
|
|
235
|
+
log.Debug(f"B2Backend._delete: file {full_filename} not found, already deleted")
|
|
236
|
+
return
|
|
237
|
+
raise
|
|
224
238
|
|
|
225
239
|
def _query(self, filename):
|
|
226
240
|
"""
|
|
@@ -231,14 +245,25 @@ class B2Backend(duplicity.backend.Backend):
|
|
|
231
245
|
:rtype: dict
|
|
232
246
|
"""
|
|
233
247
|
log.Log(f"Query: {self.path}{os.fsdecode(filename)}", log.INFO)
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
248
|
+
try:
|
|
249
|
+
file_version_info = self.file_info(quote_plus(self.path + os.fsdecode(filename), "/"))
|
|
250
|
+
return {
|
|
251
|
+
"size": (
|
|
252
|
+
int(file_version_info.size)
|
|
253
|
+
if file_version_info is not None and file_version_info.size is not None
|
|
254
|
+
else -1
|
|
255
|
+
)
|
|
256
|
+
}
|
|
257
|
+
except Exception as e:
|
|
258
|
+
code = self._error_code("query", e)
|
|
259
|
+
if code == log.ErrorCode.backend_not_found:
|
|
260
|
+
return {"size": -1}
|
|
261
|
+
raise
|
|
262
|
+
|
|
263
|
+
def _error_code(self, operation, e):
|
|
264
|
+
if e.__class__.__name__ in ("FileNotPresent", "NonExistentBucket") or str(e) == "File not found":
|
|
265
|
+
return log.ErrorCode.backend_not_found
|
|
266
|
+
return log.ErrorCode.backend_error
|
|
242
267
|
|
|
243
268
|
def file_info(self, filename):
|
|
244
269
|
if self.v_num >= [1, 9, 0]:
|
|
@@ -46,6 +46,11 @@ class HubicBackend(PyraxBackend):
|
|
|
46
46
|
"""
|
|
47
47
|
duplicity.backend.Backend.__init__(self, parsed_url)
|
|
48
48
|
|
|
49
|
+
log.Warn(
|
|
50
|
+
"DEPRECATION NOTICE: The hubic backend will be removed with the next major version release. "
|
|
51
|
+
"the hubiC service was shut down in 2022. the pyrax access library is outdated."
|
|
52
|
+
)
|
|
53
|
+
|
|
49
54
|
try:
|
|
50
55
|
import pyrax
|
|
51
56
|
except ImportError as e:
|
|
@@ -202,14 +202,24 @@ class Par2Backend(backend.Backend):
|
|
|
202
202
|
"""
|
|
203
203
|
delete given filename and its .par2 files
|
|
204
204
|
"""
|
|
205
|
-
|
|
205
|
+
try:
|
|
206
|
+
self.wrapped_backend._delete(filename)
|
|
207
|
+
except Exception as e:
|
|
208
|
+
code = backend._get_code_from_exception(self.wrapped_backend, "delete", e)
|
|
209
|
+
if code != log.ErrorCode.backend_not_found:
|
|
210
|
+
raise
|
|
206
211
|
|
|
207
212
|
remote_list = self.unfiltered_list()
|
|
208
213
|
|
|
209
214
|
c = re.compile(f"{os.fsdecode(filename)}(?:\\.vol[\\d+]*)?\\.par2")
|
|
210
215
|
for remote_filename in remote_list:
|
|
211
216
|
if c.match(os.fsdecode(remote_filename)):
|
|
212
|
-
|
|
217
|
+
try:
|
|
218
|
+
self.wrapped_backend._delete(os.fsencode(remote_filename))
|
|
219
|
+
except Exception as e:
|
|
220
|
+
code = backend._get_code_from_exception(self.wrapped_backend, "delete", e)
|
|
221
|
+
if code != log.ErrorCode.backend_not_found:
|
|
222
|
+
raise
|
|
213
223
|
|
|
214
224
|
def delete_list(self, filename_list):
|
|
215
225
|
"""
|
|
@@ -228,7 +238,12 @@ class Par2Backend(backend.Backend):
|
|
|
228
238
|
return self.wrapped_backend._delete_list(filename_list)
|
|
229
239
|
else:
|
|
230
240
|
for filename in filename_list:
|
|
231
|
-
|
|
241
|
+
try:
|
|
242
|
+
self.wrapped_backend._delete(filename)
|
|
243
|
+
except Exception as e:
|
|
244
|
+
code = backend._get_code_from_exception(self.wrapped_backend, "delete", e)
|
|
245
|
+
if code != log.ErrorCode.backend_not_found:
|
|
246
|
+
raise
|
|
232
247
|
|
|
233
248
|
def list(self):
|
|
234
249
|
"""
|
|
@@ -255,7 +270,9 @@ class Par2Backend(backend.Backend):
|
|
|
255
270
|
self.wrapped_backend._retry_cleanup()
|
|
256
271
|
|
|
257
272
|
def error_code(self, operation, e):
|
|
258
|
-
|
|
273
|
+
if hasattr(self.wrapped_backend, "_error_code"):
|
|
274
|
+
return self.wrapped_backend._error_code(operation, e)
|
|
275
|
+
return log.ErrorCode.backend_error
|
|
259
276
|
|
|
260
277
|
def query(self, filename):
|
|
261
278
|
return self.wrapped_backend._query(filename)
|
|
@@ -29,6 +29,7 @@ import tempfile
|
|
|
29
29
|
|
|
30
30
|
import duplicity.backend
|
|
31
31
|
from duplicity import config
|
|
32
|
+
from duplicity import log
|
|
32
33
|
from duplicity import tempdir
|
|
33
34
|
from duplicity import util
|
|
34
35
|
from duplicity.errors import InvalidBackendURL
|
|
@@ -65,9 +66,14 @@ class RsyncBackend(duplicity.backend.Backend):
|
|
|
65
66
|
if "RSYNC_RSH" in os.environ:
|
|
66
67
|
del os.environ["RSYNC_RSH"]
|
|
67
68
|
if self.over_rsyncd():
|
|
68
|
-
# its
|
|
69
|
+
# Split the daemon URL into its module root and the subpath used
|
|
70
|
+
# by duplicity, because rsyncd cannot create a missing subpath as
|
|
71
|
+
# the direct destination.
|
|
69
72
|
path, port = self.get_rsync_path()
|
|
70
73
|
self.url_string = f"{host}::{path.lstrip('/:')}"
|
|
74
|
+
module, separator, subpath = path.lstrip("/").partition("/")
|
|
75
|
+
self.rsyncd_module_url = f"{host}::{module}/"
|
|
76
|
+
self.rsyncd_subpath = subpath if separator else ""
|
|
71
77
|
if port:
|
|
72
78
|
port = f" --port={port}"
|
|
73
79
|
else:
|
|
@@ -101,6 +107,10 @@ class RsyncBackend(duplicity.backend.Backend):
|
|
|
101
107
|
rsyncOptions = config.rsync_options
|
|
102
108
|
# build cmd
|
|
103
109
|
self.cmd = f"rsync {portOption} {rsyncOptions}"
|
|
110
|
+
if self.over_rsyncd():
|
|
111
|
+
# Track whether the subpath has been created from the module root.
|
|
112
|
+
self.remote_path_created = False
|
|
113
|
+
self.ensure_remote_path()
|
|
104
114
|
|
|
105
115
|
def over_rsyncd(self):
|
|
106
116
|
url = self.parsed_url.url_string
|
|
@@ -116,6 +126,20 @@ class RsyncBackend(duplicity.backend.Backend):
|
|
|
116
126
|
return m.group(2), m.group(1).lstrip(":")
|
|
117
127
|
raise InvalidBackendURL(f"Could not determine rsync path: {self.munge_password(url)}")
|
|
118
128
|
|
|
129
|
+
def ensure_remote_path(self):
|
|
130
|
+
"""Create the rsync daemon subpath before accessing stored files."""
|
|
131
|
+
if not self.over_rsyncd() or self.remote_path_created or not self.rsyncd_subpath:
|
|
132
|
+
return
|
|
133
|
+
with tempfile.TemporaryDirectory() as local_path:
|
|
134
|
+
local_subpath = os.path.join(local_path, self.rsyncd_subpath)
|
|
135
|
+
# Mirror the requested subpath locally so rsync creates each
|
|
136
|
+
# missing directory below the daemon module.
|
|
137
|
+
os.makedirs(local_subpath)
|
|
138
|
+
commandline = f"{self.cmd} --recursive {local_path}/ {self.rsyncd_module_url}"
|
|
139
|
+
self.subprocess_popen(commandline)
|
|
140
|
+
log.Debug(f"Created rsync daemon subpath '{self.rsyncd_subpath}'.")
|
|
141
|
+
self.remote_path_created = True
|
|
142
|
+
|
|
119
143
|
def _put(self, source_path, remote_filename):
|
|
120
144
|
remote_filename = os.fsdecode(remote_filename)
|
|
121
145
|
remote_path = os.path.join(self.url_string, remote_filename)
|
|
@@ -318,9 +318,9 @@ class SSHPExpectBackend(duplicity.backend.Backend):
|
|
|
318
318
|
commands = mkdir_commands + ["ls -1"]
|
|
319
319
|
commandline = f"{self.sftp_command} {config.ssh_options} {self.host_string}"
|
|
320
320
|
|
|
321
|
-
|
|
321
|
+
lines = self.run_sftp_command(commandline, commands).split("\n")[1:]
|
|
322
322
|
|
|
323
|
-
return [x for x in map(str.strip,
|
|
323
|
+
return [os.fsencode(x) for x in map(str.strip, lines) if x]
|
|
324
324
|
|
|
325
325
|
def _delete(self, filename):
|
|
326
326
|
commands = [f'cd "{self.remote_dir}"']
|