WizardKit/.bin/Scripts/user_data_transfer.py
Alan Mason b37a492db5 2017-03: Retroactive Updates
## MAJOR refactoring in progress ##

# BROKEN SCRIPTS #
  (These scripts need updated to use the new global_vars & try_and_print)
    * user_data_transfer.py
    * install_sw_bundle.py

* All Python scripts
  * PLAN: Replace vars_wk with global_vars

* functions.py
  * PLAN: Will hold (nearly?) all functions going forward
    * Should simplify the remaining scripts
    * (e.g. reset_browsers and sw_diagnostics both had a backup_browsers())
  * PLAN: Move all program definitions to functions.py
    * (e.g. vars_wk['SevenZip'] --> global_vars['Programs']['SevenZip'])
  * Added major_exception()
    * Should be called if anything goes wrong to alert user and provide info
  * Added non_clobber_rename()
    * Appends a number (if necessary) to avoid overwriting data
  * Added popen_program()
    * Removes subprocess req for sw_checklist
  * Added try_and_print()
    * Run a function and show CS/NS/etc
    * Can add additional "result" strings via Exception classes
    * Passes unrecognized args/kwargs to the function
    * Used by scripts to standardize message formatting and error handling
  * exit_script() now handles opening the log (if set) and killing caffeine.exe
  * Refactored init_vars_wk/os code to work with global_vars
    * Uses the try_and_print function for better formatting and error handling
    * BREAKING: 'OS' vars now located in global_vars['OS'] (including 'Arch')
      * OS labeled as 'outdated', 'very outdated', and 'unrecognized' as needed
    * BREAKING: renamed PROGRAMS to TOOLS
      * Expanded TOOLS
  * Removed log_file as a required argument from all functions
  * Removed vars_wk/global_vars as a required argument from all functions
  * Removed unused WinPE functions
  * Sorted functions

* user_checklist() (formerly reset_browsers())
  * Most functions moved to functions.py (see above)
  * Browsers
    * Work has been split into backup, reset, and config sections
    * Script now asks all questions before starting backup/reset/config
    * Script now forces the homepage to DEFAULT_HOMEPAGE (set in functions.py)
      * (i.e. it no longer asks first, it just does it)
    * Current homepages are listed where possible before backup/reset/config

* Launch/Launchers
  * Added QuickBooks support

* Removed launchers
  * CPU-Z
  * HWMonitor
  * PerfMonitor2
  * SanDisk Express Cache
  * Shortcut Cleaner
  * SuperAntiSpyware (SAS)

* Replaced Notepad2-Mod with Notepad++
2017-11-17 00:56:16 -07:00

198 lines
8.1 KiB
Python

