← Back to team overview

duplicity-team team mailing list archive

[Merge] lp:~mbp/duplicity/433970-non-ssl into lp:duplicity

 

Martin Pool has proposed merging lp:~mbp/duplicity/433970-non-ssl into lp:duplicity.

Requested reviews:
  duplicity-team (duplicity-team)
Related bugs:
  #433970 Add an option to connect to S3 with regular HTTP (and not HTTPS)
  https://bugs.launchpad.net/bugs/433970


Hi, this fixes bug 433970 by adding an --s3-unencrypted-connection option.  This makes backups and restores several times faster from Australia to the US, and cuts the amount of traffic substantially.

I have tried to add it tastefully with the existing options.

I haven't added a test; if you like  to have tests for this kind of thing and can point me to a good example I would be happy to try.

I think the warning in the manpage about this is accurate.

Thanks!
-- 
https://code.launchpad.net/~mbp/duplicity/433970-non-ssl/+merge/38303
Your team duplicity-team is requested to review the proposed merge of lp:~mbp/duplicity/433970-non-ssl into lp:duplicity.
=== modified file 'CHANGELOG'
--- CHANGELOG	2010-08-26 14:55:22 +0000
+++ CHANGELOG	2010-10-13 07:44:44 +0000
@@ -1,3 +1,4 @@
+<<<<<<< TREE
 New in v0.7.00 (2010/08/??)
 ---------------------------
 422477  [PATCH] IMAP Backend Error in delete()
@@ -9,6 +10,24 @@
 
 New in v0.6.09 (2010/05/??)
 ----------------------------
+=======
+New in v0.6.10 (2010/09/19)
+----------------------------
+Bugs closed in this release:
+542482     Offer command to remove old incremental backups from target
+578663     Use log codes for common backend errors
+589495     duplicity --short-filenames crashes with TypeError
+612714     NameError: global name 'parsed_url' is not defined
+613448     ftpbackend fails if target directory doesn't exist
+615449     Command-line verbosity parsing crash
+
+
+New in v0.6.09 (2010/07/25)
+----------------------------
+Bugs closed in this release:
+502609     Unknown error while uploading duplicity-full-signatures
+539393     Duplicity returns 1 when continuing an interrupted backup
+>>>>>>> MERGE-SOURCE
 550455     duplicity doesn't handle with large files well
 579958     Assertion error "time not moving forward at appropriate pace"
 576564     username not url decoded in backend (at least rsync)

=== modified file 'dist/setup.py'
--- dist/setup.py	2010-07-22 19:15:11 +0000
+++ dist/setup.py	2010-10-13 07:44:44 +0000
@@ -26,7 +26,7 @@
 version_string = "$version"
 
 if sys.version_info[:2] < (2,3):
-    print "Sorry, duplicity requires version 2.3 or later of python"
+    print "Sorry, duplicity requires version 2.4 or later of python"
     sys.exit(1)
 
 incdir_list = libdir_list = None

=== modified file 'duplicity.1'
--- duplicity.1	2010-08-26 14:55:22 +0000
+++ duplicity.1	2010-10-13 07:44:44 +0000
@@ -555,12 +555,26 @@
 section.
 
 .TP
+.BI "--s3-unencrypted-connection"
+Don't use SSL for connections to S3.
+
+This may be much faster, at some cost to confidentiality.
+
+With this option, anyone who can observe traffic between your computer and S3
+will be able to tell: that you are using Duplicity, the name of the bucket,
+your AWS Access Key ID, the increment dates and the amount of data in each
+increment.
+
+This option affects only the connection, not the GPG encryption of the backup
+increment files.  Unless that is disabled, an observer will not be able to see
+the file names or contents.
+
+.TP
 .BI "--s3-use-new-style"
 When operating on Amazon S3 buckets, use new-style subdomain bucket
 addressing. This is now the preferred method to access Amazon S3, but
 is not backwards compatible if your bucket name contains upper-case
 characters or other characters that are not valid in a hostname.
-
 .TP
 .BI "--scp-command " command
 This option only matters when using the ssh/scp backend.  The

=== modified file 'duplicity/backends/botobackend.py'
--- duplicity/backends/botobackend.py	2010-08-26 14:55:22 +0000
+++ duplicity/backends/botobackend.py	2010-10-13 07:44:44 +0000
@@ -48,7 +48,7 @@
         #  //MyBucket/ and //MyBucket are equivalent.
         #  //MyBucket//My///My/Prefix/ and //MyBucket/My/Prefix are equivalent.
         self.url_parts = filter(lambda x: x != '', parsed_url.path.split('/'))
