Hello community,

here is the log from the commit of package duplicity for openSUSE:Factory 
checked in at 2015-12-17 15:52:08
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/duplicity (Old)
 and      /work/SRC/openSUSE:Factory/.duplicity.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "duplicity"

Changes:
--------
--- /work/SRC/openSUSE:Factory/duplicity/duplicity.changes      2015-10-03 
20:29:55.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.duplicity.new/duplicity.changes 2015-12-17 
15:52:09.000000000 +0100
@@ -1,0 +2,29 @@
+Wed Dec  9 09:44:40 UTC 2015 - w...@rosenauer.org
+
+- update to 0.7.06
+  * This adds support for AWS S3's newly announced Infrequent Access
+    storage class and is intended to implement Blueprint:
+    https://blueprints.launchpad.net/duplicity/+spec/aws-s3-std-ia-class
+  * A new command line option, --s3-use-ia, is added, and boto backend
+    will automatically use the correct storage class value depending on
+    whether --s3-use-rrs and --s3-use-ia is set. Command line parser will
+    prompt error if both --s3-use-ia and --s3-use-rrs are used together,
+    as they conflict with each other.
+  * Upgrade to newest version of pep8 and pylint
+  * WindowsAzureMissingResourceError and WindowsAzureConflictError
+    changed due to SDK changes.
+  * make sure packages using python's tempfile create temp files in
+    duplicity's temp dir
+  * Fixed bug #1511308 - Cannot restore no-encryption, no-compression backup
+  * Fix missing SWIFT_ENDPOINT_TYPE env var, bug #1519694.
+  * Fix bug #1520691 - Shell Code Injection in hsi backend
+  * Support new version of Azure Storage SDK
+  * Adds a backend for BackBlaze's (currently beta) B2 backup service.
+
+-------------------------------------------------------------------
+Mon Nov 23 10:53:35 UTC 2015 - w...@rosenauer.org
+
+- current FTP default is lftp; therefore recommend that instead
+  of ncftp
+
+-------------------------------------------------------------------

Old:
----
  duplicity-0.7.05.tar.gz

New:
----
  duplicity-0.7.06.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ duplicity.spec ++++++
