def main(): """entry point""" try: o = Options() except ValueError as e: LOG.err('Config format error: {}'.format(str(e))) return False ret = True try: if o.cmd_list: # list existing profiles if o.debug: LOG.dbg('running cmd: list') cmd_list_profiles(o) elif o.cmd_listfiles: # list files for selected profile if o.debug: LOG.dbg('running cmd: listfiles') cmd_list_files(o) elif o.cmd_install: # install the dotfiles stored in dotdrop if o.debug: LOG.dbg('running cmd: install') ret = cmd_install(o) elif o.cmd_compare: # compare local dotfiles with dotfiles stored in dotdrop if o.debug: LOG.dbg('running cmd: compare') tmp = get_tmpdir() ret = cmd_compare(o, tmp) # clean tmp directory remove(tmp) elif o.cmd_import: # import dotfile(s) if o.debug: LOG.dbg('running cmd: import') ret = cmd_importer(o) elif o.cmd_update: # update a dotfile if o.debug: LOG.dbg('running cmd: update') ret = cmd_update(o) elif o.cmd_detail: # detail files if o.debug: LOG.dbg('running cmd: update') cmd_detail(o) except KeyboardInterrupt: LOG.err('interrupted') ret = False return ret
def main(): """entry point""" # check dependencies are met try: dependencies_met() except Exception as e: LOG.err(e) return False t0 = time.time() try: o = Options() except YamlException as e: LOG.err('config error: {}'.format(str(e))) return False except UndefinedException as e: LOG.err('config error: {}'.format(str(e))) return False if o.debug: LOG.dbg('\n\n') options_time = time.time() - t0 ret = True t0 = time.time() command = '' try: if o.cmd_profiles: # list existing profiles command = 'profiles' if o.debug: LOG.dbg('running cmd: {}'.format(command)) cmd_list_profiles(o) elif o.cmd_files: # list files for selected profile command = 'files' if o.debug: LOG.dbg('running cmd: {}'.format(command)) cmd_files(o) elif o.cmd_install: # install the dotfiles stored in dotdrop command = 'install' if o.debug: LOG.dbg('running cmd: {}'.format(command)) ret = cmd_install(o) elif o.cmd_compare: # compare local dotfiles with dotfiles stored in dotdrop command = 'compare' if o.debug: LOG.dbg('running cmd: {}'.format(command)) tmp = get_tmpdir() ret = cmd_compare(o, tmp) # clean tmp directory removepath(tmp, LOG) elif o.cmd_import: # import dotfile(s) command = 'import' if o.debug: LOG.dbg('running cmd: {}'.format(command)) ret = cmd_importer(o) elif o.cmd_update: # update a dotfile command = 'update' if o.debug: LOG.dbg('running cmd: {}'.format(command)) ret = cmd_update(o) elif o.cmd_detail: # detail files command = 'detail' if o.debug: LOG.dbg('running cmd: {}'.format(command)) cmd_detail(o) elif o.cmd_remove: # remove dotfile command = 'remove' if o.debug: LOG.dbg('running cmd: {}'.format(command)) cmd_remove(o) except KeyboardInterrupt: LOG.err('interrupted') ret = False cmd_time = time.time() - t0 if o.debug: LOG.dbg('done executing command \"{}\"'.format(command)) LOG.dbg('options loaded in {}'.format(options_time)) LOG.dbg('command executed in {}'.format(cmd_time)) if ret and o.conf.save(): LOG.log('config file updated') if o.debug: LOG.dbg('return {}'.format(ret)) return ret
def cmd_install(o): """install dotfiles for this profile""" dotfiles = o.dotfiles if o.install_keys: # filtered dotfiles to install dotfiles = [d for d in dotfiles if d.key in set(o.install_keys)] if not dotfiles: msg = 'no dotfile to install for this profile (\"{}\")' LOG.warn(msg.format(o.profile)) return False t = Templategen(base=o.dotpath, variables=o.variables, debug=o.debug) tmpdir = None if o.install_temporary: tmpdir = get_tmpdir() inst = Installer(create=o.create, backup=o.backup, dry=o.dry, safe=o.safe, base=o.dotpath, workdir=o.workdir, diff=o.install_diff, debug=o.debug, totemp=tmpdir, showdiff=o.install_showdiff, backup_suffix=o.install_backup_suffix) installed = [] for dotfile in dotfiles: preactions = [] if not o.install_temporary and dotfile.actions \ and Cfg.key_actions_pre in dotfile.actions: for action in dotfile.actions[Cfg.key_actions_pre]: preactions.append(action) if o.debug: LOG.dbg('installing {}'.format(dotfile)) if hasattr(dotfile, 'link') and dotfile.link == LinkTypes.PARENTS: r = inst.link(t, dotfile.src, dotfile.dst, actions=preactions) elif hasattr(dotfile, 'link') and dotfile.link == LinkTypes.CHILDREN: r = inst.link_children(t, dotfile.src, dotfile.dst, actions=preactions) else: src = dotfile.src tmp = None if dotfile.trans_r: tmp = apply_trans(o.dotpath, dotfile, debug=o.debug) if not tmp: continue src = tmp r = inst.install(t, src, dotfile.dst, actions=preactions, noempty=dotfile.noempty) if tmp: tmp = os.path.join(o.dotpath, tmp) if os.path.exists(tmp): remove(tmp) if len(r) > 0: if not o.install_temporary and \ Cfg.key_actions_post in dotfile.actions: actions = dotfile.actions[Cfg.key_actions_post] # execute action for action in actions: if o.dry: LOG.dry('would execute action: {}'.format(action)) else: if o.debug: LOG.dbg('executing post action {}'.format(action)) action.execute() installed.extend(r) if o.install_temporary: LOG.log('\nInstalled to tmp \"{}\".'.format(tmpdir)) LOG.log('\n{} dotfile(s) installed.'.format(len(installed))) return True
def _exec_command(opts): """execute command""" ret = True command = '' try: if opts.cmd_profiles: # list existing profiles command = 'profiles' LOG.dbg('running cmd: {}'.format(command)) cmd_list_profiles(opts) elif opts.cmd_files: # list files for selected profile command = 'files' LOG.dbg('running cmd: {}'.format(command)) cmd_files(opts) elif opts.cmd_install: # install the dotfiles stored in dotdrop command = 'install' LOG.dbg('running cmd: {}'.format(command)) ret = cmd_install(opts) elif opts.cmd_compare: # compare local dotfiles with dotfiles stored in dotdrop command = 'compare' LOG.dbg('running cmd: {}'.format(command)) tmp = get_tmpdir() ret = cmd_compare(opts, tmp) # clean tmp directory removepath(tmp, LOG) elif opts.cmd_import: # import dotfile(s) command = 'import' LOG.dbg('running cmd: {}'.format(command)) ret = cmd_importer(opts) elif opts.cmd_update: # update a dotfile command = 'update' LOG.dbg('running cmd: {}'.format(command)) ret = cmd_update(opts) elif opts.cmd_detail: # detail files command = 'detail' LOG.dbg('running cmd: {}'.format(command)) cmd_detail(opts) elif opts.cmd_remove: # remove dotfile command = 'remove' LOG.dbg('running cmd: {}'.format(command)) cmd_remove(opts) except KeyboardInterrupt: LOG.err('interrupted') ret = False return ret, command
def cmd_install(o): """install dotfiles for this profile""" dotfiles = o.dotfiles prof = o.conf.get_profile() adapt_workers(o, LOG) pro_pre_actions = prof.get_pre_actions() if prof else [] pro_post_actions = prof.get_post_actions() if prof else [] if o.install_keys: # filtered dotfiles to install uniq = uniq_list(o.install_keys) dotfiles = [d for d in dotfiles if d.key in uniq] if not dotfiles: msg = 'no dotfile to install for this profile (\"{}\")' LOG.warn(msg.format(o.profile)) return False # the installer tmpdir = None if o.install_temporary: tmpdir = get_tmpdir() installed = [] # execute profile pre-action if o.debug: LOG.dbg('run {} profile pre actions'.format(len(pro_pre_actions))) t = _get_templater(o) ret, err = action_executor(o, pro_pre_actions, [], t, post=False)() if not ret: return False # install each dotfile if o.workers > 1: # in parallel if o.debug: LOG.dbg('run with {} workers'.format(o.workers)) ex = futures.ThreadPoolExecutor(max_workers=o.workers) wait_for = [] for dotfile in dotfiles: j = ex.submit(_dotfile_install, o, dotfile, tmpdir=tmpdir) wait_for.append(j) # check result for f in futures.as_completed(wait_for): r, key, err = f.result() if r: installed.append(key) elif err: LOG.err('installing \"{}\" failed: {}'.format(key, err)) else: # sequentially for dotfile in dotfiles: r, key, err = _dotfile_install(o, dotfile, tmpdir=tmpdir) # check result if r: installed.append(key) elif err: LOG.err('installing \"{}\" failed: {}'.format(key, err)) # execute profile post-action if len(installed) > 0 or o.install_force_action: if o.debug: msg = 'run {} profile post actions' LOG.dbg(msg.format(len(pro_post_actions))) ret, err = action_executor(o, pro_post_actions, [], t, post=False)() if not ret: return False if o.debug: LOG.dbg('install done: installed \"{}\"'.format(','.join(installed))) if o.install_temporary: LOG.log('\ninstalled to tmp \"{}\".'.format(tmpdir)) LOG.log('\n{} dotfile(s) installed.'.format(len(installed))) return True
def cmd_install(opts): """install dotfiles for this profile""" dotfiles = opts.dotfiles prof = opts.conf.get_profile() adapt_workers(opts, LOG) pro_pre_actions = prof.get_pre_actions() if prof else [] pro_post_actions = prof.get_post_actions() if prof else [] if opts.install_keys: # filtered dotfiles to install uniq = uniq_list(opts.install_keys) dotfiles = [d for d in dotfiles if d.key in uniq] if not dotfiles: msg = 'no dotfile to install for this profile (\"{}\")' LOG.warn(msg.format(opts.profile)) return False LOG.dbg('dotfiles registered for install: {}'.format( [k.key for k in dotfiles])) # the installer tmpdir = None if opts.install_temporary: tmpdir = get_tmpdir() installed = [] # clear the workdir if opts.install_clear_workdir and not opts.dry: LOG.dbg('clearing the workdir under {}'.format(opts.workdir)) for root, _, files in os.walk(opts.workdir): for file in files: fpath = os.path.join(root, file) removepath(fpath, logger=LOG) # execute profile pre-action LOG.dbg('run {} profile pre actions'.format(len(pro_pre_actions))) templ = _get_templater(opts) ret, _ = action_executor(opts, pro_pre_actions, [], templ, post=False)() if not ret: return False # install each dotfile if opts.workers > 1: # in parallel LOG.dbg('run with {} workers'.format(opts.workers)) ex = futures.ThreadPoolExecutor(max_workers=opts.workers) wait_for = [] for dotfile in dotfiles: j = ex.submit(_dotfile_install, opts, dotfile, tmpdir=tmpdir) wait_for.append(j) # check result for fut in futures.as_completed(wait_for): tmpret, key, err = fut.result() # check result if tmpret: installed.append(key) elif err: LOG.err('installing \"{}\" failed: {}'.format(key, err)) else: # sequentially for dotfile in dotfiles: tmpret, key, err = _dotfile_install(opts, dotfile, tmpdir=tmpdir) # check result if tmpret: installed.append(key) elif err: LOG.err('installing \"{}\" failed: {}'.format(key, err)) # execute profile post-action if len(installed) > 0 or opts.install_force_action: msg = 'run {} profile post actions' LOG.dbg(msg.format(len(pro_post_actions))) ret, _ = action_executor(opts, pro_post_actions, [], templ, post=False)() if not ret: return False LOG.dbg('install done: installed \"{}\"'.format(','.join(installed))) if opts.install_temporary: LOG.log('\ninstalled to tmp \"{}\".'.format(tmpdir)) LOG.log('\n{} dotfile(s) installed.'.format(len(installed))) return True
def cmd_install(o): """install dotfiles for this profile""" dotfiles = o.dotfiles prof = o.conf.get_profile() pro_pre_actions = prof.get_pre_actions() if prof else [] pro_post_actions = prof.get_post_actions() if prof else [] if o.install_keys: # filtered dotfiles to install uniq = uniq_list(o.install_keys) dotfiles = [d for d in dotfiles if d.key in uniq] if not dotfiles: msg = 'no dotfile to install for this profile (\"{}\")' LOG.warn(msg.format(o.profile)) return False t = Templategen(base=o.dotpath, variables=o.variables, func_file=o.func_file, filter_file=o.filter_file, debug=o.debug) tmpdir = None if o.install_temporary: tmpdir = get_tmpdir() inst = Installer(create=o.create, backup=o.backup, dry=o.dry, safe=o.safe, base=o.dotpath, workdir=o.workdir, diff=o.install_diff, debug=o.debug, totemp=tmpdir, showdiff=o.install_showdiff, backup_suffix=o.install_backup_suffix, diff_cmd=o.diff_command) installed = 0 tvars = t.add_tmp_vars() # execute profile pre-action if o.debug: LOG.dbg('run {} profile pre actions'.format(len(pro_pre_actions))) ret, err = action_executor(o, pro_pre_actions, [], t, post=False)() if not ret: return False # install each dotfile for dotfile in dotfiles: # add dotfile variables t.restore_vars(tvars) newvars = dotfile.get_dotfile_variables() t.add_tmp_vars(newvars=newvars) preactions = [] if not o.install_temporary: preactions.extend(dotfile.get_pre_actions()) defactions = o.install_default_actions_pre pre_actions_exec = action_executor(o, preactions, defactions, t, post=False) if o.debug: LOG.dbg('installing dotfile: \"{}\"'.format(dotfile.key)) LOG.dbg(dotfile.prt()) if hasattr(dotfile, 'link') and dotfile.link == LinkTypes.LINK: r, err = inst.link(t, dotfile.src, dotfile.dst, actionexec=pre_actions_exec) elif hasattr(dotfile, 'link') and \ dotfile.link == LinkTypes.LINK_CHILDREN: r, err = inst.link_children(t, dotfile.src, dotfile.dst, actionexec=pre_actions_exec) else: src = dotfile.src tmp = None if dotfile.trans_r: tmp = apply_trans(o.dotpath, dotfile, t, debug=o.debug) if not tmp: continue src = tmp ignores = list(set(o.install_ignore + dotfile.instignore)) ignores = patch_ignores(ignores, dotfile.dst, debug=o.debug) r, err = inst.install(t, src, dotfile.dst, actionexec=pre_actions_exec, noempty=dotfile.noempty, ignore=ignores) if tmp: tmp = os.path.join(o.dotpath, tmp) if os.path.exists(tmp): remove(tmp) if r: # dotfile was installed if not o.install_temporary: defactions = o.install_default_actions_post postactions = dotfile.get_post_actions() post_actions_exec = action_executor(o, postactions, defactions, t, post=True) post_actions_exec() installed += 1 elif not r: # dotfile was NOT installed if o.install_force_action: # pre-actions if o.debug: LOG.dbg('force pre action execution ...') pre_actions_exec() # post-actions if o.debug: LOG.dbg('force post action execution ...') postactions = dotfile.get_post_actions() post_actions_exec = action_executor(o, postactions, defactions, t, post=True) post_actions_exec() if err: LOG.err('installing \"{}\" failed: {}'.format( dotfile.key, err)) # execute profile post-action if installed > 0 or o.install_force_action: if o.debug: msg = 'run {} profile post actions' LOG.dbg(msg.format(len(pro_post_actions))) ret, err = action_executor(o, pro_post_actions, [], t, post=False)() if not ret: return False if o.debug: LOG.dbg('install done') if o.install_temporary: LOG.log('\ninstalled to tmp \"{}\".'.format(tmpdir)) LOG.log('\n{} dotfile(s) installed.'.format(installed)) return True
def main(): """entry point""" try: o = Options() except YamlException as e: LOG.err('config file error: {}'.format(str(e))) return False if o.debug: LOG.dbg('\n\n') # check dependencies are met try: dependencies_met() except Exception as e: LOG.err(e) return False ret = True try: if o.cmd_profiles: # list existing profiles if o.debug: LOG.dbg('running cmd: profiles') cmd_list_profiles(o) elif o.cmd_files: # list files for selected profile if o.debug: LOG.dbg('running cmd: files') cmd_list_files(o) elif o.cmd_install: # install the dotfiles stored in dotdrop if o.debug: LOG.dbg('running cmd: install') ret = cmd_install(o) elif o.cmd_compare: # compare local dotfiles with dotfiles stored in dotdrop if o.debug: LOG.dbg('running cmd: compare') tmp = get_tmpdir() ret = cmd_compare(o, tmp) # clean tmp directory remove(tmp) elif o.cmd_import: # import dotfile(s) if o.debug: LOG.dbg('running cmd: import') ret = cmd_importer(o) elif o.cmd_update: # update a dotfile if o.debug: LOG.dbg('running cmd: update') ret = cmd_update(o) elif o.cmd_detail: # detail files if o.debug: LOG.dbg('running cmd: detail') cmd_detail(o) elif o.cmd_remove: # remove dotfile if o.debug: LOG.dbg('running cmd: remove') cmd_remove(o) except KeyboardInterrupt: LOG.err('interrupted') ret = False if ret and o.conf.save(): LOG.log('config file updated') return ret
def cmd_install(opts, conf, temporary=False, keys=[]): """install dotfiles for this profile""" dotfiles = conf.get_dotfiles(opts['profile']) if keys: # filtered dotfiles to install dotfiles = [d for d in dotfiles if d.key in set(keys)] if not dotfiles: msg = 'no dotfile to install for this profile (\"{}\")' LOG.warn(msg.format(opts['profile'])) return False t = Templategen(base=opts['dotpath'], variables=opts['variables'], debug=opts['debug']) tmpdir = None if temporary: tmpdir = get_tmpdir() inst = Installer(create=opts['create'], backup=opts['backup'], dry=opts['dry'], safe=opts['safe'], base=opts['dotpath'], workdir=opts['workdir'], diff=opts['installdiff'], debug=opts['debug'], totemp=tmpdir, showdiff=opts['showdiff']) installed = [] for dotfile in dotfiles: preactions = [] if not temporary and dotfile.actions \ and Cfg.key_actions_pre in dotfile.actions: for action in dotfile.actions[Cfg.key_actions_pre]: preactions.append(action) if opts['debug']: LOG.dbg('installing {}'.format(dotfile)) if hasattr(dotfile, 'link') and dotfile.link == LinkTypes.PARENTS: r = inst.link(t, dotfile.src, dotfile.dst, actions=preactions) elif hasattr(dotfile, 'link') and dotfile.link == LinkTypes.CHILDREN: r = inst.linkall(t, dotfile.src, dotfile.dst, actions=preactions) else: src = dotfile.src tmp = None if dotfile.trans_r: tmp = apply_trans(opts, dotfile) if not tmp: continue src = tmp r = inst.install(t, src, dotfile.dst, actions=preactions, noempty=dotfile.noempty) if tmp: tmp = os.path.join(opts['dotpath'], tmp) if os.path.exists(tmp): remove(tmp) if len(r) > 0: if not temporary and Cfg.key_actions_post in dotfile.actions: actions = dotfile.actions[Cfg.key_actions_post] # execute action for action in actions: if opts['dry']: LOG.dry('would execute action: {}'.format(action)) else: if opts['debug']: LOG.dbg('executing post action {}'.format(action)) action.execute() installed.extend(r) if temporary: LOG.log('\nInstalled to tmp \"{}\".'.format(tmpdir)) LOG.log('\n{} dotfile(s) installed.'.format(len(installed))) return True
def main(): """entry point""" ret = True args = docopt(USAGE, version=VERSION) try: conf = Cfg(os.path.expanduser(args['--cfg']), debug=args['--verbose']) except ValueError as e: LOG.err('Config format error: {}'.format(str(e))) return False opts = conf.get_settings() opts['dry'] = args['--dry'] opts['profile'] = args['--profile'] opts['safe'] = not args['--force'] opts['debug'] = args['--verbose'] opts['installdiff'] = not args['--nodiff'] opts['link'] = LinkTypes.NOLINK if opts['link_by_default']: opts['link'] = LinkTypes.PARENTS # Only invert link type from NOLINK to PARENTS and vice-versa if args['--inv-link'] and opts['link'] == LinkTypes.NOLINK: opts['link'] = LinkTypes.PARENTS if args['--inv-link'] and opts['link'] == LinkTypes.PARENTS: opts['link'] = LinkTypes.NOLINK opts['variables'] = conf.get_variables(opts['profile'], debug=opts['debug']) opts['showdiff'] = opts['showdiff'] or args['--showdiff'] if opts['debug']: LOG.dbg('config file: {}'.format(args['--cfg'])) LOG.dbg('options:\n{}'.format(opts)) LOG.dbg('configs:\n{}'.format(conf.dump())) # resolve dynamic paths conf.eval_dotfiles(opts['profile'], opts['variables'], debug=opts['debug']) if ENV_NOBANNER not in os.environ \ and opts['banner'] \ and not args['--no-banner']: _header() try: if args['list']: # list existing profiles if opts['debug']: LOG.dbg('running cmd: list') cmd_list_profiles(conf) elif args['listfiles']: # list files for selected profile if opts['debug']: LOG.dbg('running cmd: listfiles') cmd_list_files(opts, conf, templateonly=args['--template']) elif args['install']: # install the dotfiles stored in dotdrop if opts['debug']: LOG.dbg('running cmd: install') ret = cmd_install(opts, conf, temporary=args['--temp'], keys=args['<key>']) elif args['compare']: # compare local dotfiles with dotfiles stored in dotdrop if opts['debug']: LOG.dbg('running cmd: compare') tmp = get_tmpdir() opts['dopts'] = args['--dopts'] ret = cmd_compare(opts, conf, tmp, focus=args['--file'], ignore=args['--ignore']) # clean tmp directory remove(tmp) elif args['import']: # import dotfile(s) if opts['debug']: LOG.dbg('running cmd: import') ret = cmd_importer(opts, conf, args['<path>']) elif args['update']: # update a dotfile if opts['debug']: LOG.dbg('running cmd: update') iskey = args['--key'] ret = cmd_update(opts, conf, args['<path>'], iskey=iskey, ignore=args['--ignore'], showpatch=args['--show-patch']) elif args['detail']: # detail files if opts['debug']: LOG.dbg('running cmd: update') cmd_detail(opts, conf, keys=args['<key>']) except KeyboardInterrupt: LOG.err('interrupted') ret = False if opts['debug']: LOG.dbg('configs:\n{}'.format(conf.dump())) return ret