# HG changeset patch # User Matt Mackall # Date 1391645347 21600 # Node ID cc00cd6c51c2b1ecfa295efc9f06309188506db8 # Parent 2ac278aab2b48f9cba1e282ff722b5bef73507af# Parent 6863d42eb59a39ea483eec0728b3a5d6836d20b6 merge with stable diff -r 6863d42eb59a -r cc00cd6c51c2 Makefile --- a/Makefile Wed Feb 05 17:23:35 2014 -0600 +++ b/Makefile Wed Feb 05 18:09:07 2014 -0600 @@ -102,7 +102,7 @@ update-pot: i18n/hg.pot -i18n/hg.pot: $(PYFILES) $(DOCFILES) +i18n/hg.pot: $(PYFILES) $(DOCFILES) i18n/posplit i18n/hggettext $(PYTHON) i18n/hggettext mercurial/commands.py \ hgext/*.py hgext/*/__init__.py \ mercurial/fileset.py mercurial/revset.py \ diff -r 6863d42eb59a -r cc00cd6c51c2 i18n/de.po --- a/i18n/de.po Wed Feb 05 17:23:35 2014 -0600 +++ b/i18n/de.po Wed Feb 05 18:09:07 2014 -0600 @@ -20,7 +20,7 @@ msgstr "" "Project-Id-Version: Mercurial\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-25 17:51+0100\n" +"POT-Creation-Date: 2014-01-29 16:47+0100\n" "PO-Revision-Date: 2013-09-30 20:52+0100\n" "Last-Translator: Simon Heimberg \n" "Language-Team: \n" @@ -2928,6 +2928,7 @@ " [repository]\n" " native = LF" +#. do not translate: .. note:: msgid ".. note::" msgstr "" @@ -5029,6 +5030,7 @@ " Siehe Hilfe zu 'paths' zu Pfad-Kurznamen und 'urls' für erlaubte\n" " Formate für die Quellangabe." +#. do not translate: .. container:: msgid " .. container:: verbose" msgstr "" @@ -6548,6 +6550,7 @@ " Ohne Argumente werden die aktuell aktiven Wächter ausgegeben.\n" " Mit einem Argument wird der aktuelle Wächter gesetzt." +#. do not translate: .. note:: msgid " .. note::" msgstr "" @@ -15694,6 +15697,7 @@ " order until one or more configuration files are detected." msgstr "" +#. do not translate: .. note:: msgid "" ".. note:: The registry key ``HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node" "\\Mercurial``\n" @@ -15873,6 +15877,7 @@ msgid " stable5 = latest -b stable" msgstr "" +#. do not translate: .. note:: msgid "" ".. note:: It is possible to create aliases with the same names as\n" " existing commands, which will then override the original\n" @@ -15918,6 +15923,7 @@ "echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``." msgstr "" +#. do not translate: .. note:: msgid "" ".. note:: Some global configuration options such as ``-R`` are\n" " processed before shell aliases and will thus not be passed to\n" @@ -16101,6 +16107,7 @@ "the command." msgstr "" +#. do not translate: .. note:: msgid "" ".. note:: The tempfile mechanism is recommended for Windows systems,\n" " where the standard shell I/O redirection operators often have\n" @@ -16572,6 +16579,7 @@ " update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``." msgstr "" +#. do not translate: .. note:: msgid "" ".. note:: It is generally better to use standard hooks rather than the\n" " generic pre- and post- command hooks as they are guaranteed to be\n" @@ -16580,6 +16588,7 @@ " generate a commit (e.g. tag) and not just the commit command." msgstr "" +#. do not translate: .. note:: msgid "" ".. note:: Environment variables with empty values may not be passed to\n" " hooks on platforms such as Windows. As an example, ``$HG_PARENT2``\n" @@ -18967,6 +18976,7 @@ ":Manual group: Mercurial Manual" msgstr "" +#. do not translate: .. contents:: msgid "" ".. contents::\n" " :backlinks: top\n" @@ -19017,6 +19027,7 @@ " repository." msgstr "" +#. do not translate: .. include:: msgid ".. include:: hg.1.gendoc.txt" msgstr "" @@ -19121,6 +19132,7 @@ "Public License version 2 or any later version." msgstr "" +#. do not translate: .. include:: msgid ".. include:: common.txt\n" msgstr "" @@ -19143,6 +19155,7 @@ ":Manual group: Mercurial Manual" msgstr "" +#. do not translate: .. include:: msgid ".. include:: hgignore.5.gendoc.txt" msgstr "" @@ -19170,6 +19183,7 @@ "Public License version 2 or any later version." msgstr "" +#. do not translate: .. include:: msgid ".. include:: common.txt" msgstr "" @@ -19281,6 +19295,7 @@ "regexp pattern, start it with ``^``." msgstr "" +#. do not translate: .. note:: msgid "" ".. note::\n" " Patterns specified in other than ``.hgignore`` are always rooted.\n" @@ -19333,6 +19348,7 @@ ":Manual group: Mercurial Manual" msgstr "" +#. do not translate: .. contents:: msgid "" ".. contents::\n" " :backlinks: top\n" @@ -19348,6 +19364,7 @@ "Beschreibung\n" "============" +#. do not translate: .. include:: msgid ".. include:: hgrc.5.gendoc.txt" msgstr "" @@ -19564,6 +19581,7 @@ msgid "8. The merge of the file fails and must be resolved before commit." msgstr "" +#. do not translate: .. note:: msgid "" ".. note::\n" " After selecting a merge program, Mercurial will by default attempt\n" @@ -19633,6 +19651,7 @@ msgid "Alternate pattern notations must be specified explicitly." msgstr "Andere Schreibweisen von Mustern müssen explizit angegeben werden." +#. do not translate: .. note:: msgid "" ".. note::\n" " Patterns specified in ``.hgignore`` are not rooted.\n" @@ -19804,6 +19823,7 @@ msgid " - secret changesets are neither pushed, pulled, or cloned" msgstr "" +#. do not translate: .. note:: msgid "" ".. note::\n" " Pulling a draft changeset from a publishing server does not mark it\n" @@ -19823,12 +19843,14 @@ " [phases]\n" " publish = False" +#. do not translate: .. note:: msgid "" ".. note::\n" " Servers running older versions of Mercurial are treated as\n" " publishing." msgstr "" +#. do not translate: .. note:: msgid "" ".. note::\n" " Changesets in secret phase are not exchanged with the server. This\n" @@ -20216,6 +20238,7 @@ " repositories states when committing in the parent repository." msgstr "" +#. do not translate: .. note:: msgid "" " .. note::\n" " The ``.hgsubstate`` file should not be edited manually." diff -r 6863d42eb59a -r cc00cd6c51c2 i18n/posplit --- a/i18n/posplit Wed Feb 05 17:23:35 2014 -0600 +++ b/i18n/posplit Wed Feb 05 18:09:07 2014 -0600 @@ -5,6 +5,7 @@ # license: MIT/X11/Expat # +import re import sys import polib @@ -30,6 +31,7 @@ cache = {} entries = po[:] po[:] = [] + findd = re.compile(r' *\.\. (\w+)::') # for finding directives for entry in entries: msgids = entry.msgid.split(u'\n\n') if entry.msgstr: @@ -49,8 +51,27 @@ delta = 0 for msgid, msgstr in zip(msgids, msgstrs): - if msgid: + if msgid and msgid != '::': newentry = mkentry(entry, delta, msgid, msgstr) + mdirective = findd.match(msgid) + if mdirective: + if not msgid[mdirective.end():].rstrip(): + # only directive, nothing to translate here + continue + directive = mdirective.group(1) + if directive in ('container', 'include'): + if msgid.rstrip('\n').count('\n') == 0: + # only rst syntax, nothing to translate + continue + else: + # lines following directly, unexpected + print 'Warning: text follows line with directive' \ + ' %s' % directive + comment = 'do not translate: .. %s::' % directive + if not newentry.comment: + newentry.comment = comment + elif comment not in newentry.comment: + newentry.comment += '\n' + comment addentry(po, newentry, cache) delta += 2 + msgid.count('\n') po.save() diff -r 6863d42eb59a -r cc00cd6c51c2 mercurial/bookmarks.py --- a/mercurial/bookmarks.py Wed Feb 05 17:23:35 2014 -0600 +++ b/mercurial/bookmarks.py Wed Feb 05 18:09:07 2014 -0600 @@ -363,22 +363,6 @@ writer(msg) localmarks.write() -def updateremote(ui, repo, remote, revs): - ui.debug("checking for updated bookmarks\n") - revnums = map(repo.changelog.rev, revs or []) - ancestors = [a for a in repo.changelog.ancestors(revnums, inclusive=True)] - (addsrc, adddst, advsrc, advdst, diverge, differ, invalid - ) = compare(repo, repo._bookmarks, remote.listkeys('bookmarks'), - srchex=hex) - - for b, scid, dcid in advsrc: - if ancestors and repo[scid].rev() not in ancestors: - continue - if remote.pushkey('bookmarks', b, dcid, scid): - ui.status(_("updating bookmark %s\n") % b) - else: - ui.warn(_('updating bookmark %s failed!\n') % b) - def pushtoremote(ui, repo, remote, targets): (addsrc, adddst, advsrc, advdst, diverge, differ, invalid ) = compare(repo, repo._bookmarks, remote.listkeys('bookmarks'), diff -r 6863d42eb59a -r cc00cd6c51c2 mercurial/cmdutil.py --- a/mercurial/cmdutil.py Wed Feb 05 17:23:35 2014 -0600 +++ b/mercurial/cmdutil.py Wed Feb 05 18:09:07 2014 -0600 @@ -1132,7 +1132,7 @@ elif follow: revs = repo.revs('reverse(:.)') else: - revs = list(repo) + revs = revset.baseset(repo) revs.reverse() if not revs: return [] @@ -1140,6 +1140,7 @@ slowpath = match.anypats() or (match.files() and opts.get('removed')) fncache = {} change = repo.changectx + revs = revset.baseset(revs) # First step is to fill wanted, the set of revisions that we want to yield. # When it does not induce extra cost, we also fill fncache for revisions in @@ -1471,10 +1472,11 @@ if follow and len(repo) > 0: revs = repo.revs('reverse(:.)') else: - revs = list(repo.changelog) + revs = revset.baseset(repo.changelog) revs.reverse() if not revs: return [], None, None + revs = revset.baseset(revs) expr, filematcher = _makegraphlogrevset(repo, pats, opts, revs) if possiblyunsorted: revs.sort(reverse=True) diff -r 6863d42eb59a -r cc00cd6c51c2 mercurial/commands.py --- a/mercurial/commands.py Wed Feb 05 17:23:35 2014 -0600 +++ b/mercurial/commands.py Wed Feb 05 18:09:07 2014 -0600 @@ -2558,7 +2558,7 @@ if newtree != tree: ui.note(revset.prettyformat(newtree), "\n") func = revset.match(ui, expr) - for c in func(repo, range(len(repo))): + for c in func(repo, revset.baseset(range(len(repo)))): ui.write("%s\n" % c) @command('debugsetparents', [], _('REV1 [REV2]')) diff -r 6863d42eb59a -r cc00cd6c51c2 mercurial/exchange.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/exchange.py Wed Feb 05 18:09:07 2014 -0600 @@ -0,0 +1,276 @@ +# exchange.py - utily to exchange data between repo. +# +# Copyright 2005-2007 Matt Mackall +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + +from i18n import _ +from node import hex +import errno +import util, scmutil, changegroup +import discovery, phases, obsolete, bookmarks + + +class pushoperation(object): + """A object that represent a single push operation + + It purpose is to carry push related state and very common operation. + + A new should be created at the begining of each push and discarded + afterward. + """ + + def __init__(self, repo, remote, force=False, revs=None, newbranch=False): + # repo we push from + self.repo = repo + self.ui = repo.ui + # repo we push to + self.remote = remote + # force option provided + self.force = force + # revs to be pushed (None is "all") + self.revs = revs + # allow push of new branch + self.newbranch = newbranch + +def push(repo, remote, force=False, revs=None, newbranch=False): + '''Push outgoing changesets (limited by revs) from a local + repository to remote. Return an integer: + - None means nothing to push + - 0 means HTTP error + - 1 means we pushed and remote head count is unchanged *or* + we have outgoing changesets but refused to push + - other values as described by addchangegroup() + ''' + pushop = pushoperation(repo, remote, force, revs, newbranch) + if pushop.remote.local(): + missing = (set(pushop.repo.requirements) + - pushop.remote.local().supported) + if missing: + msg = _("required features are not" + " supported in the destination:" + " %s") % (', '.join(sorted(missing))) + raise util.Abort(msg) + + # there are two ways to push to remote repo: + # + # addchangegroup assumes local user can lock remote + # repo (local filesystem, old ssh servers). + # + # unbundle assumes local user cannot lock remote repo (new ssh + # servers, http servers). + + if not pushop.remote.canpush(): + raise util.Abort(_("destination does not support push")) + unfi = pushop.repo.unfiltered() + def localphasemove(nodes, phase=phases.public): + """move to in the local source repo""" + if locallock is not None: + phases.advanceboundary(pushop.repo, phase, nodes) + else: + # repo is not locked, do not change any phases! + # Informs the user that phases should have been moved when + # applicable. + actualmoves = [n for n in nodes if phase < pushop.repo[n].phase()] + phasestr = phases.phasenames[phase] + if actualmoves: + pushop.ui.status(_('cannot lock source repo, skipping ' + 'local %s phase update\n') % phasestr) + # get local lock as we might write phase data + locallock = None + try: + locallock = pushop.repo.lock() + except IOError, err: + if err.errno != errno.EACCES: + raise + # source repo cannot be locked. + # We do not abort the push, but just disable the local phase + # synchronisation. + msg = 'cannot lock source repository: %s\n' % err + pushop.ui.debug(msg) + try: + pushop.repo.checkpush(pushop.force, pushop.revs) + lock = None + unbundle = pushop.remote.capable('unbundle') + if not unbundle: + lock = pushop.remote.lock() + try: + # discovery + fci = discovery.findcommonincoming + commoninc = fci(unfi, pushop.remote, force=pushop.force) + common, inc, remoteheads = commoninc + fco = discovery.findcommonoutgoing + outgoing = fco(unfi, pushop.remote, onlyheads=pushop.revs, + commoninc=commoninc, force=pushop.force) + + + if not outgoing.missing: + # nothing to push + scmutil.nochangesfound(unfi.ui, unfi, outgoing.excluded) + ret = None + else: + # something to push + if not pushop.force: + # if repo.obsstore == False --> no obsolete + # then, save the iteration + if unfi.obsstore: + # this message are here for 80 char limit reason + mso = _("push includes obsolete changeset: %s!") + mst = "push includes %s changeset: %s!" + # plain versions for i18n tool to detect them + _("push includes unstable changeset: %s!") + _("push includes bumped changeset: %s!") + _("push includes divergent changeset: %s!") + # If we are to push if there is at least one + # obsolete or unstable changeset in missing, at + # least one of the missinghead will be obsolete or + # unstable. So checking heads only is ok + for node in outgoing.missingheads: + ctx = unfi[node] + if ctx.obsolete(): + raise util.Abort(mso % ctx) + elif ctx.troubled(): + raise util.Abort(_(mst) + % (ctx.troubles()[0], + ctx)) + newbm = pushop.ui.configlist('bookmarks', 'pushing') + discovery.checkheads(unfi, pushop.remote, outgoing, + remoteheads, pushop.newbranch, + bool(inc), newbm) + + # TODO: get bundlecaps from remote + bundlecaps = None + # create a changegroup from local + if pushop.revs is None and not (outgoing.excluded + or pushop.repo.changelog.filteredrevs): + # push everything, + # use the fast path, no race possible on push + bundler = changegroup.bundle10(pushop.repo, bundlecaps) + cg = pushop.repo._changegroupsubset(outgoing, + bundler, + 'push', + fastpath=True) + else: + cg = pushop.repo.getlocalbundle('push', outgoing, + bundlecaps) + + # apply changegroup to remote + if unbundle: + # local repo finds heads on server, finds out what + # revs it must push. once revs transferred, if server + # finds it has different heads (someone else won + # commit/push race), server aborts. + if pushop.force: + remoteheads = ['force'] + # ssh: return remote's addchangegroup() + # http: return remote's addchangegroup() or 0 for error + ret = pushop.remote.unbundle(cg, remoteheads, 'push') + else: + # we return an integer indicating remote head count + # change + ret = pushop.remote.addchangegroup(cg, 'push', + pushop.repo.url()) + + if ret: + # push succeed, synchronize target of the push + cheads = outgoing.missingheads + elif pushop.revs is None: + # All out push fails. synchronize all common + cheads = outgoing.commonheads + else: + # I want cheads = heads(::missingheads and ::commonheads) + # (missingheads is revs with secret changeset filtered out) + # + # This can be expressed as: + # cheads = ( (missingheads and ::commonheads) + # + (commonheads and ::missingheads))" + # ) + # + # while trying to push we already computed the following: + # common = (::commonheads) + # missing = ((commonheads::missingheads) - commonheads) + # + # We can pick: + # * missingheads part of common (::commonheads) + common = set(outgoing.common) + nm = pushop.repo.changelog.nodemap + cheads = [node for node in pushop.revs if nm[node] in common] + # and + # * commonheads parents on missing + revset = unfi.set('%ln and parents(roots(%ln))', + outgoing.commonheads, + outgoing.missing) + cheads.extend(c.node() for c in revset) + # even when we don't push, exchanging phase data is useful + remotephases = pushop.remote.listkeys('phases') + if (pushop.ui.configbool('ui', '_usedassubrepo', False) + and remotephases # server supports phases + and ret is None # nothing was pushed + and remotephases.get('publishing', False)): + # When: + # - this is a subrepo push + # - and remote support phase + # - and no changeset was pushed + # - and remote is publishing + # We may be in issue 3871 case! + # We drop the possible phase synchronisation done by + # courtesy to publish changesets possibly locally draft + # on the remote. + remotephases = {'publishing': 'True'} + if not remotephases: # old server or public only repo + localphasemove(cheads) + # don't push any phase data as there is nothing to push + else: + ana = phases.analyzeremotephases(pushop.repo, cheads, + remotephases) + pheads, droots = ana + ### Apply remote phase on local + if remotephases.get('publishing', False): + localphasemove(cheads) + else: # publish = False + localphasemove(pheads) + localphasemove(cheads, phases.draft) + ### Apply local phase on remote + + # Get the list of all revs draft on remote by public here. + # XXX Beware that revset break if droots is not strictly + # XXX root we may want to ensure it is but it is costly + outdated = unfi.set('heads((%ln::%ln) and public())', + droots, cheads) + for newremotehead in outdated: + r = pushop.remote.pushkey('phases', + newremotehead.hex(), + str(phases.draft), + str(phases.public)) + if not r: + pushop.ui.warn(_('updating %s to public failed!\n') + % newremotehead) + pushop.ui.debug('try to push obsolete markers to remote\n') + obsolete.syncpush(pushop.repo, pushop.remote) + finally: + if lock is not None: + lock.release() + finally: + if locallock is not None: + locallock.release() + + _pushbookmark(pushop.ui, unfi, pushop.remote, pushop.revs) + return ret + +def _pushbookmark(ui, repo, remote, revs): + """Update bookmark position on remote""" + ui.debug("checking for updated bookmarks\n") + revnums = map(repo.changelog.rev, revs or []) + ancestors = [a for a in repo.changelog.ancestors(revnums, inclusive=True)] + (addsrc, adddst, advsrc, advdst, diverge, differ, invalid + ) = bookmarks.compare(repo, repo._bookmarks, remote.listkeys('bookmarks'), + srchex=hex) + + for b, scid, dcid in advsrc: + if ancestors and repo[scid].rev() not in ancestors: + continue + if remote.pushkey('bookmarks', b, dcid, scid): + ui.status(_("updating bookmark %s\n") % b) + else: + ui.warn(_('updating bookmark %s failed!\n') % b) diff -r 6863d42eb59a -r cc00cd6c51c2 mercurial/hgweb/webcommands.py --- a/mercurial/hgweb/webcommands.py Wed Feb 05 17:23:35 2014 -0600 +++ b/mercurial/hgweb/webcommands.py Wed Feb 05 18:09:07 2014 -0600 @@ -187,7 +187,7 @@ mfunc = revset.match(web.repo.ui, revdef) try: - revs = mfunc(web.repo, list(web.repo)) + revs = mfunc(web.repo, revset.baseset(web.repo)) return MODE_REVSET, revs # ParseError: wrongly placed tokens, wrongs arguments, etc # RepoLookupError: no such revision, e.g. in 'revision:' diff -r 6863d42eb59a -r cc00cd6c51c2 mercurial/localrepo.py --- a/mercurial/localrepo.py Wed Feb 05 17:23:35 2014 -0600 +++ b/mercurial/localrepo.py Wed Feb 05 18:09:07 2014 -0600 @@ -9,7 +9,7 @@ import peer, changegroup, subrepo, discovery, pushkey, obsolete, repoview import changelog, dirstate, filelog, manifest, context, bookmarks, phases import lock as lockmod -import transaction, store, encoding +import transaction, store, encoding, exchange import scmutil, util, extensions, hook, error, revset import match as matchmod import merge as mergemod @@ -428,7 +428,7 @@ '''Return a list of revisions matching the given revset''' expr = revset.formatspec(expr, *args) m = revset.match(None, expr) - return [r for r in m(self, list(self))] + return revset.baseset([r for r in m(self, revset.baseset(self))]) def set(self, expr, *args): ''' @@ -1750,223 +1750,7 @@ pass def push(self, remote, force=False, revs=None, newbranch=False): - '''Push outgoing changesets (limited by revs) from the current - repository to remote. Return an integer: - - None means nothing to push - - 0 means HTTP error - - 1 means we pushed and remote head count is unchanged *or* - we have outgoing changesets but refused to push - - other values as described by addchangegroup() - ''' - if remote.local(): - missing = set(self.requirements) - remote.local().supported - if missing: - msg = _("required features are not" - " supported in the destination:" - " %s") % (', '.join(sorted(missing))) - raise util.Abort(msg) - - # there are two ways to push to remote repo: - # - # addchangegroup assumes local user can lock remote - # repo (local filesystem, old ssh servers). - # - # unbundle assumes local user cannot lock remote repo (new ssh - # servers, http servers). - - if not remote.canpush(): - raise util.Abort(_("destination does not support push")) - unfi = self.unfiltered() - def localphasemove(nodes, phase=phases.public): - """move to in the local source repo""" - if locallock is not None: - phases.advanceboundary(self, phase, nodes) - else: - # repo is not locked, do not change any phases! - # Informs the user that phases should have been moved when - # applicable. - actualmoves = [n for n in nodes if phase < self[n].phase()] - phasestr = phases.phasenames[phase] - if actualmoves: - self.ui.status(_('cannot lock source repo, skipping local' - ' %s phase update\n') % phasestr) - # get local lock as we might write phase data - locallock = None - try: - locallock = self.lock() - except IOError, err: - if err.errno != errno.EACCES: - raise - # source repo cannot be locked. - # We do not abort the push, but just disable the local phase - # synchronisation. - msg = 'cannot lock source repository: %s\n' % err - self.ui.debug(msg) - try: - self.checkpush(force, revs) - lock = None - unbundle = remote.capable('unbundle') - if not unbundle: - lock = remote.lock() - try: - # discovery - fci = discovery.findcommonincoming - commoninc = fci(unfi, remote, force=force) - common, inc, remoteheads = commoninc - fco = discovery.findcommonoutgoing - outgoing = fco(unfi, remote, onlyheads=revs, - commoninc=commoninc, force=force) - - - if not outgoing.missing: - # nothing to push - scmutil.nochangesfound(unfi.ui, unfi, outgoing.excluded) - ret = None - else: - # something to push - if not force: - # if self.obsstore == False --> no obsolete - # then, save the iteration - if unfi.obsstore: - # this message are here for 80 char limit reason - mso = _("push includes obsolete changeset: %s!") - mst = "push includes %s changeset: %s!" - # plain versions for i18n tool to detect them - _("push includes unstable changeset: %s!") - _("push includes bumped changeset: %s!") - _("push includes divergent changeset: %s!") - # If we are to push if there is at least one - # obsolete or unstable changeset in missing, at - # least one of the missinghead will be obsolete or - # unstable. So checking heads only is ok - for node in outgoing.missingheads: - ctx = unfi[node] - if ctx.obsolete(): - raise util.Abort(mso % ctx) - elif ctx.troubled(): - raise util.Abort(_(mst) - % (ctx.troubles()[0], - ctx)) - newbm = self.ui.configlist('bookmarks', 'pushing') - discovery.checkheads(unfi, remote, outgoing, - remoteheads, newbranch, - bool(inc), newbm) - - # TODO: get bundlecaps from remote - bundlecaps = None - # create a changegroup from local - if revs is None and not (outgoing.excluded - or self.changelog.filteredrevs): - # push everything, - # use the fast path, no race possible on push - bundler = changegroup.bundle10(self, bundlecaps) - cg = self._changegroupsubset(outgoing, - bundler, - 'push', - fastpath=True) - else: - cg = self.getlocalbundle('push', outgoing, bundlecaps) - - # apply changegroup to remote - if unbundle: - # local repo finds heads on server, finds out what - # revs it must push. once revs transferred, if server - # finds it has different heads (someone else won - # commit/push race), server aborts. - if force: - remoteheads = ['force'] - # ssh: return remote's addchangegroup() - # http: return remote's addchangegroup() or 0 for error - ret = remote.unbundle(cg, remoteheads, 'push') - else: - # we return an integer indicating remote head count - # change - ret = remote.addchangegroup(cg, 'push', self.url()) - - if ret: - # push succeed, synchronize target of the push - cheads = outgoing.missingheads - elif revs is None: - # All out push fails. synchronize all common - cheads = outgoing.commonheads - else: - # I want cheads = heads(::missingheads and ::commonheads) - # (missingheads is revs with secret changeset filtered out) - # - # This can be expressed as: - # cheads = ( (missingheads and ::commonheads) - # + (commonheads and ::missingheads))" - # ) - # - # while trying to push we already computed the following: - # common = (::commonheads) - # missing = ((commonheads::missingheads) - commonheads) - # - # We can pick: - # * missingheads part of common (::commonheads) - common = set(outgoing.common) - nm = self.changelog.nodemap - cheads = [node for node in revs if nm[node] in common] - # and - # * commonheads parents on missing - revset = unfi.set('%ln and parents(roots(%ln))', - outgoing.commonheads, - outgoing.missing) - cheads.extend(c.node() for c in revset) - # even when we don't push, exchanging phase data is useful - remotephases = remote.listkeys('phases') - if (self.ui.configbool('ui', '_usedassubrepo', False) - and remotephases # server supports phases - and ret is None # nothing was pushed - and remotephases.get('publishing', False)): - # When: - # - this is a subrepo push - # - and remote support phase - # - and no changeset was pushed - # - and remote is publishing - # We may be in issue 3871 case! - # We drop the possible phase synchronisation done by - # courtesy to publish changesets possibly locally draft - # on the remote. - remotephases = {'publishing': 'True'} - if not remotephases: # old server or public only repo - localphasemove(cheads) - # don't push any phase data as there is nothing to push - else: - ana = phases.analyzeremotephases(self, cheads, remotephases) - pheads, droots = ana - ### Apply remote phase on local - if remotephases.get('publishing', False): - localphasemove(cheads) - else: # publish = False - localphasemove(pheads) - localphasemove(cheads, phases.draft) - ### Apply local phase on remote - - # Get the list of all revs draft on remote by public here. - # XXX Beware that revset break if droots is not strictly - # XXX root we may want to ensure it is but it is costly - outdated = unfi.set('heads((%ln::%ln) and public())', - droots, cheads) - for newremotehead in outdated: - r = remote.pushkey('phases', - newremotehead.hex(), - str(phases.draft), - str(phases.public)) - if not r: - self.ui.warn(_('updating %s to public failed!\n') - % newremotehead) - self.ui.debug('try to push obsolete markers to remote\n') - obsolete.syncpush(self, remote) - finally: - if lock is not None: - lock.release() - finally: - if locallock is not None: - locallock.release() - - bookmarks.updateremote(self.ui, unfi, remote, revs) - return ret + return exchange.push(self, remote, force, revs, newbranch) def changegroupinfo(self, nodes, source): if self.ui.verbose or source == 'bundle': diff -r 6863d42eb59a -r cc00cd6c51c2 mercurial/revset.py --- a/mercurial/revset.py Wed Feb 05 17:23:35 2014 -0600 +++ b/mercurial/revset.py Wed Feb 05 18:09:07 2014 -0600 @@ -53,9 +53,9 @@ """Return all paths between roots and heads, inclusive of both endpoint sets.""" if not roots: - return [] + return baseset([]) parentrevs = repo.changelog.parentrevs - visit = heads[:] + visit = baseset(heads) reachable = set() seen = {} minroot = min(roots) @@ -72,12 +72,12 @@ if parent >= minroot and parent not in seen: visit.append(parent) if not reachable: - return [] + return baseset([]) for rev in sorted(seen): for parent in seen[rev]: if parent in reachable: reachable.add(rev) - return sorted(reachable) + return baseset(sorted(reachable)) elements = { "(": (20, ("group", 1, ")"), ("func", 1, ")")), @@ -195,7 +195,7 @@ def getset(repo, subset, x): if not x: raise error.ParseError(_("missing argument")) - return methods[x[0]](repo, subset, *x[1:]) + return baseset(methods[x[0]](repo, subset, *x[1:])) def _getrevsource(repo, r): extra = repo[r].extra() @@ -212,10 +212,10 @@ def stringset(repo, subset, x): x = repo[x].rev() if x == -1 and len(subset) == len(repo): - return [-1] + return baseset([-1]) if len(subset) == len(repo) or x in subset: - return [x] - return [] + return baseset([x]) + return baseset([]) def symbolset(repo, subset, x): if x in symbols: @@ -223,39 +223,37 @@ return stringset(repo, subset, x) def rangeset(repo, subset, x, y): - cl = repo.changelog + cl = baseset(repo.changelog) m = getset(repo, cl, x) n = getset(repo, cl, y) if not m or not n: - return [] + return baseset([]) m, n = m[0], n[-1] if m < n: r = range(m, n + 1) else: r = range(m, n - 1, -1) - s = set(subset) - return [x for x in r if x in s] + s = subset.set() + return baseset([x for x in r if x in s]) def dagrange(repo, subset, x, y): - r = list(repo) + r = baseset(repo) xs = _revsbetween(repo, getset(repo, r, x), getset(repo, r, y)) - s = set(subset) - return [r for r in xs if r in s] + s = subset.set() + return baseset([r for r in xs if r in s]) def andset(repo, subset, x, y): return getset(repo, getset(repo, subset, x), y) def orset(repo, subset, x, y): xl = getset(repo, subset, x) - s = set(xl) - yl = getset(repo, [r for r in subset if r not in s], y) - return xl + yl + yl = getset(repo, subset - xl, y) + return baseset(xl + yl) def notset(repo, subset, x): - s = set(getset(repo, subset, x)) - return [r for r in subset if r not in s] + return subset - getset(repo, subset, x) def listset(repo, subset, a, b): raise error.ParseError(_("can't use a list in this context")) @@ -289,7 +287,7 @@ """ # i18n: "ancestor" is a keyword l = getlist(x) - rl = list(repo) + rl = baseset(repo) anc = None # (getset(repo, rl, i) for i in l) generates a list of lists @@ -304,15 +302,16 @@ anc = rev(ancestor(node(anc), node(r))) if anc is not None and anc in subset: - return [anc] - return [] + return baseset([anc]) + return baseset([]) def _ancestors(repo, subset, x, followfirst=False): - args = getset(repo, list(repo), x) + args = getset(repo, baseset(repo), x) if not args: - return [] + return baseset([]) s = set(_revancestors(repo, args, followfirst)) | set(args) - return [r for r in subset if r in s] + ss = subset.set() + return baseset([r for r in ss if r in s]) def ancestors(repo, subset, x): """``ancestors(set)`` @@ -340,7 +339,8 @@ for i in range(n): r = cl.parentrevs(r)[0] ps.add(r) - return [r for r in subset if r in ps] + s = subset.set() + return baseset([r for r in s if r in ps]) def author(repo, subset, x): """``author(string)`` @@ -349,7 +349,8 @@ # i18n: "author" is a keyword n = encoding.lower(getstring(x, _("author requires a string"))) kind, pattern, matcher = _substringmatcher(n) - return [r for r in subset if matcher(encoding.lower(repo[r].user()))] + return baseset([r for r in subset if + matcher(encoding.lower(repo[r].user()))]) def bisect(repo, subset, x): """``bisect(string)`` @@ -366,7 +367,8 @@ # i18n: "bisect" is a keyword status = getstring(x, _("bisect requires a string")).lower() state = set(hbisect.get(repo, status)) - return [r for r in subset if r in state] + s = subset.set() + return baseset([r for r in s if r in state]) # Backward-compatibility # - no help entry so that we do not advertise it any more @@ -393,7 +395,7 @@ if not bmrev: raise util.Abort(_("bookmark '%s' does not exist") % bm) bmrev = repo[bmrev].rev() - return [r for r in subset if r == bmrev] + return baseset([r for r in subset if r == bmrev]) else: matchrevs = set() for name, bmrev in repo._bookmarks.iteritems(): @@ -405,11 +407,12 @@ bmrevs = set() for bmrev in matchrevs: bmrevs.add(repo[bmrev].rev()) - return [r for r in subset if r in bmrevs] + return subset & bmrevs bms = set([repo[r].rev() for r in repo._bookmarks.values()]) - return [r for r in subset if r in bms] + s = subset.set() + return baseset([r for r in s if r in bms]) def branch(repo, subset, x): """``branch(string or set)`` @@ -431,16 +434,16 @@ # note: falls through to the revspec case if no branch with # this name exists if pattern in repo.branchmap(): - return [r for r in subset if matcher(repo[r].branch())] + return baseset([r for r in subset if matcher(repo[r].branch())]) else: - return [r for r in subset if matcher(repo[r].branch())] + return baseset([r for r in subset if matcher(repo[r].branch())]) - s = getset(repo, list(repo), x) + s = getset(repo, baseset(repo), x) b = set() for r in s: b.add(repo[r].branch()) - s = set(s) - return [r for r in subset if r in s or repo[r].branch() in b] + s = s.set() + return baseset([r for r in subset if r in s or repo[r].branch() in b]) def bumped(repo, subset, x): """``bumped()`` @@ -451,7 +454,7 @@ # i18n: "bumped" is a keyword getargs(x, 0, 0, _("bumped takes no arguments")) bumped = obsmod.getrevs(repo, 'bumped') - return [r for r in subset if r in bumped] + return subset & bumped def bundle(repo, subset, x): """``bundle()`` @@ -463,7 +466,7 @@ bundlerevs = repo.changelog.bundlerevs except AttributeError: raise util.Abort(_("no bundle provided - specify with -R")) - return [r for r in subset if r in bundlerevs] + return subset & bundlerevs def checkstatus(repo, subset, pat, field): m = None @@ -494,12 +497,12 @@ if m(f): s.append(r) break - return s + return baseset(s) def _children(repo, narrow, parentset): cs = set() if not parentset: - return cs + return baseset(cs) pr = repo.changelog.parentrevs minrev = min(parentset) for r in narrow: @@ -508,15 +511,15 @@ for p in pr(r): if p in parentset: cs.add(r) - return cs + return baseset(cs) def children(repo, subset, x): """``children(set)`` Child changesets of changesets in set. """ - s = set(getset(repo, list(repo), x)) + s = getset(repo, baseset(repo), x).set() cs = _children(repo, subset, s) - return [r for r in subset if r in cs] + return subset & cs def closed(repo, subset, x): """``closed()`` @@ -524,7 +527,7 @@ """ # i18n: "closed" is a keyword getargs(x, 0, 0, _("closed takes no arguments")) - return [r for r in subset if repo[r].closesbranch()] + return baseset([r for r in subset if repo[r].closesbranch()]) def contains(repo, subset, x): """``contains(pattern)`` @@ -553,7 +556,7 @@ if m(f): s.append(r) break - return s + return baseset(s) def converted(repo, subset, x): """``converted([id])`` @@ -575,7 +578,7 @@ source = repo[r].extra().get('convert_revision', None) return source is not None and (rev is None or source.startswith(rev)) - return [r for r in subset if _matchvalue(r)] + return baseset([r for r in subset if _matchvalue(r)]) def date(repo, subset, x): """``date(interval)`` @@ -584,7 +587,7 @@ # i18n: "date" is a keyword ds = getstring(x, _("date requires a string")) dm = util.matchdate(ds) - return [r for r in subset if dm(repo[r].date()[0])] + return baseset([r for r in subset if dm(repo[r].date()[0])]) def desc(repo, subset, x): """``desc(string)`` @@ -597,14 +600,15 @@ c = repo[r] if ds in encoding.lower(c.description()): l.append(r) - return l + return baseset(l) def _descendants(repo, subset, x, followfirst=False): - args = getset(repo, list(repo), x) + args = getset(repo, baseset(repo), x) if not args: - return [] + return baseset([]) s = set(_revdescendants(repo, args, followfirst)) | set(args) - return [r for r in subset if r in s] + ss = subset.set() + return baseset([r for r in ss if r in s]) def descendants(repo, subset, x): """``descendants(set)`` @@ -624,9 +628,9 @@ is the same as passing all(). """ if x is not None: - args = set(getset(repo, list(repo), x)) + args = getset(repo, baseset(repo), x).set() else: - args = set(getall(repo, list(repo), x)) + args = getall(repo, baseset(repo), x).set() dests = set() @@ -659,7 +663,7 @@ r = src src = _getrevsource(repo, r) - return [r for r in subset if r in dests] + return baseset([r for r in subset if r in dests]) def divergent(repo, subset, x): """``divergent()`` @@ -668,7 +672,7 @@ # i18n: "divergent" is a keyword getargs(x, 0, 0, _("divergent takes no arguments")) divergent = obsmod.getrevs(repo, 'divergent') - return [r for r in subset if r in divergent] + return baseset([r for r in subset if r in divergent]) def draft(repo, subset, x): """``draft()`` @@ -676,7 +680,7 @@ # i18n: "draft" is a keyword getargs(x, 0, 0, _("draft takes no arguments")) pc = repo._phasecache - return [r for r in subset if pc.phase(repo, r) == phases.draft] + return baseset([r for r in subset if pc.phase(repo, r) == phases.draft]) def extinct(repo, subset, x): """``extinct()`` @@ -685,7 +689,7 @@ # i18n: "extinct" is a keyword getargs(x, 0, 0, _("extinct takes no arguments")) extincts = obsmod.getrevs(repo, 'extinct') - return [r for r in subset if r in extincts] + return subset & extincts def extra(repo, subset, x): """``extra(label, [value])`` @@ -712,7 +716,7 @@ extra = repo[r].extra() return label in extra and (value is None or matcher(extra[label])) - return [r for r in subset if _matchvalue(r)] + return baseset([r for r in subset if _matchvalue(r)]) def filelog(repo, subset, x): """``filelog(pattern)`` @@ -744,7 +748,8 @@ for fr in fl: s.add(fl.linkrev(fr)) - return [r for r in subset if r in s] + ss = subset.set() + return baseset([r for r in ss if r in s]) def first(repo, subset, x): """``first(set, [n])`` @@ -763,11 +768,12 @@ # include the revision responsible for the most recent version s.add(cx.linkrev()) else: - return [] + return baseset([]) else: s = set(_revancestors(repo, [c.rev()], followfirst)) | set([c.rev()]) - return [r for r in subset if r in s] + ss = subset.set() + return baseset([r for r in ss if r in s]) def follow(repo, subset, x): """``follow([file])`` @@ -809,7 +815,7 @@ if gr.search(e): l.append(r) break - return l + return baseset(l) def _matchfiles(repo, subset, x): # _matchfiles takes a revset list of prefixed arguments: @@ -872,7 +878,7 @@ if m(f): s.append(r) break - return s + return baseset(s) def hasfile(repo, subset, x): """``file(pattern)`` @@ -896,15 +902,16 @@ hs = set() for b, ls in repo.branchmap().iteritems(): hs.update(repo[h].rev() for h in ls) - return [r for r in subset if r in hs] + s = subset.set() + return baseset([r for r in s if r in hs]) def heads(repo, subset, x): """``heads(set)`` Members of set with no children in set. """ s = getset(repo, subset, x) - ps = set(parents(repo, subset, x)) - return [r for r in s if r not in ps] + ps = parents(repo, subset, x) + return s - ps def hidden(repo, subset, x): """``hidden()`` @@ -913,7 +920,7 @@ # i18n: "hidden" is a keyword getargs(x, 0, 0, _("hidden takes no arguments")) hiddenrevs = repoview.filterrevs(repo, 'visible') - return [r for r in subset if r in hiddenrevs] + return subset & hiddenrevs def keyword(repo, subset, x): """``keyword(string)`` @@ -928,7 +935,7 @@ if util.any(kw in encoding.lower(t) for t in c.files() + [c.user(), c.description()]): l.append(r) - return l + return baseset(l) def limit(repo, subset, x): """``limit(set, [n])`` @@ -944,9 +951,9 @@ except (TypeError, ValueError): # i18n: "limit" is a keyword raise error.ParseError(_("limit expects a number")) - ss = set(subset) - os = getset(repo, list(repo), l[0])[:lim] - return [r for r in os if r in ss] + ss = subset.set() + os = getset(repo, baseset(repo), l[0])[:lim] + return baseset([r for r in os if r in ss]) def last(repo, subset, x): """``last(set, [n])`` @@ -962,20 +969,20 @@ except (TypeError, ValueError): # i18n: "last" is a keyword raise error.ParseError(_("last expects a number")) - ss = set(subset) - os = getset(repo, list(repo), l[0])[-lim:] - return [r for r in os if r in ss] + ss = subset.set() + os = getset(repo, baseset(repo), l[0])[-lim:] + return baseset([r for r in os if r in ss]) def maxrev(repo, subset, x): """``max(set)`` Changeset with highest revision number in set. """ - os = getset(repo, list(repo), x) + os = getset(repo, baseset(repo), x) if os: m = max(os) if m in subset: - return [m] - return [] + return baseset([m]) + return baseset([]) def merge(repo, subset, x): """``merge()`` @@ -984,7 +991,7 @@ # i18n: "merge" is a keyword getargs(x, 0, 0, _("merge takes no arguments")) cl = repo.changelog - return [r for r in subset if cl.parentrevs(r)[1] != -1] + return baseset([r for r in subset if cl.parentrevs(r)[1] != -1]) def branchpoint(repo, subset, x): """``branchpoint()`` @@ -994,25 +1001,25 @@ getargs(x, 0, 0, _("branchpoint takes no arguments")) cl = repo.changelog if not subset: - return [] + return baseset([]) baserev = min(subset) parentscount = [0]*(len(repo) - baserev) for r in cl.revs(start=baserev + 1): for p in cl.parentrevs(r): if p >= baserev: parentscount[p - baserev] += 1 - return [r for r in subset if (parentscount[r - baserev] > 1)] + return baseset([r for r in subset if (parentscount[r - baserev] > 1)]) def minrev(repo, subset, x): """``min(set)`` Changeset with lowest revision number in set. """ - os = getset(repo, list(repo), x) + os = getset(repo, baseset(repo), x) if os: m = min(os) if m in subset: - return [m] - return [] + return baseset([m]) + return baseset([]) def modifies(repo, subset, x): """``modifies(pattern)`` @@ -1042,7 +1049,7 @@ if pm is not None: rn = repo.changelog.rev(pm) - return [r for r in subset if r == rn] + return baseset([r for r in subset if r == rn]) def obsolete(repo, subset, x): """``obsolete()`` @@ -1050,7 +1057,7 @@ # i18n: "obsolete" is a keyword getargs(x, 0, 0, _("obsolete takes no arguments")) obsoletes = obsmod.getrevs(repo, 'obsolete') - return [r for r in subset if r in obsoletes] + return subset & obsoletes def origin(repo, subset, x): """``origin([set])`` @@ -1061,9 +1068,9 @@ for the first operation is selected. """ if x is not None: - args = set(getset(repo, list(repo), x)) + args = getset(repo, baseset(repo), x).set() else: - args = set(getall(repo, list(repo), x)) + args = getall(repo, baseset(repo), x).set() def _firstsrc(rev): src = _getrevsource(repo, rev) @@ -1078,7 +1085,8 @@ src = prev o = set([_firstsrc(r) for r in args]) - return [r for r in subset if r in o] + s = subset.set() + return baseset([r for r in s if r in o]) def outgoing(repo, subset, x): """``outgoing([path])`` @@ -1101,7 +1109,8 @@ repo.ui.popbuffer() cl = repo.changelog o = set([cl.rev(r) for r in outgoing.missing]) - return [r for r in subset if r in o] + s = subset.set() + return baseset([r for r in s if r in o]) def p1(repo, subset, x): """``p1([set])`` @@ -1109,13 +1118,13 @@ """ if x is None: p = repo[x].p1().rev() - return [r for r in subset if r == p] + return baseset([r for r in subset if r == p]) ps = set() cl = repo.changelog - for r in getset(repo, list(repo), x): + for r in getset(repo, baseset(repo), x): ps.add(cl.parentrevs(r)[0]) - return [r for r in subset if r in ps] + return subset & ps def p2(repo, subset, x): """``p2([set])`` @@ -1125,15 +1134,15 @@ ps = repo[x].parents() try: p = ps[1].rev() - return [r for r in subset if r == p] + return baseset([r for r in subset if r == p]) except IndexError: - return [] + return baseset([]) ps = set() cl = repo.changelog - for r in getset(repo, list(repo), x): + for r in getset(repo, baseset(repo), x): ps.add(cl.parentrevs(r)[1]) - return [r for r in subset if r in ps] + return subset & ps def parents(repo, subset, x): """``parents([set])`` @@ -1141,13 +1150,13 @@ """ if x is None: ps = tuple(p.rev() for p in repo[x].parents()) - return [r for r in subset if r in ps] + return subset & ps ps = set() cl = repo.changelog - for r in getset(repo, list(repo), x): + for r in getset(repo, baseset(repo), x): ps.update(cl.parentrevs(r)) - return [r for r in subset if r in ps] + return subset & ps def parentspec(repo, subset, x, n): """``set^0`` @@ -1163,7 +1172,7 @@ raise error.ParseError(_("^ expects a number 0, 1, or 2")) ps = set() cl = repo.changelog - for r in getset(repo, cl, x): + for r in getset(repo, baseset(cl), x): if n == 0: ps.add(r) elif n == 1: @@ -1172,7 +1181,7 @@ parents = cl.parentrevs(r) if len(parents) > 1: ps.add(parents[1]) - return [r for r in subset if r in ps] + return subset & ps def present(repo, subset, x): """``present(set)`` @@ -1186,7 +1195,7 @@ try: return getset(repo, subset, x) except error.RepoLookupError: - return [] + return baseset([]) def public(repo, subset, x): """``public()`` @@ -1194,7 +1203,7 @@ # i18n: "public" is a keyword getargs(x, 0, 0, _("public takes no arguments")) pc = repo._phasecache - return [r for r in subset if pc.phase(repo, r) == phases.public] + return baseset([r for r in subset if pc.phase(repo, r) == phases.public]) def remote(repo, subset, x): """``remote([id [,path]])`` @@ -1228,8 +1237,8 @@ if n in repo: r = repo[n].rev() if r in subset: - return [r] - return [] + return baseset([r]) + return baseset([]) def removes(repo, subset, x): """``removes(pattern)`` @@ -1255,7 +1264,7 @@ except (TypeError, ValueError): # i18n: "rev" is a keyword raise error.ParseError(_("rev expects a number")) - return [r for r in subset if r == l] + return baseset([r for r in subset if r == l]) def matching(repo, subset, x): """``matching(revision [, field])`` @@ -1285,7 +1294,7 @@ # i18n: "matching" is a keyword l = getargs(x, 1, 2, _("matching takes 1 or 2 arguments")) - revs = getset(repo, repo.changelog, l[0]) + revs = getset(repo, baseset(repo.changelog), l[0]) fieldlist = ['metadata'] if len(l) > 1: @@ -1367,15 +1376,13 @@ break if match: matches.add(r) - return [r for r in subset if r in matches] + return baseset([r for r in subset if r in matches]) def reverse(repo, subset, x): """``reverse(set)`` Reverse order of set. """ l = getset(repo, subset, x) - if not isinstance(l, list): - l = list(l) l.reverse() return l @@ -1383,10 +1390,10 @@ """``roots(set)`` Changesets in set with no parent changeset in set. """ - s = set(getset(repo, repo.changelog, x)) - subset = [r for r in subset if r in s] + s = getset(repo, baseset(repo.changelog), x).set() + subset = baseset([r for r in subset if r in s]) cs = _children(repo, subset, s) - return [r for r in subset if r not in cs] + return subset - cs def secret(repo, subset, x): """``secret()`` @@ -1394,7 +1401,7 @@ # i18n: "secret" is a keyword getargs(x, 0, 0, _("secret takes no arguments")) pc = repo._phasecache - return [r for r in subset if pc.phase(repo, r) == phases.secret] + return baseset([r for r in subset if pc.phase(repo, r) == phases.secret]) def sort(repo, subset, x): """``sort(set[, [-]key...])`` @@ -1450,7 +1457,7 @@ e.append(r) l.append(e) l.sort() - return [e[-1] for e in l] + return baseset([e[-1] for e in l]) def _stringmatcher(pattern): """ @@ -1519,7 +1526,7 @@ s = set([cl.rev(n) for t, n in repo.tagslist() if matcher(t)]) else: s = set([cl.rev(n) for t, n in repo.tagslist() if t != 'tip']) - return [r for r in subset if r in s] + return subset & s def tagged(repo, subset, x): return tag(repo, subset, x) @@ -1531,7 +1538,7 @@ # i18n: "unstable" is a keyword getargs(x, 0, 0, _("unstable takes no arguments")) unstables = obsmod.getrevs(repo, 'unstable') - return [r for r in subset if r in unstables] + return subset & unstables def user(repo, subset, x): @@ -1548,11 +1555,10 @@ def _list(repo, subset, x): s = getstring(x, "internal error") if not s: - return [] - if not isinstance(subset, set): - subset = set(subset) + return baseset([]) ls = [repo[r].rev() for r in s.split('\0')] - return [r for r in ls if r in subset] + s = subset.set() + return baseset([r for r in ls if r in s]) symbols = { "adds": adds, @@ -2046,5 +2052,28 @@ funcs.add(tree[1][1]) return funcs +class baseset(list): + def __init__(self, data): + super(baseset, self).__init__(data) + self._set = None + + def set(self): + if not self._set: + self._set = set(self) + return self._set + + def __sub__(self, x): + if isinstance(x, baseset): + s = x.set() + else: + s = set(x) + return baseset(self.set() - s) + + def __and__(self, x): + s = self.set() + if isinstance(x, baseset): + x = x.set() + return baseset([y for y in s if y in x]) + # tell hggettext to extract docstrings from these functions: i18nfunctions = symbols.values() diff -r 6863d42eb59a -r cc00cd6c51c2 mercurial/scmutil.py --- a/mercurial/scmutil.py Wed Feb 05 17:23:35 2014 -0600 +++ b/mercurial/scmutil.py Wed Feb 05 18:09:07 2014 -0600 @@ -524,11 +524,11 @@ # fall through to new-style queries if old-style fails m = revset.match(repo.ui, spec) - dl = [r for r in m(repo, list(repo)) if r not in seen] + dl = [r for r in m(repo, revset.baseset(repo)) if r not in seen] l.extend(dl) seen.update(dl) - return l + return revset.baseset(l) def expandpats(pats): if not util.expandglobs: