--- a/mercurial/hg.py Mon Jun 15 02:45:38 2009 -0500
+++ b/mercurial/hg.py Mon Jun 15 02:45:38 2009 -0500
@@ -297,6 +297,8 @@
fp.write("default = %s\n" % abspath)
fp.close()
+ dest_repo.ui.setconfig('paths', 'default', abspath)
+
if update:
dest_repo.ui.status(_("updating working directory\n"))
if update is not True:
--- a/mercurial/merge.py Mon Jun 15 02:45:38 2009 -0500
+++ b/mercurial/merge.py Mon Jun 15 02:45:38 2009 -0500
@@ -7,7 +7,7 @@
from node import nullid, nullrev, hex, bin
from i18n import _
-import util, filemerge, copies
+import util, filemerge, copies, subrepo
import errno, os, shutil
class mergestate(object):
@@ -241,12 +241,15 @@
ms.reset(wctx.parents()[0].node())
moves = []
action.sort(key=actionkey)
+ substate = wctx.substate # prime
# prescan for merges
for a in action:
f, m = a[:2]
if m == 'm': # merge
f2, fd, flags, move = a[2:]
+ if f == '.hgsubstate': # merged internally
+ continue
repo.ui.debug(_("preserving %s for resolve of %s\n") % (f, fd))
fcl = wctx[f]
fco = mctx[f2]
@@ -270,6 +273,8 @@
if m == "r": # remove
repo.ui.note(_("removing %s\n") % f)
audit_path(f)
+ if f == '.hgsubstate': # subrepo states need updating
+ subrepo.submerge(repo, wctx, mctx, wctx)
try:
util.unlink(repo.wjoin(f))
except OSError, inst:
@@ -278,6 +283,9 @@
(f, inst.strerror))
removed += 1
elif m == "m": # merge
+ if f == '.hgsubstate': # subrepo states need updating
+ subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx))
+ continue
f2, fd, flags, move = a[2:]
r = ms.resolve(fd, wctx, mctx)
if r > 0:
@@ -297,6 +305,8 @@
t = mctx.filectx(f).data()
repo.wwrite(f, t, flags)
updated += 1
+ if f == '.hgsubstate': # subrepo states need updating
+ subrepo.submerge(repo, wctx, mctx, wctx)
elif m == "d": # directory rename
f2, fd, flags = a[2:]
if f:
--- a/mercurial/subrepo.py Mon Jun 15 02:45:38 2009 -0500
+++ b/mercurial/subrepo.py Mon Jun 15 02:45:38 2009 -0500
@@ -6,8 +6,9 @@
# GNU General Public License version 2, incorporated herein by reference.
import errno, os
+from i18n import _
import config, util, node, error
-localrepo = None
+localrepo = hg = None
nullstate = ('', '')
@@ -43,14 +44,81 @@
''.join(['%s %s\n' % (state[s][1], s)
for s in sorted(state)]), '')
+def submerge(repo, wctx, mctx, actx):
+ if mctx == actx: # backwards?
+ actx = wctx.p1()
+ s1 = wctx.substate
+ s2 = mctx.substate
+ sa = actx.substate
+ sm = {}
+
+ for s, l in s1.items():
+ a = sa.get(s, nullstate)
+ if s in s2:
+ r = s2[s]
+ if l == r or r == a: # no change or local is newer
+ sm[s] = l
+ continue
+ elif l == a: # other side changed
+ wctx.sub(s).get(r)
+ sm[s] = r
+ elif l[0] != r[0]: # sources differ
+ if repo.ui.prompt(
+ _(' subrepository sources for %s differ\n'
+ 'use (l)ocal source (%s) or (r)emote source (%s)?'
+ % (s, l[0], r[0]),
+ (_('&Local'), _('&Remote')), _('l'))) == _('r'):
+ wctx.sub(s).get(r)
+ sm[s] = r
+ elif l[1] == a[1]: # local side is unchanged
+ wctx.sub(s).get(r)
+ sm[s] = r
+ else:
+ wctx.sub(s).merge(r)
+ sm[s] = l
+ elif l == a: # remote removed, local unchanged
+ wctx.sub(s).remove()
+ else:
+ if repo.ui.prompt(
+ _(' local changed subrepository %s which remote removed\n'
+ 'use (c)hanged version or (d)elete?' % s,
+ (_('&Changed'), _('&Delete')), _('c'))) == _('d'):
+ wctx.sub(s).remove()
+
+ for s, r in s2.items():
+ if s in s1:
+ continue
+ elif s not in sa:
+ wctx.sub(s).get(r)
+ sm[s] = r
+ elif r != sa[s]:
+ if repo.ui.prompt(
+ _(' remote changed subrepository %s which local removed\n'
+ 'use (c)hanged version or (d)elete?' % s,
+ (_('&Changed'), _('&Delete')), _('c'))) == _('c'):
+ wctx.sub(s).get(r)
+ sm[s] = r
+
+ # record merged .hgsubstate
+ writestate(repo, sm)
+
+def _abssource(repo):
+ if hasattr(repo, '_subparent'):
+ source = repo._subsource
+ if source.startswith('/') or '://' in source:
+ return source
+ return os.path.join(_abssource(repo._subparent), repo._subsource)
+ return repo.ui.config('paths', 'default', repo.root)
+
def subrepo(ctx, path):
# subrepo inherently violates our import layering rules
# because it wants to make repo objects from deep inside the stack
# so we manually delay the circular imports to not break
# scripts that don't use our demand-loading
- global localrepo
- import localrepo as l
+ global localrepo, hg
+ import localrepo as l, hg as h
localrepo = l
+ hg = h
state = ctx.substate.get(path, nullstate)
if state[0].startswith('['): # future expansion
@@ -64,7 +132,13 @@
self._state = state
r = ctx._repo
root = r.wjoin(path)
- self._repo = localrepo.localrepository(r.ui, root)
+ if os.path.exists(os.path.join(root, '.hg')):
+ self._repo = localrepo.localrepository(r.ui, root)
+ else:
+ util.makedirs(root)
+ self._repo = localrepo.localrepository(r.ui, root, create=True)
+ self._repo._subparent = r
+ self._repo._subsource = state[0]
def dirty(self):
r = self._state[1]
@@ -80,3 +154,25 @@
if not n:
return self._repo['.'].hex() # different version checked out
return node.hex(n)
+
+ def remove(self):
+ # we can't fully delete the repository as it may contain
+ # local-only history
+ self._repo.ui.note(_('removing subrepo %s\n') % self._path)
+ hg.clean(self._repo, node.nullid, False)
+
+ def get(self, state):
+ source, revision = state
+ try:
+ self._repo.lookup(revision)
+ except error.RepoError:
+ self._repo._subsource = source
+ self._repo.ui.status(_('pulling subrepo %s\n') % self._path)
+ srcurl = _abssource(self._repo)
+ other = hg.repository(self._repo.ui, srcurl)
+ self._repo.pull(other)
+
+ hg.clean(self._repo, revision, False)
+
+ def merge(self, state):
+ hg.merge(self._repo, state[1], remind=False)