예제 #1
0
def _getbundle(repo, dest, **opts):
    """return a bundle containing changesets missing in "dest"

    The `opts` keyword-arguments are the same as the one accepted by the
    `bundle` command.

    The bundle is a returned as a single in-memory binary blob.
    """
    ui = repo.ui
    tmpdir = pycompat.mkdtemp(prefix=b'hg-email-bundle-')
    tmpfn = os.path.join(tmpdir, b'bundle')
    btype = ui.config(b'patchbomb', b'bundletype')
    if btype:
        opts['type'] = btype
    try:
        dests = []
        if dest:
            dests = [dest]
        commands.bundle(ui, repo, tmpfn, *dests, **opts)
        return util.readfile(tmpfn)
    finally:
        try:
            os.unlink(tmpfn)
        except OSError:
            pass
        os.rmdir(tmpdir)
예제 #2
0
    def before(self):
        self.tmppath = pycompat.mkdtemp(prefix=b'convert-' +
                                        os.path.basename(self.path) + b'-')
        output, status = self.run(b'init', repodir=self.tmppath)
        self.checkexit(status)

        tree = self.xml(b'changes',
                        xml_output=True,
                        summary=True,
                        repodir=self.path)
        tagname = None
        child = None
        for elt in tree.findall(b'patch'):
            node = elt.get(b'hash')
            name = elt.findtext(b'name', b'')
            if name.startswith(b'TAG '):
                tagname = name[4:].strip()
            elif tagname is not None:
                self.tags[tagname] = node
                tagname = None
            self.changes[node] = elt
            self.parents[child] = [node]
            child = node
        self.parents[child] = []
예제 #3
0
파일: extdiff2.py 프로젝트: bukzor/dotfiles
def dodiff(ui, repo, cmdline, pats, opts):
  """Do the actual diff."""

  revs = opts.get('rev')
  old, new = scmutil.revpair(repo, revs)

  subrepos = opts.get('subrepos')

  matcher = scmutil.match(new, pats, opts)

  status = old.status(new, matcher, listsubrepos=subrepos)
  copy = copies.pathcopies(old, new, matcher)

  mod, add, rem = map(set, status[:3])
  paths_new = mod | add
  paths_old = mod | set(copy.values())
  paths_all = paths_old | paths_new
  if not paths_all:
    return 0

  tmproot = pycompat.mkdtemp(prefix='extdiff2.')
  try:
    # Always make a copy of old
    dir_old = snapshot(ui, repo, paths_old, old.node(), tmproot, subrepos)
    dir_old = os.path.join(tmproot, dir_old)
    label_old = '@%d' % old.rev()

    # If new in not the wc, copy it
    if new.node():
      dir_new = snapshot(ui, repo, paths_new, new.node(), tmproot, subrepos)
      label_new = '@%d' % new.rev()
    else:
      # This lets the diff tool open the changed file(s) directly
      dir_new = ''
      label_new = ''

    # Diff the files instead of the directories
    # Handle bogus modifies correctly by checking if the files exist
    for path in paths_new:
      path = util.localpath(path)
      path_old = os.path.join(dir_old, copy.get(path, path))
      label_old = path + label_old
      #if not os.path.isfile(path_old):
      #path_old = os.devnull

      path_new = os.path.join(repo.root, path)
      if not dir_new:
        path_new = os.path.relpath(path_new)
      label_new = path + label_new

      # Function to quote file/dir names in the argument string.
      replace = {
          'old': path_old,
          'olabel': label_old,
          'nlabel': label_new,
          'new': path_new,
          'root': repo.root
      }

      def quote(match):
        pre = match.group(2)
        key = match.group(3)
        return pre + procutil.shellquote(replace[key])

      regex = (br"""(['"]?)([^\s'"$]*)""" br'\$(old|new|olabel|nlabel|root)\1')
      if not re.search(regex, cmdline):
        cmdline2 = cmdline + ' $old $new'
      else:
        cmdline2 = cmdline
      cmdline3 = re.sub(regex, quote, cmdline2)

      ui.write(pycompat.bytestr(cmdline3) + b'\n')
      ui.system(cmdline3, blockedtag='extdiff2')

    return 1
  finally:
    ui.note(_('cleaning up temp directory\n'))
    shutil.rmtree(tmproot)
