##// END OF EJS Templates
subrepo: create subrepos using clone instead of pull...
Martin Geisler -
r14281:ccb7240a default
parent child Browse files
Show More
@@ -1,1045 +1,1057 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, posixpath
8 import errno, os, re, xml.dom.minidom, shutil, posixpath
9 import stat, subprocess, tarfile
9 import stat, subprocess, tarfile
10 from i18n import _
10 from i18n import _
11 import config, scmutil, util, node, error, cmdutil, bookmarks
11 import config, scmutil, util, node, error, cmdutil, bookmarks
12 hg = None
12 hg = None
13 propertycache = util.propertycache
13 propertycache = util.propertycache
14
14
15 nullstate = ('', '', 'empty')
15 nullstate = ('', '', 'empty')
16
16
17 def state(ctx, ui):
17 def state(ctx, ui):
18 """return a state dict, mapping subrepo paths configured in .hgsub
18 """return a state dict, mapping subrepo paths configured in .hgsub
19 to tuple: (source from .hgsub, revision from .hgsubstate, kind
19 to tuple: (source from .hgsub, revision from .hgsubstate, kind
20 (key in types dict))
20 (key in types dict))
21 """
21 """
22 p = config.config()
22 p = config.config()
23 def read(f, sections=None, remap=None):
23 def read(f, sections=None, remap=None):
24 if f in ctx:
24 if f in ctx:
25 try:
25 try:
26 data = ctx[f].data()
26 data = ctx[f].data()
27 except IOError, err:
27 except IOError, err:
28 if err.errno != errno.ENOENT:
28 if err.errno != errno.ENOENT:
29 raise
29 raise
30 # handle missing subrepo spec files as removed
30 # handle missing subrepo spec files as removed
31 ui.warn(_("warning: subrepo spec file %s not found\n") % f)
31 ui.warn(_("warning: subrepo spec file %s not found\n") % f)
32 return
32 return
33 p.parse(f, data, sections, remap, read)
33 p.parse(f, data, sections, remap, read)
34 else:
34 else:
35 raise util.Abort(_("subrepo spec file %s not found") % f)
35 raise util.Abort(_("subrepo spec file %s not found") % f)
36
36
37 if '.hgsub' in ctx:
37 if '.hgsub' in ctx:
38 read('.hgsub')
38 read('.hgsub')
39
39
40 for path, src in ui.configitems('subpaths'):
40 for path, src in ui.configitems('subpaths'):
41 p.set('subpaths', path, src, ui.configsource('subpaths', path))
41 p.set('subpaths', path, src, ui.configsource('subpaths', path))
42
42
43 rev = {}
43 rev = {}
44 if '.hgsubstate' in ctx:
44 if '.hgsubstate' in ctx:
45 try:
45 try:
46 for l in ctx['.hgsubstate'].data().splitlines():
46 for l in ctx['.hgsubstate'].data().splitlines():
47 revision, path = l.split(" ", 1)
47 revision, path = l.split(" ", 1)
48 rev[path] = revision
48 rev[path] = revision
49 except IOError, err:
49 except IOError, err:
50 if err.errno != errno.ENOENT:
50 if err.errno != errno.ENOENT:
51 raise
51 raise
52
52
53 state = {}
53 state = {}
54 for path, src in p[''].items():
54 for path, src in p[''].items():
55 kind = 'hg'
55 kind = 'hg'
56 if src.startswith('['):
56 if src.startswith('['):
57 if ']' not in src:
57 if ']' not in src:
58 raise util.Abort(_('missing ] in subrepo source'))
58 raise util.Abort(_('missing ] in subrepo source'))
59 kind, src = src.split(']', 1)
59 kind, src = src.split(']', 1)
60 kind = kind[1:]
60 kind = kind[1:]
61
61
62 for pattern, repl in p.items('subpaths'):
62 for pattern, repl in p.items('subpaths'):
63 # Turn r'C:\foo\bar' into r'C:\\foo\\bar' since re.sub
63 # Turn r'C:\foo\bar' into r'C:\\foo\\bar' since re.sub
64 # does a string decode.
64 # does a string decode.
65 repl = repl.encode('string-escape')
65 repl = repl.encode('string-escape')
66 # However, we still want to allow back references to go
66 # However, we still want to allow back references to go
67 # through unharmed, so we turn r'\\1' into r'\1'. Again,
67 # through unharmed, so we turn r'\\1' into r'\1'. Again,
68 # extra escapes are needed because re.sub string decodes.
68 # extra escapes are needed because re.sub string decodes.
69 repl = re.sub(r'\\\\([0-9]+)', r'\\\1', repl)
69 repl = re.sub(r'\\\\([0-9]+)', r'\\\1', repl)
70 try:
70 try:
71 src = re.sub(pattern, repl, src, 1)
71 src = re.sub(pattern, repl, src, 1)
72 except re.error, e:
72 except re.error, e:
73 raise util.Abort(_("bad subrepository pattern in %s: %s")
73 raise util.Abort(_("bad subrepository pattern in %s: %s")
74 % (p.source('subpaths', pattern), e))
74 % (p.source('subpaths', pattern), e))
75
75
76 state[path] = (src.strip(), rev.get(path, ''), kind)
76 state[path] = (src.strip(), rev.get(path, ''), kind)
77
77
78 return state
78 return state
79
79
80 def writestate(repo, state):
80 def writestate(repo, state):
81 """rewrite .hgsubstate in (outer) repo with these subrepo states"""
81 """rewrite .hgsubstate in (outer) repo with these subrepo states"""
82 repo.wwrite('.hgsubstate',
82 repo.wwrite('.hgsubstate',
83 ''.join(['%s %s\n' % (state[s][1], s)
83 ''.join(['%s %s\n' % (state[s][1], s)
84 for s in sorted(state)]), '')
84 for s in sorted(state)]), '')
85
85
86 def submerge(repo, wctx, mctx, actx, overwrite):
86 def submerge(repo, wctx, mctx, actx, overwrite):
87 """delegated from merge.applyupdates: merging of .hgsubstate file
87 """delegated from merge.applyupdates: merging of .hgsubstate file
88 in working context, merging context and ancestor context"""
88 in working context, merging context and ancestor context"""
89 if mctx == actx: # backwards?
89 if mctx == actx: # backwards?
90 actx = wctx.p1()
90 actx = wctx.p1()
91 s1 = wctx.substate
91 s1 = wctx.substate
92 s2 = mctx.substate
92 s2 = mctx.substate
93 sa = actx.substate
93 sa = actx.substate
94 sm = {}
94 sm = {}
95
95
96 repo.ui.debug("subrepo merge %s %s %s\n" % (wctx, mctx, actx))
96 repo.ui.debug("subrepo merge %s %s %s\n" % (wctx, mctx, actx))
97
97
98 def debug(s, msg, r=""):
98 def debug(s, msg, r=""):
99 if r:
99 if r:
100 r = "%s:%s:%s" % r
100 r = "%s:%s:%s" % r
101 repo.ui.debug(" subrepo %s: %s %s\n" % (s, msg, r))
101 repo.ui.debug(" subrepo %s: %s %s\n" % (s, msg, r))
102
102
103 for s, l in s1.items():
103 for s, l in s1.items():
104 a = sa.get(s, nullstate)
104 a = sa.get(s, nullstate)
105 ld = l # local state with possible dirty flag for compares
105 ld = l # local state with possible dirty flag for compares
106 if wctx.sub(s).dirty():
106 if wctx.sub(s).dirty():
107 ld = (l[0], l[1] + "+")
107 ld = (l[0], l[1] + "+")
108 if wctx == actx: # overwrite
108 if wctx == actx: # overwrite
109 a = ld
109 a = ld
110
110
111 if s in s2:
111 if s in s2:
112 r = s2[s]
112 r = s2[s]
113 if ld == r or r == a: # no change or local is newer
113 if ld == r or r == a: # no change or local is newer
114 sm[s] = l
114 sm[s] = l
115 continue
115 continue
116 elif ld == a: # other side changed
116 elif ld == a: # other side changed
117 debug(s, "other changed, get", r)
117 debug(s, "other changed, get", r)
118 wctx.sub(s).get(r, overwrite)
118 wctx.sub(s).get(r, overwrite)
119 sm[s] = r
119 sm[s] = r
120 elif ld[0] != r[0]: # sources differ
120 elif ld[0] != r[0]: # sources differ
121 if repo.ui.promptchoice(
121 if repo.ui.promptchoice(
122 _(' subrepository sources for %s differ\n'
122 _(' subrepository sources for %s differ\n'
123 'use (l)ocal source (%s) or (r)emote source (%s)?')
123 'use (l)ocal source (%s) or (r)emote source (%s)?')
124 % (s, l[0], r[0]),
124 % (s, l[0], r[0]),
125 (_('&Local'), _('&Remote')), 0):
125 (_('&Local'), _('&Remote')), 0):
126 debug(s, "prompt changed, get", r)
126 debug(s, "prompt changed, get", r)
127 wctx.sub(s).get(r, overwrite)
127 wctx.sub(s).get(r, overwrite)
128 sm[s] = r
128 sm[s] = r
129 elif ld[1] == a[1]: # local side is unchanged
129 elif ld[1] == a[1]: # local side is unchanged
130 debug(s, "other side changed, get", r)
130 debug(s, "other side changed, get", r)
131 wctx.sub(s).get(r, overwrite)
131 wctx.sub(s).get(r, overwrite)
132 sm[s] = r
132 sm[s] = r
133 else:
133 else:
134 debug(s, "both sides changed, merge with", r)
134 debug(s, "both sides changed, merge with", r)
135 wctx.sub(s).merge(r)
135 wctx.sub(s).merge(r)
136 sm[s] = l
136 sm[s] = l
137 elif ld == a: # remote removed, local unchanged
137 elif ld == a: # remote removed, local unchanged
138 debug(s, "remote removed, remove")
138 debug(s, "remote removed, remove")
139 wctx.sub(s).remove()
139 wctx.sub(s).remove()
140 else:
140 else:
141 if repo.ui.promptchoice(
141 if repo.ui.promptchoice(
142 _(' local changed subrepository %s which remote removed\n'
142 _(' local changed subrepository %s which remote removed\n'
143 'use (c)hanged version or (d)elete?') % s,
143 'use (c)hanged version or (d)elete?') % s,
144 (_('&Changed'), _('&Delete')), 0):
144 (_('&Changed'), _('&Delete')), 0):
145 debug(s, "prompt remove")
145 debug(s, "prompt remove")
146 wctx.sub(s).remove()
146 wctx.sub(s).remove()
147
147
148 for s, r in sorted(s2.items()):
148 for s, r in sorted(s2.items()):
149 if s in s1:
149 if s in s1:
150 continue
150 continue
151 elif s not in sa:
151 elif s not in sa:
152 debug(s, "remote added, get", r)
152 debug(s, "remote added, get", r)
153 mctx.sub(s).get(r)
153 mctx.sub(s).get(r)
154 sm[s] = r
154 sm[s] = r
155 elif r != sa[s]:
155 elif r != sa[s]:
156 if repo.ui.promptchoice(
156 if repo.ui.promptchoice(
157 _(' remote changed subrepository %s which local removed\n'
157 _(' remote changed subrepository %s which local removed\n'
158 'use (c)hanged version or (d)elete?') % s,
158 'use (c)hanged version or (d)elete?') % s,
159 (_('&Changed'), _('&Delete')), 0) == 0:
159 (_('&Changed'), _('&Delete')), 0) == 0:
160 debug(s, "prompt recreate", r)
160 debug(s, "prompt recreate", r)
161 wctx.sub(s).get(r)
161 wctx.sub(s).get(r)
162 sm[s] = r
162 sm[s] = r
163
163
164 # record merged .hgsubstate
164 # record merged .hgsubstate
165 writestate(repo, sm)
165 writestate(repo, sm)
166
166
167 def _updateprompt(ui, sub, dirty, local, remote):
167 def _updateprompt(ui, sub, dirty, local, remote):
168 if dirty:
168 if dirty:
169 msg = (_(' subrepository sources for %s differ\n'
169 msg = (_(' subrepository sources for %s differ\n'
170 'use (l)ocal source (%s) or (r)emote source (%s)?\n')
170 'use (l)ocal source (%s) or (r)emote source (%s)?\n')
171 % (subrelpath(sub), local, remote))
171 % (subrelpath(sub), local, remote))
172 else:
172 else:
173 msg = (_(' subrepository sources for %s differ (in checked out version)\n'
173 msg = (_(' subrepository sources for %s differ (in checked out version)\n'
174 'use (l)ocal source (%s) or (r)emote source (%s)?\n')
174 'use (l)ocal source (%s) or (r)emote source (%s)?\n')
175 % (subrelpath(sub), local, remote))
175 % (subrelpath(sub), local, remote))
176 return ui.promptchoice(msg, (_('&Local'), _('&Remote')), 0)
176 return ui.promptchoice(msg, (_('&Local'), _('&Remote')), 0)
177
177
178 def reporelpath(repo):
178 def reporelpath(repo):
179 """return path to this (sub)repo as seen from outermost repo"""
179 """return path to this (sub)repo as seen from outermost repo"""
180 parent = repo
180 parent = repo
181 while hasattr(parent, '_subparent'):
181 while hasattr(parent, '_subparent'):
182 parent = parent._subparent
182 parent = parent._subparent
183 return repo.root[len(parent.root)+1:]
183 return repo.root[len(parent.root)+1:]
184
184
185 def subrelpath(sub):
185 def subrelpath(sub):
186 """return path to this subrepo as seen from outermost repo"""
186 """return path to this subrepo as seen from outermost repo"""
187 if hasattr(sub, '_relpath'):
187 if hasattr(sub, '_relpath'):
188 return sub._relpath
188 return sub._relpath
189 if not hasattr(sub, '_repo'):
189 if not hasattr(sub, '_repo'):
190 return sub._path
190 return sub._path
191 return reporelpath(sub._repo)
191 return reporelpath(sub._repo)
192
192
193 def _abssource(repo, push=False, abort=True):
193 def _abssource(repo, push=False, abort=True):
194 """return pull/push path of repo - either based on parent repo .hgsub info
194 """return pull/push path of repo - either based on parent repo .hgsub info
195 or on the top repo config. Abort or return None if no source found."""
195 or on the top repo config. Abort or return None if no source found."""
196 if hasattr(repo, '_subparent'):
196 if hasattr(repo, '_subparent'):
197 source = util.url(repo._subsource)
197 source = util.url(repo._subsource)
198 source.path = posixpath.normpath(source.path)
198 source.path = posixpath.normpath(source.path)
199 if posixpath.isabs(source.path) or source.scheme:
199 if posixpath.isabs(source.path) or source.scheme:
200 return str(source)
200 return str(source)
201 parent = _abssource(repo._subparent, push, abort=False)
201 parent = _abssource(repo._subparent, push, abort=False)
202 if parent:
202 if parent:
203 parent = util.url(parent)
203 parent = util.url(parent)
204 parent.path = posixpath.join(parent.path, source.path)
204 parent.path = posixpath.join(parent.path, source.path)
205 parent.path = posixpath.normpath(parent.path)
205 parent.path = posixpath.normpath(parent.path)
206 return str(parent)
206 return str(parent)
207 else: # recursion reached top repo
207 else: # recursion reached top repo
208 if hasattr(repo, '_subtoppath'):
208 if hasattr(repo, '_subtoppath'):
209 return repo._subtoppath
209 return repo._subtoppath
210 if push and repo.ui.config('paths', 'default-push'):
210 if push and repo.ui.config('paths', 'default-push'):
211 return repo.ui.config('paths', 'default-push')
211 return repo.ui.config('paths', 'default-push')
212 if repo.ui.config('paths', 'default'):
212 if repo.ui.config('paths', 'default'):
213 return repo.ui.config('paths', 'default')
213 return repo.ui.config('paths', 'default')
214 if abort:
214 if abort:
215 raise util.Abort(_("default path for subrepository %s not found") %
215 raise util.Abort(_("default path for subrepository %s not found") %
216 reporelpath(repo))
216 reporelpath(repo))
217
217
218 def itersubrepos(ctx1, ctx2):
218 def itersubrepos(ctx1, ctx2):
219 """find subrepos in ctx1 or ctx2"""
219 """find subrepos in ctx1 or ctx2"""
220 # Create a (subpath, ctx) mapping where we prefer subpaths from
220 # Create a (subpath, ctx) mapping where we prefer subpaths from
221 # ctx1. The subpaths from ctx2 are important when the .hgsub file
221 # ctx1. The subpaths from ctx2 are important when the .hgsub file
222 # has been modified (in ctx2) but not yet committed (in ctx1).
222 # has been modified (in ctx2) but not yet committed (in ctx1).
223 subpaths = dict.fromkeys(ctx2.substate, ctx2)
223 subpaths = dict.fromkeys(ctx2.substate, ctx2)
224 subpaths.update(dict.fromkeys(ctx1.substate, ctx1))
224 subpaths.update(dict.fromkeys(ctx1.substate, ctx1))
225 for subpath, ctx in sorted(subpaths.iteritems()):
225 for subpath, ctx in sorted(subpaths.iteritems()):
226 yield subpath, ctx.sub(subpath)
226 yield subpath, ctx.sub(subpath)
227
227
228 def subrepo(ctx, path):
228 def subrepo(ctx, path):
229 """return instance of the right subrepo class for subrepo in path"""
229 """return instance of the right subrepo class for subrepo in path"""
230 # subrepo inherently violates our import layering rules
230 # subrepo inherently violates our import layering rules
231 # because it wants to make repo objects from deep inside the stack
231 # because it wants to make repo objects from deep inside the stack
232 # so we manually delay the circular imports to not break
232 # so we manually delay the circular imports to not break
233 # scripts that don't use our demand-loading
233 # scripts that don't use our demand-loading
234 global hg
234 global hg
235 import hg as h
235 import hg as h
236 hg = h
236 hg = h
237
237
238 scmutil.pathauditor(ctx._repo.root)(path)
238 scmutil.pathauditor(ctx._repo.root)(path)
239 state = ctx.substate.get(path, nullstate)
239 state = ctx.substate.get(path, nullstate)
240 if state[2] not in types:
240 if state[2] not in types:
241 raise util.Abort(_('unknown subrepo type %s') % state[2])
241 raise util.Abort(_('unknown subrepo type %s') % state[2])
242 return types[state[2]](ctx, path, state[:2])
242 return types[state[2]](ctx, path, state[:2])
243
243
244 # subrepo classes need to implement the following abstract class:
244 # subrepo classes need to implement the following abstract class:
245
245
246 class abstractsubrepo(object):
246 class abstractsubrepo(object):
247
247
248 def dirty(self, ignoreupdate=False):
248 def dirty(self, ignoreupdate=False):
249 """returns true if the dirstate of the subrepo is dirty or does not
249 """returns true if the dirstate of the subrepo is dirty or does not
250 match current stored state. If ignoreupdate is true, only check
250 match current stored state. If ignoreupdate is true, only check
251 whether the subrepo has uncommitted changes in its dirstate.
251 whether the subrepo has uncommitted changes in its dirstate.
252 """
252 """
253 raise NotImplementedError
253 raise NotImplementedError
254
254
255 def checknested(self, path):
255 def checknested(self, path):
256 """check if path is a subrepository within this repository"""
256 """check if path is a subrepository within this repository"""
257 return False
257 return False
258
258
259 def commit(self, text, user, date):
259 def commit(self, text, user, date):
260 """commit the current changes to the subrepo with the given
260 """commit the current changes to the subrepo with the given
261 log message. Use given user and date if possible. Return the
261 log message. Use given user and date if possible. Return the
262 new state of the subrepo.
262 new state of the subrepo.
263 """
263 """
264 raise NotImplementedError
264 raise NotImplementedError
265
265
266 def remove(self):
266 def remove(self):
267 """remove the subrepo
267 """remove the subrepo
268
268
269 (should verify the dirstate is not dirty first)
269 (should verify the dirstate is not dirty first)
270 """
270 """
271 raise NotImplementedError
271 raise NotImplementedError
272
272
273 def get(self, state, overwrite=False):
273 def get(self, state, overwrite=False):
274 """run whatever commands are needed to put the subrepo into
274 """run whatever commands are needed to put the subrepo into
275 this state
275 this state
276 """
276 """
277 raise NotImplementedError
277 raise NotImplementedError
278
278
279 def merge(self, state):
279 def merge(self, state):
280 """merge currently-saved state with the new state."""
280 """merge currently-saved state with the new state."""
281 raise NotImplementedError
281 raise NotImplementedError
282
282
283 def push(self, force):
283 def push(self, force):
284 """perform whatever action is analogous to 'hg push'
284 """perform whatever action is analogous to 'hg push'
285
285
286 This may be a no-op on some systems.
286 This may be a no-op on some systems.
287 """
287 """
288 raise NotImplementedError
288 raise NotImplementedError
289
289
290 def add(self, ui, match, dryrun, prefix):
290 def add(self, ui, match, dryrun, prefix):
291 return []
291 return []
292
292
293 def status(self, rev2, **opts):
293 def status(self, rev2, **opts):
294 return [], [], [], [], [], [], []
294 return [], [], [], [], [], [], []
295
295
296 def diff(self, diffopts, node2, match, prefix, **opts):
296 def diff(self, diffopts, node2, match, prefix, **opts):
297 pass
297 pass
298
298
299 def outgoing(self, ui, dest, opts):
299 def outgoing(self, ui, dest, opts):
300 return 1
300 return 1
301
301
302 def incoming(self, ui, source, opts):
302 def incoming(self, ui, source, opts):
303 return 1
303 return 1
304
304
305 def files(self):
305 def files(self):
306 """return filename iterator"""
306 """return filename iterator"""
307 raise NotImplementedError
307 raise NotImplementedError
308
308
309 def filedata(self, name):
309 def filedata(self, name):
310 """return file data"""
310 """return file data"""
311 raise NotImplementedError
311 raise NotImplementedError
312
312
313 def fileflags(self, name):
313 def fileflags(self, name):
314 """return file flags"""
314 """return file flags"""
315 return ''
315 return ''
316
316
317 def archive(self, ui, archiver, prefix):
317 def archive(self, ui, archiver, prefix):
318 files = self.files()
318 files = self.files()
319 total = len(files)
319 total = len(files)
320 relpath = subrelpath(self)
320 relpath = subrelpath(self)
321 ui.progress(_('archiving (%s)') % relpath, 0,
321 ui.progress(_('archiving (%s)') % relpath, 0,
322 unit=_('files'), total=total)
322 unit=_('files'), total=total)
323 for i, name in enumerate(files):
323 for i, name in enumerate(files):
324 flags = self.fileflags(name)
324 flags = self.fileflags(name)
325 mode = 'x' in flags and 0755 or 0644
325 mode = 'x' in flags and 0755 or 0644
326 symlink = 'l' in flags
326 symlink = 'l' in flags
327 archiver.addfile(os.path.join(prefix, self._path, name),
327 archiver.addfile(os.path.join(prefix, self._path, name),
328 mode, symlink, self.filedata(name))
328 mode, symlink, self.filedata(name))
329 ui.progress(_('archiving (%s)') % relpath, i + 1,
329 ui.progress(_('archiving (%s)') % relpath, i + 1,
330 unit=_('files'), total=total)
330 unit=_('files'), total=total)
331 ui.progress(_('archiving (%s)') % relpath, None)
331 ui.progress(_('archiving (%s)') % relpath, None)
332
332
333
333
334 class hgsubrepo(abstractsubrepo):
334 class hgsubrepo(abstractsubrepo):
335 def __init__(self, ctx, path, state):
335 def __init__(self, ctx, path, state):
336 self._path = path
336 self._path = path
337 self._state = state
337 self._state = state
338 r = ctx._repo
338 r = ctx._repo
339 root = r.wjoin(path)
339 root = r.wjoin(path)
340 create = False
340 create = False
341 if not os.path.exists(os.path.join(root, '.hg')):
341 if not os.path.exists(os.path.join(root, '.hg')):
342 create = True
342 create = True
343 util.makedirs(root)
343 util.makedirs(root)
344 self._repo = hg.repository(r.ui, root, create=create)
344 self._repo = hg.repository(r.ui, root, create=create)
345 self._repo._subparent = r
345 self._initrepo(r, state[0], create)
346 self._repo._subsource = state[0]
346
347 def _initrepo(self, parentrepo, source, create):
348 self._repo._subparent = parentrepo
349 self._repo._subsource = source
347
350
348 if create:
351 if create:
349 fp = self._repo.opener("hgrc", "w", text=True)
352 fp = self._repo.opener("hgrc", "w", text=True)
350 fp.write('[paths]\n')
353 fp.write('[paths]\n')
351
354
352 def addpathconfig(key, value):
355 def addpathconfig(key, value):
353 if value:
356 if value:
354 fp.write('%s = %s\n' % (key, value))
357 fp.write('%s = %s\n' % (key, value))
355 self._repo.ui.setconfig('paths', key, value)
358 self._repo.ui.setconfig('paths', key, value)
356
359
357 defpath = _abssource(self._repo, abort=False)
360 defpath = _abssource(self._repo, abort=False)
358 defpushpath = _abssource(self._repo, True, abort=False)
361 defpushpath = _abssource(self._repo, True, abort=False)
359 addpathconfig('default', defpath)
362 addpathconfig('default', defpath)
360 if defpath != defpushpath:
363 if defpath != defpushpath:
361 addpathconfig('default-push', defpushpath)
364 addpathconfig('default-push', defpushpath)
362 fp.close()
365 fp.close()
363
366
364 def add(self, ui, match, dryrun, prefix):
367 def add(self, ui, match, dryrun, prefix):
365 return cmdutil.add(ui, self._repo, match, dryrun, True,
368 return cmdutil.add(ui, self._repo, match, dryrun, True,
366 os.path.join(prefix, self._path))
369 os.path.join(prefix, self._path))
367
370
368 def status(self, rev2, **opts):
371 def status(self, rev2, **opts):
369 try:
372 try:
370 rev1 = self._state[1]
373 rev1 = self._state[1]
371 ctx1 = self._repo[rev1]
374 ctx1 = self._repo[rev1]
372 ctx2 = self._repo[rev2]
375 ctx2 = self._repo[rev2]
373 return self._repo.status(ctx1, ctx2, **opts)
376 return self._repo.status(ctx1, ctx2, **opts)
374 except error.RepoLookupError, inst:
377 except error.RepoLookupError, inst:
375 self._repo.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
378 self._repo.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
376 % (inst, subrelpath(self)))
379 % (inst, subrelpath(self)))
377 return [], [], [], [], [], [], []
380 return [], [], [], [], [], [], []
378
381
379 def diff(self, diffopts, node2, match, prefix, **opts):
382 def diff(self, diffopts, node2, match, prefix, **opts):
380 try:
383 try:
381 node1 = node.bin(self._state[1])
384 node1 = node.bin(self._state[1])
382 # We currently expect node2 to come from substate and be
385 # We currently expect node2 to come from substate and be
383 # in hex format
386 # in hex format
384 if node2 is not None:
387 if node2 is not None:
385 node2 = node.bin(node2)
388 node2 = node.bin(node2)
386 cmdutil.diffordiffstat(self._repo.ui, self._repo, diffopts,
389 cmdutil.diffordiffstat(self._repo.ui, self._repo, diffopts,
387 node1, node2, match,
390 node1, node2, match,
388 prefix=os.path.join(prefix, self._path),
391 prefix=os.path.join(prefix, self._path),
389 listsubrepos=True, **opts)
392 listsubrepos=True, **opts)
390 except error.RepoLookupError, inst:
393 except error.RepoLookupError, inst:
391 self._repo.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
394 self._repo.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
392 % (inst, subrelpath(self)))
395 % (inst, subrelpath(self)))
393
396
394 def archive(self, ui, archiver, prefix):
397 def archive(self, ui, archiver, prefix):
395 abstractsubrepo.archive(self, ui, archiver, prefix)
398 abstractsubrepo.archive(self, ui, archiver, prefix)
396
399
397 rev = self._state[1]
400 rev = self._state[1]
398 ctx = self._repo[rev]
401 ctx = self._repo[rev]
399 for subpath in ctx.substate:
402 for subpath in ctx.substate:
400 s = subrepo(ctx, subpath)
403 s = subrepo(ctx, subpath)
401 s.archive(ui, archiver, os.path.join(prefix, self._path))
404 s.archive(ui, archiver, os.path.join(prefix, self._path))
402
405
403 def dirty(self, ignoreupdate=False):
406 def dirty(self, ignoreupdate=False):
404 r = self._state[1]
407 r = self._state[1]
405 if r == '' and not ignoreupdate: # no state recorded
408 if r == '' and not ignoreupdate: # no state recorded
406 return True
409 return True
407 w = self._repo[None]
410 w = self._repo[None]
408 if w.p1() != self._repo[r] and not ignoreupdate:
411 if w.p1() != self._repo[r] and not ignoreupdate:
409 # different version checked out
412 # different version checked out
410 return True
413 return True
411 return w.dirty() # working directory changed
414 return w.dirty() # working directory changed
412
415
413 def checknested(self, path):
416 def checknested(self, path):
414 return self._repo._checknested(self._repo.wjoin(path))
417 return self._repo._checknested(self._repo.wjoin(path))
415
418
416 def commit(self, text, user, date):
419 def commit(self, text, user, date):
417 self._repo.ui.debug("committing subrepo %s\n" % subrelpath(self))
420 self._repo.ui.debug("committing subrepo %s\n" % subrelpath(self))
418 n = self._repo.commit(text, user, date)
421 n = self._repo.commit(text, user, date)
419 if not n:
422 if not n:
420 return self._repo['.'].hex() # different version checked out
423 return self._repo['.'].hex() # different version checked out
421 return node.hex(n)
424 return node.hex(n)
422
425
423 def remove(self):
426 def remove(self):
424 # we can't fully delete the repository as it may contain
427 # we can't fully delete the repository as it may contain
425 # local-only history
428 # local-only history
426 self._repo.ui.note(_('removing subrepo %s\n') % subrelpath(self))
429 self._repo.ui.note(_('removing subrepo %s\n') % subrelpath(self))
427 hg.clean(self._repo, node.nullid, False)
430 hg.clean(self._repo, node.nullid, False)
428
431
429 def _get(self, state):
432 def _get(self, state):
430 source, revision, kind = state
433 source, revision, kind = state
431 if revision not in self._repo:
434 if revision not in self._repo:
432 self._repo._subsource = source
435 self._repo._subsource = source
433 srcurl = _abssource(self._repo)
436 srcurl = _abssource(self._repo)
434 self._repo.ui.status(_('pulling subrepo %s from %s\n')
435 % (subrelpath(self), srcurl))
436 other = hg.repository(self._repo.ui, srcurl)
437 other = hg.repository(self._repo.ui, srcurl)
437 self._repo.pull(other)
438 if len(self._repo) == 0:
439 self._repo.ui.status(_('cloning subrepo %s from %s\n')
440 % (subrelpath(self), srcurl))
441 parentrepo = self._repo._subparent
442 shutil.rmtree(self._repo.root)
443 other, self._repo = hg.clone(self._repo._subparent.ui, other,
444 self._repo.root, update=False)
445 self._initrepo(parentrepo, source, create=True)
446 else:
447 self._repo.ui.status(_('pulling subrepo %s from %s\n')
448 % (subrelpath(self), srcurl))
449 self._repo.pull(other)
438 bookmarks.updatefromremote(self._repo.ui, self._repo, other)
450 bookmarks.updatefromremote(self._repo.ui, self._repo, other)
439
451
440 def get(self, state, overwrite=False):
452 def get(self, state, overwrite=False):
441 self._get(state)
453 self._get(state)
442 source, revision, kind = state
454 source, revision, kind = state
443 self._repo.ui.debug("getting subrepo %s\n" % self._path)
455 self._repo.ui.debug("getting subrepo %s\n" % self._path)
444 hg.clean(self._repo, revision, False)
456 hg.clean(self._repo, revision, False)
445
457
446 def merge(self, state):
458 def merge(self, state):
447 self._get(state)
459 self._get(state)
448 cur = self._repo['.']
460 cur = self._repo['.']
449 dst = self._repo[state[1]]
461 dst = self._repo[state[1]]
450 anc = dst.ancestor(cur)
462 anc = dst.ancestor(cur)
451
463
452 def mergefunc():
464 def mergefunc():
453 if anc == cur:
465 if anc == cur:
454 self._repo.ui.debug("updating subrepo %s\n" % subrelpath(self))
466 self._repo.ui.debug("updating subrepo %s\n" % subrelpath(self))
455 hg.update(self._repo, state[1])
467 hg.update(self._repo, state[1])
456 elif anc == dst:
468 elif anc == dst:
457 self._repo.ui.debug("skipping subrepo %s\n" % subrelpath(self))
469 self._repo.ui.debug("skipping subrepo %s\n" % subrelpath(self))
458 else:
470 else:
459 self._repo.ui.debug("merging subrepo %s\n" % subrelpath(self))
471 self._repo.ui.debug("merging subrepo %s\n" % subrelpath(self))
460 hg.merge(self._repo, state[1], remind=False)
472 hg.merge(self._repo, state[1], remind=False)
461
473
462 wctx = self._repo[None]
474 wctx = self._repo[None]
463 if self.dirty():
475 if self.dirty():
464 if anc != dst:
476 if anc != dst:
465 if _updateprompt(self._repo.ui, self, wctx.dirty(), cur, dst):
477 if _updateprompt(self._repo.ui, self, wctx.dirty(), cur, dst):
466 mergefunc()
478 mergefunc()
467 else:
479 else:
468 mergefunc()
480 mergefunc()
469 else:
481 else:
470 mergefunc()
482 mergefunc()
471
483
472 def push(self, force):
484 def push(self, force):
473 # push subrepos depth-first for coherent ordering
485 # push subrepos depth-first for coherent ordering
474 c = self._repo['']
486 c = self._repo['']
475 subs = c.substate # only repos that are committed
487 subs = c.substate # only repos that are committed
476 for s in sorted(subs):
488 for s in sorted(subs):
477 if not c.sub(s).push(force):
489 if not c.sub(s).push(force):
478 return False
490 return False
479
491
480 dsturl = _abssource(self._repo, True)
492 dsturl = _abssource(self._repo, True)
481 self._repo.ui.status(_('pushing subrepo %s to %s\n') %
493 self._repo.ui.status(_('pushing subrepo %s to %s\n') %
482 (subrelpath(self), dsturl))
494 (subrelpath(self), dsturl))
483 other = hg.repository(self._repo.ui, dsturl)
495 other = hg.repository(self._repo.ui, dsturl)
484 return self._repo.push(other, force)
496 return self._repo.push(other, force)
485
497
486 def outgoing(self, ui, dest, opts):
498 def outgoing(self, ui, dest, opts):
487 return hg.outgoing(ui, self._repo, _abssource(self._repo, True), opts)
499 return hg.outgoing(ui, self._repo, _abssource(self._repo, True), opts)
488
500
489 def incoming(self, ui, source, opts):
501 def incoming(self, ui, source, opts):
490 return hg.incoming(ui, self._repo, _abssource(self._repo, False), opts)
502 return hg.incoming(ui, self._repo, _abssource(self._repo, False), opts)
491
503
492 def files(self):
504 def files(self):
493 rev = self._state[1]
505 rev = self._state[1]
494 ctx = self._repo[rev]
506 ctx = self._repo[rev]
495 return ctx.manifest()
507 return ctx.manifest()
496
508
497 def filedata(self, name):
509 def filedata(self, name):
498 rev = self._state[1]
510 rev = self._state[1]
499 return self._repo[rev][name].data()
511 return self._repo[rev][name].data()
500
512
501 def fileflags(self, name):
513 def fileflags(self, name):
502 rev = self._state[1]
514 rev = self._state[1]
503 ctx = self._repo[rev]
515 ctx = self._repo[rev]
504 return ctx.flags(name)
516 return ctx.flags(name)
505
517
506
518
507 class svnsubrepo(abstractsubrepo):
519 class svnsubrepo(abstractsubrepo):
508 def __init__(self, ctx, path, state):
520 def __init__(self, ctx, path, state):
509 self._path = path
521 self._path = path
510 self._state = state
522 self._state = state
511 self._ctx = ctx
523 self._ctx = ctx
512 self._ui = ctx._repo.ui
524 self._ui = ctx._repo.ui
513
525
514 def _svncommand(self, commands, filename=''):
526 def _svncommand(self, commands, filename=''):
515 cmd = ['svn']
527 cmd = ['svn']
516 # Starting in svn 1.5 --non-interactive is a global flag
528 # Starting in svn 1.5 --non-interactive is a global flag
517 # instead of being per-command, but we need to support 1.4 so
529 # instead of being per-command, but we need to support 1.4 so
518 # we have to be intelligent about what commands take
530 # we have to be intelligent about what commands take
519 # --non-interactive.
531 # --non-interactive.
520 if (not self._ui.interactive() and
532 if (not self._ui.interactive() and
521 commands[0] in ('update', 'checkout', 'commit')):
533 commands[0] in ('update', 'checkout', 'commit')):
522 cmd.append('--non-interactive')
534 cmd.append('--non-interactive')
523 cmd.extend(commands)
535 cmd.extend(commands)
524 if filename is not None:
536 if filename is not None:
525 path = os.path.join(self._ctx._repo.origroot, self._path, filename)
537 path = os.path.join(self._ctx._repo.origroot, self._path, filename)
526 cmd.append(path)
538 cmd.append(path)
527 env = dict(os.environ)
539 env = dict(os.environ)
528 # Avoid localized output, preserve current locale for everything else.
540 # Avoid localized output, preserve current locale for everything else.
529 env['LC_MESSAGES'] = 'C'
541 env['LC_MESSAGES'] = 'C'
530 p = subprocess.Popen(cmd, bufsize=-1, close_fds=util.closefds,
542 p = subprocess.Popen(cmd, bufsize=-1, close_fds=util.closefds,
531 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
543 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
532 universal_newlines=True, env=env)
544 universal_newlines=True, env=env)
533 stdout, stderr = p.communicate()
545 stdout, stderr = p.communicate()
534 stderr = stderr.strip()
546 stderr = stderr.strip()
535 if stderr:
547 if stderr:
536 raise util.Abort(stderr)
548 raise util.Abort(stderr)
537 return stdout
549 return stdout
538
550
539 @propertycache
551 @propertycache
540 def _svnversion(self):
552 def _svnversion(self):
541 output = self._svncommand(['--version'], filename=None)
553 output = self._svncommand(['--version'], filename=None)
542 m = re.search(r'^svn,\s+version\s+(\d+)\.(\d+)', output)
554 m = re.search(r'^svn,\s+version\s+(\d+)\.(\d+)', output)
543 if not m:
555 if not m:
544 raise util.Abort(_('cannot retrieve svn tool version'))
556 raise util.Abort(_('cannot retrieve svn tool version'))
545 return (int(m.group(1)), int(m.group(2)))
557 return (int(m.group(1)), int(m.group(2)))
546
558
547 def _wcrevs(self):
559 def _wcrevs(self):
548 # Get the working directory revision as well as the last
560 # Get the working directory revision as well as the last
549 # commit revision so we can compare the subrepo state with
561 # commit revision so we can compare the subrepo state with
550 # both. We used to store the working directory one.
562 # both. We used to store the working directory one.
551 output = self._svncommand(['info', '--xml'])
563 output = self._svncommand(['info', '--xml'])
552 doc = xml.dom.minidom.parseString(output)
564 doc = xml.dom.minidom.parseString(output)
553 entries = doc.getElementsByTagName('entry')
565 entries = doc.getElementsByTagName('entry')
554 lastrev, rev = '0', '0'
566 lastrev, rev = '0', '0'
555 if entries:
567 if entries:
556 rev = str(entries[0].getAttribute('revision')) or '0'
568 rev = str(entries[0].getAttribute('revision')) or '0'
557 commits = entries[0].getElementsByTagName('commit')
569 commits = entries[0].getElementsByTagName('commit')
558 if commits:
570 if commits:
559 lastrev = str(commits[0].getAttribute('revision')) or '0'
571 lastrev = str(commits[0].getAttribute('revision')) or '0'
560 return (lastrev, rev)
572 return (lastrev, rev)
561
573
562 def _wcrev(self):
574 def _wcrev(self):
563 return self._wcrevs()[0]
575 return self._wcrevs()[0]
564
576
565 def _wcchanged(self):
577 def _wcchanged(self):
566 """Return (changes, extchanges) where changes is True
578 """Return (changes, extchanges) where changes is True
567 if the working directory was changed, and extchanges is
579 if the working directory was changed, and extchanges is
568 True if any of these changes concern an external entry.
580 True if any of these changes concern an external entry.
569 """
581 """
570 output = self._svncommand(['status', '--xml'])
582 output = self._svncommand(['status', '--xml'])
571 externals, changes = [], []
583 externals, changes = [], []
572 doc = xml.dom.minidom.parseString(output)
584 doc = xml.dom.minidom.parseString(output)
573 for e in doc.getElementsByTagName('entry'):
585 for e in doc.getElementsByTagName('entry'):
574 s = e.getElementsByTagName('wc-status')
586 s = e.getElementsByTagName('wc-status')
575 if not s:
587 if not s:
576 continue
588 continue
577 item = s[0].getAttribute('item')
589 item = s[0].getAttribute('item')
578 props = s[0].getAttribute('props')
590 props = s[0].getAttribute('props')
579 path = e.getAttribute('path')
591 path = e.getAttribute('path')
580 if item == 'external':
592 if item == 'external':
581 externals.append(path)
593 externals.append(path)
582 if (item not in ('', 'normal', 'unversioned', 'external')
594 if (item not in ('', 'normal', 'unversioned', 'external')
583 or props not in ('', 'none')):
595 or props not in ('', 'none')):
584 changes.append(path)
596 changes.append(path)
585 for path in changes:
597 for path in changes:
586 for ext in externals:
598 for ext in externals:
587 if path == ext or path.startswith(ext + os.sep):
599 if path == ext or path.startswith(ext + os.sep):
588 return True, True
600 return True, True
589 return bool(changes), False
601 return bool(changes), False
590
602
591 def dirty(self, ignoreupdate=False):
603 def dirty(self, ignoreupdate=False):
592 if not self._wcchanged()[0]:
604 if not self._wcchanged()[0]:
593 if self._state[1] in self._wcrevs() or ignoreupdate:
605 if self._state[1] in self._wcrevs() or ignoreupdate:
594 return False
606 return False
595 return True
607 return True
596
608
597 def commit(self, text, user, date):
609 def commit(self, text, user, date):
598 # user and date are out of our hands since svn is centralized
610 # user and date are out of our hands since svn is centralized
599 changed, extchanged = self._wcchanged()
611 changed, extchanged = self._wcchanged()
600 if not changed:
612 if not changed:
601 return self._wcrev()
613 return self._wcrev()
602 if extchanged:
614 if extchanged:
603 # Do not try to commit externals
615 # Do not try to commit externals
604 raise util.Abort(_('cannot commit svn externals'))
616 raise util.Abort(_('cannot commit svn externals'))
605 commitinfo = self._svncommand(['commit', '-m', text])
617 commitinfo = self._svncommand(['commit', '-m', text])
606 self._ui.status(commitinfo)
618 self._ui.status(commitinfo)
607 newrev = re.search('Committed revision ([0-9]+).', commitinfo)
619 newrev = re.search('Committed revision ([0-9]+).', commitinfo)
608 if not newrev:
620 if not newrev:
609 raise util.Abort(commitinfo.splitlines()[-1])
621 raise util.Abort(commitinfo.splitlines()[-1])
610 newrev = newrev.groups()[0]
622 newrev = newrev.groups()[0]
611 self._ui.status(self._svncommand(['update', '-r', newrev]))
623 self._ui.status(self._svncommand(['update', '-r', newrev]))
612 return newrev
624 return newrev
613
625
614 def remove(self):
626 def remove(self):
615 if self.dirty():
627 if self.dirty():
616 self._ui.warn(_('not removing repo %s because '
628 self._ui.warn(_('not removing repo %s because '
617 'it has changes.\n' % self._path))
629 'it has changes.\n' % self._path))
618 return
630 return
619 self._ui.note(_('removing subrepo %s\n') % self._path)
631 self._ui.note(_('removing subrepo %s\n') % self._path)
620
632
621 def onerror(function, path, excinfo):
633 def onerror(function, path, excinfo):
622 if function is not os.remove:
634 if function is not os.remove:
623 raise
635 raise
624 # read-only files cannot be unlinked under Windows
636 # read-only files cannot be unlinked under Windows
625 s = os.stat(path)
637 s = os.stat(path)
626 if (s.st_mode & stat.S_IWRITE) != 0:
638 if (s.st_mode & stat.S_IWRITE) != 0:
627 raise
639 raise
628 os.chmod(path, stat.S_IMODE(s.st_mode) | stat.S_IWRITE)
640 os.chmod(path, stat.S_IMODE(s.st_mode) | stat.S_IWRITE)
629 os.remove(path)
641 os.remove(path)
630
642
631 path = self._ctx._repo.wjoin(self._path)
643 path = self._ctx._repo.wjoin(self._path)
632 shutil.rmtree(path, onerror=onerror)
644 shutil.rmtree(path, onerror=onerror)
633 try:
645 try:
634 os.removedirs(os.path.dirname(path))
646 os.removedirs(os.path.dirname(path))
635 except OSError:
647 except OSError:
636 pass
648 pass
637
649
638 def get(self, state, overwrite=False):
650 def get(self, state, overwrite=False):
639 if overwrite:
651 if overwrite:
640 self._svncommand(['revert', '--recursive'])
652 self._svncommand(['revert', '--recursive'])
641 args = ['checkout']
653 args = ['checkout']
642 if self._svnversion >= (1, 5):
654 if self._svnversion >= (1, 5):
643 args.append('--force')
655 args.append('--force')
644 args.extend([state[0], '--revision', state[1]])
656 args.extend([state[0], '--revision', state[1]])
645 status = self._svncommand(args)
657 status = self._svncommand(args)
646 if not re.search('Checked out revision [0-9]+.', status):
658 if not re.search('Checked out revision [0-9]+.', status):
647 raise util.Abort(status.splitlines()[-1])
659 raise util.Abort(status.splitlines()[-1])
648 self._ui.status(status)
660 self._ui.status(status)
649
661
650 def merge(self, state):
662 def merge(self, state):
651 old = self._state[1]
663 old = self._state[1]
652 new = state[1]
664 new = state[1]
653 if new != self._wcrev():
665 if new != self._wcrev():
654 dirty = old == self._wcrev() or self._wcchanged()[0]
666 dirty = old == self._wcrev() or self._wcchanged()[0]
655 if _updateprompt(self._ui, self, dirty, self._wcrev(), new):
667 if _updateprompt(self._ui, self, dirty, self._wcrev(), new):
656 self.get(state, False)
668 self.get(state, False)
657
669
658 def push(self, force):
670 def push(self, force):
659 # push is a no-op for SVN
671 # push is a no-op for SVN
660 return True
672 return True
661
673
662 def files(self):
674 def files(self):
663 output = self._svncommand(['list'])
675 output = self._svncommand(['list'])
664 # This works because svn forbids \n in filenames.
676 # This works because svn forbids \n in filenames.
665 return output.splitlines()
677 return output.splitlines()
666
678
667 def filedata(self, name):
679 def filedata(self, name):
668 return self._svncommand(['cat'], name)
680 return self._svncommand(['cat'], name)
669
681
670
682
671 class gitsubrepo(abstractsubrepo):
683 class gitsubrepo(abstractsubrepo):
672 def __init__(self, ctx, path, state):
684 def __init__(self, ctx, path, state):
673 # TODO add git version check.
685 # TODO add git version check.
674 self._state = state
686 self._state = state
675 self._ctx = ctx
687 self._ctx = ctx
676 self._path = path
688 self._path = path
677 self._relpath = os.path.join(reporelpath(ctx._repo), path)
689 self._relpath = os.path.join(reporelpath(ctx._repo), path)
678 self._abspath = ctx._repo.wjoin(path)
690 self._abspath = ctx._repo.wjoin(path)
679 self._subparent = ctx._repo
691 self._subparent = ctx._repo
680 self._ui = ctx._repo.ui
692 self._ui = ctx._repo.ui
681
693
682 def _gitcommand(self, commands, env=None, stream=False):
694 def _gitcommand(self, commands, env=None, stream=False):
683 return self._gitdir(commands, env=env, stream=stream)[0]
695 return self._gitdir(commands, env=env, stream=stream)[0]
684
696
685 def _gitdir(self, commands, env=None, stream=False):
697 def _gitdir(self, commands, env=None, stream=False):
686 return self._gitnodir(commands, env=env, stream=stream,
698 return self._gitnodir(commands, env=env, stream=stream,
687 cwd=self._abspath)
699 cwd=self._abspath)
688
700
689 def _gitnodir(self, commands, env=None, stream=False, cwd=None):
701 def _gitnodir(self, commands, env=None, stream=False, cwd=None):
690 """Calls the git command
702 """Calls the git command
691
703
692 The methods tries to call the git command. versions previor to 1.6.0
704 The methods tries to call the git command. versions previor to 1.6.0
693 are not supported and very probably fail.
705 are not supported and very probably fail.
694 """
706 """
695 self._ui.debug('%s: git %s\n' % (self._relpath, ' '.join(commands)))
707 self._ui.debug('%s: git %s\n' % (self._relpath, ' '.join(commands)))
696 # unless ui.quiet is set, print git's stderr,
708 # unless ui.quiet is set, print git's stderr,
697 # which is mostly progress and useful info
709 # which is mostly progress and useful info
698 errpipe = None
710 errpipe = None
699 if self._ui.quiet:
711 if self._ui.quiet:
700 errpipe = open(os.devnull, 'w')
712 errpipe = open(os.devnull, 'w')
701 p = subprocess.Popen(['git'] + commands, bufsize=-1, cwd=cwd, env=env,
713 p = subprocess.Popen(['git'] + commands, bufsize=-1, cwd=cwd, env=env,
702 close_fds=util.closefds,
714 close_fds=util.closefds,
703 stdout=subprocess.PIPE, stderr=errpipe)
715 stdout=subprocess.PIPE, stderr=errpipe)
704 if stream:
716 if stream:
705 return p.stdout, None
717 return p.stdout, None
706
718
707 retdata = p.stdout.read().strip()
719 retdata = p.stdout.read().strip()
708 # wait for the child to exit to avoid race condition.
720 # wait for the child to exit to avoid race condition.
709 p.wait()
721 p.wait()
710
722
711 if p.returncode != 0 and p.returncode != 1:
723 if p.returncode != 0 and p.returncode != 1:
712 # there are certain error codes that are ok
724 # there are certain error codes that are ok
713 command = commands[0]
725 command = commands[0]
714 if command in ('cat-file', 'symbolic-ref'):
726 if command in ('cat-file', 'symbolic-ref'):
715 return retdata, p.returncode
727 return retdata, p.returncode
716 # for all others, abort
728 # for all others, abort
717 raise util.Abort('git %s error %d in %s' %
729 raise util.Abort('git %s error %d in %s' %
718 (command, p.returncode, self._relpath))
730 (command, p.returncode, self._relpath))
719
731
720 return retdata, p.returncode
732 return retdata, p.returncode
721
733
722 def _gitmissing(self):
734 def _gitmissing(self):
723 return not os.path.exists(os.path.join(self._abspath, '.git'))
735 return not os.path.exists(os.path.join(self._abspath, '.git'))
724
736
725 def _gitstate(self):
737 def _gitstate(self):
726 return self._gitcommand(['rev-parse', 'HEAD'])
738 return self._gitcommand(['rev-parse', 'HEAD'])
727
739
728 def _gitcurrentbranch(self):
740 def _gitcurrentbranch(self):
729 current, err = self._gitdir(['symbolic-ref', 'HEAD', '--quiet'])
741 current, err = self._gitdir(['symbolic-ref', 'HEAD', '--quiet'])
730 if err:
742 if err:
731 current = None
743 current = None
732 return current
744 return current
733
745
734 def _gitremote(self, remote):
746 def _gitremote(self, remote):
735 out = self._gitcommand(['remote', 'show', '-n', remote])
747 out = self._gitcommand(['remote', 'show', '-n', remote])
736 line = out.split('\n')[1]
748 line = out.split('\n')[1]
737 i = line.index('URL: ') + len('URL: ')
749 i = line.index('URL: ') + len('URL: ')
738 return line[i:]
750 return line[i:]
739
751
740 def _githavelocally(self, revision):
752 def _githavelocally(self, revision):
741 out, code = self._gitdir(['cat-file', '-e', revision])
753 out, code = self._gitdir(['cat-file', '-e', revision])
742 return code == 0
754 return code == 0
743
755
744 def _gitisancestor(self, r1, r2):
756 def _gitisancestor(self, r1, r2):
745 base = self._gitcommand(['merge-base', r1, r2])
757 base = self._gitcommand(['merge-base', r1, r2])
746 return base == r1
758 return base == r1
747
759
748 def _gitbranchmap(self):
760 def _gitbranchmap(self):
749 '''returns 2 things:
761 '''returns 2 things:
750 a map from git branch to revision
762 a map from git branch to revision
751 a map from revision to branches'''
763 a map from revision to branches'''
752 branch2rev = {}
764 branch2rev = {}
753 rev2branch = {}
765 rev2branch = {}
754
766
755 out = self._gitcommand(['for-each-ref', '--format',
767 out = self._gitcommand(['for-each-ref', '--format',
756 '%(objectname) %(refname)'])
768 '%(objectname) %(refname)'])
757 for line in out.split('\n'):
769 for line in out.split('\n'):
758 revision, ref = line.split(' ')
770 revision, ref = line.split(' ')
759 if (not ref.startswith('refs/heads/') and
771 if (not ref.startswith('refs/heads/') and
760 not ref.startswith('refs/remotes/')):
772 not ref.startswith('refs/remotes/')):
761 continue
773 continue
762 if ref.startswith('refs/remotes/') and ref.endswith('/HEAD'):
774 if ref.startswith('refs/remotes/') and ref.endswith('/HEAD'):
763 continue # ignore remote/HEAD redirects
775 continue # ignore remote/HEAD redirects
764 branch2rev[ref] = revision
776 branch2rev[ref] = revision
765 rev2branch.setdefault(revision, []).append(ref)
777 rev2branch.setdefault(revision, []).append(ref)
766 return branch2rev, rev2branch
778 return branch2rev, rev2branch
767
779
768 def _gittracking(self, branches):
780 def _gittracking(self, branches):
769 'return map of remote branch to local tracking branch'
781 'return map of remote branch to local tracking branch'
770 # assumes no more than one local tracking branch for each remote
782 # assumes no more than one local tracking branch for each remote
771 tracking = {}
783 tracking = {}
772 for b in branches:
784 for b in branches:
773 if b.startswith('refs/remotes/'):
785 if b.startswith('refs/remotes/'):
774 continue
786 continue
775 remote = self._gitcommand(['config', 'branch.%s.remote' % b])
787 remote = self._gitcommand(['config', 'branch.%s.remote' % b])
776 if remote:
788 if remote:
777 ref = self._gitcommand(['config', 'branch.%s.merge' % b])
789 ref = self._gitcommand(['config', 'branch.%s.merge' % b])
778 tracking['refs/remotes/%s/%s' %
790 tracking['refs/remotes/%s/%s' %
779 (remote, ref.split('/', 2)[2])] = b
791 (remote, ref.split('/', 2)[2])] = b
780 return tracking
792 return tracking
781
793
782 def _abssource(self, source):
794 def _abssource(self, source):
783 if '://' not in source:
795 if '://' not in source:
784 # recognize the scp syntax as an absolute source
796 # recognize the scp syntax as an absolute source
785 colon = source.find(':')
797 colon = source.find(':')
786 if colon != -1 and '/' not in source[:colon]:
798 if colon != -1 and '/' not in source[:colon]:
787 return source
799 return source
788 self._subsource = source
800 self._subsource = source
789 return _abssource(self)
801 return _abssource(self)
790
802
791 def _fetch(self, source, revision):
803 def _fetch(self, source, revision):
792 if self._gitmissing():
804 if self._gitmissing():
793 source = self._abssource(source)
805 source = self._abssource(source)
794 self._ui.status(_('cloning subrepo %s from %s\n') %
806 self._ui.status(_('cloning subrepo %s from %s\n') %
795 (self._relpath, source))
807 (self._relpath, source))
796 self._gitnodir(['clone', source, self._abspath])
808 self._gitnodir(['clone', source, self._abspath])
797 if self._githavelocally(revision):
809 if self._githavelocally(revision):
798 return
810 return
799 self._ui.status(_('pulling subrepo %s from %s\n') %
811 self._ui.status(_('pulling subrepo %s from %s\n') %
800 (self._relpath, self._gitremote('origin')))
812 (self._relpath, self._gitremote('origin')))
801 # try only origin: the originally cloned repo
813 # try only origin: the originally cloned repo
802 self._gitcommand(['fetch'])
814 self._gitcommand(['fetch'])
803 if not self._githavelocally(revision):
815 if not self._githavelocally(revision):
804 raise util.Abort(_("revision %s does not exist in subrepo %s\n") %
816 raise util.Abort(_("revision %s does not exist in subrepo %s\n") %
805 (revision, self._relpath))
817 (revision, self._relpath))
806
818
807 def dirty(self, ignoreupdate=False):
819 def dirty(self, ignoreupdate=False):
808 if self._gitmissing():
820 if self._gitmissing():
809 return True
821 return True
810 if not ignoreupdate and self._state[1] != self._gitstate():
822 if not ignoreupdate and self._state[1] != self._gitstate():
811 # different version checked out
823 # different version checked out
812 return True
824 return True
813 # check for staged changes or modified files; ignore untracked files
825 # check for staged changes or modified files; ignore untracked files
814 out, code = self._gitdir(['diff-index', '--quiet', 'HEAD'])
826 out, code = self._gitdir(['diff-index', '--quiet', 'HEAD'])
815 return code == 1
827 return code == 1
816
828
817 def get(self, state, overwrite=False):
829 def get(self, state, overwrite=False):
818 source, revision, kind = state
830 source, revision, kind = state
819 self._fetch(source, revision)
831 self._fetch(source, revision)
820 # if the repo was set to be bare, unbare it
832 # if the repo was set to be bare, unbare it
821 if self._gitcommand(['config', '--bool', 'core.bare']) == 'true':
833 if self._gitcommand(['config', '--bool', 'core.bare']) == 'true':
822 self._gitcommand(['config', 'core.bare', 'false'])
834 self._gitcommand(['config', 'core.bare', 'false'])
823 if self._gitstate() == revision:
835 if self._gitstate() == revision:
824 self._gitcommand(['reset', '--hard', 'HEAD'])
836 self._gitcommand(['reset', '--hard', 'HEAD'])
825 return
837 return
826 elif self._gitstate() == revision:
838 elif self._gitstate() == revision:
827 if overwrite:
839 if overwrite:
828 # first reset the index to unmark new files for commit, because
840 # first reset the index to unmark new files for commit, because
829 # reset --hard will otherwise throw away files added for commit,
841 # reset --hard will otherwise throw away files added for commit,
830 # not just unmark them.
842 # not just unmark them.
831 self._gitcommand(['reset', 'HEAD'])
843 self._gitcommand(['reset', 'HEAD'])
832 self._gitcommand(['reset', '--hard', 'HEAD'])
844 self._gitcommand(['reset', '--hard', 'HEAD'])
833 return
845 return
834 branch2rev, rev2branch = self._gitbranchmap()
846 branch2rev, rev2branch = self._gitbranchmap()
835
847
836 def checkout(args):
848 def checkout(args):
837 cmd = ['checkout']
849 cmd = ['checkout']
838 if overwrite:
850 if overwrite:
839 # first reset the index to unmark new files for commit, because
851 # first reset the index to unmark new files for commit, because
840 # the -f option will otherwise throw away files added for
852 # the -f option will otherwise throw away files added for
841 # commit, not just unmark them.
853 # commit, not just unmark them.
842 self._gitcommand(['reset', 'HEAD'])
854 self._gitcommand(['reset', 'HEAD'])
843 cmd.append('-f')
855 cmd.append('-f')
844 self._gitcommand(cmd + args)
856 self._gitcommand(cmd + args)
845
857
846 def rawcheckout():
858 def rawcheckout():
847 # no branch to checkout, check it out with no branch
859 # no branch to checkout, check it out with no branch
848 self._ui.warn(_('checking out detached HEAD in subrepo %s\n') %
860 self._ui.warn(_('checking out detached HEAD in subrepo %s\n') %
849 self._relpath)
861 self._relpath)
850 self._ui.warn(_('check out a git branch if you intend '
862 self._ui.warn(_('check out a git branch if you intend '
851 'to make changes\n'))
863 'to make changes\n'))
852 checkout(['-q', revision])
864 checkout(['-q', revision])
853
865
854 if revision not in rev2branch:
866 if revision not in rev2branch:
855 rawcheckout()
867 rawcheckout()
856 return
868 return
857 branches = rev2branch[revision]
869 branches = rev2branch[revision]
858 firstlocalbranch = None
870 firstlocalbranch = None
859 for b in branches:
871 for b in branches:
860 if b == 'refs/heads/master':
872 if b == 'refs/heads/master':
861 # master trumps all other branches
873 # master trumps all other branches
862 checkout(['refs/heads/master'])
874 checkout(['refs/heads/master'])
863 return
875 return
864 if not firstlocalbranch and not b.startswith('refs/remotes/'):
876 if not firstlocalbranch and not b.startswith('refs/remotes/'):
865 firstlocalbranch = b
877 firstlocalbranch = b
866 if firstlocalbranch:
878 if firstlocalbranch:
867 checkout([firstlocalbranch])
879 checkout([firstlocalbranch])
868 return
880 return
869
881
870 tracking = self._gittracking(branch2rev.keys())
882 tracking = self._gittracking(branch2rev.keys())
871 # choose a remote branch already tracked if possible
883 # choose a remote branch already tracked if possible
872 remote = branches[0]
884 remote = branches[0]
873 if remote not in tracking:
885 if remote not in tracking:
874 for b in branches:
886 for b in branches:
875 if b in tracking:
887 if b in tracking:
876 remote = b
888 remote = b
877 break
889 break
878
890
879 if remote not in tracking:
891 if remote not in tracking:
880 # create a new local tracking branch
892 # create a new local tracking branch
881 local = remote.split('/', 2)[2]
893 local = remote.split('/', 2)[2]
882 checkout(['-b', local, remote])
894 checkout(['-b', local, remote])
883 elif self._gitisancestor(branch2rev[tracking[remote]], remote):
895 elif self._gitisancestor(branch2rev[tracking[remote]], remote):
884 # When updating to a tracked remote branch,
896 # When updating to a tracked remote branch,
885 # if the local tracking branch is downstream of it,
897 # if the local tracking branch is downstream of it,
886 # a normal `git pull` would have performed a "fast-forward merge"
898 # a normal `git pull` would have performed a "fast-forward merge"
887 # which is equivalent to updating the local branch to the remote.
899 # which is equivalent to updating the local branch to the remote.
888 # Since we are only looking at branching at update, we need to
900 # Since we are only looking at branching at update, we need to
889 # detect this situation and perform this action lazily.
901 # detect this situation and perform this action lazily.
890 if tracking[remote] != self._gitcurrentbranch():
902 if tracking[remote] != self._gitcurrentbranch():
891 checkout([tracking[remote]])
903 checkout([tracking[remote]])
892 self._gitcommand(['merge', '--ff', remote])
904 self._gitcommand(['merge', '--ff', remote])
893 else:
905 else:
894 # a real merge would be required, just checkout the revision
906 # a real merge would be required, just checkout the revision
895 rawcheckout()
907 rawcheckout()
896
908
897 def commit(self, text, user, date):
909 def commit(self, text, user, date):
898 if self._gitmissing():
910 if self._gitmissing():
899 raise util.Abort(_("subrepo %s is missing") % self._relpath)
911 raise util.Abort(_("subrepo %s is missing") % self._relpath)
900 cmd = ['commit', '-a', '-m', text]
912 cmd = ['commit', '-a', '-m', text]
901 env = os.environ.copy()
913 env = os.environ.copy()
902 if user:
914 if user:
903 cmd += ['--author', user]
915 cmd += ['--author', user]
904 if date:
916 if date:
905 # git's date parser silently ignores when seconds < 1e9
917 # git's date parser silently ignores when seconds < 1e9
906 # convert to ISO8601
918 # convert to ISO8601
907 env['GIT_AUTHOR_DATE'] = util.datestr(date,
919 env['GIT_AUTHOR_DATE'] = util.datestr(date,
908 '%Y-%m-%dT%H:%M:%S %1%2')
920 '%Y-%m-%dT%H:%M:%S %1%2')
909 self._gitcommand(cmd, env=env)
921 self._gitcommand(cmd, env=env)
910 # make sure commit works otherwise HEAD might not exist under certain
922 # make sure commit works otherwise HEAD might not exist under certain
911 # circumstances
923 # circumstances
912 return self._gitstate()
924 return self._gitstate()
913
925
914 def merge(self, state):
926 def merge(self, state):
915 source, revision, kind = state
927 source, revision, kind = state
916 self._fetch(source, revision)
928 self._fetch(source, revision)
917 base = self._gitcommand(['merge-base', revision, self._state[1]])
929 base = self._gitcommand(['merge-base', revision, self._state[1]])
918 out, code = self._gitdir(['diff-index', '--quiet', 'HEAD'])
930 out, code = self._gitdir(['diff-index', '--quiet', 'HEAD'])
919
931
920 def mergefunc():
932 def mergefunc():
921 if base == revision:
933 if base == revision:
922 self.get(state) # fast forward merge
934 self.get(state) # fast forward merge
923 elif base != self._state[1]:
935 elif base != self._state[1]:
924 self._gitcommand(['merge', '--no-commit', revision])
936 self._gitcommand(['merge', '--no-commit', revision])
925
937
926 if self.dirty():
938 if self.dirty():
927 if self._gitstate() != revision:
939 if self._gitstate() != revision:
928 dirty = self._gitstate() == self._state[1] or code != 0
940 dirty = self._gitstate() == self._state[1] or code != 0
929 if _updateprompt(self._ui, self, dirty,
941 if _updateprompt(self._ui, self, dirty,
930 self._state[1][:7], revision[:7]):
942 self._state[1][:7], revision[:7]):
931 mergefunc()
943 mergefunc()
932 else:
944 else:
933 mergefunc()
945 mergefunc()
934
946
935 def push(self, force):
947 def push(self, force):
936 if self._gitmissing():
948 if self._gitmissing():
937 raise util.Abort(_("subrepo %s is missing") % self._relpath)
949 raise util.Abort(_("subrepo %s is missing") % self._relpath)
938 # if a branch in origin contains the revision, nothing to do
950 # if a branch in origin contains the revision, nothing to do
939 branch2rev, rev2branch = self._gitbranchmap()
951 branch2rev, rev2branch = self._gitbranchmap()
940 if self._state[1] in rev2branch:
952 if self._state[1] in rev2branch:
941 for b in rev2branch[self._state[1]]:
953 for b in rev2branch[self._state[1]]:
942 if b.startswith('refs/remotes/origin/'):
954 if b.startswith('refs/remotes/origin/'):
943 return True
955 return True
944 for b, revision in branch2rev.iteritems():
956 for b, revision in branch2rev.iteritems():
945 if b.startswith('refs/remotes/origin/'):
957 if b.startswith('refs/remotes/origin/'):
946 if self._gitisancestor(self._state[1], revision):
958 if self._gitisancestor(self._state[1], revision):
947 return True
959 return True
948 # otherwise, try to push the currently checked out branch
960 # otherwise, try to push the currently checked out branch
949 cmd = ['push']
961 cmd = ['push']
950 if force:
962 if force:
951 cmd.append('--force')
963 cmd.append('--force')
952
964
953 current = self._gitcurrentbranch()
965 current = self._gitcurrentbranch()
954 if current:
966 if current:
955 # determine if the current branch is even useful
967 # determine if the current branch is even useful
956 if not self._gitisancestor(self._state[1], current):
968 if not self._gitisancestor(self._state[1], current):
957 self._ui.warn(_('unrelated git branch checked out '
969 self._ui.warn(_('unrelated git branch checked out '
958 'in subrepo %s\n') % self._relpath)
970 'in subrepo %s\n') % self._relpath)
959 return False
971 return False
960 self._ui.status(_('pushing branch %s of subrepo %s\n') %
972 self._ui.status(_('pushing branch %s of subrepo %s\n') %
961 (current.split('/', 2)[2], self._relpath))
973 (current.split('/', 2)[2], self._relpath))
962 self._gitcommand(cmd + ['origin', current])
974 self._gitcommand(cmd + ['origin', current])
963 return True
975 return True
964 else:
976 else:
965 self._ui.warn(_('no branch checked out in subrepo %s\n'
977 self._ui.warn(_('no branch checked out in subrepo %s\n'
966 'cannot push revision %s') %
978 'cannot push revision %s') %
967 (self._relpath, self._state[1]))
979 (self._relpath, self._state[1]))
968 return False
980 return False
969
981
970 def remove(self):
982 def remove(self):
971 if self._gitmissing():
983 if self._gitmissing():
972 return
984 return
973 if self.dirty():
985 if self.dirty():
974 self._ui.warn(_('not removing repo %s because '
986 self._ui.warn(_('not removing repo %s because '
975 'it has changes.\n') % self._relpath)
987 'it has changes.\n') % self._relpath)
976 return
988 return
977 # we can't fully delete the repository as it may contain
989 # we can't fully delete the repository as it may contain
978 # local-only history
990 # local-only history
979 self._ui.note(_('removing subrepo %s\n') % self._relpath)
991 self._ui.note(_('removing subrepo %s\n') % self._relpath)
980 self._gitcommand(['config', 'core.bare', 'true'])
992 self._gitcommand(['config', 'core.bare', 'true'])
981 for f in os.listdir(self._abspath):
993 for f in os.listdir(self._abspath):
982 if f == '.git':
994 if f == '.git':
983 continue
995 continue
984 path = os.path.join(self._abspath, f)
996 path = os.path.join(self._abspath, f)
985 if os.path.isdir(path) and not os.path.islink(path):
997 if os.path.isdir(path) and not os.path.islink(path):
986 shutil.rmtree(path)
998 shutil.rmtree(path)
987 else:
999 else:
988 os.remove(path)
1000 os.remove(path)
989
1001
990 def archive(self, ui, archiver, prefix):
1002 def archive(self, ui, archiver, prefix):
991 source, revision = self._state
1003 source, revision = self._state
992 self._fetch(source, revision)
1004 self._fetch(source, revision)
993
1005
994 # Parse git's native archive command.
1006 # Parse git's native archive command.
995 # This should be much faster than manually traversing the trees
1007 # This should be much faster than manually traversing the trees
996 # and objects with many subprocess calls.
1008 # and objects with many subprocess calls.
997 tarstream = self._gitcommand(['archive', revision], stream=True)
1009 tarstream = self._gitcommand(['archive', revision], stream=True)
998 tar = tarfile.open(fileobj=tarstream, mode='r|')
1010 tar = tarfile.open(fileobj=tarstream, mode='r|')
999 relpath = subrelpath(self)
1011 relpath = subrelpath(self)
1000 ui.progress(_('archiving (%s)') % relpath, 0, unit=_('files'))
1012 ui.progress(_('archiving (%s)') % relpath, 0, unit=_('files'))
1001 for i, info in enumerate(tar):
1013 for i, info in enumerate(tar):
1002 if info.isdir():
1014 if info.isdir():
1003 continue
1015 continue
1004 if info.issym():
1016 if info.issym():
1005 data = info.linkname
1017 data = info.linkname
1006 else:
1018 else:
1007 data = tar.extractfile(info).read()
1019 data = tar.extractfile(info).read()
1008 archiver.addfile(os.path.join(prefix, self._path, info.name),
1020 archiver.addfile(os.path.join(prefix, self._path, info.name),
1009 info.mode, info.issym(), data)
1021 info.mode, info.issym(), data)
1010 ui.progress(_('archiving (%s)') % relpath, i + 1,
1022 ui.progress(_('archiving (%s)') % relpath, i + 1,
1011 unit=_('files'))
1023 unit=_('files'))
1012 ui.progress(_('archiving (%s)') % relpath, None)
1024 ui.progress(_('archiving (%s)') % relpath, None)
1013
1025
1014
1026
1015 def status(self, rev2, **opts):
1027 def status(self, rev2, **opts):
1016 if self._gitmissing():
1028 if self._gitmissing():
1017 # if the repo is missing, return no results
1029 # if the repo is missing, return no results
1018 return [], [], [], [], [], [], []
1030 return [], [], [], [], [], [], []
1019 rev1 = self._state[1]
1031 rev1 = self._state[1]
1020 modified, added, removed = [], [], []
1032 modified, added, removed = [], [], []
1021 if rev2:
1033 if rev2:
1022 command = ['diff-tree', rev1, rev2]
1034 command = ['diff-tree', rev1, rev2]
1023 else:
1035 else:
1024 command = ['diff-index', rev1]
1036 command = ['diff-index', rev1]
1025 out = self._gitcommand(command)
1037 out = self._gitcommand(command)
1026 for line in out.split('\n'):
1038 for line in out.split('\n'):
1027 tab = line.find('\t')
1039 tab = line.find('\t')
1028 if tab == -1:
1040 if tab == -1:
1029 continue
1041 continue
1030 status, f = line[tab - 1], line[tab + 1:]
1042 status, f = line[tab - 1], line[tab + 1:]
1031 if status == 'M':
1043 if status == 'M':
1032 modified.append(f)
1044 modified.append(f)
1033 elif status == 'A':
1045 elif status == 'A':
1034 added.append(f)
1046 added.append(f)
1035 elif status == 'D':
1047 elif status == 'D':
1036 removed.append(f)
1048 removed.append(f)
1037
1049
1038 deleted = unknown = ignored = clean = []
1050 deleted = unknown = ignored = clean = []
1039 return modified, added, removed, deleted, unknown, ignored, clean
1051 return modified, added, removed, deleted, unknown, ignored, clean
1040
1052
1041 types = {
1053 types = {
1042 'hg': hgsubrepo,
1054 'hg': hgsubrepo,
1043 'svn': svnsubrepo,
1055 'svn': svnsubrepo,
1044 'git': gitsubrepo,
1056 'git': gitsubrepo,
1045 }
1057 }
@@ -1,164 +1,164 b''
1
1
2 $ hg clone http://localhost:$HGPORT/ copy
2 $ hg clone http://localhost:$HGPORT/ copy
3 abort: error: Connection refused
3 abort: error: Connection refused
4 [255]
4 [255]
5 $ test -d copy
5 $ test -d copy
6 [1]
6 [1]
7
7
8 This server doesn't do range requests so it's basically only good for
8 This server doesn't do range requests so it's basically only good for
9 one pull
9 one pull
10
10
11 $ cat > dumb.py <<EOF
11 $ cat > dumb.py <<EOF
12 > import BaseHTTPServer, SimpleHTTPServer, os, signal, sys
12 > import BaseHTTPServer, SimpleHTTPServer, os, signal, sys
13 >
13 >
14 > def run(server_class=BaseHTTPServer.HTTPServer,
14 > def run(server_class=BaseHTTPServer.HTTPServer,
15 > handler_class=SimpleHTTPServer.SimpleHTTPRequestHandler):
15 > handler_class=SimpleHTTPServer.SimpleHTTPRequestHandler):
16 > server_address = ('localhost', int(os.environ['HGPORT']))
16 > server_address = ('localhost', int(os.environ['HGPORT']))
17 > httpd = server_class(server_address, handler_class)
17 > httpd = server_class(server_address, handler_class)
18 > httpd.serve_forever()
18 > httpd.serve_forever()
19 >
19 >
20 > signal.signal(signal.SIGTERM, lambda x, y: sys.exit(0))
20 > signal.signal(signal.SIGTERM, lambda x, y: sys.exit(0))
21 > run()
21 > run()
22 > EOF
22 > EOF
23 $ python dumb.py 2>/dev/null &
23 $ python dumb.py 2>/dev/null &
24 $ echo $! >> $DAEMON_PIDS
24 $ echo $! >> $DAEMON_PIDS
25 $ hg init remote
25 $ hg init remote
26 $ cd remote
26 $ cd remote
27 $ echo foo > bar
27 $ echo foo > bar
28 $ echo c2 > '.dotfile with spaces'
28 $ echo c2 > '.dotfile with spaces'
29 $ hg add
29 $ hg add
30 adding .dotfile with spaces
30 adding .dotfile with spaces
31 adding bar
31 adding bar
32 $ hg commit -m"test"
32 $ hg commit -m"test"
33 $ hg tip
33 $ hg tip
34 changeset: 0:02770d679fb8
34 changeset: 0:02770d679fb8
35 tag: tip
35 tag: tip
36 user: test
36 user: test
37 date: Thu Jan 01 00:00:00 1970 +0000
37 date: Thu Jan 01 00:00:00 1970 +0000
38 summary: test
38 summary: test
39
39
40 $ cd ..
40 $ cd ..
41 $ hg clone static-http://localhost:$HGPORT/remote local
41 $ hg clone static-http://localhost:$HGPORT/remote local
42 requesting all changes
42 requesting all changes
43 adding changesets
43 adding changesets
44 adding manifests
44 adding manifests
45 adding file changes
45 adding file changes
46 added 1 changesets with 2 changes to 2 files
46 added 1 changesets with 2 changes to 2 files
47 updating to branch default
47 updating to branch default
48 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
49 $ cd local
49 $ cd local
50 $ hg verify
50 $ hg verify
51 checking changesets
51 checking changesets
52 checking manifests
52 checking manifests
53 crosschecking files in changesets and manifests
53 crosschecking files in changesets and manifests
54 checking files
54 checking files
55 2 files, 1 changesets, 2 total revisions
55 2 files, 1 changesets, 2 total revisions
56 $ cat bar
56 $ cat bar
57 foo
57 foo
58 $ cd ../remote
58 $ cd ../remote
59 $ echo baz > quux
59 $ echo baz > quux
60 $ hg commit -A -mtest2
60 $ hg commit -A -mtest2
61 adding quux
61 adding quux
62
62
63 check for HTTP opener failures when cachefile does not exist
63 check for HTTP opener failures when cachefile does not exist
64
64
65 $ rm .hg/cache/*
65 $ rm .hg/cache/*
66 $ cd ../local
66 $ cd ../local
67 $ echo '[hooks]' >> .hg/hgrc
67 $ echo '[hooks]' >> .hg/hgrc
68 $ echo 'changegroup = python "$TESTDIR"/printenv.py changegroup' >> .hg/hgrc
68 $ echo 'changegroup = python "$TESTDIR"/printenv.py changegroup' >> .hg/hgrc
69 $ hg pull
69 $ hg pull
70 pulling from static-http://localhost:$HGPORT/remote
70 pulling from static-http://localhost:$HGPORT/remote
71 searching for changes
71 searching for changes
72 adding changesets
72 adding changesets
73 adding manifests
73 adding manifests
74 adding file changes
74 adding file changes
75 added 1 changesets with 1 changes to 1 files
75 added 1 changesets with 1 changes to 1 files
76 changegroup hook: HG_NODE=4ac2e3648604439c580c69b09ec9d93a88d93432 HG_SOURCE=pull HG_URL=http://localhost:$HGPORT/remote
76 changegroup hook: HG_NODE=4ac2e3648604439c580c69b09ec9d93a88d93432 HG_SOURCE=pull HG_URL=http://localhost:$HGPORT/remote
77 (run 'hg update' to get a working copy)
77 (run 'hg update' to get a working copy)
78
78
79 trying to push
79 trying to push
80
80
81 $ hg update
81 $ hg update
82 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
82 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
83 $ echo more foo >> bar
83 $ echo more foo >> bar
84 $ hg commit -m"test"
84 $ hg commit -m"test"
85 $ hg push
85 $ hg push
86 pushing to static-http://localhost:$HGPORT/remote
86 pushing to static-http://localhost:$HGPORT/remote
87 abort: cannot lock static-http repository
87 abort: cannot lock static-http repository
88 [255]
88 [255]
89
89
90 trying clone -r
90 trying clone -r
91
91
92 $ cd ..
92 $ cd ..
93 $ hg clone -r donotexist static-http://localhost:$HGPORT/remote local0
93 $ hg clone -r donotexist static-http://localhost:$HGPORT/remote local0
94 abort: unknown revision 'donotexist'!
94 abort: unknown revision 'donotexist'!
95 [255]
95 [255]
96 $ hg clone -r 0 static-http://localhost:$HGPORT/remote local0
96 $ hg clone -r 0 static-http://localhost:$HGPORT/remote local0
97 adding changesets
97 adding changesets
98 adding manifests
98 adding manifests
99 adding file changes
99 adding file changes
100 added 1 changesets with 2 changes to 2 files
100 added 1 changesets with 2 changes to 2 files
101 updating to branch default
101 updating to branch default
102 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
102 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
103
103
104 test with "/" URI (issue 747) and subrepo
104 test with "/" URI (issue 747) and subrepo
105
105
106 $ hg init
106 $ hg init
107 $ hg init sub
107 $ hg init sub
108 $ hg -R sub tag not-empty
108 $ hg -R sub tag not-empty
109 $ echo sub=sub > .hgsub
109 $ echo sub=sub > .hgsub
110 $ echo a > a
110 $ echo a > a
111 $ hg add a .hgsub
111 $ hg add a .hgsub
112 $ hg -q ci -ma
112 $ hg -q ci -ma
113 $ hg clone static-http://localhost:$HGPORT/ local2
113 $ hg clone static-http://localhost:$HGPORT/ local2
114 requesting all changes
114 requesting all changes
115 adding changesets
115 adding changesets
116 adding manifests
116 adding manifests
117 adding file changes
117 adding file changes
118 added 1 changesets with 3 changes to 3 files
118 added 1 changesets with 3 changes to 3 files
119 updating to branch default
119 updating to branch default
120 pulling subrepo sub from static-http://localhost:$HGPORT/sub
120 cloning subrepo sub from static-http://localhost:$HGPORT/sub
121 requesting all changes
121 requesting all changes
122 adding changesets
122 adding changesets
123 adding manifests
123 adding manifests
124 adding file changes
124 adding file changes
125 added 1 changesets with 1 changes to 1 files
125 added 1 changesets with 1 changes to 1 files
126 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
126 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
127 $ cd local2
127 $ cd local2
128 $ hg verify
128 $ hg verify
129 checking changesets
129 checking changesets
130 checking manifests
130 checking manifests
131 crosschecking files in changesets and manifests
131 crosschecking files in changesets and manifests
132 checking files
132 checking files
133 3 files, 1 changesets, 3 total revisions
133 3 files, 1 changesets, 3 total revisions
134 $ cat a
134 $ cat a
135 a
135 a
136 $ hg paths
136 $ hg paths
137 default = static-http://localhost:$HGPORT/
137 default = static-http://localhost:$HGPORT/
138
138
139 test with empty repo (issue965)
139 test with empty repo (issue965)
140
140
141 $ cd ..
141 $ cd ..
142 $ hg init remotempty
142 $ hg init remotempty
143 $ hg clone static-http://localhost:$HGPORT/remotempty local3
143 $ hg clone static-http://localhost:$HGPORT/remotempty local3
144 no changes found
144 no changes found
145 updating to branch default
145 updating to branch default
146 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
146 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
147 $ cd local3
147 $ cd local3
148 $ hg verify
148 $ hg verify
149 checking changesets
149 checking changesets
150 checking manifests
150 checking manifests
151 crosschecking files in changesets and manifests
151 crosschecking files in changesets and manifests
152 checking files
152 checking files
153 0 files, 0 changesets, 0 total revisions
153 0 files, 0 changesets, 0 total revisions
154 $ hg paths
154 $ hg paths
155 default = static-http://localhost:$HGPORT/remotempty
155 default = static-http://localhost:$HGPORT/remotempty
156
156
157 test with non-repo
157 test with non-repo
158
158
159 $ cd ..
159 $ cd ..
160 $ mkdir notarepo
160 $ mkdir notarepo
161 $ hg clone static-http://localhost:$HGPORT/notarepo local3
161 $ hg clone static-http://localhost:$HGPORT/notarepo local3
162 abort: 'http://localhost:$HGPORT/notarepo' does not appear to be an hg repository!
162 abort: 'http://localhost:$HGPORT/notarepo' does not appear to be an hg repository!
163 [255]
163 [255]
164 $ kill $!
164 $ kill $!
@@ -1,117 +1,102 b''
1 Preparing the subrepository 'sub2'
1 Preparing the subrepository 'sub2'
2
2
3 $ hg init sub2
3 $ hg init sub2
4 $ echo sub2 > sub2/sub2
4 $ echo sub2 > sub2/sub2
5 $ hg add -R sub2
5 $ hg add -R sub2
6 adding sub2/sub2
6 adding sub2/sub2
7 $ hg commit -R sub2 -m "sub2 import"
7 $ hg commit -R sub2 -m "sub2 import"
8
8
9 Preparing the 'sub1' repo which depends on the subrepo 'sub2'
9 Preparing the 'sub1' repo which depends on the subrepo 'sub2'
10
10
11 $ hg init sub1
11 $ hg init sub1
12 $ echo sub1 > sub1/sub1
12 $ echo sub1 > sub1/sub1
13 $ echo "sub2 = ../sub2" > sub1/.hgsub
13 $ echo "sub2 = ../sub2" > sub1/.hgsub
14 $ hg clone sub2 sub1/sub2
14 $ hg clone sub2 sub1/sub2
15 updating to branch default
15 updating to branch default
16 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
17 $ hg add -R sub1
17 $ hg add -R sub1
18 adding sub1/.hgsub
18 adding sub1/.hgsub
19 adding sub1/sub1
19 adding sub1/sub1
20 $ hg commit -R sub1 -m "sub1 import"
20 $ hg commit -R sub1 -m "sub1 import"
21 committing subrepository sub2
21 committing subrepository sub2
22
22
23 Preparing the 'main' repo which depends on the subrepo 'sub1'
23 Preparing the 'main' repo which depends on the subrepo 'sub1'
24
24
25 $ hg init main
25 $ hg init main
26 $ echo main > main/main
26 $ echo main > main/main
27 $ echo "sub1 = ../sub1" > main/.hgsub
27 $ echo "sub1 = ../sub1" > main/.hgsub
28 $ hg clone sub1 main/sub1
28 $ hg clone sub1 main/sub1
29 updating to branch default
29 updating to branch default
30 pulling subrepo sub2 from $TESTTMP/sub2
30 cloning subrepo sub2 from $TESTTMP/sub2
31 requesting all changes
32 adding changesets
33 adding manifests
34 adding file changes
35 added 1 changesets with 1 changes to 1 files
36 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
31 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
37 $ hg add -R main
32 $ hg add -R main
38 adding main/.hgsub
33 adding main/.hgsub
39 adding main/main
34 adding main/main
40 $ hg commit -R main -m "main import"
35 $ hg commit -R main -m "main import"
41 committing subrepository sub1
36 committing subrepository sub1
42
37
43 Cleaning both repositories, just as a clone -U
38 Cleaning both repositories, just as a clone -U
44
39
45 $ hg up -C -R sub2 null
40 $ hg up -C -R sub2 null
46 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
41 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
47 $ hg up -C -R sub1 null
42 $ hg up -C -R sub1 null
48 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
43 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
49 $ hg up -C -R main null
44 $ hg up -C -R main null
50 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
45 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
51 $ rm -rf main/sub1
46 $ rm -rf main/sub1
52 $ rm -rf sub1/sub2
47 $ rm -rf sub1/sub2
53
48
54 Clone main
49 Clone main
55
50
56 $ hg clone main cloned
51 $ hg clone main cloned
57 updating to branch default
52 updating to branch default
58 pulling subrepo sub1 from $TESTTMP/sub1
53 cloning subrepo sub1 from $TESTTMP/sub1
59 requesting all changes
54 cloning subrepo sub1/sub2 from $TESTTMP/sub2
60 adding changesets
61 adding manifests
62 adding file changes
63 added 1 changesets with 3 changes to 3 files
64 pulling subrepo sub1/sub2 from $TESTTMP/sub2
65 requesting all changes
66 adding changesets
67 adding manifests
68 adding file changes
69 added 1 changesets with 1 changes to 1 files
70 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
55 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
71
56
72 Checking cloned repo ids
57 Checking cloned repo ids
73
58
74 $ printf "cloned " ; hg id -R cloned
59 $ printf "cloned " ; hg id -R cloned
75 cloned 7f491f53a367 tip
60 cloned 7f491f53a367 tip
76 $ printf "cloned/sub1 " ; hg id -R cloned/sub1
61 $ printf "cloned/sub1 " ; hg id -R cloned/sub1
77 cloned/sub1 fc3b4ce2696f tip
62 cloned/sub1 fc3b4ce2696f tip
78 $ printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
63 $ printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
79 cloned/sub1/sub2 c57a0840e3ba tip
64 cloned/sub1/sub2 c57a0840e3ba tip
80
65
81 debugsub output for main and sub1
66 debugsub output for main and sub1
82
67
83 $ hg debugsub -R cloned
68 $ hg debugsub -R cloned
84 path sub1
69 path sub1
85 source ../sub1
70 source ../sub1
86 revision fc3b4ce2696f7741438c79207583768f2ce6b0dd
71 revision fc3b4ce2696f7741438c79207583768f2ce6b0dd
87 $ hg debugsub -R cloned/sub1
72 $ hg debugsub -R cloned/sub1
88 path sub2
73 path sub2
89 source ../sub2
74 source ../sub2
90 revision c57a0840e3badd667ef3c3ef65471609acb2ba3c
75 revision c57a0840e3badd667ef3c3ef65471609acb2ba3c
91
76
92 Modifying deeply nested 'sub2'
77 Modifying deeply nested 'sub2'
93
78
94 $ echo modified > cloned/sub1/sub2/sub2
79 $ echo modified > cloned/sub1/sub2/sub2
95 $ hg commit -m "deep nested modif should trigger a commit" -R cloned
80 $ hg commit -m "deep nested modif should trigger a commit" -R cloned
96 committing subrepository sub1
81 committing subrepository sub1
97 committing subrepository sub1/sub2
82 committing subrepository sub1/sub2
98
83
99 Checking modified node ids
84 Checking modified node ids
100
85
101 $ printf "cloned " ; hg id -R cloned
86 $ printf "cloned " ; hg id -R cloned
102 cloned ffe6649062fe tip
87 cloned ffe6649062fe tip
103 $ printf "cloned/sub1 " ; hg id -R cloned/sub1
88 $ printf "cloned/sub1 " ; hg id -R cloned/sub1
104 cloned/sub1 2ecb03bf44a9 tip
89 cloned/sub1 2ecb03bf44a9 tip
105 $ printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
90 $ printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
106 cloned/sub1/sub2 53dd3430bcaf tip
91 cloned/sub1/sub2 53dd3430bcaf tip
107
92
108 debugsub output for main and sub1
93 debugsub output for main and sub1
109
94
110 $ hg debugsub -R cloned
95 $ hg debugsub -R cloned
111 path sub1
96 path sub1
112 source ../sub1
97 source ../sub1
113 revision 2ecb03bf44a94e749e8669481dd9069526ce7cb9
98 revision 2ecb03bf44a94e749e8669481dd9069526ce7cb9
114 $ hg debugsub -R cloned/sub1
99 $ hg debugsub -R cloned/sub1
115 path sub2
100 path sub2
116 source ../sub2
101 source ../sub2
117 revision 53dd3430bcaf5ab4a7c48262bcad6d441f510487
102 revision 53dd3430bcaf5ab4a7c48262bcad6d441f510487
@@ -1,427 +1,417 b''
1 Create test repository:
1 Create test repository:
2
2
3 $ hg init repo
3 $ hg init repo
4 $ cd repo
4 $ cd repo
5 $ echo x1 > x.txt
5 $ echo x1 > x.txt
6
6
7 $ hg init foo
7 $ hg init foo
8 $ cd foo
8 $ cd foo
9 $ echo y1 > y.txt
9 $ echo y1 > y.txt
10
10
11 $ hg init bar
11 $ hg init bar
12 $ cd bar
12 $ cd bar
13 $ echo z1 > z.txt
13 $ echo z1 > z.txt
14
14
15 $ cd ..
15 $ cd ..
16 $ echo 'bar = bar' > .hgsub
16 $ echo 'bar = bar' > .hgsub
17
17
18 $ cd ..
18 $ cd ..
19 $ echo 'foo = foo' > .hgsub
19 $ echo 'foo = foo' > .hgsub
20
20
21 Add files --- .hgsub files must go first to trigger subrepos:
21 Add files --- .hgsub files must go first to trigger subrepos:
22
22
23 $ hg add -S .hgsub
23 $ hg add -S .hgsub
24 $ hg add -S foo/.hgsub
24 $ hg add -S foo/.hgsub
25 $ hg add -S foo/bar
25 $ hg add -S foo/bar
26 adding foo/bar/z.txt
26 adding foo/bar/z.txt
27 $ hg add -S
27 $ hg add -S
28 adding x.txt
28 adding x.txt
29 adding foo/y.txt
29 adding foo/y.txt
30
30
31 Test recursive status without committing anything:
31 Test recursive status without committing anything:
32
32
33 $ hg status -S
33 $ hg status -S
34 A .hgsub
34 A .hgsub
35 A foo/.hgsub
35 A foo/.hgsub
36 A foo/bar/z.txt
36 A foo/bar/z.txt
37 A foo/y.txt
37 A foo/y.txt
38 A x.txt
38 A x.txt
39
39
40 Test recursive diff without committing anything:
40 Test recursive diff without committing anything:
41
41
42 $ hg diff --nodates -S foo
42 $ hg diff --nodates -S foo
43 diff -r 000000000000 foo/.hgsub
43 diff -r 000000000000 foo/.hgsub
44 --- /dev/null
44 --- /dev/null
45 +++ b/foo/.hgsub
45 +++ b/foo/.hgsub
46 @@ -0,0 +1,1 @@
46 @@ -0,0 +1,1 @@
47 +bar = bar
47 +bar = bar
48 diff -r 000000000000 foo/y.txt
48 diff -r 000000000000 foo/y.txt
49 --- /dev/null
49 --- /dev/null
50 +++ b/foo/y.txt
50 +++ b/foo/y.txt
51 @@ -0,0 +1,1 @@
51 @@ -0,0 +1,1 @@
52 +y1
52 +y1
53 diff -r 000000000000 foo/bar/z.txt
53 diff -r 000000000000 foo/bar/z.txt
54 --- /dev/null
54 --- /dev/null
55 +++ b/foo/bar/z.txt
55 +++ b/foo/bar/z.txt
56 @@ -0,0 +1,1 @@
56 @@ -0,0 +1,1 @@
57 +z1
57 +z1
58
58
59 Commits:
59 Commits:
60
60
61 $ hg commit -m 0-0-0
61 $ hg commit -m 0-0-0
62 committing subrepository foo
62 committing subrepository foo
63 committing subrepository foo/bar
63 committing subrepository foo/bar
64
64
65 $ cd foo
65 $ cd foo
66 $ echo y2 >> y.txt
66 $ echo y2 >> y.txt
67 $ hg commit -m 0-1-0
67 $ hg commit -m 0-1-0
68
68
69 $ cd bar
69 $ cd bar
70 $ echo z2 >> z.txt
70 $ echo z2 >> z.txt
71 $ hg commit -m 0-1-1
71 $ hg commit -m 0-1-1
72
72
73 $ cd ..
73 $ cd ..
74 $ hg commit -m 0-2-1
74 $ hg commit -m 0-2-1
75 committing subrepository bar
75 committing subrepository bar
76
76
77 $ cd ..
77 $ cd ..
78 $ hg commit -m 1-2-1
78 $ hg commit -m 1-2-1
79 committing subrepository foo
79 committing subrepository foo
80
80
81 Change working directory:
81 Change working directory:
82
82
83 $ echo y3 >> foo/y.txt
83 $ echo y3 >> foo/y.txt
84 $ echo z3 >> foo/bar/z.txt
84 $ echo z3 >> foo/bar/z.txt
85 $ hg status -S
85 $ hg status -S
86 M foo/bar/z.txt
86 M foo/bar/z.txt
87 M foo/y.txt
87 M foo/y.txt
88 $ hg diff --nodates -S
88 $ hg diff --nodates -S
89 diff -r d254738c5f5e foo/y.txt
89 diff -r d254738c5f5e foo/y.txt
90 --- a/foo/y.txt
90 --- a/foo/y.txt
91 +++ b/foo/y.txt
91 +++ b/foo/y.txt
92 @@ -1,2 +1,3 @@
92 @@ -1,2 +1,3 @@
93 y1
93 y1
94 y2
94 y2
95 +y3
95 +y3
96 diff -r 9647f22de499 foo/bar/z.txt
96 diff -r 9647f22de499 foo/bar/z.txt
97 --- a/foo/bar/z.txt
97 --- a/foo/bar/z.txt
98 +++ b/foo/bar/z.txt
98 +++ b/foo/bar/z.txt
99 @@ -1,2 +1,3 @@
99 @@ -1,2 +1,3 @@
100 z1
100 z1
101 z2
101 z2
102 +z3
102 +z3
103
103
104 Status call crossing repository boundaries:
104 Status call crossing repository boundaries:
105
105
106 $ hg status -S foo/bar/z.txt
106 $ hg status -S foo/bar/z.txt
107 M foo/bar/z.txt
107 M foo/bar/z.txt
108 $ hg status -S -I 'foo/?.txt'
108 $ hg status -S -I 'foo/?.txt'
109 M foo/y.txt
109 M foo/y.txt
110 $ hg status -S -I '**/?.txt'
110 $ hg status -S -I '**/?.txt'
111 M foo/bar/z.txt
111 M foo/bar/z.txt
112 M foo/y.txt
112 M foo/y.txt
113 $ hg diff --nodates -S -I '**/?.txt'
113 $ hg diff --nodates -S -I '**/?.txt'
114 diff -r d254738c5f5e foo/y.txt
114 diff -r d254738c5f5e foo/y.txt
115 --- a/foo/y.txt
115 --- a/foo/y.txt
116 +++ b/foo/y.txt
116 +++ b/foo/y.txt
117 @@ -1,2 +1,3 @@
117 @@ -1,2 +1,3 @@
118 y1
118 y1
119 y2
119 y2
120 +y3
120 +y3
121 diff -r 9647f22de499 foo/bar/z.txt
121 diff -r 9647f22de499 foo/bar/z.txt
122 --- a/foo/bar/z.txt
122 --- a/foo/bar/z.txt
123 +++ b/foo/bar/z.txt
123 +++ b/foo/bar/z.txt
124 @@ -1,2 +1,3 @@
124 @@ -1,2 +1,3 @@
125 z1
125 z1
126 z2
126 z2
127 +z3
127 +z3
128
128
129 Status from within a subdirectory:
129 Status from within a subdirectory:
130
130
131 $ mkdir dir
131 $ mkdir dir
132 $ cd dir
132 $ cd dir
133 $ echo a1 > a.txt
133 $ echo a1 > a.txt
134 $ hg status -S
134 $ hg status -S
135 M foo/bar/z.txt
135 M foo/bar/z.txt
136 M foo/y.txt
136 M foo/y.txt
137 ? dir/a.txt
137 ? dir/a.txt
138 $ hg diff --nodates -S
138 $ hg diff --nodates -S
139 diff -r d254738c5f5e foo/y.txt
139 diff -r d254738c5f5e foo/y.txt
140 --- a/foo/y.txt
140 --- a/foo/y.txt
141 +++ b/foo/y.txt
141 +++ b/foo/y.txt
142 @@ -1,2 +1,3 @@
142 @@ -1,2 +1,3 @@
143 y1
143 y1
144 y2
144 y2
145 +y3
145 +y3
146 diff -r 9647f22de499 foo/bar/z.txt
146 diff -r 9647f22de499 foo/bar/z.txt
147 --- a/foo/bar/z.txt
147 --- a/foo/bar/z.txt
148 +++ b/foo/bar/z.txt
148 +++ b/foo/bar/z.txt
149 @@ -1,2 +1,3 @@
149 @@ -1,2 +1,3 @@
150 z1
150 z1
151 z2
151 z2
152 +z3
152 +z3
153
153
154 Status with relative path:
154 Status with relative path:
155
155
156 $ hg status -S ..
156 $ hg status -S ..
157 M ../foo/bar/z.txt
157 M ../foo/bar/z.txt
158 M ../foo/y.txt
158 M ../foo/y.txt
159 ? a.txt
159 ? a.txt
160 $ hg diff --nodates -S ..
160 $ hg diff --nodates -S ..
161 diff -r d254738c5f5e foo/y.txt
161 diff -r d254738c5f5e foo/y.txt
162 --- a/foo/y.txt
162 --- a/foo/y.txt
163 +++ b/foo/y.txt
163 +++ b/foo/y.txt
164 @@ -1,2 +1,3 @@
164 @@ -1,2 +1,3 @@
165 y1
165 y1
166 y2
166 y2
167 +y3
167 +y3
168 diff -r 9647f22de499 foo/bar/z.txt
168 diff -r 9647f22de499 foo/bar/z.txt
169 --- a/foo/bar/z.txt
169 --- a/foo/bar/z.txt
170 +++ b/foo/bar/z.txt
170 +++ b/foo/bar/z.txt
171 @@ -1,2 +1,3 @@
171 @@ -1,2 +1,3 @@
172 z1
172 z1
173 z2
173 z2
174 +z3
174 +z3
175 $ cd ..
175 $ cd ..
176
176
177 Cleanup and final commit:
177 Cleanup and final commit:
178
178
179 $ rm -r dir
179 $ rm -r dir
180 $ hg commit -m 2-3-2
180 $ hg commit -m 2-3-2
181 committing subrepository foo
181 committing subrepository foo
182 committing subrepository foo/bar
182 committing subrepository foo/bar
183
183
184 Log with the relationships between repo and its subrepo:
184 Log with the relationships between repo and its subrepo:
185
185
186 $ hg log --template '{rev}:{node|short} {desc}\n'
186 $ hg log --template '{rev}:{node|short} {desc}\n'
187 2:1326fa26d0c0 2-3-2
187 2:1326fa26d0c0 2-3-2
188 1:4b3c9ff4f66b 1-2-1
188 1:4b3c9ff4f66b 1-2-1
189 0:23376cbba0d8 0-0-0
189 0:23376cbba0d8 0-0-0
190
190
191 $ hg -R foo log --template '{rev}:{node|short} {desc}\n'
191 $ hg -R foo log --template '{rev}:{node|short} {desc}\n'
192 3:65903cebad86 2-3-2
192 3:65903cebad86 2-3-2
193 2:d254738c5f5e 0-2-1
193 2:d254738c5f5e 0-2-1
194 1:8629ce7dcc39 0-1-0
194 1:8629ce7dcc39 0-1-0
195 0:af048e97ade2 0-0-0
195 0:af048e97ade2 0-0-0
196
196
197 $ hg -R foo/bar log --template '{rev}:{node|short} {desc}\n'
197 $ hg -R foo/bar log --template '{rev}:{node|short} {desc}\n'
198 2:31ecbdafd357 2-3-2
198 2:31ecbdafd357 2-3-2
199 1:9647f22de499 0-1-1
199 1:9647f22de499 0-1-1
200 0:4904098473f9 0-0-0
200 0:4904098473f9 0-0-0
201
201
202 Status between revisions:
202 Status between revisions:
203
203
204 $ hg status -S
204 $ hg status -S
205 $ hg status -S --rev 0:1
205 $ hg status -S --rev 0:1
206 M .hgsubstate
206 M .hgsubstate
207 M foo/.hgsubstate
207 M foo/.hgsubstate
208 M foo/bar/z.txt
208 M foo/bar/z.txt
209 M foo/y.txt
209 M foo/y.txt
210 $ hg diff --nodates -S -I '**/?.txt' --rev 0:1
210 $ hg diff --nodates -S -I '**/?.txt' --rev 0:1
211 diff -r af048e97ade2 -r d254738c5f5e foo/y.txt
211 diff -r af048e97ade2 -r d254738c5f5e foo/y.txt
212 --- a/foo/y.txt
212 --- a/foo/y.txt
213 +++ b/foo/y.txt
213 +++ b/foo/y.txt
214 @@ -1,1 +1,2 @@
214 @@ -1,1 +1,2 @@
215 y1
215 y1
216 +y2
216 +y2
217 diff -r 4904098473f9 -r 9647f22de499 foo/bar/z.txt
217 diff -r 4904098473f9 -r 9647f22de499 foo/bar/z.txt
218 --- a/foo/bar/z.txt
218 --- a/foo/bar/z.txt
219 +++ b/foo/bar/z.txt
219 +++ b/foo/bar/z.txt
220 @@ -1,1 +1,2 @@
220 @@ -1,1 +1,2 @@
221 z1
221 z1
222 +z2
222 +z2
223
223
224 Enable progress extension for archive tests:
224 Enable progress extension for archive tests:
225
225
226 $ cp $HGRCPATH $HGRCPATH.no-progress
226 $ cp $HGRCPATH $HGRCPATH.no-progress
227 $ cat >> $HGRCPATH <<EOF
227 $ cat >> $HGRCPATH <<EOF
228 > [extensions]
228 > [extensions]
229 > progress =
229 > progress =
230 > [progress]
230 > [progress]
231 > assume-tty = 1
231 > assume-tty = 1
232 > delay = 0
232 > delay = 0
233 > format = topic bar number
233 > format = topic bar number
234 > refresh = 0
234 > refresh = 0
235 > width = 60
235 > width = 60
236 > EOF
236 > EOF
237
237
238 Test archiving to a directory tree (the doubled lines in the output
238 Test archiving to a directory tree (the doubled lines in the output
239 only show up in the test output, not in real usage):
239 only show up in the test output, not in real usage):
240
240
241 $ hg archive --subrepos ../archive 2>&1 | $TESTDIR/filtercr.py
241 $ hg archive --subrepos ../archive 2>&1 | $TESTDIR/filtercr.py
242
242
243 archiving [ ] 0/3
243 archiving [ ] 0/3
244 archiving [ ] 0/3
244 archiving [ ] 0/3
245 archiving [=============> ] 1/3
245 archiving [=============> ] 1/3
246 archiving [=============> ] 1/3
246 archiving [=============> ] 1/3
247 archiving [===========================> ] 2/3
247 archiving [===========================> ] 2/3
248 archiving [===========================> ] 2/3
248 archiving [===========================> ] 2/3
249 archiving [==========================================>] 3/3
249 archiving [==========================================>] 3/3
250 archiving [==========================================>] 3/3
250 archiving [==========================================>] 3/3
251
251
252 archiving (foo) [ ] 0/3
252 archiving (foo) [ ] 0/3
253 archiving (foo) [ ] 0/3
253 archiving (foo) [ ] 0/3
254 archiving (foo) [===========> ] 1/3
254 archiving (foo) [===========> ] 1/3
255 archiving (foo) [===========> ] 1/3
255 archiving (foo) [===========> ] 1/3
256 archiving (foo) [=======================> ] 2/3
256 archiving (foo) [=======================> ] 2/3
257 archiving (foo) [=======================> ] 2/3
257 archiving (foo) [=======================> ] 2/3
258 archiving (foo) [====================================>] 3/3
258 archiving (foo) [====================================>] 3/3
259 archiving (foo) [====================================>] 3/3
259 archiving (foo) [====================================>] 3/3
260
260
261 archiving (foo/bar) [ ] 0/1
261 archiving (foo/bar) [ ] 0/1
262 archiving (foo/bar) [ ] 0/1
262 archiving (foo/bar) [ ] 0/1
263 archiving (foo/bar) [================================>] 1/1
263 archiving (foo/bar) [================================>] 1/1
264 archiving (foo/bar) [================================>] 1/1
264 archiving (foo/bar) [================================>] 1/1
265 \r (esc)
265 \r (esc)
266 $ find ../archive | sort
266 $ find ../archive | sort
267 ../archive
267 ../archive
268 ../archive/.hg_archival.txt
268 ../archive/.hg_archival.txt
269 ../archive/.hgsub
269 ../archive/.hgsub
270 ../archive/.hgsubstate
270 ../archive/.hgsubstate
271 ../archive/foo
271 ../archive/foo
272 ../archive/foo/.hgsub
272 ../archive/foo/.hgsub
273 ../archive/foo/.hgsubstate
273 ../archive/foo/.hgsubstate
274 ../archive/foo/bar
274 ../archive/foo/bar
275 ../archive/foo/bar/z.txt
275 ../archive/foo/bar/z.txt
276 ../archive/foo/y.txt
276 ../archive/foo/y.txt
277 ../archive/x.txt
277 ../archive/x.txt
278
278
279 Test archiving to zip file (unzip output is unstable):
279 Test archiving to zip file (unzip output is unstable):
280
280
281 $ hg archive --subrepos ../archive.zip 2>&1 | $TESTDIR/filtercr.py
281 $ hg archive --subrepos ../archive.zip 2>&1 | $TESTDIR/filtercr.py
282
282
283 archiving [ ] 0/3
283 archiving [ ] 0/3
284 archiving [ ] 0/3
284 archiving [ ] 0/3
285 archiving [=============> ] 1/3
285 archiving [=============> ] 1/3
286 archiving [=============> ] 1/3
286 archiving [=============> ] 1/3
287 archiving [===========================> ] 2/3
287 archiving [===========================> ] 2/3
288 archiving [===========================> ] 2/3
288 archiving [===========================> ] 2/3
289 archiving [==========================================>] 3/3
289 archiving [==========================================>] 3/3
290 archiving [==========================================>] 3/3
290 archiving [==========================================>] 3/3
291
291
292 archiving (foo) [ ] 0/3
292 archiving (foo) [ ] 0/3
293 archiving (foo) [ ] 0/3
293 archiving (foo) [ ] 0/3
294 archiving (foo) [===========> ] 1/3
294 archiving (foo) [===========> ] 1/3
295 archiving (foo) [===========> ] 1/3
295 archiving (foo) [===========> ] 1/3
296 archiving (foo) [=======================> ] 2/3
296 archiving (foo) [=======================> ] 2/3
297 archiving (foo) [=======================> ] 2/3
297 archiving (foo) [=======================> ] 2/3
298 archiving (foo) [====================================>] 3/3
298 archiving (foo) [====================================>] 3/3
299 archiving (foo) [====================================>] 3/3
299 archiving (foo) [====================================>] 3/3
300
300
301 archiving (foo/bar) [ ] 0/1
301 archiving (foo/bar) [ ] 0/1
302 archiving (foo/bar) [ ] 0/1
302 archiving (foo/bar) [ ] 0/1
303 archiving (foo/bar) [================================>] 1/1
303 archiving (foo/bar) [================================>] 1/1
304 archiving (foo/bar) [================================>] 1/1
304 archiving (foo/bar) [================================>] 1/1
305 \r (esc)
305 \r (esc)
306
306
307 Disable progress extension and cleanup:
307 Disable progress extension and cleanup:
308
308
309 $ mv $HGRCPATH.no-progress $HGRCPATH
309 $ mv $HGRCPATH.no-progress $HGRCPATH
310
310
311 Clone and test outgoing:
311 Clone and test outgoing:
312
312
313 $ cd ..
313 $ cd ..
314 $ hg clone repo repo2
314 $ hg clone repo repo2
315 updating to branch default
315 updating to branch default
316 pulling subrepo foo from $TESTTMP/repo/foo
316 cloning subrepo foo from $TESTTMP/repo/foo
317 requesting all changes
317 cloning subrepo foo/bar from $TESTTMP/repo/foo/bar
318 adding changesets
319 adding manifests
320 adding file changes
321 added 4 changesets with 7 changes to 3 files
322 pulling subrepo foo/bar from $TESTTMP/repo/foo/bar
323 requesting all changes
324 adding changesets
325 adding manifests
326 adding file changes
327 added 3 changesets with 3 changes to 1 files
328 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
318 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
329 $ cd repo2
319 $ cd repo2
330 $ hg outgoing -S
320 $ hg outgoing -S
331 comparing with $TESTTMP/repo
321 comparing with $TESTTMP/repo
332 searching for changes
322 searching for changes
333 no changes found
323 no changes found
334 comparing with $TESTTMP/repo/foo
324 comparing with $TESTTMP/repo/foo
335 searching for changes
325 searching for changes
336 no changes found
326 no changes found
337 comparing with $TESTTMP/repo/foo/bar
327 comparing with $TESTTMP/repo/foo/bar
338 searching for changes
328 searching for changes
339 no changes found
329 no changes found
340 [1]
330 [1]
341
331
342 Make nested change:
332 Make nested change:
343
333
344 $ echo y4 >> foo/y.txt
334 $ echo y4 >> foo/y.txt
345 $ hg diff --nodates -S
335 $ hg diff --nodates -S
346 diff -r 65903cebad86 foo/y.txt
336 diff -r 65903cebad86 foo/y.txt
347 --- a/foo/y.txt
337 --- a/foo/y.txt
348 +++ b/foo/y.txt
338 +++ b/foo/y.txt
349 @@ -1,3 +1,4 @@
339 @@ -1,3 +1,4 @@
350 y1
340 y1
351 y2
341 y2
352 y3
342 y3
353 +y4
343 +y4
354 $ hg commit -m 3-4-2
344 $ hg commit -m 3-4-2
355 committing subrepository foo
345 committing subrepository foo
356 $ hg outgoing -S
346 $ hg outgoing -S
357 comparing with $TESTTMP/repo
347 comparing with $TESTTMP/repo
358 searching for changes
348 searching for changes
359 changeset: 3:2655b8ecc4ee
349 changeset: 3:2655b8ecc4ee
360 tag: tip
350 tag: tip
361 user: test
351 user: test
362 date: Thu Jan 01 00:00:00 1970 +0000
352 date: Thu Jan 01 00:00:00 1970 +0000
363 summary: 3-4-2
353 summary: 3-4-2
364
354
365 comparing with $TESTTMP/repo/foo
355 comparing with $TESTTMP/repo/foo
366 searching for changes
356 searching for changes
367 changeset: 4:e96193d6cb36
357 changeset: 4:e96193d6cb36
368 tag: tip
358 tag: tip
369 user: test
359 user: test
370 date: Thu Jan 01 00:00:00 1970 +0000
360 date: Thu Jan 01 00:00:00 1970 +0000
371 summary: 3-4-2
361 summary: 3-4-2
372
362
373 comparing with $TESTTMP/repo/foo/bar
363 comparing with $TESTTMP/repo/foo/bar
374 searching for changes
364 searching for changes
375 no changes found
365 no changes found
376
366
377
367
378 Switch to original repo and setup default path:
368 Switch to original repo and setup default path:
379
369
380 $ cd ../repo
370 $ cd ../repo
381 $ echo '[paths]' >> .hg/hgrc
371 $ echo '[paths]' >> .hg/hgrc
382 $ echo 'default = ../repo2' >> .hg/hgrc
372 $ echo 'default = ../repo2' >> .hg/hgrc
383
373
384 Test incoming:
374 Test incoming:
385
375
386 $ hg incoming -S
376 $ hg incoming -S
387 comparing with $TESTTMP/repo2
377 comparing with $TESTTMP/repo2
388 searching for changes
378 searching for changes
389 changeset: 3:2655b8ecc4ee
379 changeset: 3:2655b8ecc4ee
390 tag: tip
380 tag: tip
391 user: test
381 user: test
392 date: Thu Jan 01 00:00:00 1970 +0000
382 date: Thu Jan 01 00:00:00 1970 +0000
393 summary: 3-4-2
383 summary: 3-4-2
394
384
395 comparing with $TESTTMP/repo2/foo
385 comparing with $TESTTMP/repo2/foo
396 searching for changes
386 searching for changes
397 changeset: 4:e96193d6cb36
387 changeset: 4:e96193d6cb36
398 tag: tip
388 tag: tip
399 user: test
389 user: test
400 date: Thu Jan 01 00:00:00 1970 +0000
390 date: Thu Jan 01 00:00:00 1970 +0000
401 summary: 3-4-2
391 summary: 3-4-2
402
392
403 comparing with $TESTTMP/repo2/foo/bar
393 comparing with $TESTTMP/repo2/foo/bar
404 searching for changes
394 searching for changes
405 no changes found
395 no changes found
406
396
407 $ hg incoming -S --bundle incoming.hg
397 $ hg incoming -S --bundle incoming.hg
408 abort: cannot combine --bundle and --subrepos
398 abort: cannot combine --bundle and --subrepos
409 [255]
399 [255]
410
400
411 Test missing subrepo:
401 Test missing subrepo:
412
402
413 $ rm -r foo
403 $ rm -r foo
414 $ hg status -S
404 $ hg status -S
415 warning: error "unknown revision '65903cebad86f1a84bd4f1134f62fa7dcb7a1c98'" in subrepository "foo"
405 warning: error "unknown revision '65903cebad86f1a84bd4f1134f62fa7dcb7a1c98'" in subrepository "foo"
416
406
417 Issue2619: IndexError: list index out of range on hg add with subrepos
407 Issue2619: IndexError: list index out of range on hg add with subrepos
418 The subrepo must sorts after the explicit filename.
408 The subrepo must sorts after the explicit filename.
419
409
420 $ cd ..
410 $ cd ..
421 $ hg init test
411 $ hg init test
422 $ cd test
412 $ cd test
423 $ hg init x
413 $ hg init x
424 $ echo "x = x" >> .hgsub
414 $ echo "x = x" >> .hgsub
425 $ hg add .hgsub
415 $ hg add .hgsub
426 $ touch a x/a
416 $ touch a x/a
427 $ hg add a x/a
417 $ hg add a x/a
@@ -1,103 +1,103 b''
1 Preparing the subrepository 'sub'
1 Preparing the subrepository 'sub'
2
2
3 $ hg init sub
3 $ hg init sub
4 $ echo sub > sub/sub
4 $ echo sub > sub/sub
5 $ hg add -R sub
5 $ hg add -R sub
6 adding sub/sub
6 adding sub/sub
7 $ hg commit -R sub -m "sub import"
7 $ hg commit -R sub -m "sub import"
8
8
9 Preparing the 'main' repo which depends on the subrepo 'sub'
9 Preparing the 'main' repo which depends on the subrepo 'sub'
10
10
11 $ hg init main
11 $ hg init main
12 $ echo main > main/main
12 $ echo main > main/main
13 $ echo "sub = ../sub" > main/.hgsub
13 $ echo "sub = ../sub" > main/.hgsub
14 $ hg clone sub main/sub
14 $ hg clone sub main/sub
15 updating to branch default
15 updating to branch default
16 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
17 $ hg add -R main
17 $ hg add -R main
18 adding main/.hgsub
18 adding main/.hgsub
19 adding main/main
19 adding main/main
20 $ hg commit -R main -m "main import"
20 $ hg commit -R main -m "main import"
21 committing subrepository sub
21 committing subrepository sub
22
22
23 Cleaning both repositories, just as a clone -U
23 Cleaning both repositories, just as a clone -U
24
24
25 $ hg up -C -R sub null
25 $ hg up -C -R sub null
26 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
26 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
27 $ hg up -C -R main null
27 $ hg up -C -R main null
28 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
28 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
29 $ rm -rf main/sub
29 $ rm -rf main/sub
30
30
31 Serving them both using hgweb
31 Serving them both using hgweb
32
32
33 $ printf '[paths]\n/main = main\nsub = sub\n' > webdir.conf
33 $ printf '[paths]\n/main = main\nsub = sub\n' > webdir.conf
34 $ hg serve --webdir-conf webdir.conf -a localhost -p $HGPORT \
34 $ hg serve --webdir-conf webdir.conf -a localhost -p $HGPORT \
35 > -A /dev/null -E /dev/null --pid-file hg.pid -d
35 > -A /dev/null -E /dev/null --pid-file hg.pid -d
36 $ cat hg.pid >> $DAEMON_PIDS
36 $ cat hg.pid >> $DAEMON_PIDS
37
37
38 Clone main from hgweb
38 Clone main from hgweb
39
39
40 $ hg clone "http://localhost:$HGPORT/main" cloned
40 $ hg clone "http://localhost:$HGPORT/main" cloned
41 requesting all changes
41 requesting all changes
42 adding changesets
42 adding changesets
43 adding manifests
43 adding manifests
44 adding file changes
44 adding file changes
45 added 1 changesets with 3 changes to 3 files
45 added 1 changesets with 3 changes to 3 files
46 updating to branch default
46 updating to branch default
47 pulling subrepo sub from http://localhost:$HGPORT/sub
47 cloning subrepo sub from http://localhost:$HGPORT/sub
48 requesting all changes
48 requesting all changes
49 adding changesets
49 adding changesets
50 adding manifests
50 adding manifests
51 adding file changes
51 adding file changes
52 added 1 changesets with 1 changes to 1 files
52 added 1 changesets with 1 changes to 1 files
53 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
53 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
54
54
55 Checking cloned repo ids
55 Checking cloned repo ids
56
56
57 $ hg id -R cloned
57 $ hg id -R cloned
58 fdfeeb3e979e tip
58 fdfeeb3e979e tip
59 $ hg id -R cloned/sub
59 $ hg id -R cloned/sub
60 863c1745b441 tip
60 863c1745b441 tip
61
61
62 subrepo debug for 'main' clone
62 subrepo debug for 'main' clone
63
63
64 $ hg debugsub -R cloned
64 $ hg debugsub -R cloned
65 path sub
65 path sub
66 source ../sub
66 source ../sub
67 revision 863c1745b441bd97a8c4a096e87793073f4fb215
67 revision 863c1745b441bd97a8c4a096e87793073f4fb215
68
68
69 $ "$TESTDIR/killdaemons.py"
69 $ "$TESTDIR/killdaemons.py"
70
70
71 subrepo paths with ssh urls
71 subrepo paths with ssh urls
72
72
73 $ cp $TESTDIR/dummyssh $BINDIR/ssh
73 $ cp $TESTDIR/dummyssh $BINDIR/ssh
74
74
75 $ hg clone ssh://user@dummy/cloned sshclone
75 $ hg clone ssh://user@dummy/cloned sshclone
76 requesting all changes
76 requesting all changes
77 adding changesets
77 adding changesets
78 adding manifests
78 adding manifests
79 adding file changes
79 adding file changes
80 added 1 changesets with 3 changes to 3 files
80 added 1 changesets with 3 changes to 3 files
81 updating to branch default
81 updating to branch default
82 pulling subrepo sub from ssh://user@dummy/sub
82 cloning subrepo sub from ssh://user@dummy/sub
83 requesting all changes
83 requesting all changes
84 adding changesets
84 adding changesets
85 adding manifests
85 adding manifests
86 adding file changes
86 adding file changes
87 added 1 changesets with 1 changes to 1 files
87 added 1 changesets with 1 changes to 1 files
88 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
89
89
90 $ hg -R sshclone push ssh://user@dummy/$TESTTMP/cloned
90 $ hg -R sshclone push ssh://user@dummy/$TESTTMP/cloned
91 pushing to ssh://user@dummy/$TESTTMP/cloned
91 pushing to ssh://user@dummy/$TESTTMP/cloned
92 pushing subrepo sub to ssh://user@dummy/$TESTTMP/sub
92 pushing subrepo sub to ssh://user@dummy/$TESTTMP/sub
93 searching for changes
93 searching for changes
94 no changes found
94 no changes found
95 searching for changes
95 searching for changes
96 no changes found
96 no changes found
97
97
98 $ cat dummylog
98 $ cat dummylog
99 Got arguments 1:user@dummy 2:hg -R cloned serve --stdio
99 Got arguments 1:user@dummy 2:hg -R cloned serve --stdio
100 Got arguments 1:user@dummy 2:hg -R sub serve --stdio
100 Got arguments 1:user@dummy 2:hg -R sub serve --stdio
101 Got arguments 1:user@dummy 2:hg -R $TESTTMP/cloned serve --stdio
101 Got arguments 1:user@dummy 2:hg -R $TESTTMP/cloned serve --stdio
102 Got arguments 1:user@dummy 2:hg -R $TESTTMP/sub serve --stdio
102 Got arguments 1:user@dummy 2:hg -R $TESTTMP/sub serve --stdio
103 $ rm $BINDIR/ssh
103 $ rm $BINDIR/ssh
@@ -1,830 +1,805 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 (and check it is ignored by ui.commitsubrepos)
78 bump sub rev (and check it is ignored by ui.commitsubrepos)
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 --config ui.commitsubrepos=no ci -m3
82 $ hg --config ui.commitsubrepos=no ci -m3
83 committing subrepository s
83 committing subrepository s
84
84
85 leave sub dirty (and check ui.commitsubrepos=no aborts the commit)
85 leave sub dirty (and check ui.commitsubrepos=no aborts the commit)
86
86
87 $ echo c > s/a
87 $ echo c > s/a
88 $ hg --config ui.commitsubrepos=no ci -m4
88 $ hg --config ui.commitsubrepos=no ci -m4
89 abort: uncommitted changes in subrepo s
89 abort: uncommitted changes in subrepo s
90 [255]
90 [255]
91 $ hg ci -m4
91 $ hg ci -m4
92 committing subrepository s
92 committing subrepository s
93 $ hg tip -R s
93 $ hg tip -R s
94 changeset: 3:1c833a7a9e3a
94 changeset: 3:1c833a7a9e3a
95 tag: tip
95 tag: tip
96 user: test
96 user: test
97 date: Thu Jan 01 00:00:00 1970 +0000
97 date: Thu Jan 01 00:00:00 1970 +0000
98 summary: 4
98 summary: 4
99
99
100
100
101 check caching
101 check caching
102
102
103 $ hg co 0
103 $ hg co 0
104 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
104 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
105 $ hg debugsub
105 $ hg debugsub
106
106
107 restore
107 restore
108
108
109 $ hg co
109 $ hg co
110 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
110 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
111 $ hg debugsub
111 $ hg debugsub
112 path s
112 path s
113 source s
113 source s
114 revision 1c833a7a9e3a4445c711aaf0f012379cd0d4034e
114 revision 1c833a7a9e3a4445c711aaf0f012379cd0d4034e
115
115
116 new branch for merge tests
116 new branch for merge tests
117
117
118 $ hg co 1
118 $ hg co 1
119 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
119 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
120 $ echo t = t >> .hgsub
120 $ echo t = t >> .hgsub
121 $ hg init t
121 $ hg init t
122 $ echo t > t/t
122 $ echo t > t/t
123 $ hg -R t add t
123 $ hg -R t add t
124 adding t/t
124 adding t/t
125
125
126 5
126 5
127
127
128 $ hg ci -m5 # add sub
128 $ hg ci -m5 # add sub
129 committing subrepository t
129 committing subrepository t
130 created new head
130 created new head
131 $ echo t2 > t/t
131 $ echo t2 > t/t
132
132
133 6
133 6
134
134
135 $ hg st -R s
135 $ hg st -R s
136 $ hg ci -m6 # change sub
136 $ hg ci -m6 # change sub
137 committing subrepository t
137 committing subrepository t
138 $ hg debugsub
138 $ hg debugsub
139 path s
139 path s
140 source s
140 source s
141 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
141 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
142 path t
142 path t
143 source t
143 source t
144 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
144 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
145 $ echo t3 > t/t
145 $ echo t3 > t/t
146
146
147 7
147 7
148
148
149 $ hg ci -m7 # change sub again for conflict test
149 $ hg ci -m7 # change sub again for conflict test
150 committing subrepository t
150 committing subrepository t
151 $ hg rm .hgsub
151 $ hg rm .hgsub
152
152
153 8
153 8
154
154
155 $ hg ci -m8 # remove sub
155 $ hg ci -m8 # remove sub
156
156
157 merge tests
157 merge tests
158
158
159 $ hg co -C 3
159 $ hg co -C 3
160 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
160 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
161 $ hg merge 5 # test adding
161 $ hg merge 5 # test adding
162 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
162 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
163 (branch merge, don't forget to commit)
163 (branch merge, don't forget to commit)
164 $ hg debugsub
164 $ hg debugsub
165 path s
165 path s
166 source s
166 source s
167 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
167 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
168 path t
168 path t
169 source t
169 source t
170 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
170 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
171 $ hg ci -m9
171 $ hg ci -m9
172 created new head
172 created new head
173 $ hg merge 6 --debug # test change
173 $ hg merge 6 --debug # test change
174 searching for copies back to rev 2
174 searching for copies back to rev 2
175 resolving manifests
175 resolving manifests
176 overwrite None partial False
176 overwrite None partial False
177 ancestor 1f14a2e2d3ec local f0d2028bf86d+ remote 1831e14459c4
177 ancestor 1f14a2e2d3ec local f0d2028bf86d+ remote 1831e14459c4
178 .hgsubstate: versions differ -> m
178 .hgsubstate: versions differ -> m
179 updating: .hgsubstate 1/1 files (100.00%)
179 updating: .hgsubstate 1/1 files (100.00%)
180 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
180 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
181 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
181 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
182 getting subrepo t
182 getting subrepo t
183 resolving manifests
183 resolving manifests
184 overwrite True partial False
184 overwrite True partial False
185 ancestor 60ca1237c194+ local 60ca1237c194+ remote 6747d179aa9a
185 ancestor 60ca1237c194+ local 60ca1237c194+ remote 6747d179aa9a
186 t: remote is newer -> g
186 t: remote is newer -> g
187 updating: t 1/1 files (100.00%)
187 updating: t 1/1 files (100.00%)
188 getting t
188 getting t
189 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
189 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 (branch merge, don't forget to commit)
190 (branch merge, don't forget to commit)
191 $ hg debugsub
191 $ hg debugsub
192 path s
192 path s
193 source s
193 source s
194 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
194 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
195 path t
195 path t
196 source t
196 source t
197 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
197 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
198 $ echo conflict > t/t
198 $ echo conflict > t/t
199 $ hg ci -m10
199 $ hg ci -m10
200 committing subrepository t
200 committing subrepository t
201 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
201 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
202 searching for copies back to rev 2
202 searching for copies back to rev 2
203 resolving manifests
203 resolving manifests
204 overwrite None partial False
204 overwrite None partial False
205 ancestor 1831e14459c4 local e45c8b14af55+ remote f94576341bcf
205 ancestor 1831e14459c4 local e45c8b14af55+ remote f94576341bcf
206 .hgsubstate: versions differ -> m
206 .hgsubstate: versions differ -> m
207 updating: .hgsubstate 1/1 files (100.00%)
207 updating: .hgsubstate 1/1 files (100.00%)
208 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
208 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
209 subrepo t: both sides changed, merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
209 subrepo t: both sides changed, merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
210 merging subrepo t
210 merging subrepo t
211 searching for copies back to rev 2
211 searching for copies back to rev 2
212 resolving manifests
212 resolving manifests
213 overwrite None partial False
213 overwrite None partial False
214 ancestor 6747d179aa9a local 20a0db6fbf6c+ remote 7af322bc1198
214 ancestor 6747d179aa9a local 20a0db6fbf6c+ remote 7af322bc1198
215 t: versions differ -> m
215 t: versions differ -> m
216 preserving t for resolve of t
216 preserving t for resolve of t
217 updating: t 1/1 files (100.00%)
217 updating: t 1/1 files (100.00%)
218 picked tool 'internal:merge' for t (binary False symlink False)
218 picked tool 'internal:merge' for t (binary False symlink False)
219 merging t
219 merging t
220 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
220 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
221 warning: conflicts during merge.
221 warning: conflicts during merge.
222 merging t failed!
222 merging t failed!
223 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
223 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
224 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
224 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
225 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
225 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
226 (branch merge, don't forget to commit)
226 (branch merge, don't forget to commit)
227
227
228 should conflict
228 should conflict
229
229
230 $ cat t/t
230 $ cat t/t
231 <<<<<<< local
231 <<<<<<< local
232 conflict
232 conflict
233 =======
233 =======
234 t3
234 t3
235 >>>>>>> other
235 >>>>>>> other
236
236
237 clone
237 clone
238
238
239 $ cd ..
239 $ cd ..
240 $ hg clone t tc
240 $ hg clone t tc
241 updating to branch default
241 updating to branch default
242 pulling subrepo s from $TESTTMP/sub/t/s
242 cloning subrepo s from $TESTTMP/sub/t/s
243 requesting all changes
243 cloning subrepo s/ss from $TESTTMP/sub/t/s/ss
244 adding changesets
244 cloning subrepo t from $TESTTMP/sub/t/t
245 adding manifests
246 adding file changes
247 added 4 changesets with 5 changes to 3 files
248 pulling subrepo s/ss from $TESTTMP/sub/t/s/ss
249 requesting all changes
250 adding changesets
251 adding manifests
252 adding file changes
253 added 1 changesets with 1 changes to 1 files
254 pulling subrepo t from $TESTTMP/sub/t/t
255 requesting all changes
256 adding changesets
257 adding manifests
258 adding file changes
259 added 4 changesets with 4 changes to 1 files (+1 heads)
260 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
245 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
261 $ cd tc
246 $ cd tc
262 $ hg debugsub
247 $ hg debugsub
263 path s
248 path s
264 source s
249 source s
265 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
250 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
266 path t
251 path t
267 source t
252 source t
268 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
253 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
269
254
270 push
255 push
271
256
272 $ echo bah > t/t
257 $ echo bah > t/t
273 $ hg ci -m11
258 $ hg ci -m11
274 committing subrepository t
259 committing subrepository t
275 $ hg push
260 $ hg push
276 pushing to $TESTTMP/sub/t
261 pushing to $TESTTMP/sub/t
277 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
262 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
278 searching for changes
263 searching for changes
279 no changes found
264 no changes found
280 pushing subrepo s to $TESTTMP/sub/t/s
265 pushing subrepo s to $TESTTMP/sub/t/s
281 searching for changes
266 searching for changes
282 no changes found
267 no changes found
283 pushing subrepo t to $TESTTMP/sub/t/t
268 pushing subrepo t to $TESTTMP/sub/t/t
284 searching for changes
269 searching for changes
285 adding changesets
270 adding changesets
286 adding manifests
271 adding manifests
287 adding file changes
272 adding file changes
288 added 1 changesets with 1 changes to 1 files
273 added 1 changesets with 1 changes to 1 files
289 searching for changes
274 searching for changes
290 adding changesets
275 adding changesets
291 adding manifests
276 adding manifests
292 adding file changes
277 adding file changes
293 added 1 changesets with 1 changes to 1 files
278 added 1 changesets with 1 changes to 1 files
294
279
295 push -f
280 push -f
296
281
297 $ echo bah > s/a
282 $ echo bah > s/a
298 $ hg ci -m12
283 $ hg ci -m12
299 committing subrepository s
284 committing subrepository s
300 $ hg push
285 $ hg push
301 pushing to $TESTTMP/sub/t
286 pushing to $TESTTMP/sub/t
302 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
287 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
303 searching for changes
288 searching for changes
304 no changes found
289 no changes found
305 pushing subrepo s to $TESTTMP/sub/t/s
290 pushing subrepo s to $TESTTMP/sub/t/s
306 searching for changes
291 searching for changes
307 abort: push creates new remote heads on branch 'default'!
292 abort: push creates new remote heads on branch 'default'!
308 (did you forget to merge? use push -f to force)
293 (did you forget to merge? use push -f to force)
309 [255]
294 [255]
310 $ hg push -f
295 $ hg push -f
311 pushing to $TESTTMP/sub/t
296 pushing to $TESTTMP/sub/t
312 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
297 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
313 searching for changes
298 searching for changes
314 no changes found
299 no changes found
315 pushing subrepo s to $TESTTMP/sub/t/s
300 pushing subrepo s to $TESTTMP/sub/t/s
316 searching for changes
301 searching for changes
317 adding changesets
302 adding changesets
318 adding manifests
303 adding manifests
319 adding file changes
304 adding file changes
320 added 1 changesets with 1 changes to 1 files (+1 heads)
305 added 1 changesets with 1 changes to 1 files (+1 heads)
321 pushing subrepo t to $TESTTMP/sub/t/t
306 pushing subrepo t to $TESTTMP/sub/t/t
322 searching for changes
307 searching for changes
323 no changes found
308 no changes found
324 searching for changes
309 searching for changes
325 adding changesets
310 adding changesets
326 adding manifests
311 adding manifests
327 adding file changes
312 adding file changes
328 added 1 changesets with 1 changes to 1 files
313 added 1 changesets with 1 changes to 1 files
329
314
330 update
315 update
331
316
332 $ cd ../t
317 $ cd ../t
333 $ hg up -C # discard our earlier merge
318 $ hg up -C # discard our earlier merge
334 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
319 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
335 $ echo blah > t/t
320 $ echo blah > t/t
336 $ hg ci -m13
321 $ hg ci -m13
337 committing subrepository t
322 committing subrepository t
338
323
339 pull
324 pull
340
325
341 $ cd ../tc
326 $ cd ../tc
342 $ hg pull
327 $ hg pull
343 pulling from $TESTTMP/sub/t
328 pulling from $TESTTMP/sub/t
344 searching for changes
329 searching for changes
345 adding changesets
330 adding changesets
346 adding manifests
331 adding manifests
347 adding file changes
332 adding file changes
348 added 1 changesets with 1 changes to 1 files
333 added 1 changesets with 1 changes to 1 files
349 (run 'hg update' to get a working copy)
334 (run 'hg update' to get a working copy)
350
335
351 should pull t
336 should pull t
352
337
353 $ hg up
338 $ hg up
354 pulling subrepo t from $TESTTMP/sub/t/t
339 pulling subrepo t from $TESTTMP/sub/t/t
355 searching for changes
340 searching for changes
356 adding changesets
341 adding changesets
357 adding manifests
342 adding manifests
358 adding file changes
343 adding file changes
359 added 1 changesets with 1 changes to 1 files
344 added 1 changesets with 1 changes to 1 files
360 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
345 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
361 $ cat t/t
346 $ cat t/t
362 blah
347 blah
363
348
364 bogus subrepo path aborts
349 bogus subrepo path aborts
365
350
366 $ echo 'bogus=[boguspath' >> .hgsub
351 $ echo 'bogus=[boguspath' >> .hgsub
367 $ hg ci -m 'bogus subrepo path'
352 $ hg ci -m 'bogus subrepo path'
368 abort: missing ] in subrepo source
353 abort: missing ] in subrepo source
369 [255]
354 [255]
370
355
371 Issue1986: merge aborts when trying to merge a subrepo that
356 Issue1986: merge aborts when trying to merge a subrepo that
372 shouldn't need merging
357 shouldn't need merging
373
358
374 # subrepo layout
359 # subrepo layout
375 #
360 #
376 # o 5 br
361 # o 5 br
377 # /|
362 # /|
378 # o | 4 default
363 # o | 4 default
379 # | |
364 # | |
380 # | o 3 br
365 # | o 3 br
381 # |/|
366 # |/|
382 # o | 2 default
367 # o | 2 default
383 # | |
368 # | |
384 # | o 1 br
369 # | o 1 br
385 # |/
370 # |/
386 # o 0 default
371 # o 0 default
387
372
388 $ cd ..
373 $ cd ..
389 $ rm -rf sub
374 $ rm -rf sub
390 $ hg init main
375 $ hg init main
391 $ cd main
376 $ cd main
392 $ hg init s
377 $ hg init s
393 $ cd s
378 $ cd s
394 $ echo a > a
379 $ echo a > a
395 $ hg ci -Am1
380 $ hg ci -Am1
396 adding a
381 adding a
397 $ hg branch br
382 $ hg branch br
398 marked working directory as branch br
383 marked working directory as branch br
399 $ echo a >> a
384 $ echo a >> a
400 $ hg ci -m1
385 $ hg ci -m1
401 $ hg up default
386 $ hg up default
402 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
387 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
403 $ echo b > b
388 $ echo b > b
404 $ hg ci -Am1
389 $ hg ci -Am1
405 adding b
390 adding b
406 $ hg up br
391 $ hg up br
407 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
392 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
408 $ hg merge tip
393 $ hg merge tip
409 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
394 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
410 (branch merge, don't forget to commit)
395 (branch merge, don't forget to commit)
411 $ hg ci -m1
396 $ hg ci -m1
412 $ hg up 2
397 $ hg up 2
413 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
398 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
414 $ echo c > c
399 $ echo c > c
415 $ hg ci -Am1
400 $ hg ci -Am1
416 adding c
401 adding c
417 $ hg up 3
402 $ hg up 3
418 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
403 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
419 $ hg merge 4
404 $ hg merge 4
420 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
405 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
421 (branch merge, don't forget to commit)
406 (branch merge, don't forget to commit)
422 $ hg ci -m1
407 $ hg ci -m1
423
408
424 # main repo layout:
409 # main repo layout:
425 #
410 #
426 # * <-- try to merge default into br again
411 # * <-- try to merge default into br again
427 # .`|
412 # .`|
428 # . o 5 br --> substate = 5
413 # . o 5 br --> substate = 5
429 # . |
414 # . |
430 # o | 4 default --> substate = 4
415 # o | 4 default --> substate = 4
431 # | |
416 # | |
432 # | o 3 br --> substate = 2
417 # | o 3 br --> substate = 2
433 # |/|
418 # |/|
434 # o | 2 default --> substate = 2
419 # o | 2 default --> substate = 2
435 # | |
420 # | |
436 # | o 1 br --> substate = 3
421 # | o 1 br --> substate = 3
437 # |/
422 # |/
438 # o 0 default --> substate = 2
423 # o 0 default --> substate = 2
439
424
440 $ cd ..
425 $ cd ..
441 $ echo 's = s' > .hgsub
426 $ echo 's = s' > .hgsub
442 $ hg -R s up 2
427 $ hg -R s up 2
443 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
428 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
444 $ hg ci -Am1
429 $ hg ci -Am1
445 adding .hgsub
430 adding .hgsub
446 committing subrepository s
431 committing subrepository s
447 $ hg branch br
432 $ hg branch br
448 marked working directory as branch br
433 marked working directory as branch br
449 $ echo b > b
434 $ echo b > b
450 $ hg -R s up 3
435 $ hg -R s up 3
451 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
436 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
452 $ hg ci -Am1
437 $ hg ci -Am1
453 adding b
438 adding b
454 committing subrepository s
439 committing subrepository s
455 $ hg up default
440 $ hg up default
456 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
441 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
457 $ echo c > c
442 $ echo c > c
458 $ hg ci -Am1
443 $ hg ci -Am1
459 adding c
444 adding c
460 $ hg up 1
445 $ hg up 1
461 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
446 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
462 $ hg merge 2
447 $ hg merge 2
463 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
464 (branch merge, don't forget to commit)
449 (branch merge, don't forget to commit)
465 $ hg ci -m1
450 $ hg ci -m1
466 $ hg up 2
451 $ hg up 2
467 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
452 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
468 $ hg -R s up 4
453 $ hg -R s up 4
469 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
454 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
470 $ echo d > d
455 $ echo d > d
471 $ hg ci -Am1
456 $ hg ci -Am1
472 adding d
457 adding d
473 committing subrepository s
458 committing subrepository s
474 $ hg up 3
459 $ hg up 3
475 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
460 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
476 $ hg -R s up 5
461 $ hg -R s up 5
477 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
462 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
478 $ echo e > e
463 $ echo e > e
479 $ hg ci -Am1
464 $ hg ci -Am1
480 adding e
465 adding e
481 committing subrepository s
466 committing subrepository s
482
467
483 $ hg up 5
468 $ hg up 5
484 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
469 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
485 $ hg merge 4 # try to merge default into br again
470 $ hg merge 4 # try to merge default into br again
486 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
471 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
487 (branch merge, don't forget to commit)
472 (branch merge, don't forget to commit)
488 $ cd ..
473 $ cd ..
489
474
490 test subrepo delete from .hgsubstate
475 test subrepo delete from .hgsubstate
491
476
492 $ hg init testdelete
477 $ hg init testdelete
493 $ mkdir testdelete/nested testdelete/nested2
478 $ mkdir testdelete/nested testdelete/nested2
494 $ hg init testdelete/nested
479 $ hg init testdelete/nested
495 $ hg init testdelete/nested2
480 $ hg init testdelete/nested2
496 $ echo test > testdelete/nested/foo
481 $ echo test > testdelete/nested/foo
497 $ echo test > testdelete/nested2/foo
482 $ echo test > testdelete/nested2/foo
498 $ hg -R testdelete/nested add
483 $ hg -R testdelete/nested add
499 adding testdelete/nested/foo
484 adding testdelete/nested/foo
500 $ hg -R testdelete/nested2 add
485 $ hg -R testdelete/nested2 add
501 adding testdelete/nested2/foo
486 adding testdelete/nested2/foo
502 $ hg -R testdelete/nested ci -m test
487 $ hg -R testdelete/nested ci -m test
503 $ hg -R testdelete/nested2 ci -m test
488 $ hg -R testdelete/nested2 ci -m test
504 $ echo nested = nested > testdelete/.hgsub
489 $ echo nested = nested > testdelete/.hgsub
505 $ echo nested2 = nested2 >> testdelete/.hgsub
490 $ echo nested2 = nested2 >> testdelete/.hgsub
506 $ hg -R testdelete add
491 $ hg -R testdelete add
507 adding testdelete/.hgsub
492 adding testdelete/.hgsub
508 $ hg -R testdelete ci -m "nested 1 & 2 added"
493 $ hg -R testdelete ci -m "nested 1 & 2 added"
509 committing subrepository nested
494 committing subrepository nested
510 committing subrepository nested2
495 committing subrepository nested2
511 $ echo nested = nested > testdelete/.hgsub
496 $ echo nested = nested > testdelete/.hgsub
512 $ hg -R testdelete ci -m "nested 2 deleted"
497 $ hg -R testdelete ci -m "nested 2 deleted"
513 $ cat testdelete/.hgsubstate
498 $ cat testdelete/.hgsubstate
514 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
499 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
515 $ hg -R testdelete remove testdelete/.hgsub
500 $ hg -R testdelete remove testdelete/.hgsub
516 $ hg -R testdelete ci -m ".hgsub deleted"
501 $ hg -R testdelete ci -m ".hgsub deleted"
517 $ cat testdelete/.hgsubstate
502 $ cat testdelete/.hgsubstate
518
503
519 test repository cloning
504 test repository cloning
520
505
521 $ mkdir mercurial mercurial2
506 $ mkdir mercurial mercurial2
522 $ hg init nested_absolute
507 $ hg init nested_absolute
523 $ echo test > nested_absolute/foo
508 $ echo test > nested_absolute/foo
524 $ hg -R nested_absolute add
509 $ hg -R nested_absolute add
525 adding nested_absolute/foo
510 adding nested_absolute/foo
526 $ hg -R nested_absolute ci -mtest
511 $ hg -R nested_absolute ci -mtest
527 $ cd mercurial
512 $ cd mercurial
528 $ hg init nested_relative
513 $ hg init nested_relative
529 $ echo test2 > nested_relative/foo2
514 $ echo test2 > nested_relative/foo2
530 $ hg -R nested_relative add
515 $ hg -R nested_relative add
531 adding nested_relative/foo2
516 adding nested_relative/foo2
532 $ hg -R nested_relative ci -mtest2
517 $ hg -R nested_relative ci -mtest2
533 $ hg init main
518 $ hg init main
534 $ echo "nested_relative = ../nested_relative" > main/.hgsub
519 $ echo "nested_relative = ../nested_relative" > main/.hgsub
535 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
520 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
536 $ hg -R main add
521 $ hg -R main add
537 adding main/.hgsub
522 adding main/.hgsub
538 $ hg -R main ci -m "add subrepos"
523 $ hg -R main ci -m "add subrepos"
539 committing subrepository nested_absolute
524 committing subrepository nested_absolute
540 committing subrepository nested_relative
525 committing subrepository nested_relative
541 $ cd ..
526 $ cd ..
542 $ hg clone mercurial/main mercurial2/main
527 $ hg clone mercurial/main mercurial2/main
543 updating to branch default
528 updating to branch default
544 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
529 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
545 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
530 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
546 > mercurial2/main/nested_relative/.hg/hgrc
531 > mercurial2/main/nested_relative/.hg/hgrc
547 [paths]
532 [paths]
548 default = $TESTTMP/sub/mercurial/nested_absolute
533 default = $TESTTMP/sub/mercurial/nested_absolute
549 [paths]
534 [paths]
550 default = $TESTTMP/sub/mercurial/nested_relative
535 default = $TESTTMP/sub/mercurial/nested_relative
551 $ rm -rf mercurial mercurial2
536 $ rm -rf mercurial mercurial2
552
537
553 Issue1977: multirepo push should fail if subrepo push fails
538 Issue1977: multirepo push should fail if subrepo push fails
554
539
555 $ hg init repo
540 $ hg init repo
556 $ hg init repo/s
541 $ hg init repo/s
557 $ echo a > repo/s/a
542 $ echo a > repo/s/a
558 $ hg -R repo/s ci -Am0
543 $ hg -R repo/s ci -Am0
559 adding a
544 adding a
560 $ echo s = s > repo/.hgsub
545 $ echo s = s > repo/.hgsub
561 $ hg -R repo ci -Am1
546 $ hg -R repo ci -Am1
562 adding .hgsub
547 adding .hgsub
563 committing subrepository s
548 committing subrepository s
564 $ hg clone repo repo2
549 $ hg clone repo repo2
565 updating to branch default
550 updating to branch default
566 pulling subrepo s from $TESTTMP/sub/repo/s
551 cloning subrepo s from $TESTTMP/sub/repo/s
567 requesting all changes
568 adding changesets
569 adding manifests
570 adding file changes
571 added 1 changesets with 1 changes to 1 files
572 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
552 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
573 $ hg -q -R repo2 pull -u
553 $ hg -q -R repo2 pull -u
574 $ echo 1 > repo2/s/a
554 $ echo 1 > repo2/s/a
575 $ hg -R repo2/s ci -m2
555 $ hg -R repo2/s ci -m2
576 $ hg -q -R repo2/s push
556 $ hg -q -R repo2/s push
577 $ hg -R repo2/s up -C 0
557 $ hg -R repo2/s up -C 0
578 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
558 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
579 $ echo 2 > repo2/s/a
559 $ echo 2 > repo2/s/a
580 $ hg -R repo2/s ci -m3
560 $ hg -R repo2/s ci -m3
581 created new head
561 created new head
582 $ hg -R repo2 ci -m3
562 $ hg -R repo2 ci -m3
583 committing subrepository s
563 committing subrepository s
584 $ hg -q -R repo2 push
564 $ hg -q -R repo2 push
585 abort: push creates new remote heads on branch 'default'!
565 abort: push creates new remote heads on branch 'default'!
586 (did you forget to merge? use push -f to force)
566 (did you forget to merge? use push -f to force)
587 [255]
567 [255]
588 $ hg -R repo update
568 $ hg -R repo update
589 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
569 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
590 $ rm -rf repo2 repo
570 $ rm -rf repo2 repo
591
571
592
572
593 Issue1852 subrepos with relative paths always push/pull relative to default
573 Issue1852 subrepos with relative paths always push/pull relative to default
594
574
595 Prepare a repo with subrepo
575 Prepare a repo with subrepo
596
576
597 $ hg init issue1852a
577 $ hg init issue1852a
598 $ cd issue1852a
578 $ cd issue1852a
599 $ hg init sub/repo
579 $ hg init sub/repo
600 $ echo test > sub/repo/foo
580 $ echo test > sub/repo/foo
601 $ hg -R sub/repo add sub/repo/foo
581 $ hg -R sub/repo add sub/repo/foo
602 $ echo sub/repo = sub/repo > .hgsub
582 $ echo sub/repo = sub/repo > .hgsub
603 $ hg add .hgsub
583 $ hg add .hgsub
604 $ hg ci -mtest
584 $ hg ci -mtest
605 committing subrepository sub/repo
585 committing subrepository sub/repo
606 $ echo test >> sub/repo/foo
586 $ echo test >> sub/repo/foo
607 $ hg ci -mtest
587 $ hg ci -mtest
608 committing subrepository sub/repo
588 committing subrepository sub/repo
609 $ cd ..
589 $ cd ..
610
590
611 Create repo without default path, pull top repo, and see what happens on update
591 Create repo without default path, pull top repo, and see what happens on update
612
592
613 $ hg init issue1852b
593 $ hg init issue1852b
614 $ hg -R issue1852b pull issue1852a
594 $ hg -R issue1852b pull issue1852a
615 pulling from issue1852a
595 pulling from issue1852a
616 requesting all changes
596 requesting all changes
617 adding changesets
597 adding changesets
618 adding manifests
598 adding manifests
619 adding file changes
599 adding file changes
620 added 2 changesets with 3 changes to 2 files
600 added 2 changesets with 3 changes to 2 files
621 (run 'hg update' to get a working copy)
601 (run 'hg update' to get a working copy)
622 $ hg -R issue1852b update
602 $ hg -R issue1852b update
623 abort: default path for subrepository sub/repo not found
603 abort: default path for subrepository sub/repo not found
624 [255]
604 [255]
625
605
626 Pull -u now doesn't help
606 Pull -u now doesn't help
627
607
628 $ hg -R issue1852b pull -u issue1852a
608 $ hg -R issue1852b pull -u issue1852a
629 pulling from issue1852a
609 pulling from issue1852a
630 searching for changes
610 searching for changes
631 no changes found
611 no changes found
632
612
633 Try the same, but with pull -u
613 Try the same, but with pull -u
634
614
635 $ hg init issue1852c
615 $ hg init issue1852c
636 $ hg -R issue1852c pull -r0 -u issue1852a
616 $ hg -R issue1852c pull -r0 -u issue1852a
637 pulling from issue1852a
617 pulling from issue1852a
638 adding changesets
618 adding changesets
639 adding manifests
619 adding manifests
640 adding file changes
620 adding file changes
641 added 1 changesets with 2 changes to 2 files
621 added 1 changesets with 2 changes to 2 files
642 pulling subrepo sub/repo from issue1852a/sub/repo
622 cloning subrepo sub/repo from issue1852a/sub/repo
643 requesting all changes
644 adding changesets
645 adding manifests
646 adding file changes
647 added 2 changesets with 2 changes to 1 files
648 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
623 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
649
624
650 Try to push from the other side
625 Try to push from the other side
651
626
652 $ hg -R issue1852a push `pwd`/issue1852c
627 $ hg -R issue1852a push `pwd`/issue1852c
653 pushing to $TESTTMP/sub/issue1852c
628 pushing to $TESTTMP/sub/issue1852c
654 pushing subrepo sub/repo to $TESTTMP/sub/issue1852c/sub/repo
629 pushing subrepo sub/repo to $TESTTMP/sub/issue1852c/sub/repo
655 searching for changes
630 searching for changes
656 no changes found
631 no changes found
657 searching for changes
632 searching for changes
658 adding changesets
633 adding changesets
659 adding manifests
634 adding manifests
660 adding file changes
635 adding file changes
661 added 1 changesets with 1 changes to 1 files
636 added 1 changesets with 1 changes to 1 files
662
637
663 Check status of files when none of them belong to the first
638 Check status of files when none of them belong to the first
664 subrepository:
639 subrepository:
665
640
666 $ hg init subrepo-status
641 $ hg init subrepo-status
667 $ cd subrepo-status
642 $ cd subrepo-status
668 $ hg init subrepo-1
643 $ hg init subrepo-1
669 $ hg init subrepo-2
644 $ hg init subrepo-2
670 $ cd subrepo-2
645 $ cd subrepo-2
671 $ touch file
646 $ touch file
672 $ hg add file
647 $ hg add file
673 $ cd ..
648 $ cd ..
674 $ echo subrepo-1 = subrepo-1 > .hgsub
649 $ echo subrepo-1 = subrepo-1 > .hgsub
675 $ echo subrepo-2 = subrepo-2 >> .hgsub
650 $ echo subrepo-2 = subrepo-2 >> .hgsub
676 $ hg add .hgsub
651 $ hg add .hgsub
677 $ hg ci -m 'Added subrepos'
652 $ hg ci -m 'Added subrepos'
678 committing subrepository subrepo-1
653 committing subrepository subrepo-1
679 committing subrepository subrepo-2
654 committing subrepository subrepo-2
680 $ hg st subrepo-2/file
655 $ hg st subrepo-2/file
681
656
682 Check hg update --clean
657 Check hg update --clean
683 $ cd $TESTTMP/sub/t
658 $ cd $TESTTMP/sub/t
684 $ rm -r t/t.orig
659 $ rm -r t/t.orig
685 $ hg status -S --all
660 $ hg status -S --all
686 C .hgsub
661 C .hgsub
687 C .hgsubstate
662 C .hgsubstate
688 C a
663 C a
689 C s/.hgsub
664 C s/.hgsub
690 C s/.hgsubstate
665 C s/.hgsubstate
691 C s/a
666 C s/a
692 C s/ss/a
667 C s/ss/a
693 C t/t
668 C t/t
694 $ echo c1 > s/a
669 $ echo c1 > s/a
695 $ cd s
670 $ cd s
696 $ echo c1 > b
671 $ echo c1 > b
697 $ echo c1 > c
672 $ echo c1 > c
698 $ hg add b
673 $ hg add b
699 $ cd ..
674 $ cd ..
700 $ hg status -S
675 $ hg status -S
701 M s/a
676 M s/a
702 A s/b
677 A s/b
703 ? s/c
678 ? s/c
704 $ hg update -C
679 $ hg update -C
705 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
680 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
706 $ hg status -S
681 $ hg status -S
707 ? s/b
682 ? s/b
708 ? s/c
683 ? s/c
709
684
710 Sticky subrepositories, no changes
685 Sticky subrepositories, no changes
711 $ cd $TESTTMP/sub/t
686 $ cd $TESTTMP/sub/t
712 $ hg id
687 $ hg id
713 925c17564ef8 tip
688 925c17564ef8 tip
714 $ hg -R s id
689 $ hg -R s id
715 12a213df6fa9 tip
690 12a213df6fa9 tip
716 $ hg -R t id
691 $ hg -R t id
717 52c0adc0515a tip
692 52c0adc0515a tip
718 $ hg update 11
693 $ hg update 11
719 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
694 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
720 $ hg id
695 $ hg id
721 365661e5936a
696 365661e5936a
722 $ hg -R s id
697 $ hg -R s id
723 fc627a69481f
698 fc627a69481f
724 $ hg -R t id
699 $ hg -R t id
725 e95bcfa18a35
700 e95bcfa18a35
726
701
727 Sticky subrepositorys, file changes
702 Sticky subrepositorys, file changes
728 $ touch s/f1
703 $ touch s/f1
729 $ touch t/f1
704 $ touch t/f1
730 $ hg add -S s/f1
705 $ hg add -S s/f1
731 $ hg add -S t/f1
706 $ hg add -S t/f1
732 $ hg id
707 $ hg id
733 365661e5936a
708 365661e5936a
734 $ hg -R s id
709 $ hg -R s id
735 fc627a69481f+
710 fc627a69481f+
736 $ hg -R t id
711 $ hg -R t id
737 e95bcfa18a35+
712 e95bcfa18a35+
738 $ hg update tip
713 $ hg update tip
739 subrepository sources for s differ
714 subrepository sources for s differ
740 use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9)?
715 use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9)?
741 l
716 l
742 subrepository sources for t differ
717 subrepository sources for t differ
743 use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a)?
718 use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a)?
744 l
719 l
745 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
720 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
746 $ hg id
721 $ hg id
747 925c17564ef8+ tip
722 925c17564ef8+ tip
748 $ hg -R s id
723 $ hg -R s id
749 fc627a69481f+
724 fc627a69481f+
750 $ hg -R t id
725 $ hg -R t id
751 e95bcfa18a35+
726 e95bcfa18a35+
752 $ hg update --clean tip
727 $ hg update --clean tip
753 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
728 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
754
729
755 Sticky subrepository, revision updates
730 Sticky subrepository, revision updates
756 $ hg id
731 $ hg id
757 925c17564ef8 tip
732 925c17564ef8 tip
758 $ hg -R s id
733 $ hg -R s id
759 12a213df6fa9 tip
734 12a213df6fa9 tip
760 $ hg -R t id
735 $ hg -R t id
761 52c0adc0515a tip
736 52c0adc0515a tip
762 $ cd s
737 $ cd s
763 $ hg update -r -2
738 $ hg update -r -2
764 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
739 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
765 $ cd ../t
740 $ cd ../t
766 $ hg update -r 2
741 $ hg update -r 2
767 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
742 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
768 $ cd ..
743 $ cd ..
769 $ hg update 10
744 $ hg update 10
770 subrepository sources for t differ (in checked out version)
745 subrepository sources for t differ (in checked out version)
771 use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c)?
746 use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c)?
772 l
747 l
773 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
748 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
774 $ hg id
749 $ hg id
775 e45c8b14af55+
750 e45c8b14af55+
776 $ hg -R s id
751 $ hg -R s id
777 1c833a7a9e3a
752 1c833a7a9e3a
778 $ hg -R t id
753 $ hg -R t id
779 7af322bc1198
754 7af322bc1198
780
755
781 Sticky subrepository, file changes and revision updates
756 Sticky subrepository, file changes and revision updates
782 $ touch s/f1
757 $ touch s/f1
783 $ touch t/f1
758 $ touch t/f1
784 $ hg add -S s/f1
759 $ hg add -S s/f1
785 $ hg add -S t/f1
760 $ hg add -S t/f1
786 $ hg id
761 $ hg id
787 e45c8b14af55+
762 e45c8b14af55+
788 $ hg -R s id
763 $ hg -R s id
789 1c833a7a9e3a+
764 1c833a7a9e3a+
790 $ hg -R t id
765 $ hg -R t id
791 7af322bc1198+
766 7af322bc1198+
792 $ hg update tip
767 $ hg update tip
793 subrepository sources for s differ
768 subrepository sources for s differ
794 use (l)ocal source (1c833a7a9e3a) or (r)emote source (12a213df6fa9)?
769 use (l)ocal source (1c833a7a9e3a) or (r)emote source (12a213df6fa9)?
795 l
770 l
796 subrepository sources for t differ
771 subrepository sources for t differ
797 use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a)?
772 use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a)?
798 l
773 l
799 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
774 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
800 $ hg id
775 $ hg id
801 925c17564ef8 tip
776 925c17564ef8 tip
802 $ hg -R s id
777 $ hg -R s id
803 1c833a7a9e3a+
778 1c833a7a9e3a+
804 $ hg -R t id
779 $ hg -R t id
805 7af322bc1198+
780 7af322bc1198+
806
781
807 Sticky repository, update --clean
782 Sticky repository, update --clean
808 $ hg update --clean tip
783 $ hg update --clean tip
809 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
784 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
810 $ hg id
785 $ hg id
811 925c17564ef8 tip
786 925c17564ef8 tip
812 $ hg -R s id
787 $ hg -R s id
813 12a213df6fa9 tip
788 12a213df6fa9 tip
814 $ hg -R t id
789 $ hg -R t id
815 52c0adc0515a tip
790 52c0adc0515a tip
816
791
817 Test subrepo already at intended revision:
792 Test subrepo already at intended revision:
818 $ cd s
793 $ cd s
819 $ hg update fc627a69481f
794 $ hg update fc627a69481f
820 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
795 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
821 $ cd ..
796 $ cd ..
822 $ hg update 11
797 $ hg update 11
823 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
798 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
824 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
799 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
825 $ hg id -n
800 $ hg id -n
826 11+
801 11+
827 $ hg -R s id
802 $ hg -R s id
828 fc627a69481f
803 fc627a69481f
829 $ hg -R t id
804 $ hg -R t id
830 e95bcfa18a35
805 e95bcfa18a35
General Comments 0
You need to be logged in to leave comments. Login now