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()
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()
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'))
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()