-        
+
         if self.url_parts:
             self.bucket_name = self.url_parts.pop(0)
         else:
@@ -66,12 +66,13 @@
             self.key_prefix = ''
 
         self.straight_url = duplicity.backend.strip_auth_from_url(parsed_url)
+        self.parsed_url = parsed_url
         self.resetConnection()
 
     def resetConnection(self):
         self.bucket = None
         self.conn = None
-        
+
         try:
             from boto.s3.connection import S3Connection
             from boto.s3.key import Key
@@ -132,10 +133,12 @@
                            log.ErrorCode.boto_lib_too_old)
         if self.scheme == 's3+http':
             # Use the default Amazon S3 host.
-            self.conn = S3Connection()
+            self.conn = S3Connection(is_secure=(not globals.s3_unencrypted_connection))
         else:
             assert self.scheme == 's3'
-            self.conn = S3Connection(host=parsed_url.hostname)
+            self.conn = S3Connection(
+                host=self.parsed_url.hostname,
+                is_secure=(not globals.s3_unencrypted_connection))
 
         if hasattr(self.conn, 'calling_format'):
             if calling_format is None:
@@ -152,7 +155,7 @@
             raise BackendException('Boto requires a bucket name.')
 
         self.bucket = self.conn.lookup(self.bucket_name)
-        
+
     def put(self, source_path, remote_filename=None):
         #Network glitch may prevent first few attempts of creating/looking up a bucket
         for n in range(1, globals.num_retries+1):
@@ -160,7 +163,7 @@
                 break
             if n > 1:
                 time.sleep(30)
-            try:       
+            try:
                 if globals.s3_european_buckets:
                     if not globals.s3_use_new_style:
                         log.FatalError("European bucket creation was requested, but not new-style "
@@ -168,7 +171,7 @@
                                        log.ErrorCode.s3_bucket_not_style)
                     from boto.s3.connection import Location #@UnresolvedImport
                     self.bucket = self.conn.create_bucket(self.bucket_name, location = Location.EU)
-                else:                    
+                else:
                     self.bucket = self.conn.create_bucket(self.bucket_name)
             except Exception, e:
                 log.Warn("Failed to create bucket (attempt #%d) '%s' failed (reason: %s: %s)"
@@ -176,7 +179,7 @@
                                e.__class__.__name__,
                                str(e)))
                 self.resetConnection()
-                    
+
         if not remote_filename:
             remote_filename = source_path.get_filename()
         key = self.key_class(self.bucket)
@@ -185,12 +188,15 @@
             if n > 1:
                 # sleep before retry (new connection to a **hopeful** new host, so no need to wait so long)
                 time.sleep(10)
-                
-            log.Info("Uploading %s/%s to %s Storage" % (self.straight_url, remote_filename, 
-                                                        'REDUCED_REDUNDANCY' if globals.s3_use_rrs else 'STANDARD'))
+
+            if globals.s3_use_rrs:
+                storage_class = 'REDUCED_REDUNDANCY'
+            else:
+                storage_class = 'STANDARD'
+            log.Info("Uploading %s/%s to %s Storage" % (self.straight_url, remote_filename, storage_class))
             try:
-                key.set_contents_from_filename(source_path.name, {'Content-Type': 'application/octet-stream', 
-                                              'x-amz-storage-class': 'REDUCED_REDUNDANCY' if globals.s3_use_rrs else 'STANDARD'})
+                key.set_contents_from_filename(source_path.name, {'Content-Type': 'application/octet-stream',
+                                                                  'x-amz-storage-class': storage_class})
                 key.close()
                 self.resetConnection()
                 return

=== modified file 'duplicity/commandline.py'
--- duplicity/commandline.py	2010-08-26 14:55:22 +0000
+++ duplicity/commandline.py	2010-10-13 07:44:44 +0000
@@ -315,11 +315,16 @@
     # likely that you are able to restore data under problematic
     # circumstances. the default should absolutely always be False unless
     # you know what you are doing.
+<<<<<<< TREE
     parser.add_option("--ignore-errors", action="callback", 
+=======
+    parser.add_option("--ignore-errors", action="callback",
+                      dest="ignore_errors",
+>>>>>>> MERGE-SOURCE
                       callback=lambda o, s, v, p: (log.Warn(
                           _("Running in 'ignore errors' mode due to %s; please "
                             "re-consider if this was not intended") % s),
-                          setattr(p.values, o.dest, True)))
+                          setattr(p.values, "ignore errors", True)))
 
     # Whether to use the full email address as the user name when
     # logging into an imap server. If false just the user name
