Expanded source/dest disk selection sections

This commit is contained in:
2Shirt 2019-12-13 18:37:36 -07:00
parent cb7d0da816
commit bc2c3a2c80
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C
2 changed files with 68 additions and 21 deletions

View file

@ -134,21 +134,19 @@ class State():
mode = set_mode(docopt_args) mode = set_mode(docopt_args)
# Select source # Select source
try: self.source = get_object(docopt_args['<source>'])
self.source = select_disk() if not self.source:
except std.GenericAbort: self.source = select_disk('Source')
std.abort()
# Select destination # Select destination
if mode == 'Clone': self.destination = get_object(docopt_args['<destination>'])
try: if not self.destination:
self.destination = select_disk(self.source.path) if mode == 'Clone':
except std.GenericAbort: self.destination = select_disk('Destination', self.source)
elif mode == 'Image':
#TODO
std.print_error('Not implemented yet.')
std.abort() std.abort()
elif mode == 'Image':
#TODO
std.print_error('Not implemented yet.')
std.abort()
# Update panes # Update panes
self.panes['Progress'] = tmux.split_window( self.panes['Progress'] = tmux.split_window(
@ -312,6 +310,39 @@ def build_settings_menu(silent=True):
return menu return menu
def get_object(path):
"""Get object based on path, returns obj."""
obj = None
# Bail early
if not path:
return obj
# Check path
path = pathlib.Path(path).resolve()
if path.is_block_device() or path.is_char_device():
obj = hw_obj.Disk(path)
# Child/Parent check
parent = obj.details['parent']
if parent:
std.print_warning(f'"{obj.path}" is a child device')
if std.ask(f'Use parent device "{parent}" instead?'):
obj = hw_obj.Disk(parent)
elif path.is_dir():
#TODO
std.print_error('Not implemented yet.')
std.abort()
elif path.is_file():
# Assuming image file, setup loopback dev
#TODO
std.print_error('Not implemented yet.')
std.abort()
# Done
return obj
def main(): def main():
"""Main function for ddrescue TUI.""" """Main function for ddrescue TUI."""
args = docopt(DOCSTRING) args = docopt(DOCSTRING)
@ -327,7 +358,10 @@ def main():
main_menu = build_main_menu() main_menu = build_main_menu()
settings_menu = build_settings_menu() settings_menu = build_settings_menu()
state = State() state = State()
state.init_recovery(args) try:
state.init_recovery(args)
except std.GenericAbort:
std.abort()
# Show menu # Show menu
while True: while True:
@ -372,20 +406,27 @@ def run_recovery(state, main_menu, settings_menu):
std.pause('Press Enter to return to main menu...') std.pause('Press Enter to return to main menu...')
def select_disk(skip_disk=None): def select_disk(prompt, skip_disk=None):
"""Select disk from list, returns Disk().""" """Select disk from list, returns Disk()."""
disks = hw_obj.get_disks() disks = hw_obj.get_disks()
menu = std.Menu( menu = std.Menu(
title=std.color_string('ddrescue TUI: Source Selection', 'GREEN'), title=std.color_string(f'ddrescue TUI: {prompt} Selection', 'GREEN'),
) )
menu.disabled_str = 'Already selected' menu.disabled_str = 'Already selected'
menu.separator = ' ' menu.separator = ' '
menu.add_action('Quit') menu.add_action('Quit')
if skip_disk:
skip_disk = str(skip_disk)
for disk in disks: for disk in disks:
disable_option = skip_disk and disk.path.match(skip_disk) disable_option = False
size = disk.details["size"] size = disk.details["size"]
# Check if option should be disabled
if skip_disk:
parent = skip_disk.details.get('parent', None)
if (disk.path.samefile(skip_disk.path)
or (parent and disk.path.samefile(parent))):
disable_option = True
# Add to menu
menu.add_option( menu.add_option(
name=( name=(
f'{str(disk.path):<12} ' f'{str(disk.path):<12} '

View file

@ -305,7 +305,7 @@ class Disk(BaseObj):
self.details = get_disk_details_linux(self.path) self.details = get_disk_details_linux(self.path)
# Set necessary details # Set necessary details
self.details['bus'] = self.details.get('bus', '???') self.details['bus'] = str(self.details.get('bus', '???'))
self.details['bus'] = self.details['bus'].upper().replace('NVME', 'NVMe') self.details['bus'] = self.details['bus'].upper().replace('NVME', 'NVMe')
self.details['model'] = self.details.get('model', 'Unknown Model') self.details['model'] = self.details.get('model', 'Unknown Model')
self.details['name'] = self.details.get('name', self.path) self.details['name'] = self.details.get('name', self.path)
@ -569,8 +569,14 @@ def get_disk_details_linux(path):
cmd = ['lsblk', '--bytes', '--json', '--output-all', '--paths', path] cmd = ['lsblk', '--bytes', '--json', '--output-all', '--paths', path]
json_data = get_json_from_command(cmd, check=False) json_data = get_json_from_command(cmd, check=False)
details = json_data.get('blockdevices', [{}])[0] details = json_data.get('blockdevices', [{}])[0]
details['bus'] = details.pop('tran', '???')
details['ssd'] = not details.pop('rota', True) # Fix details
for dev in [details, *details.get('children', [])]:
dev['bus'] = dev.pop('tran', '???')
dev['parent'] = dev.pop('pkname', None)
dev['ssd'] = not dev.pop('rota', True)
# Done
return details return details