--- duplicity-0.6.19.orig/debian/preinst +++ duplicity-0.6.19/debian/preinst @@ -0,0 +1,8 @@ +#!/bin/sh -e + +# fix my previous errors + +rm -rf /usr/lib/python2.2/site-packages/duplicity/ +rm -rf /usr/lib/python2.3/site-packages/duplicity/ + +#DEBHELPER# --- duplicity-0.6.19.orig/debian/NEWS.Debian +++ duplicity-0.6.19/debian/NEWS.Debian @@ -0,0 +1,64 @@ +duplicity (0.6.08b-1) unstable; urgency=low + + With 0.6.06 duplicity stopped removing old data properly, + EXCEPT when one ran a cleanup option with --extra-clean enabled. + Note that normal remove* ops are not sufficient for a proper clean. + + (the cause is changeset 616, lp:~mterry/duplicity/list-old-chains) + + This has lead to numerous problems wrt. the archive dir cache growing + without bounds as well as some cache desynchronization issues. + It's also extremely counter-intuitive: despite requesting removals + not enough data is removed. + + Until upstream resolves this problem properly, the Debian version + of duplicity now automatically and unconditionally runs a + cleanup operation after a successful remove-older-than or + remove-all-but-n-full operation. + + The definition of "successful" in this context: --force was enabled, + and the remove op found something to remove. + + This forced cleanup is run with --extra-clean active. + +duplicity (0.6.04-1) unstable; urgency=low + + The --archive-dir handling has changed substantially in 0.6, + in ways that affect existing backups. + + Duplicity now requires an archive dir, and if you don't give it one + explicitly it will use ~/.cache/duplicy/. + + To distinguish between multiple backups, a per-backup subdirectory + of the archive dir is used. This suffix is a hash of the target url + or can be set with --name. + + The suffix is ALWAYS ADDED, the archive dir itself is no longer used. + + Consequences: + + * If you have existing backups with an archive dir (where you had + to specify unique archive dirs), you must add an + appropriate --name to have duplicity use the right archive directory. + + Using your existing, specific --archive-dir and --name '' works. + + * If you do not do that or if you have no existing archive dir, + then duplicity will create a new archive dir and + synchronize/recreate the archive dir content from the remote repository. + + If you use encryption then the first duplicity run (attempting this + resynchronization) will fail unless you give it the encryption passphrase + (or access to and passphrase of the relevant gnupg key) - local + archive dir contents are not encrypted but remote repositories are. + + For existing backups I'd highly recommend that you run a + collection-status first, with the appropriate --archive-dir and --name. + It may pay off to ls the archive dir afterwards, confirming that no + unintended --name subdirs have been created. + + After that step any required resynchronizations should be complete and + duplicity should again work fine for unattended backups with or without + encryption. + + -- Alexander Zangerl Fri, 31 Jul 2009 10:50:30 +1000 \ No newline at end of file --- duplicity-0.6.19.orig/debian/watch +++ duplicity-0.6.19/debian/watch @@ -0,0 +1,2 @@ +version=3 +http://launchpad.net/duplicity/+download .*/duplicity-(.+)\.tar\.gz --- duplicity-0.6.19.orig/debian/control +++ duplicity-0.6.19/debian/control @@ -0,0 +1,23 @@ +Source: duplicity +Section: utils +Priority: optional +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Alexander Zangerl +Build-Depends: debhelper (>= 5.0.37.2), librsync-dev (>=0.9.6), python-dev (>= 2.6.6-3), dpatch, rdiff, gnupg +Standards-Version: 3.9.1 +XS-Testsuite: autopkgtest +X-Python-Version: >= 2.5 + +Package: duplicity +Architecture: any +Homepage: http://duplicity.nongnu.org/ +Depends: ${shlibs:Depends}, ${python:Depends}, ${misc:Depends}, python-gnupginterface (>=0.3.2-9.1) +Suggests: python-boto, ncftp, rsync, ssh, python-paramiko +Description: encrypted bandwidth-efficient backup + Duplicity backs directories by producing encrypted tar-format volumes + and uploading them to a remote or local file server. Because duplicity + uses librsync, the incremental archives are space efficient and only + record the parts of files that have changed since the last backup. + Because duplicity uses GnuPG to encrypt and/or sign these archives, they + will be safe from spying and/or modification by the server. + --- duplicity-0.6.19.orig/debian/compat +++ duplicity-0.6.19/debian/compat @@ -0,0 +1 @@ +5 --- duplicity-0.6.19.orig/debian/duplicity.docs +++ duplicity-0.6.19/debian/duplicity.docs @@ -0,0 +1,2 @@ +debian/README.source +README-LOG --- duplicity-0.6.19.orig/debian/copyright +++ duplicity-0.6.19/debian/copyright @@ -0,0 +1,83 @@ +This package was originally debianized by Martin Wuertele +in 2003. Since April 2007 it is maintained +by Alexander Zangerl . + +It was downloaded from http://www.nongnu.org/duplicity/ + +Upstream Authors: + Ben Escoto (duplicity author) + Jiri Tyr (sftp) + intrigeri (sftp-command) + Mathias Wagner (compress) + Joey Hess (bashishm) + + +Copyright: + +duplicity: + +Copyright 2002, 2003, 2004, 2005, 2006 Ben Escoto + 2005 Jiri Tyr + 2006 intrigeri + 2006 Mathias Wagner + 2006 Joey Hess + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2, or (at your option) any later version. + +On Debian GNU/Linux systems, the complete text of the GNU General Public +License can be found in `/usr/share/common-licenses/GPL'. + + +tarfile: + +Copyright (C) 2002 Lars Gustäbel +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +gnupginterface: + +COPYRIGHT: + +Copyright (C) 2001 Frank J. Tobin, ftobin@neverending.org + +LICENSE: + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +or see http://www.gnu.org/copyleft/lesser.html + + + --- duplicity-0.6.19.orig/debian/rules +++ duplicity-0.6.19/debian/rules @@ -0,0 +1,93 @@ +#!/usr/bin/make -f +# Sample debian/rules that uses debhelper. +# GNU copyright 1997 to 1999 by Joey Hess. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +PREFIX := debian/duplicity/usr + + +ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS))) + CFLAGS += -g +endif +ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) + INSTALL_PROGRAM += -s +endif + + +# we use dpatch +include /usr/share/dpatch/dpatch.make + + +configure: configure-stamp +configure-stamp: + dh_testdir +# Add here commands to configure the package. + touch configure-stamp + + +build: build-stamp + +build-stamp: patch configure-stamp + dh_testdir + ./testing/run-tests + +# Add here commands to compile the package. + python setup.py build + touch build-stamp + +clean: clean1 unpatch +clean1: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + +# Add here commands to clean up after the build process. + rm -rf *.pyc + rm -rf build + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + +# Add here commands to install the package into debian/duplicity. + python setup.py install --prefix=$(PREFIX) --no-compile --install-layout=deb + +# remove local GnuPGInterface.py as we use the packaged version + rm -f $(PREFIX)/lib/python*/*-packages/duplicity/GnuPGInterface.py + +# remove docs as we create them with debhelper + rm -rf $(PREFIX)/share/doc/duplicity-* + + +# Build architecture-independent files here. +binary-indep: build install + +# Build architecture-dependent files here. +binary-arch: build install + # for some odd reason dh_python2 always dies with "must build for 2.5" + # unless the version guessing is switched off... + dh_python2 --no-guessing-versions + dh_testdir + dh_testroot + dh_installdocs + dh_installexamples + dh_installman + dh_installchangelogs CHANGELOG + dh_link + dh_strip + dh_compress + dh_fixperms + dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure --- duplicity-0.6.19.orig/debian/changelog +++ duplicity-0.6.19/debian/changelog @@ -0,0 +1,682 @@ +duplicity (0.6.19-0ubuntu2.1) quantal-proposed; urgency=low + + [ Michael Terry ] + * debian/patches/07u1utf8.dpatch: + - Update with a fix for a UnicodeDecodeError crash (LP: #1080423) + * debian/patches/09volcorruption.dpatch: + - Fix some data-corruption issues when resuming an interrupted + backup (LP: #1091269) + + [ Chris J Arges ] + * debian/patches/08caching.dpatch: + - Backport caching work done by Steve Atwell. (LP: #1013446) + + -- Michael Terry Wed, 05 Dec 2012 16:39:01 -0500 + +duplicity (0.6.19-0ubuntu2) quantal; urgency=low + + * debian/patches/06nodeletebasedir.dpatch: + - Backport patch to fix possible error during restore due to + duplicate entries in backup metadata from resumed backups. + LP: #929067 + + -- Michael Terry Thu, 13 Sep 2012 12:43:50 -0400 + +duplicity (0.6.19-0ubuntu1) quantal; urgency=low + + * New upstream release (LP: #1014856) + * debian/patches/06lazywarnings.dpatch: + - Dropped, included upstream + + -- Michael Terry Thu, 21 Jun 2012 13:06:46 -0400 + +duplicity (0.6.18-0ubuntu3) precise; urgency=low + + * debian/patches/06lazywarnings.dpatch: + - Backport patch to add some more machine-readable warning codes + for when duplicity can't restore a particular file. This lets + apps like deja-dup present the user with a list of files with + problems. + + -- Michael Terry Thu, 22 Mar 2012 09:24:58 -0400 + +duplicity (0.6.18-0ubuntu2) precise; urgency=low + + * debian/control: + - Drop python-paramiko to a Suggests to match the ssh Suggests and + to keep it off the CD, for space reasons. It isn't needed for + deja-dup to use ssh anyway, since deja-dup uses GIO for that. So + no loss of functionality in the desktop. + + -- Michael Terry Tue, 06 Mar 2012 10:49:42 -0500 + +duplicity (0.6.18-0ubuntu1) precise; urgency=low + + * New upstream bug-fix release + * debian/patches/01pexpect.dpatch: + - Dropped, upstream switched to paramiko instead + * debian/control: + - Switch depend on python-pexpect to python-paramiko + + -- Michael Terry Mon, 05 Mar 2012 11:42:55 -0500 + +duplicity (0.6.17-0ubuntu1) precise; urgency=low + + * New upstream release + * debian/patches/06_use_passphrase.dpatch, + debian/patches/07_large_rackspace_list.dpatch, + debian/patches/08_check_volumes.dpatch: + - Dropped, applied upstream + * debian/rules: + - Run new upstream test suite during build + * debian/control: + - Add rdiff as a build-dep to run above test suite + * debian/patches/06testfixes.dpatch: + - Fix a few tests to not fail erroneously + * debian/patches/07fixincresume.dpatch: + - Fix a bug with resuming an incremental backup that would result in + a bogus error. Also patches in a test for it. + * debian/tests/full-cycle-local: + - New DEP-8 test script that backs up locally, restores, and checks files + * debian/tests/full-cycle-u1: + - New DEP-8 test script that does the same as above, but to Ubuntu One + * debian/tests/control: + - Start of DEP-8 test suite. Only enable above full-cycle-local test + for automatic execution. The other is for manual testing right now. + + -- Michael Terry Tue, 06 Dec 2011 14:15:01 -0500 + +duplicity (0.6.15-0ubuntu2) oneiric; urgency=low + + * Backport some upstream fixes + * debian/patches/06_use_passhprase.dpatch: + - Don't prompt for passphrase if PASSPHRASE is set (LP: #836467) + * debian/patches/07_large_rackspace_list.dpatch: + - Support listing more than 10,000 files from Rackspace servers + (LP: #832149) + * debian/patches/08_check_volumes.dpatch: + - Attempt to prevent a data corruption bug that can't be reproduced + currently by detecting it up front and stopping the backup. + + -- Michael Terry Thu, 08 Sep 2011 09:10:57 -0400 + +duplicity (0.6.15-0ubuntu1) oneiric; urgency=low + + * New upstream bug-fix release + * debian/watch: + - Update to look at launchpad.net + * debian/patches/06u1ignores404.dpatch, + debian/patches/07ignoreENOTCONN.dpatch: + - Dropped, applied upstream + + -- Michael Terry Fri, 19 Aug 2011 15:30:23 -0400 + +duplicity (0.6.14-0ubuntu3) oneiric; urgency=low + + * debian/patches/07ignoreENOTCONN.dpatch: + - Patch to ignore ENOTCONN errors which can happen when gvfs-fuse + closes without cleaning up. LP: #794576 + * debian/patches/00list: + - Actually apply 06u1ignores404.dpatch from last upload as well + as the above 07 patch + + -- Michael Terry Thu, 07 Jul 2011 16:09:51 -0400 + +duplicity (0.6.14-0ubuntu2) oneiric; urgency=low + + * debian/patches/06u1ignores404.dpatch: + - Ignore 404 "file not found" errors when trying to delete files + on Ubuntu One. Backported from upstream trunk. + + -- Michael Terry Wed, 22 Jun 2011 15:17:39 -0400 + +duplicity (0.6.14-0ubuntu1) oneiric; urgency=low + + * New upstream release + * debian/patches/01collstatus.dpatch, + debian/patches/06moregrace.dpatch, + debian/patches/07ubuntuone.dpatch, + debian/patches/08levelname.dpatch: + - Dropped, included upstream + + -- Michael Terry Sat, 18 Jun 2011 21:36:07 -0400 + +duplicity (0.6.13-2ubuntu1) oneiric; urgency=low + + * debian/patches/07ubuntuone.dpatch: + - Backported from trunk; adds Ubuntu One backend + * debian/patches/08levelname.dpatch: + - Fixes logging issues introduced by above patch + + -- Michael Terry Mon, 13 Jun 2011 11:53:19 -0400 + +duplicity (0.6.13-2) unstable; urgency=low + + * applied fix to allow collectionstatus op without access to key + (closes: #625645) + + -- Alexander Zangerl Sat, 21 May 2011 17:46:28 +1000 + +duplicity (0.6.13-1) unstable; urgency=low + + * New upstream release + * band-aid for #601584: now the error report is at least more verbose + + -- Alexander Zangerl Thu, 21 Apr 2011 18:28:56 +1000 + +duplicity (0.6.12-1) unstable; urgency=low + + * New upstream release (closes: #615668, #579966) + * switched to dh_python2 (closes: #616797) + * now uses mainstream GnuPGInterface module again + + -- Alexander Zangerl Sun, 13 Mar 2011 00:03:18 +1000 + +duplicity (0.6.09-5) unstable; urgency=low + + * changed homepage field (closes: #599060) + * added patch for problems with rsync 3.0.7++ (closes: #595562) + + -- Alexander Zangerl Sat, 20 Nov 2010 14:37:54 +1000 + +duplicity (0.6.09-4) unstable; urgency=low + + * and again i uploaded the Lenny-built package..sigh. (closes: #594562) + * lifted standards version, updated suggests a bit + + -- Alexander Zangerl Tue, 07 Sep 2010 16:45:19 +1000 + +duplicity (0.6.09-3) unstable; urgency=low + + * add patch to prime option parser with proper arguments + (closes: #595567) + + -- Alexander Zangerl Mon, 06 Sep 2010 12:57:46 +1000 + +duplicity (0.6.09-2) unstable; urgency=high + + * added copyright text for the local, modified, version + of GnuPGInterface (closes: #594532) + * upload version built against python 2.6, making the package + installable in Squeeze (closes: #594562) + + -- Alexander Zangerl Sat, 28 Aug 2010 14:37:44 +1000 + +duplicity (0.6.09-1) unstable; urgency=low + + * New upstream release (closes: #581260, #572102, #531786) + + -- Alexander Zangerl Wed, 25 Aug 2010 23:32:30 +1000 + +duplicity (0.6.08b-1) unstable; urgency=low + + * New upstream release + * backed out patch for upstream bug#497243 from 06-3 and -4, as + that fix was only cosmetic. + This version now enforces extra-clean cleanups on any remove operation, + which both fixes the cache desync issue as well as the accumulation of + old cruft in remote archive and local cache. + NEWS.Debian and manpage have been updated to + mention that behaviour. (closes: #572792) + + -- Alexander Zangerl Mon, 15 Mar 2010 20:52:56 +1000 + +duplicity (0.6.06-5) unstable; urgency=low + + * updated watch file (closes: #573890) + + -- Alexander Zangerl Mon, 15 Mar 2010 19:48:37 +1000 + +duplicity (0.6.06-4) unstable; urgency=low + + * updated fix for upstream bug#497243 to fix one remaining + case where cache desynchronization occurs. + + -- Alexander Zangerl Sun, 28 Feb 2010 11:10:07 +1000 + +duplicity (0.6.06-3) unstable; urgency=low + + * applied fix for upstream bug#497243: cache desynchronization. + + -- Alexander Zangerl Tue, 26 Jan 2010 17:12:18 +1000 + +duplicity (0.6.06-2) unstable; urgency=high + + * fixed ssh backend failure (tried to import local pexpect module) + (closes: #556095) + + -- Alexander Zangerl Mon, 16 Nov 2009 04:48:45 +1000 + +duplicity (0.6.06-1) unstable; urgency=low + + * New upstream release (closes: #539903, #420858) + * does no longer depend on python-gnupginterface: upstream + provides a modified version which is claimed to be incompatible + * does not install a local version of python-pexpect + anymore (closes: #555359) + + -- Alexander Zangerl Fri, 13 Nov 2009 07:30:49 +1000 + +duplicity (0.6.05-2) unstable; urgency=low + + * adjusted rules to cater for future python2.6 install + setup (closes: #547825) + + -- Alexander Zangerl Fri, 25 Sep 2009 11:05:38 +1000 + +duplicity (0.6.05-1) unstable; urgency=low + + * New upstream release + * lifted standards version + + -- Alexander Zangerl Sun, 20 Sep 2009 10:46:40 +1000 + +duplicity (0.6.04-1) unstable; urgency=low + + * New upstream release (closes: #536361, #537260, #42858, + #399371, #388180, #386749 ) + * new project homepage + * added notes regarding changed archive-dir behaviour + + -- Alexander Zangerl Wed, 12 Aug 2009 12:34:01 +1000 + +duplicity (0.5.16-1) unstable; urgency=low + + * New upstream release (closes: #524786) + * removed last remaining debian-local patch + + -- Alexander Zangerl Thu, 23 Apr 2009 14:51:28 +1000 + +duplicity (0.5.11-2) unstable; urgency=low + + * changed the setup to temporarily include upstream's repaired copy of + GnuPGInterface.py: because of #509415 in python-gnupginterface + duplicity currently does not work with public key encryption, + no signing and archive dirs. + + -- Alexander Zangerl Mon, 16 Mar 2009 15:57:01 +1000 + +duplicity (0.5.11-1) unstable; urgency=low + + * New upstream release (closes: #519576) + + -- Alexander Zangerl Sat, 14 Mar 2009 09:14:57 +1000 + +duplicity (0.5.06-2) unstable; urgency=low + + * applied most recent upstream fixes + + -- Alexander Zangerl Sat, 31 Jan 2009 14:31:17 +1000 + +duplicity (0.5.06-1) unstable; urgency=low + + * New upstream release + * built against sid, not etch (closes: #513446) + + -- Alexander Zangerl Fri, 30 Jan 2009 11:32:32 +1000 + +duplicity (0.5.02-2) unstable; urgency=low + + * lifted standards version + * added homepage to control (closes: #512798) + + -- Alexander Zangerl Wed, 28 Jan 2009 11:59:57 +1000 + +duplicity (0.5.02-1) unstable; urgency=low + + * New upstream release (closes: #502207) + + -- Alexander Zangerl Wed, 15 Oct 2008 08:38:15 +1000 + +duplicity (0.4.12-2) unstable; urgency=low + + * applied upstream patch to repair --no-encryption option + (which wrongly requested a passphrase) (closes: #497071) + + -- Alexander Zangerl Sun, 31 Aug 2008 12:24:40 +1000 + +duplicity (0.4.12-1) unstable; urgency=low + + * New upstream release + + -- Alexander Zangerl Thu, 21 Aug 2008 10:49:04 +1000 + +duplicity (0.4.11-2) unstable; urgency=high + + * rebuilt for testing's 2.5 python (closes: #480568) + + -- Alexander Zangerl Sun, 11 May 2008 11:10:01 +1000 + +duplicity (0.4.11-1) unstable; urgency=low + + * New upstream release + * make duplicity accept s3 access credentials from boto config files + and not just the environment (closes: #480417) + + -- Alexander Zangerl Sat, 10 May 2008 11:17:39 +1000 + +duplicity (0.4.10-2) unstable; urgency=low + + * applied patch to work around newer python-boto behaviour + which can make existing S3 backups inaccessible. (closes: #475890) + + -- Alexander Zangerl Tue, 15 Apr 2008 12:46:32 +1000 + +duplicity (0.4.10-1) unstable; urgency=low + + * New upstream release + + -- Alexander Zangerl Mon, 31 Mar 2008 22:19:16 +1000 + +duplicity (0.4.8-1) unstable; urgency=high + + * New upstream release + * fixed backup data corruption for rsync backend + + -- Alexander Zangerl Fri, 21 Dec 2007 17:16:42 +1000 + +duplicity (0.4.7-1) unstable; urgency=low + + * New upstream release (closes: #452700) + + -- Alexander Zangerl Sat, 8 Dec 2007 10:29:26 +1000 + +duplicity (0.4.3-6) unstable; urgency=low + + * fixed some manpage typos (closes: #450881) + + -- Alexander Zangerl Thu, 15 Nov 2007 12:21:48 +1000 + +duplicity (0.4.3-5) unstable; urgency=low + + * minor manpage improvements in response to #447538 + + -- Alexander Zangerl Wed, 24 Oct 2007 12:22:14 +1000 + +duplicity (0.4.3-4) unstable; urgency=low + + * applied Christoph Martin's patch to the ftp backend + to make duplicity cooperate with etch's ncftp (closes: #444972) + + -- Alexander Zangerl Sat, 6 Oct 2007 20:02:43 +1000 + +duplicity (0.4.3-3) unstable; urgency=medium + + * reworked the "no passphrase" patch to properly cover + symmetric encryption, where a passphrase is always needed + (closes: #443803) + + -- Alexander Zangerl Tue, 25 Sep 2007 12:14:26 +1000 + +duplicity (0.4.3-2) unstable; urgency=low + + * now suggests ncftp (closes: #442834) and mentions that in NEWS.Debian + i have decided that Recommends: is too strong here, as ftp is a lousy + protocol which should be avoided as much as possible. + * applied upstream fix for leaking ftp passphrases via the commandline + (closes: #442840). the fix works only with ncftp version 3.2.1 + and newer, which means etch is out. + * applied upstream patch for upstream-#21123, which fixes another + ftp backend problem. + * finally fixed the superfluous passphrase dialogs + * tidied build process for easier integration into ubuntu, removing + some unnecessary python version dependencies + * applied upstream patch for upstream-#6211, restoring strict host key + checks for the ssh backend. + + -- Alexander Zangerl Wed, 19 Sep 2007 22:36:04 +1000 + +duplicity (0.4.3-1) unstable; urgency=low + + * New upstream release (closes: #439057) + this release closes a whole bunch of old and recent debian bugs + bzip2 is now optional (closes: #437694) + the manpage is mostly ok now (closes: #345172) + passphrase handling was overhauled (closes: #370198) + sockets are now cleanly ignored (closes: #246984) + commands are retried for temporary problems (closes: #346306) + * new S3 backend (closes: #384490) + this requires python-boto, which is now listed as suggested + * updated dependencies with python-pexpect + * unattended encrypted backups with archive dir work (closes: #369971, #404345) + * patch set reworked + * added local fix for offending/garbage files prohibiting + further actions (closes: #228388) + * added local fix for better tempfile naming + + -- Alexander Zangerl Sat, 8 Sep 2007 20:09:26 +1000 + +duplicity (0.4.2-16) unstable; urgency=low + + * added example backup script (closes: #408749) + * re-added ftp-timeout-patch, which was lost somewhere around 0.4.2-6 + and added pending ftp-mkdir-patch (closes: #413335) + + -- Alexander Zangerl Tue, 19 Jun 2007 12:38:43 +1000 + +duplicity (0.4.2-15) unstable; urgency=low + + * added --help option and usage message (closes: #345165) + + -- Alexander Zangerl Tue, 19 Jun 2007 12:09:21 +1000 + +duplicity (0.4.2-14) unstable; urgency=high + + * fixed bad patch sequence that broke sftp support (closes: #426819) + + -- Alexander Zangerl Fri, 1 Jun 2007 00:19:32 +1000 + +duplicity (0.4.2-13) unstable; urgency=low + + * added a --volsize option to allow user-specified volume chunks + instead of always splitting at 5Mb. + + -- Alexander Zangerl Thu, 24 May 2007 22:48:52 +1000 + +duplicity (0.4.2-12) unstable; urgency=low + + * reworked the patch set + * added patch for archive-dir and incrementals (closes: #370206) + * added patch for encrypted unattended backups + with archive-dir (closes: #369971) + + -- Alexander Zangerl Tue, 10 Apr 2007 14:28:13 +1000 + +duplicity (0.4.2-11) unstable; urgency=low + + * I'm adopting duplicity. Thanks to Martin Wuertele + for his past work on duplicity! (closes: #418159) + * finetuned debhelper dependency + + -- Alexander Zangerl Sun, 8 Apr 2007 17:40:30 +1000 + +duplicity (0.4.2-10.1) unstable; urgency=medium + + * Switch back to python 2.4, as python-central can apparently no longer cope + with 2.3, and 2.4 seems to work ok now; patch from Joey Hess. + (Closes: #396158) + + -- Steinar H. Gunderson Sat, 11 Nov 2006 13:32:07 +0100 + +duplicity (0.4.2-10) unstable; urgency=low + + * fix build target (Closes: #386933) + + -- Martin Wuertele Sat, 16 Sep 2006 10:22:28 +0200 + +duplicity (0.4.2-9) unstable; urgency=low + + * switched to python-central + * removed modules patch (no more needed) + + -- Martin Wuertele Sun, 10 Sep 2006 14:29:07 +0200 + +duplicity (0.4.2-8) unstable; urgency=high + + * depend on python2.3 fixing restore (Closes: #386607) + + -- Martin Wuertele Sat, 9 Sep 2006 11:10:48 +0200 + +duplicity (0.4.2-7.1) unstable; urgency=high + + * NMU + * Don't call dh_pysupport with -n; we need those generated manintainer + scripts to, well, work. Closes: #384489, #384826 + + -- Joey Hess Fri, 8 Sep 2006 01:41:52 -0400 + +duplicity (0.4.2-7) unstable; urgency=low + + * Fix arch so _librsync.so gets compiled (Closes: #385989) + + -- Martin Wuertele Mon, 4 Sep 2006 22:25:09 +0200 + +duplicity (0.4.2-6) unstable; urgency=low + + * switch to dpatch for patch management + * fix private module search path and make sure postint/postrm work + (Closes: #384489) + * updated copyright + + -- Martin Wuertele Sat, 26 Aug 2006 23:25:57 +0200 + +duplicity (0.4.2-5) unstable; urgency=low + + * removed patches from debian-revision + * added README.Debian describing applied patches + * fix targets (Closes: #384570) + + -- Martin Wuertele Fri, 25 Aug 2006 17:39:09 +0200 + +duplicity (0.4.2-4+sftp+compression) unstable; urgency=low + + * temporary disable amazons3 patch + * don't pass /usr/share/python-support to dh_pysupport to fix + searchpath (Closes: #384489) + + -- Martin Wuertele Thu, 24 Aug 2006 19:55:40 +0200 + +duplicity (0.4.2-3+sftp+amazons3+compression) unstable; urgency=low + + * remove old byte compiled stuff in preinst (Closes: #384142) + + -- Martin Wuertele Tue, 22 Aug 2006 22:26:46 +0200 + +duplicity (0.4.2-2+sftp+amazons3+compression.2) unstable; urgency=low + + * Non-maintainer upload. + * Update package to the last python policy (Closes: #380784). + + -- Pierre Habouzit Sat, 12 Aug 2006 23:20:21 +0200 + +duplicity (0.4.2-2+sftp+amazons3+compression.1) unstable; urgency=low + + * NMU + * Fix echo -e bashism. Closes: #375543 + + -- Joey Hess Wed, 5 Jul 2006 16:09:56 -0400 + +duplicity (0.4.2-2+sftp+amazons3+compression) unstable; urgency=low + + * changed build-depends from python2.3-dev to python-dev >= 2.3 + (Closes: #367484) + + -- Martin Wuertele Thu, 18 May 2006 13:35:15 -0500 + +duplicity (0.4.2-1+sftp+amazons3+compression) unstable; urgency=low + + * new upstream release (Closes: #358519) + * fixes some scp/sftp problems + * understands ftp 450 (Closes: #238677) + * --remove-older-than makes sure duplicity deletes older signatures + * --remove-older-than now cannot delete the active backup chain + (Closes: #228386) + * added sftp patch by intrigeri + * added amazon s3 patch by Brian Sutherland + * added compression patch by Mathias Wagner + + + -- Martin Wuertele Mon, 15 May 2006 13:44:05 -0500 + +duplicity (0.4.1-8) unstable; urgency=high + + * added patch to fix ftp timeout exception when backing up huge files with + small changes (patch by Stefan Schimanski ) + + -- Martin Wuertele Mon, 6 Sep 2004 18:57:42 +0200 + +duplicity (0.4.1-7) unstable; urgency=low + + * fixed linebreak in duplicity.1 (Thanks to Uli Martens + + -- Martin Wuertele Fri, 3 Sep 2004 16:36:45 +0200 + +duplicity (0.4.1-6) unstable; urgency=low + + * fixed permissions for tarfile.py + * converted changelog to UTF-8 + * fixed python dependency to 2.3 in tarfile.py + + -- Martin Wuertele Sat, 1 May 2004 22:27:22 +0200 + +duplicity (0.4.1-5) unstable; urgency=low + + * Depend on python-gnupginterface instead of providing GnuPGInterface.py + (Closes: #230048) + + -- Martin Wuertele Fri, 30 Jan 2004 18:13:05 +0100 + +duplicity (0.4.1-4) unstable; urgency=low + + * removed byte compiled code and added postinst to do so + (Closes: #221399) + + -- Martin Wuertele Thu, 20 Nov 2003 19:49:57 +0100 + +duplicity (0.4.1-3) unstable; urgency=low + + * removed CHANGELOG.gz from package + (Closes: #219784) + + -- Martin Wuertele Sun, 9 Nov 2003 19:51:53 +0100 + +duplicity (0.4.1-2) unstable; urgency=low + + * use librsync.h and depend on librsync-dev >= 0.9.6 since prior versions + provide rsync.h + + -- Martin Wuertele Sun, 31 Aug 2003 17:19:58 +0200 + +duplicity (0.4.1-1) unstable; urgency=low + + * new upstream release + + -- Martin Würtele Mon, 11 Aug 2003 21:09:56 +0200 + +duplicity (0.4.0-4) unstable; urgency=low + + * fixed auto build problem + (Closes: #204720) + + -- Martin Würtele Sun, 10 Aug 2003 14:03:20 +0200 + +duplicity (0.4.0-3) unstable; urgency=low + + * recompiled witch python 2.3 + + -- Martin Würtele Sat, 9 Aug 2003 09:17:33 +0200 + +duplicity (0.4.0-2) unstable; urgency=low + + * applied LongLink patch from cvs + * added tarfile license to copyright + + -- Martin Würtele Fri, 8 Aug 2003 16:06:27 +0200 + +duplicity (0.4.0-1) unstable; urgency=low + + * Initial Release. + (Closes: #188713) + + -- Martin Wuertele Sat, 12 Apr 2003 17:06:27 +0200 + --- duplicity-0.6.19.orig/debian/docs +++ duplicity-0.6.19/debian/docs @@ -0,0 +1,2 @@ +README +debian/NEWS.Debian --- duplicity-0.6.19.orig/debian/README.source +++ duplicity-0.6.19/debian/README.source @@ -0,0 +1,38 @@ +This package uses dpatch to manage all modifications to the upstream +source. Changes are stored in the source package as diffs in +debian/patches and applied during the build. + +To get the fully patched source after unpacking the source package, cd +to the root level of the source package and run: + + debian/rules patch + +Removing a patch is as simple as removing its entry from the +debian/patches/00list file, and please also remove the patch file +itself. + +Creating a new patch is done with "dpatch-edit-patch patch XX_patchname" +where you should replace XX with a new number and patchname with a +descriptive shortname of the patch. You can then simply edit all the +files your patch wants to edit, and then simply "exit 0" from the shell +to actually create the patch file. + +To tweak an already existing patch, call "dpatch-edit-patch XX_patchname" +and replace XX_patchname with the actual filename from debian/patches +you want to use. + +To clean up afterwards again, "debian/rules unpatch" will do the +work for you - or you can of course choose to call +"fakeroot debian/rules clean" all together. + + +--- + +this documentation is part of dpatch package, and may be used by +packages using dpatch to comply with policy on README.source. This +documentation is meant to be useful to users who are not proficient in +dpatch in doing work with dpatch-based packages. Please send any +improvements to the BTS of dpatch package. + +original text by Gerfried Fuchs, edited by Junichi Uekawa +10 Aug 2008. --- duplicity-0.6.19.orig/debian/duplicity.examples +++ duplicity-0.6.19/debian/duplicity.examples @@ -0,0 +1 @@ +debian/examples/system-backup --- duplicity-0.6.19.orig/debian/dirs +++ duplicity-0.6.19/debian/dirs @@ -0,0 +1 @@ +usr/bin --- duplicity-0.6.19.orig/debian/tests/control +++ duplicity-0.6.19/debian/tests/control @@ -0,0 +1 @@ +Tests: full-cycle-local --- duplicity-0.6.19.orig/debian/tests/full-cycle-u1 +++ duplicity-0.6.19/debian/tests/full-cycle-u1 @@ -0,0 +1,26 @@ +#!/bin/sh +set -e + +if [ -z "$TMPDIR" ]; then + TMPDIR=/tmp/adt + rm -rf $TMPDIR + mkdir -p $TMPDIR +fi + +export XDG_CACHE_HOME=$TMPDIR/cache +export PASSPHRASE=test + +# clean up from any previous run +python -c ' +import ubuntuone.couch.auth as auth +volume = "https://one.ubuntu.com/api/file_storage/v1/volumes/~/duplicity-test" +print auth.request(volume, http_method="DELETE") +' + +cp -r /bin $TMPDIR/source +duplicity $TMPDIR/source u1+http://duplicity-test +rm -r $XDG_CACHE_HOME +duplicity u1+http://duplicity-test $TMPDIR/restore +diff -p $TMPDIR/source $TMPDIR/restore + +echo "PASSED" --- duplicity-0.6.19.orig/debian/tests/full-cycle-local +++ duplicity-0.6.19/debian/tests/full-cycle-local @@ -0,0 +1,19 @@ +#!/bin/sh +set -e + +if [ -z "$TMPDIR" ]; then + TMPDIR=/tmp/adt + rm -rf $TMPDIR + mkdir -p $TMPDIR +fi + +export XDG_CACHE_HOME=$TMPDIR/cache +export PASSPHRASE=test + +cp -r /bin $TMPDIR/source +duplicity $TMPDIR/source file://$TMPDIR/backup +rm -r $XDG_CACHE_HOME +duplicity file://$TMPDIR/backup $TMPDIR/restore +diff -p $TMPDIR/source $TMPDIR/restore + +echo "PASSED" --- duplicity-0.6.19.orig/debian/patches/09volcorruption.dpatch +++ duplicity-0.6.19/debian/patches/09volcorruption.dpatch @@ -0,0 +1,485 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## 08volcorruption.dpatch by Michael Terry +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: No description. + +@DPATCH@ +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' duplicity-0.6.19~/bin/duplicity duplicity-0.6.19/bin/duplicity +--- duplicity-0.6.19~/bin/duplicity 2013-01-11 10:53:08.000000000 -0500 ++++ duplicity-0.6.19/bin/duplicity 2013-01-11 10:53:09.003418766 -0500 +@@ -221,7 +221,13 @@ + # Just spin our wheels + while tarblock_iter.next(): + if (tarblock_iter.previous_index == last_index): +- if (tarblock_iter.previous_block > last_block): ++ # If both the previous index and this index are done, exit now ++ # before we hit the next index, to prevent skipping its first ++ # block. ++ if not last_block and not tarblock_iter.previous_block: ++ break ++ # Only check block number if last_block is also a number ++ if last_block and tarblock_iter.previous_block > last_block: + break + if tarblock_iter.previous_index > last_index: + log.Warn(_("File %s complete in backup set.\n" +@@ -936,11 +942,10 @@ + """ + Copy data from src_iter to file at fn + """ +- block_size = 128 * 1024 + file = open(filename, "wb") + while True: + try: +- data = src_iter.next(block_size).data ++ data = src_iter.next().data + except StopIteration: + break + file.write(data) +@@ -988,9 +993,9 @@ + def __init__(self, fileobj): + self.fileobj = fileobj + +- def next(self, size): ++ def next(self): + try: +- res = Block(self.fileobj.read(size)) ++ res = Block(self.fileobj.read(self.get_read_size())) + except Exception: + if hasattr(self.fileobj, 'name'): + name = self.fileobj.name +@@ -1004,6 +1009,9 @@ + raise StopIteration + return res + ++ def get_read_size(self): ++ return 128 * 1024 ++ + def get_footer(self): + return "" + +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' duplicity-0.6.19~/duplicity/diffdir.py duplicity-0.6.19/duplicity/diffdir.py +--- duplicity-0.6.19~/duplicity/diffdir.py 2013-01-11 10:53:08.000000000 -0500 ++++ duplicity-0.6.19/duplicity/diffdir.py 2013-01-11 10:53:09.007418783 -0500 +@@ -481,14 +481,14 @@ + filler_data = "" + return TarBlock(index, "%s%s%s" % (headers, file_data, filler_data)) + +- def process(self, val, size): ++ def process(self, val): + """ + Turn next value of input_iter into a TarBlock + """ + assert not self.process_waiting + XXX # Override in subclass @UndefinedVariable + +- def process_continued(self, size): ++ def process_continued(self): + """ + Get more tarblocks + +@@ -498,15 +498,15 @@ + assert self.process_waiting + XXX # Override in subclass @UndefinedVariable + +- def next(self, size = 1024 * 1024): ++ def next(self): + """ +- Return next block, no bigger than size, and update offset ++ Return next block and update offset + """ + if self.process_waiting: +- result = self.process_continued(size) ++ result = self.process_continued() + else: + # Below a StopIteration exception will just be passed upwards +- result = self.process(self.input_iter.next(), size) ++ result = self.process(self.input_iter.next()) + block_number = self.process_next_vol_number + self.offset += len(result.data) + self.previous_index = result.index +@@ -517,6 +517,13 @@ + self.remember_next = False + return result + ++ def get_read_size(self): ++ # read size must always be the same, because if we are restarting a ++ # backup volume where the previous volume ended in a data block, we ++ # have to be able to assume it's length in order to continue reading ++ # the file from the right place. ++ return 64 * 1024 ++ + def get_previous_index(self): + """ + Return index of last tarblock, or None if no previous index +@@ -553,7 +560,7 @@ + """ + TarBlockIter that does no file reading + """ +- def process(self, delta_ropath, size): ++ def process(self, delta_ropath): + """ + Get a fake tarblock from delta_ropath + """ +@@ -577,13 +584,9 @@ + """ + TarBlockIter that yields blocks of a signature tar from path_iter + """ +- def process(self, path, size): ++ def process(self, path): + """ + Return associated signature TarBlock from path +- +- Here size is just ignored --- let's hope a signature isn't too +- big. Also signatures are stored in multiple volumes so it +- doesn't matter. + """ + ti = path.get_tarinfo() + if path.isreg(): +@@ -606,7 +609,7 @@ + delta_path_iter, so the delta information has already been + calculated. + """ +- def process(self, delta_ropath, size): ++ def process(self, delta_ropath): + """ + Get a tarblock from delta_ropath + """ +@@ -631,8 +634,7 @@ + + # Now handle single volume block case + fp = delta_ropath.open("rb") +- # Below the 512 is the usual length of a tar header +- data, last_block = self.get_data_block(fp, size - 512) ++ data, last_block = self.get_data_block(fp) + if stats: + stats.RawDeltaSize += len(data) + if last_block: +@@ -654,11 +656,11 @@ + self.process_next_vol_number = 2 + return self.tarinfo2tarblock(index, ti, data) + +- def get_data_block(self, fp, max_size): ++ def get_data_block(self, fp): + """ + Return pair (next data block, boolean last data block) + """ +- read_size = min(64*1024, max(max_size, 512)) ++ read_size = self.get_read_size() + buf = fp.read(read_size) + if len(buf) < read_size: + if fp.close(): +@@ -667,7 +669,7 @@ + else: + return (buf, False) + +- def process_continued(self, size): ++ def process_continued(self): + """ + Return next volume in multivol diff or snapshot + """ +@@ -675,7 +677,7 @@ + ropath = self.process_ropath + ti, index = ropath.get_tarinfo(), ropath.index + ti.name = "%s/%d" % (self.process_prefix, self.process_next_vol_number) +- data, last_block = self.get_data_block(self.process_fp, size - 512) ++ data, last_block = self.get_data_block(self.process_fp) + if stats: + stats.RawDeltaSize += len(data) + if last_block: +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' duplicity-0.6.19~/duplicity/dup_temp.py duplicity-0.6.19/duplicity/dup_temp.py +--- duplicity-0.6.19~/duplicity/dup_temp.py 2013-01-11 10:53:08.000000000 -0500 ++++ duplicity-0.6.19/duplicity/dup_temp.py 2013-01-11 10:53:09.007418783 -0500 +@@ -256,9 +256,9 @@ + def __init__(self, src): + self.src = src + self.fp = src.open("rb") +- def next(self, size): ++ def next(self): + try: +- res = Block(self.fp.read(size)) ++ res = Block(self.fp.read(self.get_read_size())) + except Exception: + log.FatalError(_("Failed to read %s: %s") % + (self.src.name, sys.exc_info()), +@@ -267,5 +267,7 @@ + self.fp.close() + raise StopIteration + return res ++ def get_read_size(self): ++ return 128 * 1024 + def get_footer(self): + return "" +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' duplicity-0.6.19~/duplicity/gpg.py duplicity-0.6.19/duplicity/gpg.py +--- duplicity-0.6.19~/duplicity/gpg.py 2013-01-11 10:53:08.000000000 -0500 ++++ duplicity-0.6.19/duplicity/gpg.py 2013-01-11 10:53:09.007418783 -0500 +@@ -307,17 +307,16 @@ + def get_current_size(): + return os.stat(filename).st_size + +- block_size = 128 * 1024 # don't bother requesting blocks smaller, but also don't ask for bigger + target_size = size - 50 * 1024 # fudge factor, compensate for gpg buffering + data_size = target_size - max_footer_size + file = GPGFile(True, path.Path(filename), profile) + at_end_of_blockiter = 0 + while True: + bytes_to_go = data_size - get_current_size() +- if bytes_to_go < block_size: ++ if bytes_to_go < block_iter.get_read_size(): + break + try: +- data = block_iter.next(min(block_size, bytes_to_go)).data ++ data = block_iter.next().data + except StopIteration: + at_end_of_blockiter = 1 + break +@@ -366,10 +365,10 @@ + at_end_of_blockiter = 0 + while True: + bytes_to_go = size - file_counted.byte_count +- if bytes_to_go < 32 * 1024: ++ if bytes_to_go < block_iter.get_read_size(): + break + try: +- new_block = block_iter.next(min(128*1024, bytes_to_go)) ++ new_block = block_iter.next() + except StopIteration: + at_end_of_blockiter = 1 + break +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' duplicity-0.6.19~/testing/tests/gpgtest.py duplicity-0.6.19/testing/tests/gpgtest.py +--- duplicity-0.6.19~/testing/tests/gpgtest.py 2012-05-22 10:58:52.000000000 -0400 ++++ duplicity-0.6.19/testing/tests/gpgtest.py 2013-01-11 10:53:09.007418783 -0500 +@@ -134,7 +134,7 @@ + #print os.stat("testfiles/output/gzwrite.gz").st_size-size + assert size - 64 * 1024 <= os.stat("testfiles/output/gzwrite.gz").st_size <= size + 64 * 1024 + gwfh.set_at_end() +- gpg.GzipWriteFile(gwfh, "testfiles/output/gzwrite.gpg", size = size) ++ gpg.GzipWriteFile(gwfh, "testfiles/output/gzwrite.gz", size = size) + #print os.stat("testfiles/output/gzwrite.gz").st_size + + +@@ -157,13 +157,18 @@ + s2 = size - s1 + return "a"*s1 + self.from_random_fp.read(s2) + +- def next(self, size): ++ def next(self): + if self.at_end: raise StopIteration +- if random.randrange(2): real_size = size +- else: real_size = random.randrange(0, size) +- block_data = self.get_buffer(real_size) ++ block_data = self.get_buffer(self.get_read_size()) + return GPGWriteHelper2(block_data) + ++ def get_read_size(self): ++ size = 64 * 1024 ++ if random.randrange(2): ++ return size ++ else: ++ return random.randrange(0, size) ++ + def get_footer(self): + return "e" * random.randrange(0, 15000) + +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' duplicity-0.6.19~/testing/tests/restarttest.py duplicity-0.6.19/testing/tests/restarttest.py +--- duplicity-0.6.19~/testing/tests/restarttest.py 2013-01-11 10:53:08.000000000 -0500 ++++ duplicity-0.6.19/testing/tests/restarttest.py 2013-01-11 10:53:09.007418783 -0500 +@@ -36,7 +36,6 @@ + other_args = ["-v0", "--no-print-statistics"] + #other_args = ["--short-filenames"] + #other_args = ["--ssh-command 'ssh -v'", "--scp-command 'scp -C'"] +-#other_args = ['--no-encryption'] + + # If this is set to true, after each backup, verify contents + verify = 1 +@@ -52,8 +51,9 @@ + Test checkpoint/restart using duplicity binary + """ + def setUp(self): ++ self.class_args = [] + assert not os.system("tar xzf testfiles.tar.gz > /dev/null 2>&1") +- assert not os.system("rm -rf testfiles/output " ++ assert not os.system("rm -rf testfiles/output testfiles/largefiles " + "testfiles/restore_out testfiles/cache") + assert not os.system("mkdir testfiles/output testfiles/cache") + backend = duplicity.backend.get_backend(backend_url) +@@ -76,6 +76,7 @@ + cmd_list.append("--current-time %s" % (current_time,)) + if other_args: + cmd_list.extend(other_args) ++ cmd_list.extend(self.class_args) + cmd_list.extend(arglist) + cmdline = " ".join(cmd_list) + #print "Running '%s'." % cmdline +@@ -140,11 +141,14 @@ + self.verify(dirname, + time = current_time, options = restore_options) + +- def make_largefiles(self): +- # create 3 2M files ++ def make_largefiles(self, count=3, size=2): ++ """ ++ Makes a number of large files in testfiles/largefiles that each are ++ the specified number of megabytes. ++ """ + assert not os.system("mkdir testfiles/largefiles") +- for n in (1,2,3): +- assert not os.system("dd if=/dev/urandom of=testfiles/largefiles/file%d bs=1024 count=2048 > /dev/null 2>&1" % n) ++ for n in range(count): ++ assert not os.system("dd if=/dev/urandom of=testfiles/largefiles/file%d bs=1024 count=%d > /dev/null 2>&1" % (n + 1, size * 1024)) + + def check_same(self, filename1, filename2): + """ +@@ -288,6 +292,128 @@ + self.backup("inc", "testfiles/largefiles") + self.verify("testfiles/largefiles") + ++ def make_fake_second_volume(self, name): ++ """ ++ Takes a successful backup and pretend that we interrupted a backup ++ after two-volumes. (This is because we want to be able to model ++ restarting the second volume and duplicity deletes the last volume ++ found because it may have not finished uploading.) ++ """ ++ # First, confirm that we have signs of a successful backup ++ self.assertEqual(len(glob.glob("testfiles/output/*.manifest*")), 1) ++ self.assertEqual(len(glob.glob("testfiles/output/*.sigtar*")), 1) ++ self.assertEqual(len(glob.glob("testfiles/cache/%s/*" % name)), 2) ++ self.assertEqual(len(glob.glob( ++ "testfiles/cache/%s/*.manifest*" % name)), 1) ++ self.assertEqual(len(glob.glob( ++ "testfiles/cache/%s/*.sigtar*" % name)), 1) ++ # Alright, everything is in order; fake a second interrupted volume ++ assert not os.system("rm testfiles/output/*.manifest*") ++ assert not os.system("rm testfiles/output/*.sigtar*") ++ assert not os.system("rm -f testfiles/output/*.vol[23456789].*") ++ assert not os.system("rm -f testfiles/output/*.vol1[^.]+.*") ++ self.assertEqual(len(glob.glob("testfiles/output/*.difftar*")), 1) ++ assert not os.system("rm testfiles/cache/%s/*.sigtar*" % name) ++ assert not os.system("cp testfiles/output/*.difftar* " ++ "`ls testfiles/output/*.difftar* | " ++ " sed 's|vol1|vol2|'`") ++ assert not os.system("head -n6 testfiles/cache/%s/*.manifest > " ++ "testfiles/cache/%s/" ++ "`basename testfiles/cache/%s/*.manifest`" ++ ".part" % (name, name, name)) ++ assert not os.system("rm testfiles/cache/%s/*.manifest" % name) ++ assert not os.system("""echo 'Volume 2: ++ StartingPath foo ++ EndingPath bar ++ Hash SHA1 sha1' >> testfiles/cache/%s/*.manifest.part""" % name) ++ ++ def test_split_after_small(self): ++ """ ++ If we restart right after a volume that ended with a small ++ (one-block) file, make sure we restart in the right place. ++ """ ++ source = 'testfiles/largefiles' ++ assert not os.system("mkdir -p %s" % source) ++ assert not os.system("echo hello > %s/file1" % source) ++ self.backup("full", source, options=["--name=backup1"]) ++ # Fake an interruption ++ self.make_fake_second_volume("backup1") ++ # Add new small file ++ assert not os.system("echo hello > %s/newfile" % source) ++ # 'restart' the backup ++ self.backup("full", source, options=["--name=backup1"]) ++ # Confirm we actually resumed the previous backup ++ self.assertEqual(len(os.listdir("testfiles/output")), 4) ++ # Now make sure everything is byte-for-byte the same once restored ++ self.restore() ++ assert not os.system("diff -r %s testfiles/restore_out" % source) ++ ++ def test_split_after_large(self): ++ """ ++ If we restart right after a volume that ended with a large ++ (multi-block) file, make sure we restart in the right place. ++ """ ++ source = 'testfiles/largefiles' ++ self.make_largefiles(count=1, size=1) ++ self.backup("full", source, options=["--name=backup1"]) ++ # Fake an interruption ++ self.make_fake_second_volume("backup1") ++ # Add new small file ++ assert not os.system("echo hello > %s/newfile" % source) ++ # 'restart' the backup ++ self.backup("full", source, options=["--name=backup1"]) ++ # Confirm we actually resumed the previous backup ++ self.assertEqual(len(os.listdir("testfiles/output")), 4) ++ # Now make sure everything is byte-for-byte the same once restored ++ self.restore() ++ assert not os.system("diff -r %s testfiles/restore_out" % source) ++ ++ def test_split_inside_large(self): ++ """ ++ If we restart right after a volume that ended inside of a large ++ (multi-block) file, make sure we restart in the right place. ++ """ ++ source = 'testfiles/largefiles' ++ self.make_largefiles(count=1, size=3) ++ self.backup("full", source, options=["--vols 1", "--name=backup1"]) ++ # Fake an interruption ++ self.make_fake_second_volume("backup1") ++ # 'restart' the backup ++ self.backup("full", source, options=["--vols 1", "--name=backup1"]) ++ # Now make sure everything is byte-for-byte the same once restored ++ self.restore() ++ assert not os.system("diff -r %s testfiles/restore_out" % source) ++ ++ def test_new_file(self): ++ """ ++ If we restart right after a volume, but there are new files that would ++ have been backed up earlier in the volume, make sure we don't wig out. ++ (Expected result is to ignore new, ealier files, but pick up later ++ ones.) ++ """ ++ source = 'testfiles/largefiles' ++ self.make_largefiles(count=1, size=1) ++ self.backup("full", source, options=["--name=backup1"]) ++ # Fake an interruption ++ self.make_fake_second_volume("backup1") ++ # Add new files, earlier and later in filename sort order ++ assert not os.system("echo hello > %s/a" % source) ++ assert not os.system("echo hello > %s/z" % source) ++ # 'restart' the backup ++ self.backup("full", source, options=["--name=backup1"]) ++ # Now make sure everything is the same once restored, except 'a' ++ self.restore() ++ assert not os.system("test ! -e testfiles/restore_out/a") ++ assert not os.system("diff %s/file1 testfiles/restore_out/file1" % source) ++ assert not os.system("diff %s/z testfiles/restore_out/z" % source) ++ ++ ++# Note that this class duplicates all the tests in RestartTest ++class RestartTestWithoutEncryption(RestartTest): ++ def setUp(self): ++ RestartTest.setUp(self) ++ self.class_args.extend(["--no-encryption"]) ++ + def test_no_write_double_snapshot(self): + """ + Test that restarting a full backup does not write duplicate entries +@@ -298,12 +424,12 @@ + self.make_largefiles() + # Start backup + try: +- self.backup("full", "testfiles/largefiles", options = ["--fail 2", "--vols 1", "--no-encryption"]) ++ self.backup("full", "testfiles/largefiles", options = ["--fail 2", "--vols 1"]) + self.fail() + except CmdError, e: + self.assertEqual(30, e.exit_status) + # Finish it +- self.backup("full", "testfiles/largefiles", options = ["--no-encryption"]) ++ self.backup("full", "testfiles/largefiles") + # Now check sigtar + sigtars = glob.glob("testfiles/output/duplicity-full*.sigtar.gz") + self.assertEqual(1, len(sigtars)) +@@ -320,7 +446,7 @@ + https://launchpad.net/bugs/929067 + """ + # Intial normal backup +- self.backup("full", "testfiles/blocktartest", options = ["--no-encryption"]) ++ self.backup("full", "testfiles/blocktartest") + # Create an exact clone of the snapshot folder in the sigtar already. + # Permissions and mtime must match. + os.mkdir("testfiles/snapshot", 0755) --- duplicity-0.6.19.orig/debian/patches/00list +++ duplicity-0.6.19/debian/patches/00list @@ -0,0 +1,7 @@ +02cachedesync +03forcecleanup +05upstreamgpgintf +06nodeletebasedir +07u1utf8 +08caching +09volcorruption --- duplicity-0.6.19.orig/debian/patches/03forcecleanup.dpatch +++ duplicity-0.6.19/debian/patches/03forcecleanup.dpatch @@ -0,0 +1,75 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## 03forcecleanup.dpatch by +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: fix for #572792: we force a extra-clean cleanup for all remove* ops + +@DPATCH@ +diff -urNad duplicity-0.6.12~/bin/duplicity duplicity-0.6.12/bin/duplicity +--- duplicity-0.6.12~/bin/duplicity 2011-03-12 19:45:46.000000000 +1000 ++++ duplicity-0.6.12/bin/duplicity 2011-03-12 19:50:23.011966125 +1000 +@@ -774,12 +774,24 @@ + log.Notice("Deleting set " + set.type + " " + dup_time.timetopretty(set.get_time())) + set.delete() + col_stats.set_values(sig_chain_warning=None) ++ ++ # force a cleanup operation to get rid of unnecessary old cruft ++ # we said we want to remove them! didn't we, huh? ++ # bad duplicity, bad doggy! ++ # note: in the long run backing out changeset 616 might be ++ # better, but for now this will ease the pain. ++ globals.extra_clean=True ++ cleanup(col_stats) + else: + log.Notice(gettext.ngettext("Found old backup set at the following time:", + "Found old backup sets at the following times:", + len(setlist)) + + "\n" + set_times_str(setlist) + "\n" + + _("Rerun command with --force option to actually delete.")) ++ # see above for rationale. ++ # this here is to print a list of to-be-removed files (--force is off) ++ globals.extra_clean=True ++ cleanup(col_stats) + + + def sync_archive(): +diff -urNad duplicity-0.6.12~/bin/duplicity.1 duplicity-0.6.12/bin/duplicity.1 +--- duplicity-0.6.12~/bin/duplicity.1 2011-03-12 19:45:46.000000000 +1000 ++++ duplicity-0.6.12/bin/duplicity.1 2011-03-12 19:45:52.722966225 +1000 +@@ -178,6 +178,14 @@ + the other hand if the archive has been deleted or corrupted, this + command may not detect it. + ++.B Note: ++the Debian version of duplicity automatically runs a ++cleanup --extra-clean whenever old backup sets are removed (i.e. if one ++of the remove commands is run with the --force option present and ++if something removable is found). This is to ++limit the amount of old outdated material that otherwise accumulates ++in the archive dir. ++ + .TP + .BI "remove-older-than " time + Delete all backup sets older than the given time. Old backup sets +@@ -223,6 +231,9 @@ + .I --force + will be needed to delete the files rather than just list them. + ++The note regarding automatic cleanups above ++also applies to remove-all-but-n-full. ++ + .TP + .B verify + Enter verify mode instead of restore. If the --file-to-restore option +diff -urNad duplicity-0.6.12~/duplicity/collections.py duplicity-0.6.12/duplicity/collections.py +--- duplicity-0.6.12~/duplicity/collections.py 2011-03-12 19:45:52.673966360 +1000 ++++ duplicity-0.6.12/duplicity/collections.py 2011-03-12 19:45:52.722966225 +1000 +@@ -991,8 +991,6 @@ + if self.matched_chain_pair: + matched_sig_chain = self.matched_chain_pair[0] + for sig_chain in self.all_sig_chains: +- print sig_chain.start_time, matched_sig_chain.start_time, +- print sig_chain.end_time, matched_sig_chain.end_time + if (sig_chain.start_time == matched_sig_chain.start_time and + sig_chain.end_time == matched_sig_chain.end_time): + old_sig_chains.remove(sig_chain) --- duplicity-0.6.19.orig/debian/patches/07u1utf8.dpatch +++ duplicity-0.6.19/debian/patches/07u1utf8.dpatch @@ -0,0 +1,19 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## 07u1utf8.dpatch by Michael Terry +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: No description. + +@DPATCH@ +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' duplicity-0.6.19~/duplicity/backends/u1backend.py duplicity-0.6.19/duplicity/backends/u1backend.py +--- duplicity-0.6.19~/duplicity/backends/u1backend.py 2012-05-22 10:58:52.000000000 -0400 ++++ duplicity-0.6.19/duplicity/backends/u1backend.py 2012-12-05 16:38:45.087816820 -0500 +@@ -218,7 +218,7 @@ + if node.get('has_children') == True: + for child in node.get('children'): + path = urllib.unquote(child.get('path')).lstrip('/') +- filelist += [path] ++ filelist += [path.encode('utf-8')] + return filelist + + @retry --- duplicity-0.6.19.orig/debian/patches/02cachedesync.dpatch +++ duplicity-0.6.19/debian/patches/02cachedesync.dpatch @@ -0,0 +1,26 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## 02cachedesync.dpatch by +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: fix for (upstream)#497243: remove causes cache desynchronization +## DP: backed out the attempted fix, as it only dealt with the symptomps +## DP: and not the root-cause (which is the ill-advised change-set 616) + +@DPATCH@ +diff -urNad duplicity-0.6.08b~/duplicity/collections.py duplicity-0.6.08b/duplicity/collections.py +--- duplicity-0.6.08b~/duplicity/collections.py 2010-03-12 11:39:06.000000000 +1000 ++++ duplicity-0.6.08b/duplicity/collections.py 2010-03-15 20:41:30.904266406 +1000 +@@ -145,12 +145,7 @@ + if (pr + and pr.time == self.time + and pr.start_time == self.start_time +- and pr.end_time == self.end_time +- and pr.type != "new-sig" ): +- # do not remove new sigs from the cache: +- # they aren't removed from the remote archive, +- # and subsequent backups will have to resync +- # which is bad if running non-interactive with encrypt-key ++ and pr.end_time == self.end_time): + try: + globals.archive_dir.append(lfn).delete() + except Exception: --- duplicity-0.6.19.orig/debian/patches/06nodeletebasedir.dpatch +++ duplicity-0.6.19/debian/patches/06nodeletebasedir.dpatch @@ -0,0 +1,370 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## 06nodeletebasedir.patch.dpatch by Michael Terry +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: No description. + +@DPATCH@ +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' duplicity-0.6.19~/bin/duplicity duplicity-0.6.19/bin/duplicity +--- duplicity-0.6.19~/bin/duplicity 2012-09-28 14:04:24.784985288 -0400 ++++ duplicity-0.6.19/bin/duplicity 2012-09-28 14:05:10.656985775 -0400 +@@ -472,7 +472,8 @@ + fh = dup_temp.get_fileobj_duppath(globals.archive_dir, + part_sig_filename, + perm_sig_filename, +- remote_sig_filename) ++ remote_sig_filename, ++ overwrite=True) + return fh + + +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' duplicity-0.6.19~/duplicity/diffdir.py duplicity-0.6.19/duplicity/diffdir.py +--- duplicity-0.6.19~/duplicity/diffdir.py 2012-05-22 10:58:52.000000000 -0400 ++++ duplicity-0.6.19/duplicity/diffdir.py 2012-09-28 14:05:10.656985775 -0400 +@@ -189,8 +189,10 @@ + log.Debug(_("Comparing %s and %s") % (new_path and new_path.index, + sig_path and sig_path.index)) + if not new_path or not new_path.type: +- # file doesn't exist +- if sig_path and sig_path.exists(): ++ # File doesn't exist (but ignore attempts to delete base dir; ++ # old versions of duplicity could have written out the sigtar in ++ # such a way as to fool us; LP: #929067) ++ if sig_path and sig_path.exists() and sig_path.index != (): + # but signature says it did + log.Info(_("D %s") % + (sig_path.get_relative_path(),), +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' duplicity-0.6.19~/duplicity/dup_temp.py duplicity-0.6.19/duplicity/dup_temp.py +--- duplicity-0.6.19~/duplicity/dup_temp.py 2012-05-22 10:58:52.000000000 -0400 ++++ duplicity-0.6.19/duplicity/dup_temp.py 2012-09-28 14:05:10.660985775 -0400 +@@ -60,7 +60,7 @@ + return fh + + +-def get_fileobj_duppath(dirpath, partname, permname, remname): ++def get_fileobj_duppath(dirpath, partname, permname, remname, overwrite=False): + """ + Return a file object open for writing, will write to filename + +@@ -76,7 +76,10 @@ + partname = partname, permname = permname, remname = remname) + else: + dp = path.DupPath(dirpath.name, index = (partname,)) +- fh = FileobjHooked(dp.filtered_open("ab"), tdp = None, dirpath = dirpath, ++ mode = "ab" ++ if overwrite: ++ mode = "wb" ++ fh = FileobjHooked(dp.filtered_open(mode), tdp = None, dirpath = dirpath, + partname = partname, permname = permname, remname = remname) + + def rename_and_forget(): +File ./testing/testfiles/dir1/fifo is a fifo while file /tmp/dpep-work.o5DzJd/duplicity-0.6.19/testing/testfiles/dir1/fifo is a fifo +File ./testing/testfiles/dir2/fifo is a fifo while file /tmp/dpep-work.o5DzJd/duplicity-0.6.19/testing/testfiles/dir2/fifo is a fifo +File ./testing/testfiles/dir3/fifo is a fifo while file /tmp/dpep-work.o5DzJd/duplicity-0.6.19/testing/testfiles/dir3/fifo is a fifo +File ./testing/testfiles/various_file_types/fifo is a fifo while file /tmp/dpep-work.o5DzJd/duplicity-0.6.19/testing/testfiles/various_file_types/fifo is a fifo +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' duplicity-0.6.19~/testing/tests/restarttest.py duplicity-0.6.19/testing/tests/restarttest.py +--- duplicity-0.6.19~/testing/tests/restarttest.py 2012-05-22 10:58:52.000000000 -0400 ++++ duplicity-0.6.19/testing/tests/restarttest.py 2012-09-28 14:05:10.660985775 -0400 +@@ -21,6 +21,8 @@ + + import helper + import sys, os, unittest ++import glob ++import subprocess + + import duplicity.backend + from duplicity import path +@@ -41,7 +43,9 @@ + + class CmdError(Exception): + """Indicates an error running an external command""" +- pass ++ def __init__(self, code): ++ Exception.__init__(self, code) ++ self.exit_status = code + + class RestartTest(unittest.TestCase): + """ +@@ -49,6 +53,14 @@ + """ + def setUp(self): + assert not os.system("tar xzf testfiles.tar.gz > /dev/null 2>&1") ++ assert not os.system("rm -rf testfiles/output " ++ "testfiles/restore_out testfiles/cache") ++ assert not os.system("mkdir testfiles/output testfiles/cache") ++ backend = duplicity.backend.get_backend(backend_url) ++ bl = backend.list() ++ if bl: ++ backend.delete(backend.list()) ++ backend.close() + + def tearDown(self): + assert not os.system("rm -rf testfiles tempdir temp2.tar") +@@ -72,7 +84,7 @@ + # print "CMD: %s" % cmdline + return_val = os.system(cmdline) + if return_val: +- raise CmdError(return_val) ++ raise CmdError(os.WEXITSTATUS(return_val)) + + def backup(self, type, input_dir, options = [], current_time = None): + """Run duplicity backup to default directory""" +@@ -103,25 +115,11 @@ + options.extend(['--restore-time', str(time)]) + self.run_duplicity(args, options, current_time) + +- def deltmp(self): +- """ +- Delete temporary directories +- """ +- assert not os.system("rm -rf testfiles/output " +- "testfiles/restore_out testfiles/cache") +- assert not os.system("mkdir testfiles/output testfiles/cache") +- backend = duplicity.backend.get_backend(backend_url) +- bl = backend.list() +- if bl: +- backend.delete(backend.list()) +- backend.close() +- + def runtest(self, dirlist, backup_options = [], restore_options = []): + """ + Run backup/restore test on directories in dirlist + """ + assert len(dirlist) >= 1 +- self.deltmp() + + # Back up directories to local backend + current_time = 100000 +@@ -142,6 +140,12 @@ + self.verify(dirname, + time = current_time, options = restore_options) + ++ def make_largefiles(self): ++ # create 3 2M files ++ assert not os.system("mkdir testfiles/largefiles") ++ for n in (1,2,3): ++ assert not os.system("dd if=/dev/urandom of=testfiles/largefiles/file%d bs=1024 count=2048 > /dev/null 2>&1" % n) ++ + def check_same(self, filename1, filename2): + """ + Verify two filenames are the same +@@ -153,14 +157,14 @@ + """ + Test basic Checkpoint/Restart + """ +- excludes = ["--exclude **/output", +- "--exclude **/cache",] +- self.deltmp() ++ excludes = ["--exclude '**/output'", ++ "--exclude '**/cache'",] + # we know we're going to fail this one, its forced + try: + self.backup("full", "testfiles", options = ["--vol 1", "--fail 1"] + excludes) +- except CmdError: +- pass ++ self.fail() ++ except CmdError, e: ++ self.assertEqual(30, e.exit_status) + # this one should pass OK + self.backup("full", "testfiles", options = excludes) + self.verify("testfiles", options = excludes) +@@ -169,39 +173,42 @@ + """ + Test multiple Checkpoint/Restart + """ +- excludes = ["--exclude **/output", +- "--exclude **/cache",] +- self.deltmp() ++ excludes = ["--exclude '**/output'", ++ "--exclude '**/cache'",] ++ self.make_largefiles() + # we know we're going to fail these, they are forced + try: +- self.backup("full", "testfiles", options = ["--vol 1", "--fail 1"] + excludes) +- except CmdError: +- pass ++ self.backup("full", "testfiles/largefiles", options = ["--vol 1", "--fail 1"] + excludes) ++ self.fail() ++ except CmdError, e: ++ self.assertEqual(30, e.exit_status) + try: +- self.backup("full", "testfiles", options = ["--vol 1", "--fail 2"] + excludes) +- except CmdError: +- pass ++ self.backup("full", "testfiles/largefiles", options = ["--vol 1", "--fail 2"] + excludes) ++ self.fail() ++ except CmdError, e: ++ self.assertEqual(30, e.exit_status) + try: +- self.backup("full", "testfiles", options = ["--vol 1", "--fail 3"] + excludes) +- except CmdError: +- pass ++ self.backup("full", "testfiles/largefiles", options = ["--vol 1", "--fail 3"] + excludes) ++ self.fail() ++ except CmdError, e: ++ self.assertEqual(30, e.exit_status) + # this one should pass OK +- self.backup("full", "testfiles", options = excludes) +- self.verify("testfiles", options = excludes) ++ self.backup("full", "testfiles/largefiles", options = excludes) ++ self.verify("testfiles/largefiles", options = excludes) + + def test_first_volume_failure(self): + """ + Test restart when no volumes are available on the remote. + Caused when duplicity fails before the first transfer. + """ +- excludes = ["--exclude **/output", +- "--exclude **/cache",] +- self.deltmp() ++ excludes = ["--exclude '**/output'", ++ "--exclude '**/cache'",] + # we know we're going to fail these, they are forced + try: + self.backup("full", "testfiles", options = ["--vol 1", "--fail 1"] + excludes) +- except CmdError: +- pass ++ self.fail() ++ except CmdError, e: ++ self.assertEqual(30, e.exit_status) + assert not os.system("rm testfiles/output/duplicity-full*difftar*") + # this one should pass OK + self.backup("full", "testfiles", options = excludes) +@@ -213,12 +220,12 @@ + than the local manifest has on record. Caused when duplicity + fails the last queued transfer(s). + """ +- self.deltmp() + # we know we're going to fail these, they are forced + try: + self.backup("full", "/bin", options = ["--vol 1", "--fail 3"]) +- except CmdError: +- pass ++ self.fail() ++ except CmdError, e: ++ self.assertEqual(30, e.exit_status) + assert not os.system("rm testfiles/output/duplicity-full*vol[23].difftar*") + # this one should pass OK + self.backup("full", "/bin", options = ["--vol 1"]) +@@ -230,16 +237,13 @@ + Caused when the user deletes a file after a failure. This test puts + the file in the middle of the backup, with files following. + """ +- self.deltmp() +- # create 3 2M files +- assert not os.system("mkdir testfiles/largefiles") +- for n in (1,2,3): +- assert not os.system("dd if=/dev/urandom of=testfiles/largefiles/file%d bs=1024 count=2048 > /dev/null 2>&1" % n) ++ self.make_largefiles() + # we know we're going to fail, it's forced + try: + self.backup("full", "testfiles/largefiles", options = ["--vol 1", "--fail 3"]) +- except CmdError: +- pass ++ self.fail() ++ except CmdError, e: ++ self.assertEqual(30, e.exit_status) + assert not os.system("rm testfiles/largefiles/file2") + # this one should pass OK + self.backup("full", "testfiles/largefiles", options = ["--vol 1"]) +@@ -253,16 +257,13 @@ + Caused when the user deletes a file after a failure. This test puts + the file at the end of the backup, with no files following. + """ +- self.deltmp() +- # create 3 2M files +- assert not os.system("mkdir testfiles/largefiles") +- for n in (1,2,3): +- assert not os.system("dd if=/dev/urandom of=testfiles/largefiles/file%d bs=1024 count=2048 > /dev/null 2>&1" % n) ++ self.make_largefiles() + # we know we're going to fail, it's forced + try: + self.backup("full", "testfiles/largefiles", options = ["--vol 1", "--fail 6"]) +- except CmdError: +- pass ++ self.fail() ++ except CmdError, e: ++ self.assertEqual(30, e.exit_status) + assert not os.system("rm testfiles/largefiles/file3") + # this one should pass OK + self.backup("full", "testfiles/largefiles", options = ["--vol 1"]) +@@ -276,19 +277,73 @@ + """ + # Make first normal full backup + self.backup("full", "testfiles/dir1") +- # create 3 2M files +- assert not os.system("mkdir testfiles/largefiles") +- for n in (1,2,3): +- assert not os.system("dd if=/dev/urandom of=testfiles/largefiles/file%d bs=1024 count=2048 > /dev/null 2>&1" % n) ++ self.make_largefiles() + # Force a failure partway through + try: + self.backup("inc", "testfiles/largefiles", options = ["--vols 1", "--fail 2"]) +- assert False # shouldn't get this far ++ self.fail() + except CmdError, e: +- pass ++ self.assertEqual(30, e.exit_status) + # Now finish that incremental + self.backup("inc", "testfiles/largefiles") + self.verify("testfiles/largefiles") + ++ def test_no_write_double_snapshot(self): ++ """ ++ Test that restarting a full backup does not write duplicate entries ++ into the sigtar, causing problems reading it back in older ++ versions. ++ https://launchpad.net/bugs/929067 ++ """ ++ self.make_largefiles() ++ # Start backup ++ try: ++ self.backup("full", "testfiles/largefiles", options = ["--fail 2", "--vols 1", "--no-encryption"]) ++ self.fail() ++ except CmdError, e: ++ self.assertEqual(30, e.exit_status) ++ # Finish it ++ self.backup("full", "testfiles/largefiles", options = ["--no-encryption"]) ++ # Now check sigtar ++ sigtars = glob.glob("testfiles/output/duplicity-full*.sigtar.gz") ++ self.assertEqual(1, len(sigtars)) ++ sigtar = sigtars[0] ++ output = subprocess.check_output(["tar", "t", "--file=%s" % sigtar]) ++ self.assertEqual(1, output.split("\n").count("snapshot/")) ++ ++ def xtest_ignore_double_snapshot(self): ++ """ ++ Test that we gracefully ignore double snapshot entries in a signature ++ file. This winds its way through duplicity as a deleted base dir, ++ which doesn't make sense and should be ignored. An older version of ++ duplicity accidentally created such files as a result of a restart. ++ https://launchpad.net/bugs/929067 ++ """ ++ # Intial normal backup ++ self.backup("full", "testfiles/blocktartest", options = ["--no-encryption"]) ++ # Create an exact clone of the snapshot folder in the sigtar already. ++ # Permissions and mtime must match. ++ os.mkdir("testfiles/snapshot", 0755) ++ os.utime("testfiles/snapshot", (1030384548, 1030384548)) ++ # Adjust the sigtar.gz file to have a bogus second snapshot/ entry ++ # at the beginning. ++ sigtars = glob.glob("testfiles/output/duplicity-full*.sigtar.gz") ++ self.assertEqual(1, len(sigtars)) ++ sigtar = sigtars[0] ++ self.assertEqual(0, os.system("tar c --file=testfiles/snapshot.sigtar -C testfiles snapshot")) ++ self.assertEqual(0, os.system("gunzip -c %s > testfiles/full.sigtar" % sigtar)) ++ self.assertEqual(0, os.system("tar A --file=testfiles/snapshot.sigtar testfiles/full.sigtar")) ++ self.assertEqual(0, os.system("gzip testfiles/snapshot.sigtar")) ++ os.remove(sigtar) ++ os.rename("testfiles/snapshot.sigtar.gz", sigtar) ++ # Clear cache so our adjusted sigtar will be sync'd back into the cache ++ self.assertEqual(0, os.system("rm -r testfiles/cache")) ++ # Try a follow on incremental (which in buggy versions, would create ++ # a deleted entry for the base dir) ++ self.backup("inc", "testfiles/blocktartest") ++ self.assertEqual(1, len(glob.glob("testfiles/output/duplicity-new*.sigtar.gz"))) ++ # Confirm we can restore it (which in buggy versions, would fail) ++ self.restore() ++ + if __name__ == "__main__": + unittest.main() --- duplicity-0.6.19.orig/debian/patches/08caching.dpatch +++ duplicity-0.6.19/debian/patches/08caching.dpatch @@ -0,0 +1,139 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## 07caching.dpatch by Chris J Arges +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: This patch backports caching support. (LP: #1013446) + +@DPATCH@ +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' duplicity-0.6.18~/duplicity/cached_ops.py duplicity-0.6.18/duplicity/cached_ops.py +--- duplicity-0.6.18~/duplicity/cached_ops.py 1969-12-31 18:00:00.000000000 -0600 ++++ duplicity-0.6.18/duplicity/cached_ops.py 2012-11-14 10:38:11.539372820 -0600 +@@ -0,0 +1,62 @@ ++# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- ++# ++# Copyright 2012 Google Inc. ++# ++# This file is part of duplicity. ++# ++# Duplicity is free software; you can redistribute it and/or modify it ++# under the terms of the GNU General Public License as published by the ++# Free Software Foundation; either version 2 of the License, or (at your ++# option) any later version. ++# ++# Duplicity is distributed in the hope that it will be useful, but ++# WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++# General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with duplicity; if not, write to the Free Software Foundation, ++# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ ++"""Cache-wrapped functions for grp and pwd lookups.""" ++ ++import grp ++import pwd ++ ++ ++class CachedCall(object): ++ """Decorator for caching the results of function calls.""" ++ ++ def __init__(self, f): ++ self.cache = {} ++ self.f = f ++ ++ def __call__(self, *args): ++ try: ++ return self.cache[args] ++ except (KeyError, TypeError), e: ++ result = self.f(*args) ++ if not isinstance(e, TypeError): ++ # TypeError most likely means that args is not hashable ++ self.cache[args] = result ++ return result ++ ++ ++@CachedCall ++def getgrgid(gid): ++ return grp.getgrgid(gid) ++ ++ ++@CachedCall ++def getgrnam(name): ++ return grp.getgrnam(name) ++ ++ ++@CachedCall ++def getpwnam(name): ++ return pwd.getpwnam(name) ++ ++ ++@CachedCall ++def getpwuid(uid): ++ return pwd.getpwuid(uid) +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' duplicity-0.6.18~/duplicity/path.py duplicity-0.6.18/duplicity/path.py +--- duplicity-0.6.18~/duplicity/path.py 2012-02-29 13:24:04.000000000 -0600 ++++ duplicity-0.6.18/duplicity/path.py 2012-11-14 10:38:11.539372820 -0600 +@@ -26,7 +26,7 @@ + + """ + +-import stat, errno, socket, time, re, gzip, pwd, grp ++import stat, errno, socket, time, re, gzip + + from duplicity import tarfile + from duplicity import file_naming +@@ -36,6 +36,7 @@ + from duplicity import librsync + from duplicity import log #@UnusedImport + from duplicity import dup_time ++from duplicity import cached_ops + from duplicity.lazy import * #@UnusedWildImport + + _copy_blocksize = 64 * 1024 +@@ -206,13 +207,13 @@ + try: + if globals.numeric_owner: + raise KeyError +- self.stat.st_uid = pwd.getpwnam(tarinfo.uname)[2] ++ self.stat.st_uid = cached_ops.getpwnam(tarinfo.uname)[2] + except KeyError: + self.stat.st_uid = tarinfo.uid + try: + if globals.numeric_owner: + raise KeyError +- self.stat.st_gid = grp.getgrnam(tarinfo.gname)[2] ++ self.stat.st_gid = cached_ops.getgrnam(tarinfo.gname)[2] + except KeyError: + self.stat.st_gid = tarinfo.gid + +@@ -284,11 +285,11 @@ + ti.mtime = int(self.stat.st_mtime) + + try: +- ti.uname = pwd.getpwuid(ti.uid)[0] ++ ti.uname = cached_ops.getpwuid(ti.uid)[0] + except KeyError: + ti.uname = '' + try: +- ti.gname = grp.getgrgid(ti.gid)[0] ++ ti.gname = cached_ops.getgrgid(ti.gid)[0] + except KeyError: + ti.gname = '' + +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' duplicity-0.6.18~/duplicity/tarfile.py duplicity-0.6.18/duplicity/tarfile.py +--- duplicity-0.6.18~/duplicity/tarfile.py 2012-02-29 13:24:04.000000000 -0600 ++++ duplicity-0.6.18/duplicity/tarfile.py 2012-11-14 10:38:11.539372820 -0600 +@@ -53,10 +53,8 @@ + import re + import operator + +-try: +- import grp, pwd +-except ImportError: +- grp = pwd = None ++from duplicity import cached_ops ++grp = pwd = cached_ops + + # from tarfile import * + __all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError"] --- duplicity-0.6.19.orig/debian/patches/05upstreamgpgintf.dpatch +++ duplicity-0.6.19/debian/patches/05upstreamgpgintf.dpatch @@ -0,0 +1,19 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## 05upstreamgpgintf.dpatch by +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: ensure that the public gnupginterface module is imported + +@DPATCH@ +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' duplicity-0.6.12~/duplicity/gpg.py duplicity-0.6.12/duplicity/gpg.py +--- duplicity-0.6.12~/duplicity/gpg.py 2011-03-09 05:54:31.000000000 +1000 ++++ duplicity-0.6.12/duplicity/gpg.py 2011-03-13 00:31:52.648673991 +1000 +@@ -27,7 +27,7 @@ + + from duplicity import misc + from duplicity import globals +-from duplicity import GnuPGInterface ++import GnuPGInterface + + try: + from hashlib import sha1 --- duplicity-0.6.19.orig/debian/examples/system-backup +++ duplicity-0.6.19/debian/examples/system-backup @@ -0,0 +1,116 @@ +#!/bin/bash +# +# Copyright (C) 2007 Francois Marier +# +# This backup script is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This script is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Email-Reminder; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# Usage: +# backup automatic backup +# backup --full force a full backup +# backup --list-current-files list of files currently backed up +# backup --file-to-restore directory/foo restore the given file as "./restored_foo" +# +# Note that the following files should be in the same directory as this script: +# +# include Files and directories to include in the backup (one per line) +# exclude From the directories previously mentioned, which ones to omit +# id_rsa Private ssh key for the backup host +# id_rsa.pub Public ssh key for the backup host (copied there as .ssh/authorized_keys) +# known_hosts Contains the fingerprints for the backup host + +# -----------START OF USER CONFIGURATION------------ + +# HINT: Generate a good passphrase using "pwgen -s 16" +GPG_PASSWORD="" + +# The directory where this script and all the configuration files are located +BACKUP_HOME="/home/my_username/.backup" + +# The name of the database to backup +WIKIDB="wikidb" + +# The MySQL root password +MYSQL_PASSWORD="mysql_root_password" + +# To limit the SCP transfers to a certain number of bytes per second +SCP_LIMIT="520" + +# How many days to keep the old backups +OLDAGE="9D" + +# Which host (using ssh) to copy the backup to +SSH_HOST="username@some_host.somewhere.net" + +# -----------END OF USER CONFIGURATION------------ + +# Internal variables +SSH_IDENTITY="IdentityFile=$BACKUP_HOME/id_rsa" +SSH_HOSTKEY="UserKnownHostsFile=$BACKUP_HOME/known_hosts" +SSH="ssh -o $SSH_IDENTITY -o $SSH_HOSTKEY" +SCP="scp -q -l $SCP_LIMIT -o $SSH_IDENTITY -o $SSH_HOSTKEY" +SFTP="sftp -o $SSH_IDENTITY -o $SSH_HOSTKEY" +INCLUDE_FILE="$BACKUP_HOME/include" +EXCLUDE_FILE="$BACKUP_HOME/exclude" +DUMP_FILE="$BACKUP_HOME/$WIKIDB-dump.sql" +PKG_FILE="$BACKUP_HOME/dpkg-selections" + +# Create the backup directory in case it doesn't exist +$SSH $SSH_HOST mkdir -p $HOSTNAME + +# If the list of files has been requested, only do that +if [ "$1" = "--list-current-files" ]; then + SCP="scp -q -o $SSH_IDENTITY -o $SSH_HOSTKEY" + PASSPHRASE=$GPG_PASSWORD duplicity --list-current-files --ssh-command "$SSH" --scp-command "$SCP" --sftp-command "$SFTP" scp://$SSH_HOST/$HOSTNAME + exit 0 + +# Restore the given file +elif [ "$1" = "--file-to-restore" ]; then + if [ "$2" = "" ]; then + echo "You must specify a file to restore" + exit 2 + fi + SCP="scp -q -o $SSH_IDENTITY -o $SSH_HOSTKEY" + PASSPHRASE=$GPG_PASSWORD duplicity --ssh-command "$SSH" --scp-command "$SCP" --sftp-command "$SFTP" --file-to-restore "$2" scp://$SSH_HOST/$HOSTNAME restored_`basename $2` + exit 0 + +# Catch invalid arguments +elif [ "$1" != "--full" -a "$1" != "" ]; then + echo "Invalid argument: $1" + exit 1 +fi + +# Delete files related to failed backups +PASSPHRASE=$GPG_PASSWORD duplicity --cleanup --verbosity 1 --sftp-command "$SFTP" scp://$SSH_HOST/$HOSTNAME + +# Delete old expired backups +PASSPHRASE=$GPG_PASSWORD duplicity --force --remove-older-than $OLDAGE --verbosity 1 --sftp-command "$SFTP" scp://$SSH_HOST/$HOSTNAME + +# Dump Wiki DB and list of Debian packages +mysqldump --opt $WIKIDB -uroot -p$MYSQL_PASSWORD > $DUMP_FILE +dpkg --get-selections > $PKG_FILE + +# Check whether a full backup was requested +FULLBACKUP="" +if [ "$1" = "--full" ]; then + FULLBACKUP="--full" +fi + +# Do the actual backup using Duplicity +PASSPHRASE=$GPG_PASSWORD duplicity $FULLBACKUP --no-print-statistics --remove-older-than $OLDAGE --verbosity 1 --exclude-device-files --include $PKG_FILE --include $DUMP_FILE --exclude-globbing-filelist $EXCLUDE_FILE --include-globbing-filelist $INCLUDE_FILE --exclude '**' --ssh-command "$SSH" --scp-command "$SCP" --sftp-command "$SFTP" / scp://$SSH_HOST/$HOSTNAME + +# Cleanup the temporary files +rm -f $DUMP_FILE +rm -f $PKG_FILE