--- /var/tmp/diff_new_pack.75ffJb/_old  2015-12-17 15:52:10.000000000 +0100
+++ /var/tmp/diff_new_pack.75ffJb/_new  2015-12-17 15:52:10.000000000 +0100
@@ -19,7 +19,7 @@
 %{!?python_sitelib:  %global python_sitelib  %(python -c "from 
distutils.sysconfig import get_python_lib; print(get_python_lib())")}
 %{!?python_sitearch: %global python_sitearch %(python -c "from 
distutils.sysconfig import get_python_lib; print(get_python_lib(1))")}
 Name:           duplicity
-Version:        0.7.05
+Version:        0.7.06
 Release:        0
 Summary:        Encrypted bandwidth-efficient backup using the rsync algorithm
 License:        GPL-3.0+
@@ -31,7 +31,7 @@
 BuildRequires:  python-devel
 BuildRequires:  python-setuptools
 Requires:       gpg
-Recommends:     ncftp
+Recommends:     lftp
 Requires:       python-lockfile
 Recommends:     python-boto
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build

++++++ duplicity-0.7.05.tar.gz -> duplicity-0.7.06.tar.gz ++++++
++++ 2334 lines of diff (skipped)
++++    retrying with extended exclude list
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/.bzrignore new/duplicity-0.7.06/.bzrignore
--- old/duplicity-0.7.05/.bzrignore     2015-09-15 16:32:51.000000000 +0200
+++ new/duplicity-0.7.06/.bzrignore     2015-12-07 13:03:38.000000000 +0100
@@ -6,6 +6,7 @@
 .pydevproject
 .settings
 .tox
+__pycache__
 build
 config.py
 duplicity.egg-info
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/CHANGELOG new/duplicity-0.7.06/CHANGELOG
--- old/duplicity-0.7.05/CHANGELOG      2015-09-15 16:32:51.000000000 +0200
+++ new/duplicity-0.7.06/CHANGELOG      2015-12-07 13:03:38.000000000 +0100
@@ -1,3 +1,60 @@
+New in v0.7.06 (2015/12/07)
+---------------------------
+* Merged in lp:~mnjul/duplicity/s3-infreq-access
+  - This adds support for AWS S3's newly announced Infrequent Access
+    storage class and is intended to implement Blueprint:
+    https://blueprints.launchpad.net/duplicity/+spec/aws-s3-std-ia-class .
+  - A new command line option, --s3-use-ia, is added, and boto backend
+    will automatically use the correct storage class value depending on
+    whether --s3-use-rrs and --s3-use-ia is set. Command line parser will
+    prompt error if both --s3-use-ia and --s3-use-rrs are used together,
+    as they conflict with each other.
+  - The manpage has been updated giving a short explanation on the new
+    option. Its wording derives from Amazon's official announcement:
+    https://aws.amazon.com/about-aws/whats-new/2015/09/announcing-new-\
+    amazon-s3-storage-class-and-lower-glacier-prices/
+* The ptyprocess module no longer supports Python 2.6, so fix tox.ini to
+  use an older version.  Make explicit environs for all tests.
+* Upgrade to newest version of pep8 and pylint.   Add three ignores
+  to test_pep8 and one to test_pylint to get the rest to pass.  They
+* Applied patch from Alexander Zangerl to update to changes in lockfile
+  API 0.9 and later.  Updated README to notify users.
+* Modded tox.ini to use the latest lockfile.
+* Merged in lp:~ed.so/duplicity/setup.shebang
+  - Having the python interpreter searched in the PATH is much more
+    flexible than the /usr/bin/python inserted into our scripts shebang
+    by setuptools.  This patch prevents that. don't touch my shebang! :)
+* Cleanup issues around Launchpad build, mainly lockfile >= 0.9.
+* Merged in lp:~michal-s/duplicity/duplicity
+  - WindowsAzureMissingResourceError and WindowsAzureConflictError
+    changed due to SDK changes.
+  are all valid in our case.
+* Reversed previous changes to lockfile.  Now it will take any version
+  extant in the LP build repository.  (PyPi is not avail in LP build).
+* Merged in lp:~ed.so/duplicity/tempfile.tempdir
+  - make sure packages using python's tempfile create temp files in
+    duplicity's temp dir
+* Fixed bug #1511308 - Cannot restore no-encryption, no-compression backup
+  - Corrected code to include plain file in write_multivolume()
+  - Added PlainWriteFile() to gpg.py
+* Merged in lp:~michal-s/duplicity/duplicity
+  - Fix azurebackend storage class import
+* Merged in lp:~feraudet/duplicity/fix
+  - Fix missing SWIFT_ENDPOINT_TYPE env var, bug 1519694.
+* Fix bug #1520691 - Shell Code Injection in hsi backend
+  - Replace use of os.popen3() with subprocess equivalent.
+  - Added code to expand relative program path to full path.
+  - Fix hisbackend where it expected a list not a string.
+* Merged in lp:~noizyland/duplicity/azurebackend-fixes
+  - Support new version of Azure Storage SDK
+  - Refactor _list method to support containers with >5000 blobs
+* Merged in lp:~matthew-t-bentley/duplicity/b2
+  - Adds a backed for BackBlaze's (currently beta) B2 backup service.
+  - This adds backends/b2backend.py, modifies log.py to add an
+    error code and modifies commandline.py to add the b2://
+    example to the help text.
+
+
 New in v0.7.05 (2015/09/15)
 ---------------------------
 * Merged in lp:~aaron-whitehouse/duplicity/fix_patch_error
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/Changelog.GNU new/duplicity-0.7.06/Changelog.GNU
--- old/duplicity-0.7.05/Changelog.GNU  2015-09-15 16:32:51.000000000 +0200
+++ new/duplicity-0.7.06/Changelog.GNU  2015-12-07 13:03:38.000000000 +0100
@@ -1,3 +1,101 @@
+2015-12-07  Kenneth Loafman  <kenn...@loafman.com>
+
+    * Prep for 0.7.06
+
+2015-12-04  Kenneth Loafman  <kenn...@loafman.com>
+
+    * Merged in lp:~matthew-t-bentley/duplicity/b2
+      - Adds a backed for BackBlaze's (currently beta) B2 backup service.
+      - This adds backends/b2backend.py, modifies log.py to add an
+        error code and modifies commandline.py to add the b2://
+        example to the help text.
+
+2015-12-03  Kenneth Loafman  <kenn...@loafman.com>
+
+    * Merged in lp:~noizyland/duplicity/azurebackend-fixes
+      - Support new version of Azure Storage SDK
+      - Refactor _list method to support containers with >5000 blobs
+
+2015-11-30  Kenneth Loafman  <kenn...@loafman.com>
+
+    * Fix bug #1520691 - Shell Code Injection in hsi backend (2)
+      - Added code to expand relative program path to full path.
+      - Fix hisbackend where it expected a list not a string.
+
+2015-11-28  Kenneth Loafman  <kenn...@loafman.com>
+
+    * Fix bug #1520691 - Shell Code Injection in hsi backend
+      - Replace use of os.popen3() with subprocess equivalent.
+
+2015-11-25  Kenneth Loafman  <kenn...@loafman.com>
+
+    * Merged in lp:~feraudet/duplicity/fix
+      - Fix missing SWIFT_ENDPOINT_TYPE env var, bug 1519694.
+
+2015-11-24  Kenneth Loafman  <kenn...@loafman.com>
+
+    * Merged in lp:~michal-s/duplicity/duplicity
+      - Fix azurebackend storage class import
+
+2015-11-05  Kenneth Loafman  <kenn...@loafman.com>
+
+    * Fixed bug #1511308 - Cannot restore no-encryption, no-compression backup
+      - Corrected code to include plain file in write_multivolume()
+      - Added PlainWriteFile() to gpg.py
+
+2015-11-01  Kenneth Loafman  <kenn...@loafman.com>
+
+    * Merged in lp:~ed.so/duplicity/tempfile.tempdir
+      - make sure packages using python's tempfile create temp files in
+          duplicity's temp dir
+
+2015-10-31  Kenneth Loafman  <kenn...@loafman.com>
+
+    * Reversed previous changes to lockfile.  Now it will take any version
+      extant in the LP build repository.  (PyPi is not avail in LP build).
+
+2015-10-27  Kenneth Loafman  <kenn...@loafman.com>
+
+    * Cleanup issues around Launchpad build, mainly lockfile >= 0.9.
+    * Merged in lp:~michal-s/duplicity/duplicity
+      - WindowsAzureMissingResourceError and WindowsAzureConflictError
+        changed due to SDK changes.
+
+2015-10-26  Kenneth Loafman  <kenn...@loafman.com>
+
+    * Applied patch from Alexander Zangerl to update to changes in lockfile
+      API 0.9 and later.  Updated README to notify users.
+    * Modded tox.ini to use the latest lockfile.
+    * Merged in lp:~ed.so/duplicity/setup.shebang
+      - Having the python interpreter searched in the PATH is much more
+        flexible than the /usr/bin/python inserted into our scripts shebang
+        by setuptools.  This patch prevents that. don't touch my shebang! :)
+
+2015-10-12  Kenneth Loafman  <kenn...@loafman.com>
+
+    * Upgrade to newest version of pep8 and pylint.   Add three ignores
+      to test_pep8 and one to test_pylint to get the rest to pass.  They
+      are all valid in our case.
+
+2015-10-10  Kenneth Loafman  <kenn...@loafman.com>
+
+    * Merged in lp:~mnjul/duplicity/s3-infreq-access
+      - This adds support for AWS S3's newly announced Infrequent Access
+        storage class and is intended to implement Blueprint:
+        https://blueprints.launchpad.net/duplicity/+spec/aws-s3-std-ia-class .
+      - A new command line option, --s3-use-ia, is added, and boto backend
+        will automatically use the correct storage class value depending on
+        whether --s3-use-rrs and --s3-use-ia is set. Command line parser will
+        prompt error if both --s3-use-ia and --s3-use-rrs are used together,
+        as they conflict with each other.
+      - The manpage has been updated giving a short explanation on the new
+        option. Its wording derives from Amazon's official announcement:
+        https://aws.amazon.com/about-aws/whats-new/2015/09/announcing-new-\
+        amazon-s3-storage-class-and-lower-glacier-prices/
+    * The ptyprocess module no longer supports Python 2.6, so fix tox.ini to
+      use an older version.  Make explicit environs for all tests.
+
+
 2015-09-15  Kenneth Loafman  <kenn...@loafman.com>
 
     * Merged in lp:~duplicity-team/duplicity/po-updates
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/README new/duplicity-0.7.06/README
--- old/duplicity-0.7.05/README 2015-09-15 16:32:51.000000000 +0200
+++ new/duplicity-0.7.06/README 2015-12-07 13:03:38.000000000 +0100
@@ -22,7 +22,7 @@
  * Python v2.6 or later
  * librsync v0.9.6 or later
  * GnuPG v1.x for encryption
- * python-lockfile for concurrency locking
+ * python-lockfile v0.9 or later for concurrency locking
  * for scp/sftp -- python-paramiko and python-pycryptopp
  * for ftp -- lftp version 3.7.15 or later
  * Boto 2.0 or later for single-processing S3 or GCS access (default)
@@ -74,4 +74,4 @@
 
 or post to the mailing list at
 
-  http://mail.nongnu.org/mailman/listinfo/duplicity-talk/
\ No newline at end of file
+  http://mail.nongnu.org/mailman/listinfo/duplicity-talk/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/bin/duplicity new/duplicity-0.7.06/bin/duplicity
--- old/duplicity-0.7.05/bin/duplicity  2015-09-15 16:32:52.000000000 +0200
+++ new/duplicity-0.7.06/bin/duplicity  2015-12-07 13:03:39.000000000 +0100
@@ -2,7 +2,7 @@
 # -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
 #
 # duplicity -- Encrypted bandwidth efficient backup
-# Version 0.7.05 released September 15, 2015
+# Version 0.7.06 released December 07, 2015
 #
 # Copyright 2002 Ben Escoto <b...@emerose.org>
 # Copyright 2007 Kenneth Loafman <kenn...@loafman.com>
@@ -39,12 +39,15 @@
 import re
 import threading
 from datetime import datetime
-from lockfile import FileLock
+try:
+    from lockfile import FileLock
+except:
+    from lockfile import LockFile as FileLock
 
-if '--pydevd' in sys.argv:
+if '--pydevd' in sys.argv or os.getenv('PYDEVD', None):
     # The following is for starting remote debugging in Eclipse with Pydev.
     # Adjust the path to your location and version of Eclipse and Pydev.
-    pysrc = "/opt/eclipse/plugins/org.python.pydev_3.9.2.201502050007/pysrc"
+    pysrc = "/opt/liclipse/plugins/org.python.pydev_4.4.0.201510052047/pysrc"
     sys.path.append(pysrc)
     import pydevd  # @UnresolvedImport
     pydevd.settrace()
@@ -124,15 +127,15 @@
         and (globals.gpg_profile.sign_key in globals.gpg_profile.recipients
              or globals.gpg_profile.sign_key in 
globals.gpg_profile.hidden_recipients)
         and 'PASSPHRASE' in os.environ):  # noqa
-            log.Notice(_("Reuse configured PASSPHRASE as SIGN_PASSPHRASE"))
-            return os.environ['PASSPHRASE']
+        log.Notice(_("Reuse configured PASSPHRASE as SIGN_PASSPHRASE"))
+        return os.environ['PASSPHRASE']
     # if one encryption key is also the signing key assume that the passphrase 
is identical
     if (not for_signing
         and (globals.gpg_profile.sign_key in globals.gpg_profile.recipients
              or globals.gpg_profile.sign_key in 
globals.gpg_profile.hidden_recipients)
         and 'SIGN_PASSPHRASE' in os.environ):  # noqa
-            log.Notice(_("Reuse configured SIGN_PASSPHRASE as PASSPHRASE"))
-            return os.environ['SIGN_PASSPHRASE']
+        log.Notice(_("Reuse configured SIGN_PASSPHRASE as PASSPHRASE"))
+        return os.environ['SIGN_PASSPHRASE']
 
     # Next, verify we need to ask the user
 
@@ -419,10 +422,11 @@
 
         # write volume
         if globals.encryption:
-            at_end = gpg.GPGWriteFile(tarblock_iter, tdp.name,
-                                      globals.gpg_profile, globals.volsize)
-        else:
+            at_end = gpg.GPGWriteFile(tarblock_iter, tdp.name, 
globals.gpg_profile, globals.volsize)
+        elif globals.compression:
             at_end = gpg.GzipWriteFile(tarblock_iter, tdp.name, 
globals.volsize)
+        else:
+            at_end = gpg.PlainWriteFile(tarblock_iter, tdp.name, 
globals.volsize)
         tdp.setdata()
 
         # Add volume information to manifest
@@ -717,7 +721,7 @@
     if not patchdir.Write_ROPaths(globals.local_path,
                                   restore_get_patched_rop_iter(col_stats)):
         if globals.restore_dir:
-            log.FatalError(_("%s not found in archive, no files restored.")
+            log.FatalError(_("%s not found in archive - no files restored.")
                            % (util.ufn(globals.restore_dir)),
                            log.ErrorCode.restore_dir_not_found)
         else:
@@ -1082,6 +1086,7 @@
             """
             Data block to return from SrcIter
             """
+
             def __init__(self, data):
                 self.data = data
 
@@ -1089,6 +1094,7 @@
             """
             Iterate over source and return Block of data.
             """
+
             def __init__(self, fileobj):
                 self.fileobj = fileobj
 
@@ -1261,7 +1267,7 @@
     log Python, duplicity, and system versions
     """
     log.Log(u'=' * 80, verbosity)
-    log.Log(u"duplicity 0.7.05 (September 15, 2015)", verbosity)
+    log.Log(u"duplicity 0.7.06 (December 07, 2015)", verbosity)
     log.Log(u"Args: %s" % util.ufn(' '.join(sys.argv)), verbosity)
     log.Log(u' '.join(platform.uname()), verbosity)
     log.Log(u"%s %s" % (sys.executable or sys.platform, sys.version), 
verbosity)
@@ -1273,6 +1279,7 @@
     Class to aid in restart of inc or full backup.
     Instance in globals.restart if restart in progress.
     """
+
     def __init__(self, last_backup):
         self.type = None
         self.start_time = None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/bin/duplicity.1 new/duplicity-0.7.06/bin/duplicity.1
--- old/duplicity-0.7.05/bin/duplicity.1        2015-09-15 16:32:52.000000000 
+0200
+++ new/duplicity-0.7.06/bin/duplicity.1        2015-12-07 13:03:39.000000000 
+0100
@@ -1,4 +1,4 @@
-.TH DUPLICITY 1 "September 15, 2015" "Version 0.7.05" "User Manuals" \"  -*- 
nroff -*-
+.TH DUPLICITY 1 "December 07, 2015" "Version 0.7.06" "User Manuals" \"  -*- 
nroff -*-
 .\" disable justification (adjust text to left margin only)
 .\" command line examples stay readable through that
 .ad l
@@ -726,6 +726,14 @@
 Storage on S3.
 
 .TP
+.BI "--s3-use-ia"
+Store volumes using Standard - Infrequent Access when uploading to Amazon S3.
+This storage class has a lower storage cost but a higher per-request cost, and
+the storage cost is calculated against a 30-day storage minimum. According to
+Amazon, this storage is ideal for long-term file storage, backups, and disaster
+recovery.
+
+.TP
 .BI "--s3-use-multiprocessing"
 Allow multipart volumne uploads to S3 through multiprocessing. This option
 requires Python 2.6 and can be used to make uploads to S3 more efficient.
@@ -1002,6 +1010,12 @@
 .B "A NOTE ON AZURE ACCESS"
 .RE
 .PP
+.BR "B2"
+.PP
+.RS
+b2://account_id[:application_key]@bucket_name/[folder/]
+.RE
+.PP
 .BR "Cloud Files" " (Rackspace)"
 .PP
 .RS
@@ -1457,8 +1471,8 @@
 if /home/ben/1234567 existed.
 
 .SH A NOTE ON AZURE ACCESS
-The Azure backend requires the Microsoft Azure SDK for Python to be installed
-on the system.
+The Azure backend requires the Microsoft Azure Storage SDK for Python to be 
+installed on the system.
 See
 .B REQUIREMENTS
 above.
@@ -1952,8 +1966,8 @@
 Some backends also require additional components (probably available as 
packages for your specific platform):
 .TP
 .BR "azure backend" " (Azure Blob Storage Service)"
-.B Microsoft Azure SDK for Python
-- https://github.com/Azure/azure-sdk-for-python
+.B Microsoft Azure Storage SDK for Python
+- https://pypi.python.org/pypi/azure-storage/
 .TP
 .BR "boto backend" " (S3 Amazon Web Services, Google Cloud Storage)"
 .B boto version 2.0+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/bin/rdiffdir new/duplicity-0.7.06/bin/rdiffdir
--- old/duplicity-0.7.05/bin/rdiffdir   2015-09-15 16:32:52.000000000 +0200
+++ new/duplicity-0.7.06/bin/rdiffdir   2015-12-07 13:03:39.000000000 +0100
@@ -1,6 +1,6 @@
 #!/usr/bin/env python2
 # rdiffdir -- Extend rdiff functionality to directories
-# Version 0.7.05 released September 15, 2015
+# Version 0.7.06 released December 07, 2015
 #
 # Copyright 2002 Ben Escoto <b...@emerose.org>
 # Copyright 2007 Kenneth Loafman <kenn...@loafman.com>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/bin/rdiffdir.1 new/duplicity-0.7.06/bin/rdiffdir.1
--- old/duplicity-0.7.05/bin/rdiffdir.1 2015-09-15 16:32:52.000000000 +0200
+++ new/duplicity-0.7.06/bin/rdiffdir.1 2015-12-07 13:03:39.000000000 +0100
@@ -1,4 +1,4 @@
-.TH RDIFFDIR 1 "September 15, 2015" "Version 0.7.05" "User Manuals" \"  -*- 
nroff -*-
+.TH RDIFFDIR 1 "December 07, 2015" "Version 0.7.06" "User Manuals" \"  -*- 
nroff -*-
 .\" disable justification (adjust text to left margin only)
 .\" command line examples stay readable through that
 .ad l
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/duplicity/backend.py 
new/duplicity-0.7.06/duplicity/backend.py
--- old/duplicity-0.7.05/duplicity/backend.py   2015-09-15 16:32:51.000000000 
+0200
+++ new/duplicity-0.7.06/duplicity/backend.py   2015-12-07 13:03:38.000000000 
+0100
@@ -452,8 +452,11 @@
         Execute the given command line, interpreted as a shell command.
         Returns int Exitcode, string StdOut, string StdErr
         """
+        import shlex
         from subprocess import Popen, PIPE
-        p = Popen(commandline, shell=True, stdout=PIPE, stderr=PIPE)
+        args = shlex.split(commandline)
+        args[0] = self.which(args[0])
+        p = Popen(args, stdout=PIPE, stderr=PIPE)
         stdout, stderr = p.communicate()
 
         return p.returncode, stdout, stderr
@@ -485,6 +488,28 @@
                                        (private, result, stdout + '\n' + 
stderr))
         return result, stdout, stderr
 
+    def which(self, program):
+        """
+        Return absolute path for program name.
+        Returns None if program not found.
+        """
+
+        def is_exe(fpath):
+            return os.path.isfile(fpath) and os.path.isabs(fpath) and 
os.access(fpath, os.X_OK)
+
+        fpath, fname = os.path.split(program)
+        if fpath:
+            if is_exe(program):
+                return program
+        else:
+            for path in os.getenv("PATH").split(os.pathsep):
+                path = path.strip('"')
+                exe_file = os.path.abspath(os.path.join(path, program))
+                if is_exe(exe_file):
+                    return exe_file
+
+        return None
+
 
 class BackendWrapper(object):
     """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/duplicity/backends/_boto_single.py 
new/duplicity-0.7.06/duplicity/backends/_boto_single.py
--- old/duplicity-0.7.05/duplicity/backends/_boto_single.py     2015-09-15 
16:32:51.000000000 +0200
+++ new/duplicity-0.7.06/duplicity/backends/_boto_single.py     2015-12-07 
13:03:38.000000000 +0100
@@ -221,6 +221,8 @@
 
         if globals.s3_use_rrs:
             storage_class = 'REDUCED_REDUNDANCY'
+        elif globals.s3_use_ia:
+            storage_class = 'STANDARD_IA'
         else:
             storage_class = 'STANDARD'
         log.Info("Uploading %s/%s to %s Storage" % (self.straight_url, 
remote_filename, storage_class))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/duplicity/backends/azurebackend.py 
new/duplicity-0.7.06/duplicity/backends/azurebackend.py
--- old/duplicity-0.7.05/duplicity/backends/azurebackend.py     2015-09-15 
16:32:51.000000000 +0200
+++ new/duplicity-0.7.06/duplicity/backends/azurebackend.py     2015-12-07 
13:03:38.000000000 +0100
@@ -33,29 +33,36 @@
     def __init__(self, parsed_url):
         duplicity.backend.Backend.__init__(self, parsed_url)
 
-        # Import Microsoft Azure SDK for Python library.
+        # Import Microsoft Azure Storage SDK for Python library.
         try:
             import azure
-            from azure.storage import BlobService
+            import azure.storage
+            if hasattr(azure.storage, 'BlobService'):
+                # v0.11.1 and below
+                from azure.storage import BlobService
+                self.AzureMissingResourceError = 
azure.WindowsAzureMissingResourceError
+                self.AzureConflictError = azure.WindowsAzureConflictError
+            else:
+                # v1.0.0 and above
+                from azure.storage.blob import BlobService
+                self.AzureMissingResourceError = 
azure.common.AzureMissingResourceHttpError
+                self.AzureConflictError = azure.common.AzureConflictHttpError
         except ImportError:
-            raise BackendException('Azure backend requires Microsoft Azure SDK 
for Python '
-                                   
'(https://github.com/Azure/azure-sdk-for-python).')
+            raise BackendException('Azure backend requires Microsoft Azure 
Storage SDK for Python '
+                                   
'(https://pypi.python.org/pypi/azure-storage/).')
 
         if 'AZURE_ACCOUNT_NAME' not in os.environ:
             raise BackendException('AZURE_ACCOUNT_NAME environment variable 
not set.')
-
         if 'AZURE_ACCOUNT_KEY' not in os.environ:
             raise BackendException('AZURE_ACCOUNT_KEY environment variable not 
set.')
+        self.blob_service = 
BlobService(account_name=os.environ['AZURE_ACCOUNT_NAME'],
+                                        
account_key=os.environ['AZURE_ACCOUNT_KEY'])
 
-        account_name = os.environ['AZURE_ACCOUNT_NAME']
-        account_key = os.environ['AZURE_ACCOUNT_KEY']
-        self.WindowsAzureMissingResourceError = 
azure.WindowsAzureMissingResourceError
-        self.blob_service = BlobService(account_name=account_name, 
account_key=account_key)
         # TODO: validate container name
         self.container = parsed_url.path.lstrip('/')
         try:
             self.blob_service.create_container(self.container, 
fail_on_exist=True)
-        except azure.WindowsAzureConflictError:
+        except self.AzureConflictError:
             # Indicates that the resource could not be created because it 
already exists.
             pass
         except Exception as e:
@@ -64,16 +71,23 @@
                            log.ErrorCode.connection_failed)
 
     def _put(self, source_path, remote_filename):
-        # 
http://azure.microsoft.com/en-us/documentation/articles/storage-python-how-to-use-blob-storage/#upload-blob
+        # 
https://azure.microsoft.com/en-us/documentation/articles/storage-python-how-to-use-blob-storage/#upload-a-blob-into-a-container
         self.blob_service.put_block_blob_from_path(self.container, 
remote_filename, source_path.name)
 
     def _get(self, remote_filename, local_path):
-        # 
http://azure.microsoft.com/en-us/documentation/articles/storage-python-how-to-use-blob-storage/#download-blobs
+        # 
https://azure.microsoft.com/en-us/documentation/articles/storage-python-how-to-use-blob-storage/#download-blobs
         self.blob_service.get_blob_to_path(self.container, remote_filename, 
local_path.name)
 
     def _list(self):
-        # 
http://azure.microsoft.com/en-us/documentation/articles/storage-python-how-to-use-blob-storage/#list-blob
-        blobs = self.blob_service.list_blobs(self.container)
+        # 
https://azure.microsoft.com/en-us/documentation/articles/storage-python-how-to-use-blob-storage/#list-the-blobs-in-a-container
+        blobs = []
+        marker = None
+        while True:
+            batch = self.blob_service.list_blobs(self.container, marker=marker)
+            blobs.extend(batch)
+            if not batch.next_marker:
+                break
+            marker = batch.next_marker
         return [blob.name for blob in blobs]
 
     def _delete(self, filename):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/duplicity/backends/b2backend.py 
new/duplicity-0.7.06/duplicity/backends/b2backend.py
--- old/duplicity-0.7.05/duplicity/backends/b2backend.py        1970-01-01 
01:00:00.000000000 +0100
+++ new/duplicity-0.7.06/duplicity/backends/b2backend.py        2015-12-07 
13:03:38.000000000 +0100
@@ -0,0 +1,340 @@
+#
+# Copyright (c) 2015 Matthew Bentley
+#
+#
+# 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.
+
+import os
+import hashlib
+
+import duplicity.backend
+from duplicity.errors import BackendException, FatalBackendException
+
+import json
+import urllib2
+import base64
+
+
+class B2Backend(duplicity.backend.Backend):
+    """
+    Backend for BackBlaze's B2 storage service
+    """
+
+    def __init__(self, parsed_url):
+        """
+        Authorize to B2 api and set up needed variables
+        """
+        duplicity.backend.Backend.__init__(self, parsed_url)
+
+        self.account_id = parsed_url.username
+        account_key = self.get_password()
+
+        self.url_parts = [
+            x for x in parsed_url.path.replace("@", "/").split('/') if x != ''
+        ]
+        if self.url_parts:
+            self.username = self.url_parts.pop(0)
+            self.bucket_name = self.url_parts.pop(0)
+        else:
+            raise BackendException("B2 requires a bucket name")
+        self.path = "/".join(self.url_parts)
+
+        id_and_key = self.account_id + ":" + account_key
+        basic_auth_string = 'Basic ' + base64.b64encode(id_and_key)
+        headers = {'Authorization': basic_auth_string}
+
+        request = urllib2.Request(
+            'https://api.backblaze.com/b2api/v1/b2_authorize_account',
+            headers=headers
+        )
+
+        response = urllib2.urlopen(request)
+        response_data = json.loads(response.read())
+        response.close()
+
+        self.auth_token = response_data['authorizationToken']
+        self.api_url = response_data['apiUrl']
+        self.download_url = response_data['downloadUrl']
+
+        try:
+            self.find_or_create_bucket(self.bucket_name)
+        except urllib2.HTTPError:
+            raise FatalBackendException("Bucket cannot be created")
+
+    def _get(self, remote_filename, local_path):
+        """
+        Download remote_filename to local_path
+        """
+        remote_filename = self.full_filename(remote_filename)
+        url = self.download_url + \
+            '/file/' + self.bucket_name + '/' + \
+            remote_filename
+        resp = self.get_or_post(url, None)
+
+        to_file = open(local_path.name, 'wb')
+        to_file.write(resp)
+        to_file.close()
+
+    def _put(self, source_path, remote_filename):
+        """
+        Copy source_path to remote_filename
+        """
+        self._delete(remote_filename)
+        digest = self.hex_sha1_of_file(source_path)
+        content_type = 'application/pgp-encrypted'
+        remote_filename = self.full_filename(remote_filename)
+
+        info = self.get_upload_info(self.bucket_id)
+        url = info['uploadUrl']
+
+        headers = {
+            'Authorization': info['authorizationToken'],
+            'X-Bz-File-Name': remote_filename,
+            'Content-Type': content_type,
+            'X-Bz-Content-Sha1': digest,
+            'Content-Length': str(os.path.getsize(source_path.name)),
+        }
+        data_file = source_path.open()
+        self.get_or_post(url, None, headers, data_file=data_file)
+
+    def _list(self):
+        """
+        List files on remote server
+        """
+        endpoint = 'b2_list_file_names'
+        url = self.formatted_url(endpoint)
+        params = {
+            'bucketId': self.bucket_id,
+            'maxFileCount': 1000,
+        }
+        try:
+            resp = self.get_or_post(url, params)
+        except urllib2.HTTPError:
+            return []
+
+        files = [x['fileName'].split('/')[-1] for x in resp['files']]
+
+        next_file = resp['nextFileName']
+        while next_file:
+            params['startFileName'] = next_file
+            try:
+                resp = self.get_or_post(url, params)
+            except urllib2.HTTPError:
+                return files
+
+            files += [x['fileName'].split('/')[-1] for x in resp['files']]
+            next_file = resp['nextFileName']
+
+        return files
+
+    def _delete(self, filename):
+        """
+        Delete filename from remote server
+        """
+        endpoint = 'b2_delete_file_version'
+        url = self.formatted_url(endpoint)
+        fileid = self.get_file_id(filename)
+        if fileid is None:
+            return
+        filename = self.full_filename(filename)
+        params = {'fileName': filename, 'fileId': fileid}
+        try:
+            self.get_or_post(url, params)
+        except urllib2.HTTPError as e:
+            if e.code == 400:
+                return
+            else:
+                raise e
+
+    def _query(self, filename):
+        """
+        Get size info of filename
+        """
+        info = self.get_file_info(filename)
+        if not info:
+            return {'size': -1}
+
+        return {'size': info['size']}
+
+    def _error_code(self, operation, e):
+        if isinstance(e, urllib2.HTTPError):
+            if e.code == 400:
+                return log.ErrorCode.bad_request
+            if e.code == 500:
+                return log.ErrorCode.backed_error
+            if e.code == 403:
+                return log.ErrorCode.backed_permission_denied
+
+    def find_or_create_bucket(self, bucket_name):
+        """
+        Find a bucket with name bucket_name and save its id.
+        If it doesn't exist, create it
+        """
+        endpoint = 'b2_list_buckets'
+        url = self.formatted_url(endpoint)
+
+        params = {'accountId': self.account_id}
+        resp = self.get_or_post(url, params)
+
+        bucket_names = [x['bucketName'] for x in resp['buckets']]
+
+        if bucket_name not in bucket_names:
+            self.create_bucket(bucket_name)
+        else:
+            self.bucket_id = {
+                x[
+                    'bucketName'
+                ]: x['bucketId'] for x in resp['buckets']
+            }[bucket_name]
+
+    def create_bucket(self, bucket_name):
+        """
+        Create a bucket with name bucket_name and save its id
+        """
+        endpoint = 'b2_create_bucket'
+        url = self.formatted_url(endpoint)
+        params = {
+            'accountId': self.account_id,
+            'bucketName': bucket_name,
+            'bucketType': 'allPrivate'
+        }
+        resp = self.get_or_post(url, params)
+
+        self.bucket_id = resp['bucketId']
+
+    def formatted_url(self, endpoint):
+        """
+        Return the full api endpoint from just the last part
+        """
+        return '%s/b2api/v1/%s' % (self.api_url, endpoint)
+
+    def get_upload_info(self, bucket_id):
+        """
+        Get an upload url for a bucket
+        """
+        endpoint = 'b2_get_upload_url'
+        url = self.formatted_url(endpoint)
+        return self.get_or_post(url, {'bucketId': bucket_id})
+
+    def get_or_post(self, url, data, headers=None, data_file=None):
+        """
+        Sends the request, either get or post.
+        If data and data_file are None, send a get request.
+        data_file takes precedence over data.
+        If headers are not supplied, just send with an auth key
+        """
+        if headers is None:
+            headers = {'Authorization': self.auth_token}
+        if data_file is not None:
+            data = data_file
+        else:
+            data = json.dumps(data) if data else None
+
+        encoded_headers = dict(
+            (k, urllib2.quote(v.encode('utf-8')))
+            for (k, v) in headers.iteritems()
+        )
+
+        with OpenUrl(url, data, encoded_headers) as resp:
+            out = resp.read()
+            try:
+                return json.loads(out)
+            except ValueError:
+                return out
+
+    def get_file_info(self, filename):
+        """
+        Get a file info from filename
+        """
+        endpoint = 'b2_list_file_names'
+        url = self.formatted_url(endpoint)
+        filename = self.full_filename(filename)
+        params = {
+            'bucketId': self.bucket_id,
+            'maxFileCount': 1,
+            'startFileName': filename,
+        }
+        resp = self.get_or_post(url, params)
+
+        try:
+            return resp['files'][0]
+        except IndexError:
+            return None
+        except TypeError:
+            return None
+
+    def get_file_id(self, filename):
+        """
+        Get a file id form filename
+        """
+        try:
+            return self.get_file_info(filename)['fileId']
+        except IndexError:
+            return None
+        except TypeError:
+            return None
+
+    def full_filename(self, filename):
+        if self.path:
+            return self.path + '/' + filename
+        else:
+            return filename
+
+    @staticmethod
+    def hex_sha1_of_file(path):
+        """
+        Calculate the sha1 of a file to upload
+        """
+        f = path.open()
+        block_size = 1024 * 1024
+        digest = hashlib.sha1()
+        while True:
+            data = f.read(block_size)
+            if len(data) == 0:
+                break
+            digest.update(data)
+        f.close()
+        return digest.hexdigest()
+
+
+class OpenUrl(object):
+    """
+    Context manager that handles an open urllib2.Request, and provides
+    the file-like object that is the response.
+    """
+
+    def __init__(self, url, data, headers):
+        self.url = url
+        self.data = data
+        self.headers = headers
+        self.file = None
+
+    def __enter__(self):
+        request = urllib2.Request(self.url, self.data, self.headers)
+        self.file = urllib2.urlopen(request)
+        return self.file
+
+    def __exit__(self, exception_type, exception, traceback):
+        if self.file is not None:
+            self.file.close()
+
+
+duplicity.backend.register_backend("b2", B2Backend)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/duplicity/backends/hsibackend.py 
new/duplicity-0.7.06/duplicity/backends/hsibackend.py
--- old/duplicity-0.7.05/duplicity/backends/hsibackend.py       2015-09-15 
16:32:51.000000000 +0200
+++ new/duplicity-0.7.06/duplicity/backends/hsibackend.py       2015-12-07 
13:03:38.000000000 +0100
@@ -44,10 +44,13 @@
         self.subprocess_popen(commandline)
 
     def _list(self):
+        import sys
         commandline = '%s "ls -l %s"' % (hsi_command, self.remote_dir)
-        l = os.popen3(commandline)[2].readlines()[3:]
+        l = self.subprocess_popen(commandline)[2]
+        l = l.split(os.linesep)[3:]
         for i in range(0, len(l)):
-            l[i] = l[i].split()[-1]
+            if l[i]:
+                l[i] = l[i].split()[-1]
         return [x for x in l if x]
 
     def _delete(self, filename):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/duplicity/backends/swiftbackend.py 
new/duplicity-0.7.06/duplicity/backends/swiftbackend.py
--- old/duplicity-0.7.05/duplicity/backends/swiftbackend.py     2015-09-15 
16:32:51.000000000 +0200
+++ new/duplicity-0.7.06/duplicity/backends/swiftbackend.py     2015-12-07 
13:03:38.000000000 +0100
@@ -78,6 +78,8 @@
                     os_options.update({'project_domain_id': 
os.environ['SWIFT_PROJECT_DOMAIN_ID']})
                 if 'SWIFT_TENANTNAME' in os.environ:
                     os_options.update({'tenant_name': 
os.environ['SWIFT_TENANTNAME']})
+                if 'SWIFT_ENDPOINT_TYPE' in os.environ:
+                    os_options.update({'endpoint_type': 
os.environ['SWIFT_ENDPOINT_TYPE']})
 
         else:
             conn_kwargs['auth_version'] = '1'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/duplicity/commandline.py 
new/duplicity-0.7.06/duplicity/commandline.py
--- old/duplicity-0.7.05/duplicity/commandline.py       2015-09-15 
16:32:51.000000000 +0200
+++ new/duplicity-0.7.06/duplicity/commandline.py       2015-12-07 
13:03:38.000000000 +0100
@@ -523,6 +523,9 @@
     # Whether to use S3 Reduced Redudancy Storage
     parser.add_option("--s3-use-rrs", action="store_true")
 
+    # Whether to use S3 Infrequent Access Storage
+    parser.add_option("--s3-use-ia", action="store_true")
+
     # Whether to use "new-style" subdomain addressing for S3 buckets. Such
     # use is not backwards-compatible with upper-case buckets, or buckets
     # that are otherwise not expressable in a valid hostname.
@@ -864,7 +867,14 @@
         # TRANSL: Used in usage help to represent a user name (i.e. login).
         # Example:
         # ftp://user[:password]@other.host[:port]/some_dir
-        'user': _("user")
+        'user': _("user"),
+
+        # TRANSL: account id for b2. Example: b2://account_id@bucket/
+        'account_id': _("account_id"),
+
+        # TRANSL: application_key for b2.
+        # Example: b2://account_id:application_key@bucket/
+        'application_key': _("application_key"),
     }
 
     # TRANSL: Header in usage help
@@ -907,6 +917,7 @@
   dpbx:///%(some_dir)s
   onedrive://%(some_dir)s
   azure://%(container_name)s
+  b2://%(account_id)s[:%(application_key)s]@%(bucket_name)s/[%(some_dir)s/]
 
 """ % dict
 
@@ -1057,6 +1068,8 @@
         if globals.restore_dir:
             command_line_error("restore option incompatible with %s backup"
                                % (action,))
+        if globals.s3_use_rrs and globals.s3_use_ia:
+            command_line_error("--s3-use-rrs and --s3-use-ia cannot be used 
together")
 
 
 def ProcessCommandLine(cmdline_list):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/duplicity/globals.py 
new/duplicity-0.7.06/duplicity/globals.py
--- old/duplicity-0.7.05/duplicity/globals.py   2015-09-15 16:32:52.000000000 
+0200
+++ new/duplicity-0.7.06/duplicity/globals.py   2015-12-07 13:03:39.000000000 
+0100
@@ -26,7 +26,7 @@
 
 
 # The current version of duplicity
-version = "0.7.05"
+version = "0.7.06"
 
 # Prefix for all files (appended before type-specific prefixes)
 file_prefix = ""
@@ -191,6 +191,9 @@
 # Whether to use S3 Reduced Redudancy Storage
 s3_use_rrs = False
 
+# Whether to use S3 Infrequent Access Storage
+s3_use_ia = False
+
 # True if we should use boto multiprocessing version
 s3_use_multiprocessing = False
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/duplicity/gpg.py new/duplicity-0.7.06/duplicity/gpg.py
--- old/duplicity-0.7.05/duplicity/gpg.py       2015-09-15 16:32:51.000000000 
+0200
+++ new/duplicity-0.7.06/duplicity/gpg.py       2015-12-07 13:03:38.000000000 
+0100
@@ -357,9 +357,7 @@
         raise
 
 
-def GzipWriteFile(block_iter, filename,
-                  size=200 * 1024 * 1024,
-                  max_footer_size=16 * 1024):
+def GzipWriteFile(block_iter, filename, size=200 * 1024 * 1024, gzipped=True):
     """
     Write gzipped compressed file of given size
 
@@ -388,7 +386,12 @@
             return self.fileobj.close()
 
     file_counted = FileCounted(open(filename, "wb"))
-    gzip_file = gzip.GzipFile(None, "wb", 6, file_counted)
+
+    # if gzipped wrap with GzipFile else plain file out
+    if gzipped:
+        outfile = gzip.GzipFile(None, "wb", 6, file_counted)
+    else:
+        outfile = file_counted
     at_end_of_blockiter = 0
     while True:
         bytes_to_go = size - file_counted.byte_count
@@ -399,12 +402,27 @@
         except StopIteration:
             at_end_of_blockiter = 1
             break
-        gzip_file.write(new_block.data)
+        outfile.write(new_block.data)
 
-    assert not gzip_file.close() and not file_counted.close()
+    assert not outfile.close() and not file_counted.close()
     return at_end_of_blockiter
 
 
+def PlainWriteFile(block_iter, filename, size=200 * 1024 * 1024, 
gzipped=False):
+    """
+    Write plain uncompressed file of given size
+
+    This is like the earlier GPGWriteFile except it writes a gzipped
+    file instead of a gpg'd file.  This function is somewhat out of
+    place, because it doesn't deal with GPG at all, but it is very
+    similar to GPGWriteFile so they might as well be defined together.
+
+    The input requirements on block_iter and the output is the same as
+    GPGWriteFile (returns true if wrote until end of block_iter).
+    """
+    return GzipWriteFile(block_iter, filename, size, gzipped)
+
+
 def get_hash(hash, path, hex=1):
     """
     Return hash of path
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/duplicity/log.py new/duplicity-0.7.06/duplicity/log.py
--- old/duplicity-0.7.05/duplicity/log.py       2015-09-15 16:32:51.000000000 
+0200
+++ new/duplicity-0.7.06/duplicity/log.py       2015-12-07 13:03:38.000000000 
+0100
@@ -307,6 +307,8 @@
 
     dpbx_nologin = 47
 
+    bad_request = 48
+
     # 50->69 reserved for backend errors
     backend_error = 50
     backend_permission_denied = 51
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/duplicity/tempdir.py 
new/duplicity-0.7.06/duplicity/tempdir.py
--- old/duplicity-0.7.05/duplicity/tempdir.py   2015-09-15 16:32:51.000000000 
+0200
+++ new/duplicity-0.7.06/duplicity/tempdir.py   2015-12-07 13:03:38.000000000 
+0100
@@ -38,6 +38,9 @@
 # instance
 _defaultLock = threading.Lock()
 _defaultInstance = None
+# backup the initial tmp dir path because we will force tempfile
+# later to use our generated _defaultInstance.dir() as temproot
+_initialSystemTempRoot = tempfile.gettempdir()
 
 
 def default():
@@ -57,6 +60,8 @@
     try:
         if _defaultInstance is None or _defaultInstance.dir() is None:
             _defaultInstance = TemporaryDirectory(temproot=globals.temproot)
+            # set the temp dir to be the default in tempfile module from now on
+            tempfile.tempdir = _defaultInstance.dir()
         return _defaultInstance
     finally:
         _defaultLock.release()
@@ -116,6 +121,12 @@
         tempbase - The temp root directory, or None to use system
         default (recommended).
         """
+        if temproot is None:
+            if globals.temproot:
+                temproot = globals.temproot
+            else:
+                global _initialSystemTempRoot
+                temproot = _initialSystemTempRoot
         self.__dir = tempfile.mkdtemp("-tempdir", "duplicity-", temproot)
 
         log.Info(_("Using temporary directory %s") % util.ufn(self.__dir))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/duplicity/util.py new/duplicity-0.7.06/duplicity/util.py
--- old/duplicity-0.7.05/duplicity/util.py      2015-09-15 16:32:51.000000000 
+0200
+++ new/duplicity-0.7.06/duplicity/util.py      2015-12-07 13:03:38.000000000 
+0100
@@ -31,7 +31,7 @@
 import string
 import traceback
 
-from lockfile import FileLock, UnlockError
+from lockfile import UnlockError
 
 from duplicity import tarfile
 
@@ -104,6 +104,7 @@
 
 
 class BlackHoleList(list):
+
     def append(self, x):
         pass
 
@@ -161,7 +162,7 @@
 
 def release_lockfile():
     if globals.lockfile and globals.lockfile.is_locked():
-        log.Debug(_("Releasing lockfile %s") % globals.lockfile)
+        log.Debug(_("Releasing lockfile %s") % globals.lockfile.lock_file)
         try:
             globals.lockfile.release()
         except UnlockError:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/po/POTFILES.in new/duplicity-0.7.06/po/POTFILES.in
--- old/duplicity-0.7.05/po/POTFILES.in 2015-09-15 16:32:51.000000000 +0200
+++ new/duplicity-0.7.06/po/POTFILES.in 2015-12-07 13:03:38.000000000 +0100
@@ -15,38 +15,40 @@
 duplicity/robust.py
 duplicity/diffdir.py
 duplicity/lazy.py
-duplicity/backends/copycombackend.py
-duplicity/backends/_cf_pyrax.py
-duplicity/backends/ssh_paramiko_backend.py
-duplicity/backends/localbackend.py
-duplicity/backends/imapbackend.py
-duplicity/backends/pydrivebackend.py
 duplicity/backends/azurebackend.py
-duplicity/backends/par2backend.py
+duplicity/backends/b2backend.py
 duplicity/backends/botobackend.py
-duplicity/backends/swiftbackend.py
-duplicity/backends/hubicbackend.py
-duplicity/backends/_boto_single.py
-duplicity/backends/multibackend.py
 duplicity/backends/_boto_multi.py
-duplicity/backends/__init__.py
+duplicity/backends/_boto_single.py
+duplicity/backends/cfbackend.py
+duplicity/backends/_cf_cloudfiles.py
+duplicity/backends/_cf_pyrax.py
+duplicity/backends/copycombackend.py
 duplicity/backends/dpbxbackend.py
+duplicity/backends/gdocsbackend.py
+duplicity/backends/giobackend.py
 duplicity/backends/hsibackend.py
-duplicity/backends/tahoebackend.py
-duplicity/backends/sxbackend.py
-duplicity/backends/rsyncbackend.py
-duplicity/backends/ssh_pexpect_backend.py
-duplicity/backends/_cf_cloudfiles.py
-duplicity/backends/onedrivebackend.py
-duplicity/backends/ncftpbackend.py
+duplicity/backends/hubicbackend.py
+duplicity/backends/imapbackend.py
+duplicity/backends/__init__.py
 duplicity/backends/lftpbackend.py
-duplicity/backends/gdocsbackend.py
+duplicity/backends/localbackend.py
 duplicity/backends/megabackend.py
-duplicity/backends/giobackend.py
+duplicity/backends/multibackend.py
+duplicity/backends/ncftpbackend.py
+duplicity/backends/onedrivebackend.py
+duplicity/backends/par2backend.py
+duplicity/backends/pydrivebackend.py
+duplicity/backends/README
+duplicity/backends/rsyncbackend.py
+duplicity/backends/ssh_paramiko_backend.py
+duplicity/backends/ssh_pexpect_backend.py
+duplicity/backends/swiftbackend.py
+duplicity/backends/sxbackend.py
+duplicity/backends/tahoebackend.py
 duplicity/backends/webdavbackend.py
 duplicity/backends/pyrax_identity/hubic.py
 duplicity/backends/pyrax_identity/__init__.py
-duplicity/backends/cfbackend.py
 duplicity/__init__.py
 duplicity/librsync.py
 duplicity/errors.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/setup.py new/duplicity-0.7.06/setup.py
--- old/duplicity-0.7.05/setup.py       2015-09-15 16:32:52.000000000 +0200
+++ new/duplicity-0.7.06/setup.py       2015-12-07 13:03:39.000000000 +0100
@@ -26,11 +26,12 @@
 from setuptools.command.test import test
 from setuptools.command.install import install
 from setuptools.command.sdist import sdist
+from distutils.command.build_scripts import build_scripts
 
-version_string = "0.7.05"
+version_string = "0.7.06"
 
-if sys.version_info[:2] < (2, 6):
-    print("Sorry, duplicity requires version 2.6 or later of python")
+if sys.version_info[:2] < (2, 6) or sys.version_info[:2] > (2, 7):
+    print("Sorry, duplicity requires version 2.6 or 2.7 of python.")
     sys.exit(1)
 
 incdir_list = libdir_list = None
@@ -70,6 +71,7 @@
 
 
 class TestCommand(test):
+
     def run(self):
         # Make sure all modules are ready
         build_cmd = self.get_finalized_command("build_py")
@@ -96,6 +98,7 @@
 
 
 class InstallCommand(install):
+
     def run(self):
         # Normally, install will call build().  But we want to delete the
         # testing dir between building and installing.  So we manually build
@@ -113,6 +116,7 @@
 
 # TODO: move logic from dist/makedist inline
 class SDistCommand(sdist):
+
     def run(self):
         version = version_string
         if version[0] == '$':
@@ -123,6 +127,47 @@
         os.system("mv duplicity-" + version + ".tar.gz " + self.dist_dir)
 
 
+# don't touch my shebang
+class BSCommand (build_scripts):
+
+    def run(self):
+        """
+        Copy, chmod each script listed in 'self.scripts'
+        essentially this is the stripped 
+         distutils.command.build_scripts.copy_scripts()
+        routine
+        """
+        from stat import ST_MODE
+        from distutils.dep_util import newer
+        from distutils import log
+
+        self.mkpath(self.build_dir)
+        outfiles = []
+        for script in self.scripts:
+            outfile = os.path.join(self.build_dir, os.path.basename(script))
+            outfiles.append(outfile)
+
+            if not self.force and not newer(script, outfile):
+                log.debug("not copying %s (up-to-date)", script)
+                continue
+
+            log.info("copying and NOT adjusting %s -> %s", script,
+                     self.build_dir)
+            self.copy_file(script, outfile)
+
+        if os.name == 'posix':
+            for file in outfiles:
+                if self.dry_run:
+                    log.info("changing mode of %s", file)
+                else:
+                    oldmode = os.stat(file)[ST_MODE] & 0o7777
+                    newmode = (oldmode | 0o555) & 0o7777
+                    if newmode != oldmode:
+                        log.info("changing mode of %s from %o to %o",
+                                 file, oldmode, newmode)
+                        os.chmod(file, newmode)
+
+
 setup(name="duplicity",
       version=version_string,
       description="Encrypted backup using rsync algorithm",
@@ -132,12 +177,12 @@
       maintainer_email="kenn...@loafman.com",
       url="http://duplicity.nongnu.org/index.html";,
       packages=['duplicity',
-                  'duplicity.backends',
-                  'duplicity.backends.pyrax_identity',
-                  'testing',
-                  'testing.functional',
-                  'testing.overrides',
-                  'testing.unit'],
+                'duplicity.backends',
+                'duplicity.backends.pyrax_identity',
+                'testing',
+                'testing.functional',
+                'testing.overrides',
+                'testing.unit'],
       package_dir={"duplicity": "duplicity",
                    "duplicity.backends": "duplicity/backends", },
       ext_modules=[Extension("duplicity._librsync",
@@ -147,9 +192,11 @@
                              libraries=["rsync"])],
       scripts=['bin/rdiffdir', 'bin/duplicity'],
       data_files=data_files,
+      install_requires=['lockfile'],
       tests_require=['lockfile', 'mock', 'pexpect'],
       test_suite='testing',
       cmdclass={'test': TestCommand,
                 'install': InstallCommand,
-                'sdist': SDistCommand},
+                'sdist': SDistCommand,
+                'build_scripts': BSCommand},
       )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/testing/functional/__init__.py 
new/duplicity-0.7.06/testing/functional/__init__.py
--- old/duplicity-0.7.05/testing/functional/__init__.py 2015-09-15 
16:32:51.000000000 +0200
+++ new/duplicity-0.7.06/testing/functional/__init__.py 2015-12-07 
13:03:38.000000000 +0100
@@ -85,8 +85,10 @@
         child.wait()
 
         return_val = child.exitstatus
-        # output = child.read()
-        # print "Ran duplicity command: ", cmdline, "\n with return_val: ", 
return_val, "\n and output:\n", output
+#         output = child.read()
+#         print "\nduplicity command: ", cmdline, \
+#               "\n with return_val: ", return_val, \
+#               "\n and output:\n", output
 
         if fail:
             self.assertEqual(30, return_val)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/testing/test_code.py 
new/duplicity-0.7.06/testing/test_code.py
--- old/duplicity-0.7.05/testing/test_code.py   2015-09-15 16:32:51.000000000 
+0200
+++ new/duplicity-0.7.06/testing/test_code.py   2015-12-07 13:03:38.000000000 
+0100
@@ -75,7 +75,9 @@
             "--disable=E0611",  # No name in module
             "--disable=E1101",  # Has no member
             "--disable=E1103",  # Maybe has no member
+            "--disable=E0712",  # Catching an exception which doesn't inherit 
from BaseException
             "--ignore=_librsync.so",
+            "--msg-template='{path}:{line}: [{msg_id}({symbol}), {obj}] 
{msg}'",
             os.path.join(_top_dir, 'duplicity'),
             os.path.join(_top_dir, 'bin/duplicity'),
             os.path.join(_top_dir, 'bin/rdiffdir')],
@@ -87,7 +89,10 @@
                          'Must set environment var RUN_CODE_TESTS=1')
     def test_pep8(self):
         ignores = [
-            "E501",
+            "E402",  # module level import not at top of file
+            "E501",  # line too long
+            "E731",  # do not assign a lambda expression, use a def
+            "W503",  # line break before binary operator
         ]
         self.run_checker(["pep8",
                           "--ignore=" + ','.join(ignores),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/testing/unit/test_tempdir.py 
new/duplicity-0.7.06/testing/unit/test_tempdir.py
--- old/duplicity-0.7.05/testing/unit/test_tempdir.py   2015-09-15 
16:32:51.000000000 +0200
+++ new/duplicity-0.7.06/testing/unit/test_tempdir.py   2015-12-07 
13:03:38.000000000 +0100
@@ -20,6 +20,7 @@
 # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
 import os
+import tempfile
 import unittest
 
 from duplicity import tempdir
@@ -30,20 +31,57 @@
     def test_all(self):
         td = tempdir.default()
 
+        # are generated temp files unique?
         self.assertTrue(td.mktemp() != td.mktemp())
 
+        # create and remove a temp dir 
         dir = td.mktemp()
         os.mkdir(dir)
         os.rmdir(dir)
 
+        # test mkstemp()
         fd, fname = td.mkstemp()
         os.close(fd)
         os.unlink(fname)
         td.forget(fname)
 
+        # test mkstemp_file()
         fo, fname = td.mkstemp_file()
         fo.close()  # don't forget, leave to cleanup()
 
+        # cleanup
+        td.cleanup()
+
+    def test_dirname(self):
+        """
+        test if we generated a dirname
+        """ 
+        td = tempdir.default()
+        dirname = td.dir()
+        self.assertTrue( dirname is not None )
+        
+        """
+        test if duplicity's temp files are created in our temp dir
+        """ 
+        f1d, f1_name = tempdir.default().mkstemp()
+        f1_dirname = os.path.dirname( f1_name )
+        
+        self.assertTrue( dirname == f1_dirname )
+        
+        """
+        test if tempfile creates in our temp dir now as well by default
+        """ 
+        f2 = tempfile.NamedTemporaryFile()
+        f2_dirname = os.path.dirname( f2.name )
+        
+        self.assertTrue( dirname == f2_dirname )
+        
+        # cleanup
+        os.close(f1d)
+        os.unlink(f1_name)
+        td.forget(f1_name)
+        f2.close()
+        
         td.cleanup()
 
 if __name__ == "__main__":
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/duplicity-0.7.05/tox.ini new/duplicity-0.7.06/tox.ini
--- old/duplicity-0.7.05/tox.ini        2015-09-15 16:32:51.000000000 +0200
+++ new/duplicity-0.7.06/tox.ini        2015-12-07 13:03:38.000000000 +0100
@@ -1,24 +1,32 @@
 [tox]
 envlist=py26,py27,lpbuildd-precise
 
-[testenv:lpbuildd-precise]
+[testenv:py26]
 setenv=
-       RUN_CODE_TESTS=0
+    RUN_CODE_TESTS=0
 deps=
-    lockfile==0.8
     mock==0.7.2
     pexpect==2.4
-    python==2.7
+    ptyprocess==0.4
+    python==2.6
+    unittest2
 
-[testenv]
+[testenv:py27]
 setenv=
-       RUN_CODE_TESTS=1
+    RUN_CODE_TESTS=1
 deps=
-    lockfile
     mock
     pexpect
-    unittest2
-# conditional deps (py26: unittest2) don't work on tox <1.8
+    python==2.7
+
+[testenv:lpbuildd-precise]
+setenv=
+    RUN_CODE_TESTS=0
+deps=
+    mock==0.7.2
+    pexpect==2.4
+    python==2.7
 
+[testenv]
 commands=
-       {envpython} {toxinidir}/setup.py test {posargs}
+    {envpython} {toxinidir}/setup.py test {posargs}


Reply via email to