##// END OF EJS Templates
merge: let the user choose to merge, keep local or keep remote subrepo revisions...
Angel Ezquerra -
r19811:5e10d41e default
parent child Browse files
Show More
@@ -1,1454 +1,1469
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, shutil, posixpath, sys
8 import errno, os, re, shutil, posixpath, sys
9 import xml.dom.minidom
9 import xml.dom.minidom
10 import stat, subprocess, tarfile
10 import stat, subprocess, tarfile
11 from i18n import _
11 from i18n import _
12 import config, scmutil, util, node, error, cmdutil, bookmarks, match as matchmod
12 import config, scmutil, util, node, error, cmdutil, bookmarks, match as matchmod
13 hg = None
13 hg = None
14 propertycache = util.propertycache
14 propertycache = util.propertycache
15
15
16 nullstate = ('', '', 'empty')
16 nullstate = ('', '', 'empty')
17
17
18 def _expandedabspath(path):
18 def _expandedabspath(path):
19 '''
19 '''
20 get a path or url and if it is a path expand it and return an absolute path
20 get a path or url and if it is a path expand it and return an absolute path
21 '''
21 '''
22 expandedpath = util.urllocalpath(util.expandpath(path))
22 expandedpath = util.urllocalpath(util.expandpath(path))
23 u = util.url(expandedpath)
23 u = util.url(expandedpath)
24 if not u.scheme:
24 if not u.scheme:
25 path = util.normpath(os.path.abspath(u.path))
25 path = util.normpath(os.path.abspath(u.path))
26 return path
26 return path
27
27
28 def _getstorehashcachename(remotepath):
28 def _getstorehashcachename(remotepath):
29 '''get a unique filename for the store hash cache of a remote repository'''
29 '''get a unique filename for the store hash cache of a remote repository'''
30 return util.sha1(_expandedabspath(remotepath)).hexdigest()[0:12]
30 return util.sha1(_expandedabspath(remotepath)).hexdigest()[0:12]
31
31
32 def _calcfilehash(filename):
32 def _calcfilehash(filename):
33 data = ''
33 data = ''
34 if os.path.exists(filename):
34 if os.path.exists(filename):
35 fd = open(filename, 'rb')
35 fd = open(filename, 'rb')
36 data = fd.read()
36 data = fd.read()
37 fd.close()
37 fd.close()
38 return util.sha1(data).hexdigest()
38 return util.sha1(data).hexdigest()
39
39
40 class SubrepoAbort(error.Abort):
40 class SubrepoAbort(error.Abort):
41 """Exception class used to avoid handling a subrepo error more than once"""
41 """Exception class used to avoid handling a subrepo error more than once"""
42 def __init__(self, *args, **kw):
42 def __init__(self, *args, **kw):
43 error.Abort.__init__(self, *args, **kw)
43 error.Abort.__init__(self, *args, **kw)
44 self.subrepo = kw.get('subrepo')
44 self.subrepo = kw.get('subrepo')
45 self.cause = kw.get('cause')
45 self.cause = kw.get('cause')
46
46
47 def annotatesubrepoerror(func):
47 def annotatesubrepoerror(func):
48 def decoratedmethod(self, *args, **kargs):
48 def decoratedmethod(self, *args, **kargs):
49 try:
49 try:
50 res = func(self, *args, **kargs)
50 res = func(self, *args, **kargs)
51 except SubrepoAbort, ex:
51 except SubrepoAbort, ex:
52 # This exception has already been handled
52 # This exception has already been handled
53 raise ex
53 raise ex
54 except error.Abort, ex:
54 except error.Abort, ex:
55 subrepo = subrelpath(self)
55 subrepo = subrelpath(self)
56 errormsg = str(ex) + ' ' + _('(in subrepo %s)') % subrepo
56 errormsg = str(ex) + ' ' + _('(in subrepo %s)') % subrepo
57 # avoid handling this exception by raising a SubrepoAbort exception
57 # avoid handling this exception by raising a SubrepoAbort exception
58 raise SubrepoAbort(errormsg, hint=ex.hint, subrepo=subrepo,
58 raise SubrepoAbort(errormsg, hint=ex.hint, subrepo=subrepo,
59 cause=sys.exc_info())
59 cause=sys.exc_info())
60 return res
60 return res
61 return decoratedmethod
61 return decoratedmethod
62
62
63 def state(ctx, ui):
63 def state(ctx, ui):
64 """return a state dict, mapping subrepo paths configured in .hgsub
64 """return a state dict, mapping subrepo paths configured in .hgsub
65 to tuple: (source from .hgsub, revision from .hgsubstate, kind
65 to tuple: (source from .hgsub, revision from .hgsubstate, kind
66 (key in types dict))
66 (key in types dict))
67 """
67 """
68 p = config.config()
68 p = config.config()
69 def read(f, sections=None, remap=None):
69 def read(f, sections=None, remap=None):
70 if f in ctx:
70 if f in ctx:
71 try:
71 try:
72 data = ctx[f].data()
72 data = ctx[f].data()
73 except IOError, err:
73 except IOError, err:
74 if err.errno != errno.ENOENT:
74 if err.errno != errno.ENOENT:
75 raise
75 raise
76 # handle missing subrepo spec files as removed
76 # handle missing subrepo spec files as removed
77 ui.warn(_("warning: subrepo spec file %s not found\n") % f)
77 ui.warn(_("warning: subrepo spec file %s not found\n") % f)
78 return
78 return
79 p.parse(f, data, sections, remap, read)
79 p.parse(f, data, sections, remap, read)
80 else:
80 else:
81 raise util.Abort(_("subrepo spec file %s not found") % f)
81 raise util.Abort(_("subrepo spec file %s not found") % f)
82
82
83 if '.hgsub' in ctx:
83 if '.hgsub' in ctx:
84 read('.hgsub')
84 read('.hgsub')
85
85
86 for path, src in ui.configitems('subpaths'):
86 for path, src in ui.configitems('subpaths'):
87 p.set('subpaths', path, src, ui.configsource('subpaths', path))
87 p.set('subpaths', path, src, ui.configsource('subpaths', path))
88
88
89 rev = {}
89 rev = {}
90 if '.hgsubstate' in ctx:
90 if '.hgsubstate' in ctx:
91 try:
91 try:
92 for i, l in enumerate(ctx['.hgsubstate'].data().splitlines()):
92 for i, l in enumerate(ctx['.hgsubstate'].data().splitlines()):
93 l = l.lstrip()
93 l = l.lstrip()
94 if not l:
94 if not l:
95 continue
95 continue
96 try:
96 try:
97 revision, path = l.split(" ", 1)
97 revision, path = l.split(" ", 1)
98 except ValueError:
98 except ValueError:
99 raise util.Abort(_("invalid subrepository revision "
99 raise util.Abort(_("invalid subrepository revision "
100 "specifier in .hgsubstate line %d")
100 "specifier in .hgsubstate line %d")
101 % (i + 1))
101 % (i + 1))
102 rev[path] = revision
102 rev[path] = revision
103 except IOError, err:
103 except IOError, err:
104 if err.errno != errno.ENOENT:
104 if err.errno != errno.ENOENT:
105 raise
105 raise
106
106
107 def remap(src):
107 def remap(src):
108 for pattern, repl in p.items('subpaths'):
108 for pattern, repl in p.items('subpaths'):
109 # Turn r'C:\foo\bar' into r'C:\\foo\\bar' since re.sub
109 # Turn r'C:\foo\bar' into r'C:\\foo\\bar' since re.sub
110 # does a string decode.
110 # does a string decode.
111 repl = repl.encode('string-escape')
111 repl = repl.encode('string-escape')
112 # However, we still want to allow back references to go
112 # However, we still want to allow back references to go
113 # through unharmed, so we turn r'\\1' into r'\1'. Again,
113 # through unharmed, so we turn r'\\1' into r'\1'. Again,
114 # extra escapes are needed because re.sub string decodes.
114 # extra escapes are needed because re.sub string decodes.
115 repl = re.sub(r'\\\\([0-9]+)', r'\\\1', repl)
115 repl = re.sub(r'\\\\([0-9]+)', r'\\\1', repl)
116 try:
116 try:
117 src = re.sub(pattern, repl, src, 1)
117 src = re.sub(pattern, repl, src, 1)
118 except re.error, e:
118 except re.error, e:
119 raise util.Abort(_("bad subrepository pattern in %s: %s")
119 raise util.Abort(_("bad subrepository pattern in %s: %s")
120 % (p.source('subpaths', pattern), e))
120 % (p.source('subpaths', pattern), e))
121 return src
121 return src
122
122
123 state = {}
123 state = {}
124 for path, src in p[''].items():
124 for path, src in p[''].items():
125 kind = 'hg'
125 kind = 'hg'
126 if src.startswith('['):
126 if src.startswith('['):
127 if ']' not in src:
127 if ']' not in src:
128 raise util.Abort(_('missing ] in subrepo source'))
128 raise util.Abort(_('missing ] in subrepo source'))
129 kind, src = src.split(']', 1)
129 kind, src = src.split(']', 1)
130 kind = kind[1:]
130 kind = kind[1:]
131 src = src.lstrip() # strip any extra whitespace after ']'
131 src = src.lstrip() # strip any extra whitespace after ']'
132
132
133 if not util.url(src).isabs():
133 if not util.url(src).isabs():
134 parent = _abssource(ctx._repo, abort=False)
134 parent = _abssource(ctx._repo, abort=False)
135 if parent:
135 if parent:
136 parent = util.url(parent)
136 parent = util.url(parent)
137 parent.path = posixpath.join(parent.path or '', src)
137 parent.path = posixpath.join(parent.path or '', src)
138 parent.path = posixpath.normpath(parent.path)
138 parent.path = posixpath.normpath(parent.path)
139 joined = str(parent)
139 joined = str(parent)
140 # Remap the full joined path and use it if it changes,
140 # Remap the full joined path and use it if it changes,
141 # else remap the original source.
141 # else remap the original source.
142 remapped = remap(joined)
142 remapped = remap(joined)
143 if remapped == joined:
143 if remapped == joined:
144 src = remap(src)
144 src = remap(src)
145 else:
145 else:
146 src = remapped
146 src = remapped
147
147
148 src = remap(src)
148 src = remap(src)
149 state[util.pconvert(path)] = (src.strip(), rev.get(path, ''), kind)
149 state[util.pconvert(path)] = (src.strip(), rev.get(path, ''), kind)
150
150
151 return state
151 return state
152
152
153 def writestate(repo, state):
153 def writestate(repo, state):
154 """rewrite .hgsubstate in (outer) repo with these subrepo states"""
154 """rewrite .hgsubstate in (outer) repo with these subrepo states"""
155 lines = ['%s %s\n' % (state[s][1], s) for s in sorted(state)]
155 lines = ['%s %s\n' % (state[s][1], s) for s in sorted(state)]
156 repo.wwrite('.hgsubstate', ''.join(lines), '')
156 repo.wwrite('.hgsubstate', ''.join(lines), '')
157
157
158 def submerge(repo, wctx, mctx, actx, overwrite):
158 def submerge(repo, wctx, mctx, actx, overwrite):
159 """delegated from merge.applyupdates: merging of .hgsubstate file
159 """delegated from merge.applyupdates: merging of .hgsubstate file
160 in working context, merging context and ancestor context"""
160 in working context, merging context and ancestor context"""
161 if mctx == actx: # backwards?
161 if mctx == actx: # backwards?
162 actx = wctx.p1()
162 actx = wctx.p1()
163 s1 = wctx.substate
163 s1 = wctx.substate
164 s2 = mctx.substate
164 s2 = mctx.substate
165 sa = actx.substate
165 sa = actx.substate
166 sm = {}
166 sm = {}
167
167
168 repo.ui.debug("subrepo merge %s %s %s\n" % (wctx, mctx, actx))
168 repo.ui.debug("subrepo merge %s %s %s\n" % (wctx, mctx, actx))
169
169
170 def debug(s, msg, r=""):
170 def debug(s, msg, r=""):
171 if r:
171 if r:
172 r = "%s:%s:%s" % r
172 r = "%s:%s:%s" % r
173 repo.ui.debug(" subrepo %s: %s %s\n" % (s, msg, r))
173 repo.ui.debug(" subrepo %s: %s %s\n" % (s, msg, r))
174
174
175 for s, l in sorted(s1.iteritems()):
175 for s, l in sorted(s1.iteritems()):
176 a = sa.get(s, nullstate)
176 a = sa.get(s, nullstate)
177 ld = l # local state with possible dirty flag for compares
177 ld = l # local state with possible dirty flag for compares
178 if wctx.sub(s).dirty():
178 if wctx.sub(s).dirty():
179 ld = (l[0], l[1] + "+")
179 ld = (l[0], l[1] + "+")
180 if wctx == actx: # overwrite
180 if wctx == actx: # overwrite
181 a = ld
181 a = ld
182
182
183 if s in s2:
183 if s in s2:
184 r = s2[s]
184 r = s2[s]
185 if ld == r or r == a: # no change or local is newer
185 if ld == r or r == a: # no change or local is newer
186 sm[s] = l
186 sm[s] = l
187 continue
187 continue
188 elif ld == a: # other side changed
188 elif ld == a: # other side changed
189 debug(s, "other changed, get", r)
189 debug(s, "other changed, get", r)
190 wctx.sub(s).get(r, overwrite)
190 wctx.sub(s).get(r, overwrite)
191 sm[s] = r
191 sm[s] = r
192 elif ld[0] != r[0]: # sources differ
192 elif ld[0] != r[0]: # sources differ
193 if repo.ui.promptchoice(
193 if repo.ui.promptchoice(
194 _(' subrepository sources for %s differ\n'
194 _(' subrepository sources for %s differ\n'
195 'use (l)ocal source (%s) or (r)emote source (%s)?'
195 'use (l)ocal source (%s) or (r)emote source (%s)?'
196 '$$ &Local $$ &Remote') % (s, l[0], r[0]), 0):
196 '$$ &Local $$ &Remote') % (s, l[0], r[0]), 0):
197 debug(s, "prompt changed, get", r)
197 debug(s, "prompt changed, get", r)
198 wctx.sub(s).get(r, overwrite)
198 wctx.sub(s).get(r, overwrite)
199 sm[s] = r
199 sm[s] = r
200 elif ld[1] == a[1]: # local side is unchanged
200 elif ld[1] == a[1]: # local side is unchanged
201 debug(s, "other side changed, get", r)
201 debug(s, "other side changed, get", r)
202 wctx.sub(s).get(r, overwrite)
202 wctx.sub(s).get(r, overwrite)
203 sm[s] = r
203 sm[s] = r
204 else:
204 else:
205 debug(s, "both sides changed, merge with", r)
205 debug(s, "both sides changed")
206 wctx.sub(s).merge(r)
206 option = repo.ui.promptchoice(
207 sm[s] = l
207 _(' subrepository %s diverged (local revision: %s, '
208 'remote revision: %s)\n'
209 '(M)erge, keep (l)ocal or keep (r)emote?'
210 '$$ &Merge $$ &Local $$ &Remote')
211 % (s, l[1][:12], r[1][:12]), 0)
212 if option == 0:
213 wctx.sub(s).merge(r)
214 sm[s] = l
215 debug(s, "merge with", r)
216 elif option == 1:
217 sm[s] = l
218 debug(s, "keep local subrepo revision", l)
219 else:
220 wctx.sub(s).get(r, overwrite)
221 sm[s] = r
222 debug(s, "get remote subrepo revision", r)
208 elif ld == a: # remote removed, local unchanged
223 elif ld == a: # remote removed, local unchanged
209 debug(s, "remote removed, remove")
224 debug(s, "remote removed, remove")
210 wctx.sub(s).remove()
225 wctx.sub(s).remove()
211 elif a == nullstate: # not present in remote or ancestor
226 elif a == nullstate: # not present in remote or ancestor
212 debug(s, "local added, keep")
227 debug(s, "local added, keep")
213 sm[s] = l
228 sm[s] = l
214 continue
229 continue
215 else:
230 else:
216 if repo.ui.promptchoice(
231 if repo.ui.promptchoice(
217 _(' local changed subrepository %s which remote removed\n'
232 _(' local changed subrepository %s which remote removed\n'
218 'use (c)hanged version or (d)elete?'
233 'use (c)hanged version or (d)elete?'
219 '$$ &Changed $$ &Delete') % s, 0):
234 '$$ &Changed $$ &Delete') % s, 0):
220 debug(s, "prompt remove")
235 debug(s, "prompt remove")
221 wctx.sub(s).remove()
236 wctx.sub(s).remove()
222
237
223 for s, r in sorted(s2.items()):
238 for s, r in sorted(s2.items()):
224 if s in s1:
239 if s in s1:
225 continue
240 continue
226 elif s not in sa:
241 elif s not in sa:
227 debug(s, "remote added, get", r)
242 debug(s, "remote added, get", r)
228 mctx.sub(s).get(r)
243 mctx.sub(s).get(r)
229 sm[s] = r
244 sm[s] = r
230 elif r != sa[s]:
245 elif r != sa[s]:
231 if repo.ui.promptchoice(
246 if repo.ui.promptchoice(
232 _(' remote changed subrepository %s which local removed\n'
247 _(' remote changed subrepository %s which local removed\n'
233 'use (c)hanged version or (d)elete?'
248 'use (c)hanged version or (d)elete?'
234 '$$ &Changed $$ &Delete') % s, 0) == 0:
249 '$$ &Changed $$ &Delete') % s, 0) == 0:
235 debug(s, "prompt recreate", r)
250 debug(s, "prompt recreate", r)
236 wctx.sub(s).get(r)
251 wctx.sub(s).get(r)
237 sm[s] = r
252 sm[s] = r
238
253
239 # record merged .hgsubstate
254 # record merged .hgsubstate
240 writestate(repo, sm)
255 writestate(repo, sm)
241 return sm
256 return sm
242
257
243 def _updateprompt(ui, sub, dirty, local, remote):
258 def _updateprompt(ui, sub, dirty, local, remote):
244 if dirty:
259 if dirty:
245 msg = (_(' subrepository sources for %s differ\n'
260 msg = (_(' subrepository sources for %s differ\n'
246 'use (l)ocal source (%s) or (r)emote source (%s)?\n'
261 'use (l)ocal source (%s) or (r)emote source (%s)?\n'
247 '$$ &Local $$ &Remote')
262 '$$ &Local $$ &Remote')
248 % (subrelpath(sub), local, remote))
263 % (subrelpath(sub), local, remote))
249 else:
264 else:
250 msg = (_(' subrepository sources for %s differ (in checked out '
265 msg = (_(' subrepository sources for %s differ (in checked out '
251 'version)\n'
266 'version)\n'
252 'use (l)ocal source (%s) or (r)emote source (%s)?\n'
267 'use (l)ocal source (%s) or (r)emote source (%s)?\n'
253 '$$ &Local $$ &Remote')
268 '$$ &Local $$ &Remote')
254 % (subrelpath(sub), local, remote))
269 % (subrelpath(sub), local, remote))
255 return ui.promptchoice(msg, 0)
270 return ui.promptchoice(msg, 0)
256
271
257 def reporelpath(repo):
272 def reporelpath(repo):
258 """return path to this (sub)repo as seen from outermost repo"""
273 """return path to this (sub)repo as seen from outermost repo"""
259 parent = repo
274 parent = repo
260 while util.safehasattr(parent, '_subparent'):
275 while util.safehasattr(parent, '_subparent'):
261 parent = parent._subparent
276 parent = parent._subparent
262 p = parent.root.rstrip(os.sep)
277 p = parent.root.rstrip(os.sep)
263 return repo.root[len(p) + 1:]
278 return repo.root[len(p) + 1:]
264
279
265 def subrelpath(sub):
280 def subrelpath(sub):
266 """return path to this subrepo as seen from outermost repo"""
281 """return path to this subrepo as seen from outermost repo"""
267 if util.safehasattr(sub, '_relpath'):
282 if util.safehasattr(sub, '_relpath'):
268 return sub._relpath
283 return sub._relpath
269 if not util.safehasattr(sub, '_repo'):
284 if not util.safehasattr(sub, '_repo'):
270 return sub._path
285 return sub._path
271 return reporelpath(sub._repo)
286 return reporelpath(sub._repo)
272
287
273 def _abssource(repo, push=False, abort=True):
288 def _abssource(repo, push=False, abort=True):
274 """return pull/push path of repo - either based on parent repo .hgsub info
289 """return pull/push path of repo - either based on parent repo .hgsub info
275 or on the top repo config. Abort or return None if no source found."""
290 or on the top repo config. Abort or return None if no source found."""
276 if util.safehasattr(repo, '_subparent'):
291 if util.safehasattr(repo, '_subparent'):
277 source = util.url(repo._subsource)
292 source = util.url(repo._subsource)
278 if source.isabs():
293 if source.isabs():
279 return str(source)
294 return str(source)
280 source.path = posixpath.normpath(source.path)
295 source.path = posixpath.normpath(source.path)
281 parent = _abssource(repo._subparent, push, abort=False)
296 parent = _abssource(repo._subparent, push, abort=False)
282 if parent:
297 if parent:
283 parent = util.url(util.pconvert(parent))
298 parent = util.url(util.pconvert(parent))
284 parent.path = posixpath.join(parent.path or '', source.path)
299 parent.path = posixpath.join(parent.path or '', source.path)
285 parent.path = posixpath.normpath(parent.path)
300 parent.path = posixpath.normpath(parent.path)
286 return str(parent)
301 return str(parent)
287 else: # recursion reached top repo
302 else: # recursion reached top repo
288 if util.safehasattr(repo, '_subtoppath'):
303 if util.safehasattr(repo, '_subtoppath'):
289 return repo._subtoppath
304 return repo._subtoppath
290 if push and repo.ui.config('paths', 'default-push'):
305 if push and repo.ui.config('paths', 'default-push'):
291 return repo.ui.config('paths', 'default-push')
306 return repo.ui.config('paths', 'default-push')
292 if repo.ui.config('paths', 'default'):
307 if repo.ui.config('paths', 'default'):
293 return repo.ui.config('paths', 'default')
308 return repo.ui.config('paths', 'default')
294 if repo.sharedpath != repo.path:
309 if repo.sharedpath != repo.path:
295 # chop off the .hg component to get the default path form
310 # chop off the .hg component to get the default path form
296 return os.path.dirname(repo.sharedpath)
311 return os.path.dirname(repo.sharedpath)
297 if abort:
312 if abort:
298 raise util.Abort(_("default path for subrepository not found"))
313 raise util.Abort(_("default path for subrepository not found"))
299
314
300 def itersubrepos(ctx1, ctx2):
315 def itersubrepos(ctx1, ctx2):
301 """find subrepos in ctx1 or ctx2"""
316 """find subrepos in ctx1 or ctx2"""
302 # Create a (subpath, ctx) mapping where we prefer subpaths from
317 # Create a (subpath, ctx) mapping where we prefer subpaths from
303 # ctx1. The subpaths from ctx2 are important when the .hgsub file
318 # ctx1. The subpaths from ctx2 are important when the .hgsub file
304 # has been modified (in ctx2) but not yet committed (in ctx1).
319 # has been modified (in ctx2) but not yet committed (in ctx1).
305 subpaths = dict.fromkeys(ctx2.substate, ctx2)
320 subpaths = dict.fromkeys(ctx2.substate, ctx2)
306 subpaths.update(dict.fromkeys(ctx1.substate, ctx1))
321 subpaths.update(dict.fromkeys(ctx1.substate, ctx1))
307 for subpath, ctx in sorted(subpaths.iteritems()):
322 for subpath, ctx in sorted(subpaths.iteritems()):
308 yield subpath, ctx.sub(subpath)
323 yield subpath, ctx.sub(subpath)
309
324
310 def subrepo(ctx, path):
325 def subrepo(ctx, path):
311 """return instance of the right subrepo class for subrepo in path"""
326 """return instance of the right subrepo class for subrepo in path"""
312 # subrepo inherently violates our import layering rules
327 # subrepo inherently violates our import layering rules
313 # because it wants to make repo objects from deep inside the stack
328 # because it wants to make repo objects from deep inside the stack
314 # so we manually delay the circular imports to not break
329 # so we manually delay the circular imports to not break
315 # scripts that don't use our demand-loading
330 # scripts that don't use our demand-loading
316 global hg
331 global hg
317 import hg as h
332 import hg as h
318 hg = h
333 hg = h
319
334
320 scmutil.pathauditor(ctx._repo.root)(path)
335 scmutil.pathauditor(ctx._repo.root)(path)
321 state = ctx.substate[path]
336 state = ctx.substate[path]
322 if state[2] not in types:
337 if state[2] not in types:
323 raise util.Abort(_('unknown subrepo type %s') % state[2])
338 raise util.Abort(_('unknown subrepo type %s') % state[2])
324 return types[state[2]](ctx, path, state[:2])
339 return types[state[2]](ctx, path, state[:2])
325
340
326 # subrepo classes need to implement the following abstract class:
341 # subrepo classes need to implement the following abstract class:
327
342
328 class abstractsubrepo(object):
343 class abstractsubrepo(object):
329
344
330 def storeclean(self, path):
345 def storeclean(self, path):
331 """
346 """
332 returns true if the repository has not changed since it was last
347 returns true if the repository has not changed since it was last
333 cloned from or pushed to a given repository.
348 cloned from or pushed to a given repository.
334 """
349 """
335 return False
350 return False
336
351
337 def dirty(self, ignoreupdate=False):
352 def dirty(self, ignoreupdate=False):
338 """returns true if the dirstate of the subrepo is dirty or does not
353 """returns true if the dirstate of the subrepo is dirty or does not
339 match current stored state. If ignoreupdate is true, only check
354 match current stored state. If ignoreupdate is true, only check
340 whether the subrepo has uncommitted changes in its dirstate.
355 whether the subrepo has uncommitted changes in its dirstate.
341 """
356 """
342 raise NotImplementedError
357 raise NotImplementedError
343
358
344 def basestate(self):
359 def basestate(self):
345 """current working directory base state, disregarding .hgsubstate
360 """current working directory base state, disregarding .hgsubstate
346 state and working directory modifications"""
361 state and working directory modifications"""
347 raise NotImplementedError
362 raise NotImplementedError
348
363
349 def checknested(self, path):
364 def checknested(self, path):
350 """check if path is a subrepository within this repository"""
365 """check if path is a subrepository within this repository"""
351 return False
366 return False
352
367
353 def commit(self, text, user, date):
368 def commit(self, text, user, date):
354 """commit the current changes to the subrepo with the given
369 """commit the current changes to the subrepo with the given
355 log message. Use given user and date if possible. Return the
370 log message. Use given user and date if possible. Return the
356 new state of the subrepo.
371 new state of the subrepo.
357 """
372 """
358 raise NotImplementedError
373 raise NotImplementedError
359
374
360 def remove(self):
375 def remove(self):
361 """remove the subrepo
376 """remove the subrepo
362
377
363 (should verify the dirstate is not dirty first)
378 (should verify the dirstate is not dirty first)
364 """
379 """
365 raise NotImplementedError
380 raise NotImplementedError
366
381
367 def get(self, state, overwrite=False):
382 def get(self, state, overwrite=False):
368 """run whatever commands are needed to put the subrepo into
383 """run whatever commands are needed to put the subrepo into
369 this state
384 this state
370 """
385 """
371 raise NotImplementedError
386 raise NotImplementedError
372
387
373 def merge(self, state):
388 def merge(self, state):
374 """merge currently-saved state with the new state."""
389 """merge currently-saved state with the new state."""
375 raise NotImplementedError
390 raise NotImplementedError
376
391
377 def push(self, opts):
392 def push(self, opts):
378 """perform whatever action is analogous to 'hg push'
393 """perform whatever action is analogous to 'hg push'
379
394
380 This may be a no-op on some systems.
395 This may be a no-op on some systems.
381 """
396 """
382 raise NotImplementedError
397 raise NotImplementedError
383
398
384 def add(self, ui, match, dryrun, listsubrepos, prefix, explicitonly):
399 def add(self, ui, match, dryrun, listsubrepos, prefix, explicitonly):
385 return []
400 return []
386
401
387 def status(self, rev2, **opts):
402 def status(self, rev2, **opts):
388 return [], [], [], [], [], [], []
403 return [], [], [], [], [], [], []
389
404
390 def diff(self, ui, diffopts, node2, match, prefix, **opts):
405 def diff(self, ui, diffopts, node2, match, prefix, **opts):
391 pass
406 pass
392
407
393 def outgoing(self, ui, dest, opts):
408 def outgoing(self, ui, dest, opts):
394 return 1
409 return 1
395
410
396 def incoming(self, ui, source, opts):
411 def incoming(self, ui, source, opts):
397 return 1
412 return 1
398
413
399 def files(self):
414 def files(self):
400 """return filename iterator"""
415 """return filename iterator"""
401 raise NotImplementedError
416 raise NotImplementedError
402
417
403 def filedata(self, name):
418 def filedata(self, name):
404 """return file data"""
419 """return file data"""
405 raise NotImplementedError
420 raise NotImplementedError
406
421
407 def fileflags(self, name):
422 def fileflags(self, name):
408 """return file flags"""
423 """return file flags"""
409 return ''
424 return ''
410
425
411 def archive(self, ui, archiver, prefix, match=None):
426 def archive(self, ui, archiver, prefix, match=None):
412 if match is not None:
427 if match is not None:
413 files = [f for f in self.files() if match(f)]
428 files = [f for f in self.files() if match(f)]
414 else:
429 else:
415 files = self.files()
430 files = self.files()
416 total = len(files)
431 total = len(files)
417 relpath = subrelpath(self)
432 relpath = subrelpath(self)
418 ui.progress(_('archiving (%s)') % relpath, 0,
433 ui.progress(_('archiving (%s)') % relpath, 0,
419 unit=_('files'), total=total)
434 unit=_('files'), total=total)
420 for i, name in enumerate(files):
435 for i, name in enumerate(files):
421 flags = self.fileflags(name)
436 flags = self.fileflags(name)
422 mode = 'x' in flags and 0755 or 0644
437 mode = 'x' in flags and 0755 or 0644
423 symlink = 'l' in flags
438 symlink = 'l' in flags
424 archiver.addfile(os.path.join(prefix, self._path, name),
439 archiver.addfile(os.path.join(prefix, self._path, name),
425 mode, symlink, self.filedata(name))
440 mode, symlink, self.filedata(name))
426 ui.progress(_('archiving (%s)') % relpath, i + 1,
441 ui.progress(_('archiving (%s)') % relpath, i + 1,
427 unit=_('files'), total=total)
442 unit=_('files'), total=total)
428 ui.progress(_('archiving (%s)') % relpath, None)
443 ui.progress(_('archiving (%s)') % relpath, None)
429 return total
444 return total
430
445
431 def walk(self, match):
446 def walk(self, match):
432 '''
447 '''
433 walk recursively through the directory tree, finding all files
448 walk recursively through the directory tree, finding all files
434 matched by the match function
449 matched by the match function
435 '''
450 '''
436 pass
451 pass
437
452
438 def forget(self, ui, match, prefix):
453 def forget(self, ui, match, prefix):
439 return ([], [])
454 return ([], [])
440
455
441 def revert(self, ui, substate, *pats, **opts):
456 def revert(self, ui, substate, *pats, **opts):
442 ui.warn('%s: reverting %s subrepos is unsupported\n' \
457 ui.warn('%s: reverting %s subrepos is unsupported\n' \
443 % (substate[0], substate[2]))
458 % (substate[0], substate[2]))
444 return []
459 return []
445
460
446 class hgsubrepo(abstractsubrepo):
461 class hgsubrepo(abstractsubrepo):
447 def __init__(self, ctx, path, state):
462 def __init__(self, ctx, path, state):
448 self._path = path
463 self._path = path
449 self._state = state
464 self._state = state
450 r = ctx._repo
465 r = ctx._repo
451 root = r.wjoin(path)
466 root = r.wjoin(path)
452 create = False
467 create = False
453 if not os.path.exists(os.path.join(root, '.hg')):
468 if not os.path.exists(os.path.join(root, '.hg')):
454 create = True
469 create = True
455 util.makedirs(root)
470 util.makedirs(root)
456 self._repo = hg.repository(r.baseui, root, create=create)
471 self._repo = hg.repository(r.baseui, root, create=create)
457 for s, k in [('ui', 'commitsubrepos')]:
472 for s, k in [('ui', 'commitsubrepos')]:
458 v = r.ui.config(s, k)
473 v = r.ui.config(s, k)
459 if v:
474 if v:
460 self._repo.ui.setconfig(s, k, v)
475 self._repo.ui.setconfig(s, k, v)
461 self._repo.ui.setconfig('ui', '_usedassubrepo', 'True')
476 self._repo.ui.setconfig('ui', '_usedassubrepo', 'True')
462 self._initrepo(r, state[0], create)
477 self._initrepo(r, state[0], create)
463
478
464 def storeclean(self, path):
479 def storeclean(self, path):
465 clean = True
480 clean = True
466 lock = self._repo.lock()
481 lock = self._repo.lock()
467 itercache = self._calcstorehash(path)
482 itercache = self._calcstorehash(path)
468 try:
483 try:
469 for filehash in self._readstorehashcache(path):
484 for filehash in self._readstorehashcache(path):
470 if filehash != itercache.next():
485 if filehash != itercache.next():
471 clean = False
486 clean = False
472 break
487 break
473 except StopIteration:
488 except StopIteration:
474 # the cached and current pull states have a different size
489 # the cached and current pull states have a different size
475 clean = False
490 clean = False
476 if clean:
491 if clean:
477 try:
492 try:
478 itercache.next()
493 itercache.next()
479 # the cached and current pull states have a different size
494 # the cached and current pull states have a different size
480 clean = False
495 clean = False
481 except StopIteration:
496 except StopIteration:
482 pass
497 pass
483 lock.release()
498 lock.release()
484 return clean
499 return clean
485
500
486 def _calcstorehash(self, remotepath):
501 def _calcstorehash(self, remotepath):
487 '''calculate a unique "store hash"
502 '''calculate a unique "store hash"
488
503
489 This method is used to to detect when there are changes that may
504 This method is used to to detect when there are changes that may
490 require a push to a given remote path.'''
505 require a push to a given remote path.'''
491 # sort the files that will be hashed in increasing (likely) file size
506 # sort the files that will be hashed in increasing (likely) file size
492 filelist = ('bookmarks', 'store/phaseroots', 'store/00changelog.i')
507 filelist = ('bookmarks', 'store/phaseroots', 'store/00changelog.i')
493 yield '# %s\n' % _expandedabspath(remotepath)
508 yield '# %s\n' % _expandedabspath(remotepath)
494 for relname in filelist:
509 for relname in filelist:
495 absname = os.path.normpath(self._repo.join(relname))
510 absname = os.path.normpath(self._repo.join(relname))
496 yield '%s = %s\n' % (relname, _calcfilehash(absname))
511 yield '%s = %s\n' % (relname, _calcfilehash(absname))
497
512
498 def _getstorehashcachepath(self, remotepath):
513 def _getstorehashcachepath(self, remotepath):
499 '''get a unique path for the store hash cache'''
514 '''get a unique path for the store hash cache'''
500 return self._repo.join(os.path.join(
515 return self._repo.join(os.path.join(
501 'cache', 'storehash', _getstorehashcachename(remotepath)))
516 'cache', 'storehash', _getstorehashcachename(remotepath)))
502
517
503 def _readstorehashcache(self, remotepath):
518 def _readstorehashcache(self, remotepath):
504 '''read the store hash cache for a given remote repository'''
519 '''read the store hash cache for a given remote repository'''
505 cachefile = self._getstorehashcachepath(remotepath)
520 cachefile = self._getstorehashcachepath(remotepath)
506 if not os.path.exists(cachefile):
521 if not os.path.exists(cachefile):
507 return ''
522 return ''
508 fd = open(cachefile, 'r')
523 fd = open(cachefile, 'r')
509 pullstate = fd.readlines()
524 pullstate = fd.readlines()
510 fd.close()
525 fd.close()
511 return pullstate
526 return pullstate
512
527
513 def _cachestorehash(self, remotepath):
528 def _cachestorehash(self, remotepath):
514 '''cache the current store hash
529 '''cache the current store hash
515
530
516 Each remote repo requires its own store hash cache, because a subrepo
531 Each remote repo requires its own store hash cache, because a subrepo
517 store may be "clean" versus a given remote repo, but not versus another
532 store may be "clean" versus a given remote repo, but not versus another
518 '''
533 '''
519 cachefile = self._getstorehashcachepath(remotepath)
534 cachefile = self._getstorehashcachepath(remotepath)
520 lock = self._repo.lock()
535 lock = self._repo.lock()
521 storehash = list(self._calcstorehash(remotepath))
536 storehash = list(self._calcstorehash(remotepath))
522 cachedir = os.path.dirname(cachefile)
537 cachedir = os.path.dirname(cachefile)
523 if not os.path.exists(cachedir):
538 if not os.path.exists(cachedir):
524 util.makedirs(cachedir, notindexed=True)
539 util.makedirs(cachedir, notindexed=True)
525 fd = open(cachefile, 'w')
540 fd = open(cachefile, 'w')
526 fd.writelines(storehash)
541 fd.writelines(storehash)
527 fd.close()
542 fd.close()
528 lock.release()
543 lock.release()
529
544
530 @annotatesubrepoerror
545 @annotatesubrepoerror
531 def _initrepo(self, parentrepo, source, create):
546 def _initrepo(self, parentrepo, source, create):
532 self._repo._subparent = parentrepo
547 self._repo._subparent = parentrepo
533 self._repo._subsource = source
548 self._repo._subsource = source
534
549
535 if create:
550 if create:
536 fp = self._repo.opener("hgrc", "w", text=True)
551 fp = self._repo.opener("hgrc", "w", text=True)
537 fp.write('[paths]\n')
552 fp.write('[paths]\n')
538
553
539 def addpathconfig(key, value):
554 def addpathconfig(key, value):
540 if value:
555 if value:
541 fp.write('%s = %s\n' % (key, value))
556 fp.write('%s = %s\n' % (key, value))
542 self._repo.ui.setconfig('paths', key, value)
557 self._repo.ui.setconfig('paths', key, value)
543
558
544 defpath = _abssource(self._repo, abort=False)
559 defpath = _abssource(self._repo, abort=False)
545 defpushpath = _abssource(self._repo, True, abort=False)
560 defpushpath = _abssource(self._repo, True, abort=False)
546 addpathconfig('default', defpath)
561 addpathconfig('default', defpath)
547 if defpath != defpushpath:
562 if defpath != defpushpath:
548 addpathconfig('default-push', defpushpath)
563 addpathconfig('default-push', defpushpath)
549 fp.close()
564 fp.close()
550
565
551 @annotatesubrepoerror
566 @annotatesubrepoerror
552 def add(self, ui, match, dryrun, listsubrepos, prefix, explicitonly):
567 def add(self, ui, match, dryrun, listsubrepos, prefix, explicitonly):
553 return cmdutil.add(ui, self._repo, match, dryrun, listsubrepos,
568 return cmdutil.add(ui, self._repo, match, dryrun, listsubrepos,
554 os.path.join(prefix, self._path), explicitonly)
569 os.path.join(prefix, self._path), explicitonly)
555
570
556 @annotatesubrepoerror
571 @annotatesubrepoerror
557 def status(self, rev2, **opts):
572 def status(self, rev2, **opts):
558 try:
573 try:
559 rev1 = self._state[1]
574 rev1 = self._state[1]
560 ctx1 = self._repo[rev1]
575 ctx1 = self._repo[rev1]
561 ctx2 = self._repo[rev2]
576 ctx2 = self._repo[rev2]
562 return self._repo.status(ctx1, ctx2, **opts)
577 return self._repo.status(ctx1, ctx2, **opts)
563 except error.RepoLookupError, inst:
578 except error.RepoLookupError, inst:
564 self._repo.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
579 self._repo.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
565 % (inst, subrelpath(self)))
580 % (inst, subrelpath(self)))
566 return [], [], [], [], [], [], []
581 return [], [], [], [], [], [], []
567
582
568 @annotatesubrepoerror
583 @annotatesubrepoerror
569 def diff(self, ui, diffopts, node2, match, prefix, **opts):
584 def diff(self, ui, diffopts, node2, match, prefix, **opts):
570 try:
585 try:
571 node1 = node.bin(self._state[1])
586 node1 = node.bin(self._state[1])
572 # We currently expect node2 to come from substate and be
587 # We currently expect node2 to come from substate and be
573 # in hex format
588 # in hex format
574 if node2 is not None:
589 if node2 is not None:
575 node2 = node.bin(node2)
590 node2 = node.bin(node2)
576 cmdutil.diffordiffstat(ui, self._repo, diffopts,
591 cmdutil.diffordiffstat(ui, self._repo, diffopts,
577 node1, node2, match,
592 node1, node2, match,
578 prefix=posixpath.join(prefix, self._path),
593 prefix=posixpath.join(prefix, self._path),
579 listsubrepos=True, **opts)
594 listsubrepos=True, **opts)
580 except error.RepoLookupError, inst:
595 except error.RepoLookupError, inst:
581 self._repo.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
596 self._repo.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
582 % (inst, subrelpath(self)))
597 % (inst, subrelpath(self)))
583
598
584 @annotatesubrepoerror
599 @annotatesubrepoerror
585 def archive(self, ui, archiver, prefix, match=None):
600 def archive(self, ui, archiver, prefix, match=None):
586 self._get(self._state + ('hg',))
601 self._get(self._state + ('hg',))
587 total = abstractsubrepo.archive(self, ui, archiver, prefix, match)
602 total = abstractsubrepo.archive(self, ui, archiver, prefix, match)
588 rev = self._state[1]
603 rev = self._state[1]
589 ctx = self._repo[rev]
604 ctx = self._repo[rev]
590 for subpath in ctx.substate:
605 for subpath in ctx.substate:
591 s = subrepo(ctx, subpath)
606 s = subrepo(ctx, subpath)
592 submatch = matchmod.narrowmatcher(subpath, match)
607 submatch = matchmod.narrowmatcher(subpath, match)
593 total += s.archive(
608 total += s.archive(
594 ui, archiver, os.path.join(prefix, self._path), submatch)
609 ui, archiver, os.path.join(prefix, self._path), submatch)
595 return total
610 return total
596
611
597 @annotatesubrepoerror
612 @annotatesubrepoerror
598 def dirty(self, ignoreupdate=False):
613 def dirty(self, ignoreupdate=False):
599 r = self._state[1]
614 r = self._state[1]
600 if r == '' and not ignoreupdate: # no state recorded
615 if r == '' and not ignoreupdate: # no state recorded
601 return True
616 return True
602 w = self._repo[None]
617 w = self._repo[None]
603 if r != w.p1().hex() and not ignoreupdate:
618 if r != w.p1().hex() and not ignoreupdate:
604 # different version checked out
619 # different version checked out
605 return True
620 return True
606 return w.dirty() # working directory changed
621 return w.dirty() # working directory changed
607
622
608 def basestate(self):
623 def basestate(self):
609 return self._repo['.'].hex()
624 return self._repo['.'].hex()
610
625
611 def checknested(self, path):
626 def checknested(self, path):
612 return self._repo._checknested(self._repo.wjoin(path))
627 return self._repo._checknested(self._repo.wjoin(path))
613
628
614 @annotatesubrepoerror
629 @annotatesubrepoerror
615 def commit(self, text, user, date):
630 def commit(self, text, user, date):
616 # don't bother committing in the subrepo if it's only been
631 # don't bother committing in the subrepo if it's only been
617 # updated
632 # updated
618 if not self.dirty(True):
633 if not self.dirty(True):
619 return self._repo['.'].hex()
634 return self._repo['.'].hex()
620 self._repo.ui.debug("committing subrepo %s\n" % subrelpath(self))
635 self._repo.ui.debug("committing subrepo %s\n" % subrelpath(self))
621 n = self._repo.commit(text, user, date)
636 n = self._repo.commit(text, user, date)
622 if not n:
637 if not n:
623 return self._repo['.'].hex() # different version checked out
638 return self._repo['.'].hex() # different version checked out
624 return node.hex(n)
639 return node.hex(n)
625
640
626 @annotatesubrepoerror
641 @annotatesubrepoerror
627 def remove(self):
642 def remove(self):
628 # we can't fully delete the repository as it may contain
643 # we can't fully delete the repository as it may contain
629 # local-only history
644 # local-only history
630 self._repo.ui.note(_('removing subrepo %s\n') % subrelpath(self))
645 self._repo.ui.note(_('removing subrepo %s\n') % subrelpath(self))
631 hg.clean(self._repo, node.nullid, False)
646 hg.clean(self._repo, node.nullid, False)
632
647
633 def _get(self, state):
648 def _get(self, state):
634 source, revision, kind = state
649 source, revision, kind = state
635 if revision not in self._repo:
650 if revision not in self._repo:
636 self._repo._subsource = source
651 self._repo._subsource = source
637 srcurl = _abssource(self._repo)
652 srcurl = _abssource(self._repo)
638 other = hg.peer(self._repo, {}, srcurl)
653 other = hg.peer(self._repo, {}, srcurl)
639 if len(self._repo) == 0:
654 if len(self._repo) == 0:
640 self._repo.ui.status(_('cloning subrepo %s from %s\n')
655 self._repo.ui.status(_('cloning subrepo %s from %s\n')
641 % (subrelpath(self), srcurl))
656 % (subrelpath(self), srcurl))
642 parentrepo = self._repo._subparent
657 parentrepo = self._repo._subparent
643 shutil.rmtree(self._repo.path)
658 shutil.rmtree(self._repo.path)
644 other, cloned = hg.clone(self._repo._subparent.baseui, {},
659 other, cloned = hg.clone(self._repo._subparent.baseui, {},
645 other, self._repo.root,
660 other, self._repo.root,
646 update=False)
661 update=False)
647 self._repo = cloned.local()
662 self._repo = cloned.local()
648 self._initrepo(parentrepo, source, create=True)
663 self._initrepo(parentrepo, source, create=True)
649 self._cachestorehash(srcurl)
664 self._cachestorehash(srcurl)
650 else:
665 else:
651 self._repo.ui.status(_('pulling subrepo %s from %s\n')
666 self._repo.ui.status(_('pulling subrepo %s from %s\n')
652 % (subrelpath(self), srcurl))
667 % (subrelpath(self), srcurl))
653 cleansub = self.storeclean(srcurl)
668 cleansub = self.storeclean(srcurl)
654 remotebookmarks = other.listkeys('bookmarks')
669 remotebookmarks = other.listkeys('bookmarks')
655 self._repo.pull(other)
670 self._repo.pull(other)
656 bookmarks.updatefromremote(self._repo.ui, self._repo,
671 bookmarks.updatefromremote(self._repo.ui, self._repo,
657 remotebookmarks, srcurl)
672 remotebookmarks, srcurl)
658 if cleansub:
673 if cleansub:
659 # keep the repo clean after pull
674 # keep the repo clean after pull
660 self._cachestorehash(srcurl)
675 self._cachestorehash(srcurl)
661
676
662 @annotatesubrepoerror
677 @annotatesubrepoerror
663 def get(self, state, overwrite=False):
678 def get(self, state, overwrite=False):
664 self._get(state)
679 self._get(state)
665 source, revision, kind = state
680 source, revision, kind = state
666 self._repo.ui.debug("getting subrepo %s\n" % self._path)
681 self._repo.ui.debug("getting subrepo %s\n" % self._path)
667 hg.updaterepo(self._repo, revision, overwrite)
682 hg.updaterepo(self._repo, revision, overwrite)
668
683
669 @annotatesubrepoerror
684 @annotatesubrepoerror
670 def merge(self, state):
685 def merge(self, state):
671 self._get(state)
686 self._get(state)
672 cur = self._repo['.']
687 cur = self._repo['.']
673 dst = self._repo[state[1]]
688 dst = self._repo[state[1]]
674 anc = dst.ancestor(cur)
689 anc = dst.ancestor(cur)
675
690
676 def mergefunc():
691 def mergefunc():
677 if anc == cur and dst.branch() == cur.branch():
692 if anc == cur and dst.branch() == cur.branch():
678 self._repo.ui.debug("updating subrepo %s\n" % subrelpath(self))
693 self._repo.ui.debug("updating subrepo %s\n" % subrelpath(self))
679 hg.update(self._repo, state[1])
694 hg.update(self._repo, state[1])
680 elif anc == dst:
695 elif anc == dst:
681 self._repo.ui.debug("skipping subrepo %s\n" % subrelpath(self))
696 self._repo.ui.debug("skipping subrepo %s\n" % subrelpath(self))
682 else:
697 else:
683 self._repo.ui.debug("merging subrepo %s\n" % subrelpath(self))
698 self._repo.ui.debug("merging subrepo %s\n" % subrelpath(self))
684 hg.merge(self._repo, state[1], remind=False)
699 hg.merge(self._repo, state[1], remind=False)
685
700
686 wctx = self._repo[None]
701 wctx = self._repo[None]
687 if self.dirty():
702 if self.dirty():
688 if anc != dst:
703 if anc != dst:
689 if _updateprompt(self._repo.ui, self, wctx.dirty(), cur, dst):
704 if _updateprompt(self._repo.ui, self, wctx.dirty(), cur, dst):
690 mergefunc()
705 mergefunc()
691 else:
706 else:
692 mergefunc()
707 mergefunc()
693 else:
708 else:
694 mergefunc()
709 mergefunc()
695
710
696 @annotatesubrepoerror
711 @annotatesubrepoerror
697 def push(self, opts):
712 def push(self, opts):
698 force = opts.get('force')
713 force = opts.get('force')
699 newbranch = opts.get('new_branch')
714 newbranch = opts.get('new_branch')
700 ssh = opts.get('ssh')
715 ssh = opts.get('ssh')
701
716
702 # push subrepos depth-first for coherent ordering
717 # push subrepos depth-first for coherent ordering
703 c = self._repo['']
718 c = self._repo['']
704 subs = c.substate # only repos that are committed
719 subs = c.substate # only repos that are committed
705 for s in sorted(subs):
720 for s in sorted(subs):
706 if c.sub(s).push(opts) == 0:
721 if c.sub(s).push(opts) == 0:
707 return False
722 return False
708
723
709 dsturl = _abssource(self._repo, True)
724 dsturl = _abssource(self._repo, True)
710 if not force:
725 if not force:
711 if self.storeclean(dsturl):
726 if self.storeclean(dsturl):
712 self._repo.ui.status(
727 self._repo.ui.status(
713 _('no changes made to subrepo %s since last push to %s\n')
728 _('no changes made to subrepo %s since last push to %s\n')
714 % (subrelpath(self), dsturl))
729 % (subrelpath(self), dsturl))
715 return None
730 return None
716 self._repo.ui.status(_('pushing subrepo %s to %s\n') %
731 self._repo.ui.status(_('pushing subrepo %s to %s\n') %
717 (subrelpath(self), dsturl))
732 (subrelpath(self), dsturl))
718 other = hg.peer(self._repo, {'ssh': ssh}, dsturl)
733 other = hg.peer(self._repo, {'ssh': ssh}, dsturl)
719 res = self._repo.push(other, force, newbranch=newbranch)
734 res = self._repo.push(other, force, newbranch=newbranch)
720
735
721 # the repo is now clean
736 # the repo is now clean
722 self._cachestorehash(dsturl)
737 self._cachestorehash(dsturl)
723 return res
738 return res
724
739
725 @annotatesubrepoerror
740 @annotatesubrepoerror
726 def outgoing(self, ui, dest, opts):
741 def outgoing(self, ui, dest, opts):
727 return hg.outgoing(ui, self._repo, _abssource(self._repo, True), opts)
742 return hg.outgoing(ui, self._repo, _abssource(self._repo, True), opts)
728
743
729 @annotatesubrepoerror
744 @annotatesubrepoerror
730 def incoming(self, ui, source, opts):
745 def incoming(self, ui, source, opts):
731 return hg.incoming(ui, self._repo, _abssource(self._repo, False), opts)
746 return hg.incoming(ui, self._repo, _abssource(self._repo, False), opts)
732
747
733 @annotatesubrepoerror
748 @annotatesubrepoerror
734 def files(self):
749 def files(self):
735 rev = self._state[1]
750 rev = self._state[1]
736 ctx = self._repo[rev]
751 ctx = self._repo[rev]
737 return ctx.manifest()
752 return ctx.manifest()
738
753
739 def filedata(self, name):
754 def filedata(self, name):
740 rev = self._state[1]
755 rev = self._state[1]
741 return self._repo[rev][name].data()
756 return self._repo[rev][name].data()
742
757
743 def fileflags(self, name):
758 def fileflags(self, name):
744 rev = self._state[1]
759 rev = self._state[1]
745 ctx = self._repo[rev]
760 ctx = self._repo[rev]
746 return ctx.flags(name)
761 return ctx.flags(name)
747
762
748 def walk(self, match):
763 def walk(self, match):
749 ctx = self._repo[None]
764 ctx = self._repo[None]
750 return ctx.walk(match)
765 return ctx.walk(match)
751
766
752 @annotatesubrepoerror
767 @annotatesubrepoerror
753 def forget(self, ui, match, prefix):
768 def forget(self, ui, match, prefix):
754 return cmdutil.forget(ui, self._repo, match,
769 return cmdutil.forget(ui, self._repo, match,
755 os.path.join(prefix, self._path), True)
770 os.path.join(prefix, self._path), True)
756
771
757 @annotatesubrepoerror
772 @annotatesubrepoerror
758 def revert(self, ui, substate, *pats, **opts):
773 def revert(self, ui, substate, *pats, **opts):
759 # reverting a subrepo is a 2 step process:
774 # reverting a subrepo is a 2 step process:
760 # 1. if the no_backup is not set, revert all modified
775 # 1. if the no_backup is not set, revert all modified
761 # files inside the subrepo
776 # files inside the subrepo
762 # 2. update the subrepo to the revision specified in
777 # 2. update the subrepo to the revision specified in
763 # the corresponding substate dictionary
778 # the corresponding substate dictionary
764 ui.status(_('reverting subrepo %s\n') % substate[0])
779 ui.status(_('reverting subrepo %s\n') % substate[0])
765 if not opts.get('no_backup'):
780 if not opts.get('no_backup'):
766 # Revert all files on the subrepo, creating backups
781 # Revert all files on the subrepo, creating backups
767 # Note that this will not recursively revert subrepos
782 # Note that this will not recursively revert subrepos
768 # We could do it if there was a set:subrepos() predicate
783 # We could do it if there was a set:subrepos() predicate
769 opts = opts.copy()
784 opts = opts.copy()
770 opts['date'] = None
785 opts['date'] = None
771 opts['rev'] = substate[1]
786 opts['rev'] = substate[1]
772
787
773 pats = []
788 pats = []
774 if not opts.get('all'):
789 if not opts.get('all'):
775 pats = ['set:modified()']
790 pats = ['set:modified()']
776 self.filerevert(ui, *pats, **opts)
791 self.filerevert(ui, *pats, **opts)
777
792
778 # Update the repo to the revision specified in the given substate
793 # Update the repo to the revision specified in the given substate
779 self.get(substate, overwrite=True)
794 self.get(substate, overwrite=True)
780
795
781 def filerevert(self, ui, *pats, **opts):
796 def filerevert(self, ui, *pats, **opts):
782 ctx = self._repo[opts['rev']]
797 ctx = self._repo[opts['rev']]
783 parents = self._repo.dirstate.parents()
798 parents = self._repo.dirstate.parents()
784 if opts.get('all'):
799 if opts.get('all'):
785 pats = ['set:modified()']
800 pats = ['set:modified()']
786 else:
801 else:
787 pats = []
802 pats = []
788 cmdutil.revert(ui, self._repo, ctx, parents, *pats, **opts)
803 cmdutil.revert(ui, self._repo, ctx, parents, *pats, **opts)
789
804
790 class svnsubrepo(abstractsubrepo):
805 class svnsubrepo(abstractsubrepo):
791 def __init__(self, ctx, path, state):
806 def __init__(self, ctx, path, state):
792 self._path = path
807 self._path = path
793 self._state = state
808 self._state = state
794 self._ctx = ctx
809 self._ctx = ctx
795 self._ui = ctx._repo.ui
810 self._ui = ctx._repo.ui
796 self._exe = util.findexe('svn')
811 self._exe = util.findexe('svn')
797 if not self._exe:
812 if not self._exe:
798 raise util.Abort(_("'svn' executable not found for subrepo '%s'")
813 raise util.Abort(_("'svn' executable not found for subrepo '%s'")
799 % self._path)
814 % self._path)
800
815
801 def _svncommand(self, commands, filename='', failok=False):
816 def _svncommand(self, commands, filename='', failok=False):
802 cmd = [self._exe]
817 cmd = [self._exe]
803 extrakw = {}
818 extrakw = {}
804 if not self._ui.interactive():
819 if not self._ui.interactive():
805 # Making stdin be a pipe should prevent svn from behaving
820 # Making stdin be a pipe should prevent svn from behaving
806 # interactively even if we can't pass --non-interactive.
821 # interactively even if we can't pass --non-interactive.
807 extrakw['stdin'] = subprocess.PIPE
822 extrakw['stdin'] = subprocess.PIPE
808 # Starting in svn 1.5 --non-interactive is a global flag
823 # Starting in svn 1.5 --non-interactive is a global flag
809 # instead of being per-command, but we need to support 1.4 so
824 # instead of being per-command, but we need to support 1.4 so
810 # we have to be intelligent about what commands take
825 # we have to be intelligent about what commands take
811 # --non-interactive.
826 # --non-interactive.
812 if commands[0] in ('update', 'checkout', 'commit'):
827 if commands[0] in ('update', 'checkout', 'commit'):
813 cmd.append('--non-interactive')
828 cmd.append('--non-interactive')
814 cmd.extend(commands)
829 cmd.extend(commands)
815 if filename is not None:
830 if filename is not None:
816 path = os.path.join(self._ctx._repo.origroot, self._path, filename)
831 path = os.path.join(self._ctx._repo.origroot, self._path, filename)
817 cmd.append(path)
832 cmd.append(path)
818 env = dict(os.environ)
833 env = dict(os.environ)
819 # Avoid localized output, preserve current locale for everything else.
834 # Avoid localized output, preserve current locale for everything else.
820 lc_all = env.get('LC_ALL')
835 lc_all = env.get('LC_ALL')
821 if lc_all:
836 if lc_all:
822 env['LANG'] = lc_all
837 env['LANG'] = lc_all
823 del env['LC_ALL']
838 del env['LC_ALL']
824 env['LC_MESSAGES'] = 'C'
839 env['LC_MESSAGES'] = 'C'
825 p = subprocess.Popen(cmd, bufsize=-1, close_fds=util.closefds,
840 p = subprocess.Popen(cmd, bufsize=-1, close_fds=util.closefds,
826 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
841 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
827 universal_newlines=True, env=env, **extrakw)
842 universal_newlines=True, env=env, **extrakw)
828 stdout, stderr = p.communicate()
843 stdout, stderr = p.communicate()
829 stderr = stderr.strip()
844 stderr = stderr.strip()
830 if not failok:
845 if not failok:
831 if p.returncode:
846 if p.returncode:
832 raise util.Abort(stderr or 'exited with code %d' % p.returncode)
847 raise util.Abort(stderr or 'exited with code %d' % p.returncode)
833 if stderr:
848 if stderr:
834 self._ui.warn(stderr + '\n')
849 self._ui.warn(stderr + '\n')
835 return stdout, stderr
850 return stdout, stderr
836
851
837 @propertycache
852 @propertycache
838 def _svnversion(self):
853 def _svnversion(self):
839 output, err = self._svncommand(['--version', '--quiet'], filename=None)
854 output, err = self._svncommand(['--version', '--quiet'], filename=None)
840 m = re.search(r'^(\d+)\.(\d+)', output)
855 m = re.search(r'^(\d+)\.(\d+)', output)
841 if not m:
856 if not m:
842 raise util.Abort(_('cannot retrieve svn tool version'))
857 raise util.Abort(_('cannot retrieve svn tool version'))
843 return (int(m.group(1)), int(m.group(2)))
858 return (int(m.group(1)), int(m.group(2)))
844
859
845 def _wcrevs(self):
860 def _wcrevs(self):
846 # Get the working directory revision as well as the last
861 # Get the working directory revision as well as the last
847 # commit revision so we can compare the subrepo state with
862 # commit revision so we can compare the subrepo state with
848 # both. We used to store the working directory one.
863 # both. We used to store the working directory one.
849 output, err = self._svncommand(['info', '--xml'])
864 output, err = self._svncommand(['info', '--xml'])
850 doc = xml.dom.minidom.parseString(output)
865 doc = xml.dom.minidom.parseString(output)
851 entries = doc.getElementsByTagName('entry')
866 entries = doc.getElementsByTagName('entry')
852 lastrev, rev = '0', '0'
867 lastrev, rev = '0', '0'
853 if entries:
868 if entries:
854 rev = str(entries[0].getAttribute('revision')) or '0'
869 rev = str(entries[0].getAttribute('revision')) or '0'
855 commits = entries[0].getElementsByTagName('commit')
870 commits = entries[0].getElementsByTagName('commit')
856 if commits:
871 if commits:
857 lastrev = str(commits[0].getAttribute('revision')) or '0'
872 lastrev = str(commits[0].getAttribute('revision')) or '0'
858 return (lastrev, rev)
873 return (lastrev, rev)
859
874
860 def _wcrev(self):
875 def _wcrev(self):
861 return self._wcrevs()[0]
876 return self._wcrevs()[0]
862
877
863 def _wcchanged(self):
878 def _wcchanged(self):
864 """Return (changes, extchanges, missing) where changes is True
879 """Return (changes, extchanges, missing) where changes is True
865 if the working directory was changed, extchanges is
880 if the working directory was changed, extchanges is
866 True if any of these changes concern an external entry and missing
881 True if any of these changes concern an external entry and missing
867 is True if any change is a missing entry.
882 is True if any change is a missing entry.
868 """
883 """
869 output, err = self._svncommand(['status', '--xml'])
884 output, err = self._svncommand(['status', '--xml'])
870 externals, changes, missing = [], [], []
885 externals, changes, missing = [], [], []
871 doc = xml.dom.minidom.parseString(output)
886 doc = xml.dom.minidom.parseString(output)
872 for e in doc.getElementsByTagName('entry'):
887 for e in doc.getElementsByTagName('entry'):
873 s = e.getElementsByTagName('wc-status')
888 s = e.getElementsByTagName('wc-status')
874 if not s:
889 if not s:
875 continue
890 continue
876 item = s[0].getAttribute('item')
891 item = s[0].getAttribute('item')
877 props = s[0].getAttribute('props')
892 props = s[0].getAttribute('props')
878 path = e.getAttribute('path')
893 path = e.getAttribute('path')
879 if item == 'external':
894 if item == 'external':
880 externals.append(path)
895 externals.append(path)
881 elif item == 'missing':
896 elif item == 'missing':
882 missing.append(path)
897 missing.append(path)
883 if (item not in ('', 'normal', 'unversioned', 'external')
898 if (item not in ('', 'normal', 'unversioned', 'external')
884 or props not in ('', 'none', 'normal')):
899 or props not in ('', 'none', 'normal')):
885 changes.append(path)
900 changes.append(path)
886 for path in changes:
901 for path in changes:
887 for ext in externals:
902 for ext in externals:
888 if path == ext or path.startswith(ext + os.sep):
903 if path == ext or path.startswith(ext + os.sep):
889 return True, True, bool(missing)
904 return True, True, bool(missing)
890 return bool(changes), False, bool(missing)
905 return bool(changes), False, bool(missing)
891
906
892 def dirty(self, ignoreupdate=False):
907 def dirty(self, ignoreupdate=False):
893 if not self._wcchanged()[0]:
908 if not self._wcchanged()[0]:
894 if self._state[1] in self._wcrevs() or ignoreupdate:
909 if self._state[1] in self._wcrevs() or ignoreupdate:
895 return False
910 return False
896 return True
911 return True
897
912
898 def basestate(self):
913 def basestate(self):
899 lastrev, rev = self._wcrevs()
914 lastrev, rev = self._wcrevs()
900 if lastrev != rev:
915 if lastrev != rev:
901 # Last committed rev is not the same than rev. We would
916 # Last committed rev is not the same than rev. We would
902 # like to take lastrev but we do not know if the subrepo
917 # like to take lastrev but we do not know if the subrepo
903 # URL exists at lastrev. Test it and fallback to rev it
918 # URL exists at lastrev. Test it and fallback to rev it
904 # is not there.
919 # is not there.
905 try:
920 try:
906 self._svncommand(['list', '%s@%s' % (self._state[0], lastrev)])
921 self._svncommand(['list', '%s@%s' % (self._state[0], lastrev)])
907 return lastrev
922 return lastrev
908 except error.Abort:
923 except error.Abort:
909 pass
924 pass
910 return rev
925 return rev
911
926
912 @annotatesubrepoerror
927 @annotatesubrepoerror
913 def commit(self, text, user, date):
928 def commit(self, text, user, date):
914 # user and date are out of our hands since svn is centralized
929 # user and date are out of our hands since svn is centralized
915 changed, extchanged, missing = self._wcchanged()
930 changed, extchanged, missing = self._wcchanged()
916 if not changed:
931 if not changed:
917 return self.basestate()
932 return self.basestate()
918 if extchanged:
933 if extchanged:
919 # Do not try to commit externals
934 # Do not try to commit externals
920 raise util.Abort(_('cannot commit svn externals'))
935 raise util.Abort(_('cannot commit svn externals'))
921 if missing:
936 if missing:
922 # svn can commit with missing entries but aborting like hg
937 # svn can commit with missing entries but aborting like hg
923 # seems a better approach.
938 # seems a better approach.
924 raise util.Abort(_('cannot commit missing svn entries'))
939 raise util.Abort(_('cannot commit missing svn entries'))
925 commitinfo, err = self._svncommand(['commit', '-m', text])
940 commitinfo, err = self._svncommand(['commit', '-m', text])
926 self._ui.status(commitinfo)
941 self._ui.status(commitinfo)
927 newrev = re.search('Committed revision ([0-9]+).', commitinfo)
942 newrev = re.search('Committed revision ([0-9]+).', commitinfo)
928 if not newrev:
943 if not newrev:
929 if not commitinfo.strip():
944 if not commitinfo.strip():
930 # Sometimes, our definition of "changed" differs from
945 # Sometimes, our definition of "changed" differs from
931 # svn one. For instance, svn ignores missing files
946 # svn one. For instance, svn ignores missing files
932 # when committing. If there are only missing files, no
947 # when committing. If there are only missing files, no
933 # commit is made, no output and no error code.
948 # commit is made, no output and no error code.
934 raise util.Abort(_('failed to commit svn changes'))
949 raise util.Abort(_('failed to commit svn changes'))
935 raise util.Abort(commitinfo.splitlines()[-1])
950 raise util.Abort(commitinfo.splitlines()[-1])
936 newrev = newrev.groups()[0]
951 newrev = newrev.groups()[0]
937 self._ui.status(self._svncommand(['update', '-r', newrev])[0])
952 self._ui.status(self._svncommand(['update', '-r', newrev])[0])
938 return newrev
953 return newrev
939
954
940 @annotatesubrepoerror
955 @annotatesubrepoerror
941 def remove(self):
956 def remove(self):
942 if self.dirty():
957 if self.dirty():
943 self._ui.warn(_('not removing repo %s because '
958 self._ui.warn(_('not removing repo %s because '
944 'it has changes.\n' % self._path))
959 'it has changes.\n' % self._path))
945 return
960 return
946 self._ui.note(_('removing subrepo %s\n') % self._path)
961 self._ui.note(_('removing subrepo %s\n') % self._path)
947
962
948 def onerror(function, path, excinfo):
963 def onerror(function, path, excinfo):
949 if function is not os.remove:
964 if function is not os.remove:
950 raise
965 raise
951 # read-only files cannot be unlinked under Windows
966 # read-only files cannot be unlinked under Windows
952 s = os.stat(path)
967 s = os.stat(path)
953 if (s.st_mode & stat.S_IWRITE) != 0:
968 if (s.st_mode & stat.S_IWRITE) != 0:
954 raise
969 raise
955 os.chmod(path, stat.S_IMODE(s.st_mode) | stat.S_IWRITE)
970 os.chmod(path, stat.S_IMODE(s.st_mode) | stat.S_IWRITE)
956 os.remove(path)
971 os.remove(path)
957
972
958 path = self._ctx._repo.wjoin(self._path)
973 path = self._ctx._repo.wjoin(self._path)
959 shutil.rmtree(path, onerror=onerror)
974 shutil.rmtree(path, onerror=onerror)
960 try:
975 try:
961 os.removedirs(os.path.dirname(path))
976 os.removedirs(os.path.dirname(path))
962 except OSError:
977 except OSError:
963 pass
978 pass
964
979
965 @annotatesubrepoerror
980 @annotatesubrepoerror
966 def get(self, state, overwrite=False):
981 def get(self, state, overwrite=False):
967 if overwrite:
982 if overwrite:
968 self._svncommand(['revert', '--recursive'])
983 self._svncommand(['revert', '--recursive'])
969 args = ['checkout']
984 args = ['checkout']
970 if self._svnversion >= (1, 5):
985 if self._svnversion >= (1, 5):
971 args.append('--force')
986 args.append('--force')
972 # The revision must be specified at the end of the URL to properly
987 # The revision must be specified at the end of the URL to properly
973 # update to a directory which has since been deleted and recreated.
988 # update to a directory which has since been deleted and recreated.
974 args.append('%s@%s' % (state[0], state[1]))
989 args.append('%s@%s' % (state[0], state[1]))
975 status, err = self._svncommand(args, failok=True)
990 status, err = self._svncommand(args, failok=True)
976 if not re.search('Checked out revision [0-9]+.', status):
991 if not re.search('Checked out revision [0-9]+.', status):
977 if ('is already a working copy for a different URL' in err
992 if ('is already a working copy for a different URL' in err
978 and (self._wcchanged()[:2] == (False, False))):
993 and (self._wcchanged()[:2] == (False, False))):
979 # obstructed but clean working copy, so just blow it away.
994 # obstructed but clean working copy, so just blow it away.
980 self.remove()
995 self.remove()
981 self.get(state, overwrite=False)
996 self.get(state, overwrite=False)
982 return
997 return
983 raise util.Abort((status or err).splitlines()[-1])
998 raise util.Abort((status or err).splitlines()[-1])
984 self._ui.status(status)
999 self._ui.status(status)
985
1000
986 @annotatesubrepoerror
1001 @annotatesubrepoerror
987 def merge(self, state):
1002 def merge(self, state):
988 old = self._state[1]
1003 old = self._state[1]
989 new = state[1]
1004 new = state[1]
990 wcrev = self._wcrev()
1005 wcrev = self._wcrev()
991 if new != wcrev:
1006 if new != wcrev:
992 dirty = old == wcrev or self._wcchanged()[0]
1007 dirty = old == wcrev or self._wcchanged()[0]
993 if _updateprompt(self._ui, self, dirty, wcrev, new):
1008 if _updateprompt(self._ui, self, dirty, wcrev, new):
994 self.get(state, False)
1009 self.get(state, False)
995
1010
996 def push(self, opts):
1011 def push(self, opts):
997 # push is a no-op for SVN
1012 # push is a no-op for SVN
998 return True
1013 return True
999
1014
1000 @annotatesubrepoerror
1015 @annotatesubrepoerror
1001 def files(self):
1016 def files(self):
1002 output = self._svncommand(['list', '--recursive', '--xml'])[0]
1017 output = self._svncommand(['list', '--recursive', '--xml'])[0]
1003 doc = xml.dom.minidom.parseString(output)
1018 doc = xml.dom.minidom.parseString(output)
1004 paths = []
1019 paths = []
1005 for e in doc.getElementsByTagName('entry'):
1020 for e in doc.getElementsByTagName('entry'):
1006 kind = str(e.getAttribute('kind'))
1021 kind = str(e.getAttribute('kind'))
1007 if kind != 'file':
1022 if kind != 'file':
1008 continue
1023 continue
1009 name = ''.join(c.data for c
1024 name = ''.join(c.data for c
1010 in e.getElementsByTagName('name')[0].childNodes
1025 in e.getElementsByTagName('name')[0].childNodes
1011 if c.nodeType == c.TEXT_NODE)
1026 if c.nodeType == c.TEXT_NODE)
1012 paths.append(name.encode('utf-8'))
1027 paths.append(name.encode('utf-8'))
1013 return paths
1028 return paths
1014
1029
1015 def filedata(self, name):
1030 def filedata(self, name):
1016 return self._svncommand(['cat'], name)[0]
1031 return self._svncommand(['cat'], name)[0]
1017
1032
1018
1033
1019 class gitsubrepo(abstractsubrepo):
1034 class gitsubrepo(abstractsubrepo):
1020 def __init__(self, ctx, path, state):
1035 def __init__(self, ctx, path, state):
1021 self._state = state
1036 self._state = state
1022 self._ctx = ctx
1037 self._ctx = ctx
1023 self._path = path
1038 self._path = path
1024 self._relpath = os.path.join(reporelpath(ctx._repo), path)
1039 self._relpath = os.path.join(reporelpath(ctx._repo), path)
1025 self._abspath = ctx._repo.wjoin(path)
1040 self._abspath = ctx._repo.wjoin(path)
1026 self._subparent = ctx._repo
1041 self._subparent = ctx._repo
1027 self._ui = ctx._repo.ui
1042 self._ui = ctx._repo.ui
1028 self._ensuregit()
1043 self._ensuregit()
1029
1044
1030 def _ensuregit(self):
1045 def _ensuregit(self):
1031 try:
1046 try:
1032 self._gitexecutable = 'git'
1047 self._gitexecutable = 'git'
1033 out, err = self._gitnodir(['--version'])
1048 out, err = self._gitnodir(['--version'])
1034 except OSError, e:
1049 except OSError, e:
1035 if e.errno != 2 or os.name != 'nt':
1050 if e.errno != 2 or os.name != 'nt':
1036 raise
1051 raise
1037 self._gitexecutable = 'git.cmd'
1052 self._gitexecutable = 'git.cmd'
1038 out, err = self._gitnodir(['--version'])
1053 out, err = self._gitnodir(['--version'])
1039 m = re.search(r'^git version (\d+)\.(\d+)\.(\d+)', out)
1054 m = re.search(r'^git version (\d+)\.(\d+)\.(\d+)', out)
1040 if not m:
1055 if not m:
1041 self._ui.warn(_('cannot retrieve git version'))
1056 self._ui.warn(_('cannot retrieve git version'))
1042 return
1057 return
1043 version = (int(m.group(1)), m.group(2), m.group(3))
1058 version = (int(m.group(1)), m.group(2), m.group(3))
1044 # git 1.4.0 can't work at all, but 1.5.X can in at least some cases,
1059 # git 1.4.0 can't work at all, but 1.5.X can in at least some cases,
1045 # despite the docstring comment. For now, error on 1.4.0, warn on
1060 # despite the docstring comment. For now, error on 1.4.0, warn on
1046 # 1.5.0 but attempt to continue.
1061 # 1.5.0 but attempt to continue.
1047 if version < (1, 5, 0):
1062 if version < (1, 5, 0):
1048 raise util.Abort(_('git subrepo requires at least 1.6.0 or later'))
1063 raise util.Abort(_('git subrepo requires at least 1.6.0 or later'))
1049 elif version < (1, 6, 0):
1064 elif version < (1, 6, 0):
1050 self._ui.warn(_('git subrepo requires at least 1.6.0 or later'))
1065 self._ui.warn(_('git subrepo requires at least 1.6.0 or later'))
1051
1066
1052 def _gitcommand(self, commands, env=None, stream=False):
1067 def _gitcommand(self, commands, env=None, stream=False):
1053 return self._gitdir(commands, env=env, stream=stream)[0]
1068 return self._gitdir(commands, env=env, stream=stream)[0]
1054
1069
1055 def _gitdir(self, commands, env=None, stream=False):
1070 def _gitdir(self, commands, env=None, stream=False):
1056 return self._gitnodir(commands, env=env, stream=stream,
1071 return self._gitnodir(commands, env=env, stream=stream,
1057 cwd=self._abspath)
1072 cwd=self._abspath)
1058
1073
1059 def _gitnodir(self, commands, env=None, stream=False, cwd=None):
1074 def _gitnodir(self, commands, env=None, stream=False, cwd=None):
1060 """Calls the git command
1075 """Calls the git command
1061
1076
1062 The methods tries to call the git command. versions prior to 1.6.0
1077 The methods tries to call the git command. versions prior to 1.6.0
1063 are not supported and very probably fail.
1078 are not supported and very probably fail.
1064 """
1079 """
1065 self._ui.debug('%s: git %s\n' % (self._relpath, ' '.join(commands)))
1080 self._ui.debug('%s: git %s\n' % (self._relpath, ' '.join(commands)))
1066 # unless ui.quiet is set, print git's stderr,
1081 # unless ui.quiet is set, print git's stderr,
1067 # which is mostly progress and useful info
1082 # which is mostly progress and useful info
1068 errpipe = None
1083 errpipe = None
1069 if self._ui.quiet:
1084 if self._ui.quiet:
1070 errpipe = open(os.devnull, 'w')
1085 errpipe = open(os.devnull, 'w')
1071 p = subprocess.Popen([self._gitexecutable] + commands, bufsize=-1,
1086 p = subprocess.Popen([self._gitexecutable] + commands, bufsize=-1,
1072 cwd=cwd, env=env, close_fds=util.closefds,
1087 cwd=cwd, env=env, close_fds=util.closefds,
1073 stdout=subprocess.PIPE, stderr=errpipe)
1088 stdout=subprocess.PIPE, stderr=errpipe)
1074 if stream:
1089 if stream:
1075 return p.stdout, None
1090 return p.stdout, None
1076
1091
1077 retdata = p.stdout.read().strip()
1092 retdata = p.stdout.read().strip()
1078 # wait for the child to exit to avoid race condition.
1093 # wait for the child to exit to avoid race condition.
1079 p.wait()
1094 p.wait()
1080
1095
1081 if p.returncode != 0 and p.returncode != 1:
1096 if p.returncode != 0 and p.returncode != 1:
1082 # there are certain error codes that are ok
1097 # there are certain error codes that are ok
1083 command = commands[0]
1098 command = commands[0]
1084 if command in ('cat-file', 'symbolic-ref'):
1099 if command in ('cat-file', 'symbolic-ref'):
1085 return retdata, p.returncode
1100 return retdata, p.returncode
1086 # for all others, abort
1101 # for all others, abort
1087 raise util.Abort('git %s error %d in %s' %
1102 raise util.Abort('git %s error %d in %s' %
1088 (command, p.returncode, self._relpath))
1103 (command, p.returncode, self._relpath))
1089
1104
1090 return retdata, p.returncode
1105 return retdata, p.returncode
1091
1106
1092 def _gitmissing(self):
1107 def _gitmissing(self):
1093 return not os.path.exists(os.path.join(self._abspath, '.git'))
1108 return not os.path.exists(os.path.join(self._abspath, '.git'))
1094
1109
1095 def _gitstate(self):
1110 def _gitstate(self):
1096 return self._gitcommand(['rev-parse', 'HEAD'])
1111 return self._gitcommand(['rev-parse', 'HEAD'])
1097
1112
1098 def _gitcurrentbranch(self):
1113 def _gitcurrentbranch(self):
1099 current, err = self._gitdir(['symbolic-ref', 'HEAD', '--quiet'])
1114 current, err = self._gitdir(['symbolic-ref', 'HEAD', '--quiet'])
1100 if err:
1115 if err:
1101 current = None
1116 current = None
1102 return current
1117 return current
1103
1118
1104 def _gitremote(self, remote):
1119 def _gitremote(self, remote):
1105 out = self._gitcommand(['remote', 'show', '-n', remote])
1120 out = self._gitcommand(['remote', 'show', '-n', remote])
1106 line = out.split('\n')[1]
1121 line = out.split('\n')[1]
1107 i = line.index('URL: ') + len('URL: ')
1122 i = line.index('URL: ') + len('URL: ')
1108 return line[i:]
1123 return line[i:]
1109
1124
1110 def _githavelocally(self, revision):
1125 def _githavelocally(self, revision):
1111 out, code = self._gitdir(['cat-file', '-e', revision])
1126 out, code = self._gitdir(['cat-file', '-e', revision])
1112 return code == 0
1127 return code == 0
1113
1128
1114 def _gitisancestor(self, r1, r2):
1129 def _gitisancestor(self, r1, r2):
1115 base = self._gitcommand(['merge-base', r1, r2])
1130 base = self._gitcommand(['merge-base', r1, r2])
1116 return base == r1
1131 return base == r1
1117
1132
1118 def _gitisbare(self):
1133 def _gitisbare(self):
1119 return self._gitcommand(['config', '--bool', 'core.bare']) == 'true'
1134 return self._gitcommand(['config', '--bool', 'core.bare']) == 'true'
1120
1135
1121 def _gitupdatestat(self):
1136 def _gitupdatestat(self):
1122 """This must be run before git diff-index.
1137 """This must be run before git diff-index.
1123 diff-index only looks at changes to file stat;
1138 diff-index only looks at changes to file stat;
1124 this command looks at file contents and updates the stat."""
1139 this command looks at file contents and updates the stat."""
1125 self._gitcommand(['update-index', '-q', '--refresh'])
1140 self._gitcommand(['update-index', '-q', '--refresh'])
1126
1141
1127 def _gitbranchmap(self):
1142 def _gitbranchmap(self):
1128 '''returns 2 things:
1143 '''returns 2 things:
1129 a map from git branch to revision
1144 a map from git branch to revision
1130 a map from revision to branches'''
1145 a map from revision to branches'''
1131 branch2rev = {}
1146 branch2rev = {}
1132 rev2branch = {}
1147 rev2branch = {}
1133
1148
1134 out = self._gitcommand(['for-each-ref', '--format',
1149 out = self._gitcommand(['for-each-ref', '--format',
1135 '%(objectname) %(refname)'])
1150 '%(objectname) %(refname)'])
1136 for line in out.split('\n'):
1151 for line in out.split('\n'):
1137 revision, ref = line.split(' ')
1152 revision, ref = line.split(' ')
1138 if (not ref.startswith('refs/heads/') and
1153 if (not ref.startswith('refs/heads/') and
1139 not ref.startswith('refs/remotes/')):
1154 not ref.startswith('refs/remotes/')):
1140 continue
1155 continue
1141 if ref.startswith('refs/remotes/') and ref.endswith('/HEAD'):
1156 if ref.startswith('refs/remotes/') and ref.endswith('/HEAD'):
1142 continue # ignore remote/HEAD redirects
1157 continue # ignore remote/HEAD redirects
1143 branch2rev[ref] = revision
1158 branch2rev[ref] = revision
1144 rev2branch.setdefault(revision, []).append(ref)
1159 rev2branch.setdefault(revision, []).append(ref)
1145 return branch2rev, rev2branch
1160 return branch2rev, rev2branch
1146
1161
1147 def _gittracking(self, branches):
1162 def _gittracking(self, branches):
1148 'return map of remote branch to local tracking branch'
1163 'return map of remote branch to local tracking branch'
1149 # assumes no more than one local tracking branch for each remote
1164 # assumes no more than one local tracking branch for each remote
1150 tracking = {}
1165 tracking = {}
1151 for b in branches:
1166 for b in branches:
1152 if b.startswith('refs/remotes/'):
1167 if b.startswith('refs/remotes/'):
1153 continue
1168 continue
1154 bname = b.split('/', 2)[2]
1169 bname = b.split('/', 2)[2]
1155 remote = self._gitcommand(['config', 'branch.%s.remote' % bname])
1170 remote = self._gitcommand(['config', 'branch.%s.remote' % bname])
1156 if remote:
1171 if remote:
1157 ref = self._gitcommand(['config', 'branch.%s.merge' % bname])
1172 ref = self._gitcommand(['config', 'branch.%s.merge' % bname])
1158 tracking['refs/remotes/%s/%s' %
1173 tracking['refs/remotes/%s/%s' %
1159 (remote, ref.split('/', 2)[2])] = b
1174 (remote, ref.split('/', 2)[2])] = b
1160 return tracking
1175 return tracking
1161
1176
1162 def _abssource(self, source):
1177 def _abssource(self, source):
1163 if '://' not in source:
1178 if '://' not in source:
1164 # recognize the scp syntax as an absolute source
1179 # recognize the scp syntax as an absolute source
1165 colon = source.find(':')
1180 colon = source.find(':')
1166 if colon != -1 and '/' not in source[:colon]:
1181 if colon != -1 and '/' not in source[:colon]:
1167 return source
1182 return source
1168 self._subsource = source
1183 self._subsource = source
1169 return _abssource(self)
1184 return _abssource(self)
1170
1185
1171 def _fetch(self, source, revision):
1186 def _fetch(self, source, revision):
1172 if self._gitmissing():
1187 if self._gitmissing():
1173 source = self._abssource(source)
1188 source = self._abssource(source)
1174 self._ui.status(_('cloning subrepo %s from %s\n') %
1189 self._ui.status(_('cloning subrepo %s from %s\n') %
1175 (self._relpath, source))
1190 (self._relpath, source))
1176 self._gitnodir(['clone', source, self._abspath])
1191 self._gitnodir(['clone', source, self._abspath])
1177 if self._githavelocally(revision):
1192 if self._githavelocally(revision):
1178 return
1193 return
1179 self._ui.status(_('pulling subrepo %s from %s\n') %
1194 self._ui.status(_('pulling subrepo %s from %s\n') %
1180 (self._relpath, self._gitremote('origin')))
1195 (self._relpath, self._gitremote('origin')))
1181 # try only origin: the originally cloned repo
1196 # try only origin: the originally cloned repo
1182 self._gitcommand(['fetch'])
1197 self._gitcommand(['fetch'])
1183 if not self._githavelocally(revision):
1198 if not self._githavelocally(revision):
1184 raise util.Abort(_("revision %s does not exist in subrepo %s\n") %
1199 raise util.Abort(_("revision %s does not exist in subrepo %s\n") %
1185 (revision, self._relpath))
1200 (revision, self._relpath))
1186
1201
1187 @annotatesubrepoerror
1202 @annotatesubrepoerror
1188 def dirty(self, ignoreupdate=False):
1203 def dirty(self, ignoreupdate=False):
1189 if self._gitmissing():
1204 if self._gitmissing():
1190 return self._state[1] != ''
1205 return self._state[1] != ''
1191 if self._gitisbare():
1206 if self._gitisbare():
1192 return True
1207 return True
1193 if not ignoreupdate and self._state[1] != self._gitstate():
1208 if not ignoreupdate and self._state[1] != self._gitstate():
1194 # different version checked out
1209 # different version checked out
1195 return True
1210 return True
1196 # check for staged changes or modified files; ignore untracked files
1211 # check for staged changes or modified files; ignore untracked files
1197 self._gitupdatestat()
1212 self._gitupdatestat()
1198 out, code = self._gitdir(['diff-index', '--quiet', 'HEAD'])
1213 out, code = self._gitdir(['diff-index', '--quiet', 'HEAD'])
1199 return code == 1
1214 return code == 1
1200
1215
1201 def basestate(self):
1216 def basestate(self):
1202 return self._gitstate()
1217 return self._gitstate()
1203
1218
1204 @annotatesubrepoerror
1219 @annotatesubrepoerror
1205 def get(self, state, overwrite=False):
1220 def get(self, state, overwrite=False):
1206 source, revision, kind = state
1221 source, revision, kind = state
1207 if not revision:
1222 if not revision:
1208 self.remove()
1223 self.remove()
1209 return
1224 return
1210 self._fetch(source, revision)
1225 self._fetch(source, revision)
1211 # if the repo was set to be bare, unbare it
1226 # if the repo was set to be bare, unbare it
1212 if self._gitisbare():
1227 if self._gitisbare():
1213 self._gitcommand(['config', 'core.bare', 'false'])
1228 self._gitcommand(['config', 'core.bare', 'false'])
1214 if self._gitstate() == revision:
1229 if self._gitstate() == revision:
1215 self._gitcommand(['reset', '--hard', 'HEAD'])
1230 self._gitcommand(['reset', '--hard', 'HEAD'])
1216 return
1231 return
1217 elif self._gitstate() == revision:
1232 elif self._gitstate() == revision:
1218 if overwrite:
1233 if overwrite:
1219 # first reset the index to unmark new files for commit, because
1234 # first reset the index to unmark new files for commit, because
1220 # reset --hard will otherwise throw away files added for commit,
1235 # reset --hard will otherwise throw away files added for commit,
1221 # not just unmark them.
1236 # not just unmark them.
1222 self._gitcommand(['reset', 'HEAD'])
1237 self._gitcommand(['reset', 'HEAD'])
1223 self._gitcommand(['reset', '--hard', 'HEAD'])
1238 self._gitcommand(['reset', '--hard', 'HEAD'])
1224 return
1239 return
1225 branch2rev, rev2branch = self._gitbranchmap()
1240 branch2rev, rev2branch = self._gitbranchmap()
1226
1241
1227 def checkout(args):
1242 def checkout(args):
1228 cmd = ['checkout']
1243 cmd = ['checkout']
1229 if overwrite:
1244 if overwrite:
1230 # first reset the index to unmark new files for commit, because
1245 # first reset the index to unmark new files for commit, because
1231 # the -f option will otherwise throw away files added for
1246 # the -f option will otherwise throw away files added for
1232 # commit, not just unmark them.
1247 # commit, not just unmark them.
1233 self._gitcommand(['reset', 'HEAD'])
1248 self._gitcommand(['reset', 'HEAD'])
1234 cmd.append('-f')
1249 cmd.append('-f')
1235 self._gitcommand(cmd + args)
1250 self._gitcommand(cmd + args)
1236
1251
1237 def rawcheckout():
1252 def rawcheckout():
1238 # no branch to checkout, check it out with no branch
1253 # no branch to checkout, check it out with no branch
1239 self._ui.warn(_('checking out detached HEAD in subrepo %s\n') %
1254 self._ui.warn(_('checking out detached HEAD in subrepo %s\n') %
1240 self._relpath)
1255 self._relpath)
1241 self._ui.warn(_('check out a git branch if you intend '
1256 self._ui.warn(_('check out a git branch if you intend '
1242 'to make changes\n'))
1257 'to make changes\n'))
1243 checkout(['-q', revision])
1258 checkout(['-q', revision])
1244
1259
1245 if revision not in rev2branch:
1260 if revision not in rev2branch:
1246 rawcheckout()
1261 rawcheckout()
1247 return
1262 return
1248 branches = rev2branch[revision]
1263 branches = rev2branch[revision]
1249 firstlocalbranch = None
1264 firstlocalbranch = None
1250 for b in branches:
1265 for b in branches:
1251 if b == 'refs/heads/master':
1266 if b == 'refs/heads/master':
1252 # master trumps all other branches
1267 # master trumps all other branches
1253 checkout(['refs/heads/master'])
1268 checkout(['refs/heads/master'])
1254 return
1269 return
1255 if not firstlocalbranch and not b.startswith('refs/remotes/'):
1270 if not firstlocalbranch and not b.startswith('refs/remotes/'):
1256 firstlocalbranch = b
1271 firstlocalbranch = b
1257 if firstlocalbranch:
1272 if firstlocalbranch:
1258 checkout([firstlocalbranch])
1273 checkout([firstlocalbranch])
1259 return
1274 return
1260
1275
1261 tracking = self._gittracking(branch2rev.keys())
1276 tracking = self._gittracking(branch2rev.keys())
1262 # choose a remote branch already tracked if possible
1277 # choose a remote branch already tracked if possible
1263 remote = branches[0]
1278 remote = branches[0]
1264 if remote not in tracking:
1279 if remote not in tracking:
1265 for b in branches:
1280 for b in branches:
1266 if b in tracking:
1281 if b in tracking:
1267 remote = b
1282 remote = b
1268 break
1283 break
1269
1284
1270 if remote not in tracking:
1285 if remote not in tracking:
1271 # create a new local tracking branch
1286 # create a new local tracking branch
1272 local = remote.split('/', 3)[3]
1287 local = remote.split('/', 3)[3]
1273 checkout(['-b', local, remote])
1288 checkout(['-b', local, remote])
1274 elif self._gitisancestor(branch2rev[tracking[remote]], remote):
1289 elif self._gitisancestor(branch2rev[tracking[remote]], remote):
1275 # When updating to a tracked remote branch,
1290 # When updating to a tracked remote branch,
1276 # if the local tracking branch is downstream of it,
1291 # if the local tracking branch is downstream of it,
1277 # a normal `git pull` would have performed a "fast-forward merge"
1292 # a normal `git pull` would have performed a "fast-forward merge"
1278 # which is equivalent to updating the local branch to the remote.
1293 # which is equivalent to updating the local branch to the remote.
1279 # Since we are only looking at branching at update, we need to
1294 # Since we are only looking at branching at update, we need to
1280 # detect this situation and perform this action lazily.
1295 # detect this situation and perform this action lazily.
1281 if tracking[remote] != self._gitcurrentbranch():
1296 if tracking[remote] != self._gitcurrentbranch():
1282 checkout([tracking[remote]])
1297 checkout([tracking[remote]])
1283 self._gitcommand(['merge', '--ff', remote])
1298 self._gitcommand(['merge', '--ff', remote])
1284 else:
1299 else:
1285 # a real merge would be required, just checkout the revision
1300 # a real merge would be required, just checkout the revision
1286 rawcheckout()
1301 rawcheckout()
1287
1302
1288 @annotatesubrepoerror
1303 @annotatesubrepoerror
1289 def commit(self, text, user, date):
1304 def commit(self, text, user, date):
1290 if self._gitmissing():
1305 if self._gitmissing():
1291 raise util.Abort(_("subrepo %s is missing") % self._relpath)
1306 raise util.Abort(_("subrepo %s is missing") % self._relpath)
1292 cmd = ['commit', '-a', '-m', text]
1307 cmd = ['commit', '-a', '-m', text]
1293 env = os.environ.copy()
1308 env = os.environ.copy()
1294 if user:
1309 if user:
1295 cmd += ['--author', user]
1310 cmd += ['--author', user]
1296 if date:
1311 if date:
1297 # git's date parser silently ignores when seconds < 1e9
1312 # git's date parser silently ignores when seconds < 1e9
1298 # convert to ISO8601
1313 # convert to ISO8601
1299 env['GIT_AUTHOR_DATE'] = util.datestr(date,
1314 env['GIT_AUTHOR_DATE'] = util.datestr(date,
1300 '%Y-%m-%dT%H:%M:%S %1%2')
1315 '%Y-%m-%dT%H:%M:%S %1%2')
1301 self._gitcommand(cmd, env=env)
1316 self._gitcommand(cmd, env=env)
1302 # make sure commit works otherwise HEAD might not exist under certain
1317 # make sure commit works otherwise HEAD might not exist under certain
1303 # circumstances
1318 # circumstances
1304 return self._gitstate()
1319 return self._gitstate()
1305
1320
1306 @annotatesubrepoerror
1321 @annotatesubrepoerror
1307 def merge(self, state):
1322 def merge(self, state):
1308 source, revision, kind = state
1323 source, revision, kind = state
1309 self._fetch(source, revision)
1324 self._fetch(source, revision)
1310 base = self._gitcommand(['merge-base', revision, self._state[1]])
1325 base = self._gitcommand(['merge-base', revision, self._state[1]])
1311 self._gitupdatestat()
1326 self._gitupdatestat()
1312 out, code = self._gitdir(['diff-index', '--quiet', 'HEAD'])
1327 out, code = self._gitdir(['diff-index', '--quiet', 'HEAD'])
1313
1328
1314 def mergefunc():
1329 def mergefunc():
1315 if base == revision:
1330 if base == revision:
1316 self.get(state) # fast forward merge
1331 self.get(state) # fast forward merge
1317 elif base != self._state[1]:
1332 elif base != self._state[1]:
1318 self._gitcommand(['merge', '--no-commit', revision])
1333 self._gitcommand(['merge', '--no-commit', revision])
1319
1334
1320 if self.dirty():
1335 if self.dirty():
1321 if self._gitstate() != revision:
1336 if self._gitstate() != revision:
1322 dirty = self._gitstate() == self._state[1] or code != 0
1337 dirty = self._gitstate() == self._state[1] or code != 0
1323 if _updateprompt(self._ui, self, dirty,
1338 if _updateprompt(self._ui, self, dirty,
1324 self._state[1][:7], revision[:7]):
1339 self._state[1][:7], revision[:7]):
1325 mergefunc()
1340 mergefunc()
1326 else:
1341 else:
1327 mergefunc()
1342 mergefunc()
1328
1343
1329 @annotatesubrepoerror
1344 @annotatesubrepoerror
1330 def push(self, opts):
1345 def push(self, opts):
1331 force = opts.get('force')
1346 force = opts.get('force')
1332
1347
1333 if not self._state[1]:
1348 if not self._state[1]:
1334 return True
1349 return True
1335 if self._gitmissing():
1350 if self._gitmissing():
1336 raise util.Abort(_("subrepo %s is missing") % self._relpath)
1351 raise util.Abort(_("subrepo %s is missing") % self._relpath)
1337 # if a branch in origin contains the revision, nothing to do
1352 # if a branch in origin contains the revision, nothing to do
1338 branch2rev, rev2branch = self._gitbranchmap()
1353 branch2rev, rev2branch = self._gitbranchmap()
1339 if self._state[1] in rev2branch:
1354 if self._state[1] in rev2branch:
1340 for b in rev2branch[self._state[1]]:
1355 for b in rev2branch[self._state[1]]:
1341 if b.startswith('refs/remotes/origin/'):
1356 if b.startswith('refs/remotes/origin/'):
1342 return True
1357 return True
1343 for b, revision in branch2rev.iteritems():
1358 for b, revision in branch2rev.iteritems():
1344 if b.startswith('refs/remotes/origin/'):
1359 if b.startswith('refs/remotes/origin/'):
1345 if self._gitisancestor(self._state[1], revision):
1360 if self._gitisancestor(self._state[1], revision):
1346 return True
1361 return True
1347 # otherwise, try to push the currently checked out branch
1362 # otherwise, try to push the currently checked out branch
1348 cmd = ['push']
1363 cmd = ['push']
1349 if force:
1364 if force:
1350 cmd.append('--force')
1365 cmd.append('--force')
1351
1366
1352 current = self._gitcurrentbranch()
1367 current = self._gitcurrentbranch()
1353 if current:
1368 if current:
1354 # determine if the current branch is even useful
1369 # determine if the current branch is even useful
1355 if not self._gitisancestor(self._state[1], current):
1370 if not self._gitisancestor(self._state[1], current):
1356 self._ui.warn(_('unrelated git branch checked out '
1371 self._ui.warn(_('unrelated git branch checked out '
1357 'in subrepo %s\n') % self._relpath)
1372 'in subrepo %s\n') % self._relpath)
1358 return False
1373 return False
1359 self._ui.status(_('pushing branch %s of subrepo %s\n') %
1374 self._ui.status(_('pushing branch %s of subrepo %s\n') %
1360 (current.split('/', 2)[2], self._relpath))
1375 (current.split('/', 2)[2], self._relpath))
1361 self._gitcommand(cmd + ['origin', current])
1376 self._gitcommand(cmd + ['origin', current])
1362 return True
1377 return True
1363 else:
1378 else:
1364 self._ui.warn(_('no branch checked out in subrepo %s\n'
1379 self._ui.warn(_('no branch checked out in subrepo %s\n'
1365 'cannot push revision %s\n') %
1380 'cannot push revision %s\n') %
1366 (self._relpath, self._state[1]))
1381 (self._relpath, self._state[1]))
1367 return False
1382 return False
1368
1383
1369 @annotatesubrepoerror
1384 @annotatesubrepoerror
1370 def remove(self):
1385 def remove(self):
1371 if self._gitmissing():
1386 if self._gitmissing():
1372 return
1387 return
1373 if self.dirty():
1388 if self.dirty():
1374 self._ui.warn(_('not removing repo %s because '
1389 self._ui.warn(_('not removing repo %s because '
1375 'it has changes.\n') % self._relpath)
1390 'it has changes.\n') % self._relpath)
1376 return
1391 return
1377 # we can't fully delete the repository as it may contain
1392 # we can't fully delete the repository as it may contain
1378 # local-only history
1393 # local-only history
1379 self._ui.note(_('removing subrepo %s\n') % self._relpath)
1394 self._ui.note(_('removing subrepo %s\n') % self._relpath)
1380 self._gitcommand(['config', 'core.bare', 'true'])
1395 self._gitcommand(['config', 'core.bare', 'true'])
1381 for f in os.listdir(self._abspath):
1396 for f in os.listdir(self._abspath):
1382 if f == '.git':
1397 if f == '.git':
1383 continue
1398 continue
1384 path = os.path.join(self._abspath, f)
1399 path = os.path.join(self._abspath, f)
1385 if os.path.isdir(path) and not os.path.islink(path):
1400 if os.path.isdir(path) and not os.path.islink(path):
1386 shutil.rmtree(path)
1401 shutil.rmtree(path)
1387 else:
1402 else:
1388 os.remove(path)
1403 os.remove(path)
1389
1404
1390 def archive(self, ui, archiver, prefix, match=None):
1405 def archive(self, ui, archiver, prefix, match=None):
1391 total = 0
1406 total = 0
1392 source, revision = self._state
1407 source, revision = self._state
1393 if not revision:
1408 if not revision:
1394 return total
1409 return total
1395 self._fetch(source, revision)
1410 self._fetch(source, revision)
1396
1411
1397 # Parse git's native archive command.
1412 # Parse git's native archive command.
1398 # This should be much faster than manually traversing the trees
1413 # This should be much faster than manually traversing the trees
1399 # and objects with many subprocess calls.
1414 # and objects with many subprocess calls.
1400 tarstream = self._gitcommand(['archive', revision], stream=True)
1415 tarstream = self._gitcommand(['archive', revision], stream=True)
1401 tar = tarfile.open(fileobj=tarstream, mode='r|')
1416 tar = tarfile.open(fileobj=tarstream, mode='r|')
1402 relpath = subrelpath(self)
1417 relpath = subrelpath(self)
1403 ui.progress(_('archiving (%s)') % relpath, 0, unit=_('files'))
1418 ui.progress(_('archiving (%s)') % relpath, 0, unit=_('files'))
1404 for i, info in enumerate(tar):
1419 for i, info in enumerate(tar):
1405 if info.isdir():
1420 if info.isdir():
1406 continue
1421 continue
1407 if match and not match(info.name):
1422 if match and not match(info.name):
1408 continue
1423 continue
1409 if info.issym():
1424 if info.issym():
1410 data = info.linkname
1425 data = info.linkname
1411 else:
1426 else:
1412 data = tar.extractfile(info).read()
1427 data = tar.extractfile(info).read()
1413 archiver.addfile(os.path.join(prefix, self._path, info.name),
1428 archiver.addfile(os.path.join(prefix, self._path, info.name),
1414 info.mode, info.issym(), data)
1429 info.mode, info.issym(), data)
1415 total += 1
1430 total += 1
1416 ui.progress(_('archiving (%s)') % relpath, i + 1,
1431 ui.progress(_('archiving (%s)') % relpath, i + 1,
1417 unit=_('files'))
1432 unit=_('files'))
1418 ui.progress(_('archiving (%s)') % relpath, None)
1433 ui.progress(_('archiving (%s)') % relpath, None)
1419 return total
1434 return total
1420
1435
1421
1436
1422 @annotatesubrepoerror
1437 @annotatesubrepoerror
1423 def status(self, rev2, **opts):
1438 def status(self, rev2, **opts):
1424 rev1 = self._state[1]
1439 rev1 = self._state[1]
1425 if self._gitmissing() or not rev1:
1440 if self._gitmissing() or not rev1:
1426 # if the repo is missing, return no results
1441 # if the repo is missing, return no results
1427 return [], [], [], [], [], [], []
1442 return [], [], [], [], [], [], []
1428 modified, added, removed = [], [], []
1443 modified, added, removed = [], [], []
1429 self._gitupdatestat()
1444 self._gitupdatestat()
1430 if rev2:
1445 if rev2:
1431 command = ['diff-tree', rev1, rev2]
1446 command = ['diff-tree', rev1, rev2]
1432 else:
1447 else:
1433 command = ['diff-index', rev1]
1448 command = ['diff-index', rev1]
1434 out = self._gitcommand(command)
1449 out = self._gitcommand(command)
1435 for line in out.split('\n'):
1450 for line in out.split('\n'):
1436 tab = line.find('\t')
1451 tab = line.find('\t')
1437 if tab == -1:
1452 if tab == -1:
1438 continue
1453 continue
1439 status, f = line[tab - 1], line[tab + 1:]
1454 status, f = line[tab - 1], line[tab + 1:]
1440 if status == 'M':
1455 if status == 'M':
1441 modified.append(f)
1456 modified.append(f)
1442 elif status == 'A':
1457 elif status == 'A':
1443 added.append(f)
1458 added.append(f)
1444 elif status == 'D':
1459 elif status == 'D':
1445 removed.append(f)
1460 removed.append(f)
1446
1461
1447 deleted = unknown = ignored = clean = []
1462 deleted = unknown = ignored = clean = []
1448 return modified, added, removed, deleted, unknown, ignored, clean
1463 return modified, added, removed, deleted, unknown, ignored, clean
1449
1464
1450 types = {
1465 types = {
1451 'hg': hgsubrepo,
1466 'hg': hgsubrepo,
1452 'svn': svnsubrepo,
1467 'svn': svnsubrepo,
1453 'git': gitsubrepo,
1468 'git': gitsubrepo,
1454 }
1469 }
@@ -1,540 +1,542
1 $ echo "[ui]" >> $HGRCPATH
1 $ echo "[ui]" >> $HGRCPATH
2 $ echo "commitsubrepos = Yes" >> $HGRCPATH
2 $ echo "commitsubrepos = Yes" >> $HGRCPATH
3 $ echo "[extensions]" >> $HGRCPATH
3 $ echo "[extensions]" >> $HGRCPATH
4 $ echo "mq=" >> $HGRCPATH
4 $ echo "mq=" >> $HGRCPATH
5 $ echo "record=" >> $HGRCPATH
5 $ echo "record=" >> $HGRCPATH
6 $ echo "[diff]" >> $HGRCPATH
6 $ echo "[diff]" >> $HGRCPATH
7 $ echo "nodates=1" >> $HGRCPATH
7 $ echo "nodates=1" >> $HGRCPATH
8
8
9 $ stdin=`pwd`/stdin.tmp
9 $ stdin=`pwd`/stdin.tmp
10
10
11 fn to create new repository w/dirty subrepo, and cd into it
11 fn to create new repository w/dirty subrepo, and cd into it
12 $ mkrepo() {
12 $ mkrepo() {
13 > hg init $1
13 > hg init $1
14 > cd $1
14 > cd $1
15 > hg qinit
15 > hg qinit
16 > }
16 > }
17
17
18 fn to create dirty subrepo
18 fn to create dirty subrepo
19 $ mksubrepo() {
19 $ mksubrepo() {
20 > hg init $1
20 > hg init $1
21 > cd $1
21 > cd $1
22 > echo a > a
22 > echo a > a
23 > hg add
23 > hg add
24 > cd ..
24 > cd ..
25 > }
25 > }
26
26
27 $ testadd() {
27 $ testadd() {
28 > cat - > "$stdin"
28 > cat - > "$stdin"
29 > mksubrepo sub
29 > mksubrepo sub
30 > echo sub = sub >> .hgsub
30 > echo sub = sub >> .hgsub
31 > hg add .hgsub
31 > hg add .hgsub
32 > echo % abort when adding .hgsub w/dirty subrepo
32 > echo % abort when adding .hgsub w/dirty subrepo
33 > hg status -S
33 > hg status -S
34 > echo '%' $*
34 > echo '%' $*
35 > cat "$stdin" | hg $*
35 > cat "$stdin" | hg $*
36 > echo [$?]
36 > echo [$?]
37 > hg -R sub ci -m0sub
37 > hg -R sub ci -m0sub
38 > echo % update substate when adding .hgsub w/clean updated subrepo
38 > echo % update substate when adding .hgsub w/clean updated subrepo
39 > hg status -S
39 > hg status -S
40 > echo '%' $*
40 > echo '%' $*
41 > cat "$stdin" | hg $*
41 > cat "$stdin" | hg $*
42 > hg debugsub
42 > hg debugsub
43 > }
43 > }
44
44
45 $ testmod() {
45 $ testmod() {
46 > cat - > "$stdin"
46 > cat - > "$stdin"
47 > mksubrepo sub2
47 > mksubrepo sub2
48 > echo sub2 = sub2 >> .hgsub
48 > echo sub2 = sub2 >> .hgsub
49 > echo % abort when modifying .hgsub w/dirty subrepo
49 > echo % abort when modifying .hgsub w/dirty subrepo
50 > hg status -S
50 > hg status -S
51 > echo '%' $*
51 > echo '%' $*
52 > cat "$stdin" | hg $*
52 > cat "$stdin" | hg $*
53 > echo [$?]
53 > echo [$?]
54 > hg -R sub2 ci -m0sub2
54 > hg -R sub2 ci -m0sub2
55 > echo % update substate when modifying .hgsub w/clean updated subrepo
55 > echo % update substate when modifying .hgsub w/clean updated subrepo
56 > hg status -S
56 > hg status -S
57 > echo '%' $*
57 > echo '%' $*
58 > cat "$stdin" | hg $*
58 > cat "$stdin" | hg $*
59 > hg debugsub
59 > hg debugsub
60 > }
60 > }
61
61
62 $ testrm1() {
62 $ testrm1() {
63 > cat - > "$stdin"
63 > cat - > "$stdin"
64 > mksubrepo sub3
64 > mksubrepo sub3
65 > echo sub3 = sub3 >> .hgsub
65 > echo sub3 = sub3 >> .hgsub
66 > hg ci -Aqmsub3
66 > hg ci -Aqmsub3
67 > $EXTRA
67 > $EXTRA
68 > echo b >> sub3/a
68 > echo b >> sub3/a
69 > hg rm .hgsub
69 > hg rm .hgsub
70 > echo % update substate when removing .hgsub w/dirty subrepo
70 > echo % update substate when removing .hgsub w/dirty subrepo
71 > hg status -S
71 > hg status -S
72 > echo '%' $*
72 > echo '%' $*
73 > cat "$stdin" | hg $*
73 > cat "$stdin" | hg $*
74 > echo % debugsub should be empty
74 > echo % debugsub should be empty
75 > hg debugsub
75 > hg debugsub
76 > }
76 > }
77
77
78 $ testrm2() {
78 $ testrm2() {
79 > cat - > "$stdin"
79 > cat - > "$stdin"
80 > mksubrepo sub4
80 > mksubrepo sub4
81 > echo sub4 = sub4 >> .hgsub
81 > echo sub4 = sub4 >> .hgsub
82 > hg ci -Aqmsub4
82 > hg ci -Aqmsub4
83 > $EXTRA
83 > $EXTRA
84 > hg rm .hgsub
84 > hg rm .hgsub
85 > echo % update substate when removing .hgsub w/clean updated subrepo
85 > echo % update substate when removing .hgsub w/clean updated subrepo
86 > hg status -S
86 > hg status -S
87 > echo '%' $*
87 > echo '%' $*
88 > cat "$stdin" | hg $*
88 > cat "$stdin" | hg $*
89 > echo % debugsub should be empty
89 > echo % debugsub should be empty
90 > hg debugsub
90 > hg debugsub
91 > }
91 > }
92
92
93
93
94 handle subrepos safely on qnew
94 handle subrepos safely on qnew
95
95
96 $ mkrepo repo-2499-qnew
96 $ mkrepo repo-2499-qnew
97 $ testadd qnew -m0 0.diff
97 $ testadd qnew -m0 0.diff
98 adding a
98 adding a
99 % abort when adding .hgsub w/dirty subrepo
99 % abort when adding .hgsub w/dirty subrepo
100 A .hgsub
100 A .hgsub
101 A sub/a
101 A sub/a
102 % qnew -m0 0.diff
102 % qnew -m0 0.diff
103 abort: uncommitted changes in subrepository sub
103 abort: uncommitted changes in subrepository sub
104 [255]
104 [255]
105 % update substate when adding .hgsub w/clean updated subrepo
105 % update substate when adding .hgsub w/clean updated subrepo
106 A .hgsub
106 A .hgsub
107 % qnew -m0 0.diff
107 % qnew -m0 0.diff
108 path sub
108 path sub
109 source sub
109 source sub
110 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
110 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
111
111
112 $ testmod qnew -m1 1.diff
112 $ testmod qnew -m1 1.diff
113 adding a
113 adding a
114 % abort when modifying .hgsub w/dirty subrepo
114 % abort when modifying .hgsub w/dirty subrepo
115 M .hgsub
115 M .hgsub
116 A sub2/a
116 A sub2/a
117 % qnew -m1 1.diff
117 % qnew -m1 1.diff
118 abort: uncommitted changes in subrepository sub2
118 abort: uncommitted changes in subrepository sub2
119 [255]
119 [255]
120 % update substate when modifying .hgsub w/clean updated subrepo
120 % update substate when modifying .hgsub w/clean updated subrepo
121 M .hgsub
121 M .hgsub
122 % qnew -m1 1.diff
122 % qnew -m1 1.diff
123 path sub
123 path sub
124 source sub
124 source sub
125 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
125 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
126 path sub2
126 path sub2
127 source sub2
127 source sub2
128 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
128 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
129
129
130 $ hg qpop -qa
130 $ hg qpop -qa
131 patch queue now empty
131 patch queue now empty
132 $ testrm1 qnew -m2 2.diff
132 $ testrm1 qnew -m2 2.diff
133 adding a
133 adding a
134 % update substate when removing .hgsub w/dirty subrepo
134 % update substate when removing .hgsub w/dirty subrepo
135 M sub3/a
135 M sub3/a
136 R .hgsub
136 R .hgsub
137 % qnew -m2 2.diff
137 % qnew -m2 2.diff
138 % debugsub should be empty
138 % debugsub should be empty
139
139
140 $ hg qpop -qa
140 $ hg qpop -qa
141 patch queue now empty
141 patch queue now empty
142 $ testrm2 qnew -m3 3.diff
142 $ testrm2 qnew -m3 3.diff
143 adding a
143 adding a
144 % update substate when removing .hgsub w/clean updated subrepo
144 % update substate when removing .hgsub w/clean updated subrepo
145 R .hgsub
145 R .hgsub
146 % qnew -m3 3.diff
146 % qnew -m3 3.diff
147 % debugsub should be empty
147 % debugsub should be empty
148
148
149 $ cd ..
149 $ cd ..
150
150
151
151
152 handle subrepos safely on qrefresh
152 handle subrepos safely on qrefresh
153
153
154 $ mkrepo repo-2499-qrefresh
154 $ mkrepo repo-2499-qrefresh
155 $ hg qnew -m0 0.diff
155 $ hg qnew -m0 0.diff
156 $ testadd qrefresh
156 $ testadd qrefresh
157 adding a
157 adding a
158 % abort when adding .hgsub w/dirty subrepo
158 % abort when adding .hgsub w/dirty subrepo
159 A .hgsub
159 A .hgsub
160 A sub/a
160 A sub/a
161 % qrefresh
161 % qrefresh
162 abort: uncommitted changes in subrepository sub
162 abort: uncommitted changes in subrepository sub
163 [255]
163 [255]
164 % update substate when adding .hgsub w/clean updated subrepo
164 % update substate when adding .hgsub w/clean updated subrepo
165 A .hgsub
165 A .hgsub
166 % qrefresh
166 % qrefresh
167 path sub
167 path sub
168 source sub
168 source sub
169 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
169 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
170
170
171 $ hg qnew -m1 1.diff
171 $ hg qnew -m1 1.diff
172 $ testmod qrefresh
172 $ testmod qrefresh
173 adding a
173 adding a
174 % abort when modifying .hgsub w/dirty subrepo
174 % abort when modifying .hgsub w/dirty subrepo
175 M .hgsub
175 M .hgsub
176 A sub2/a
176 A sub2/a
177 % qrefresh
177 % qrefresh
178 abort: uncommitted changes in subrepository sub2
178 abort: uncommitted changes in subrepository sub2
179 [255]
179 [255]
180 % update substate when modifying .hgsub w/clean updated subrepo
180 % update substate when modifying .hgsub w/clean updated subrepo
181 M .hgsub
181 M .hgsub
182 % qrefresh
182 % qrefresh
183 path sub
183 path sub
184 source sub
184 source sub
185 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
185 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
186 path sub2
186 path sub2
187 source sub2
187 source sub2
188 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
188 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
189
189
190 $ hg qpop -qa
190 $ hg qpop -qa
191 patch queue now empty
191 patch queue now empty
192 $ EXTRA='hg qnew -m2 2.diff'
192 $ EXTRA='hg qnew -m2 2.diff'
193 $ testrm1 qrefresh
193 $ testrm1 qrefresh
194 adding a
194 adding a
195 % update substate when removing .hgsub w/dirty subrepo
195 % update substate when removing .hgsub w/dirty subrepo
196 M sub3/a
196 M sub3/a
197 R .hgsub
197 R .hgsub
198 % qrefresh
198 % qrefresh
199 % debugsub should be empty
199 % debugsub should be empty
200
200
201 $ hg qpop -qa
201 $ hg qpop -qa
202 patch queue now empty
202 patch queue now empty
203 $ EXTRA='hg qnew -m3 3.diff'
203 $ EXTRA='hg qnew -m3 3.diff'
204 $ testrm2 qrefresh
204 $ testrm2 qrefresh
205 adding a
205 adding a
206 % update substate when removing .hgsub w/clean updated subrepo
206 % update substate when removing .hgsub w/clean updated subrepo
207 R .hgsub
207 R .hgsub
208 % qrefresh
208 % qrefresh
209 % debugsub should be empty
209 % debugsub should be empty
210 $ EXTRA=
210 $ EXTRA=
211
211
212 $ cd ..
212 $ cd ..
213
213
214
214
215 handle subrepos safely on qpush/qpop
215 handle subrepos safely on qpush/qpop
216 (and we cannot qpop / qpush with a modified subrepo)
216 (and we cannot qpop / qpush with a modified subrepo)
217
217
218 $ mkrepo repo-2499-qpush
218 $ mkrepo repo-2499-qpush
219 $ mksubrepo sub
219 $ mksubrepo sub
220 adding a
220 adding a
221 $ hg -R sub ci -m0sub
221 $ hg -R sub ci -m0sub
222 $ echo sub = sub > .hgsub
222 $ echo sub = sub > .hgsub
223 $ hg add .hgsub
223 $ hg add .hgsub
224 $ hg commit -m0
224 $ hg commit -m0
225 $ hg debugsub
225 $ hg debugsub
226 path sub
226 path sub
227 source sub
227 source sub
228 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
228 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
229 $ echo foo > ./sub/a
229 $ echo foo > ./sub/a
230 $ hg -R sub commit -m foo
230 $ hg -R sub commit -m foo
231 $ hg commit -m1
231 $ hg commit -m1
232 $ hg qimport -r "0:tip"
232 $ hg qimport -r "0:tip"
233 $ hg -R sub id --id
233 $ hg -R sub id --id
234 aa037b301eba
234 aa037b301eba
235
235
236 qpop
236 qpop
237 $ hg -R sub update 0000
237 $ hg -R sub update 0000
238 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
238 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
239 $ hg qpop
239 $ hg qpop
240 abort: local changed subrepos found, refresh first
240 abort: local changed subrepos found, refresh first
241 [255]
241 [255]
242 $ hg revert sub
242 $ hg revert sub
243 reverting subrepo sub
243 reverting subrepo sub
244 adding sub/a
244 adding sub/a
245 $ hg qpop
245 $ hg qpop
246 popping 1.diff
246 popping 1.diff
247 now at: 0.diff
247 now at: 0.diff
248 $ hg status -AS
248 $ hg status -AS
249 C .hgsub
249 C .hgsub
250 C .hgsubstate
250 C .hgsubstate
251 C sub/a
251 C sub/a
252 $ hg -R sub id --id
252 $ hg -R sub id --id
253 b2fdb12cd82b
253 b2fdb12cd82b
254
254
255 qpush
255 qpush
256 $ hg -R sub update 0000
256 $ hg -R sub update 0000
257 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
257 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
258 $ hg qpush
258 $ hg qpush
259 abort: local changed subrepos found, refresh first
259 abort: local changed subrepos found, refresh first
260 [255]
260 [255]
261 $ hg revert sub
261 $ hg revert sub
262 reverting subrepo sub
262 reverting subrepo sub
263 adding sub/a
263 adding sub/a
264 $ hg qpush
264 $ hg qpush
265 applying 1.diff
265 applying 1.diff
266 subrepository sub diverged (local revision: b2fdb12cd82b, remote revision: aa037b301eba)
267 (M)erge, keep (l)ocal or keep (r)emote? m
266 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
268 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
267 now at: 1.diff
269 now at: 1.diff
268 $ hg status -AS
270 $ hg status -AS
269 C .hgsub
271 C .hgsub
270 C .hgsubstate
272 C .hgsubstate
271 C sub/a
273 C sub/a
272 $ hg -R sub id --id
274 $ hg -R sub id --id
273 aa037b301eba
275 aa037b301eba
274
276
275 $ cd ..
277 $ cd ..
276
278
277
279
278 handle subrepos safely on qrecord
280 handle subrepos safely on qrecord
279
281
280 $ mkrepo repo-2499-qrecord
282 $ mkrepo repo-2499-qrecord
281 $ testadd qrecord --config ui.interactive=1 -m0 0.diff <<EOF
283 $ testadd qrecord --config ui.interactive=1 -m0 0.diff <<EOF
282 > y
284 > y
283 > y
285 > y
284 > EOF
286 > EOF
285 adding a
287 adding a
286 % abort when adding .hgsub w/dirty subrepo
288 % abort when adding .hgsub w/dirty subrepo
287 A .hgsub
289 A .hgsub
288 A sub/a
290 A sub/a
289 % qrecord --config ui.interactive=1 -m0 0.diff
291 % qrecord --config ui.interactive=1 -m0 0.diff
290 diff --git a/.hgsub b/.hgsub
292 diff --git a/.hgsub b/.hgsub
291 new file mode 100644
293 new file mode 100644
292 examine changes to '.hgsub'? [Ynesfdaq?]
294 examine changes to '.hgsub'? [Ynesfdaq?]
293 abort: uncommitted changes in subrepository sub
295 abort: uncommitted changes in subrepository sub
294 [255]
296 [255]
295 % update substate when adding .hgsub w/clean updated subrepo
297 % update substate when adding .hgsub w/clean updated subrepo
296 A .hgsub
298 A .hgsub
297 % qrecord --config ui.interactive=1 -m0 0.diff
299 % qrecord --config ui.interactive=1 -m0 0.diff
298 diff --git a/.hgsub b/.hgsub
300 diff --git a/.hgsub b/.hgsub
299 new file mode 100644
301 new file mode 100644
300 examine changes to '.hgsub'? [Ynesfdaq?]
302 examine changes to '.hgsub'? [Ynesfdaq?]
301 path sub
303 path sub
302 source sub
304 source sub
303 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
305 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
304
306
305 $ testmod qrecord --config ui.interactive=1 -m1 1.diff <<EOF
307 $ testmod qrecord --config ui.interactive=1 -m1 1.diff <<EOF
306 > y
308 > y
307 > y
309 > y
308 > EOF
310 > EOF
309 adding a
311 adding a
310 % abort when modifying .hgsub w/dirty subrepo
312 % abort when modifying .hgsub w/dirty subrepo
311 M .hgsub
313 M .hgsub
312 A sub2/a
314 A sub2/a
313 % qrecord --config ui.interactive=1 -m1 1.diff
315 % qrecord --config ui.interactive=1 -m1 1.diff
314 diff --git a/.hgsub b/.hgsub
316 diff --git a/.hgsub b/.hgsub
315 1 hunks, 1 lines changed
317 1 hunks, 1 lines changed
316 examine changes to '.hgsub'? [Ynesfdaq?]
318 examine changes to '.hgsub'? [Ynesfdaq?]
317 @@ -1,1 +1,2 @@
319 @@ -1,1 +1,2 @@
318 sub = sub
320 sub = sub
319 +sub2 = sub2
321 +sub2 = sub2
320 record this change to '.hgsub'? [Ynesfdaq?]
322 record this change to '.hgsub'? [Ynesfdaq?]
321 abort: uncommitted changes in subrepository sub2
323 abort: uncommitted changes in subrepository sub2
322 [255]
324 [255]
323 % update substate when modifying .hgsub w/clean updated subrepo
325 % update substate when modifying .hgsub w/clean updated subrepo
324 M .hgsub
326 M .hgsub
325 % qrecord --config ui.interactive=1 -m1 1.diff
327 % qrecord --config ui.interactive=1 -m1 1.diff
326 diff --git a/.hgsub b/.hgsub
328 diff --git a/.hgsub b/.hgsub
327 1 hunks, 1 lines changed
329 1 hunks, 1 lines changed
328 examine changes to '.hgsub'? [Ynesfdaq?]
330 examine changes to '.hgsub'? [Ynesfdaq?]
329 @@ -1,1 +1,2 @@
331 @@ -1,1 +1,2 @@
330 sub = sub
332 sub = sub
331 +sub2 = sub2
333 +sub2 = sub2
332 record this change to '.hgsub'? [Ynesfdaq?]
334 record this change to '.hgsub'? [Ynesfdaq?]
333 path sub
335 path sub
334 source sub
336 source sub
335 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
337 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
336 path sub2
338 path sub2
337 source sub2
339 source sub2
338 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
340 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
339
341
340 $ hg qpop -qa
342 $ hg qpop -qa
341 patch queue now empty
343 patch queue now empty
342 $ testrm1 qrecord --config ui.interactive=1 -m2 2.diff <<EOF
344 $ testrm1 qrecord --config ui.interactive=1 -m2 2.diff <<EOF
343 > y
345 > y
344 > y
346 > y
345 > EOF
347 > EOF
346 adding a
348 adding a
347 % update substate when removing .hgsub w/dirty subrepo
349 % update substate when removing .hgsub w/dirty subrepo
348 M sub3/a
350 M sub3/a
349 R .hgsub
351 R .hgsub
350 % qrecord --config ui.interactive=1 -m2 2.diff
352 % qrecord --config ui.interactive=1 -m2 2.diff
351 diff --git a/.hgsub b/.hgsub
353 diff --git a/.hgsub b/.hgsub
352 deleted file mode 100644
354 deleted file mode 100644
353 examine changes to '.hgsub'? [Ynesfdaq?]
355 examine changes to '.hgsub'? [Ynesfdaq?]
354 % debugsub should be empty
356 % debugsub should be empty
355
357
356 $ hg qpop -qa
358 $ hg qpop -qa
357 patch queue now empty
359 patch queue now empty
358 $ testrm2 qrecord --config ui.interactive=1 -m3 3.diff <<EOF
360 $ testrm2 qrecord --config ui.interactive=1 -m3 3.diff <<EOF
359 > y
361 > y
360 > y
362 > y
361 > EOF
363 > EOF
362 adding a
364 adding a
363 % update substate when removing .hgsub w/clean updated subrepo
365 % update substate when removing .hgsub w/clean updated subrepo
364 R .hgsub
366 R .hgsub
365 % qrecord --config ui.interactive=1 -m3 3.diff
367 % qrecord --config ui.interactive=1 -m3 3.diff
366 diff --git a/.hgsub b/.hgsub
368 diff --git a/.hgsub b/.hgsub
367 deleted file mode 100644
369 deleted file mode 100644
368 examine changes to '.hgsub'? [Ynesfdaq?]
370 examine changes to '.hgsub'? [Ynesfdaq?]
369 % debugsub should be empty
371 % debugsub should be empty
370
372
371 $ cd ..
373 $ cd ..
372
374
373
375
374 correctly handle subrepos with patch queues
376 correctly handle subrepos with patch queues
375 $ mkrepo repo-subrepo-with-queue
377 $ mkrepo repo-subrepo-with-queue
376 $ mksubrepo sub
378 $ mksubrepo sub
377 adding a
379 adding a
378 $ hg -R sub qnew sub0.diff
380 $ hg -R sub qnew sub0.diff
379 $ echo sub = sub >> .hgsub
381 $ echo sub = sub >> .hgsub
380 $ hg add .hgsub
382 $ hg add .hgsub
381 $ hg qnew 0.diff
383 $ hg qnew 0.diff
382
384
383 $ cd ..
385 $ cd ..
384
386
385 check whether MQ operations can import updated .hgsubstate correctly
387 check whether MQ operations can import updated .hgsubstate correctly
386 both into 'revision' and 'patch file under .hg/patches':
388 both into 'revision' and 'patch file under .hg/patches':
387
389
388 $ hg init importing-hgsubstate
390 $ hg init importing-hgsubstate
389 $ cd importing-hgsubstate
391 $ cd importing-hgsubstate
390
392
391 $ echo a > a
393 $ echo a > a
392 $ hg commit -u test -d '0 0' -Am '#0 in parent'
394 $ hg commit -u test -d '0 0' -Am '#0 in parent'
393 adding a
395 adding a
394 $ hg init sub
396 $ hg init sub
395 $ echo sa > sub/sa
397 $ echo sa > sub/sa
396 $ hg -R sub commit -u test -d '0 0' -Am '#0 in sub'
398 $ hg -R sub commit -u test -d '0 0' -Am '#0 in sub'
397 adding sa
399 adding sa
398 $ echo 'sub = sub' > .hgsub
400 $ echo 'sub = sub' > .hgsub
399 $ touch .hgsubstate
401 $ touch .hgsubstate
400 $ hg add .hgsub .hgsubstate
402 $ hg add .hgsub .hgsubstate
401
403
402 $ hg qnew -u test -d '0 0' import-at-qnew
404 $ hg qnew -u test -d '0 0' import-at-qnew
403 $ hg -R sub parents --template '{node} sub\n'
405 $ hg -R sub parents --template '{node} sub\n'
404 b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
406 b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
405 $ cat .hgsubstate
407 $ cat .hgsubstate
406 b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
408 b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
407 $ hg diff -c tip
409 $ hg diff -c tip
408 diff -r f499373e340c -r b20ffac88564 .hgsub
410 diff -r f499373e340c -r b20ffac88564 .hgsub
409 --- /dev/null
411 --- /dev/null
410 +++ b/.hgsub
412 +++ b/.hgsub
411 @@ -0,0 +1,1 @@
413 @@ -0,0 +1,1 @@
412 +sub = sub
414 +sub = sub
413 diff -r f499373e340c -r b20ffac88564 .hgsubstate
415 diff -r f499373e340c -r b20ffac88564 .hgsubstate
414 --- /dev/null
416 --- /dev/null
415 +++ b/.hgsubstate
417 +++ b/.hgsubstate
416 @@ -0,0 +1,1 @@
418 @@ -0,0 +1,1 @@
417 +b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
419 +b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
418 $ cat .hg/patches/import-at-qnew
420 $ cat .hg/patches/import-at-qnew
419 # HG changeset patch
421 # HG changeset patch
420 # Parent f499373e340cdca5d01dee904aeb42dd2a325e71
422 # Parent f499373e340cdca5d01dee904aeb42dd2a325e71
421 # User test
423 # User test
422 # Date 0 0
424 # Date 0 0
423
425
424 diff -r f499373e340c -r b20ffac88564 .hgsub
426 diff -r f499373e340c -r b20ffac88564 .hgsub
425 --- /dev/null
427 --- /dev/null
426 +++ b/.hgsub
428 +++ b/.hgsub
427 @@ -0,0 +1,1 @@
429 @@ -0,0 +1,1 @@
428 +sub = sub
430 +sub = sub
429 diff -r f499373e340c -r b20ffac88564 .hgsubstate
431 diff -r f499373e340c -r b20ffac88564 .hgsubstate
430 --- /dev/null
432 --- /dev/null
431 +++ b/.hgsubstate
433 +++ b/.hgsubstate
432 @@ -0,0 +1,1 @@
434 @@ -0,0 +1,1 @@
433 +b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
435 +b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
434 $ hg qpop
436 $ hg qpop
435 popping import-at-qnew
437 popping import-at-qnew
436 patch queue now empty
438 patch queue now empty
437 $ hg qpush
439 $ hg qpush
438 applying import-at-qnew
440 applying import-at-qnew
439 now at: import-at-qnew
441 now at: import-at-qnew
440
442
441 $ hg qnew import-at-qrefresh
443 $ hg qnew import-at-qrefresh
442 $ echo sb > sub/sb
444 $ echo sb > sub/sb
443 $ hg -R sub commit -u test -d '0 0' -Am '#1 in sub'
445 $ hg -R sub commit -u test -d '0 0' -Am '#1 in sub'
444 adding sb
446 adding sb
445 $ hg qrefresh -u test -d '0 0'
447 $ hg qrefresh -u test -d '0 0'
446 $ hg -R sub parents --template '{node} sub\n'
448 $ hg -R sub parents --template '{node} sub\n'
447 88ac1bef5ed43b689d1d200b59886b675dec474b sub
449 88ac1bef5ed43b689d1d200b59886b675dec474b sub
448 $ cat .hgsubstate
450 $ cat .hgsubstate
449 88ac1bef5ed43b689d1d200b59886b675dec474b sub
451 88ac1bef5ed43b689d1d200b59886b675dec474b sub
450 $ hg diff -c tip
452 $ hg diff -c tip
451 diff -r 44f846335325 -r b3e8c5fa3aaa .hgsubstate
453 diff -r 44f846335325 -r b3e8c5fa3aaa .hgsubstate
452 --- a/.hgsubstate
454 --- a/.hgsubstate
453 +++ b/.hgsubstate
455 +++ b/.hgsubstate
454 @@ -1,1 +1,1 @@
456 @@ -1,1 +1,1 @@
455 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
457 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
456 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
458 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
457 $ cat .hg/patches/import-at-qrefresh
459 $ cat .hg/patches/import-at-qrefresh
458 # HG changeset patch
460 # HG changeset patch
459 # Date 0 0
461 # Date 0 0
460 # User test
462 # User test
461 # Parent 44f846335325209be6be35dc2c9a4be107278c09
463 # Parent 44f846335325209be6be35dc2c9a4be107278c09
462
464
463 diff -r 44f846335325 .hgsubstate
465 diff -r 44f846335325 .hgsubstate
464 --- a/.hgsubstate
466 --- a/.hgsubstate
465 +++ b/.hgsubstate
467 +++ b/.hgsubstate
466 @@ -1,1 +1,1 @@
468 @@ -1,1 +1,1 @@
467 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
469 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
468 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
470 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
469
471
470 $ hg qrefresh -u test -d '0 0'
472 $ hg qrefresh -u test -d '0 0'
471 $ cat .hgsubstate
473 $ cat .hgsubstate
472 88ac1bef5ed43b689d1d200b59886b675dec474b sub
474 88ac1bef5ed43b689d1d200b59886b675dec474b sub
473 $ hg diff -c tip
475 $ hg diff -c tip
474 diff -r 44f846335325 -r b3e8c5fa3aaa .hgsubstate
476 diff -r 44f846335325 -r b3e8c5fa3aaa .hgsubstate
475 --- a/.hgsubstate
477 --- a/.hgsubstate
476 +++ b/.hgsubstate
478 +++ b/.hgsubstate
477 @@ -1,1 +1,1 @@
479 @@ -1,1 +1,1 @@
478 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
480 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
479 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
481 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
480 $ cat .hg/patches/import-at-qrefresh
482 $ cat .hg/patches/import-at-qrefresh
481 # HG changeset patch
483 # HG changeset patch
482 # Date 0 0
484 # Date 0 0
483 # User test
485 # User test
484 # Parent 44f846335325209be6be35dc2c9a4be107278c09
486 # Parent 44f846335325209be6be35dc2c9a4be107278c09
485
487
486 diff -r 44f846335325 .hgsubstate
488 diff -r 44f846335325 .hgsubstate
487 --- a/.hgsubstate
489 --- a/.hgsubstate
488 +++ b/.hgsubstate
490 +++ b/.hgsubstate
489 @@ -1,1 +1,1 @@
491 @@ -1,1 +1,1 @@
490 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
492 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
491 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
493 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
492
494
493 $ hg update -C tip
495 $ hg update -C tip
494 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
496 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
495 $ hg qpop -a
497 $ hg qpop -a
496 popping import-at-qrefresh
498 popping import-at-qrefresh
497 popping import-at-qnew
499 popping import-at-qnew
498 patch queue now empty
500 patch queue now empty
499
501
500 $ hg -R sub update -C 0
502 $ hg -R sub update -C 0
501 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
503 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
502 $ echo 'sub = sub' > .hgsub
504 $ echo 'sub = sub' > .hgsub
503 $ hg commit -Am '#1 in parent'
505 $ hg commit -Am '#1 in parent'
504 adding .hgsub
506 adding .hgsub
505 $ hg -R sub update -C 1
507 $ hg -R sub update -C 1
506 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
508 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
507 $ hg commit -Am '#2 in parent (but will be rolled back soon)'
509 $ hg commit -Am '#2 in parent (but will be rolled back soon)'
508 $ hg rollback
510 $ hg rollback
509 repository tip rolled back to revision 1 (undo commit)
511 repository tip rolled back to revision 1 (undo commit)
510 working directory now based on revision 1
512 working directory now based on revision 1
511 $ hg status
513 $ hg status
512 M .hgsubstate
514 M .hgsubstate
513 $ hg qnew -u test -d '0 0' checkstate-at-qnew
515 $ hg qnew -u test -d '0 0' checkstate-at-qnew
514 $ hg -R sub parents --template '{node} sub\n'
516 $ hg -R sub parents --template '{node} sub\n'
515 88ac1bef5ed43b689d1d200b59886b675dec474b sub
517 88ac1bef5ed43b689d1d200b59886b675dec474b sub
516 $ cat .hgsubstate
518 $ cat .hgsubstate
517 88ac1bef5ed43b689d1d200b59886b675dec474b sub
519 88ac1bef5ed43b689d1d200b59886b675dec474b sub
518 $ hg diff -c tip
520 $ hg diff -c tip
519 diff -r 4d91eb2fa1d1 -r 1259c112d884 .hgsubstate
521 diff -r 4d91eb2fa1d1 -r 1259c112d884 .hgsubstate
520 --- a/.hgsubstate
522 --- a/.hgsubstate
521 +++ b/.hgsubstate
523 +++ b/.hgsubstate
522 @@ -1,1 +1,1 @@
524 @@ -1,1 +1,1 @@
523 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
525 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
524 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
526 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
525 $ cat .hg/patches/checkstate-at-qnew
527 $ cat .hg/patches/checkstate-at-qnew
526 # HG changeset patch
528 # HG changeset patch
527 # Parent 4d91eb2fa1d1b22ec513347b9cd06f6b49d470fa
529 # Parent 4d91eb2fa1d1b22ec513347b9cd06f6b49d470fa
528 # User test
530 # User test
529 # Date 0 0
531 # Date 0 0
530
532
531 diff -r 4d91eb2fa1d1 -r 1259c112d884 .hgsubstate
533 diff -r 4d91eb2fa1d1 -r 1259c112d884 .hgsubstate
532 --- a/.hgsubstate
534 --- a/.hgsubstate
533 +++ b/.hgsubstate
535 +++ b/.hgsubstate
534 @@ -1,1 +1,1 @@
536 @@ -1,1 +1,1 @@
535 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
537 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
536 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
538 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
537
539
538 $ cd ..
540 $ cd ..
539
541
540 $ cd ..
542 $ cd ..
@@ -1,560 +1,568
1 $ "$TESTDIR/hghave" git || exit 80
1 $ "$TESTDIR/hghave" git || exit 80
2
2
3 make git commits repeatable
3 make git commits repeatable
4
4
5 $ echo "[core]" >> $HOME/.gitconfig
5 $ echo "[core]" >> $HOME/.gitconfig
6 $ echo "autocrlf = false" >> $HOME/.gitconfig
6 $ echo "autocrlf = false" >> $HOME/.gitconfig
7 $ GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME
7 $ GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME
8 $ GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL
8 $ GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL
9 $ GIT_AUTHOR_DATE='1234567891 +0000'; export GIT_AUTHOR_DATE
9 $ GIT_AUTHOR_DATE='1234567891 +0000'; export GIT_AUTHOR_DATE
10 $ GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; export GIT_COMMITTER_NAME
10 $ GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; export GIT_COMMITTER_NAME
11 $ GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"; export GIT_COMMITTER_EMAIL
11 $ GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"; export GIT_COMMITTER_EMAIL
12 $ GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"; export GIT_COMMITTER_DATE
12 $ GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"; export GIT_COMMITTER_DATE
13
13
14 root hg repo
14 root hg repo
15
15
16 $ hg init t
16 $ hg init t
17 $ cd t
17 $ cd t
18 $ echo a > a
18 $ echo a > a
19 $ hg add a
19 $ hg add a
20 $ hg commit -m a
20 $ hg commit -m a
21 $ cd ..
21 $ cd ..
22
22
23 new external git repo
23 new external git repo
24
24
25 $ mkdir gitroot
25 $ mkdir gitroot
26 $ cd gitroot
26 $ cd gitroot
27 $ git init -q
27 $ git init -q
28 $ echo g > g
28 $ echo g > g
29 $ git add g
29 $ git add g
30 $ git commit -q -m g
30 $ git commit -q -m g
31
31
32 add subrepo clone
32 add subrepo clone
33
33
34 $ cd ../t
34 $ cd ../t
35 $ echo 's = [git]../gitroot' > .hgsub
35 $ echo 's = [git]../gitroot' > .hgsub
36 $ git clone -q ../gitroot s
36 $ git clone -q ../gitroot s
37 $ hg add .hgsub
37 $ hg add .hgsub
38 $ hg commit -m 'new git subrepo'
38 $ hg commit -m 'new git subrepo'
39 $ hg debugsub
39 $ hg debugsub
40 path s
40 path s
41 source ../gitroot
41 source ../gitroot
42 revision da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
42 revision da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
43
43
44 record a new commit from upstream from a different branch
44 record a new commit from upstream from a different branch
45
45
46 $ cd ../gitroot
46 $ cd ../gitroot
47 $ git checkout -q -b testing
47 $ git checkout -q -b testing
48 $ echo gg >> g
48 $ echo gg >> g
49 $ git commit -q -a -m gg
49 $ git commit -q -a -m gg
50
50
51 $ cd ../t/s
51 $ cd ../t/s
52 $ git pull -q >/dev/null 2>/dev/null
52 $ git pull -q >/dev/null 2>/dev/null
53 $ git checkout -q -b testing origin/testing >/dev/null
53 $ git checkout -q -b testing origin/testing >/dev/null
54
54
55 $ cd ..
55 $ cd ..
56 $ hg status --subrepos
56 $ hg status --subrepos
57 M s/g
57 M s/g
58 $ hg commit -m 'update git subrepo'
58 $ hg commit -m 'update git subrepo'
59 $ hg debugsub
59 $ hg debugsub
60 path s
60 path s
61 source ../gitroot
61 source ../gitroot
62 revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a
62 revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a
63
63
64 make $GITROOT pushable, by replacing it with a clone with nothing checked out
64 make $GITROOT pushable, by replacing it with a clone with nothing checked out
65
65
66 $ cd ..
66 $ cd ..
67 $ git clone gitroot gitrootbare --bare -q
67 $ git clone gitroot gitrootbare --bare -q
68 $ rm -rf gitroot
68 $ rm -rf gitroot
69 $ mv gitrootbare gitroot
69 $ mv gitrootbare gitroot
70
70
71 clone root
71 clone root
72
72
73 $ cd t
73 $ cd t
74 $ hg clone . ../tc
74 $ hg clone . ../tc
75 updating to branch default
75 updating to branch default
76 cloning subrepo s from $TESTTMP/gitroot
76 cloning subrepo s from $TESTTMP/gitroot
77 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
77 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
78 $ cd ../tc
78 $ cd ../tc
79 $ hg debugsub
79 $ hg debugsub
80 path s
80 path s
81 source ../gitroot
81 source ../gitroot
82 revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a
82 revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a
83
83
84 update to previous substate
84 update to previous substate
85
85
86 $ hg update 1 -q
86 $ hg update 1 -q
87 $ cat s/g
87 $ cat s/g
88 g
88 g
89 $ hg debugsub
89 $ hg debugsub
90 path s
90 path s
91 source ../gitroot
91 source ../gitroot
92 revision da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
92 revision da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
93
93
94 clone root, make local change
94 clone root, make local change
95
95
96 $ cd ../t
96 $ cd ../t
97 $ hg clone . ../ta
97 $ hg clone . ../ta
98 updating to branch default
98 updating to branch default
99 cloning subrepo s from $TESTTMP/gitroot
99 cloning subrepo s from $TESTTMP/gitroot
100 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
100 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
101
101
102 $ cd ../ta
102 $ cd ../ta
103 $ echo ggg >> s/g
103 $ echo ggg >> s/g
104 $ hg status --subrepos
104 $ hg status --subrepos
105 M s/g
105 M s/g
106 $ hg commit --subrepos -m ggg
106 $ hg commit --subrepos -m ggg
107 committing subrepository s
107 committing subrepository s
108 $ hg debugsub
108 $ hg debugsub
109 path s
109 path s
110 source ../gitroot
110 source ../gitroot
111 revision 79695940086840c99328513acbe35f90fcd55e57
111 revision 79695940086840c99328513acbe35f90fcd55e57
112
112
113 clone root separately, make different local change
113 clone root separately, make different local change
114
114
115 $ cd ../t
115 $ cd ../t
116 $ hg clone . ../tb
116 $ hg clone . ../tb
117 updating to branch default
117 updating to branch default
118 cloning subrepo s from $TESTTMP/gitroot
118 cloning subrepo s from $TESTTMP/gitroot
119 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
119 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
120
120
121 $ cd ../tb/s
121 $ cd ../tb/s
122 $ echo f > f
122 $ echo f > f
123 $ git add f
123 $ git add f
124 $ cd ..
124 $ cd ..
125
125
126 $ hg status --subrepos
126 $ hg status --subrepos
127 A s/f
127 A s/f
128 $ hg commit --subrepos -m f
128 $ hg commit --subrepos -m f
129 committing subrepository s
129 committing subrepository s
130 $ hg debugsub
130 $ hg debugsub
131 path s
131 path s
132 source ../gitroot
132 source ../gitroot
133 revision aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
133 revision aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
134
134
135 user b push changes
135 user b push changes
136
136
137 $ hg push 2>/dev/null
137 $ hg push 2>/dev/null
138 pushing to $TESTTMP/t (glob)
138 pushing to $TESTTMP/t (glob)
139 pushing branch testing of subrepo s
139 pushing branch testing of subrepo s
140 searching for changes
140 searching for changes
141 adding changesets
141 adding changesets
142 adding manifests
142 adding manifests
143 adding file changes
143 adding file changes
144 added 1 changesets with 1 changes to 1 files
144 added 1 changesets with 1 changes to 1 files
145
145
146 user a pulls, merges, commits
146 user a pulls, merges, commits
147
147
148 $ cd ../ta
148 $ cd ../ta
149 $ hg pull
149 $ hg pull
150 pulling from $TESTTMP/t (glob)
150 pulling from $TESTTMP/t (glob)
151 searching for changes
151 searching for changes
152 adding changesets
152 adding changesets
153 adding manifests
153 adding manifests
154 adding file changes
154 adding file changes
155 added 1 changesets with 1 changes to 1 files (+1 heads)
155 added 1 changesets with 1 changes to 1 files (+1 heads)
156 (run 'hg heads' to see heads, 'hg merge' to merge)
156 (run 'hg heads' to see heads, 'hg merge' to merge)
157 $ hg merge 2>/dev/null
157 $ hg merge 2>/dev/null
158 subrepository s diverged (local revision: 796959400868, remote revision: aa84837ccfbd)
159 (M)erge, keep (l)ocal or keep (r)emote? m
158 pulling subrepo s from $TESTTMP/gitroot
160 pulling subrepo s from $TESTTMP/gitroot
159 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
161 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
160 (branch merge, don't forget to commit)
162 (branch merge, don't forget to commit)
161 $ cat s/f
163 $ cat s/f
162 f
164 f
163 $ cat s/g
165 $ cat s/g
164 g
166 g
165 gg
167 gg
166 ggg
168 ggg
167 $ hg commit --subrepos -m 'merge'
169 $ hg commit --subrepos -m 'merge'
168 committing subrepository s
170 committing subrepository s
169 $ hg status --subrepos --rev 1:5
171 $ hg status --subrepos --rev 1:5
170 M .hgsubstate
172 M .hgsubstate
171 M s/g
173 M s/g
172 A s/f
174 A s/f
173 $ hg debugsub
175 $ hg debugsub
174 path s
176 path s
175 source ../gitroot
177 source ../gitroot
176 revision f47b465e1bce645dbf37232a00574aa1546ca8d3
178 revision f47b465e1bce645dbf37232a00574aa1546ca8d3
177 $ hg push 2>/dev/null
179 $ hg push 2>/dev/null
178 pushing to $TESTTMP/t (glob)
180 pushing to $TESTTMP/t (glob)
179 pushing branch testing of subrepo s
181 pushing branch testing of subrepo s
180 searching for changes
182 searching for changes
181 adding changesets
183 adding changesets
182 adding manifests
184 adding manifests
183 adding file changes
185 adding file changes
184 added 2 changesets with 2 changes to 1 files
186 added 2 changesets with 2 changes to 1 files
185
187
186 make upstream git changes
188 make upstream git changes
187
189
188 $ cd ..
190 $ cd ..
189 $ git clone -q gitroot gitclone
191 $ git clone -q gitroot gitclone
190 $ cd gitclone
192 $ cd gitclone
191 $ echo ff >> f
193 $ echo ff >> f
192 $ git commit -q -a -m ff
194 $ git commit -q -a -m ff
193 $ echo fff >> f
195 $ echo fff >> f
194 $ git commit -q -a -m fff
196 $ git commit -q -a -m fff
195 $ git push origin testing 2>/dev/null
197 $ git push origin testing 2>/dev/null
196
198
197 make and push changes to hg without updating the subrepo
199 make and push changes to hg without updating the subrepo
198
200
199 $ cd ../t
201 $ cd ../t
200 $ hg clone . ../td
202 $ hg clone . ../td
201 updating to branch default
203 updating to branch default
202 cloning subrepo s from $TESTTMP/gitroot
204 cloning subrepo s from $TESTTMP/gitroot
203 checking out detached HEAD in subrepo s
205 checking out detached HEAD in subrepo s
204 check out a git branch if you intend to make changes
206 check out a git branch if you intend to make changes
205 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
207 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
206 $ cd ../td
208 $ cd ../td
207 $ echo aa >> a
209 $ echo aa >> a
208 $ hg commit -m aa
210 $ hg commit -m aa
209 $ hg push
211 $ hg push
210 pushing to $TESTTMP/t (glob)
212 pushing to $TESTTMP/t (glob)
211 searching for changes
213 searching for changes
212 adding changesets
214 adding changesets
213 adding manifests
215 adding manifests
214 adding file changes
216 adding file changes
215 added 1 changesets with 1 changes to 1 files
217 added 1 changesets with 1 changes to 1 files
216
218
217 sync to upstream git, distribute changes
219 sync to upstream git, distribute changes
218
220
219 $ cd ../ta
221 $ cd ../ta
220 $ hg pull -u -q
222 $ hg pull -u -q
221 $ cd s
223 $ cd s
222 $ git pull -q >/dev/null 2>/dev/null
224 $ git pull -q >/dev/null 2>/dev/null
223 $ cd ..
225 $ cd ..
224 $ hg commit -m 'git upstream sync'
226 $ hg commit -m 'git upstream sync'
225 $ hg debugsub
227 $ hg debugsub
226 path s
228 path s
227 source ../gitroot
229 source ../gitroot
228 revision 32a343883b74769118bb1d3b4b1fbf9156f4dddc
230 revision 32a343883b74769118bb1d3b4b1fbf9156f4dddc
229 $ hg push -q
231 $ hg push -q
230
232
231 $ cd ../tb
233 $ cd ../tb
232 $ hg pull -q
234 $ hg pull -q
233 $ hg update 2>/dev/null
235 $ hg update 2>/dev/null
234 pulling subrepo s from $TESTTMP/gitroot
236 pulling subrepo s from $TESTTMP/gitroot
235 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
237 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
236 $ hg debugsub
238 $ hg debugsub
237 path s
239 path s
238 source ../gitroot
240 source ../gitroot
239 revision 32a343883b74769118bb1d3b4b1fbf9156f4dddc
241 revision 32a343883b74769118bb1d3b4b1fbf9156f4dddc
240
242
241 create a new git branch
243 create a new git branch
242
244
243 $ cd s
245 $ cd s
244 $ git checkout -b b2
246 $ git checkout -b b2
245 Switched to a new branch 'b2'
247 Switched to a new branch 'b2'
246 $ echo a>a
248 $ echo a>a
247 $ git add a
249 $ git add a
248 $ git commit -qm 'add a'
250 $ git commit -qm 'add a'
249 $ cd ..
251 $ cd ..
250 $ hg commit -m 'add branch in s'
252 $ hg commit -m 'add branch in s'
251
253
252 pulling new git branch should not create tracking branch named 'origin/b2'
254 pulling new git branch should not create tracking branch named 'origin/b2'
253 (issue3870)
255 (issue3870)
254 $ cd ../td/s
256 $ cd ../td/s
255 $ git remote set-url origin $TESTTMP/tb/s
257 $ git remote set-url origin $TESTTMP/tb/s
256 $ git branch --no-track oldtesting
258 $ git branch --no-track oldtesting
257 $ cd ..
259 $ cd ..
258 $ hg pull -q ../tb
260 $ hg pull -q ../tb
259 $ hg up
261 $ hg up
260 From $TESTTMP/tb/s
262 From $TESTTMP/tb/s
261 * [new branch] b2 -> origin/b2
263 * [new branch] b2 -> origin/b2
262 Previous HEAD position was f47b465... merge
264 Previous HEAD position was f47b465... merge
263 Switched to a new branch 'b2'
265 Switched to a new branch 'b2'
264 pulling subrepo s from $TESTTMP/tb/s
266 pulling subrepo s from $TESTTMP/tb/s
265 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
267 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
266
268
267 update to a revision without the subrepo, keeping the local git repository
269 update to a revision without the subrepo, keeping the local git repository
268
270
269 $ cd ../t
271 $ cd ../t
270 $ hg up 0
272 $ hg up 0
271 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
273 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
272 $ ls -a s
274 $ ls -a s
273 .
275 .
274 ..
276 ..
275 .git
277 .git
276
278
277 $ hg up 2
279 $ hg up 2
278 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
280 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
279 $ ls -a s
281 $ ls -a s
280 .
282 .
281 ..
283 ..
282 .git
284 .git
283 g
285 g
284
286
285 archive subrepos
287 archive subrepos
286
288
287 $ cd ../tc
289 $ cd ../tc
288 $ hg pull -q
290 $ hg pull -q
289 $ hg archive --subrepos -r 5 ../archive 2>/dev/null
291 $ hg archive --subrepos -r 5 ../archive 2>/dev/null
290 pulling subrepo s from $TESTTMP/gitroot
292 pulling subrepo s from $TESTTMP/gitroot
291 $ cd ../archive
293 $ cd ../archive
292 $ cat s/f
294 $ cat s/f
293 f
295 f
294 $ cat s/g
296 $ cat s/g
295 g
297 g
296 gg
298 gg
297 ggg
299 ggg
298
300
299 $ hg -R ../tc archive --subrepo -r 5 -X ../tc/**f ../archive_x 2>/dev/null
301 $ hg -R ../tc archive --subrepo -r 5 -X ../tc/**f ../archive_x 2>/dev/null
300 $ find ../archive_x | sort | grep -v pax_global_header
302 $ find ../archive_x | sort | grep -v pax_global_header
301 ../archive_x
303 ../archive_x
302 ../archive_x/.hg_archival.txt
304 ../archive_x/.hg_archival.txt
303 ../archive_x/.hgsub
305 ../archive_x/.hgsub
304 ../archive_x/.hgsubstate
306 ../archive_x/.hgsubstate
305 ../archive_x/a
307 ../archive_x/a
306 ../archive_x/s
308 ../archive_x/s
307 ../archive_x/s/g
309 ../archive_x/s/g
308
310
309 create nested repo
311 create nested repo
310
312
311 $ cd ..
313 $ cd ..
312 $ hg init outer
314 $ hg init outer
313 $ cd outer
315 $ cd outer
314 $ echo b>b
316 $ echo b>b
315 $ hg add b
317 $ hg add b
316 $ hg commit -m b
318 $ hg commit -m b
317
319
318 $ hg clone ../t inner
320 $ hg clone ../t inner
319 updating to branch default
321 updating to branch default
320 cloning subrepo s from $TESTTMP/gitroot
322 cloning subrepo s from $TESTTMP/gitroot
321 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
323 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
322 $ echo inner = inner > .hgsub
324 $ echo inner = inner > .hgsub
323 $ hg add .hgsub
325 $ hg add .hgsub
324 $ hg commit -m 'nested sub'
326 $ hg commit -m 'nested sub'
325
327
326 nested commit
328 nested commit
327
329
328 $ echo ffff >> inner/s/f
330 $ echo ffff >> inner/s/f
329 $ hg status --subrepos
331 $ hg status --subrepos
330 M inner/s/f
332 M inner/s/f
331 $ hg commit --subrepos -m nested
333 $ hg commit --subrepos -m nested
332 committing subrepository inner
334 committing subrepository inner
333 committing subrepository inner/s (glob)
335 committing subrepository inner/s (glob)
334
336
335 nested archive
337 nested archive
336
338
337 $ hg archive --subrepos ../narchive
339 $ hg archive --subrepos ../narchive
338 $ ls ../narchive/inner/s | grep -v pax_global_header
340 $ ls ../narchive/inner/s | grep -v pax_global_header
339 f
341 f
340 g
342 g
341
343
342 relative source expansion
344 relative source expansion
343
345
344 $ cd ..
346 $ cd ..
345 $ mkdir d
347 $ mkdir d
346 $ hg clone t d/t
348 $ hg clone t d/t
347 updating to branch default
349 updating to branch default
348 cloning subrepo s from $TESTTMP/gitroot
350 cloning subrepo s from $TESTTMP/gitroot
349 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
351 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
350
352
351 Don't crash if the subrepo is missing
353 Don't crash if the subrepo is missing
352
354
353 $ hg clone t missing -q
355 $ hg clone t missing -q
354 $ cd missing
356 $ cd missing
355 $ rm -rf s
357 $ rm -rf s
356 $ hg status -S
358 $ hg status -S
357 $ hg sum | grep commit
359 $ hg sum | grep commit
358 commit: 1 subrepos
360 commit: 1 subrepos
359 $ hg push -q
361 $ hg push -q
360 abort: subrepo s is missing (in subrepo s)
362 abort: subrepo s is missing (in subrepo s)
361 [255]
363 [255]
362 $ hg commit --subrepos -qm missing
364 $ hg commit --subrepos -qm missing
363 abort: subrepo s is missing (in subrepo s)
365 abort: subrepo s is missing (in subrepo s)
364 [255]
366 [255]
365 $ hg update -C
367 $ hg update -C
366 cloning subrepo s from $TESTTMP/gitroot
368 cloning subrepo s from $TESTTMP/gitroot
367 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
369 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
368 $ hg sum | grep commit
370 $ hg sum | grep commit
369 commit: (clean)
371 commit: (clean)
370
372
371 Don't crash if the .hgsubstate entry is missing
373 Don't crash if the .hgsubstate entry is missing
372
374
373 $ hg update 1 -q
375 $ hg update 1 -q
374 $ hg rm .hgsubstate
376 $ hg rm .hgsubstate
375 $ hg commit .hgsubstate -m 'no substate'
377 $ hg commit .hgsubstate -m 'no substate'
376 nothing changed
378 nothing changed
377 [1]
379 [1]
378 $ hg tag -l nosubstate
380 $ hg tag -l nosubstate
379 $ hg manifest
381 $ hg manifest
380 .hgsub
382 .hgsub
381 .hgsubstate
383 .hgsubstate
382 a
384 a
383
385
384 $ hg status -S
386 $ hg status -S
385 R .hgsubstate
387 R .hgsubstate
386 $ hg sum | grep commit
388 $ hg sum | grep commit
387 commit: 1 removed, 1 subrepos (new branch head)
389 commit: 1 removed, 1 subrepos (new branch head)
388
390
389 $ hg commit -m 'restore substate'
391 $ hg commit -m 'restore substate'
390 nothing changed
392 nothing changed
391 [1]
393 [1]
392 $ hg manifest
394 $ hg manifest
393 .hgsub
395 .hgsub
394 .hgsubstate
396 .hgsubstate
395 a
397 a
396 $ hg sum | grep commit
398 $ hg sum | grep commit
397 commit: 1 removed, 1 subrepos (new branch head)
399 commit: 1 removed, 1 subrepos (new branch head)
398
400
399 $ hg update -qC nosubstate
401 $ hg update -qC nosubstate
400 $ ls s
402 $ ls s
401 g
403 g
402
404
403 issue3109: false positives in git diff-index
405 issue3109: false positives in git diff-index
404
406
405 $ hg update -q
407 $ hg update -q
406 $ touch -t 200001010000 s/g
408 $ touch -t 200001010000 s/g
407 $ hg status --subrepos
409 $ hg status --subrepos
408 $ touch -t 200001010000 s/g
410 $ touch -t 200001010000 s/g
409 $ hg sum | grep commit
411 $ hg sum | grep commit
410 commit: (clean)
412 commit: (clean)
411
413
412 Check hg update --clean
414 Check hg update --clean
413 $ cd $TESTTMP/ta
415 $ cd $TESTTMP/ta
414 $ echo > s/g
416 $ echo > s/g
415 $ cd s
417 $ cd s
416 $ echo c1 > f1
418 $ echo c1 > f1
417 $ echo c1 > f2
419 $ echo c1 > f2
418 $ git add f1
420 $ git add f1
419 $ cd ..
421 $ cd ..
420 $ hg status -S
422 $ hg status -S
421 M s/g
423 M s/g
422 A s/f1
424 A s/f1
423 $ ls s
425 $ ls s
424 f
426 f
425 f1
427 f1
426 f2
428 f2
427 g
429 g
428 $ hg update --clean
430 $ hg update --clean
429 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
431 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
430 $ hg status -S
432 $ hg status -S
431 $ ls s
433 $ ls s
432 f
434 f
433 f1
435 f1
434 f2
436 f2
435 g
437 g
436
438
437 Sticky subrepositories, no changes
439 Sticky subrepositories, no changes
438 $ cd $TESTTMP/ta
440 $ cd $TESTTMP/ta
439 $ hg id -n
441 $ hg id -n
440 7
442 7
441 $ cd s
443 $ cd s
442 $ git rev-parse HEAD
444 $ git rev-parse HEAD
443 32a343883b74769118bb1d3b4b1fbf9156f4dddc
445 32a343883b74769118bb1d3b4b1fbf9156f4dddc
444 $ cd ..
446 $ cd ..
445 $ hg update 1 > /dev/null 2>&1
447 $ hg update 1 > /dev/null 2>&1
446 $ hg id -n
448 $ hg id -n
447 1
449 1
448 $ cd s
450 $ cd s
449 $ git rev-parse HEAD
451 $ git rev-parse HEAD
450 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
452 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
451 $ cd ..
453 $ cd ..
452
454
453 Sticky subrepositorys, file changes
455 Sticky subrepositorys, file changes
454 $ touch s/f1
456 $ touch s/f1
455 $ cd s
457 $ cd s
456 $ git add f1
458 $ git add f1
457 $ cd ..
459 $ cd ..
458 $ hg id -n
460 $ hg id -n
459 1+
461 1+
460 $ cd s
462 $ cd s
461 $ git rev-parse HEAD
463 $ git rev-parse HEAD
462 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
464 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
463 $ cd ..
465 $ cd ..
464 $ hg update 4
466 $ hg update 4
467 subrepository s diverged (local revision: da5f5b1d8ffc, remote revision: aa84837ccfbd)
468 (M)erge, keep (l)ocal or keep (r)emote? m
465 subrepository sources for s differ
469 subrepository sources for s differ
466 use (l)ocal source (da5f5b1) or (r)emote source (aa84837)?
470 use (l)ocal source (da5f5b1) or (r)emote source (aa84837)?
467 l
471 l
468 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
472 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
469 $ hg id -n
473 $ hg id -n
470 4+
474 4+
471 $ cd s
475 $ cd s
472 $ git rev-parse HEAD
476 $ git rev-parse HEAD
473 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
477 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
474 $ cd ..
478 $ cd ..
475 $ hg update --clean tip > /dev/null 2>&1
479 $ hg update --clean tip > /dev/null 2>&1
476
480
477 Sticky subrepository, revision updates
481 Sticky subrepository, revision updates
478 $ hg id -n
482 $ hg id -n
479 7
483 7
480 $ cd s
484 $ cd s
481 $ git rev-parse HEAD
485 $ git rev-parse HEAD
482 32a343883b74769118bb1d3b4b1fbf9156f4dddc
486 32a343883b74769118bb1d3b4b1fbf9156f4dddc
483 $ cd ..
487 $ cd ..
484 $ cd s
488 $ cd s
485 $ git checkout aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
489 $ git checkout aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
486 Previous HEAD position was 32a3438... fff
490 Previous HEAD position was 32a3438... fff
487 HEAD is now at aa84837... f
491 HEAD is now at aa84837... f
488 $ cd ..
492 $ cd ..
489 $ hg update 1
493 $ hg update 1
494 subrepository s diverged (local revision: 32a343883b74, remote revision: da5f5b1d8ffc)
495 (M)erge, keep (l)ocal or keep (r)emote? m
490 subrepository sources for s differ (in checked out version)
496 subrepository sources for s differ (in checked out version)
491 use (l)ocal source (32a3438) or (r)emote source (da5f5b1)?
497 use (l)ocal source (32a3438) or (r)emote source (da5f5b1)?
492 l
498 l
493 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
499 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
494 $ hg id -n
500 $ hg id -n
495 1+
501 1+
496 $ cd s
502 $ cd s
497 $ git rev-parse HEAD
503 $ git rev-parse HEAD
498 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
504 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
499 $ cd ..
505 $ cd ..
500
506
501 Sticky subrepository, file changes and revision updates
507 Sticky subrepository, file changes and revision updates
502 $ touch s/f1
508 $ touch s/f1
503 $ cd s
509 $ cd s
504 $ git add f1
510 $ git add f1
505 $ git rev-parse HEAD
511 $ git rev-parse HEAD
506 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
512 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
507 $ cd ..
513 $ cd ..
508 $ hg id -n
514 $ hg id -n
509 1+
515 1+
510 $ hg update 7
516 $ hg update 7
517 subrepository s diverged (local revision: 32a343883b74, remote revision: 32a343883b74)
518 (M)erge, keep (l)ocal or keep (r)emote? m
511 subrepository sources for s differ
519 subrepository sources for s differ
512 use (l)ocal source (32a3438) or (r)emote source (32a3438)?
520 use (l)ocal source (32a3438) or (r)emote source (32a3438)?
513 l
521 l
514 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
522 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
515 $ hg id -n
523 $ hg id -n
516 7+
524 7+
517 $ cd s
525 $ cd s
518 $ git rev-parse HEAD
526 $ git rev-parse HEAD
519 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
527 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
520 $ cd ..
528 $ cd ..
521
529
522 Sticky repository, update --clean
530 Sticky repository, update --clean
523 $ hg update --clean tip 2>/dev/null
531 $ hg update --clean tip 2>/dev/null
524 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
532 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
525 $ hg id -n
533 $ hg id -n
526 7
534 7
527 $ cd s
535 $ cd s
528 $ git rev-parse HEAD
536 $ git rev-parse HEAD
529 32a343883b74769118bb1d3b4b1fbf9156f4dddc
537 32a343883b74769118bb1d3b4b1fbf9156f4dddc
530 $ cd ..
538 $ cd ..
531
539
532 Test subrepo already at intended revision:
540 Test subrepo already at intended revision:
533 $ cd s
541 $ cd s
534 $ git checkout 32a343883b74769118bb1d3b4b1fbf9156f4dddc
542 $ git checkout 32a343883b74769118bb1d3b4b1fbf9156f4dddc
535 HEAD is now at 32a3438... fff
543 HEAD is now at 32a3438... fff
536 $ cd ..
544 $ cd ..
537 $ hg update 1
545 $ hg update 1
538 Previous HEAD position was 32a3438... fff
546 Previous HEAD position was 32a3438... fff
539 HEAD is now at da5f5b1... g
547 HEAD is now at da5f5b1... g
540 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
548 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
541 $ hg id -n
549 $ hg id -n
542 1
550 1
543 $ cd s
551 $ cd s
544 $ git rev-parse HEAD
552 $ git rev-parse HEAD
545 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
553 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
546 $ cd ..
554 $ cd ..
547
555
548 Test forgetting files, not implemented in git subrepo, used to
556 Test forgetting files, not implemented in git subrepo, used to
549 traceback
557 traceback
550 #if no-windows
558 #if no-windows
551 $ hg forget 'notafile*'
559 $ hg forget 'notafile*'
552 notafile*: No such file or directory
560 notafile*: No such file or directory
553 [1]
561 [1]
554 #else
562 #else
555 $ hg forget 'notafile'
563 $ hg forget 'notafile'
556 notafile: * (glob)
564 notafile: * (glob)
557 [1]
565 [1]
558 #endif
566 #endif
559
567
560 $ cd ..
568 $ cd ..
@@ -1,626 +1,634
1 $ "$TESTDIR/hghave" svn15 || exit 80
1 $ "$TESTDIR/hghave" svn15 || exit 80
2
2
3 $ SVNREPOPATH=`pwd`/svn-repo
3 $ SVNREPOPATH=`pwd`/svn-repo
4 #if windows
4 #if windows
5 $ SVNREPOURL=file:///`python -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
5 $ SVNREPOURL=file:///`python -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
6 #else
6 #else
7 $ SVNREPOURL=file://`python -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
7 $ SVNREPOURL=file://`python -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
8 #endif
8 #endif
9
9
10 create subversion repo
10 create subversion repo
11
11
12 $ WCROOT="`pwd`/svn-wc"
12 $ WCROOT="`pwd`/svn-wc"
13 $ svnadmin create svn-repo
13 $ svnadmin create svn-repo
14 $ svn co "$SVNREPOURL" svn-wc
14 $ svn co "$SVNREPOURL" svn-wc
15 Checked out revision 0.
15 Checked out revision 0.
16 $ cd svn-wc
16 $ cd svn-wc
17 $ mkdir src
17 $ mkdir src
18 $ echo alpha > src/alpha
18 $ echo alpha > src/alpha
19 $ svn add src
19 $ svn add src
20 A src
20 A src
21 A src/alpha (glob)
21 A src/alpha (glob)
22 $ mkdir externals
22 $ mkdir externals
23 $ echo other > externals/other
23 $ echo other > externals/other
24 $ svn add externals
24 $ svn add externals
25 A externals
25 A externals
26 A externals/other (glob)
26 A externals/other (glob)
27 $ svn ci -m 'Add alpha'
27 $ svn ci -m 'Add alpha'
28 Adding externals
28 Adding externals
29 Adding externals/other (glob)
29 Adding externals/other (glob)
30 Adding src
30 Adding src
31 Adding src/alpha (glob)
31 Adding src/alpha (glob)
32 Transmitting file data ..
32 Transmitting file data ..
33 Committed revision 1.
33 Committed revision 1.
34 $ svn up -q
34 $ svn up -q
35 $ echo "externals -r1 $SVNREPOURL/externals" > extdef
35 $ echo "externals -r1 $SVNREPOURL/externals" > extdef
36 $ svn propset -F extdef svn:externals src
36 $ svn propset -F extdef svn:externals src
37 property 'svn:externals' set on 'src'
37 property 'svn:externals' set on 'src'
38 $ svn ci -m 'Setting externals'
38 $ svn ci -m 'Setting externals'
39 Sending src
39 Sending src
40
40
41 Committed revision 2.
41 Committed revision 2.
42 $ cd ..
42 $ cd ..
43
43
44 create hg repo
44 create hg repo
45
45
46 $ mkdir sub
46 $ mkdir sub
47 $ cd sub
47 $ cd sub
48 $ hg init t
48 $ hg init t
49 $ cd t
49 $ cd t
50
50
51 first revision, no sub
51 first revision, no sub
52
52
53 $ echo a > a
53 $ echo a > a
54 $ hg ci -Am0
54 $ hg ci -Am0
55 adding a
55 adding a
56
56
57 add first svn sub with leading whitespaces
57 add first svn sub with leading whitespaces
58
58
59 $ echo "s = [svn] $SVNREPOURL/src" >> .hgsub
59 $ echo "s = [svn] $SVNREPOURL/src" >> .hgsub
60 $ echo "subdir/s = [svn] $SVNREPOURL/src" >> .hgsub
60 $ echo "subdir/s = [svn] $SVNREPOURL/src" >> .hgsub
61 $ svn co --quiet "$SVNREPOURL"/src s
61 $ svn co --quiet "$SVNREPOURL"/src s
62 $ mkdir subdir
62 $ mkdir subdir
63 $ svn co --quiet "$SVNREPOURL"/src subdir/s
63 $ svn co --quiet "$SVNREPOURL"/src subdir/s
64 $ hg add .hgsub
64 $ hg add .hgsub
65 $ hg ci -m1
65 $ hg ci -m1
66
66
67 make sure we avoid empty commits (issue2445)
67 make sure we avoid empty commits (issue2445)
68
68
69 $ hg sum
69 $ hg sum
70 parent: 1:* tip (glob)
70 parent: 1:* tip (glob)
71 1
71 1
72 branch: default
72 branch: default
73 commit: (clean)
73 commit: (clean)
74 update: (current)
74 update: (current)
75 $ hg ci -moops
75 $ hg ci -moops
76 nothing changed
76 nothing changed
77 [1]
77 [1]
78
78
79 debugsub
79 debugsub
80
80
81 $ hg debugsub
81 $ hg debugsub
82 path s
82 path s
83 source file://*/svn-repo/src (glob)
83 source file://*/svn-repo/src (glob)
84 revision 2
84 revision 2
85 path subdir/s
85 path subdir/s
86 source file://*/svn-repo/src (glob)
86 source file://*/svn-repo/src (glob)
87 revision 2
87 revision 2
88
88
89 change file in svn and hg, commit
89 change file in svn and hg, commit
90
90
91 $ echo a >> a
91 $ echo a >> a
92 $ echo alpha >> s/alpha
92 $ echo alpha >> s/alpha
93 $ hg sum
93 $ hg sum
94 parent: 1:* tip (glob)
94 parent: 1:* tip (glob)
95 1
95 1
96 branch: default
96 branch: default
97 commit: 1 modified, 1 subrepos
97 commit: 1 modified, 1 subrepos
98 update: (current)
98 update: (current)
99 $ hg commit --subrepos -m 'Message!' | grep -v Updating
99 $ hg commit --subrepos -m 'Message!' | grep -v Updating
100 committing subrepository s
100 committing subrepository s
101 Sending*s/alpha (glob)
101 Sending*s/alpha (glob)
102 Transmitting file data .
102 Transmitting file data .
103 Committed revision 3.
103 Committed revision 3.
104
104
105 Fetching external item into '*s/externals'* (glob)
105 Fetching external item into '*s/externals'* (glob)
106 External at revision 1.
106 External at revision 1.
107
107
108 At revision 3.
108 At revision 3.
109 $ hg debugsub
109 $ hg debugsub
110 path s
110 path s
111 source file://*/svn-repo/src (glob)
111 source file://*/svn-repo/src (glob)
112 revision 3
112 revision 3
113 path subdir/s
113 path subdir/s
114 source file://*/svn-repo/src (glob)
114 source file://*/svn-repo/src (glob)
115 revision 2
115 revision 2
116
116
117 missing svn file, commit should fail
117 missing svn file, commit should fail
118
118
119 $ rm s/alpha
119 $ rm s/alpha
120 $ hg commit --subrepos -m 'abort on missing file'
120 $ hg commit --subrepos -m 'abort on missing file'
121 committing subrepository s
121 committing subrepository s
122 abort: cannot commit missing svn entries (in subrepo s)
122 abort: cannot commit missing svn entries (in subrepo s)
123 [255]
123 [255]
124 $ svn revert s/alpha > /dev/null
124 $ svn revert s/alpha > /dev/null
125
125
126 add an unrelated revision in svn and update the subrepo to without
126 add an unrelated revision in svn and update the subrepo to without
127 bringing any changes.
127 bringing any changes.
128
128
129 $ svn mkdir "$SVNREPOURL/unrelated" -m 'create unrelated'
129 $ svn mkdir "$SVNREPOURL/unrelated" -m 'create unrelated'
130
130
131 Committed revision 4.
131 Committed revision 4.
132 $ svn up -q s
132 $ svn up -q s
133 $ hg sum
133 $ hg sum
134 parent: 2:* tip (glob)
134 parent: 2:* tip (glob)
135 Message!
135 Message!
136 branch: default
136 branch: default
137 commit: (clean)
137 commit: (clean)
138 update: (current)
138 update: (current)
139
139
140 $ echo a > s/a
140 $ echo a > s/a
141
141
142 should be empty despite change to s/a
142 should be empty despite change to s/a
143
143
144 $ hg st
144 $ hg st
145
145
146 add a commit from svn
146 add a commit from svn
147
147
148 $ cd "$WCROOT/src"
148 $ cd "$WCROOT/src"
149 $ svn up -q
149 $ svn up -q
150 $ echo xyz >> alpha
150 $ echo xyz >> alpha
151 $ svn propset svn:mime-type 'text/xml' alpha
151 $ svn propset svn:mime-type 'text/xml' alpha
152 property 'svn:mime-type' set on 'alpha'
152 property 'svn:mime-type' set on 'alpha'
153 $ svn ci -m 'amend a from svn'
153 $ svn ci -m 'amend a from svn'
154 Sending *alpha (glob)
154 Sending *alpha (glob)
155 Transmitting file data .
155 Transmitting file data .
156 Committed revision 5.
156 Committed revision 5.
157 $ cd ../../sub/t
157 $ cd ../../sub/t
158
158
159 this commit from hg will fail
159 this commit from hg will fail
160
160
161 $ echo zzz >> s/alpha
161 $ echo zzz >> s/alpha
162 $ (hg ci --subrepos -m 'amend alpha from hg' 2>&1; echo "[$?]") | grep -vi 'out of date'
162 $ (hg ci --subrepos -m 'amend alpha from hg' 2>&1; echo "[$?]") | grep -vi 'out of date'
163 committing subrepository s
163 committing subrepository s
164 abort: svn:*Commit failed (details follow): (glob)
164 abort: svn:*Commit failed (details follow): (glob)
165 [255]
165 [255]
166 $ svn revert -q s/alpha
166 $ svn revert -q s/alpha
167
167
168 this commit fails because of meta changes
168 this commit fails because of meta changes
169
169
170 $ svn propset svn:mime-type 'text/html' s/alpha
170 $ svn propset svn:mime-type 'text/html' s/alpha
171 property 'svn:mime-type' set on 's/alpha' (glob)
171 property 'svn:mime-type' set on 's/alpha' (glob)
172 $ (hg ci --subrepos -m 'amend alpha from hg' 2>&1; echo "[$?]") | grep -vi 'out of date'
172 $ (hg ci --subrepos -m 'amend alpha from hg' 2>&1; echo "[$?]") | grep -vi 'out of date'
173 committing subrepository s
173 committing subrepository s
174 abort: svn:*Commit failed (details follow): (glob)
174 abort: svn:*Commit failed (details follow): (glob)
175 [255]
175 [255]
176 $ svn revert -q s/alpha
176 $ svn revert -q s/alpha
177
177
178 this commit fails because of externals changes
178 this commit fails because of externals changes
179
179
180 $ echo zzz > s/externals/other
180 $ echo zzz > s/externals/other
181 $ hg ci --subrepos -m 'amend externals from hg'
181 $ hg ci --subrepos -m 'amend externals from hg'
182 committing subrepository s
182 committing subrepository s
183 abort: cannot commit svn externals (in subrepo s)
183 abort: cannot commit svn externals (in subrepo s)
184 [255]
184 [255]
185 $ hg diff --subrepos -r 1:2 | grep -v diff
185 $ hg diff --subrepos -r 1:2 | grep -v diff
186 --- a/.hgsubstate Thu Jan 01 00:00:00 1970 +0000
186 --- a/.hgsubstate Thu Jan 01 00:00:00 1970 +0000
187 +++ b/.hgsubstate Thu Jan 01 00:00:00 1970 +0000
187 +++ b/.hgsubstate Thu Jan 01 00:00:00 1970 +0000
188 @@ -1,2 +1,2 @@
188 @@ -1,2 +1,2 @@
189 -2 s
189 -2 s
190 +3 s
190 +3 s
191 2 subdir/s
191 2 subdir/s
192 --- a/a Thu Jan 01 00:00:00 1970 +0000
192 --- a/a Thu Jan 01 00:00:00 1970 +0000
193 +++ b/a Thu Jan 01 00:00:00 1970 +0000
193 +++ b/a Thu Jan 01 00:00:00 1970 +0000
194 @@ -1,1 +1,2 @@
194 @@ -1,1 +1,2 @@
195 a
195 a
196 +a
196 +a
197 $ svn revert -q s/externals/other
197 $ svn revert -q s/externals/other
198
198
199 this commit fails because of externals meta changes
199 this commit fails because of externals meta changes
200
200
201 $ svn propset svn:mime-type 'text/html' s/externals/other
201 $ svn propset svn:mime-type 'text/html' s/externals/other
202 property 'svn:mime-type' set on 's/externals/other' (glob)
202 property 'svn:mime-type' set on 's/externals/other' (glob)
203 $ hg ci --subrepos -m 'amend externals from hg'
203 $ hg ci --subrepos -m 'amend externals from hg'
204 committing subrepository s
204 committing subrepository s
205 abort: cannot commit svn externals (in subrepo s)
205 abort: cannot commit svn externals (in subrepo s)
206 [255]
206 [255]
207 $ svn revert -q s/externals/other
207 $ svn revert -q s/externals/other
208
208
209 clone
209 clone
210
210
211 $ cd ..
211 $ cd ..
212 $ hg clone t tc
212 $ hg clone t tc
213 updating to branch default
213 updating to branch default
214 A tc/s/alpha (glob)
214 A tc/s/alpha (glob)
215 U tc/s (glob)
215 U tc/s (glob)
216
216
217 Fetching external item into 'tc/s/externals'* (glob)
217 Fetching external item into 'tc/s/externals'* (glob)
218 A tc/s/externals/other (glob)
218 A tc/s/externals/other (glob)
219 Checked out external at revision 1.
219 Checked out external at revision 1.
220
220
221 Checked out revision 3.
221 Checked out revision 3.
222 A tc/subdir/s/alpha (glob)
222 A tc/subdir/s/alpha (glob)
223 U tc/subdir/s (glob)
223 U tc/subdir/s (glob)
224
224
225 Fetching external item into 'tc/subdir/s/externals'* (glob)
225 Fetching external item into 'tc/subdir/s/externals'* (glob)
226 A tc/subdir/s/externals/other (glob)
226 A tc/subdir/s/externals/other (glob)
227 Checked out external at revision 1.
227 Checked out external at revision 1.
228
228
229 Checked out revision 2.
229 Checked out revision 2.
230 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
230 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
231 $ cd tc
231 $ cd tc
232
232
233 debugsub in clone
233 debugsub in clone
234
234
235 $ hg debugsub
235 $ hg debugsub
236 path s
236 path s
237 source file://*/svn-repo/src (glob)
237 source file://*/svn-repo/src (glob)
238 revision 3
238 revision 3
239 path subdir/s
239 path subdir/s
240 source file://*/svn-repo/src (glob)
240 source file://*/svn-repo/src (glob)
241 revision 2
241 revision 2
242
242
243 verify subrepo is contained within the repo directory
243 verify subrepo is contained within the repo directory
244
244
245 $ python -c "import os.path; print os.path.exists('s')"
245 $ python -c "import os.path; print os.path.exists('s')"
246 True
246 True
247
247
248 update to nullrev (must delete the subrepo)
248 update to nullrev (must delete the subrepo)
249
249
250 $ hg up null
250 $ hg up null
251 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
251 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
252 $ ls
252 $ ls
253
253
254 Check hg update --clean
254 Check hg update --clean
255 $ cd "$TESTTMP/sub/t"
255 $ cd "$TESTTMP/sub/t"
256 $ cd s
256 $ cd s
257 $ echo c0 > alpha
257 $ echo c0 > alpha
258 $ echo c1 > f1
258 $ echo c1 > f1
259 $ echo c1 > f2
259 $ echo c1 > f2
260 $ svn add f1 -q
260 $ svn add f1 -q
261 $ svn status | sort
261 $ svn status | sort
262
262
263 ? * a (glob)
263 ? * a (glob)
264 ? * f2 (glob)
264 ? * f2 (glob)
265 A * f1 (glob)
265 A * f1 (glob)
266 M * alpha (glob)
266 M * alpha (glob)
267 Performing status on external item at 'externals'* (glob)
267 Performing status on external item at 'externals'* (glob)
268 X * externals (glob)
268 X * externals (glob)
269 $ cd ../..
269 $ cd ../..
270 $ hg -R t update -C
270 $ hg -R t update -C
271
271
272 Fetching external item into 't/s/externals'* (glob)
272 Fetching external item into 't/s/externals'* (glob)
273 Checked out external at revision 1.
273 Checked out external at revision 1.
274
274
275 Checked out revision 3.
275 Checked out revision 3.
276 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
276 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
277 $ cd t/s
277 $ cd t/s
278 $ svn status | sort
278 $ svn status | sort
279
279
280 ? * a (glob)
280 ? * a (glob)
281 ? * f1 (glob)
281 ? * f1 (glob)
282 ? * f2 (glob)
282 ? * f2 (glob)
283 Performing status on external item at 'externals'* (glob)
283 Performing status on external item at 'externals'* (glob)
284 X * externals (glob)
284 X * externals (glob)
285
285
286 Sticky subrepositories, no changes
286 Sticky subrepositories, no changes
287 $ cd "$TESTTMP/sub/t"
287 $ cd "$TESTTMP/sub/t"
288 $ hg id -n
288 $ hg id -n
289 2
289 2
290 $ cd s
290 $ cd s
291 $ svnversion
291 $ svnversion
292 3
292 3
293 $ cd ..
293 $ cd ..
294 $ hg update 1
294 $ hg update 1
295 U *s/alpha (glob)
295 U *s/alpha (glob)
296
296
297 Fetching external item into '*s/externals'* (glob)
297 Fetching external item into '*s/externals'* (glob)
298 Checked out external at revision 1.
298 Checked out external at revision 1.
299
299
300 Checked out revision 2.
300 Checked out revision 2.
301 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
301 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
302 $ hg id -n
302 $ hg id -n
303 1
303 1
304 $ cd s
304 $ cd s
305 $ svnversion
305 $ svnversion
306 2
306 2
307 $ cd ..
307 $ cd ..
308
308
309 Sticky subrepositorys, file changes
309 Sticky subrepositorys, file changes
310 $ touch s/f1
310 $ touch s/f1
311 $ cd s
311 $ cd s
312 $ svn add f1
312 $ svn add f1
313 A f1
313 A f1
314 $ cd ..
314 $ cd ..
315 $ hg id -n
315 $ hg id -n
316 1+
316 1+
317 $ cd s
317 $ cd s
318 $ svnversion
318 $ svnversion
319 2M
319 2M
320 $ cd ..
320 $ cd ..
321 $ hg update tip
321 $ hg update tip
322 subrepository s diverged (local revision: 2, remote revision: 3)
323 (M)erge, keep (l)ocal or keep (r)emote? m
322 subrepository sources for s differ
324 subrepository sources for s differ
323 use (l)ocal source (2) or (r)emote source (3)?
325 use (l)ocal source (2) or (r)emote source (3)?
324 l
326 l
325 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
327 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
326 $ hg id -n
328 $ hg id -n
327 2+
329 2+
328 $ cd s
330 $ cd s
329 $ svnversion
331 $ svnversion
330 2M
332 2M
331 $ cd ..
333 $ cd ..
332 $ hg update --clean tip
334 $ hg update --clean tip
333 U *s/alpha (glob)
335 U *s/alpha (glob)
334
336
335 Fetching external item into '*s/externals'* (glob)
337 Fetching external item into '*s/externals'* (glob)
336 Checked out external at revision 1.
338 Checked out external at revision 1.
337
339
338 Checked out revision 3.
340 Checked out revision 3.
339 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
341 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
340
342
341 Sticky subrepository, revision updates
343 Sticky subrepository, revision updates
342 $ hg id -n
344 $ hg id -n
343 2
345 2
344 $ cd s
346 $ cd s
345 $ svnversion
347 $ svnversion
346 3
348 3
347 $ cd ..
349 $ cd ..
348 $ cd s
350 $ cd s
349 $ svn update -qr 1
351 $ svn update -qr 1
350 $ cd ..
352 $ cd ..
351 $ hg update 1
353 $ hg update 1
354 subrepository s diverged (local revision: 3, remote revision: 2)
355 (M)erge, keep (l)ocal or keep (r)emote? m
352 subrepository sources for s differ (in checked out version)
356 subrepository sources for s differ (in checked out version)
353 use (l)ocal source (1) or (r)emote source (2)?
357 use (l)ocal source (1) or (r)emote source (2)?
354 l
358 l
355 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
359 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
356 $ hg id -n
360 $ hg id -n
357 1+
361 1+
358 $ cd s
362 $ cd s
359 $ svnversion
363 $ svnversion
360 1
364 1
361 $ cd ..
365 $ cd ..
362
366
363 Sticky subrepository, file changes and revision updates
367 Sticky subrepository, file changes and revision updates
364 $ touch s/f1
368 $ touch s/f1
365 $ cd s
369 $ cd s
366 $ svn add f1
370 $ svn add f1
367 A f1
371 A f1
368 $ svnversion
372 $ svnversion
369 1M
373 1M
370 $ cd ..
374 $ cd ..
371 $ hg id -n
375 $ hg id -n
372 1+
376 1+
373 $ hg update tip
377 $ hg update tip
378 subrepository s diverged (local revision: 3, remote revision: 3)
379 (M)erge, keep (l)ocal or keep (r)emote? m
374 subrepository sources for s differ
380 subrepository sources for s differ
375 use (l)ocal source (1) or (r)emote source (3)?
381 use (l)ocal source (1) or (r)emote source (3)?
376 l
382 l
377 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
383 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
378 $ hg id -n
384 $ hg id -n
379 2+
385 2+
380 $ cd s
386 $ cd s
381 $ svnversion
387 $ svnversion
382 1M
388 1M
383 $ cd ..
389 $ cd ..
384
390
385 Sticky repository, update --clean
391 Sticky repository, update --clean
386 $ hg update --clean tip | grep -v 's[/\]externals[/\]other'
392 $ hg update --clean tip | grep -v 's[/\]externals[/\]other'
387 U *s/alpha (glob)
393 U *s/alpha (glob)
388 U *s (glob)
394 U *s (glob)
389
395
390 Fetching external item into '*s/externals'* (glob)
396 Fetching external item into '*s/externals'* (glob)
391 Checked out external at revision 1.
397 Checked out external at revision 1.
392
398
393 Checked out revision 3.
399 Checked out revision 3.
394 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
400 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
395 $ hg id -n
401 $ hg id -n
396 2
402 2
397 $ cd s
403 $ cd s
398 $ svnversion
404 $ svnversion
399 3
405 3
400 $ cd ..
406 $ cd ..
401
407
402 Test subrepo already at intended revision:
408 Test subrepo already at intended revision:
403 $ cd s
409 $ cd s
404 $ svn update -qr 2
410 $ svn update -qr 2
405 $ cd ..
411 $ cd ..
406 $ hg update 1
412 $ hg update 1
413 subrepository s diverged (local revision: 3, remote revision: 2)
414 (M)erge, keep (l)ocal or keep (r)emote? m
407 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
415 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
408 $ hg id -n
416 $ hg id -n
409 1+
417 1+
410 $ cd s
418 $ cd s
411 $ svnversion
419 $ svnversion
412 2
420 2
413 $ cd ..
421 $ cd ..
414
422
415 Test case where subversion would fail to update the subrepo because there
423 Test case where subversion would fail to update the subrepo because there
416 are unknown directories being replaced by tracked ones (happens with rebase).
424 are unknown directories being replaced by tracked ones (happens with rebase).
417
425
418 $ cd "$WCROOT/src"
426 $ cd "$WCROOT/src"
419 $ mkdir dir
427 $ mkdir dir
420 $ echo epsilon.py > dir/epsilon.py
428 $ echo epsilon.py > dir/epsilon.py
421 $ svn add dir
429 $ svn add dir
422 A dir
430 A dir
423 A dir/epsilon.py (glob)
431 A dir/epsilon.py (glob)
424 $ svn ci -m 'Add dir/epsilon.py'
432 $ svn ci -m 'Add dir/epsilon.py'
425 Adding *dir (glob)
433 Adding *dir (glob)
426 Adding *dir/epsilon.py (glob)
434 Adding *dir/epsilon.py (glob)
427 Transmitting file data .
435 Transmitting file data .
428 Committed revision 6.
436 Committed revision 6.
429 $ cd ../..
437 $ cd ../..
430 $ hg init rebaserepo
438 $ hg init rebaserepo
431 $ cd rebaserepo
439 $ cd rebaserepo
432 $ svn co -r5 --quiet "$SVNREPOURL"/src s
440 $ svn co -r5 --quiet "$SVNREPOURL"/src s
433 $ echo "s = [svn] $SVNREPOURL/src" >> .hgsub
441 $ echo "s = [svn] $SVNREPOURL/src" >> .hgsub
434 $ hg add .hgsub
442 $ hg add .hgsub
435 $ hg ci -m addsub
443 $ hg ci -m addsub
436 $ echo a > a
444 $ echo a > a
437 $ hg ci -Am adda
445 $ hg ci -Am adda
438 adding a
446 adding a
439 $ hg up 0
447 $ hg up 0
440 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
448 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
441 $ svn up -qr6 s
449 $ svn up -qr6 s
442 $ hg ci -m updatesub
450 $ hg ci -m updatesub
443 created new head
451 created new head
444 $ echo pyc > s/dir/epsilon.pyc
452 $ echo pyc > s/dir/epsilon.pyc
445 $ hg up 1
453 $ hg up 1
446 D *s/dir (glob)
454 D *s/dir (glob)
447
455
448 Fetching external item into '*s/externals'* (glob)
456 Fetching external item into '*s/externals'* (glob)
449 Checked out external at revision 1.
457 Checked out external at revision 1.
450
458
451 Checked out revision 5.
459 Checked out revision 5.
452 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
460 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
453 $ hg up -q 2
461 $ hg up -q 2
454
462
455 Modify one of the externals to point to a different path so we can
463 Modify one of the externals to point to a different path so we can
456 test having obstructions when switching branches on checkout:
464 test having obstructions when switching branches on checkout:
457 $ hg checkout tip
465 $ hg checkout tip
458 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
466 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
459 $ echo "obstruct = [svn] $SVNREPOURL/externals" >> .hgsub
467 $ echo "obstruct = [svn] $SVNREPOURL/externals" >> .hgsub
460 $ svn co -r5 --quiet "$SVNREPOURL"/externals obstruct
468 $ svn co -r5 --quiet "$SVNREPOURL"/externals obstruct
461 $ hg commit -m 'Start making obstructed working copy'
469 $ hg commit -m 'Start making obstructed working copy'
462 $ hg book other
470 $ hg book other
463 $ hg co -r 'p1(tip)'
471 $ hg co -r 'p1(tip)'
464 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
472 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
465 $ echo "obstruct = [svn] $SVNREPOURL/src" >> .hgsub
473 $ echo "obstruct = [svn] $SVNREPOURL/src" >> .hgsub
466 $ svn co -r5 --quiet "$SVNREPOURL"/src obstruct
474 $ svn co -r5 --quiet "$SVNREPOURL"/src obstruct
467 $ hg commit -m 'Other branch which will be obstructed'
475 $ hg commit -m 'Other branch which will be obstructed'
468 created new head
476 created new head
469
477
470 Switching back to the head where we have another path mapped to the
478 Switching back to the head where we have another path mapped to the
471 same subrepo should work if the subrepo is clean.
479 same subrepo should work if the subrepo is clean.
472 $ hg co other
480 $ hg co other
473 A *obstruct/other (glob)
481 A *obstruct/other (glob)
474 Checked out revision 1.
482 Checked out revision 1.
475 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
483 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
476
484
477 This is surprising, but is also correct based on the current code:
485 This is surprising, but is also correct based on the current code:
478 $ echo "updating should (maybe) fail" > obstruct/other
486 $ echo "updating should (maybe) fail" > obstruct/other
479 $ hg co tip
487 $ hg co tip
480 abort: uncommitted changes
488 abort: uncommitted changes
481 (commit or update --clean to discard changes)
489 (commit or update --clean to discard changes)
482 [255]
490 [255]
483
491
484 Point to a Subversion branch which has since been deleted and recreated
492 Point to a Subversion branch which has since been deleted and recreated
485 First, create that condition in the repository.
493 First, create that condition in the repository.
486
494
487 $ hg ci --subrepos -m cleanup | grep -v Updating
495 $ hg ci --subrepos -m cleanup | grep -v Updating
488 committing subrepository obstruct
496 committing subrepository obstruct
489 Sending obstruct/other (glob)
497 Sending obstruct/other (glob)
490 Transmitting file data .
498 Transmitting file data .
491 Committed revision 7.
499 Committed revision 7.
492 At revision 7.
500 At revision 7.
493 $ svn mkdir -m "baseline" $SVNREPOURL/trunk
501 $ svn mkdir -m "baseline" $SVNREPOURL/trunk
494
502
495 Committed revision 8.
503 Committed revision 8.
496 $ svn copy -m "initial branch" $SVNREPOURL/trunk $SVNREPOURL/branch
504 $ svn copy -m "initial branch" $SVNREPOURL/trunk $SVNREPOURL/branch
497
505
498 Committed revision 9.
506 Committed revision 9.
499 $ svn co --quiet "$SVNREPOURL"/branch tempwc
507 $ svn co --quiet "$SVNREPOURL"/branch tempwc
500 $ cd tempwc
508 $ cd tempwc
501 $ echo "something old" > somethingold
509 $ echo "something old" > somethingold
502 $ svn add somethingold
510 $ svn add somethingold
503 A somethingold
511 A somethingold
504 $ svn ci -m 'Something old'
512 $ svn ci -m 'Something old'
505 Adding somethingold
513 Adding somethingold
506 Transmitting file data .
514 Transmitting file data .
507 Committed revision 10.
515 Committed revision 10.
508 $ svn rm -m "remove branch" $SVNREPOURL/branch
516 $ svn rm -m "remove branch" $SVNREPOURL/branch
509
517
510 Committed revision 11.
518 Committed revision 11.
511 $ svn copy -m "recreate branch" $SVNREPOURL/trunk $SVNREPOURL/branch
519 $ svn copy -m "recreate branch" $SVNREPOURL/trunk $SVNREPOURL/branch
512
520
513 Committed revision 12.
521 Committed revision 12.
514 $ svn up -q
522 $ svn up -q
515 $ echo "something new" > somethingnew
523 $ echo "something new" > somethingnew
516 $ svn add somethingnew
524 $ svn add somethingnew
517 A somethingnew
525 A somethingnew
518 $ svn ci -m 'Something new'
526 $ svn ci -m 'Something new'
519 Adding somethingnew
527 Adding somethingnew
520 Transmitting file data .
528 Transmitting file data .
521 Committed revision 13.
529 Committed revision 13.
522 $ cd ..
530 $ cd ..
523 $ rm -rf tempwc
531 $ rm -rf tempwc
524 $ svn co "$SVNREPOURL/branch"@10 recreated
532 $ svn co "$SVNREPOURL/branch"@10 recreated
525 A recreated/somethingold (glob)
533 A recreated/somethingold (glob)
526 Checked out revision 10.
534 Checked out revision 10.
527 $ echo "recreated = [svn] $SVNREPOURL/branch" >> .hgsub
535 $ echo "recreated = [svn] $SVNREPOURL/branch" >> .hgsub
528 $ hg ci -m addsub
536 $ hg ci -m addsub
529 $ cd recreated
537 $ cd recreated
530 $ svn up -q
538 $ svn up -q
531 $ cd ..
539 $ cd ..
532 $ hg ci -m updatesub
540 $ hg ci -m updatesub
533 $ hg up -r-2
541 $ hg up -r-2
534 D *recreated/somethingnew (glob)
542 D *recreated/somethingnew (glob)
535 A *recreated/somethingold (glob)
543 A *recreated/somethingold (glob)
536 Checked out revision 10.
544 Checked out revision 10.
537 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
545 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
538 $ test -f recreated/somethingold
546 $ test -f recreated/somethingold
539
547
540 Test archive
548 Test archive
541
549
542 $ hg archive -S ../archive-all --debug
550 $ hg archive -S ../archive-all --debug
543 archiving: 0/2 files (0.00%)
551 archiving: 0/2 files (0.00%)
544 archiving: .hgsub 1/2 files (50.00%)
552 archiving: .hgsub 1/2 files (50.00%)
545 archiving: .hgsubstate 2/2 files (100.00%)
553 archiving: .hgsubstate 2/2 files (100.00%)
546 archiving (obstruct): 0/1 files (0.00%)
554 archiving (obstruct): 0/1 files (0.00%)
547 archiving (obstruct): 1/1 files (100.00%)
555 archiving (obstruct): 1/1 files (100.00%)
548 archiving (recreated): 0/1 files (0.00%)
556 archiving (recreated): 0/1 files (0.00%)
549 archiving (recreated): 1/1 files (100.00%)
557 archiving (recreated): 1/1 files (100.00%)
550 archiving (s): 0/2 files (0.00%)
558 archiving (s): 0/2 files (0.00%)
551 archiving (s): 1/2 files (50.00%)
559 archiving (s): 1/2 files (50.00%)
552 archiving (s): 2/2 files (100.00%)
560 archiving (s): 2/2 files (100.00%)
553
561
554 $ hg archive -S ../archive-exclude --debug -X **old
562 $ hg archive -S ../archive-exclude --debug -X **old
555 archiving: 0/2 files (0.00%)
563 archiving: 0/2 files (0.00%)
556 archiving: .hgsub 1/2 files (50.00%)
564 archiving: .hgsub 1/2 files (50.00%)
557 archiving: .hgsubstate 2/2 files (100.00%)
565 archiving: .hgsubstate 2/2 files (100.00%)
558 archiving (obstruct): 0/1 files (0.00%)
566 archiving (obstruct): 0/1 files (0.00%)
559 archiving (obstruct): 1/1 files (100.00%)
567 archiving (obstruct): 1/1 files (100.00%)
560 archiving (recreated): 0 files
568 archiving (recreated): 0 files
561 archiving (s): 0/2 files (0.00%)
569 archiving (s): 0/2 files (0.00%)
562 archiving (s): 1/2 files (50.00%)
570 archiving (s): 1/2 files (50.00%)
563 archiving (s): 2/2 files (100.00%)
571 archiving (s): 2/2 files (100.00%)
564 $ find ../archive-exclude | sort
572 $ find ../archive-exclude | sort
565 ../archive-exclude
573 ../archive-exclude
566 ../archive-exclude/.hg_archival.txt
574 ../archive-exclude/.hg_archival.txt
567 ../archive-exclude/.hgsub
575 ../archive-exclude/.hgsub
568 ../archive-exclude/.hgsubstate
576 ../archive-exclude/.hgsubstate
569 ../archive-exclude/obstruct
577 ../archive-exclude/obstruct
570 ../archive-exclude/obstruct/other
578 ../archive-exclude/obstruct/other
571 ../archive-exclude/s
579 ../archive-exclude/s
572 ../archive-exclude/s/alpha
580 ../archive-exclude/s/alpha
573 ../archive-exclude/s/dir
581 ../archive-exclude/s/dir
574 ../archive-exclude/s/dir/epsilon.py
582 ../archive-exclude/s/dir/epsilon.py
575
583
576 Test forgetting files, not implemented in svn subrepo, used to
584 Test forgetting files, not implemented in svn subrepo, used to
577 traceback
585 traceback
578
586
579 #if no-windows
587 #if no-windows
580 $ hg forget 'notafile*'
588 $ hg forget 'notafile*'
581 notafile*: No such file or directory
589 notafile*: No such file or directory
582 [1]
590 [1]
583 #else
591 #else
584 $ hg forget 'notafile'
592 $ hg forget 'notafile'
585 notafile: * (glob)
593 notafile: * (glob)
586 [1]
594 [1]
587 #endif
595 #endif
588
596
589 Test a subrepo referencing a just moved svn path. Last commit rev will
597 Test a subrepo referencing a just moved svn path. Last commit rev will
590 be different from the revision, and the path will be different as
598 be different from the revision, and the path will be different as
591 well.
599 well.
592
600
593 $ cd "$WCROOT"
601 $ cd "$WCROOT"
594 $ svn up > /dev/null
602 $ svn up > /dev/null
595 $ mkdir trunk/subdir branches
603 $ mkdir trunk/subdir branches
596 $ echo a > trunk/subdir/a
604 $ echo a > trunk/subdir/a
597 $ svn add trunk/subdir branches
605 $ svn add trunk/subdir branches
598 A trunk/subdir (glob)
606 A trunk/subdir (glob)
599 A trunk/subdir/a (glob)
607 A trunk/subdir/a (glob)
600 A branches
608 A branches
601 $ svn ci -m addsubdir
609 $ svn ci -m addsubdir
602 Adding branches
610 Adding branches
603 Adding trunk/subdir (glob)
611 Adding trunk/subdir (glob)
604 Adding trunk/subdir/a (glob)
612 Adding trunk/subdir/a (glob)
605 Transmitting file data .
613 Transmitting file data .
606 Committed revision 14.
614 Committed revision 14.
607 $ svn cp -m branchtrunk $SVNREPOURL/trunk $SVNREPOURL/branches/somebranch
615 $ svn cp -m branchtrunk $SVNREPOURL/trunk $SVNREPOURL/branches/somebranch
608
616
609 Committed revision 15.
617 Committed revision 15.
610 $ cd ..
618 $ cd ..
611
619
612 $ hg init repo2
620 $ hg init repo2
613 $ cd repo2
621 $ cd repo2
614 $ svn co $SVNREPOURL/branches/somebranch/subdir
622 $ svn co $SVNREPOURL/branches/somebranch/subdir
615 A subdir/a (glob)
623 A subdir/a (glob)
616 Checked out revision 15.
624 Checked out revision 15.
617 $ echo "subdir = [svn] $SVNREPOURL/branches/somebranch/subdir" > .hgsub
625 $ echo "subdir = [svn] $SVNREPOURL/branches/somebranch/subdir" > .hgsub
618 $ hg add .hgsub
626 $ hg add .hgsub
619 $ hg ci -m addsub
627 $ hg ci -m addsub
620 $ hg up null
628 $ hg up null
621 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
629 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
622 $ hg up
630 $ hg up
623 A *subdir/a (glob)
631 A *subdir/a (glob)
624 Checked out revision 15.
632 Checked out revision 15.
625 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
633 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
626 $ cd ..
634 $ cd ..
@@ -1,1216 +1,1235
1 Let commit recurse into subrepos by default to match pre-2.0 behavior:
1 Let commit recurse into subrepos by default to match pre-2.0 behavior:
2
2
3 $ echo "[ui]" >> $HGRCPATH
3 $ echo "[ui]" >> $HGRCPATH
4 $ echo "commitsubrepos = Yes" >> $HGRCPATH
4 $ echo "commitsubrepos = Yes" >> $HGRCPATH
5
5
6 $ hg init t
6 $ hg init t
7 $ cd t
7 $ cd t
8
8
9 first revision, no sub
9 first revision, no sub
10
10
11 $ echo a > a
11 $ echo a > a
12 $ hg ci -Am0
12 $ hg ci -Am0
13 adding a
13 adding a
14
14
15 add first sub
15 add first sub
16
16
17 $ echo s = s > .hgsub
17 $ echo s = s > .hgsub
18 $ hg add .hgsub
18 $ hg add .hgsub
19 $ hg init s
19 $ hg init s
20 $ echo a > s/a
20 $ echo a > s/a
21
21
22 Issue2232: committing a subrepo without .hgsub
22 Issue2232: committing a subrepo without .hgsub
23
23
24 $ hg ci -mbad s
24 $ hg ci -mbad s
25 abort: can't commit subrepos without .hgsub
25 abort: can't commit subrepos without .hgsub
26 [255]
26 [255]
27
27
28 $ hg -R s ci -Ams0
28 $ hg -R s ci -Ams0
29 adding a
29 adding a
30 $ hg sum
30 $ hg sum
31 parent: 0:f7b1eb17ad24 tip
31 parent: 0:f7b1eb17ad24 tip
32 0
32 0
33 branch: default
33 branch: default
34 commit: 1 added, 1 subrepos
34 commit: 1 added, 1 subrepos
35 update: (current)
35 update: (current)
36 $ hg ci -m1
36 $ hg ci -m1
37
37
38 Revert subrepo and test subrepo fileset keyword:
38 Revert subrepo and test subrepo fileset keyword:
39
39
40 $ echo b > s/a
40 $ echo b > s/a
41 $ hg revert "set:subrepo('glob:s*')"
41 $ hg revert "set:subrepo('glob:s*')"
42 reverting subrepo s
42 reverting subrepo s
43 reverting s/a (glob)
43 reverting s/a (glob)
44 $ rm s/a.orig
44 $ rm s/a.orig
45
45
46 Revert subrepo with no backup. The "reverting s/a" line is gone since
46 Revert subrepo with no backup. The "reverting s/a" line is gone since
47 we're really running 'hg update' in the subrepo:
47 we're really running 'hg update' in the subrepo:
48
48
49 $ echo b > s/a
49 $ echo b > s/a
50 $ hg revert --no-backup s
50 $ hg revert --no-backup s
51 reverting subrepo s
51 reverting subrepo s
52
52
53 Issue2022: update -C
53 Issue2022: update -C
54
54
55 $ echo b > s/a
55 $ echo b > s/a
56 $ hg sum
56 $ hg sum
57 parent: 1:7cf8cfea66e4 tip
57 parent: 1:7cf8cfea66e4 tip
58 1
58 1
59 branch: default
59 branch: default
60 commit: 1 subrepos
60 commit: 1 subrepos
61 update: (current)
61 update: (current)
62 $ hg co -C 1
62 $ hg co -C 1
63 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
63 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
64 $ hg sum
64 $ hg sum
65 parent: 1:7cf8cfea66e4 tip
65 parent: 1:7cf8cfea66e4 tip
66 1
66 1
67 branch: default
67 branch: default
68 commit: (clean)
68 commit: (clean)
69 update: (current)
69 update: (current)
70
70
71 commands that require a clean repo should respect subrepos
71 commands that require a clean repo should respect subrepos
72
72
73 $ echo b >> s/a
73 $ echo b >> s/a
74 $ hg backout tip
74 $ hg backout tip
75 abort: uncommitted changes in subrepo s
75 abort: uncommitted changes in subrepo s
76 [255]
76 [255]
77 $ hg revert -C -R s s/a
77 $ hg revert -C -R s s/a
78
78
79 add sub sub
79 add sub sub
80
80
81 $ echo ss = ss > s/.hgsub
81 $ echo ss = ss > s/.hgsub
82 $ hg init s/ss
82 $ hg init s/ss
83 $ echo a > s/ss/a
83 $ echo a > s/ss/a
84 $ hg -R s add s/.hgsub
84 $ hg -R s add s/.hgsub
85 $ hg -R s/ss add s/ss/a
85 $ hg -R s/ss add s/ss/a
86 $ hg sum
86 $ hg sum
87 parent: 1:7cf8cfea66e4 tip
87 parent: 1:7cf8cfea66e4 tip
88 1
88 1
89 branch: default
89 branch: default
90 commit: 1 subrepos
90 commit: 1 subrepos
91 update: (current)
91 update: (current)
92 $ hg ci -m2
92 $ hg ci -m2
93 committing subrepository s
93 committing subrepository s
94 committing subrepository s/ss (glob)
94 committing subrepository s/ss (glob)
95 $ hg sum
95 $ hg sum
96 parent: 2:df30734270ae tip
96 parent: 2:df30734270ae tip
97 2
97 2
98 branch: default
98 branch: default
99 commit: (clean)
99 commit: (clean)
100 update: (current)
100 update: (current)
101
101
102 bump sub rev (and check it is ignored by ui.commitsubrepos)
102 bump sub rev (and check it is ignored by ui.commitsubrepos)
103
103
104 $ echo b > s/a
104 $ echo b > s/a
105 $ hg -R s ci -ms1
105 $ hg -R s ci -ms1
106 $ hg --config ui.commitsubrepos=no ci -m3
106 $ hg --config ui.commitsubrepos=no ci -m3
107
107
108 leave sub dirty (and check ui.commitsubrepos=no aborts the commit)
108 leave sub dirty (and check ui.commitsubrepos=no aborts the commit)
109
109
110 $ echo c > s/a
110 $ echo c > s/a
111 $ hg --config ui.commitsubrepos=no ci -m4
111 $ hg --config ui.commitsubrepos=no ci -m4
112 abort: uncommitted changes in subrepo s
112 abort: uncommitted changes in subrepo s
113 (use --subrepos for recursive commit)
113 (use --subrepos for recursive commit)
114 [255]
114 [255]
115 $ hg id
115 $ hg id
116 f6affe3fbfaa+ tip
116 f6affe3fbfaa+ tip
117 $ hg -R s ci -mc
117 $ hg -R s ci -mc
118 $ hg id
118 $ hg id
119 f6affe3fbfaa+ tip
119 f6affe3fbfaa+ tip
120 $ echo d > s/a
120 $ echo d > s/a
121 $ hg ci -m4
121 $ hg ci -m4
122 committing subrepository s
122 committing subrepository s
123 $ hg tip -R s
123 $ hg tip -R s
124 changeset: 4:02dcf1d70411
124 changeset: 4:02dcf1d70411
125 tag: tip
125 tag: tip
126 user: test
126 user: test
127 date: Thu Jan 01 00:00:00 1970 +0000
127 date: Thu Jan 01 00:00:00 1970 +0000
128 summary: 4
128 summary: 4
129
129
130
130
131 check caching
131 check caching
132
132
133 $ hg co 0
133 $ hg co 0
134 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
134 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
135 $ hg debugsub
135 $ hg debugsub
136
136
137 restore
137 restore
138
138
139 $ hg co
139 $ hg co
140 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
140 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 $ hg debugsub
141 $ hg debugsub
142 path s
142 path s
143 source s
143 source s
144 revision 02dcf1d704118aee3ee306ccfa1910850d5b05ef
144 revision 02dcf1d704118aee3ee306ccfa1910850d5b05ef
145
145
146 new branch for merge tests
146 new branch for merge tests
147
147
148 $ hg co 1
148 $ hg co 1
149 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
149 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
150 $ echo t = t >> .hgsub
150 $ echo t = t >> .hgsub
151 $ hg init t
151 $ hg init t
152 $ echo t > t/t
152 $ echo t > t/t
153 $ hg -R t add t
153 $ hg -R t add t
154 adding t/t (glob)
154 adding t/t (glob)
155
155
156 5
156 5
157
157
158 $ hg ci -m5 # add sub
158 $ hg ci -m5 # add sub
159 committing subrepository t
159 committing subrepository t
160 created new head
160 created new head
161 $ echo t2 > t/t
161 $ echo t2 > t/t
162
162
163 6
163 6
164
164
165 $ hg st -R s
165 $ hg st -R s
166 $ hg ci -m6 # change sub
166 $ hg ci -m6 # change sub
167 committing subrepository t
167 committing subrepository t
168 $ hg debugsub
168 $ hg debugsub
169 path s
169 path s
170 source s
170 source s
171 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
171 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
172 path t
172 path t
173 source t
173 source t
174 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
174 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
175 $ echo t3 > t/t
175 $ echo t3 > t/t
176
176
177 7
177 7
178
178
179 $ hg ci -m7 # change sub again for conflict test
179 $ hg ci -m7 # change sub again for conflict test
180 committing subrepository t
180 committing subrepository t
181 $ hg rm .hgsub
181 $ hg rm .hgsub
182
182
183 8
183 8
184
184
185 $ hg ci -m8 # remove sub
185 $ hg ci -m8 # remove sub
186
186
187 merge tests
187 merge tests
188
188
189 $ hg co -C 3
189 $ hg co -C 3
190 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
191 $ hg merge 5 # test adding
191 $ hg merge 5 # test adding
192 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
192 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
193 (branch merge, don't forget to commit)
193 (branch merge, don't forget to commit)
194 $ hg debugsub
194 $ hg debugsub
195 path s
195 path s
196 source s
196 source s
197 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
197 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
198 path t
198 path t
199 source t
199 source t
200 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
200 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
201 $ hg ci -m9
201 $ hg ci -m9
202 created new head
202 created new head
203 $ hg merge 6 --debug # test change
203 $ hg merge 6 --debug # test change
204 searching for copies back to rev 2
204 searching for copies back to rev 2
205 resolving manifests
205 resolving manifests
206 branchmerge: True, force: False, partial: False
206 branchmerge: True, force: False, partial: False
207 ancestor: 1f14a2e2d3ec, local: f0d2028bf86d+, remote: 1831e14459c4
207 ancestor: 1f14a2e2d3ec, local: f0d2028bf86d+, remote: 1831e14459c4
208 .hgsubstate: versions differ -> m
208 .hgsubstate: versions differ -> m
209 updating: .hgsubstate 1/1 files (100.00%)
209 updating: .hgsubstate 1/1 files (100.00%)
210 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
210 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
211 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
211 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
212 getting subrepo t
212 getting subrepo t
213 resolving manifests
213 resolving manifests
214 branchmerge: False, force: False, partial: False
214 branchmerge: False, force: False, partial: False
215 ancestor: 60ca1237c194, local: 60ca1237c194+, remote: 6747d179aa9a
215 ancestor: 60ca1237c194, local: 60ca1237c194+, remote: 6747d179aa9a
216 t: remote is newer -> g
216 t: remote is newer -> g
217 getting t
217 getting t
218 updating: t 1/1 files (100.00%)
218 updating: t 1/1 files (100.00%)
219 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
219 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
220 (branch merge, don't forget to commit)
220 (branch merge, don't forget to commit)
221 $ hg debugsub
221 $ hg debugsub
222 path s
222 path s
223 source s
223 source s
224 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
224 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
225 path t
225 path t
226 source t
226 source t
227 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
227 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
228 $ echo conflict > t/t
228 $ echo conflict > t/t
229 $ hg ci -m10
229 $ hg ci -m10
230 committing subrepository t
230 committing subrepository t
231 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
231 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
232 searching for copies back to rev 2
232 searching for copies back to rev 2
233 resolving manifests
233 resolving manifests
234 branchmerge: True, force: False, partial: False
234 branchmerge: True, force: False, partial: False
235 ancestor: 1831e14459c4, local: e45c8b14af55+, remote: f94576341bcf
235 ancestor: 1831e14459c4, local: e45c8b14af55+, remote: f94576341bcf
236 .hgsubstate: versions differ -> m
236 .hgsubstate: versions differ -> m
237 updating: .hgsubstate 1/1 files (100.00%)
237 updating: .hgsubstate 1/1 files (100.00%)
238 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
238 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
239 subrepo t: both sides changed, merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
239 subrepo t: both sides changed
240 subrepository t diverged (local revision: 20a0db6fbf6c, remote revision: 7af322bc1198)
241 (M)erge, keep (l)ocal or keep (r)emote? m
240 merging subrepo t
242 merging subrepo t
241 searching for copies back to rev 2
243 searching for copies back to rev 2
242 resolving manifests
244 resolving manifests
243 branchmerge: True, force: False, partial: False
245 branchmerge: True, force: False, partial: False
244 ancestor: 6747d179aa9a, local: 20a0db6fbf6c+, remote: 7af322bc1198
246 ancestor: 6747d179aa9a, local: 20a0db6fbf6c+, remote: 7af322bc1198
245 t: versions differ -> m
247 t: versions differ -> m
246 preserving t for resolve of t
248 preserving t for resolve of t
247 updating: t 1/1 files (100.00%)
249 updating: t 1/1 files (100.00%)
248 picked tool 'internal:merge' for t (binary False symlink False)
250 picked tool 'internal:merge' for t (binary False symlink False)
249 merging t
251 merging t
250 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
252 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
251 warning: conflicts during merge.
253 warning: conflicts during merge.
252 merging t incomplete! (edit conflicts, then use 'hg resolve --mark')
254 merging t incomplete! (edit conflicts, then use 'hg resolve --mark')
253 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
255 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
254 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
256 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
257 subrepo t: merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
255 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
258 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
256 (branch merge, don't forget to commit)
259 (branch merge, don't forget to commit)
257
260
258 should conflict
261 should conflict
259
262
260 $ cat t/t
263 $ cat t/t
261 <<<<<<< local
264 <<<<<<< local
262 conflict
265 conflict
263 =======
266 =======
264 t3
267 t3
265 >>>>>>> other
268 >>>>>>> other
266
269
267 clone
270 clone
268
271
269 $ cd ..
272 $ cd ..
270 $ hg clone t tc
273 $ hg clone t tc
271 updating to branch default
274 updating to branch default
272 cloning subrepo s from $TESTTMP/t/s
275 cloning subrepo s from $TESTTMP/t/s
273 cloning subrepo s/ss from $TESTTMP/t/s/ss (glob)
276 cloning subrepo s/ss from $TESTTMP/t/s/ss (glob)
274 cloning subrepo t from $TESTTMP/t/t
277 cloning subrepo t from $TESTTMP/t/t
275 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
278 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
276 $ cd tc
279 $ cd tc
277 $ hg debugsub
280 $ hg debugsub
278 path s
281 path s
279 source s
282 source s
280 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
283 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
281 path t
284 path t
282 source t
285 source t
283 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
286 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
284
287
285 push
288 push
286
289
287 $ echo bah > t/t
290 $ echo bah > t/t
288 $ hg ci -m11
291 $ hg ci -m11
289 committing subrepository t
292 committing subrepository t
290 $ hg push
293 $ hg push
291 pushing to $TESTTMP/t (glob)
294 pushing to $TESTTMP/t (glob)
292 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
295 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
293 no changes made to subrepo s since last push to $TESTTMP/t/s
296 no changes made to subrepo s since last push to $TESTTMP/t/s
294 pushing subrepo t to $TESTTMP/t/t
297 pushing subrepo t to $TESTTMP/t/t
295 searching for changes
298 searching for changes
296 adding changesets
299 adding changesets
297 adding manifests
300 adding manifests
298 adding file changes
301 adding file changes
299 added 1 changesets with 1 changes to 1 files
302 added 1 changesets with 1 changes to 1 files
300 searching for changes
303 searching for changes
301 adding changesets
304 adding changesets
302 adding manifests
305 adding manifests
303 adding file changes
306 adding file changes
304 added 1 changesets with 1 changes to 1 files
307 added 1 changesets with 1 changes to 1 files
305
308
306 push -f
309 push -f
307
310
308 $ echo bah > s/a
311 $ echo bah > s/a
309 $ hg ci -m12
312 $ hg ci -m12
310 committing subrepository s
313 committing subrepository s
311 $ hg push
314 $ hg push
312 pushing to $TESTTMP/t (glob)
315 pushing to $TESTTMP/t (glob)
313 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
316 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
314 pushing subrepo s to $TESTTMP/t/s
317 pushing subrepo s to $TESTTMP/t/s
315 searching for changes
318 searching for changes
316 abort: push creates new remote head 12a213df6fa9! (in subrepo s)
319 abort: push creates new remote head 12a213df6fa9! (in subrepo s)
317 (did you forget to merge? use push -f to force)
320 (did you forget to merge? use push -f to force)
318 [255]
321 [255]
319 $ hg push -f
322 $ hg push -f
320 pushing to $TESTTMP/t (glob)
323 pushing to $TESTTMP/t (glob)
321 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
324 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
322 searching for changes
325 searching for changes
323 no changes found
326 no changes found
324 pushing subrepo s to $TESTTMP/t/s
327 pushing subrepo s to $TESTTMP/t/s
325 searching for changes
328 searching for changes
326 adding changesets
329 adding changesets
327 adding manifests
330 adding manifests
328 adding file changes
331 adding file changes
329 added 1 changesets with 1 changes to 1 files (+1 heads)
332 added 1 changesets with 1 changes to 1 files (+1 heads)
330 pushing subrepo t to $TESTTMP/t/t
333 pushing subrepo t to $TESTTMP/t/t
331 searching for changes
334 searching for changes
332 no changes found
335 no changes found
333 searching for changes
336 searching for changes
334 adding changesets
337 adding changesets
335 adding manifests
338 adding manifests
336 adding file changes
339 adding file changes
337 added 1 changesets with 1 changes to 1 files
340 added 1 changesets with 1 changes to 1 files
338
341
339 check that unmodified subrepos are not pushed
342 check that unmodified subrepos are not pushed
340
343
341 $ hg clone . ../tcc
344 $ hg clone . ../tcc
342 updating to branch default
345 updating to branch default
343 cloning subrepo s from $TESTTMP/tc/s
346 cloning subrepo s from $TESTTMP/tc/s
344 cloning subrepo s/ss from $TESTTMP/tc/s/ss (glob)
347 cloning subrepo s/ss from $TESTTMP/tc/s/ss (glob)
345 cloning subrepo t from $TESTTMP/tc/t
348 cloning subrepo t from $TESTTMP/tc/t
346 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
349 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
347
350
348 the subrepos on the new clone have nothing to push to its source
351 the subrepos on the new clone have nothing to push to its source
349
352
350 $ hg push -R ../tcc .
353 $ hg push -R ../tcc .
351 pushing to .
354 pushing to .
352 no changes made to subrepo s/ss since last push to s/ss (glob)
355 no changes made to subrepo s/ss since last push to s/ss (glob)
353 no changes made to subrepo s since last push to s
356 no changes made to subrepo s since last push to s
354 no changes made to subrepo t since last push to t
357 no changes made to subrepo t since last push to t
355 searching for changes
358 searching for changes
356 no changes found
359 no changes found
357 [1]
360 [1]
358
361
359 the subrepos on the source do not have a clean store versus the clone target
362 the subrepos on the source do not have a clean store versus the clone target
360 because they were never explicitly pushed to the source
363 because they were never explicitly pushed to the source
361
364
362 $ hg push ../tcc
365 $ hg push ../tcc
363 pushing to ../tcc
366 pushing to ../tcc
364 pushing subrepo s/ss to ../tcc/s/ss (glob)
367 pushing subrepo s/ss to ../tcc/s/ss (glob)
365 searching for changes
368 searching for changes
366 no changes found
369 no changes found
367 pushing subrepo s to ../tcc/s
370 pushing subrepo s to ../tcc/s
368 searching for changes
371 searching for changes
369 no changes found
372 no changes found
370 pushing subrepo t to ../tcc/t
373 pushing subrepo t to ../tcc/t
371 searching for changes
374 searching for changes
372 no changes found
375 no changes found
373 searching for changes
376 searching for changes
374 no changes found
377 no changes found
375 [1]
378 [1]
376
379
377 after push their stores become clean
380 after push their stores become clean
378
381
379 $ hg push ../tcc
382 $ hg push ../tcc
380 pushing to ../tcc
383 pushing to ../tcc
381 no changes made to subrepo s/ss since last push to ../tcc/s/ss (glob)
384 no changes made to subrepo s/ss since last push to ../tcc/s/ss (glob)
382 no changes made to subrepo s since last push to ../tcc/s
385 no changes made to subrepo s since last push to ../tcc/s
383 no changes made to subrepo t since last push to ../tcc/t
386 no changes made to subrepo t since last push to ../tcc/t
384 searching for changes
387 searching for changes
385 no changes found
388 no changes found
386 [1]
389 [1]
387
390
388 updating a subrepo to a different revision or changing
391 updating a subrepo to a different revision or changing
389 its working directory does not make its store dirty
392 its working directory does not make its store dirty
390
393
391 $ hg -R s update '.^'
394 $ hg -R s update '.^'
392 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
395 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
393 $ hg push
396 $ hg push
394 pushing to $TESTTMP/t (glob)
397 pushing to $TESTTMP/t (glob)
395 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
398 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
396 no changes made to subrepo s since last push to $TESTTMP/t/s
399 no changes made to subrepo s since last push to $TESTTMP/t/s
397 no changes made to subrepo t since last push to $TESTTMP/t/t
400 no changes made to subrepo t since last push to $TESTTMP/t/t
398 searching for changes
401 searching for changes
399 no changes found
402 no changes found
400 [1]
403 [1]
401 $ echo foo >> s/a
404 $ echo foo >> s/a
402 $ hg push
405 $ hg push
403 pushing to $TESTTMP/t (glob)
406 pushing to $TESTTMP/t (glob)
404 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
407 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
405 no changes made to subrepo s since last push to $TESTTMP/t/s
408 no changes made to subrepo s since last push to $TESTTMP/t/s
406 no changes made to subrepo t since last push to $TESTTMP/t/t
409 no changes made to subrepo t since last push to $TESTTMP/t/t
407 searching for changes
410 searching for changes
408 no changes found
411 no changes found
409 [1]
412 [1]
410 $ hg -R s update -C tip
413 $ hg -R s update -C tip
411 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
414 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
412
415
413 committing into a subrepo makes its store (but not its parent's store) dirty
416 committing into a subrepo makes its store (but not its parent's store) dirty
414
417
415 $ echo foo >> s/ss/a
418 $ echo foo >> s/ss/a
416 $ hg -R s/ss commit -m 'test dirty store detection'
419 $ hg -R s/ss commit -m 'test dirty store detection'
417 $ hg push
420 $ hg push
418 pushing to $TESTTMP/t (glob)
421 pushing to $TESTTMP/t (glob)
419 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
422 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
420 searching for changes
423 searching for changes
421 adding changesets
424 adding changesets
422 adding manifests
425 adding manifests
423 adding file changes
426 adding file changes
424 added 1 changesets with 1 changes to 1 files
427 added 1 changesets with 1 changes to 1 files
425 no changes made to subrepo s since last push to $TESTTMP/t/s
428 no changes made to subrepo s since last push to $TESTTMP/t/s
426 no changes made to subrepo t since last push to $TESTTMP/t/t
429 no changes made to subrepo t since last push to $TESTTMP/t/t
427 searching for changes
430 searching for changes
428 no changes found
431 no changes found
429 [1]
432 [1]
430
433
431 a subrepo store may be clean versus one repo but not versus another
434 a subrepo store may be clean versus one repo but not versus another
432
435
433 $ hg push
436 $ hg push
434 pushing to $TESTTMP/t (glob)
437 pushing to $TESTTMP/t (glob)
435 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
438 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
436 no changes made to subrepo s since last push to $TESTTMP/t/s
439 no changes made to subrepo s since last push to $TESTTMP/t/s
437 no changes made to subrepo t since last push to $TESTTMP/t/t
440 no changes made to subrepo t since last push to $TESTTMP/t/t
438 searching for changes
441 searching for changes
439 no changes found
442 no changes found
440 [1]
443 [1]
441 $ hg push ../tcc
444 $ hg push ../tcc
442 pushing to ../tcc
445 pushing to ../tcc
443 pushing subrepo s/ss to ../tcc/s/ss (glob)
446 pushing subrepo s/ss to ../tcc/s/ss (glob)
444 searching for changes
447 searching for changes
445 adding changesets
448 adding changesets
446 adding manifests
449 adding manifests
447 adding file changes
450 adding file changes
448 added 1 changesets with 1 changes to 1 files
451 added 1 changesets with 1 changes to 1 files
449 no changes made to subrepo s since last push to ../tcc/s
452 no changes made to subrepo s since last push to ../tcc/s
450 no changes made to subrepo t since last push to ../tcc/t
453 no changes made to subrepo t since last push to ../tcc/t
451 searching for changes
454 searching for changes
452 no changes found
455 no changes found
453 [1]
456 [1]
454
457
455 update
458 update
456
459
457 $ cd ../t
460 $ cd ../t
458 $ hg up -C # discard our earlier merge
461 $ hg up -C # discard our earlier merge
459 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
460 $ echo blah > t/t
463 $ echo blah > t/t
461 $ hg ci -m13
464 $ hg ci -m13
462 committing subrepository t
465 committing subrepository t
463
466
464 backout calls revert internally with minimal opts, which should not raise
467 backout calls revert internally with minimal opts, which should not raise
465 KeyError
468 KeyError
466
469
467 $ hg backout ".^"
470 $ hg backout ".^"
468 reverting .hgsubstate
471 reverting .hgsubstate
469 reverting subrepo s
472 reverting subrepo s
470 reverting s/a (glob)
473 reverting s/a (glob)
471 reverting subrepo ss
474 reverting subrepo ss
472 reverting subrepo t
475 reverting subrepo t
473 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
476 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
474
477
475 $ hg up -C # discard changes
478 $ hg up -C # discard changes
476 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
479 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
477
480
478 pull
481 pull
479
482
480 $ cd ../tc
483 $ cd ../tc
481 $ hg pull
484 $ hg pull
482 pulling from $TESTTMP/t (glob)
485 pulling from $TESTTMP/t (glob)
483 searching for changes
486 searching for changes
484 adding changesets
487 adding changesets
485 adding manifests
488 adding manifests
486 adding file changes
489 adding file changes
487 added 1 changesets with 1 changes to 1 files
490 added 1 changesets with 1 changes to 1 files
488 (run 'hg update' to get a working copy)
491 (run 'hg update' to get a working copy)
489
492
490 should pull t
493 should pull t
491
494
492 $ hg up
495 $ hg up
493 pulling subrepo t from $TESTTMP/t/t
496 pulling subrepo t from $TESTTMP/t/t
494 searching for changes
497 searching for changes
495 adding changesets
498 adding changesets
496 adding manifests
499 adding manifests
497 adding file changes
500 adding file changes
498 added 1 changesets with 1 changes to 1 files
501 added 1 changesets with 1 changes to 1 files
499 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
502 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
500 $ cat t/t
503 $ cat t/t
501 blah
504 blah
502
505
503 bogus subrepo path aborts
506 bogus subrepo path aborts
504
507
505 $ echo 'bogus=[boguspath' >> .hgsub
508 $ echo 'bogus=[boguspath' >> .hgsub
506 $ hg ci -m 'bogus subrepo path'
509 $ hg ci -m 'bogus subrepo path'
507 abort: missing ] in subrepo source
510 abort: missing ] in subrepo source
508 [255]
511 [255]
509
512
510 Issue1986: merge aborts when trying to merge a subrepo that
513 Issue1986: merge aborts when trying to merge a subrepo that
511 shouldn't need merging
514 shouldn't need merging
512
515
513 # subrepo layout
516 # subrepo layout
514 #
517 #
515 # o 5 br
518 # o 5 br
516 # /|
519 # /|
517 # o | 4 default
520 # o | 4 default
518 # | |
521 # | |
519 # | o 3 br
522 # | o 3 br
520 # |/|
523 # |/|
521 # o | 2 default
524 # o | 2 default
522 # | |
525 # | |
523 # | o 1 br
526 # | o 1 br
524 # |/
527 # |/
525 # o 0 default
528 # o 0 default
526
529
527 $ cd ..
530 $ cd ..
528 $ rm -rf sub
531 $ rm -rf sub
529 $ hg init main
532 $ hg init main
530 $ cd main
533 $ cd main
531 $ hg init s
534 $ hg init s
532 $ cd s
535 $ cd s
533 $ echo a > a
536 $ echo a > a
534 $ hg ci -Am1
537 $ hg ci -Am1
535 adding a
538 adding a
536 $ hg branch br
539 $ hg branch br
537 marked working directory as branch br
540 marked working directory as branch br
538 (branches are permanent and global, did you want a bookmark?)
541 (branches are permanent and global, did you want a bookmark?)
539 $ echo a >> a
542 $ echo a >> a
540 $ hg ci -m1
543 $ hg ci -m1
541 $ hg up default
544 $ hg up default
542 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
545 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
543 $ echo b > b
546 $ echo b > b
544 $ hg ci -Am1
547 $ hg ci -Am1
545 adding b
548 adding b
546 $ hg up br
549 $ hg up br
547 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
550 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
548 $ hg merge tip
551 $ hg merge tip
549 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
552 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
550 (branch merge, don't forget to commit)
553 (branch merge, don't forget to commit)
551 $ hg ci -m1
554 $ hg ci -m1
552 $ hg up 2
555 $ hg up 2
553 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
556 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
554 $ echo c > c
557 $ echo c > c
555 $ hg ci -Am1
558 $ hg ci -Am1
556 adding c
559 adding c
557 $ hg up 3
560 $ hg up 3
558 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
561 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
559 $ hg merge 4
562 $ hg merge 4
560 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
563 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
561 (branch merge, don't forget to commit)
564 (branch merge, don't forget to commit)
562 $ hg ci -m1
565 $ hg ci -m1
563
566
564 # main repo layout:
567 # main repo layout:
565 #
568 #
566 # * <-- try to merge default into br again
569 # * <-- try to merge default into br again
567 # .`|
570 # .`|
568 # . o 5 br --> substate = 5
571 # . o 5 br --> substate = 5
569 # . |
572 # . |
570 # o | 4 default --> substate = 4
573 # o | 4 default --> substate = 4
571 # | |
574 # | |
572 # | o 3 br --> substate = 2
575 # | o 3 br --> substate = 2
573 # |/|
576 # |/|
574 # o | 2 default --> substate = 2
577 # o | 2 default --> substate = 2
575 # | |
578 # | |
576 # | o 1 br --> substate = 3
579 # | o 1 br --> substate = 3
577 # |/
580 # |/
578 # o 0 default --> substate = 2
581 # o 0 default --> substate = 2
579
582
580 $ cd ..
583 $ cd ..
581 $ echo 's = s' > .hgsub
584 $ echo 's = s' > .hgsub
582 $ hg -R s up 2
585 $ hg -R s up 2
583 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
586 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
584 $ hg ci -Am1
587 $ hg ci -Am1
585 adding .hgsub
588 adding .hgsub
586 $ hg branch br
589 $ hg branch br
587 marked working directory as branch br
590 marked working directory as branch br
588 (branches are permanent and global, did you want a bookmark?)
591 (branches are permanent and global, did you want a bookmark?)
589 $ echo b > b
592 $ echo b > b
590 $ hg -R s up 3
593 $ hg -R s up 3
591 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
594 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
592 $ hg ci -Am1
595 $ hg ci -Am1
593 adding b
596 adding b
594 $ hg up default
597 $ hg up default
595 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
598 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
596 $ echo c > c
599 $ echo c > c
597 $ hg ci -Am1
600 $ hg ci -Am1
598 adding c
601 adding c
599 $ hg up 1
602 $ hg up 1
600 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
603 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
601 $ hg merge 2
604 $ hg merge 2
602 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
605 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
603 (branch merge, don't forget to commit)
606 (branch merge, don't forget to commit)
604 $ hg ci -m1
607 $ hg ci -m1
605 $ hg up 2
608 $ hg up 2
606 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
609 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
607 $ hg -R s up 4
610 $ hg -R s up 4
608 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
611 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
609 $ echo d > d
612 $ echo d > d
610 $ hg ci -Am1
613 $ hg ci -Am1
611 adding d
614 adding d
612 $ hg up 3
615 $ hg up 3
613 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
616 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
614 $ hg -R s up 5
617 $ hg -R s up 5
615 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
618 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
616 $ echo e > e
619 $ echo e > e
617 $ hg ci -Am1
620 $ hg ci -Am1
618 adding e
621 adding e
619
622
620 $ hg up 5
623 $ hg up 5
621 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
624 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
622 $ hg merge 4 # try to merge default into br again
625 $ hg merge 4 # try to merge default into br again
626 subrepository s diverged (local revision: f8f13b33206e, remote revision: a3f9062a4f88)
627 (M)erge, keep (l)ocal or keep (r)emote? m
623 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
628 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
624 (branch merge, don't forget to commit)
629 (branch merge, don't forget to commit)
625 $ cd ..
630 $ cd ..
626
631
627 test subrepo delete from .hgsubstate
632 test subrepo delete from .hgsubstate
628
633
629 $ hg init testdelete
634 $ hg init testdelete
630 $ mkdir testdelete/nested testdelete/nested2
635 $ mkdir testdelete/nested testdelete/nested2
631 $ hg init testdelete/nested
636 $ hg init testdelete/nested
632 $ hg init testdelete/nested2
637 $ hg init testdelete/nested2
633 $ echo test > testdelete/nested/foo
638 $ echo test > testdelete/nested/foo
634 $ echo test > testdelete/nested2/foo
639 $ echo test > testdelete/nested2/foo
635 $ hg -R testdelete/nested add
640 $ hg -R testdelete/nested add
636 adding testdelete/nested/foo (glob)
641 adding testdelete/nested/foo (glob)
637 $ hg -R testdelete/nested2 add
642 $ hg -R testdelete/nested2 add
638 adding testdelete/nested2/foo (glob)
643 adding testdelete/nested2/foo (glob)
639 $ hg -R testdelete/nested ci -m test
644 $ hg -R testdelete/nested ci -m test
640 $ hg -R testdelete/nested2 ci -m test
645 $ hg -R testdelete/nested2 ci -m test
641 $ echo nested = nested > testdelete/.hgsub
646 $ echo nested = nested > testdelete/.hgsub
642 $ echo nested2 = nested2 >> testdelete/.hgsub
647 $ echo nested2 = nested2 >> testdelete/.hgsub
643 $ hg -R testdelete add
648 $ hg -R testdelete add
644 adding testdelete/.hgsub (glob)
649 adding testdelete/.hgsub (glob)
645 $ hg -R testdelete ci -m "nested 1 & 2 added"
650 $ hg -R testdelete ci -m "nested 1 & 2 added"
646 $ echo nested = nested > testdelete/.hgsub
651 $ echo nested = nested > testdelete/.hgsub
647 $ hg -R testdelete ci -m "nested 2 deleted"
652 $ hg -R testdelete ci -m "nested 2 deleted"
648 $ cat testdelete/.hgsubstate
653 $ cat testdelete/.hgsubstate
649 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
654 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
650 $ hg -R testdelete remove testdelete/.hgsub
655 $ hg -R testdelete remove testdelete/.hgsub
651 $ hg -R testdelete ci -m ".hgsub deleted"
656 $ hg -R testdelete ci -m ".hgsub deleted"
652 $ cat testdelete/.hgsubstate
657 $ cat testdelete/.hgsubstate
653 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
658 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
654
659
655 test repository cloning
660 test repository cloning
656
661
657 $ mkdir mercurial mercurial2
662 $ mkdir mercurial mercurial2
658 $ hg init nested_absolute
663 $ hg init nested_absolute
659 $ echo test > nested_absolute/foo
664 $ echo test > nested_absolute/foo
660 $ hg -R nested_absolute add
665 $ hg -R nested_absolute add
661 adding nested_absolute/foo (glob)
666 adding nested_absolute/foo (glob)
662 $ hg -R nested_absolute ci -mtest
667 $ hg -R nested_absolute ci -mtest
663 $ cd mercurial
668 $ cd mercurial
664 $ hg init nested_relative
669 $ hg init nested_relative
665 $ echo test2 > nested_relative/foo2
670 $ echo test2 > nested_relative/foo2
666 $ hg -R nested_relative add
671 $ hg -R nested_relative add
667 adding nested_relative/foo2 (glob)
672 adding nested_relative/foo2 (glob)
668 $ hg -R nested_relative ci -mtest2
673 $ hg -R nested_relative ci -mtest2
669 $ hg init main
674 $ hg init main
670 $ echo "nested_relative = ../nested_relative" > main/.hgsub
675 $ echo "nested_relative = ../nested_relative" > main/.hgsub
671 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
676 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
672 $ hg -R main add
677 $ hg -R main add
673 adding main/.hgsub (glob)
678 adding main/.hgsub (glob)
674 $ hg -R main ci -m "add subrepos"
679 $ hg -R main ci -m "add subrepos"
675 $ cd ..
680 $ cd ..
676 $ hg clone mercurial/main mercurial2/main
681 $ hg clone mercurial/main mercurial2/main
677 updating to branch default
682 updating to branch default
678 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
683 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
679 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
684 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
680 > mercurial2/main/nested_relative/.hg/hgrc
685 > mercurial2/main/nested_relative/.hg/hgrc
681 [paths]
686 [paths]
682 default = $TESTTMP/mercurial/nested_absolute
687 default = $TESTTMP/mercurial/nested_absolute
683 [paths]
688 [paths]
684 default = $TESTTMP/mercurial/nested_relative
689 default = $TESTTMP/mercurial/nested_relative
685 $ rm -rf mercurial mercurial2
690 $ rm -rf mercurial mercurial2
686
691
687 Issue1977: multirepo push should fail if subrepo push fails
692 Issue1977: multirepo push should fail if subrepo push fails
688
693
689 $ hg init repo
694 $ hg init repo
690 $ hg init repo/s
695 $ hg init repo/s
691 $ echo a > repo/s/a
696 $ echo a > repo/s/a
692 $ hg -R repo/s ci -Am0
697 $ hg -R repo/s ci -Am0
693 adding a
698 adding a
694 $ echo s = s > repo/.hgsub
699 $ echo s = s > repo/.hgsub
695 $ hg -R repo ci -Am1
700 $ hg -R repo ci -Am1
696 adding .hgsub
701 adding .hgsub
697 $ hg clone repo repo2
702 $ hg clone repo repo2
698 updating to branch default
703 updating to branch default
699 cloning subrepo s from $TESTTMP/repo/s
704 cloning subrepo s from $TESTTMP/repo/s
700 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
705 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
701 $ hg -q -R repo2 pull -u
706 $ hg -q -R repo2 pull -u
702 $ echo 1 > repo2/s/a
707 $ echo 1 > repo2/s/a
703 $ hg -R repo2/s ci -m2
708 $ hg -R repo2/s ci -m2
704 $ hg -q -R repo2/s push
709 $ hg -q -R repo2/s push
705 $ hg -R repo2/s up -C 0
710 $ hg -R repo2/s up -C 0
706 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
711 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
707 $ echo 2 > repo2/s/b
712 $ echo 2 > repo2/s/b
708 $ hg -R repo2/s ci -m3 -A
713 $ hg -R repo2/s ci -m3 -A
709 adding b
714 adding b
710 created new head
715 created new head
711 $ hg -R repo2 ci -m3
716 $ hg -R repo2 ci -m3
712 $ hg -q -R repo2 push
717 $ hg -q -R repo2 push
713 abort: push creates new remote head cc505f09a8b2! (in subrepo s)
718 abort: push creates new remote head cc505f09a8b2! (in subrepo s)
714 (did you forget to merge? use push -f to force)
719 (did you forget to merge? use push -f to force)
715 [255]
720 [255]
716 $ hg -R repo update
721 $ hg -R repo update
717 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
722 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
718
723
719 test if untracked file is not overwritten
724 test if untracked file is not overwritten
720
725
721 $ echo issue3276_ok > repo/s/b
726 $ echo issue3276_ok > repo/s/b
722 $ hg -R repo2 push -f -q
727 $ hg -R repo2 push -f -q
723 $ hg -R repo update
728 $ hg -R repo update
724 b: untracked file differs
729 b: untracked file differs
725 abort: untracked files in working directory differ from files in requested revision (in subrepo s)
730 abort: untracked files in working directory differ from files in requested revision (in subrepo s)
726 [255]
731 [255]
727
732
728 $ cat repo/s/b
733 $ cat repo/s/b
729 issue3276_ok
734 issue3276_ok
730 $ rm repo/s/b
735 $ rm repo/s/b
731 $ hg -R repo revert --all
736 $ hg -R repo revert --all
732 reverting repo/.hgsubstate (glob)
737 reverting repo/.hgsubstate (glob)
733 reverting subrepo s
738 reverting subrepo s
734 $ hg -R repo update
739 $ hg -R repo update
735 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
740 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
736 $ cat repo/s/b
741 $ cat repo/s/b
737 2
742 2
738 $ rm -rf repo2 repo
743 $ rm -rf repo2 repo
739
744
740
745
741 Issue1852 subrepos with relative paths always push/pull relative to default
746 Issue1852 subrepos with relative paths always push/pull relative to default
742
747
743 Prepare a repo with subrepo
748 Prepare a repo with subrepo
744
749
745 $ hg init issue1852a
750 $ hg init issue1852a
746 $ cd issue1852a
751 $ cd issue1852a
747 $ hg init sub/repo
752 $ hg init sub/repo
748 $ echo test > sub/repo/foo
753 $ echo test > sub/repo/foo
749 $ hg -R sub/repo add sub/repo/foo
754 $ hg -R sub/repo add sub/repo/foo
750 $ echo sub/repo = sub/repo > .hgsub
755 $ echo sub/repo = sub/repo > .hgsub
751 $ hg add .hgsub
756 $ hg add .hgsub
752 $ hg ci -mtest
757 $ hg ci -mtest
753 committing subrepository sub/repo (glob)
758 committing subrepository sub/repo (glob)
754 $ echo test >> sub/repo/foo
759 $ echo test >> sub/repo/foo
755 $ hg ci -mtest
760 $ hg ci -mtest
756 committing subrepository sub/repo (glob)
761 committing subrepository sub/repo (glob)
757 $ cd ..
762 $ cd ..
758
763
759 Create repo without default path, pull top repo, and see what happens on update
764 Create repo without default path, pull top repo, and see what happens on update
760
765
761 $ hg init issue1852b
766 $ hg init issue1852b
762 $ hg -R issue1852b pull issue1852a
767 $ hg -R issue1852b pull issue1852a
763 pulling from issue1852a
768 pulling from issue1852a
764 requesting all changes
769 requesting all changes
765 adding changesets
770 adding changesets
766 adding manifests
771 adding manifests
767 adding file changes
772 adding file changes
768 added 2 changesets with 3 changes to 2 files
773 added 2 changesets with 3 changes to 2 files
769 (run 'hg update' to get a working copy)
774 (run 'hg update' to get a working copy)
770 $ hg -R issue1852b update
775 $ hg -R issue1852b update
771 abort: default path for subrepository not found (in subrepo sub/repo) (glob)
776 abort: default path for subrepository not found (in subrepo sub/repo) (glob)
772 [255]
777 [255]
773
778
774 Ensure a full traceback, not just the SubrepoAbort part
779 Ensure a full traceback, not just the SubrepoAbort part
775
780
776 $ hg -R issue1852b update --traceback 2>&1 | grep 'raise util\.Abort'
781 $ hg -R issue1852b update --traceback 2>&1 | grep 'raise util\.Abort'
777 raise util.Abort(_("default path for subrepository not found"))
782 raise util.Abort(_("default path for subrepository not found"))
778
783
779 Pull -u now doesn't help
784 Pull -u now doesn't help
780
785
781 $ hg -R issue1852b pull -u issue1852a
786 $ hg -R issue1852b pull -u issue1852a
782 pulling from issue1852a
787 pulling from issue1852a
783 searching for changes
788 searching for changes
784 no changes found
789 no changes found
785
790
786 Try the same, but with pull -u
791 Try the same, but with pull -u
787
792
788 $ hg init issue1852c
793 $ hg init issue1852c
789 $ hg -R issue1852c pull -r0 -u issue1852a
794 $ hg -R issue1852c pull -r0 -u issue1852a
790 pulling from issue1852a
795 pulling from issue1852a
791 adding changesets
796 adding changesets
792 adding manifests
797 adding manifests
793 adding file changes
798 adding file changes
794 added 1 changesets with 2 changes to 2 files
799 added 1 changesets with 2 changes to 2 files
795 cloning subrepo sub/repo from issue1852a/sub/repo (glob)
800 cloning subrepo sub/repo from issue1852a/sub/repo (glob)
796 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
801 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
797
802
798 Try to push from the other side
803 Try to push from the other side
799
804
800 $ hg -R issue1852a push `pwd`/issue1852c
805 $ hg -R issue1852a push `pwd`/issue1852c
801 pushing to $TESTTMP/issue1852c (glob)
806 pushing to $TESTTMP/issue1852c (glob)
802 pushing subrepo sub/repo to $TESTTMP/issue1852c/sub/repo (glob)
807 pushing subrepo sub/repo to $TESTTMP/issue1852c/sub/repo (glob)
803 searching for changes
808 searching for changes
804 no changes found
809 no changes found
805 searching for changes
810 searching for changes
806 adding changesets
811 adding changesets
807 adding manifests
812 adding manifests
808 adding file changes
813 adding file changes
809 added 1 changesets with 1 changes to 1 files
814 added 1 changesets with 1 changes to 1 files
810
815
811 Incoming and outgoing should not use the default path:
816 Incoming and outgoing should not use the default path:
812
817
813 $ hg clone -q issue1852a issue1852d
818 $ hg clone -q issue1852a issue1852d
814 $ hg -R issue1852d outgoing --subrepos issue1852c
819 $ hg -R issue1852d outgoing --subrepos issue1852c
815 comparing with issue1852c
820 comparing with issue1852c
816 searching for changes
821 searching for changes
817 no changes found
822 no changes found
818 comparing with issue1852c/sub/repo
823 comparing with issue1852c/sub/repo
819 searching for changes
824 searching for changes
820 no changes found
825 no changes found
821 [1]
826 [1]
822 $ hg -R issue1852d incoming --subrepos issue1852c
827 $ hg -R issue1852d incoming --subrepos issue1852c
823 comparing with issue1852c
828 comparing with issue1852c
824 searching for changes
829 searching for changes
825 no changes found
830 no changes found
826 comparing with issue1852c/sub/repo
831 comparing with issue1852c/sub/repo
827 searching for changes
832 searching for changes
828 no changes found
833 no changes found
829 [1]
834 [1]
830
835
831 Check status of files when none of them belong to the first
836 Check status of files when none of them belong to the first
832 subrepository:
837 subrepository:
833
838
834 $ hg init subrepo-status
839 $ hg init subrepo-status
835 $ cd subrepo-status
840 $ cd subrepo-status
836 $ hg init subrepo-1
841 $ hg init subrepo-1
837 $ hg init subrepo-2
842 $ hg init subrepo-2
838 $ cd subrepo-2
843 $ cd subrepo-2
839 $ touch file
844 $ touch file
840 $ hg add file
845 $ hg add file
841 $ cd ..
846 $ cd ..
842 $ echo subrepo-1 = subrepo-1 > .hgsub
847 $ echo subrepo-1 = subrepo-1 > .hgsub
843 $ echo subrepo-2 = subrepo-2 >> .hgsub
848 $ echo subrepo-2 = subrepo-2 >> .hgsub
844 $ hg add .hgsub
849 $ hg add .hgsub
845 $ hg ci -m 'Added subrepos'
850 $ hg ci -m 'Added subrepos'
846 committing subrepository subrepo-2
851 committing subrepository subrepo-2
847 $ hg st subrepo-2/file
852 $ hg st subrepo-2/file
848
853
849 Check that share works with subrepo
854 Check that share works with subrepo
850 $ hg --config extensions.share= share . ../shared
855 $ hg --config extensions.share= share . ../shared
851 updating working directory
856 updating working directory
852 cloning subrepo subrepo-2 from $TESTTMP/subrepo-status/subrepo-2
857 cloning subrepo subrepo-2 from $TESTTMP/subrepo-status/subrepo-2
853 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
858 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
854 $ test -f ../shared/subrepo-1/.hg/sharedpath
859 $ test -f ../shared/subrepo-1/.hg/sharedpath
855 [1]
860 [1]
856 $ hg -R ../shared in
861 $ hg -R ../shared in
857 abort: repository default not found!
862 abort: repository default not found!
858 [255]
863 [255]
859 $ hg -R ../shared/subrepo-2 showconfig paths
864 $ hg -R ../shared/subrepo-2 showconfig paths
860 paths.default=$TESTTMP/subrepo-status/subrepo-2
865 paths.default=$TESTTMP/subrepo-status/subrepo-2
861 $ hg -R ../shared/subrepo-1 sum --remote
866 $ hg -R ../shared/subrepo-1 sum --remote
862 parent: -1:000000000000 tip (empty repository)
867 parent: -1:000000000000 tip (empty repository)
863 branch: default
868 branch: default
864 commit: (clean)
869 commit: (clean)
865 update: (current)
870 update: (current)
866 remote: (synced)
871 remote: (synced)
867
872
868 Check hg update --clean
873 Check hg update --clean
869 $ cd $TESTTMP/t
874 $ cd $TESTTMP/t
870 $ rm -r t/t.orig
875 $ rm -r t/t.orig
871 $ hg status -S --all
876 $ hg status -S --all
872 C .hgsub
877 C .hgsub
873 C .hgsubstate
878 C .hgsubstate
874 C a
879 C a
875 C s/.hgsub
880 C s/.hgsub
876 C s/.hgsubstate
881 C s/.hgsubstate
877 C s/a
882 C s/a
878 C s/ss/a
883 C s/ss/a
879 C t/t
884 C t/t
880 $ echo c1 > s/a
885 $ echo c1 > s/a
881 $ cd s
886 $ cd s
882 $ echo c1 > b
887 $ echo c1 > b
883 $ echo c1 > c
888 $ echo c1 > c
884 $ hg add b
889 $ hg add b
885 $ cd ..
890 $ cd ..
886 $ hg status -S
891 $ hg status -S
887 M s/a
892 M s/a
888 A s/b
893 A s/b
889 ? s/c
894 ? s/c
890 $ hg update -C
895 $ hg update -C
891 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
896 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
892 $ hg status -S
897 $ hg status -S
893 ? s/b
898 ? s/b
894 ? s/c
899 ? s/c
895
900
896 Sticky subrepositories, no changes
901 Sticky subrepositories, no changes
897 $ cd $TESTTMP/t
902 $ cd $TESTTMP/t
898 $ hg id
903 $ hg id
899 925c17564ef8 tip
904 925c17564ef8 tip
900 $ hg -R s id
905 $ hg -R s id
901 12a213df6fa9 tip
906 12a213df6fa9 tip
902 $ hg -R t id
907 $ hg -R t id
903 52c0adc0515a tip
908 52c0adc0515a tip
904 $ hg update 11
909 $ hg update 11
905 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
910 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
906 $ hg id
911 $ hg id
907 365661e5936a
912 365661e5936a
908 $ hg -R s id
913 $ hg -R s id
909 fc627a69481f
914 fc627a69481f
910 $ hg -R t id
915 $ hg -R t id
911 e95bcfa18a35
916 e95bcfa18a35
912
917
913 Sticky subrepositorys, file changes
918 Sticky subrepositorys, file changes
914 $ touch s/f1
919 $ touch s/f1
915 $ touch t/f1
920 $ touch t/f1
916 $ hg add -S s/f1
921 $ hg add -S s/f1
917 $ hg add -S t/f1
922 $ hg add -S t/f1
918 $ hg id
923 $ hg id
919 365661e5936a+
924 365661e5936a+
920 $ hg -R s id
925 $ hg -R s id
921 fc627a69481f+
926 fc627a69481f+
922 $ hg -R t id
927 $ hg -R t id
923 e95bcfa18a35+
928 e95bcfa18a35+
924 $ hg update tip
929 $ hg update tip
930 subrepository s diverged (local revision: fc627a69481f, remote revision: 12a213df6fa9)
931 (M)erge, keep (l)ocal or keep (r)emote? m
925 subrepository sources for s differ
932 subrepository sources for s differ
926 use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9)?
933 use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9)?
927 l
934 l
935 subrepository t diverged (local revision: e95bcfa18a35, remote revision: 52c0adc0515a)
936 (M)erge, keep (l)ocal or keep (r)emote? m
928 subrepository sources for t differ
937 subrepository sources for t differ
929 use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a)?
938 use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a)?
930 l
939 l
931 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
940 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
932 $ hg id
941 $ hg id
933 925c17564ef8+ tip
942 925c17564ef8+ tip
934 $ hg -R s id
943 $ hg -R s id
935 fc627a69481f+
944 fc627a69481f+
936 $ hg -R t id
945 $ hg -R t id
937 e95bcfa18a35+
946 e95bcfa18a35+
938 $ hg update --clean tip
947 $ hg update --clean tip
939 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
948 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
940
949
941 Sticky subrepository, revision updates
950 Sticky subrepository, revision updates
942 $ hg id
951 $ hg id
943 925c17564ef8 tip
952 925c17564ef8 tip
944 $ hg -R s id
953 $ hg -R s id
945 12a213df6fa9 tip
954 12a213df6fa9 tip
946 $ hg -R t id
955 $ hg -R t id
947 52c0adc0515a tip
956 52c0adc0515a tip
948 $ cd s
957 $ cd s
949 $ hg update -r -2
958 $ hg update -r -2
950 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
959 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
951 $ cd ../t
960 $ cd ../t
952 $ hg update -r 2
961 $ hg update -r 2
953 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
962 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
954 $ cd ..
963 $ cd ..
955 $ hg update 10
964 $ hg update 10
965 subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
966 (M)erge, keep (l)ocal or keep (r)emote? m
967 subrepository t diverged (local revision: 52c0adc0515a, remote revision: 20a0db6fbf6c)
968 (M)erge, keep (l)ocal or keep (r)emote? m
956 subrepository sources for t differ (in checked out version)
969 subrepository sources for t differ (in checked out version)
957 use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c)?
970 use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c)?
958 l
971 l
959 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
972 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
960 $ hg id
973 $ hg id
961 e45c8b14af55+
974 e45c8b14af55+
962 $ hg -R s id
975 $ hg -R s id
963 02dcf1d70411
976 02dcf1d70411
964 $ hg -R t id
977 $ hg -R t id
965 7af322bc1198
978 7af322bc1198
966
979
967 Sticky subrepository, file changes and revision updates
980 Sticky subrepository, file changes and revision updates
968 $ touch s/f1
981 $ touch s/f1
969 $ touch t/f1
982 $ touch t/f1
970 $ hg add -S s/f1
983 $ hg add -S s/f1
971 $ hg add -S t/f1
984 $ hg add -S t/f1
972 $ hg id
985 $ hg id
973 e45c8b14af55+
986 e45c8b14af55+
974 $ hg -R s id
987 $ hg -R s id
975 02dcf1d70411+
988 02dcf1d70411+
976 $ hg -R t id
989 $ hg -R t id
977 7af322bc1198+
990 7af322bc1198+
978 $ hg update tip
991 $ hg update tip
992 subrepository s diverged (local revision: 12a213df6fa9, remote revision: 12a213df6fa9)
993 (M)erge, keep (l)ocal or keep (r)emote? m
979 subrepository sources for s differ
994 subrepository sources for s differ
980 use (l)ocal source (02dcf1d70411) or (r)emote source (12a213df6fa9)?
995 use (l)ocal source (02dcf1d70411) or (r)emote source (12a213df6fa9)?
981 l
996 l
997 subrepository t diverged (local revision: 52c0adc0515a, remote revision: 52c0adc0515a)
998 (M)erge, keep (l)ocal or keep (r)emote? m
982 subrepository sources for t differ
999 subrepository sources for t differ
983 use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a)?
1000 use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a)?
984 l
1001 l
985 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1002 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
986 $ hg id
1003 $ hg id
987 925c17564ef8+ tip
1004 925c17564ef8+ tip
988 $ hg -R s id
1005 $ hg -R s id
989 02dcf1d70411+
1006 02dcf1d70411+
990 $ hg -R t id
1007 $ hg -R t id
991 7af322bc1198+
1008 7af322bc1198+
992
1009
993 Sticky repository, update --clean
1010 Sticky repository, update --clean
994 $ hg update --clean tip
1011 $ hg update --clean tip
995 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1012 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
996 $ hg id
1013 $ hg id
997 925c17564ef8 tip
1014 925c17564ef8 tip
998 $ hg -R s id
1015 $ hg -R s id
999 12a213df6fa9 tip
1016 12a213df6fa9 tip
1000 $ hg -R t id
1017 $ hg -R t id
1001 52c0adc0515a tip
1018 52c0adc0515a tip
1002
1019
1003 Test subrepo already at intended revision:
1020 Test subrepo already at intended revision:
1004 $ cd s
1021 $ cd s
1005 $ hg update fc627a69481f
1022 $ hg update fc627a69481f
1006 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1023 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1007 $ cd ..
1024 $ cd ..
1008 $ hg update 11
1025 $ hg update 11
1026 subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
1027 (M)erge, keep (l)ocal or keep (r)emote? m
1009 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1028 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1010 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1029 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1011 $ hg id -n
1030 $ hg id -n
1012 11+
1031 11+
1013 $ hg -R s id
1032 $ hg -R s id
1014 fc627a69481f
1033 fc627a69481f
1015 $ hg -R t id
1034 $ hg -R t id
1016 e95bcfa18a35
1035 e95bcfa18a35
1017
1036
1018 Test that removing .hgsubstate doesn't break anything:
1037 Test that removing .hgsubstate doesn't break anything:
1019
1038
1020 $ hg rm -f .hgsubstate
1039 $ hg rm -f .hgsubstate
1021 $ hg ci -mrm
1040 $ hg ci -mrm
1022 nothing changed
1041 nothing changed
1023 [1]
1042 [1]
1024 $ hg log -vr tip
1043 $ hg log -vr tip
1025 changeset: 13:925c17564ef8
1044 changeset: 13:925c17564ef8
1026 tag: tip
1045 tag: tip
1027 user: test
1046 user: test
1028 date: Thu Jan 01 00:00:00 1970 +0000
1047 date: Thu Jan 01 00:00:00 1970 +0000
1029 files: .hgsubstate
1048 files: .hgsubstate
1030 description:
1049 description:
1031 13
1050 13
1032
1051
1033
1052
1034
1053
1035 Test that removing .hgsub removes .hgsubstate:
1054 Test that removing .hgsub removes .hgsubstate:
1036
1055
1037 $ hg rm .hgsub
1056 $ hg rm .hgsub
1038 $ hg ci -mrm2
1057 $ hg ci -mrm2
1039 created new head
1058 created new head
1040 $ hg log -vr tip
1059 $ hg log -vr tip
1041 changeset: 14:2400bccd50af
1060 changeset: 14:2400bccd50af
1042 tag: tip
1061 tag: tip
1043 parent: 11:365661e5936a
1062 parent: 11:365661e5936a
1044 user: test
1063 user: test
1045 date: Thu Jan 01 00:00:00 1970 +0000
1064 date: Thu Jan 01 00:00:00 1970 +0000
1046 files: .hgsub .hgsubstate
1065 files: .hgsub .hgsubstate
1047 description:
1066 description:
1048 rm2
1067 rm2
1049
1068
1050
1069
1051 Test issue3153: diff -S with deleted subrepos
1070 Test issue3153: diff -S with deleted subrepos
1052
1071
1053 $ hg diff --nodates -S -c .
1072 $ hg diff --nodates -S -c .
1054 diff -r 365661e5936a -r 2400bccd50af .hgsub
1073 diff -r 365661e5936a -r 2400bccd50af .hgsub
1055 --- a/.hgsub
1074 --- a/.hgsub
1056 +++ /dev/null
1075 +++ /dev/null
1057 @@ -1,2 +0,0 @@
1076 @@ -1,2 +0,0 @@
1058 -s = s
1077 -s = s
1059 -t = t
1078 -t = t
1060 diff -r 365661e5936a -r 2400bccd50af .hgsubstate
1079 diff -r 365661e5936a -r 2400bccd50af .hgsubstate
1061 --- a/.hgsubstate
1080 --- a/.hgsubstate
1062 +++ /dev/null
1081 +++ /dev/null
1063 @@ -1,2 +0,0 @@
1082 @@ -1,2 +0,0 @@
1064 -fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
1083 -fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
1065 -e95bcfa18a358dc4936da981ebf4147b4cad1362 t
1084 -e95bcfa18a358dc4936da981ebf4147b4cad1362 t
1066
1085
1067 Test behavior of add for explicit path in subrepo:
1086 Test behavior of add for explicit path in subrepo:
1068 $ cd ..
1087 $ cd ..
1069 $ hg init explicit
1088 $ hg init explicit
1070 $ cd explicit
1089 $ cd explicit
1071 $ echo s = s > .hgsub
1090 $ echo s = s > .hgsub
1072 $ hg add .hgsub
1091 $ hg add .hgsub
1073 $ hg init s
1092 $ hg init s
1074 $ hg ci -m0
1093 $ hg ci -m0
1075 Adding with an explicit path in a subrepo adds the file
1094 Adding with an explicit path in a subrepo adds the file
1076 $ echo c1 > f1
1095 $ echo c1 > f1
1077 $ echo c2 > s/f2
1096 $ echo c2 > s/f2
1078 $ hg st -S
1097 $ hg st -S
1079 ? f1
1098 ? f1
1080 ? s/f2
1099 ? s/f2
1081 $ hg add s/f2
1100 $ hg add s/f2
1082 $ hg st -S
1101 $ hg st -S
1083 A s/f2
1102 A s/f2
1084 ? f1
1103 ? f1
1085 $ hg ci -R s -m0
1104 $ hg ci -R s -m0
1086 $ hg ci -Am1
1105 $ hg ci -Am1
1087 adding f1
1106 adding f1
1088 Adding with an explicit path in a subrepo with -S has the same behavior
1107 Adding with an explicit path in a subrepo with -S has the same behavior
1089 $ echo c3 > f3
1108 $ echo c3 > f3
1090 $ echo c4 > s/f4
1109 $ echo c4 > s/f4
1091 $ hg st -S
1110 $ hg st -S
1092 ? f3
1111 ? f3
1093 ? s/f4
1112 ? s/f4
1094 $ hg add -S s/f4
1113 $ hg add -S s/f4
1095 $ hg st -S
1114 $ hg st -S
1096 A s/f4
1115 A s/f4
1097 ? f3
1116 ? f3
1098 $ hg ci -R s -m1
1117 $ hg ci -R s -m1
1099 $ hg ci -Ama2
1118 $ hg ci -Ama2
1100 adding f3
1119 adding f3
1101 Adding without a path or pattern silently ignores subrepos
1120 Adding without a path or pattern silently ignores subrepos
1102 $ echo c5 > f5
1121 $ echo c5 > f5
1103 $ echo c6 > s/f6
1122 $ echo c6 > s/f6
1104 $ echo c7 > s/f7
1123 $ echo c7 > s/f7
1105 $ hg st -S
1124 $ hg st -S
1106 ? f5
1125 ? f5
1107 ? s/f6
1126 ? s/f6
1108 ? s/f7
1127 ? s/f7
1109 $ hg add
1128 $ hg add
1110 adding f5
1129 adding f5
1111 $ hg st -S
1130 $ hg st -S
1112 A f5
1131 A f5
1113 ? s/f6
1132 ? s/f6
1114 ? s/f7
1133 ? s/f7
1115 $ hg ci -R s -Am2
1134 $ hg ci -R s -Am2
1116 adding f6
1135 adding f6
1117 adding f7
1136 adding f7
1118 $ hg ci -m3
1137 $ hg ci -m3
1119 Adding without a path or pattern with -S also adds files in subrepos
1138 Adding without a path or pattern with -S also adds files in subrepos
1120 $ echo c8 > f8
1139 $ echo c8 > f8
1121 $ echo c9 > s/f9
1140 $ echo c9 > s/f9
1122 $ echo c10 > s/f10
1141 $ echo c10 > s/f10
1123 $ hg st -S
1142 $ hg st -S
1124 ? f8
1143 ? f8
1125 ? s/f10
1144 ? s/f10
1126 ? s/f9
1145 ? s/f9
1127 $ hg add -S
1146 $ hg add -S
1128 adding f8
1147 adding f8
1129 adding s/f10 (glob)
1148 adding s/f10 (glob)
1130 adding s/f9 (glob)
1149 adding s/f9 (glob)
1131 $ hg st -S
1150 $ hg st -S
1132 A f8
1151 A f8
1133 A s/f10
1152 A s/f10
1134 A s/f9
1153 A s/f9
1135 $ hg ci -R s -m3
1154 $ hg ci -R s -m3
1136 $ hg ci -m4
1155 $ hg ci -m4
1137 Adding with a pattern silently ignores subrepos
1156 Adding with a pattern silently ignores subrepos
1138 $ echo c11 > fm11
1157 $ echo c11 > fm11
1139 $ echo c12 > fn12
1158 $ echo c12 > fn12
1140 $ echo c13 > s/fm13
1159 $ echo c13 > s/fm13
1141 $ echo c14 > s/fn14
1160 $ echo c14 > s/fn14
1142 $ hg st -S
1161 $ hg st -S
1143 ? fm11
1162 ? fm11
1144 ? fn12
1163 ? fn12
1145 ? s/fm13
1164 ? s/fm13
1146 ? s/fn14
1165 ? s/fn14
1147 $ hg add 'glob:**fm*'
1166 $ hg add 'glob:**fm*'
1148 adding fm11
1167 adding fm11
1149 $ hg st -S
1168 $ hg st -S
1150 A fm11
1169 A fm11
1151 ? fn12
1170 ? fn12
1152 ? s/fm13
1171 ? s/fm13
1153 ? s/fn14
1172 ? s/fn14
1154 $ hg ci -R s -Am4
1173 $ hg ci -R s -Am4
1155 adding fm13
1174 adding fm13
1156 adding fn14
1175 adding fn14
1157 $ hg ci -Am5
1176 $ hg ci -Am5
1158 adding fn12
1177 adding fn12
1159 Adding with a pattern with -S also adds matches in subrepos
1178 Adding with a pattern with -S also adds matches in subrepos
1160 $ echo c15 > fm15
1179 $ echo c15 > fm15
1161 $ echo c16 > fn16
1180 $ echo c16 > fn16
1162 $ echo c17 > s/fm17
1181 $ echo c17 > s/fm17
1163 $ echo c18 > s/fn18
1182 $ echo c18 > s/fn18
1164 $ hg st -S
1183 $ hg st -S
1165 ? fm15
1184 ? fm15
1166 ? fn16
1185 ? fn16
1167 ? s/fm17
1186 ? s/fm17
1168 ? s/fn18
1187 ? s/fn18
1169 $ hg add -S 'glob:**fm*'
1188 $ hg add -S 'glob:**fm*'
1170 adding fm15
1189 adding fm15
1171 adding s/fm17 (glob)
1190 adding s/fm17 (glob)
1172 $ hg st -S
1191 $ hg st -S
1173 A fm15
1192 A fm15
1174 A s/fm17
1193 A s/fm17
1175 ? fn16
1194 ? fn16
1176 ? s/fn18
1195 ? s/fn18
1177 $ hg ci -R s -Am5
1196 $ hg ci -R s -Am5
1178 adding fn18
1197 adding fn18
1179 $ hg ci -Am6
1198 $ hg ci -Am6
1180 adding fn16
1199 adding fn16
1181
1200
1182 Test behavior of forget for explicit path in subrepo:
1201 Test behavior of forget for explicit path in subrepo:
1183 Forgetting an explicit path in a subrepo untracks the file
1202 Forgetting an explicit path in a subrepo untracks the file
1184 $ echo c19 > s/f19
1203 $ echo c19 > s/f19
1185 $ hg add s/f19
1204 $ hg add s/f19
1186 $ hg st -S
1205 $ hg st -S
1187 A s/f19
1206 A s/f19
1188 $ hg forget s/f19
1207 $ hg forget s/f19
1189 $ hg st -S
1208 $ hg st -S
1190 ? s/f19
1209 ? s/f19
1191 $ rm s/f19
1210 $ rm s/f19
1192 $ cd ..
1211 $ cd ..
1193
1212
1194 Courtesy phases synchronisation to publishing server does not block the push
1213 Courtesy phases synchronisation to publishing server does not block the push
1195 (issue3781)
1214 (issue3781)
1196
1215
1197 $ cp -r main issue3781
1216 $ cp -r main issue3781
1198 $ cp -r main issue3781-dest
1217 $ cp -r main issue3781-dest
1199 $ cd issue3781-dest/s
1218 $ cd issue3781-dest/s
1200 $ hg phase tip # show we have draft changeset
1219 $ hg phase tip # show we have draft changeset
1201 5: draft
1220 5: draft
1202 $ chmod a-w .hg/store/phaseroots # prevent phase push
1221 $ chmod a-w .hg/store/phaseroots # prevent phase push
1203 $ cd ../../issue3781
1222 $ cd ../../issue3781
1204 $ cat >> .hg/hgrc << EOF
1223 $ cat >> .hg/hgrc << EOF
1205 > [paths]
1224 > [paths]
1206 > default=../issue3781-dest/
1225 > default=../issue3781-dest/
1207 > EOF
1226 > EOF
1208 $ hg push
1227 $ hg push
1209 pushing to $TESTTMP/issue3781-dest (glob)
1228 pushing to $TESTTMP/issue3781-dest (glob)
1210 pushing subrepo s to $TESTTMP/issue3781-dest/s
1229 pushing subrepo s to $TESTTMP/issue3781-dest/s
1211 searching for changes
1230 searching for changes
1212 no changes found
1231 no changes found
1213 searching for changes
1232 searching for changes
1214 no changes found
1233 no changes found
1215 [1]
1234 [1]
1216
1235
General Comments 0
You need to be logged in to leave comments. Login now