We seem to be successfully cleaning unneeded DifferenceEntry's
This commit is contained in:
parent
76c0b0d7df
commit
856d8a99b9
128
backup-diff.py
128
backup-diff.py
@ -32,12 +32,17 @@ class BackupDiff:
|
|||||||
self.__backup_path_items = None
|
self.__backup_path_items = None
|
||||||
|
|
||||||
self.__difference_entries = None
|
self.__difference_entries = None
|
||||||
|
self.__do_clean_difference_entries = True
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
self.consume_arguments()
|
self.consume_arguments()
|
||||||
self.calculate_comparison_items()
|
self.calculate_comparison_items()
|
||||||
self.calculate_difference_entries()
|
self.calculate_difference_entries()
|
||||||
|
|
||||||
|
if self.__do_clean_difference_entries:
|
||||||
|
self.clean_difference_entries()
|
||||||
|
|
||||||
self.print_report()
|
self.print_report()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -72,6 +77,9 @@ class BackupDiff:
|
|||||||
i, one_path = self.consume_argument_companion(i)
|
i, one_path = self.consume_argument_companion(i)
|
||||||
self.__backup_path = os.path.abspath(one_path)
|
self.__backup_path = os.path.abspath(one_path)
|
||||||
self.log("Found backup destination path argument:", self.__backup_path)
|
self.log("Found backup destination path argument:", self.__backup_path)
|
||||||
|
|
||||||
|
elif arg == "--no-clean":
|
||||||
|
self.__do_clean_difference_entries = False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def consume_argument_companion(arg_index):
|
def consume_argument_companion(arg_index):
|
||||||
@ -156,6 +164,84 @@ class BackupDiff:
|
|||||||
|
|
||||||
self.__difference_entries = entries
|
self.__difference_entries = entries
|
||||||
|
|
||||||
|
def clean_difference_entries(self, entries: list=None):
|
||||||
|
|
||||||
|
if entries is None:
|
||||||
|
entries = self.__difference_entries
|
||||||
|
|
||||||
|
# Build a temp list of all known difference entries
|
||||||
|
temp_entries = []
|
||||||
|
for entry in entries:
|
||||||
|
temp_entries.append(entry)
|
||||||
|
# print("Temp entries count:", len(temp_entries))
|
||||||
|
|
||||||
|
# Loop through entries, attempting to clean for one at a time,
|
||||||
|
# until no cleaning has been done
|
||||||
|
while True:
|
||||||
|
|
||||||
|
most_shallow_entry = None
|
||||||
|
|
||||||
|
# Locate the most shallow entry
|
||||||
|
for entry in temp_entries:
|
||||||
|
|
||||||
|
if entry.get_is_missing_from_source() or entry.get_is_missing_from_backup():
|
||||||
|
|
||||||
|
# print("Found entry of type 'missing'")
|
||||||
|
# print(entry)
|
||||||
|
|
||||||
|
item = entry.get_item()
|
||||||
|
if entry.get_is_dir():
|
||||||
|
# print("Found entry dir:", item)
|
||||||
|
if most_shallow_entry is None or len(item) < len(most_shallow_entry.get_item()):
|
||||||
|
most_shallow_entry = entry
|
||||||
|
# print("Found shallow entry:")
|
||||||
|
# print(entry)
|
||||||
|
|
||||||
|
# Finish if we haven't found anything
|
||||||
|
if not most_shallow_entry:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Remove this entry from the temp list, and clean with it as root
|
||||||
|
temp_entries.remove(most_shallow_entry)
|
||||||
|
self.clean_child_difference_entries(entries, most_shallow_entry)
|
||||||
|
|
||||||
|
def clean_child_difference_entries(self, entries: list, root_entry):
|
||||||
|
|
||||||
|
if entries is None:
|
||||||
|
entries = self.__difference_entries
|
||||||
|
|
||||||
|
# print("Enter clean_child_difference_entries")
|
||||||
|
# print(root_entry)
|
||||||
|
|
||||||
|
root_entry_item = root_entry.get_item()
|
||||||
|
|
||||||
|
entries_to_delete = []
|
||||||
|
|
||||||
|
# Check every other entry as a possible child of the root
|
||||||
|
for child_entry in entries:
|
||||||
|
|
||||||
|
if child_entry != root_entry:
|
||||||
|
|
||||||
|
child_entry_item = child_entry.get_item()
|
||||||
|
|
||||||
|
# Entry must be longer than the shallow entry
|
||||||
|
if len(child_entry_item) >= len(root_entry_item):
|
||||||
|
|
||||||
|
# Entry must begin with the shallow entry (ie shallow must be a root path of deeper)
|
||||||
|
if child_entry_item.find(root_entry_item) == 0:
|
||||||
|
|
||||||
|
# We can purge the deeper entry
|
||||||
|
entries_to_delete.append(child_entry)
|
||||||
|
# print("Deleting unneeded child entry:")
|
||||||
|
# print("> Root:", root_entry_item)
|
||||||
|
# print("> Child:", child_entry_item)
|
||||||
|
|
||||||
|
# Handle entries to delete
|
||||||
|
for entry in entries_to_delete:
|
||||||
|
entries.remove(entry)
|
||||||
|
|
||||||
|
return len(entries_to_delete) > 0
|
||||||
|
|
||||||
def strip_root_dir(self, root_dir, paths: set):
|
def strip_root_dir(self, root_dir, paths: set):
|
||||||
|
|
||||||
if isinstance(paths, str):
|
if isinstance(paths, str):
|
||||||
@ -197,10 +283,12 @@ class BackupDiff:
|
|||||||
|
|
||||||
# In source but not backup
|
# In source but not backup
|
||||||
if os.path.exists(path_source) and not os.path.exists(path_backup):
|
if os.path.exists(path_source) and not os.path.exists(path_backup):
|
||||||
|
entry.set_is_dir(os.path.isdir(path_source))
|
||||||
entry.set_is_missing_from_backup()
|
entry.set_is_missing_from_backup()
|
||||||
|
|
||||||
# In backup but not source
|
# In backup but not source
|
||||||
elif os.path.exists(path_backup) and not os.path.exists(path_source):
|
elif os.path.exists(path_backup) and not os.path.exists(path_source):
|
||||||
|
entry.set_is_dir(os.path.isdir(path_backup))
|
||||||
entry.set_is_missing_from_source()
|
entry.set_is_missing_from_source()
|
||||||
|
|
||||||
# Type mismatch
|
# Type mismatch
|
||||||
@ -222,6 +310,8 @@ class BackupDiff:
|
|||||||
path_source_size = os.path.getsize(path_source)
|
path_source_size = os.path.getsize(path_source)
|
||||||
path_backup_size = os.path.getsize(path_backup)
|
path_backup_size = os.path.getsize(path_backup)
|
||||||
|
|
||||||
|
entry.set_is_dir(os.path.isdir(path_source))
|
||||||
|
|
||||||
# Different file sizes
|
# Different file sizes
|
||||||
if os.path.isfile(path_source) \
|
if os.path.isfile(path_source) \
|
||||||
and os.path.isfile(path_backup) \
|
and os.path.isfile(path_backup) \
|
||||||
@ -312,7 +402,7 @@ class BackupDiff:
|
|||||||
if hooded:
|
if hooded:
|
||||||
print("*" * len(title))
|
print("*" * len(title))
|
||||||
print(title)
|
print(title)
|
||||||
|
|
||||||
def print_report(self):
|
def print_report(self):
|
||||||
|
|
||||||
report = self.generate_report()
|
report = self.generate_report()
|
||||||
@ -328,14 +418,23 @@ class BackupDiff:
|
|||||||
print("Source:", self.__source_path)
|
print("Source:", self.__source_path)
|
||||||
print("Backup:", self.__backup_path)
|
print("Backup:", self.__backup_path)
|
||||||
|
|
||||||
#
|
# Print each non-empty report section
|
||||||
found_anything = False
|
found_anything = False
|
||||||
for section_key in section_order:
|
for section_key in section_order:
|
||||||
if len(report[section_key]["entries"]):
|
if len(report[section_key]["entries"]):
|
||||||
found_anything = True
|
found_anything = True
|
||||||
self.print_report_heading(report[section_key]["label"])
|
self.print_report_heading(report[section_key]["label"])
|
||||||
for entry in report[section_key]["entries"]:
|
for entry in report[section_key]["entries"]:
|
||||||
print(entry.get_item())
|
|
||||||
|
if entry.get_is_dir():
|
||||||
|
prefix = "Directory: "
|
||||||
|
elif entry.get_is_file():
|
||||||
|
prefix = "File: "
|
||||||
|
else:
|
||||||
|
prefix = ""
|
||||||
|
|
||||||
|
print(prefix + entry.get_item())
|
||||||
|
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
if not found_anything:
|
if not found_anything:
|
||||||
@ -348,6 +447,8 @@ class DifferenceEntry:
|
|||||||
def __init__(self, item):
|
def __init__(self, item):
|
||||||
|
|
||||||
self.__item = None
|
self.__item = None
|
||||||
|
self.__item_is_file = None
|
||||||
|
self.__item_is_dir = None
|
||||||
self.__type = None
|
self.__type = None
|
||||||
self.__message = None
|
self.__message = None
|
||||||
|
|
||||||
@ -380,6 +481,27 @@ class DifferenceEntry:
|
|||||||
|
|
||||||
return self.__item
|
return self.__item
|
||||||
|
|
||||||
|
def set_is_dir(self, is_dir: bool=True):
|
||||||
|
|
||||||
|
if is_dir:
|
||||||
|
self.__item_is_dir = True
|
||||||
|
self.__item_is_file = False
|
||||||
|
else:
|
||||||
|
self.__item_is_dir = False
|
||||||
|
self.__item_is_file = True
|
||||||
|
|
||||||
|
def get_is_dir(self):
|
||||||
|
|
||||||
|
return self.__item_is_dir
|
||||||
|
|
||||||
|
def set_is_file(self, is_file: bool=True):
|
||||||
|
|
||||||
|
self.set_is_dir( not is_file)
|
||||||
|
|
||||||
|
def get_is_file(self):
|
||||||
|
|
||||||
|
return self.__item_is_file
|
||||||
|
|
||||||
def set_is_type_mismatch(self, message):
|
def set_is_type_mismatch(self, message):
|
||||||
|
|
||||||
self.__type = self.CONST_TYPE_TYPE_MISMATCH
|
self.__type = self.CONST_TYPE_TYPE_MISMATCH
|
||||||
|
Loading…
Reference in New Issue
Block a user