121
122
def check_manifests(self):
122
123
"""Make sure remote manifest is equal to local one"""
123
124
if not self.remote_manifest_name and not self.local_manifest_path:
124
log.FatalError("Fatal Error: No manifests found for most recent backup",
125
log.FatalError(_("Fatal Error: No manifests found for most recent backup"),
125
126
log.ErrorCode.no_manifests)
126
127
assert self.remote_manifest_name, "if only one, should be remote"
130
131
local_manifest = self.get_local_manifest()
131
132
if remote_manifest and self.local_manifest_path and local_manifest:
132
133
if remote_manifest != local_manifest:
133
log.FatalError("Fatal Error: Remote manifest does not match local one. Either the "
134
"remote backup set or the local archive directory has been corrupted.",
134
log.FatalError(_("Fatal Error: Remote manifest does not match "
135
"local one. Either the remote backup set or "
136
"the local archive directory has been corrupted."),
135
137
log.ErrorCode.mismatched_manifests)
136
138
if not remote_manifest:
137
139
if self.local_manifest_path:
138
140
remote_manifest = local_manifest
140
log.FatalError("Fatal Error: Neither remote nor local manifest is readable.",
142
log.FatalError(_("Fatal Error: Neither remote nor local "
143
"manifest is readable."),
141
144
log.ErrorCode.unreadable_manifests)
142
145
remote_manifest.check_dirinfo()
222
225
if (self.incset_list
223
226
and incset.start_time == self.incset_list[-1].start_time
224
227
and incset.end_time > self.incset_list[-1]):
225
log.Log("Preferring Backupset over previous one!", 8)
228
log.Log(_("Preferring Backupset over previous one!"), 8)
226
229
self.incset_list[-1] = incset
228
log.Log("Ignoring incremental Backupset (start_time: %s; needed: %s)" %
231
log.Log(_("Ignoring incremental Backupset (start_time: %s; needed: %s)") %
229
232
(dup_time.timetopretty(incset.start_time),
230
233
dup_time.timetopretty(self.end_time)), 8)
232
235
self.end_time = incset.end_time
233
log.Log("Added incremental Backupset (start_time: %s / end_time: %s)" %
236
log.Log(_("Added incremental Backupset (start_time: %s / end_time: %s)") %
234
237
(dup_time.timetopretty(incset.start_time),
235
238
dup_time.timetopretty(incset.end_time)), 8)
236
239
assert self.end_time
282
285
"""Return string representation, for testing purposes"""
283
286
set_schema = "%20s %30s %15s"
284
287
l = ["-------------------------",
285
"Chain start time: " + dup_time.timetopretty(self.start_time),
286
"Chain end time: " + dup_time.timetopretty(self.end_time),
287
"Number of contained backup sets: %d" %
288
_("Chain start time: ") + dup_time.timetopretty(self.start_time),
289
_("Chain end time: ") + dup_time.timetopretty(self.end_time),
290
_("Number of contained backup sets: %d") %
288
291
(len(self.incset_list)+1,),
289
"Total number of contained volumes: %d" %
292
_("Total number of contained volumes: %d") %
290
293
(self.get_num_volumes(),),
291
set_schema % ("Type of backup set:", "Time:", "Num volumes:")]
294
set_schema % (_("Type of backup set:"), _("Time:"), _("Num volumes:"))]
293
296
for s in self.get_all_sets():
301
type = _("Incremental")
299
302
time = s.end_time
300
303
l.append(set_schema % (type, dup_time.timetopretty(time), len(s)))
469
472
def __str__(self):
470
473
"""Return string summary of the collection"""
471
l = ["Collection Status",
474
l = [_("Collection Status"),
472
475
"-----------------",
473
"Connecting with backend: %s" %
476
_("Connecting with backend: %s") %
474
477
(self.backend.__class__.__name__,),
475
"Archive dir: %s" % (self.archive_dir,)]
478
_("Archive dir: %s") % (self.archive_dir,)]
477
l.append("\nFound %d backup chains without signatures."
481
gettext.ngettext("Found %d backup chain without signatures.",
482
"Found %d backup chains without signatures.",
483
len(self.other_backup_chains))
478
484
% len(self.other_backup_chains))
479
485
for i in range(len(self.other_backup_chains)):
480
l.append("Signature-less chain %d of %d:" %
486
l.append(_("Signature-less chain %d of %d:") %
481
487
(i+1, len(self.other_backup_chains)))
482
488
l.append(str(self.other_backup_chains[i]))
485
491
if self.matched_chain_pair:
486
l.append("\nFound a complete backup chain with matching "
492
l.append("\n" + _("Found a complete backup chain with matching "
488
494
l.append(str(self.matched_chain_pair[1]))
490
l.append("No backup chains with active signatures found")
496
l.append(_("No backup chains with active signatures found"))
492
498
if self.orphaned_backup_sets or self.incomplete_backup_sets:
493
l.append("Also found %d backup sets not part of any chain,"
499
l.append(gettext.ngettext("Also found %d backup set not part of any chain,",
500
"Also found %d backup sets not part of any chain,",
501
len(self.orphaned_backup_sets))
494
502
% (len(self.orphaned_backup_sets),))
495
l.append("and %d incomplete backup sets."
503
l.append(gettext.ngettext("and %d incomplete backup set.",
504
"and %d incomplete backup sets.",
505
len(self.incomplete_backup_sets))
496
506
% (len(self.incomplete_backup_sets),))
497
l.append("These may be deleted by running duplicity with the "
507
l.append(_("These may be deleted by running duplicity with the "
508
"--cleanup option."))
500
l.append("No orphaned or incomplete backup sets found.")
510
l.append(_("No orphaned or incomplete backup sets found."))
502
512
return "\n".join(l)
513
523
self.values_set = 1
514
524
backend_filename_list = self.backend.list()
515
log.Debug("%d files exist on backend" % (len(backend_filename_list,)))
525
log.Debug(gettext.ngettext("%d file exists on backend",
526
"%d files exist on backend",
527
len(backend_filename_list)) %
528
len(backend_filename_list))
517
530
(backup_chains, self.orphaned_backup_sets,
518
531
self.incomplete_backup_sets) = \
558
571
elif (len(latest_backup_chain.get_all_sets()) >= 2 and
559
572
sig_chains[i].end_time == latest_backup_chain.get_all_sets()[-2].end_time):
560
573
# It matches, remove the last backup set:
561
log.Warn("Warning, discarding last backup set, because of missing signature file.")
574
log.Warn(_("Warning, discarding last backup set, because "
575
"of missing signature file."))
562
576
self.incomplete_backup_sets.append(latest_backup_chain.incset_list[-1])
563
577
latest_backup_chain.incset_list = latest_backup_chain.incset_list[:-1]
587
601
"""Log various error messages if find incomplete/orphaned files"""
588
602
assert self.values_set
589
603
if self.orphaned_sig_names:
590
log.Warn("Warning, found the following orphaned signature files:\n"
591
+ "\n".join(self.orphaned_sig_names),
604
log.Warn(gettext.ngettext("Warning, found the following orphaned "
606
"Warning, found the following orphaned "
608
len(self.orphaned_sig_names))
609
+ "\n" + "\n".join(self.orphaned_sig_names),
592
610
log.WarningCode.orphaned_sig)
593
611
if self.other_sig_chains and sig_chain_warning:
594
612
if self.matched_chain_pair:
595
log.Warn("Warning, found unnecessary signature chain(s)",
613
log.Warn(gettext.ngettext("Warning, found an unnecessary "
615
"Warning, found unnecessary "
617
len(self.other_sig_chains)),
596
618
log.WarningCode.unnecessary_sig)
598
log.Warn("Warning, found signatures but no corresponding "
599
"backup files", log.WarningCode.unmatched_sig)
620
log.Warn(_("Warning, found signatures but no corresponding "
621
"backup files"), log.WarningCode.unmatched_sig)
601
623
if self.incomplete_backup_sets:
602
log.Warn("Warning, found incomplete backup sets, probably left "
603
"from aborted session", log.WarningCode.incomplete_backup)
624
log.Warn(_("Warning, found incomplete backup sets, probably left "
625
"from aborted session"), log.WarningCode.incomplete_backup)
604
626
if self.orphaned_backup_sets:
605
log.Warn("Warning, found the following orphaned backup files:\n"
606
+ "\n".join(map(lambda x: str(x),
627
log.Warn(gettext.ngettext("Warning, found the following orphaned "
629
"Warning, found the following orphaned "
631
len(self.orphaned_backup_sets))
632
+ "\n" + "\n".join(map(lambda x: str(x),
607
633
self.orphaned_backup_sets)),
608
634
log.WarningCode.orphaned_backup)
619
log.Debug("Extracting backup chains from list of files: %s" % (filename_list,))
645
log.Debug(_("Extracting backup chains from list of files: %s")
620
647
# First put filenames in set form
622
649
def add_to_sets(filename):
623
650
"""Try adding filename to existing sets, or make new one"""
625
652
if set.add_filename(filename):
626
log.Debug("File %s is part of known set" % (filename,))
653
log.Debug(_("File %s is part of known set") % (filename,))
629
log.Debug("File %s is not part of a known set; creating new set" % (filename,))
656
log.Debug(_("File %s is not part of a known set; creating new set") % (filename,))
630
657
new_set = BackupSet(self.backend)
631
658
if new_set.add_filename(filename):
632
659
sets.append(new_set)
634
log.Log("Ignoring file (rejected by backup set) '%s'" % filename, 9)
661
log.Log(_("Ignoring file (rejected by backup set) '%s'") % filename, 9)
635
662
map(add_to_sets, filename_list)
636
663
sets, incomplete_sets = self.get_sorted_sets(sets)
642
669
new_chain = BackupChain(self.backend)
643
670
new_chain.set_full(set)
644
671
chains.append(new_chain)
645
log.Debug("Found backup chain %s" % (new_chain.short_desc()))
672
log.Debug(_("Found backup chain %s") % (new_chain.short_desc()))
647
674
assert set.type == "inc"
648
675
for chain in chains:
649
676
if chain.add_inc(set):
650
log.Debug("Added set %s to pre-existing chain %s" % (set.get_timestr(),
677
log.Debug(_("Added set %s to pre-existing chain %s") % (set.get_timestr(),
651
678
chain.short_desc()))
654
log.Debug("Found orphaned set %s" % (set.get_timestr(),))
681
log.Debug(_("Found orphaned set %s") % (set.get_timestr(),))
655
682
orphaned_sets.append(set)
656
683
map(add_to_chains, sets)
657
684
return (chains, orphaned_sets, incomplete_sets)