예제 #4
0
파일: extdiff.py 프로젝트: CJX32/my_blog
def dodiff(ui, repo, cmdline, pats, opts, guitool=False):
    '''Do the actual diff:

    - copy to a temp structure if diffing 2 internal revisions
    - copy to a temp structure if diffing working revision with
      another one and more than 1 file is changed
    - just invoke the diff for a single file in the working dir
    '''

    revs = opts.get(b'rev')
    change = opts.get(b'change')
    do3way = b'$parent2' in cmdline

    if revs and change:
        msg = _(b'cannot specify --rev and --change at the same time')
        raise error.Abort(msg)
    elif change:
        ctx2 = scmutil.revsingle(repo, change, None)
        ctx1a, ctx1b = ctx2.p1(), ctx2.p2()
    else:
        ctx1a, ctx2 = scmutil.revpair(repo, revs)
        if not revs:
            ctx1b = repo[None].p2()
        else:
            ctx1b = repo[nullid]

    perfile = opts.get(b'per_file')
    confirm = opts.get(b'confirm')

    node1a = ctx1a.node()
    node1b = ctx1b.node()
    node2 = ctx2.node()

    # Disable 3-way merge if there is only one parent
    if do3way:
        if node1b == nullid:
            do3way = False

    subrepos = opts.get(b'subrepos')

    matcher = scmutil.match(repo[node2], pats, opts)

    if opts.get(b'patch'):
        if subrepos:
            raise error.Abort(_(b'--patch cannot be used with --subrepos'))
        if perfile:
            raise error.Abort(_(b'--patch cannot be used with --per-file'))
        if node2 is None:
            raise error.Abort(_(b'--patch requires two revisions'))
    else:
        mod_a, add_a, rem_a = map(
            set,
            repo.status(node1a, node2, matcher, listsubrepos=subrepos)[:3])
        if do3way:
            mod_b, add_b, rem_b = map(
                set,
                repo.status(node1b, node2, matcher, listsubrepos=subrepos)[:3],
            )
        else:
            mod_b, add_b, rem_b = set(), set(), set()
        modadd = mod_a | add_a | mod_b | add_b
        common = modadd | rem_a | rem_b
        if not common:
            return 0

    tmproot = pycompat.mkdtemp(prefix=b'extdiff.')
    try:
        if not opts.get(b'patch'):
            # Always make a copy of node1a (and node1b, if applicable)
            dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a)
            dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot,
                             subrepos)[0]
            rev1a = b'@%d' % repo[node1a].rev()
            if do3way:
                dir1b_files = mod_b | rem_b | ((mod_a | add_a) - add_b)
                dir1b = snapshot(ui, repo, dir1b_files, node1b, tmproot,
                                 subrepos)[0]
                rev1b = b'@%d' % repo[node1b].rev()
            else:
                dir1b = None
                rev1b = b''

            fnsandstat = []

            # If node2 in not the wc or there is >1 change, copy it
            dir2root = b''
            rev2 = b''
            if node2:
                dir2 = snapshot(ui, repo, modadd, node2, tmproot, subrepos)[0]
                rev2 = b'@%d' % repo[node2].rev()
            elif len(common) > 1:
                # we only actually need to get the files to copy back to
                # the working dir in this case (because the other cases
                # are: diffing 2 revisions or single file -- in which case
                # the file is already directly passed to the diff tool).
                dir2, fnsandstat = snapshot(ui, repo, modadd, None, tmproot,
                                            subrepos)
            else:
                # This lets the diff tool open the changed file directly
                dir2 = b''
                dir2root = repo.root

            label1a = rev1a
            label1b = rev1b
            label2 = rev2

            # If only one change, diff the files instead of the directories
            # Handle bogus modifies correctly by checking if the files exist
            if len(common) == 1:
                common_file = util.localpath(common.pop())
                dir1a = os.path.join(tmproot, dir1a, common_file)
                label1a = common_file + rev1a
                if not os.path.isfile(dir1a):
                    dir1a = os.devnull
                if do3way:
                    dir1b = os.path.join(tmproot, dir1b, common_file)
                    label1b = common_file + rev1b
                    if not os.path.isfile(dir1b):
                        dir1b = os.devnull
                dir2 = os.path.join(dir2root, dir2, common_file)
                label2 = common_file + rev2
        else:
            template = b'hg-%h.patch'
            with formatter.nullformatter(ui, b'extdiff', {}) as fm:
                cmdutil.export(
                    repo,
                    [repo[node1a].rev(), repo[node2].rev()],
                    fm,
                    fntemplate=repo.vfs.reljoin(tmproot, template),
                    match=matcher,
                )
            label1a = cmdutil.makefilename(repo[node1a], template)
            label2 = cmdutil.makefilename(repo[node2], template)
            dir1a = repo.vfs.reljoin(tmproot, label1a)
            dir2 = repo.vfs.reljoin(tmproot, label2)
            dir1b = None
            label1b = None
            fnsandstat = []

        if not perfile:
            # Run the external tool on the 2 temp directories or the patches
            cmdline = formatcmdline(
                cmdline,
                repo.root,
                do3way=do3way,
                parent1=dir1a,
                plabel1=label1a,
                parent2=dir1b,
                plabel2=label1b,
                child=dir2,
                clabel=label2,
            )
            ui.debug(b'running %r in %s\n' %
                     (pycompat.bytestr(cmdline), tmproot))
            ui.system(cmdline, cwd=tmproot, blockedtag=b'extdiff')
        else:
            # Run the external tool once for each pair of files
            _runperfilediff(
                cmdline,
                repo.root,
                ui,
                guitool=guitool,
                do3way=do3way,
                confirm=confirm,
                commonfiles=common,
                tmproot=tmproot,
                dir1a=dir1a,
                dir1b=dir1b,
                dir2root=dir2root,
                dir2=dir2,
                rev1a=rev1a,
                rev1b=rev1b,
                rev2=rev2,
            )

        for copy_fn, working_fn, st in fnsandstat:
            cpstat = os.lstat(copy_fn)
            # Some tools copy the file and attributes, so mtime may not detect
            # all changes.  A size check will detect more cases, but not all.
            # The only certain way to detect every case is to diff all files,
            # which could be expensive.
            # copyfile() carries over the permission, so the mode check could
            # be in an 'elif' branch, but for the case where the file has
            # changed without affecting mtime or size.
            if (cpstat[stat.ST_MTIME] != st[stat.ST_MTIME]
                    or cpstat.st_size != st.st_size
                    or (cpstat.st_mode & 0o100) != (st.st_mode & 0o100)):
                ui.debug(b'file changed while diffing. '
                         b'Overwriting: %s (src: %s)\n' %
                         (working_fn, copy_fn))
                util.copyfile(copy_fn, working_fn)

        return 1
    finally:
        ui.note(_(b'cleaning up temp directory\n'))
        shutil.rmtree(tmproot)
예제 #5
0
파일: keyword.py 프로젝트: CJX32/my_blog
def demo(ui, repo, *args, **opts):
    '''print [keywordmaps] configuration and an expansion example

    Show current, custom, or default keyword template maps and their
    expansions.

    Extend the current configuration by specifying maps as arguments
    and using -f/--rcfile to source an external hgrc file.

    Use -d/--default to disable current configuration.

    See :hg:`help templates` for information on templates and filters.
    '''

    def demoitems(section, items):
        ui.write(b'[%s]\n' % section)
        for k, v in sorted(items):
            if isinstance(v, bool):
                v = stringutil.pprint(v)
            ui.write(b'%s = %s\n' % (k, v))

    fn = b'demo.txt'
    tmpdir = pycompat.mkdtemp(b'', b'kwdemo.')
    ui.note(_(b'creating temporary repository at %s\n') % tmpdir)
    if repo is None:
        baseui = ui
    else:
        baseui = repo.baseui
    repo = localrepo.instance(baseui, tmpdir, create=True)
    ui.setconfig(b'keyword', fn, b'', b'keyword')
    svn = ui.configbool(b'keywordset', b'svn')
    # explicitly set keywordset for demo output
    ui.setconfig(b'keywordset', b'svn', svn, b'keyword')

    uikwmaps = ui.configitems(b'keywordmaps')
    if args or opts.get(r'rcfile'):
        ui.status(_(b'\n\tconfiguration using custom keyword template maps\n'))
        if uikwmaps:
            ui.status(_(b'\textending current template maps\n'))
        if opts.get(r'default') or not uikwmaps:
            if svn:
                ui.status(_(b'\toverriding default svn keywordset\n'))
            else:
                ui.status(_(b'\toverriding default cvs keywordset\n'))
        if opts.get(r'rcfile'):
            ui.readconfig(opts.get(b'rcfile'))
        if args:
            # simulate hgrc parsing
            rcmaps = b'[keywordmaps]\n%s\n' % b'\n'.join(args)
            repo.vfs.write(b'hgrc', rcmaps)
            ui.readconfig(repo.vfs.join(b'hgrc'))
        kwmaps = dict(ui.configitems(b'keywordmaps'))
    elif opts.get(r'default'):
        if svn:
            ui.status(_(b'\n\tconfiguration using default svn keywordset\n'))
        else:
            ui.status(_(b'\n\tconfiguration using default cvs keywordset\n'))
        kwmaps = _defaultkwmaps(ui)
        if uikwmaps:
            ui.status(_(b'\tdisabling current template maps\n'))
            for k, v in pycompat.iteritems(kwmaps):
                ui.setconfig(b'keywordmaps', k, v, b'keyword')
    else:
        ui.status(_(b'\n\tconfiguration using current keyword template maps\n'))
        if uikwmaps:
            kwmaps = dict(uikwmaps)
        else:
            kwmaps = _defaultkwmaps(ui)

    uisetup(ui)
    reposetup(ui, repo)
    ui.writenoi18n(b'[extensions]\nkeyword =\n')
    demoitems(b'keyword', ui.configitems(b'keyword'))
    demoitems(b'keywordset', ui.configitems(b'keywordset'))
    demoitems(b'keywordmaps', pycompat.iteritems(kwmaps))
    keywords = b'$' + b'$\n$'.join(sorted(kwmaps.keys())) + b'$\n'
    repo.wvfs.write(fn, keywords)
    repo[None].add([fn])
    ui.note(_(b'\nkeywords written to %s:\n') % fn)
    ui.note(keywords)
    with repo.wlock():
        repo.dirstate.setbranch(b'demobranch')
    for name, cmd in ui.configitems(b'hooks'):
        if name.split(b'.', 1)[0].find(b'commit') > -1:
            repo.ui.setconfig(b'hooks', name, b'', b'keyword')
    msg = _(b'hg keyword configuration and expansion example')
    ui.note((b"hg ci -m '%s'\n" % msg))
    repo.commit(text=msg)
    ui.status(_(b'\n\tkeywords expanded\n'))
    ui.write(repo.wread(fn))
    repo.wvfs.rmtree(repo.root)
예제 #6
0
def dodiff(ui, repo, cmdline, pats, opts, guitool=False):
    """Do the actual diff:

    - copy to a temp structure if diffing 2 internal revisions
    - copy to a temp structure if diffing working revision with
      another one and more than 1 file is changed
    - just invoke the diff for a single file in the working dir
    """

    cmdutil.check_at_most_one_arg(opts, b'rev', b'change')
    revs = opts.get(b'rev')
    from_rev = opts.get(b'from')
    to_rev = opts.get(b'to')
    change = opts.get(b'change')
    do3way = b'$parent2' in cmdline

    if change:
        ctx2 = scmutil.revsingle(repo, change, None)
        ctx1a, ctx1b = ctx2.p1(), ctx2.p2()
    elif from_rev or to_rev:
        repo = scmutil.unhidehashlikerevs(
            repo, [from_rev] + [to_rev], b'nowarn'
        )
        ctx1a = scmutil.revsingle(repo, from_rev, None)
        ctx1b = repo[nullrev]
        ctx2 = scmutil.revsingle(repo, to_rev, None)
    else:
        ctx1a, ctx2 = scmutil.revpair(repo, revs)
        if not revs:
            ctx1b = repo[None].p2()
        else:
            ctx1b = repo[nullrev]

    # Disable 3-way merge if there is only one parent
    if do3way:
        if ctx1b.rev() == nullrev:
            do3way = False

    matcher = scmutil.match(ctx2, pats, opts)

    if opts.get(b'patch'):
        if opts.get(b'subrepos'):
            raise error.Abort(_(b'--patch cannot be used with --subrepos'))
        if opts.get(b'per_file'):
            raise error.Abort(_(b'--patch cannot be used with --per-file'))
        if ctx2.node() is None:
            raise error.Abort(_(b'--patch requires two revisions'))

    tmproot = pycompat.mkdtemp(prefix=b'extdiff.')
    try:
        if opts.get(b'patch'):
            return diffpatch(
                ui, repo, ctx1a.node(), ctx2.node(), tmproot, matcher, cmdline
            )

        return diffrevs(
            ui,
            repo,
            ctx1a,
            ctx1b,
            ctx2,
            matcher,
            tmproot,
            cmdline,
            do3way,
            guitool,
            opts,
        )

    finally:
        ui.note(_(b'cleaning up temp directory\n'))
        shutil.rmtree(tmproot)