# Wizard Kit: Copy user data to the system over the network
import os
import re
from operator import itemgetter
# Init
os.chdir(os.path.dirname(os.path.realpath(__file__)))
os.system('title Wizard Kit: Data 1')
from functions import *
init_global_vars()
set_global_vars(LogFile='{LogDir}\\Data 1.log'.format(**global_vars))
set_global_vars(TransferDir='{ClientDir}\\Transfer'.format(**global_vars))
def abort():
print_warning('Aborted.')
exit_script(global_vars)
def transfer_file_based(source_path, subdir=None):
# Set Destination
if subdir is None:
dest_path = global_vars['TransferDir']
else:
dest_path = '{TransferDir}\\{subdir}'.format(subdir=subdir, **global_vars)
os.makedirs(dest_path, exist_ok=True)
# Main copy
selected_items = []
for item in os.scandir(source_path):
if REGEX_INCL_ROOT_ITEMS.search(item.name):
selected_items.append(item.path)
elif not REGEX_EXCL_ROOT_ITEMS.search(item.name):
if ask('Copy: "{name}" item?'.format(name=item.name)):
selected_items.append(item.path)
if len(selected_items) > 0:
_args = global_vars['FastCopyArgs'].copy() + selected_items
_args.append('/to={dest_path}\\'.format(dest_path=dest_path))
try:
print_standard('Copying main user data...')
run_program(global_vars['FastCopy'], _args, check=True)
except subprocess.CalledProcessError:
print_warning('WARNING: Errors encountered while copying main user data')
else:
print_error('ERROR: No files selected for transfer?')
abort()
# Fonts
selected_items = []
if os.path.exists('{source}\\Windows\\Fonts'.format(source=source_path)):
selected_items.append('{source}\\Windows\\Fonts'.format(source=source_path))
if len(selected_items) > 0:
_args = global_vars['FastCopyArgs'].copy() + selected_items
_args.append('/to={dest_path}\\Windows\\'.format(dest_path=dest_path))
try:
print_standard('Copying Fonts...')
run_program(global_vars['FastCopy'], _args, check=True)
except subprocess.CalledProcessError:
print_warning('WARNING: Errors encountered while copying Fonts')
# Registry
selected_items = []
if os.path.exists('{source}\\Windows\\System32\\config'.format(source=source_path)):
selected_items.append('{source}\\Windows\\System32\\config'.format(source=source_path))
if os.path.exists('{source}\\Windows\\System32\\OEM'.format(source=source_path)):
selected_items.append('{source}\\Windows\\System32\\OEM'.format(source=source_path))
if len(selected_items) > 0:
_args = global_vars['FastCopyArgs'].copy() + selected_items
_args.append('/to={dest_path}\\Windows\\System32\\'.format(dest_path=dest_path))
try:
print_standard('Copying Registry...')
run_program(global_vars['FastCopy'], _args, check=True)
except subprocess.CalledProcessError:
print_warning('WARNING: Errors encountered while copying registry')
def transfer_image_based(source_path):
print_standard('Assessing image...')
os.makedirs(global_vars['TransferDir'], exist_ok=True)
# Scan source
_args = [
'dir',
'{source}'.format(source=source_path), '1']
try:
_list = run_program(global_vars['Tools']['wimlib-imagex'], _args, check=True)
except subprocess.CalledProcessError as err:
print_error('ERROR: Failed to get file list.')
print(err)
abort()
# Add items to list
selected_items = []
root_items = [i.strip() for i in _list.stdout.decode('utf-8', 'ignore').splitlines() if i.count('\\') == 1 and i.strip() != '\\']
for item in root_items:
if REGEX_INCL_ROOT_ITEMS.search(item):
selected_items.append(item)
elif not REGEX_EXCL_ROOT_ITEMS.search(item):
if ask('Extract: "{name}" item?'.format(name=item)):
selected_items.append(item)
# Extract files
if len(selected_items) > 0:
# Write files.txt
with open('{TmpDir}\\wim_files.txt'.format(**global_vars), 'w') as f:
# Defaults
for item in EXTRA_INCL_WIM_ITEMS:
f.write('{item}\n'.format(item=item))
for item in selected_items:
f.write('{item}\n'.format(item=item))
try:
print_standard('Extracting user data...')
_args = [
'extract',
'{source}'.format(source=source_path), '1',
'@{TmpDir}\\wim_files.txt'.format(**global_vars),
'--dest-dir={TransferDir}\\'.format(**global_vars),
'--no-acls',
'--nullglob']
run_program(global_vars['Tools']['wimlib-imagex'], _args, check=True)
except subprocess.CalledProcessError:
print_warning('WARNING: Errors encountered while extracting user data')
else:
print_error('ERROR: No files selected for extraction?')
abort()
if __name__ == '__main__':
stay_awake(global_vars)
# Check for existing TransferDir
if os.path.exists(global_vars['TransferDir']):
print_warning('Folder "{TransferDir}" exists. This script will rename the existing folder in order to avoid overwriting data.'.format(**global_vars))
if (ask('Rename existing folder and proceed?')):
_old_transfer = '{TransferDir}.old'.format(**global_vars)
_i = 1;
while os.path.exists(_old_transfer):
_old_transfer = '{TransferDir}.old{i}'.format(i=_i, **global_vars)
_i += 1
print_info('Renaming "{TransferDir}" to "{old_transfer}"'.format(old_transfer=_old_transfer, **global_vars))
os.rename(global_vars['TransferDir'], _old_transfer)
else:
abort()
# Set ticket number
ticket = None
while ticket is None:
tmp = input('Enter ticket number: ')
if re.match(r'^([0-9]+([-_]?\w+|))$', tmp):
ticket = tmp
# Get backup
backup_source = select_backup(ticket)
if backup_source is None:
abort()
# Determine restore method
extract_item('wimlib', global_vars, silent=True)
restore_source = None
restore_options = []
_file_based = False
for item in os.scandir(backup_source.path):
if item.is_dir():
_file_based = True
restore_options.append({'Name': 'File-Based:\t{source}'.format(source=item.name), 'Source': item})
for _subitem in os.scandir(item.path):
if is_valid_wim_image(_subitem):
restore_options.append({'Name': 'Image-Based: {dir}\\{source}'.format(dir=item.name, source=_subitem.name), 'Source': _subitem})
elif is_valid_wim_image(item):
restore_options.append({'Name': 'Image-Based:\t{source}'.format(source=item.name), 'Source': item})
if _file_based:
restore_options.append({'Name': 'File-Based:\t.', 'Source': backup_source})
restore_options = sorted(restore_options, key=itemgetter('Name'))
actions = [{'Name': 'Quit', 'Letter': 'Q'}]
if len(restore_options) > 0:
selection = menu_select('Which backup are we using? (Path: {path})'.format(path=backup_source.path), restore_options, actions)
if selection == 'Q':
abort()
else:
restore_source = restore_options[int(selection)-1]['Source']
else:
print_error('ERROR: No restoration options detected.')
abort()
# Start transfer
print_info('Using backup: {path}'.format(path=restore_source.path))
if restore_source.is_dir():
transfer_file_based(restore_source.path)
# Check for Windows.old*
for item in os.scandir(restore_source.path):
if item.is_dir() and re.search(r'^Windows.old', item.name, re.IGNORECASE):
transfer_file_based(item.path, subdir=item.name)
if restore_source.is_file():
transfer_image_based(restore_source.path)
cleanup_transfer()
# Done
umount_backup_shares()
print_success('Done.')
run_kvrt()
pause("Press Enter to exit...")
exit_script(global_vars)