Esempio n. 1
0
def abort(repo, originalwd, target, state):
    'Restore the repository to its original state'
    dstates = [s for s in state.values() if s != nullrev]
    if [d for d in dstates if not repo[d].mutable()]:
        repo.ui.warn(
            _("warning: immutable rebased changeset detected, "
              "can't abort\n"))
        return -1

    descendants = set()
    if dstates:
        descendants = set(repo.changelog.descendants(*dstates))
    if descendants - set(dstates):
        repo.ui.warn(
            _("warning: new changesets detected on target branch, "
              "can't abort\n"))
        return -1
    else:
        # Strip from the first rebased revision
        merge.update(repo, repo[originalwd].rev(), False, True, False)
        rebased = filter(lambda x: x > -1 and x != target, state.values())
        if rebased:
            strippoint = min(rebased)
            # no backup of rebased cset versions needed
            repair.strip(repo.ui, repo, repo[strippoint].node())
        clearstatus(repo)
        repo.ui.warn(_('rebase aborted\n'))
        return 0
Esempio n. 2
0
def abort(repo, originalwd, target, state):
    'Restore the repository to its original state'
    dstates = [s for s in state.values() if s > nullrev]
    immutable = [d for d in dstates if not repo[d].mutable()]
    cleanup = True
    if immutable:
        repo.ui.warn(_("warning: can't clean up immutable changesets %s\n")
                     % ', '.join(str(repo[r]) for r in immutable),
                     hint=_('see hg help phases for details'))
        cleanup = False

    descendants = set()
    if dstates:
        descendants = set(repo.changelog.descendants(dstates))
    if descendants - set(dstates):
        repo.ui.warn(_("warning: new changesets detected on target branch, "
                       "can't strip\n"))
        cleanup = False

    if cleanup:
        # Update away from the rebase if necessary
        if inrebase(repo, originalwd, state):
            merge.update(repo, repo[originalwd].rev(), False, True, False)

        # Strip from the first rebased revision
        rebased = filter(lambda x: x > -1 and x != target, state.values())
        if rebased:
            strippoints = [c.node()  for c in repo.set('roots(%ld)', rebased)]
            # no backup of rebased cset versions needed
            repair.strip(repo.ui, repo, strippoints)

    clearstatus(repo)
    repo.ui.warn(_('rebase aborted\n'))
    return 0
def fix_hgtags(ui, repo, head_hgtags, tagsmap):
    for tf in iter(tagsmap):
        ui.debug('fix_hgtags: tagsmap %s -> %s\n' % (tf, tagsmap[tf]))
    for old in iter(head_hgtags):
        new = map_recursive(tagsmap, old)
        ui.debug('fix_hgtags: head %s -> %s\n' % (old, new))
        merge.update(repo, repo[new].node(), False, False, False)
        tfile = open('.hgtags', 'wb')
        lines = StringIO.StringIO(head_hgtags[old])
        for line in lines:
            if not line:
                continue
            (nodehex, name) = line.split(" ", 1)
            name = name.strip()
            nhm = map_recursive(tagsmap, nodehex)
            ui.debug('fix_hgtags: hgtags write: %s %s\n' % (nhm, name))
            tfile.write('%s %s\n' % (nhm, name))
        lines.close()    
        tfile.close()
        wctx = repo[None]
        if '.hgtags' not in wctx:
            wctx.add(['.hgtags'])
        nrev = repo.commit(text="collapse tag fix")
        if nrev:
            nctx = repo[nrev]
            ui.debug(_('fix_hgtags: nctx rev %d node %r files %r\n') % 
                     (nctx.rev(), hex(nctx.node()), nctx.files()))
            ui.debug(_('fix_hgtags: nctx parents %r\n') % 
                      ([hex(p.node()) for p in nctx.parents()]))
        else:
            ui.debug(_('fix_hgtags: nctx: None\n'))
Esempio n. 4
0
def unshelveabort(ui, repo, state, opts):
    """subcommand that abort an in-progress unshelve"""
    with repo.lock():
        try:
            checkparents(repo, state)

            merge.update(repo, state.pendingctx, branchmerge=False, force=True)
            if (state.activebookmark
                    and state.activebookmark in repo._bookmarks):
                bookmarks.activate(repo, state.activebookmark)

            if repo.vfs.exists('unshelverebasestate'):
                repo.vfs.rename('unshelverebasestate', 'rebasestate')
                rebase.clearstatus(repo)

            mergefiles(ui, repo, state.wctx, state.pendingctx)
            if not phases.supportinternal(repo):
                repair.strip(ui,
                             repo,
                             state.nodestoremove,
                             backup=False,
                             topic='shelve')
        finally:
            shelvedstate.clear(repo)
            ui.warn(_("unshelve of '%s' aborted\n") % state.name)
Esempio n. 5
0
def makecollapsed(ui, repo, parent, revs):
    'Creates the collapsed revision on top of parent'

    last = max(revs)
    ui.debug(_('updating to revision %d\n') % parent)
    merge.update(repo, parent.node(), False, False, False)
    ui.debug(_('reverting to revision %d\n') % last)
    commands.revert(ui, repo, rev=last, all=True, date=None)
    msg = ''

    first = True
    for r in revs:
        if not first:
            msg += '----------------\n'
        first = False
        msg += repo[r].description() + "\n"

    msg += "\nHG: Enter commit message.  Lines beginning with 'HG:' are removed.\n"
    msg += "HG: Remove all lines to abort the collapse operation.\n"

    msg = ui.edit(msg, ui.username())

    if not msg:
        raise util.Abort(_('empty commit message, collapse won\'t proceed'))

    newrev = repo.commit(
        text=msg,
        user=repo[last].user(),
        date=repo[last].date())

    return repo[newrev]
def rebasenode(repo, rev, p1, base, state, collapse, target):
    'Rebase a single revision rev on top of p1 using base as merge ancestor'
    # Merge phase
    # Update to target and merge it with local
    if repo['.'].rev() != p1:
        repo.ui.debug(" update to %d:%s\n" % (p1, repo[p1]))
        merge.update(repo, p1, False, True, False)
    else:
        repo.ui.debug(" already in target\n")
    repo.dirstate.write()
    repo.ui.debug(" merge against %d:%s\n" % (rev, repo[rev]))
    if base is not None:
        repo.ui.debug("   detach base %d:%s\n" % (base, repo[base]))
    # When collapsing in-place, the parent is the common ancestor, we
    # have to allow merging with it.
    stats = merge.update(repo, rev, True, True, False, base, collapse,
                        labels=['dest', 'source'])
    if collapse:
        copies.duplicatecopies(repo, rev, target)
    else:
        # If we're not using --collapse, we need to
        # duplicate copies between the revision we're
        # rebasing and its first parent, but *not*
        # duplicate any copies that have already been
        # performed in the destination.
        p1rev = repo[rev].p1().rev()
        copies.duplicatecopies(repo, rev, p1rev, skiprev=target)
    return stats