@@ -371,7 +376,12 @@
     parser.add_option("--num-retries", type="int", metavar=_("number"))
 
     # Whether the old filename format is in effect.
+<<<<<<< TREE
     parser.add_option("--old-filenames", action="callback", 
+=======
+    parser.add_option("--old-filenames", action="callback",
+                      dest="old_filenames",
+>>>>>>> MERGE-SOURCE
                       callback=lambda o, s, v, p: (setattr(p.values, o.dest, True),
                                                    old_fn_deprecation(s)))
 
@@ -397,6 +407,10 @@
     # that are otherwise not expressable in a valid hostname.
     parser.add_option("--s3-use-new-style", action="store_true")
 
+    # Whether to use plain HTTP (without SSL) to send data to S3
+    # See <https://bugs.launchpad.net/duplicity/+bug/433970>.
+    parser.add_option("--s3-unencrypted-connection", action="store_true")
+
     # scp command to use
     # TRANSL: noun
     parser.add_option("--scp-command", metavar=_("command"))
@@ -406,7 +420,12 @@
     parser.add_option("--sftp-command", metavar=_("command"))
 
     # If set, use short (< 30 char) filenames for all the remote files.
+<<<<<<< TREE
     parser.add_option("--short-filenames", action="callback", 
+=======
+    parser.add_option("--short-filenames", action="callback",
+                      dest="short_filenames",
+>>>>>>> MERGE-SOURCE
                       callback=lambda o, s, v, p: (setattr(p.values, o.dest, True),
                                                    old_fn_deprecation(s)))
 

=== modified file 'duplicity/globals.py'
--- duplicity/globals.py	2010-08-26 14:55:22 +0000
+++ duplicity/globals.py	2010-10-13 07:44:44 +0000
@@ -151,6 +151,10 @@
 # support european for now).
 s3_european_buckets = False
 
+# Whether to use plain HTTP (without SSL) to send data to S3
+# See <https://bugs.launchpad.net/duplicity/+bug/433970>.
+s3_unencrypted_connection = False
+
 # Whether to use S3 Reduced Redudancy Storage
 s3_use_rrs = False
 

=== modified file 'po/duplicity.pot'
--- po/duplicity.pot	2010-08-26 14:55:22 +0000
+++ po/duplicity.pot	2010-10-13 07:44:44 +0000
@@ -8,7 +8,11 @@
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: Kenneth Loafman <kenneth@xxxxxxxxxxx>\n"
+<<<<<<< TREE
 "POT-Creation-Date: 2010-08-26 09:41-0500\n"
+=======
+"POT-Creation-Date: 2010-09-19 11:18-0500\n"
+>>>>>>> MERGE-SOURCE
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@xxxxxx>\n"
@@ -17,211 +21,375 @@
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
 
+<<<<<<< TREE
 #: ../duplicity-bin:193
+=======
+#: ../duplicity-bin:191
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid ""
 "Unable to locate last file %s and block %d in backup set.\n"
 "Attempting restart on the next file %s."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:199
+=======
+#: ../duplicity-bin:197
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid ""
 "Unable to locate last file %s and block %d in backup set.\n"
 "There are no more files to be backed up."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:462
+=======
+#: ../duplicity-bin:443
+>>>>>>> MERGE-SOURCE
 msgid ""
 "Fatal Error: Unable to start incremental backup.  Old signatures not found "
 "and incremental specified"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:466
+=======
+#: ../duplicity-bin:447
+>>>>>>> MERGE-SOURCE
 msgid "No signatures found, switching to full backup."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:480
+=======
+#: ../duplicity-bin:461
+>>>>>>> MERGE-SOURCE
 msgid "Backup Statistics"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:560
+=======
+#: ../duplicity-bin:541
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "%s not found in archive, no files restored."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:564
+=======
+#: ../duplicity-bin:545
+>>>>>>> MERGE-SOURCE
 msgid "No files found in archive - nothing restored."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:597
+=======
+#: ../duplicity-bin:578
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "Processed volume %d of %d"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:637
+=======
+#: ../duplicity-bin:618
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "Invalid data - %s hash mismatch:"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:638
+=======
+#: ../duplicity-bin:619
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "Calculated hash: %s"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:639
+=======
+#: ../duplicity-bin:620
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "Manifest hash: %s"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:656
+=======
+#: ../duplicity-bin:637
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "Volume was signed by key %s, not %s"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:686
+=======
+#: ../duplicity-bin:667
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "Verify complete: %s, %s."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:687
+=======
+#: ../duplicity-bin:668
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "%d file compared"
 msgid_plural "%d files compared"
 msgstr[0] ""
 msgstr[1] ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:689
+=======
+#: ../duplicity-bin:670
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "%d difference found"
 msgid_plural "%d differences found"
 msgstr[0] ""
 msgstr[1] ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:708
+=======
+#: ../duplicity-bin:689
+>>>>>>> MERGE-SOURCE
 msgid "No extraneous files found, nothing deleted in cleanup."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:713
+=======
+#: ../duplicity-bin:694
+>>>>>>> MERGE-SOURCE
 msgid "Deleting this file from backend:"
 msgid_plural "Deleting these files from backend:"
 msgstr[0] ""
 msgstr[1] ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:722
+=======
+#: ../duplicity-bin:703
+>>>>>>> MERGE-SOURCE
 msgid "Found the following file to delete:"
 msgid_plural "Found the following files to delete:"
 msgstr[0] ""
 msgstr[1] ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:726
+=======
+#: ../duplicity-bin:707
+>>>>>>> MERGE-SOURCE
 msgid "Run duplicity again with the --force option to actually delete."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:765
+=======
+#: ../duplicity-bin:746
+>>>>>>> MERGE-SOURCE
 msgid "There are backup set(s) at time(s):"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:767
+=======
+#: ../duplicity-bin:748
+>>>>>>> MERGE-SOURCE
 msgid "Which can't be deleted because newer sets depend on them."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:771
+=======
+#: ../duplicity-bin:752
+>>>>>>> MERGE-SOURCE
 msgid ""
 "Current active backup chain is older than specified time.  However, it will "
 "not be deleted.  To remove all your backups, manually purge the repository."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:777
+=======
+#: ../duplicity-bin:758
+>>>>>>> MERGE-SOURCE
 msgid "No old backup sets found, nothing deleted."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:780
+=======
+#: ../duplicity-bin:761
+>>>>>>> MERGE-SOURCE
 msgid "Deleting backup set at time:"
 msgid_plural "Deleting backup sets at times:"
 msgstr[0] ""
 msgstr[1] ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:797
+=======
+#: ../duplicity-bin:778
+>>>>>>> MERGE-SOURCE
 msgid "Found old backup set at the following time:"
 msgid_plural "Found old backup sets at the following times:"
 msgstr[0] ""
 msgstr[1] ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:801
+=======
+#: ../duplicity-bin:782
+>>>>>>> MERGE-SOURCE
 msgid "Rerun command with --force option to actually delete."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:888
+=======
+#: ../duplicity-bin:865
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "Deleting local %s (not authoritative at backend)."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:913 ../duplicity/dup_temp.py:239
+=======
+#: ../duplicity-bin:890 ../duplicity/dup_temp.py:239
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "Failed to read %s: %s"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:924
+=======
+#: ../duplicity-bin:901
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "Copying %s to local cache."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:965
+=======
+#: ../duplicity-bin:942
+>>>>>>> MERGE-SOURCE
 msgid "Local and Remote metadata are synchronized, no sync needed."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:970
+=======
+#: ../duplicity-bin:947
+>>>>>>> MERGE-SOURCE
 msgid "Synchronizing remote metadata to local cache..."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:979
+=======
+#: ../duplicity-bin:956
+>>>>>>> MERGE-SOURCE
 msgid "Sync would copy the following from remote to local:"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:982
+=======
+#: ../duplicity-bin:959
+>>>>>>> MERGE-SOURCE
 msgid "Sync would remove the following spurious local files:"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:1025
+=======
+#: ../duplicity-bin:1002
+>>>>>>> MERGE-SOURCE
 msgid "Unable to get free space on temp."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:1033
+=======
+#: ../duplicity-bin:1010
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "Temp space has %d available, backup needs approx %d."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:1036
+=======
+#: ../duplicity-bin:1013
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "Temp has %d available, backup will use approx %d."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:1044
+=======
+#: ../duplicity-bin:1021
+>>>>>>> MERGE-SOURCE
 msgid "Unable to get max open files."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:1048
+=======
+#: ../duplicity-bin:1025
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid ""
 "Max open files of %s is too low, should be >= 1024.\n"
 "Use 'ulimit -n 1024' or higher to correct.\n"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:1094
+=======
+#: ../duplicity-bin:1071
+>>>>>>> MERGE-SOURCE
 msgid ""
 "RESTART: The first volume failed to upload before termination.\n"
 "         Restart is impossible...starting backup from beginning."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:1100
+=======
+#: ../duplicity-bin:1077
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid ""
 "RESTART: Volumes %d to %d failed to upload before termination.\n"
 "         Restarting backup at volume %d."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:1108
+=======
+#: ../duplicity-bin:1085
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid ""
 "RESTART: Impossible backup state: manifest has %d vols, remote has %d vols.\n"
@@ -230,39 +398,71 @@
 "         backup then restart the backup from the beginning."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:1189
+=======
+#: ../duplicity-bin:1166
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "Last %s backup left a partial set, restarting."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:1193
+=======
+#: ../duplicity-bin:1170
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "Cleaning up previous partial %s backup set, restarting."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:1204
+=======
+#: ../duplicity-bin:1181
+>>>>>>> MERGE-SOURCE
 msgid "Last full backup date:"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:1206
+=======
+#: ../duplicity-bin:1183
+>>>>>>> MERGE-SOURCE
 msgid "Last full backup date: none"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:1208
+=======
+#: ../duplicity-bin:1185
+>>>>>>> MERGE-SOURCE
 msgid "Last full backup is too old, forcing full backup"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:1282
+=======
+#: ../duplicity-bin:1259
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "GPG error detail: %s"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:1291
+=======
+#: ../duplicity-bin:1268
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "User error detail: %s"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity-bin:1300
+=======
+#: ../duplicity-bin:1277
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "Backend error detail: %s"
 msgstr ""
@@ -329,6 +529,7 @@
 msgstr[0] ""
 msgstr[1] ""
 
+<<<<<<< TREE
 #: ../duplicity/backend.py:415 ../duplicity/backend.py:432
 #, python-format
 msgid "Reading results of '%s'"
@@ -342,6 +543,14 @@
 msgstr ""
 
 #: ../duplicity/collections.py:203
+=======
+#: ../duplicity/backend.py:415 ../duplicity/backend.py:432
+#, python-format
+msgid "Reading results of '%s'"
+msgstr ""
+
+#: ../duplicity/collections.py:181
+>>>>>>> MERGE-SOURCE
 msgid "Fatal Error: No manifests found for most recent backup"
 msgstr ""
 
@@ -559,7 +768,11 @@
 "starting at time %s."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity/commandline.py:70
+=======
+#: ../duplicity/commandline.py:67
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid ""
 "Warning: Option %s is pending deprecation and will be removed in a future "
@@ -567,27 +780,46 @@
 "Use of default filenames is strongly suggested."
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity/commandline.py:185
+=======
+#: ../duplicity/commandline.py:182
+>>>>>>> MERGE-SOURCE
 msgid "Unable to load gio module"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity/commandline.py:207
+=======
+#: ../duplicity/commandline.py:204
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid "Error opening file %s"
 msgstr ""
 
 #. Used in usage help to represent a Unix-style path name. Example:
 #. --archive-dir <path>
+<<<<<<< TREE
 #: ../duplicity/commandline.py:228 ../duplicity/commandline.py:236
 #: ../duplicity/commandline.py:296 ../duplicity/commandline.py:426
 #: ../duplicity/commandline.py:641
+=======
+#: ../duplicity/commandline.py:225 ../duplicity/commandline.py:233
+#: ../duplicity/commandline.py:293 ../duplicity/commandline.py:426
+#: ../duplicity/commandline.py:641
+>>>>>>> MERGE-SOURCE
 msgid "path"
 msgstr ""
 
 #. Used in usage help to represent an ID for a GnuPG key. Example:
 #. --encrypt-key <gpg_key_id>
+<<<<<<< TREE
 #: ../duplicity/commandline.py:248 ../duplicity/commandline.py:415
 #: ../duplicity/commandline.py:614
+=======
+#: ../duplicity/commandline.py:245 ../duplicity/commandline.py:415
+#: ../duplicity/commandline.py:614
+>>>>>>> MERGE-SOURCE
 msgid "gpg-key-id"
 msgstr ""
 
@@ -595,42 +827,72 @@
 #. matching one or more files, as described in the documentation.
 #. Example:
 #. --exclude <shell_pattern>
+<<<<<<< TREE
 #: ../duplicity/commandline.py:256 ../duplicity/commandline.py:335
 #: ../duplicity/commandline.py:664
+=======
+#: ../duplicity/commandline.py:253 ../duplicity/commandline.py:333
+#: ../duplicity/commandline.py:664
+>>>>>>> MERGE-SOURCE
 msgid "shell_pattern"
 msgstr ""
 
 #. Used in usage help to represent the name of a file. Example:
 #. --log-file <filename>
+<<<<<<< TREE
 #: ../duplicity/commandline.py:262 ../duplicity/commandline.py:269
 #: ../duplicity/commandline.py:274 ../duplicity/commandline.py:337
 #: ../duplicity/commandline.py:339 ../duplicity/commandline.py:350
 #: ../duplicity/commandline.py:610
+=======
+#: ../duplicity/commandline.py:259 ../duplicity/commandline.py:266
+#: ../duplicity/commandline.py:271 ../duplicity/commandline.py:335
+#: ../duplicity/commandline.py:337 ../duplicity/commandline.py:348
+#: ../duplicity/commandline.py:610
+>>>>>>> MERGE-SOURCE
 msgid "filename"
 msgstr ""
 
 #. Used in usage help to represent a regular expression (regexp).
+<<<<<<< TREE
 #: ../duplicity/commandline.py:281 ../duplicity/commandline.py:341
+=======
+#: ../duplicity/commandline.py:278 ../duplicity/commandline.py:339
+>>>>>>> MERGE-SOURCE
 msgid "regular_expression"
 msgstr ""
 
 #. Used in usage help to represent a time spec for a previous
 #. point in time, as described in the documentation. Example:
 #. duplicity remove-older-than time [options] target_url
+<<<<<<< TREE
 #: ../duplicity/commandline.py:308 ../duplicity/commandline.py:386
 #: ../duplicity/commandline.py:696
+=======
+#: ../duplicity/commandline.py:305 ../duplicity/commandline.py:385
+#: ../duplicity/commandline.py:696
+>>>>>>> MERGE-SOURCE
 msgid "time"
 msgstr ""
 
 #. Used in usage help. (Should be consistent with the "Options:"
 #. header.) Example:
 #. duplicity [full|incremental] [options] source_dir target_url
+<<<<<<< TREE
 #: ../duplicity/commandline.py:312 ../duplicity/commandline.py:423
 #: ../duplicity/commandline.py:629
+=======
+#: ../duplicity/commandline.py:309 ../duplicity/commandline.py:423
+#: ../duplicity/commandline.py:629
+>>>>>>> MERGE-SOURCE
 msgid "options"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity/commandline.py:320
+=======
+#: ../duplicity/commandline.py:318
+>>>>>>> MERGE-SOURCE
 #, python-format
 msgid ""
 "Running in 'ignore errors' mode due to %s; please re-consider if this was "
@@ -638,30 +900,52 @@
 msgstr ""
 
 #. Used in usage help to represent an imap mailbox
+<<<<<<< TREE
 #: ../duplicity/commandline.py:333
+=======
+#: ../duplicity/commandline.py:331
+>>>>>>> MERGE-SOURCE
 msgid "imap_mailbox"
 msgstr ""
 
+<<<<<<< TREE
 #: ../duplicity/commandline.py:344
+=======
+#: ../duplicity/commandline.py:342
+>>>>>>> MERGE-SOURCE
 msgid "file_descriptor"
 msgstr ""
 
 #. Used in usage help (noun)
+<<<<<<< TREE
 #: ../duplicity/commandline.py:355
+=======
+#: ../duplicity/commandline.py:353
+>>>>>>> MERGE-SOURCE
 msgid "backup name"
 msgstr ""
 
 #. Used in usage help to represent a desired number of
 #. something. Example:
 #. --num-retries <number>
+<<<<<<< TREE
 #: ../duplicity/commandline.py:371 ../duplicity/commandline.py:456
 #: ../duplicity/commandline.py:624
+=======
+#: ../duplicity/commandline.py:369 ../duplicity/commandline.py:456
+#: ../duplicity/commandline.py:624
+>>>>>>> MERGE-SOURCE
 msgid "number"
 msgstr ""
 
 #. noun
+<<<<<<< TREE
 #: ../duplicity/commandline.py:402 ../duplicity/commandline.py:406
 #: ../duplicity/commandline.py:595
+=======
+#: ../duplicity/commandline.py:401 ../duplicity/commandline.py:405
+#: ../duplicity/commandline.py:595
+>>>>>>> MERGE-SOURCE
 msgid "command"
 msgstr ""
 


Follow ups