예제 #7
0
def dodiff(ui, repo, cmdline, pats, opts):
    '''Do the actual diff:

    - copy to a temp structure if diffing 2 internal revisions
    - copy to a temp structure if diffing working revision with
      another one and more than 1 file is changed
    - just invoke the diff for a single file in the working dir
    '''

    revs = opts.get('rev')
    change = opts.get('change')
    do3way = '$parent2' in cmdline

    if revs and change:
        msg = _('cannot specify --rev and --change at the same time')
        raise error.Abort(msg)
    elif change:
        ctx2 = scmutil.revsingle(repo, change, None)
        ctx1a, ctx1b = ctx2.p1(), ctx2.p2()
    else:
        ctx1a, ctx2 = scmutil.revpair(repo, revs)
        if not revs:
            ctx1b = repo[None].p2()
        else:
            ctx1b = repo[nullid]

    node1a = ctx1a.node()
    node1b = ctx1b.node()
    node2 = ctx2.node()

    # Disable 3-way merge if there is only one parent
    if do3way:
        if node1b == nullid:
            do3way = False

    subrepos = opts.get('subrepos')

    matcher = scmutil.match(repo[node2], pats, opts)

    if opts.get('patch'):
        if subrepos:
            raise error.Abort(_('--patch cannot be used with --subrepos'))
        if node2 is None:
            raise error.Abort(_('--patch requires two revisions'))
    else:
        mod_a, add_a, rem_a = map(
            set,
            repo.status(node1a, node2, matcher, listsubrepos=subrepos)[:3])
        if do3way:
            mod_b, add_b, rem_b = map(
                set,
                repo.status(node1b, node2, matcher, listsubrepos=subrepos)[:3])
        else:
            mod_b, add_b, rem_b = set(), set(), set()
        modadd = mod_a | add_a | mod_b | add_b
        common = modadd | rem_a | rem_b
        if not common:
            return 0

    tmproot = pycompat.mkdtemp(prefix='extdiff.')
    try:
        if not opts.get('patch'):
            # Always make a copy of node1a (and node1b, if applicable)
            dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a)
            dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot,
                             subrepos)[0]
            rev1a = '@%d' % repo[node1a].rev()
            if do3way:
                dir1b_files = mod_b | rem_b | ((mod_a | add_a) - add_b)
                dir1b = snapshot(ui, repo, dir1b_files, node1b, tmproot,
                                 subrepos)[0]
                rev1b = '@%d' % repo[node1b].rev()
            else:
                dir1b = None
                rev1b = ''

            fnsandstat = []

            # If node2 in not the wc or there is >1 change, copy it
            dir2root = ''
            rev2 = ''
            if node2:
                dir2 = snapshot(ui, repo, modadd, node2, tmproot, subrepos)[0]
                rev2 = '@%d' % repo[node2].rev()
            elif len(common) > 1:
                #we only actually need to get the files to copy back to
                #the working dir in this case (because the other cases
                #are: diffing 2 revisions or single file -- in which case
                #the file is already directly passed to the diff tool).
                dir2, fnsandstat = snapshot(ui, repo, modadd, None, tmproot,
                                            subrepos)
            else:
                # This lets the diff tool open the changed file directly
                dir2 = ''
                dir2root = repo.root

            label1a = rev1a
            label1b = rev1b
            label2 = rev2

            # If only one change, diff the files instead of the directories
            # Handle bogus modifies correctly by checking if the files exist
            if len(common) == 1:
                common_file = util.localpath(common.pop())
                dir1a = os.path.join(tmproot, dir1a, common_file)
                label1a = common_file + rev1a
                if not os.path.isfile(dir1a):
                    dir1a = os.devnull
                if do3way:
                    dir1b = os.path.join(tmproot, dir1b, common_file)
                    label1b = common_file + rev1b
                    if not os.path.isfile(dir1b):
                        dir1b = os.devnull
                dir2 = os.path.join(dir2root, dir2, common_file)
                label2 = common_file + rev2
        else:
            template = 'hg-%h.patch'
            with formatter.nullformatter(ui, 'extdiff', {}) as fm:
                cmdutil.export(repo, [repo[node1a].rev(), repo[node2].rev()],
                               fm,
                               fntemplate=repo.vfs.reljoin(tmproot, template),
                               match=matcher)
            label1a = cmdutil.makefilename(repo[node1a], template)
            label2 = cmdutil.makefilename(repo[node2], template)
            dir1a = repo.vfs.reljoin(tmproot, label1a)
            dir2 = repo.vfs.reljoin(tmproot, label2)
            dir1b = None
            label1b = None
            fnsandstat = []

        # Function to quote file/dir names in the argument string.
        # When not operating in 3-way mode, an empty string is
        # returned for parent2
        replace = {
            'parent': dir1a,
            'parent1': dir1a,
            'parent2': dir1b,
            'plabel1': label1a,
            'plabel2': label1b,
            'clabel': label2,
            'child': dir2,
            'root': repo.root
        }

        def quote(match):
            pre = match.group(2)
            key = match.group(3)
            if not do3way and key == 'parent2':
                return pre
            return pre + procutil.shellquote(replace[key])

        # Match parent2 first, so 'parent1?' will match both parent1 and parent
        regex = (br'''(['"]?)([^\s'"$]*)'''
                 br'\$(parent2|parent1?|child|plabel1|plabel2|clabel|root)\1')
        if not do3way and not re.search(regex, cmdline):
            cmdline += ' $parent1 $child'
        cmdline = re.sub(regex, quote, cmdline)

        ui.debug('running %r in %s\n' % (pycompat.bytestr(cmdline), tmproot))
        ui.system(cmdline, cwd=tmproot, blockedtag='extdiff')

        for copy_fn, working_fn, st in fnsandstat:
            cpstat = os.lstat(copy_fn)
            # Some tools copy the file and attributes, so mtime may not detect
            # all changes.  A size check will detect more cases, but not all.
            # The only certain way to detect every case is to diff all files,
            # which could be expensive.
            # copyfile() carries over the permission, so the mode check could
            # be in an 'elif' branch, but for the case where the file has
            # changed without affecting mtime or size.
            if (cpstat[stat.ST_MTIME] != st[stat.ST_MTIME]
                    or cpstat.st_size != st.st_size
                    or (cpstat.st_mode & 0o100) != (st.st_mode & 0o100)):
                ui.debug('file changed while diffing. '
                         'Overwriting: %s (src: %s)\n' % (working_fn, copy_fn))
                util.copyfile(copy_fn, working_fn)

        return 1
    finally:
        ui.note(_('cleaning up temp directory\n'))
        shutil.rmtree(tmproot)