Esempio n. 7
0
def rebasenode(repo, rev, p1, base, state, collapse, target):
    'Rebase a single revision rev on top of p1 using base as merge ancestor'
    # Merge phase
    # Update to target and merge it with local
    if repo['.'].rev() != p1:
        repo.ui.debug(" update to %d:%s\n" % (p1, repo[p1]))
        merge.update(repo, p1, False, True, False)
    else:
        repo.ui.debug(" already in target\n")
    repo.dirstate.write(repo.currenttransaction())
    repo.ui.debug(" merge against %d:%s\n" % (rev, repo[rev]))
    if base is not None:
        repo.ui.debug("   detach base %d:%s\n" % (base, repo[base]))
    # When collapsing in-place, the parent is the common ancestor, we
    # have to allow merging with it.
    stats = merge.update(repo, rev, True, True, False, base, collapse,
                        labels=['dest', 'source'])
    if collapse:
        copies.duplicatecopies(repo, rev, target)
    else:
        # If we're not using --collapse, we need to
        # duplicate copies between the revision we're
        # rebasing and its first parent, but *not*
        # duplicate any copies that have already been
        # performed in the destination.
        p1rev = repo[rev].p1().rev()
        copies.duplicatecopies(repo, rev, p1rev, skiprev=target)
    return stats
Esempio n. 8
0
def abort(repo, originalwd, target, state):
    'Restore the repository to its original state'
    dstates = [s for s in state.values() if s != nullrev]
    immutable = [d for d in dstates if not repo[d].mutable()]
    if immutable:
        raise util.Abort(_("can't abort rebase due to immutable changesets %s")
                         % ', '.join(str(repo[r]) for r in immutable),
                         hint=_('see hg help phases for details'))

    descendants = set()
    if dstates:
        descendants = set(repo.changelog.descendants(*dstates))
    if descendants - set(dstates):
        repo.ui.warn(_("warning: new changesets detected on target branch, "
                       "can't abort\n"))
        return -1
    else:
        # Strip from the first rebased revision
        merge.update(repo, repo[originalwd].rev(), False, True, False)
        rebased = filter(lambda x: x > -1 and x != target, state.values())
        if rebased:
            strippoint = min(rebased)
            # no backup of rebased cset versions needed
            repair.strip(repo.ui, repo, repo[strippoint].node())
        clearstatus(repo)
        repo.ui.warn(_('rebase aborted\n'))
        return 0
Esempio n. 9
0
File: hg.py Progetto: jonashaag/vcs
    def checkout_branch(self, branch=None):
        if branch is None:
            branch = self.repository.DEFAULT_BRANCH_NAME
        if branch not in self.repository.branches:
            raise BranchDoesNotExistError

        hg_merge.update(self.repository._repo, branch, False, False, None)
Esempio n. 10
0
def rebasenode(repo, rev, p1, state, collapse):
    'Rebase a single revision'
    # Merge phase
    # Update to target and merge it with local
    if repo['.'].rev() != repo[p1].rev():
        repo.ui.debug(" update to %d:%s\n" % (repo[p1].rev(), repo[p1]))
        merge.update(repo, p1, False, True, False)
    else:
        repo.ui.debug(" already in target\n")
    repo.dirstate.write()
    repo.ui.debug(" merge against %d:%s\n" % (repo[rev].rev(), repo[rev]))
    if repo[rev].rev() == repo[min(state)].rev():
        # Case (1) initial changeset of a non-detaching rebase.
        # Let the merge mechanism find the base itself.
        base = None
    elif not repo[rev].p2():
        # Case (2) detaching the node with a single parent, use this parent
        base = repo[rev].p1().node()
    else:
        # In case of merge, we need to pick the right parent as merge base.
        #
        # Imagine we have:
        # - M: currently rebase revision in this step
        # - A: one parent of M
        # - B: second parent of M
        # - D: destination of this merge step (p1 var)
        #
        # If we are rebasing on D, D is the successors of A or B. The right
        # merge base is the one D succeed to. We pretend it is B for the rest
        # of this comment
        #
        # If we pick B as the base, the merge involves:
        # - changes from B to M (actual changeset payload)
        # - changes from B to D (induced by rebase) as D is a rebased
        #   version of B)
        # Which exactly represent the rebase operation.
        #
        # If we pick the A as the base, the merge involves
        # - changes from A to M (actual changeset payload)
        # - changes from A to D (with include changes between unrelated A and B
        #   plus changes induced by rebase)
        # Which does not represent anything sensible and creates a lot of
        # conflicts.
        for p in repo[rev].parents():
            if state.get(p.rev()) == repo[p1].rev():
                base = p.node()
                break
        else:  # fallback when base not found
            base = None

            # Raise because this function is called wrong (see issue 4106)
            raise AssertionError('no base found to rebase on '
                                 '(rebasenode called wrong)')
    if base is not None:
        repo.ui.debug("   detach base %d:%s\n" %
                      (repo[base].rev(), repo[base]))
    # When collapsing in-place, the parent is the common ancestor, we
    # have to allow merging with it.
    return merge.update(repo, rev, True, True, False, base, collapse)
Esempio n. 11
0
def rebasenode(repo, rev, p1, state, collapse):
    'Rebase a single revision'
    # Merge phase
    # Update to target and merge it with local
    if repo['.'].rev() != repo[p1].rev():
        repo.ui.debug(" update to %d:%s\n" % (repo[p1].rev(), repo[p1]))
        merge.update(repo, p1, False, True, False)
    else:
        repo.ui.debug(" already in target\n")
    repo.dirstate.write()
    repo.ui.debug(" merge against %d:%s\n" % (repo[rev].rev(), repo[rev]))
    if repo[rev].rev() == repo[min(state)].rev():
        # Case (1) initial changeset of a non-detaching rebase.
        # Let the merge mechanism find the base itself.
        base = None
    elif not repo[rev].p2():
        # Case (2) detaching the node with a single parent, use this parent
        base = repo[rev].p1().node()
    else:
        # In case of merge, we need to pick the right parent as merge base.
        #
        # Imagine we have:
        # - M: currently rebase revision in this step
        # - A: one parent of M
        # - B: second parent of M
        # - D: destination of this merge step (p1 var)
        #
        # If we are rebasing on D, D is the successors of A or B. The right
        # merge base is the one D succeed to. We pretend it is B for the rest
        # of this comment
        #
        # If we pick B as the base, the merge involves:
        # - changes from B to M (actual changeset payload)
        # - changes from B to D (induced by rebase) as D is a rebased
        #   version of B)
        # Which exactly represent the rebase operation.
        #
        # If we pick the A as the base, the merge involves
        # - changes from A to M (actual changeset payload)
        # - changes from A to D (with include changes between unrelated A and B
        #   plus changes induced by rebase)
        # Which does not represent anything sensible and creates a lot of
        # conflicts.
        for p in repo[rev].parents():
            if state.get(p.rev()) == repo[p1].rev():
                base = p.node()
                break
        else: # fallback when base not found
            base = None

            # Raise because this function is called wrong (see issue 4106)
            raise AssertionError('no base found to rebase on '
                                 '(rebasenode called wrong)')
    if base is not None:
        repo.ui.debug("   detach base %d:%s\n" % (repo[base].rev(), repo[base]))
    # When collapsing in-place, the parent is the common ancestor, we
    # have to allow merging with it.
    return merge.update(repo, rev, True, True, False, base, collapse,
                        labels=['dest', 'source'])
Esempio n. 12
0
def makecollapsed(ui, repo, parent, revs, branch, tagsmap, parent_hgtags, 
                  movelog, opts):
    'Creates the collapsed revision on top of parent'

    last = max(revs)
    ui.debug(_('updating to revision %d\n') % parent)
    merge.update(repo, parent.node(), False, False, False)
    ui.debug(_('reverting to revision %d\n') % last)
    recreaterev(ui, repo, last)
    repo.dirstate.setbranch(branch)
    msg = ''
    nodelist = []
    if opts['message'] != "" :
        msg = opts['message']
    else:
        first = True
        for r in revs:
            nodelist.append(hex(repo[r].node()))
            if repo[r].files() != ['.hgtags']:
                if not first:
                    if opts['changelog']:
                        msg += '\n'
                    else:
                        msg += '----------------\n'
                first = False
                if opts['changelog']:
                    msg += "* " + ' '.join(repo[r].files()) + ":\n"

                msg += repo[r].description() + "\n"

        msg += "\nHG: Enter commit message.  Lines beginning with 'HG:' are removed.\n"
        msg += "HG: Remove all lines to abort the collapse operation.\n"

        if ui.config('ui', 'interactive') != 'off':
            msg = ui.edit(msg, ui.username())

        pattern = re.compile("^HG:.*\n", re.MULTILINE);
        msg  = re.sub(pattern, "", msg).strip();

    if not msg:
        raise util.Abort(_('empty commit message, collapse won\'t proceed'))

    write_hgtags(parent_hgtags)
    newrev = repo.commit(
        text=msg,
        user=repo[last].user(),
        date=repo[last].date())

    ctx = repo[newrev]

    newhex = hex(ctx.node())
    for n in nodelist:
        ui.debug(_('makecollapsed %s -> %s\n' % (n, newhex))) 
        tagsmap[n] = newhex
        if movelog:
            movelog.write('coll %s -> %s\n' % (n, newhex))
        
    return ctx
Esempio n. 13
0
def rebasenode(repo, rev, target, state, skipped, targetancestors, collapse,
               extrafn):
    'Rebase a single revision'
    repo.ui.debug(_("rebasing %d:%s\n") % (rev, repo[rev]))

    p1, p2 = defineparents(repo, rev, target, state, targetancestors)

    repo.ui.debug(
        _(" future parents are %d and %d\n") %
        (repo[p1].rev(), repo[p2].rev()))

    # Merge phase
    if len(repo.parents()) != 2:
        # Update to target and merge it with local
        if repo['.'].rev() != repo[p1].rev():
            repo.ui.debug(_(" update to %d:%s\n") % (repo[p1].rev(), repo[p1]))
            merge.update(repo, p1, False, True, False)
        else:
            repo.ui.debug(_(" already in target\n"))
        repo.dirstate.write()
        repo.ui.debug(
            _(" merge against %d:%s\n") % (repo[rev].rev(), repo[rev]))
        first = repo[rev].rev() == repo[min(state)].rev()
        stats = rebasemerge(repo, rev, first)

        if stats[3] > 0:
            raise util.Abort(
                _('fix unresolved conflicts with hg resolve then '
                  'run hg rebase --continue'))
    else:  # we have an interrupted rebase
        repo.ui.debug(_('resuming interrupted rebase\n'))

    # Keep track of renamed files in the revision that is going to be rebased
    # Here we simulate the copies and renames in the source changeset
    cop, diver = copies.copies(repo, repo[rev], repo[target], repo[p2], True)
    m1 = repo[rev].manifest()
    m2 = repo[target].manifest()
    for k, v in cop.iteritems():
        if k in m1:
            if v in m1 or v in m2:
                repo.dirstate.copy(v, k)
                if v in m2 and v not in m1:
                    repo.dirstate.remove(v)

    newrev = concludenode(repo, rev, p1, p2, state, collapse, extrafn=extrafn)

    # Update the state
    if newrev is not None:
        state[rev] = repo[newrev].rev()
    else:
        if not collapse:
            repo.ui.note(_('no changes, revision %d skipped\n') % rev)
            repo.ui.debug(_('next revision set to %s\n') % p1)
            skipped.add(rev)
        state[rev] = p1
Esempio n. 14
0
def rebasenode(repo, rev, target, state, skipped, targetancestors, collapse,
               extrafn):
    'Rebase a single revision'
    repo.ui.debug(_("rebasing %d:%s\n") % (rev, repo[rev]))

    p1, p2 = defineparents(repo, rev, target, state, targetancestors)

    repo.ui.debug(_(" future parents are %d and %d\n") % (repo[p1].rev(),
                                                            repo[p2].rev()))

    # Merge phase
    if len(repo.parents()) != 2:
        # Update to target and merge it with local
        if repo['.'].rev() != repo[p1].rev():
            repo.ui.debug(_(" update to %d:%s\n") % (repo[p1].rev(), repo[p1]))
            merge.update(repo, p1, False, True, False)
        else:
            repo.ui.debug(_(" already in target\n"))
        repo.dirstate.write()
        repo.ui.debug(_(" merge against %d:%s\n") % (repo[rev].rev(), repo[rev]))
        first = repo[rev].rev() == repo[min(state)].rev()
        stats = rebasemerge(repo, rev, first)

        if stats[3] > 0:
            raise util.Abort(_('fix unresolved conflicts with hg resolve then '
                                                'run hg rebase --continue'))
    else: # we have an interrupted rebase
        repo.ui.debug(_('resuming interrupted rebase\n'))

    # Keep track of renamed files in the revision that is going to be rebased
    # Here we simulate the copies and renames in the source changeset
    cop, diver = copies.copies(repo, repo[rev], repo[target], repo[p2], True)
    m1 = repo[rev].manifest()
    m2 = repo[target].manifest()
    for k, v in cop.iteritems():
        if k in m1:
            if v in m1 or v in m2:
                repo.dirstate.copy(v, k)
                if v in m2 and v not in m1:
                    repo.dirstate.remove(v)

    newrev = concludenode(repo, rev, p1, p2, state, collapse,
                          extrafn=extrafn)

    # Update the state
    if newrev is not None:
        state[rev] = repo[newrev].rev()
    else:
        if not collapse:
            repo.ui.note(_('no changes, revision %d skipped\n') % rev)
            repo.ui.debug(_('next revision set to %s\n') % p1)
            skipped.add(rev)
        state[rev] = p1
Esempio n. 15
0
def override_rollback(orig, ui, repo, **opts):
    result = orig(ui, repo, **opts)
    merge.update(repo, node=None, branchmerge=False, force=True,
        partial=lfutil.isstandin)
    lfdirstate = lfutil.openlfdirstate(ui, repo)
    lfiles = lfutil.listlfiles(repo)
    oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
    for file in lfiles:
        if file in oldlfiles:
            lfdirstate.normallookup(file)
        else:
            lfdirstate.add(file)
    lfdirstate.write()
    return result
Esempio n. 16
0
def abort(repo, originalwd, target, state):
    'Restore the repository to its original state'
    if set(repo.changelog.descendants(target)) - set(state.values()):
        repo.ui.warn(_("warning: new changesets detected on target branch, "
                                                    "not stripping\n"))
    else:
        # Strip from the first rebased revision
        merge.update(repo, repo[originalwd].rev(), False, True, False)
        rebased = filter(lambda x: x > -1, state.values())
        if rebased:
            strippoint = min(rebased)
            repair.strip(repo.ui, repo, repo[strippoint].node(), "strip")
        clearstatus(repo)
        repo.ui.status(_('rebase aborted\n'))
Esempio n. 17
0
def rebasenode(repo, rev, p1, p2, state):
    'Rebase a single revision'
    # Merge phase
    # Update to target and merge it with local
    if repo['.'].rev() != repo[p1].rev():
        repo.ui.debug(" update to %d:%s\n" % (repo[p1].rev(), repo[p1]))
        merge.update(repo, p1, False, True, False)
    else:
        repo.ui.debug(" already in target\n")
    repo.dirstate.write()
    repo.ui.debug(" merge against %d:%s\n" % (repo[rev].rev(), repo[rev]))
    first = repo[rev].rev() == repo[min(state)].rev()
    stats = rebasemerge(repo, rev, first)
    return stats
Esempio n. 18
0
def rebasenode(repo, rev, p1, p2, state):
    'Rebase a single revision'
    # Merge phase
    # Update to target and merge it with local
    if repo['.'].rev() != repo[p1].rev():
        repo.ui.debug(" update to %d:%s\n" % (repo[p1].rev(), repo[p1]))
        merge.update(repo, p1, False, True, False)
    else:
        repo.ui.debug(" already in target\n")
    repo.dirstate.write()
    repo.ui.debug(" merge against %d:%s\n" % (repo[rev].rev(), repo[rev]))
    first = repo[rev].rev() == repo[min(state)].rev()
    stats = rebasemerge(repo, rev, first)
    return stats
Esempio n. 19
0
def abort(repo, originalwd, target, state):
    'Restore the repository to its original state'
    if set(repo.changelog.descendants(target)) - set(state.values()):
        repo.ui.warn(
            _("warning: new changesets detected on target branch, "
              "not stripping\n"))
    else:
        # Strip from the first rebased revision
        merge.update(repo, repo[originalwd].rev(), False, True, False)
        rebased = filter(lambda x: x > -1, state.values())
        if rebased:
            strippoint = min(rebased)
            repair.strip(repo.ui, repo, repo[strippoint].node(), "strip")
        clearstatus(repo)
        repo.ui.status(_('rebase aborted\n'))
Esempio n. 20
0
def abort(repo, originalwd, target, state, activebookmark=None):
    '''Restore the repository to its original state.  Additional args:

    activebookmark: the name of the bookmark that should be active after the
        restore'''

    try:
        # If the first commits in the rebased set get skipped during the rebase,
        # their values within the state mapping will be the target rev id. The
        # dstates list must must not contain the target rev (issue4896)
        dstates = [s for s in state.values() if s >= 0 and s != target]
        immutable = [d for d in dstates if not repo[d].mutable()]
        cleanup = True
        if immutable:
            repo.ui.warn(_("warning: can't clean up public changesets %s\n")
                        % ', '.join(str(repo[r]) for r in immutable),
                        hint=_('see "hg help phases" for details'))
            cleanup = False

        descendants = set()
        if dstates:
            descendants = set(repo.changelog.descendants(dstates))
        if descendants - set(dstates):
            repo.ui.warn(_("warning: new changesets detected on target branch, "
                        "can't strip\n"))
            cleanup = False

        if cleanup:
            # Update away from the rebase if necessary
            if needupdate(repo, state):
                merge.update(repo, originalwd, False, True, False)

            # Strip from the first rebased revision
            rebased = filter(lambda x: x >= 0 and x != target, state.values())
            if rebased:
                strippoints = [
                        c.node()  for c in repo.set('roots(%ld)', rebased)]
                # no backup of rebased cset versions needed
                repair.strip(repo.ui, repo, strippoints)

        if activebookmark and activebookmark in repo._bookmarks:
            bookmarks.activate(repo, activebookmark)

    finally:
        clearstatus(repo)
        repo.ui.warn(_('rebase aborted\n'))
    return 0
Esempio n. 21
0
def rebasenode(repo, rev, p1, state, collapse):
    'Rebase a single revision'
    # Merge phase
    # Update to target and merge it with local
    if repo['.'].rev() != repo[p1].rev():
        repo.ui.debug(" update to %d:%s\n" % (repo[p1].rev(), repo[p1]))
        merge.update(repo, p1, False, True, False)
    else:
        repo.ui.debug(" already in target\n")
    repo.dirstate.write()
    repo.ui.debug(" merge against %d:%s\n" % (repo[rev].rev(), repo[rev]))
    base = None
    if repo[rev].rev() != repo[min(state)].rev():
        base = repo[rev].p1().node()
    # When collapsing in-place, the parent is the common ancestor, we
    # have to allow merging with it.
    return merge.update(repo, rev, True, True, False, base, collapse)
Esempio n. 22
0
def override_rollback(orig, ui, repo, **opts):
    result = orig(ui, repo, **opts)
    merge.update(repo,
                 node=None,
                 branchmerge=False,
                 force=True,
                 partial=lfutil.isstandin)
    lfdirstate = lfutil.openlfdirstate(ui, repo)
    lfiles = lfutil.listlfiles(repo)
    oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
    for file in lfiles:
        if file in oldlfiles:
            lfdirstate.normallookup(file)
        else:
            lfdirstate.add(file)
    lfdirstate.write()
    return result
Esempio n. 23
0
def rebasenode(repo, rev, p1, state, collapse):
    'Rebase a single revision'
    # Merge phase
    # Update to target and merge it with local
    if repo['.'].rev() != repo[p1].rev():
        repo.ui.debug(" update to %d:%s\n" % (repo[p1].rev(), repo[p1]))
        merge.update(repo, p1, False, True, False)
    else:
        repo.ui.debug(" already in target\n")
    repo.dirstate.write()
    repo.ui.debug(" merge against %d:%s\n" % (repo[rev].rev(), repo[rev]))
    base = None
    if repo[rev].rev() != repo[min(state)].rev():
        base = repo[rev].p1().node()
    # When collapsing in-place, the parent is the common ancestor, we
    # have to allow merging with it.
    return merge.update(repo, rev, True, True, False, base, collapse)
Esempio n. 24
0
def _moveto(repo, bookmark, ctx, clean=False):
    """Moves the given bookmark and the working copy to the given revision.
    By default it does not overwrite the working copy contents unless clean is
    True.

    Assumes the wlock is already taken.
    """
    # Move working copy over
    if clean:
        merge.update(repo, ctx.node(),
                     False, # not a branchmerge
                     True, # force overwriting files
                     None) # not a partial update
    else:
        # Mark any files that are different between the two as normal-lookup
        # so they show up correctly in hg status afterwards.
        wctx = repo[None]
        m1 = wctx.manifest()
        m2 = ctx.manifest()
        diff = m1.diff(m2)

        changedfiles = []
        changedfiles.extend(diff.iterkeys())

        dirstate = repo.dirstate
        dirchanges = [f for f in dirstate if dirstate[f] != 'n']
        changedfiles.extend(dirchanges)

        if changedfiles or ctx.node() != repo['.'].node():
            with dirstate.parentchange():
                dirstate.rebuild(ctx.node(), m2, changedfiles)

    # Move bookmark over
    if bookmark:
        lock = tr = None
        try:
            lock = repo.lock()
            tr = repo.transaction('reset')
            changes = [(bookmark, ctx.node())]
            repo._bookmarks.applychanges(repo, tr, changes)
            tr.close()
        finally:
            lockmod.release(lock, tr)
