##// END OF EJS Templates
subrepo: abort instead of pushing/pulling to the repo itself...
Mads Kiilerich -
r12753:ef5eaf53 default
parent child Browse files
Show More
@@ -1,572 +1,580 b''
1 # subrepo.py - sub-repository handling for Mercurial
1 # subrepo.py - sub-repository handling for Mercurial
2 #
2 #
3 # Copyright 2009-2010 Matt Mackall <mpm@selenic.com>
3 # Copyright 2009-2010 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 import errno, os, re, xml.dom.minidom, shutil, urlparse, posixpath
8 import errno, os, re, xml.dom.minidom, shutil, urlparse, posixpath
9 from i18n import _
9 from i18n import _
10 import config, util, node, error, cmdutil
10 import config, util, node, error, cmdutil
11 hg = None
11 hg = None
12
12
13 nullstate = ('', '', 'empty')
13 nullstate = ('', '', 'empty')
14
14
15 def state(ctx, ui):
15 def state(ctx, ui):
16 """return a state dict, mapping subrepo paths configured in .hgsub
16 """return a state dict, mapping subrepo paths configured in .hgsub
17 to tuple: (source from .hgsub, revision from .hgsubstate, kind
17 to tuple: (source from .hgsub, revision from .hgsubstate, kind
18 (key in types dict))
18 (key in types dict))
19 """
19 """
20 p = config.config()
20 p = config.config()
21 def read(f, sections=None, remap=None):
21 def read(f, sections=None, remap=None):
22 if f in ctx:
22 if f in ctx:
23 p.parse(f, ctx[f].data(), sections, remap, read)
23 p.parse(f, ctx[f].data(), sections, remap, read)
24 else:
24 else:
25 raise util.Abort(_("subrepo spec file %s not found") % f)
25 raise util.Abort(_("subrepo spec file %s not found") % f)
26
26
27 if '.hgsub' in ctx:
27 if '.hgsub' in ctx:
28 read('.hgsub')
28 read('.hgsub')
29
29
30 for path, src in ui.configitems('subpaths'):
30 for path, src in ui.configitems('subpaths'):
31 p.set('subpaths', path, src, ui.configsource('subpaths', path))
31 p.set('subpaths', path, src, ui.configsource('subpaths', path))
32
32
33 rev = {}
33 rev = {}
34 if '.hgsubstate' in ctx:
34 if '.hgsubstate' in ctx:
35 try:
35 try:
36 for l in ctx['.hgsubstate'].data().splitlines():
36 for l in ctx['.hgsubstate'].data().splitlines():
37 revision, path = l.split(" ", 1)
37 revision, path = l.split(" ", 1)
38 rev[path] = revision
38 rev[path] = revision
39 except IOError, err:
39 except IOError, err:
40 if err.errno != errno.ENOENT:
40 if err.errno != errno.ENOENT:
41 raise
41 raise
42
42
43 state = {}
43 state = {}
44 for path, src in p[''].items():
44 for path, src in p[''].items():
45 kind = 'hg'
45 kind = 'hg'
46 if src.startswith('['):
46 if src.startswith('['):
47 if ']' not in src:
47 if ']' not in src:
48 raise util.Abort(_('missing ] in subrepo source'))
48 raise util.Abort(_('missing ] in subrepo source'))
49 kind, src = src.split(']', 1)
49 kind, src = src.split(']', 1)
50 kind = kind[1:]
50 kind = kind[1:]
51
51
52 for pattern, repl in p.items('subpaths'):
52 for pattern, repl in p.items('subpaths'):
53 # Turn r'C:\foo\bar' into r'C:\\foo\\bar' since re.sub
53 # Turn r'C:\foo\bar' into r'C:\\foo\\bar' since re.sub
54 # does a string decode.
54 # does a string decode.
55 repl = repl.encode('string-escape')
55 repl = repl.encode('string-escape')
56 # However, we still want to allow back references to go
56 # However, we still want to allow back references to go
57 # through unharmed, so we turn r'\\1' into r'\1'. Again,
57 # through unharmed, so we turn r'\\1' into r'\1'. Again,
58 # extra escapes are needed because re.sub string decodes.
58 # extra escapes are needed because re.sub string decodes.
59 repl = re.sub(r'\\\\([0-9]+)', r'\\\1', repl)
59 repl = re.sub(r'\\\\([0-9]+)', r'\\\1', repl)
60 try:
60 try:
61 src = re.sub(pattern, repl, src, 1)
61 src = re.sub(pattern, repl, src, 1)
62 except re.error, e:
62 except re.error, e:
63 raise util.Abort(_("bad subrepository pattern in %s: %s")
63 raise util.Abort(_("bad subrepository pattern in %s: %s")
64 % (p.source('subpaths', pattern), e))
64 % (p.source('subpaths', pattern), e))
65
65
66 state[path] = (src.strip(), rev.get(path, ''), kind)
66 state[path] = (src.strip(), rev.get(path, ''), kind)
67
67
68 return state
68 return state
69
69
70 def writestate(repo, state):
70 def writestate(repo, state):
71 """rewrite .hgsubstate in (outer) repo with these subrepo states"""
71 """rewrite .hgsubstate in (outer) repo with these subrepo states"""
72 repo.wwrite('.hgsubstate',
72 repo.wwrite('.hgsubstate',
73 ''.join(['%s %s\n' % (state[s][1], s)
73 ''.join(['%s %s\n' % (state[s][1], s)
74 for s in sorted(state)]), '')
74 for s in sorted(state)]), '')
75
75
76 def submerge(repo, wctx, mctx, actx):
76 def submerge(repo, wctx, mctx, actx):
77 """delegated from merge.applyupdates: merging of .hgsubstate file
77 """delegated from merge.applyupdates: merging of .hgsubstate file
78 in working context, merging context and ancestor context"""
78 in working context, merging context and ancestor context"""
79 if mctx == actx: # backwards?
79 if mctx == actx: # backwards?
80 actx = wctx.p1()
80 actx = wctx.p1()
81 s1 = wctx.substate
81 s1 = wctx.substate
82 s2 = mctx.substate
82 s2 = mctx.substate
83 sa = actx.substate
83 sa = actx.substate
84 sm = {}
84 sm = {}
85
85
86 repo.ui.debug("subrepo merge %s %s %s\n" % (wctx, mctx, actx))
86 repo.ui.debug("subrepo merge %s %s %s\n" % (wctx, mctx, actx))
87
87
88 def debug(s, msg, r=""):
88 def debug(s, msg, r=""):
89 if r:
89 if r:
90 r = "%s:%s:%s" % r
90 r = "%s:%s:%s" % r
91 repo.ui.debug(" subrepo %s: %s %s\n" % (s, msg, r))
91 repo.ui.debug(" subrepo %s: %s %s\n" % (s, msg, r))
92
92
93 for s, l in s1.items():
93 for s, l in s1.items():
94 a = sa.get(s, nullstate)
94 a = sa.get(s, nullstate)
95 ld = l # local state with possible dirty flag for compares
95 ld = l # local state with possible dirty flag for compares
96 if wctx.sub(s).dirty():
96 if wctx.sub(s).dirty():
97 ld = (l[0], l[1] + "+")
97 ld = (l[0], l[1] + "+")
98 if wctx == actx: # overwrite
98 if wctx == actx: # overwrite
99 a = ld
99 a = ld
100
100
101 if s in s2:
101 if s in s2:
102 r = s2[s]
102 r = s2[s]
103 if ld == r or r == a: # no change or local is newer
103 if ld == r or r == a: # no change or local is newer
104 sm[s] = l
104 sm[s] = l
105 continue
105 continue
106 elif ld == a: # other side changed
106 elif ld == a: # other side changed
107 debug(s, "other changed, get", r)
107 debug(s, "other changed, get", r)
108 wctx.sub(s).get(r)
108 wctx.sub(s).get(r)
109 sm[s] = r
109 sm[s] = r
110 elif ld[0] != r[0]: # sources differ
110 elif ld[0] != r[0]: # sources differ
111 if repo.ui.promptchoice(
111 if repo.ui.promptchoice(
112 _(' subrepository sources for %s differ\n'
112 _(' subrepository sources for %s differ\n'
113 'use (l)ocal source (%s) or (r)emote source (%s)?')
113 'use (l)ocal source (%s) or (r)emote source (%s)?')
114 % (s, l[0], r[0]),
114 % (s, l[0], r[0]),
115 (_('&Local'), _('&Remote')), 0):
115 (_('&Local'), _('&Remote')), 0):
116 debug(s, "prompt changed, get", r)
116 debug(s, "prompt changed, get", r)
117 wctx.sub(s).get(r)
117 wctx.sub(s).get(r)
118 sm[s] = r
118 sm[s] = r
119 elif ld[1] == a[1]: # local side is unchanged
119 elif ld[1] == a[1]: # local side is unchanged
120 debug(s, "other side changed, get", r)
120 debug(s, "other side changed, get", r)
121 wctx.sub(s).get(r)
121 wctx.sub(s).get(r)
122 sm[s] = r
122 sm[s] = r
123 else:
123 else:
124 debug(s, "both sides changed, merge with", r)
124 debug(s, "both sides changed, merge with", r)
125 wctx.sub(s).merge(r)
125 wctx.sub(s).merge(r)
126 sm[s] = l
126 sm[s] = l
127 elif ld == a: # remote removed, local unchanged
127 elif ld == a: # remote removed, local unchanged
128 debug(s, "remote removed, remove")
128 debug(s, "remote removed, remove")
129 wctx.sub(s).remove()
129 wctx.sub(s).remove()
130 else:
130 else:
131 if repo.ui.promptchoice(
131 if repo.ui.promptchoice(
132 _(' local changed subrepository %s which remote removed\n'
132 _(' local changed subrepository %s which remote removed\n'
133 'use (c)hanged version or (d)elete?') % s,
133 'use (c)hanged version or (d)elete?') % s,
134 (_('&Changed'), _('&Delete')), 0):
134 (_('&Changed'), _('&Delete')), 0):
135 debug(s, "prompt remove")
135 debug(s, "prompt remove")
136 wctx.sub(s).remove()
136 wctx.sub(s).remove()
137
137
138 for s, r in s2.items():
138 for s, r in s2.items():
139 if s in s1:
139 if s in s1:
140 continue
140 continue
141 elif s not in sa:
141 elif s not in sa:
142 debug(s, "remote added, get", r)
142 debug(s, "remote added, get", r)
143 mctx.sub(s).get(r)
143 mctx.sub(s).get(r)
144 sm[s] = r
144 sm[s] = r
145 elif r != sa[s]:
145 elif r != sa[s]:
146 if repo.ui.promptchoice(
146 if repo.ui.promptchoice(
147 _(' remote changed subrepository %s which local removed\n'
147 _(' remote changed subrepository %s which local removed\n'
148 'use (c)hanged version or (d)elete?') % s,
148 'use (c)hanged version or (d)elete?') % s,
149 (_('&Changed'), _('&Delete')), 0) == 0:
149 (_('&Changed'), _('&Delete')), 0) == 0:
150 debug(s, "prompt recreate", r)
150 debug(s, "prompt recreate", r)
151 wctx.sub(s).get(r)
151 wctx.sub(s).get(r)
152 sm[s] = r
152 sm[s] = r
153
153
154 # record merged .hgsubstate
154 # record merged .hgsubstate
155 writestate(repo, sm)
155 writestate(repo, sm)
156
156
157 def reporelpath(repo):
157 def reporelpath(repo):
158 """return path to this (sub)repo as seen from outermost repo"""
158 """return path to this (sub)repo as seen from outermost repo"""
159 parent = repo
159 parent = repo
160 while hasattr(parent, '_subparent'):
160 while hasattr(parent, '_subparent'):
161 parent = parent._subparent
161 parent = parent._subparent
162 return repo.root[len(parent.root)+1:]
162 return repo.root[len(parent.root)+1:]
163
163
164 def subrelpath(sub):
164 def subrelpath(sub):
165 """return path to this subrepo as seen from outermost repo"""
165 """return path to this subrepo as seen from outermost repo"""
166 if not hasattr(sub, '_repo'):
166 if not hasattr(sub, '_repo'):
167 return sub._path
167 return sub._path
168 return reporelpath(sub._repo)
168 return reporelpath(sub._repo)
169
169
170 def _abssource(repo, push=False):
170 def _abssource(repo, push=False, abort=True):
171 """return pull/push path of repo - either based on parent repo
171 """return pull/push path of repo - either based on parent repo .hgsub info
172 .hgsub info or on the subrepos own config"""
172 or on the top repo config. Abort or return None if no source found."""
173 if hasattr(repo, '_subparent'):
173 if hasattr(repo, '_subparent'):
174 source = repo._subsource
174 source = repo._subsource
175 if source.startswith('/') or '://' in source:
175 if source.startswith('/') or '://' in source:
176 return source
176 return source
177 parent = _abssource(repo._subparent, push)
177 parent = _abssource(repo._subparent, push, abort=False)
178 if '://' in parent:
178 if parent:
179 if parent[-1] == '/':
179 if '://' in parent:
180 parent = parent[:-1]
180 if parent[-1] == '/':
181 r = urlparse.urlparse(parent + '/' + source)
181 parent = parent[:-1]
182 r = urlparse.urlunparse((r[0], r[1],
182 r = urlparse.urlparse(parent + '/' + source)
183 posixpath.normpath(r[2]),
183 r = urlparse.urlunparse((r[0], r[1],
184 r[3], r[4], r[5]))
184 posixpath.normpath(r[2]),
185 return r
185 r[3], r[4], r[5]))
186 return posixpath.normpath(os.path.join(parent, repo._subsource))
186 return r
187 if push and repo.ui.config('paths', 'default-push'):
187 else: # plain file system path
188 return repo.ui.config('paths', 'default-push', repo.root)
188 return posixpath.normpath(os.path.join(parent, repo._subsource))
189 return repo.ui.config('paths', 'default', repo.root)
189 else: # recursion reached top repo
190 if push and repo.ui.config('paths', 'default-push'):
191 return repo.ui.config('paths', 'default-push')
192 if repo.ui.config('paths', 'default'):
193 return repo.ui.config('paths', 'default')
194 if abort:
195 raise util.Abort(_("default path for subrepository %s not found") %
196 reporelpath(repo))
190
197
191 def itersubrepos(ctx1, ctx2):
198 def itersubrepos(ctx1, ctx2):
192 """find subrepos in ctx1 or ctx2"""
199 """find subrepos in ctx1 or ctx2"""
193 # Create a (subpath, ctx) mapping where we prefer subpaths from
200 # Create a (subpath, ctx) mapping where we prefer subpaths from
194 # ctx1. The subpaths from ctx2 are important when the .hgsub file
201 # ctx1. The subpaths from ctx2 are important when the .hgsub file
195 # has been modified (in ctx2) but not yet committed (in ctx1).
202 # has been modified (in ctx2) but not yet committed (in ctx1).
196 subpaths = dict.fromkeys(ctx2.substate, ctx2)
203 subpaths = dict.fromkeys(ctx2.substate, ctx2)
197 subpaths.update(dict.fromkeys(ctx1.substate, ctx1))
204 subpaths.update(dict.fromkeys(ctx1.substate, ctx1))
198 for subpath, ctx in sorted(subpaths.iteritems()):
205 for subpath, ctx in sorted(subpaths.iteritems()):
199 yield subpath, ctx.sub(subpath)
206 yield subpath, ctx.sub(subpath)
200
207
201 def subrepo(ctx, path):
208 def subrepo(ctx, path):
202 """return instance of the right subrepo class for subrepo in path"""
209 """return instance of the right subrepo class for subrepo in path"""
203 # subrepo inherently violates our import layering rules
210 # subrepo inherently violates our import layering rules
204 # because it wants to make repo objects from deep inside the stack
211 # because it wants to make repo objects from deep inside the stack
205 # so we manually delay the circular imports to not break
212 # so we manually delay the circular imports to not break
206 # scripts that don't use our demand-loading
213 # scripts that don't use our demand-loading
207 global hg
214 global hg
208 import hg as h
215 import hg as h
209 hg = h
216 hg = h
210
217
211 util.path_auditor(ctx._repo.root)(path)
218 util.path_auditor(ctx._repo.root)(path)
212 state = ctx.substate.get(path, nullstate)
219 state = ctx.substate.get(path, nullstate)
213 if state[2] not in types:
220 if state[2] not in types:
214 raise util.Abort(_('unknown subrepo type %s') % state[2])
221 raise util.Abort(_('unknown subrepo type %s') % state[2])
215 return types[state[2]](ctx, path, state[:2])
222 return types[state[2]](ctx, path, state[:2])
216
223
217 # subrepo classes need to implement the following abstract class:
224 # subrepo classes need to implement the following abstract class:
218
225
219 class abstractsubrepo(object):
226 class abstractsubrepo(object):
220
227
221 def dirty(self):
228 def dirty(self):
222 """returns true if the dirstate of the subrepo does not match
229 """returns true if the dirstate of the subrepo does not match
223 current stored state
230 current stored state
224 """
231 """
225 raise NotImplementedError
232 raise NotImplementedError
226
233
227 def checknested(self, path):
234 def checknested(self, path):
228 """check if path is a subrepository within this repository"""
235 """check if path is a subrepository within this repository"""
229 return False
236 return False
230
237
231 def commit(self, text, user, date):
238 def commit(self, text, user, date):
232 """commit the current changes to the subrepo with the given
239 """commit the current changes to the subrepo with the given
233 log message. Use given user and date if possible. Return the
240 log message. Use given user and date if possible. Return the
234 new state of the subrepo.
241 new state of the subrepo.
235 """
242 """
236 raise NotImplementedError
243 raise NotImplementedError
237
244
238 def remove(self):
245 def remove(self):
239 """remove the subrepo
246 """remove the subrepo
240
247
241 (should verify the dirstate is not dirty first)
248 (should verify the dirstate is not dirty first)
242 """
249 """
243 raise NotImplementedError
250 raise NotImplementedError
244
251
245 def get(self, state):
252 def get(self, state):
246 """run whatever commands are needed to put the subrepo into
253 """run whatever commands are needed to put the subrepo into
247 this state
254 this state
248 """
255 """
249 raise NotImplementedError
256 raise NotImplementedError
250
257
251 def merge(self, state):
258 def merge(self, state):
252 """merge currently-saved state with the new state."""
259 """merge currently-saved state with the new state."""
253 raise NotImplementedError
260 raise NotImplementedError
254
261
255 def push(self, force):
262 def push(self, force):
256 """perform whatever action is analogous to 'hg push'
263 """perform whatever action is analogous to 'hg push'
257
264
258 This may be a no-op on some systems.
265 This may be a no-op on some systems.
259 """
266 """
260 raise NotImplementedError
267 raise NotImplementedError
261
268
262 def add(self, ui, match, dryrun, prefix):
269 def add(self, ui, match, dryrun, prefix):
263 return []
270 return []
264
271
265 def status(self, rev2, **opts):
272 def status(self, rev2, **opts):
266 return [], [], [], [], [], [], []
273 return [], [], [], [], [], [], []
267
274
268 def diff(self, diffopts, node2, match, prefix, **opts):
275 def diff(self, diffopts, node2, match, prefix, **opts):
269 pass
276 pass
270
277
271 def outgoing(self, ui, dest, opts):
278 def outgoing(self, ui, dest, opts):
272 return 1
279 return 1
273
280
274 def incoming(self, ui, source, opts):
281 def incoming(self, ui, source, opts):
275 return 1
282 return 1
276
283
277 def files(self):
284 def files(self):
278 """return filename iterator"""
285 """return filename iterator"""
279 raise NotImplementedError
286 raise NotImplementedError
280
287
281 def filedata(self, name):
288 def filedata(self, name):
282 """return file data"""
289 """return file data"""
283 raise NotImplementedError
290 raise NotImplementedError
284
291
285 def fileflags(self, name):
292 def fileflags(self, name):
286 """return file flags"""
293 """return file flags"""
287 return ''
294 return ''
288
295
289 def archive(self, archiver, prefix):
296 def archive(self, archiver, prefix):
290 for name in self.files():
297 for name in self.files():
291 flags = self.fileflags(name)
298 flags = self.fileflags(name)
292 mode = 'x' in flags and 0755 or 0644
299 mode = 'x' in flags and 0755 or 0644
293 symlink = 'l' in flags
300 symlink = 'l' in flags
294 archiver.addfile(os.path.join(prefix, self._path, name),
301 archiver.addfile(os.path.join(prefix, self._path, name),
295 mode, symlink, self.filedata(name))
302 mode, symlink, self.filedata(name))
296
303
297
304
298 class hgsubrepo(abstractsubrepo):
305 class hgsubrepo(abstractsubrepo):
299 def __init__(self, ctx, path, state):
306 def __init__(self, ctx, path, state):
300 self._path = path
307 self._path = path
301 self._state = state
308 self._state = state
302 r = ctx._repo
309 r = ctx._repo
303 root = r.wjoin(path)
310 root = r.wjoin(path)
304 create = False
311 create = False
305 if not os.path.exists(os.path.join(root, '.hg')):
312 if not os.path.exists(os.path.join(root, '.hg')):
306 create = True
313 create = True
307 util.makedirs(root)
314 util.makedirs(root)
308 self._repo = hg.repository(r.ui, root, create=create)
315 self._repo = hg.repository(r.ui, root, create=create)
309 self._repo._subparent = r
316 self._repo._subparent = r
310 self._repo._subsource = state[0]
317 self._repo._subsource = state[0]
311
318
312 if create:
319 if create:
313 fp = self._repo.opener("hgrc", "w", text=True)
320 fp = self._repo.opener("hgrc", "w", text=True)
314 fp.write('[paths]\n')
321 fp.write('[paths]\n')
315
322
316 def addpathconfig(key, value):
323 def addpathconfig(key, value):
317 fp.write('%s = %s\n' % (key, value))
324 if value:
318 self._repo.ui.setconfig('paths', key, value)
325 fp.write('%s = %s\n' % (key, value))
326 self._repo.ui.setconfig('paths', key, value)
319
327
320 defpath = _abssource(self._repo)
328 defpath = _abssource(self._repo, abort=False)
321 defpushpath = _abssource(self._repo, True)
329 defpushpath = _abssource(self._repo, True, abort=False)
322 addpathconfig('default', defpath)
330 addpathconfig('default', defpath)
323 if defpath != defpushpath:
331 if defpath != defpushpath:
324 addpathconfig('default-push', defpushpath)
332 addpathconfig('default-push', defpushpath)
325 fp.close()
333 fp.close()
326
334
327 def add(self, ui, match, dryrun, prefix):
335 def add(self, ui, match, dryrun, prefix):
328 return cmdutil.add(ui, self._repo, match, dryrun, True,
336 return cmdutil.add(ui, self._repo, match, dryrun, True,
329 os.path.join(prefix, self._path))
337 os.path.join(prefix, self._path))
330
338
331 def status(self, rev2, **opts):
339 def status(self, rev2, **opts):
332 try:
340 try:
333 rev1 = self._state[1]
341 rev1 = self._state[1]
334 ctx1 = self._repo[rev1]
342 ctx1 = self._repo[rev1]
335 ctx2 = self._repo[rev2]
343 ctx2 = self._repo[rev2]
336 return self._repo.status(ctx1, ctx2, **opts)
344 return self._repo.status(ctx1, ctx2, **opts)
337 except error.RepoLookupError, inst:
345 except error.RepoLookupError, inst:
338 self._repo.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
346 self._repo.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
339 % (inst, subrelpath(self)))
347 % (inst, subrelpath(self)))
340 return [], [], [], [], [], [], []
348 return [], [], [], [], [], [], []
341
349
342 def diff(self, diffopts, node2, match, prefix, **opts):
350 def diff(self, diffopts, node2, match, prefix, **opts):
343 try:
351 try:
344 node1 = node.bin(self._state[1])
352 node1 = node.bin(self._state[1])
345 # We currently expect node2 to come from substate and be
353 # We currently expect node2 to come from substate and be
346 # in hex format
354 # in hex format
347 if node2 is not None:
355 if node2 is not None:
348 node2 = node.bin(node2)
356 node2 = node.bin(node2)
349 cmdutil.diffordiffstat(self._repo.ui, self._repo, diffopts,
357 cmdutil.diffordiffstat(self._repo.ui, self._repo, diffopts,
350 node1, node2, match,
358 node1, node2, match,
351 prefix=os.path.join(prefix, self._path),
359 prefix=os.path.join(prefix, self._path),
352 listsubrepos=True, **opts)
360 listsubrepos=True, **opts)
353 except error.RepoLookupError, inst:
361 except error.RepoLookupError, inst:
354 self._repo.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
362 self._repo.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
355 % (inst, subrelpath(self)))
363 % (inst, subrelpath(self)))
356
364
357 def archive(self, archiver, prefix):
365 def archive(self, archiver, prefix):
358 abstractsubrepo.archive(self, archiver, prefix)
366 abstractsubrepo.archive(self, archiver, prefix)
359
367
360 rev = self._state[1]
368 rev = self._state[1]
361 ctx = self._repo[rev]
369 ctx = self._repo[rev]
362 for subpath in ctx.substate:
370 for subpath in ctx.substate:
363 s = subrepo(ctx, subpath)
371 s = subrepo(ctx, subpath)
364 s.archive(archiver, os.path.join(prefix, self._path))
372 s.archive(archiver, os.path.join(prefix, self._path))
365
373
366 def dirty(self):
374 def dirty(self):
367 r = self._state[1]
375 r = self._state[1]
368 if r == '':
376 if r == '':
369 return True
377 return True
370 w = self._repo[None]
378 w = self._repo[None]
371 if w.p1() != self._repo[r]: # version checked out change
379 if w.p1() != self._repo[r]: # version checked out change
372 return True
380 return True
373 return w.dirty() # working directory changed
381 return w.dirty() # working directory changed
374
382
375 def checknested(self, path):
383 def checknested(self, path):
376 return self._repo._checknested(self._repo.wjoin(path))
384 return self._repo._checknested(self._repo.wjoin(path))
377
385
378 def commit(self, text, user, date):
386 def commit(self, text, user, date):
379 self._repo.ui.debug("committing subrepo %s\n" % subrelpath(self))
387 self._repo.ui.debug("committing subrepo %s\n" % subrelpath(self))
380 n = self._repo.commit(text, user, date)
388 n = self._repo.commit(text, user, date)
381 if not n:
389 if not n:
382 return self._repo['.'].hex() # different version checked out
390 return self._repo['.'].hex() # different version checked out
383 return node.hex(n)
391 return node.hex(n)
384
392
385 def remove(self):
393 def remove(self):
386 # we can't fully delete the repository as it may contain
394 # we can't fully delete the repository as it may contain
387 # local-only history
395 # local-only history
388 self._repo.ui.note(_('removing subrepo %s\n') % subrelpath(self))
396 self._repo.ui.note(_('removing subrepo %s\n') % subrelpath(self))
389 hg.clean(self._repo, node.nullid, False)
397 hg.clean(self._repo, node.nullid, False)
390
398
391 def _get(self, state):
399 def _get(self, state):
392 source, revision, kind = state
400 source, revision, kind = state
393 try:
401 try:
394 self._repo.lookup(revision)
402 self._repo.lookup(revision)
395 except error.RepoError:
403 except error.RepoError:
396 self._repo._subsource = source
404 self._repo._subsource = source
397 srcurl = _abssource(self._repo)
405 srcurl = _abssource(self._repo)
398 self._repo.ui.status(_('pulling subrepo %s from %s\n')
406 self._repo.ui.status(_('pulling subrepo %s from %s\n')
399 % (subrelpath(self), srcurl))
407 % (subrelpath(self), srcurl))
400 other = hg.repository(self._repo.ui, srcurl)
408 other = hg.repository(self._repo.ui, srcurl)
401 self._repo.pull(other)
409 self._repo.pull(other)
402
410
403 def get(self, state):
411 def get(self, state):
404 self._get(state)
412 self._get(state)
405 source, revision, kind = state
413 source, revision, kind = state
406 self._repo.ui.debug("getting subrepo %s\n" % self._path)
414 self._repo.ui.debug("getting subrepo %s\n" % self._path)
407 hg.clean(self._repo, revision, False)
415 hg.clean(self._repo, revision, False)
408
416
409 def merge(self, state):
417 def merge(self, state):
410 self._get(state)
418 self._get(state)
411 cur = self._repo['.']
419 cur = self._repo['.']
412 dst = self._repo[state[1]]
420 dst = self._repo[state[1]]
413 anc = dst.ancestor(cur)
421 anc = dst.ancestor(cur)
414 if anc == cur:
422 if anc == cur:
415 self._repo.ui.debug("updating subrepo %s\n" % subrelpath(self))
423 self._repo.ui.debug("updating subrepo %s\n" % subrelpath(self))
416 hg.update(self._repo, state[1])
424 hg.update(self._repo, state[1])
417 elif anc == dst:
425 elif anc == dst:
418 self._repo.ui.debug("skipping subrepo %s\n" % subrelpath(self))
426 self._repo.ui.debug("skipping subrepo %s\n" % subrelpath(self))
419 else:
427 else:
420 self._repo.ui.debug("merging subrepo %s\n" % subrelpath(self))
428 self._repo.ui.debug("merging subrepo %s\n" % subrelpath(self))
421 hg.merge(self._repo, state[1], remind=False)
429 hg.merge(self._repo, state[1], remind=False)
422
430
423 def push(self, force):
431 def push(self, force):
424 # push subrepos depth-first for coherent ordering
432 # push subrepos depth-first for coherent ordering
425 c = self._repo['']
433 c = self._repo['']
426 subs = c.substate # only repos that are committed
434 subs = c.substate # only repos that are committed
427 for s in sorted(subs):
435 for s in sorted(subs):
428 if not c.sub(s).push(force):
436 if not c.sub(s).push(force):
429 return False
437 return False
430
438
431 dsturl = _abssource(self._repo, True)
439 dsturl = _abssource(self._repo, True)
432 self._repo.ui.status(_('pushing subrepo %s to %s\n') %
440 self._repo.ui.status(_('pushing subrepo %s to %s\n') %
433 (subrelpath(self), dsturl))
441 (subrelpath(self), dsturl))
434 other = hg.repository(self._repo.ui, dsturl)
442 other = hg.repository(self._repo.ui, dsturl)
435 return self._repo.push(other, force)
443 return self._repo.push(other, force)
436
444
437 def outgoing(self, ui, dest, opts):
445 def outgoing(self, ui, dest, opts):
438 return hg.outgoing(ui, self._repo, _abssource(self._repo, True), opts)
446 return hg.outgoing(ui, self._repo, _abssource(self._repo, True), opts)
439
447
440 def incoming(self, ui, source, opts):
448 def incoming(self, ui, source, opts):
441 return hg.incoming(ui, self._repo, _abssource(self._repo, False), opts)
449 return hg.incoming(ui, self._repo, _abssource(self._repo, False), opts)
442
450
443 def files(self):
451 def files(self):
444 rev = self._state[1]
452 rev = self._state[1]
445 ctx = self._repo[rev]
453 ctx = self._repo[rev]
446 return ctx.manifest()
454 return ctx.manifest()
447
455
448 def filedata(self, name):
456 def filedata(self, name):
449 rev = self._state[1]
457 rev = self._state[1]
450 return self._repo[rev][name].data()
458 return self._repo[rev][name].data()
451
459
452 def fileflags(self, name):
460 def fileflags(self, name):
453 rev = self._state[1]
461 rev = self._state[1]
454 ctx = self._repo[rev]
462 ctx = self._repo[rev]
455 return ctx.flags(name)
463 return ctx.flags(name)
456
464
457
465
458 class svnsubrepo(abstractsubrepo):
466 class svnsubrepo(abstractsubrepo):
459 def __init__(self, ctx, path, state):
467 def __init__(self, ctx, path, state):
460 self._path = path
468 self._path = path
461 self._state = state
469 self._state = state
462 self._ctx = ctx
470 self._ctx = ctx
463 self._ui = ctx._repo.ui
471 self._ui = ctx._repo.ui
464
472
465 def _svncommand(self, commands, filename=''):
473 def _svncommand(self, commands, filename=''):
466 path = os.path.join(self._ctx._repo.origroot, self._path, filename)
474 path = os.path.join(self._ctx._repo.origroot, self._path, filename)
467 cmd = ['svn'] + commands + [path]
475 cmd = ['svn'] + commands + [path]
468 cmd = [util.shellquote(arg) for arg in cmd]
476 cmd = [util.shellquote(arg) for arg in cmd]
469 cmd = util.quotecommand(' '.join(cmd))
477 cmd = util.quotecommand(' '.join(cmd))
470 env = dict(os.environ)
478 env = dict(os.environ)
471 # Avoid localized output, preserve current locale for everything else.
479 # Avoid localized output, preserve current locale for everything else.
472 env['LC_MESSAGES'] = 'C'
480 env['LC_MESSAGES'] = 'C'
473 write, read, err = util.popen3(cmd, env=env, newlines=True)
481 write, read, err = util.popen3(cmd, env=env, newlines=True)
474 retdata = read.read()
482 retdata = read.read()
475 err = err.read().strip()
483 err = err.read().strip()
476 if err:
484 if err:
477 raise util.Abort(err)
485 raise util.Abort(err)
478 return retdata
486 return retdata
479
487
480 def _wcrev(self):
488 def _wcrev(self):
481 output = self._svncommand(['info', '--xml'])
489 output = self._svncommand(['info', '--xml'])
482 doc = xml.dom.minidom.parseString(output)
490 doc = xml.dom.minidom.parseString(output)
483 entries = doc.getElementsByTagName('entry')
491 entries = doc.getElementsByTagName('entry')
484 if not entries:
492 if not entries:
485 return 0
493 return 0
486 return int(entries[0].getAttribute('revision') or 0)
494 return int(entries[0].getAttribute('revision') or 0)
487
495
488 def _wcchanged(self):
496 def _wcchanged(self):
489 """Return (changes, extchanges) where changes is True
497 """Return (changes, extchanges) where changes is True
490 if the working directory was changed, and extchanges is
498 if the working directory was changed, and extchanges is
491 True if any of these changes concern an external entry.
499 True if any of these changes concern an external entry.
492 """
500 """
493 output = self._svncommand(['status', '--xml'])
501 output = self._svncommand(['status', '--xml'])
494 externals, changes = [], []
502 externals, changes = [], []
495 doc = xml.dom.minidom.parseString(output)
503 doc = xml.dom.minidom.parseString(output)
496 for e in doc.getElementsByTagName('entry'):
504 for e in doc.getElementsByTagName('entry'):
497 s = e.getElementsByTagName('wc-status')
505 s = e.getElementsByTagName('wc-status')
498 if not s:
506 if not s:
499 continue
507 continue
500 item = s[0].getAttribute('item')
508 item = s[0].getAttribute('item')
501 props = s[0].getAttribute('props')
509 props = s[0].getAttribute('props')
502 path = e.getAttribute('path')
510 path = e.getAttribute('path')
503 if item == 'external':
511 if item == 'external':
504 externals.append(path)
512 externals.append(path)
505 if (item not in ('', 'normal', 'unversioned', 'external')
513 if (item not in ('', 'normal', 'unversioned', 'external')
506 or props not in ('', 'none')):
514 or props not in ('', 'none')):
507 changes.append(path)
515 changes.append(path)
508 for path in changes:
516 for path in changes:
509 for ext in externals:
517 for ext in externals:
510 if path == ext or path.startswith(ext + os.sep):
518 if path == ext or path.startswith(ext + os.sep):
511 return True, True
519 return True, True
512 return bool(changes), False
520 return bool(changes), False
513
521
514 def dirty(self):
522 def dirty(self):
515 if self._wcrev() == self._state[1] and not self._wcchanged()[0]:
523 if self._wcrev() == self._state[1] and not self._wcchanged()[0]:
516 return False
524 return False
517 return True
525 return True
518
526
519 def commit(self, text, user, date):
527 def commit(self, text, user, date):
520 # user and date are out of our hands since svn is centralized
528 # user and date are out of our hands since svn is centralized
521 changed, extchanged = self._wcchanged()
529 changed, extchanged = self._wcchanged()
522 if not changed:
530 if not changed:
523 return self._wcrev()
531 return self._wcrev()
524 if extchanged:
532 if extchanged:
525 # Do not try to commit externals
533 # Do not try to commit externals
526 raise util.Abort(_('cannot commit svn externals'))
534 raise util.Abort(_('cannot commit svn externals'))
527 commitinfo = self._svncommand(['commit', '-m', text])
535 commitinfo = self._svncommand(['commit', '-m', text])
528 self._ui.status(commitinfo)
536 self._ui.status(commitinfo)
529 newrev = re.search('Committed revision ([0-9]+).', commitinfo)
537 newrev = re.search('Committed revision ([0-9]+).', commitinfo)
530 if not newrev:
538 if not newrev:
531 raise util.Abort(commitinfo.splitlines()[-1])
539 raise util.Abort(commitinfo.splitlines()[-1])
532 newrev = newrev.groups()[0]
540 newrev = newrev.groups()[0]
533 self._ui.status(self._svncommand(['update', '-r', newrev]))
541 self._ui.status(self._svncommand(['update', '-r', newrev]))
534 return newrev
542 return newrev
535
543
536 def remove(self):
544 def remove(self):
537 if self.dirty():
545 if self.dirty():
538 self._ui.warn(_('not removing repo %s because '
546 self._ui.warn(_('not removing repo %s because '
539 'it has changes.\n' % self._path))
547 'it has changes.\n' % self._path))
540 return
548 return
541 self._ui.note(_('removing subrepo %s\n') % self._path)
549 self._ui.note(_('removing subrepo %s\n') % self._path)
542 shutil.rmtree(self._ctx.repo.join(self._path))
550 shutil.rmtree(self._ctx.repo.join(self._path))
543
551
544 def get(self, state):
552 def get(self, state):
545 status = self._svncommand(['checkout', state[0], '--revision', state[1]])
553 status = self._svncommand(['checkout', state[0], '--revision', state[1]])
546 if not re.search('Checked out revision [0-9]+.', status):
554 if not re.search('Checked out revision [0-9]+.', status):
547 raise util.Abort(status.splitlines()[-1])
555 raise util.Abort(status.splitlines()[-1])
548 self._ui.status(status)
556 self._ui.status(status)
549
557
550 def merge(self, state):
558 def merge(self, state):
551 old = int(self._state[1])
559 old = int(self._state[1])
552 new = int(state[1])
560 new = int(state[1])
553 if new > old:
561 if new > old:
554 self.get(state)
562 self.get(state)
555
563
556 def push(self, force):
564 def push(self, force):
557 # push is a no-op for SVN
565 # push is a no-op for SVN
558 return True
566 return True
559
567
560 def files(self):
568 def files(self):
561 output = self._svncommand(['list'])
569 output = self._svncommand(['list'])
562 # This works because svn forbids \n in filenames.
570 # This works because svn forbids \n in filenames.
563 return output.splitlines()
571 return output.splitlines()
564
572
565 def filedata(self, name):
573 def filedata(self, name):
566 return self._svncommand(['cat'], name)
574 return self._svncommand(['cat'], name)
567
575
568
576
569 types = {
577 types = {
570 'hg': hgsubrepo,
578 'hg': hgsubrepo,
571 'svn': svnsubrepo,
579 'svn': svnsubrepo,
572 }
580 }
@@ -1,587 +1,648 b''
1 $ rm -rf sub
1 $ rm -rf sub
2 $ mkdir sub
2 $ mkdir sub
3 $ cd sub
3 $ cd sub
4 $ hg init t
4 $ hg init t
5 $ cd t
5 $ cd t
6
6
7 first revision, no sub
7 first revision, no sub
8
8
9 $ echo a > a
9 $ echo a > a
10 $ hg ci -Am0
10 $ hg ci -Am0
11 adding a
11 adding a
12
12
13 add first sub
13 add first sub
14
14
15 $ echo s = s > .hgsub
15 $ echo s = s > .hgsub
16 $ hg add .hgsub
16 $ hg add .hgsub
17 $ hg init s
17 $ hg init s
18 $ echo a > s/a
18 $ echo a > s/a
19
19
20 Issue2232: committing a subrepo without .hgsub
20 Issue2232: committing a subrepo without .hgsub
21
21
22 $ hg ci -mbad s
22 $ hg ci -mbad s
23 abort: can't commit subrepos without .hgsub
23 abort: can't commit subrepos without .hgsub
24 [255]
24 [255]
25
25
26 $ hg -R s ci -Ams0
26 $ hg -R s ci -Ams0
27 adding a
27 adding a
28 $ hg sum
28 $ hg sum
29 parent: 0:f7b1eb17ad24 tip
29 parent: 0:f7b1eb17ad24 tip
30 0
30 0
31 branch: default
31 branch: default
32 commit: 1 added, 1 subrepos
32 commit: 1 added, 1 subrepos
33 update: (current)
33 update: (current)
34 $ hg ci -m1
34 $ hg ci -m1
35 committing subrepository s
35 committing subrepository s
36
36
37 Issue2022: update -C
37 Issue2022: update -C
38
38
39 $ echo b > s/a
39 $ echo b > s/a
40 $ hg sum
40 $ hg sum
41 parent: 1:7cf8cfea66e4 tip
41 parent: 1:7cf8cfea66e4 tip
42 1
42 1
43 branch: default
43 branch: default
44 commit: 1 subrepos
44 commit: 1 subrepos
45 update: (current)
45 update: (current)
46 $ hg co -C 1
46 $ hg co -C 1
47 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
47 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 $ hg sum
48 $ hg sum
49 parent: 1:7cf8cfea66e4 tip
49 parent: 1:7cf8cfea66e4 tip
50 1
50 1
51 branch: default
51 branch: default
52 commit: (clean)
52 commit: (clean)
53 update: (current)
53 update: (current)
54
54
55 add sub sub
55 add sub sub
56
56
57 $ echo ss = ss > s/.hgsub
57 $ echo ss = ss > s/.hgsub
58 $ hg init s/ss
58 $ hg init s/ss
59 $ echo a > s/ss/a
59 $ echo a > s/ss/a
60 $ hg -R s add s/.hgsub
60 $ hg -R s add s/.hgsub
61 $ hg -R s/ss add s/ss/a
61 $ hg -R s/ss add s/ss/a
62 $ hg sum
62 $ hg sum
63 parent: 1:7cf8cfea66e4 tip
63 parent: 1:7cf8cfea66e4 tip
64 1
64 1
65 branch: default
65 branch: default
66 commit: 1 subrepos
66 commit: 1 subrepos
67 update: (current)
67 update: (current)
68 $ hg ci -m2
68 $ hg ci -m2
69 committing subrepository s
69 committing subrepository s
70 committing subrepository s/ss
70 committing subrepository s/ss
71 $ hg sum
71 $ hg sum
72 parent: 2:df30734270ae tip
72 parent: 2:df30734270ae tip
73 2
73 2
74 branch: default
74 branch: default
75 commit: (clean)
75 commit: (clean)
76 update: (current)
76 update: (current)
77
77
78 bump sub rev
78 bump sub rev
79
79
80 $ echo b > s/a
80 $ echo b > s/a
81 $ hg -R s ci -ms1
81 $ hg -R s ci -ms1
82 $ hg ci -m3
82 $ hg ci -m3
83 committing subrepository s
83 committing subrepository s
84
84
85 leave sub dirty
85 leave sub dirty
86
86
87 $ echo c > s/a
87 $ echo c > s/a
88 $ hg ci -m4
88 $ hg ci -m4
89 committing subrepository s
89 committing subrepository s
90 $ hg tip -R s
90 $ hg tip -R s
91 changeset: 3:1c833a7a9e3a
91 changeset: 3:1c833a7a9e3a
92 tag: tip
92 tag: tip
93 user: test
93 user: test
94 date: Thu Jan 01 00:00:00 1970 +0000
94 date: Thu Jan 01 00:00:00 1970 +0000
95 summary: 4
95 summary: 4
96
96
97
97
98 check caching
98 check caching
99
99
100 $ hg co 0
100 $ hg co 0
101 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
101 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
102 $ hg debugsub
102 $ hg debugsub
103
103
104 restore
104 restore
105
105
106 $ hg co
106 $ hg co
107 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
108 $ hg debugsub
108 $ hg debugsub
109 path s
109 path s
110 source s
110 source s
111 revision 1c833a7a9e3a4445c711aaf0f012379cd0d4034e
111 revision 1c833a7a9e3a4445c711aaf0f012379cd0d4034e
112
112
113 new branch for merge tests
113 new branch for merge tests
114
114
115 $ hg co 1
115 $ hg co 1
116 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
116 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
117 $ echo t = t >> .hgsub
117 $ echo t = t >> .hgsub
118 $ hg init t
118 $ hg init t
119 $ echo t > t/t
119 $ echo t > t/t
120 $ hg -R t add t
120 $ hg -R t add t
121 adding t/t
121 adding t/t
122
122
123 5
123 5
124
124
125 $ hg ci -m5 # add sub
125 $ hg ci -m5 # add sub
126 committing subrepository t
126 committing subrepository t
127 created new head
127 created new head
128 $ echo t2 > t/t
128 $ echo t2 > t/t
129
129
130 6
130 6
131
131
132 $ hg st -R s
132 $ hg st -R s
133 $ hg ci -m6 # change sub
133 $ hg ci -m6 # change sub
134 committing subrepository t
134 committing subrepository t
135 $ hg debugsub
135 $ hg debugsub
136 path s
136 path s
137 source s
137 source s
138 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
138 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
139 path t
139 path t
140 source t
140 source t
141 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
141 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
142 $ echo t3 > t/t
142 $ echo t3 > t/t
143
143
144 7
144 7
145
145
146 $ hg ci -m7 # change sub again for conflict test
146 $ hg ci -m7 # change sub again for conflict test
147 committing subrepository t
147 committing subrepository t
148 $ hg rm .hgsub
148 $ hg rm .hgsub
149
149
150 8
150 8
151
151
152 $ hg ci -m8 # remove sub
152 $ hg ci -m8 # remove sub
153
153
154 merge tests
154 merge tests
155
155
156 $ hg co -C 3
156 $ hg co -C 3
157 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
157 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
158 $ hg merge 5 # test adding
158 $ hg merge 5 # test adding
159 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
159 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
160 (branch merge, don't forget to commit)
160 (branch merge, don't forget to commit)
161 $ hg debugsub
161 $ hg debugsub
162 path s
162 path s
163 source s
163 source s
164 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
164 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
165 path t
165 path t
166 source t
166 source t
167 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
167 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
168 $ hg ci -m9
168 $ hg ci -m9
169 created new head
169 created new head
170 $ hg merge 6 --debug # test change
170 $ hg merge 6 --debug # test change
171 searching for copies back to rev 2
171 searching for copies back to rev 2
172 resolving manifests
172 resolving manifests
173 overwrite None partial False
173 overwrite None partial False
174 ancestor 1f14a2e2d3ec local f0d2028bf86d+ remote 1831e14459c4
174 ancestor 1f14a2e2d3ec local f0d2028bf86d+ remote 1831e14459c4
175 .hgsubstate: versions differ -> m
175 .hgsubstate: versions differ -> m
176 updating: .hgsubstate 1/1 files (100.00%)
176 updating: .hgsubstate 1/1 files (100.00%)
177 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
177 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
178 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
178 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
179 getting subrepo t
179 getting subrepo t
180 resolving manifests
180 resolving manifests
181 overwrite True partial False
181 overwrite True partial False
182 ancestor 60ca1237c194+ local 60ca1237c194+ remote 6747d179aa9a
182 ancestor 60ca1237c194+ local 60ca1237c194+ remote 6747d179aa9a
183 t: remote is newer -> g
183 t: remote is newer -> g
184 updating: t 1/1 files (100.00%)
184 updating: t 1/1 files (100.00%)
185 getting t
185 getting t
186 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
186 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
187 (branch merge, don't forget to commit)
187 (branch merge, don't forget to commit)
188 $ hg debugsub
188 $ hg debugsub
189 path s
189 path s
190 source s
190 source s
191 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
191 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
192 path t
192 path t
193 source t
193 source t
194 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
194 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
195 $ echo conflict > t/t
195 $ echo conflict > t/t
196 $ hg ci -m10
196 $ hg ci -m10
197 committing subrepository t
197 committing subrepository t
198 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
198 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
199 searching for copies back to rev 2
199 searching for copies back to rev 2
200 resolving manifests
200 resolving manifests
201 overwrite None partial False
201 overwrite None partial False
202 ancestor 1831e14459c4 local e45c8b14af55+ remote f94576341bcf
202 ancestor 1831e14459c4 local e45c8b14af55+ remote f94576341bcf
203 .hgsubstate: versions differ -> m
203 .hgsubstate: versions differ -> m
204 updating: .hgsubstate 1/1 files (100.00%)
204 updating: .hgsubstate 1/1 files (100.00%)
205 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
205 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
206 subrepo t: both sides changed, merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
206 subrepo t: both sides changed, merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
207 merging subrepo t
207 merging subrepo t
208 searching for copies back to rev 2
208 searching for copies back to rev 2
209 resolving manifests
209 resolving manifests
210 overwrite None partial False
210 overwrite None partial False
211 ancestor 6747d179aa9a local 20a0db6fbf6c+ remote 7af322bc1198
211 ancestor 6747d179aa9a local 20a0db6fbf6c+ remote 7af322bc1198
212 t: versions differ -> m
212 t: versions differ -> m
213 preserving t for resolve of t
213 preserving t for resolve of t
214 updating: t 1/1 files (100.00%)
214 updating: t 1/1 files (100.00%)
215 picked tool 'internal:merge' for t (binary False symlink False)
215 picked tool 'internal:merge' for t (binary False symlink False)
216 merging t
216 merging t
217 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
217 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
218 warning: conflicts during merge.
218 warning: conflicts during merge.
219 merging t failed!
219 merging t failed!
220 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
220 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
221 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
221 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
222 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
222 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
223 (branch merge, don't forget to commit)
223 (branch merge, don't forget to commit)
224
224
225 should conflict
225 should conflict
226
226
227 $ cat t/t
227 $ cat t/t
228 <<<<<<< local
228 <<<<<<< local
229 conflict
229 conflict
230 =======
230 =======
231 t3
231 t3
232 >>>>>>> other
232 >>>>>>> other
233
233
234 clone
234 clone
235
235
236 $ cd ..
236 $ cd ..
237 $ hg clone t tc
237 $ hg clone t tc
238 updating to branch default
238 updating to branch default
239 pulling subrepo s from $TESTTMP/sub/t/s
239 pulling subrepo s from $TESTTMP/sub/t/s
240 requesting all changes
240 requesting all changes
241 adding changesets
241 adding changesets
242 adding manifests
242 adding manifests
243 adding file changes
243 adding file changes
244 added 4 changesets with 5 changes to 3 files
244 added 4 changesets with 5 changes to 3 files
245 pulling subrepo s/ss from $TESTTMP/sub/t/s/ss
245 pulling subrepo s/ss from $TESTTMP/sub/t/s/ss
246 requesting all changes
246 requesting all changes
247 adding changesets
247 adding changesets
248 adding manifests
248 adding manifests
249 adding file changes
249 adding file changes
250 added 1 changesets with 1 changes to 1 files
250 added 1 changesets with 1 changes to 1 files
251 pulling subrepo t from $TESTTMP/sub/t/t
251 pulling subrepo t from $TESTTMP/sub/t/t
252 requesting all changes
252 requesting all changes
253 adding changesets
253 adding changesets
254 adding manifests
254 adding manifests
255 adding file changes
255 adding file changes
256 added 4 changesets with 4 changes to 1 files (+1 heads)
256 added 4 changesets with 4 changes to 1 files (+1 heads)
257 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
257 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
258 $ cd tc
258 $ cd tc
259 $ hg debugsub
259 $ hg debugsub
260 path s
260 path s
261 source s
261 source s
262 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
262 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
263 path t
263 path t
264 source t
264 source t
265 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
265 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
266
266
267 push
267 push
268
268
269 $ echo bah > t/t
269 $ echo bah > t/t
270 $ hg ci -m11
270 $ hg ci -m11
271 committing subrepository t
271 committing subrepository t
272 $ hg push
272 $ hg push
273 pushing to $TESTTMP/sub/t
273 pushing to $TESTTMP/sub/t
274 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
274 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
275 searching for changes
275 searching for changes
276 no changes found
276 no changes found
277 pushing subrepo s to $TESTTMP/sub/t/s
277 pushing subrepo s to $TESTTMP/sub/t/s
278 searching for changes
278 searching for changes
279 no changes found
279 no changes found
280 pushing subrepo t to $TESTTMP/sub/t/t
280 pushing subrepo t to $TESTTMP/sub/t/t
281 searching for changes
281 searching for changes
282 adding changesets
282 adding changesets
283 adding manifests
283 adding manifests
284 adding file changes
284 adding file changes
285 added 1 changesets with 1 changes to 1 files
285 added 1 changesets with 1 changes to 1 files
286 searching for changes
286 searching for changes
287 adding changesets
287 adding changesets
288 adding manifests
288 adding manifests
289 adding file changes
289 adding file changes
290 added 1 changesets with 1 changes to 1 files
290 added 1 changesets with 1 changes to 1 files
291
291
292 push -f
292 push -f
293
293
294 $ echo bah > s/a
294 $ echo bah > s/a
295 $ hg ci -m12
295 $ hg ci -m12
296 committing subrepository s
296 committing subrepository s
297 $ hg push
297 $ hg push
298 pushing to $TESTTMP/sub/t
298 pushing to $TESTTMP/sub/t
299 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
299 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
300 searching for changes
300 searching for changes
301 no changes found
301 no changes found
302 pushing subrepo s to $TESTTMP/sub/t/s
302 pushing subrepo s to $TESTTMP/sub/t/s
303 searching for changes
303 searching for changes
304 abort: push creates new remote heads on branch 'default'!
304 abort: push creates new remote heads on branch 'default'!
305 (did you forget to merge? use push -f to force)
305 (did you forget to merge? use push -f to force)
306 [255]
306 [255]
307 $ hg push -f
307 $ hg push -f
308 pushing to $TESTTMP/sub/t
308 pushing to $TESTTMP/sub/t
309 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
309 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
310 searching for changes
310 searching for changes
311 no changes found
311 no changes found
312 pushing subrepo s to $TESTTMP/sub/t/s
312 pushing subrepo s to $TESTTMP/sub/t/s
313 searching for changes
313 searching for changes
314 adding changesets
314 adding changesets
315 adding manifests
315 adding manifests
316 adding file changes
316 adding file changes
317 added 1 changesets with 1 changes to 1 files (+1 heads)
317 added 1 changesets with 1 changes to 1 files (+1 heads)
318 pushing subrepo t to $TESTTMP/sub/t/t
318 pushing subrepo t to $TESTTMP/sub/t/t
319 searching for changes
319 searching for changes
320 no changes found
320 no changes found
321 searching for changes
321 searching for changes
322 adding changesets
322 adding changesets
323 adding manifests
323 adding manifests
324 adding file changes
324 adding file changes
325 added 1 changesets with 1 changes to 1 files
325 added 1 changesets with 1 changes to 1 files
326
326
327 update
327 update
328
328
329 $ cd ../t
329 $ cd ../t
330 $ hg up -C # discard our earlier merge
330 $ hg up -C # discard our earlier merge
331 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
331 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
332 $ echo blah > t/t
332 $ echo blah > t/t
333 $ hg ci -m13
333 $ hg ci -m13
334 committing subrepository t
334 committing subrepository t
335
335
336 pull
336 pull
337
337
338 $ cd ../tc
338 $ cd ../tc
339 $ hg pull
339 $ hg pull
340 pulling from $TESTTMP/sub/t
340 pulling from $TESTTMP/sub/t
341 searching for changes
341 searching for changes
342 adding changesets
342 adding changesets
343 adding manifests
343 adding manifests
344 adding file changes
344 adding file changes
345 added 1 changesets with 1 changes to 1 files
345 added 1 changesets with 1 changes to 1 files
346 (run 'hg update' to get a working copy)
346 (run 'hg update' to get a working copy)
347
347
348 should pull t
348 should pull t
349
349
350 $ hg up
350 $ hg up
351 pulling subrepo t from $TESTTMP/sub/t/t
351 pulling subrepo t from $TESTTMP/sub/t/t
352 searching for changes
352 searching for changes
353 adding changesets
353 adding changesets
354 adding manifests
354 adding manifests
355 adding file changes
355 adding file changes
356 added 1 changesets with 1 changes to 1 files
356 added 1 changesets with 1 changes to 1 files
357 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
357 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
358 $ cat t/t
358 $ cat t/t
359 blah
359 blah
360
360
361 bogus subrepo path aborts
361 bogus subrepo path aborts
362
362
363 $ echo 'bogus=[boguspath' >> .hgsub
363 $ echo 'bogus=[boguspath' >> .hgsub
364 $ hg ci -m 'bogus subrepo path'
364 $ hg ci -m 'bogus subrepo path'
365 abort: missing ] in subrepo source
365 abort: missing ] in subrepo source
366 [255]
366 [255]
367
367
368 Issue1986: merge aborts when trying to merge a subrepo that
368 Issue1986: merge aborts when trying to merge a subrepo that
369 shouldn't need merging
369 shouldn't need merging
370
370
371 # subrepo layout
371 # subrepo layout
372 #
372 #
373 # o 5 br
373 # o 5 br
374 # /|
374 # /|
375 # o | 4 default
375 # o | 4 default
376 # | |
376 # | |
377 # | o 3 br
377 # | o 3 br
378 # |/|
378 # |/|
379 # o | 2 default
379 # o | 2 default
380 # | |
380 # | |
381 # | o 1 br
381 # | o 1 br
382 # |/
382 # |/
383 # o 0 default
383 # o 0 default
384
384
385 $ cd ..
385 $ cd ..
386 $ rm -rf sub
386 $ rm -rf sub
387 $ hg init main
387 $ hg init main
388 $ cd main
388 $ cd main
389 $ hg init s
389 $ hg init s
390 $ cd s
390 $ cd s
391 $ echo a > a
391 $ echo a > a
392 $ hg ci -Am1
392 $ hg ci -Am1
393 adding a
393 adding a
394 $ hg branch br
394 $ hg branch br
395 marked working directory as branch br
395 marked working directory as branch br
396 $ echo a >> a
396 $ echo a >> a
397 $ hg ci -m1
397 $ hg ci -m1
398 $ hg up default
398 $ hg up default
399 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
399 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
400 $ echo b > b
400 $ echo b > b
401 $ hg ci -Am1
401 $ hg ci -Am1
402 adding b
402 adding b
403 $ hg up br
403 $ hg up br
404 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
404 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
405 $ hg merge tip
405 $ hg merge tip
406 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
406 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
407 (branch merge, don't forget to commit)
407 (branch merge, don't forget to commit)
408 $ hg ci -m1
408 $ hg ci -m1
409 $ hg up 2
409 $ hg up 2
410 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
410 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
411 $ echo c > c
411 $ echo c > c
412 $ hg ci -Am1
412 $ hg ci -Am1
413 adding c
413 adding c
414 $ hg up 3
414 $ hg up 3
415 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
415 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
416 $ hg merge 4
416 $ hg merge 4
417 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
417 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
418 (branch merge, don't forget to commit)
418 (branch merge, don't forget to commit)
419 $ hg ci -m1
419 $ hg ci -m1
420
420
421 # main repo layout:
421 # main repo layout:
422 #
422 #
423 # * <-- try to merge default into br again
423 # * <-- try to merge default into br again
424 # .`|
424 # .`|
425 # . o 5 br --> substate = 5
425 # . o 5 br --> substate = 5
426 # . |
426 # . |
427 # o | 4 default --> substate = 4
427 # o | 4 default --> substate = 4
428 # | |
428 # | |
429 # | o 3 br --> substate = 2
429 # | o 3 br --> substate = 2
430 # |/|
430 # |/|
431 # o | 2 default --> substate = 2
431 # o | 2 default --> substate = 2
432 # | |
432 # | |
433 # | o 1 br --> substate = 3
433 # | o 1 br --> substate = 3
434 # |/
434 # |/
435 # o 0 default --> substate = 2
435 # o 0 default --> substate = 2
436
436
437 $ cd ..
437 $ cd ..
438 $ echo 's = s' > .hgsub
438 $ echo 's = s' > .hgsub
439 $ hg -R s up 2
439 $ hg -R s up 2
440 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
440 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
441 $ hg ci -Am1
441 $ hg ci -Am1
442 adding .hgsub
442 adding .hgsub
443 committing subrepository s
443 committing subrepository s
444 $ hg branch br
444 $ hg branch br
445 marked working directory as branch br
445 marked working directory as branch br
446 $ echo b > b
446 $ echo b > b
447 $ hg -R s up 3
447 $ hg -R s up 3
448 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
448 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
449 $ hg ci -Am1
449 $ hg ci -Am1
450 adding b
450 adding b
451 committing subrepository s
451 committing subrepository s
452 $ hg up default
452 $ hg up default
453 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
453 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
454 $ echo c > c
454 $ echo c > c
455 $ hg ci -Am1
455 $ hg ci -Am1
456 adding c
456 adding c
457 $ hg up 1
457 $ hg up 1
458 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
458 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
459 $ hg merge 2
459 $ hg merge 2
460 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
460 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
461 (branch merge, don't forget to commit)
461 (branch merge, don't forget to commit)
462 $ hg ci -m1
462 $ hg ci -m1
463 $ hg up 2
463 $ hg up 2
464 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
464 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
465 $ hg -R s up 4
465 $ hg -R s up 4
466 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
466 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
467 $ echo d > d
467 $ echo d > d
468 $ hg ci -Am1
468 $ hg ci -Am1
469 adding d
469 adding d
470 committing subrepository s
470 committing subrepository s
471 $ hg up 3
471 $ hg up 3
472 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
472 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
473 $ hg -R s up 5
473 $ hg -R s up 5
474 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
474 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
475 $ echo e > e
475 $ echo e > e
476 $ hg ci -Am1
476 $ hg ci -Am1
477 adding e
477 adding e
478 committing subrepository s
478 committing subrepository s
479
479
480 $ hg up 5
480 $ hg up 5
481 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
481 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
482 $ hg merge 4 # try to merge default into br again
482 $ hg merge 4 # try to merge default into br again
483 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
483 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
484 (branch merge, don't forget to commit)
484 (branch merge, don't forget to commit)
485 $ cd ..
485 $ cd ..
486
486
487 test subrepo delete from .hgsubstate
487 test subrepo delete from .hgsubstate
488
488
489 $ hg init testdelete
489 $ hg init testdelete
490 $ mkdir testdelete/nested testdelete/nested2
490 $ mkdir testdelete/nested testdelete/nested2
491 $ hg init testdelete/nested
491 $ hg init testdelete/nested
492 $ hg init testdelete/nested2
492 $ hg init testdelete/nested2
493 $ echo test > testdelete/nested/foo
493 $ echo test > testdelete/nested/foo
494 $ echo test > testdelete/nested2/foo
494 $ echo test > testdelete/nested2/foo
495 $ hg -R testdelete/nested add
495 $ hg -R testdelete/nested add
496 adding testdelete/nested/foo
496 adding testdelete/nested/foo
497 $ hg -R testdelete/nested2 add
497 $ hg -R testdelete/nested2 add
498 adding testdelete/nested2/foo
498 adding testdelete/nested2/foo
499 $ hg -R testdelete/nested ci -m test
499 $ hg -R testdelete/nested ci -m test
500 $ hg -R testdelete/nested2 ci -m test
500 $ hg -R testdelete/nested2 ci -m test
501 $ echo nested = nested > testdelete/.hgsub
501 $ echo nested = nested > testdelete/.hgsub
502 $ echo nested2 = nested2 >> testdelete/.hgsub
502 $ echo nested2 = nested2 >> testdelete/.hgsub
503 $ hg -R testdelete add
503 $ hg -R testdelete add
504 adding testdelete/.hgsub
504 adding testdelete/.hgsub
505 $ hg -R testdelete ci -m "nested 1 & 2 added"
505 $ hg -R testdelete ci -m "nested 1 & 2 added"
506 committing subrepository nested
506 committing subrepository nested
507 committing subrepository nested2
507 committing subrepository nested2
508 $ echo nested = nested > testdelete/.hgsub
508 $ echo nested = nested > testdelete/.hgsub
509 $ hg -R testdelete ci -m "nested 2 deleted"
509 $ hg -R testdelete ci -m "nested 2 deleted"
510 $ cat testdelete/.hgsubstate
510 $ cat testdelete/.hgsubstate
511 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
511 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
512 $ hg -R testdelete remove testdelete/.hgsub
512 $ hg -R testdelete remove testdelete/.hgsub
513 $ hg -R testdelete ci -m ".hgsub deleted"
513 $ hg -R testdelete ci -m ".hgsub deleted"
514 $ cat testdelete/.hgsubstate
514 $ cat testdelete/.hgsubstate
515
515
516 test repository cloning
516 test repository cloning
517
517
518 $ mkdir mercurial mercurial2
518 $ mkdir mercurial mercurial2
519 $ hg init nested_absolute
519 $ hg init nested_absolute
520 $ echo test > nested_absolute/foo
520 $ echo test > nested_absolute/foo
521 $ hg -R nested_absolute add
521 $ hg -R nested_absolute add
522 adding nested_absolute/foo
522 adding nested_absolute/foo
523 $ hg -R nested_absolute ci -mtest
523 $ hg -R nested_absolute ci -mtest
524 $ cd mercurial
524 $ cd mercurial
525 $ hg init nested_relative
525 $ hg init nested_relative
526 $ echo test2 > nested_relative/foo2
526 $ echo test2 > nested_relative/foo2
527 $ hg -R nested_relative add
527 $ hg -R nested_relative add
528 adding nested_relative/foo2
528 adding nested_relative/foo2
529 $ hg -R nested_relative ci -mtest2
529 $ hg -R nested_relative ci -mtest2
530 $ hg init main
530 $ hg init main
531 $ echo "nested_relative = ../nested_relative" > main/.hgsub
531 $ echo "nested_relative = ../nested_relative" > main/.hgsub
532 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
532 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
533 $ hg -R main add
533 $ hg -R main add
534 adding main/.hgsub
534 adding main/.hgsub
535 $ hg -R main ci -m "add subrepos"
535 $ hg -R main ci -m "add subrepos"
536 committing subrepository nested_absolute
536 committing subrepository nested_absolute
537 committing subrepository nested_relative
537 committing subrepository nested_relative
538 $ cd ..
538 $ cd ..
539 $ hg clone mercurial/main mercurial2/main
539 $ hg clone mercurial/main mercurial2/main
540 updating to branch default
540 updating to branch default
541 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
541 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
542 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
542 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
543 > mercurial2/main/nested_relative/.hg/hgrc
543 > mercurial2/main/nested_relative/.hg/hgrc
544 [paths]
544 [paths]
545 default = $TESTTMP/sub/mercurial/nested_absolute
545 default = $TESTTMP/sub/mercurial/nested_absolute
546 [paths]
546 [paths]
547 default = $TESTTMP/sub/mercurial/nested_relative
547 default = $TESTTMP/sub/mercurial/nested_relative
548 $ rm -rf mercurial mercurial2
548 $ rm -rf mercurial mercurial2
549
549
550 Issue1977: multirepo push should fail if subrepo push fails
550 Issue1977: multirepo push should fail if subrepo push fails
551
551
552 $ hg init repo
552 $ hg init repo
553 $ hg init repo/s
553 $ hg init repo/s
554 $ echo a > repo/s/a
554 $ echo a > repo/s/a
555 $ hg -R repo/s ci -Am0
555 $ hg -R repo/s ci -Am0
556 adding a
556 adding a
557 $ echo s = s > repo/.hgsub
557 $ echo s = s > repo/.hgsub
558 $ hg -R repo ci -Am1
558 $ hg -R repo ci -Am1
559 adding .hgsub
559 adding .hgsub
560 committing subrepository s
560 committing subrepository s
561 $ hg clone repo repo2
561 $ hg clone repo repo2
562 updating to branch default
562 updating to branch default
563 pulling subrepo s from $TESTTMP/sub/repo/s
563 pulling subrepo s from $TESTTMP/sub/repo/s
564 requesting all changes
564 requesting all changes
565 adding changesets
565 adding changesets
566 adding manifests
566 adding manifests
567 adding file changes
567 adding file changes
568 added 1 changesets with 1 changes to 1 files
568 added 1 changesets with 1 changes to 1 files
569 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
569 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
570 $ hg -q -R repo2 pull -u
570 $ hg -q -R repo2 pull -u
571 $ echo 1 > repo2/s/a
571 $ echo 1 > repo2/s/a
572 $ hg -R repo2/s ci -m2
572 $ hg -R repo2/s ci -m2
573 $ hg -q -R repo2/s push
573 $ hg -q -R repo2/s push
574 $ hg -R repo2/s up -C 0
574 $ hg -R repo2/s up -C 0
575 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
575 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
576 $ echo 2 > repo2/s/a
576 $ echo 2 > repo2/s/a
577 $ hg -R repo2/s ci -m3
577 $ hg -R repo2/s ci -m3
578 created new head
578 created new head
579 $ hg -R repo2 ci -m3
579 $ hg -R repo2 ci -m3
580 committing subrepository s
580 committing subrepository s
581 $ hg -q -R repo2 push
581 $ hg -q -R repo2 push
582 abort: push creates new remote heads on branch 'default'!
582 abort: push creates new remote heads on branch 'default'!
583 (did you forget to merge? use push -f to force)
583 (did you forget to merge? use push -f to force)
584 [255]
584 [255]
585 $ hg -R repo update
585 $ hg -R repo update
586 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
586 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
587 $ rm -rf repo2 repo
587 $ rm -rf repo2 repo
588
589
590 Issue1852 subrepos with relative paths always push/pull relative to default
591
592 Prepare a repo with subrepo
593
594 $ hg init issue1852a
595 $ cd issue1852a
596 $ hg init sub/repo
597 $ echo test > sub/repo/foo
598 $ hg -R sub/repo add sub/repo/foo
599 $ echo sub/repo = sub/repo > .hgsub
600 $ hg add .hgsub
601 $ hg ci -mtest
602 committing subrepository sub/repo
603 $ echo test >> sub/repo/foo
604 $ hg ci -mtest
605 committing subrepository sub/repo
606 $ cd ..
607
608 Create repo without default path, pull top repo, and see what happens on update
609
610 $ hg init issue1852b
611 $ hg -R issue1852b pull issue1852a
612 pulling from issue1852a
613 requesting all changes
614 adding changesets
615 adding manifests
616 adding file changes
617 added 2 changesets with 3 changes to 2 files
618 (run 'hg update' to get a working copy)
619 $ hg -R issue1852b update
620 abort: default path for subrepository sub/repo not found
621 [255]
622
623 Pull -u now doesn't help
624
625 $ hg -R issue1852b pull -u issue1852a
626 pulling from issue1852a
627 searching for changes
628 no changes found
629
630 Try the same, but with pull -u
631
632 $ hg init issue1852c
633 $ hg -R issue1852c pull -r0 -u issue1852a
634 pulling from issue1852a
635 requesting all changes
636 adding changesets
637 adding manifests
638 adding file changes
639 added 1 changesets with 2 changes to 2 files
640 abort: default path for subrepository sub/repo not found
641 [255]
642
643 Try to push from the other side
644
645 $ hg -R issue1852a push issue1852c
646 pushing to issue1852c
647 abort: default path for subrepository sub/repo not found
648 [255]
General Comments 0
You need to be logged in to leave comments. Login now