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