# HG changeset patch # User Matt Mackall # Date 1392327204 21600 # Node ID d0bca0649c7f554d42ceb7e24448dbba663821a8 # Parent 7b5ec1c7e8e29d063b8bab5f93e5a69bdd8a2bb7# Parent da64679bfc8a761cacb5976efba411362c8bc51e merge with crew diff -r da64679bfc8a -r d0bca0649c7f mercurial/exchange.py --- a/mercurial/exchange.py Thu Feb 13 13:08:50 2014 +0100 +++ b/mercurial/exchange.py Thu Feb 13 15:33:24 2014 -0600 @@ -395,6 +395,25 @@ self._trname = 'pull\n' + util.hidepassword(remote.url()) # hold the transaction once created self._tr = None + # set of common changeset between local and remote before pull + self.common = None + # set of pulled head + self.rheads = None + # list of missing changeset to fetch remotly + self.fetch = None + + @util.propertycache + def pulledsubset(self): + """heads of the set of changeset target by the pull""" + # compute target subset + if self.heads is None: + # We pulled every thing possible + # sync on everything common + return self.common + self.rheads + else: + # We pulled a specific subset + # sync on this subset + return self.heads def gettransaction(self): """get appropriate pull transaction, creating it if needed""" @@ -428,62 +447,14 @@ pullop.remote, heads=pullop.heads, force=force) - common, fetch, rheads = tmp - if not fetch: + pullop.common, pullop.fetch, pullop.rheads = tmp + if not pullop.fetch: pullop.repo.ui.status(_("no changes found\n")) result = 0 else: - # We delay the open of the transaction as late as possible so we - # don't open transaction for nothing or you break future useful - # rollback call - pullop.gettransaction() - if pullop.heads is None and list(common) == [nullid]: - pullop.repo.ui.status(_("requesting all changes\n")) - elif (pullop.heads is None - and pullop.remote.capable('changegroupsubset')): - # issue1320, avoid a race if remote changed after discovery - pullop.heads = rheads + result = _pullchangeset(pullop) - if pullop.remote.capable('getbundle'): - # TODO: get bundlecaps from remote - cg = pullop.remote.getbundle('pull', common=common, - heads=pullop.heads or rheads) - elif pullop.heads is None: - cg = pullop.remote.changegroup(fetch, 'pull') - elif not pullop.remote.capable('changegroupsubset'): - raise util.Abort(_("partial pull cannot be done because " - "other repository doesn't support " - "changegroupsubset.")) - else: - cg = pullop.remote.changegroupsubset(fetch, pullop.heads, - 'pull') - result = pullop.repo.addchangegroup(cg, 'pull', - pullop.remote.url()) - - # compute target subset - if pullop.heads is None: - # We pulled every thing possible - # sync on everything common - subset = common + rheads - else: - # We pulled a specific subset - # sync on this subset - subset = pullop.heads - - # Get remote phases data from remote - remotephases = pullop.remote.listkeys('phases') - publishing = bool(remotephases.get('publishing', False)) - if remotephases and not publishing: - # remote is new and unpublishing - pheads, _dr = phases.analyzeremotephases(pullop.repo, subset, - remotephases) - phases.advanceboundary(pullop.repo, phases.public, pheads) - phases.advanceboundary(pullop.repo, phases.draft, subset) - else: - # Remote is old or publishing all common changesets - # should be seen as public - phases.advanceboundary(pullop.repo, phases.public, subset) - + _pullphase(pullop) _pullobsolete(pullop) pullop.closetransaction() finally: @@ -492,6 +463,50 @@ return result +def _pullchangeset(pullop): + """pull changeset from unbundle into the local repo""" + # We delay the open of the transaction as late as possible so we + # don't open transaction for nothing or you break future useful + # rollback call + pullop.gettransaction() + if pullop.heads is None and list(pullop.common) == [nullid]: + pullop.repo.ui.status(_("requesting all changes\n")) + elif pullop.heads is None and pullop.remote.capable('changegroupsubset'): + # issue1320, avoid a race if remote changed after discovery + pullop.heads = pullop.rheads + + if pullop.remote.capable('getbundle'): + # TODO: get bundlecaps from remote + cg = pullop.remote.getbundle('pull', common=pullop.common, + heads=pullop.heads or pullop.rheads) + elif pullop.heads is None: + cg = pullop.remote.changegroup(pullop.fetch, 'pull') + elif not pullop.remote.capable('changegroupsubset'): + raise util.Abort(_("partial pull cannot be done because " + "other repository doesn't support " + "changegroupsubset.")) + else: + cg = pullop.remote.changegroupsubset(pullop.fetch, pullop.heads, 'pull') + return pullop.repo.addchangegroup(cg, 'pull', pullop.remote.url()) + +def _pullphase(pullop): + # Get remote phases data from remote + remotephases = pullop.remote.listkeys('phases') + publishing = bool(remotephases.get('publishing', False)) + if remotephases and not publishing: + # remote is new and unpublishing + pheads, _dr = phases.analyzeremotephases(pullop.repo, + pullop.pulledsubset, + remotephases) + phases.advanceboundary(pullop.repo, phases.public, pheads) + phases.advanceboundary(pullop.repo, phases.draft, + pullop.pulledsubset) + else: + # Remote is old or publishing all common changesets + # should be seen as public + phases.advanceboundary(pullop.repo, phases.public, + pullop.pulledsubset) + def _pullobsolete(pullop): """utility function to pull obsolete markers from a remote diff -r da64679bfc8a -r d0bca0649c7f mercurial/revset.py --- a/mercurial/revset.py Thu Feb 13 13:08:50 2014 +0100 +++ b/mercurial/revset.py Thu Feb 13 15:33:24 2014 -0600 @@ -522,7 +522,7 @@ """ # i18n: "closed" is a keyword getargs(x, 0, 0, _("closed takes no arguments")) - return baseset([r for r in subset if repo[r].closesbranch()]) + return lazyset(subset, lambda r: repo[r].closesbranch()) def contains(repo, subset, x): """``contains(pattern)`` @@ -571,7 +571,7 @@ source = repo[r].extra().get('convert_revision', None) return source is not None and (rev is None or source.startswith(rev)) - return baseset([r for r in subset if _matchvalue(r)]) + return lazyset(subset, lambda r: _matchvalue(r)) def date(repo, subset, x): """``date(interval)`` @@ -708,7 +708,7 @@ extra = repo[r].extra() return label in extra and (value is None or matcher(extra[label])) - return baseset([r for r in subset if _matchvalue(r)]) + return lazyset(subset, lambda r: _matchvalue(r)) def filelog(repo, subset, x): """``filelog(pattern)`` @@ -2129,5 +2129,57 @@ def set(self): return set([r for r in self]) +class spanset(object): + """Duck type for baseset class which represents a range of revisions and + can work lazily and without having all the range in memory + """ + def __init__(self, start, end): + self._start = start + self._end = end + + def __iter__(self): + if self._start <= self._end: + for r in xrange(self._start, self._end): + yield r + else: + for r in xrange(self._start, self._end, -1): + yield r + + def __contains__(self, x): + return (x <= self._start and x > self._end) or (x >= self._start and x< + self._end) + + def __and__(self, x): + return lazyset(self, lambda r: r in x) + + def __sub__(self, x): + return lazyset(self, lambda r: r not in x) + + def __add__(self, x): + l = baseset(self) + return l + baseset(x) + + def __len__(self): + return abs(self._end - self._start) + + def __getitem__(self, x): + # Basic implementation to be changed in future patches. + l = baseset([r for r in self]) + return l[x] + + def sort(self, reverse=False): + # Basic implementation to be changed in future patches. + if reverse: + self.reverse() + + def reverse(self): + if self._start <= self._end: + self._start, self._end = self._end - 1, self._start - 1 + else: + self._start, self._end = self._end + 1, self._start + 1 + + def set(self): + return self + # tell hggettext to extract docstrings from these functions: i18nfunctions = symbols.values()