Mercurial > hg-stable
changeset 17139:ad1b5e070f16
merge with main
author | Martin Geisler <mg@aragost.com> |
---|---|
date | Thu, 12 Jul 2012 10:03:50 +0200 |
parents | 528cb91a90ee (current diff) 4fb2d3d16743 (diff) |
children | f7152a0d90df |
files | mercurial/localrepo.py mercurial/revlog.py |
diffstat | 12 files changed, 389 insertions(+), 136 deletions(-) [+] |
line wrap: on
line diff
--- a/hgext/histedit.py Wed Jul 11 15:39:00 2012 -0700 +++ b/hgext/histedit.py Thu Jul 12 10:03:50 2012 +0200 @@ -4,10 +4,142 @@ # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -"""Interactive history editing. +"""interactive history editing + +With this extension installed, Mercurial gains one new command: histedit. Usage +is as follows, assuming the following history:: + + @ 3[tip] 7c2fd3b9020c 2009-04-27 18:04 -0500 durin42 + | Add delta + | + o 2 030b686bedc4 2009-04-27 18:04 -0500 durin42 + | Add gamma + | + o 1 c561b4e977df 2009-04-27 18:04 -0500 durin42 + | Add beta + | + o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42 + Add alpha + +If you were to run ``hg histedit c561b4e977df``, you would see the following +file open in your editor:: + + pick c561b4e977df Add beta + pick 030b686bedc4 Add gamma + pick 7c2fd3b9020c Add delta + + # Edit history between 633536316234 and 7c2fd3b9020c + # + # Commands: + # p, pick = use commit + # e, edit = use commit, but stop for amending + # f, fold = use commit, but fold into previous commit + # d, drop = remove commit from history + # m, mess = edit message without changing commit content + # + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + +In this file, lines beginning with ``#`` are ignored. You must specify a rule +for each revision in your history. For example, if you had meant to add gamma +before beta, and then wanted to add delta in the same revision as beta, you +would reorganize the file to look like this:: + + pick 030b686bedc4 Add gamma + pick c561b4e977df Add beta + fold 7c2fd3b9020c Add delta + + # Edit history between 633536316234 and 7c2fd3b9020c + # + # Commands: + # p, pick = use commit + # e, edit = use commit, but stop for amending + # f, fold = use commit, but fold into previous commit + # d, drop = remove commit from history + # m, mess = edit message without changing commit content + # + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + +At which point you close the editor and ``histedit`` starts working. When you +specify a ``fold`` operation, ``histedit`` will open an editor when it folds +those revisions together, offering you a chance to clean up the commit message:: + + Add beta + *** + Add delta -Inspired by git rebase --interactive. +Edit the commit message to your liking, then close the editor. For +this example, let's assume that the commit message was changed to +``Add beta and delta.`` After histedit has run and had a chance to +remove any old or temporary revisions it needed, the history looks +like this:: + + @ 2[tip] 989b4d060121 2009-04-27 18:04 -0500 durin42 + | Add beta and delta. + | + o 1 081603921c3f 2009-04-27 18:04 -0500 durin42 + | Add gamma + | + o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42 + Add alpha + +Note that ``histedit`` does *not* remove any revisions (even its own temporary +ones) until after it has completed all the editing operations, so it will +probably perform several strip operations when it's done. For the above example, +it had to run strip twice. Strip can be slow depending on a variety of factors, +so you might need to be a little patient. You can choose to keep the original +revisions by passing the ``--keep`` flag. + +The ``edit`` operation will drop you back to a command prompt, +allowing you to edit files freely, or even use ``hg record`` to commit +some changes as a separate commit. When you're done, any remaining +uncommitted changes will be committed as well. When done, run ``hg +histedit --continue`` to finish this step. You'll be prompted for a +new commit message, but the default commit message will be the +original message for the ``edit`` ed revision. + +The ``message`` operation will give you a chance to revise a commit +message without changing the contents. It's a shortcut for doing +``edit`` immediately followed by `hg histedit --continue``. + +If ``histedit`` encounters a conflict when moving a revision (while +handling ``pick`` or ``fold``), it'll stop in a similar manner to +``edit`` with the difference that it won't prompt you for a commit +message when done. If you decide at this point that you don't like how +much work it will be to rearrange history, or that you made a mistake, +you can use ``hg histedit --abort`` to abandon the new changes you +have made and return to the state before you attempted to edit your +history. + +If we clone the example repository above and add three more changes, such that +we have the following history:: + + @ 6[tip] 038383181893 2009-04-27 18:04 -0500 stefan + | Add theta + | + o 5 140988835471 2009-04-27 18:04 -0500 stefan + | Add eta + | + o 4 122930637314 2009-04-27 18:04 -0500 stefan + | Add zeta + | + o 3 836302820282 2009-04-27 18:04 -0500 stefan + | Add epsilon + | + o 2 989b4d060121 2009-04-27 18:04 -0500 durin42 + | Add beta and delta. + | + o 1 081603921c3f 2009-04-27 18:04 -0500 durin42 + | Add gamma + | + o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42 + Add alpha + +If you run ``hg histedit --outgoing`` on the clone then it is the same +as running ``hg histedit 836302820282``. If you need plan to push to a +repository that Mercurial does not detect to be related to the source +repo, you can add a ``--force`` option. """ + try: import cPickle as pickle except ImportError: @@ -243,7 +375,7 @@ 'mess': message, } def histedit(ui, repo, *parent, **opts): - """hg histedit <parent> + """interactively edit changeset history """ # TODO only abort if we try and histedit mq patches, not just # blanket if mq patches are applied somewhere @@ -307,7 +439,11 @@ new = repo.commit(text=message, user=oldctx.user(), date=oldctx.date(), extra=oldctx.extra()) - if action in ('f', 'fold'): + # If we're resuming a fold and we have new changes, mark the + # replacements and finish the fold. If not, it's more like a + # drop of the changesets that disappeared, and we can skip + # this step. + if action in ('f', 'fold') and (new or newchildren): if new: tmpnodes.append(new) else: @@ -396,13 +532,11 @@ (parentctx, created_, replaced_, tmpnodes_) = actiontable[action]( ui, repo, parentctx, ha, opts) - hexshort = lambda x: node.hex(x)[:12] - if replaced_: clen, rlen = len(created_), len(replaced_) if clen == rlen == 1: ui.debug('histedit: exact replacement of %s with %s\n' % ( - hexshort(replaced_[0]), hexshort(created_[0]))) + node.short(replaced_[0]), node.short(created_[0]))) replacemap[replaced_[0]] = created_[0] elif clen > rlen: @@ -412,7 +546,7 @@ # TODO synthesize patch names for created patches replacemap[replaced_[0]] = created_[-1] ui.debug('histedit: created many, assuming %s replaced by %s' % - (hexshort(replaced_[0]), hexshort(created_[-1]))) + (node.short(replaced_[0]), node.short(created_[-1]))) elif rlen > clen: if not created_: # This must be a drop. Try and put our metadata on @@ -420,7 +554,7 @@ assert rlen == 1 r = replaced_[0] ui.debug('histedit: %s seems replaced with nothing, ' - 'finding a parent\n' % (hexshort(r))) + 'finding a parent\n' % (node.short(r))) pctx = repo[r].parents()[0] if pctx.node() in replacemap: ui.debug('histedit: parent is already replaced\n') @@ -428,12 +562,12 @@ else: replacemap[r] = pctx.node() ui.debug('histedit: %s best replaced by %s\n' % ( - hexshort(r), hexshort(replacemap[r]))) + node.short(r), node.short(replacemap[r]))) else: assert len(created_) == 1 for r in replaced_: ui.debug('histedit: %s replaced by %s\n' % ( - hexshort(r), hexshort(created_[0]))) + node.short(r), node.short(created_[0]))) replacemap[r] = created_[0] else: assert False, ( @@ -456,8 +590,8 @@ return while new in replacemap: new = replacemap[new] - ui.note(_('histedit: %s to %s\n') % (hexshort(old), - hexshort(new))) + ui.note(_('histedit: %s to %s\n') % (node.short(old), + node.short(new))) octx = repo[old] marks = octx.bookmarks() if marks: @@ -559,6 +693,6 @@ 'force outgoing even for unrelated repositories')), ('r', 'rev', [], _('first revision to be edited')), ], - __doc__, + _("[PARENT]"), ), }
--- a/hgext/largefiles/basestore.py Wed Jul 11 15:39:00 2012 -0700 +++ b/hgext/largefiles/basestore.py Thu Jul 12 10:03:50 2012 +0200 @@ -48,8 +48,8 @@ '''Put source file into the store under <filename>/<hash>.''' raise NotImplementedError('abstract method') - def exists(self, hash): - '''Check to see if the store contains the given hash.''' + def exists(self, hashes): + '''Check to see if the store contains the given hashes.''' raise NotImplementedError('abstract method') def get(self, files):
--- a/hgext/largefiles/lfcommands.py Wed Jul 11 15:39:00 2012 -0700 +++ b/hgext/largefiles/lfcommands.py Thu Jul 12 10:03:50 2012 +0200 @@ -340,7 +340,11 @@ store = basestore._openstore(rsrc, rdst, put=True) at = 0 - files = filter(lambda h: not store.exists(h), files) + ui.debug("sending statlfile command for %d largefiles\n" % len(files)) + retval = store.exists(files) + files = filter(lambda h: not retval[h], files) + ui.debug("%d largefiles need to be uploaded\n" % len(files)) + for hash in files: ui.progress(_('uploading largefiles'), at, unit='largefile', total=len(files))
--- a/hgext/largefiles/proto.py Wed Jul 11 15:39:00 2012 -0700 +++ b/hgext/largefiles/proto.py Thu Jul 12 10:03:50 2012 +0200 @@ -7,6 +7,7 @@ import urllib2 from mercurial import error, httprepo, util, wireproto +from mercurial.wireproto import batchable, future from mercurial.i18n import _ import lfutil @@ -119,15 +120,19 @@ length)) return (length, stream) + @batchable def statlfile(self, sha): + f = future() + result = {'sha': sha} + yield result, f try: - return int(self._call("statlfile", sha=sha)) + yield int(f.value) except (ValueError, urllib2.HTTPError): # If the server returns anything but an integer followed by a # newline, newline, it's not speaking our language; if we get # an HTTP error, we can't be sure the largefile is present; # either way, consider it missing. - return 2 + yield 2 repo.__class__ = lfileswirerepository
--- a/hgext/largefiles/remotestore.py Wed Jul 11 15:39:00 2012 -0700 +++ b/hgext/largefiles/remotestore.py Thu Jul 12 10:03:50 2012 +0200 @@ -10,6 +10,7 @@ from mercurial import util from mercurial.i18n import _ +from mercurial.wireproto import remotebatch import lfutil import basestore @@ -20,8 +21,6 @@ super(remotestore, self).__init__(ui, repo, url) def put(self, source, hash): - if self._verify(hash): - return if self.sendfile(source, hash): raise util.Abort( _('remotestore: could not put %s to remote store %s') @@ -29,8 +28,8 @@ self.ui.debug( _('remotestore: put %s to remote store %s') % (source, self.url)) - def exists(self, hash): - return self._verify(hash) + def exists(self, hashes): + return self._verify(hashes) def sendfile(self, filename, hash): self.ui.debug('remotestore: sendfile(%s, %s)\n' % (filename, hash)) @@ -74,8 +73,8 @@ infile = lfutil.limitreader(infile, length) return lfutil.copyandhash(lfutil.blockstream(infile), tmpfile) - def _verify(self, hash): - return not self._stat(hash) + def _verify(self, hashes): + return self._stat(hashes) def _verifyfile(self, cctx, cset, contents, standin, verified): filename = lfutil.splitstandin(standin) @@ -104,3 +103,8 @@ else: raise RuntimeError('verify failed: unexpected response from ' 'statlfile (%r)' % stat) + + def batch(self): + '''Support for remote batching.''' + return remotebatch(self) +
--- a/hgext/largefiles/wirestore.py Wed Jul 11 15:39:00 2012 -0700 +++ b/hgext/largefiles/wirestore.py Thu Jul 12 10:03:50 2012 +0200 @@ -25,5 +25,13 @@ def _get(self, hash): return self.remote.getlfile(hash) - def _stat(self, hash): - return self.remote.statlfile(hash) + def _stat(self, hashes): + batch = self.remote.batch() + futures = {} + for hash in hashes: + futures[hash] = batch.statlfile(hash) + batch.submit() + retval = {} + for hash in hashes: + retval[hash] = not futures[hash].value + return retval
--- a/mercurial/commands.py Wed Jul 11 15:39:00 2012 -0700 +++ b/mercurial/commands.py Thu Jul 12 10:03:50 2012 +0200 @@ -2061,17 +2061,22 @@ succs = tuple(bin(succ) for succ in successors) l = repo.lock() try: - repo.obsstore.create(bin(precursor), succs, 0, metadata) + tr = repo.transaction('debugobsolete') + try: + repo.obsstore.create(tr, bin(precursor), succs, 0, metadata) + tr.close() + finally: + tr.release() finally: l.release() else: - for mctx in obsolete.allmarkers(repo): - ui.write(hex(mctx.precnode())) - for repl in mctx.succnodes(): + for m in obsolete.allmarkers(repo): + ui.write(hex(m.precnode())) + for repl in m.succnodes(): ui.write(' ') ui.write(hex(repl)) - ui.write(' %X ' % mctx._data[2]) - ui.write(mctx.metadata()) + ui.write(' %X ' % m._data[2]) + ui.write(m.metadata()) ui.write('\n') @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
--- a/mercurial/localrepo.py Wed Jul 11 15:39:00 2012 -0700 +++ b/mercurial/localrepo.py Thu Jul 12 10:03:50 2012 +0200 @@ -197,10 +197,7 @@ @storecache('obsstore') def obsstore(self): - store = obsolete.obsstore() - data = self.sopener.tryread('obsstore') - if data: - store.loadmarkers(data) + store = obsolete.obsstore(self.sopener) return store @storecache('00changelog.i') @@ -994,16 +991,6 @@ self.store.write() if '_phasecache' in vars(self): self._phasecache.write() - if 'obsstore' in vars(self) and self.obsstore._new: - # XXX: transaction logic should be used here. But for - # now rewriting the whole file is good enough. - f = self.sopener('obsstore', 'wb', atomictemp=True) - try: - self.obsstore.flushmarkers(f) - f.close() - except: # re-raises - f.discard() - raise for k, ce in self._filecache.items(): if k == 'dirstate': continue @@ -1622,6 +1609,10 @@ return r def pull(self, remote, heads=None, force=False): + # don't open transaction for nothing or you break future useful + # rollback call + tr = None + trname = 'pull\n' + util.hidepassword(remote.url()) lock = self.lock() try: tmp = discovery.findcommonincoming(self, remote, heads=heads, @@ -1632,6 +1623,7 @@ added = [] result = 0 else: + tr = self.transaction(trname) if heads is None and list(common) == [nullid]: self.ui.status(_("requesting all changes\n")) elif heads is None and remote.capable('changegroupsubset'): @@ -1680,9 +1672,15 @@ remoteobs = remote.listkeys('obsolete') if 'dump' in remoteobs: + if tr is None: + tr = self.transaction(trname) data = base85.b85decode(remoteobs['dump']) - self.obsstore.mergemarkers(data) + self.obsstore.mergemarkers(tr, data) + if tr is not None: + tr.close() finally: + if tr is not None: + tr.release() lock.release() return result @@ -1823,9 +1821,8 @@ self.ui.warn(_('updating %s to public failed!\n') % newremotehead) if 'obsolete' in self.listkeys('namespaces') and self.obsstore: - data = self.obsstore._writemarkers() - r = remote.pushkey('obsolete', 'dump', '', - base85.b85encode(data)) + data = self.listkeys('obsolete')['dump'] + r = remote.pushkey('obsolete', 'dump', '', data) if not r: self.ui.warn(_('failed to push obsolete markers!\n')) finally:
--- a/mercurial/obsolete.py Wed Jul 11 15:39:00 2012 -0700 +++ b/mercurial/obsolete.py Thu Jul 12 10:03:50 2012 +0200 @@ -156,12 +156,16 @@ - successors: new -> set(old) """ - def __init__(self): + def __init__(self, sopener): self._all = [] # new markers to serialize - self._new = [] self.precursors = {} self.successors = {} + self.sopener = sopener + data = sopener.tryread('obsstore') + if data: + for marker in _readmarkers(data): + self._load(marker) def __iter__(self): return iter(self._all) @@ -169,7 +173,7 @@ def __nonzero__(self): return bool(self._all) - def create(self, prec, succs=(), flag=0, metadata=None): + def create(self, transaction, prec, succs=(), flag=0, metadata=None): """obsolete: add a new obsolete marker * ensuring it is hashable @@ -184,33 +188,33 @@ if len(succ) != 20: raise ValueError(succ) marker = (str(prec), tuple(succs), int(flag), encodemeta(metadata)) - self.add(marker) - - def add(self, marker): - """Add a new marker to the store + self.add(transaction, marker) - This marker still needs to be written to disk""" - self._new.append(marker) - self._load(marker) - - def loadmarkers(self, data): - """Load all markers in data, mark them as known.""" - for marker in _readmarkers(data): + def add(self, transaction, marker): + """Add a new marker to the store""" + if marker not in self._all: + f = self.sopener('obsstore', 'ab') + try: + offset = f.tell() + transaction.add('obsstore', offset) + if offset == 0: + # new file add version header + f.write(_pack('>B', _fmversion)) + _writemarkers(f.write, [marker]) + finally: + # XXX: f.close() == filecache invalidation == obsstore rebuilt. + # call 'filecacheentry.refresh()' here + f.close() self._load(marker) - def mergemarkers(self, data): - other = set(_readmarkers(data)) + def mergemarkers(self, transation, data): + other = _readmarkers(data) local = set(self._all) - new = other - local + new = [m for m in other if m not in local] for marker in new: - self.add(marker) - - def flushmarkers(self, stream): - """Write all markers to a stream - - After this operation, "new" markers are considered "known".""" - self._writemarkers(stream) - self._new[:] = [] + # XXX: N marker == N x (open, write, close) + # we should write them all at once + self.add(transation, marker) def _load(self, marker): self._all.append(marker) @@ -219,32 +223,25 @@ for suc in sucs: self.successors.setdefault(suc, set()).add(marker) - def _writemarkers(self, stream=None): - # Kept separate from flushmarkers(), it will be reused for - # markers exchange. - if stream is None: - final = [] - w = final.append - else: - w = stream.write - w(_pack('>B', _fmversion)) - for marker in self._all: - pre, sucs, flags, metadata = marker - nbsuc = len(sucs) - format = _fmfixed + (_fmnode * nbsuc) - data = [nbsuc, len(metadata), flags, pre] - data.extend(sucs) - w(_pack(format, *data)) - w(metadata) - if stream is None: - return ''.join(final) +def _writemarkers(write, markers): + # Kept separate from flushmarkers(), it will be reused for + # markers exchange. + for marker in markers: + pre, sucs, flags, metadata = marker + nbsuc = len(sucs) + format = _fmfixed + (_fmnode * nbsuc) + data = [nbsuc, len(metadata), flags, pre] + data.extend(sucs) + write(_pack(format, *data)) + write(metadata) def listmarkers(repo): """List markers over pushkey""" if not repo.obsstore: return {} - data = repo.obsstore._writemarkers() - return {'dump': base85.b85encode(data)} + data = [_pack('>B', _fmversion)] + _writemarkers(data.append, repo.obsstore) + return {'dump': base85.b85encode(''.join(data))} def pushmarker(repo, key, old, new): """Push markers over pushkey""" @@ -257,8 +254,13 @@ data = base85.b85decode(new) lock = repo.lock() try: - repo.obsstore.mergemarkers(data) - return 1 + tr = repo.transaction('pushkey: obsolete markers') + try: + repo.obsstore.mergemarkers(tr, data) + tr.close() + return 1 + finally: + tr.release() finally: lock.release()
--- a/mercurial/revlog.py Wed Jul 11 15:39:00 2012 -0700 +++ b/mercurial/revlog.py Thu Jul 12 10:03:50 2012 +0200 @@ -75,35 +75,6 @@ s.update(text) return s.digest() -def compress(text): - """ generate a possibly-compressed representation of text """ - if not text: - return ("", text) - l = len(text) - bin = None - if l < 44: - pass - elif l > 1000000: - # zlib makes an internal copy, thus doubling memory usage for - # large files, so lets do this in pieces - z = zlib.compressobj() - p = [] - pos = 0 - while pos < l: - pos2 = pos + 2**20 - p.append(z.compress(text[pos:pos2])) - pos = pos2 - p.append(z.flush()) - if sum(map(len, p)) < l: - bin = "".join(p) - else: - bin = _compress(text) - if bin is None or len(bin) > l: - if text[0] == '\0': - return ("", text) - return ('u', text) - return ("", bin) - def decompress(bin): """ decompress the given input """ if not bin: @@ -1017,6 +988,35 @@ dfh.close() ifh.close() + def compress(self, text): + """ generate a possibly-compressed representation of text """ + if not text: + return ("", text) + l = len(text) + bin = None + if l < 44: + pass + elif l > 1000000: + # zlib makes an internal copy, thus doubling memory usage for + # large files, so lets do this in pieces + z = zlib.compressobj() + p = [] + pos = 0 + while pos < l: + pos2 = pos + 2**20 + p.append(z.compress(text[pos:pos2])) + pos = pos2 + p.append(z.flush()) + if sum(map(len, p)) < l: + bin = "".join(p) + else: + bin = _compress(text) + if bin is None or len(bin) > l: + if text[0] == '\0': + return ("", text) + return ('u', text) + return ("", bin) + def _addrevision(self, node, text, transaction, link, p1, p2, cachedelta, ifh, dfh): """internal function to add revisions to the log @@ -1049,7 +1049,7 @@ t = buildtext() ptext = self.revision(self.node(rev)) delta = mdiff.textdiff(ptext, t) - data = compress(delta) + data = self.compress(delta) l = len(data[1]) + len(data[0]) if basecache[0] == rev: chainbase = basecache[1] @@ -1094,7 +1094,7 @@ textlen = len(text) if d is None or dist > textlen * 2: text = buildtext() - data = compress(text) + data = self.compress(text) l = len(data[1]) + len(data[0]) base = chainbase = curr
--- a/tests/test-histedit-fold.t Wed Jul 11 15:39:00 2012 -0700 +++ b/tests/test-histedit-fold.t Thu Jul 12 10:03:50 2012 +0200 @@ -108,3 +108,78 @@ f $ cd .. + +folding and creating no new change doesn't break: + $ mkdir fold-to-empty-test + $ cd fold-to-empty-test + $ hg init + $ printf "1\n2\n3\n" > file + $ hg add file + $ hg commit -m '1+2+3' + $ echo 4 >> file + $ hg commit -m '+4' + $ echo 5 >> file + $ hg commit -m '+5' + $ echo 6 >> file + $ hg commit -m '+6' + $ hg log --graph + @ changeset: 3:251d831eeec5 + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: +6 + | + o changeset: 2:888f9082bf99 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: +5 + | + o changeset: 1:617f94f13c0f + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: +4 + | + o changeset: 0:0189ba417d34 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: 1+2+3 + + + $ cat > editor.py <<EOF + > import re, sys + > rules = sys.argv[1] + > data = open(rules).read() + > data = re.sub(r'pick ([0-9a-f]{12} 2 \+5)', r'drop \1', data) + > data = re.sub(r'pick ([0-9a-f]{12} 2 \+6)', r'fold \1', data) + > open(rules, 'w').write(data) + > EOF + + $ HGEDITOR='python editor.py' hg histedit 1 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + patching file file + Hunk #1 FAILED at 2 + 1 out of 1 hunks FAILED -- saving rejects to file file.rej + abort: Fix up the change and run hg histedit --continue + [255] +There were conflicts, but we'll continue without resolving. This +should effectively drop the changes from +6. + $ hg status + ? editor.py + ? file.rej + $ hg histedit --continue + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + saved backup bundle to $TESTTMP/*-backup.hg (glob) + $ hg log --graph + @ changeset: 1:617f94f13c0f + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: +4 + | + o changeset: 0:0189ba417d34 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: 1+2+3 + + + $ cd ..
--- a/tests/test-obsolete.t Wed Jul 11 15:39:00 2012 -0700 +++ b/tests/test-obsolete.t Thu Jul 12 10:03:50 2012 +0200 @@ -158,9 +158,28 @@ added 6 changesets with 6 changes to 6 files (+3 heads) (run 'hg heads' to see heads, 'hg merge' to merge) $ hg debugobsolete + 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'} + cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'} ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'} + 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'} + +Rollback//Transaction support + + $ hg debugobsolete -d '1340 0' aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + $ hg debugobsolete + 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'} cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'} + ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'} + 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'} + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 0 {'date': '1340 0', 'user': 'test'} + $ hg rollback -n + repository tip rolled back to revision 5 (undo debugobsolete) + $ hg rollback + repository tip rolled back to revision 5 (undo debugobsolete) + $ hg debugobsolete 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'} + cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'} + ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'} 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'} $ cd .. @@ -176,9 +195,9 @@ adding file changes added 6 changesets with 6 changes to 6 files (+3 heads) $ hg -R tmpd debugobsolete - ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'} + 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'} cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'} - 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'} + ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'} 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'} @@ -200,9 +219,9 @@ (run 'hg heads' to see heads, 'hg merge' to merge) $ hg debugobsolete 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339 0 {'date': '1339 0', 'user': 'test'} - ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'} + 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'} cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'} - 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'} + ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'} 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'} On push @@ -213,8 +232,8 @@ no changes found [1] $ hg -R ../tmpc debugobsolete - ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'} + 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'} cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'} - 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'} + ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'} 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'} 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339 0 {'date': '1339 0', 'user': 'test'}