def parse_diff_lines(diff_lines): files_with_attributes = [] nested_file_list = nested_dict() def parse_line(line): if line: line_split = line.split() else: return 0, "", "", "" if line_split[0] in {'added', 'removed', 'changed'}: change_type = line_split[0] if line_split[1] in ['directory', 'link']: size = 0 full_path = re.search(r'^\w+ \w+ +(.*)', line).group(1) else: significand = line_split[1] unit = line_split[2] size = calc_size(significand, unit) full_path = re.search(r'^\w+ +\S+ \w?B (.*)', line).group(1) else: size_change = re.search( r' *[\+-]?(\d+\.*\d*) (\w?B) +[\+-]?.+\w?B ', line) if size_change: significand = size_change.group(1) unit = size_change.group(2) size = calc_size(significand, unit) rest_of_line = line[size_change.end(0):] else: size = 0 rest_of_line = line owner_change = re.search(r' *(\[[^:]+:[^\]]+ -> [^:]+:[^\]]+\]) ', rest_of_line) if owner_change: rest_of_line = rest_of_line[owner_change.end(0):] permission_change = re.search(r' *(\[.{24}\]) ', rest_of_line) if permission_change: change_type = permission_change.group(1) rest_of_line = rest_of_line[permission_change.end(0):] else: change_type = "modified" full_path = rest_of_line.lstrip(' ') dir, name = os.path.split(full_path) # add to nested dict of folders to find nested dirs. d = get_dict_from_list(nested_file_list, dir.split('/')) if name not in d: d[name] = {} return size, change_type, name, dir for line in diff_lines: files_with_attributes.append(parse_line(line)) return (files_with_attributes, nested_file_list)
def __init__(self, fs_data, archive): super().__init__() self.setupUi(self) files_with_attributes = [] nested_file_list = nested_dict() self.selected = set() def parse_json_line(line): data = json.loads(line) size = data["size"] # python >= 3.7 # modified = datetime.fromisoformat(data["mtime"]).ctime() # python < 3.7 try: modified = datetime.strptime(data["mtime"], "%Y-%m-%dT%H:%M:%S.%f").ctime() except ValueError: modified = datetime.strptime(data["mtime"], "%Y-%m-%dT%H:%M:%S").ctime() dirpath, name = os.path.split(data["path"]) # add to nested dict of folders to find nested dirs. d = get_dict_from_list(nested_file_list, dirpath.split("/")) if name not in d: d[name] = {} return size, modified, name, dirpath for line in fs_data.split("\n"): try: files_with_attributes.append(parse_json_line(line)) except ValueError: pass model = ExtractTree(files_with_attributes, nested_file_list, self.selected) view = self.treeView view.setAlternatingRowColors(True) view.setUniformRowHeights(True) # Allows for scrolling optimizations. view.setModel(model) header = view.header() header.setStretchLastSection(False) header.setSectionResizeMode(1, QHeaderView.ResizeToContents) header.setSectionResizeMode(2, QHeaderView.ResizeToContents) header.setSectionResizeMode(0, QHeaderView.Stretch) self.archiveNameLabel.setText(f"{archive.name}, {archive.time}") self.cancelButton.clicked.connect(self.close) self.extractButton.clicked.connect(self.accept)
def __init__(self, fs_data, archive): super().__init__() self.setupUi(self) global files_with_attributes, nested_file_list, selected_files_folders # Clear global file lists files_with_attributes = [] nested_file_list = nested_dict() selected_files_folders = set() def parse_line(line): size, modified, full_path = line.split('\t') size = int(size) dir, name = os.path.split(full_path) # add to nested dict of folders to find nested dirs. d = get_dict_from_list(nested_file_list, dir.split('/')) if name not in d: d[name] = {} return size, modified, name, dir for l in fs_data.split('\n'): try: files_with_attributes.append(parse_line(l)) except ValueError: pass model = TreeModel() view = self.treeView view.setAlternatingRowColors(True) view.setUniformRowHeights(True) # Allows for scrolling optimizations. view.setModel(model) header = view.header() header.setStretchLastSection(False) header.setSectionResizeMode(1, QHeaderView.ResizeToContents) header.setSectionResizeMode(2, QHeaderView.ResizeToContents) header.setSectionResizeMode(0, QHeaderView.Stretch) self.archiveNameLabel.setText(f'{archive.name}, {archive.time}') self.cancelButton.clicked.connect(self.close) self.extractButton.clicked.connect(self.accept) self.selected = selected_files_folders
def __init__(self, fs_data, archive_newer, archive_older): super().__init__() self.setupUi(self) global files_with_attributes, nested_file_list, selected_files_folders # Clear global file lists files_with_attributes = [] nested_file_list = nested_dict() selected_files_folders = set() def parse_line(line): if line: line_splitted = line.split() else: return 0, "", "", "" if line_splitted[0] == 'added' or line_splitted[0] == 'removed': change_type = line_splitted[0] size = line_splitted[1] unit = line_splitted[2] else: change_type = "modified" size = line_splitted[0] unit = line_splitted[1] # If present remove '+' or '-' sign at the front if '+' in size or '-' in size: size = size[1:] if line_splitted[0].startswith("["): size = 0 change_type = line[:line.find(line_splitted[3])] full_path = line[line.find(line_splitted[3]):] dir, name = os.path.split(full_path) # add to nested dict of folders to find nested dirs. d = get_dict_from_list(nested_file_list, full_path.split('/')) elif line_splitted[1] not in ['directory', 'link']: if unit == 'B': size = int(size) elif unit == 'kB': size = int(float(size) * 10**3) elif unit == 'MB': size = int(float(size) * 10**6) elif unit == 'GB': size = int(float(size) * 10**9) elif unit == 'TB': size = int(float(size) * 10**12) if change_type == 'added' or change_type == 'removed': full_path = line[line.find(line_splitted[3]):] elif change_type == "modified": full_path = line[line.find(line_splitted[4]):] dir, name = os.path.split(full_path) # add to nested dict of folders to find nested dirs. d = get_dict_from_list(nested_file_list, dir.split('/')) if name not in d: d[name] = {} else: size = 0 full_path = line[line.find(line_splitted[2]):] dir, name = os.path.split(full_path) # add to nested dict of folders to find nested dirs. d = get_dict_from_list(nested_file_list, full_path.split('/')) return size, change_type, name, dir for l in fs_data.split('\n'): files_with_attributes.append(parse_line(l)) model = TreeModel() view = self.treeView view.setAlternatingRowColors(True) view.setUniformRowHeights(True) # Allows for scrolling optimizations. view.setModel(model) header = view.header() header.setStretchLastSection(False) header.setSectionResizeMode(1, QHeaderView.ResizeToContents) header.setSectionResizeMode(2, QHeaderView.ResizeToContents) header.setSectionResizeMode(0, QHeaderView.Stretch) self.archiveNameLabel_1.setText(f'{archive_newer.name}') self.archiveNameLabel_2.setText(f'{archive_older.name}') self.okButton.clicked.connect(self.accept) self.selected = selected_files_folders
def __init__(self, fs_data, archive_newer, archive_older): super().__init__() self.setupUi(self) files_with_attributes = [] nested_file_list = nested_dict() def parse_line(line): if line: line_split = line.split() else: return 0, "", "", "" if line_split[0] == 'added' or line_split[0] == 'removed': change_type = line_split[0] if line_split[1] in ['directory', 'link']: size = 0 full_path = re.search(r'^\w+ \w+ +(.*)', line).group(1) else: significand = line_split[1] unit = line_split[2] size = calc_size(significand, unit) full_path = re.search(r'^\w+ +\S+ \w?B (.*)', line).group(1) else: size_change = re.search( r' *[\+-]?(\d+\.*\d*) (\w?B) +[\+-]?.+\w?B ', line) if size_change: significand = size_change.group(1) unit = size_change.group(2) size = calc_size(significand, unit) full_path_index = size_change.end(0) else: size = 0 permission_change = re.search(r' *(\[.{24}\]) ', line) if permission_change: change_type = permission_change.group(1) full_path_index = permission_change.end(0) else: change_type = "modified" if size_change and permission_change: full_path_index = max(size_change.end(0), permission_change.end(0)) full_path = line[full_path_index:] dir, name = os.path.split(full_path) # add to nested dict of folders to find nested dirs. d = get_dict_from_list(nested_file_list, dir.split('/')) if name not in d: d[name] = {} return size, change_type, name, dir for l in fs_data.split('\n'): files_with_attributes.append(parse_line(l)) model = DiffTree(files_with_attributes, nested_file_list) view = self.treeView view.setAlternatingRowColors(True) view.setUniformRowHeights(True) # Allows for scrolling optimizations. view.setModel(model) header = view.header() header.setStretchLastSection(False) header.setSectionResizeMode(1, QHeaderView.ResizeToContents) header.setSectionResizeMode(2, QHeaderView.ResizeToContents) header.setSectionResizeMode(0, QHeaderView.Stretch) self.archiveNameLabel_1.setText(f'{archive_newer.name}') self.archiveNameLabel_2.setText(f'{archive_older.name}') self.okButton.clicked.connect(self.accept)
def parse_diff_json_lines(diffs): files_with_attributes = [] nested_file_list = nested_dict() for item in diffs: dirpath, name = os.path.split(item['path']) # add to nested dict of folders to find nested dirs. d = get_dict_from_list(nested_file_list, dirpath.split('/')) if name not in d: d[name] = {} # added link, removed link, changed link # modified (added, removed), added (size), removed (size) # added directory, removed directory # owner (old_user, new_user, old_group, new_group)) # mode (old_mode, new_mode) size = 0 change_type = None change_type_priority = 0 for change in item['changes']: # if more than one type of change has happened for this file/dir/link, then report the most important # (higher priority) if {'type': 'modified'} == change: # modified, but can't compare ids if change_type_priority < 3: change_type = 'modified' change_type_priority = 3 elif change['type'] == 'modified': # only reveal 'added' to match what happens in non-json parsing - maybe update dialog to show more info. # size = change['added'] - change['removed'] size = change['added'] if change_type_priority < 3: # non-json-lines mode only reports owner changes as 'modified' in the tree - maybe update dialog to # show more info. # change_type = '{:>9} {:>9}'.format(pretty_bytes(change['added'], precision=1, sign=True), # pretty_bytes(-change['removed'], precision=1, sign=True)) change_type = 'modified' change_type_priority = 3 elif change['type'] in [ 'added', 'removed', 'added link', 'removed link', 'changed link', 'added directory', 'removed directory' ]: size = change.get('size', 0) if change_type_priority < 2: change_type = change['type'].split()[ 0] # 'added', 'removed' or 'changed' change_type_priority = 2 elif change['type'] == 'mode': # mode change can occur along with previous changes - don't override if change_type_priority < 4: change_type = '[{} -> {}]'.format(change['old_mode'], change['new_mode']) change_type_priority = 4 elif change['type'] == 'owner': # owner change can occur along with previous changes - don't override if change_type_priority < 1: # non-json-lines mode only reports owner changes as 'modified' in the tree - matbe update dialog to # show more info. # change_type = '{}:{} -> {}:{}'.format(change['old_user'], change['old_group'], # change['new_user'], change['new_group']) change_type = 'modified' change_type_priority = 1 assert change_type # either no changes, or unrecognized change(s) files_with_attributes.append((size, change_type, name, dirpath)) return (files_with_attributes, nested_file_list)
import os import datetime from collections import namedtuple from PyQt5 import uic from PyQt5.QtCore import QAbstractItemModel, QModelIndex, Qt from PyQt5.QtWidgets import QApplication, QHeaderView from vorta.utils import get_asset, pretty_bytes, get_dict_from_list, nested_dict uifile = get_asset('UI/extractdialog.ui') ExtractDialogUI, ExtractDialogBase = uic.loadUiType(uifile) ISO_FORMAT = '%Y-%m-%dT%H:%M:%S.%f' files_with_attributes = [] nested_file_list = nested_dict() selected_files_folders = set() class ExtractDialog(ExtractDialogBase, ExtractDialogUI): def __init__(self, fs_data, archive): super().__init__() self.setupUi(self) global files_with_attributes, nested_file_list, selected_files_folders def parse_line(line): size, modified, full_path = line.split('\t') size = int(size) dir, name = os.path.split(full_path) # add to nested dict of folders to find nested dirs.