# HG changeset patch # User Kostia Balytskyi # Date 1459548770 25200 # Node ID f456834b2f7e664250ebbb9e165afa690a296967 # Parent 2637d6ad3e61cc8bcc16529a5a6124169f41c94f commands: allow debugobsolete to delete arbitrary obsmarkers Sample usage is: '$ hg debugobsolete --delete 0 5' This is a debug feature that will help people working on evolution and obsolescense. diff -r 2637d6ad3e61 -r f456834b2f7e mercurial/commands.py --- a/mercurial/commands.py Fri Apr 01 15:20:31 2016 -0700 +++ b/mercurial/commands.py Fri Apr 01 15:12:50 2016 -0700 @@ -3041,6 +3041,7 @@ _('record parent information for the precursor')), ('r', 'rev', [], _('display markers relevant to REV')), ('', 'index', False, _('display index of the marker')), + ('', 'delete', [], _('delete markers specified by indices')), ] + commitopts2, _('[OBSOLETED [REPLACEMENT ...]]')) def debugobsolete(ui, repo, precursor=None, *successors, **opts): @@ -3061,6 +3062,32 @@ raise error.Abort('changeset references must be full hexadecimal ' 'node identifiers') + if opts.get('delete'): + try: + indices = [int(v) for v in opts.get('delete')] + except ValueError: + raise error.Abort(_('invalid index value'), + hint=_('use integers fro indices')) + + if repo.currenttransaction(): + raise error.Abort(_('Cannot delete obsmarkers in the middle ' + 'of transaction.')) + + w = repo.wlock() + l = repo.lock() + try: + tr = repo.transaction('debugobsolete') + try: + n = repo.obsstore.delete(indices) + ui.write(_('Deleted %i obsolescense markers\n') % n) + tr.close() + finally: + tr.release() + finally: + l.release() + w.release() + return + if precursor is not None: if opts['rev']: raise error.Abort('cannot select revision when creating marker') diff -r 2637d6ad3e61 -r f456834b2f7e mercurial/obsolete.py --- a/mercurial/obsolete.py Fri Apr 01 15:20:31 2016 -0700 +++ b/mercurial/obsolete.py Fri Apr 01 15:12:50 2016 -0700 @@ -628,6 +628,30 @@ transaction.hookargs['new_obsmarkers'] = str(previous + len(new)) return len(new) + def delete(self, indices): + """Delete some obsmarkers from store and return the number of them + + Indices is a list of ints which are the indices + of the markers to be deleted.""" + if not indices: + # we don't want to rewrite the obsstore with the same content + return + + left = [] + current = self._all + n = 0 + for i, m in enumerate(current): + if i in indices: + n += 1 + continue + left.append(m) + + newobsstore = self.svfs('obsstore', 'w', atomictemp=True) + for bytes in encodemarkers(left, True, self._version): + newobsstore.write(bytes) + newobsstore.close() + return n + def mergemarkers(self, transaction, data): """merge a binary stream of markers inside the obsstore diff -r 2637d6ad3e61 -r f456834b2f7e tests/test-completion.t --- a/tests/test-completion.t Fri Apr 01 15:20:31 2016 -0700 +++ b/tests/test-completion.t Fri Apr 01 15:12:50 2016 -0700 @@ -261,7 +261,7 @@ debuglocks: force-lock, force-wlock debugmergestate: debugnamecomplete: - debugobsolete: flags, record-parents, rev, index, date, user + debugobsolete: flags, record-parents, rev, index, delete, date, user debugpathcomplete: full, normal, added, removed debugpushkey: debugpvec: diff -r 2637d6ad3e61 -r f456834b2f7e tests/test-obsolete.t --- a/tests/test-obsolete.t Fri Apr 01 15:20:31 2016 -0700 +++ b/tests/test-obsolete.t Fri Apr 01 15:12:50 2016 -0700 @@ -1083,4 +1083,17 @@ | @ 0:a78f55e5508c (draft) [ ] 0 + $ cd .. +Test the --delete option of debugobsolete command + $ hg init dorepo + $ cd dorepo + $ echo a > a && hg ci -Am a + adding a + $ hg ci --amend -m aa + $ hg debugobsolete + cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b f9bd49731b0b175e42992a3c8fa6c678b2bc11f1 0 (.*) {'user': 'test'} (re) + $ hg debugobsolete --delete 0 + Deleted 1 obsolescense markers + $ hg debugobsolete + $ cd ..