Merge branch 'project-overhaul' into dev

This commit is contained in:
2Shirt 2020-01-30 14:03:11 -07:00
commit 6cee9930c1
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C
5 changed files with 63 additions and 20 deletions

View file

@ -82,7 +82,9 @@ PANE_RATIOS = (
) )
PLATFORM = std.PLATFORM PLATFORM = std.PLATFORM
RECOMMENDED_FSTYPES = re.compile(r'^(ext[234]|ntfs|xfs)$') RECOMMENDED_FSTYPES = re.compile(r'^(ext[234]|ntfs|xfs)$')
RECOMMENDED_MAP_FSTYPES = re.compile(r'^(cifs|ext[234]|ntfs|vfat|xfs)$') RECOMMENDED_MAP_FSTYPES = re.compile(
r'^(apfs|cifs|ext[234]|hfs.?|ntfs|vfat|xfs)$'
)
SETTING_PRESETS = ( SETTING_PRESETS = (
'Default', 'Default',
'Fast', 'Fast',
@ -725,6 +727,8 @@ class State():
self.update_progress_pane('Idle') self.update_progress_pane('Idle')
self.confirm_selections('Start recovery?') self.confirm_selections('Start recovery?')
# TODO: Unmount source and/or destination under macOS
# Prep destination # Prep destination
if self.mode == 'Clone': if self.mode == 'Clone':
self.prep_destination(source_parts, dry_run=docopt_args['--dry-run']) self.prep_destination(source_parts, dry_run=docopt_args['--dry-run'])
@ -1194,7 +1198,6 @@ def build_directory_report(path):
line = f'{path:<{width}}{line}' line = f'{path:<{width}}{line}'
report.append(line) report.append(line)
else: else:
# TODO Get dir details under macOS
report.append(std.color_string('PATH', 'BLUE')) report.append(std.color_string('PATH', 'BLUE'))
report.append(str(path)) report.append(str(path))
@ -1447,8 +1450,11 @@ def fstype_is_ok(path, map_dir=False):
# Get fstype # Get fstype
if PLATFORM == 'Darwin': if PLATFORM == 'Darwin':
# TODO: Determine fstype under macOS try:
pass fstype = get_fstype_macos(path)
except (IndexError, TypeError, ValueError):
# Ignore for now
pass
elif PLATFORM == 'Linux': elif PLATFORM == 'Linux':
cmd = [ cmd = [
'findmnt', 'findmnt',
@ -1515,6 +1521,24 @@ def get_etoc():
return etoc return etoc
def get_fstype_macos(path):
"""Get fstype for path under macOS, returns str.
NOTE: This method is not very effecient.
"""
cmd = ['df', path]
# Get device based on the path
proc = exe.run_program(cmd, check=False)
dev = proc.stdout.splitlines()[1].split()[0]
# Get device details
dev = hw_obj.Disk(dev)
# Done
return dev.details['fstype']
def get_object(path): def get_object(path):
"""Get object based on path, returns obj.""" """Get object based on path, returns obj."""
obj = None obj = None

View file

@ -321,6 +321,7 @@ class Disk(BaseObj):
self.details['bus'] = str(self.details.get('bus', '???')).upper() self.details['bus'] = str(self.details.get('bus', '???')).upper()
self.details['bus'] = self.details['bus'].replace('IMAGE', 'Image') self.details['bus'] = self.details['bus'].replace('IMAGE', 'Image')
self.details['bus'] = self.details['bus'].replace('NVME', 'NVMe') self.details['bus'] = self.details['bus'].replace('NVME', 'NVMe')
self.details['fstype'] = self.details.get('fstype', 'Unknown')
self.details['log-sec'] = self.details.get('log-sec', 512) self.details['log-sec'] = self.details.get('log-sec', 512)
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)
@ -655,12 +656,15 @@ def get_disk_details_macos(path):
dev['label'] = dev.pop('VolumeName', '') dev['label'] = dev.pop('VolumeName', '')
dev['model'] = dev.pop('MediaName', 'Unknown') dev['model'] = dev.pop('MediaName', 'Unknown')
dev['mountpoint'] = dev.pop('MountPoint', '') dev['mountpoint'] = dev.pop('MountPoint', '')
dev['name'] = dev.get('name', str(dev['path']))
dev['phy-sec'] = dev.pop('DeviceBlockSize', 512) dev['phy-sec'] = dev.pop('DeviceBlockSize', 512)
dev['serial'] = get_disk_serial_macos(dev['path']) dev['serial'] = get_disk_serial_macos(dev['path'])
dev['size'] = dev.pop('Size', -1) dev['size'] = dev.pop('Size', -1)
dev['ssd'] = dev.pop('SolidState', False) dev['ssd'] = dev.pop('SolidState', False)
dev['vendor'] = '' dev['vendor'] = ''
if not dev.get('WholeDisk', True): if dev.get('WholeDisk', True):
dev['parent'] = None
else:
dev['parent'] = dev.pop('ParentWholeDisk', None) dev['parent'] = dev.pop('ParentWholeDisk', None)
# Done # Done

View file

@ -50,14 +50,11 @@ def build_ufd():
args = docopt(DOCSTRING) args = docopt(DOCSTRING)
log.update_log_path(dest_name='build-ufd', timestamp=True) log.update_log_path(dest_name='build-ufd', timestamp=True)
try_print = std.TryAndPrint() try_print = std.TryAndPrint()
try_print.add_error(FileNotFoundError)
try_print.catch_all = False try_print.catch_all = False
try_print.verbose = True
try_print.indent = 2 try_print.indent = 2
# Check if running with root permissions
if not linux.running_as_root():
std.print_error('This script is meant to be run as root')
std.abort()
# Show header # Show header
std.print_success(KIT_NAME_FULL) std.print_success(KIT_NAME_FULL)
std.print_warning('UFD Build Tool') std.print_warning('UFD Build Tool')
@ -195,6 +192,7 @@ def confirm_selections(update=False):
def copy_source(source, items, overwrite=False): def copy_source(source, items, overwrite=False):
"""Copy source items to /mnt/UFD.""" """Copy source items to /mnt/UFD."""
is_image = source.is_file() is_image = source.is_file()
items_not_found = False
# Mount source if necessary # Mount source if necessary
if is_image: if is_image:
@ -207,17 +205,20 @@ def copy_source(source, items, overwrite=False):
try: try:
io.recursive_copy(i_source, i_dest, overwrite=overwrite) io.recursive_copy(i_source, i_dest, overwrite=overwrite)
except FileNotFoundError: except FileNotFoundError:
# Going to assume (hope) that this is fine items_not_found = True
pass
# Unmount source if necessary # Unmount source if necessary
if is_image: if is_image:
linux.unmount('/mnt/Source') linux.unmount('/mnt/Source')
# Raise exception if item(s) were not found
raise FileNotFoundError('One or more items not found')
def create_table(dev_path, use_mbr=False): def create_table(dev_path, use_mbr=False):
"""Create GPT or DOS partition table.""" """Create GPT or DOS partition table."""
cmd = [ cmd = [
'sudo',
'parted', dev_path, 'parted', dev_path,
'--script', '--script',
'--', '--',
@ -254,6 +255,7 @@ def find_first_partition(dev_path):
def format_partition(dev_path, label): def format_partition(dev_path, label):
"""Format first partition on device FAT32.""" """Format first partition on device FAT32."""
cmd = [ cmd = [
'sudo',
'mkfs.vfat', 'mkfs.vfat',
'-F', '32', '-F', '32',
'-n', label, '-n', label,
@ -287,13 +289,14 @@ def hide_items(ufd_dev, items):
# Hide items # Hide items
for item in items: for item in items:
cmd = [f'yes | mattrib +h "U:/{item}"'] cmd = [f'yes | sudo mattrib +h "U:/{item}"']
run_program(cmd, check=False, shell=True) run_program(cmd, shell=True)
def install_syslinux_to_dev(ufd_dev, use_mbr): def install_syslinux_to_dev(ufd_dev, use_mbr):
"""Install Syslinux to UFD (dev).""" """Install Syslinux to UFD (dev)."""
cmd = [ cmd = [
'sudo',
'dd', 'dd',
'bs=440', 'bs=440',
'count=1', 'count=1',
@ -306,6 +309,7 @@ def install_syslinux_to_dev(ufd_dev, use_mbr):
def install_syslinux_to_partition(partition): def install_syslinux_to_partition(partition):
"""Install Syslinux to UFD (partition).""" """Install Syslinux to UFD (partition)."""
cmd = [ cmd = [
'sudo',
'syslinux', 'syslinux',
'--install', '--install',
'--directory', '--directory',
@ -335,6 +339,7 @@ def is_valid_path(path_obj, path_type):
def set_boot_flag(dev_path, use_mbr=False): def set_boot_flag(dev_path, use_mbr=False):
"""Set modern or legacy boot flag.""" """Set modern or legacy boot flag."""
cmd = [ cmd = [
'sudo',
'parted', dev_path, 'parted', dev_path,
'set', '1', 'set', '1',
'boot' if use_mbr else 'legacy_boot', 'boot' if use_mbr else 'legacy_boot',
@ -410,6 +415,7 @@ def update_boot_entries():
# Use UUID instead of label # Use UUID instead of label
cmd = [ cmd = [
'sudo',
'sed', 'sed',
'--in-place', '--in-place',
'--regexp-extended', '--regexp-extended',
@ -428,6 +434,7 @@ def update_boot_entries():
# Entry found, update config files # Entry found, update config files
cmd = [ cmd = [
'sudo',
'sed', 'sed',
'--in-place', '--in-place',
f's/#{b_comment}#//', f's/#{b_comment}#//',
@ -476,6 +483,7 @@ def verify_ufd(dev_path):
def zero_device(dev_path): def zero_device(dev_path):
"""Zero-out first 64MB of device.""" """Zero-out first 64MB of device."""
cmd = [ cmd = [
'sudo',
'dd', 'dd',
'bs=4M', 'bs=4M',
'count=16', 'count=16',

View file

@ -388,6 +388,7 @@ class Menu():
class TryAndPrint(): class TryAndPrint():
# pylint: disable=too-many-instance-attributes
"""Object used to standardize running functions and returning the result. """Object used to standardize running functions and returning the result.
The errors and warning attributes are used to allow fine-tuned results The errors and warning attributes are used to allow fine-tuned results
@ -396,11 +397,12 @@ class TryAndPrint():
def __init__(self, msg_bad='FAILED', msg_good='SUCCESS'): def __init__(self, msg_bad='FAILED', msg_good='SUCCESS'):
self.catch_all = True self.catch_all = True
self.indent = INDENT self.indent = INDENT
self.msg_bad = msg_bad
self.msg_good = msg_good
self.width = WIDTH
self.list_errors = ['GenericError'] self.list_errors = ['GenericError']
self.list_warnings = ['GenericWarning'] self.list_warnings = ['GenericWarning']
self.msg_bad = msg_bad
self.msg_good = msg_good
self.verbose = False
self.width = WIDTH
def _format_exception_message(self, _exception): def _format_exception_message(self, _exception):
"""Format using the exception's args or name, returns str.""" """Format using the exception's args or name, returns str."""
@ -525,13 +527,13 @@ class TryAndPrint():
def run( def run(
self, message, function, *args, self, message, function, *args,
catch_all=None, msg_good=None, verbose=False, **kwargs): catch_all=None, msg_good=None, verbose=None, **kwargs):
# pylint: disable=catching-non-exception # pylint: disable=catching-non-exception
"""Run a function and print the results, returns results as dict. """Run a function and print the results, returns results as dict.
If catch_all is True then (nearly) all exceptions will be caught. If catch_all is True then (nearly) all exceptions will be caught.
Otherwise if an exception occurs that wasn't specified it will be Otherwise if an exception occurs that wasn't specified it will be
re-raised. If passed it will override self.catch_all for this call. re-raised.
If the function returns data it will be used instead of msg_good, If the function returns data it will be used instead of msg_good,
msg_bad, or exception text. msg_bad, or exception text.
@ -542,6 +544,9 @@ class TryAndPrint():
If verbose is True then exception names or messages will be used for If verbose is True then exception names or messages will be used for
the result message. Otherwise it will simply be set to result_bad. the result message. Otherwise it will simply be set to result_bad.
If catch_all and/or verbose are passed it will override
self.catch_all and/or self.verbose for this call.
args and kwargs are passed to the function. args and kwargs are passed to the function.
""" """
LOG.debug('function: %s.%s', function.__module__, function.__name__) LOG.debug('function: %s.%s', function.__module__, function.__name__)
@ -558,6 +563,8 @@ class TryAndPrint():
result_msg = 'UNKNOWN' result_msg = 'UNKNOWN'
if catch_all is None: if catch_all is None:
catch_all = self.catch_all catch_all = self.catch_all
if verbose is None:
verbose = self.verbose
# Build exception tuples # Build exception tuples
e_exceptions = tuple(self._get_exception(e) for e in self.list_errors) e_exceptions = tuple(self._get_exception(e) for e in self.list_errors)

View file

@ -234,7 +234,7 @@
</menu> </menu>
<separator/> <separator/>
<item label="Exit"> <action name="Execute"> <item label="Exit"> <action name="Execute">
<execute>oblogout</execute> <execute>wk-exit</execute>
</action> </item> </action> </item>
</menu> </menu>
</openbox_menu> </openbox_menu>