Пример #1
0
    def test_link_children(self):

        # create source dir
        src_dir = get_tempdir()
        self.assertTrue(os.path.exists(src_dir))
        self.addCleanup(clean, src_dir)

        # where dotfiles will be installed
        dst_dir = get_tempdir()
        self.assertTrue(os.path.exists(dst_dir))
        self.addCleanup(clean, dst_dir)

        # create 3 random files in source
        srcs = [create_random_file(src_dir)[0] for _ in range(3)]

        installer = Installer()
        installer.linkall(templater=MagicMock(),
                          src=src_dir,
                          dst=dst_dir,
                          actions=[])

        # Ensure all destination files point to source
        for src in srcs:
            dst = os.path.join(dst_dir, src)
            self.assertEqual(os.path.realpath(dst), src)
Пример #2
0
    def test_fails_when_src_file(self):

        # create source dir
        src_dir = get_tempdir()
        self.assertTrue(os.path.exists(src_dir))
        self.addCleanup(clean, src_dir)

        src = create_random_file(src_dir)[0]

        logger = MagicMock()
        templater = MagicMock()
        installer = Installer()
        installer.log.err = logger

        # pass src file not src dir
        res = installer.linkall(templater=templater,
                                src=src,
                                dst='/dev/null',
                                actions=[])

        # ensure nothing performed
        self.assertEqual(res, [])
        # ensure logger logged error
        logger.assert_called_with(
            'source dotfile is not a directory: {}'.format(src))
Пример #3
0
    def test_runs_templater(self):
        """test runs templater"""
        # create source dir
        src_dir = get_tempdir()
        self.assertTrue(os.path.exists(src_dir))
        self.addCleanup(clean, src_dir)

        # where dotfiles will be installed
        dst_dir = get_tempdir()
        self.assertTrue(os.path.exists(dst_dir))
        self.addCleanup(clean, dst_dir)

        # create 3 random files in source
        srcs = [create_random_file(src_dir)[0] for _ in range(3)]

        # setup installer and mocks
        installer = Installer()
        templater = MagicMock()
        templater.generate.return_value = b'content'

        installer.install(templater=templater,
                          src=src_dir,
                          dst=dst_dir,
                          linktype=LinkTypes.LINK_CHILDREN,
                          actionexec=None)

        for src in srcs:
            dst = os.path.join(dst_dir, os.path.basename(src))

            # ensure dst is link
            self.assertTrue(os.path.islink(dst))
            # ensure dst not directly linked to src
            self.assertNotEqual(os.path.realpath(dst), src)
Пример #4
0
    def test_fails_when_src_file(self):
        """test fails when src file"""
        # create source dir
        src_dir = get_tempdir()
        self.assertTrue(os.path.exists(src_dir))
        self.addCleanup(clean, src_dir)

        src = create_random_file(src_dir)[0]

        # logger = MagicMock()
        templater = MagicMock()
        installer = Installer()
        # installer.log.err = logger

        # pass src file not src dir
        res, err = installer.install(templater=templater,
                                     src=src,
                                     dst='/dev/null',
                                     linktype=LinkTypes.LINK_CHILDREN,
                                     actionexec=None)

        # ensure nothing performed
        self.assertFalse(res)
        e = 'source dotfile is not a directory: {}'.format(src)
        self.assertEqual(err, e)
Пример #5
0
 def compare(self, opts, conf, tmp, nbdotfiles):
     dotfiles = conf.get_dotfiles(opts['profile'])
     self.assertTrue(len(dotfiles) == nbdotfiles)
     t = Templategen(base=opts['dotpath'], debug=True)
     inst = Installer(create=opts['create'],
                      backup=opts['backup'],
                      dry=opts['dry'],
                      base=opts['dotpath'],
                      debug=True)
     comp = Comparator()
     results = {}
     for dotfile in dotfiles:
         ret, insttmp = inst.install_to_temp(t, tmp, dotfile.src,
                                             dotfile.dst)
         if not ret:
             results[path] = False
             continue
         diff = comp.compare(insttmp,
                             dotfile.dst,
                             ignore=['whatever', 'whatelse'])
         print('XXXX diff for {} and {}:\n{}'.format(
             dotfile.src, dotfile.dst, diff))
         path = os.path.expanduser(dotfile.dst)
         results[path] = diff == ''
     return results
Пример #6
0
    def test_runs_templater(self, mocked_templategen):

        # create source dir
        src_dir = get_tempdir()
        self.assertTrue(os.path.exists(src_dir))
        self.addCleanup(clean, src_dir)

        # where dotfiles will be installed
        dst_dir = get_tempdir()
        self.assertTrue(os.path.exists(dst_dir))
        self.addCleanup(clean, dst_dir)

        # create 3 random files in source
        srcs = [create_random_file(src_dir)[0] for _ in range(3)]

        # setup installer and mocks
        installer = Installer()
        templater = MagicMock()
        templater.generate.return_value = b'content'
        # make templategen treat everything as a template
        mocked_templategen.is_template.return_value = True

        installer.linkall(templater=templater,
                          src=src_dir,
                          dst=dst_dir,
                          actions=[])

        for src in srcs:
            dst = os.path.join(dst_dir, os.path.basename(src))

            # ensure dst is link
            self.assertTrue(os.path.islink(dst))
            # ensure dst not directly linked to src
            # TODO: maybe check that its actually linked to template folder
            self.assertNotEqual(os.path.realpath(dst), src)
Пример #7
0
def install(opts, conf):
    """install all dotfiles for this profile"""
    dotfiles = conf.get_dotfiles(opts['profile'])
    if dotfiles == []:
        msg = 'no dotfiles defined for this profile (\"{}\")'
        LOG.err(msg.format(opts['profile']))
        return False
    t = Templategen(base=opts['dotpath'], debug=opts['debug'])
    inst = Installer(create=opts['create'],
                     backup=opts['backup'],
                     dry=opts['dry'],
                     safe=opts['safe'],
                     base=opts['dotpath'],
                     diff=opts['installdiff'],
                     debug=opts['debug'])
    installed = []
    for dotfile in dotfiles:
        if dotfile.actions and Cfg.key_actions_pre in dotfile.actions:
            for action in dotfile.actions[Cfg.key_actions_pre]:
                if opts['dry']:
                    LOG.dry('would execute action: {}'.format(action))
                else:
                    if opts['debug']:
                        LOG.dbg('executing pre action {}'.format(action))
                    action.execute()
        if opts['debug']:
            LOG.dbg('installing {}'.format(dotfile))
        if hasattr(dotfile, 'link') and dotfile.link:
            r = inst.link(dotfile.src, dotfile.dst)
        else:
            src = dotfile.src
            tmp = None
            if dotfile.trans:
                tmp = apply_trans(opts, dotfile)
                if not tmp:
                    continue
                src = tmp
            r = inst.install(t, opts['profile'], src, dotfile.dst)
            if tmp:
                tmp = os.path.join(opts['dotpath'], tmp)
                if os.path.exists(tmp):
                    remove(tmp)
        if len(r) > 0:
            if 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)
    LOG.log('\n{} dotfile(s) installed.'.format(len(installed)))
    return True
Пример #8
0
 def compare(self, opts, conf, tmp, nbdotfiles):
     dotfiles = conf.get_dotfiles(opts['profile'])
     self.assertTrue(len(dotfiles) == nbdotfiles)
     t = Templategen(base=opts['dotpath'])
     inst = Installer(create=opts['create'], backup=opts['backup'],
                      dry=opts['dry'], base=opts['dotpath'], quiet=True)
     results = {}
     for dotfile in dotfiles:
         same, _ = inst.compare(t, tmp, opts['profile'],
                                dotfile.src, dotfile.dst)
         path = os.path.expanduser(dotfile.dst)
         results[path] = same
     return results
Пример #9
0
 def compare(self, opts, conf, tmp, nbdotfiles):
     dotfiles = conf.get_dotfiles(opts['profile'])
     self.assertTrue(len(dotfiles) == nbdotfiles)
     t = Templategen(base=opts['dotpath'])
     inst = Installer(create=opts['create'], backup=opts['backup'],
                      dry=opts['dry'], base=opts['dotpath'], quiet=True)
     results = {}
     for dotfile in dotfiles:
         same, _ = inst.compare(t, tmp, opts['profile'],
                                dotfile.src, dotfile.dst)
         path = os.path.expanduser(dotfile.dst)
         results[path] = same
     return results
Пример #10
0
    def test_fails_without_src(self):
        """test fails without src"""
        src = '/some/non/existant/file'

        installer = Installer()
        logger = MagicMock()
        installer.log.err = logger

        res = installer.link_children(templater=MagicMock(), src=src,
                                      dst='/dev/null', actions=[])

        self.assertEqual(res, [])
        logger.assert_called_with('source dotfile does not exist: {}'
                                  .format(src))
Пример #11
0
    def test_fails_without_src(self):
        """test fails without src"""
        src = '/some/non/existant/file'

        installer = Installer()
        # logger = MagicMock()
        # installer.log.err = logger

        res, err = installer.link_children(templater=MagicMock(), src=src,
                                           dst='/dev/null', actionexec=None)

        self.assertFalse(res)
        e = 'source dotfile does not exist: {}'.format(src)
        self.assertEqual(err, e)
Пример #12
0
 def compare(self, o, tmp, nbdotfiles):
     dotfiles = o.dotfiles
     self.assertTrue(len(dotfiles) == nbdotfiles)
     t = Templategen(base=o.dotpath, debug=True)
     inst = Installer(create=o.create, backup=o.backup,
                      dry=o.dry, base=o.dotpath, debug=o.debug)
     comp = Comparator()
     results = {}
     for dotfile in dotfiles:
         path = os.path.expanduser(dotfile.dst)
         ret, insttmp = inst.install_to_temp(t, tmp, dotfile.src,
                                             dotfile.dst)
         if not ret:
             results[path] = False
             continue
         diff = comp.compare(insttmp, dotfile.dst,
                             ignore=['whatever', 'whatelse'])
         results[path] = diff == ''
     return results
Пример #13
0
    def test_creates_dst(self):
        """test creates dst"""
        src_dir = get_tempdir()
        self.assertTrue(os.path.exists(src_dir))
        self.addCleanup(clean, src_dir)

        # where dotfiles will be installed
        dst_dir = get_tempdir()
        self.addCleanup(clean, dst_dir)

        # move dst dir to new (uncreated) dir in dst
        dst_dir = os.path.join(dst_dir, get_string(6))
        self.assertFalse(os.path.exists(dst_dir))

        installer = Installer()
        installer.link_children(templater=MagicMock(), src=src_dir,
                                dst=dst_dir, actionexec=None)

        # ensure dst dir created
        self.assertTrue(os.path.exists(dst_dir))
Пример #14
0
def _get_install_installer(o, tmpdir=None):
    """get an installer instance for cmd_install"""
    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)
    return inst
Пример #15
0
    def test_prompts_to_replace_dst(self):
        """test prompts to replace dst"""
        # create source dir
        src_dir = get_tempdir()
        self.assertTrue(os.path.exists(src_dir))
        self.addCleanup(clean, src_dir)

        # where dotfiles will be installed
        dst_dir = get_tempdir()
        self.addCleanup(clean, dst_dir)

        # Create destination file to be replaced
        dst = os.path.join(dst_dir, get_string(6))
        with open(dst, 'w'):
            pass
        self.assertTrue(os.path.isfile(dst))

        # setup mocks
        ask = MagicMock()
        ask.return_value = True

        # setup installer
        installer = Installer()
        installer.safe = True
        installer.log.ask = ask

        installer.install(templater=MagicMock(),
                          src=src_dir,
                          dst=dst,
                          linktype=LinkTypes.LINK_CHILDREN,
                          actionexec=None)

        # ensure destination now a directory
        self.assertTrue(os.path.isdir(dst))

        # ensure prompted
        ask.assert_called_with(
            'Remove regular file {} and replace with empty directory?'.format(
                dst))
Пример #16
0
def cmd_compare(o, tmp):
    """compare dotfiles and return True if all identical"""
    dotfiles = o.dotfiles
    if not dotfiles:
        msg = 'no dotfile defined for this profile (\"{}\")'
        LOG.warn(msg.format(o.profile))
        return True
    # compare only specific files
    same = True
    selected = dotfiles
    if o.compare_focus:
        selected = _select(o.compare_focus, dotfiles)

    if len(selected) < 1:
        return False

    t = Templategen(base=o.dotpath,
                    variables=o.variables,
                    func_file=o.func_file,
                    filter_file=o.filter_file,
                    debug=o.debug)
    tvars = t.add_tmp_vars()
    inst = Installer(create=o.create,
                     backup=o.backup,
                     dry=o.dry,
                     base=o.dotpath,
                     workdir=o.workdir,
                     debug=o.debug,
                     backup_suffix=o.install_backup_suffix,
                     diff_cmd=o.diff_command)
    comp = Comparator(diff_cmd=o.diff_command, debug=o.debug)

    for dotfile in selected:
        if not dotfile.src and not dotfile.dst:
            # ignore fake dotfile
            continue
        # add dotfile variables
        t.restore_vars(tvars)
        newvars = dotfile.get_dotfile_variables()
        t.add_tmp_vars(newvars=newvars)

        # dotfiles does not exist / not installed
        if o.debug:
            LOG.dbg('comparing {}'.format(dotfile))
        src = dotfile.src
        if not os.path.lexists(os.path.expanduser(dotfile.dst)):
            line = '=> compare {}: \"{}\" does not exist on destination'
            LOG.log(line.format(dotfile.key, dotfile.dst))
            same = False
            continue

        # apply transformation
        tmpsrc = None
        if dotfile.trans_r:
            if o.debug:
                LOG.dbg('applying transformation before comparing')
            tmpsrc = apply_trans(o.dotpath, dotfile, t, debug=o.debug)
            if not tmpsrc:
                # could not apply trans
                same = False
                continue
            src = tmpsrc

        # is a symlink pointing to itself
        asrc = os.path.join(o.dotpath, os.path.expanduser(src))
        adst = os.path.expanduser(dotfile.dst)
        if os.path.samefile(asrc, adst):
            if o.debug:
                line = '=> compare {}: diffing with \"{}\"'
                LOG.dbg(line.format(dotfile.key, dotfile.dst))
                LOG.dbg('points to itself')
            continue

        log_dst = dotfile.dst
        if log_dst.startswith(os.path.expanduser('~')):
            log_dst = log_dst.replace(os.path.expanduser('~'), '~', 1)

        # install dotfile to temporary dir and compare
        ret, err, insttmp = inst.install_to_temp(t,
                                                 tmp,
                                                 src,
                                                 dotfile.dst,
                                                 template=dotfile.template)
        if not ret:
            # failed to install to tmp
            line = '=> compare {}: error'
            LOG.log(line.format(dotfile.key, err))
            LOG.err(err)
            same = False
            continue
        ignores = list(set(o.compare_ignore + dotfile.cmpignore))
        ignores = patch_ignores(ignores, dotfile.dst, debug=o.debug)

        src_newer = os.path.getmtime(asrc) > os.path.getmtime(adst)

        if o.debug:
            LOG.dbg('src newer: {}'.format(src_newer))

        diff = ''
        if o.compare_target == 'local' \
                or (o.compare_target == 'smart' and not src_newer):
            diff = comp.compare(dotfile.dst, insttmp, ignore=ignores)
            diff_target = dotfile.dst
        else:
            diff = comp.compare(insttmp, dotfile.dst, ignore=ignores)
            diff_target = insttmp

        # clean tmp transformed dotfile if any
        if tmpsrc:
            tmpsrc = os.path.join(o.dotpath, tmpsrc)
            if os.path.exists(tmpsrc):
                remove(tmpsrc, LOG)

        if diff == '':
            # no difference
            if o.debug:
                line = '=> compare {}: diffing with \"{}\"'
                LOG.dbg(line.format(dotfile.src_key, log_dst))
                LOG.dbg('same file')
        else:
            # print diff results
            line = '=> compare {}: diffing with \"{}\"'
            if diff_target == dotfile.dst:
                line = line.format(log_dst, dotfile.src_key)
            else:
                line = line.format(dotfile.src_key, log_dst)
            LOG.log(line)
            if o.compare_target == 'smart':
                if src_newer:
                    LOG.sub('{} is newer'.format(dotfile.src_key))
                else:
                    LOG.sub('{} is newer'.format(log_dst))
            if not o.compare_fileonly:
                LOG.emph(diff)
            same = False

    return same
Пример #17
0
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
Пример #18
0
def cmd_compare(o, tmp):
    """compare dotfiles and return True if all identical"""
    dotfiles = o.dotfiles
    if dotfiles == []:
        msg = 'no dotfile defined for this profile (\"{}\")'
        LOG.warn(msg.format(o.profile))
        return True
    # compare only specific files
    same = True
    selected = dotfiles
    if o.compare_focus:
        selected = _select(o.compare_focus, dotfiles)

    if len(selected) < 1:
        return False

    t = Templategen(base=o.dotpath, variables=o.variables, debug=o.debug)
    inst = Installer(create=o.create,
                     backup=o.backup,
                     dry=o.dry,
                     base=o.dotpath,
                     workdir=o.workdir,
                     debug=o.debug,
                     backup_suffix=o.install_backup_suffix)
    comp = Comparator(diffopts=o.compare_dopts, debug=o.debug)

    for dotfile in selected:
        if o.debug:
            LOG.dbg('comparing {}'.format(dotfile))
        src = dotfile.src
        if not os.path.lexists(os.path.expanduser(dotfile.dst)):
            line = '=> compare {}: \"{}\" does not exist on local'
            LOG.log(line.format(dotfile.key, dotfile.dst))
            same = False
            continue

        tmpsrc = None
        if dotfile.trans_r:
            # apply transformation
            tmpsrc = apply_trans(o.dotpath, dotfile, debug=o.debug)
            if not tmpsrc:
                # could not apply trans
                same = False
                continue
            src = tmpsrc
        # install dotfile to temporary dir
        ret, insttmp = inst.install_to_temp(t, tmp, src, dotfile.dst)
        if not ret:
            # failed to install to tmp
            same = False
            continue
        ignores = list(set(o.compare_ignore + dotfile.cmpignore))
        diff = comp.compare(insttmp, dotfile.dst, ignore=ignores)
        if tmpsrc:
            # clean tmp transformed dotfile if any
            tmpsrc = os.path.join(o.dotpath, tmpsrc)
            if os.path.exists(tmpsrc):
                remove(tmpsrc)
        if diff == '':
            if o.debug:
                line = '=> compare {}: diffing with \"{}\"'
                LOG.dbg(line.format(dotfile.key, dotfile.dst))
                LOG.dbg('same file')
        else:
            line = '=> compare {}: diffing with \"{}\"'
            LOG.log(line.format(dotfile.key, dotfile.dst))
            LOG.emph(diff)
            same = False

    return same
Пример #19
0
def _dotfile_compare(o, dotfile, tmp):
    """
    compare a dotfile
    returns True if same
    """
    t = _get_templater(o)
    inst = Installer(create=o.create,
                     backup=o.backup,
                     dry=o.dry,
                     base=o.dotpath,
                     workdir=o.workdir,
                     debug=o.debug,
                     backup_suffix=o.install_backup_suffix,
                     diff_cmd=o.diff_command)
    comp = Comparator(diff_cmd=o.diff_command, debug=o.debug)

    # add dotfile variables
    newvars = dotfile.get_dotfile_variables()
    t.add_tmp_vars(newvars=newvars)

    # dotfiles does not exist / not installed
    if o.debug:
        LOG.dbg('comparing {}'.format(dotfile))

    src = dotfile.src
    if not os.path.lexists(os.path.expanduser(dotfile.dst)):
        line = '=> compare {}: \"{}\" does not exist on destination'
        LOG.log(line.format(dotfile.key, dotfile.dst))
        return False

    # apply transformation
    tmpsrc = None
    if dotfile.trans_r:
        if o.debug:
            LOG.dbg('applying transformation before comparing')
        tmpsrc = apply_trans(o.dotpath, dotfile, t, debug=o.debug)
        if not tmpsrc:
            # could not apply trans
            return False
        src = tmpsrc

    # is a symlink pointing to itself
    asrc = os.path.join(o.dotpath, os.path.expanduser(src))
    adst = os.path.expanduser(dotfile.dst)
    if os.path.samefile(asrc, adst):
        if o.debug:
            line = '=> compare {}: diffing with \"{}\"'
            LOG.dbg(line.format(dotfile.key, dotfile.dst))
            LOG.dbg('points to itself')
        return True

    ignores = list(set(o.compare_ignore + dotfile.cmpignore))
    ignores = patch_ignores(ignores, dotfile.dst, debug=o.debug)

    insttmp = None
    if dotfile.template and Templategen.is_template(src, ignore=ignores):
        # install dotfile to temporary dir for compare
        ret, err, insttmp = inst.install_to_temp(t,
                                                 tmp,
                                                 src,
                                                 dotfile.dst,
                                                 is_template=True,
                                                 chmod=dotfile.chmod)
        if not ret:
            # failed to install to tmp
            line = '=> compare {} error: {}'
            LOG.log(line.format(dotfile.key, err))
            LOG.err(err)
            return False
        src = insttmp

    # compare
    diff = comp.compare(src, dotfile.dst, ignore=ignores)

    # clean tmp transformed dotfile if any
    if tmpsrc:
        tmpsrc = os.path.join(o.dotpath, tmpsrc)
        if os.path.exists(tmpsrc):
            removepath(tmpsrc, LOG)

    # clean tmp template dotfile if any
    if insttmp:
        if os.path.exists(insttmp):
            removepath(insttmp, LOG)

    if diff != '':
        # print diff results
        line = '=> compare {}: diffing with \"{}\"'
        LOG.log(line.format(dotfile.key, dotfile.dst))
        if o.compare_fileonly:
            LOG.raw('<files are different>')
        else:
            LOG.emph(diff)
        return False
    # no difference
    if o.debug:
        line = '=> compare {}: diffing with \"{}\"'
        LOG.dbg(line.format(dotfile.key, dotfile.dst))
        LOG.dbg('same file')
    return True
Пример #20
0
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(profile=opts['profile'],
                    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 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:
            r = inst.link(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 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
Пример #21
0
def cmd_compare(opts, conf, tmp, focus=[], ignore=[]):
    """compare dotfiles and return True if all identical"""
    dotfiles = conf.get_dotfiles(opts['profile'])
    if dotfiles == []:
        msg = 'no dotfile defined for this profile (\"{}\")'
        LOG.warn(msg.format(opts['profile']))
        return True
    # compare only specific files
    same = True
    selected = dotfiles
    if focus:
        selected = _select(focus, dotfiles)

    if len(selected) < 1:
        return False

    t = Templategen(profile=opts['profile'],
                    base=opts['dotpath'],
                    variables=opts['variables'],
                    debug=opts['debug'])
    inst = Installer(create=opts['create'],
                     backup=opts['backup'],
                     dry=opts['dry'],
                     base=opts['dotpath'],
                     workdir=opts['workdir'],
                     debug=opts['debug'])
    comp = Comparator(diffopts=opts['dopts'], debug=opts['debug'])

    for dotfile in selected:
        if opts['debug']:
            LOG.dbg('comparing {}'.format(dotfile))
        src = dotfile.src
        if not os.path.lexists(os.path.expanduser(dotfile.dst)):
            LOG.emph('\"{}\" does not exist on local\n'.format(dotfile.dst))

        tmpsrc = None
        if dotfile.trans_r:
            # apply transformation
            tmpsrc = apply_trans(opts, dotfile)
            if not tmpsrc:
                # could not apply trans
                continue
            src = tmpsrc
        # install dotfile to temporary dir
        ret, insttmp = inst.install_to_temp(t, tmp, src, dotfile.dst)
        if not ret:
            # failed to install to tmp
            continue
        ignores = list(set(ignore + dotfile.cmpignore))
        diff = comp.compare(insttmp, dotfile.dst, ignore=ignores)
        if tmpsrc:
            # clean tmp transformed dotfile if any
            tmpsrc = os.path.join(opts['dotpath'], tmpsrc)
            if os.path.exists(tmpsrc):
                remove(tmpsrc)
        if diff == '':
            if opts['debug']:
                LOG.dbg('diffing \"{}\" VS \"{}\"'.format(
                    dotfile.key, dotfile.dst))
                LOG.dbg('same file')
        else:
            LOG.log('diffing \"{}\" VS \"{}\"'.format(dotfile.key,
                                                      dotfile.dst))
            LOG.emph(diff)
            same = False

    return same
Пример #22
0
def cmd_compare(o, tmp):
    """compare dotfiles and return True if all identical"""
    dotfiles = o.dotfiles
    if not dotfiles:
        msg = 'no dotfile defined for this profile (\"{}\")'
        LOG.warn(msg.format(o.profile))
        return True
    # compare only specific files
    same = True
    selected = dotfiles
    if o.compare_focus:
        selected = _select(o.compare_focus, dotfiles)

    if len(selected) < 1:
        return False

    t = Templategen(base=o.dotpath,
                    variables=o.variables,
                    func_file=o.func_file,
                    filter_file=o.filter_file,
                    debug=o.debug)
    tvars = t.add_tmp_vars()
    inst = Installer(create=o.create,
                     backup=o.backup,
                     dry=o.dry,
                     base=o.dotpath,
                     workdir=o.workdir,
                     debug=o.debug,
                     backup_suffix=o.install_backup_suffix,
                     diff_cmd=o.diff_command)
    comp = Comparator(diff_cmd=o.diff_command, debug=o.debug)

    for dotfile in selected:
        # add dotfile variables
        t.restore_vars(tvars)
        newvars = dotfile.get_dotfile_variables()
        t.add_tmp_vars(newvars=newvars)

        if o.debug:
            LOG.dbg('comparing {}'.format(dotfile))
        src = dotfile.src
        if not os.path.lexists(os.path.expanduser(dotfile.dst)):
            line = '=> compare {}: \"{}\" does not exist on destination'
            LOG.log(line.format(dotfile.key, dotfile.dst))
            same = False
            continue

        tmpsrc = None
        if dotfile.trans_r:
            # apply transformation
            if o.debug:
                LOG.dbg('applying transformation before comparing')
            tmpsrc = apply_trans(o.dotpath, dotfile, t, debug=o.debug)
            if not tmpsrc:
                # could not apply trans
                same = False
                continue
            src = tmpsrc

        # is a symlink pointing to itself
        asrc = os.path.join(o.dotpath, os.path.expanduser(src))
        adst = os.path.expanduser(dotfile.dst)
        if os.path.samefile(asrc, adst):
            if o.debug:
                line = '=> compare {}: diffing with \"{}\"'
                LOG.dbg(line.format(dotfile.key, dotfile.dst))
                LOG.dbg('points to itself')
            continue

        # install dotfile to temporary dir
        ret, insttmp = inst.install_to_temp(t, tmp, src, dotfile.dst)
        if not ret:
            # failed to install to tmp
            same = False
            continue
        ignores = list(set(o.compare_ignore + dotfile.cmpignore))
        ignores = patch_ignores(ignores, dotfile.dst, debug=o.debug)
        diff = comp.compare(insttmp, dotfile.dst, ignore=ignores)
        if tmpsrc:
            # clean tmp transformed dotfile if any
            tmpsrc = os.path.join(o.dotpath, tmpsrc)
            if os.path.exists(tmpsrc):
                remove(tmpsrc)
        if diff == '':
            if o.debug:
                line = '=> compare {}: diffing with \"{}\"'
                LOG.dbg(line.format(dotfile.key, dotfile.dst))
                LOG.dbg('same file')
        else:
            line = '=> compare {}: diffing with \"{}\"'
            LOG.log(line.format(dotfile.key, dotfile.dst))
            LOG.emph(diff)
            same = False

    return same
Пример #23
0
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