Re: [PATCH 3 of 3 V2] manifest: change manifestctx to not inherit from manifestdict
Queued, thanks! I've said it before, but I really like the direction this is going. I'm a little embarrassed I didn't think of creating the context objects myself. It seems so obvious now :-) Now I just need to figure out how to make narrowhg deal with these changes. Shouldn't be too hard, but will probably involve some duplication during the transition, just like manifest.py itself has a lot of duplication during the transition. On Wed, Aug 31, 2016 at 1:30 PM, Durham Goodewrote: > # HG changeset patch > # User Durham Goode > # Date 1472672813 25200 > # Wed Aug 31 12:46:53 2016 -0700 > # Node ID e65cbaceb14f4b522ab59cdccf3f4b2761b2e3bd > # Parent 59bc68e1d78538bb83f60c0d4f9342ec0a8893bf > manifest: change manifestctx to not inherit from manifestdict > > If manifestctx inherits from manifestdict, it requires some weird logic to > lazily load the dict if a piece of information is asked for. This ended up > being > complicated and unintuitive to use. > > Let's move the dict creation to .read(). This will make even more sense once > we > start adding readdelta() and other similar methods to manifestctx. > > diff --git a/mercurial/context.py b/mercurial/context.py > --- a/mercurial/context.py > +++ b/mercurial/context.py > @@ -528,7 +528,7 @@ class changectx(basectx): > > @propertycache > def _manifest(self): > -return self._repo.manifestlog[self._changeset.manifest] > +return self._repo.manifestlog[self._changeset.manifest].read() > > @propertycache > def _manifestdelta(self): > diff --git a/mercurial/manifest.py b/mercurial/manifest.py > --- a/mercurial/manifest.py > +++ b/mercurial/manifest.py > @@ -960,12 +960,13 @@ class manifestlog(object): > self._mancache[node] = m > return m > > -class manifestctx(manifestdict): > +class manifestctx(object): > """A class representing a single revision of a manifest, including its > contents, its parent revs, and its linkrev. > """ > def __init__(self, revlog, node): > self._revlog = revlog > +self._data = None > > self._node = node > > @@ -976,21 +977,26 @@ class manifestctx(manifestdict): > #rev = revlog.rev(node) > #self.linkrev = revlog.linkrev(rev) > > -# This should eventually be made lazy loaded, so consumers can access > -# the node/p1/linkrev data without having to parse the whole > manifest. > -data = revlog.revision(node) > -arraytext = array.array('c', data) > -revlog._fulltextcache[node] = arraytext > -super(manifestctx, self).__init__(data) > - > def node(self): > return self._node > > -class treemanifestctx(treemanifest): > +def read(self): > +if not self._data: > +if self._node == revlog.nullid: > +self._data = manifestdict() > +else: > +text = self._revlog.revision(self._node) > +arraytext = array.array('c', text) > +self._revlog._fulltextcache[self._node] = arraytext > +self._data = manifestdict(text) > +return self._data > + > +class treemanifestctx(object): > def __init__(self, revlog, dir, node): > revlog = revlog.dirlog(dir) > self._revlog = revlog > self._dir = dir > +self._data = None > > self._node = node > > @@ -1001,19 +1007,26 @@ class treemanifestctx(treemanifest): > #rev = revlog.rev(node) > #self.linkrev = revlog.linkrev(rev) > > -if revlog._treeondisk: > -super(treemanifestctx, self).__init__(dir=dir) > -def gettext(): > -return revlog.revision(node) > -def readsubtree(dir, subm): > -return revlog.dirlog(dir).read(subm) > -self.read(gettext, readsubtree) > -self.setnode(node) > -else: > -text = revlog.revision(node) > -arraytext = array.array('c', text) > -revlog.fulltextcache[node] = arraytext > -super(treemanifestctx, self).__init__(dir=dir, text=text) > +def read(self): > +if not self._data: > +if self._node == revlog.nullid: > +self._data = treemanifest() > +elif self._revlog._treeondisk: > +m = treemanifest(dir=self._dir) > +def gettext(): > +return self._revlog.revision(self._node) > +def readsubtree(dir, subm): > +return treemanifestctx(self._revlog, dir, subm).read() > +m.read(gettext, readsubtree) > +m.setnode(self._node) > +self._data = m > +else: > +text = self._revlog.revision(self._node) > +arraytext = array.array('c', text) > +self._revlog.fulltextcache[self._node] = arraytext > +self._data =
[PATCH 2 of 3] evolve: removed redundant try/finally blocks
# HG changeset patch # User Pulkit Goyal <7895pul...@gmail.com> # Date 1472684936 -19800 # Thu Sep 01 04:38:56 2016 +0530 # Branch stable # Node ID 2ab652cca0c72df663446cc5e79bef2afa0e9854 # Parent 20689e0835c621df4cd19efe7bd06127ab1e0bf8 evolve: removed redundant try/finally blocks There were two todo's to remove the redundant try finally blocks. Done that and also fixed the indentation afterwards. diff -r 20689e0835c6 -r 2ab652cca0c7 hgext/evolve.py --- a/hgext/evolve.py Thu Sep 01 03:23:31 2016 +0530 +++ b/hgext/evolve.py Thu Sep 01 04:38:56 2016 +0530 @@ -963,28 +963,25 @@ tr = repo.currenttransaction() assert tr is not None try: -try: -r = _evolvemerge(repo, orig, dest, pctx, keepbranch) -if r[-1]: #some conflict -raise error.Abort( -'unresolved merge conflicts (see hg help resolve)') -nodenew = _relocatecommit(repo, orig, commitmsg) -except error.Abort as exc: -repo.dirstate.beginparentchange() -repo.setparents(repo['.'].node(), nullid) -writedirstate(repo.dirstate, tr) -# fix up dirstate for copies and renames -copies.duplicatecopies(repo, dest.rev(), orig.p1().rev()) -repo.dirstate.endparentchange() -class LocalMergeFailure(MergeFailure, exc.__class__): -pass -exc.__class__ = LocalMergeFailure -tr.close() # to keep changes in this transaction (e.g. dirstate) -raise -oldbookmarks = repo.nodebookmarks(nodesrc) -_finalizerelocate(repo, orig, dest, nodenew, tr) -finally: -pass # TODO: remove this redundant try/finally block +r = _evolvemerge(repo, orig, dest, pctx, keepbranch) +if r[-1]: #some conflict +raise error.Abort( +'unresolved merge conflicts (see hg help resolve)') +nodenew = _relocatecommit(repo, orig, commitmsg) +except error.Abort as exc: +repo.dirstate.beginparentchange() +repo.setparents(repo['.'].node(), nullid) +writedirstate(repo.dirstate, tr) +# fix up dirstate for copies and renames +copies.duplicatecopies(repo, dest.rev(), orig.p1().rev()) +repo.dirstate.endparentchange() +class LocalMergeFailure(MergeFailure, exc.__class__): +pass +exc.__class__ = LocalMergeFailure +tr.close() # to keep changes in this transaction (e.g. dirstate) +raise +oldbookmarks = repo.nodebookmarks(nodesrc) +_finalizerelocate(repo, orig, dest, nodenew, tr) return nodenew def _bookmarksupdater(repo, oldid, tr): @@ -1993,73 +1990,70 @@ tr = repo.currenttransaction() assert tr is not None bmupdate = _bookmarksupdater(repo, bumped.node(), tr) -try: -if not list(repo.set('parents(%d) and parents(%d)', bumped, prec)): -# Need to rebase the changeset at the right place -repo.ui.status( -_('rebasing to destination parent: %s\n') % prec.p1()) -try: -tmpid = relocate(repo, bumped, prec.p1()) -if tmpid is not None: -tmpctx = repo[tmpid] -obsolete.createmarkers(repo, [(bumped, (tmpctx,))]) -except MergeFailure: -repo.opener.write('graftstate', bumped.hex() + '\n') -repo.ui.write_err(_('evolution failed!\n')) -repo.ui.write_err( -_('fix conflict and run "hg evolve --continue"\n')) -raise -# Create the new commit context -repo.ui.status(_('computing new diff\n')) -files = set() -copied = copies.pathcopies(prec, bumped) -precmanifest = prec.manifest() -# 3.3.2 needs a list. -# future 3.4 don't detect the size change during iteration -# this is fishy -for key, val in list(bumped.manifest().iteritems()): -precvalue = precmanifest.get(key, None) -if precvalue is not None: -del precmanifest[key] -if precvalue != val: -files.add(key) -files.update(precmanifest) # add missing files -# commit it -if files: # something to commit! -def filectxfn(repo, ctx, path): -if path in bumped: -fctx = bumped[path] -flags = fctx.flags() -mctx = memfilectx(repo, fctx.path(), fctx.data(), - islink='l' in flags, - isexec='x' in flags, - copied=copied.get(path)) -return mctx -return None -text = 'bumped update to %s:\n\n' % prec -text += bumped.description() - -new = context.memctx(repo, -
[PATCH 3 of 3] evolve: drop point release of versions
# HG changeset patch # User Pulkit Goyal <7895pul...@gmail.com> # Date 1472695827 -19800 # Thu Sep 01 07:40:27 2016 +0530 # Branch stable # Node ID 3f1d6170cb2a3a967d0eaa08c8d3a80037948bf0 # Parent 2ab652cca0c72df663446cc5e79bef2afa0e9854 evolve: drop point release of versions Modern Mercurial only looks at X.Y versions, so point releases can be dropped. diff -r 2ab652cca0c7 -r 3f1d6170cb2a hgext/evolve.py --- a/hgext/evolve.py Thu Sep 01 04:38:56 2016 +0530 +++ b/hgext/evolve.py Thu Sep 01 07:40:27 2016 +0530 @@ -20,7 +20,7 @@ ''' __version__ = '5.4.0' -testedwith = '3.4.3 3.5.2 3.6.2 3.7.3 3.8.1' +testedwith = '3.4 3.5 3.6 3.7 3.8' buglink = 'https://bz.mercurial-scm.org/' diff -r 2ab652cca0c7 -r 3f1d6170cb2a hgext/simple4server.py --- a/hgext/simple4server.pyThu Sep 01 04:38:56 2016 +0530 +++ b/hgext/simple4server.pyThu Sep 01 07:40:27 2016 +0530 @@ -8,7 +8,7 @@ For client side usages it is recommended to use the evolve extension for improved user interface.''' -testedwith = '3.3.3 3.4-rc' +testedwith = '3.3 3.4-rc' buglink = 'https://bz.mercurial-scm.org/' import mercurial.obsolete ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 2] evolve: update bugzilla link
> While you're here, the point release of the version can be dropped, as > modern Mercurial only looks at the X.Y versions. Okay I am sending a V2 with this patch queued. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 2] evolve: update bugzilla link
On Wed, Aug 31, 2016 at 4:14 PM, Pulkit Goyal <7895pul...@gmail.com> wrote: > # HG changeset patch > # User Pulkit Goyal <7895pul...@gmail.com> > # Date 1472680411 -19800 > # Thu Sep 01 03:23:31 2016 +0530 > # Branch stable > # Node ID 20689e0835c621df4cd19efe7bd06127ab1e0bf8 > # Parent 7a2e0629bdee8cd842bb884094cef9683ed49520 > evolve: update bugzilla link > > The bugzilla link is updated to https://bz.mercurial-scm.org/ > > diff -r 7a2e0629bdee -r 20689e0835c6 hgext/evolve.py > --- a/hgext/evolve.py Fri May 27 17:33:53 2016 +0200 > +++ b/hgext/evolve.py Thu Sep 01 03:23:31 2016 +0530 > @@ -21,7 +21,7 @@ > > __version__ = '5.4.0' > testedwith = '3.4.3 3.5.2 3.6.2 3.7.3 3.8.1' > While you're here, the point release of the version can be dropped, as modern Mercurial only looks at the X.Y versions. > -buglink = 'http://bz.selenic.com/' > +buglink = 'https://bz.mercurial-scm.org/' > > > evolutionhelptext = """ > diff -r 7a2e0629bdee -r 20689e0835c6 hgext/simple4server.py > --- a/hgext/simple4server.pyFri May 27 17:33:53 2016 +0200 > +++ b/hgext/simple4server.pyThu Sep 01 03:23:31 2016 +0530 > @@ -9,7 +9,7 @@ > improved user interface.''' > > testedwith = '3.3.3 3.4-rc' > -buglink = 'http://bz.selenic.com/' > +buglink = 'https://bz.mercurial-scm.org/' > > import mercurial.obsolete > > ___ > Mercurial-devel mailing list > Mercurial-devel@mercurial-scm.org > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel > ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH] py3: remove use of *L syntax
# HG changeset patch # User Pulkit Goyal <7895pul...@gmail.com> # Date 1472677186 -19800 # Thu Sep 01 02:29:46 2016 +0530 # Node ID 5ffa4cfc09d7c563b09bc3d4fbd50bccff16aa6a # Parent 8a84347b9907ada91f9f3a21aca1fb62cac0fed5 py3: remove use of *L syntax The int in Python 3 behaves as long so no need of L's in py3. Moreover we dont need long here. diff -r 8a84347b9907 -r 5ffa4cfc09d7 hgext/color.py --- a/hgext/color.pyMon Aug 29 17:48:14 2016 -0700 +++ b/hgext/color.pyThu Sep 01 02:29:46 2016 +0530 @@ -558,8 +558,8 @@ ('srWindow', _SMALL_RECT), ('dwMaximumWindowSize', _COORD)] -_STD_OUTPUT_HANDLE = 0xfff5L # (DWORD)-11 -_STD_ERROR_HANDLE = 0xfff4L # (DWORD)-12 +_STD_OUTPUT_HANDLE = 0xfff5 # (DWORD)-11 +_STD_ERROR_HANDLE = 0xfff4 # (DWORD)-12 _FOREGROUND_BLUE = 0x0001 _FOREGROUND_GREEN = 0x0002 diff -r 8a84347b9907 -r 5ffa4cfc09d7 mercurial/archival.py --- a/mercurial/archival.py Mon Aug 29 17:48:14 2016 -0700 +++ b/mercurial/archival.py Thu Sep 01 02:29:46 2016 +0530 @@ -231,7 +231,7 @@ if islink: mode = 0o777 ftype = _UNX_IFLNK -i.external_attr = (mode | ftype) << 16L +i.external_attr = (mode | ftype) << 16 # add "extended-timestamp" extra block, because zip archives # without this will be extracted with unexpected timestamp, # if TZ is not configured as GMT diff -r 8a84347b9907 -r 5ffa4cfc09d7 mercurial/commands.py --- a/mercurial/commands.py Mon Aug 29 17:48:14 2016 -0700 +++ b/mercurial/commands.py Thu Sep 01 02:29:46 2016 +0530 @@ -3381,9 +3381,9 @@ nump2prev = 0 chainlengths = [] -datasize = [None, 0, 0L] -fullsize = [None, 0, 0L] -deltasize = [None, 0, 0L] +datasize = [None, 0, 0] +fullsize = [None, 0, 0] +deltasize = [None, 0, 0] def addsize(size, l): if l[0] is None or size < l[0]: diff -r 8a84347b9907 -r 5ffa4cfc09d7 tests/test-check-py3-compat.t --- a/tests/test-check-py3-compat.t Mon Aug 29 17:48:14 2016 -0700 +++ b/tests/test-check-py3-compat.t Thu Sep 01 02:29:46 2016 +0530 @@ -26,7 +26,7 @@ hgext/children.py: error importing: str expected, not bytes (error at encoding.py:*) hgext/churn.py: error importing: str expected, not bytes (error at encoding.py:*) hgext/clonebundles.py: error importing: str expected, not bytes (error at encoding.py:*) - hgext/color.py: invalid syntax: invalid syntax (, line *) + hgext/color.py: error importing: str expected, not bytes (error at encoding.py:*) hgext/convert/bzr.py: error importing: str expected, not bytes (error at encoding.py:*) hgext/convert/common.py: error importing: str expected, not bytes (error at encoding.py:*) hgext/convert/convcmd.py: error importing: str expected, not bytes (error at encoding.py:*) @@ -79,7 +79,7 @@ hgext/transplant.py: error importing: str expected, not bytes (error at encoding.py:*) hgext/win32mbcs.py: error importing: str expected, not bytes (error at encoding.py:*) hgext/win32text.py: error importing: str expected, not bytes (error at encoding.py:*) - mercurial/archival.py: invalid syntax: invalid syntax (, line *) + mercurial/archival.py: error importing: str expected, not bytes (error at encoding.py:*) mercurial/bookmarks.py: error importing: str expected, not bytes (error at encoding.py:*) mercurial/branchmap.py: error importing: str expected, not bytes (error at encoding.py:*) mercurial/bundle2.py: error importing: str expected, not bytes (error at encoding.py:*) @@ -88,7 +88,7 @@ mercurial/changegroup.py: error importing: str expected, not bytes (error at encoding.py:*) mercurial/changelog.py: error importing: str expected, not bytes (error at encoding.py:*) mercurial/cmdutil.py: error importing: str expected, not bytes (error at encoding.py:*) - mercurial/commands.py: invalid syntax: invalid syntax (, line *) + mercurial/commands.py: error importing: str expected, not bytes (error at encoding.py:*) mercurial/commandserver.py: error importing: str expected, not bytes (error at encoding.py:*) mercurial/config.py: error importing: str expected, not bytes (error at encoding.py:*) mercurial/context.py: error importing: str expected, not bytes (error at encoding.py:*) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 2] evolve: removed redundant try/finally blocks
# HG changeset patch # User Pulkit Goyal <7895pul...@gmail.com> # Date 1472684936 -19800 # Thu Sep 01 04:38:56 2016 +0530 # Branch stable # Node ID 2ab652cca0c72df663446cc5e79bef2afa0e9854 # Parent 20689e0835c621df4cd19efe7bd06127ab1e0bf8 evolve: removed redundant try/finally blocks There were two todo's to remove the redundant try finally blocks. Done that and also fixed the indentation afterwards. diff -r 20689e0835c6 -r 2ab652cca0c7 hgext/evolve.py --- a/hgext/evolve.py Thu Sep 01 03:23:31 2016 +0530 +++ b/hgext/evolve.py Thu Sep 01 04:38:56 2016 +0530 @@ -963,28 +963,25 @@ tr = repo.currenttransaction() assert tr is not None try: -try: -r = _evolvemerge(repo, orig, dest, pctx, keepbranch) -if r[-1]: #some conflict -raise error.Abort( -'unresolved merge conflicts (see hg help resolve)') -nodenew = _relocatecommit(repo, orig, commitmsg) -except error.Abort as exc: -repo.dirstate.beginparentchange() -repo.setparents(repo['.'].node(), nullid) -writedirstate(repo.dirstate, tr) -# fix up dirstate for copies and renames -copies.duplicatecopies(repo, dest.rev(), orig.p1().rev()) -repo.dirstate.endparentchange() -class LocalMergeFailure(MergeFailure, exc.__class__): -pass -exc.__class__ = LocalMergeFailure -tr.close() # to keep changes in this transaction (e.g. dirstate) -raise -oldbookmarks = repo.nodebookmarks(nodesrc) -_finalizerelocate(repo, orig, dest, nodenew, tr) -finally: -pass # TODO: remove this redundant try/finally block +r = _evolvemerge(repo, orig, dest, pctx, keepbranch) +if r[-1]: #some conflict +raise error.Abort( +'unresolved merge conflicts (see hg help resolve)') +nodenew = _relocatecommit(repo, orig, commitmsg) +except error.Abort as exc: +repo.dirstate.beginparentchange() +repo.setparents(repo['.'].node(), nullid) +writedirstate(repo.dirstate, tr) +# fix up dirstate for copies and renames +copies.duplicatecopies(repo, dest.rev(), orig.p1().rev()) +repo.dirstate.endparentchange() +class LocalMergeFailure(MergeFailure, exc.__class__): +pass +exc.__class__ = LocalMergeFailure +tr.close() # to keep changes in this transaction (e.g. dirstate) +raise +oldbookmarks = repo.nodebookmarks(nodesrc) +_finalizerelocate(repo, orig, dest, nodenew, tr) return nodenew def _bookmarksupdater(repo, oldid, tr): @@ -1993,73 +1990,70 @@ tr = repo.currenttransaction() assert tr is not None bmupdate = _bookmarksupdater(repo, bumped.node(), tr) -try: -if not list(repo.set('parents(%d) and parents(%d)', bumped, prec)): -# Need to rebase the changeset at the right place -repo.ui.status( -_('rebasing to destination parent: %s\n') % prec.p1()) -try: -tmpid = relocate(repo, bumped, prec.p1()) -if tmpid is not None: -tmpctx = repo[tmpid] -obsolete.createmarkers(repo, [(bumped, (tmpctx,))]) -except MergeFailure: -repo.opener.write('graftstate', bumped.hex() + '\n') -repo.ui.write_err(_('evolution failed!\n')) -repo.ui.write_err( -_('fix conflict and run "hg evolve --continue"\n')) -raise -# Create the new commit context -repo.ui.status(_('computing new diff\n')) -files = set() -copied = copies.pathcopies(prec, bumped) -precmanifest = prec.manifest() -# 3.3.2 needs a list. -# future 3.4 don't detect the size change during iteration -# this is fishy -for key, val in list(bumped.manifest().iteritems()): -precvalue = precmanifest.get(key, None) -if precvalue is not None: -del precmanifest[key] -if precvalue != val: -files.add(key) -files.update(precmanifest) # add missing files -# commit it -if files: # something to commit! -def filectxfn(repo, ctx, path): -if path in bumped: -fctx = bumped[path] -flags = fctx.flags() -mctx = memfilectx(repo, fctx.path(), fctx.data(), - islink='l' in flags, - isexec='x' in flags, - copied=copied.get(path)) -return mctx -return None -text = 'bumped update to %s:\n\n' % prec -text += bumped.description() - -new = context.memctx(repo, -
Re: [PATCH 4 of 8 v2] commands: stop abusing int-ness of Python booleans
> On Aug 31, 2016, at 17:19, Kevin Bullock> wrote: > >> On Aug 30, 2016, at 15:16, Augie Fackler wrote: >> >> # HG changeset patch >> # User Augie Fackler >> # Date 1472586452 14400 >> # Tue Aug 30 15:47:32 2016 -0400 >> # Node ID c65c0181a9885d3c95e808272c2f609c3a9c8749 >> # Parent 69d84366fa224f5dedfdd18a9f5e2413060a8121 >> commands: stop abusing int-ness of Python booleans >> >> This will break as soon as fancyopts starts returning None for all >> unspecified boolean flags. >> >> diff --git a/mercurial/commands.py b/mercurial/commands.py >> --- a/mercurial/commands.py >> +++ b/mercurial/commands.py >> @@ -896,7 +896,8 @@ def bisect(ui, repo, rev=None, extra=Non >>bad = True >>else: >>reset = True >> -elif extra or good + bad + skip + reset + extend + bool(command) > 1: >> +elif extra or sum(1 for b in (good, bad, skip, >> + reset, extend, command) if b) > 1: > > Couldn't we stop abusing math for this at all using any()? > >elif extra or any((good, bad, skip, reset, extend, command)): > > Docs say it was added in Python 2.5. No, because we care if *more than one* of the bools was true. I originally had the same idea though. > > pacem in terris / мир / शान्ति / سَلاَم / 平和 > Kevin R. Bullock > > ___ > Mercurial-devel mailing list > Mercurial-devel@mercurial-scm.org > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
RFC: bitmap storage for hidden
One of the performance costs that affects every command is the computehidden function (which computes what commits are hidden based on a combination of obsmarkers, bookmarks, workingcopy, phases, and tags). At Facebook this function alone can add 300ms to every command a user runs (depending on a variety of factors). I've begun work on a storage structure for this information, so we don't need to recompute it during every read command. Before I go through the work to polish it enough to send it upstream, I want to run it by people for comments. The idea is basically: - Have a file that acts as a bitmap, where a changelog rev number maps to a particular bit, and if that bit is set then the node is considered hidden. computehidden will return a class that uses this to answer filteredrevs.__contains__ calls. - When something is changed that would affect visibility (bookmark edit, phase change, obsmarker creation, dirstate movement, tag edit), that code is responsible for calling hidden.updatevisibilty(repo, affectednodes) which reports which nodes are touched by the edit (like the old bookmark node and the new bookmark node), and updatevisibility() does the minimal calculation of visibility changes and propagates those changes to the node ancestors as required. - The file would be stored in .hg/cache/hidden, and would only be 122kb per million commits, so we'd just use the normal copy + atomic rename strategy for transactionality (i.e. transaction.addfilegenerator) - In theory the file would always be up-to-date, but we can put some metadata at the front of the file to allow verifying the repo hasn't changed significantly out from under it (recording tip, working copy parents, obsmarker file timestamp, etc). If the repo has changed, or if the bitmap doesn't yet exist, it can be trivially calculated using hidden.updatevisibility(repo.revs('not public()')) in a manner similar to how it works today. Notable issues: - A number of places treat filteredrevs as a set, and do things like 'myset - repo.filteredrevs'. With a bitmap this doesn't work, so we need to translate it to '(r for r in myset if r not in repo.filteredrevs)'. Which is probably a better O() anyway since it won't be affected by the size of filteredrevs. - filteredrevs is currently a frozen set. Editing the bitmap will have to be done in a way where the edits only become visible when the 'frozen' set is invalidated. So we maintain the existing behavior. Follow up ideas: - Once this ships as a cache, it might be possible to progress it to not-a-cache, such that we could define visibility in other terms. For instance, we could allow hiding/reviving commits without obsolescence markers in non-evolve repos. This is a bit more of a long term thought, but might be worth brainstorming about. My code so far can be seen at: https://bitbucket.org/DurhamG/hg/commits/branch/bitmap Though it's currently missing some key features (cache validity checking, tests don't all pass yet, file is in .hg/store instead of .hg/cache). ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 3 V2] manifest: make uses of _mancache aware of contexts
# HG changeset patch # User Durham Goode# Date 1472518929 25200 # Mon Aug 29 18:02:09 2016 -0700 # Node ID 59bc68e1d78538bb83f60c0d4f9342ec0a8893bf # Parent abce9af35512d8589683d94f34f6d8aa21163568 manifest: make uses of _mancache aware of contexts In a future patch we will change manifestctx and treemanifestctx to no longer derive from manifestdict and treemanifest, respectively. This means that consumers of the _mancache will now need to be aware of the different between the two, until we get rid of the manifest entirely and the _mancache becomes only filled with ctxs. diff --git a/mercurial/bundlerepo.py b/mercurial/bundlerepo.py --- a/mercurial/bundlerepo.py +++ b/mercurial/bundlerepo.py @@ -204,8 +204,8 @@ class bundlemanifest(bundlerevlog, manif if isinstance(node, int): node = self.node(node) -if node in self._mancache: -result = self._mancache[node].text() +if node in self.fulltextcache: +result = self.fulltextcache[node].tostring() else: result = manifest.manifest.revision(self, nodeorrev) return result diff --git a/mercurial/manifest.py b/mercurial/manifest.py --- a/mercurial/manifest.py +++ b/mercurial/manifest.py @@ -1128,7 +1128,11 @@ class manifest(manifestrevlog): if node == revlog.nullid: return self._newmanifest() # don't upset local cache if node in self._mancache: -return self._mancache[node] +cached = self._mancache[node] +if (isinstance(cached, manifestctx) or +isinstance(cached, treemanifestctx)): +cached = cached.read() +return cached if self._treeondisk: def gettext(): return self.revision(node) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 3 V2] manifest: add treemanifestctx class
# HG changeset patch # User Durham Goode# Date 1472675389 25200 # Wed Aug 31 13:29:49 2016 -0700 # Node ID abce9af35512d8589683d94f34f6d8aa21163568 # Parent 318e2b600b80e4ed3c6f37df46ec7544f60d4c0b manifest: add treemanifestctx class Before we start using repo.manifestlog in the rest of the code base, we need to make sure that it's capable of returning treemanifests. As we add new functionality to manifestctx, we'll add it to treemanifestctx at the same time. We also comment out the manifestctx p1, p2, and linkrev fields for now, since we're not implementing them on treemanifest yet. diff --git a/mercurial/manifest.py b/mercurial/manifest.py --- a/mercurial/manifest.py +++ b/mercurial/manifest.py @@ -944,22 +944,20 @@ class manifestlog(object): """Retrieves the manifest instance for the given node. Throws a KeyError if not found. """ -if (self._oldmanifest._treeondisk -or self._oldmanifest._treeinmem): -# TODO: come back and support tree manifests directly -return self._oldmanifest.read(node) - -if node == revlog.nullid: -return manifestdict() if node in self._mancache: cachemf = self._mancache[node] # The old manifest may put non-ctx manifests in the cache, so skip # those since they don't implement the full api. -if isinstance(cachemf, manifestctx): +if (isinstance(cachemf, manifestctx) or +isinstance(cachemf, treemanifestctx)): return cachemf -m = manifestctx(self._revlog, node) -self._mancache[node] = m +if self._oldmanifest._treeinmem: +m = treemanifestctx(self._revlog, '', node) +else: +m = manifestctx(self._revlog, node) +if node != revlog.nullid: +self._mancache[node] = m return m class manifestctx(manifestdict): @@ -970,9 +968,13 @@ class manifestctx(manifestdict): self._revlog = revlog self._node = node -self.p1, self.p2 = revlog.parents(node) -rev = revlog.rev(node) -self.linkrev = revlog.linkrev(rev) + +# TODO: We eventually want p1, p2, and linkrev exposed on this class, +# but let's add it later when something needs it and we can load it +# lazily. +#self.p1, self.p2 = revlog.parents(node) +#rev = revlog.rev(node) +#self.linkrev = revlog.linkrev(rev) # This should eventually be made lazy loaded, so consumers can access # the node/p1/linkrev data without having to parse the whole manifest. @@ -984,6 +986,38 @@ class manifestctx(manifestdict): def node(self): return self._node +class treemanifestctx(treemanifest): +def __init__(self, revlog, dir, node): +revlog = revlog.dirlog(dir) +self._revlog = revlog +self._dir = dir + +self._node = node + +# TODO: Load p1/p2/linkrev lazily. They need to be lazily loaded so that +# we can instantiate treemanifestctx objects for directories we don't +# have on disk. +#self.p1, self.p2 = revlog.parents(node) +#rev = revlog.rev(node) +#self.linkrev = revlog.linkrev(rev) + +if revlog._treeondisk: +super(treemanifestctx, self).__init__(dir=dir) +def gettext(): +return revlog.revision(node) +def readsubtree(dir, subm): +return revlog.dirlog(dir).read(subm) +self.read(gettext, readsubtree) +self.setnode(node) +else: +text = revlog.revision(node) +arraytext = array.array('c', text) +revlog.fulltextcache[node] = arraytext +super(treemanifestctx, self).__init__(dir=dir, text=text) + +def node(self): +return self._node + class manifest(manifestrevlog): def __init__(self, opener, dir='', dirlogcache=None): '''The 'dir' and 'dirlogcache' arguments are for internal use by ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 3 of 3 V2] manifest: change manifestctx to not inherit from manifestdict
# HG changeset patch # User Durham Goode# Date 1472672813 25200 # Wed Aug 31 12:46:53 2016 -0700 # Node ID e65cbaceb14f4b522ab59cdccf3f4b2761b2e3bd # Parent 59bc68e1d78538bb83f60c0d4f9342ec0a8893bf manifest: change manifestctx to not inherit from manifestdict If manifestctx inherits from manifestdict, it requires some weird logic to lazily load the dict if a piece of information is asked for. This ended up being complicated and unintuitive to use. Let's move the dict creation to .read(). This will make even more sense once we start adding readdelta() and other similar methods to manifestctx. diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -528,7 +528,7 @@ class changectx(basectx): @propertycache def _manifest(self): -return self._repo.manifestlog[self._changeset.manifest] +return self._repo.manifestlog[self._changeset.manifest].read() @propertycache def _manifestdelta(self): diff --git a/mercurial/manifest.py b/mercurial/manifest.py --- a/mercurial/manifest.py +++ b/mercurial/manifest.py @@ -960,12 +960,13 @@ class manifestlog(object): self._mancache[node] = m return m -class manifestctx(manifestdict): +class manifestctx(object): """A class representing a single revision of a manifest, including its contents, its parent revs, and its linkrev. """ def __init__(self, revlog, node): self._revlog = revlog +self._data = None self._node = node @@ -976,21 +977,26 @@ class manifestctx(manifestdict): #rev = revlog.rev(node) #self.linkrev = revlog.linkrev(rev) -# This should eventually be made lazy loaded, so consumers can access -# the node/p1/linkrev data without having to parse the whole manifest. -data = revlog.revision(node) -arraytext = array.array('c', data) -revlog._fulltextcache[node] = arraytext -super(manifestctx, self).__init__(data) - def node(self): return self._node -class treemanifestctx(treemanifest): +def read(self): +if not self._data: +if self._node == revlog.nullid: +self._data = manifestdict() +else: +text = self._revlog.revision(self._node) +arraytext = array.array('c', text) +self._revlog._fulltextcache[self._node] = arraytext +self._data = manifestdict(text) +return self._data + +class treemanifestctx(object): def __init__(self, revlog, dir, node): revlog = revlog.dirlog(dir) self._revlog = revlog self._dir = dir +self._data = None self._node = node @@ -1001,19 +1007,26 @@ class treemanifestctx(treemanifest): #rev = revlog.rev(node) #self.linkrev = revlog.linkrev(rev) -if revlog._treeondisk: -super(treemanifestctx, self).__init__(dir=dir) -def gettext(): -return revlog.revision(node) -def readsubtree(dir, subm): -return revlog.dirlog(dir).read(subm) -self.read(gettext, readsubtree) -self.setnode(node) -else: -text = revlog.revision(node) -arraytext = array.array('c', text) -revlog.fulltextcache[node] = arraytext -super(treemanifestctx, self).__init__(dir=dir, text=text) +def read(self): +if not self._data: +if self._node == revlog.nullid: +self._data = treemanifest() +elif self._revlog._treeondisk: +m = treemanifest(dir=self._dir) +def gettext(): +return self._revlog.revision(self._node) +def readsubtree(dir, subm): +return treemanifestctx(self._revlog, dir, subm).read() +m.read(gettext, readsubtree) +m.setnode(self._node) +self._data = m +else: +text = self._revlog.revision(self._node) +arraytext = array.array('c', text) +self._revlog.fulltextcache[self._node] = arraytext +self._data = treemanifest(dir=self._dir, text=text) + +return self._data def node(self): return self._node ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 8 of 8 v2] help: mark boolean flags with a ^ and explain that they can be negated (RFC)
> options ([+] can be repeated, [?] are flags): This is closer to how I was envisioning it. > Having --no-noninteractive seems really sad. We could make --noninteractive > hidden and then advertise --no-interactive as the long version. Agreed > Also, I don't think --no-no-backup is a good idea. --backup should be its > negation. Agreed ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH] bundle2: handleoutput i18n
On 2016-08-30 13:19, Matt Mackall wrote: On Tue, 2016-08-30 at 11:10 +0900, Akihiko Odaki wrote: Hi, Thanl you for reviewing my patch. On 2016-08-30 09:38, Matt Mackall wrote: > On Sun, 2016-08-28 at 10:57 +0900, Akihiko Odaki wrote: >> # HG changeset patch >> # User Akihiko Odaki>> # Date 1472348629 -32400 >> # Sun Aug 28 10:43:49 2016 +0900 >> # Node ID 3e9c35285720b3eecbda43d3d60e483d63ba7ae4 >> # Parent 4fca69e3d51cc45f331a74caa6e923523ebf7f02 >> bundle2: handleoutput i18n > > This would be easier to read as "bundle2: localize handleoutput remote prompts" I understand. > >> diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py >> --- a/mercurial/bundle2.py >> +++ b/mercurial/bundle2.py >> @@ -1467,7 +1467,7 @@ def handlecheckheads(op, inpart): >> def handleoutput(op, inpart): >> """forward output captured on the server to the client""" >> for line in inpart.read().splitlines(): >> -op.ui.status(('remote: %s\n' % line)) > > You'll note there is an extra level of useless parentheses here. They actually > serve a purpose: they stop check-code.py from complaining about not using _(). > > So someone didn't put _() there on purpose. Whenever you see something > apparently pointless that was also clearly done on purpose, you need to figure > out why it was done before you take it out: you might be breaking something that > isn't obvious. I thought it should use _() because other codes do so. Here is `grep -r 'remote: ' mercurial`. Yes, that does appear right. But did you also check the history of the file you're changing to see if there was a reason that someone used () to silence a warning rather than just using _() correctly? Yes, I checked and it was written by Pierre-Yves David, so he is in Cc. The revision is b7435117d951. Sorry for forgetting to tell that. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH] histedit: correct output of error when 'base' is from the edit list
On Tue, 30 Aug 2016 13:18:54 -0400, Augie Fackler wrote: > # HG changeset patch > # User Augie Fackler> # Date 1472577230 14400 > # Tue Aug 30 13:13:50 2016 -0400 > # Node ID 4e6fc4921eca722aa5c7967408d93ca3c59b1593 > # Parent 12f8bef59bfa2739d0c5d8425ab494fd2fe38a81 > histedit: correct output of error when 'base' is from the edit list LGTM, queued, thanks. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 03 of 12 topics] flake8: fix E127 style
On Tue, Aug 30, 2016 at 08:58:09PM -0700, Sean Farley wrote: > # HG changeset patch > # User Sean Farley> # Date 1472591416 25200 > # Tue Aug 30 14:10:16 2016 -0700 > # Node ID a6f4b32f655ba895875640534b051c5ebe632695 > # Parent 78dd9f1db1b1cf5a869e1240bb4ed523e930c907 > # EXP-Topic flake8 > flake8: fix E127 style I might suggest describing what e127 is in the log message? This kind of buries the lede in terms of actual content changes IMO. > > diff --git a/hgext3rd/topic/topicmap.py b/hgext3rd/topic/topicmap.py > --- a/hgext3rd/topic/topicmap.py > +++ b/hgext3rd/topic/topicmap.py > @@ -125,11 +125,11 @@ class topiccache(oldbranchcache): > if (self.tipnode == repo.changelog.node(self.tiprev)): > fh = scmutil.filteredhash(repo, self.tiprev) > if fh is None: > fh = nullid > if ((self.filteredhash == fh) > - and (self.phaseshash == _phaseshash(repo, > self.tiprev))): > +and (self.phaseshash == _phaseshash(repo, self.tiprev))): > return True > return False > except IndexError: > return False > > diff --git a/setup.cfg b/setup.cfg > --- a/setup.cfg > +++ b/setup.cfg > @@ -1,2 +1,2 @@ > [flake8] > -ignore = E261, E266, E302, E129, E731, E124, E713, E301, E501, E111, E123, > E222, W503, W391, E127 > +ignore = E261, E266, E302, E129, E731, E124, E713, E301, E501, E111, E123, > E222, W503, W391 > ___ > Mercurial-devel mailing list > Mercurial-devel@mercurial-scm.org > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 05 of 12 topics] flake8: fix W503 style
On Tue, Aug 30, 2016 at 08:58:11PM -0700, Sean Farley wrote: > # HG changeset patch > # User Sean Farley> # Date 1472595240 25200 > # Tue Aug 30 15:14:00 2016 -0700 > # Node ID 752a62b50ba31b768c52c6b423cd1a36d0c6eae2 > # Parent 8f1e18702ba107ffcb35be04dc8a1e650e5c1e7f > # EXP-Topic flake8 > flake8: fix W503 style > > diff --git a/hgext3rd/topic/destination.py b/hgext3rd/topic/destination.py > --- a/hgext3rd/topic/destination.py > +++ b/hgext3rd/topic/destination.py > @@ -72,12 +72,12 @@ def _destupdatetopic(repo, clean, check) > if bookmarks.isactivewdirparent(repo): > movemark = repo['.'].node() > return node, movemark, None > > def desthistedit(orig, ui, repo): > -if not (ui.config('histedit', 'defaultrev', None) is None > -and repo.currenttopic): > +if not (ui.config('histedit', 'defaultrev', None) is None and > +repo.currenttopic): I know I intentionally put the binary operator at the start of the subsequent line because then it's less ambiguous when visually parsing, eg: if (foo and bar): baz leaves it more visually obvious where the body of the if statement begins than if (foo and bar): baz I'm not sure how others feel. > return orig(ui, repo) > revs = repo.revs('::. and stack()') > if revs: > return revs.min() > return None > @@ -104,13 +104,13 @@ def modsetup(ui): > extensions.wrapfunction(destutil, '_destmergebranch', > _destmergebranch) > try: > rebase = extensions.find('rebase') > except KeyError: > rebase = None > -if (util.safehasattr(rebase, '_destrebase') > +if (util.safehasattr(rebase, '_destrebase') and > # logic not shared with merge yet < hg-3.8 > -and not util.safehasattr(rebase, '_definesets')): > +not util.safehasattr(rebase, '_definesets')): > extensions.wrapfunction(rebase, '_destrebase', _destmergebranch) > if util.safehasattr(destutil, 'destupdatesteps'): > bridx = destutil.destupdatesteps.index('branch') > destutil.destupdatesteps.insert(bridx, 'topic') > destutil.destupdatestepmap['topic'] = _destupdatetopic > diff --git a/hgext3rd/topic/discovery.py b/hgext3rd/topic/discovery.py > --- a/hgext3rd/topic/discovery.py > +++ b/hgext3rd/topic/discovery.py > @@ -14,12 +14,12 @@ from mercurial import ( > ) > > from . import topicmap > > def _headssummary(orig, repo, remote, outgoing): > -publishing = ('phases' not in remote.listkeys('namespaces') > - or bool(remote.listkeys('phases').get('publishing', > False))) > +publishing = ('phases' not in remote.listkeys('namespaces') or > + bool(remote.listkeys('phases').get('publishing', False))) > if publishing or not remote.capable('topics'): > return orig(repo, remote, outgoing) > oldrepo = repo.__class__ > oldbranchcache = branchmap.branchcache > oldfilename = branchmap._filename > diff --git a/hgext3rd/topic/topicmap.py b/hgext3rd/topic/topicmap.py > --- a/hgext3rd/topic/topicmap.py > +++ b/hgext3rd/topic/topicmap.py > @@ -124,12 +124,12 @@ class topiccache(oldbranchcache): > try: > if (self.tipnode == repo.changelog.node(self.tiprev)): > fh = scmutil.filteredhash(repo, self.tiprev) > if fh is None: > fh = nullid > -if ((self.filteredhash == fh) > -and (self.phaseshash == _phaseshash(repo, self.tiprev))): > +if ((self.filteredhash == fh) and > +(self.phaseshash == _phaseshash(repo, self.tiprev))): > return True > return False > except IndexError: > return False > > diff --git a/setup.cfg b/setup.cfg > --- a/setup.cfg > +++ b/setup.cfg > @@ -1,2 +1,2 @@ > [flake8] > -ignore = E261, E266, E302, E129, E731, E124, E713, E301, E501, E111, E123, > E222, W503 > +ignore = E261, E266, E302, E129, E731, E124, E713, E301, E501, E111, E123, > E222 > ___ > Mercurial-devel mailing list > Mercurial-devel@mercurial-scm.org > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH STABLE] bundle2: localize "remote: "
On Tue, 2016-08-30 at 17:49 -0700, Gregory Szorc wrote: > However, I'm going to posit that _() not being used was accidental. We > translate "remote: " everywhere else. This code is running locally (not on > the server). So I don't see why we wouldn't tranhslate. I agree it's almost certainly wrong. But the thing I'm getting at is: - we've had rules forever to make sure all write/status messages get translated - so it's weird when one isn't - and extra weird when an obvious one like this has willfully defeated the rule - such weirdness should trigger a higher level of investigation and rationale When we fix things that are obviously wrong, we always risk breaking things that are actually subtly right. A really good warning sign that we're about to do that is when we find something that's obviously wrong.. but also inexplicable. -- Mathematics is the supreme nostalgia of our time. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel