From patchwork Wed Apr 17 15:58:42 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [07,of,16] exchangeutil: turn pull into an object From: Pierre-Yves David X-Patchwork-Id: 1396 Message-Id: To: mercurial-devel@selenic.com Cc: pierre-yves.david@logilab.fr Date: Wed, 17 Apr 2013 17:58:42 +0200 # HG changeset patch # User Pierre-Yves David # Date 1366206025 -7200 # Wed Apr 17 15:40:25 2013 +0200 # Node ID e98361603d55211f03b4a2a6aa8af2f92d9661b5 # Parent ebab1a6407d1d19dd84a4ad7721c5dbfcad31b68 exchangeutil: turn pull into an object This move toward a small state-full, one-shot object where each step are isolated. Smaller function are easier to maintains and wrap. diff --git a/mercurial/exchangeutil.py b/mercurial/exchangeutil.py --- a/mercurial/exchangeutil.py +++ b/mercurial/exchangeutil.py @@ -234,90 +234,92 @@ class pushoperation(object): else: repo.ui.warn(_('updating bookmark %s' ' failed!\n') % k) -def pull(repo, remote, heads=None, force=False): - # don't open transaction for nothing or you break future useful - # rollback call - tr = None - trname = 'pull\n' + util.hidepassword(remote.url()) - lock = repo.lock() - try: - tmp = discovery.findcommonincoming(repo, remote, heads=heads, - force=force) - common, fetch, rheads = tmp - if not fetch: - repo.ui.status(_("no changes found\n")) - added = [] - result = 0 - else: - tr = repo.transaction(trname) - if heads is None and list(common) == [nullid]: - repo.ui.status(_("requesting all changes\n")) - elif heads is None and remote.capable('changegroupsubset'): - # issue1320, avoid a race if remote changed after discovery - heads = rheads +class pulloperation(object): - if remote.capable('getbundle'): - cg = remote.getbundle('pull', common=common, - heads=heads or rheads) - elif heads is None: - cg = remote.changegroup(fetch, 'pull') - elif not remote.capable('changegroupsubset'): - raise util.Abort(_("partial pull cannot be done because " - "other repository doesn't support " - "changegroupsubset.")) + def perform(self, repo, remote, heads=None, force=False): + # don't open transaction for nothing or you break future useful + # rollback call + tr = None + trname = 'pull\n' + util.hidepassword(remote.url()) + lock = repo.lock() + try: + tmp = discovery.findcommonincoming(repo, remote, heads=heads, + force=force) + common, fetch, rheads = tmp + if not fetch: + repo.ui.status(_("no changes found\n")) + added = [] + result = 0 else: - cg = remote.changegroupsubset(fetch, heads, 'pull') - # we use unfiltered changelog here because hidden revision must - # be taken in account for phase synchronization. They may - # becomes public and becomes visible again. - cl = repo.unfiltered().changelog - clstart = len(cl) - result = repo.addchangegroup(cg, 'pull', remote.url()) - clend = len(cl) - added = [cl.node(r) for r in xrange(clstart, clend)] + tr = repo.transaction(trname) + if heads is None and list(common) == [nullid]: + repo.ui.status(_("requesting all changes\n")) + elif heads is None and remote.capable('changegroupsubset'): + # issue1320, avoid a race if remote changed after discovery + heads = rheads - # compute target subset - if heads is None: - # We pulled every thing possible - # sync on everything common - subset = common + added - else: - # We pulled a specific subset - # sync on this subset - subset = heads + if remote.capable('getbundle'): + cg = remote.getbundle('pull', common=common, + heads=heads or rheads) + elif heads is None: + cg = remote.changegroup(fetch, 'pull') + elif not remote.capable('changegroupsubset'): + raise util.Abort(_("partial pull cannot be done because " + "other repository doesn't support " + "changegroupsubset.")) + else: + cg = remote.changegroupsubset(fetch, heads, 'pull') + # we use unfiltered changelog here because hidden revision must + # be taken in account for phase synchronization. They may + # becomes public and becomes visible again. + cl = repo.unfiltered().changelog + clstart = len(cl) + result = repo.addchangegroup(cg, 'pull', remote.url()) + clend = len(cl) + added = [cl.node(r) for r in xrange(clstart, clend)] - # Get remote phases data from remote - remotephases = remote.listkeys('phases') - publishing = bool(remotephases.get('publishing', False)) - if remotephases and not publishing: - # remote is new and unpublishing - pheads, _dr = phases.analyzeremotephases(repo, subset, - remotephases) - phases.advanceboundary(repo, phases.public, pheads) - phases.advanceboundary(repo, phases.draft, subset) - else: - # Remote is old or publishing all common changesets - # should be seen as public - phases.advanceboundary(repo, phases.public, subset) + # compute target subset + if heads is None: + # We pulled every thing possible + # sync on everything common + subset = common + added + else: + # We pulled a specific subset + # sync on this subset + subset = heads - if obsolete._enabled: - repo.ui.debug('fetching remote obsolete markers\n') - remoteobs = remote.listkeys('obsolete') - if 'dump0' in remoteobs: - if tr is None: - tr = repo.transaction(trname) - for key in sorted(remoteobs, reverse=True): - if key.startswith('dump'): - data = base85.b85decode(remoteobs[key]) - repo.obsstore.mergemarkers(tr, data) - repo.invalidatevolatilesets() - if tr is not None: - tr.close() - finally: - if tr is not None: - tr.release() - lock.release() + # Get remote phases data from remote + remotephases = remote.listkeys('phases') + publishing = bool(remotephases.get('publishing', False)) + if remotephases and not publishing: + # remote is new and unpublishing + pheads, _dr = phases.analyzeremotephases(repo, subset, + remotephases) + phases.advanceboundary(repo, phases.public, pheads) + phases.advanceboundary(repo, phases.draft, subset) + else: + # Remote is old or publishing all common changesets + # should be seen as public + phases.advanceboundary(repo, phases.public, subset) - return result + if obsolete._enabled: + repo.ui.debug('fetching remote obsolete markers\n') + remoteobs = remote.listkeys('obsolete') + if 'dump0' in remoteobs: + if tr is None: + tr = repo.transaction(trname) + for key in sorted(remoteobs, reverse=True): + if key.startswith('dump'): + data = base85.b85decode(remoteobs[key]) + repo.obsstore.mergemarkers(tr, data) + repo.invalidatevolatilesets() + if tr is not None: + tr.close() + finally: + if tr is not None: + tr.release() + lock.release() + + return result diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -1650,11 +1650,12 @@ class localrepository(object): r.append(l) return r def pull(self, remote, heads=None, force=False): - return exchangeutil.pull (self, remote, heads, force) + pull = exchangeutil.pulloperation() + return pull.perform(self, remote, heads, force) def checkpush(self, force, revs): """Extensions can override this function if additional checks have to be performed before pushing, or call it if they override push command.