Update ddrescue-tui to use new Disk object vars

This commit is contained in:
2Shirt 2022-05-01 16:20:39 -07:00
parent 2585ed584c
commit 6642aad2c8
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C
2 changed files with 41 additions and 41 deletions

View file

@ -133,12 +133,12 @@ class BlockPair():
NOTE: source should be a wk.hw.obj.Disk() object NOTE: source should be a wk.hw.obj.Disk() object
and destination should be a pathlib.Path() object. and destination should be a pathlib.Path() object.
""" """
self.sector_size = source.details.get('phy-sec', 512) self.sector_size = source.phy_sec
self.source = source.path self.source = source.path
self.destination = destination self.destination = destination
self.map_data = {} self.map_data = {}
self.map_path = None self.map_path = None
self.size = source.details['size'] self.size = source.size
self.status = OrderedDict({ self.status = OrderedDict({
'read-skip': 'Pending', 'read-skip': 'Pending',
'read-full': 'Pending', 'read-full': 'Pending',
@ -150,9 +150,9 @@ class BlockPair():
# Set map path # Set map path
# e.g. '(Clone|Image)_Model[_p#]_Size[_Label].map' # e.g. '(Clone|Image)_Model[_p#]_Size[_Label].map'
map_name = model if model else 'None' map_name = model if model else 'None'
if source.details['bus'] == 'Image': if source.bus == 'Image':
map_name = 'Image' map_name = 'Image'
if source.details['parent']: if source.parent:
part_num = re.sub(r"^.*?(\d+)$", r"\1", source.path.name) part_num = re.sub(r"^.*?(\d+)$", r"\1", source.path.name)
map_name += f'_p{part_num}' map_name += f'_p{part_num}'
size_str = std.bytes_to_string( size_str = std.bytes_to_string(
@ -160,8 +160,8 @@ class BlockPair():
use_binary=False, use_binary=False,
) )
map_name += f'_{size_str.replace(" ", "")}' map_name += f'_{size_str.replace(" ", "")}'
if source.details.get('label', ''): if source.raw_details.get('label', ''):
map_name += f'_{source.details["label"]}' map_name += f'_{source.raw_details["label"]}'
map_name = map_name.replace(' ', '_') map_name = map_name.replace(' ', '_')
map_name = map_name.replace('/', '_') map_name = map_name.replace('/', '_')
if destination.is_dir(): if destination.is_dir():
@ -316,8 +316,8 @@ class BlockPair():
# Mark future passes as skipped if applicable # Mark future passes as skipped if applicable
if percent == 100: if percent == 100:
status_keys = list(self.status.keys()) status_keys = list(self.status.keys())
for i in status_keys[status_keys.index(pass_name)+1:]: for pass_n in status_keys[status_keys.index(pass_name)+1:]:
self.status[status_keys[i]] = 'Skipped' self.status[pass_n] = 'Skipped'
class State(): class State():
@ -342,13 +342,13 @@ class State():
BlockPair( BlockPair(
source=source, source=source,
destination=destination, destination=destination,
model=self.source.details['model'], model=self.source.model,
working_dir=self.working_dir, working_dir=self.working_dir,
)) ))
def _get_clone_settings_path(self): def _get_clone_settings_path(self):
"""get Clone settings file path, returns pathlib.Path obj.""" """get Clone settings file path, returns pathlib.Path obj."""
description = self.source.details['model'] description = self.source.model
if not description: if not description:
description = self.source.path.name description = self.source.path.name
return pathlib.Path(f'{self.working_dir}/Clone_{description}.json') return pathlib.Path(f'{self.working_dir}/Clone_{description}.json')
@ -441,10 +441,10 @@ class State():
else: else:
bail = False bail = False
for key in ('model', 'serial'): for key in ('model', 'serial'):
if settings['Source'][key] != self.source.details[key]: if settings['Source'][key] != getattr(self.source, key):
std.print_error(f"Clone settings don't match source {key}") std.print_error(f"Clone settings don't match source {key}")
bail = True bail = True
if settings['Destination'][key] != self.destination.details[key]: if settings['Destination'][key] != getattr(self.destination, key):
std.print_error(f"Clone settings don't match destination {key}") std.print_error(f"Clone settings don't match destination {key}")
bail = True bail = True
if bail: if bail:
@ -455,13 +455,13 @@ class State():
settings = CLONE_SETTINGS.copy() settings = CLONE_SETTINGS.copy()
if not settings['Source']: if not settings['Source']:
settings['Source'] = { settings['Source'] = {
'model': self.source.details['model'], 'model': self.source.model,
'serial': self.source.details['serial'], 'serial': self.source.serial,
} }
if not settings['Destination']: if not settings['Destination']:
settings['Destination'] = { settings['Destination'] = {
'model': self.destination.details['model'], 'model': self.destination.model,
'serial': self.destination.details['serial'], 'serial': self.destination.serial,
} }
# Done # Done
@ -621,7 +621,7 @@ class State():
for part in source_parts: for part in source_parts:
report.append( report.append(
f'{part.path.name:<9} ' f'{part.path.name:<9} '
f'{std.bytes_to_string(part.details["size"], use_binary=False)}' f'{std.bytes_to_string(part.size, use_binary=False)}'
) )
report.append(' ') report.append(' ')
@ -880,7 +880,7 @@ class State():
# Add selected partition(s) # Add selected partition(s)
for part in source_parts: for part in source_parts:
num_sectors = part.details['size'] / self.destination.details['log-sec'] num_sectors = part.size / self.destination.log_sec
num_sectors = math.ceil(num_sectors) num_sectors = math.ceil(num_sectors)
part_num += 1 part_num += 1
sfdisk_script.append( sfdisk_script.append(
@ -888,7 +888,7 @@ class State():
table_type=settings['Table Type'], table_type=settings['Table Type'],
dev_path=f'{dest_prefix}{part_num}', dev_path=f'{dest_prefix}{part_num}',
size=num_sectors, size=num_sectors,
details=part.details, details=part.raw_details,
), ),
) )
@ -981,7 +981,7 @@ class State():
# 1 LBA for the protective MBR # 1 LBA for the protective MBR
# 33 LBAs each for the primary and backup GPT tables # 33 LBAs each for the primary and backup GPT tables
# Source: https://en.wikipedia.org/wiki/GUID_Partition_Table # Source: https://en.wikipedia.org/wiki/GUID_Partition_Table
required_size += (1 + 33 + 33) * self.destination.details['phy-sec'] required_size += (1 + 33 + 33) * self.destination.phy_sec
if settings['Create Boot Partition']: if settings['Create Boot Partition']:
# 384MiB EFI System Partition and a 16MiB MS Reserved partition # 384MiB EFI System Partition and a 16MiB MS Reserved partition
required_size += (384 + 16) * 1024**2 required_size += (384 + 16) * 1024**2
@ -1004,7 +1004,7 @@ class State():
# Check destination size # Check destination size
if self.mode == 'Clone': if self.mode == 'Clone':
destination_size = self.destination.details['size'] destination_size = self.destination.size
error_msg = 'A larger destination disk is required' error_msg = 'A larger destination disk is required'
else: else:
# NOTE: Adding an extra 5% here to better ensure it will fit # NOTE: Adding an extra 5% here to better ensure it will fit
@ -1311,13 +1311,13 @@ def build_directory_report(path):
def build_disk_report(dev): def build_disk_report(dev):
"""Build device report, returns list.""" """Build device report, returns list."""
children = dev.details.get('children', []) children = dev.raw_details.get('children', [])
report = [] report = []
# Get widths # Get widths
widths = { widths = {
'fstype': max(6, len(str(dev.details.get('fstype', '')))), 'fstype': max(6, len(str(dev.filesystem))),
'label': max(5, len(str(dev.details.get('label', '')))), 'label': max(5, len(str(dev.raw_details.get('label', '')))),
'name': max(4, len(dev.path.name)), 'name': max(4, len(dev.path.name)),
} }
for child in children: for child in children:
@ -1332,10 +1332,10 @@ def build_disk_report(dev):
# Disk details # Disk details
report.append(f'{dev.path.name} {dev.description}') report.append(f'{dev.path.name} {dev.description}')
report.append(' ') report.append(' ')
dev_fstype = dev.details.get('fstype', '') dev_fstype = dev.filesystem
dev_label = dev.details.get('label', '') dev_label = dev.raw_details.get('label', '')
dev_name = dev.path.name dev_name = dev.path.name
dev_size = std.bytes_to_string(dev.details["size"], use_binary=False) dev_size = std.bytes_to_string(dev.size, use_binary=False)
# Partition details # Partition details
report.append( report.append(
@ -1684,11 +1684,10 @@ def get_object(path):
obj = hw_disk.Disk(path) obj = hw_disk.Disk(path)
# Child/Parent check # Child/Parent check
parent = obj.raw_details['parent'] if obj.parent:
if parent:
std.print_warning(f'"{obj.path}" is a child device') std.print_warning(f'"{obj.path}" is a child device')
if std.ask(f'Use parent device "{parent}" instead?'): if std.ask(f'Use parent device "{obj.parent}" instead?'):
obj = hw_disk.Disk(parent) obj = hw_disk.Disk(obj.parent)
elif path.is_dir(): elif path.is_dir():
obj = path obj = path
elif path.is_file(): elif path.is_file():
@ -1736,7 +1735,7 @@ def get_table_type(disk):
NOTE: If resulting table type is not GPT or MBR NOTE: If resulting table type is not GPT or MBR
then an exception is raised. then an exception is raised.
""" """
table_type = str(disk.details.get('pttype', '')).upper() table_type = str(disk.raw_details.get('pttype', '')).upper()
table_type = table_type.replace('DOS', 'MBR') table_type = table_type.replace('DOS', 'MBR')
# Check type # Check type
@ -2239,23 +2238,22 @@ def select_disk(prompt, skip_disk=None):
menu.add_action('Quit') menu.add_action('Quit')
for disk in disks: for disk in disks:
disable_option = False disable_option = False
size = disk.details["size"] size = disk.size
# Check if option should be disabled # Check if option should be disabled
if skip_disk: if skip_disk:
parent = skip_disk.details.get('parent', None)
if (disk.path.samefile(skip_disk.path) if (disk.path.samefile(skip_disk.path)
or (parent and disk.path.samefile(parent))): or (skip_disk.parent and disk.path.samefile(skip_disk.parent))):
disable_option = True disable_option = True
# Add to menu # Add to menu
menu.add_option( menu.add_option(
name=( name=(
f'{str(disk.path):<12} ' f'{str(disk.path):<12} '
f'{disk.details["bus"]:<5} ' f'{disk.bus:<5} '
f'{std.bytes_to_string(size, decimals=1, use_binary=False):<8} ' f'{std.bytes_to_string(size, decimals=1, use_binary=False):<8} '
f'{disk.details["model"]} ' f'{disk.model} '
f'{disk.details["serial"]}' f'{disk.serial}'
), ),
details={'Disabled': disable_option, 'Object': disk}, details={'Disabled': disable_option, 'Object': disk},
) )
@ -2305,12 +2303,12 @@ def select_disk_parts(prompt, disk):
return [disk] return [disk]
# Bail early if child device selected # Bail early if child device selected
if disk.details.get('parent', False): if disk.parent:
return [disk] return [disk]
# Add parts # Add parts
whole_disk_str = f'{str(disk.path):<14} (Whole device)' whole_disk_str = f'{str(disk.path):<14} (Whole device)'
for part in disk.details.get('children', []): for part in disk.raw_details.get('children', []):
size = part["size"] size = part["size"]
name = ( name = (
f'{str(part["path"]):<14} ' f'{str(part["path"]):<14} '
@ -2333,7 +2331,7 @@ def select_disk_parts(prompt, disk):
object_list.append(option['Path']) object_list.append(option['Path'])
# Check if whole disk selected # Check if whole disk selected
if len(object_list) == len(disk.details.get('children', [])): if len(object_list) == len(disk.raw_details.get('children', [])):
# NOTE: This is not true if the disk has no partitions # NOTE: This is not true if the disk has no partitions
msg = f'Preserve partition table and unused space in {prompt.lower()}?' msg = f'Preserve partition table and unused space in {prompt.lower()}?'
if std.ask(msg): if std.ask(msg):

View file

@ -42,6 +42,7 @@ class Disk:
name: str = field(init=False) name: str = field(init=False)
notes: list[str] = field(init=False, default_factory=list) notes: list[str] = field(init=False, default_factory=list)
path: Union[pathlib.Path, str] path: Union[pathlib.Path, str]
parent: str = field(init=False)
phy_sec: int = field(init=False) phy_sec: int = field(init=False)
raw_details: dict[str, Any] = field(init=False) raw_details: dict[str, Any] = field(init=False)
raw_smartctl: dict[str, Any] = field(init=False) raw_smartctl: dict[str, Any] = field(init=False)
@ -127,6 +128,7 @@ class Disk:
self.log_sec = self.raw_details.get('log-sec', 512) self.log_sec = self.raw_details.get('log-sec', 512)
self.model = self.raw_details.get('model', 'Unknown Model') self.model = self.raw_details.get('model', 'Unknown Model')
self.name = self.raw_details.get('name', self.path) self.name = self.raw_details.get('name', self.path)
self.parent = self.raw_details.get('parent', None)
self.phy_sec = self.raw_details.get('phy-sec', 512) self.phy_sec = self.raw_details.get('phy-sec', 512)
self.serial = self.raw_details.get('serial', 'Unknown Serial') self.serial = self.raw_details.get('serial', 'Unknown Serial')
self.size = self.raw_details.get('size', -1) self.size = self.raw_details.get('size', -1)