@@ -4654,6 +4654,8 @@
('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
('b', 'branch', [], _('a specific branch you would like to pull'),
_('BRANCH')),
+ ('S', 'subrepos', None,
+ _('pull current and incoming subrepos recursively')),
] + remoteopts,
_('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
def pull(ui, repo, source="default", **opts):
@@ -4698,7 +4700,9 @@
"so a rev cannot be specified.")
raise util.Abort(err)
- modheads = repo.pull(other, heads=revs, force=opts.get('force'))
+ modheads = repo.pull(other, heads=revs, force=opts.get('force'),
+ subrepos=opts.get('subrepos'))
+
bookmarks.updatefromremote(ui, repo, other, source)
if checkout:
checkout = str(repo.changelog.rev(other.lookup(checkout)))
@@ -10,12 +10,14 @@
import changelog, dirstate, filelog, manifest, context, bookmarks, phases
import lock, transaction, store, encoding, base85
import scmutil, util, extensions, hook, error, revset
+import config
import match as matchmod
import merge as mergemod
import tags as tagsmod
from lock import release
import weakref, errno, os, time, inspect
import branchmap
+import itertools
propertycache = util.propertycache
filecache = scmutil.filecache
@@ -1646,11 +1648,13 @@
return r
- def pull(self, remote, heads=None, force=False):
+ def pull(self, remote, heads=None, force=False, subrepos=False):
# don't open transaction for nothing or you break future useful
# rollback call
tr = None
trname = 'pull\n' + util.hidepassword(remote.url())
+ if subrepos:
+ oldtip = len(self)
lock = self.lock()
try:
tmp = discovery.findcommonincoming(self, remote, heads=heads,
@@ -1730,8 +1734,43 @@
tr.release()
lock.release()
+ # update current and new subrepos
+ if subrepos:
+ # pull (or clone) the subrepos that are referenced by the
+ # current revision or by any of the incoming revisions
+ revstocheck = itertools.chain(['.'], self.changelog.revs(oldtip))
+ self.getsubrepos(revs=revstocheck, source=remote.url())
+
return result
+ def getsubrepos(self, revs=None, source=None):
+ """Get (clone or pull) the subrepos that are referenced
+ on any of the revisions on the given revision list
+ """
+ if revs is None:
+ # check all revisions
+ revs = self.changelog.revs()
+ # use a sortdict to make sure that we get the subrepos
+ # in the order they are found
+ substopull = config.sortdict()
+ for rev in revs:
+ ctx = self[rev]
+ # read the substate items in alphabetical order to ensure
+ # that we always process the subrepos in the same order
+ for sname in sorted(ctx.substate):
+ sinfo = ctx.substate[sname]
+ substopull[(sname, sinfo[0], sinfo[2])] = ctx
+ try:
+ self._subtoppath = source
+ for (sname, ssource, stype), ctx in substopull.items():
+ try:
+ ctx.sub(sname).pull(ssource)
+ except (error.RepoError, urllib2.HTTPError), ex:
+ self.ui.warn(_('could not pull subrepo %s from %s (%s)\n')
+ % (sname, ssource, str(ex)))
+ finally:
+ del self._subtoppath
+
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
@@ -330,6 +330,11 @@
"""
raise NotImplementedError
+ def pull(self, source):
+ """pull from the given parent repository source
+ """
+ raise NotImplementedError
+
def get(self, state, overwrite=False):
"""run whatever commands are needed to put the subrepo into
this state
@@ -528,8 +533,13 @@
self._repo.ui.note(_('removing subrepo %s\n') % subrelpath(self))
hg.clean(self._repo, node.nullid, False)
+ def pull(self, source):
+ state = (source, None, 'hg')
+ return self._get(state)
+
def _get(self, state):
source, revision, kind = state
+ subrepos = revision is None
if revision not in self._repo:
self._repo._subsource = source
srcurl = _abssource(self._repo)
@@ -547,7 +557,7 @@
else:
self._repo.ui.status(_('pulling subrepo %s from %s\n')
% (subrelpath(self), srcurl))
- self._repo.pull(other)
+ self._repo.pull(other, subrepos=subrepos)
bookmarks.updatefromremote(self._repo.ui, self._repo, other,
srcurl)
@@ -204,7 +204,7 @@
init: ssh, remotecmd, insecure
log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
merge: force, rev, preview, tool
- pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
+ pull: update, force, rev, bookmark, branch, subrepos, ssh, remotecmd, insecure
push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
remove: after, force, include, exclude
serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate