Ejemplo n.º 1
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
Ejemplo n.º 2
0
    def _prepare_hierarchy(self, src, dst):
        """prepare hierarchy for dotfile"""
        srcf = os.path.join(self.dotpath, src)
        if self._ignore(srcf):
            return False

        srcfd = os.path.dirname(srcf)
        if self._ignore(srcfd):
            return False

        # a dotfile in dotpath already exists at that spot
        if os.path.exists(srcf):
            if self.safe:
                c = Comparator(debug=self.debug, diff_cmd=self.diff_cmd)
                diff = c.compare(srcf, dst)
                if diff != '':
                    # files are different, dunno what to do
                    self.log.log('diff \"{}\" VS \"{}\"'.format(dst, srcf))
                    self.log.emph(diff)
                    # ask user
                    msg = 'Dotfile \"{}\" already exists, overwrite?'
                    if not self.log.ask(msg.format(srcf)):
                        return False
                    if self.debug:
                        self.log.dbg('will overwrite existing file')

        # create directory hierarchy
        if self.dry:
            cmd = 'mkdir -p {}'.format(srcfd)
            self.log.dry('would run: {}'.format(cmd))
        else:
            try:
                os.makedirs(srcfd, exist_ok=True)
            except Exception:
                self.log.err('importing \"{}\" failed!'.format(dst))
                return False

        if self.dry:
            self.log.dry('would copy {} to {}'.format(dst, srcf))
        else:
            # copy the file to the dotpath
            try:
                if os.path.isdir(dst):
                    if os.path.exists(srcf):
                        shutil.rmtree(srcf)
                    ig = shutil.ignore_patterns(*self.ignore)
                    shutil.copytree(dst,
                                    srcf,
                                    copy_function=self._cp,
                                    ignore=ig)
                else:
                    shutil.copy2(dst, srcf)
            except shutil.Error as e:
                src = e.args[0][0][0]
                why = e.args[0][0][2]
                self.log.err('importing \"{}\" failed: {}'.format(src, why))

        return True
Ejemplo n.º 3
0
 def _diff_before_write(self, src, dst):
     """diff before writing when using --showdiff - not efficient"""
     # create tmp to diff for templates
     comp = Comparator(debug=self.debug)
     diff = comp.compare(src, dst)
     # fake the output for readability
     if not diff:
         return
     self.log.log('diff \"{}\" VS \"{}\"'.format(src, dst))
     self.log.emph(diff)
Ejemplo n.º 4
0
 def _diff_before_write(self, src, dst, src_content):
     """diff before writing when using --showdiff - not efficient"""
     # create tmp to diff for templates
     tmpfile = utils.get_tmpfile()
     with open(tmpfile, 'wb') as f:
         f.write(src_content)
     comp = Comparator(debug=self.debug)
     diff = comp.compare(tmpfile, dst)
     # fake the output for readability
     self.log.log('diff \"{}\" VS \"{}\"'.format(src, dst))
     self.log.emph(diff)
     if tmpfile:
         utils.remove(tmpfile)
Ejemplo n.º 5
0
 def _prepare_hier_when_exists(self, srcf, dst):
     """a dotfile in dotpath already exists at that spot"""
     if not os.path.exists(srcf):
         return True
     if not self.safe:
         return True
     cmp = Comparator(debug=self.debug, diff_cmd=self.diff_cmd)
     diff = cmp.compare(srcf, dst)
     if diff != '':
         # files are different, dunno what to do
         self.log.log('diff \"{}\" VS \"{}\"'.format(dst, srcf))
         self.log.emph(diff)
         # ask user
         msg = 'Dotfile \"{}\" already exists, overwrite?'
         if not self.log.ask(msg.format(srcf)):
             return False
         self.log.dbg('will overwrite existing file')
     return True
Ejemplo n.º 6
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
Ejemplo n.º 7
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
Ejemplo n.º 8
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
Ejemplo n.º 9
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
Ejemplo n.º 10
0
def cmd_importer(o):
    """import dotfile(s) from paths"""
    ret = True
    cnt = 0
    paths = o.import_path
    for path in paths:
        if o.debug:
            LOG.dbg('trying to import {}'.format(path))
        if not os.path.exists(path):
            LOG.err('\"{}\" does not exist, ignored!'.format(path))
            ret = False
            continue
        dst = path.rstrip(os.sep)
        dst = os.path.abspath(dst)

        src = strip_home(dst)
        if o.import_as:
            # handle import as
            src = os.path.expanduser(o.import_as)
            src = src.rstrip(os.sep)
            src = os.path.abspath(src)
            src = strip_home(src)
            if o.debug:
                LOG.dbg('import src for {} as {}'.format(dst, src))

        strip = '.' + os.sep
        if o.keepdot:
            strip = os.sep
        src = src.lstrip(strip)

        # set the link attribute
        linktype = o.import_link
        if linktype == LinkTypes.LINK_CHILDREN and \
                not os.path.isdir(path):
            LOG.err('importing \"{}\" failed!'.format(path))
            ret = False
            continue

        if o.debug:
            LOG.dbg('import dotfile: src:{} dst:{}'.format(src, dst))

        # test no other dotfile exists with same
        # dst for this profile but different src
        dfs = o.conf.get_dotfile_by_dst(dst)
        if dfs:
            invalid = False
            for df in dfs:
                profiles = o.conf.get_profiles_by_dotfile_key(df.key)
                profiles = [x.key for x in profiles]
                if o.profile in profiles and \
                        not o.conf.get_dotfile_by_src_dst(src, dst):
                    # same profile
                    # different src
                    LOG.err('duplicate dotfile for this profile')
                    ret = False
                    invalid = True
                    break
            if invalid:
                continue

        # prepare hierarchy for dotfile
        srcf = os.path.join(o.dotpath, src)
        overwrite = not os.path.exists(srcf)
        if os.path.exists(srcf):
            overwrite = True
            if o.safe:
                c = Comparator(debug=o.debug, diff_cmd=o.diff_command)
                diff = c.compare(srcf, dst)
                if diff != '':
                    # files are different, dunno what to do
                    LOG.log('diff \"{}\" VS \"{}\"'.format(dst, srcf))
                    LOG.emph(diff)
                    # ask user
                    msg = 'Dotfile \"{}\" already exists, overwrite?'
                    overwrite = LOG.ask(msg.format(srcf))

        if o.debug:
            LOG.dbg('will overwrite: {}'.format(overwrite))
        if overwrite:
            cmd = ['mkdir', '-p', '{}'.format(os.path.dirname(srcf))]
            if o.dry:
                LOG.dry('would run: {}'.format(' '.join(cmd)))
            else:
                r, _ = run(cmd, raw=False, debug=o.debug, checkerr=True)
                if not r:
                    LOG.err('importing \"{}\" failed!'.format(path))
                    ret = False
                    continue
            if o.dry:
                LOG.dry('would copy {} to {}'.format(dst, srcf))
            else:
                if os.path.isdir(dst):
                    if os.path.exists(srcf):
                        shutil.rmtree(srcf)
                    shutil.copytree(dst, srcf)
                else:
                    shutil.copy2(dst, srcf)
        retconf = o.conf.new(src, dst, linktype)
        if retconf:
            LOG.sub('\"{}\" imported'.format(path))
            cnt += 1
        else:
            LOG.warn('\"{}\" ignored'.format(path))
    if o.dry:
        LOG.dry('new config file would be:')
        LOG.raw(o.conf.dump())
    else:
        o.conf.save()
    LOG.log('\n{} file(s) imported.'.format(cnt))
    return ret
Ejemplo n.º 11
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
Ejemplo n.º 12
0
def cmd_importer(o):
    """import dotfile(s) from paths"""
    ret = True
    cnt = 0
    paths = o.import_path
    for path in paths:
        if o.debug:
            LOG.dbg('trying to import {}'.format(path))
        if not os.path.exists(path):
            LOG.err('\"{}\" does not exist, ignored!'.format(path))
            ret = False
            continue
        dst = path.rstrip(os.sep)
        dst = os.path.abspath(dst)
        src = strip_home(dst)
        strip = '.' + os.sep
        if o.keepdot:
            strip = os.sep
        src = src.lstrip(strip)

        # set the link attribute
        linktype = o.import_link
        if linktype == LinkTypes.LINK_CHILDREN and \
                not os.path.isdir(path):
            LOG.err('importing \"{}\" failed!'.format(path))
            ret = False
            continue

        if o.debug:
            LOG.dbg('new dotfile: src:{} dst:{}'.format(src, dst))

        # prepare hierarchy for dotfile
        srcf = os.path.join(o.dotpath, src)
        overwrite = not os.path.exists(srcf)
        if os.path.exists(srcf):
            overwrite = True
            if o.safe:
                c = Comparator(debug=o.debug)
                diff = c.compare(srcf, dst)
                if diff != '':
                    # files are different, dunno what to do
                    LOG.log('diff \"{}\" VS \"{}\"'.format(dst, srcf))
                    LOG.emph(diff)
                    # ask user
                    msg = 'Dotfile \"{}\" already exists, overwrite?'
                    overwrite = LOG.ask(msg.format(srcf))

        if o.debug:
            LOG.dbg('will overwrite: {}'.format(overwrite))
        if overwrite:
            cmd = ['mkdir', '-p', '{}'.format(os.path.dirname(srcf))]
            if o.dry:
                LOG.dry('would run: {}'.format(' '.join(cmd)))
            else:
                r, _ = run(cmd, raw=False, debug=o.debug, checkerr=True)
                if not r:
                    LOG.err('importing \"{}\" failed!'.format(path))
                    ret = False
                    continue
            cmd = ['cp', '-R', '-L', dst, srcf]
            if o.dry:
                LOG.dry('would run: {}'.format(' '.join(cmd)))
            else:
                r, _ = run(cmd, raw=False, debug=o.debug, checkerr=True)
                if not r:
                    LOG.err('importing \"{}\" failed!'.format(path))
                    ret = False
                    continue
        retconf = o.conf.new(src, dst, linktype, o.profile)
        if retconf:
            LOG.sub('\"{}\" imported'.format(path))
            cnt += 1
        else:
            LOG.warn('\"{}\" ignored'.format(path))
    if o.dry:
        LOG.dry('new config file would be:')
        LOG.raw(o.conf.dump())
    else:
        o.conf.save()
    LOG.log('\n{} file(s) imported.'.format(cnt))
    return ret
Ejemplo n.º 13
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