Beispiel #1
0
def qnew_wrapper(self, repo, patchfn, *pats, **opts):
    mqmessage = opts.pop('mqmessage', None)
    mqcommit, q, r = mqcommit_info(self, repo, opts)

    mq.new(self, repo, patchfn, *pats, **opts)

    if mqcommit and mqmessage:
        mqmessage = mqmessage.replace("%p", patchfn)
        mqmessage = mqmessage.replace("%a", 'NEW')
        commands.commit(r.ui, r, message=mqmessage)
Beispiel #2
0
def qbug(ui, repo, bug_no, *args, **opts):
    """start a new patch to fix a specific Launchpad bug report.

    Does the same as the qnew command, but fetches bug report details
    from Launchpad and initializes the patch description with it.
    """
    details = fetch_bug_details(int(bug_no))
    patch_name = "bug-%s.patch" % bug_no

    opts['message'] = BUG_TEMPLATE % (bug_no, details)
    result = mq.new(ui, repo, patch_name, *args, **opts)
    ui.write("Starting new patch for LP#%s (%s)\n" % (bug_no, details))
    return result
def qbackout(ui, repo, rev, **opts):
    """backout a change or set of changes

    qbackout creates a new patch or patches on top of any currently-applied
    patches. If the -s/--single option is set, then all backed-out changesets
    will be rolled up into a single backout changeset. Otherwise, there will
    be one backout changeset queued up for each backed-out changeset.

    The --apply option will reapply a patch instead of backing it out, which
    can be useful when you (or someone else) has backed your patch out and
    you want to try again.

    Normally, qbackout will error out if the patch (backout or application)
    fails to apply. The --nopush option may be used to leave the patch in your
    queue without pushing it so you can fix the conflicts manually.

    Examples:
      hg qbackout -r 20 -r 30    # backout revisions 20 and 30

      hg qbackout -r 20+30       # backout revisions 20 and 30

      hg qbackout -r 20+30:32    # backout revisions 20, 30, 31, and 32

      hg qbackout -r a3a81775    # the usual revision syntax is available

    See "hg help revisions" and "hg help revsets" for more about specifying
    revisions.
    """
    if not opts.get('force'):
        ui.status('checking for uncommitted changes\n')
        cmdutil.bailifchanged(repo)
    backout = not opts.get('apply')
    desc = { 'action': 'backout',
             'Actioned': 'Backed out',
             'actioning': 'backing out',
             'name': 'backout'
             }
    if not backout:
        desc = { 'action': 'apply',
                 'Actioned': 'Reapplied',
                 'actioning': 'Reapplying',
                 'name': 'patch'
                 }

    rev = scmutil.revrange(repo, rev)
    if len(rev) == 0:
        raise util.Abort('at least one revision required')

    csets = [ repo[r] for r in rev ]
    reverse_order = backout
    if opts.get('nopush'):
        reverse_order = not reverse_order
    csets.sort(reverse=reverse_order, key=lambda cset: cset.rev())

    if opts.get('single') and opts.get('name') and len(rev) > 1:
        raise util.Abort('option "-n" not valid when backing out multiple changes')

    new_opts = opts.copy()
    mq.setupheaderopts(ui, new_opts)

    def bugs_suffix(bugs):
        if len(bugs) == 0:
            return ''
        elif len(bugs) == 1:
            return ' (bug ' + list(bugs)[0] + ')'
        else:
            return ' (' + ', '.join(map(lambda b: 'bug %s' % b, bugs)) + ')'

    def parse_bugs(msg):
        bugs = set()
        m = bug_re.search(msg)
        if m:
            bugs.add(m.group(2))
        return bugs

    def apply_change(node, reverse, push_patch=True, name=None):
        p1, p2 = repo.changelog.parents(node)
        if p2 != nullid:
            raise util.Abort('cannot %s a merge changeset' % desc['action'])

        opts = mdiff.defaultopts
        opts.git = True
        rpatch = StringIO.StringIO()
        orig, mod = (node, p1) if reverse else (p1, node)
        for chunk in patch.diff(repo, node1=orig, node2=mod, opts=opts):
            rpatch.write(chunk)
        rpatch.seek(0)

        saved_stdin = None
        try:
            save_fin = ui.fin
            ui.fin = rpatch
        except:
            # Old versions of hg did not use the ui.fin mechanism
            saved_stdin = sys.stdin
            sys.stdin = rpatch

        if push_patch:
            commands.import_(ui, repo, '-',
                             force=True,
                             no_commit=True,
                             strip=1,
                             base='')
        else:
            mq.qimport(ui, repo, '-', name=name, rev=[], git=True)

        if saved_stdin is None:
            ui.fin = save_fin
        else:
            sys.stdin = saved_stdin

    allbugs = set()
    messages = []
    for cset in csets:
        # Hunt down original description if we might want to use it
        orig_desc = None
        orig_desc_cset = None
        orig_author = None
        r = cset
        while len(csets) == 1 or not opts.get('single'):
            ui.debug("Parsing message for %s\n" % short(r.node()))
            m = backout_re.match(r.description())
            if m:
                ui.debug("  looks like a backout of %s\n" % m.group(1))
            else:
                m = reapply_re.match(r.description())
                if m:
                    ui.debug("  looks like a reapply of %s\n" % m.group(1))
                else:
                    ui.debug("  looks like the original description\n")
                    orig_desc = r.description()
                    orig_desc_cset = r
                    orig_author = r.user()
                    break
            r = repo[m.group(1)]

        bugs = parse_bugs(cset.description())
        allbugs.update(bugs)
        node = cset.node()
        shortnode = short(node)
        ui.status('%s %s\n' % (desc['actioning'], shortnode))
        if opts.get('nopush') and opts.get('single'):
            ui.fatal("--single not supported with --nopush")
        patchname = None
        if not opts.get('single'):
            patchname = opts.get('name') or '%s-%s' % (desc['name'], shortnode)
        apply_change(node, backout, push_patch=(not opts.get('nopush')), name=patchname)
        msg = ('%s changeset %s' % (desc['Actioned'], shortnode)) + bugs_suffix(bugs)
        user = None

        if backout:
            # If backing out a backout, reuse the original commit message & author.
            if orig_desc_cset is not None and orig_desc_cset != cset:
                msg = orig_desc
                user = orig_author
        else:
            # If reapplying the original change, reuse the original commit message & author.
            if orig_desc_cset is not None and orig_desc_cset == cset:
                msg = orig_desc
                user = orig_author

        messages.append(msg)
        if not opts.get('single') and not opts.get('nopush'):
            new_opts['message'] = messages[-1]
            # Override the user to that of the original patch author in the case of --apply
            if user is not None:
                new_opts['user'] = user
            mq.new(ui, repo, patchname, **new_opts)
            if ui.verbose:
                ui.write("queued up patch %s\n" % patchname)

    msg = ('%s %d changesets' % (desc['Actioned'], len(rev))) + bugs_suffix(allbugs) + '\n'
    messages.insert(0, msg)
    new_opts['message'] = "\n".join(messages)
    if opts.get('single'):
        patchname = opts.get('name') or '%s-%d-changesets' % (desc['name'], len(rev))
        mq.new(ui, repo, patchname, **new_opts)
 def commit_change(ui, repo, action, force_name=None, node=None, revisions=None, **opts):
     patchname = compute_patch_name(action, force_name, node=node, revisions=revisions)
     mq.new(ui, repo, patchname, **opts)
     if ui.verbose:
         ui.write("queued up patch %s\n" % patchname)
 def commit_change(ui, repo, action, force_name=None, node=None, revisions=None, **opts):
     patchname = compute_patch_name(action, force_name, node=node, revisions=revisions)
     mq.new(ui, repo, patchname, **opts)
     if ui.verbose:
         ui.write("queued up patch %s\n" % patchname)