Merge lp:~mterry/duplicity/list-old-chains-0.6 into lp:duplicity/0.6

Proposed by Michael Terry
Status: Merged
Merged at revision: not available
Proposed branch: lp:~mterry/duplicity/list-old-chains-0.6
Merge into: lp:duplicity/0.6
Diff against target: 1408 lines
7 files modified
duplicity-bin (+5/-8)
duplicity.1 (+8/-0)
duplicity/collections.py (+56/-44)
duplicity/commandline.py (+4/-0)
duplicity/globals.py (+3/-0)
duplicity/log.py (+1/-0)
po/duplicity.pot (+184/-187)
To merge this branch: bzr merge lp:~mterry/duplicity/list-old-chains-0.6
Reviewer Review Type Date Requested Status
duplicity-team Pending
Review via email: mp+13870@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Michael Terry (mterry) wrote :

Here's the list-old-chains work I've mentioned in the mailing list.

It does several things:
A) Don't delete signature files on old backup chains when doing normal backup work or cleanup

B) Add an --extra-clean option to the cleanup command that will delete those old signatures to save space

C) Support using those old signatures, if available, when using the list-current-files command and a time argument

D) Warn if a time is requested, but we don't have a signature for that time period (either because the time requested doesn't have a backup chain at all or if the signatures are missing for it)

I also have a branch for 0.7, merge request coming soon.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'duplicity-bin'
2--- duplicity-bin 2009-10-09 13:53:36 +0000
3+++ duplicity-bin 2009-10-23 20:40:23 +0000
4@@ -425,7 +425,7 @@
5 man_outfp.to_remote()
6 man_outfp.to_final()
7
8- col_stats.set_values(sig_chain_warning=None).cleanup_signatures()
9+ col_stats.set_values(sig_chain_warning=None)
10
11 print_statistics(diffdir.stats, bytes_written)
12
13@@ -509,11 +509,8 @@
14 @rtype: void
15 @return: void
16 """
17- sig_chain = check_sig_chain(col_stats)
18- if not sig_chain:
19- log.FatalError(_("No signature data found, unable to list files."),
20- log.ErrorCode.no_sigs)
21- time = globals.restore_time # if None, will use latest
22+ time = globals.restore_time or dup_time.curtime
23+ sig_chain = col_stats.get_signature_chain_at_time(time)
24 path_iter = diffdir.get_combined_path_iter(sig_chain.get_fileobjs(time))
25 for path in path_iter:
26 if path.difftype != "deleted":
27@@ -685,7 +682,7 @@
28 @rtype: void
29 @return: void
30 """
31- ext_local, ext_remote = col_stats.get_extraneous()
32+ ext_local, ext_remote = col_stats.get_extraneous(globals.extra_clean)
33 extraneous = ext_local + ext_remote
34 if not extraneous:
35 log.Warn(_("No extraneous files found, nothing deleted in cleanup."))
36@@ -770,7 +767,7 @@
37 setlist.reverse() # save oldest for last
38 for set in setlist:
39 set.delete()
40- col_stats.set_values(sig_chain_warning=None).cleanup_signatures()
41+ col_stats.set_values(sig_chain_warning=None)
42 else:
43 log.Notice(gettext.ngettext("Found old backup set at the following time:",
44 "Found old backup sets at the following times:",
45
46=== modified file 'duplicity.1'
47--- duplicity.1 2009-07-21 20:46:04 +0000
48+++ duplicity.1 2009-10-23 20:40:23 +0000
49@@ -342,6 +342,14 @@
50 section for more information.
51
52 .TP
53+.B --extra-clean
54+When cleaning up, be more aggressive about saving space. For example, this
55+may delete signature files for old backup chains.
56+See the
57+.B cleanup
58+argument for more information.
59+
60+.TP
61 .BI "--file-to-restore " path
62 This option may be given in restore mode, causing only
63 .I path
64
65=== modified file 'duplicity/collections.py'
66--- duplicity/collections.py 2009-09-04 17:07:57 +0000
67+++ duplicity/collections.py 2009-10-23 20:40:23 +0000
68@@ -562,7 +562,7 @@
69 # These should be sorted by end_time
70 self.all_backup_chains = None
71 self.other_backup_chains = None
72- self.other_sig_chains = None
73+ self.all_sig_chains = None
74
75 # Other misc paths and sets which shouldn't be there
76 self.local_orphaned_sig_names = []
77@@ -581,6 +581,7 @@
78 "archive-dir %s" % (self.archive_dir,)]
79
80 for i in range(len(self.other_backup_chains)):
81+ # A bit of a misnomer. Chain might have a sig.
82 l.append("chain-no-sig %d" % (i,))
83 l += self.other_backup_chains[i].to_log_info(' ')
84
85@@ -604,18 +605,18 @@
86 _("Archive dir: %s") % (self.archive_dir.name,)]
87
88 l.append("\n" +
89- gettext.ngettext("Found %d backup chain without signatures.",
90- "Found %d backup chains without signatures.",
91+ gettext.ngettext("Found %d secondary backup chain.",
92+ "Found %d secondary backup chains.",
93 len(self.other_backup_chains))
94 % len(self.other_backup_chains))
95 for i in range(len(self.other_backup_chains)):
96- l.append(_("Signature-less chain %d of %d:") %
97+ l.append(_("Secondary chain %d of %d:") %
98 (i+1, len(self.other_backup_chains)))
99 l.append(str(self.other_backup_chains[i]))
100 l.append("")
101
102 if self.matched_chain_pair:
103- l.append("\n" + _("Found a complete backup chain with matching "
104+ l.append("\n" + _("Found primary backup chain with matching "
105 "signature chain:"))
106 l.append(str(self.matched_chain_pair[1]))
107 else:
108@@ -696,12 +697,12 @@
109 latest backup chain, use the local sig chain (it does not need
110 to be downloaded).
111 """
112- self.other_sig_chains = sig_chains
113+ sig_chains = sig_chains and self.get_sorted_chains(sig_chains)
114+ self.all_sig_chains = sig_chains
115 self.other_backup_chains = backup_chains[:]
116 self.matched_chain_pair = None
117 if sig_chains and backup_chains:
118 latest_backup_chain = backup_chains[-1]
119- sig_chains = self.get_sorted_chains(sig_chains)
120 for i in range(len(sig_chains)-1, -1, -1):
121 if sig_chains[i].end_time == latest_backup_chain.end_time:
122 pass
123@@ -720,19 +721,9 @@
124 if self.matched_chain_pair == None:
125 self.matched_chain_pair = (sig_chains[i], latest_backup_chain)
126
127- del sig_chains[i]
128 break
129
130 if self.matched_chain_pair:
131- # if we have local and remote sig chains, remove both from the other_sig_chains list
132- matched_sig_chain = self.matched_chain_pair[0]
133- if len(self.other_sig_chains) > 1:
134- for sig_chain in self.other_sig_chains[1:]:
135- if (sig_chain.islocal() != matched_sig_chain.islocal() and
136- sig_chain.start_time == matched_sig_chain.start_time and
137- sig_chain.end_time == matched_sig_chain.end_time):
138- self.other_sig_chains.remove(sig_chain)
139- self.other_sig_chains.remove(matched_sig_chain)
140 self.other_backup_chains.remove(self.matched_chain_pair[1])
141
142 def warn(self, sig_chain_warning):
143@@ -759,18 +750,9 @@
144 + "\n" + "\n".join(self.remote_orphaned_sig_names),
145 log.WarningCode.orphaned_sig)
146
147- if self.other_sig_chains and sig_chain_warning:
148- if self.matched_chain_pair:
149- log.Warn(gettext.ngettext("Warning, found an unnecessary "
150- "signature chain",
151- "Warning, found unnecessary "
152- "signature chains",
153- len(self.other_sig_chains))
154- + "\n" + "\n".join([f.fullsig for f in self.other_sig_chains]),
155- log.WarningCode.unnecessary_sig)
156- else:
157- log.Warn(_("Warning, found signatures but no corresponding "
158- "backup files"), log.WarningCode.unmatched_sig)
159+ if self.all_sig_chains and sig_chain_warning and not self.matched_chain_pair:
160+ log.Warn(_("Warning, found signatures but no corresponding "
161+ "backup files"), log.WarningCode.unmatched_sig)
162
163 if self.incomplete_backup_sets:
164 log.Warn(_("Warning, found incomplete backup sets, probably left "
165@@ -965,13 +947,34 @@
166 else:
167 return self.all_backup_chains[0] # no chains are old enough
168
169- def cleanup_signatures(self):
170- """
171- Delete unnecessary older signatures
172- """
173- map(SignatureChain.delete, self.other_sig_chains)
174-
175- def get_extraneous(self):
176+ def get_signature_chain_at_time(self, time):
177+ """
178+ Return signature chain covering specified time
179+
180+ Tries to find the signature chain covering the given time. If
181+ there is none, return the earliest chain before, and failing
182+ that, the earliest chain.
183+ """
184+ if not self.all_sig_chains:
185+ raise CollectionsError("No signature chains found")
186+
187+ covering_chains = filter(lambda c: c.start_time <= time <= c.end_time,
188+ self.all_sig_chains)
189+ if covering_chains:
190+ return covering_chains[-1] # prefer local if multiple sig chains
191+
192+ old_chains = filter(lambda c: c.end_time < time,
193+ self.all_sig_chains)
194+ if old_chains:
195+ return old_chains[-1]
196+ else:
197+ # no chains are old enough, give oldest and warn user
198+ oldest = self.all_sig_chains[0]
199+ if time < oldest.start_time:
200+ log.Warn(_("No signature chain for the requested time. Using oldest available chain, starting at time %s.") % dup_time.timetopretty(oldest.start_time), log.WarningCode.no_sig_for_time, dup_time.timetostring(oldest.start_time))
201+ return oldest
202+
203+ def get_extraneous(self, extra_clean):
204 """
205 Return list of the names of extraneous duplicity files
206
207@@ -982,14 +985,23 @@
208 assert self.values_set
209 local_filenames = []
210 remote_filenames = []
211- ext_containers = (self.other_sig_chains, self.orphaned_backup_sets,
212- self.incomplete_backup_sets)
213- for set_or_chain_list in ext_containers:
214- for set_or_chain in set_or_chain_list:
215- if set_or_chain.backend:
216- remote_filenames.extend(set_or_chain.get_filenames())
217- else:
218- local_filenames.extend(set_or_chain.get_filenames())
219+ ext_containers = self.orphaned_backup_sets + self.incomplete_backup_sets
220+ if extra_clean:
221+ old_sig_chains = self.all_sig_chains[:]
222+ if self.matched_chain_pair:
223+ matched_sig_chain = self.matched_chain_pair[0]
224+ for sig_chain in self.all_sig_chains:
225+ print sig_chain.start_time, matched_sig_chain.start_time,
226+ print sig_chain.end_time, matched_sig_chain.end_time
227+ if (sig_chain.start_time == matched_sig_chain.start_time and
228+ sig_chain.end_time == matched_sig_chain.end_time):
229+ old_sig_chains.remove(sig_chain)
230+ ext_containers += old_sig_chains
231+ for set_or_chain in ext_containers:
232+ if set_or_chain.backend:
233+ remote_filenames.extend(set_or_chain.get_filenames())
234+ else:
235+ local_filenames.extend(set_or_chain.get_filenames())
236 local_filenames += self.local_orphaned_sig_names
237 remote_filenames += self.remote_orphaned_sig_names
238 return local_filenames, remote_filenames
239
240=== modified file 'duplicity/commandline.py'
241--- duplicity/commandline.py 2009-09-01 00:46:32 +0000
242+++ duplicity/commandline.py 2009-10-23 20:40:23 +0000
243@@ -76,6 +76,7 @@
244 "exclude-filelist-stdin",
245 "exclude-other-filesystems",
246 "exclude-regexp=",
247+ "extra-clean",
248 "fail-on-volume=",
249 "file-to-restore=",
250 "force",
251@@ -268,6 +269,8 @@
252 elif opt == "--exclude-filelist-stdin":
253 select_opts.append(("--exclude-filelist", "standard input"))
254 select_files.append(sys.stdin)
255+ elif opt == "--extra-clean":
256+ globals.extra_clean = True
257 elif opt == "--fail-on-volume":
258 globals.fail_on_volume = get_int(arg, opt)
259 elif opt == "--full-if-older-than":
260@@ -632,6 +635,7 @@
261 --exclude-globbing-filelist <%(filename)s>
262 --exclude-other-filesystems
263 --exclude-regexp <regexp>
264+ --extra-clean
265 --file-to-restore <%(path)s>
266 --full-if-older-than <%(time)s>
267 --force
268
269=== modified file 'duplicity/globals.py'
270--- duplicity/globals.py 2009-08-12 17:43:42 +0000
271+++ duplicity/globals.py 2009-10-23 20:40:23 +0000
272@@ -178,3 +178,6 @@
273 # circumstances. the default should absolutely always be True unless
274 # you know what you are doing.
275 ignore_errors = False
276+
277+# If we should be particularly aggressive when cleaning up
278+extra_clean = False
279
280=== modified file 'duplicity/log.py'
281--- duplicity/log.py 2009-09-20 18:42:22 +0000
282+++ duplicity/log.py 2009-10-23 20:40:23 +0000
283@@ -127,6 +127,7 @@
284 cannot_iterate = 8
285 cannot_stat = 9
286 cannot_read = 10
287+ no_sig_for_time = 11
288
289 def Warn(s, code=WarningCode.generic, extra=None):
290 """Shortcut used for warning messages (verbosity 2)"""
291
292=== modified file 'po/duplicity.pot'
293--- po/duplicity.pot 2009-09-15 11:36:53 +0000
294+++ po/duplicity.pot 2009-10-23 20:40:23 +0000
295@@ -8,7 +8,7 @@
296 msgstr ""
297 "Project-Id-Version: PACKAGE VERSION\n"
298 "Report-Msgid-Bugs-To: Kenneth Loafman <kenneth@loafman.com>\n"
299-"POT-Creation-Date: 2009-09-15 06:36-0500\n"
300+"POT-Creation-Date: 2009-10-23 16:33-0400\n"
301 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
302 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
303 "Language-Team: LANGUAGE <LL@li.org>\n"
304@@ -17,215 +17,211 @@
305 "Content-Transfer-Encoding: 8bit\n"
306 "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
307
308-#: ../duplicity-bin:191
309+#: ../duplicity-bin:190
310 #, python-format
311 msgid ""
312 "Unable to locate last file %s and block %d in backup set.\n"
313 "Attempting restart on the next file %s."
314 msgstr ""
315
316-#: ../duplicity-bin:197
317+#: ../duplicity-bin:196
318 #, python-format
319 msgid ""
320 "Unable to locate last file %s and block %d in backup set.\n"
321 "There are no more files to be backed up."
322 msgstr ""
323
324-#: ../duplicity-bin:443
325+#: ../duplicity-bin:442
326 msgid ""
327 "Fatal Error: Unable to start incremental backup. Old signatures not found "
328 "and incremental specified"
329 msgstr ""
330
331-#: ../duplicity-bin:447
332+#: ../duplicity-bin:446
333 msgid "No signatures found, switching to full backup."
334 msgstr ""
335
336-#: ../duplicity-bin:461
337+#: ../duplicity-bin:460
338 msgid "Backup Statistics"
339 msgstr ""
340
341-#: ../duplicity-bin:515
342-msgid "No signature data found, unable to list files."
343+#: ../duplicity-bin:540
344+#, python-format
345+msgid "%s not found in archive, no files restored."
346 msgstr ""
347
348 #: ../duplicity-bin:544
349-#, python-format
350-msgid "%s not found in archive, no files restored."
351-msgstr ""
352-
353-#: ../duplicity-bin:548
354 msgid "No files found in archive - nothing restored."
355 msgstr ""
356
357-#: ../duplicity-bin:581
358+#: ../duplicity-bin:577
359 #, python-format
360 msgid "Processed volume %d of %d"
361 msgstr ""
362
363-#: ../duplicity-bin:621
364+#: ../duplicity-bin:617
365 #, python-format
366 msgid "Invalid data - %s hash mismatch:"
367 msgstr ""
368
369-#: ../duplicity-bin:622
370+#: ../duplicity-bin:618
371 #, python-format
372 msgid "Calculated hash: %s"
373 msgstr ""
374
375-#: ../duplicity-bin:623
376+#: ../duplicity-bin:619
377 #, python-format
378 msgid "Manifest hash: %s"
379 msgstr ""
380
381-#: ../duplicity-bin:640
382+#: ../duplicity-bin:636
383 #, python-format
384 msgid "Volume was signed by key %s, not %s"
385 msgstr ""
386
387-#: ../duplicity-bin:670
388+#: ../duplicity-bin:666
389 #, python-format
390 msgid "Verify complete: %s, %s."
391 msgstr ""
392
393-#: ../duplicity-bin:671
394+#: ../duplicity-bin:667
395 #, python-format
396 msgid "%d file compared"
397 msgid_plural "%d files compared"
398 msgstr[0] ""
399 msgstr[1] ""
400
401-#: ../duplicity-bin:673
402+#: ../duplicity-bin:669
403 #, python-format
404 msgid "%d difference found"
405 msgid_plural "%d differences found"
406 msgstr[0] ""
407 msgstr[1] ""
408
409-#: ../duplicity-bin:692
410+#: ../duplicity-bin:688
411 msgid "No extraneous files found, nothing deleted in cleanup."
412 msgstr ""
413
414-#: ../duplicity-bin:697
415+#: ../duplicity-bin:693
416 msgid "Deleting this file from backend:"
417 msgid_plural "Deleting these files from backend:"
418 msgstr[0] ""
419 msgstr[1] ""
420
421-#: ../duplicity-bin:706
422+#: ../duplicity-bin:702
423 msgid "Found the following file to delete:"
424 msgid_plural "Found the following files to delete:"
425 msgstr[0] ""
426 msgstr[1] ""
427
428-#: ../duplicity-bin:710
429+#: ../duplicity-bin:706
430 msgid "Run duplicity again with the --force option to actually delete."
431 msgstr ""
432
433-#: ../duplicity-bin:749
434+#: ../duplicity-bin:745
435 msgid "There are backup set(s) at time(s):"
436 msgstr ""
437
438+#: ../duplicity-bin:747
439+msgid "Which can't be deleted because newer sets depend on them."
440+msgstr ""
441+
442 #: ../duplicity-bin:751
443-msgid "Which can't be deleted because newer sets depend on them."
444-msgstr ""
445-
446-#: ../duplicity-bin:755
447 msgid ""
448 "Current active backup chain is older than specified time. However, it will "
449 "not be deleted. To remove all your backups, manually purge the repository."
450 msgstr ""
451
452-#: ../duplicity-bin:761
453+#: ../duplicity-bin:757
454 msgid "No old backup sets found, nothing deleted."
455 msgstr ""
456
457-#: ../duplicity-bin:764
458+#: ../duplicity-bin:760
459 msgid "Deleting backup set at time:"
460 msgid_plural "Deleting backup sets at times:"
461 msgstr[0] ""
462 msgstr[1] ""
463
464-#: ../duplicity-bin:776
465+#: ../duplicity-bin:772
466 msgid "Found old backup set at the following time:"
467 msgid_plural "Found old backup sets at the following times:"
468 msgstr[0] ""
469 msgstr[1] ""
470
471-#: ../duplicity-bin:780
472+#: ../duplicity-bin:776
473 msgid "Rerun command with --force option to actually delete."
474 msgstr ""
475
476-#: ../duplicity-bin:863
477+#: ../duplicity-bin:859
478 #, python-format
479 msgid "Deleting local %s (not authoritative at backend)."
480 msgstr ""
481
482-#: ../duplicity-bin:888 ../duplicity/dup_temp.py:239
483+#: ../duplicity-bin:884 ../duplicity/dup_temp.py:239
484 #, python-format
485 msgid "Failed to read %s: %s"
486 msgstr ""
487
488-#: ../duplicity-bin:899
489+#: ../duplicity-bin:895
490 #, python-format
491 msgid "Copying %s to local cache."
492 msgstr ""
493
494-#: ../duplicity-bin:943
495+#: ../duplicity-bin:936
496 msgid "Local and Remote metadata are synchronized, no sync needed."
497 msgstr ""
498
499-#: ../duplicity-bin:948
500+#: ../duplicity-bin:941
501 msgid "Synchronizing remote metadata to local cache..."
502 msgstr ""
503
504-#: ../duplicity-bin:955
505+#: ../duplicity-bin:950
506 msgid "Sync would copy the following from remote to local:"
507 msgstr ""
508
509-#: ../duplicity-bin:958
510+#: ../duplicity-bin:953
511 msgid "Sync would remove the following spurious local files:"
512 msgstr ""
513
514-#: ../duplicity-bin:1001
515+#: ../duplicity-bin:996
516 msgid "Unable to get free space on temp."
517 msgstr ""
518
519-#: ../duplicity-bin:1009
520+#: ../duplicity-bin:1004
521 #, python-format
522 msgid "Temp space has %d available, backup needs approx %d."
523 msgstr ""
524
525-#: ../duplicity-bin:1012
526+#: ../duplicity-bin:1007
527 #, python-format
528 msgid "Temp has %d available, backup will use approx %d."
529 msgstr ""
530
531-#: ../duplicity-bin:1020
532+#: ../duplicity-bin:1015
533 msgid "Unable to get max open files."
534 msgstr ""
535
536-#: ../duplicity-bin:1024
537+#: ../duplicity-bin:1019
538 #, python-format
539 msgid ""
540 "Max open files of %s is too low, should be >= 1024.\n"
541 "Use 'ulimit -n 1024' or higher to correct.\n"
542 msgstr ""
543
544-#: ../duplicity-bin:1070
545+#: ../duplicity-bin:1065
546 msgid ""
547 "RESTART: The first volume failed to upload before termination.\n"
548 " Restart is impossible...starting backup from beginning."
549 msgstr ""
550
551-#: ../duplicity-bin:1076
552+#: ../duplicity-bin:1071
553 #, python-format
554 msgid ""
555 "RESTART: Volumes %d to %d failed to upload before termination.\n"
556 " Restarting backup at volume %d."
557 msgstr ""
558
559-#: ../duplicity-bin:1084
560+#: ../duplicity-bin:1079
561 #, python-format
562 msgid ""
563 "RESTART: Impossible backup state: manifest has %d vols, remote has %d vols.\n"
564@@ -234,39 +230,39 @@
565 " backup then restart the backup from the beginning."
566 msgstr ""
567
568-#: ../duplicity-bin:1162
569+#: ../duplicity-bin:1157
570 #, python-format
571 msgid "Last %s backup left a partial set, restarting."
572 msgstr ""
573
574-#: ../duplicity-bin:1166
575+#: ../duplicity-bin:1161
576 #, python-format
577 msgid "Cleaning up previous partial %s backup set, restarting."
578 msgstr ""
579
580-#: ../duplicity-bin:1177
581+#: ../duplicity-bin:1172
582 msgid "Last full backup date:"
583 msgstr ""
584
585-#: ../duplicity-bin:1179
586+#: ../duplicity-bin:1174
587 msgid "Last full backup date: none"
588 msgstr ""
589
590-#: ../duplicity-bin:1181
591+#: ../duplicity-bin:1176
592 msgid "Last full backup is too old, forcing full backup"
593 msgstr ""
594
595-#: ../duplicity-bin:1255
596+#: ../duplicity-bin:1250
597 #, python-format
598 msgid "GPG error detail: %s"
599 msgstr ""
600
601-#: ../duplicity-bin:1264
602+#: ../duplicity-bin:1259
603 #, python-format
604 msgid "User error detail: %s"
605 msgstr ""
606
607-#: ../duplicity-bin:1273
608+#: ../duplicity-bin:1268
609 #, python-format
610 msgid "Backend error detail: %s"
611 msgstr ""
612@@ -412,48 +408,48 @@
613 msgid "remote"
614 msgstr ""
615
616-#: ../duplicity/collections.py:600
617+#: ../duplicity/collections.py:601
618 msgid "Collection Status"
619 msgstr ""
620
621-#: ../duplicity/collections.py:602
622+#: ../duplicity/collections.py:603
623 #, python-format
624 msgid "Connecting with backend: %s"
625 msgstr ""
626
627-#: ../duplicity/collections.py:604
628+#: ../duplicity/collections.py:605
629 #, python-format
630 msgid "Archive dir: %s"
631 msgstr ""
632
633-#: ../duplicity/collections.py:607
634+#: ../duplicity/collections.py:608
635 #, python-format
636-msgid "Found %d backup chain without signatures."
637-msgid_plural "Found %d backup chains without signatures."
638+msgid "Found %d secondary backup chain."
639+msgid_plural "Found %d secondary backup chains."
640 msgstr[0] ""
641 msgstr[1] ""
642
643-#: ../duplicity/collections.py:612
644+#: ../duplicity/collections.py:613
645 #, python-format
646-msgid "Signature-less chain %d of %d:"
647-msgstr ""
648-
649-#: ../duplicity/collections.py:618
650-msgid "Found a complete backup chain with matching signature chain:"
651-msgstr ""
652-
653-#: ../duplicity/collections.py:622
654+msgid "Secondary chain %d of %d:"
655+msgstr ""
656+
657+#: ../duplicity/collections.py:619
658+msgid "Found primary backup chain with matching signature chain:"
659+msgstr ""
660+
661+#: ../duplicity/collections.py:623
662 msgid "No backup chains with active signatures found"
663 msgstr ""
664
665-#: ../duplicity/collections.py:625
666+#: ../duplicity/collections.py:626
667 #, python-format
668 msgid "Also found %d backup set not part of any chain,"
669 msgid_plural "Also found %d backup sets not part of any chain,"
670 msgstr[0] ""
671 msgstr[1] ""
672
673-#: ../duplicity/collections.py:629
674+#: ../duplicity/collections.py:630
675 #, python-format
676 msgid "and %d incomplete backup set."
677 msgid_plural "and %d incomplete backup sets."
678@@ -461,101 +457,102 @@
679 msgstr[1] ""
680
681 #. "cleanup" is a hard-coded command, so do not translate it
682-#: ../duplicity/collections.py:634
683+#: ../duplicity/collections.py:635
684 msgid "These may be deleted by running duplicity with the \"cleanup\" command."
685 msgstr ""
686
687-#: ../duplicity/collections.py:637
688+#: ../duplicity/collections.py:638
689 msgid "No orphaned or incomplete backup sets found."
690 msgstr ""
691
692-#: ../duplicity/collections.py:653
693+#: ../duplicity/collections.py:654
694 #, python-format
695 msgid "%d file exists on backend"
696 msgid_plural "%d files exist on backend"
697 msgstr[0] ""
698 msgstr[1] ""
699
700-#: ../duplicity/collections.py:660
701+#: ../duplicity/collections.py:661
702 #, python-format
703 msgid "%d file exists in cache"
704 msgid_plural "%d files exist in cache"
705 msgstr[0] ""
706 msgstr[1] ""
707
708-#: ../duplicity/collections.py:712
709+#: ../duplicity/collections.py:713
710 msgid "Warning, discarding last backup set, because of missing signature file."
711 msgstr ""
712
713-#: ../duplicity/collections.py:745
714+#: ../duplicity/collections.py:736
715 msgid "Warning, found the following local orphaned signature file:"
716 msgid_plural "Warning, found the following local orphaned signature files:"
717 msgstr[0] ""
718 msgstr[1] ""
719
720-#: ../duplicity/collections.py:754
721+#: ../duplicity/collections.py:745
722 msgid "Warning, found the following remote orphaned signature file:"
723 msgid_plural "Warning, found the following remote orphaned signature files:"
724 msgstr[0] ""
725 msgstr[1] ""
726
727-#: ../duplicity/collections.py:764
728-msgid "Warning, found an unnecessary signature chain"
729-msgid_plural "Warning, found unnecessary signature chains"
730-msgstr[0] ""
731-msgstr[1] ""
732-
733-#: ../duplicity/collections.py:772
734+#: ../duplicity/collections.py:754
735 msgid "Warning, found signatures but no corresponding backup files"
736 msgstr ""
737
738-#: ../duplicity/collections.py:776
739+#: ../duplicity/collections.py:758
740 msgid ""
741 "Warning, found incomplete backup sets, probably left from aborted session"
742 msgstr ""
743
744-#: ../duplicity/collections.py:780
745+#: ../duplicity/collections.py:762
746 msgid "Warning, found the following orphaned backup file:"
747 msgid_plural "Warning, found the following orphaned backup files:"
748 msgstr[0] ""
749 msgstr[1] ""
750
751-#: ../duplicity/collections.py:798
752+#: ../duplicity/collections.py:780
753 #, python-format
754 msgid "Extracting backup chains from list of files: %s"
755 msgstr ""
756
757-#: ../duplicity/collections.py:808
758+#: ../duplicity/collections.py:790
759 #, python-format
760 msgid "File %s is part of known set"
761 msgstr ""
762
763-#: ../duplicity/collections.py:811
764+#: ../duplicity/collections.py:793
765 #, python-format
766 msgid "File %s is not part of a known set; creating new set"
767 msgstr ""
768
769-#: ../duplicity/collections.py:816
770+#: ../duplicity/collections.py:798
771 #, python-format
772 msgid "Ignoring file (rejected by backup set) '%s'"
773 msgstr ""
774
775-#: ../duplicity/collections.py:829
776+#: ../duplicity/collections.py:811
777 #, python-format
778 msgid "Found backup chain %s"
779 msgstr ""
780
781-#: ../duplicity/collections.py:834
782+#: ../duplicity/collections.py:816
783 #, python-format
784 msgid "Added set %s to pre-existing chain %s"
785 msgstr ""
786
787-#: ../duplicity/collections.py:838
788+#: ../duplicity/collections.py:820
789 #, python-format
790 msgid "Found orphaned set %s"
791 msgstr ""
792
793-#: ../duplicity/commandline.py:125
794+#: ../duplicity/collections.py:974
795+#, python-format
796+msgid ""
797+"No signature chain for the requested time. Using oldest available chain, "
798+"starting at time %s."
799+msgstr ""
800+
801+#: ../duplicity/commandline.py:126
802 #, python-format
803 msgid ""
804 "Warning: Option %s is pending deprecation and will be removed in a future "
805@@ -563,164 +560,164 @@
806 "Use of default filenames is strongly suggested."
807 msgstr ""
808
809-#: ../duplicity/commandline.py:176
810+#: ../duplicity/commandline.py:177
811 #, python-format
812 msgid "Error opening file %s"
813 msgstr ""
814
815-#: ../duplicity/commandline.py:288
816+#: ../duplicity/commandline.py:291
817 msgid "Unable to load gio module"
818 msgstr ""
819
820-#: ../duplicity/commandline.py:383
821+#: ../duplicity/commandline.py:386
822 msgid ""
823 "running in 'ignore errors' mode due to --ignore-errors; please re-consider "
824 "if this was not intended"
825 msgstr ""
826
827-#: ../duplicity/commandline.py:423
828+#: ../duplicity/commandline.py:426
829 #, python-format
830 msgid "Using archive dir: %s"
831 msgstr ""
832
833-#: ../duplicity/commandline.py:424
834+#: ../duplicity/commandline.py:427
835 #, python-format
836 msgid "Using backup name: %s"
837 msgstr ""
838
839-#: ../duplicity/commandline.py:431
840+#: ../duplicity/commandline.py:434
841 #, python-format
842 msgid "Command line error: %s"
843 msgstr ""
844
845-#: ../duplicity/commandline.py:432
846+#: ../duplicity/commandline.py:435
847 msgid "Enter 'duplicity --help' for help screen."
848 msgstr ""
849
850 #. Used in usage help to represent a Unix-style path name. Example:
851 #. rsync://user[:password]@other_host[:port]//absolute_path
852-#: ../duplicity/commandline.py:445
853+#: ../duplicity/commandline.py:448
854 msgid "absolute_path"
855 msgstr ""
856
857 #. Used in usage help. Example:
858 #. tahoe://alias/some_dir
859-#: ../duplicity/commandline.py:449
860+#: ../duplicity/commandline.py:452
861 msgid "alias"
862 msgstr ""
863
864 #. Used in usage help (noun)
865-#: ../duplicity/commandline.py:452
866+#: ../duplicity/commandline.py:455
867 msgid "backup name"
868 msgstr ""
869
870 #. Used in help to represent a "bucket name" for Amazon Web
871 #. Services' Simple Storage Service (S3). Example:
872 #. s3://other.host/bucket_name[/prefix]
873-#: ../duplicity/commandline.py:457
874+#: ../duplicity/commandline.py:460
875 msgid "bucket_name"
876 msgstr ""
877
878 #. abbreviation for "character" (noun)
879-#: ../duplicity/commandline.py:460
880+#: ../duplicity/commandline.py:463
881 msgid "char"
882 msgstr ""
883
884 #. noun
885-#: ../duplicity/commandline.py:463
886+#: ../duplicity/commandline.py:466
887 msgid "command"
888 msgstr ""
889
890 #. Used in usage help to represent the name of a container in
891 #. Amazon Web Services' Cloudfront. Example:
892 #. cf+http://container_name
893-#: ../duplicity/commandline.py:468
894+#: ../duplicity/commandline.py:471
895 msgid "container_name"
896 msgstr ""
897
898 #. noun
899-#: ../duplicity/commandline.py:471
900+#: ../duplicity/commandline.py:474
901 msgid "count"
902 msgstr ""
903
904 #. Used in usage help to represent the name of a file directory
905-#: ../duplicity/commandline.py:474
906+#: ../duplicity/commandline.py:477
907 msgid "directory"
908 msgstr ""
909
910 #. Used in usage help to represent the name of a file. Example:
911 #. --log-file <filename>
912-#: ../duplicity/commandline.py:478
913+#: ../duplicity/commandline.py:481
914 msgid "filename"
915 msgstr ""
916
917 #. Used in usage help to represent an ID for a GnuPG key. Example:
918 #. --encrypt-key <gpg_key_id>
919-#: ../duplicity/commandline.py:482
920+#: ../duplicity/commandline.py:485
921 msgid "gpg-key-id"
922 msgstr ""
923
924 #. Used in usage help, e.g. to represent the name of a code
925 #. module. Example:
926 #. rsync://user[:password]@other.host[:port]::/module/some_dir
927-#: ../duplicity/commandline.py:487
928+#: ../duplicity/commandline.py:490
929 msgid "module"
930 msgstr ""
931
932 #. Used in usage help to represent a desired number of
933 #. something. Example:
934 #. --num-retries <number>
935-#: ../duplicity/commandline.py:492
936+#: ../duplicity/commandline.py:495
937 msgid "number"
938 msgstr ""
939
940 #. Used in usage help. (Should be consistent with the "Options:"
941 #. header.) Example:
942 #. duplicity [full|incremental] [options] source_dir target_url
943-#: ../duplicity/commandline.py:497
944+#: ../duplicity/commandline.py:500
945 msgid "options"
946 msgstr ""
947
948 #. Used in usage help to represent an internet hostname. Example:
949 #. ftp://user[:password]@other.host[:port]/some_dir
950-#: ../duplicity/commandline.py:501
951+#: ../duplicity/commandline.py:504
952 msgid "other.host"
953 msgstr ""
954
955 #. Used in usage help. Example:
956 #. ftp://user[:password]@other.host[:port]/some_dir
957-#: ../duplicity/commandline.py:505
958+#: ../duplicity/commandline.py:508
959 msgid "password"
960 msgstr ""
961
962 #. Used in usage help to represent a Unix-style path name. Example:
963 #. --archive-dir <path>
964-#: ../duplicity/commandline.py:509
965+#: ../duplicity/commandline.py:512
966 msgid "path"
967 msgstr ""
968
969 #. Used in usage help to represent a TCP port number. Example:
970 #. ftp://user[:password]@other.host[:port]/some_dir
971-#: ../duplicity/commandline.py:513
972+#: ../duplicity/commandline.py:516
973 msgid "port"
974 msgstr ""
975
976 #. Used in usage help. This represents a string to be used as a
977 #. prefix to names for backup files created by Duplicity. Example:
978 #. s3://other.host/bucket_name[/prefix]
979-#: ../duplicity/commandline.py:518
980+#: ../duplicity/commandline.py:521
981 msgid "prefix"
982 msgstr ""
983
984 #. Used in usage help to represent a Unix-style path name. Example:
985 #. rsync://user[:password]@other.host[:port]/relative_path
986-#: ../duplicity/commandline.py:522
987+#: ../duplicity/commandline.py:525
988 msgid "relative_path"
989 msgstr ""
990
991 #. Used in usage help. Example:
992 #. --timeout <seconds>
993-#: ../duplicity/commandline.py:526
994+#: ../duplicity/commandline.py:529
995 msgid "seconds"
996 msgstr ""
997
998@@ -728,14 +725,14 @@
999 #. matching one or more files, as described in the documentation.
1000 #. Example:
1001 #. --exclude <shell_pattern>
1002-#: ../duplicity/commandline.py:532
1003+#: ../duplicity/commandline.py:535
1004 msgid "shell_pattern"
1005 msgstr ""
1006
1007 #. Used in usage help to represent the name of a single file
1008 #. directory or a Unix-style path to a directory. Example:
1009 #. file:///some_dir
1010-#: ../duplicity/commandline.py:537
1011+#: ../duplicity/commandline.py:540
1012 msgid "some_dir"
1013 msgstr ""
1014
1015@@ -743,14 +740,14 @@
1016 #. directory or a Unix-style path to a directory where files will be
1017 #. coming FROM. Example:
1018 #. duplicity [full|incremental] [options] source_dir target_url
1019-#: ../duplicity/commandline.py:543
1020+#: ../duplicity/commandline.py:546
1021 msgid "source_dir"
1022 msgstr ""
1023
1024 #. Used in usage help to represent a URL files will be coming
1025 #. FROM. Example:
1026 #. duplicity [restore] [options] source_url target_dir
1027-#: ../duplicity/commandline.py:548
1028+#: ../duplicity/commandline.py:551
1029 msgid "source_url"
1030 msgstr ""
1031
1032@@ -758,60 +755,60 @@
1033 #. directory or a Unix-style path to a directory. where files will be
1034 #. going TO. Example:
1035 #. duplicity [restore] [options] source_url target_dir
1036-#: ../duplicity/commandline.py:554
1037+#: ../duplicity/commandline.py:557
1038 msgid "target_dir"
1039 msgstr ""
1040
1041 #. Used in usage help to represent a URL files will be going TO.
1042 #. Example:
1043 #. duplicity [full|incremental] [options] source_dir target_url
1044-#: ../duplicity/commandline.py:559
1045+#: ../duplicity/commandline.py:562
1046 msgid "target_url"
1047 msgstr ""
1048
1049 #. Used in usage help to represent a time spec for a previous
1050 #. point in time, as described in the documentation. Example:
1051 #. duplicity remove-older-than time [options] target_url
1052-#: ../duplicity/commandline.py:564
1053+#: ../duplicity/commandline.py:567
1054 msgid "time"
1055 msgstr ""
1056
1057 #. Used in usage help to represent a user name (i.e. login).
1058 #. Example:
1059 #. ftp://user[:password]@other.host[:port]/some_dir
1060-#: ../duplicity/commandline.py:569
1061+#: ../duplicity/commandline.py:572
1062 msgid "user"
1063 msgstr ""
1064
1065-#: ../duplicity/commandline.py:571
1066+#: ../duplicity/commandline.py:574
1067 #, python-format
1068 msgid "duplicity version %s running on %s."
1069 msgstr ""
1070
1071 #. Header in usage help
1072-#: ../duplicity/commandline.py:575
1073+#: ../duplicity/commandline.py:578
1074 msgid "Usage:"
1075 msgstr ""
1076
1077 #. Header in usage help
1078-#: ../duplicity/commandline.py:588
1079+#: ../duplicity/commandline.py:591
1080 msgid "Backends and their URL formats:"
1081 msgstr ""
1082
1083 #. Header in usage help
1084-#: ../duplicity/commandline.py:608
1085+#: ../duplicity/commandline.py:611
1086 msgid "Commands:"
1087 msgstr ""
1088
1089 #. Header in usage help
1090-#: ../duplicity/commandline.py:622
1091+#: ../duplicity/commandline.py:625
1092 msgid "Options:"
1093 msgstr ""
1094
1095 #. In this portion of the usage instructions, "[ewnid]" indicates which
1096 #. characters are permitted (e, w, n, i, or d); the brackets imply their own
1097 #. meaning in regex; i.e., only one of the characters is allowed in an instance.
1098-#: ../duplicity/commandline.py:676
1099+#: ../duplicity/commandline.py:680
1100 msgid ""
1101 " Verbosity must be one of: digit [0-9], character [ewnid],\n"
1102 " or word ['error', 'warning', 'notice', 'info', 'debug'].\n"
1103@@ -819,36 +816,36 @@
1104 " that verbosity level is set at 2 (Warning) or higher.\n"
1105 msgstr ""
1106
1107-#: ../duplicity/commandline.py:702
1108+#: ../duplicity/commandline.py:706
1109 #, python-format
1110 msgid "Specified archive directory '%s' does not exist, or is not a directory"
1111 msgstr ""
1112
1113-#: ../duplicity/commandline.py:711
1114+#: ../duplicity/commandline.py:715
1115 #, python-format
1116 msgid ""
1117 "Sign key should be an 8 character hex string, like 'AA0E73D2'.\n"
1118 "Received '%s' instead."
1119 msgstr ""
1120
1121-#: ../duplicity/commandline.py:769
1122+#: ../duplicity/commandline.py:773
1123 #, python-format
1124 msgid ""
1125 "Restore destination directory %s already exists.\n"
1126 "Will not overwrite."
1127 msgstr ""
1128
1129-#: ../duplicity/commandline.py:774
1130+#: ../duplicity/commandline.py:778
1131 #, python-format
1132 msgid "Verify directory %s does not exist"
1133 msgstr ""
1134
1135-#: ../duplicity/commandline.py:780
1136+#: ../duplicity/commandline.py:784
1137 #, python-format
1138 msgid "Backup source directory %s does not exist."
1139 msgstr ""
1140
1141-#: ../duplicity/commandline.py:855
1142+#: ../duplicity/commandline.py:859
1143 #, python-format
1144 msgid ""
1145 "Bad URL '%s'.\n"
1146@@ -856,36 +853,36 @@
1147 "\"file:///usr/local\". See the man page for more information."
1148 msgstr ""
1149
1150-#: ../duplicity/commandline.py:880
1151+#: ../duplicity/commandline.py:884
1152 msgid "Main action: "
1153 msgstr ""
1154
1155-#: ../duplicity/diffdir.py:105
1156+#: ../duplicity/diffdir.py:104
1157 #, python-format
1158 msgid "Error %s getting delta for %s"
1159 msgstr ""
1160
1161-#: ../duplicity/diffdir.py:119
1162+#: ../duplicity/diffdir.py:118
1163 #, python-format
1164 msgid "Getting delta of %s and %s"
1165 msgstr ""
1166
1167-#: ../duplicity/diffdir.py:164
1168+#: ../duplicity/diffdir.py:163
1169 #, python-format
1170 msgid "A %s"
1171 msgstr ""
1172
1173-#: ../duplicity/diffdir.py:171
1174+#: ../duplicity/diffdir.py:170
1175 #, python-format
1176 msgid "M %s"
1177 msgstr ""
1178
1179-#: ../duplicity/diffdir.py:193
1180+#: ../duplicity/diffdir.py:192
1181 #, python-format
1182 msgid "Comparing %s and %s"
1183 msgstr ""
1184
1185-#: ../duplicity/diffdir.py:199
1186+#: ../duplicity/diffdir.py:198
1187 #, python-format
1188 msgid "D %s"
1189 msgstr ""
1190@@ -913,22 +910,22 @@
1191 "the day)."
1192 msgstr ""
1193
1194-#: ../duplicity/lazy.py:326
1195+#: ../duplicity/lazy.py:325
1196 #, python-format
1197 msgid "Warning: oldindex %s >= newindex %s"
1198 msgstr ""
1199
1200-#: ../duplicity/lazy.py:401
1201+#: ../duplicity/lazy.py:400
1202 #, python-format
1203 msgid "Error '%s' processing %s"
1204 msgstr ""
1205
1206-#: ../duplicity/lazy.py:409
1207+#: ../duplicity/lazy.py:408
1208 #, python-format
1209 msgid "Skipping %s because of previous error"
1210 msgstr ""
1211
1212-#: ../duplicity/manifest.py:86
1213+#: ../duplicity/manifest.py:87
1214 #, python-format
1215 msgid ""
1216 "Fatal Error: Backup source host has changed.\n"
1217@@ -936,7 +933,7 @@
1218 "Previous hostname: %s"
1219 msgstr ""
1220
1221-#: ../duplicity/manifest.py:91
1222+#: ../duplicity/manifest.py:94
1223 #, python-format
1224 msgid ""
1225 "Fatal Error: Backup source directory has changed.\n"
1226@@ -944,7 +941,7 @@
1227 "Previous directory: %s"
1228 msgstr ""
1229
1230-#: ../duplicity/manifest.py:98
1231+#: ../duplicity/manifest.py:103
1232 msgid ""
1233 "Aborting because you may have accidentally tried to backup two different "
1234 "data sets to the same remote location, or using the same archive directory. "
1235@@ -952,39 +949,39 @@
1236 "seeing this message"
1237 msgstr ""
1238
1239-#: ../duplicity/manifest.py:193
1240+#: ../duplicity/manifest.py:198
1241 msgid "Manifests not equal because different volume numbers"
1242 msgstr ""
1243
1244-#: ../duplicity/manifest.py:198
1245+#: ../duplicity/manifest.py:203
1246 msgid "Manifests not equal because volume lists differ"
1247 msgstr ""
1248
1249-#: ../duplicity/manifest.py:203
1250+#: ../duplicity/manifest.py:208
1251 msgid "Manifests not equal because hosts or directories differ"
1252 msgstr ""
1253
1254-#: ../duplicity/manifest.py:350
1255+#: ../duplicity/manifest.py:355
1256 msgid "Warning, found extra Volume identifier"
1257 msgstr ""
1258
1259-#: ../duplicity/manifest.py:376
1260+#: ../duplicity/manifest.py:381
1261 msgid "Other is not VolumeInfo"
1262 msgstr ""
1263
1264-#: ../duplicity/manifest.py:379
1265+#: ../duplicity/manifest.py:384
1266 msgid "Volume numbers don't match"
1267 msgstr ""
1268
1269-#: ../duplicity/manifest.py:382
1270+#: ../duplicity/manifest.py:387
1271 msgid "start_indicies don't match"
1272 msgstr ""
1273
1274-#: ../duplicity/manifest.py:385
1275+#: ../duplicity/manifest.py:390
1276 msgid "end_index don't match"
1277 msgstr ""
1278
1279-#: ../duplicity/manifest.py:392
1280+#: ../duplicity/manifest.py:397
1281 msgid "Hashes don't match"
1282 msgstr ""
1283
1284@@ -1000,12 +997,12 @@
1285 "Renaming %s to %s"
1286 msgstr ""
1287
1288-#: ../duplicity/patchdir.py:72 ../duplicity/patchdir.py:77
1289+#: ../duplicity/patchdir.py:71 ../duplicity/patchdir.py:76
1290 #, python-format
1291 msgid "Patching %s"
1292 msgstr ""
1293
1294-#: ../duplicity/patchdir.py:565
1295+#: ../duplicity/patchdir.py:564
1296 #, python-format
1297 msgid "Writing %s of type %s"
1298 msgstr ""
1299@@ -1084,33 +1081,33 @@
1300 msgid "Error listing directory %s"
1301 msgstr ""
1302
1303-#: ../duplicity/selection.py:120
1304+#: ../duplicity/selection.py:118
1305 #, python-format
1306 msgid "Skipping socket %s"
1307 msgstr ""
1308
1309-#: ../duplicity/selection.py:124
1310+#: ../duplicity/selection.py:122
1311 #, python-format
1312 msgid "Error initializing file %s"
1313 msgstr ""
1314
1315-#: ../duplicity/selection.py:128 ../duplicity/selection.py:149
1316+#: ../duplicity/selection.py:126 ../duplicity/selection.py:147
1317 #, python-format
1318 msgid "Error accessing possibly locked file %s"
1319 msgstr ""
1320
1321-#: ../duplicity/selection.py:164
1322+#: ../duplicity/selection.py:162
1323 #, python-format
1324 msgid "Warning: base %s doesn't exist, continuing"
1325 msgstr ""
1326
1327-#: ../duplicity/selection.py:167 ../duplicity/selection.py:185
1328-#: ../duplicity/selection.py:188
1329+#: ../duplicity/selection.py:165 ../duplicity/selection.py:183
1330+#: ../duplicity/selection.py:186
1331 #, python-format
1332 msgid "Selecting %s"
1333 msgstr ""
1334
1335-#: ../duplicity/selection.py:269
1336+#: ../duplicity/selection.py:267
1337 #, python-format
1338 msgid ""
1339 "Fatal Error: The file specification\n"
1340@@ -1121,14 +1118,14 @@
1341 "pattern (such as '**') which matches the base directory."
1342 msgstr ""
1343
1344-#: ../duplicity/selection.py:277
1345+#: ../duplicity/selection.py:275
1346 #, python-format
1347 msgid ""
1348 "Fatal Error while processing expression\n"
1349 "%s"
1350 msgstr ""
1351
1352-#: ../duplicity/selection.py:287
1353+#: ../duplicity/selection.py:285
1354 #, python-format
1355 msgid ""
1356 "Last selection expression:\n"
1357@@ -1138,43 +1135,43 @@
1358 "probably isn't what you meant."
1359 msgstr ""
1360
1361-#: ../duplicity/selection.py:312
1362+#: ../duplicity/selection.py:310
1363 #, python-format
1364 msgid "Reading filelist %s"
1365 msgstr ""
1366
1367-#: ../duplicity/selection.py:315
1368+#: ../duplicity/selection.py:313
1369 #, python-format
1370 msgid "Sorting filelist %s"
1371 msgstr ""
1372
1373-#: ../duplicity/selection.py:342
1374+#: ../duplicity/selection.py:340
1375 #, python-format
1376 msgid ""
1377 "Warning: file specification '%s' in filelist %s\n"
1378 "doesn't start with correct prefix %s. Ignoring."
1379 msgstr ""
1380
1381-#: ../duplicity/selection.py:346
1382+#: ../duplicity/selection.py:344
1383 msgid "Future prefix errors will not be logged."
1384 msgstr ""
1385
1386-#: ../duplicity/selection.py:362
1387+#: ../duplicity/selection.py:360
1388 #, python-format
1389 msgid "Error closing filelist %s"
1390 msgstr ""
1391
1392-#: ../duplicity/selection.py:429
1393+#: ../duplicity/selection.py:427
1394 #, python-format
1395 msgid "Reading globbing filelist %s"
1396 msgstr ""
1397
1398-#: ../duplicity/selection.py:462
1399+#: ../duplicity/selection.py:460
1400 #, python-format
1401 msgid "Error compiling regular expression %s"
1402 msgstr ""
1403
1404-#: ../duplicity/selection.py:478
1405+#: ../duplicity/selection.py:476
1406 msgid ""
1407 "Warning: exclude-device-files is not the first selector.\n"
1408 "This may not be what you intended"

Subscribers

People subscribed via source and target branches

to all changes: