Merge remote-tracking branch 'upstream/dev' into dev
This commit is contained in:
commit
c1970b8c23
12 changed files with 107 additions and 51 deletions
|
|
@ -2,6 +2,12 @@
|
||||||
#
|
#
|
||||||
## Wizard Kit: TMUX Launcher
|
## Wizard Kit: TMUX Launcher
|
||||||
|
|
||||||
|
# Live macOS env workaround
|
||||||
|
tmux_args=()
|
||||||
|
if [[ -e "/.wk-live-macos" ]]; then
|
||||||
|
tmux_args=(-f "/etc/tmux.conf" -S "$(mktemp).socket")
|
||||||
|
fi
|
||||||
|
|
||||||
function ask() {
|
function ask() {
|
||||||
while :; do
|
while :; do
|
||||||
read -p "$1 [Y/N] " -r answer
|
read -p "$1 [Y/N] " -r answer
|
||||||
|
|
@ -25,24 +31,24 @@ function launch_in_tmux() {
|
||||||
[[ -n "${TMUX_CMD:-}" ]] || return $(err "Required variable missing (TMUX_CMD)")
|
[[ -n "${TMUX_CMD:-}" ]] || return $(err "Required variable missing (TMUX_CMD)")
|
||||||
|
|
||||||
# Check for running session
|
# Check for running session
|
||||||
if tmux list-session | grep -q "$SESSION_NAME"; then
|
if tmux "${tmux_args[@]}" list-session | grep -q "$SESSION_NAME"; then
|
||||||
echo "WARNING: tmux session $SESSION_NAME already exists."
|
echo "WARNING: tmux session $SESSION_NAME already exists."
|
||||||
echo ""
|
echo ""
|
||||||
if ask "Connect to current session?"; then
|
if ask "Connect to current session?"; then
|
||||||
if [[ -n "${TMUX:-}" ]]; then
|
if [[ -n "${TMUX:-}" ]]; then
|
||||||
# Running inside TMUX, switch to session
|
# Running inside TMUX, switch to session
|
||||||
tmux switch-client -t "$SESSION_NAME"
|
tmux "${tmux_args[@]}" switch-client -t "$SESSION_NAME"
|
||||||
if ! jobs %% >/dev/null 2>&1; then
|
if ! jobs %% >/dev/null 2>&1; then
|
||||||
# No running jobs, try exiting abandoned tmux session
|
# No running jobs, try exiting abandoned tmux session
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
# Running outside TMUX, attach to session
|
# Running outside TMUX, attach to session
|
||||||
tmux attach-session -t "$SESSION_NAME"
|
tmux "${tmux_args[@]}" attach-session -t "$SESSION_NAME"
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
elif ask "Kill current session and start new session?"; then
|
elif ask "Kill current session and start new session?"; then
|
||||||
tmux kill-session -t "$SESSION_NAME" || \
|
tmux "${tmux_args[@]}" kill-session -t "$SESSION_NAME" || \
|
||||||
die "Failed to kill session: $SESSION_NAME"
|
die "Failed to kill session: $SESSION_NAME"
|
||||||
else
|
else
|
||||||
echo "Aborted."
|
echo "Aborted."
|
||||||
|
|
@ -53,16 +59,16 @@ function launch_in_tmux() {
|
||||||
# Start session
|
# Start session
|
||||||
if [[ -n "${TMUX:-}" ]]; then
|
if [[ -n "${TMUX:-}" ]]; then
|
||||||
# Running inside TMUX, save current session/window names
|
# Running inside TMUX, save current session/window names
|
||||||
ORIGINAL_SESSION_NAME="$(tmux display-message -p '#S')"
|
ORIGINAL_SESSION_NAME="$(tmux "${tmux_args[@]}" display-message -p '#S')"
|
||||||
ORIGINAL_WINDOW_NAME="$(tmux display-message -p '#W')"
|
ORIGINAL_WINDOW_NAME="$(tmux "${tmux_args[@]}" display-message -p '#W')"
|
||||||
tmux rename-session "$SESSION_NAME"
|
tmux "${tmux_args[@]}" rename-session "$SESSION_NAME"
|
||||||
tmux rename-window "$WINDOW_NAME"
|
tmux "${tmux_args[@]}" rename-window "$WINDOW_NAME"
|
||||||
"$TMUX_CMD" "$@"
|
"$TMUX_CMD" "$@"
|
||||||
# Restore previous session/window names
|
# Restore previous session/window names
|
||||||
tmux rename-session "${ORIGINAL_SESSION_NAME}"
|
tmux "${tmux_args[@]}" rename-session "${ORIGINAL_SESSION_NAME}"
|
||||||
tmux rename-window "${ORIGINAL_WINDOW_NAME}"
|
tmux "${tmux_args[@]}" rename-window "${ORIGINAL_WINDOW_NAME}"
|
||||||
else
|
else
|
||||||
# Running outside TMUX, start/attach to session
|
# Running outside TMUX, start/attach to session
|
||||||
tmux new-session -s "$SESSION_NAME" -n "$WINDOW_NAME" "$TMUX_CMD" "$@"
|
tmux "${tmux_args[@]}" new-session -s "$SESSION_NAME" -n "$WINDOW_NAME" "$TMUX_CMD" "$@"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
|
@ -77,6 +78,10 @@ def build_cmd_kwargs(cmd, minimized=False, pipe=True, shell=False, **kwargs):
|
||||||
'shell': shell,
|
'shell': shell,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Strip sudo if appropriate
|
||||||
|
if cmd[0] == 'sudo' and os.name == 'posix' and os.geteuid() == 0:
|
||||||
|
cmd.pop(0)
|
||||||
|
|
||||||
# Add additional kwargs if applicable
|
# Add additional kwargs if applicable
|
||||||
for key in 'check cwd encoding errors stderr stdin stdout'.split():
|
for key in 'check cwd encoding errors stderr stdin stdout'.split():
|
||||||
if key in kwargs:
|
if key in kwargs:
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
|
|
@ -729,6 +731,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'])
|
||||||
|
|
@ -1225,7 +1229,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))
|
||||||
|
|
||||||
|
|
@ -1478,8 +1481,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',
|
||||||
|
|
@ -1546,6 +1552,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
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,11 @@ class State():
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# No blocking errors encountered, check for minor attribute failures
|
# No blocking errors encountered, check for minor attribute failures
|
||||||
if not disk.check_attributes(only_blocking=False):
|
if ('Disk Attributes' in disk.tests
|
||||||
|
and not disk.tests['Disk Attributes'].failed
|
||||||
|
and not disk.check_attributes(only_blocking=False)):
|
||||||
|
# Mid-diag failure detected
|
||||||
|
LOG.warning('Disk attributes failure detected during diagnostics')
|
||||||
disk.tests['Disk Attributes'].failed = True
|
disk.tests['Disk Attributes'].failed = True
|
||||||
disk.tests['Disk Attributes'].set_status('Failed')
|
disk.tests['Disk Attributes'].set_status('Failed')
|
||||||
|
|
||||||
|
|
@ -405,7 +409,6 @@ def audio_test():
|
||||||
"""Run an OS-specific audio test."""
|
"""Run an OS-specific audio test."""
|
||||||
if PLATFORM == 'Linux':
|
if PLATFORM == 'Linux':
|
||||||
audio_test_linux()
|
audio_test_linux()
|
||||||
# TODO: Add tests for other OS
|
|
||||||
|
|
||||||
|
|
||||||
def audio_test_linux():
|
def audio_test_linux():
|
||||||
|
|
@ -456,10 +459,10 @@ def build_menu(cli_mode=False, quick_mode=False):
|
||||||
|
|
||||||
# Compatibility checks
|
# Compatibility checks
|
||||||
if PLATFORM != 'Linux':
|
if PLATFORM != 'Linux':
|
||||||
for name in ('Audio Test', 'Keyboard Test', 'Network Test'):
|
for name in ('Audio Test', 'Keyboard Test'):
|
||||||
menu.actions[name]['Disabled'] = True
|
menu.actions[name]['Disabled'] = True
|
||||||
if PLATFORM not in ('Darwin', 'Linux'):
|
if PLATFORM not in ('Darwin', 'Linux'):
|
||||||
for name in ('Matrix', 'Tubes'):
|
for name in ('Matrix', 'Network Test', 'Tubes'):
|
||||||
menu.actions[name]['Disabled'] = True
|
menu.actions[name]['Disabled'] = True
|
||||||
|
|
||||||
# Done
|
# Done
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -368,13 +369,9 @@ class Disk(BaseObj):
|
||||||
try:
|
try:
|
||||||
details = self.smartctl['ata_smart_data']['self_test']
|
details = self.smartctl['ata_smart_data']['self_test']
|
||||||
except (KeyError, TypeError):
|
except (KeyError, TypeError):
|
||||||
# Assuming disk lacks SMART support, ignore and return nearly empty dict.
|
# Assuming disk lacks SMART support, ignore and return empty dict.
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Ensure status is present even if empty
|
|
||||||
if 'status' not in details:
|
|
||||||
details['status'] = {}
|
|
||||||
|
|
||||||
# Done
|
# Done
|
||||||
return details
|
return details
|
||||||
|
|
||||||
|
|
@ -385,7 +382,6 @@ class Disk(BaseObj):
|
||||||
aligned = is_4k_aligned_macos(self.details)
|
aligned = is_4k_aligned_macos(self.details)
|
||||||
elif PLATFORM == 'Linux':
|
elif PLATFORM == 'Linux':
|
||||||
aligned = is_4k_aligned_linux(self.path, self.details['phy-sec'])
|
aligned = is_4k_aligned_linux(self.path, self.details['phy-sec'])
|
||||||
#TODO: Add checks for other OS
|
|
||||||
|
|
||||||
return aligned
|
return aligned
|
||||||
|
|
||||||
|
|
@ -502,11 +498,11 @@ class Disk(BaseObj):
|
||||||
_f.write(f'{header_str}\nSMART self-test status:\n {status_str}')
|
_f.write(f'{header_str}\nSMART self-test status:\n {status_str}')
|
||||||
|
|
||||||
# Check if finished
|
# Check if finished
|
||||||
if 'remaining_percent' not in test_details['status']:
|
if 'remaining_percent' not in test_details.get('status', {}):
|
||||||
finished = True
|
finished = True
|
||||||
break
|
break
|
||||||
|
|
||||||
elif 'remaining_percent' in test_details['status']:
|
elif 'remaining_percent' in test_details.get('status', {}):
|
||||||
started = True
|
started = True
|
||||||
|
|
||||||
# Check result
|
# Check result
|
||||||
|
|
@ -660,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
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
"""WizardKit: UFD Functions"""
|
"""WizardKit: UFD Functions"""
|
||||||
# vim: sts=2 sw=2 ts=2
|
# vim: sts=2 sw=2 ts=2
|
||||||
# TODO: Replace some lsblk usage with hw_obj?
|
|
||||||
# TODO: Reduce imports if possible
|
|
||||||
# TODO: Needs testing
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
@ -57,14 +54,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')
|
||||||
|
|
@ -202,6 +196,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:
|
||||||
|
|
@ -214,17 +209,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',
|
||||||
'--',
|
'--',
|
||||||
|
|
@ -261,6 +259,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,
|
||||||
|
|
@ -294,13 +293,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',
|
||||||
|
|
@ -313,6 +313,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',
|
||||||
|
|
@ -342,6 +343,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',
|
||||||
|
|
@ -417,6 +419,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',
|
||||||
|
|
@ -438,6 +441,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}#//',
|
||||||
|
|
@ -486,6 +490,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',
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,10 @@ from wk.io import non_clobber_path
|
||||||
|
|
||||||
|
|
||||||
# STATIC VARIABLES
|
# STATIC VARIABLES
|
||||||
if os.name == 'nt':
|
if os.path.exists('/.wk-live-macos'):
|
||||||
|
# Workaround for live macOS env
|
||||||
|
DEFAULT_LOG_DIR = '/var/log/WizardKit'
|
||||||
|
elif os.name == 'nt':
|
||||||
# Example: "C:\WK\1955-11-05\WizardKit"
|
# Example: "C:\WK\1955-11-05\WizardKit"
|
||||||
DEFAULT_LOG_DIR = (
|
DEFAULT_LOG_DIR = (
|
||||||
f'{os.environ.get("SYSTEMDRIVE", "C:")}/'
|
f'{os.environ.get("SYSTEMDRIVE", "C:")}/'
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,6 @@ def share_is_mounted(details):
|
||||||
if row['source'] == f'//{details["Address"]}/{details["Share"]}':
|
if row['source'] == f'//{details["Address"]}/{details["Share"]}':
|
||||||
mounted = True
|
mounted = True
|
||||||
break
|
break
|
||||||
#TODO: Check mount status under Windows
|
|
||||||
#elif PLATFORM == 'Windows':
|
#elif PLATFORM == 'Windows':
|
||||||
|
|
||||||
# Done
|
# Done
|
||||||
|
|
|
||||||
|
|
@ -179,7 +179,6 @@ def running_as_root():
|
||||||
|
|
||||||
def scan_corestorage_container(container, timeout=300):
|
def scan_corestorage_container(container, timeout=300):
|
||||||
"""Scan CoreStorage container for inner volumes, returns list."""
|
"""Scan CoreStorage container for inner volumes, returns list."""
|
||||||
# TODO: Test Scanning CoreStorage containers
|
|
||||||
detected_volumes = {}
|
detected_volumes = {}
|
||||||
inner_volumes = []
|
inner_volumes = []
|
||||||
log_path = format_log_path(log_name=f'{container.path.name}_testdisk')
|
log_path = format_log_path(log_name=f'{container.path.name}_testdisk')
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ from wk.std import GenericError, GenericWarning, sleep
|
||||||
|
|
||||||
# STATIC VARIABLES
|
# STATIC VARIABLES
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
OS_VERSION = float(platform.win32_ver()[0]) # TODO: Check if Win8.1 returns '8'
|
OS_VERSION = float(platform.win32_ver()[0])
|
||||||
REG_MSISERVER = r'HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Network\MSIServer'
|
REG_MSISERVER = r'HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Network\MSIServer'
|
||||||
SLMGR = pathlib.Path(f'{os.environ.get("SYSTEMROOT")}/System32/slmgr.vbs')
|
SLMGR = pathlib.Path(f'{os.environ.get("SYSTEMROOT")}/System32/slmgr.vbs')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,8 @@ class Menu():
|
||||||
checkmark = '*'
|
checkmark = '*'
|
||||||
if 'DISPLAY' in os.environ or PLATFORM == 'Darwin':
|
if 'DISPLAY' in os.environ or PLATFORM == 'Darwin':
|
||||||
checkmark = '✓'
|
checkmark = '✓'
|
||||||
|
if os.path.exists('/.wk-live-macos'):
|
||||||
|
checkmark = '*'
|
||||||
display_name = f'{index if index else name[:1].upper()}: '
|
display_name = f'{index if index else name[:1].upper()}: '
|
||||||
if not (index and index >= 10):
|
if not (index and index >= 10):
|
||||||
display_name = f' {display_name}'
|
display_name = f' {display_name}'
|
||||||
|
|
@ -386,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
|
||||||
|
|
@ -394,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."""
|
||||||
|
|
@ -523,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.
|
||||||
|
|
@ -540,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__)
|
||||||
|
|
@ -556,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)
|
||||||
|
|
@ -726,7 +735,11 @@ def choice(choices, prompt='答えろ!'):
|
||||||
def clear_screen():
|
def clear_screen():
|
||||||
"""Simple wrapper for clear/cls."""
|
"""Simple wrapper for clear/cls."""
|
||||||
cmd = 'cls' if os.name == 'nt' else 'clear'
|
cmd = 'cls' if os.name == 'nt' else 'clear'
|
||||||
subprocess.run(cmd, check=False, shell=True, stderr=subprocess.PIPE)
|
proc = subprocess.run(cmd, check=False, shell=True, stderr=subprocess.PIPE)
|
||||||
|
|
||||||
|
# Workaround for live macOS env
|
||||||
|
if proc.returncode != 0:
|
||||||
|
print('\033c')
|
||||||
|
|
||||||
|
|
||||||
def color_string(strings, colors, sep=' '):
|
def color_string(strings, colors, sep=' '):
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue