예제 #1
0
 def applybundle(self):
     fp = self.opener()
     try:
         gen = exchange.readbundle(self.repo.ui, fp, self.fname, self.vfs)
         bundle2.applybundle(self.repo, gen, self.repo.currenttransaction(),
                             source='unshelve',
                             url='bundle:' + self.vfs.join(self.fname),
                             targetphase=phases.secret)
     finally:
         fp.close()
예제 #2
0
 def applybundle(self):
     fp = self.opener()
     try:
         gen = exchange.readbundle(self.repo.ui, fp, self.fname, self.vfs)
         bundle2.applybundle(self.repo, gen, self.repo.currenttransaction(),
                             source='unshelve',
                             url='bundle:' + self.vfs.join(self.fname),
                             targetphase=phases.secret)
     finally:
         fp.close()
예제 #3
0
파일: shelve.py 프로젝트: pombredanne/hg
 def applybundle(self):
     fp = self.opener()
     try:
         targetphase = phases.internal
         if not phases.supportinternal(self.repo):
             targetphase = phases.secret
         gen = exchange.readbundle(self.repo.ui, fp, self.fname, self.vfs)
         pretip = self.repo['tip']
         tr = self.repo.currenttransaction()
         bundle2.applybundle(self.repo,
                             gen,
                             tr,
                             source='unshelve',
                             url='bundle:' + self.vfs.join(self.fname),
                             targetphase=targetphase)
         shelvectx = self.repo['tip']
         if pretip == shelvectx:
             shelverev = tr.changes['revduplicates'][-1]
             shelvectx = self.repo[shelverev]
         return shelvectx
     finally:
         fp.close()
예제 #4
0
def _histedit(ui, repo, state, *freeargs, **opts):
    # TODO only abort if we try and histedit mq patches, not just
    # blanket if mq patches are applied somewhere
    mq = getattr(repo, 'mq', None)
    if mq and mq.applied:
        raise error.Abort(_('source has mq patches applied'))

    # basic argument incompatibility processing
    outg = opts.get('outgoing')
    cont = opts.get('continue')
    editplan = opts.get('edit_plan')
    abort = opts.get('abort')
    force = opts.get('force')
    rules = opts.get('commands', '')
    revs = opts.get('rev', [])
    goal = 'new' # This invocation goal, in new, continue, abort
    if force and not outg:
        raise error.Abort(_('--force only allowed with --outgoing'))
    if cont:
        if any((outg, abort, revs, freeargs, rules, editplan)):
            raise error.Abort(_('no arguments allowed with --continue'))
        goal = 'continue'
    elif abort:
        if any((outg, revs, freeargs, rules, editplan)):
            raise error.Abort(_('no arguments allowed with --abort'))
        goal = 'abort'
    elif editplan:
        if any((outg, revs, freeargs)):
            raise error.Abort(_('only --commands argument allowed with '
                               '--edit-plan'))
        goal = 'edit-plan'
    else:
        if os.path.exists(os.path.join(repo.path, 'histedit-state')):
            raise error.Abort(_('history edit already in progress, try '
                               '--continue or --abort'))
        if outg:
            if revs:
                raise error.Abort(_('no revisions allowed with --outgoing'))
            if len(freeargs) > 1:
                raise error.Abort(
                    _('only one repo argument allowed with --outgoing'))
        else:
            revs.extend(freeargs)
            if len(revs) == 0:
                # experimental config: histedit.defaultrev
                histeditdefault = ui.config('histedit', 'defaultrev')
                if histeditdefault:
                    revs.append(histeditdefault)
            if len(revs) != 1:
                raise error.Abort(
                    _('histedit requires exactly one ancestor revision'))


    replacements = []
    state.keep = opts.get('keep', False)
    supportsmarkers = obsolete.isenabled(repo, obsolete.createmarkersopt)

    # rebuild state
    if goal == 'continue':
        state.read()
        state = bootstrapcontinue(ui, state, opts)
    elif goal == 'edit-plan':
        state.read()
        if not rules:
            comment = editcomment % (node.short(state.parentctxnode),
                                     node.short(state.topmost))
            rules = ruleeditor(repo, ui, state.rules, comment)
        else:
            if rules == '-':
                f = sys.stdin
            else:
                f = open(rules)
            rules = f.read()
            f.close()
        rules = [l for l in (r.strip() for r in rules.splitlines())
                 if l and not l.startswith('#')]
        rules = verifyrules(rules, repo, [repo[c] for [_a, c] in state.rules])
        state.rules = rules
        state.write()
        return
    elif goal == 'abort':
        try:
            state.read()
            tmpnodes, leafs = newnodestoabort(state)
            ui.debug('restore wc to old parent %s\n'
                    % node.short(state.topmost))

            # Recover our old commits if necessary
            if not state.topmost in repo and state.backupfile:
                backupfile = repo.join(state.backupfile)
                f = hg.openpath(ui, backupfile)
                gen = exchange.readbundle(ui, f, backupfile)
                tr = repo.transaction('histedit.abort')
                try:
                    if not isinstance(gen, bundle2.unbundle20):
                        gen.apply(repo, 'histedit', 'bundle:' + backupfile)
                    if isinstance(gen, bundle2.unbundle20):
                        bundle2.applybundle(repo, gen, tr,
                                            source='histedit',
                                            url='bundle:' + backupfile)
                    tr.close()
                finally:
                    tr.release()

                os.remove(backupfile)

            # check whether we should update away
            if repo.unfiltered().revs('parents() and (%n  or %ln::)',
                                    state.parentctxnode, leafs | tmpnodes):
                hg.clean(repo, state.topmost)
            cleanupnode(ui, repo, 'created', tmpnodes)
            cleanupnode(ui, repo, 'temp', leafs)
        except Exception:
            if state.inprogress():
                ui.warn(_('warning: encountered an exception during histedit '
                    '--abort; the repository may not have been completely '
                    'cleaned up\n'))
            raise
        finally:
                state.clear()
        return
    else:
        cmdutil.checkunfinished(repo)
        cmdutil.bailifchanged(repo)

        topmost, empty = repo.dirstate.parents()
        if outg:
            if freeargs:
                remote = freeargs[0]
            else:
                remote = None
            root = findoutgoing(ui, repo, remote, force, opts)
        else:
            rr = list(repo.set('roots(%ld)', scmutil.revrange(repo, revs)))
            if len(rr) != 1:
                raise error.Abort(_('The specified revisions must have '
                    'exactly one common root'))
            root = rr[0].node()

        revs = between(repo, root, topmost, state.keep)
        if not revs:
            raise error.Abort(_('%s is not an ancestor of working directory') %
                             node.short(root))

        ctxs = [repo[r] for r in revs]
        if not rules:
            comment = editcomment % (node.short(root), node.short(topmost))
            rules = ruleeditor(repo, ui, [['pick', c] for c in ctxs], comment)
        else:
            if rules == '-':
                f = sys.stdin
            else:
                f = open(rules)
            rules = f.read()
            f.close()
        rules = [l for l in (r.strip() for r in rules.splitlines())
                 if l and not l.startswith('#')]
        rules = verifyrules(rules, repo, ctxs)

        parentctxnode = repo[root].parents()[0].node()

        state.parentctxnode = parentctxnode
        state.rules = rules
        state.topmost = topmost
        state.replacements = replacements

        # Create a backup so we can always abort completely.
        backupfile = None
        if not obsolete.isenabled(repo, obsolete.createmarkersopt):
            backupfile = repair._bundle(repo, [parentctxnode], [topmost], root,
                                        'histedit')
        state.backupfile = backupfile

    # preprocess rules so that we can hide inner folds from the user
    # and only show one editor
    rules = state.rules[:]
    for idx, ((action, ha), (nextact, unused)) in enumerate(
            zip(rules, rules[1:] + [(None, None)])):
        if action == 'fold' and nextact == 'fold':
            state.rules[idx] = '_multifold', ha

    while state.rules:
        state.write()
        action, ha = state.rules.pop(0)
        ui.debug('histedit: processing %s %s\n' % (action, ha[:12]))
        actobj = actiontable[action].fromrule(state, ha)
        parentctx, replacement_ = actobj.run()
        state.parentctxnode = parentctx.node()
        state.replacements.extend(replacement_)
    state.write()

    hg.update(repo, state.parentctxnode)

    mapping, tmpnodes, created, ntm = processreplacement(state)
    if mapping:
        for prec, succs in mapping.iteritems():
            if not succs:
                ui.debug('histedit: %s is dropped\n' % node.short(prec))
            else:
                ui.debug('histedit: %s is replaced by %s\n' % (
                    node.short(prec), node.short(succs[0])))
                if len(succs) > 1:
                    m = 'histedit:                            %s'
                    for n in succs[1:]:
                        ui.debug(m % node.short(n))

    if supportsmarkers:
        # Only create markers if the temp nodes weren't already removed.
        obsolete.createmarkers(repo, ((repo[t],()) for t in sorted(tmpnodes)
                                       if t in repo))
    else:
        cleanupnode(ui, repo, 'temp', tmpnodes)

    if not state.keep:
        if mapping:
            movebookmarks(ui, repo, mapping, state.topmost, ntm)
            # TODO update mq state
        if supportsmarkers:
            markers = []
            # sort by revision number because it sound "right"
            for prec in sorted(mapping, key=repo.changelog.rev):
                succs = mapping[prec]
                markers.append((repo[prec],
                                tuple(repo[s] for s in succs)))
            if markers:
                obsolete.createmarkers(repo, markers)
        else:
            cleanupnode(ui, repo, 'replaced', mapping)

    state.clear()
    if os.path.exists(repo.sjoin('undo')):
        os.unlink(repo.sjoin('undo'))
예제 #5
0
def backups(ui, repo, *pats, **opts):
    '''lists the changesets available in backup bundles

    Without any arguments, this command prints a list of the changesets in each
    backup bundle.

    --recover takes a changeset hash and unbundles the first bundle that
    contains that hash, which puts that changeset back in your repository.

    --verbose will print the entire commit message and the bundle path for that
    backup.
    '''
    supportsmarkers = obsolete.isenabled(repo, obsolete.createmarkersopt)
    if supportsmarkers and ui.configbool('backups', 'warnobsolescence', True):
        # Warn users of obsolescence markers that they probably don't want to
        # use backups but reflog instead
        ui.warn(msgwithcreatermarkers)
    backuppath = repo.vfs.join("strip-backup")
    backups = filter(os.path.isfile, glob.glob(backuppath + "/*.hg"))
    backups.sort(key=lambda x: os.path.getmtime(x), reverse=True)

    opts['bundle'] = ''
    opts['force'] = None

    if util.safehasattr(cmdutil, 'loglimit'):
        # legacy case
        loglimit = cmdutil.loglimit
        show_changeset = cmdutil.show_changeset
    else:
        # since core commit c8e2d6ed1f9e
        from mercurial import logcmdutil
        loglimit = logcmdutil.getlimit
        show_changeset = logcmdutil.changesetdisplayer

    def display(other, chlist, displayer):
        limit = loglimit(opts)
        if opts.get('newest_first'):
            chlist.reverse()
        count = 0
        for n in chlist:
            if limit is not None and count >= limit:
                break
            parents = [p for p in other.changelog.parents(n) if p != nullid]
            if opts.get('no_merges') and len(parents) == 2:
                continue
            count += 1
            displayer.show(other[n])

    recovernode = opts.get('recover')
    if recovernode:
        if scmutil.isrevsymbol(repo, recovernode):
            ui.warn(_("%s already exists in the repo\n") % recovernode)
            return
    else:
        msg = _('Recover changesets using: hg backups --recover '
                '<changeset hash>\n\nAvailable backup changesets:')
        ui.status(msg, label="status.removed")

    for backup in backups:
        # Much of this is copied from the hg incoming logic
        source = os.path.relpath(backup, pycompat.getcwd())
        source = ui.expandpath(source)
        source, branches = hg.parseurl(source, opts.get('branch'))
        try:
            other = hg.peer(repo, opts, source)
        except error.LookupError as ex:
            msg = _("\nwarning: unable to open bundle %s") % source
            hint = _("\n(missing parent rev %s)\n") % short(ex.name)
            ui.warn(msg)
            ui.warn(hint)
            continue
        revs, checkout = hg.addbranchrevs(repo, other, branches,
                                          opts.get('rev'))

        if revs:
            revs = [other.lookup(rev) for rev in revs]

        quiet = ui.quiet
        try:
            ui.quiet = True
            other, chlist, cleanupfn = bundlerepo.getremotechanges(ui, repo,
                                        other, revs, opts["bundle"],
                                        opts["force"])
        except error.LookupError:
            continue
        finally:
            ui.quiet = quiet

        try:
            if chlist:
                if recovernode:
                    tr = lock = None
                    try:
                        lock = repo.lock()
                        if scmutil.isrevsymbol(other, recovernode):
                            ui.status(_("Unbundling %s\n") % (recovernode))
                            f = hg.openpath(ui, source)
                            gen = exchange.readbundle(ui, f, source)
                            tr = repo.transaction("unbundle")
                            if not isinstance(gen, bundle2.unbundle20):
                                gen.apply(repo, 'unbundle', 'bundle:' + source)
                            if isinstance(gen, bundle2.unbundle20):
                                bundle2.applybundle(repo, gen, tr,
                                                    source='unbundle',
                                                    url='bundle:' + source)
                            tr.close()
                            break
                    finally:
                        lockmod.release(lock, tr)
                else:
                    backupdate = os.path.getmtime(source)
                    backupdate = time.strftime('%a %H:%M, %Y-%m-%d',
                                                time.localtime(backupdate))
                    ui.status("\n%s\n" % (backupdate.ljust(50)))
                    if not ui.verbose:
                        opts['template'] = verbosetemplate
                    else:
                        ui.status("%s%s\n" % ("bundle:".ljust(13), source))
                    displayer = show_changeset(ui, other, opts, False)
                    display(other, chlist, displayer)
                    displayer.close()
        finally:
            cleanupfn()