Esempio n. 25
0
def abort(repo, originalwd, target, state, activebookmark=None):
    '''Restore the repository to its original state.  Additional args:

    activebookmark: the name of the bookmark that should be active after the
        restore'''
    dstates = [s for s in state.values() if s >= 0]
    immutable = [d for d in dstates if not repo[d].mutable()]
    cleanup = True
    if immutable:
        repo.ui.warn(_("warning: can't clean up public changesets %s\n") %
                     ', '.join(str(repo[r]) for r in immutable),
                     hint=_('see "hg help phases" for details'))
        cleanup = False

    descendants = set()
    if dstates:
        descendants = set(repo.changelog.descendants(dstates))
    if descendants - set(dstates):
        repo.ui.warn(
            _("warning: new changesets detected on target branch, "
              "can't strip\n"))
        cleanup = False

    if cleanup:
        # Update away from the rebase if necessary
        if needupdate(repo, state):
            merge.update(repo, originalwd, False, True, False)

        # Strip from the first rebased revision
        rebased = filter(lambda x: x >= 0 and x != target, state.values())
        if rebased:
            strippoints = [c.node() for c in repo.set('roots(%ld)', rebased)]
            # no backup of rebased cset versions needed
            repair.strip(repo.ui, repo, strippoints)

    if activebookmark and activebookmark in repo._bookmarks:
        bookmarks.activate(repo, activebookmark)

    clearstatus(repo)
    repo.ui.warn(_('rebase aborted\n'))
    return 0
Esempio n. 26
0
def pullrebase(orig, ui, repo, *args, **opts):
    'Call rebase after pull if the latter has been invoked with --rebase'
    if opts.get('rebase'):
        if opts.get('update'):
            del opts['update']
            ui.debug('--update and --rebase are not compatible, ignoring '
                     'the update flag\n')

        cmdutil.bail_if_changed(repo)
        revsprepull = len(repo)
        orig(ui, repo, *args, **opts)
        revspostpull = len(repo)
        if revspostpull > revsprepull:
            rebase(ui, repo, **opts)
            branch = repo[None].branch()
            dest = repo[branch].rev()
            if dest != repo['.'].rev():
                # there was nothing to rebase we force an update
                merge.update(repo, dest, False, False, False)
    else:
        orig(ui, repo, *args, **opts)
Esempio n. 27
0
def pullrebase(orig, ui, repo, *args, **opts):
    'Call rebase after pull if the latter has been invoked with --rebase'
    if opts.get('rebase'):
        if opts.get('update'):
            del opts['update']
            ui.debug('--update and --rebase are not compatible, ignoring '
                     'the update flag\n')

        cmdutil.bail_if_changed(repo)
        revsprepull = len(repo)
        orig(ui, repo, *args, **opts)
        revspostpull = len(repo)
        if revspostpull > revsprepull:
            rebase(ui, repo, **opts)
            branch = repo[None].branch()
            dest = repo[branch].rev()
            if dest != repo['.'].rev():
                # there was nothing to rebase we force an update
                merge.update(repo, dest, False, False, False)
    else:
        orig(ui, repo, *args, **opts)
Esempio n. 28
0
def abort(repo, originalwd, target, state, activebookmark=None):
    """Restore the repository to its original state.  Additional args:

    activebookmark: the name of the bookmark that should be active after the
        restore"""
    dstates = [s for s in state.values() if s >= 0]
    immutable = [d for d in dstates if not repo[d].mutable()]
    cleanup = True
    if immutable:
        repo.ui.warn(
            _("warning: can't clean up public changesets %s\n") % ", ".join(str(repo[r]) for r in immutable),
            hint=_('see "hg help phases" for details'),
        )
        cleanup = False

    descendants = set()
    if dstates:
        descendants = set(repo.changelog.descendants(dstates))
    if descendants - set(dstates):
        repo.ui.warn(_("warning: new changesets detected on target branch, " "can't strip\n"))
        cleanup = False

    if cleanup:
        # Update away from the rebase if necessary
        if needupdate(repo, state):
            merge.update(repo, originalwd, False, True, False)

        # Strip from the first rebased revision
        rebased = filter(lambda x: x >= 0 and x != target, state.values())
        if rebased:
            strippoints = [c.node() for c in repo.set("roots(%ld)", rebased)]
            # no backup of rebased cset versions needed
            repair.strip(repo.ui, repo, strippoints)

    if activebookmark and activebookmark in repo._bookmarks:
        bookmarks.activate(repo, activebookmark)

    clearstatus(repo)
    repo.ui.warn(_("rebase aborted\n"))
    return 0
Esempio n. 29
0
def makecollapsed(ui, repo, parent, revs, branch, opts):
    'Creates the collapsed revision on top of parent'

    last = max(revs)
    ui.debug(_('updating to revision %d\n') % parent)
    merge.update(repo, parent.node(), False, False, False)
    ui.debug(_('reverting to revision %d\n') % last)
    recreaterev(ui, repo, last)
    repo.dirstate.setbranch(branch)
    msg = ''
    if opts['message'] != "" :
        msg = opts['message']
    else:
        first = True
        for r in revs:
            if not first:
                msg += '----------------\n'
            first = False
            msg += repo[r].description() + "\n"

        msg += "\nHG: Enter commit message.  Lines beginning with 'HG:' are removed.\n"
        msg += "HG: Remove all lines to abort the collapse operation.\n"

        if ui.config('ui', 'interactive') != 'off':
            msg = ui.edit(msg, ui.username())

        pattern = re.compile("^HG:.*\n", re.MULTILINE);
        msg  = re.sub(pattern, "", msg).strip();

    if not msg:
        raise util.Abort(_('empty commit message, collapse won\'t proceed'))

    newrev = repo.commit(
        text=msg,
        user=repo[last].user(),
        date=repo[last].date())

    return repo[newrev]
Esempio n. 30
0
def publish(ui, repo, source="", node="default", **opts):

    # 只对静态编译框架维护的库进行操作
    if not opm.StaticPackage.is_root(repo.root) or source == "pull":
        return

    publish_branch = ui.config("opm", "publish-branch", "default")  # 默认作为发布源的分支名称
    node = repo[node]
    node_branch = node.branch()

    # 不是需要被编译的分支
    # 不判断分支,因为通过changegroup hook触发编译时,获取到的分支信息有可能不是default,导致不编译
    # if node_branch != publish_branch:
    # ui.warn('%s: ignore branch %s\n' % (repo.root, node_branch))
    # return

    # update到需要编译的分支
    mergemod.update(repo, publish_branch, False, False, None)

    # 生成commitlog
    commitlog_path = os.path.realpath(os.path.join(repo.root, "./commitlog.txt"))
    parent = node.parents()[0].rev()
    rev = node.rev()
    ui.write("%s: update version from %s to %s\n" % (repo.root, parent, rev))
    os.chdir(repo.root)
    os.system("hg log -b %s -r %s:%s > %s" % (node_branch, parent, rev, commitlog_path))

    # 编译自己
    _publish(ui, repo, commitlog_path, rebuild=True)

    # 编译依赖自己的库
    package = opm.StaticPackage(repo.root)
    for repo_path in package.get_reverse_libs(all=True):
        sub_repo = hg.repository(ui, repo_path)
        _publish(sub_repo.ui, sub_repo, commitlog_path, rebuild=False)

    # 删除commitlog
    os.remove(commitlog_path)
Esempio n. 31
0
def abort(repo, originalwd, target, state):
    'Restore the repository to its original state'
    descendants = repo.changelog.descendants
    ispublic = lambda r: repo._phaserev[r] == phases.public
    if filter(ispublic, descendants(target)):
        repo.ui.warn(_("warning: immutable rebased changeset detected, "
                       "can't abort\n"))
        return -1
    elif set(descendants(target)) - set(state.values()):
        repo.ui.warn(_("warning: new changesets detected on target branch, "
                                                    "can't abort\n"))
        return -1
    else:
        # Strip from the first rebased revision
        merge.update(repo, repo[originalwd].rev(), False, True, False)
        rebased = filter(lambda x: x > -1 and x != target, state.values())
        if rebased:
            strippoint = min(rebased)
            # no backup of rebased cset versions needed
            repair.strip(repo.ui, repo, repo[strippoint].node())
        clearstatus(repo)
        repo.ui.warn(_('rebase aborted\n'))
        return 0
Esempio n. 32
0
def makecollapsed(ui, repo, parent, revs, branch, opts):
    'Creates the collapsed revision on top of parent'

    last = max(revs)
    ui.debug(_('updating to revision %d\n') % parent)
    merge.update(repo, parent.node(), False, False, False)
    ui.debug(_('reverting to revision %d\n') % last)
    recreaterev(ui, repo, last)
    repo.dirstate.setbranch(branch)
    msg = ''
    if opts['message'] != "":
        msg = opts['message']
    else:
        first = True
        for r in revs:
            if not first:
                msg += '----------------\n'
            first = False
            msg += repo[r].description() + "\n"

        msg += "\nHG: Enter commit message.  Lines beginning with 'HG:' are removed.\n"
        msg += "HG: Remove all lines to abort the collapse operation.\n"

        if ui.config('ui', 'interactive') != 'off':
            msg = ui.edit(msg, ui.username())

        pattern = re.compile("^HG:.*\n", re.MULTILINE)
        msg = re.sub(pattern, "", msg).strip()

    if not msg:
        raise util.Abort(_('empty commit message, collapse won\'t proceed'))

    newrev = repo.commit(text=msg,
                         user=repo[last].user(),
                         date=repo[last].date())

    return repo[newrev]
Esempio n. 33
0
def rebasemerge(repo, rev, first=False):
    'return the correct ancestor'
    oldancestor = ancestor.ancestor

    def newancestor(a, b, pfunc):
        ancestor.ancestor = oldancestor
        if b == rev:
            return repo[rev].parents()[0].rev()
        return ancestor.ancestor(a, b, pfunc)

    if not first:
        ancestor.ancestor = newancestor
    else:
        repo.ui.debug(_("first revision, do not change ancestor\n"))
    stats = merge.update(repo, rev, True, True, False)
    return stats
Esempio n. 34
0
def rebasemerge(repo, rev, first=False):
    'return the correct ancestor'
    oldancestor = ancestor.ancestor

    def newancestor(a, b, pfunc):
        ancestor.ancestor = oldancestor
        if b == rev:
            return repo[rev].parents()[0].rev()
        return ancestor.ancestor(a, b, pfunc)

    if not first:
        ancestor.ancestor = newancestor
    else:
        repo.ui.debug(_("first revision, do not change ancestor\n"))
    stats = merge.update(repo, rev, True, True, False)
    return stats
Esempio n. 35
0
def applychanges(ui, repo, ctx, opts):
    """Merge changeset from ctx (only) in the current working directory"""
    wcpar = repo.dirstate.parents()[0]
    if ctx.p1().node() == wcpar:
        # edition ar "in place" we do not need to make any merge,
        # just applies changes on parent for edition
        cmdutil.revert(ui, repo, ctx, (wcpar, node.nullid), all=True)
        stats = None
    else:
        try:
            # ui.forcemerge is an internal variable, do not document
            repo.ui.setconfig("ui", "forcemerge", opts.get("tool", ""))
            stats = mergemod.update(repo, ctx.node(), True, True, False, ctx.p1().node())
        finally:
            repo.ui.setconfig("ui", "forcemerge", "")
        repo.setparents(wcpar, node.nullid)
        repo.dirstate.write()
        # fix up dirstate for copies and renames
    cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
    return stats
Esempio n. 36
0
def applychanges(ui, repo, ctx, opts):
    """Merge changeset from ctx (only) in the current working directory"""
    wcpar = repo.dirstate.parents()[0]
    if ctx.p1().node() == wcpar:
        # edition ar "in place" we do not need to make any merge,
        # just applies changes on parent for edition
        cmdutil.revert(ui, repo, ctx, (wcpar, node.nullid), all=True)
        stats = None
    else:
        try:
            # ui.forcemerge is an internal variable, do not document
            repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
            stats = mergemod.update(repo, ctx.node(), True, True, False,
                                    ctx.p1().node())
        finally:
            repo.ui.setconfig('ui', 'forcemerge', '')
        repo.setparents(wcpar, node.nullid)
        repo.dirstate.write()
        # fix up dirstate for copies and renames
    cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
    return stats
Esempio n. 37
0
    def apply(self, repo, source, revmap, merges, opts={}):
        '''apply the revisions in revmap one by one in revision order'''
        revs = sorted(revmap)
        p1, p2 = repo.dirstate.parents()
        pulls = []
        diffopts = patch.diffopts(self.ui, opts)
        diffopts.git = True

        lock = wlock = tr = None
        try:
            wlock = repo.wlock()
            lock = repo.lock()
            tr = repo.transaction('transplant')
            for rev in revs:
                node = revmap[rev]
                revstr = '%s:%s' % (rev, short(node))

                if self.applied(repo, node, p1):
                    self.ui.warn(_('skipping already applied revision %s\n') %
                                 revstr)
                    continue

                parents = source.changelog.parents(node)
                if not (opts.get('filter') or opts.get('log')):
                    # If the changeset parent is the same as the
                    # wdir's parent, just pull it.
                    if parents[0] == p1:
                        pulls.append(node)
                        p1 = node
                        continue
                    if pulls:
                        if source != repo:
                            repo.pull(source.peer(), heads=pulls)
                        merge.update(repo, pulls[-1], False, False, None)
                        p1, p2 = repo.dirstate.parents()
                        pulls = []

                domerge = False
                if node in merges:
                    # pulling all the merge revs at once would mean we
                    # couldn't transplant after the latest even if
                    # transplants before them fail.
                    domerge = True
                    if not hasnode(repo, node):
                        repo.pull(source.peer(), heads=[node])

                skipmerge = False
                if parents[1] != revlog.nullid:
                    if not opts.get('parent'):
                        self.ui.note(_('skipping merge changeset %s:%s\n')
                                     % (rev, short(node)))
                        skipmerge = True
                    else:
                        parent = source.lookup(opts['parent'])
                        if parent not in parents:
                            raise util.Abort(_('%s is not a parent of %s') %
                                             (short(parent), short(node)))
                else:
                    parent = parents[0]

                if skipmerge:
                    patchfile = None
                else:
                    fd, patchfile = tempfile.mkstemp(prefix='hg-transplant-')
                    fp = os.fdopen(fd, 'w')
                    gen = patch.diff(source, parent, node, opts=diffopts)
                    for chunk in gen:
                        fp.write(chunk)
                    fp.close()

                del revmap[rev]
                if patchfile or domerge:
                    try:
                        try:
                            n = self.applyone(repo, node,
                                              source.changelog.read(node),
                                              patchfile, merge=domerge,
                                              log=opts.get('log'),
                                              filter=opts.get('filter'))
                        except TransplantError:
                            # Do not rollback, it is up to the user to
                            # fix the merge or cancel everything
                            tr.close()
                            raise
                        if n and domerge:
                            self.ui.status(_('%s merged at %s\n') % (revstr,
                                      short(n)))
                        elif n:
                            self.ui.status(_('%s transplanted to %s\n')
                                           % (short(node),
                                              short(n)))
                    finally:
                        if patchfile:
                            os.unlink(patchfile)
            tr.close()
            if pulls:
                repo.pull(source.peer(), heads=pulls)
                merge.update(repo, pulls[-1], False, False, None)
        finally:
            self.saveseries(revmap, merges)
            self.transplants.write()
            if tr:
                tr.release()
            lock.release()
            wlock.release()
Esempio n. 38
0
def do_collapse(ui, repo, first, last, revs, movelog, timedelta, opts):        
    ui.debug(_('Collapsing revisions %s\n') % revs)

    if opts['debugdelay']:
        debug_delay = float(opts['debugdelay'])
    else:
        debug_delay = False

    for r in revs:
        if repo[r].user() != ui.username() and not opts['force']:
            raise util.Abort(_('revision %s does not belong to %s\n') %
                (r, ui.username()))
        if r != last:
            children = repo[r].children()
            if len(children) > 1:
                for c in children:
                    if not c.rev() in revs:
                        raise util.Abort(_('revision %s has child %s not '
                            'being collapsed, please rebase\n') % (r, c.rev()))
        if r != first:
            parents = repo[r].parents()
            if len(parents) > 1:
                for p in parents:
                    if not p.rev() in revs:
                        raise util.Abort(_('revision %s has parent %s not '
                            'being collapsed.') % (r, p.rev()))

    if len(repo[first].parents()) > 1:
        raise util.Abort(_('start revision %s has multiple parents, '
            'won\'t collapse.') % first)

    try:
        cmdutil.bailifchanged(repo)
    except AttributeError:
        cmdutil.bail_if_changed(repo)

    parent = repo[first].parents()[0]
    tomove = list(repo.changelog.descendants(last))

    head_hgtags = get_hgtags_from_heads(ui, repo, last)
    if '.hgtags' in parent:
        parent_hgtags = parent['.hgtags'].data()
    else:
        parent_hgtags = False

    movemap = dict.fromkeys(tomove, nullrev)
    ui.debug(_('will move revisions: %s\n') % tomove)

    tagsmap = dict()
    if opts['noop']:
        ui.status(_('noop: not collapsing\n'))
    else:
        origparent = repo['.'].rev()
        collapsed = None

        try:
            branch = repo[last].branch()
            collapsed = makecollapsed(ui, repo, parent, revs, branch, tagsmap,
                                      parent_hgtags, movelog, opts)
            movemap[max(revs)] = collapsed
            movedescendants(ui, repo, collapsed, tomove, movemap, tagsmap, 
                            parent_hgtags, movelog, debug_delay)
            fix_hgtags(ui, repo, head_hgtags, tagsmap)
        except:
            merge.update(repo, repo[origparent].rev(), False, True, False)
            if collapsed:
                repair.strip(ui, repo, collapsed.node(), "strip")
            raise

        if not opts['keep']:
            ui.debug(_('stripping revision %d\n') % first)
            repair.strip(ui, repo, repo[first].node(), "strip")

        ui.status(_('collapse completed\n'))
def update(rev):
    merge.update(repo, rev, False, True, False)
Esempio n. 40
0
def merge_(rev):
    merge.update(repo, rev, branchmerge=True, force=False)
def merge_(rev):
    merge.update(repo, rev, True, False, False)
def merge_(rev):
    merge.update(repo, rev, True, False, False)
def update(rev):
    merge.update(repo, rev, False, True, False)
Esempio n. 44
0
def collapse(ui, repo, **opts):
    """collapse multiple revisions into one

    Collapse combines multiple consecutive changesets into a single changeset,
    preserving any descendants of the final changeset. The commit messages for
    the collapsed changesets are concatenated and may be edited before the
    collapse is completed.
    """

    rng = cmdutil.revrange(repo, opts['rev'])
    if not rng:
        raise util.Abort(_('no revisions specified'))

    first = rng[0]
    last = rng[-1]
    revs = inbetween(repo, first, last)

    if not revs:
        raise util.Abort(_('revision %s is not an ancestor of revision %s\n') %
                            (first, last))
    elif len(revs) == 1:
        raise util.Abort(_('only one revision specified'))

    ui.debug(_('Collapsing revisions %s\n') % revs)

    for r in revs:
        if repo[r].user() != ui.username() and not opts['force']:
            raise util.Abort(_('revision %s does not belong to %s\n') %
                (r, ui.username()))
        if r != last:
            children = repo[r].children()
            if len(children) > 1:
                for c in children:
                    if not c.rev() in revs:
                        raise util.Abort(_('revision %s has child %s not '
                            'being collapsed, please rebase\n') % (r, c.rev()))
        if r != first:
            parents = repo[r].parents()
            if len(parents) > 1:
                for p in parents:
                    if not p.rev() in revs:
                        raise util.Abort(_('revision %s has parent %s not '
                            'being collapsed.') % (r, p.rev()))

    if len(repo[first].parents()) > 1:
        raise util.Abort(_('start revision %s has multiple parents, '
            'won\'t collapse.') % first)

    cmdutil.bail_if_changed(repo)

    parent = repo[first].parents()[0]
    tomove = list(repo.changelog.descendants(last))
    movemap = dict.fromkeys(tomove, nullrev)
    ui.debug(_('will move revisions: %s\n') % tomove)

    origparent = repo['.'].rev()
    collapsed = None

    try:
        branch = repo[last].branch()
        collapsed = makecollapsed(ui, repo, parent, revs, branch, opts)
        movemap[max(revs)] = collapsed
        movedescendants(ui, repo, collapsed, tomove, movemap)
    except:
        merge.update(repo, repo[origparent].rev(), False, True, False)
        if collapsed:
            repair.strip(ui, repo, collapsed.node(), "strip")
        raise

    if not opts['keep']:
        ui.debug(_('stripping revision %d\n') % first)
        repair.strip(ui, repo, repo[first].node(), "strip")

    ui.status(_('collapse completed\n'))
Esempio n. 45
0
def fixupamend(ui, repo):
    """rebases any children found on the preamend changset and strips the
    preamend changset
    """
    wlock = None
    lock = None
    tr = None
    try:
        wlock = repo.wlock()
        lock = repo.lock()
        current = repo['.']

        # Use obsolescence information to fix up the amend instead of relying
        # on the preamend bookmark if the user enables this feature.
        if ui.configbool('fbamend', 'userestack'):
            with repo.transaction('fixupamend') as tr:
                try:
                    common.restackonce(ui, repo, current.rev())
                except error.InterventionRequired:
                    tr.close()
                    raise
            return

        preamendname = _preamendname(repo, current.node())
        if not preamendname in repo._bookmarks:
            raise error.Abort(_('no bookmark %s') % preamendname,
                             hint=_('check if your bookmark is active'))

        old = repo[preamendname]
        if old == current:
            hint = _('please examine smartlog and rebase your changsets '
                     'manually')
            err = _('cannot automatically determine what to rebase '
                    'because bookmark "%s" points to the current changset') % \
                   preamendname
            raise error.Abort(err, hint=hint)
        oldbookmarks = old.bookmarks()

        ui.status(_("rebasing the children of %s\n") % (preamendname))

        active = bmactive(repo)
        opts = {
            'rev' : [str(c.rev()) for c in old.descendants()],
            'dest' : current.rev()
        }

        if opts['rev'] and opts['rev'][0]:
            rebasemod.rebase(ui, repo, **opts)

        changes = []
        for bookmark in oldbookmarks:
            changes.append((bookmark, None)) # delete the bookmark
        tr = repo.transaction('fixupamend')
        repo._bookmarks.applychanges(repo, tr, changes)

        if obsolete.isenabled(repo, obsolete.createmarkersopt):
            tr.close()
        else:
            tr.close()
            repair.strip(ui, repo, old.node(), topic='preamend-backup')

        merge.update(repo, current.node(), False, True, False)
        if active:
            bmactivate(repo, active)
    finally:
        lockmod.release(wlock, lock, tr)
Esempio n. 46
0
    def apply(self, repo, source, revmap, merges, opts={}):
        '''apply the revisions in revmap one by one in revision order'''
        revs = revmap.keys()
        revs.sort()

        p1, p2 = repo.dirstate.parents()
        pulls = []
        diffopts = patch.diffopts(self.ui, opts)
        diffopts.git = True

        lock = wlock = None
        try:
            wlock = repo.wlock()
            lock = repo.lock()
            for rev in revs:
                node = revmap[rev]
                revstr = '%s:%s' % (rev, revlog.short(node))

                if self.applied(repo, node, p1):
                    self.ui.warn(_('skipping already applied revision %s\n') %
                                 revstr)
                    continue

                parents = source.changelog.parents(node)
                if not opts.get('filter'):
                    # If the changeset parent is the same as the wdir's parent,
                    # just pull it.
                    if parents[0] == p1:
                        pulls.append(node)
                        p1 = node
                        continue
                    if pulls:
                        if source != repo:
                            repo.pull(source, heads=pulls)
                        merge.update(repo, pulls[-1], False, False, None)
                        p1, p2 = repo.dirstate.parents()
                        pulls = []

                domerge = False
                if node in merges:
                    # pulling all the merge revs at once would mean we couldn't
                    # transplant after the latest even if transplants before them
                    # fail.
                    domerge = True
                    if not hasnode(repo, node):
                        repo.pull(source, heads=[node])

                if parents[1] != revlog.nullid:
                    self.ui.note(_('skipping merge changeset %s:%s\n')
                                 % (rev, revlog.short(node)))
                    patchfile = None
                else:
                    fd, patchfile = tempfile.mkstemp(prefix='hg-transplant-')
                    fp = os.fdopen(fd, 'w')
                    patch.diff(source, parents[0], node, fp=fp, opts=diffopts)
                    fp.close()

                del revmap[rev]
                if patchfile or domerge:
                    try:
                        n = self.applyone(repo, node,
                                          source.changelog.read(node),
                                          patchfile, merge=domerge,
                                          log=opts.get('log'),
                                          filter=opts.get('filter'))
                        if n and domerge:
                            self.ui.status(_('%s merged at %s\n') % (revstr,
                                      revlog.short(n)))
                        elif n:
                            self.ui.status(_('%s transplanted to %s\n') % (revlog.short(node),
                                                                       revlog.short(n)))
                    finally:
                        if patchfile:
                            os.unlink(patchfile)
            if pulls:
                repo.pull(source, heads=pulls)
                merge.update(repo, pulls[-1], False, False, None)
        finally:
            self.saveseries(revmap, merges)
            self.transplants.write()
            del lock, wlock
Esempio n. 47
0
def collapse(ui, repo, **opts):
    """collapse multiple revisions into one

    Collapse combines multiple consecutive changesets into a single changeset,
    preserving any descendants of the final changeset. The commit messages for
    the collapsed changesets are concatenated and may be edited before the
    collapse is completed.
    """

    rng = cmdutil.revrange(repo, opts['rev'])
    first = rng[0]
    last = rng[len(rng) - 1]
    revs = inbetween(repo, first, last)

    if not revs:
        raise util.Abort(_('revision %s is not an ancestor of revision %s\n') %
                            (first, last))
    elif len(revs) == 1:
        raise util.Abort(_('only one revision specified'))

    ui.debug(_('Collapsing revisions %s\n') % revs)

    for r in revs:
        if repo[r].user() != ui.username() and not opts['force']:
            raise util.Abort(_('revision %s does not belong to %s\n') %
                (r, ui.username()))
        if r != last:
            children = repo[r].children()
            if len(children) > 1:
                for c in children:
                    if not c.rev() in revs:
                        raise util.Abort(_('revision %s has child %s not '
                            'being collapsed, please rebase\n') % (r, c.rev()))
        if r != first:
            parents = repo[r].parents()
            if len(parents) > 1:
                for p in parents:
                    if not p.rev() in revs:
                        raise util.Abort(_('revision %s has parent %s not '
                            'being collapsed.') % (r, p.rev()))

    if len(repo[first].parents()) > 1:
        raise util.Abort(_('start revision %s has multiple parents, '
            'won\'t collapse.') % first)

    cmdutil.bail_if_changed(repo)

    parent = repo[first].parents()[0]
    tomove = list(repo.changelog.descendants(last))
    movemap = dict.fromkeys(tomove, nullrev)
    ui.debug(_('will move revisions: %s\n') % tomove)
    
    origparent = repo['.'].rev()
    collapsed = None
    
    try:
        collapsed = makecollapsed(ui, repo, parent, revs)
        movemap[max(revs)] = collapsed
        movedescendants(ui, repo, collapsed, tomove, movemap)
    except:
        merge.update(repo, repo[origparent].rev(), False, True, False)
        if collapsed:
            repair.strip(ui, repo, collapsed.node(), "strip")
        raise

    if not opts['keep']:
        ui.debug(_('stripping revision %d\n') % first)
        repair.strip(ui, repo, repo[first].node(), "strip")

    ui.status(_('collapse completed\n'))