##// END OF EJS Templates
subrepos: make last line of prompts <40 english chars (issue6158)...
Kyle Lippincott -
r42791:f6540aba default
parent child Browse files
Show More
@@ -1,1838 +1,1840 b''
1 # subrepo.py - sub-repository classes and factory
1 # subrepo.py - sub-repository classes and factory
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 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import copy
10 import copy
11 import errno
11 import errno
12 import hashlib
12 import hashlib
13 import os
13 import os
14 import re
14 import re
15 import stat
15 import stat
16 import subprocess
16 import subprocess
17 import sys
17 import sys
18 import tarfile
18 import tarfile
19 import xml.dom.minidom
19 import xml.dom.minidom
20
20
21 from .i18n import _
21 from .i18n import _
22 from . import (
22 from . import (
23 cmdutil,
23 cmdutil,
24 encoding,
24 encoding,
25 error,
25 error,
26 exchange,
26 exchange,
27 logcmdutil,
27 logcmdutil,
28 match as matchmod,
28 match as matchmod,
29 node,
29 node,
30 pathutil,
30 pathutil,
31 phases,
31 phases,
32 pycompat,
32 pycompat,
33 scmutil,
33 scmutil,
34 subrepoutil,
34 subrepoutil,
35 util,
35 util,
36 vfs as vfsmod,
36 vfs as vfsmod,
37 )
37 )
38 from .utils import (
38 from .utils import (
39 dateutil,
39 dateutil,
40 procutil,
40 procutil,
41 stringutil,
41 stringutil,
42 )
42 )
43
43
44 hg = None
44 hg = None
45 reporelpath = subrepoutil.reporelpath
45 reporelpath = subrepoutil.reporelpath
46 subrelpath = subrepoutil.subrelpath
46 subrelpath = subrepoutil.subrelpath
47 _abssource = subrepoutil._abssource
47 _abssource = subrepoutil._abssource
48 propertycache = util.propertycache
48 propertycache = util.propertycache
49
49
50 def _expandedabspath(path):
50 def _expandedabspath(path):
51 '''
51 '''
52 get a path or url and if it is a path expand it and return an absolute path
52 get a path or url and if it is a path expand it and return an absolute path
53 '''
53 '''
54 expandedpath = util.urllocalpath(util.expandpath(path))
54 expandedpath = util.urllocalpath(util.expandpath(path))
55 u = util.url(expandedpath)
55 u = util.url(expandedpath)
56 if not u.scheme:
56 if not u.scheme:
57 path = util.normpath(os.path.abspath(u.path))
57 path = util.normpath(os.path.abspath(u.path))
58 return path
58 return path
59
59
60 def _getstorehashcachename(remotepath):
60 def _getstorehashcachename(remotepath):
61 '''get a unique filename for the store hash cache of a remote repository'''
61 '''get a unique filename for the store hash cache of a remote repository'''
62 return node.hex(hashlib.sha1(_expandedabspath(remotepath)).digest())[0:12]
62 return node.hex(hashlib.sha1(_expandedabspath(remotepath)).digest())[0:12]
63
63
64 class SubrepoAbort(error.Abort):
64 class SubrepoAbort(error.Abort):
65 """Exception class used to avoid handling a subrepo error more than once"""
65 """Exception class used to avoid handling a subrepo error more than once"""
66 def __init__(self, *args, **kw):
66 def __init__(self, *args, **kw):
67 self.subrepo = kw.pop(r'subrepo', None)
67 self.subrepo = kw.pop(r'subrepo', None)
68 self.cause = kw.pop(r'cause', None)
68 self.cause = kw.pop(r'cause', None)
69 error.Abort.__init__(self, *args, **kw)
69 error.Abort.__init__(self, *args, **kw)
70
70
71 def annotatesubrepoerror(func):
71 def annotatesubrepoerror(func):
72 def decoratedmethod(self, *args, **kargs):
72 def decoratedmethod(self, *args, **kargs):
73 try:
73 try:
74 res = func(self, *args, **kargs)
74 res = func(self, *args, **kargs)
75 except SubrepoAbort as ex:
75 except SubrepoAbort as ex:
76 # This exception has already been handled
76 # This exception has already been handled
77 raise ex
77 raise ex
78 except error.Abort as ex:
78 except error.Abort as ex:
79 subrepo = subrelpath(self)
79 subrepo = subrelpath(self)
80 errormsg = (stringutil.forcebytestr(ex) + ' '
80 errormsg = (stringutil.forcebytestr(ex) + ' '
81 + _('(in subrepository "%s")') % subrepo)
81 + _('(in subrepository "%s")') % subrepo)
82 # avoid handling this exception by raising a SubrepoAbort exception
82 # avoid handling this exception by raising a SubrepoAbort exception
83 raise SubrepoAbort(errormsg, hint=ex.hint, subrepo=subrepo,
83 raise SubrepoAbort(errormsg, hint=ex.hint, subrepo=subrepo,
84 cause=sys.exc_info())
84 cause=sys.exc_info())
85 return res
85 return res
86 return decoratedmethod
86 return decoratedmethod
87
87
88 def _updateprompt(ui, sub, dirty, local, remote):
88 def _updateprompt(ui, sub, dirty, local, remote):
89 if dirty:
89 if dirty:
90 msg = (_(' subrepository sources for %s differ\n'
90 msg = (_(' subrepository sources for %s differ\n'
91 'use (l)ocal source (%s) or (r)emote source (%s)?'
91 'you can use (l)ocal source (%s) or (r)emote source (%s).\n'
92 'what do you want to do?'
92 '$$ &Local $$ &Remote')
93 '$$ &Local $$ &Remote')
93 % (subrelpath(sub), local, remote))
94 % (subrelpath(sub), local, remote))
94 else:
95 else:
95 msg = (_(' subrepository sources for %s differ (in checked out '
96 msg = (_(' subrepository sources for %s differ (in checked out '
96 'version)\n'
97 'version)\n'
97 'use (l)ocal source (%s) or (r)emote source (%s)?'
98 'you can use (l)ocal source (%s) or (r)emote source (%s).\n'
99 'what do you want to do?'
98 '$$ &Local $$ &Remote')
100 '$$ &Local $$ &Remote')
99 % (subrelpath(sub), local, remote))
101 % (subrelpath(sub), local, remote))
100 return ui.promptchoice(msg, 0)
102 return ui.promptchoice(msg, 0)
101
103
102 def _sanitize(ui, vfs, ignore):
104 def _sanitize(ui, vfs, ignore):
103 for dirname, dirs, names in vfs.walk():
105 for dirname, dirs, names in vfs.walk():
104 for i, d in enumerate(dirs):
106 for i, d in enumerate(dirs):
105 if d.lower() == ignore:
107 if d.lower() == ignore:
106 del dirs[i]
108 del dirs[i]
107 break
109 break
108 if vfs.basename(dirname).lower() != '.hg':
110 if vfs.basename(dirname).lower() != '.hg':
109 continue
111 continue
110 for f in names:
112 for f in names:
111 if f.lower() == 'hgrc':
113 if f.lower() == 'hgrc':
112 ui.warn(_("warning: removing potentially hostile 'hgrc' "
114 ui.warn(_("warning: removing potentially hostile 'hgrc' "
113 "in '%s'\n") % vfs.join(dirname))
115 "in '%s'\n") % vfs.join(dirname))
114 vfs.unlink(vfs.reljoin(dirname, f))
116 vfs.unlink(vfs.reljoin(dirname, f))
115
117
116 def _auditsubrepopath(repo, path):
118 def _auditsubrepopath(repo, path):
117 # sanity check for potentially unsafe paths such as '~' and '$FOO'
119 # sanity check for potentially unsafe paths such as '~' and '$FOO'
118 if path.startswith('~') or '$' in path or util.expandpath(path) != path:
120 if path.startswith('~') or '$' in path or util.expandpath(path) != path:
119 raise error.Abort(_('subrepo path contains illegal component: %s')
121 raise error.Abort(_('subrepo path contains illegal component: %s')
120 % path)
122 % path)
121 # auditor doesn't check if the path itself is a symlink
123 # auditor doesn't check if the path itself is a symlink
122 pathutil.pathauditor(repo.root)(path)
124 pathutil.pathauditor(repo.root)(path)
123 if repo.wvfs.islink(path):
125 if repo.wvfs.islink(path):
124 raise error.Abort(_("subrepo '%s' traverses symbolic link") % path)
126 raise error.Abort(_("subrepo '%s' traverses symbolic link") % path)
125
127
126 SUBREPO_ALLOWED_DEFAULTS = {
128 SUBREPO_ALLOWED_DEFAULTS = {
127 'hg': True,
129 'hg': True,
128 'git': False,
130 'git': False,
129 'svn': False,
131 'svn': False,
130 }
132 }
131
133
132 def _checktype(ui, kind):
134 def _checktype(ui, kind):
133 # subrepos.allowed is a master kill switch. If disabled, subrepos are
135 # subrepos.allowed is a master kill switch. If disabled, subrepos are
134 # disabled period.
136 # disabled period.
135 if not ui.configbool('subrepos', 'allowed', True):
137 if not ui.configbool('subrepos', 'allowed', True):
136 raise error.Abort(_('subrepos not enabled'),
138 raise error.Abort(_('subrepos not enabled'),
137 hint=_("see 'hg help config.subrepos' for details"))
139 hint=_("see 'hg help config.subrepos' for details"))
138
140
139 default = SUBREPO_ALLOWED_DEFAULTS.get(kind, False)
141 default = SUBREPO_ALLOWED_DEFAULTS.get(kind, False)
140 if not ui.configbool('subrepos', '%s:allowed' % kind, default):
142 if not ui.configbool('subrepos', '%s:allowed' % kind, default):
141 raise error.Abort(_('%s subrepos not allowed') % kind,
143 raise error.Abort(_('%s subrepos not allowed') % kind,
142 hint=_("see 'hg help config.subrepos' for details"))
144 hint=_("see 'hg help config.subrepos' for details"))
143
145
144 if kind not in types:
146 if kind not in types:
145 raise error.Abort(_('unknown subrepo type %s') % kind)
147 raise error.Abort(_('unknown subrepo type %s') % kind)
146
148
147 def subrepo(ctx, path, allowwdir=False, allowcreate=True):
149 def subrepo(ctx, path, allowwdir=False, allowcreate=True):
148 """return instance of the right subrepo class for subrepo in path"""
150 """return instance of the right subrepo class for subrepo in path"""
149 # subrepo inherently violates our import layering rules
151 # subrepo inherently violates our import layering rules
150 # because it wants to make repo objects from deep inside the stack
152 # because it wants to make repo objects from deep inside the stack
151 # so we manually delay the circular imports to not break
153 # so we manually delay the circular imports to not break
152 # scripts that don't use our demand-loading
154 # scripts that don't use our demand-loading
153 global hg
155 global hg
154 from . import hg as h
156 from . import hg as h
155 hg = h
157 hg = h
156
158
157 repo = ctx.repo()
159 repo = ctx.repo()
158 _auditsubrepopath(repo, path)
160 _auditsubrepopath(repo, path)
159 state = ctx.substate[path]
161 state = ctx.substate[path]
160 _checktype(repo.ui, state[2])
162 _checktype(repo.ui, state[2])
161 if allowwdir:
163 if allowwdir:
162 state = (state[0], ctx.subrev(path), state[2])
164 state = (state[0], ctx.subrev(path), state[2])
163 return types[state[2]](ctx, path, state[:2], allowcreate)
165 return types[state[2]](ctx, path, state[:2], allowcreate)
164
166
165 def nullsubrepo(ctx, path, pctx):
167 def nullsubrepo(ctx, path, pctx):
166 """return an empty subrepo in pctx for the extant subrepo in ctx"""
168 """return an empty subrepo in pctx for the extant subrepo in ctx"""
167 # subrepo inherently violates our import layering rules
169 # subrepo inherently violates our import layering rules
168 # because it wants to make repo objects from deep inside the stack
170 # because it wants to make repo objects from deep inside the stack
169 # so we manually delay the circular imports to not break
171 # so we manually delay the circular imports to not break
170 # scripts that don't use our demand-loading
172 # scripts that don't use our demand-loading
171 global hg
173 global hg
172 from . import hg as h
174 from . import hg as h
173 hg = h
175 hg = h
174
176
175 repo = ctx.repo()
177 repo = ctx.repo()
176 _auditsubrepopath(repo, path)
178 _auditsubrepopath(repo, path)
177 state = ctx.substate[path]
179 state = ctx.substate[path]
178 _checktype(repo.ui, state[2])
180 _checktype(repo.ui, state[2])
179 subrev = ''
181 subrev = ''
180 if state[2] == 'hg':
182 if state[2] == 'hg':
181 subrev = "0" * 40
183 subrev = "0" * 40
182 return types[state[2]](pctx, path, (state[0], subrev), True)
184 return types[state[2]](pctx, path, (state[0], subrev), True)
183
185
184 # subrepo classes need to implement the following abstract class:
186 # subrepo classes need to implement the following abstract class:
185
187
186 class abstractsubrepo(object):
188 class abstractsubrepo(object):
187
189
188 def __init__(self, ctx, path):
190 def __init__(self, ctx, path):
189 """Initialize abstractsubrepo part
191 """Initialize abstractsubrepo part
190
192
191 ``ctx`` is the context referring this subrepository in the
193 ``ctx`` is the context referring this subrepository in the
192 parent repository.
194 parent repository.
193
195
194 ``path`` is the path to this subrepository as seen from
196 ``path`` is the path to this subrepository as seen from
195 innermost repository.
197 innermost repository.
196 """
198 """
197 self.ui = ctx.repo().ui
199 self.ui = ctx.repo().ui
198 self._ctx = ctx
200 self._ctx = ctx
199 self._path = path
201 self._path = path
200
202
201 def addwebdirpath(self, serverpath, webconf):
203 def addwebdirpath(self, serverpath, webconf):
202 """Add the hgwebdir entries for this subrepo, and any of its subrepos.
204 """Add the hgwebdir entries for this subrepo, and any of its subrepos.
203
205
204 ``serverpath`` is the path component of the URL for this repo.
206 ``serverpath`` is the path component of the URL for this repo.
205
207
206 ``webconf`` is the dictionary of hgwebdir entries.
208 ``webconf`` is the dictionary of hgwebdir entries.
207 """
209 """
208 pass
210 pass
209
211
210 def storeclean(self, path):
212 def storeclean(self, path):
211 """
213 """
212 returns true if the repository has not changed since it was last
214 returns true if the repository has not changed since it was last
213 cloned from or pushed to a given repository.
215 cloned from or pushed to a given repository.
214 """
216 """
215 return False
217 return False
216
218
217 def dirty(self, ignoreupdate=False, missing=False):
219 def dirty(self, ignoreupdate=False, missing=False):
218 """returns true if the dirstate of the subrepo is dirty or does not
220 """returns true if the dirstate of the subrepo is dirty or does not
219 match current stored state. If ignoreupdate is true, only check
221 match current stored state. If ignoreupdate is true, only check
220 whether the subrepo has uncommitted changes in its dirstate. If missing
222 whether the subrepo has uncommitted changes in its dirstate. If missing
221 is true, check for deleted files.
223 is true, check for deleted files.
222 """
224 """
223 raise NotImplementedError
225 raise NotImplementedError
224
226
225 def dirtyreason(self, ignoreupdate=False, missing=False):
227 def dirtyreason(self, ignoreupdate=False, missing=False):
226 """return reason string if it is ``dirty()``
228 """return reason string if it is ``dirty()``
227
229
228 Returned string should have enough information for the message
230 Returned string should have enough information for the message
229 of exception.
231 of exception.
230
232
231 This returns None, otherwise.
233 This returns None, otherwise.
232 """
234 """
233 if self.dirty(ignoreupdate=ignoreupdate, missing=missing):
235 if self.dirty(ignoreupdate=ignoreupdate, missing=missing):
234 return _('uncommitted changes in subrepository "%s"'
236 return _('uncommitted changes in subrepository "%s"'
235 ) % subrelpath(self)
237 ) % subrelpath(self)
236
238
237 def bailifchanged(self, ignoreupdate=False, hint=None):
239 def bailifchanged(self, ignoreupdate=False, hint=None):
238 """raise Abort if subrepository is ``dirty()``
240 """raise Abort if subrepository is ``dirty()``
239 """
241 """
240 dirtyreason = self.dirtyreason(ignoreupdate=ignoreupdate,
242 dirtyreason = self.dirtyreason(ignoreupdate=ignoreupdate,
241 missing=True)
243 missing=True)
242 if dirtyreason:
244 if dirtyreason:
243 raise error.Abort(dirtyreason, hint=hint)
245 raise error.Abort(dirtyreason, hint=hint)
244
246
245 def basestate(self):
247 def basestate(self):
246 """current working directory base state, disregarding .hgsubstate
248 """current working directory base state, disregarding .hgsubstate
247 state and working directory modifications"""
249 state and working directory modifications"""
248 raise NotImplementedError
250 raise NotImplementedError
249
251
250 def checknested(self, path):
252 def checknested(self, path):
251 """check if path is a subrepository within this repository"""
253 """check if path is a subrepository within this repository"""
252 return False
254 return False
253
255
254 def commit(self, text, user, date):
256 def commit(self, text, user, date):
255 """commit the current changes to the subrepo with the given
257 """commit the current changes to the subrepo with the given
256 log message. Use given user and date if possible. Return the
258 log message. Use given user and date if possible. Return the
257 new state of the subrepo.
259 new state of the subrepo.
258 """
260 """
259 raise NotImplementedError
261 raise NotImplementedError
260
262
261 def phase(self, state):
263 def phase(self, state):
262 """returns phase of specified state in the subrepository.
264 """returns phase of specified state in the subrepository.
263 """
265 """
264 return phases.public
266 return phases.public
265
267
266 def remove(self):
268 def remove(self):
267 """remove the subrepo
269 """remove the subrepo
268
270
269 (should verify the dirstate is not dirty first)
271 (should verify the dirstate is not dirty first)
270 """
272 """
271 raise NotImplementedError
273 raise NotImplementedError
272
274
273 def get(self, state, overwrite=False):
275 def get(self, state, overwrite=False):
274 """run whatever commands are needed to put the subrepo into
276 """run whatever commands are needed to put the subrepo into
275 this state
277 this state
276 """
278 """
277 raise NotImplementedError
279 raise NotImplementedError
278
280
279 def merge(self, state):
281 def merge(self, state):
280 """merge currently-saved state with the new state."""
282 """merge currently-saved state with the new state."""
281 raise NotImplementedError
283 raise NotImplementedError
282
284
283 def push(self, opts):
285 def push(self, opts):
284 """perform whatever action is analogous to 'hg push'
286 """perform whatever action is analogous to 'hg push'
285
287
286 This may be a no-op on some systems.
288 This may be a no-op on some systems.
287 """
289 """
288 raise NotImplementedError
290 raise NotImplementedError
289
291
290 def add(self, ui, match, prefix, uipathfn, explicitonly, **opts):
292 def add(self, ui, match, prefix, uipathfn, explicitonly, **opts):
291 return []
293 return []
292
294
293 def addremove(self, matcher, prefix, uipathfn, opts):
295 def addremove(self, matcher, prefix, uipathfn, opts):
294 self.ui.warn("%s: %s" % (prefix, _("addremove is not supported")))
296 self.ui.warn("%s: %s" % (prefix, _("addremove is not supported")))
295 return 1
297 return 1
296
298
297 def cat(self, match, fm, fntemplate, prefix, **opts):
299 def cat(self, match, fm, fntemplate, prefix, **opts):
298 return 1
300 return 1
299
301
300 def status(self, rev2, **opts):
302 def status(self, rev2, **opts):
301 return scmutil.status([], [], [], [], [], [], [])
303 return scmutil.status([], [], [], [], [], [], [])
302
304
303 def diff(self, ui, diffopts, node2, match, prefix, **opts):
305 def diff(self, ui, diffopts, node2, match, prefix, **opts):
304 pass
306 pass
305
307
306 def outgoing(self, ui, dest, opts):
308 def outgoing(self, ui, dest, opts):
307 return 1
309 return 1
308
310
309 def incoming(self, ui, source, opts):
311 def incoming(self, ui, source, opts):
310 return 1
312 return 1
311
313
312 def files(self):
314 def files(self):
313 """return filename iterator"""
315 """return filename iterator"""
314 raise NotImplementedError
316 raise NotImplementedError
315
317
316 def filedata(self, name, decode):
318 def filedata(self, name, decode):
317 """return file data, optionally passed through repo decoders"""
319 """return file data, optionally passed through repo decoders"""
318 raise NotImplementedError
320 raise NotImplementedError
319
321
320 def fileflags(self, name):
322 def fileflags(self, name):
321 """return file flags"""
323 """return file flags"""
322 return ''
324 return ''
323
325
324 def matchfileset(self, expr, badfn=None):
326 def matchfileset(self, expr, badfn=None):
325 """Resolve the fileset expression for this repo"""
327 """Resolve the fileset expression for this repo"""
326 return matchmod.never(badfn=badfn)
328 return matchmod.never(badfn=badfn)
327
329
328 def printfiles(self, ui, m, uipathfn, fm, fmt, subrepos):
330 def printfiles(self, ui, m, uipathfn, fm, fmt, subrepos):
329 """handle the files command for this subrepo"""
331 """handle the files command for this subrepo"""
330 return 1
332 return 1
331
333
332 def archive(self, archiver, prefix, match=None, decode=True):
334 def archive(self, archiver, prefix, match=None, decode=True):
333 if match is not None:
335 if match is not None:
334 files = [f for f in self.files() if match(f)]
336 files = [f for f in self.files() if match(f)]
335 else:
337 else:
336 files = self.files()
338 files = self.files()
337 total = len(files)
339 total = len(files)
338 relpath = subrelpath(self)
340 relpath = subrelpath(self)
339 progress = self.ui.makeprogress(_('archiving (%s)') % relpath,
341 progress = self.ui.makeprogress(_('archiving (%s)') % relpath,
340 unit=_('files'), total=total)
342 unit=_('files'), total=total)
341 progress.update(0)
343 progress.update(0)
342 for name in files:
344 for name in files:
343 flags = self.fileflags(name)
345 flags = self.fileflags(name)
344 mode = 'x' in flags and 0o755 or 0o644
346 mode = 'x' in flags and 0o755 or 0o644
345 symlink = 'l' in flags
347 symlink = 'l' in flags
346 archiver.addfile(prefix + name, mode, symlink,
348 archiver.addfile(prefix + name, mode, symlink,
347 self.filedata(name, decode))
349 self.filedata(name, decode))
348 progress.increment()
350 progress.increment()
349 progress.complete()
351 progress.complete()
350 return total
352 return total
351
353
352 def walk(self, match):
354 def walk(self, match):
353 '''
355 '''
354 walk recursively through the directory tree, finding all files
356 walk recursively through the directory tree, finding all files
355 matched by the match function
357 matched by the match function
356 '''
358 '''
357
359
358 def forget(self, match, prefix, uipathfn, dryrun, interactive):
360 def forget(self, match, prefix, uipathfn, dryrun, interactive):
359 return ([], [])
361 return ([], [])
360
362
361 def removefiles(self, matcher, prefix, uipathfn, after, force, subrepos,
363 def removefiles(self, matcher, prefix, uipathfn, after, force, subrepos,
362 dryrun, warnings):
364 dryrun, warnings):
363 """remove the matched files from the subrepository and the filesystem,
365 """remove the matched files from the subrepository and the filesystem,
364 possibly by force and/or after the file has been removed from the
366 possibly by force and/or after the file has been removed from the
365 filesystem. Return 0 on success, 1 on any warning.
367 filesystem. Return 0 on success, 1 on any warning.
366 """
368 """
367 warnings.append(_("warning: removefiles not implemented (%s)")
369 warnings.append(_("warning: removefiles not implemented (%s)")
368 % self._path)
370 % self._path)
369 return 1
371 return 1
370
372
371 def revert(self, substate, *pats, **opts):
373 def revert(self, substate, *pats, **opts):
372 self.ui.warn(_('%s: reverting %s subrepos is unsupported\n')
374 self.ui.warn(_('%s: reverting %s subrepos is unsupported\n')
373 % (substate[0], substate[2]))
375 % (substate[0], substate[2]))
374 return []
376 return []
375
377
376 def shortid(self, revid):
378 def shortid(self, revid):
377 return revid
379 return revid
378
380
379 def unshare(self):
381 def unshare(self):
380 '''
382 '''
381 convert this repository from shared to normal storage.
383 convert this repository from shared to normal storage.
382 '''
384 '''
383
385
384 def verify(self):
386 def verify(self):
385 '''verify the integrity of the repository. Return 0 on success or
387 '''verify the integrity of the repository. Return 0 on success or
386 warning, 1 on any error.
388 warning, 1 on any error.
387 '''
389 '''
388 return 0
390 return 0
389
391
390 @propertycache
392 @propertycache
391 def wvfs(self):
393 def wvfs(self):
392 """return vfs to access the working directory of this subrepository
394 """return vfs to access the working directory of this subrepository
393 """
395 """
394 return vfsmod.vfs(self._ctx.repo().wvfs.join(self._path))
396 return vfsmod.vfs(self._ctx.repo().wvfs.join(self._path))
395
397
396 @propertycache
398 @propertycache
397 def _relpath(self):
399 def _relpath(self):
398 """return path to this subrepository as seen from outermost repository
400 """return path to this subrepository as seen from outermost repository
399 """
401 """
400 return self.wvfs.reljoin(reporelpath(self._ctx.repo()), self._path)
402 return self.wvfs.reljoin(reporelpath(self._ctx.repo()), self._path)
401
403
402 class hgsubrepo(abstractsubrepo):
404 class hgsubrepo(abstractsubrepo):
403 def __init__(self, ctx, path, state, allowcreate):
405 def __init__(self, ctx, path, state, allowcreate):
404 super(hgsubrepo, self).__init__(ctx, path)
406 super(hgsubrepo, self).__init__(ctx, path)
405 self._state = state
407 self._state = state
406 r = ctx.repo()
408 r = ctx.repo()
407 root = r.wjoin(util.localpath(path))
409 root = r.wjoin(util.localpath(path))
408 create = allowcreate and not r.wvfs.exists('%s/.hg' % path)
410 create = allowcreate and not r.wvfs.exists('%s/.hg' % path)
409 # repository constructor does expand variables in path, which is
411 # repository constructor does expand variables in path, which is
410 # unsafe since subrepo path might come from untrusted source.
412 # unsafe since subrepo path might come from untrusted source.
411 if os.path.realpath(util.expandpath(root)) != root:
413 if os.path.realpath(util.expandpath(root)) != root:
412 raise error.Abort(_('subrepo path contains illegal component: %s')
414 raise error.Abort(_('subrepo path contains illegal component: %s')
413 % path)
415 % path)
414 self._repo = hg.repository(r.baseui, root, create=create)
416 self._repo = hg.repository(r.baseui, root, create=create)
415 if self._repo.root != root:
417 if self._repo.root != root:
416 raise error.ProgrammingError('failed to reject unsafe subrepo '
418 raise error.ProgrammingError('failed to reject unsafe subrepo '
417 'path: %s (expanded to %s)'
419 'path: %s (expanded to %s)'
418 % (root, self._repo.root))
420 % (root, self._repo.root))
419
421
420 # Propagate the parent's --hidden option
422 # Propagate the parent's --hidden option
421 if r is r.unfiltered():
423 if r is r.unfiltered():
422 self._repo = self._repo.unfiltered()
424 self._repo = self._repo.unfiltered()
423
425
424 self.ui = self._repo.ui
426 self.ui = self._repo.ui
425 for s, k in [('ui', 'commitsubrepos')]:
427 for s, k in [('ui', 'commitsubrepos')]:
426 v = r.ui.config(s, k)
428 v = r.ui.config(s, k)
427 if v:
429 if v:
428 self.ui.setconfig(s, k, v, 'subrepo')
430 self.ui.setconfig(s, k, v, 'subrepo')
429 # internal config: ui._usedassubrepo
431 # internal config: ui._usedassubrepo
430 self.ui.setconfig('ui', '_usedassubrepo', 'True', 'subrepo')
432 self.ui.setconfig('ui', '_usedassubrepo', 'True', 'subrepo')
431 self._initrepo(r, state[0], create)
433 self._initrepo(r, state[0], create)
432
434
433 @annotatesubrepoerror
435 @annotatesubrepoerror
434 def addwebdirpath(self, serverpath, webconf):
436 def addwebdirpath(self, serverpath, webconf):
435 cmdutil.addwebdirpath(self._repo, subrelpath(self), webconf)
437 cmdutil.addwebdirpath(self._repo, subrelpath(self), webconf)
436
438
437 def storeclean(self, path):
439 def storeclean(self, path):
438 with self._repo.lock():
440 with self._repo.lock():
439 return self._storeclean(path)
441 return self._storeclean(path)
440
442
441 def _storeclean(self, path):
443 def _storeclean(self, path):
442 clean = True
444 clean = True
443 itercache = self._calcstorehash(path)
445 itercache = self._calcstorehash(path)
444 for filehash in self._readstorehashcache(path):
446 for filehash in self._readstorehashcache(path):
445 if filehash != next(itercache, None):
447 if filehash != next(itercache, None):
446 clean = False
448 clean = False
447 break
449 break
448 if clean:
450 if clean:
449 # if not empty:
451 # if not empty:
450 # the cached and current pull states have a different size
452 # the cached and current pull states have a different size
451 clean = next(itercache, None) is None
453 clean = next(itercache, None) is None
452 return clean
454 return clean
453
455
454 def _calcstorehash(self, remotepath):
456 def _calcstorehash(self, remotepath):
455 '''calculate a unique "store hash"
457 '''calculate a unique "store hash"
456
458
457 This method is used to to detect when there are changes that may
459 This method is used to to detect when there are changes that may
458 require a push to a given remote path.'''
460 require a push to a given remote path.'''
459 # sort the files that will be hashed in increasing (likely) file size
461 # sort the files that will be hashed in increasing (likely) file size
460 filelist = ('bookmarks', 'store/phaseroots', 'store/00changelog.i')
462 filelist = ('bookmarks', 'store/phaseroots', 'store/00changelog.i')
461 yield '# %s\n' % _expandedabspath(remotepath)
463 yield '# %s\n' % _expandedabspath(remotepath)
462 vfs = self._repo.vfs
464 vfs = self._repo.vfs
463 for relname in filelist:
465 for relname in filelist:
464 filehash = node.hex(hashlib.sha1(vfs.tryread(relname)).digest())
466 filehash = node.hex(hashlib.sha1(vfs.tryread(relname)).digest())
465 yield '%s = %s\n' % (relname, filehash)
467 yield '%s = %s\n' % (relname, filehash)
466
468
467 @propertycache
469 @propertycache
468 def _cachestorehashvfs(self):
470 def _cachestorehashvfs(self):
469 return vfsmod.vfs(self._repo.vfs.join('cache/storehash'))
471 return vfsmod.vfs(self._repo.vfs.join('cache/storehash'))
470
472
471 def _readstorehashcache(self, remotepath):
473 def _readstorehashcache(self, remotepath):
472 '''read the store hash cache for a given remote repository'''
474 '''read the store hash cache for a given remote repository'''
473 cachefile = _getstorehashcachename(remotepath)
475 cachefile = _getstorehashcachename(remotepath)
474 return self._cachestorehashvfs.tryreadlines(cachefile, 'r')
476 return self._cachestorehashvfs.tryreadlines(cachefile, 'r')
475
477
476 def _cachestorehash(self, remotepath):
478 def _cachestorehash(self, remotepath):
477 '''cache the current store hash
479 '''cache the current store hash
478
480
479 Each remote repo requires its own store hash cache, because a subrepo
481 Each remote repo requires its own store hash cache, because a subrepo
480 store may be "clean" versus a given remote repo, but not versus another
482 store may be "clean" versus a given remote repo, but not versus another
481 '''
483 '''
482 cachefile = _getstorehashcachename(remotepath)
484 cachefile = _getstorehashcachename(remotepath)
483 with self._repo.lock():
485 with self._repo.lock():
484 storehash = list(self._calcstorehash(remotepath))
486 storehash = list(self._calcstorehash(remotepath))
485 vfs = self._cachestorehashvfs
487 vfs = self._cachestorehashvfs
486 vfs.writelines(cachefile, storehash, mode='wb', notindexed=True)
488 vfs.writelines(cachefile, storehash, mode='wb', notindexed=True)
487
489
488 def _getctx(self):
490 def _getctx(self):
489 '''fetch the context for this subrepo revision, possibly a workingctx
491 '''fetch the context for this subrepo revision, possibly a workingctx
490 '''
492 '''
491 if self._ctx.rev() is None:
493 if self._ctx.rev() is None:
492 return self._repo[None] # workingctx if parent is workingctx
494 return self._repo[None] # workingctx if parent is workingctx
493 else:
495 else:
494 rev = self._state[1]
496 rev = self._state[1]
495 return self._repo[rev]
497 return self._repo[rev]
496
498
497 @annotatesubrepoerror
499 @annotatesubrepoerror
498 def _initrepo(self, parentrepo, source, create):
500 def _initrepo(self, parentrepo, source, create):
499 self._repo._subparent = parentrepo
501 self._repo._subparent = parentrepo
500 self._repo._subsource = source
502 self._repo._subsource = source
501
503
502 if create:
504 if create:
503 lines = ['[paths]\n']
505 lines = ['[paths]\n']
504
506
505 def addpathconfig(key, value):
507 def addpathconfig(key, value):
506 if value:
508 if value:
507 lines.append('%s = %s\n' % (key, value))
509 lines.append('%s = %s\n' % (key, value))
508 self.ui.setconfig('paths', key, value, 'subrepo')
510 self.ui.setconfig('paths', key, value, 'subrepo')
509
511
510 defpath = _abssource(self._repo, abort=False)
512 defpath = _abssource(self._repo, abort=False)
511 defpushpath = _abssource(self._repo, True, abort=False)
513 defpushpath = _abssource(self._repo, True, abort=False)
512 addpathconfig('default', defpath)
514 addpathconfig('default', defpath)
513 if defpath != defpushpath:
515 if defpath != defpushpath:
514 addpathconfig('default-push', defpushpath)
516 addpathconfig('default-push', defpushpath)
515
517
516 self._repo.vfs.write('hgrc', util.tonativeeol(''.join(lines)))
518 self._repo.vfs.write('hgrc', util.tonativeeol(''.join(lines)))
517
519
518 @annotatesubrepoerror
520 @annotatesubrepoerror
519 def add(self, ui, match, prefix, uipathfn, explicitonly, **opts):
521 def add(self, ui, match, prefix, uipathfn, explicitonly, **opts):
520 return cmdutil.add(ui, self._repo, match, prefix, uipathfn,
522 return cmdutil.add(ui, self._repo, match, prefix, uipathfn,
521 explicitonly, **opts)
523 explicitonly, **opts)
522
524
523 @annotatesubrepoerror
525 @annotatesubrepoerror
524 def addremove(self, m, prefix, uipathfn, opts):
526 def addremove(self, m, prefix, uipathfn, opts):
525 # In the same way as sub directories are processed, once in a subrepo,
527 # In the same way as sub directories are processed, once in a subrepo,
526 # always entry any of its subrepos. Don't corrupt the options that will
528 # always entry any of its subrepos. Don't corrupt the options that will
527 # be used to process sibling subrepos however.
529 # be used to process sibling subrepos however.
528 opts = copy.copy(opts)
530 opts = copy.copy(opts)
529 opts['subrepos'] = True
531 opts['subrepos'] = True
530 return scmutil.addremove(self._repo, m, prefix, uipathfn, opts)
532 return scmutil.addremove(self._repo, m, prefix, uipathfn, opts)
531
533
532 @annotatesubrepoerror
534 @annotatesubrepoerror
533 def cat(self, match, fm, fntemplate, prefix, **opts):
535 def cat(self, match, fm, fntemplate, prefix, **opts):
534 rev = self._state[1]
536 rev = self._state[1]
535 ctx = self._repo[rev]
537 ctx = self._repo[rev]
536 return cmdutil.cat(self.ui, self._repo, ctx, match, fm, fntemplate,
538 return cmdutil.cat(self.ui, self._repo, ctx, match, fm, fntemplate,
537 prefix, **opts)
539 prefix, **opts)
538
540
539 @annotatesubrepoerror
541 @annotatesubrepoerror
540 def status(self, rev2, **opts):
542 def status(self, rev2, **opts):
541 try:
543 try:
542 rev1 = self._state[1]
544 rev1 = self._state[1]
543 ctx1 = self._repo[rev1]
545 ctx1 = self._repo[rev1]
544 ctx2 = self._repo[rev2]
546 ctx2 = self._repo[rev2]
545 return self._repo.status(ctx1, ctx2, **opts)
547 return self._repo.status(ctx1, ctx2, **opts)
546 except error.RepoLookupError as inst:
548 except error.RepoLookupError as inst:
547 self.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
549 self.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
548 % (inst, subrelpath(self)))
550 % (inst, subrelpath(self)))
549 return scmutil.status([], [], [], [], [], [], [])
551 return scmutil.status([], [], [], [], [], [], [])
550
552
551 @annotatesubrepoerror
553 @annotatesubrepoerror
552 def diff(self, ui, diffopts, node2, match, prefix, **opts):
554 def diff(self, ui, diffopts, node2, match, prefix, **opts):
553 try:
555 try:
554 node1 = node.bin(self._state[1])
556 node1 = node.bin(self._state[1])
555 # We currently expect node2 to come from substate and be
557 # We currently expect node2 to come from substate and be
556 # in hex format
558 # in hex format
557 if node2 is not None:
559 if node2 is not None:
558 node2 = node.bin(node2)
560 node2 = node.bin(node2)
559 logcmdutil.diffordiffstat(ui, self._repo, diffopts, node1, node2,
561 logcmdutil.diffordiffstat(ui, self._repo, diffopts, node1, node2,
560 match, prefix=prefix, listsubrepos=True,
562 match, prefix=prefix, listsubrepos=True,
561 **opts)
563 **opts)
562 except error.RepoLookupError as inst:
564 except error.RepoLookupError as inst:
563 self.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
565 self.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
564 % (inst, subrelpath(self)))
566 % (inst, subrelpath(self)))
565
567
566 @annotatesubrepoerror
568 @annotatesubrepoerror
567 def archive(self, archiver, prefix, match=None, decode=True):
569 def archive(self, archiver, prefix, match=None, decode=True):
568 self._get(self._state + ('hg',))
570 self._get(self._state + ('hg',))
569 files = self.files()
571 files = self.files()
570 if match:
572 if match:
571 files = [f for f in files if match(f)]
573 files = [f for f in files if match(f)]
572 rev = self._state[1]
574 rev = self._state[1]
573 ctx = self._repo[rev]
575 ctx = self._repo[rev]
574 scmutil.prefetchfiles(self._repo, [ctx.rev()],
576 scmutil.prefetchfiles(self._repo, [ctx.rev()],
575 scmutil.matchfiles(self._repo, files))
577 scmutil.matchfiles(self._repo, files))
576 total = abstractsubrepo.archive(self, archiver, prefix, match)
578 total = abstractsubrepo.archive(self, archiver, prefix, match)
577 for subpath in ctx.substate:
579 for subpath in ctx.substate:
578 s = subrepo(ctx, subpath, True)
580 s = subrepo(ctx, subpath, True)
579 submatch = matchmod.subdirmatcher(subpath, match)
581 submatch = matchmod.subdirmatcher(subpath, match)
580 subprefix = prefix + subpath + '/'
582 subprefix = prefix + subpath + '/'
581 total += s.archive(archiver, subprefix, submatch,
583 total += s.archive(archiver, subprefix, submatch,
582 decode)
584 decode)
583 return total
585 return total
584
586
585 @annotatesubrepoerror
587 @annotatesubrepoerror
586 def dirty(self, ignoreupdate=False, missing=False):
588 def dirty(self, ignoreupdate=False, missing=False):
587 r = self._state[1]
589 r = self._state[1]
588 if r == '' and not ignoreupdate: # no state recorded
590 if r == '' and not ignoreupdate: # no state recorded
589 return True
591 return True
590 w = self._repo[None]
592 w = self._repo[None]
591 if r != w.p1().hex() and not ignoreupdate:
593 if r != w.p1().hex() and not ignoreupdate:
592 # different version checked out
594 # different version checked out
593 return True
595 return True
594 return w.dirty(missing=missing) # working directory changed
596 return w.dirty(missing=missing) # working directory changed
595
597
596 def basestate(self):
598 def basestate(self):
597 return self._repo['.'].hex()
599 return self._repo['.'].hex()
598
600
599 def checknested(self, path):
601 def checknested(self, path):
600 return self._repo._checknested(self._repo.wjoin(path))
602 return self._repo._checknested(self._repo.wjoin(path))
601
603
602 @annotatesubrepoerror
604 @annotatesubrepoerror
603 def commit(self, text, user, date):
605 def commit(self, text, user, date):
604 # don't bother committing in the subrepo if it's only been
606 # don't bother committing in the subrepo if it's only been
605 # updated
607 # updated
606 if not self.dirty(True):
608 if not self.dirty(True):
607 return self._repo['.'].hex()
609 return self._repo['.'].hex()
608 self.ui.debug("committing subrepo %s\n" % subrelpath(self))
610 self.ui.debug("committing subrepo %s\n" % subrelpath(self))
609 n = self._repo.commit(text, user, date)
611 n = self._repo.commit(text, user, date)
610 if not n:
612 if not n:
611 return self._repo['.'].hex() # different version checked out
613 return self._repo['.'].hex() # different version checked out
612 return node.hex(n)
614 return node.hex(n)
613
615
614 @annotatesubrepoerror
616 @annotatesubrepoerror
615 def phase(self, state):
617 def phase(self, state):
616 return self._repo[state or '.'].phase()
618 return self._repo[state or '.'].phase()
617
619
618 @annotatesubrepoerror
620 @annotatesubrepoerror
619 def remove(self):
621 def remove(self):
620 # we can't fully delete the repository as it may contain
622 # we can't fully delete the repository as it may contain
621 # local-only history
623 # local-only history
622 self.ui.note(_('removing subrepo %s\n') % subrelpath(self))
624 self.ui.note(_('removing subrepo %s\n') % subrelpath(self))
623 hg.clean(self._repo, node.nullid, False)
625 hg.clean(self._repo, node.nullid, False)
624
626
625 def _get(self, state):
627 def _get(self, state):
626 source, revision, kind = state
628 source, revision, kind = state
627 parentrepo = self._repo._subparent
629 parentrepo = self._repo._subparent
628
630
629 if revision in self._repo.unfiltered():
631 if revision in self._repo.unfiltered():
630 # Allow shared subrepos tracked at null to setup the sharedpath
632 # Allow shared subrepos tracked at null to setup the sharedpath
631 if len(self._repo) != 0 or not parentrepo.shared():
633 if len(self._repo) != 0 or not parentrepo.shared():
632 return True
634 return True
633 self._repo._subsource = source
635 self._repo._subsource = source
634 srcurl = _abssource(self._repo)
636 srcurl = _abssource(self._repo)
635
637
636 # Defer creating the peer until after the status message is logged, in
638 # Defer creating the peer until after the status message is logged, in
637 # case there are network problems.
639 # case there are network problems.
638 getpeer = lambda: hg.peer(self._repo, {}, srcurl)
640 getpeer = lambda: hg.peer(self._repo, {}, srcurl)
639
641
640 if len(self._repo) == 0:
642 if len(self._repo) == 0:
641 # use self._repo.vfs instead of self.wvfs to remove .hg only
643 # use self._repo.vfs instead of self.wvfs to remove .hg only
642 self._repo.vfs.rmtree()
644 self._repo.vfs.rmtree()
643
645
644 # A remote subrepo could be shared if there is a local copy
646 # A remote subrepo could be shared if there is a local copy
645 # relative to the parent's share source. But clone pooling doesn't
647 # relative to the parent's share source. But clone pooling doesn't
646 # assemble the repos in a tree, so that can't be consistently done.
648 # assemble the repos in a tree, so that can't be consistently done.
647 # A simpler option is for the user to configure clone pooling, and
649 # A simpler option is for the user to configure clone pooling, and
648 # work with that.
650 # work with that.
649 if parentrepo.shared() and hg.islocal(srcurl):
651 if parentrepo.shared() and hg.islocal(srcurl):
650 self.ui.status(_('sharing subrepo %s from %s\n')
652 self.ui.status(_('sharing subrepo %s from %s\n')
651 % (subrelpath(self), srcurl))
653 % (subrelpath(self), srcurl))
652 shared = hg.share(self._repo._subparent.baseui,
654 shared = hg.share(self._repo._subparent.baseui,
653 getpeer(), self._repo.root,
655 getpeer(), self._repo.root,
654 update=False, bookmarks=False)
656 update=False, bookmarks=False)
655 self._repo = shared.local()
657 self._repo = shared.local()
656 else:
658 else:
657 # TODO: find a common place for this and this code in the
659 # TODO: find a common place for this and this code in the
658 # share.py wrap of the clone command.
660 # share.py wrap of the clone command.
659 if parentrepo.shared():
661 if parentrepo.shared():
660 pool = self.ui.config('share', 'pool')
662 pool = self.ui.config('share', 'pool')
661 if pool:
663 if pool:
662 pool = util.expandpath(pool)
664 pool = util.expandpath(pool)
663
665
664 shareopts = {
666 shareopts = {
665 'pool': pool,
667 'pool': pool,
666 'mode': self.ui.config('share', 'poolnaming'),
668 'mode': self.ui.config('share', 'poolnaming'),
667 }
669 }
668 else:
670 else:
669 shareopts = {}
671 shareopts = {}
670
672
671 self.ui.status(_('cloning subrepo %s from %s\n')
673 self.ui.status(_('cloning subrepo %s from %s\n')
672 % (subrelpath(self), util.hidepassword(srcurl)))
674 % (subrelpath(self), util.hidepassword(srcurl)))
673 other, cloned = hg.clone(self._repo._subparent.baseui, {},
675 other, cloned = hg.clone(self._repo._subparent.baseui, {},
674 getpeer(), self._repo.root,
676 getpeer(), self._repo.root,
675 update=False, shareopts=shareopts)
677 update=False, shareopts=shareopts)
676 self._repo = cloned.local()
678 self._repo = cloned.local()
677 self._initrepo(parentrepo, source, create=True)
679 self._initrepo(parentrepo, source, create=True)
678 self._cachestorehash(srcurl)
680 self._cachestorehash(srcurl)
679 else:
681 else:
680 self.ui.status(_('pulling subrepo %s from %s\n')
682 self.ui.status(_('pulling subrepo %s from %s\n')
681 % (subrelpath(self), util.hidepassword(srcurl)))
683 % (subrelpath(self), util.hidepassword(srcurl)))
682 cleansub = self.storeclean(srcurl)
684 cleansub = self.storeclean(srcurl)
683 exchange.pull(self._repo, getpeer())
685 exchange.pull(self._repo, getpeer())
684 if cleansub:
686 if cleansub:
685 # keep the repo clean after pull
687 # keep the repo clean after pull
686 self._cachestorehash(srcurl)
688 self._cachestorehash(srcurl)
687 return False
689 return False
688
690
689 @annotatesubrepoerror
691 @annotatesubrepoerror
690 def get(self, state, overwrite=False):
692 def get(self, state, overwrite=False):
691 inrepo = self._get(state)
693 inrepo = self._get(state)
692 source, revision, kind = state
694 source, revision, kind = state
693 repo = self._repo
695 repo = self._repo
694 repo.ui.debug("getting subrepo %s\n" % self._path)
696 repo.ui.debug("getting subrepo %s\n" % self._path)
695 if inrepo:
697 if inrepo:
696 urepo = repo.unfiltered()
698 urepo = repo.unfiltered()
697 ctx = urepo[revision]
699 ctx = urepo[revision]
698 if ctx.hidden():
700 if ctx.hidden():
699 urepo.ui.warn(
701 urepo.ui.warn(
700 _('revision %s in subrepository "%s" is hidden\n')
702 _('revision %s in subrepository "%s" is hidden\n')
701 % (revision[0:12], self._path))
703 % (revision[0:12], self._path))
702 repo = urepo
704 repo = urepo
703 hg.updaterepo(repo, revision, overwrite)
705 hg.updaterepo(repo, revision, overwrite)
704
706
705 @annotatesubrepoerror
707 @annotatesubrepoerror
706 def merge(self, state):
708 def merge(self, state):
707 self._get(state)
709 self._get(state)
708 cur = self._repo['.']
710 cur = self._repo['.']
709 dst = self._repo[state[1]]
711 dst = self._repo[state[1]]
710 anc = dst.ancestor(cur)
712 anc = dst.ancestor(cur)
711
713
712 def mergefunc():
714 def mergefunc():
713 if anc == cur and dst.branch() == cur.branch():
715 if anc == cur and dst.branch() == cur.branch():
714 self.ui.debug('updating subrepository "%s"\n'
716 self.ui.debug('updating subrepository "%s"\n'
715 % subrelpath(self))
717 % subrelpath(self))
716 hg.update(self._repo, state[1])
718 hg.update(self._repo, state[1])
717 elif anc == dst:
719 elif anc == dst:
718 self.ui.debug('skipping subrepository "%s"\n'
720 self.ui.debug('skipping subrepository "%s"\n'
719 % subrelpath(self))
721 % subrelpath(self))
720 else:
722 else:
721 self.ui.debug('merging subrepository "%s"\n' % subrelpath(self))
723 self.ui.debug('merging subrepository "%s"\n' % subrelpath(self))
722 hg.merge(self._repo, state[1], remind=False)
724 hg.merge(self._repo, state[1], remind=False)
723
725
724 wctx = self._repo[None]
726 wctx = self._repo[None]
725 if self.dirty():
727 if self.dirty():
726 if anc != dst:
728 if anc != dst:
727 if _updateprompt(self.ui, self, wctx.dirty(), cur, dst):
729 if _updateprompt(self.ui, self, wctx.dirty(), cur, dst):
728 mergefunc()
730 mergefunc()
729 else:
731 else:
730 mergefunc()
732 mergefunc()
731 else:
733 else:
732 mergefunc()
734 mergefunc()
733
735
734 @annotatesubrepoerror
736 @annotatesubrepoerror
735 def push(self, opts):
737 def push(self, opts):
736 force = opts.get('force')
738 force = opts.get('force')
737 newbranch = opts.get('new_branch')
739 newbranch = opts.get('new_branch')
738 ssh = opts.get('ssh')
740 ssh = opts.get('ssh')
739
741
740 # push subrepos depth-first for coherent ordering
742 # push subrepos depth-first for coherent ordering
741 c = self._repo['.']
743 c = self._repo['.']
742 subs = c.substate # only repos that are committed
744 subs = c.substate # only repos that are committed
743 for s in sorted(subs):
745 for s in sorted(subs):
744 if c.sub(s).push(opts) == 0:
746 if c.sub(s).push(opts) == 0:
745 return False
747 return False
746
748
747 dsturl = _abssource(self._repo, True)
749 dsturl = _abssource(self._repo, True)
748 if not force:
750 if not force:
749 if self.storeclean(dsturl):
751 if self.storeclean(dsturl):
750 self.ui.status(
752 self.ui.status(
751 _('no changes made to subrepo %s since last push to %s\n')
753 _('no changes made to subrepo %s since last push to %s\n')
752 % (subrelpath(self), util.hidepassword(dsturl)))
754 % (subrelpath(self), util.hidepassword(dsturl)))
753 return None
755 return None
754 self.ui.status(_('pushing subrepo %s to %s\n') %
756 self.ui.status(_('pushing subrepo %s to %s\n') %
755 (subrelpath(self), util.hidepassword(dsturl)))
757 (subrelpath(self), util.hidepassword(dsturl)))
756 other = hg.peer(self._repo, {'ssh': ssh}, dsturl)
758 other = hg.peer(self._repo, {'ssh': ssh}, dsturl)
757 res = exchange.push(self._repo, other, force, newbranch=newbranch)
759 res = exchange.push(self._repo, other, force, newbranch=newbranch)
758
760
759 # the repo is now clean
761 # the repo is now clean
760 self._cachestorehash(dsturl)
762 self._cachestorehash(dsturl)
761 return res.cgresult
763 return res.cgresult
762
764
763 @annotatesubrepoerror
765 @annotatesubrepoerror
764 def outgoing(self, ui, dest, opts):
766 def outgoing(self, ui, dest, opts):
765 if 'rev' in opts or 'branch' in opts:
767 if 'rev' in opts or 'branch' in opts:
766 opts = copy.copy(opts)
768 opts = copy.copy(opts)
767 opts.pop('rev', None)
769 opts.pop('rev', None)
768 opts.pop('branch', None)
770 opts.pop('branch', None)
769 return hg.outgoing(ui, self._repo, _abssource(self._repo, True), opts)
771 return hg.outgoing(ui, self._repo, _abssource(self._repo, True), opts)
770
772
771 @annotatesubrepoerror
773 @annotatesubrepoerror
772 def incoming(self, ui, source, opts):
774 def incoming(self, ui, source, opts):
773 if 'rev' in opts or 'branch' in opts:
775 if 'rev' in opts or 'branch' in opts:
774 opts = copy.copy(opts)
776 opts = copy.copy(opts)
775 opts.pop('rev', None)
777 opts.pop('rev', None)
776 opts.pop('branch', None)
778 opts.pop('branch', None)
777 return hg.incoming(ui, self._repo, _abssource(self._repo, False), opts)
779 return hg.incoming(ui, self._repo, _abssource(self._repo, False), opts)
778
780
779 @annotatesubrepoerror
781 @annotatesubrepoerror
780 def files(self):
782 def files(self):
781 rev = self._state[1]
783 rev = self._state[1]
782 ctx = self._repo[rev]
784 ctx = self._repo[rev]
783 return ctx.manifest().keys()
785 return ctx.manifest().keys()
784
786
785 def filedata(self, name, decode):
787 def filedata(self, name, decode):
786 rev = self._state[1]
788 rev = self._state[1]
787 data = self._repo[rev][name].data()
789 data = self._repo[rev][name].data()
788 if decode:
790 if decode:
789 data = self._repo.wwritedata(name, data)
791 data = self._repo.wwritedata(name, data)
790 return data
792 return data
791
793
792 def fileflags(self, name):
794 def fileflags(self, name):
793 rev = self._state[1]
795 rev = self._state[1]
794 ctx = self._repo[rev]
796 ctx = self._repo[rev]
795 return ctx.flags(name)
797 return ctx.flags(name)
796
798
797 @annotatesubrepoerror
799 @annotatesubrepoerror
798 def printfiles(self, ui, m, uipathfn, fm, fmt, subrepos):
800 def printfiles(self, ui, m, uipathfn, fm, fmt, subrepos):
799 # If the parent context is a workingctx, use the workingctx here for
801 # If the parent context is a workingctx, use the workingctx here for
800 # consistency.
802 # consistency.
801 if self._ctx.rev() is None:
803 if self._ctx.rev() is None:
802 ctx = self._repo[None]
804 ctx = self._repo[None]
803 else:
805 else:
804 rev = self._state[1]
806 rev = self._state[1]
805 ctx = self._repo[rev]
807 ctx = self._repo[rev]
806 return cmdutil.files(ui, ctx, m, uipathfn, fm, fmt, subrepos)
808 return cmdutil.files(ui, ctx, m, uipathfn, fm, fmt, subrepos)
807
809
808 @annotatesubrepoerror
810 @annotatesubrepoerror
809 def matchfileset(self, expr, badfn=None):
811 def matchfileset(self, expr, badfn=None):
810 if self._ctx.rev() is None:
812 if self._ctx.rev() is None:
811 ctx = self._repo[None]
813 ctx = self._repo[None]
812 else:
814 else:
813 rev = self._state[1]
815 rev = self._state[1]
814 ctx = self._repo[rev]
816 ctx = self._repo[rev]
815
817
816 matchers = [ctx.matchfileset(expr, badfn=badfn)]
818 matchers = [ctx.matchfileset(expr, badfn=badfn)]
817
819
818 for subpath in ctx.substate:
820 for subpath in ctx.substate:
819 sub = ctx.sub(subpath)
821 sub = ctx.sub(subpath)
820
822
821 try:
823 try:
822 sm = sub.matchfileset(expr, badfn=badfn)
824 sm = sub.matchfileset(expr, badfn=badfn)
823 pm = matchmod.prefixdirmatcher(subpath, sm, badfn=badfn)
825 pm = matchmod.prefixdirmatcher(subpath, sm, badfn=badfn)
824 matchers.append(pm)
826 matchers.append(pm)
825 except error.LookupError:
827 except error.LookupError:
826 self.ui.status(_("skipping missing subrepository: %s\n")
828 self.ui.status(_("skipping missing subrepository: %s\n")
827 % self.wvfs.reljoin(reporelpath(self), subpath))
829 % self.wvfs.reljoin(reporelpath(self), subpath))
828 if len(matchers) == 1:
830 if len(matchers) == 1:
829 return matchers[0]
831 return matchers[0]
830 return matchmod.unionmatcher(matchers)
832 return matchmod.unionmatcher(matchers)
831
833
832 def walk(self, match):
834 def walk(self, match):
833 ctx = self._repo[None]
835 ctx = self._repo[None]
834 return ctx.walk(match)
836 return ctx.walk(match)
835
837
836 @annotatesubrepoerror
838 @annotatesubrepoerror
837 def forget(self, match, prefix, uipathfn, dryrun, interactive):
839 def forget(self, match, prefix, uipathfn, dryrun, interactive):
838 return cmdutil.forget(self.ui, self._repo, match, prefix, uipathfn,
840 return cmdutil.forget(self.ui, self._repo, match, prefix, uipathfn,
839 True, dryrun=dryrun, interactive=interactive)
841 True, dryrun=dryrun, interactive=interactive)
840
842
841 @annotatesubrepoerror
843 @annotatesubrepoerror
842 def removefiles(self, matcher, prefix, uipathfn, after, force, subrepos,
844 def removefiles(self, matcher, prefix, uipathfn, after, force, subrepos,
843 dryrun, warnings):
845 dryrun, warnings):
844 return cmdutil.remove(self.ui, self._repo, matcher, prefix, uipathfn,
846 return cmdutil.remove(self.ui, self._repo, matcher, prefix, uipathfn,
845 after, force, subrepos, dryrun)
847 after, force, subrepos, dryrun)
846
848
847 @annotatesubrepoerror
849 @annotatesubrepoerror
848 def revert(self, substate, *pats, **opts):
850 def revert(self, substate, *pats, **opts):
849 # reverting a subrepo is a 2 step process:
851 # reverting a subrepo is a 2 step process:
850 # 1. if the no_backup is not set, revert all modified
852 # 1. if the no_backup is not set, revert all modified
851 # files inside the subrepo
853 # files inside the subrepo
852 # 2. update the subrepo to the revision specified in
854 # 2. update the subrepo to the revision specified in
853 # the corresponding substate dictionary
855 # the corresponding substate dictionary
854 self.ui.status(_('reverting subrepo %s\n') % substate[0])
856 self.ui.status(_('reverting subrepo %s\n') % substate[0])
855 if not opts.get(r'no_backup'):
857 if not opts.get(r'no_backup'):
856 # Revert all files on the subrepo, creating backups
858 # Revert all files on the subrepo, creating backups
857 # Note that this will not recursively revert subrepos
859 # Note that this will not recursively revert subrepos
858 # We could do it if there was a set:subrepos() predicate
860 # We could do it if there was a set:subrepos() predicate
859 opts = opts.copy()
861 opts = opts.copy()
860 opts[r'date'] = None
862 opts[r'date'] = None
861 opts[r'rev'] = substate[1]
863 opts[r'rev'] = substate[1]
862
864
863 self.filerevert(*pats, **opts)
865 self.filerevert(*pats, **opts)
864
866
865 # Update the repo to the revision specified in the given substate
867 # Update the repo to the revision specified in the given substate
866 if not opts.get(r'dry_run'):
868 if not opts.get(r'dry_run'):
867 self.get(substate, overwrite=True)
869 self.get(substate, overwrite=True)
868
870
869 def filerevert(self, *pats, **opts):
871 def filerevert(self, *pats, **opts):
870 ctx = self._repo[opts[r'rev']]
872 ctx = self._repo[opts[r'rev']]
871 parents = self._repo.dirstate.parents()
873 parents = self._repo.dirstate.parents()
872 if opts.get(r'all'):
874 if opts.get(r'all'):
873 pats = ['set:modified()']
875 pats = ['set:modified()']
874 else:
876 else:
875 pats = []
877 pats = []
876 cmdutil.revert(self.ui, self._repo, ctx, parents, *pats, **opts)
878 cmdutil.revert(self.ui, self._repo, ctx, parents, *pats, **opts)
877
879
878 def shortid(self, revid):
880 def shortid(self, revid):
879 return revid[:12]
881 return revid[:12]
880
882
881 @annotatesubrepoerror
883 @annotatesubrepoerror
882 def unshare(self):
884 def unshare(self):
883 # subrepo inherently violates our import layering rules
885 # subrepo inherently violates our import layering rules
884 # because it wants to make repo objects from deep inside the stack
886 # because it wants to make repo objects from deep inside the stack
885 # so we manually delay the circular imports to not break
887 # so we manually delay the circular imports to not break
886 # scripts that don't use our demand-loading
888 # scripts that don't use our demand-loading
887 global hg
889 global hg
888 from . import hg as h
890 from . import hg as h
889 hg = h
891 hg = h
890
892
891 # Nothing prevents a user from sharing in a repo, and then making that a
893 # Nothing prevents a user from sharing in a repo, and then making that a
892 # subrepo. Alternately, the previous unshare attempt may have failed
894 # subrepo. Alternately, the previous unshare attempt may have failed
893 # part way through. So recurse whether or not this layer is shared.
895 # part way through. So recurse whether or not this layer is shared.
894 if self._repo.shared():
896 if self._repo.shared():
895 self.ui.status(_("unsharing subrepo '%s'\n") % self._relpath)
897 self.ui.status(_("unsharing subrepo '%s'\n") % self._relpath)
896
898
897 hg.unshare(self.ui, self._repo)
899 hg.unshare(self.ui, self._repo)
898
900
899 def verify(self):
901 def verify(self):
900 try:
902 try:
901 rev = self._state[1]
903 rev = self._state[1]
902 ctx = self._repo.unfiltered()[rev]
904 ctx = self._repo.unfiltered()[rev]
903 if ctx.hidden():
905 if ctx.hidden():
904 # Since hidden revisions aren't pushed/pulled, it seems worth an
906 # Since hidden revisions aren't pushed/pulled, it seems worth an
905 # explicit warning.
907 # explicit warning.
906 ui = self._repo.ui
908 ui = self._repo.ui
907 ui.warn(_("subrepo '%s' is hidden in revision %s\n") %
909 ui.warn(_("subrepo '%s' is hidden in revision %s\n") %
908 (self._relpath, node.short(self._ctx.node())))
910 (self._relpath, node.short(self._ctx.node())))
909 return 0
911 return 0
910 except error.RepoLookupError:
912 except error.RepoLookupError:
911 # A missing subrepo revision may be a case of needing to pull it, so
913 # A missing subrepo revision may be a case of needing to pull it, so
912 # don't treat this as an error.
914 # don't treat this as an error.
913 self._repo.ui.warn(_("subrepo '%s' not found in revision %s\n") %
915 self._repo.ui.warn(_("subrepo '%s' not found in revision %s\n") %
914 (self._relpath, node.short(self._ctx.node())))
916 (self._relpath, node.short(self._ctx.node())))
915 return 0
917 return 0
916
918
917 @propertycache
919 @propertycache
918 def wvfs(self):
920 def wvfs(self):
919 """return own wvfs for efficiency and consistency
921 """return own wvfs for efficiency and consistency
920 """
922 """
921 return self._repo.wvfs
923 return self._repo.wvfs
922
924
923 @propertycache
925 @propertycache
924 def _relpath(self):
926 def _relpath(self):
925 """return path to this subrepository as seen from outermost repository
927 """return path to this subrepository as seen from outermost repository
926 """
928 """
927 # Keep consistent dir separators by avoiding vfs.join(self._path)
929 # Keep consistent dir separators by avoiding vfs.join(self._path)
928 return reporelpath(self._repo)
930 return reporelpath(self._repo)
929
931
930 class svnsubrepo(abstractsubrepo):
932 class svnsubrepo(abstractsubrepo):
931 def __init__(self, ctx, path, state, allowcreate):
933 def __init__(self, ctx, path, state, allowcreate):
932 super(svnsubrepo, self).__init__(ctx, path)
934 super(svnsubrepo, self).__init__(ctx, path)
933 self._state = state
935 self._state = state
934 self._exe = procutil.findexe('svn')
936 self._exe = procutil.findexe('svn')
935 if not self._exe:
937 if not self._exe:
936 raise error.Abort(_("'svn' executable not found for subrepo '%s'")
938 raise error.Abort(_("'svn' executable not found for subrepo '%s'")
937 % self._path)
939 % self._path)
938
940
939 def _svncommand(self, commands, filename='', failok=False):
941 def _svncommand(self, commands, filename='', failok=False):
940 cmd = [self._exe]
942 cmd = [self._exe]
941 extrakw = {}
943 extrakw = {}
942 if not self.ui.interactive():
944 if not self.ui.interactive():
943 # Making stdin be a pipe should prevent svn from behaving
945 # Making stdin be a pipe should prevent svn from behaving
944 # interactively even if we can't pass --non-interactive.
946 # interactively even if we can't pass --non-interactive.
945 extrakw[r'stdin'] = subprocess.PIPE
947 extrakw[r'stdin'] = subprocess.PIPE
946 # Starting in svn 1.5 --non-interactive is a global flag
948 # Starting in svn 1.5 --non-interactive is a global flag
947 # instead of being per-command, but we need to support 1.4 so
949 # instead of being per-command, but we need to support 1.4 so
948 # we have to be intelligent about what commands take
950 # we have to be intelligent about what commands take
949 # --non-interactive.
951 # --non-interactive.
950 if commands[0] in ('update', 'checkout', 'commit'):
952 if commands[0] in ('update', 'checkout', 'commit'):
951 cmd.append('--non-interactive')
953 cmd.append('--non-interactive')
952 cmd.extend(commands)
954 cmd.extend(commands)
953 if filename is not None:
955 if filename is not None:
954 path = self.wvfs.reljoin(self._ctx.repo().origroot,
956 path = self.wvfs.reljoin(self._ctx.repo().origroot,
955 self._path, filename)
957 self._path, filename)
956 cmd.append(path)
958 cmd.append(path)
957 env = dict(encoding.environ)
959 env = dict(encoding.environ)
958 # Avoid localized output, preserve current locale for everything else.
960 # Avoid localized output, preserve current locale for everything else.
959 lc_all = env.get('LC_ALL')
961 lc_all = env.get('LC_ALL')
960 if lc_all:
962 if lc_all:
961 env['LANG'] = lc_all
963 env['LANG'] = lc_all
962 del env['LC_ALL']
964 del env['LC_ALL']
963 env['LC_MESSAGES'] = 'C'
965 env['LC_MESSAGES'] = 'C'
964 p = subprocess.Popen(pycompat.rapply(procutil.tonativestr, cmd),
966 p = subprocess.Popen(pycompat.rapply(procutil.tonativestr, cmd),
965 bufsize=-1, close_fds=procutil.closefds,
967 bufsize=-1, close_fds=procutil.closefds,
966 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
968 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
967 env=procutil.tonativeenv(env), **extrakw)
969 env=procutil.tonativeenv(env), **extrakw)
968 stdout, stderr = map(util.fromnativeeol, p.communicate())
970 stdout, stderr = map(util.fromnativeeol, p.communicate())
969 stderr = stderr.strip()
971 stderr = stderr.strip()
970 if not failok:
972 if not failok:
971 if p.returncode:
973 if p.returncode:
972 raise error.Abort(stderr or 'exited with code %d'
974 raise error.Abort(stderr or 'exited with code %d'
973 % p.returncode)
975 % p.returncode)
974 if stderr:
976 if stderr:
975 self.ui.warn(stderr + '\n')
977 self.ui.warn(stderr + '\n')
976 return stdout, stderr
978 return stdout, stderr
977
979
978 @propertycache
980 @propertycache
979 def _svnversion(self):
981 def _svnversion(self):
980 output, err = self._svncommand(['--version', '--quiet'], filename=None)
982 output, err = self._svncommand(['--version', '--quiet'], filename=None)
981 m = re.search(br'^(\d+)\.(\d+)', output)
983 m = re.search(br'^(\d+)\.(\d+)', output)
982 if not m:
984 if not m:
983 raise error.Abort(_('cannot retrieve svn tool version'))
985 raise error.Abort(_('cannot retrieve svn tool version'))
984 return (int(m.group(1)), int(m.group(2)))
986 return (int(m.group(1)), int(m.group(2)))
985
987
986 def _svnmissing(self):
988 def _svnmissing(self):
987 return not self.wvfs.exists('.svn')
989 return not self.wvfs.exists('.svn')
988
990
989 def _wcrevs(self):
991 def _wcrevs(self):
990 # Get the working directory revision as well as the last
992 # Get the working directory revision as well as the last
991 # commit revision so we can compare the subrepo state with
993 # commit revision so we can compare the subrepo state with
992 # both. We used to store the working directory one.
994 # both. We used to store the working directory one.
993 output, err = self._svncommand(['info', '--xml'])
995 output, err = self._svncommand(['info', '--xml'])
994 doc = xml.dom.minidom.parseString(output)
996 doc = xml.dom.minidom.parseString(output)
995 entries = doc.getElementsByTagName(r'entry')
997 entries = doc.getElementsByTagName(r'entry')
996 lastrev, rev = '0', '0'
998 lastrev, rev = '0', '0'
997 if entries:
999 if entries:
998 rev = pycompat.bytestr(entries[0].getAttribute(r'revision')) or '0'
1000 rev = pycompat.bytestr(entries[0].getAttribute(r'revision')) or '0'
999 commits = entries[0].getElementsByTagName(r'commit')
1001 commits = entries[0].getElementsByTagName(r'commit')
1000 if commits:
1002 if commits:
1001 lastrev = pycompat.bytestr(
1003 lastrev = pycompat.bytestr(
1002 commits[0].getAttribute(r'revision')) or '0'
1004 commits[0].getAttribute(r'revision')) or '0'
1003 return (lastrev, rev)
1005 return (lastrev, rev)
1004
1006
1005 def _wcrev(self):
1007 def _wcrev(self):
1006 return self._wcrevs()[0]
1008 return self._wcrevs()[0]
1007
1009
1008 def _wcchanged(self):
1010 def _wcchanged(self):
1009 """Return (changes, extchanges, missing) where changes is True
1011 """Return (changes, extchanges, missing) where changes is True
1010 if the working directory was changed, extchanges is
1012 if the working directory was changed, extchanges is
1011 True if any of these changes concern an external entry and missing
1013 True if any of these changes concern an external entry and missing
1012 is True if any change is a missing entry.
1014 is True if any change is a missing entry.
1013 """
1015 """
1014 output, err = self._svncommand(['status', '--xml'])
1016 output, err = self._svncommand(['status', '--xml'])
1015 externals, changes, missing = [], [], []
1017 externals, changes, missing = [], [], []
1016 doc = xml.dom.minidom.parseString(output)
1018 doc = xml.dom.minidom.parseString(output)
1017 for e in doc.getElementsByTagName(r'entry'):
1019 for e in doc.getElementsByTagName(r'entry'):
1018 s = e.getElementsByTagName(r'wc-status')
1020 s = e.getElementsByTagName(r'wc-status')
1019 if not s:
1021 if not s:
1020 continue
1022 continue
1021 item = s[0].getAttribute(r'item')
1023 item = s[0].getAttribute(r'item')
1022 props = s[0].getAttribute(r'props')
1024 props = s[0].getAttribute(r'props')
1023 path = e.getAttribute(r'path').encode('utf8')
1025 path = e.getAttribute(r'path').encode('utf8')
1024 if item == r'external':
1026 if item == r'external':
1025 externals.append(path)
1027 externals.append(path)
1026 elif item == r'missing':
1028 elif item == r'missing':
1027 missing.append(path)
1029 missing.append(path)
1028 if (item not in (r'', r'normal', r'unversioned', r'external')
1030 if (item not in (r'', r'normal', r'unversioned', r'external')
1029 or props not in (r'', r'none', r'normal')):
1031 or props not in (r'', r'none', r'normal')):
1030 changes.append(path)
1032 changes.append(path)
1031 for path in changes:
1033 for path in changes:
1032 for ext in externals:
1034 for ext in externals:
1033 if path == ext or path.startswith(ext + pycompat.ossep):
1035 if path == ext or path.startswith(ext + pycompat.ossep):
1034 return True, True, bool(missing)
1036 return True, True, bool(missing)
1035 return bool(changes), False, bool(missing)
1037 return bool(changes), False, bool(missing)
1036
1038
1037 @annotatesubrepoerror
1039 @annotatesubrepoerror
1038 def dirty(self, ignoreupdate=False, missing=False):
1040 def dirty(self, ignoreupdate=False, missing=False):
1039 if self._svnmissing():
1041 if self._svnmissing():
1040 return self._state[1] != ''
1042 return self._state[1] != ''
1041 wcchanged = self._wcchanged()
1043 wcchanged = self._wcchanged()
1042 changed = wcchanged[0] or (missing and wcchanged[2])
1044 changed = wcchanged[0] or (missing and wcchanged[2])
1043 if not changed:
1045 if not changed:
1044 if self._state[1] in self._wcrevs() or ignoreupdate:
1046 if self._state[1] in self._wcrevs() or ignoreupdate:
1045 return False
1047 return False
1046 return True
1048 return True
1047
1049
1048 def basestate(self):
1050 def basestate(self):
1049 lastrev, rev = self._wcrevs()
1051 lastrev, rev = self._wcrevs()
1050 if lastrev != rev:
1052 if lastrev != rev:
1051 # Last committed rev is not the same than rev. We would
1053 # Last committed rev is not the same than rev. We would
1052 # like to take lastrev but we do not know if the subrepo
1054 # like to take lastrev but we do not know if the subrepo
1053 # URL exists at lastrev. Test it and fallback to rev it
1055 # URL exists at lastrev. Test it and fallback to rev it
1054 # is not there.
1056 # is not there.
1055 try:
1057 try:
1056 self._svncommand(['list', '%s@%s' % (self._state[0], lastrev)])
1058 self._svncommand(['list', '%s@%s' % (self._state[0], lastrev)])
1057 return lastrev
1059 return lastrev
1058 except error.Abort:
1060 except error.Abort:
1059 pass
1061 pass
1060 return rev
1062 return rev
1061
1063
1062 @annotatesubrepoerror
1064 @annotatesubrepoerror
1063 def commit(self, text, user, date):
1065 def commit(self, text, user, date):
1064 # user and date are out of our hands since svn is centralized
1066 # user and date are out of our hands since svn is centralized
1065 changed, extchanged, missing = self._wcchanged()
1067 changed, extchanged, missing = self._wcchanged()
1066 if not changed:
1068 if not changed:
1067 return self.basestate()
1069 return self.basestate()
1068 if extchanged:
1070 if extchanged:
1069 # Do not try to commit externals
1071 # Do not try to commit externals
1070 raise error.Abort(_('cannot commit svn externals'))
1072 raise error.Abort(_('cannot commit svn externals'))
1071 if missing:
1073 if missing:
1072 # svn can commit with missing entries but aborting like hg
1074 # svn can commit with missing entries but aborting like hg
1073 # seems a better approach.
1075 # seems a better approach.
1074 raise error.Abort(_('cannot commit missing svn entries'))
1076 raise error.Abort(_('cannot commit missing svn entries'))
1075 commitinfo, err = self._svncommand(['commit', '-m', text])
1077 commitinfo, err = self._svncommand(['commit', '-m', text])
1076 self.ui.status(commitinfo)
1078 self.ui.status(commitinfo)
1077 newrev = re.search('Committed revision ([0-9]+).', commitinfo)
1079 newrev = re.search('Committed revision ([0-9]+).', commitinfo)
1078 if not newrev:
1080 if not newrev:
1079 if not commitinfo.strip():
1081 if not commitinfo.strip():
1080 # Sometimes, our definition of "changed" differs from
1082 # Sometimes, our definition of "changed" differs from
1081 # svn one. For instance, svn ignores missing files
1083 # svn one. For instance, svn ignores missing files
1082 # when committing. If there are only missing files, no
1084 # when committing. If there are only missing files, no
1083 # commit is made, no output and no error code.
1085 # commit is made, no output and no error code.
1084 raise error.Abort(_('failed to commit svn changes'))
1086 raise error.Abort(_('failed to commit svn changes'))
1085 raise error.Abort(commitinfo.splitlines()[-1])
1087 raise error.Abort(commitinfo.splitlines()[-1])
1086 newrev = newrev.groups()[0]
1088 newrev = newrev.groups()[0]
1087 self.ui.status(self._svncommand(['update', '-r', newrev])[0])
1089 self.ui.status(self._svncommand(['update', '-r', newrev])[0])
1088 return newrev
1090 return newrev
1089
1091
1090 @annotatesubrepoerror
1092 @annotatesubrepoerror
1091 def remove(self):
1093 def remove(self):
1092 if self.dirty():
1094 if self.dirty():
1093 self.ui.warn(_('not removing repo %s because '
1095 self.ui.warn(_('not removing repo %s because '
1094 'it has changes.\n') % self._path)
1096 'it has changes.\n') % self._path)
1095 return
1097 return
1096 self.ui.note(_('removing subrepo %s\n') % self._path)
1098 self.ui.note(_('removing subrepo %s\n') % self._path)
1097
1099
1098 self.wvfs.rmtree(forcibly=True)
1100 self.wvfs.rmtree(forcibly=True)
1099 try:
1101 try:
1100 pwvfs = self._ctx.repo().wvfs
1102 pwvfs = self._ctx.repo().wvfs
1101 pwvfs.removedirs(pwvfs.dirname(self._path))
1103 pwvfs.removedirs(pwvfs.dirname(self._path))
1102 except OSError:
1104 except OSError:
1103 pass
1105 pass
1104
1106
1105 @annotatesubrepoerror
1107 @annotatesubrepoerror
1106 def get(self, state, overwrite=False):
1108 def get(self, state, overwrite=False):
1107 if overwrite:
1109 if overwrite:
1108 self._svncommand(['revert', '--recursive'])
1110 self._svncommand(['revert', '--recursive'])
1109 args = ['checkout']
1111 args = ['checkout']
1110 if self._svnversion >= (1, 5):
1112 if self._svnversion >= (1, 5):
1111 args.append('--force')
1113 args.append('--force')
1112 # The revision must be specified at the end of the URL to properly
1114 # The revision must be specified at the end of the URL to properly
1113 # update to a directory which has since been deleted and recreated.
1115 # update to a directory which has since been deleted and recreated.
1114 args.append('%s@%s' % (state[0], state[1]))
1116 args.append('%s@%s' % (state[0], state[1]))
1115
1117
1116 # SEC: check that the ssh url is safe
1118 # SEC: check that the ssh url is safe
1117 util.checksafessh(state[0])
1119 util.checksafessh(state[0])
1118
1120
1119 status, err = self._svncommand(args, failok=True)
1121 status, err = self._svncommand(args, failok=True)
1120 _sanitize(self.ui, self.wvfs, '.svn')
1122 _sanitize(self.ui, self.wvfs, '.svn')
1121 if not re.search('Checked out revision [0-9]+.', status):
1123 if not re.search('Checked out revision [0-9]+.', status):
1122 if ('is already a working copy for a different URL' in err
1124 if ('is already a working copy for a different URL' in err
1123 and (self._wcchanged()[:2] == (False, False))):
1125 and (self._wcchanged()[:2] == (False, False))):
1124 # obstructed but clean working copy, so just blow it away.
1126 # obstructed but clean working copy, so just blow it away.
1125 self.remove()
1127 self.remove()
1126 self.get(state, overwrite=False)
1128 self.get(state, overwrite=False)
1127 return
1129 return
1128 raise error.Abort((status or err).splitlines()[-1])
1130 raise error.Abort((status or err).splitlines()[-1])
1129 self.ui.status(status)
1131 self.ui.status(status)
1130
1132
1131 @annotatesubrepoerror
1133 @annotatesubrepoerror
1132 def merge(self, state):
1134 def merge(self, state):
1133 old = self._state[1]
1135 old = self._state[1]
1134 new = state[1]
1136 new = state[1]
1135 wcrev = self._wcrev()
1137 wcrev = self._wcrev()
1136 if new != wcrev:
1138 if new != wcrev:
1137 dirty = old == wcrev or self._wcchanged()[0]
1139 dirty = old == wcrev or self._wcchanged()[0]
1138 if _updateprompt(self.ui, self, dirty, wcrev, new):
1140 if _updateprompt(self.ui, self, dirty, wcrev, new):
1139 self.get(state, False)
1141 self.get(state, False)
1140
1142
1141 def push(self, opts):
1143 def push(self, opts):
1142 # push is a no-op for SVN
1144 # push is a no-op for SVN
1143 return True
1145 return True
1144
1146
1145 @annotatesubrepoerror
1147 @annotatesubrepoerror
1146 def files(self):
1148 def files(self):
1147 output = self._svncommand(['list', '--recursive', '--xml'])[0]
1149 output = self._svncommand(['list', '--recursive', '--xml'])[0]
1148 doc = xml.dom.minidom.parseString(output)
1150 doc = xml.dom.minidom.parseString(output)
1149 paths = []
1151 paths = []
1150 for e in doc.getElementsByTagName(r'entry'):
1152 for e in doc.getElementsByTagName(r'entry'):
1151 kind = pycompat.bytestr(e.getAttribute(r'kind'))
1153 kind = pycompat.bytestr(e.getAttribute(r'kind'))
1152 if kind != 'file':
1154 if kind != 'file':
1153 continue
1155 continue
1154 name = r''.join(c.data for c
1156 name = r''.join(c.data for c
1155 in e.getElementsByTagName(r'name')[0].childNodes
1157 in e.getElementsByTagName(r'name')[0].childNodes
1156 if c.nodeType == c.TEXT_NODE)
1158 if c.nodeType == c.TEXT_NODE)
1157 paths.append(name.encode('utf8'))
1159 paths.append(name.encode('utf8'))
1158 return paths
1160 return paths
1159
1161
1160 def filedata(self, name, decode):
1162 def filedata(self, name, decode):
1161 return self._svncommand(['cat'], name)[0]
1163 return self._svncommand(['cat'], name)[0]
1162
1164
1163
1165
1164 class gitsubrepo(abstractsubrepo):
1166 class gitsubrepo(abstractsubrepo):
1165 def __init__(self, ctx, path, state, allowcreate):
1167 def __init__(self, ctx, path, state, allowcreate):
1166 super(gitsubrepo, self).__init__(ctx, path)
1168 super(gitsubrepo, self).__init__(ctx, path)
1167 self._state = state
1169 self._state = state
1168 self._abspath = ctx.repo().wjoin(path)
1170 self._abspath = ctx.repo().wjoin(path)
1169 self._subparent = ctx.repo()
1171 self._subparent = ctx.repo()
1170 self._ensuregit()
1172 self._ensuregit()
1171
1173
1172 def _ensuregit(self):
1174 def _ensuregit(self):
1173 try:
1175 try:
1174 self._gitexecutable = 'git'
1176 self._gitexecutable = 'git'
1175 out, err = self._gitnodir(['--version'])
1177 out, err = self._gitnodir(['--version'])
1176 except OSError as e:
1178 except OSError as e:
1177 genericerror = _("error executing git for subrepo '%s': %s")
1179 genericerror = _("error executing git for subrepo '%s': %s")
1178 notfoundhint = _("check git is installed and in your PATH")
1180 notfoundhint = _("check git is installed and in your PATH")
1179 if e.errno != errno.ENOENT:
1181 if e.errno != errno.ENOENT:
1180 raise error.Abort(genericerror % (
1182 raise error.Abort(genericerror % (
1181 self._path, encoding.strtolocal(e.strerror)))
1183 self._path, encoding.strtolocal(e.strerror)))
1182 elif pycompat.iswindows:
1184 elif pycompat.iswindows:
1183 try:
1185 try:
1184 self._gitexecutable = 'git.cmd'
1186 self._gitexecutable = 'git.cmd'
1185 out, err = self._gitnodir(['--version'])
1187 out, err = self._gitnodir(['--version'])
1186 except OSError as e2:
1188 except OSError as e2:
1187 if e2.errno == errno.ENOENT:
1189 if e2.errno == errno.ENOENT:
1188 raise error.Abort(_("couldn't find 'git' or 'git.cmd'"
1190 raise error.Abort(_("couldn't find 'git' or 'git.cmd'"
1189 " for subrepo '%s'") % self._path,
1191 " for subrepo '%s'") % self._path,
1190 hint=notfoundhint)
1192 hint=notfoundhint)
1191 else:
1193 else:
1192 raise error.Abort(genericerror % (self._path,
1194 raise error.Abort(genericerror % (self._path,
1193 encoding.strtolocal(e2.strerror)))
1195 encoding.strtolocal(e2.strerror)))
1194 else:
1196 else:
1195 raise error.Abort(_("couldn't find git for subrepo '%s'")
1197 raise error.Abort(_("couldn't find git for subrepo '%s'")
1196 % self._path, hint=notfoundhint)
1198 % self._path, hint=notfoundhint)
1197 versionstatus = self._checkversion(out)
1199 versionstatus = self._checkversion(out)
1198 if versionstatus == 'unknown':
1200 if versionstatus == 'unknown':
1199 self.ui.warn(_('cannot retrieve git version\n'))
1201 self.ui.warn(_('cannot retrieve git version\n'))
1200 elif versionstatus == 'abort':
1202 elif versionstatus == 'abort':
1201 raise error.Abort(_('git subrepo requires at least 1.6.0 or later'))
1203 raise error.Abort(_('git subrepo requires at least 1.6.0 or later'))
1202 elif versionstatus == 'warning':
1204 elif versionstatus == 'warning':
1203 self.ui.warn(_('git subrepo requires at least 1.6.0 or later\n'))
1205 self.ui.warn(_('git subrepo requires at least 1.6.0 or later\n'))
1204
1206
1205 @staticmethod
1207 @staticmethod
1206 def _gitversion(out):
1208 def _gitversion(out):
1207 m = re.search(br'^git version (\d+)\.(\d+)\.(\d+)', out)
1209 m = re.search(br'^git version (\d+)\.(\d+)\.(\d+)', out)
1208 if m:
1210 if m:
1209 return (int(m.group(1)), int(m.group(2)), int(m.group(3)))
1211 return (int(m.group(1)), int(m.group(2)), int(m.group(3)))
1210
1212
1211 m = re.search(br'^git version (\d+)\.(\d+)', out)
1213 m = re.search(br'^git version (\d+)\.(\d+)', out)
1212 if m:
1214 if m:
1213 return (int(m.group(1)), int(m.group(2)), 0)
1215 return (int(m.group(1)), int(m.group(2)), 0)
1214
1216
1215 return -1
1217 return -1
1216
1218
1217 @staticmethod
1219 @staticmethod
1218 def _checkversion(out):
1220 def _checkversion(out):
1219 '''ensure git version is new enough
1221 '''ensure git version is new enough
1220
1222
1221 >>> _checkversion = gitsubrepo._checkversion
1223 >>> _checkversion = gitsubrepo._checkversion
1222 >>> _checkversion(b'git version 1.6.0')
1224 >>> _checkversion(b'git version 1.6.0')
1223 'ok'
1225 'ok'
1224 >>> _checkversion(b'git version 1.8.5')
1226 >>> _checkversion(b'git version 1.8.5')
1225 'ok'
1227 'ok'
1226 >>> _checkversion(b'git version 1.4.0')
1228 >>> _checkversion(b'git version 1.4.0')
1227 'abort'
1229 'abort'
1228 >>> _checkversion(b'git version 1.5.0')
1230 >>> _checkversion(b'git version 1.5.0')
1229 'warning'
1231 'warning'
1230 >>> _checkversion(b'git version 1.9-rc0')
1232 >>> _checkversion(b'git version 1.9-rc0')
1231 'ok'
1233 'ok'
1232 >>> _checkversion(b'git version 1.9.0.265.g81cdec2')
1234 >>> _checkversion(b'git version 1.9.0.265.g81cdec2')
1233 'ok'
1235 'ok'
1234 >>> _checkversion(b'git version 1.9.0.GIT')
1236 >>> _checkversion(b'git version 1.9.0.GIT')
1235 'ok'
1237 'ok'
1236 >>> _checkversion(b'git version 12345')
1238 >>> _checkversion(b'git version 12345')
1237 'unknown'
1239 'unknown'
1238 >>> _checkversion(b'no')
1240 >>> _checkversion(b'no')
1239 'unknown'
1241 'unknown'
1240 '''
1242 '''
1241 version = gitsubrepo._gitversion(out)
1243 version = gitsubrepo._gitversion(out)
1242 # git 1.4.0 can't work at all, but 1.5.X can in at least some cases,
1244 # git 1.4.0 can't work at all, but 1.5.X can in at least some cases,
1243 # despite the docstring comment. For now, error on 1.4.0, warn on
1245 # despite the docstring comment. For now, error on 1.4.0, warn on
1244 # 1.5.0 but attempt to continue.
1246 # 1.5.0 but attempt to continue.
1245 if version == -1:
1247 if version == -1:
1246 return 'unknown'
1248 return 'unknown'
1247 if version < (1, 5, 0):
1249 if version < (1, 5, 0):
1248 return 'abort'
1250 return 'abort'
1249 elif version < (1, 6, 0):
1251 elif version < (1, 6, 0):
1250 return 'warning'
1252 return 'warning'
1251 return 'ok'
1253 return 'ok'
1252
1254
1253 def _gitcommand(self, commands, env=None, stream=False):
1255 def _gitcommand(self, commands, env=None, stream=False):
1254 return self._gitdir(commands, env=env, stream=stream)[0]
1256 return self._gitdir(commands, env=env, stream=stream)[0]
1255
1257
1256 def _gitdir(self, commands, env=None, stream=False):
1258 def _gitdir(self, commands, env=None, stream=False):
1257 return self._gitnodir(commands, env=env, stream=stream,
1259 return self._gitnodir(commands, env=env, stream=stream,
1258 cwd=self._abspath)
1260 cwd=self._abspath)
1259
1261
1260 def _gitnodir(self, commands, env=None, stream=False, cwd=None):
1262 def _gitnodir(self, commands, env=None, stream=False, cwd=None):
1261 """Calls the git command
1263 """Calls the git command
1262
1264
1263 The methods tries to call the git command. versions prior to 1.6.0
1265 The methods tries to call the git command. versions prior to 1.6.0
1264 are not supported and very probably fail.
1266 are not supported and very probably fail.
1265 """
1267 """
1266 self.ui.debug('%s: git %s\n' % (self._relpath, ' '.join(commands)))
1268 self.ui.debug('%s: git %s\n' % (self._relpath, ' '.join(commands)))
1267 if env is None:
1269 if env is None:
1268 env = encoding.environ.copy()
1270 env = encoding.environ.copy()
1269 # disable localization for Git output (issue5176)
1271 # disable localization for Git output (issue5176)
1270 env['LC_ALL'] = 'C'
1272 env['LC_ALL'] = 'C'
1271 # fix for Git CVE-2015-7545
1273 # fix for Git CVE-2015-7545
1272 if 'GIT_ALLOW_PROTOCOL' not in env:
1274 if 'GIT_ALLOW_PROTOCOL' not in env:
1273 env['GIT_ALLOW_PROTOCOL'] = 'file:git:http:https:ssh'
1275 env['GIT_ALLOW_PROTOCOL'] = 'file:git:http:https:ssh'
1274 # unless ui.quiet is set, print git's stderr,
1276 # unless ui.quiet is set, print git's stderr,
1275 # which is mostly progress and useful info
1277 # which is mostly progress and useful info
1276 errpipe = None
1278 errpipe = None
1277 if self.ui.quiet:
1279 if self.ui.quiet:
1278 errpipe = open(os.devnull, 'w')
1280 errpipe = open(os.devnull, 'w')
1279 if self.ui._colormode and len(commands) and commands[0] == "diff":
1281 if self.ui._colormode and len(commands) and commands[0] == "diff":
1280 # insert the argument in the front,
1282 # insert the argument in the front,
1281 # the end of git diff arguments is used for paths
1283 # the end of git diff arguments is used for paths
1282 commands.insert(1, '--color')
1284 commands.insert(1, '--color')
1283 p = subprocess.Popen(pycompat.rapply(procutil.tonativestr,
1285 p = subprocess.Popen(pycompat.rapply(procutil.tonativestr,
1284 [self._gitexecutable] + commands),
1286 [self._gitexecutable] + commands),
1285 bufsize=-1,
1287 bufsize=-1,
1286 cwd=pycompat.rapply(procutil.tonativestr, cwd),
1288 cwd=pycompat.rapply(procutil.tonativestr, cwd),
1287 env=procutil.tonativeenv(env),
1289 env=procutil.tonativeenv(env),
1288 close_fds=procutil.closefds,
1290 close_fds=procutil.closefds,
1289 stdout=subprocess.PIPE, stderr=errpipe)
1291 stdout=subprocess.PIPE, stderr=errpipe)
1290 if stream:
1292 if stream:
1291 return p.stdout, None
1293 return p.stdout, None
1292
1294
1293 retdata = p.stdout.read().strip()
1295 retdata = p.stdout.read().strip()
1294 # wait for the child to exit to avoid race condition.
1296 # wait for the child to exit to avoid race condition.
1295 p.wait()
1297 p.wait()
1296
1298
1297 if p.returncode != 0 and p.returncode != 1:
1299 if p.returncode != 0 and p.returncode != 1:
1298 # there are certain error codes that are ok
1300 # there are certain error codes that are ok
1299 command = commands[0]
1301 command = commands[0]
1300 if command in ('cat-file', 'symbolic-ref'):
1302 if command in ('cat-file', 'symbolic-ref'):
1301 return retdata, p.returncode
1303 return retdata, p.returncode
1302 # for all others, abort
1304 # for all others, abort
1303 raise error.Abort(_('git %s error %d in %s') %
1305 raise error.Abort(_('git %s error %d in %s') %
1304 (command, p.returncode, self._relpath))
1306 (command, p.returncode, self._relpath))
1305
1307
1306 return retdata, p.returncode
1308 return retdata, p.returncode
1307
1309
1308 def _gitmissing(self):
1310 def _gitmissing(self):
1309 return not self.wvfs.exists('.git')
1311 return not self.wvfs.exists('.git')
1310
1312
1311 def _gitstate(self):
1313 def _gitstate(self):
1312 return self._gitcommand(['rev-parse', 'HEAD'])
1314 return self._gitcommand(['rev-parse', 'HEAD'])
1313
1315
1314 def _gitcurrentbranch(self):
1316 def _gitcurrentbranch(self):
1315 current, err = self._gitdir(['symbolic-ref', 'HEAD', '--quiet'])
1317 current, err = self._gitdir(['symbolic-ref', 'HEAD', '--quiet'])
1316 if err:
1318 if err:
1317 current = None
1319 current = None
1318 return current
1320 return current
1319
1321
1320 def _gitremote(self, remote):
1322 def _gitremote(self, remote):
1321 out = self._gitcommand(['remote', 'show', '-n', remote])
1323 out = self._gitcommand(['remote', 'show', '-n', remote])
1322 line = out.split('\n')[1]
1324 line = out.split('\n')[1]
1323 i = line.index('URL: ') + len('URL: ')
1325 i = line.index('URL: ') + len('URL: ')
1324 return line[i:]
1326 return line[i:]
1325
1327
1326 def _githavelocally(self, revision):
1328 def _githavelocally(self, revision):
1327 out, code = self._gitdir(['cat-file', '-e', revision])
1329 out, code = self._gitdir(['cat-file', '-e', revision])
1328 return code == 0
1330 return code == 0
1329
1331
1330 def _gitisancestor(self, r1, r2):
1332 def _gitisancestor(self, r1, r2):
1331 base = self._gitcommand(['merge-base', r1, r2])
1333 base = self._gitcommand(['merge-base', r1, r2])
1332 return base == r1
1334 return base == r1
1333
1335
1334 def _gitisbare(self):
1336 def _gitisbare(self):
1335 return self._gitcommand(['config', '--bool', 'core.bare']) == 'true'
1337 return self._gitcommand(['config', '--bool', 'core.bare']) == 'true'
1336
1338
1337 def _gitupdatestat(self):
1339 def _gitupdatestat(self):
1338 """This must be run before git diff-index.
1340 """This must be run before git diff-index.
1339 diff-index only looks at changes to file stat;
1341 diff-index only looks at changes to file stat;
1340 this command looks at file contents and updates the stat."""
1342 this command looks at file contents and updates the stat."""
1341 self._gitcommand(['update-index', '-q', '--refresh'])
1343 self._gitcommand(['update-index', '-q', '--refresh'])
1342
1344
1343 def _gitbranchmap(self):
1345 def _gitbranchmap(self):
1344 '''returns 2 things:
1346 '''returns 2 things:
1345 a map from git branch to revision
1347 a map from git branch to revision
1346 a map from revision to branches'''
1348 a map from revision to branches'''
1347 branch2rev = {}
1349 branch2rev = {}
1348 rev2branch = {}
1350 rev2branch = {}
1349
1351
1350 out = self._gitcommand(['for-each-ref', '--format',
1352 out = self._gitcommand(['for-each-ref', '--format',
1351 '%(objectname) %(refname)'])
1353 '%(objectname) %(refname)'])
1352 for line in out.split('\n'):
1354 for line in out.split('\n'):
1353 revision, ref = line.split(' ')
1355 revision, ref = line.split(' ')
1354 if (not ref.startswith('refs/heads/') and
1356 if (not ref.startswith('refs/heads/') and
1355 not ref.startswith('refs/remotes/')):
1357 not ref.startswith('refs/remotes/')):
1356 continue
1358 continue
1357 if ref.startswith('refs/remotes/') and ref.endswith('/HEAD'):
1359 if ref.startswith('refs/remotes/') and ref.endswith('/HEAD'):
1358 continue # ignore remote/HEAD redirects
1360 continue # ignore remote/HEAD redirects
1359 branch2rev[ref] = revision
1361 branch2rev[ref] = revision
1360 rev2branch.setdefault(revision, []).append(ref)
1362 rev2branch.setdefault(revision, []).append(ref)
1361 return branch2rev, rev2branch
1363 return branch2rev, rev2branch
1362
1364
1363 def _gittracking(self, branches):
1365 def _gittracking(self, branches):
1364 'return map of remote branch to local tracking branch'
1366 'return map of remote branch to local tracking branch'
1365 # assumes no more than one local tracking branch for each remote
1367 # assumes no more than one local tracking branch for each remote
1366 tracking = {}
1368 tracking = {}
1367 for b in branches:
1369 for b in branches:
1368 if b.startswith('refs/remotes/'):
1370 if b.startswith('refs/remotes/'):
1369 continue
1371 continue
1370 bname = b.split('/', 2)[2]
1372 bname = b.split('/', 2)[2]
1371 remote = self._gitcommand(['config', 'branch.%s.remote' % bname])
1373 remote = self._gitcommand(['config', 'branch.%s.remote' % bname])
1372 if remote:
1374 if remote:
1373 ref = self._gitcommand(['config', 'branch.%s.merge' % bname])
1375 ref = self._gitcommand(['config', 'branch.%s.merge' % bname])
1374 tracking['refs/remotes/%s/%s' %
1376 tracking['refs/remotes/%s/%s' %
1375 (remote, ref.split('/', 2)[2])] = b
1377 (remote, ref.split('/', 2)[2])] = b
1376 return tracking
1378 return tracking
1377
1379
1378 def _abssource(self, source):
1380 def _abssource(self, source):
1379 if '://' not in source:
1381 if '://' not in source:
1380 # recognize the scp syntax as an absolute source
1382 # recognize the scp syntax as an absolute source
1381 colon = source.find(':')
1383 colon = source.find(':')
1382 if colon != -1 and '/' not in source[:colon]:
1384 if colon != -1 and '/' not in source[:colon]:
1383 return source
1385 return source
1384 self._subsource = source
1386 self._subsource = source
1385 return _abssource(self)
1387 return _abssource(self)
1386
1388
1387 def _fetch(self, source, revision):
1389 def _fetch(self, source, revision):
1388 if self._gitmissing():
1390 if self._gitmissing():
1389 # SEC: check for safe ssh url
1391 # SEC: check for safe ssh url
1390 util.checksafessh(source)
1392 util.checksafessh(source)
1391
1393
1392 source = self._abssource(source)
1394 source = self._abssource(source)
1393 self.ui.status(_('cloning subrepo %s from %s\n') %
1395 self.ui.status(_('cloning subrepo %s from %s\n') %
1394 (self._relpath, source))
1396 (self._relpath, source))
1395 self._gitnodir(['clone', source, self._abspath])
1397 self._gitnodir(['clone', source, self._abspath])
1396 if self._githavelocally(revision):
1398 if self._githavelocally(revision):
1397 return
1399 return
1398 self.ui.status(_('pulling subrepo %s from %s\n') %
1400 self.ui.status(_('pulling subrepo %s from %s\n') %
1399 (self._relpath, self._gitremote('origin')))
1401 (self._relpath, self._gitremote('origin')))
1400 # try only origin: the originally cloned repo
1402 # try only origin: the originally cloned repo
1401 self._gitcommand(['fetch'])
1403 self._gitcommand(['fetch'])
1402 if not self._githavelocally(revision):
1404 if not self._githavelocally(revision):
1403 raise error.Abort(_('revision %s does not exist in subrepository '
1405 raise error.Abort(_('revision %s does not exist in subrepository '
1404 '"%s"\n') % (revision, self._relpath))
1406 '"%s"\n') % (revision, self._relpath))
1405
1407
1406 @annotatesubrepoerror
1408 @annotatesubrepoerror
1407 def dirty(self, ignoreupdate=False, missing=False):
1409 def dirty(self, ignoreupdate=False, missing=False):
1408 if self._gitmissing():
1410 if self._gitmissing():
1409 return self._state[1] != ''
1411 return self._state[1] != ''
1410 if self._gitisbare():
1412 if self._gitisbare():
1411 return True
1413 return True
1412 if not ignoreupdate and self._state[1] != self._gitstate():
1414 if not ignoreupdate and self._state[1] != self._gitstate():
1413 # different version checked out
1415 # different version checked out
1414 return True
1416 return True
1415 # check for staged changes or modified files; ignore untracked files
1417 # check for staged changes or modified files; ignore untracked files
1416 self._gitupdatestat()
1418 self._gitupdatestat()
1417 out, code = self._gitdir(['diff-index', '--quiet', 'HEAD'])
1419 out, code = self._gitdir(['diff-index', '--quiet', 'HEAD'])
1418 return code == 1
1420 return code == 1
1419
1421
1420 def basestate(self):
1422 def basestate(self):
1421 return self._gitstate()
1423 return self._gitstate()
1422
1424
1423 @annotatesubrepoerror
1425 @annotatesubrepoerror
1424 def get(self, state, overwrite=False):
1426 def get(self, state, overwrite=False):
1425 source, revision, kind = state
1427 source, revision, kind = state
1426 if not revision:
1428 if not revision:
1427 self.remove()
1429 self.remove()
1428 return
1430 return
1429 self._fetch(source, revision)
1431 self._fetch(source, revision)
1430 # if the repo was set to be bare, unbare it
1432 # if the repo was set to be bare, unbare it
1431 if self._gitisbare():
1433 if self._gitisbare():
1432 self._gitcommand(['config', 'core.bare', 'false'])
1434 self._gitcommand(['config', 'core.bare', 'false'])
1433 if self._gitstate() == revision:
1435 if self._gitstate() == revision:
1434 self._gitcommand(['reset', '--hard', 'HEAD'])
1436 self._gitcommand(['reset', '--hard', 'HEAD'])
1435 return
1437 return
1436 elif self._gitstate() == revision:
1438 elif self._gitstate() == revision:
1437 if overwrite:
1439 if overwrite:
1438 # first reset the index to unmark new files for commit, because
1440 # first reset the index to unmark new files for commit, because
1439 # reset --hard will otherwise throw away files added for commit,
1441 # reset --hard will otherwise throw away files added for commit,
1440 # not just unmark them.
1442 # not just unmark them.
1441 self._gitcommand(['reset', 'HEAD'])
1443 self._gitcommand(['reset', 'HEAD'])
1442 self._gitcommand(['reset', '--hard', 'HEAD'])
1444 self._gitcommand(['reset', '--hard', 'HEAD'])
1443 return
1445 return
1444 branch2rev, rev2branch = self._gitbranchmap()
1446 branch2rev, rev2branch = self._gitbranchmap()
1445
1447
1446 def checkout(args):
1448 def checkout(args):
1447 cmd = ['checkout']
1449 cmd = ['checkout']
1448 if overwrite:
1450 if overwrite:
1449 # first reset the index to unmark new files for commit, because
1451 # first reset the index to unmark new files for commit, because
1450 # the -f option will otherwise throw away files added for
1452 # the -f option will otherwise throw away files added for
1451 # commit, not just unmark them.
1453 # commit, not just unmark them.
1452 self._gitcommand(['reset', 'HEAD'])
1454 self._gitcommand(['reset', 'HEAD'])
1453 cmd.append('-f')
1455 cmd.append('-f')
1454 self._gitcommand(cmd + args)
1456 self._gitcommand(cmd + args)
1455 _sanitize(self.ui, self.wvfs, '.git')
1457 _sanitize(self.ui, self.wvfs, '.git')
1456
1458
1457 def rawcheckout():
1459 def rawcheckout():
1458 # no branch to checkout, check it out with no branch
1460 # no branch to checkout, check it out with no branch
1459 self.ui.warn(_('checking out detached HEAD in '
1461 self.ui.warn(_('checking out detached HEAD in '
1460 'subrepository "%s"\n') % self._relpath)
1462 'subrepository "%s"\n') % self._relpath)
1461 self.ui.warn(_('check out a git branch if you intend '
1463 self.ui.warn(_('check out a git branch if you intend '
1462 'to make changes\n'))
1464 'to make changes\n'))
1463 checkout(['-q', revision])
1465 checkout(['-q', revision])
1464
1466
1465 if revision not in rev2branch:
1467 if revision not in rev2branch:
1466 rawcheckout()
1468 rawcheckout()
1467 return
1469 return
1468 branches = rev2branch[revision]
1470 branches = rev2branch[revision]
1469 firstlocalbranch = None
1471 firstlocalbranch = None
1470 for b in branches:
1472 for b in branches:
1471 if b == 'refs/heads/master':
1473 if b == 'refs/heads/master':
1472 # master trumps all other branches
1474 # master trumps all other branches
1473 checkout(['refs/heads/master'])
1475 checkout(['refs/heads/master'])
1474 return
1476 return
1475 if not firstlocalbranch and not b.startswith('refs/remotes/'):
1477 if not firstlocalbranch and not b.startswith('refs/remotes/'):
1476 firstlocalbranch = b
1478 firstlocalbranch = b
1477 if firstlocalbranch:
1479 if firstlocalbranch:
1478 checkout([firstlocalbranch])
1480 checkout([firstlocalbranch])
1479 return
1481 return
1480
1482
1481 tracking = self._gittracking(branch2rev.keys())
1483 tracking = self._gittracking(branch2rev.keys())
1482 # choose a remote branch already tracked if possible
1484 # choose a remote branch already tracked if possible
1483 remote = branches[0]
1485 remote = branches[0]
1484 if remote not in tracking:
1486 if remote not in tracking:
1485 for b in branches:
1487 for b in branches:
1486 if b in tracking:
1488 if b in tracking:
1487 remote = b
1489 remote = b
1488 break
1490 break
1489
1491
1490 if remote not in tracking:
1492 if remote not in tracking:
1491 # create a new local tracking branch
1493 # create a new local tracking branch
1492 local = remote.split('/', 3)[3]
1494 local = remote.split('/', 3)[3]
1493 checkout(['-b', local, remote])
1495 checkout(['-b', local, remote])
1494 elif self._gitisancestor(branch2rev[tracking[remote]], remote):
1496 elif self._gitisancestor(branch2rev[tracking[remote]], remote):
1495 # When updating to a tracked remote branch,
1497 # When updating to a tracked remote branch,
1496 # if the local tracking branch is downstream of it,
1498 # if the local tracking branch is downstream of it,
1497 # a normal `git pull` would have performed a "fast-forward merge"
1499 # a normal `git pull` would have performed a "fast-forward merge"
1498 # which is equivalent to updating the local branch to the remote.
1500 # which is equivalent to updating the local branch to the remote.
1499 # Since we are only looking at branching at update, we need to
1501 # Since we are only looking at branching at update, we need to
1500 # detect this situation and perform this action lazily.
1502 # detect this situation and perform this action lazily.
1501 if tracking[remote] != self._gitcurrentbranch():
1503 if tracking[remote] != self._gitcurrentbranch():
1502 checkout([tracking[remote]])
1504 checkout([tracking[remote]])
1503 self._gitcommand(['merge', '--ff', remote])
1505 self._gitcommand(['merge', '--ff', remote])
1504 _sanitize(self.ui, self.wvfs, '.git')
1506 _sanitize(self.ui, self.wvfs, '.git')
1505 else:
1507 else:
1506 # a real merge would be required, just checkout the revision
1508 # a real merge would be required, just checkout the revision
1507 rawcheckout()
1509 rawcheckout()
1508
1510
1509 @annotatesubrepoerror
1511 @annotatesubrepoerror
1510 def commit(self, text, user, date):
1512 def commit(self, text, user, date):
1511 if self._gitmissing():
1513 if self._gitmissing():
1512 raise error.Abort(_("subrepo %s is missing") % self._relpath)
1514 raise error.Abort(_("subrepo %s is missing") % self._relpath)
1513 cmd = ['commit', '-a', '-m', text]
1515 cmd = ['commit', '-a', '-m', text]
1514 env = encoding.environ.copy()
1516 env = encoding.environ.copy()
1515 if user:
1517 if user:
1516 cmd += ['--author', user]
1518 cmd += ['--author', user]
1517 if date:
1519 if date:
1518 # git's date parser silently ignores when seconds < 1e9
1520 # git's date parser silently ignores when seconds < 1e9
1519 # convert to ISO8601
1521 # convert to ISO8601
1520 env['GIT_AUTHOR_DATE'] = dateutil.datestr(date,
1522 env['GIT_AUTHOR_DATE'] = dateutil.datestr(date,
1521 '%Y-%m-%dT%H:%M:%S %1%2')
1523 '%Y-%m-%dT%H:%M:%S %1%2')
1522 self._gitcommand(cmd, env=env)
1524 self._gitcommand(cmd, env=env)
1523 # make sure commit works otherwise HEAD might not exist under certain
1525 # make sure commit works otherwise HEAD might not exist under certain
1524 # circumstances
1526 # circumstances
1525 return self._gitstate()
1527 return self._gitstate()
1526
1528
1527 @annotatesubrepoerror
1529 @annotatesubrepoerror
1528 def merge(self, state):
1530 def merge(self, state):
1529 source, revision, kind = state
1531 source, revision, kind = state
1530 self._fetch(source, revision)
1532 self._fetch(source, revision)
1531 base = self._gitcommand(['merge-base', revision, self._state[1]])
1533 base = self._gitcommand(['merge-base', revision, self._state[1]])
1532 self._gitupdatestat()
1534 self._gitupdatestat()
1533 out, code = self._gitdir(['diff-index', '--quiet', 'HEAD'])
1535 out, code = self._gitdir(['diff-index', '--quiet', 'HEAD'])
1534
1536
1535 def mergefunc():
1537 def mergefunc():
1536 if base == revision:
1538 if base == revision:
1537 self.get(state) # fast forward merge
1539 self.get(state) # fast forward merge
1538 elif base != self._state[1]:
1540 elif base != self._state[1]:
1539 self._gitcommand(['merge', '--no-commit', revision])
1541 self._gitcommand(['merge', '--no-commit', revision])
1540 _sanitize(self.ui, self.wvfs, '.git')
1542 _sanitize(self.ui, self.wvfs, '.git')
1541
1543
1542 if self.dirty():
1544 if self.dirty():
1543 if self._gitstate() != revision:
1545 if self._gitstate() != revision:
1544 dirty = self._gitstate() == self._state[1] or code != 0
1546 dirty = self._gitstate() == self._state[1] or code != 0
1545 if _updateprompt(self.ui, self, dirty,
1547 if _updateprompt(self.ui, self, dirty,
1546 self._state[1][:7], revision[:7]):
1548 self._state[1][:7], revision[:7]):
1547 mergefunc()
1549 mergefunc()
1548 else:
1550 else:
1549 mergefunc()
1551 mergefunc()
1550
1552
1551 @annotatesubrepoerror
1553 @annotatesubrepoerror
1552 def push(self, opts):
1554 def push(self, opts):
1553 force = opts.get('force')
1555 force = opts.get('force')
1554
1556
1555 if not self._state[1]:
1557 if not self._state[1]:
1556 return True
1558 return True
1557 if self._gitmissing():
1559 if self._gitmissing():
1558 raise error.Abort(_("subrepo %s is missing") % self._relpath)
1560 raise error.Abort(_("subrepo %s is missing") % self._relpath)
1559 # if a branch in origin contains the revision, nothing to do
1561 # if a branch in origin contains the revision, nothing to do
1560 branch2rev, rev2branch = self._gitbranchmap()
1562 branch2rev, rev2branch = self._gitbranchmap()
1561 if self._state[1] in rev2branch:
1563 if self._state[1] in rev2branch:
1562 for b in rev2branch[self._state[1]]:
1564 for b in rev2branch[self._state[1]]:
1563 if b.startswith('refs/remotes/origin/'):
1565 if b.startswith('refs/remotes/origin/'):
1564 return True
1566 return True
1565 for b, revision in branch2rev.iteritems():
1567 for b, revision in branch2rev.iteritems():
1566 if b.startswith('refs/remotes/origin/'):
1568 if b.startswith('refs/remotes/origin/'):
1567 if self._gitisancestor(self._state[1], revision):
1569 if self._gitisancestor(self._state[1], revision):
1568 return True
1570 return True
1569 # otherwise, try to push the currently checked out branch
1571 # otherwise, try to push the currently checked out branch
1570 cmd = ['push']
1572 cmd = ['push']
1571 if force:
1573 if force:
1572 cmd.append('--force')
1574 cmd.append('--force')
1573
1575
1574 current = self._gitcurrentbranch()
1576 current = self._gitcurrentbranch()
1575 if current:
1577 if current:
1576 # determine if the current branch is even useful
1578 # determine if the current branch is even useful
1577 if not self._gitisancestor(self._state[1], current):
1579 if not self._gitisancestor(self._state[1], current):
1578 self.ui.warn(_('unrelated git branch checked out '
1580 self.ui.warn(_('unrelated git branch checked out '
1579 'in subrepository "%s"\n') % self._relpath)
1581 'in subrepository "%s"\n') % self._relpath)
1580 return False
1582 return False
1581 self.ui.status(_('pushing branch %s of subrepository "%s"\n') %
1583 self.ui.status(_('pushing branch %s of subrepository "%s"\n') %
1582 (current.split('/', 2)[2], self._relpath))
1584 (current.split('/', 2)[2], self._relpath))
1583 ret = self._gitdir(cmd + ['origin', current])
1585 ret = self._gitdir(cmd + ['origin', current])
1584 return ret[1] == 0
1586 return ret[1] == 0
1585 else:
1587 else:
1586 self.ui.warn(_('no branch checked out in subrepository "%s"\n'
1588 self.ui.warn(_('no branch checked out in subrepository "%s"\n'
1587 'cannot push revision %s\n') %
1589 'cannot push revision %s\n') %
1588 (self._relpath, self._state[1]))
1590 (self._relpath, self._state[1]))
1589 return False
1591 return False
1590
1592
1591 @annotatesubrepoerror
1593 @annotatesubrepoerror
1592 def add(self, ui, match, prefix, uipathfn, explicitonly, **opts):
1594 def add(self, ui, match, prefix, uipathfn, explicitonly, **opts):
1593 if self._gitmissing():
1595 if self._gitmissing():
1594 return []
1596 return []
1595
1597
1596 s = self.status(None, unknown=True, clean=True)
1598 s = self.status(None, unknown=True, clean=True)
1597
1599
1598 tracked = set()
1600 tracked = set()
1599 # dirstates 'amn' warn, 'r' is added again
1601 # dirstates 'amn' warn, 'r' is added again
1600 for l in (s.modified, s.added, s.deleted, s.clean):
1602 for l in (s.modified, s.added, s.deleted, s.clean):
1601 tracked.update(l)
1603 tracked.update(l)
1602
1604
1603 # Unknown files not of interest will be rejected by the matcher
1605 # Unknown files not of interest will be rejected by the matcher
1604 files = s.unknown
1606 files = s.unknown
1605 files.extend(match.files())
1607 files.extend(match.files())
1606
1608
1607 rejected = []
1609 rejected = []
1608
1610
1609 files = [f for f in sorted(set(files)) if match(f)]
1611 files = [f for f in sorted(set(files)) if match(f)]
1610 for f in files:
1612 for f in files:
1611 exact = match.exact(f)
1613 exact = match.exact(f)
1612 command = ["add"]
1614 command = ["add"]
1613 if exact:
1615 if exact:
1614 command.append("-f") #should be added, even if ignored
1616 command.append("-f") #should be added, even if ignored
1615 if ui.verbose or not exact:
1617 if ui.verbose or not exact:
1616 ui.status(_('adding %s\n') % uipathfn(f))
1618 ui.status(_('adding %s\n') % uipathfn(f))
1617
1619
1618 if f in tracked: # hg prints 'adding' even if already tracked
1620 if f in tracked: # hg prints 'adding' even if already tracked
1619 if exact:
1621 if exact:
1620 rejected.append(f)
1622 rejected.append(f)
1621 continue
1623 continue
1622 if not opts.get(r'dry_run'):
1624 if not opts.get(r'dry_run'):
1623 self._gitcommand(command + [f])
1625 self._gitcommand(command + [f])
1624
1626
1625 for f in rejected:
1627 for f in rejected:
1626 ui.warn(_("%s already tracked!\n") % uipathfn(f))
1628 ui.warn(_("%s already tracked!\n") % uipathfn(f))
1627
1629
1628 return rejected
1630 return rejected
1629
1631
1630 @annotatesubrepoerror
1632 @annotatesubrepoerror
1631 def remove(self):
1633 def remove(self):
1632 if self._gitmissing():
1634 if self._gitmissing():
1633 return
1635 return
1634 if self.dirty():
1636 if self.dirty():
1635 self.ui.warn(_('not removing repo %s because '
1637 self.ui.warn(_('not removing repo %s because '
1636 'it has changes.\n') % self._relpath)
1638 'it has changes.\n') % self._relpath)
1637 return
1639 return
1638 # we can't fully delete the repository as it may contain
1640 # we can't fully delete the repository as it may contain
1639 # local-only history
1641 # local-only history
1640 self.ui.note(_('removing subrepo %s\n') % self._relpath)
1642 self.ui.note(_('removing subrepo %s\n') % self._relpath)
1641 self._gitcommand(['config', 'core.bare', 'true'])
1643 self._gitcommand(['config', 'core.bare', 'true'])
1642 for f, kind in self.wvfs.readdir():
1644 for f, kind in self.wvfs.readdir():
1643 if f == '.git':
1645 if f == '.git':
1644 continue
1646 continue
1645 if kind == stat.S_IFDIR:
1647 if kind == stat.S_IFDIR:
1646 self.wvfs.rmtree(f)
1648 self.wvfs.rmtree(f)
1647 else:
1649 else:
1648 self.wvfs.unlink(f)
1650 self.wvfs.unlink(f)
1649
1651
1650 def archive(self, archiver, prefix, match=None, decode=True):
1652 def archive(self, archiver, prefix, match=None, decode=True):
1651 total = 0
1653 total = 0
1652 source, revision = self._state
1654 source, revision = self._state
1653 if not revision:
1655 if not revision:
1654 return total
1656 return total
1655 self._fetch(source, revision)
1657 self._fetch(source, revision)
1656
1658
1657 # Parse git's native archive command.
1659 # Parse git's native archive command.
1658 # This should be much faster than manually traversing the trees
1660 # This should be much faster than manually traversing the trees
1659 # and objects with many subprocess calls.
1661 # and objects with many subprocess calls.
1660 tarstream = self._gitcommand(['archive', revision], stream=True)
1662 tarstream = self._gitcommand(['archive', revision], stream=True)
1661 tar = tarfile.open(fileobj=tarstream, mode=r'r|')
1663 tar = tarfile.open(fileobj=tarstream, mode=r'r|')
1662 relpath = subrelpath(self)
1664 relpath = subrelpath(self)
1663 progress = self.ui.makeprogress(_('archiving (%s)') % relpath,
1665 progress = self.ui.makeprogress(_('archiving (%s)') % relpath,
1664 unit=_('files'))
1666 unit=_('files'))
1665 progress.update(0)
1667 progress.update(0)
1666 for info in tar:
1668 for info in tar:
1667 if info.isdir():
1669 if info.isdir():
1668 continue
1670 continue
1669 bname = pycompat.fsencode(info.name)
1671 bname = pycompat.fsencode(info.name)
1670 if match and not match(bname):
1672 if match and not match(bname):
1671 continue
1673 continue
1672 if info.issym():
1674 if info.issym():
1673 data = info.linkname
1675 data = info.linkname
1674 else:
1676 else:
1675 data = tar.extractfile(info).read()
1677 data = tar.extractfile(info).read()
1676 archiver.addfile(prefix + bname, info.mode, info.issym(), data)
1678 archiver.addfile(prefix + bname, info.mode, info.issym(), data)
1677 total += 1
1679 total += 1
1678 progress.increment()
1680 progress.increment()
1679 progress.complete()
1681 progress.complete()
1680 return total
1682 return total
1681
1683
1682
1684
1683 @annotatesubrepoerror
1685 @annotatesubrepoerror
1684 def cat(self, match, fm, fntemplate, prefix, **opts):
1686 def cat(self, match, fm, fntemplate, prefix, **opts):
1685 rev = self._state[1]
1687 rev = self._state[1]
1686 if match.anypats():
1688 if match.anypats():
1687 return 1 #No support for include/exclude yet
1689 return 1 #No support for include/exclude yet
1688
1690
1689 if not match.files():
1691 if not match.files():
1690 return 1
1692 return 1
1691
1693
1692 # TODO: add support for non-plain formatter (see cmdutil.cat())
1694 # TODO: add support for non-plain formatter (see cmdutil.cat())
1693 for f in match.files():
1695 for f in match.files():
1694 output = self._gitcommand(["show", "%s:%s" % (rev, f)])
1696 output = self._gitcommand(["show", "%s:%s" % (rev, f)])
1695 fp = cmdutil.makefileobj(self._ctx, fntemplate,
1697 fp = cmdutil.makefileobj(self._ctx, fntemplate,
1696 pathname=self.wvfs.reljoin(prefix, f))
1698 pathname=self.wvfs.reljoin(prefix, f))
1697 fp.write(output)
1699 fp.write(output)
1698 fp.close()
1700 fp.close()
1699 return 0
1701 return 0
1700
1702
1701
1703
1702 @annotatesubrepoerror
1704 @annotatesubrepoerror
1703 def status(self, rev2, **opts):
1705 def status(self, rev2, **opts):
1704 rev1 = self._state[1]
1706 rev1 = self._state[1]
1705 if self._gitmissing() or not rev1:
1707 if self._gitmissing() or not rev1:
1706 # if the repo is missing, return no results
1708 # if the repo is missing, return no results
1707 return scmutil.status([], [], [], [], [], [], [])
1709 return scmutil.status([], [], [], [], [], [], [])
1708 modified, added, removed = [], [], []
1710 modified, added, removed = [], [], []
1709 self._gitupdatestat()
1711 self._gitupdatestat()
1710 if rev2:
1712 if rev2:
1711 command = ['diff-tree', '--no-renames', '-r', rev1, rev2]
1713 command = ['diff-tree', '--no-renames', '-r', rev1, rev2]
1712 else:
1714 else:
1713 command = ['diff-index', '--no-renames', rev1]
1715 command = ['diff-index', '--no-renames', rev1]
1714 out = self._gitcommand(command)
1716 out = self._gitcommand(command)
1715 for line in out.split('\n'):
1717 for line in out.split('\n'):
1716 tab = line.find('\t')
1718 tab = line.find('\t')
1717 if tab == -1:
1719 if tab == -1:
1718 continue
1720 continue
1719 status, f = line[tab - 1:tab], line[tab + 1:]
1721 status, f = line[tab - 1:tab], line[tab + 1:]
1720 if status == 'M':
1722 if status == 'M':
1721 modified.append(f)
1723 modified.append(f)
1722 elif status == 'A':
1724 elif status == 'A':
1723 added.append(f)
1725 added.append(f)
1724 elif status == 'D':
1726 elif status == 'D':
1725 removed.append(f)
1727 removed.append(f)
1726
1728
1727 deleted, unknown, ignored, clean = [], [], [], []
1729 deleted, unknown, ignored, clean = [], [], [], []
1728
1730
1729 command = ['status', '--porcelain', '-z']
1731 command = ['status', '--porcelain', '-z']
1730 if opts.get(r'unknown'):
1732 if opts.get(r'unknown'):
1731 command += ['--untracked-files=all']
1733 command += ['--untracked-files=all']
1732 if opts.get(r'ignored'):
1734 if opts.get(r'ignored'):
1733 command += ['--ignored']
1735 command += ['--ignored']
1734 out = self._gitcommand(command)
1736 out = self._gitcommand(command)
1735
1737
1736 changedfiles = set()
1738 changedfiles = set()
1737 changedfiles.update(modified)
1739 changedfiles.update(modified)
1738 changedfiles.update(added)
1740 changedfiles.update(added)
1739 changedfiles.update(removed)
1741 changedfiles.update(removed)
1740 for line in out.split('\0'):
1742 for line in out.split('\0'):
1741 if not line:
1743 if not line:
1742 continue
1744 continue
1743 st = line[0:2]
1745 st = line[0:2]
1744 #moves and copies show 2 files on one line
1746 #moves and copies show 2 files on one line
1745 if line.find('\0') >= 0:
1747 if line.find('\0') >= 0:
1746 filename1, filename2 = line[3:].split('\0')
1748 filename1, filename2 = line[3:].split('\0')
1747 else:
1749 else:
1748 filename1 = line[3:]
1750 filename1 = line[3:]
1749 filename2 = None
1751 filename2 = None
1750
1752
1751 changedfiles.add(filename1)
1753 changedfiles.add(filename1)
1752 if filename2:
1754 if filename2:
1753 changedfiles.add(filename2)
1755 changedfiles.add(filename2)
1754
1756
1755 if st == '??':
1757 if st == '??':
1756 unknown.append(filename1)
1758 unknown.append(filename1)
1757 elif st == '!!':
1759 elif st == '!!':
1758 ignored.append(filename1)
1760 ignored.append(filename1)
1759
1761
1760 if opts.get(r'clean'):
1762 if opts.get(r'clean'):
1761 out = self._gitcommand(['ls-files'])
1763 out = self._gitcommand(['ls-files'])
1762 for f in out.split('\n'):
1764 for f in out.split('\n'):
1763 if not f in changedfiles:
1765 if not f in changedfiles:
1764 clean.append(f)
1766 clean.append(f)
1765
1767
1766 return scmutil.status(modified, added, removed, deleted,
1768 return scmutil.status(modified, added, removed, deleted,
1767 unknown, ignored, clean)
1769 unknown, ignored, clean)
1768
1770
1769 @annotatesubrepoerror
1771 @annotatesubrepoerror
1770 def diff(self, ui, diffopts, node2, match, prefix, **opts):
1772 def diff(self, ui, diffopts, node2, match, prefix, **opts):
1771 node1 = self._state[1]
1773 node1 = self._state[1]
1772 cmd = ['diff', '--no-renames']
1774 cmd = ['diff', '--no-renames']
1773 if opts[r'stat']:
1775 if opts[r'stat']:
1774 cmd.append('--stat')
1776 cmd.append('--stat')
1775 else:
1777 else:
1776 # for Git, this also implies '-p'
1778 # for Git, this also implies '-p'
1777 cmd.append('-U%d' % diffopts.context)
1779 cmd.append('-U%d' % diffopts.context)
1778
1780
1779 if diffopts.noprefix:
1781 if diffopts.noprefix:
1780 cmd.extend(['--src-prefix=%s/' % prefix,
1782 cmd.extend(['--src-prefix=%s/' % prefix,
1781 '--dst-prefix=%s/' % prefix])
1783 '--dst-prefix=%s/' % prefix])
1782 else:
1784 else:
1783 cmd.extend(['--src-prefix=a/%s/' % prefix,
1785 cmd.extend(['--src-prefix=a/%s/' % prefix,
1784 '--dst-prefix=b/%s/' % prefix])
1786 '--dst-prefix=b/%s/' % prefix])
1785
1787
1786 if diffopts.ignorews:
1788 if diffopts.ignorews:
1787 cmd.append('--ignore-all-space')
1789 cmd.append('--ignore-all-space')
1788 if diffopts.ignorewsamount:
1790 if diffopts.ignorewsamount:
1789 cmd.append('--ignore-space-change')
1791 cmd.append('--ignore-space-change')
1790 if (self._gitversion(self._gitcommand(['--version'])) >= (1, 8, 4)
1792 if (self._gitversion(self._gitcommand(['--version'])) >= (1, 8, 4)
1791 and diffopts.ignoreblanklines):
1793 and diffopts.ignoreblanklines):
1792 cmd.append('--ignore-blank-lines')
1794 cmd.append('--ignore-blank-lines')
1793
1795
1794 cmd.append(node1)
1796 cmd.append(node1)
1795 if node2:
1797 if node2:
1796 cmd.append(node2)
1798 cmd.append(node2)
1797
1799
1798 output = ""
1800 output = ""
1799 if match.always():
1801 if match.always():
1800 output += self._gitcommand(cmd) + '\n'
1802 output += self._gitcommand(cmd) + '\n'
1801 else:
1803 else:
1802 st = self.status(node2)[:3]
1804 st = self.status(node2)[:3]
1803 files = [f for sublist in st for f in sublist]
1805 files = [f for sublist in st for f in sublist]
1804 for f in files:
1806 for f in files:
1805 if match(f):
1807 if match(f):
1806 output += self._gitcommand(cmd + ['--', f]) + '\n'
1808 output += self._gitcommand(cmd + ['--', f]) + '\n'
1807
1809
1808 if output.strip():
1810 if output.strip():
1809 ui.write(output)
1811 ui.write(output)
1810
1812
1811 @annotatesubrepoerror
1813 @annotatesubrepoerror
1812 def revert(self, substate, *pats, **opts):
1814 def revert(self, substate, *pats, **opts):
1813 self.ui.status(_('reverting subrepo %s\n') % substate[0])
1815 self.ui.status(_('reverting subrepo %s\n') % substate[0])
1814 if not opts.get(r'no_backup'):
1816 if not opts.get(r'no_backup'):
1815 status = self.status(None)
1817 status = self.status(None)
1816 names = status.modified
1818 names = status.modified
1817 for name in names:
1819 for name in names:
1818 # backuppath() expects a path relative to the parent repo (the
1820 # backuppath() expects a path relative to the parent repo (the
1819 # repo that ui.origbackuppath is relative to)
1821 # repo that ui.origbackuppath is relative to)
1820 parentname = os.path.join(self._path, name)
1822 parentname = os.path.join(self._path, name)
1821 bakname = scmutil.backuppath(self.ui, self._subparent,
1823 bakname = scmutil.backuppath(self.ui, self._subparent,
1822 parentname)
1824 parentname)
1823 self.ui.note(_('saving current version of %s as %s\n') %
1825 self.ui.note(_('saving current version of %s as %s\n') %
1824 (name, os.path.relpath(bakname)))
1826 (name, os.path.relpath(bakname)))
1825 util.rename(self.wvfs.join(name), bakname)
1827 util.rename(self.wvfs.join(name), bakname)
1826
1828
1827 if not opts.get(r'dry_run'):
1829 if not opts.get(r'dry_run'):
1828 self.get(substate, overwrite=True)
1830 self.get(substate, overwrite=True)
1829 return []
1831 return []
1830
1832
1831 def shortid(self, revid):
1833 def shortid(self, revid):
1832 return revid[:7]
1834 return revid[:7]
1833
1835
1834 types = {
1836 types = {
1835 'hg': hgsubrepo,
1837 'hg': hgsubrepo,
1836 'svn': svnsubrepo,
1838 'svn': svnsubrepo,
1837 'git': gitsubrepo,
1839 'git': gitsubrepo,
1838 }
1840 }
@@ -1,394 +1,397 b''
1 # subrepoutil.py - sub-repository operations and substate handling
1 # subrepoutil.py - sub-repository operations and substate handling
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 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import errno
10 import errno
11 import os
11 import os
12 import posixpath
12 import posixpath
13 import re
13 import re
14
14
15 from .i18n import _
15 from .i18n import _
16 from . import (
16 from . import (
17 config,
17 config,
18 error,
18 error,
19 filemerge,
19 filemerge,
20 pathutil,
20 pathutil,
21 phases,
21 phases,
22 util,
22 util,
23 )
23 )
24 from .utils import (
24 from .utils import (
25 stringutil,
25 stringutil,
26 )
26 )
27
27
28 nullstate = ('', '', 'empty')
28 nullstate = ('', '', 'empty')
29
29
30 def state(ctx, ui):
30 def state(ctx, ui):
31 """return a state dict, mapping subrepo paths configured in .hgsub
31 """return a state dict, mapping subrepo paths configured in .hgsub
32 to tuple: (source from .hgsub, revision from .hgsubstate, kind
32 to tuple: (source from .hgsub, revision from .hgsubstate, kind
33 (key in types dict))
33 (key in types dict))
34 """
34 """
35 p = config.config()
35 p = config.config()
36 repo = ctx.repo()
36 repo = ctx.repo()
37 def read(f, sections=None, remap=None):
37 def read(f, sections=None, remap=None):
38 if f in ctx:
38 if f in ctx:
39 try:
39 try:
40 data = ctx[f].data()
40 data = ctx[f].data()
41 except IOError as err:
41 except IOError as err:
42 if err.errno != errno.ENOENT:
42 if err.errno != errno.ENOENT:
43 raise
43 raise
44 # handle missing subrepo spec files as removed
44 # handle missing subrepo spec files as removed
45 ui.warn(_("warning: subrepo spec file \'%s\' not found\n") %
45 ui.warn(_("warning: subrepo spec file \'%s\' not found\n") %
46 repo.pathto(f))
46 repo.pathto(f))
47 return
47 return
48 p.parse(f, data, sections, remap, read)
48 p.parse(f, data, sections, remap, read)
49 else:
49 else:
50 raise error.Abort(_("subrepo spec file \'%s\' not found") %
50 raise error.Abort(_("subrepo spec file \'%s\' not found") %
51 repo.pathto(f))
51 repo.pathto(f))
52 if '.hgsub' in ctx:
52 if '.hgsub' in ctx:
53 read('.hgsub')
53 read('.hgsub')
54
54
55 for path, src in ui.configitems('subpaths'):
55 for path, src in ui.configitems('subpaths'):
56 p.set('subpaths', path, src, ui.configsource('subpaths', path))
56 p.set('subpaths', path, src, ui.configsource('subpaths', path))
57
57
58 rev = {}
58 rev = {}
59 if '.hgsubstate' in ctx:
59 if '.hgsubstate' in ctx:
60 try:
60 try:
61 for i, l in enumerate(ctx['.hgsubstate'].data().splitlines()):
61 for i, l in enumerate(ctx['.hgsubstate'].data().splitlines()):
62 l = l.lstrip()
62 l = l.lstrip()
63 if not l:
63 if not l:
64 continue
64 continue
65 try:
65 try:
66 revision, path = l.split(" ", 1)
66 revision, path = l.split(" ", 1)
67 except ValueError:
67 except ValueError:
68 raise error.Abort(_("invalid subrepository revision "
68 raise error.Abort(_("invalid subrepository revision "
69 "specifier in \'%s\' line %d")
69 "specifier in \'%s\' line %d")
70 % (repo.pathto('.hgsubstate'), (i + 1)))
70 % (repo.pathto('.hgsubstate'), (i + 1)))
71 rev[path] = revision
71 rev[path] = revision
72 except IOError as err:
72 except IOError as err:
73 if err.errno != errno.ENOENT:
73 if err.errno != errno.ENOENT:
74 raise
74 raise
75
75
76 def remap(src):
76 def remap(src):
77 for pattern, repl in p.items('subpaths'):
77 for pattern, repl in p.items('subpaths'):
78 # Turn r'C:\foo\bar' into r'C:\\foo\\bar' since re.sub
78 # Turn r'C:\foo\bar' into r'C:\\foo\\bar' since re.sub
79 # does a string decode.
79 # does a string decode.
80 repl = stringutil.escapestr(repl)
80 repl = stringutil.escapestr(repl)
81 # However, we still want to allow back references to go
81 # However, we still want to allow back references to go
82 # through unharmed, so we turn r'\\1' into r'\1'. Again,
82 # through unharmed, so we turn r'\\1' into r'\1'. Again,
83 # extra escapes are needed because re.sub string decodes.
83 # extra escapes are needed because re.sub string decodes.
84 repl = re.sub(br'\\\\([0-9]+)', br'\\\1', repl)
84 repl = re.sub(br'\\\\([0-9]+)', br'\\\1', repl)
85 try:
85 try:
86 src = re.sub(pattern, repl, src, 1)
86 src = re.sub(pattern, repl, src, 1)
87 except re.error as e:
87 except re.error as e:
88 raise error.Abort(_("bad subrepository pattern in %s: %s")
88 raise error.Abort(_("bad subrepository pattern in %s: %s")
89 % (p.source('subpaths', pattern),
89 % (p.source('subpaths', pattern),
90 stringutil.forcebytestr(e)))
90 stringutil.forcebytestr(e)))
91 return src
91 return src
92
92
93 state = {}
93 state = {}
94 for path, src in p[''].items():
94 for path, src in p[''].items():
95 kind = 'hg'
95 kind = 'hg'
96 if src.startswith('['):
96 if src.startswith('['):
97 if ']' not in src:
97 if ']' not in src:
98 raise error.Abort(_('missing ] in subrepository source'))
98 raise error.Abort(_('missing ] in subrepository source'))
99 kind, src = src.split(']', 1)
99 kind, src = src.split(']', 1)
100 kind = kind[1:]
100 kind = kind[1:]
101 src = src.lstrip() # strip any extra whitespace after ']'
101 src = src.lstrip() # strip any extra whitespace after ']'
102
102
103 if not util.url(src).isabs():
103 if not util.url(src).isabs():
104 parent = _abssource(repo, abort=False)
104 parent = _abssource(repo, abort=False)
105 if parent:
105 if parent:
106 parent = util.url(parent)
106 parent = util.url(parent)
107 parent.path = posixpath.join(parent.path or '', src)
107 parent.path = posixpath.join(parent.path or '', src)
108 parent.path = posixpath.normpath(parent.path)
108 parent.path = posixpath.normpath(parent.path)
109 joined = bytes(parent)
109 joined = bytes(parent)
110 # Remap the full joined path and use it if it changes,
110 # Remap the full joined path and use it if it changes,
111 # else remap the original source.
111 # else remap the original source.
112 remapped = remap(joined)
112 remapped = remap(joined)
113 if remapped == joined:
113 if remapped == joined:
114 src = remap(src)
114 src = remap(src)
115 else:
115 else:
116 src = remapped
116 src = remapped
117
117
118 src = remap(src)
118 src = remap(src)
119 state[util.pconvert(path)] = (src.strip(), rev.get(path, ''), kind)
119 state[util.pconvert(path)] = (src.strip(), rev.get(path, ''), kind)
120
120
121 return state
121 return state
122
122
123 def writestate(repo, state):
123 def writestate(repo, state):
124 """rewrite .hgsubstate in (outer) repo with these subrepo states"""
124 """rewrite .hgsubstate in (outer) repo with these subrepo states"""
125 lines = ['%s %s\n' % (state[s][1], s) for s in sorted(state)
125 lines = ['%s %s\n' % (state[s][1], s) for s in sorted(state)
126 if state[s][1] != nullstate[1]]
126 if state[s][1] != nullstate[1]]
127 repo.wwrite('.hgsubstate', ''.join(lines), '')
127 repo.wwrite('.hgsubstate', ''.join(lines), '')
128
128
129 def submerge(repo, wctx, mctx, actx, overwrite, labels=None):
129 def submerge(repo, wctx, mctx, actx, overwrite, labels=None):
130 """delegated from merge.applyupdates: merging of .hgsubstate file
130 """delegated from merge.applyupdates: merging of .hgsubstate file
131 in working context, merging context and ancestor context"""
131 in working context, merging context and ancestor context"""
132 if mctx == actx: # backwards?
132 if mctx == actx: # backwards?
133 actx = wctx.p1()
133 actx = wctx.p1()
134 s1 = wctx.substate
134 s1 = wctx.substate
135 s2 = mctx.substate
135 s2 = mctx.substate
136 sa = actx.substate
136 sa = actx.substate
137 sm = {}
137 sm = {}
138
138
139 repo.ui.debug("subrepo merge %s %s %s\n" % (wctx, mctx, actx))
139 repo.ui.debug("subrepo merge %s %s %s\n" % (wctx, mctx, actx))
140
140
141 def debug(s, msg, r=""):
141 def debug(s, msg, r=""):
142 if r:
142 if r:
143 r = "%s:%s:%s" % r
143 r = "%s:%s:%s" % r
144 repo.ui.debug(" subrepo %s: %s %s\n" % (s, msg, r))
144 repo.ui.debug(" subrepo %s: %s %s\n" % (s, msg, r))
145
145
146 promptssrc = filemerge.partextras(labels)
146 promptssrc = filemerge.partextras(labels)
147 for s, l in sorted(s1.iteritems()):
147 for s, l in sorted(s1.iteritems()):
148 a = sa.get(s, nullstate)
148 a = sa.get(s, nullstate)
149 ld = l # local state with possible dirty flag for compares
149 ld = l # local state with possible dirty flag for compares
150 if wctx.sub(s).dirty():
150 if wctx.sub(s).dirty():
151 ld = (l[0], l[1] + "+")
151 ld = (l[0], l[1] + "+")
152 if wctx == actx: # overwrite
152 if wctx == actx: # overwrite
153 a = ld
153 a = ld
154
154
155 prompts = promptssrc.copy()
155 prompts = promptssrc.copy()
156 prompts['s'] = s
156 prompts['s'] = s
157 if s in s2:
157 if s in s2:
158 r = s2[s]
158 r = s2[s]
159 if ld == r or r == a: # no change or local is newer
159 if ld == r or r == a: # no change or local is newer
160 sm[s] = l
160 sm[s] = l
161 continue
161 continue
162 elif ld == a: # other side changed
162 elif ld == a: # other side changed
163 debug(s, "other changed, get", r)
163 debug(s, "other changed, get", r)
164 wctx.sub(s).get(r, overwrite)
164 wctx.sub(s).get(r, overwrite)
165 sm[s] = r
165 sm[s] = r
166 elif ld[0] != r[0]: # sources differ
166 elif ld[0] != r[0]: # sources differ
167 prompts['lo'] = l[0]
167 prompts['lo'] = l[0]
168 prompts['ro'] = r[0]
168 prompts['ro'] = r[0]
169 if repo.ui.promptchoice(
169 if repo.ui.promptchoice(
170 _(' subrepository sources for %(s)s differ\n'
170 _(' subrepository sources for %(s)s differ\n'
171 'use (l)ocal%(l)s source (%(lo)s)'
171 'you can use (l)ocal%(l)s source (%(lo)s)'
172 ' or (r)emote%(o)s source (%(ro)s)?'
172 ' or (r)emote%(o)s source (%(ro)s).\n'
173 'what do you want to do?'
173 '$$ &Local $$ &Remote') % prompts, 0):
174 '$$ &Local $$ &Remote') % prompts, 0):
174 debug(s, "prompt changed, get", r)
175 debug(s, "prompt changed, get", r)
175 wctx.sub(s).get(r, overwrite)
176 wctx.sub(s).get(r, overwrite)
176 sm[s] = r
177 sm[s] = r
177 elif ld[1] == a[1]: # local side is unchanged
178 elif ld[1] == a[1]: # local side is unchanged
178 debug(s, "other side changed, get", r)
179 debug(s, "other side changed, get", r)
179 wctx.sub(s).get(r, overwrite)
180 wctx.sub(s).get(r, overwrite)
180 sm[s] = r
181 sm[s] = r
181 else:
182 else:
182 debug(s, "both sides changed")
183 debug(s, "both sides changed")
183 srepo = wctx.sub(s)
184 srepo = wctx.sub(s)
184 prompts['sl'] = srepo.shortid(l[1])
185 prompts['sl'] = srepo.shortid(l[1])
185 prompts['sr'] = srepo.shortid(r[1])
186 prompts['sr'] = srepo.shortid(r[1])
186 option = repo.ui.promptchoice(
187 option = repo.ui.promptchoice(
187 _(' subrepository %(s)s diverged (local revision: %(sl)s, '
188 _(' subrepository %(s)s diverged (local revision: %(sl)s, '
188 'remote revision: %(sr)s)\n'
189 'remote revision: %(sr)s)\n'
189 '(M)erge, keep (l)ocal%(l)s or keep (r)emote%(o)s?'
190 'you can (m)erge, keep (l)ocal%(l)s or keep '
191 '(r)emote%(o)s.\n'
192 'what do you want to do?'
190 '$$ &Merge $$ &Local $$ &Remote')
193 '$$ &Merge $$ &Local $$ &Remote')
191 % prompts, 0)
194 % prompts, 0)
192 if option == 0:
195 if option == 0:
193 wctx.sub(s).merge(r)
196 wctx.sub(s).merge(r)
194 sm[s] = l
197 sm[s] = l
195 debug(s, "merge with", r)
198 debug(s, "merge with", r)
196 elif option == 1:
199 elif option == 1:
197 sm[s] = l
200 sm[s] = l
198 debug(s, "keep local subrepo revision", l)
201 debug(s, "keep local subrepo revision", l)
199 else:
202 else:
200 wctx.sub(s).get(r, overwrite)
203 wctx.sub(s).get(r, overwrite)
201 sm[s] = r
204 sm[s] = r
202 debug(s, "get remote subrepo revision", r)
205 debug(s, "get remote subrepo revision", r)
203 elif ld == a: # remote removed, local unchanged
206 elif ld == a: # remote removed, local unchanged
204 debug(s, "remote removed, remove")
207 debug(s, "remote removed, remove")
205 wctx.sub(s).remove()
208 wctx.sub(s).remove()
206 elif a == nullstate: # not present in remote or ancestor
209 elif a == nullstate: # not present in remote or ancestor
207 debug(s, "local added, keep")
210 debug(s, "local added, keep")
208 sm[s] = l
211 sm[s] = l
209 continue
212 continue
210 else:
213 else:
211 if repo.ui.promptchoice(
214 if repo.ui.promptchoice(
212 _(' local%(l)s changed subrepository %(s)s'
215 _(' local%(l)s changed subrepository %(s)s'
213 ' which remote%(o)s removed\n'
216 ' which remote%(o)s removed\n'
214 'use (c)hanged version or (d)elete?'
217 'use (c)hanged version or (d)elete?'
215 '$$ &Changed $$ &Delete') % prompts, 0):
218 '$$ &Changed $$ &Delete') % prompts, 0):
216 debug(s, "prompt remove")
219 debug(s, "prompt remove")
217 wctx.sub(s).remove()
220 wctx.sub(s).remove()
218
221
219 for s, r in sorted(s2.items()):
222 for s, r in sorted(s2.items()):
220 if s in s1:
223 if s in s1:
221 continue
224 continue
222 elif s not in sa:
225 elif s not in sa:
223 debug(s, "remote added, get", r)
226 debug(s, "remote added, get", r)
224 mctx.sub(s).get(r)
227 mctx.sub(s).get(r)
225 sm[s] = r
228 sm[s] = r
226 elif r != sa[s]:
229 elif r != sa[s]:
227 prompts = promptssrc.copy()
230 prompts = promptssrc.copy()
228 prompts['s'] = s
231 prompts['s'] = s
229 if repo.ui.promptchoice(
232 if repo.ui.promptchoice(
230 _(' remote%(o)s changed subrepository %(s)s'
233 _(' remote%(o)s changed subrepository %(s)s'
231 ' which local%(l)s removed\n'
234 ' which local%(l)s removed\n'
232 'use (c)hanged version or (d)elete?'
235 'use (c)hanged version or (d)elete?'
233 '$$ &Changed $$ &Delete') % prompts, 0) == 0:
236 '$$ &Changed $$ &Delete') % prompts, 0) == 0:
234 debug(s, "prompt recreate", r)
237 debug(s, "prompt recreate", r)
235 mctx.sub(s).get(r)
238 mctx.sub(s).get(r)
236 sm[s] = r
239 sm[s] = r
237
240
238 # record merged .hgsubstate
241 # record merged .hgsubstate
239 writestate(repo, sm)
242 writestate(repo, sm)
240 return sm
243 return sm
241
244
242 def precommit(ui, wctx, status, match, force=False):
245 def precommit(ui, wctx, status, match, force=False):
243 """Calculate .hgsubstate changes that should be applied before committing
246 """Calculate .hgsubstate changes that should be applied before committing
244
247
245 Returns (subs, commitsubs, newstate) where
248 Returns (subs, commitsubs, newstate) where
246 - subs: changed subrepos (including dirty ones)
249 - subs: changed subrepos (including dirty ones)
247 - commitsubs: dirty subrepos which the caller needs to commit recursively
250 - commitsubs: dirty subrepos which the caller needs to commit recursively
248 - newstate: new state dict which the caller must write to .hgsubstate
251 - newstate: new state dict which the caller must write to .hgsubstate
249
252
250 This also updates the given status argument.
253 This also updates the given status argument.
251 """
254 """
252 subs = []
255 subs = []
253 commitsubs = set()
256 commitsubs = set()
254 newstate = wctx.substate.copy()
257 newstate = wctx.substate.copy()
255
258
256 # only manage subrepos and .hgsubstate if .hgsub is present
259 # only manage subrepos and .hgsubstate if .hgsub is present
257 if '.hgsub' in wctx:
260 if '.hgsub' in wctx:
258 # we'll decide whether to track this ourselves, thanks
261 # we'll decide whether to track this ourselves, thanks
259 for c in status.modified, status.added, status.removed:
262 for c in status.modified, status.added, status.removed:
260 if '.hgsubstate' in c:
263 if '.hgsubstate' in c:
261 c.remove('.hgsubstate')
264 c.remove('.hgsubstate')
262
265
263 # compare current state to last committed state
266 # compare current state to last committed state
264 # build new substate based on last committed state
267 # build new substate based on last committed state
265 oldstate = wctx.p1().substate
268 oldstate = wctx.p1().substate
266 for s in sorted(newstate.keys()):
269 for s in sorted(newstate.keys()):
267 if not match(s):
270 if not match(s):
268 # ignore working copy, use old state if present
271 # ignore working copy, use old state if present
269 if s in oldstate:
272 if s in oldstate:
270 newstate[s] = oldstate[s]
273 newstate[s] = oldstate[s]
271 continue
274 continue
272 if not force:
275 if not force:
273 raise error.Abort(
276 raise error.Abort(
274 _("commit with new subrepo %s excluded") % s)
277 _("commit with new subrepo %s excluded") % s)
275 dirtyreason = wctx.sub(s).dirtyreason(True)
278 dirtyreason = wctx.sub(s).dirtyreason(True)
276 if dirtyreason:
279 if dirtyreason:
277 if not ui.configbool('ui', 'commitsubrepos'):
280 if not ui.configbool('ui', 'commitsubrepos'):
278 raise error.Abort(dirtyreason,
281 raise error.Abort(dirtyreason,
279 hint=_("use --subrepos for recursive commit"))
282 hint=_("use --subrepos for recursive commit"))
280 subs.append(s)
283 subs.append(s)
281 commitsubs.add(s)
284 commitsubs.add(s)
282 else:
285 else:
283 bs = wctx.sub(s).basestate()
286 bs = wctx.sub(s).basestate()
284 newstate[s] = (newstate[s][0], bs, newstate[s][2])
287 newstate[s] = (newstate[s][0], bs, newstate[s][2])
285 if oldstate.get(s, (None, None, None))[1] != bs:
288 if oldstate.get(s, (None, None, None))[1] != bs:
286 subs.append(s)
289 subs.append(s)
287
290
288 # check for removed subrepos
291 # check for removed subrepos
289 for p in wctx.parents():
292 for p in wctx.parents():
290 r = [s for s in p.substate if s not in newstate]
293 r = [s for s in p.substate if s not in newstate]
291 subs += [s for s in r if match(s)]
294 subs += [s for s in r if match(s)]
292 if subs:
295 if subs:
293 if (not match('.hgsub') and
296 if (not match('.hgsub') and
294 '.hgsub' in (wctx.modified() + wctx.added())):
297 '.hgsub' in (wctx.modified() + wctx.added())):
295 raise error.Abort(_("can't commit subrepos without .hgsub"))
298 raise error.Abort(_("can't commit subrepos without .hgsub"))
296 status.modified.insert(0, '.hgsubstate')
299 status.modified.insert(0, '.hgsubstate')
297
300
298 elif '.hgsub' in status.removed:
301 elif '.hgsub' in status.removed:
299 # clean up .hgsubstate when .hgsub is removed
302 # clean up .hgsubstate when .hgsub is removed
300 if ('.hgsubstate' in wctx and
303 if ('.hgsubstate' in wctx and
301 '.hgsubstate' not in (status.modified + status.added +
304 '.hgsubstate' not in (status.modified + status.added +
302 status.removed)):
305 status.removed)):
303 status.removed.insert(0, '.hgsubstate')
306 status.removed.insert(0, '.hgsubstate')
304
307
305 return subs, commitsubs, newstate
308 return subs, commitsubs, newstate
306
309
307 def reporelpath(repo):
310 def reporelpath(repo):
308 """return path to this (sub)repo as seen from outermost repo"""
311 """return path to this (sub)repo as seen from outermost repo"""
309 parent = repo
312 parent = repo
310 while util.safehasattr(parent, '_subparent'):
313 while util.safehasattr(parent, '_subparent'):
311 parent = parent._subparent
314 parent = parent._subparent
312 return repo.root[len(pathutil.normasprefix(parent.root)):]
315 return repo.root[len(pathutil.normasprefix(parent.root)):]
313
316
314 def subrelpath(sub):
317 def subrelpath(sub):
315 """return path to this subrepo as seen from outermost repo"""
318 """return path to this subrepo as seen from outermost repo"""
316 return sub._relpath
319 return sub._relpath
317
320
318 def _abssource(repo, push=False, abort=True):
321 def _abssource(repo, push=False, abort=True):
319 """return pull/push path of repo - either based on parent repo .hgsub info
322 """return pull/push path of repo - either based on parent repo .hgsub info
320 or on the top repo config. Abort or return None if no source found."""
323 or on the top repo config. Abort or return None if no source found."""
321 if util.safehasattr(repo, '_subparent'):
324 if util.safehasattr(repo, '_subparent'):
322 source = util.url(repo._subsource)
325 source = util.url(repo._subsource)
323 if source.isabs():
326 if source.isabs():
324 return bytes(source)
327 return bytes(source)
325 source.path = posixpath.normpath(source.path)
328 source.path = posixpath.normpath(source.path)
326 parent = _abssource(repo._subparent, push, abort=False)
329 parent = _abssource(repo._subparent, push, abort=False)
327 if parent:
330 if parent:
328 parent = util.url(util.pconvert(parent))
331 parent = util.url(util.pconvert(parent))
329 parent.path = posixpath.join(parent.path or '', source.path)
332 parent.path = posixpath.join(parent.path or '', source.path)
330 parent.path = posixpath.normpath(parent.path)
333 parent.path = posixpath.normpath(parent.path)
331 return bytes(parent)
334 return bytes(parent)
332 else: # recursion reached top repo
335 else: # recursion reached top repo
333 path = None
336 path = None
334 if util.safehasattr(repo, '_subtoppath'):
337 if util.safehasattr(repo, '_subtoppath'):
335 path = repo._subtoppath
338 path = repo._subtoppath
336 elif push and repo.ui.config('paths', 'default-push'):
339 elif push and repo.ui.config('paths', 'default-push'):
337 path = repo.ui.config('paths', 'default-push')
340 path = repo.ui.config('paths', 'default-push')
338 elif repo.ui.config('paths', 'default'):
341 elif repo.ui.config('paths', 'default'):
339 path = repo.ui.config('paths', 'default')
342 path = repo.ui.config('paths', 'default')
340 elif repo.shared():
343 elif repo.shared():
341 # chop off the .hg component to get the default path form. This has
344 # chop off the .hg component to get the default path form. This has
342 # already run through vfsmod.vfs(..., realpath=True), so it doesn't
345 # already run through vfsmod.vfs(..., realpath=True), so it doesn't
343 # have problems with 'C:'
346 # have problems with 'C:'
344 return os.path.dirname(repo.sharedpath)
347 return os.path.dirname(repo.sharedpath)
345 if path:
348 if path:
346 # issue5770: 'C:\' and 'C:' are not equivalent paths. The former is
349 # issue5770: 'C:\' and 'C:' are not equivalent paths. The former is
347 # as expected: an absolute path to the root of the C: drive. The
350 # as expected: an absolute path to the root of the C: drive. The
348 # latter is a relative path, and works like so:
351 # latter is a relative path, and works like so:
349 #
352 #
350 # C:\>cd C:\some\path
353 # C:\>cd C:\some\path
351 # C:\>D:
354 # C:\>D:
352 # D:\>python -c "import os; print os.path.abspath('C:')"
355 # D:\>python -c "import os; print os.path.abspath('C:')"
353 # C:\some\path
356 # C:\some\path
354 #
357 #
355 # D:\>python -c "import os; print os.path.abspath('C:relative')"
358 # D:\>python -c "import os; print os.path.abspath('C:relative')"
356 # C:\some\path\relative
359 # C:\some\path\relative
357 if util.hasdriveletter(path):
360 if util.hasdriveletter(path):
358 if len(path) == 2 or path[2:3] not in br'\/':
361 if len(path) == 2 or path[2:3] not in br'\/':
359 path = os.path.abspath(path)
362 path = os.path.abspath(path)
360 return path
363 return path
361
364
362 if abort:
365 if abort:
363 raise error.Abort(_("default path for subrepository not found"))
366 raise error.Abort(_("default path for subrepository not found"))
364
367
365 def newcommitphase(ui, ctx):
368 def newcommitphase(ui, ctx):
366 commitphase = phases.newcommitphase(ui)
369 commitphase = phases.newcommitphase(ui)
367 substate = getattr(ctx, "substate", None)
370 substate = getattr(ctx, "substate", None)
368 if not substate:
371 if not substate:
369 return commitphase
372 return commitphase
370 check = ui.config('phases', 'checksubrepos')
373 check = ui.config('phases', 'checksubrepos')
371 if check not in ('ignore', 'follow', 'abort'):
374 if check not in ('ignore', 'follow', 'abort'):
372 raise error.Abort(_('invalid phases.checksubrepos configuration: %s')
375 raise error.Abort(_('invalid phases.checksubrepos configuration: %s')
373 % (check))
376 % (check))
374 if check == 'ignore':
377 if check == 'ignore':
375 return commitphase
378 return commitphase
376 maxphase = phases.public
379 maxphase = phases.public
377 maxsub = None
380 maxsub = None
378 for s in sorted(substate):
381 for s in sorted(substate):
379 sub = ctx.sub(s)
382 sub = ctx.sub(s)
380 subphase = sub.phase(substate[s][1])
383 subphase = sub.phase(substate[s][1])
381 if maxphase < subphase:
384 if maxphase < subphase:
382 maxphase = subphase
385 maxphase = subphase
383 maxsub = s
386 maxsub = s
384 if commitphase < maxphase:
387 if commitphase < maxphase:
385 if check == 'abort':
388 if check == 'abort':
386 raise error.Abort(_("can't commit in %s phase"
389 raise error.Abort(_("can't commit in %s phase"
387 " conflicting %s from subrepository %s") %
390 " conflicting %s from subrepository %s") %
388 (phases.phasenames[commitphase],
391 (phases.phasenames[commitphase],
389 phases.phasenames[maxphase], maxsub))
392 phases.phasenames[maxphase], maxsub))
390 ui.warn(_("warning: changes are committed in"
393 ui.warn(_("warning: changes are committed in"
391 " %s phase from subrepository %s\n") %
394 " %s phase from subrepository %s\n") %
392 (phases.phasenames[maxphase], maxsub))
395 (phases.phasenames[maxphase], maxsub))
393 return maxphase
396 return maxphase
394 return commitphase
397 return commitphase
@@ -1,795 +1,797 b''
1 #require no-reposimplestore
1 #require no-reposimplestore
2
2
3 This file focuses mainly on updating largefiles in the working
3 This file focuses mainly on updating largefiles in the working
4 directory (and ".hg/largefiles/dirstate")
4 directory (and ".hg/largefiles/dirstate")
5
5
6 $ cat >> $HGRCPATH <<EOF
6 $ cat >> $HGRCPATH <<EOF
7 > [ui]
7 > [ui]
8 > merge = internal:merge
8 > merge = internal:merge
9 > [extensions]
9 > [extensions]
10 > largefiles =
10 > largefiles =
11 > [extdiff]
11 > [extdiff]
12 > # for portability:
12 > # for portability:
13 > pdiff = sh "$RUNTESTDIR/pdiff"
13 > pdiff = sh "$RUNTESTDIR/pdiff"
14 > EOF
14 > EOF
15
15
16 $ hg init repo
16 $ hg init repo
17 $ cd repo
17 $ cd repo
18
18
19 $ echo large1 > large1
19 $ echo large1 > large1
20 $ echo large2 > large2
20 $ echo large2 > large2
21 $ hg add --large large1 large2
21 $ hg add --large large1 large2
22 $ echo normal1 > normal1
22 $ echo normal1 > normal1
23 $ hg add normal1
23 $ hg add normal1
24 $ hg commit -m '#0'
24 $ hg commit -m '#0'
25 $ echo 'large1 in #1' > large1
25 $ echo 'large1 in #1' > large1
26 $ echo 'normal1 in #1' > normal1
26 $ echo 'normal1 in #1' > normal1
27 $ hg commit -m '#1'
27 $ hg commit -m '#1'
28 $ hg pdiff -r '.^' --config extensions.extdiff=
28 $ hg pdiff -r '.^' --config extensions.extdiff=
29 diff -Nru repo.0d9d9b8dc9a3/.hglf/large1 repo/.hglf/large1
29 diff -Nru repo.0d9d9b8dc9a3/.hglf/large1 repo/.hglf/large1
30 --- repo.0d9d9b8dc9a3/.hglf/large1 * (glob)
30 --- repo.0d9d9b8dc9a3/.hglf/large1 * (glob)
31 +++ repo/.hglf/large1 * (glob)
31 +++ repo/.hglf/large1 * (glob)
32 @@ -1* +1* @@ (glob)
32 @@ -1* +1* @@ (glob)
33 -4669e532d5b2c093a78eca010077e708a071bb64
33 -4669e532d5b2c093a78eca010077e708a071bb64
34 +58e24f733a964da346e2407a2bee99d9001184f5
34 +58e24f733a964da346e2407a2bee99d9001184f5
35 diff -Nru repo.0d9d9b8dc9a3/normal1 repo/normal1
35 diff -Nru repo.0d9d9b8dc9a3/normal1 repo/normal1
36 --- repo.0d9d9b8dc9a3/normal1 * (glob)
36 --- repo.0d9d9b8dc9a3/normal1 * (glob)
37 +++ repo/normal1 * (glob)
37 +++ repo/normal1 * (glob)
38 @@ -1* +1* @@ (glob)
38 @@ -1* +1* @@ (glob)
39 -normal1
39 -normal1
40 +normal1 in #1
40 +normal1 in #1
41 [1]
41 [1]
42 $ hg update -q -C 0
42 $ hg update -q -C 0
43 $ echo 'large2 in #2' > large2
43 $ echo 'large2 in #2' > large2
44 $ hg commit -m '#2'
44 $ hg commit -m '#2'
45 created new head
45 created new head
46
46
47 Test that update also updates the lfdirstate of 'unsure' largefiles after
47 Test that update also updates the lfdirstate of 'unsure' largefiles after
48 hashing them:
48 hashing them:
49
49
50 The previous operations will usually have left us with largefiles with a mtime
50 The previous operations will usually have left us with largefiles with a mtime
51 within the same second as the dirstate was written.
51 within the same second as the dirstate was written.
52 The lfdirstate entries will thus have been written with an invalidated/unset
52 The lfdirstate entries will thus have been written with an invalidated/unset
53 mtime to make sure further changes within the same second is detected.
53 mtime to make sure further changes within the same second is detected.
54 We will however occasionally be "lucky" and get a tick between writing
54 We will however occasionally be "lucky" and get a tick between writing
55 largefiles and writing dirstate so we get valid lfdirstate timestamps. The
55 largefiles and writing dirstate so we get valid lfdirstate timestamps. The
56 following verification is thus disabled but can be verified manually.
56 following verification is thus disabled but can be verified manually.
57
57
58 #if false
58 #if false
59 $ hg debugdirstate --large --nodate
59 $ hg debugdirstate --large --nodate
60 n 644 7 unset large1
60 n 644 7 unset large1
61 n 644 13 unset large2
61 n 644 13 unset large2
62 #endif
62 #endif
63
63
64 Wait to make sure we get a tick so the mtime of the largefiles become valid.
64 Wait to make sure we get a tick so the mtime of the largefiles become valid.
65
65
66 $ sleep 1
66 $ sleep 1
67
67
68 A linear merge will update standins before performing the actual merge. It will
68 A linear merge will update standins before performing the actual merge. It will
69 do a lfdirstate status walk and find 'unset'/'unsure' files, hash them, and
69 do a lfdirstate status walk and find 'unset'/'unsure' files, hash them, and
70 update the corresponding standins.
70 update the corresponding standins.
71 Verify that it actually marks the clean files as clean in lfdirstate so
71 Verify that it actually marks the clean files as clean in lfdirstate so
72 we don't have to hash them again next time we update.
72 we don't have to hash them again next time we update.
73
73
74 $ hg up
74 $ hg up
75 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
75 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
76 updated to "f74e50bd9e55: #2"
76 updated to "f74e50bd9e55: #2"
77 1 other heads for branch "default"
77 1 other heads for branch "default"
78 $ hg debugdirstate --large --nodate
78 $ hg debugdirstate --large --nodate
79 n 644 7 set large1
79 n 644 7 set large1
80 n 644 13 set large2
80 n 644 13 set large2
81
81
82 Test that lfdirstate keeps track of last modification of largefiles and
82 Test that lfdirstate keeps track of last modification of largefiles and
83 prevents unnecessary hashing of content - also after linear/noop update
83 prevents unnecessary hashing of content - also after linear/noop update
84
84
85 $ sleep 1
85 $ sleep 1
86 $ hg st
86 $ hg st
87 $ hg debugdirstate --large --nodate
87 $ hg debugdirstate --large --nodate
88 n 644 7 set large1
88 n 644 7 set large1
89 n 644 13 set large2
89 n 644 13 set large2
90 $ hg up
90 $ hg up
91 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
91 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
92 updated to "f74e50bd9e55: #2"
92 updated to "f74e50bd9e55: #2"
93 1 other heads for branch "default"
93 1 other heads for branch "default"
94 $ hg debugdirstate --large --nodate
94 $ hg debugdirstate --large --nodate
95 n 644 7 set large1
95 n 644 7 set large1
96 n 644 13 set large2
96 n 644 13 set large2
97
97
98 Test that "hg merge" updates largefiles from "other" correctly
98 Test that "hg merge" updates largefiles from "other" correctly
99
99
100 (getting largefiles from "other" normally)
100 (getting largefiles from "other" normally)
101
101
102 $ hg status -A large1
102 $ hg status -A large1
103 C large1
103 C large1
104 $ cat large1
104 $ cat large1
105 large1
105 large1
106 $ cat .hglf/large1
106 $ cat .hglf/large1
107 4669e532d5b2c093a78eca010077e708a071bb64
107 4669e532d5b2c093a78eca010077e708a071bb64
108 $ hg merge --config debug.dirstate.delaywrite=2
108 $ hg merge --config debug.dirstate.delaywrite=2
109 getting changed largefiles
109 getting changed largefiles
110 1 largefiles updated, 0 removed
110 1 largefiles updated, 0 removed
111 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
111 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
112 (branch merge, don't forget to commit)
112 (branch merge, don't forget to commit)
113 $ hg status -A large1
113 $ hg status -A large1
114 M large1
114 M large1
115 $ cat large1
115 $ cat large1
116 large1 in #1
116 large1 in #1
117 $ cat .hglf/large1
117 $ cat .hglf/large1
118 58e24f733a964da346e2407a2bee99d9001184f5
118 58e24f733a964da346e2407a2bee99d9001184f5
119 $ hg diff -c 1 --nodates .hglf/large1 | grep '^[+-][0-9a-z]'
119 $ hg diff -c 1 --nodates .hglf/large1 | grep '^[+-][0-9a-z]'
120 -4669e532d5b2c093a78eca010077e708a071bb64
120 -4669e532d5b2c093a78eca010077e708a071bb64
121 +58e24f733a964da346e2407a2bee99d9001184f5
121 +58e24f733a964da346e2407a2bee99d9001184f5
122
122
123 (getting largefiles from "other" via conflict prompt)
123 (getting largefiles from "other" via conflict prompt)
124
124
125 $ hg update -q -C 2
125 $ hg update -q -C 2
126 $ echo 'large1 in #3' > large1
126 $ echo 'large1 in #3' > large1
127 $ echo 'normal1 in #3' > normal1
127 $ echo 'normal1 in #3' > normal1
128 $ hg commit -m '#3'
128 $ hg commit -m '#3'
129 $ cat .hglf/large1
129 $ cat .hglf/large1
130 e5bb990443d6a92aaf7223813720f7566c9dd05b
130 e5bb990443d6a92aaf7223813720f7566c9dd05b
131 $ hg merge --config debug.dirstate.delaywrite=2 --config ui.interactive=True <<EOF
131 $ hg merge --config debug.dirstate.delaywrite=2 --config ui.interactive=True <<EOF
132 > o
132 > o
133 > EOF
133 > EOF
134 largefile large1 has a merge conflict
134 largefile large1 has a merge conflict
135 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
135 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
136 you can keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5.
136 you can keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5.
137 what do you want to do? o
137 what do you want to do? o
138 merging normal1
138 merging normal1
139 warning: conflicts while merging normal1! (edit, then use 'hg resolve --mark')
139 warning: conflicts while merging normal1! (edit, then use 'hg resolve --mark')
140 getting changed largefiles
140 getting changed largefiles
141 1 largefiles updated, 0 removed
141 1 largefiles updated, 0 removed
142 0 files updated, 1 files merged, 0 files removed, 1 files unresolved
142 0 files updated, 1 files merged, 0 files removed, 1 files unresolved
143 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
143 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
144 [1]
144 [1]
145 $ hg status -A large1
145 $ hg status -A large1
146 M large1
146 M large1
147 $ cat large1
147 $ cat large1
148 large1 in #1
148 large1 in #1
149 $ cat .hglf/large1
149 $ cat .hglf/large1
150 58e24f733a964da346e2407a2bee99d9001184f5
150 58e24f733a964da346e2407a2bee99d9001184f5
151 $ rm normal1.orig
151 $ rm normal1.orig
152
152
153 (merge non-existing largefiles from "other" via conflict prompt -
153 (merge non-existing largefiles from "other" via conflict prompt -
154 make sure the following commit doesn't abort in a confusing way when trying to
154 make sure the following commit doesn't abort in a confusing way when trying to
155 mark the non-existing file as normal in lfdirstate)
155 mark the non-existing file as normal in lfdirstate)
156
156
157 $ mv .hg/largefiles/58e24f733a964da346e2407a2bee99d9001184f5 .
157 $ mv .hg/largefiles/58e24f733a964da346e2407a2bee99d9001184f5 .
158 $ hg update -q -C 3
158 $ hg update -q -C 3
159 $ hg merge --config largefiles.usercache=not --config debug.dirstate.delaywrite=2 --tool :local --config ui.interactive=True <<EOF
159 $ hg merge --config largefiles.usercache=not --config debug.dirstate.delaywrite=2 --tool :local --config ui.interactive=True <<EOF
160 > o
160 > o
161 > EOF
161 > EOF
162 largefile large1 has a merge conflict
162 largefile large1 has a merge conflict
163 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
163 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
164 you can keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5.
164 you can keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5.
165 what do you want to do? o
165 what do you want to do? o
166 getting changed largefiles
166 getting changed largefiles
167 large1: largefile 58e24f733a964da346e2407a2bee99d9001184f5 not available from file:/*/$TESTTMP/repo (glob)
167 large1: largefile 58e24f733a964da346e2407a2bee99d9001184f5 not available from file:/*/$TESTTMP/repo (glob)
168 0 largefiles updated, 0 removed
168 0 largefiles updated, 0 removed
169 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
169 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
170 (branch merge, don't forget to commit)
170 (branch merge, don't forget to commit)
171 $ hg commit -m '1-2-3 testing' --config largefiles.usercache=not
171 $ hg commit -m '1-2-3 testing' --config largefiles.usercache=not
172 large1: largefile 58e24f733a964da346e2407a2bee99d9001184f5 not available from local store
172 large1: largefile 58e24f733a964da346e2407a2bee99d9001184f5 not available from local store
173 $ hg up -C . --config largefiles.usercache=not
173 $ hg up -C . --config largefiles.usercache=not
174 getting changed largefiles
174 getting changed largefiles
175 large1: largefile 58e24f733a964da346e2407a2bee99d9001184f5 not available from file:/*/$TESTTMP/repo (glob)
175 large1: largefile 58e24f733a964da346e2407a2bee99d9001184f5 not available from file:/*/$TESTTMP/repo (glob)
176 0 largefiles updated, 0 removed
176 0 largefiles updated, 0 removed
177 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
177 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
178 $ hg st large1
178 $ hg st large1
179 ! large1
179 ! large1
180 $ hg rollback -q
180 $ hg rollback -q
181 $ mv 58e24f733a964da346e2407a2bee99d9001184f5 .hg/largefiles/
181 $ mv 58e24f733a964da346e2407a2bee99d9001184f5 .hg/largefiles/
182
182
183 Test that "hg revert -r REV" updates largefiles from "REV" correctly
183 Test that "hg revert -r REV" updates largefiles from "REV" correctly
184
184
185 $ hg update -q -C 3
185 $ hg update -q -C 3
186 $ hg status -A large1
186 $ hg status -A large1
187 C large1
187 C large1
188 $ cat large1
188 $ cat large1
189 large1 in #3
189 large1 in #3
190 $ cat .hglf/large1
190 $ cat .hglf/large1
191 e5bb990443d6a92aaf7223813720f7566c9dd05b
191 e5bb990443d6a92aaf7223813720f7566c9dd05b
192 $ hg diff -c 1 --nodates .hglf/large1 | grep '^[+-][0-9a-z]'
192 $ hg diff -c 1 --nodates .hglf/large1 | grep '^[+-][0-9a-z]'
193 -4669e532d5b2c093a78eca010077e708a071bb64
193 -4669e532d5b2c093a78eca010077e708a071bb64
194 +58e24f733a964da346e2407a2bee99d9001184f5
194 +58e24f733a964da346e2407a2bee99d9001184f5
195 $ hg revert --no-backup -r 1 --config debug.dirstate.delaywrite=2 large1
195 $ hg revert --no-backup -r 1 --config debug.dirstate.delaywrite=2 large1
196 $ hg status -A large1
196 $ hg status -A large1
197 M large1
197 M large1
198 $ cat large1
198 $ cat large1
199 large1 in #1
199 large1 in #1
200 $ cat .hglf/large1
200 $ cat .hglf/large1
201 58e24f733a964da346e2407a2bee99d9001184f5
201 58e24f733a964da346e2407a2bee99d9001184f5
202
202
203 Test that "hg rollback" restores status of largefiles correctly
203 Test that "hg rollback" restores status of largefiles correctly
204
204
205 $ hg update -C -q
205 $ hg update -C -q
206 $ hg remove large1
206 $ hg remove large1
207 $ test -f .hglf/large1
207 $ test -f .hglf/large1
208 [1]
208 [1]
209 $ hg forget large2
209 $ hg forget large2
210 $ test -f .hglf/large2
210 $ test -f .hglf/large2
211 [1]
211 [1]
212 $ echo largeX > largeX
212 $ echo largeX > largeX
213 $ hg add --large largeX
213 $ hg add --large largeX
214 $ cat .hglf/largeX
214 $ cat .hglf/largeX
215
215
216 $ hg commit -m 'will be rollback-ed soon'
216 $ hg commit -m 'will be rollback-ed soon'
217 $ echo largeY > largeY
217 $ echo largeY > largeY
218 $ hg add --large largeY
218 $ hg add --large largeY
219
219
220 $ hg status -A large1
220 $ hg status -A large1
221 large1: $ENOENT$
221 large1: $ENOENT$
222
222
223 $ hg status -A large2
223 $ hg status -A large2
224 ? large2
224 ? large2
225 $ hg status -A largeX
225 $ hg status -A largeX
226 C largeX
226 C largeX
227 $ hg status -A largeY
227 $ hg status -A largeY
228 A largeY
228 A largeY
229 $ hg rollback
229 $ hg rollback
230 repository tip rolled back to revision 3 (undo commit)
230 repository tip rolled back to revision 3 (undo commit)
231 working directory now based on revision 3
231 working directory now based on revision 3
232 $ hg status -A large1
232 $ hg status -A large1
233 R large1
233 R large1
234 $ test -f .hglf/large1
234 $ test -f .hglf/large1
235 [1]
235 [1]
236 $ hg status -A large2
236 $ hg status -A large2
237 R large2
237 R large2
238 $ test -f .hglf/large2
238 $ test -f .hglf/large2
239 [1]
239 [1]
240 $ hg status -A largeX
240 $ hg status -A largeX
241 A largeX
241 A largeX
242 $ cat .hglf/largeX
242 $ cat .hglf/largeX
243
243
244 $ hg status -A largeY
244 $ hg status -A largeY
245 ? largeY
245 ? largeY
246 $ test -f .hglf/largeY
246 $ test -f .hglf/largeY
247 [1]
247 [1]
248 $ rm largeY
248 $ rm largeY
249
249
250 Test that "hg rollback" restores standins correctly
250 Test that "hg rollback" restores standins correctly
251
251
252 $ hg commit -m 'will be rollback-ed soon'
252 $ hg commit -m 'will be rollback-ed soon'
253 $ hg update -q -C 2
253 $ hg update -q -C 2
254 $ cat large1
254 $ cat large1
255 large1
255 large1
256 $ cat .hglf/large1
256 $ cat .hglf/large1
257 4669e532d5b2c093a78eca010077e708a071bb64
257 4669e532d5b2c093a78eca010077e708a071bb64
258 $ cat large2
258 $ cat large2
259 large2 in #2
259 large2 in #2
260 $ cat .hglf/large2
260 $ cat .hglf/large2
261 3cfce6277e7668985707b6887ce56f9f62f6ccd9
261 3cfce6277e7668985707b6887ce56f9f62f6ccd9
262
262
263 $ hg rollback -q -f
263 $ hg rollback -q -f
264 $ cat large1
264 $ cat large1
265 large1
265 large1
266 $ cat .hglf/large1
266 $ cat .hglf/large1
267 4669e532d5b2c093a78eca010077e708a071bb64
267 4669e532d5b2c093a78eca010077e708a071bb64
268 $ cat large2
268 $ cat large2
269 large2 in #2
269 large2 in #2
270 $ cat .hglf/large2
270 $ cat .hglf/large2
271 3cfce6277e7668985707b6887ce56f9f62f6ccd9
271 3cfce6277e7668985707b6887ce56f9f62f6ccd9
272
272
273 (rollback the parent of the working directory, when the parent of it
273 (rollback the parent of the working directory, when the parent of it
274 is not branch-tip)
274 is not branch-tip)
275
275
276 $ hg update -q -C 1
276 $ hg update -q -C 1
277 $ cat .hglf/large1
277 $ cat .hglf/large1
278 58e24f733a964da346e2407a2bee99d9001184f5
278 58e24f733a964da346e2407a2bee99d9001184f5
279 $ cat .hglf/large2
279 $ cat .hglf/large2
280 1deebade43c8c498a3c8daddac0244dc55d1331d
280 1deebade43c8c498a3c8daddac0244dc55d1331d
281
281
282 $ echo normalX > normalX
282 $ echo normalX > normalX
283 $ hg add normalX
283 $ hg add normalX
284 $ hg commit -m 'will be rollback-ed soon'
284 $ hg commit -m 'will be rollback-ed soon'
285 $ hg rollback -q
285 $ hg rollback -q
286
286
287 $ cat .hglf/large1
287 $ cat .hglf/large1
288 58e24f733a964da346e2407a2bee99d9001184f5
288 58e24f733a964da346e2407a2bee99d9001184f5
289 $ cat .hglf/large2
289 $ cat .hglf/large2
290 1deebade43c8c498a3c8daddac0244dc55d1331d
290 1deebade43c8c498a3c8daddac0244dc55d1331d
291 $ rm normalX
291 $ rm normalX
292
292
293 Test that "hg status" shows status of largefiles correctly just after
293 Test that "hg status" shows status of largefiles correctly just after
294 automated commit like rebase/transplant
294 automated commit like rebase/transplant
295
295
296 $ cat >> .hg/hgrc <<EOF
296 $ cat >> .hg/hgrc <<EOF
297 > [extensions]
297 > [extensions]
298 > rebase =
298 > rebase =
299 > strip =
299 > strip =
300 > transplant =
300 > transplant =
301 > EOF
301 > EOF
302 $ hg update -q -C 1
302 $ hg update -q -C 1
303 $ hg remove large1
303 $ hg remove large1
304 $ echo largeX > largeX
304 $ echo largeX > largeX
305 $ hg add --large largeX
305 $ hg add --large largeX
306 $ hg commit -m '#4'
306 $ hg commit -m '#4'
307
307
308 $ hg rebase -s 1 -d 2 --keep
308 $ hg rebase -s 1 -d 2 --keep
309 rebasing 1:72518492caa6 "#1"
309 rebasing 1:72518492caa6 "#1"
310 rebasing 4:07d6153b5c04 "#4" (tip)
310 rebasing 4:07d6153b5c04 "#4" (tip)
311
311
312 $ hg status -A large1
312 $ hg status -A large1
313 large1: $ENOENT$
313 large1: $ENOENT$
314
314
315 $ hg status -A largeX
315 $ hg status -A largeX
316 C largeX
316 C largeX
317 $ hg strip -q 5
317 $ hg strip -q 5
318
318
319 $ hg update -q -C 2
319 $ hg update -q -C 2
320 $ hg transplant -q 1 4
320 $ hg transplant -q 1 4
321
321
322 $ hg status -A large1
322 $ hg status -A large1
323 large1: $ENOENT$
323 large1: $ENOENT$
324
324
325 $ hg status -A largeX
325 $ hg status -A largeX
326 C largeX
326 C largeX
327 $ hg strip -q 5
327 $ hg strip -q 5
328
328
329 $ hg update -q -C 2
329 $ hg update -q -C 2
330 $ hg transplant -q --merge 1 --merge 4
330 $ hg transplant -q --merge 1 --merge 4
331
331
332 $ hg status -A large1
332 $ hg status -A large1
333 large1: $ENOENT$
333 large1: $ENOENT$
334
334
335 $ hg status -A largeX
335 $ hg status -A largeX
336 C largeX
336 C largeX
337 $ hg strip -q 5
337 $ hg strip -q 5
338
338
339 Test that linear merge can detect modification (and conflict) correctly
339 Test that linear merge can detect modification (and conflict) correctly
340
340
341 (linear merge without conflict)
341 (linear merge without conflict)
342
342
343 $ echo 'large2 for linear merge (no conflict)' > large2
343 $ echo 'large2 for linear merge (no conflict)' > large2
344 $ hg update 3 --config debug.dirstate.delaywrite=2
344 $ hg update 3 --config debug.dirstate.delaywrite=2
345 getting changed largefiles
345 getting changed largefiles
346 1 largefiles updated, 0 removed
346 1 largefiles updated, 0 removed
347 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
347 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
348 $ hg status -A large2
348 $ hg status -A large2
349 M large2
349 M large2
350 $ cat large2
350 $ cat large2
351 large2 for linear merge (no conflict)
351 large2 for linear merge (no conflict)
352 $ cat .hglf/large2
352 $ cat .hglf/large2
353 9c4bf8f1b33536d6e5f89447e10620cfe52ea710
353 9c4bf8f1b33536d6e5f89447e10620cfe52ea710
354
354
355 (linear merge with conflict, choosing "other")
355 (linear merge with conflict, choosing "other")
356
356
357 $ hg update -q -C 2
357 $ hg update -q -C 2
358 $ echo 'large1 for linear merge (conflict)' > large1
358 $ echo 'large1 for linear merge (conflict)' > large1
359 $ hg update 3 --config ui.interactive=True <<EOF
359 $ hg update 3 --config ui.interactive=True <<EOF
360 > o
360 > o
361 > EOF
361 > EOF
362 largefile large1 has a merge conflict
362 largefile large1 has a merge conflict
363 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
363 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
364 you can keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b.
364 you can keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b.
365 what do you want to do? o
365 what do you want to do? o
366 getting changed largefiles
366 getting changed largefiles
367 1 largefiles updated, 0 removed
367 1 largefiles updated, 0 removed
368 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
368 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
369 $ hg status -A large1
369 $ hg status -A large1
370 C large1
370 C large1
371 $ cat large1
371 $ cat large1
372 large1 in #3
372 large1 in #3
373 $ cat .hglf/large1
373 $ cat .hglf/large1
374 e5bb990443d6a92aaf7223813720f7566c9dd05b
374 e5bb990443d6a92aaf7223813720f7566c9dd05b
375
375
376 (linear merge with conflict, choosing "local")
376 (linear merge with conflict, choosing "local")
377
377
378 $ hg update -q -C 2
378 $ hg update -q -C 2
379 $ echo 'large1 for linear merge (conflict)' > large1
379 $ echo 'large1 for linear merge (conflict)' > large1
380 $ hg update 3 --config debug.dirstate.delaywrite=2
380 $ hg update 3 --config debug.dirstate.delaywrite=2
381 largefile large1 has a merge conflict
381 largefile large1 has a merge conflict
382 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
382 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
383 you can keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b.
383 you can keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b.
384 what do you want to do? l
384 what do you want to do? l
385 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
385 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
386 $ hg status -A large1
386 $ hg status -A large1
387 M large1
387 M large1
388 $ cat large1
388 $ cat large1
389 large1 for linear merge (conflict)
389 large1 for linear merge (conflict)
390 $ cat .hglf/large1
390 $ cat .hglf/large1
391 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
391 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
392
392
393 Test a linear merge to a revision containing same-name normal file
393 Test a linear merge to a revision containing same-name normal file
394
394
395 $ hg update -q -C 3
395 $ hg update -q -C 3
396 $ hg remove large2
396 $ hg remove large2
397 $ echo 'large2 as normal file' > large2
397 $ echo 'large2 as normal file' > large2
398 $ hg add large2
398 $ hg add large2
399 $ echo 'large3 as normal file' > large3
399 $ echo 'large3 as normal file' > large3
400 $ hg add large3
400 $ hg add large3
401 $ hg commit -m '#5'
401 $ hg commit -m '#5'
402 $ hg manifest
402 $ hg manifest
403 .hglf/large1
403 .hglf/large1
404 large2
404 large2
405 large3
405 large3
406 normal1
406 normal1
407
407
408 (modified largefile is already switched to normal)
408 (modified largefile is already switched to normal)
409
409
410 $ hg update -q -C 2
410 $ hg update -q -C 2
411 $ echo 'modified large2 for linear merge' > large2
411 $ echo 'modified large2 for linear merge' > large2
412 $ hg update -q 5
412 $ hg update -q 5
413 remote turned local largefile large2 into a normal file
413 remote turned local largefile large2 into a normal file
414 keep (l)argefile or use (n)ormal file? l
414 keep (l)argefile or use (n)ormal file? l
415 $ hg debugdirstate --no-dates | grep large2
415 $ hg debugdirstate --no-dates | grep large2
416 a 0 -1 unset .hglf/large2
416 a 0 -1 unset .hglf/large2
417 r 0 0 set large2
417 r 0 0 set large2
418 $ hg status -A large2
418 $ hg status -A large2
419 A large2
419 A large2
420 $ cat large2
420 $ cat large2
421 modified large2 for linear merge
421 modified large2 for linear merge
422
422
423 (added largefile is already committed as normal)
423 (added largefile is already committed as normal)
424
424
425 $ hg update -q -C 2
425 $ hg update -q -C 2
426 $ echo 'large3 as large file for linear merge' > large3
426 $ echo 'large3 as large file for linear merge' > large3
427 $ hg add --large large3
427 $ hg add --large large3
428 $ hg update -q 5
428 $ hg update -q 5
429 remote turned local largefile large3 into a normal file
429 remote turned local largefile large3 into a normal file
430 keep (l)argefile or use (n)ormal file? l
430 keep (l)argefile or use (n)ormal file? l
431 $ hg debugdirstate --no-dates | grep large3
431 $ hg debugdirstate --no-dates | grep large3
432 a 0 -1 unset .hglf/large3
432 a 0 -1 unset .hglf/large3
433 r 0 0 set large3
433 r 0 0 set large3
434 $ hg status -A large3
434 $ hg status -A large3
435 A large3
435 A large3
436 $ cat large3
436 $ cat large3
437 large3 as large file for linear merge
437 large3 as large file for linear merge
438 $ rm -f large3 .hglf/large3
438 $ rm -f large3 .hglf/large3
439
439
440 Test that the internal linear merging works correctly
440 Test that the internal linear merging works correctly
441 (both heads are stripped to keep pairing of revision number and commit log)
441 (both heads are stripped to keep pairing of revision number and commit log)
442
442
443 $ hg update -q -C 2
443 $ hg update -q -C 2
444 $ hg strip 3 4
444 $ hg strip 3 4
445 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/9530e27857f7-2e7b195d-backup.hg
445 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/9530e27857f7-2e7b195d-backup.hg
446 $ mv .hg/strip-backup/9530e27857f7-2e7b195d-backup.hg $TESTTMP
446 $ mv .hg/strip-backup/9530e27857f7-2e7b195d-backup.hg $TESTTMP
447
447
448 (internal linear merging at "hg pull --update")
448 (internal linear merging at "hg pull --update")
449
449
450 $ echo 'large1 for linear merge (conflict)' > large1
450 $ echo 'large1 for linear merge (conflict)' > large1
451 $ echo 'large2 for linear merge (conflict with normal file)' > large2
451 $ echo 'large2 for linear merge (conflict with normal file)' > large2
452 $ hg pull --update --config debug.dirstate.delaywrite=2 $TESTTMP/9530e27857f7-2e7b195d-backup.hg
452 $ hg pull --update --config debug.dirstate.delaywrite=2 $TESTTMP/9530e27857f7-2e7b195d-backup.hg
453 pulling from $TESTTMP/9530e27857f7-2e7b195d-backup.hg
453 pulling from $TESTTMP/9530e27857f7-2e7b195d-backup.hg
454 searching for changes
454 searching for changes
455 adding changesets
455 adding changesets
456 adding manifests
456 adding manifests
457 adding file changes
457 adding file changes
458 added 3 changesets with 5 changes to 5 files
458 added 3 changesets with 5 changes to 5 files
459 new changesets 9530e27857f7:d65e59e952a9 (3 drafts)
459 new changesets 9530e27857f7:d65e59e952a9 (3 drafts)
460 remote turned local largefile large2 into a normal file
460 remote turned local largefile large2 into a normal file
461 keep (l)argefile or use (n)ormal file? l
461 keep (l)argefile or use (n)ormal file? l
462 largefile large1 has a merge conflict
462 largefile large1 has a merge conflict
463 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
463 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
464 you can keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b.
464 you can keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b.
465 what do you want to do? l
465 what do you want to do? l
466 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
466 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
467 updated to "d65e59e952a9: #5"
467 updated to "d65e59e952a9: #5"
468 1 other heads for branch "default"
468 1 other heads for branch "default"
469
469
470 $ hg status -A large1
470 $ hg status -A large1
471 M large1
471 M large1
472 $ cat large1
472 $ cat large1
473 large1 for linear merge (conflict)
473 large1 for linear merge (conflict)
474 $ cat .hglf/large1
474 $ cat .hglf/large1
475 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
475 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
476 $ hg status -A large2
476 $ hg status -A large2
477 A large2
477 A large2
478 $ cat large2
478 $ cat large2
479 large2 for linear merge (conflict with normal file)
479 large2 for linear merge (conflict with normal file)
480 $ cat .hglf/large2
480 $ cat .hglf/large2
481 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
481 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
482
482
483 (internal linear merging at "hg unbundle --update")
483 (internal linear merging at "hg unbundle --update")
484
484
485 $ hg update -q -C 2
485 $ hg update -q -C 2
486 $ hg rollback -q
486 $ hg rollback -q
487
487
488 $ echo 'large1 for linear merge (conflict)' > large1
488 $ echo 'large1 for linear merge (conflict)' > large1
489 $ echo 'large2 for linear merge (conflict with normal file)' > large2
489 $ echo 'large2 for linear merge (conflict with normal file)' > large2
490 $ hg unbundle --update --config debug.dirstate.delaywrite=2 $TESTTMP/9530e27857f7-2e7b195d-backup.hg
490 $ hg unbundle --update --config debug.dirstate.delaywrite=2 $TESTTMP/9530e27857f7-2e7b195d-backup.hg
491 adding changesets
491 adding changesets
492 adding manifests
492 adding manifests
493 adding file changes
493 adding file changes
494 added 3 changesets with 5 changes to 5 files
494 added 3 changesets with 5 changes to 5 files
495 new changesets 9530e27857f7:d65e59e952a9 (3 drafts)
495 new changesets 9530e27857f7:d65e59e952a9 (3 drafts)
496 remote turned local largefile large2 into a normal file
496 remote turned local largefile large2 into a normal file
497 keep (l)argefile or use (n)ormal file? l
497 keep (l)argefile or use (n)ormal file? l
498 largefile large1 has a merge conflict
498 largefile large1 has a merge conflict
499 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
499 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
500 you can keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b.
500 you can keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b.
501 what do you want to do? l
501 what do you want to do? l
502 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
502 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
503 updated to "d65e59e952a9: #5"
503 updated to "d65e59e952a9: #5"
504 1 other heads for branch "default"
504 1 other heads for branch "default"
505
505
506 $ hg status -A large1
506 $ hg status -A large1
507 M large1
507 M large1
508 $ cat large1
508 $ cat large1
509 large1 for linear merge (conflict)
509 large1 for linear merge (conflict)
510 $ cat .hglf/large1
510 $ cat .hglf/large1
511 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
511 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
512 $ hg status -A large2
512 $ hg status -A large2
513 A large2
513 A large2
514 $ cat large2
514 $ cat large2
515 large2 for linear merge (conflict with normal file)
515 large2 for linear merge (conflict with normal file)
516 $ cat .hglf/large2
516 $ cat .hglf/large2
517 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
517 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
518
518
519 (internal linear merging in subrepo at "hg update")
519 (internal linear merging in subrepo at "hg update")
520
520
521 $ cd ..
521 $ cd ..
522 $ hg init subparent
522 $ hg init subparent
523 $ cd subparent
523 $ cd subparent
524
524
525 $ hg clone -q -u 2 ../repo sub
525 $ hg clone -q -u 2 ../repo sub
526 $ cat > .hgsub <<EOF
526 $ cat > .hgsub <<EOF
527 > sub = sub
527 > sub = sub
528 > EOF
528 > EOF
529 $ hg add .hgsub
529 $ hg add .hgsub
530 $ hg commit -m '#0@parent'
530 $ hg commit -m '#0@parent'
531 $ cat .hgsubstate
531 $ cat .hgsubstate
532 f74e50bd9e5594b7cf1e6c5cbab86ddd25f3ca2f sub
532 f74e50bd9e5594b7cf1e6c5cbab86ddd25f3ca2f sub
533 $ hg -R sub update -q
533 $ hg -R sub update -q
534 $ hg commit -m '#1@parent'
534 $ hg commit -m '#1@parent'
535 $ cat .hgsubstate
535 $ cat .hgsubstate
536 d65e59e952a9638e2ce863b41a420ca723dd3e8d sub
536 d65e59e952a9638e2ce863b41a420ca723dd3e8d sub
537 $ hg update -q 0
537 $ hg update -q 0
538
538
539 $ echo 'large1 for linear merge (conflict)' > sub/large1
539 $ echo 'large1 for linear merge (conflict)' > sub/large1
540 $ echo 'large2 for linear merge (conflict with normal file)' > sub/large2
540 $ echo 'large2 for linear merge (conflict with normal file)' > sub/large2
541 $ hg update --config ui.interactive=True --config debug.dirstate.delaywrite=2 <<EOF
541 $ hg update --config ui.interactive=True --config debug.dirstate.delaywrite=2 <<EOF
542 > m
542 > m
543 > r
543 > r
544 > l
544 > l
545 > l
545 > l
546 > EOF
546 > EOF
547 subrepository sub diverged (local revision: f74e50bd9e55, remote revision: d65e59e952a9)
547 subrepository sub diverged (local revision: f74e50bd9e55, remote revision: d65e59e952a9)
548 (M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
548 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [destination].
549 what do you want to do? m
549 subrepository sources for sub differ (in checked out version)
550 subrepository sources for sub differ (in checked out version)
550 use (l)ocal source (f74e50bd9e55) or (r)emote source (d65e59e952a9)? r
551 you can use (l)ocal source (f74e50bd9e55) or (r)emote source (d65e59e952a9).
552 what do you want to do? r
551 remote turned local largefile large2 into a normal file
553 remote turned local largefile large2 into a normal file
552 keep (l)argefile or use (n)ormal file? l
554 keep (l)argefile or use (n)ormal file? l
553 largefile large1 has a merge conflict
555 largefile large1 has a merge conflict
554 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
556 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
555 you can keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b.
557 you can keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b.
556 what do you want to do? l
558 what do you want to do? l
557 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
559 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
558 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
560 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
559
561
560 $ hg -R sub status -A sub/large1
562 $ hg -R sub status -A sub/large1
561 M sub/large1
563 M sub/large1
562 $ cat sub/large1
564 $ cat sub/large1
563 large1 for linear merge (conflict)
565 large1 for linear merge (conflict)
564 $ cat sub/.hglf/large1
566 $ cat sub/.hglf/large1
565 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
567 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
566 $ hg -R sub status -A sub/large2
568 $ hg -R sub status -A sub/large2
567 A sub/large2
569 A sub/large2
568 $ cat sub/large2
570 $ cat sub/large2
569 large2 for linear merge (conflict with normal file)
571 large2 for linear merge (conflict with normal file)
570 $ cat sub/.hglf/large2
572 $ cat sub/.hglf/large2
571 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
573 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
572
574
573 $ cd ..
575 $ cd ..
574 $ cd repo
576 $ cd repo
575
577
576 Test that rebase updates largefiles in the working directory even if
578 Test that rebase updates largefiles in the working directory even if
577 it is aborted by conflict.
579 it is aborted by conflict.
578
580
579 $ hg update -q -C 3
581 $ hg update -q -C 3
580 $ cat .hglf/large1
582 $ cat .hglf/large1
581 e5bb990443d6a92aaf7223813720f7566c9dd05b
583 e5bb990443d6a92aaf7223813720f7566c9dd05b
582 $ cat large1
584 $ cat large1
583 large1 in #3
585 large1 in #3
584 $ hg rebase -s 1 -d 3 --keep --config ui.interactive=True <<EOF
586 $ hg rebase -s 1 -d 3 --keep --config ui.interactive=True <<EOF
585 > o
587 > o
586 > EOF
588 > EOF
587 rebasing 1:72518492caa6 "#1"
589 rebasing 1:72518492caa6 "#1"
588 largefile large1 has a merge conflict
590 largefile large1 has a merge conflict
589 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
591 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
590 you can keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5.
592 you can keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5.
591 what do you want to do? o
593 what do you want to do? o
592 merging normal1
594 merging normal1
593 warning: conflicts while merging normal1! (edit, then use 'hg resolve --mark')
595 warning: conflicts while merging normal1! (edit, then use 'hg resolve --mark')
594 unresolved conflicts (see hg resolve, then hg rebase --continue)
596 unresolved conflicts (see hg resolve, then hg rebase --continue)
595 [1]
597 [1]
596 $ cat .hglf/large1
598 $ cat .hglf/large1
597 58e24f733a964da346e2407a2bee99d9001184f5
599 58e24f733a964da346e2407a2bee99d9001184f5
598 $ cat large1
600 $ cat large1
599 large1 in #1
601 large1 in #1
600 $ rm normal1.orig
602 $ rm normal1.orig
601
603
602 Test that rebase updates standins for manually modified largefiles at
604 Test that rebase updates standins for manually modified largefiles at
603 the 1st commit of resuming.
605 the 1st commit of resuming.
604
606
605 $ echo "manually modified before 'hg rebase --continue'" > large1
607 $ echo "manually modified before 'hg rebase --continue'" > large1
606 $ hg resolve -m normal1
608 $ hg resolve -m normal1
607 (no more unresolved files)
609 (no more unresolved files)
608 continue: hg rebase --continue
610 continue: hg rebase --continue
609 $ hg rebase --continue --config ui.interactive=True <<EOF
611 $ hg rebase --continue --config ui.interactive=True <<EOF
610 > c
612 > c
611 > EOF
613 > EOF
612 rebasing 1:72518492caa6 "#1"
614 rebasing 1:72518492caa6 "#1"
613 rebasing 4:07d6153b5c04 "#4"
615 rebasing 4:07d6153b5c04 "#4"
614 file '.hglf/large1' was deleted in other [source] but was modified in local [dest].
616 file '.hglf/large1' was deleted in other [source] but was modified in local [dest].
615 You can use (c)hanged version, (d)elete, or leave (u)nresolved.
617 You can use (c)hanged version, (d)elete, or leave (u)nresolved.
616 What do you want to do? c
618 What do you want to do? c
617
619
618 $ hg diff -c "tip~1" --nodates .hglf/large1 | grep '^[+-][0-9a-z]'
620 $ hg diff -c "tip~1" --nodates .hglf/large1 | grep '^[+-][0-9a-z]'
619 -e5bb990443d6a92aaf7223813720f7566c9dd05b
621 -e5bb990443d6a92aaf7223813720f7566c9dd05b
620 +8a4f783556e7dea21139ca0466eafce954c75c13
622 +8a4f783556e7dea21139ca0466eafce954c75c13
621 $ rm -f large1
623 $ rm -f large1
622 $ hg update -q -C tip
624 $ hg update -q -C tip
623 $ cat large1
625 $ cat large1
624 manually modified before 'hg rebase --continue'
626 manually modified before 'hg rebase --continue'
625
627
626 Test that transplant updates largefiles, of which standins are safely
628 Test that transplant updates largefiles, of which standins are safely
627 changed, even if it is aborted by conflict of other.
629 changed, even if it is aborted by conflict of other.
628
630
629 $ hg update -q -C 5
631 $ hg update -q -C 5
630 $ cat .hglf/large1
632 $ cat .hglf/large1
631 e5bb990443d6a92aaf7223813720f7566c9dd05b
633 e5bb990443d6a92aaf7223813720f7566c9dd05b
632 $ cat large1
634 $ cat large1
633 large1 in #3
635 large1 in #3
634 $ hg diff -c 4 .hglf/largeX | grep '^[+-][0-9a-z]'
636 $ hg diff -c 4 .hglf/largeX | grep '^[+-][0-9a-z]'
635 +fa44618ea25181aff4f48b70428294790cec9f61
637 +fa44618ea25181aff4f48b70428294790cec9f61
636 $ hg transplant 4
638 $ hg transplant 4
637 applying 07d6153b5c04
639 applying 07d6153b5c04
638 patching file .hglf/large1
640 patching file .hglf/large1
639 Hunk #1 FAILED at 0
641 Hunk #1 FAILED at 0
640 1 out of 1 hunks FAILED -- saving rejects to file .hglf/large1.rej
642 1 out of 1 hunks FAILED -- saving rejects to file .hglf/large1.rej
641 patch failed to apply
643 patch failed to apply
642 abort: fix up the working directory and run hg transplant --continue
644 abort: fix up the working directory and run hg transplant --continue
643 [255]
645 [255]
644 $ hg status -A large1
646 $ hg status -A large1
645 C large1
647 C large1
646 $ cat .hglf/large1
648 $ cat .hglf/large1
647 e5bb990443d6a92aaf7223813720f7566c9dd05b
649 e5bb990443d6a92aaf7223813720f7566c9dd05b
648 $ cat large1
650 $ cat large1
649 large1 in #3
651 large1 in #3
650 $ hg status -A largeX
652 $ hg status -A largeX
651 A largeX
653 A largeX
652 $ cat .hglf/largeX
654 $ cat .hglf/largeX
653 fa44618ea25181aff4f48b70428294790cec9f61
655 fa44618ea25181aff4f48b70428294790cec9f61
654 $ cat largeX
656 $ cat largeX
655 largeX
657 largeX
656
658
657 Test that transplant updates standins for manually modified largefiles
659 Test that transplant updates standins for manually modified largefiles
658 at the 1st commit of resuming.
660 at the 1st commit of resuming.
659
661
660 $ echo "manually modified before 'hg transplant --continue'" > large1
662 $ echo "manually modified before 'hg transplant --continue'" > large1
661 $ hg transplant --continue
663 $ hg transplant --continue
662 07d6153b5c04 transplanted as f1bf30eb88cc
664 07d6153b5c04 transplanted as f1bf30eb88cc
663 $ hg diff -c tip .hglf/large1 | grep '^[+-][0-9a-z]'
665 $ hg diff -c tip .hglf/large1 | grep '^[+-][0-9a-z]'
664 -e5bb990443d6a92aaf7223813720f7566c9dd05b
666 -e5bb990443d6a92aaf7223813720f7566c9dd05b
665 +6a4f36d4075fbe0f30ec1d26ca44e63c05903671
667 +6a4f36d4075fbe0f30ec1d26ca44e63c05903671
666 $ rm -f large1
668 $ rm -f large1
667 $ hg update -q -C tip
669 $ hg update -q -C tip
668 $ cat large1
670 $ cat large1
669 manually modified before 'hg transplant --continue'
671 manually modified before 'hg transplant --continue'
670
672
671 Test that "hg status" doesn't show removal of largefiles not managed
673 Test that "hg status" doesn't show removal of largefiles not managed
672 in the target context.
674 in the target context.
673
675
674 $ hg update -q -C 4
676 $ hg update -q -C 4
675 $ hg remove largeX
677 $ hg remove largeX
676 $ hg status -A largeX
678 $ hg status -A largeX
677 R largeX
679 R largeX
678 $ hg status -A --rev '.^1' largeX
680 $ hg status -A --rev '.^1' largeX
679
681
680 #if execbit
682 #if execbit
681
683
682 Test that "hg status" against revisions other than parent notices exec
684 Test that "hg status" against revisions other than parent notices exec
683 bit changes of largefiles.
685 bit changes of largefiles.
684
686
685 $ hg update -q -C 4
687 $ hg update -q -C 4
686
688
687 (the case that large2 doesn't have exec bit in the target context but
689 (the case that large2 doesn't have exec bit in the target context but
688 in the working context)
690 in the working context)
689
691
690 $ chmod +x large2
692 $ chmod +x large2
691 $ hg status -A --rev 0 large2
693 $ hg status -A --rev 0 large2
692 M large2
694 M large2
693 $ hg commit -m 'chmod +x large2'
695 $ hg commit -m 'chmod +x large2'
694
696
695 (the case that large2 has exec bit in the target context but not in
697 (the case that large2 has exec bit in the target context but not in
696 the working context)
698 the working context)
697
699
698 $ echo dummy > dummy
700 $ echo dummy > dummy
699 $ hg add dummy
701 $ hg add dummy
700 $ hg commit -m 'revision for separation'
702 $ hg commit -m 'revision for separation'
701 $ chmod -x large2
703 $ chmod -x large2
702 $ hg status -A --rev '.^1' large2
704 $ hg status -A --rev '.^1' large2
703 M large2
705 M large2
704
706
705 #else
707 #else
706
708
707 Test that "hg status" against revisions other than parent ignores exec
709 Test that "hg status" against revisions other than parent ignores exec
708 bit correctly on the platform being unaware of it.
710 bit correctly on the platform being unaware of it.
709
711
710 $ hg update -q -C 4
712 $ hg update -q -C 4
711
713
712 $ cat > ../exec-bit.patch <<EOF
714 $ cat > ../exec-bit.patch <<EOF
713 > # HG changeset patch
715 > # HG changeset patch
714 > # User test
716 > # User test
715 > # Date 0 0
717 > # Date 0 0
716 > # Thu Jan 01 00:00:00 1970 +0000
718 > # Thu Jan 01 00:00:00 1970 +0000
717 > # Node ID be1b433a65b12b27b5519d92213e14f7e1769b90
719 > # Node ID be1b433a65b12b27b5519d92213e14f7e1769b90
718 > # Parent 07d6153b5c04313efb75deec9ba577de7faeb727
720 > # Parent 07d6153b5c04313efb75deec9ba577de7faeb727
719 > chmod +x large2
721 > chmod +x large2
720 >
722 >
721 > diff --git a/.hglf/large2 b/.hglf/large2
723 > diff --git a/.hglf/large2 b/.hglf/large2
722 > old mode 100644
724 > old mode 100644
723 > new mode 100755
725 > new mode 100755
724 > EOF
726 > EOF
725 $ hg import --exact --bypass ../exec-bit.patch
727 $ hg import --exact --bypass ../exec-bit.patch
726 applying ../exec-bit.patch
728 applying ../exec-bit.patch
727 $ hg status -A --rev tip large2
729 $ hg status -A --rev tip large2
728 C large2
730 C large2
729
731
730 #endif
732 #endif
731
733
732 The fileset revset is evaluated for each revision, instead of once on wdir(),
734 The fileset revset is evaluated for each revision, instead of once on wdir(),
733 and then patterns matched on each revision. Here, no exec bits are set in
735 and then patterns matched on each revision. Here, no exec bits are set in
734 wdir(), but a matching revision is detected.
736 wdir(), but a matching revision is detected.
735
737
736 (Teach large2 is not an executable. Maybe this is a bug of largefiles.)
738 (Teach large2 is not an executable. Maybe this is a bug of largefiles.)
737 #if execbit
739 #if execbit
738 $ chmod -x .hglf/large2
740 $ chmod -x .hglf/large2
739 #endif
741 #endif
740
742
741 $ hg files 'set:exec()'
743 $ hg files 'set:exec()'
742 [1]
744 [1]
743 $ hg log -qr 'file("set:exec()")'
745 $ hg log -qr 'file("set:exec()")'
744 9:be1b433a65b1
746 9:be1b433a65b1
745
747
746 Test a fatal error interrupting an update. Verify that status report dirty
748 Test a fatal error interrupting an update. Verify that status report dirty
747 files correctly after an interrupted update. Also verify that checking all
749 files correctly after an interrupted update. Also verify that checking all
748 hashes reveals it isn't clean.
750 hashes reveals it isn't clean.
749
751
750 Start with clean dirstates:
752 Start with clean dirstates:
751 $ hg up --quiet --clean --rev "8^"
753 $ hg up --quiet --clean --rev "8^"
752 $ sleep 1
754 $ sleep 1
753 $ hg st
755 $ hg st
754 Update standins without updating largefiles - large1 is modified and largeX is
756 Update standins without updating largefiles - large1 is modified and largeX is
755 added:
757 added:
756 $ cat << EOF > ../crashupdatelfiles.py
758 $ cat << EOF > ../crashupdatelfiles.py
757 > import hgext.largefiles.lfutil
759 > import hgext.largefiles.lfutil
758 > def getlfilestoupdate(oldstandins, newstandins):
760 > def getlfilestoupdate(oldstandins, newstandins):
759 > raise SystemExit(7)
761 > raise SystemExit(7)
760 > hgext.largefiles.lfutil.getlfilestoupdate = getlfilestoupdate
762 > hgext.largefiles.lfutil.getlfilestoupdate = getlfilestoupdate
761 > EOF
763 > EOF
762 $ hg up -Cr "8" --config extensions.crashupdatelfiles=../crashupdatelfiles.py
764 $ hg up -Cr "8" --config extensions.crashupdatelfiles=../crashupdatelfiles.py
763 [7]
765 [7]
764 Check large1 content and status ... and that update will undo modifications:
766 Check large1 content and status ... and that update will undo modifications:
765 $ cat large1
767 $ cat large1
766 large1 in #3
768 large1 in #3
767 $ hg st
769 $ hg st
768 M large1
770 M large1
769 ! largeX
771 ! largeX
770 $ hg up -Cr .
772 $ hg up -Cr .
771 getting changed largefiles
773 getting changed largefiles
772 2 largefiles updated, 0 removed
774 2 largefiles updated, 0 removed
773 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
775 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
774 $ cat large1
776 $ cat large1
775 manually modified before 'hg transplant --continue'
777 manually modified before 'hg transplant --continue'
776 $ hg st
778 $ hg st
777 Force largefiles rehashing and check that all changes have been caught by
779 Force largefiles rehashing and check that all changes have been caught by
778 status and update:
780 status and update:
779 $ rm .hg/largefiles/dirstate
781 $ rm .hg/largefiles/dirstate
780 $ hg st
782 $ hg st
781
783
782 $ cd ..
784 $ cd ..
783
785
784 Test that "hg convert" avoids copying largefiles from the working
786 Test that "hg convert" avoids copying largefiles from the working
785 directory into store, because "hg convert" doesn't update largefiles
787 directory into store, because "hg convert" doesn't update largefiles
786 in the working directory (removing files under ".cache/largefiles"
788 in the working directory (removing files under ".cache/largefiles"
787 forces "hg convert" to copy corresponding largefiles)
789 forces "hg convert" to copy corresponding largefiles)
788
790
789 $ cat >> $HGRCPATH <<EOF
791 $ cat >> $HGRCPATH <<EOF
790 > [extensions]
792 > [extensions]
791 > convert =
793 > convert =
792 > EOF
794 > EOF
793
795
794 $ rm $TESTTMP/.cache/largefiles/6a4f36d4075fbe0f30ec1d26ca44e63c05903671
796 $ rm $TESTTMP/.cache/largefiles/6a4f36d4075fbe0f30ec1d26ca44e63c05903671
795 $ hg convert -q repo repo.converted
797 $ hg convert -q repo repo.converted
@@ -1,615 +1,616 b''
1 $ cat <<EOF >> $HGRCPATH
1 $ cat <<EOF >> $HGRCPATH
2 > [ui]
2 > [ui]
3 > commitsubrepos = Yes
3 > commitsubrepos = Yes
4 > [extensions]
4 > [extensions]
5 > mq =
5 > mq =
6 > record =
6 > record =
7 > [diff]
7 > [diff]
8 > nodates = 1
8 > nodates = 1
9 > EOF
9 > EOF
10
10
11 $ stdin=`pwd`/stdin.tmp
11 $ stdin=`pwd`/stdin.tmp
12
12
13 fn to create new repository w/dirty subrepo, and cd into it
13 fn to create new repository w/dirty subrepo, and cd into it
14 $ mkrepo() {
14 $ mkrepo() {
15 > hg init $1
15 > hg init $1
16 > cd $1
16 > cd $1
17 > hg qinit
17 > hg qinit
18 > }
18 > }
19
19
20 fn to create dirty subrepo
20 fn to create dirty subrepo
21 $ mksubrepo() {
21 $ mksubrepo() {
22 > hg init $1
22 > hg init $1
23 > cd $1
23 > cd $1
24 > echo a > a
24 > echo a > a
25 > hg add
25 > hg add
26 > cd ..
26 > cd ..
27 > }
27 > }
28
28
29 $ testadd() {
29 $ testadd() {
30 > cat - > "$stdin"
30 > cat - > "$stdin"
31 > mksubrepo sub
31 > mksubrepo sub
32 > echo sub = sub >> .hgsub
32 > echo sub = sub >> .hgsub
33 > hg add .hgsub
33 > hg add .hgsub
34 > echo % abort when adding .hgsub w/dirty subrepo
34 > echo % abort when adding .hgsub w/dirty subrepo
35 > hg status -S
35 > hg status -S
36 > echo '%' $*
36 > echo '%' $*
37 > cat "$stdin" | hg $*
37 > cat "$stdin" | hg $*
38 > echo [$?]
38 > echo [$?]
39 > hg -R sub ci -m0sub
39 > hg -R sub ci -m0sub
40 > echo % update substate when adding .hgsub w/clean updated subrepo
40 > echo % update substate when adding .hgsub w/clean updated subrepo
41 > hg status -S
41 > hg status -S
42 > echo '%' $*
42 > echo '%' $*
43 > cat "$stdin" | hg $*
43 > cat "$stdin" | hg $*
44 > hg debugsub
44 > hg debugsub
45 > }
45 > }
46
46
47 $ testmod() {
47 $ testmod() {
48 > cat - > "$stdin"
48 > cat - > "$stdin"
49 > mksubrepo sub2
49 > mksubrepo sub2
50 > echo sub2 = sub2 >> .hgsub
50 > echo sub2 = sub2 >> .hgsub
51 > echo % abort when modifying .hgsub w/dirty subrepo
51 > echo % abort when modifying .hgsub w/dirty subrepo
52 > hg status -S
52 > hg status -S
53 > echo '%' $*
53 > echo '%' $*
54 > cat "$stdin" | hg $*
54 > cat "$stdin" | hg $*
55 > echo [$?]
55 > echo [$?]
56 > hg -R sub2 ci -m0sub2
56 > hg -R sub2 ci -m0sub2
57 > echo % update substate when modifying .hgsub w/clean updated subrepo
57 > echo % update substate when modifying .hgsub w/clean updated subrepo
58 > hg status -S
58 > hg status -S
59 > echo '%' $*
59 > echo '%' $*
60 > cat "$stdin" | hg $*
60 > cat "$stdin" | hg $*
61 > hg debugsub
61 > hg debugsub
62 > }
62 > }
63
63
64 $ testrm1() {
64 $ testrm1() {
65 > cat - > "$stdin"
65 > cat - > "$stdin"
66 > mksubrepo sub3
66 > mksubrepo sub3
67 > echo sub3 = sub3 >> .hgsub
67 > echo sub3 = sub3 >> .hgsub
68 > hg ci -Aqmsub3
68 > hg ci -Aqmsub3
69 > $EXTRA
69 > $EXTRA
70 > echo b >> sub3/a
70 > echo b >> sub3/a
71 > hg rm .hgsub
71 > hg rm .hgsub
72 > echo % update substate when removing .hgsub w/dirty subrepo
72 > echo % update substate when removing .hgsub w/dirty subrepo
73 > hg status -S
73 > hg status -S
74 > echo '%' $*
74 > echo '%' $*
75 > cat "$stdin" | hg $*
75 > cat "$stdin" | hg $*
76 > echo % debugsub should be empty
76 > echo % debugsub should be empty
77 > hg debugsub
77 > hg debugsub
78 > }
78 > }
79
79
80 $ testrm2() {
80 $ testrm2() {
81 > cat - > "$stdin"
81 > cat - > "$stdin"
82 > mksubrepo sub4
82 > mksubrepo sub4
83 > echo sub4 = sub4 >> .hgsub
83 > echo sub4 = sub4 >> .hgsub
84 > hg ci -Aqmsub4
84 > hg ci -Aqmsub4
85 > $EXTRA
85 > $EXTRA
86 > hg rm .hgsub
86 > hg rm .hgsub
87 > echo % update substate when removing .hgsub w/clean updated subrepo
87 > echo % update substate when removing .hgsub w/clean updated subrepo
88 > hg status -S
88 > hg status -S
89 > echo '%' $*
89 > echo '%' $*
90 > cat "$stdin" | hg $*
90 > cat "$stdin" | hg $*
91 > echo % debugsub should be empty
91 > echo % debugsub should be empty
92 > hg debugsub
92 > hg debugsub
93 > }
93 > }
94
94
95
95
96 handle subrepos safely on qnew
96 handle subrepos safely on qnew
97
97
98 $ mkrepo repo-2499-qnew
98 $ mkrepo repo-2499-qnew
99 $ testadd qnew -X path:no-effect -m0 0.diff
99 $ testadd qnew -X path:no-effect -m0 0.diff
100 adding a
100 adding a
101 % abort when adding .hgsub w/dirty subrepo
101 % abort when adding .hgsub w/dirty subrepo
102 A .hgsub
102 A .hgsub
103 A sub/a
103 A sub/a
104 % qnew -X path:no-effect -m0 0.diff
104 % qnew -X path:no-effect -m0 0.diff
105 abort: uncommitted changes in subrepository "sub"
105 abort: uncommitted changes in subrepository "sub"
106 [255]
106 [255]
107 % update substate when adding .hgsub w/clean updated subrepo
107 % update substate when adding .hgsub w/clean updated subrepo
108 A .hgsub
108 A .hgsub
109 A sub/a
109 A sub/a
110 % qnew -X path:no-effect -m0 0.diff
110 % qnew -X path:no-effect -m0 0.diff
111 path sub
111 path sub
112 source sub
112 source sub
113 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
113 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
114
114
115 $ testmod qnew --cwd .. -R repo-2499-qnew -X path:no-effect -m1 1.diff
115 $ testmod qnew --cwd .. -R repo-2499-qnew -X path:no-effect -m1 1.diff
116 adding a
116 adding a
117 % abort when modifying .hgsub w/dirty subrepo
117 % abort when modifying .hgsub w/dirty subrepo
118 M .hgsub
118 M .hgsub
119 A sub2/a
119 A sub2/a
120 % qnew --cwd .. -R repo-2499-qnew -X path:no-effect -m1 1.diff
120 % qnew --cwd .. -R repo-2499-qnew -X path:no-effect -m1 1.diff
121 abort: uncommitted changes in subrepository "sub2"
121 abort: uncommitted changes in subrepository "sub2"
122 [255]
122 [255]
123 % update substate when modifying .hgsub w/clean updated subrepo
123 % update substate when modifying .hgsub w/clean updated subrepo
124 M .hgsub
124 M .hgsub
125 A sub2/a
125 A sub2/a
126 % qnew --cwd .. -R repo-2499-qnew -X path:no-effect -m1 1.diff
126 % qnew --cwd .. -R repo-2499-qnew -X path:no-effect -m1 1.diff
127 path sub
127 path sub
128 source sub
128 source sub
129 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
129 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
130 path sub2
130 path sub2
131 source sub2
131 source sub2
132 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
132 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
133
133
134 $ hg qpop -qa
134 $ hg qpop -qa
135 patch queue now empty
135 patch queue now empty
136 $ testrm1 qnew -m2 2.diff
136 $ testrm1 qnew -m2 2.diff
137 adding a
137 adding a
138 % update substate when removing .hgsub w/dirty subrepo
138 % update substate when removing .hgsub w/dirty subrepo
139 M sub3/a
139 M sub3/a
140 R .hgsub
140 R .hgsub
141 % qnew -m2 2.diff
141 % qnew -m2 2.diff
142 % debugsub should be empty
142 % debugsub should be empty
143
143
144 $ hg qpop -qa
144 $ hg qpop -qa
145 patch queue now empty
145 patch queue now empty
146 $ testrm2 qnew -m3 3.diff
146 $ testrm2 qnew -m3 3.diff
147 adding a
147 adding a
148 % update substate when removing .hgsub w/clean updated subrepo
148 % update substate when removing .hgsub w/clean updated subrepo
149 R .hgsub
149 R .hgsub
150 % qnew -m3 3.diff
150 % qnew -m3 3.diff
151 % debugsub should be empty
151 % debugsub should be empty
152
152
153 $ cd ..
153 $ cd ..
154
154
155
155
156 handle subrepos safely on qrefresh
156 handle subrepos safely on qrefresh
157
157
158 $ mkrepo repo-2499-qrefresh
158 $ mkrepo repo-2499-qrefresh
159 $ hg qnew -m0 0.diff
159 $ hg qnew -m0 0.diff
160 $ testadd qrefresh
160 $ testadd qrefresh
161 adding a
161 adding a
162 % abort when adding .hgsub w/dirty subrepo
162 % abort when adding .hgsub w/dirty subrepo
163 A .hgsub
163 A .hgsub
164 A sub/a
164 A sub/a
165 % qrefresh
165 % qrefresh
166 abort: uncommitted changes in subrepository "sub"
166 abort: uncommitted changes in subrepository "sub"
167 [255]
167 [255]
168 % update substate when adding .hgsub w/clean updated subrepo
168 % update substate when adding .hgsub w/clean updated subrepo
169 A .hgsub
169 A .hgsub
170 A sub/a
170 A sub/a
171 % qrefresh
171 % qrefresh
172 path sub
172 path sub
173 source sub
173 source sub
174 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
174 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
175
175
176 $ hg qnew -m1 1.diff
176 $ hg qnew -m1 1.diff
177 $ testmod qrefresh
177 $ testmod qrefresh
178 adding a
178 adding a
179 % abort when modifying .hgsub w/dirty subrepo
179 % abort when modifying .hgsub w/dirty subrepo
180 M .hgsub
180 M .hgsub
181 A sub2/a
181 A sub2/a
182 % qrefresh
182 % qrefresh
183 abort: uncommitted changes in subrepository "sub2"
183 abort: uncommitted changes in subrepository "sub2"
184 [255]
184 [255]
185 % update substate when modifying .hgsub w/clean updated subrepo
185 % update substate when modifying .hgsub w/clean updated subrepo
186 M .hgsub
186 M .hgsub
187 A sub2/a
187 A sub2/a
188 % qrefresh
188 % qrefresh
189 path sub
189 path sub
190 source sub
190 source sub
191 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
191 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
192 path sub2
192 path sub2
193 source sub2
193 source sub2
194 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
194 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
195
195
196 $ hg qpop -qa
196 $ hg qpop -qa
197 patch queue now empty
197 patch queue now empty
198 $ EXTRA='hg qnew -m2 2.diff'
198 $ EXTRA='hg qnew -m2 2.diff'
199 $ testrm1 qrefresh
199 $ testrm1 qrefresh
200 adding a
200 adding a
201 % update substate when removing .hgsub w/dirty subrepo
201 % update substate when removing .hgsub w/dirty subrepo
202 M sub3/a
202 M sub3/a
203 R .hgsub
203 R .hgsub
204 % qrefresh
204 % qrefresh
205 % debugsub should be empty
205 % debugsub should be empty
206
206
207 $ hg qpop -qa
207 $ hg qpop -qa
208 patch queue now empty
208 patch queue now empty
209 $ EXTRA='hg qnew -m3 3.diff'
209 $ EXTRA='hg qnew -m3 3.diff'
210 $ testrm2 qrefresh
210 $ testrm2 qrefresh
211 adding a
211 adding a
212 % update substate when removing .hgsub w/clean updated subrepo
212 % update substate when removing .hgsub w/clean updated subrepo
213 R .hgsub
213 R .hgsub
214 % qrefresh
214 % qrefresh
215 % debugsub should be empty
215 % debugsub should be empty
216 $ EXTRA=
216 $ EXTRA=
217
217
218 $ cd ..
218 $ cd ..
219
219
220
220
221 handle subrepos safely on qpush/qpop
221 handle subrepos safely on qpush/qpop
222 (and we cannot qpop / qpush with a modified subrepo)
222 (and we cannot qpop / qpush with a modified subrepo)
223
223
224 $ mkrepo repo-2499-qpush
224 $ mkrepo repo-2499-qpush
225 $ mksubrepo sub
225 $ mksubrepo sub
226 adding a
226 adding a
227 $ hg -R sub ci -m0sub
227 $ hg -R sub ci -m0sub
228 $ echo sub = sub > .hgsub
228 $ echo sub = sub > .hgsub
229 $ hg add .hgsub
229 $ hg add .hgsub
230 $ hg commit -m0
230 $ hg commit -m0
231 $ hg debugsub
231 $ hg debugsub
232 path sub
232 path sub
233 source sub
233 source sub
234 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
234 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
235 $ echo foo > ./sub/a
235 $ echo foo > ./sub/a
236 $ hg -R sub commit -m foo
236 $ hg -R sub commit -m foo
237 $ hg commit -m1
237 $ hg commit -m1
238 $ hg qimport -r "0:tip"
238 $ hg qimport -r "0:tip"
239 $ hg -R sub id --id
239 $ hg -R sub id --id
240 aa037b301eba
240 aa037b301eba
241
241
242 qpop
242 qpop
243 $ hg -R sub update 0000
243 $ hg -R sub update 0000
244 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
244 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
245 $ hg qpop
245 $ hg qpop
246 abort: local changed subrepos found, qrefresh first
246 abort: local changed subrepos found, qrefresh first
247 [255]
247 [255]
248 $ hg revert sub
248 $ hg revert sub
249 reverting subrepo sub
249 reverting subrepo sub
250 adding sub/a
250 adding sub/a
251 $ hg qpop
251 $ hg qpop
252 popping 1
252 popping 1
253 now at: 0
253 now at: 0
254 $ hg status -AS
254 $ hg status -AS
255 C .hgsub
255 C .hgsub
256 C .hgsubstate
256 C .hgsubstate
257 C sub/a
257 C sub/a
258 $ hg -R sub id --id
258 $ hg -R sub id --id
259 b2fdb12cd82b
259 b2fdb12cd82b
260
260
261 qpush
261 qpush
262 $ hg -R sub update 0000
262 $ hg -R sub update 0000
263 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
263 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
264 $ hg qpush
264 $ hg qpush
265 abort: local changed subrepos found, qrefresh first
265 abort: local changed subrepos found, qrefresh first
266 [255]
266 [255]
267 $ hg revert sub
267 $ hg revert sub
268 reverting subrepo sub
268 reverting subrepo sub
269 adding sub/a
269 adding sub/a
270 $ hg qpush
270 $ hg qpush
271 applying 1
271 applying 1
272 subrepository sub diverged (local revision: b2fdb12cd82b, remote revision: aa037b301eba)
272 subrepository sub diverged (local revision: b2fdb12cd82b, remote revision: aa037b301eba)
273 (M)erge, keep (l)ocal or keep (r)emote? m
273 you can (m)erge, keep (l)ocal or keep (r)emote.
274 what do you want to do? m
274 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
275 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
275 now at: 1
276 now at: 1
276 $ hg status -AS
277 $ hg status -AS
277 C .hgsub
278 C .hgsub
278 C .hgsubstate
279 C .hgsubstate
279 C sub/a
280 C sub/a
280 $ hg -R sub id --id
281 $ hg -R sub id --id
281 aa037b301eba
282 aa037b301eba
282
283
283 $ cd ..
284 $ cd ..
284
285
285
286
286 handle subrepos safely on qrecord
287 handle subrepos safely on qrecord
287
288
288 $ mkrepo repo-2499-qrecord
289 $ mkrepo repo-2499-qrecord
289 $ testadd qrecord --config ui.interactive=1 -m0 0.diff <<EOF
290 $ testadd qrecord --config ui.interactive=1 -m0 0.diff <<EOF
290 > y
291 > y
291 > y
292 > y
292 > EOF
293 > EOF
293 adding a
294 adding a
294 % abort when adding .hgsub w/dirty subrepo
295 % abort when adding .hgsub w/dirty subrepo
295 A .hgsub
296 A .hgsub
296 A sub/a
297 A sub/a
297 % qrecord --config ui.interactive=1 -m0 0.diff
298 % qrecord --config ui.interactive=1 -m0 0.diff
298 abort: uncommitted changes in subrepository "sub"
299 abort: uncommitted changes in subrepository "sub"
299 [255]
300 [255]
300 % update substate when adding .hgsub w/clean updated subrepo
301 % update substate when adding .hgsub w/clean updated subrepo
301 A .hgsub
302 A .hgsub
302 A sub/a
303 A sub/a
303 % qrecord --config ui.interactive=1 -m0 0.diff
304 % qrecord --config ui.interactive=1 -m0 0.diff
304 diff --git a/.hgsub b/.hgsub
305 diff --git a/.hgsub b/.hgsub
305 new file mode 100644
306 new file mode 100644
306 examine changes to '.hgsub'?
307 examine changes to '.hgsub'?
307 (enter ? for help) [Ynesfdaq?] y
308 (enter ? for help) [Ynesfdaq?] y
308
309
309 @@ -0,0 +1,1 @@
310 @@ -0,0 +1,1 @@
310 +sub = sub
311 +sub = sub
311 record this change to '.hgsub'?
312 record this change to '.hgsub'?
312 (enter ? for help) [Ynesfdaq?] y
313 (enter ? for help) [Ynesfdaq?] y
313
314
314 warning: subrepo spec file '.hgsub' not found
315 warning: subrepo spec file '.hgsub' not found
315 warning: subrepo spec file '.hgsub' not found
316 warning: subrepo spec file '.hgsub' not found
316 path sub
317 path sub
317 source sub
318 source sub
318 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
319 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
319 $ testmod qrecord --config ui.interactive=1 -m1 1.diff <<EOF
320 $ testmod qrecord --config ui.interactive=1 -m1 1.diff <<EOF
320 > y
321 > y
321 > y
322 > y
322 > EOF
323 > EOF
323 adding a
324 adding a
324 % abort when modifying .hgsub w/dirty subrepo
325 % abort when modifying .hgsub w/dirty subrepo
325 M .hgsub
326 M .hgsub
326 A sub2/a
327 A sub2/a
327 % qrecord --config ui.interactive=1 -m1 1.diff
328 % qrecord --config ui.interactive=1 -m1 1.diff
328 abort: uncommitted changes in subrepository "sub2"
329 abort: uncommitted changes in subrepository "sub2"
329 [255]
330 [255]
330 % update substate when modifying .hgsub w/clean updated subrepo
331 % update substate when modifying .hgsub w/clean updated subrepo
331 M .hgsub
332 M .hgsub
332 A sub2/a
333 A sub2/a
333 % qrecord --config ui.interactive=1 -m1 1.diff
334 % qrecord --config ui.interactive=1 -m1 1.diff
334 diff --git a/.hgsub b/.hgsub
335 diff --git a/.hgsub b/.hgsub
335 1 hunks, 1 lines changed
336 1 hunks, 1 lines changed
336 examine changes to '.hgsub'?
337 examine changes to '.hgsub'?
337 (enter ? for help) [Ynesfdaq?] y
338 (enter ? for help) [Ynesfdaq?] y
338
339
339 @@ -1,1 +1,2 @@
340 @@ -1,1 +1,2 @@
340 sub = sub
341 sub = sub
341 +sub2 = sub2
342 +sub2 = sub2
342 record this change to '.hgsub'?
343 record this change to '.hgsub'?
343 (enter ? for help) [Ynesfdaq?] y
344 (enter ? for help) [Ynesfdaq?] y
344
345
345 path sub
346 path sub
346 source sub
347 source sub
347 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
348 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
348 path sub2
349 path sub2
349 source sub2
350 source sub2
350 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
351 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
351
352
352 $ hg qpop -qa
353 $ hg qpop -qa
353 patch queue now empty
354 patch queue now empty
354 $ testrm1 qrecord --config ui.interactive=1 -m2 2.diff <<EOF
355 $ testrm1 qrecord --config ui.interactive=1 -m2 2.diff <<EOF
355 > y
356 > y
356 > y
357 > y
357 > EOF
358 > EOF
358 adding a
359 adding a
359 % update substate when removing .hgsub w/dirty subrepo
360 % update substate when removing .hgsub w/dirty subrepo
360 M sub3/a
361 M sub3/a
361 R .hgsub
362 R .hgsub
362 % qrecord --config ui.interactive=1 -m2 2.diff
363 % qrecord --config ui.interactive=1 -m2 2.diff
363 diff --git a/.hgsub b/.hgsub
364 diff --git a/.hgsub b/.hgsub
364 deleted file mode 100644
365 deleted file mode 100644
365 examine changes to '.hgsub'?
366 examine changes to '.hgsub'?
366 (enter ? for help) [Ynesfdaq?] y
367 (enter ? for help) [Ynesfdaq?] y
367
368
368 % debugsub should be empty
369 % debugsub should be empty
369
370
370 $ hg qpop -qa
371 $ hg qpop -qa
371 patch queue now empty
372 patch queue now empty
372 $ testrm2 qrecord --config ui.interactive=1 -m3 3.diff <<EOF
373 $ testrm2 qrecord --config ui.interactive=1 -m3 3.diff <<EOF
373 > y
374 > y
374 > y
375 > y
375 > EOF
376 > EOF
376 adding a
377 adding a
377 % update substate when removing .hgsub w/clean updated subrepo
378 % update substate when removing .hgsub w/clean updated subrepo
378 R .hgsub
379 R .hgsub
379 % qrecord --config ui.interactive=1 -m3 3.diff
380 % qrecord --config ui.interactive=1 -m3 3.diff
380 diff --git a/.hgsub b/.hgsub
381 diff --git a/.hgsub b/.hgsub
381 deleted file mode 100644
382 deleted file mode 100644
382 examine changes to '.hgsub'?
383 examine changes to '.hgsub'?
383 (enter ? for help) [Ynesfdaq?] y
384 (enter ? for help) [Ynesfdaq?] y
384
385
385 % debugsub should be empty
386 % debugsub should be empty
386
387
387 $ cd ..
388 $ cd ..
388
389
389
390
390 correctly handle subrepos with patch queues
391 correctly handle subrepos with patch queues
391 $ mkrepo repo-subrepo-with-queue
392 $ mkrepo repo-subrepo-with-queue
392 $ mksubrepo sub
393 $ mksubrepo sub
393 adding a
394 adding a
394 $ hg -R sub qnew sub0.diff
395 $ hg -R sub qnew sub0.diff
395 $ echo sub = sub >> .hgsub
396 $ echo sub = sub >> .hgsub
396 $ hg add .hgsub
397 $ hg add .hgsub
397 $ hg qnew 0.diff
398 $ hg qnew 0.diff
398
399
399 $ cd ..
400 $ cd ..
400
401
401 check whether MQ operations can import updated .hgsubstate correctly
402 check whether MQ operations can import updated .hgsubstate correctly
402 both into 'revision' and 'patch file under .hg/patches':
403 both into 'revision' and 'patch file under .hg/patches':
403
404
404 $ hg init importing-hgsubstate
405 $ hg init importing-hgsubstate
405 $ cd importing-hgsubstate
406 $ cd importing-hgsubstate
406
407
407 $ echo a > a
408 $ echo a > a
408 $ hg commit -u test -d '0 0' -Am '#0 in parent'
409 $ hg commit -u test -d '0 0' -Am '#0 in parent'
409 adding a
410 adding a
410 $ hg init sub
411 $ hg init sub
411 $ echo sa > sub/sa
412 $ echo sa > sub/sa
412 $ hg -R sub commit -u test -d '0 0' -Am '#0 in sub'
413 $ hg -R sub commit -u test -d '0 0' -Am '#0 in sub'
413 adding sa
414 adding sa
414 $ echo 'sub = sub' > .hgsub
415 $ echo 'sub = sub' > .hgsub
415 $ touch .hgsubstate
416 $ touch .hgsubstate
416 $ hg add .hgsub .hgsubstate
417 $ hg add .hgsub .hgsubstate
417
418
418 $ hg qnew -u test -d '0 0' import-at-qnew
419 $ hg qnew -u test -d '0 0' import-at-qnew
419 $ hg -R sub parents --template '{node} sub\n'
420 $ hg -R sub parents --template '{node} sub\n'
420 b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
421 b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
421 $ cat .hgsubstate
422 $ cat .hgsubstate
422 b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
423 b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
423 $ hg diff -c tip
424 $ hg diff -c tip
424 diff -r f499373e340c -r f69e96d86e75 .hgsub
425 diff -r f499373e340c -r f69e96d86e75 .hgsub
425 --- /dev/null
426 --- /dev/null
426 +++ b/.hgsub
427 +++ b/.hgsub
427 @@ -0,0 +1,1 @@
428 @@ -0,0 +1,1 @@
428 +sub = sub
429 +sub = sub
429 diff -r f499373e340c -r f69e96d86e75 .hgsubstate
430 diff -r f499373e340c -r f69e96d86e75 .hgsubstate
430 --- /dev/null
431 --- /dev/null
431 +++ b/.hgsubstate
432 +++ b/.hgsubstate
432 @@ -0,0 +1,1 @@
433 @@ -0,0 +1,1 @@
433 +b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
434 +b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
434 $ cat .hg/patches/import-at-qnew
435 $ cat .hg/patches/import-at-qnew
435 # HG changeset patch
436 # HG changeset patch
436 # User test
437 # User test
437 # Date 0 0
438 # Date 0 0
438 # Parent f499373e340cdca5d01dee904aeb42dd2a325e71
439 # Parent f499373e340cdca5d01dee904aeb42dd2a325e71
439
440
440 diff -r f499373e340c -r f69e96d86e75 .hgsub
441 diff -r f499373e340c -r f69e96d86e75 .hgsub
441 --- /dev/null
442 --- /dev/null
442 +++ b/.hgsub
443 +++ b/.hgsub
443 @@ -0,0 +1,1 @@
444 @@ -0,0 +1,1 @@
444 +sub = sub
445 +sub = sub
445 diff -r f499373e340c -r f69e96d86e75 .hgsubstate
446 diff -r f499373e340c -r f69e96d86e75 .hgsubstate
446 --- /dev/null
447 --- /dev/null
447 +++ b/.hgsubstate
448 +++ b/.hgsubstate
448 @@ -0,0 +1,1 @@
449 @@ -0,0 +1,1 @@
449 +b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
450 +b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
450 $ hg parents --template '{node}\n'
451 $ hg parents --template '{node}\n'
451 f69e96d86e75a6d4fd88285dc9697acb23951041
452 f69e96d86e75a6d4fd88285dc9697acb23951041
452 $ hg parents --template '{files}\n'
453 $ hg parents --template '{files}\n'
453 .hgsub .hgsubstate
454 .hgsub .hgsubstate
454
455
455 check also whether qnew not including ".hgsubstate" explicitly causes
456 check also whether qnew not including ".hgsubstate" explicitly causes
456 as same result (in node hash) as one including it.
457 as same result (in node hash) as one including it.
457
458
458 $ hg qpop -a -q
459 $ hg qpop -a -q
459 patch queue now empty
460 patch queue now empty
460 $ hg qdelete import-at-qnew
461 $ hg qdelete import-at-qnew
461 $ echo 'sub = sub' > .hgsub
462 $ echo 'sub = sub' > .hgsub
462 $ hg add .hgsub
463 $ hg add .hgsub
463 $ rm -f .hgsubstate
464 $ rm -f .hgsubstate
464 $ hg qnew -u test -d '0 0' import-at-qnew
465 $ hg qnew -u test -d '0 0' import-at-qnew
465 $ hg parents --template '{node}\n'
466 $ hg parents --template '{node}\n'
466 f69e96d86e75a6d4fd88285dc9697acb23951041
467 f69e96d86e75a6d4fd88285dc9697acb23951041
467 $ hg parents --template '{files}\n'
468 $ hg parents --template '{files}\n'
468 .hgsub .hgsubstate
469 .hgsub .hgsubstate
469
470
470 check whether qrefresh imports updated .hgsubstate correctly
471 check whether qrefresh imports updated .hgsubstate correctly
471
472
472 $ hg qpop
473 $ hg qpop
473 popping import-at-qnew
474 popping import-at-qnew
474 patch queue now empty
475 patch queue now empty
475 $ hg qpush
476 $ hg qpush
476 applying import-at-qnew
477 applying import-at-qnew
477 now at: import-at-qnew
478 now at: import-at-qnew
478 $ hg parents --template '{files}\n'
479 $ hg parents --template '{files}\n'
479 .hgsub .hgsubstate
480 .hgsub .hgsubstate
480
481
481 $ hg qnew import-at-qrefresh
482 $ hg qnew import-at-qrefresh
482 $ echo sb > sub/sb
483 $ echo sb > sub/sb
483 $ hg -R sub commit -u test -d '0 0' -Am '#1 in sub'
484 $ hg -R sub commit -u test -d '0 0' -Am '#1 in sub'
484 adding sb
485 adding sb
485 $ hg qrefresh -u test -d '0 0'
486 $ hg qrefresh -u test -d '0 0'
486 $ hg -R sub parents --template '{node} sub\n'
487 $ hg -R sub parents --template '{node} sub\n'
487 88ac1bef5ed43b689d1d200b59886b675dec474b sub
488 88ac1bef5ed43b689d1d200b59886b675dec474b sub
488 $ cat .hgsubstate
489 $ cat .hgsubstate
489 88ac1bef5ed43b689d1d200b59886b675dec474b sub
490 88ac1bef5ed43b689d1d200b59886b675dec474b sub
490 $ hg diff -c tip
491 $ hg diff -c tip
491 diff -r 05b056bb9c8c -r d987bec230f4 .hgsubstate
492 diff -r 05b056bb9c8c -r d987bec230f4 .hgsubstate
492 --- a/.hgsubstate
493 --- a/.hgsubstate
493 +++ b/.hgsubstate
494 +++ b/.hgsubstate
494 @@ -1,1 +1,1 @@
495 @@ -1,1 +1,1 @@
495 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
496 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
496 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
497 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
497 $ cat .hg/patches/import-at-qrefresh
498 $ cat .hg/patches/import-at-qrefresh
498 # HG changeset patch
499 # HG changeset patch
499 # User test
500 # User test
500 # Date 0 0
501 # Date 0 0
501 # Parent 05b056bb9c8c05ff15258b84fd42ab3527271033
502 # Parent 05b056bb9c8c05ff15258b84fd42ab3527271033
502
503
503 diff -r 05b056bb9c8c .hgsubstate
504 diff -r 05b056bb9c8c .hgsubstate
504 --- a/.hgsubstate
505 --- a/.hgsubstate
505 +++ b/.hgsubstate
506 +++ b/.hgsubstate
506 @@ -1,1 +1,1 @@
507 @@ -1,1 +1,1 @@
507 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
508 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
508 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
509 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
509 $ hg parents --template '{files}\n'
510 $ hg parents --template '{files}\n'
510 .hgsubstate
511 .hgsubstate
511
512
512 $ hg qrefresh -u test -d '0 0'
513 $ hg qrefresh -u test -d '0 0'
513 $ cat .hgsubstate
514 $ cat .hgsubstate
514 88ac1bef5ed43b689d1d200b59886b675dec474b sub
515 88ac1bef5ed43b689d1d200b59886b675dec474b sub
515 $ hg diff -c tip
516 $ hg diff -c tip
516 diff -r 05b056bb9c8c -r d987bec230f4 .hgsubstate
517 diff -r 05b056bb9c8c -r d987bec230f4 .hgsubstate
517 --- a/.hgsubstate
518 --- a/.hgsubstate
518 +++ b/.hgsubstate
519 +++ b/.hgsubstate
519 @@ -1,1 +1,1 @@
520 @@ -1,1 +1,1 @@
520 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
521 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
521 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
522 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
522 $ cat .hg/patches/import-at-qrefresh
523 $ cat .hg/patches/import-at-qrefresh
523 # HG changeset patch
524 # HG changeset patch
524 # User test
525 # User test
525 # Date 0 0
526 # Date 0 0
526 # Parent 05b056bb9c8c05ff15258b84fd42ab3527271033
527 # Parent 05b056bb9c8c05ff15258b84fd42ab3527271033
527
528
528 diff -r 05b056bb9c8c .hgsubstate
529 diff -r 05b056bb9c8c .hgsubstate
529 --- a/.hgsubstate
530 --- a/.hgsubstate
530 +++ b/.hgsubstate
531 +++ b/.hgsubstate
531 @@ -1,1 +1,1 @@
532 @@ -1,1 +1,1 @@
532 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
533 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
533 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
534 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
534 $ hg parents --template '{files}\n'
535 $ hg parents --template '{files}\n'
535 .hgsubstate
536 .hgsubstate
536
537
537 $ hg update -C tip
538 $ hg update -C tip
538 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
539 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
539 $ hg qpop -a
540 $ hg qpop -a
540 popping import-at-qrefresh
541 popping import-at-qrefresh
541 popping import-at-qnew
542 popping import-at-qnew
542 patch queue now empty
543 patch queue now empty
543
544
544 $ hg -R sub update -C 0
545 $ hg -R sub update -C 0
545 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
546 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
546 $ echo 'sub = sub' > .hgsub
547 $ echo 'sub = sub' > .hgsub
547 $ hg commit -Am '#1 in parent'
548 $ hg commit -Am '#1 in parent'
548 adding .hgsub
549 adding .hgsub
549 $ hg -R sub update -C 1
550 $ hg -R sub update -C 1
550 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
551 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
551 $ hg commit -Am '#2 in parent (but will be rolled back soon)'
552 $ hg commit -Am '#2 in parent (but will be rolled back soon)'
552 $ hg rollback
553 $ hg rollback
553 repository tip rolled back to revision 1 (undo commit)
554 repository tip rolled back to revision 1 (undo commit)
554 working directory now based on revision 1
555 working directory now based on revision 1
555 $ hg status
556 $ hg status
556 M .hgsubstate
557 M .hgsubstate
557 $ hg qnew -u test -d '0 0' checkstate-at-qnew
558 $ hg qnew -u test -d '0 0' checkstate-at-qnew
558 $ hg -R sub parents --template '{node} sub\n'
559 $ hg -R sub parents --template '{node} sub\n'
559 88ac1bef5ed43b689d1d200b59886b675dec474b sub
560 88ac1bef5ed43b689d1d200b59886b675dec474b sub
560 $ cat .hgsubstate
561 $ cat .hgsubstate
561 88ac1bef5ed43b689d1d200b59886b675dec474b sub
562 88ac1bef5ed43b689d1d200b59886b675dec474b sub
562 $ hg diff -c tip
563 $ hg diff -c tip
563 diff -r 4d91eb2fa1d1 -r 1259c112d884 .hgsubstate
564 diff -r 4d91eb2fa1d1 -r 1259c112d884 .hgsubstate
564 --- a/.hgsubstate
565 --- a/.hgsubstate
565 +++ b/.hgsubstate
566 +++ b/.hgsubstate
566 @@ -1,1 +1,1 @@
567 @@ -1,1 +1,1 @@
567 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
568 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
568 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
569 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
569 $ cat .hg/patches/checkstate-at-qnew
570 $ cat .hg/patches/checkstate-at-qnew
570 # HG changeset patch
571 # HG changeset patch
571 # User test
572 # User test
572 # Date 0 0
573 # Date 0 0
573 # Parent 4d91eb2fa1d1b22ec513347b9cd06f6b49d470fa
574 # Parent 4d91eb2fa1d1b22ec513347b9cd06f6b49d470fa
574
575
575 diff -r 4d91eb2fa1d1 -r 1259c112d884 .hgsubstate
576 diff -r 4d91eb2fa1d1 -r 1259c112d884 .hgsubstate
576 --- a/.hgsubstate
577 --- a/.hgsubstate
577 +++ b/.hgsubstate
578 +++ b/.hgsubstate
578 @@ -1,1 +1,1 @@
579 @@ -1,1 +1,1 @@
579 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
580 -b6f6e9c41f3dfd374a6d2ed4535c87951cf979cf sub
580 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
581 +88ac1bef5ed43b689d1d200b59886b675dec474b sub
581 $ hg parents --template '{files}\n'
582 $ hg parents --template '{files}\n'
582 .hgsubstate
583 .hgsubstate
583
584
584 check whether qrefresh not including ".hgsubstate" explicitly causes
585 check whether qrefresh not including ".hgsubstate" explicitly causes
585 as same result (in node hash) as one including it.
586 as same result (in node hash) as one including it.
586
587
587 $ hg update -C -q 0
588 $ hg update -C -q 0
588 $ hg qpop -a -q
589 $ hg qpop -a -q
589 patch queue now empty
590 patch queue now empty
590 $ hg qnew -u test -d '0 0' add-hgsub-at-qrefresh
591 $ hg qnew -u test -d '0 0' add-hgsub-at-qrefresh
591 $ echo 'sub = sub' > .hgsub
592 $ echo 'sub = sub' > .hgsub
592 $ echo > .hgsubstate
593 $ echo > .hgsubstate
593 $ hg add .hgsub .hgsubstate
594 $ hg add .hgsub .hgsubstate
594 $ hg qrefresh -u test -d '0 0'
595 $ hg qrefresh -u test -d '0 0'
595 $ hg parents --template '{node}\n'
596 $ hg parents --template '{node}\n'
596 7c48c35501aae6770ed9c2517014628615821a8e
597 7c48c35501aae6770ed9c2517014628615821a8e
597 $ hg parents --template '{files}\n'
598 $ hg parents --template '{files}\n'
598 .hgsub .hgsubstate
599 .hgsub .hgsubstate
599
600
600 $ hg qpop -a -q
601 $ hg qpop -a -q
601 patch queue now empty
602 patch queue now empty
602 $ hg qdelete add-hgsub-at-qrefresh
603 $ hg qdelete add-hgsub-at-qrefresh
603 $ hg qnew -u test -d '0 0' add-hgsub-at-qrefresh
604 $ hg qnew -u test -d '0 0' add-hgsub-at-qrefresh
604 $ echo 'sub = sub' > .hgsub
605 $ echo 'sub = sub' > .hgsub
605 $ hg add .hgsub
606 $ hg add .hgsub
606 $ rm -f .hgsubstate
607 $ rm -f .hgsubstate
607 $ hg qrefresh -u test -d '0 0'
608 $ hg qrefresh -u test -d '0 0'
608 $ hg parents --template '{node}\n'
609 $ hg parents --template '{node}\n'
609 7c48c35501aae6770ed9c2517014628615821a8e
610 7c48c35501aae6770ed9c2517014628615821a8e
610 $ hg parents --template '{files}\n'
611 $ hg parents --template '{files}\n'
611 .hgsub .hgsubstate
612 .hgsub .hgsubstate
612
613
613 $ cd ..
614 $ cd ..
614
615
615 $ cd ..
616 $ cd ..
@@ -1,1255 +1,1262 b''
1 #require git
1 #require git
2
2
3 make git commits repeatable
3 make git commits repeatable
4
4
5 $ cat >> $HGRCPATH <<EOF
5 $ cat >> $HGRCPATH <<EOF
6 > [defaults]
6 > [defaults]
7 > commit = -d "0 0"
7 > commit = -d "0 0"
8 > EOF
8 > EOF
9
9
10 $ echo "[core]" >> $HOME/.gitconfig
10 $ echo "[core]" >> $HOME/.gitconfig
11 $ echo "autocrlf = false" >> $HOME/.gitconfig
11 $ echo "autocrlf = false" >> $HOME/.gitconfig
12 $ GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME
12 $ GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME
13 $ GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL
13 $ GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL
14 $ GIT_AUTHOR_DATE='1234567891 +0000'; export GIT_AUTHOR_DATE
14 $ GIT_AUTHOR_DATE='1234567891 +0000'; export GIT_AUTHOR_DATE
15 $ GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; export GIT_COMMITTER_NAME
15 $ GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; export GIT_COMMITTER_NAME
16 $ GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"; export GIT_COMMITTER_EMAIL
16 $ GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"; export GIT_COMMITTER_EMAIL
17 $ GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"; export GIT_COMMITTER_DATE
17 $ GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"; export GIT_COMMITTER_DATE
18 $ GIT_CONFIG_NOSYSTEM=1; export GIT_CONFIG_NOSYSTEM
18 $ GIT_CONFIG_NOSYSTEM=1; export GIT_CONFIG_NOSYSTEM
19
19
20 root hg repo
20 root hg repo
21
21
22 $ hg init t
22 $ hg init t
23 $ cd t
23 $ cd t
24 $ echo a > a
24 $ echo a > a
25 $ hg add a
25 $ hg add a
26 $ hg commit -m a
26 $ hg commit -m a
27 $ cd ..
27 $ cd ..
28
28
29 new external git repo
29 new external git repo
30
30
31 $ mkdir gitroot
31 $ mkdir gitroot
32 $ cd gitroot
32 $ cd gitroot
33 $ git init -q
33 $ git init -q
34 $ echo g > g
34 $ echo g > g
35 $ git add g
35 $ git add g
36 $ git commit -q -m g
36 $ git commit -q -m g
37
37
38 add subrepo clone
38 add subrepo clone
39
39
40 $ cd ../t
40 $ cd ../t
41 $ echo 's = [git]../gitroot' > .hgsub
41 $ echo 's = [git]../gitroot' > .hgsub
42 $ git clone -q ../gitroot s
42 $ git clone -q ../gitroot s
43 $ hg add .hgsub
43 $ hg add .hgsub
44
44
45 git subrepo is disabled by default
45 git subrepo is disabled by default
46
46
47 $ hg commit -m 'new git subrepo'
47 $ hg commit -m 'new git subrepo'
48 abort: git subrepos not allowed
48 abort: git subrepos not allowed
49 (see 'hg help config.subrepos' for details)
49 (see 'hg help config.subrepos' for details)
50 [255]
50 [255]
51
51
52 so enable it
52 so enable it
53
53
54 $ cat >> $HGRCPATH <<EOF
54 $ cat >> $HGRCPATH <<EOF
55 > [subrepos]
55 > [subrepos]
56 > git:allowed = true
56 > git:allowed = true
57 > EOF
57 > EOF
58
58
59 $ hg commit -m 'new git subrepo'
59 $ hg commit -m 'new git subrepo'
60
60
61 $ hg debugsub
61 $ hg debugsub
62 path s
62 path s
63 source ../gitroot
63 source ../gitroot
64 revision da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
64 revision da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
65
65
66 record a new commit from upstream from a different branch
66 record a new commit from upstream from a different branch
67
67
68 $ cd ../gitroot
68 $ cd ../gitroot
69 $ git checkout -q -b testing
69 $ git checkout -q -b testing
70 $ echo gg >> g
70 $ echo gg >> g
71 $ git commit -q -a -m gg
71 $ git commit -q -a -m gg
72
72
73 $ cd ../t/s
73 $ cd ../t/s
74 $ git pull -q >/dev/null 2>/dev/null
74 $ git pull -q >/dev/null 2>/dev/null
75 $ git checkout -q -b testing origin/testing >/dev/null
75 $ git checkout -q -b testing origin/testing >/dev/null
76
76
77 $ cd ..
77 $ cd ..
78 $ hg status --subrepos
78 $ hg status --subrepos
79 M s/g
79 M s/g
80 $ hg commit -m 'update git subrepo'
80 $ hg commit -m 'update git subrepo'
81 $ hg debugsub
81 $ hg debugsub
82 path s
82 path s
83 source ../gitroot
83 source ../gitroot
84 revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a
84 revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a
85
85
86 make $GITROOT pushable, by replacing it with a clone with nothing checked out
86 make $GITROOT pushable, by replacing it with a clone with nothing checked out
87
87
88 $ cd ..
88 $ cd ..
89 $ git clone gitroot gitrootbare --bare -q
89 $ git clone gitroot gitrootbare --bare -q
90 $ rm -rf gitroot
90 $ rm -rf gitroot
91 $ mv gitrootbare gitroot
91 $ mv gitrootbare gitroot
92
92
93 clone root
93 clone root
94
94
95 $ cd t
95 $ cd t
96 $ hg clone . ../tc 2> /dev/null
96 $ hg clone . ../tc 2> /dev/null
97 updating to branch default
97 updating to branch default
98 cloning subrepo s from $TESTTMP/gitroot
98 cloning subrepo s from $TESTTMP/gitroot
99 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
99 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
100 $ cd ../tc
100 $ cd ../tc
101 $ hg debugsub
101 $ hg debugsub
102 path s
102 path s
103 source ../gitroot
103 source ../gitroot
104 revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a
104 revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a
105 $ cd ..
105 $ cd ..
106
106
107 clone with subrepo disabled (update should fail)
107 clone with subrepo disabled (update should fail)
108
108
109 $ hg clone t -U tc2 --config subrepos.allowed=false
109 $ hg clone t -U tc2 --config subrepos.allowed=false
110 $ hg update -R tc2 --config subrepos.allowed=false
110 $ hg update -R tc2 --config subrepos.allowed=false
111 abort: subrepos not enabled
111 abort: subrepos not enabled
112 (see 'hg help config.subrepos' for details)
112 (see 'hg help config.subrepos' for details)
113 [255]
113 [255]
114 $ ls tc2
114 $ ls tc2
115 a
115 a
116
116
117 $ hg clone t tc3 --config subrepos.allowed=false
117 $ hg clone t tc3 --config subrepos.allowed=false
118 updating to branch default
118 updating to branch default
119 abort: subrepos not enabled
119 abort: subrepos not enabled
120 (see 'hg help config.subrepos' for details)
120 (see 'hg help config.subrepos' for details)
121 [255]
121 [255]
122 $ ls tc3
122 $ ls tc3
123 a
123 a
124
124
125 update to previous substate
125 update to previous substate
126
126
127 $ cd tc
127 $ cd tc
128 $ hg update 1 -q
128 $ hg update 1 -q
129 $ cat s/g
129 $ cat s/g
130 g
130 g
131 $ hg debugsub
131 $ hg debugsub
132 path s
132 path s
133 source ../gitroot
133 source ../gitroot
134 revision da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
134 revision da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
135
135
136 clone root, make local change
136 clone root, make local change
137
137
138 $ cd ../t
138 $ cd ../t
139 $ hg clone . ../ta 2> /dev/null
139 $ hg clone . ../ta 2> /dev/null
140 updating to branch default
140 updating to branch default
141 cloning subrepo s from $TESTTMP/gitroot
141 cloning subrepo s from $TESTTMP/gitroot
142 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
142 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
143
143
144 $ cd ../ta
144 $ cd ../ta
145 $ echo ggg >> s/g
145 $ echo ggg >> s/g
146 $ hg status --subrepos
146 $ hg status --subrepos
147 M s/g
147 M s/g
148 $ hg diff --subrepos
148 $ hg diff --subrepos
149 diff --git a/s/g b/s/g
149 diff --git a/s/g b/s/g
150 index 089258f..85341ee 100644
150 index 089258f..85341ee 100644
151 --- a/s/g
151 --- a/s/g
152 +++ b/s/g
152 +++ b/s/g
153 @@ -1,2 +1,3 @@
153 @@ -1,2 +1,3 @@
154 g
154 g
155 gg
155 gg
156 +ggg
156 +ggg
157 $ hg commit --subrepos -m ggg
157 $ hg commit --subrepos -m ggg
158 committing subrepository s
158 committing subrepository s
159 $ hg debugsub
159 $ hg debugsub
160 path s
160 path s
161 source ../gitroot
161 source ../gitroot
162 revision 79695940086840c99328513acbe35f90fcd55e57
162 revision 79695940086840c99328513acbe35f90fcd55e57
163
163
164 clone root separately, make different local change
164 clone root separately, make different local change
165
165
166 $ cd ../t
166 $ cd ../t
167 $ hg clone . ../tb 2> /dev/null
167 $ hg clone . ../tb 2> /dev/null
168 updating to branch default
168 updating to branch default
169 cloning subrepo s from $TESTTMP/gitroot
169 cloning subrepo s from $TESTTMP/gitroot
170 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
170 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
171
171
172 $ cd ../tb/s
172 $ cd ../tb/s
173 $ hg status --subrepos
173 $ hg status --subrepos
174 $ echo f > f
174 $ echo f > f
175 $ hg status --subrepos
175 $ hg status --subrepos
176 ? s/f
176 ? s/f
177 $ hg add .
177 $ hg add .
178 adding f
178 adding f
179 $ git add f
179 $ git add f
180 $ cd ..
180 $ cd ..
181
181
182 $ hg status --subrepos
182 $ hg status --subrepos
183 A s/f
183 A s/f
184 $ hg commit --subrepos -m f
184 $ hg commit --subrepos -m f
185 committing subrepository s
185 committing subrepository s
186 $ hg debugsub
186 $ hg debugsub
187 path s
187 path s
188 source ../gitroot
188 source ../gitroot
189 revision aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
189 revision aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
190
190
191 user b push changes
191 user b push changes
192
192
193 $ hg push 2>/dev/null
193 $ hg push 2>/dev/null
194 pushing to $TESTTMP/t
194 pushing to $TESTTMP/t
195 pushing branch testing of subrepository "s"
195 pushing branch testing of subrepository "s"
196 searching for changes
196 searching for changes
197 adding changesets
197 adding changesets
198 adding manifests
198 adding manifests
199 adding file changes
199 adding file changes
200 added 1 changesets with 1 changes to 1 files
200 added 1 changesets with 1 changes to 1 files
201
201
202 user a pulls, merges, commits
202 user a pulls, merges, commits
203
203
204 $ cd ../ta
204 $ cd ../ta
205 $ hg pull
205 $ hg pull
206 pulling from $TESTTMP/t
206 pulling from $TESTTMP/t
207 searching for changes
207 searching for changes
208 adding changesets
208 adding changesets
209 adding manifests
209 adding manifests
210 adding file changes
210 adding file changes
211 added 1 changesets with 1 changes to 1 files (+1 heads)
211 added 1 changesets with 1 changes to 1 files (+1 heads)
212 new changesets 089416c11d73
212 new changesets 089416c11d73
213 (run 'hg heads' to see heads, 'hg merge' to merge)
213 (run 'hg heads' to see heads, 'hg merge' to merge)
214 $ hg merge 2>/dev/null
214 $ hg merge 2>/dev/null
215 subrepository s diverged (local revision: 7969594, remote revision: aa84837)
215 subrepository s diverged (local revision: 7969594, remote revision: aa84837)
216 (M)erge, keep (l)ocal [working copy] or keep (r)emote [merge rev]? m
216 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [merge rev].
217 what do you want to do? m
217 pulling subrepo s from $TESTTMP/gitroot
218 pulling subrepo s from $TESTTMP/gitroot
218 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
219 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
219 (branch merge, don't forget to commit)
220 (branch merge, don't forget to commit)
220 $ hg st --subrepos s
221 $ hg st --subrepos s
221 A s/f
222 A s/f
222 $ cat s/f
223 $ cat s/f
223 f
224 f
224 $ cat s/g
225 $ cat s/g
225 g
226 g
226 gg
227 gg
227 ggg
228 ggg
228 $ hg commit --subrepos -m 'merge'
229 $ hg commit --subrepos -m 'merge'
229 committing subrepository s
230 committing subrepository s
230 $ hg status --subrepos --rev 1:5
231 $ hg status --subrepos --rev 1:5
231 M .hgsubstate
232 M .hgsubstate
232 M s/g
233 M s/g
233 A s/f
234 A s/f
234 $ hg debugsub
235 $ hg debugsub
235 path s
236 path s
236 source ../gitroot
237 source ../gitroot
237 revision f47b465e1bce645dbf37232a00574aa1546ca8d3
238 revision f47b465e1bce645dbf37232a00574aa1546ca8d3
238 $ hg push 2>/dev/null
239 $ hg push 2>/dev/null
239 pushing to $TESTTMP/t
240 pushing to $TESTTMP/t
240 pushing branch testing of subrepository "s"
241 pushing branch testing of subrepository "s"
241 searching for changes
242 searching for changes
242 adding changesets
243 adding changesets
243 adding manifests
244 adding manifests
244 adding file changes
245 adding file changes
245 added 2 changesets with 2 changes to 1 files
246 added 2 changesets with 2 changes to 1 files
246
247
247 make upstream git changes
248 make upstream git changes
248
249
249 $ cd ..
250 $ cd ..
250 $ git clone -q gitroot gitclone
251 $ git clone -q gitroot gitclone
251 $ cd gitclone
252 $ cd gitclone
252 $ echo ff >> f
253 $ echo ff >> f
253 $ git commit -q -a -m ff
254 $ git commit -q -a -m ff
254 $ echo fff >> f
255 $ echo fff >> f
255 $ git commit -q -a -m fff
256 $ git commit -q -a -m fff
256 $ git push origin testing 2>/dev/null
257 $ git push origin testing 2>/dev/null
257
258
258 make and push changes to hg without updating the subrepo
259 make and push changes to hg without updating the subrepo
259
260
260 $ cd ../t
261 $ cd ../t
261 $ hg clone . ../td 2>&1 | egrep -v '^Cloning into|^done\.'
262 $ hg clone . ../td 2>&1 | egrep -v '^Cloning into|^done\.'
262 updating to branch default
263 updating to branch default
263 cloning subrepo s from $TESTTMP/gitroot
264 cloning subrepo s from $TESTTMP/gitroot
264 checking out detached HEAD in subrepository "s"
265 checking out detached HEAD in subrepository "s"
265 check out a git branch if you intend to make changes
266 check out a git branch if you intend to make changes
266 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
267 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
267 $ cd ../td
268 $ cd ../td
268 $ echo aa >> a
269 $ echo aa >> a
269 $ hg commit -m aa
270 $ hg commit -m aa
270 $ hg push
271 $ hg push
271 pushing to $TESTTMP/t
272 pushing to $TESTTMP/t
272 searching for changes
273 searching for changes
273 adding changesets
274 adding changesets
274 adding manifests
275 adding manifests
275 adding file changes
276 adding file changes
276 added 1 changesets with 1 changes to 1 files
277 added 1 changesets with 1 changes to 1 files
277
278
278 sync to upstream git, distribute changes
279 sync to upstream git, distribute changes
279
280
280 $ cd ../ta
281 $ cd ../ta
281 $ hg pull -u -q
282 $ hg pull -u -q
282 $ cd s
283 $ cd s
283 $ git pull -q >/dev/null 2>/dev/null
284 $ git pull -q >/dev/null 2>/dev/null
284 $ cd ..
285 $ cd ..
285 $ hg commit -m 'git upstream sync'
286 $ hg commit -m 'git upstream sync'
286 $ hg debugsub
287 $ hg debugsub
287 path s
288 path s
288 source ../gitroot
289 source ../gitroot
289 revision 32a343883b74769118bb1d3b4b1fbf9156f4dddc
290 revision 32a343883b74769118bb1d3b4b1fbf9156f4dddc
290 $ hg push -q
291 $ hg push -q
291
292
292 $ cd ../tb
293 $ cd ../tb
293 $ hg pull -q
294 $ hg pull -q
294 $ hg update 2>/dev/null
295 $ hg update 2>/dev/null
295 pulling subrepo s from $TESTTMP/gitroot
296 pulling subrepo s from $TESTTMP/gitroot
296 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
297 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
297 $ hg debugsub
298 $ hg debugsub
298 path s
299 path s
299 source ../gitroot
300 source ../gitroot
300 revision 32a343883b74769118bb1d3b4b1fbf9156f4dddc
301 revision 32a343883b74769118bb1d3b4b1fbf9156f4dddc
301
302
302 create a new git branch
303 create a new git branch
303
304
304 $ cd s
305 $ cd s
305 $ git checkout -b b2
306 $ git checkout -b b2
306 Switched to a new branch 'b2'
307 Switched to a new branch 'b2'
307 $ echo a>a
308 $ echo a>a
308 $ git add a
309 $ git add a
309 $ git commit -qm 'add a'
310 $ git commit -qm 'add a'
310 $ cd ..
311 $ cd ..
311 $ hg commit -m 'add branch in s'
312 $ hg commit -m 'add branch in s'
312
313
313 pulling new git branch should not create tracking branch named 'origin/b2'
314 pulling new git branch should not create tracking branch named 'origin/b2'
314 (issue3870)
315 (issue3870)
315 $ cd ../td/s
316 $ cd ../td/s
316 $ git remote set-url origin $TESTTMP/tb/s
317 $ git remote set-url origin $TESTTMP/tb/s
317 $ git branch --no-track oldtesting
318 $ git branch --no-track oldtesting
318 $ cd ..
319 $ cd ..
319 $ hg pull -q ../tb
320 $ hg pull -q ../tb
320 $ hg up
321 $ hg up
321 From $TESTTMP/tb/s
322 From $TESTTMP/tb/s
322 * [new branch] b2 -> origin/b2
323 * [new branch] b2 -> origin/b2
323 Previous HEAD position was f47b465* merge (glob)
324 Previous HEAD position was f47b465* merge (glob)
324 Switched to a new branch 'b2'
325 Switched to a new branch 'b2'
325 pulling subrepo s from $TESTTMP/tb/s
326 pulling subrepo s from $TESTTMP/tb/s
326 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
327 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
327
328
328 update to a revision without the subrepo, keeping the local git repository
329 update to a revision without the subrepo, keeping the local git repository
329
330
330 $ cd ../t
331 $ cd ../t
331 $ hg up 0
332 $ hg up 0
332 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
333 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
333 $ ls -a s
334 $ ls -a s
334 .
335 .
335 ..
336 ..
336 .git
337 .git
337
338
338 $ hg up 2
339 $ hg up 2
339 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
340 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
340 $ ls -a s
341 $ ls -a s
341 .
342 .
342 ..
343 ..
343 .git
344 .git
344 g
345 g
345
346
346 archive subrepos
347 archive subrepos
347
348
348 $ cd ../tc
349 $ cd ../tc
349 $ hg pull -q
350 $ hg pull -q
350 $ hg archive --subrepos -r 5 ../archive 2>/dev/null
351 $ hg archive --subrepos -r 5 ../archive 2>/dev/null
351 pulling subrepo s from $TESTTMP/gitroot
352 pulling subrepo s from $TESTTMP/gitroot
352 $ cd ../archive
353 $ cd ../archive
353 $ cat s/f
354 $ cat s/f
354 f
355 f
355 $ cat s/g
356 $ cat s/g
356 g
357 g
357 gg
358 gg
358 ggg
359 ggg
359
360
360 $ hg -R ../tc archive --subrepo -r 5 -X ../tc/**f ../archive_x 2>/dev/null
361 $ hg -R ../tc archive --subrepo -r 5 -X ../tc/**f ../archive_x 2>/dev/null
361 $ find ../archive_x | sort | grep -v pax_global_header
362 $ find ../archive_x | sort | grep -v pax_global_header
362 ../archive_x
363 ../archive_x
363 ../archive_x/.hg_archival.txt
364 ../archive_x/.hg_archival.txt
364 ../archive_x/.hgsub
365 ../archive_x/.hgsub
365 ../archive_x/.hgsubstate
366 ../archive_x/.hgsubstate
366 ../archive_x/a
367 ../archive_x/a
367 ../archive_x/s
368 ../archive_x/s
368 ../archive_x/s/g
369 ../archive_x/s/g
369
370
370 $ hg -R ../tc archive -S ../archive.tgz --prefix '.' 2>/dev/null
371 $ hg -R ../tc archive -S ../archive.tgz --prefix '.' 2>/dev/null
371 $ tar -tzf ../archive.tgz | sort | grep -v pax_global_header
372 $ tar -tzf ../archive.tgz | sort | grep -v pax_global_header
372 .hg_archival.txt
373 .hg_archival.txt
373 .hgsub
374 .hgsub
374 .hgsubstate
375 .hgsubstate
375 a
376 a
376 s/g
377 s/g
377
378
378 create nested repo
379 create nested repo
379
380
380 $ cd ..
381 $ cd ..
381 $ hg init outer
382 $ hg init outer
382 $ cd outer
383 $ cd outer
383 $ echo b>b
384 $ echo b>b
384 $ hg add b
385 $ hg add b
385 $ hg commit -m b
386 $ hg commit -m b
386
387
387 $ hg clone ../t inner 2> /dev/null
388 $ hg clone ../t inner 2> /dev/null
388 updating to branch default
389 updating to branch default
389 cloning subrepo s from $TESTTMP/gitroot
390 cloning subrepo s from $TESTTMP/gitroot
390 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
391 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
391 $ echo inner = inner > .hgsub
392 $ echo inner = inner > .hgsub
392 $ hg add .hgsub
393 $ hg add .hgsub
393 $ hg commit -m 'nested sub'
394 $ hg commit -m 'nested sub'
394
395
395 nested commit
396 nested commit
396
397
397 $ echo ffff >> inner/s/f
398 $ echo ffff >> inner/s/f
398 $ hg status --subrepos
399 $ hg status --subrepos
399 M inner/s/f
400 M inner/s/f
400 $ hg commit --subrepos -m nested
401 $ hg commit --subrepos -m nested
401 committing subrepository inner
402 committing subrepository inner
402 committing subrepository inner/s
403 committing subrepository inner/s
403
404
404 nested archive
405 nested archive
405
406
406 $ hg archive --subrepos ../narchive
407 $ hg archive --subrepos ../narchive
407 $ ls ../narchive/inner/s | grep -v pax_global_header
408 $ ls ../narchive/inner/s | grep -v pax_global_header
408 f
409 f
409 g
410 g
410
411
411 relative source expansion
412 relative source expansion
412
413
413 $ cd ..
414 $ cd ..
414 $ mkdir d
415 $ mkdir d
415 $ hg clone t d/t 2> /dev/null
416 $ hg clone t d/t 2> /dev/null
416 updating to branch default
417 updating to branch default
417 cloning subrepo s from $TESTTMP/gitroot
418 cloning subrepo s from $TESTTMP/gitroot
418 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
419 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
419
420
420 Don't crash if the subrepo is missing
421 Don't crash if the subrepo is missing
421
422
422 $ hg clone t missing -q
423 $ hg clone t missing -q
423 $ cd missing
424 $ cd missing
424 $ rm -rf s
425 $ rm -rf s
425 $ hg status -S
426 $ hg status -S
426 $ hg sum | grep commit
427 $ hg sum | grep commit
427 commit: 1 subrepos
428 commit: 1 subrepos
428 $ hg push -q
429 $ hg push -q
429 abort: subrepo s is missing (in subrepository "s")
430 abort: subrepo s is missing (in subrepository "s")
430 [255]
431 [255]
431 $ hg commit --subrepos -qm missing
432 $ hg commit --subrepos -qm missing
432 abort: subrepo s is missing (in subrepository "s")
433 abort: subrepo s is missing (in subrepository "s")
433 [255]
434 [255]
434
435
435 #if symlink
436 #if symlink
436 Don't crash if subrepo is a broken symlink
437 Don't crash if subrepo is a broken symlink
437 $ ln -s broken s
438 $ ln -s broken s
438 $ hg status -S
439 $ hg status -S
439 abort: subrepo 's' traverses symbolic link
440 abort: subrepo 's' traverses symbolic link
440 [255]
441 [255]
441 $ hg push -q
442 $ hg push -q
442 abort: subrepo 's' traverses symbolic link
443 abort: subrepo 's' traverses symbolic link
443 [255]
444 [255]
444 $ hg commit --subrepos -qm missing
445 $ hg commit --subrepos -qm missing
445 abort: subrepo 's' traverses symbolic link
446 abort: subrepo 's' traverses symbolic link
446 [255]
447 [255]
447 $ rm s
448 $ rm s
448 #endif
449 #endif
449
450
450 $ hg update -C 2> /dev/null
451 $ hg update -C 2> /dev/null
451 cloning subrepo s from $TESTTMP/gitroot
452 cloning subrepo s from $TESTTMP/gitroot
452 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
453 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
453 $ hg sum | grep commit
454 $ hg sum | grep commit
454 commit: (clean)
455 commit: (clean)
455
456
456 Don't crash if the .hgsubstate entry is missing
457 Don't crash if the .hgsubstate entry is missing
457
458
458 $ hg update 1 -q
459 $ hg update 1 -q
459 $ hg rm .hgsubstate
460 $ hg rm .hgsubstate
460 $ hg commit .hgsubstate -m 'no substate'
461 $ hg commit .hgsubstate -m 'no substate'
461 nothing changed
462 nothing changed
462 [1]
463 [1]
463 $ hg tag -l nosubstate
464 $ hg tag -l nosubstate
464 $ hg manifest
465 $ hg manifest
465 .hgsub
466 .hgsub
466 .hgsubstate
467 .hgsubstate
467 a
468 a
468
469
469 $ hg status -S
470 $ hg status -S
470 R .hgsubstate
471 R .hgsubstate
471 $ hg sum | grep commit
472 $ hg sum | grep commit
472 commit: 1 removed, 1 subrepos (new branch head)
473 commit: 1 removed, 1 subrepos (new branch head)
473
474
474 $ hg commit -m 'restore substate'
475 $ hg commit -m 'restore substate'
475 nothing changed
476 nothing changed
476 [1]
477 [1]
477 $ hg manifest
478 $ hg manifest
478 .hgsub
479 .hgsub
479 .hgsubstate
480 .hgsubstate
480 a
481 a
481 $ hg sum | grep commit
482 $ hg sum | grep commit
482 commit: 1 removed, 1 subrepos (new branch head)
483 commit: 1 removed, 1 subrepos (new branch head)
483
484
484 $ hg update -qC nosubstate
485 $ hg update -qC nosubstate
485 $ ls s
486 $ ls s
486 g
487 g
487
488
488 issue3109: false positives in git diff-index
489 issue3109: false positives in git diff-index
489
490
490 $ hg update -q
491 $ hg update -q
491 $ touch -t 200001010000 s/g
492 $ touch -t 200001010000 s/g
492 $ hg status --subrepos
493 $ hg status --subrepos
493 $ touch -t 200001010000 s/g
494 $ touch -t 200001010000 s/g
494 $ hg sum | grep commit
495 $ hg sum | grep commit
495 commit: (clean)
496 commit: (clean)
496
497
497 Check hg update --clean
498 Check hg update --clean
498 $ cd $TESTTMP/ta
499 $ cd $TESTTMP/ta
499 $ echo > s/g
500 $ echo > s/g
500 $ cd s
501 $ cd s
501 $ echo c1 > f1
502 $ echo c1 > f1
502 $ echo c1 > f2
503 $ echo c1 > f2
503 $ git add f1
504 $ git add f1
504 $ cd ..
505 $ cd ..
505 $ hg status -S
506 $ hg status -S
506 M s/g
507 M s/g
507 A s/f1
508 A s/f1
508 ? s/f2
509 ? s/f2
509 $ ls s
510 $ ls s
510 f
511 f
511 f1
512 f1
512 f2
513 f2
513 g
514 g
514 $ hg update --clean
515 $ hg update --clean
515 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
516 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
516 $ hg status -S
517 $ hg status -S
517 ? s/f1
518 ? s/f1
518 ? s/f2
519 ? s/f2
519 $ ls s
520 $ ls s
520 f
521 f
521 f1
522 f1
522 f2
523 f2
523 g
524 g
524
525
525 Sticky subrepositories, no changes
526 Sticky subrepositories, no changes
526 $ cd $TESTTMP/ta
527 $ cd $TESTTMP/ta
527 $ hg id -n
528 $ hg id -n
528 7
529 7
529 $ cd s
530 $ cd s
530 $ git rev-parse HEAD
531 $ git rev-parse HEAD
531 32a343883b74769118bb1d3b4b1fbf9156f4dddc
532 32a343883b74769118bb1d3b4b1fbf9156f4dddc
532 $ cd ..
533 $ cd ..
533 $ hg update 1 > /dev/null 2>&1
534 $ hg update 1 > /dev/null 2>&1
534 $ hg id -n
535 $ hg id -n
535 1
536 1
536 $ cd s
537 $ cd s
537 $ git rev-parse HEAD
538 $ git rev-parse HEAD
538 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
539 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
539 $ cd ..
540 $ cd ..
540
541
541 Sticky subrepositories, file changes
542 Sticky subrepositories, file changes
542 $ touch s/f1
543 $ touch s/f1
543 $ cd s
544 $ cd s
544 $ git add f1
545 $ git add f1
545 $ cd ..
546 $ cd ..
546 $ hg id -n
547 $ hg id -n
547 1+
548 1+
548 $ cd s
549 $ cd s
549 $ git rev-parse HEAD
550 $ git rev-parse HEAD
550 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
551 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
551 $ cd ..
552 $ cd ..
552 $ hg update 4
553 $ hg update 4
553 subrepository s diverged (local revision: da5f5b1, remote revision: aa84837)
554 subrepository s diverged (local revision: da5f5b1, remote revision: aa84837)
554 (M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
555 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [destination].
556 what do you want to do? m
555 subrepository sources for s differ
557 subrepository sources for s differ
556 use (l)ocal source (da5f5b1) or (r)emote source (aa84837)? l
558 you can use (l)ocal source (da5f5b1) or (r)emote source (aa84837).
559 what do you want to do? l
557 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
560 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
558 $ hg id -n
561 $ hg id -n
559 4+
562 4+
560 $ cd s
563 $ cd s
561 $ git rev-parse HEAD
564 $ git rev-parse HEAD
562 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
565 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
563 $ cd ..
566 $ cd ..
564 $ hg update --clean tip > /dev/null 2>&1
567 $ hg update --clean tip > /dev/null 2>&1
565
568
566 Sticky subrepository, revision updates
569 Sticky subrepository, revision updates
567 $ hg id -n
570 $ hg id -n
568 7
571 7
569 $ cd s
572 $ cd s
570 $ git rev-parse HEAD
573 $ git rev-parse HEAD
571 32a343883b74769118bb1d3b4b1fbf9156f4dddc
574 32a343883b74769118bb1d3b4b1fbf9156f4dddc
572 $ cd ..
575 $ cd ..
573 $ cd s
576 $ cd s
574 $ git checkout aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
577 $ git checkout aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
575 Previous HEAD position was 32a3438* fff (glob)
578 Previous HEAD position was 32a3438* fff (glob)
576 HEAD is now at aa84837* f (glob)
579 HEAD is now at aa84837* f (glob)
577 $ cd ..
580 $ cd ..
578 $ hg update 1
581 $ hg update 1
579 subrepository s diverged (local revision: 32a3438, remote revision: da5f5b1)
582 subrepository s diverged (local revision: 32a3438, remote revision: da5f5b1)
580 (M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
583 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [destination].
584 what do you want to do? m
581 subrepository sources for s differ (in checked out version)
585 subrepository sources for s differ (in checked out version)
582 use (l)ocal source (32a3438) or (r)emote source (da5f5b1)? l
586 you can use (l)ocal source (32a3438) or (r)emote source (da5f5b1).
587 what do you want to do? l
583 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
588 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
584 $ hg id -n
589 $ hg id -n
585 1+
590 1+
586 $ cd s
591 $ cd s
587 $ git rev-parse HEAD
592 $ git rev-parse HEAD
588 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
593 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
589 $ cd ..
594 $ cd ..
590
595
591 Sticky subrepository, file changes and revision updates
596 Sticky subrepository, file changes and revision updates
592 $ touch s/f1
597 $ touch s/f1
593 $ cd s
598 $ cd s
594 $ git add f1
599 $ git add f1
595 $ git rev-parse HEAD
600 $ git rev-parse HEAD
596 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
601 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
597 $ cd ..
602 $ cd ..
598 $ hg id -n
603 $ hg id -n
599 1+
604 1+
600 $ hg update 7
605 $ hg update 7
601 subrepository s diverged (local revision: 32a3438, remote revision: 32a3438)
606 subrepository s diverged (local revision: 32a3438, remote revision: 32a3438)
602 (M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
607 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [destination].
608 what do you want to do? m
603 subrepository sources for s differ
609 subrepository sources for s differ
604 use (l)ocal source (32a3438) or (r)emote source (32a3438)? l
610 you can use (l)ocal source (32a3438) or (r)emote source (32a3438).
611 what do you want to do? l
605 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
612 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
606 $ hg id -n
613 $ hg id -n
607 7+
614 7+
608 $ cd s
615 $ cd s
609 $ git rev-parse HEAD
616 $ git rev-parse HEAD
610 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
617 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
611 $ cd ..
618 $ cd ..
612
619
613 Sticky repository, update --clean
620 Sticky repository, update --clean
614 $ hg update --clean tip 2>/dev/null
621 $ hg update --clean tip 2>/dev/null
615 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
622 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
616 $ hg id -n
623 $ hg id -n
617 7
624 7
618 $ cd s
625 $ cd s
619 $ git rev-parse HEAD
626 $ git rev-parse HEAD
620 32a343883b74769118bb1d3b4b1fbf9156f4dddc
627 32a343883b74769118bb1d3b4b1fbf9156f4dddc
621 $ cd ..
628 $ cd ..
622
629
623 Test subrepo already at intended revision:
630 Test subrepo already at intended revision:
624 $ cd s
631 $ cd s
625 $ git checkout 32a343883b74769118bb1d3b4b1fbf9156f4dddc
632 $ git checkout 32a343883b74769118bb1d3b4b1fbf9156f4dddc
626 HEAD is now at 32a3438* fff (glob)
633 HEAD is now at 32a3438* fff (glob)
627 $ cd ..
634 $ cd ..
628 $ hg update 1
635 $ hg update 1
629 Previous HEAD position was 32a3438* fff (glob)
636 Previous HEAD position was 32a3438* fff (glob)
630 HEAD is now at da5f5b1* g (glob)
637 HEAD is now at da5f5b1* g (glob)
631 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
638 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
632 $ hg id -n
639 $ hg id -n
633 1
640 1
634 $ cd s
641 $ cd s
635 $ git rev-parse HEAD
642 $ git rev-parse HEAD
636 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
643 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
637 $ cd ..
644 $ cd ..
638
645
639 Test forgetting files, not implemented in git subrepo, used to
646 Test forgetting files, not implemented in git subrepo, used to
640 traceback
647 traceback
641 #if no-windows
648 #if no-windows
642 $ hg forget 'notafile*'
649 $ hg forget 'notafile*'
643 notafile*: $ENOENT$
650 notafile*: $ENOENT$
644 [1]
651 [1]
645 #else
652 #else
646 error: The filename, directory name, or volume label syntax is incorrect
653 error: The filename, directory name, or volume label syntax is incorrect
647 $ hg forget 'notafile'
654 $ hg forget 'notafile'
648 notafile: * (glob)
655 notafile: * (glob)
649 [1]
656 [1]
650 #endif
657 #endif
651
658
652 $ cd ..
659 $ cd ..
653
660
654 Test sanitizing ".hg/hgrc" in subrepo
661 Test sanitizing ".hg/hgrc" in subrepo
655
662
656 $ cd t
663 $ cd t
657 $ hg tip -q
664 $ hg tip -q
658 7:af6d2edbb0d3
665 7:af6d2edbb0d3
659 $ hg update -q -C af6d2edbb0d3
666 $ hg update -q -C af6d2edbb0d3
660 $ cd s
667 $ cd s
661 $ git checkout -q -b sanitize-test
668 $ git checkout -q -b sanitize-test
662 $ mkdir .hg
669 $ mkdir .hg
663 $ echo '.hg/hgrc in git repo' > .hg/hgrc
670 $ echo '.hg/hgrc in git repo' > .hg/hgrc
664 $ mkdir -p sub/.hg
671 $ mkdir -p sub/.hg
665 $ echo 'sub/.hg/hgrc in git repo' > sub/.hg/hgrc
672 $ echo 'sub/.hg/hgrc in git repo' > sub/.hg/hgrc
666 $ git add .hg sub
673 $ git add .hg sub
667 $ git commit -qm 'add .hg/hgrc to be sanitized at hg update'
674 $ git commit -qm 'add .hg/hgrc to be sanitized at hg update'
668 $ git push -q origin sanitize-test
675 $ git push -q origin sanitize-test
669 $ cd ..
676 $ cd ..
670 $ grep ' s$' .hgsubstate
677 $ grep ' s$' .hgsubstate
671 32a343883b74769118bb1d3b4b1fbf9156f4dddc s
678 32a343883b74769118bb1d3b4b1fbf9156f4dddc s
672 $ hg commit -qm 'commit with git revision including .hg/hgrc'
679 $ hg commit -qm 'commit with git revision including .hg/hgrc'
673 $ hg parents -q
680 $ hg parents -q
674 8:3473d20bddcf
681 8:3473d20bddcf
675 $ grep ' s$' .hgsubstate
682 $ grep ' s$' .hgsubstate
676 c4069473b459cf27fd4d7c2f50c4346b4e936599 s
683 c4069473b459cf27fd4d7c2f50c4346b4e936599 s
677 $ cd ..
684 $ cd ..
678
685
679 $ hg -R tc pull -q
686 $ hg -R tc pull -q
680 $ hg -R tc update -q -C 3473d20bddcf 2>&1 | sort
687 $ hg -R tc update -q -C 3473d20bddcf 2>&1 | sort
681 warning: removing potentially hostile 'hgrc' in '$TESTTMP/tc/s/.hg'
688 warning: removing potentially hostile 'hgrc' in '$TESTTMP/tc/s/.hg'
682 warning: removing potentially hostile 'hgrc' in '$TESTTMP/tc/s/sub/.hg'
689 warning: removing potentially hostile 'hgrc' in '$TESTTMP/tc/s/sub/.hg'
683 $ cd tc
690 $ cd tc
684 $ hg parents -q
691 $ hg parents -q
685 8:3473d20bddcf
692 8:3473d20bddcf
686 $ grep ' s$' .hgsubstate
693 $ grep ' s$' .hgsubstate
687 c4069473b459cf27fd4d7c2f50c4346b4e936599 s
694 c4069473b459cf27fd4d7c2f50c4346b4e936599 s
688 $ test -f s/.hg/hgrc
695 $ test -f s/.hg/hgrc
689 [1]
696 [1]
690 $ test -f s/sub/.hg/hgrc
697 $ test -f s/sub/.hg/hgrc
691 [1]
698 [1]
692 $ cd ..
699 $ cd ..
693
700
694 additional test for "git merge --ff" route:
701 additional test for "git merge --ff" route:
695
702
696 $ cd t
703 $ cd t
697 $ hg tip -q
704 $ hg tip -q
698 8:3473d20bddcf
705 8:3473d20bddcf
699 $ hg update -q -C af6d2edbb0d3
706 $ hg update -q -C af6d2edbb0d3
700 $ cd s
707 $ cd s
701 $ git checkout -q testing
708 $ git checkout -q testing
702 $ mkdir .hg
709 $ mkdir .hg
703 $ echo '.hg/hgrc in git repo' > .hg/hgrc
710 $ echo '.hg/hgrc in git repo' > .hg/hgrc
704 $ mkdir -p sub/.hg
711 $ mkdir -p sub/.hg
705 $ echo 'sub/.hg/hgrc in git repo' > sub/.hg/hgrc
712 $ echo 'sub/.hg/hgrc in git repo' > sub/.hg/hgrc
706 $ git add .hg sub
713 $ git add .hg sub
707 $ git commit -qm 'add .hg/hgrc to be sanitized at hg update (git merge --ff)'
714 $ git commit -qm 'add .hg/hgrc to be sanitized at hg update (git merge --ff)'
708 $ git push -q origin testing
715 $ git push -q origin testing
709 $ cd ..
716 $ cd ..
710 $ grep ' s$' .hgsubstate
717 $ grep ' s$' .hgsubstate
711 32a343883b74769118bb1d3b4b1fbf9156f4dddc s
718 32a343883b74769118bb1d3b4b1fbf9156f4dddc s
712 $ hg commit -qm 'commit with git revision including .hg/hgrc'
719 $ hg commit -qm 'commit with git revision including .hg/hgrc'
713 $ hg parents -q
720 $ hg parents -q
714 9:ed23f7fe024e
721 9:ed23f7fe024e
715 $ grep ' s$' .hgsubstate
722 $ grep ' s$' .hgsubstate
716 f262643c1077219fbd3858d54e78ef050ef84fbf s
723 f262643c1077219fbd3858d54e78ef050ef84fbf s
717 $ cd ..
724 $ cd ..
718
725
719 $ cd tc
726 $ cd tc
720 $ hg update -q -C af6d2edbb0d3
727 $ hg update -q -C af6d2edbb0d3
721 $ test -f s/.hg/hgrc
728 $ test -f s/.hg/hgrc
722 [1]
729 [1]
723 $ test -f s/sub/.hg/hgrc
730 $ test -f s/sub/.hg/hgrc
724 [1]
731 [1]
725 $ cd ..
732 $ cd ..
726 $ hg -R tc pull -q
733 $ hg -R tc pull -q
727 $ hg -R tc update -q -C ed23f7fe024e 2>&1 | sort
734 $ hg -R tc update -q -C ed23f7fe024e 2>&1 | sort
728 warning: removing potentially hostile 'hgrc' in '$TESTTMP/tc/s/.hg'
735 warning: removing potentially hostile 'hgrc' in '$TESTTMP/tc/s/.hg'
729 warning: removing potentially hostile 'hgrc' in '$TESTTMP/tc/s/sub/.hg'
736 warning: removing potentially hostile 'hgrc' in '$TESTTMP/tc/s/sub/.hg'
730 $ cd tc
737 $ cd tc
731 $ hg parents -q
738 $ hg parents -q
732 9:ed23f7fe024e
739 9:ed23f7fe024e
733 $ grep ' s$' .hgsubstate
740 $ grep ' s$' .hgsubstate
734 f262643c1077219fbd3858d54e78ef050ef84fbf s
741 f262643c1077219fbd3858d54e78ef050ef84fbf s
735 $ test -f s/.hg/hgrc
742 $ test -f s/.hg/hgrc
736 [1]
743 [1]
737 $ test -f s/sub/.hg/hgrc
744 $ test -f s/sub/.hg/hgrc
738 [1]
745 [1]
739
746
740 Test that sanitizing is omitted in meta data area:
747 Test that sanitizing is omitted in meta data area:
741
748
742 $ mkdir s/.git/.hg
749 $ mkdir s/.git/.hg
743 $ echo '.hg/hgrc in git metadata area' > s/.git/.hg/hgrc
750 $ echo '.hg/hgrc in git metadata area' > s/.git/.hg/hgrc
744 $ hg update -q -C af6d2edbb0d3
751 $ hg update -q -C af6d2edbb0d3
745 checking out detached HEAD in subrepository "s"
752 checking out detached HEAD in subrepository "s"
746 check out a git branch if you intend to make changes
753 check out a git branch if you intend to make changes
747
754
748 check differences made by most recent change
755 check differences made by most recent change
749 $ cd s
756 $ cd s
750 $ cat > foobar << EOF
757 $ cat > foobar << EOF
751 > woopwoop
758 > woopwoop
752 >
759 >
753 > foo
760 > foo
754 > bar
761 > bar
755 > EOF
762 > EOF
756 $ git add foobar
763 $ git add foobar
757 $ cd ..
764 $ cd ..
758
765
759 $ hg diff --subrepos
766 $ hg diff --subrepos
760 diff --git a/s/foobar b/s/foobar
767 diff --git a/s/foobar b/s/foobar
761 new file mode 100644
768 new file mode 100644
762 index 0000000..8a5a5e2
769 index 0000000..8a5a5e2
763 --- /dev/null
770 --- /dev/null
764 +++ b/s/foobar
771 +++ b/s/foobar
765 @@ -0,0 +1,4 @@
772 @@ -0,0 +1,4 @@
766 +woopwoop
773 +woopwoop
767 +
774 +
768 +foo
775 +foo
769 +bar
776 +bar
770
777
771 $ hg commit --subrepos -m "Added foobar"
778 $ hg commit --subrepos -m "Added foobar"
772 committing subrepository s
779 committing subrepository s
773 created new head
780 created new head
774
781
775 $ hg diff -c . --subrepos --nodates
782 $ hg diff -c . --subrepos --nodates
776 diff -r af6d2edbb0d3 -r 255ee8cf690e .hgsubstate
783 diff -r af6d2edbb0d3 -r 255ee8cf690e .hgsubstate
777 --- a/.hgsubstate
784 --- a/.hgsubstate
778 +++ b/.hgsubstate
785 +++ b/.hgsubstate
779 @@ -1,1 +1,1 @@
786 @@ -1,1 +1,1 @@
780 -32a343883b74769118bb1d3b4b1fbf9156f4dddc s
787 -32a343883b74769118bb1d3b4b1fbf9156f4dddc s
781 +fd4dbf828a5b2fcd36b2bcf21ea773820970d129 s
788 +fd4dbf828a5b2fcd36b2bcf21ea773820970d129 s
782 diff --git a/s/foobar b/s/foobar
789 diff --git a/s/foobar b/s/foobar
783 new file mode 100644
790 new file mode 100644
784 index 0000000..8a5a5e2
791 index 0000000..8a5a5e2
785 --- /dev/null
792 --- /dev/null
786 +++ b/s/foobar
793 +++ b/s/foobar
787 @@ -0,0 +1,4 @@
794 @@ -0,0 +1,4 @@
788 +woopwoop
795 +woopwoop
789 +
796 +
790 +foo
797 +foo
791 +bar
798 +bar
792
799
793 check output when only diffing the subrepository
800 check output when only diffing the subrepository
794 $ hg diff -c . --subrepos s
801 $ hg diff -c . --subrepos s
795 diff --git a/s/foobar b/s/foobar
802 diff --git a/s/foobar b/s/foobar
796 new file mode 100644
803 new file mode 100644
797 index 0000000..8a5a5e2
804 index 0000000..8a5a5e2
798 --- /dev/null
805 --- /dev/null
799 +++ b/s/foobar
806 +++ b/s/foobar
800 @@ -0,0 +1,4 @@
807 @@ -0,0 +1,4 @@
801 +woopwoop
808 +woopwoop
802 +
809 +
803 +foo
810 +foo
804 +bar
811 +bar
805
812
806 check output when diffing something else
813 check output when diffing something else
807 $ hg diff -c . --subrepos .hgsubstate --nodates
814 $ hg diff -c . --subrepos .hgsubstate --nodates
808 diff -r af6d2edbb0d3 -r 255ee8cf690e .hgsubstate
815 diff -r af6d2edbb0d3 -r 255ee8cf690e .hgsubstate
809 --- a/.hgsubstate
816 --- a/.hgsubstate
810 +++ b/.hgsubstate
817 +++ b/.hgsubstate
811 @@ -1,1 +1,1 @@
818 @@ -1,1 +1,1 @@
812 -32a343883b74769118bb1d3b4b1fbf9156f4dddc s
819 -32a343883b74769118bb1d3b4b1fbf9156f4dddc s
813 +fd4dbf828a5b2fcd36b2bcf21ea773820970d129 s
820 +fd4dbf828a5b2fcd36b2bcf21ea773820970d129 s
814
821
815 add new changes, including whitespace
822 add new changes, including whitespace
816 $ cd s
823 $ cd s
817 $ cat > foobar << EOF
824 $ cat > foobar << EOF
818 > woop woop
825 > woop woop
819 >
826 >
820 > foo
827 > foo
821 > bar
828 > bar
822 > EOF
829 > EOF
823 $ echo foo > barfoo
830 $ echo foo > barfoo
824 $ git add barfoo
831 $ git add barfoo
825 $ cd ..
832 $ cd ..
826
833
827 $ hg diff --subrepos --ignore-all-space
834 $ hg diff --subrepos --ignore-all-space
828 diff --git a/s/barfoo b/s/barfoo
835 diff --git a/s/barfoo b/s/barfoo
829 new file mode 100644
836 new file mode 100644
830 index 0000000..257cc56
837 index 0000000..257cc56
831 --- /dev/null
838 --- /dev/null
832 +++ b/s/barfoo
839 +++ b/s/barfoo
833 @@ -0,0 +1* @@ (glob)
840 @@ -0,0 +1* @@ (glob)
834 +foo
841 +foo
835 $ hg diff --subrepos s/foobar
842 $ hg diff --subrepos s/foobar
836 diff --git a/s/foobar b/s/foobar
843 diff --git a/s/foobar b/s/foobar
837 index 8a5a5e2..bd5812a 100644
844 index 8a5a5e2..bd5812a 100644
838 --- a/s/foobar
845 --- a/s/foobar
839 +++ b/s/foobar
846 +++ b/s/foobar
840 @@ -1,4 +1,4 @@
847 @@ -1,4 +1,4 @@
841 -woopwoop
848 -woopwoop
842 +woop woop
849 +woop woop
843
850
844 foo
851 foo
845 bar
852 bar
846
853
847 execute a diffstat
854 execute a diffstat
848 the output contains a regex, because git 1.7.10 and 1.7.11
855 the output contains a regex, because git 1.7.10 and 1.7.11
849 change the amount of whitespace
856 change the amount of whitespace
850 $ hg diff --subrepos --stat
857 $ hg diff --subrepos --stat
851 \s*barfoo \|\s+1 \+ (re)
858 \s*barfoo \|\s+1 \+ (re)
852 \s*foobar \|\s+2 \+- (re)
859 \s*foobar \|\s+2 \+- (re)
853 2 files changed, 2 insertions\(\+\), 1 deletions?\(-\) (re)
860 2 files changed, 2 insertions\(\+\), 1 deletions?\(-\) (re)
854
861
855 adding an include should ignore the other elements
862 adding an include should ignore the other elements
856 $ hg diff --subrepos -I s/foobar
863 $ hg diff --subrepos -I s/foobar
857 diff --git a/s/foobar b/s/foobar
864 diff --git a/s/foobar b/s/foobar
858 index 8a5a5e2..bd5812a 100644
865 index 8a5a5e2..bd5812a 100644
859 --- a/s/foobar
866 --- a/s/foobar
860 +++ b/s/foobar
867 +++ b/s/foobar
861 @@ -1,4 +1,4 @@
868 @@ -1,4 +1,4 @@
862 -woopwoop
869 -woopwoop
863 +woop woop
870 +woop woop
864
871
865 foo
872 foo
866 bar
873 bar
867
874
868 adding an exclude should ignore this element
875 adding an exclude should ignore this element
869 $ hg diff --subrepos -X s/foobar
876 $ hg diff --subrepos -X s/foobar
870 diff --git a/s/barfoo b/s/barfoo
877 diff --git a/s/barfoo b/s/barfoo
871 new file mode 100644
878 new file mode 100644
872 index 0000000..257cc56
879 index 0000000..257cc56
873 --- /dev/null
880 --- /dev/null
874 +++ b/s/barfoo
881 +++ b/s/barfoo
875 @@ -0,0 +1* @@ (glob)
882 @@ -0,0 +1* @@ (glob)
876 +foo
883 +foo
877
884
878 moving a file should show a removal and an add
885 moving a file should show a removal and an add
879 $ hg revert --all
886 $ hg revert --all
880 reverting subrepo ../gitroot
887 reverting subrepo ../gitroot
881 $ cd s
888 $ cd s
882 $ git mv foobar woop
889 $ git mv foobar woop
883 $ cd ..
890 $ cd ..
884 $ hg diff --subrepos
891 $ hg diff --subrepos
885 diff --git a/s/foobar b/s/foobar
892 diff --git a/s/foobar b/s/foobar
886 deleted file mode 100644
893 deleted file mode 100644
887 index 8a5a5e2..0000000
894 index 8a5a5e2..0000000
888 --- a/s/foobar
895 --- a/s/foobar
889 +++ /dev/null
896 +++ /dev/null
890 @@ -1,4 +0,0 @@
897 @@ -1,4 +0,0 @@
891 -woopwoop
898 -woopwoop
892 -
899 -
893 -foo
900 -foo
894 -bar
901 -bar
895 diff --git a/s/woop b/s/woop
902 diff --git a/s/woop b/s/woop
896 new file mode 100644
903 new file mode 100644
897 index 0000000..8a5a5e2
904 index 0000000..8a5a5e2
898 --- /dev/null
905 --- /dev/null
899 +++ b/s/woop
906 +++ b/s/woop
900 @@ -0,0 +1,4 @@
907 @@ -0,0 +1,4 @@
901 +woopwoop
908 +woopwoop
902 +
909 +
903 +foo
910 +foo
904 +bar
911 +bar
905 $ rm s/woop
912 $ rm s/woop
906
913
907 revert the subrepository
914 revert the subrepository
908 $ hg revert --all
915 $ hg revert --all
909 reverting subrepo ../gitroot
916 reverting subrepo ../gitroot
910
917
911 $ hg status --subrepos
918 $ hg status --subrepos
912 ? s/barfoo
919 ? s/barfoo
913 ? s/foobar.orig
920 ? s/foobar.orig
914
921
915 $ mv s/foobar.orig s/foobar
922 $ mv s/foobar.orig s/foobar
916
923
917 $ hg revert --no-backup s
924 $ hg revert --no-backup s
918 reverting subrepo ../gitroot
925 reverting subrepo ../gitroot
919
926
920 $ hg status --subrepos
927 $ hg status --subrepos
921 ? s/barfoo
928 ? s/barfoo
922
929
923 revert moves orig files to the right place
930 revert moves orig files to the right place
924 $ echo 'bloop' > s/foobar
931 $ echo 'bloop' > s/foobar
925 $ hg revert --all --verbose --config 'ui.origbackuppath=.hg/origbackups'
932 $ hg revert --all --verbose --config 'ui.origbackuppath=.hg/origbackups'
926 reverting subrepo ../gitroot
933 reverting subrepo ../gitroot
927 creating directory: $TESTTMP/tc/.hg/origbackups/s
934 creating directory: $TESTTMP/tc/.hg/origbackups/s
928 saving current version of foobar as .hg/origbackups/s/foobar
935 saving current version of foobar as .hg/origbackups/s/foobar
929 $ ls .hg/origbackups/s
936 $ ls .hg/origbackups/s
930 foobar
937 foobar
931 $ rm -rf .hg/origbackups
938 $ rm -rf .hg/origbackups
932
939
933 show file at specific revision
940 show file at specific revision
934 $ cat > s/foobar << EOF
941 $ cat > s/foobar << EOF
935 > woop woop
942 > woop woop
936 > fooo bar
943 > fooo bar
937 > EOF
944 > EOF
938 $ hg commit --subrepos -m "updated foobar"
945 $ hg commit --subrepos -m "updated foobar"
939 committing subrepository s
946 committing subrepository s
940 $ cat > s/foobar << EOF
947 $ cat > s/foobar << EOF
941 > current foobar
948 > current foobar
942 > (should not be visible using hg cat)
949 > (should not be visible using hg cat)
943 > EOF
950 > EOF
944
951
945 $ hg cat -r . s/foobar
952 $ hg cat -r . s/foobar
946 woop woop
953 woop woop
947 fooo bar (no-eol)
954 fooo bar (no-eol)
948 $ hg cat -r "parents(.)" s/foobar > catparents
955 $ hg cat -r "parents(.)" s/foobar > catparents
949
956
950 $ mkdir -p tmp/s
957 $ mkdir -p tmp/s
951
958
952 $ hg cat -r "parents(.)" --output tmp/%% s/foobar
959 $ hg cat -r "parents(.)" --output tmp/%% s/foobar
953 $ diff tmp/% catparents
960 $ diff tmp/% catparents
954
961
955 $ hg cat -r "parents(.)" --output tmp/%s s/foobar
962 $ hg cat -r "parents(.)" --output tmp/%s s/foobar
956 $ diff tmp/foobar catparents
963 $ diff tmp/foobar catparents
957
964
958 $ hg cat -r "parents(.)" --output tmp/%d/otherfoobar s/foobar
965 $ hg cat -r "parents(.)" --output tmp/%d/otherfoobar s/foobar
959 $ diff tmp/s/otherfoobar catparents
966 $ diff tmp/s/otherfoobar catparents
960
967
961 $ hg cat -r "parents(.)" --output tmp/%p s/foobar
968 $ hg cat -r "parents(.)" --output tmp/%p s/foobar
962 $ diff tmp/s/foobar catparents
969 $ diff tmp/s/foobar catparents
963
970
964 $ hg cat -r "parents(.)" --output tmp/%H s/foobar
971 $ hg cat -r "parents(.)" --output tmp/%H s/foobar
965 $ diff tmp/255ee8cf690ec86e99b1e80147ea93ece117cd9d catparents
972 $ diff tmp/255ee8cf690ec86e99b1e80147ea93ece117cd9d catparents
966
973
967 $ hg cat -r "parents(.)" --output tmp/%R s/foobar
974 $ hg cat -r "parents(.)" --output tmp/%R s/foobar
968 $ diff tmp/10 catparents
975 $ diff tmp/10 catparents
969
976
970 $ hg cat -r "parents(.)" --output tmp/%h s/foobar
977 $ hg cat -r "parents(.)" --output tmp/%h s/foobar
971 $ diff tmp/255ee8cf690e catparents
978 $ diff tmp/255ee8cf690e catparents
972
979
973 $ rm tmp/10
980 $ rm tmp/10
974 $ hg cat -r "parents(.)" --output tmp/%r s/foobar
981 $ hg cat -r "parents(.)" --output tmp/%r s/foobar
975 $ diff tmp/10 catparents
982 $ diff tmp/10 catparents
976
983
977 $ mkdir tmp/tc
984 $ mkdir tmp/tc
978 $ hg cat -r "parents(.)" --output tmp/%b/foobar s/foobar
985 $ hg cat -r "parents(.)" --output tmp/%b/foobar s/foobar
979 $ diff tmp/tc/foobar catparents
986 $ diff tmp/tc/foobar catparents
980
987
981 cleanup
988 cleanup
982 $ rm -r tmp
989 $ rm -r tmp
983 $ rm catparents
990 $ rm catparents
984
991
985 add git files, using either files or patterns
992 add git files, using either files or patterns
986 $ echo "hsss! hsssssssh!" > s/snake.python
993 $ echo "hsss! hsssssssh!" > s/snake.python
987 $ echo "ccc" > s/c.c
994 $ echo "ccc" > s/c.c
988 $ echo "cpp" > s/cpp.cpp
995 $ echo "cpp" > s/cpp.cpp
989
996
990 $ hg add s/snake.python s/c.c s/cpp.cpp
997 $ hg add s/snake.python s/c.c s/cpp.cpp
991 $ hg st --subrepos s
998 $ hg st --subrepos s
992 M s/foobar
999 M s/foobar
993 A s/c.c
1000 A s/c.c
994 A s/cpp.cpp
1001 A s/cpp.cpp
995 A s/snake.python
1002 A s/snake.python
996 ? s/barfoo
1003 ? s/barfoo
997 $ hg revert s
1004 $ hg revert s
998 reverting subrepo ../gitroot
1005 reverting subrepo ../gitroot
999
1006
1000 $ hg add --subrepos "glob:**.python"
1007 $ hg add --subrepos "glob:**.python"
1001 adding s/snake.python
1008 adding s/snake.python
1002 $ hg st --subrepos s
1009 $ hg st --subrepos s
1003 A s/snake.python
1010 A s/snake.python
1004 ? s/barfoo
1011 ? s/barfoo
1005 ? s/c.c
1012 ? s/c.c
1006 ? s/cpp.cpp
1013 ? s/cpp.cpp
1007 ? s/foobar.orig
1014 ? s/foobar.orig
1008 $ hg revert s
1015 $ hg revert s
1009 reverting subrepo ../gitroot
1016 reverting subrepo ../gitroot
1010
1017
1011 $ hg add --subrepos s
1018 $ hg add --subrepos s
1012 adding s/barfoo
1019 adding s/barfoo
1013 adding s/c.c
1020 adding s/c.c
1014 adding s/cpp.cpp
1021 adding s/cpp.cpp
1015 adding s/foobar.orig
1022 adding s/foobar.orig
1016 adding s/snake.python
1023 adding s/snake.python
1017 $ hg st --subrepos s
1024 $ hg st --subrepos s
1018 A s/barfoo
1025 A s/barfoo
1019 A s/c.c
1026 A s/c.c
1020 A s/cpp.cpp
1027 A s/cpp.cpp
1021 A s/foobar.orig
1028 A s/foobar.orig
1022 A s/snake.python
1029 A s/snake.python
1023 $ hg revert s
1030 $ hg revert s
1024 reverting subrepo ../gitroot
1031 reverting subrepo ../gitroot
1025 make sure everything is reverted correctly
1032 make sure everything is reverted correctly
1026 $ hg st --subrepos s
1033 $ hg st --subrepos s
1027 ? s/barfoo
1034 ? s/barfoo
1028 ? s/c.c
1035 ? s/c.c
1029 ? s/cpp.cpp
1036 ? s/cpp.cpp
1030 ? s/foobar.orig
1037 ? s/foobar.orig
1031 ? s/snake.python
1038 ? s/snake.python
1032
1039
1033 $ hg add --subrepos --exclude "path:s/c.c"
1040 $ hg add --subrepos --exclude "path:s/c.c"
1034 adding s/barfoo
1041 adding s/barfoo
1035 adding s/cpp.cpp
1042 adding s/cpp.cpp
1036 adding s/foobar.orig
1043 adding s/foobar.orig
1037 adding s/snake.python
1044 adding s/snake.python
1038 $ hg st --subrepos s
1045 $ hg st --subrepos s
1039 A s/barfoo
1046 A s/barfoo
1040 A s/cpp.cpp
1047 A s/cpp.cpp
1041 A s/foobar.orig
1048 A s/foobar.orig
1042 A s/snake.python
1049 A s/snake.python
1043 ? s/c.c
1050 ? s/c.c
1044 $ hg revert --all -q
1051 $ hg revert --all -q
1045
1052
1046 .hgignore should not have influence in subrepos
1053 .hgignore should not have influence in subrepos
1047 $ cat > .hgignore << EOF
1054 $ cat > .hgignore << EOF
1048 > syntax: glob
1055 > syntax: glob
1049 > *.python
1056 > *.python
1050 > EOF
1057 > EOF
1051 $ hg add .hgignore
1058 $ hg add .hgignore
1052 $ hg add --subrepos "glob:**.python" s/barfoo
1059 $ hg add --subrepos "glob:**.python" s/barfoo
1053 adding s/snake.python
1060 adding s/snake.python
1054 $ hg st --subrepos s
1061 $ hg st --subrepos s
1055 A s/barfoo
1062 A s/barfoo
1056 A s/snake.python
1063 A s/snake.python
1057 ? s/c.c
1064 ? s/c.c
1058 ? s/cpp.cpp
1065 ? s/cpp.cpp
1059 ? s/foobar.orig
1066 ? s/foobar.orig
1060 $ hg revert --all -q
1067 $ hg revert --all -q
1061
1068
1062 .gitignore should have influence,
1069 .gitignore should have influence,
1063 except for explicitly added files (no patterns)
1070 except for explicitly added files (no patterns)
1064 $ cat > s/.gitignore << EOF
1071 $ cat > s/.gitignore << EOF
1065 > *.python
1072 > *.python
1066 > EOF
1073 > EOF
1067 $ hg add s/.gitignore
1074 $ hg add s/.gitignore
1068 $ hg st --subrepos s
1075 $ hg st --subrepos s
1069 A s/.gitignore
1076 A s/.gitignore
1070 ? s/barfoo
1077 ? s/barfoo
1071 ? s/c.c
1078 ? s/c.c
1072 ? s/cpp.cpp
1079 ? s/cpp.cpp
1073 ? s/foobar.orig
1080 ? s/foobar.orig
1074 $ hg st --subrepos s --all
1081 $ hg st --subrepos s --all
1075 A s/.gitignore
1082 A s/.gitignore
1076 ? s/barfoo
1083 ? s/barfoo
1077 ? s/c.c
1084 ? s/c.c
1078 ? s/cpp.cpp
1085 ? s/cpp.cpp
1079 ? s/foobar.orig
1086 ? s/foobar.orig
1080 I s/snake.python
1087 I s/snake.python
1081 C s/f
1088 C s/f
1082 C s/foobar
1089 C s/foobar
1083 C s/g
1090 C s/g
1084 $ hg add --subrepos "glob:**.python"
1091 $ hg add --subrepos "glob:**.python"
1085 $ hg st --subrepos s
1092 $ hg st --subrepos s
1086 A s/.gitignore
1093 A s/.gitignore
1087 ? s/barfoo
1094 ? s/barfoo
1088 ? s/c.c
1095 ? s/c.c
1089 ? s/cpp.cpp
1096 ? s/cpp.cpp
1090 ? s/foobar.orig
1097 ? s/foobar.orig
1091 $ hg add --subrepos s/snake.python
1098 $ hg add --subrepos s/snake.python
1092 $ hg st --subrepos s
1099 $ hg st --subrepos s
1093 A s/.gitignore
1100 A s/.gitignore
1094 A s/snake.python
1101 A s/snake.python
1095 ? s/barfoo
1102 ? s/barfoo
1096 ? s/c.c
1103 ? s/c.c
1097 ? s/cpp.cpp
1104 ? s/cpp.cpp
1098 ? s/foobar.orig
1105 ? s/foobar.orig
1099
1106
1100 correctly do a dry run
1107 correctly do a dry run
1101 $ hg add --subrepos s --dry-run
1108 $ hg add --subrepos s --dry-run
1102 adding s/barfoo
1109 adding s/barfoo
1103 adding s/c.c
1110 adding s/c.c
1104 adding s/cpp.cpp
1111 adding s/cpp.cpp
1105 adding s/foobar.orig
1112 adding s/foobar.orig
1106 $ hg st --subrepos s
1113 $ hg st --subrepos s
1107 A s/.gitignore
1114 A s/.gitignore
1108 A s/snake.python
1115 A s/snake.python
1109 ? s/barfoo
1116 ? s/barfoo
1110 ? s/c.c
1117 ? s/c.c
1111 ? s/cpp.cpp
1118 ? s/cpp.cpp
1112 ? s/foobar.orig
1119 ? s/foobar.orig
1113
1120
1114 error given when adding an already tracked file
1121 error given when adding an already tracked file
1115 $ hg add s/.gitignore
1122 $ hg add s/.gitignore
1116 s/.gitignore already tracked!
1123 s/.gitignore already tracked!
1117 [1]
1124 [1]
1118 $ hg add s/g
1125 $ hg add s/g
1119 s/g already tracked!
1126 s/g already tracked!
1120 [1]
1127 [1]
1121
1128
1122 removed files can be re-added
1129 removed files can be re-added
1123 removing files using 'rm' or 'git rm' has the same effect,
1130 removing files using 'rm' or 'git rm' has the same effect,
1124 since we ignore the staging area
1131 since we ignore the staging area
1125 $ hg ci --subrepos -m 'snake'
1132 $ hg ci --subrepos -m 'snake'
1126 committing subrepository s
1133 committing subrepository s
1127 $ cd s
1134 $ cd s
1128 $ rm snake.python
1135 $ rm snake.python
1129 (remove leftover .hg so Mercurial doesn't look for a root here)
1136 (remove leftover .hg so Mercurial doesn't look for a root here)
1130 $ rm -rf .hg
1137 $ rm -rf .hg
1131 $ hg status --subrepos --all .
1138 $ hg status --subrepos --all .
1132 R snake.python
1139 R snake.python
1133 ? barfoo
1140 ? barfoo
1134 ? c.c
1141 ? c.c
1135 ? cpp.cpp
1142 ? cpp.cpp
1136 ? foobar.orig
1143 ? foobar.orig
1137 C .gitignore
1144 C .gitignore
1138 C f
1145 C f
1139 C foobar
1146 C foobar
1140 C g
1147 C g
1141 $ git rm snake.python
1148 $ git rm snake.python
1142 rm 'snake.python'
1149 rm 'snake.python'
1143 $ hg status --subrepos --all .
1150 $ hg status --subrepos --all .
1144 R snake.python
1151 R snake.python
1145 ? barfoo
1152 ? barfoo
1146 ? c.c
1153 ? c.c
1147 ? cpp.cpp
1154 ? cpp.cpp
1148 ? foobar.orig
1155 ? foobar.orig
1149 C .gitignore
1156 C .gitignore
1150 C f
1157 C f
1151 C foobar
1158 C foobar
1152 C g
1159 C g
1153 $ touch snake.python
1160 $ touch snake.python
1154 $ cd ..
1161 $ cd ..
1155 $ hg add s/snake.python
1162 $ hg add s/snake.python
1156 $ hg status -S
1163 $ hg status -S
1157 M s/snake.python
1164 M s/snake.python
1158 ? .hgignore
1165 ? .hgignore
1159 ? s/barfoo
1166 ? s/barfoo
1160 ? s/c.c
1167 ? s/c.c
1161 ? s/cpp.cpp
1168 ? s/cpp.cpp
1162 ? s/foobar.orig
1169 ? s/foobar.orig
1163 $ hg revert --all -q
1170 $ hg revert --all -q
1164
1171
1165 make sure we show changed files, rather than changed subtrees
1172 make sure we show changed files, rather than changed subtrees
1166 $ mkdir s/foo
1173 $ mkdir s/foo
1167 $ touch s/foo/bwuh
1174 $ touch s/foo/bwuh
1168 $ hg add s/foo/bwuh
1175 $ hg add s/foo/bwuh
1169 $ hg commit -S -m "add bwuh"
1176 $ hg commit -S -m "add bwuh"
1170 committing subrepository s
1177 committing subrepository s
1171 $ hg status -S --change .
1178 $ hg status -S --change .
1172 M .hgsubstate
1179 M .hgsubstate
1173 A s/foo/bwuh
1180 A s/foo/bwuh
1174 ? s/barfoo
1181 ? s/barfoo
1175 ? s/c.c
1182 ? s/c.c
1176 ? s/cpp.cpp
1183 ? s/cpp.cpp
1177 ? s/foobar.orig
1184 ? s/foobar.orig
1178 ? s/snake.python.orig
1185 ? s/snake.python.orig
1179
1186
1180 #if git19
1187 #if git19
1181
1188
1182 test for Git CVE-2016-3068
1189 test for Git CVE-2016-3068
1183 $ hg init malicious-subrepository
1190 $ hg init malicious-subrepository
1184 $ cd malicious-subrepository
1191 $ cd malicious-subrepository
1185 $ echo "s = [git]ext::sh -c echo% pwned:% \$PWNED_MSG% >pwned.txt" > .hgsub
1192 $ echo "s = [git]ext::sh -c echo% pwned:% \$PWNED_MSG% >pwned.txt" > .hgsub
1186 $ git init s
1193 $ git init s
1187 Initialized empty Git repository in $TESTTMP/tc/malicious-subrepository/s/.git/
1194 Initialized empty Git repository in $TESTTMP/tc/malicious-subrepository/s/.git/
1188 $ cd s
1195 $ cd s
1189 $ git commit --allow-empty -m 'empty'
1196 $ git commit --allow-empty -m 'empty'
1190 [master (root-commit) 153f934] empty
1197 [master (root-commit) 153f934] empty
1191 $ cd ..
1198 $ cd ..
1192 $ hg add .hgsub
1199 $ hg add .hgsub
1193 $ hg commit -m "add subrepo"
1200 $ hg commit -m "add subrepo"
1194 $ cd ..
1201 $ cd ..
1195 $ rm -f pwned.txt
1202 $ rm -f pwned.txt
1196 $ unset GIT_ALLOW_PROTOCOL
1203 $ unset GIT_ALLOW_PROTOCOL
1197 $ PWNED_MSG="your git is too old or mercurial has regressed" hg clone \
1204 $ PWNED_MSG="your git is too old or mercurial has regressed" hg clone \
1198 > malicious-subrepository malicious-subrepository-protected
1205 > malicious-subrepository malicious-subrepository-protected
1199 Cloning into '$TESTTMP/tc/malicious-subrepository-protected/s'...
1206 Cloning into '$TESTTMP/tc/malicious-subrepository-protected/s'...
1200 fatal: transport 'ext' not allowed
1207 fatal: transport 'ext' not allowed
1201 updating to branch default
1208 updating to branch default
1202 cloning subrepo s from ext::sh -c echo% pwned:% $PWNED_MSG% >pwned.txt
1209 cloning subrepo s from ext::sh -c echo% pwned:% $PWNED_MSG% >pwned.txt
1203 abort: git clone error 128 in s (in subrepository "s")
1210 abort: git clone error 128 in s (in subrepository "s")
1204 [255]
1211 [255]
1205 $ f -Dq pwned.txt
1212 $ f -Dq pwned.txt
1206 pwned.txt: file not found
1213 pwned.txt: file not found
1207
1214
1208 whitelisting of ext should be respected (that's the git submodule behaviour)
1215 whitelisting of ext should be respected (that's the git submodule behaviour)
1209 $ rm -f pwned.txt
1216 $ rm -f pwned.txt
1210 $ env GIT_ALLOW_PROTOCOL=ext PWNED_MSG="you asked for it" hg clone \
1217 $ env GIT_ALLOW_PROTOCOL=ext PWNED_MSG="you asked for it" hg clone \
1211 > malicious-subrepository malicious-subrepository-clone-allowed
1218 > malicious-subrepository malicious-subrepository-clone-allowed
1212 Cloning into '$TESTTMP/tc/malicious-subrepository-clone-allowed/s'...
1219 Cloning into '$TESTTMP/tc/malicious-subrepository-clone-allowed/s'...
1213 fatal: Could not read from remote repository.
1220 fatal: Could not read from remote repository.
1214
1221
1215 Please make sure you have the correct access rights
1222 Please make sure you have the correct access rights
1216 and the repository exists.
1223 and the repository exists.
1217 updating to branch default
1224 updating to branch default
1218 cloning subrepo s from ext::sh -c echo% pwned:% $PWNED_MSG% >pwned.txt
1225 cloning subrepo s from ext::sh -c echo% pwned:% $PWNED_MSG% >pwned.txt
1219 abort: git clone error 128 in s (in subrepository "s")
1226 abort: git clone error 128 in s (in subrepository "s")
1220 [255]
1227 [255]
1221 $ f -Dq pwned.txt
1228 $ f -Dq pwned.txt
1222 pwned: you asked for it
1229 pwned: you asked for it
1223
1230
1224 #endif
1231 #endif
1225
1232
1226 test for ssh exploit with git subrepos 2017-07-25
1233 test for ssh exploit with git subrepos 2017-07-25
1227
1234
1228 $ hg init malicious-proxycommand
1235 $ hg init malicious-proxycommand
1229 $ cd malicious-proxycommand
1236 $ cd malicious-proxycommand
1230 $ echo 's = [git]ssh://-oProxyCommand=rm${IFS}non-existent/path' > .hgsub
1237 $ echo 's = [git]ssh://-oProxyCommand=rm${IFS}non-existent/path' > .hgsub
1231 $ git init s
1238 $ git init s
1232 Initialized empty Git repository in $TESTTMP/tc/malicious-proxycommand/s/.git/
1239 Initialized empty Git repository in $TESTTMP/tc/malicious-proxycommand/s/.git/
1233 $ cd s
1240 $ cd s
1234 $ git commit --allow-empty -m 'empty'
1241 $ git commit --allow-empty -m 'empty'
1235 [master (root-commit) 153f934] empty
1242 [master (root-commit) 153f934] empty
1236 $ cd ..
1243 $ cd ..
1237 $ hg add .hgsub
1244 $ hg add .hgsub
1238 $ hg ci -m 'add subrepo'
1245 $ hg ci -m 'add subrepo'
1239 $ cd ..
1246 $ cd ..
1240 $ hg clone malicious-proxycommand malicious-proxycommand-clone
1247 $ hg clone malicious-proxycommand malicious-proxycommand-clone
1241 updating to branch default
1248 updating to branch default
1242 abort: potentially unsafe url: 'ssh://-oProxyCommand=rm${IFS}non-existent/path' (in subrepository "s")
1249 abort: potentially unsafe url: 'ssh://-oProxyCommand=rm${IFS}non-existent/path' (in subrepository "s")
1243 [255]
1250 [255]
1244
1251
1245 also check that a percent encoded '-' (%2D) doesn't work
1252 also check that a percent encoded '-' (%2D) doesn't work
1246
1253
1247 $ cd malicious-proxycommand
1254 $ cd malicious-proxycommand
1248 $ echo 's = [git]ssh://%2DoProxyCommand=rm${IFS}non-existent/path' > .hgsub
1255 $ echo 's = [git]ssh://%2DoProxyCommand=rm${IFS}non-existent/path' > .hgsub
1249 $ hg ci -m 'change url to percent encoded'
1256 $ hg ci -m 'change url to percent encoded'
1250 $ cd ..
1257 $ cd ..
1251 $ rm -r malicious-proxycommand-clone
1258 $ rm -r malicious-proxycommand-clone
1252 $ hg clone malicious-proxycommand malicious-proxycommand-clone
1259 $ hg clone malicious-proxycommand malicious-proxycommand-clone
1253 updating to branch default
1260 updating to branch default
1254 abort: potentially unsafe url: 'ssh://-oProxyCommand=rm${IFS}non-existent/path' (in subrepository "s")
1261 abort: potentially unsafe url: 'ssh://-oProxyCommand=rm${IFS}non-existent/path' (in subrepository "s")
1255 [255]
1262 [255]
@@ -1,686 +1,693 b''
1 #require svn15
1 #require svn15
2
2
3 $ SVNREPOPATH=`pwd`/svn-repo
3 $ SVNREPOPATH=`pwd`/svn-repo
4 $ SVNREPOURL="`"$PYTHON" $TESTDIR/svnurlof.py \"$SVNREPOPATH\"`"
4 $ SVNREPOURL="`"$PYTHON" $TESTDIR/svnurlof.py \"$SVNREPOPATH\"`"
5
5
6 $ filter_svn_output () {
6 $ filter_svn_output () {
7 > egrep -v 'Committing|Transmitting|Updating|(^$)' || true
7 > egrep -v 'Committing|Transmitting|Updating|(^$)' || true
8 > }
8 > }
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
21 A src/alpha
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
26 A externals/other
27 $ svn ci -qm 'Add alpha'
27 $ svn ci -qm 'Add alpha'
28 $ svn up -q
28 $ svn up -q
29 $ echo "externals -r1 $SVNREPOURL/externals" > extdef
29 $ echo "externals -r1 $SVNREPOURL/externals" > extdef
30 $ svn propset -F extdef svn:externals src
30 $ svn propset -F extdef svn:externals src
31 property 'svn:externals' set on 'src'
31 property 'svn:externals' set on 'src'
32 $ svn ci -qm 'Setting externals'
32 $ svn ci -qm 'Setting externals'
33 $ cd ..
33 $ cd ..
34
34
35 create hg repo
35 create hg repo
36
36
37 $ mkdir sub
37 $ mkdir sub
38 $ cd sub
38 $ cd sub
39 $ hg init t
39 $ hg init t
40 $ cd t
40 $ cd t
41
41
42 first revision, no sub
42 first revision, no sub
43
43
44 $ echo a > a
44 $ echo a > a
45 $ hg ci -Am0
45 $ hg ci -Am0
46 adding a
46 adding a
47
47
48 add first svn sub with leading whitespaces
48 add first svn sub with leading whitespaces
49
49
50 $ echo "s = [svn] $SVNREPOURL/src" >> .hgsub
50 $ echo "s = [svn] $SVNREPOURL/src" >> .hgsub
51 $ echo "subdir/s = [svn] $SVNREPOURL/src" >> .hgsub
51 $ echo "subdir/s = [svn] $SVNREPOURL/src" >> .hgsub
52 $ svn co --quiet "$SVNREPOURL"/src s
52 $ svn co --quiet "$SVNREPOURL"/src s
53 $ mkdir subdir
53 $ mkdir subdir
54 $ svn co --quiet "$SVNREPOURL"/src subdir/s
54 $ svn co --quiet "$SVNREPOURL"/src subdir/s
55 $ hg add .hgsub
55 $ hg add .hgsub
56
56
57 svn subrepo is disabled by default
57 svn subrepo is disabled by default
58
58
59 $ hg ci -m1
59 $ hg ci -m1
60 abort: svn subrepos not allowed
60 abort: svn subrepos not allowed
61 (see 'hg help config.subrepos' for details)
61 (see 'hg help config.subrepos' for details)
62 [255]
62 [255]
63
63
64 so enable it
64 so enable it
65
65
66 $ cat >> $HGRCPATH <<EOF
66 $ cat >> $HGRCPATH <<EOF
67 > [subrepos]
67 > [subrepos]
68 > svn:allowed = true
68 > svn:allowed = true
69 > EOF
69 > EOF
70
70
71 $ hg ci -m1
71 $ hg ci -m1
72
72
73 make sure we avoid empty commits (issue2445)
73 make sure we avoid empty commits (issue2445)
74
74
75 $ hg sum
75 $ hg sum
76 parent: 1:* tip (glob)
76 parent: 1:* tip (glob)
77 1
77 1
78 branch: default
78 branch: default
79 commit: (clean)
79 commit: (clean)
80 update: (current)
80 update: (current)
81 phases: 2 draft
81 phases: 2 draft
82 $ hg ci -moops
82 $ hg ci -moops
83 nothing changed
83 nothing changed
84 [1]
84 [1]
85
85
86 debugsub
86 debugsub
87
87
88 $ hg debugsub
88 $ hg debugsub
89 path s
89 path s
90 source file:/*/$TESTTMP/svn-repo/src (glob)
90 source file:/*/$TESTTMP/svn-repo/src (glob)
91 revision 2
91 revision 2
92 path subdir/s
92 path subdir/s
93 source file:/*/$TESTTMP/svn-repo/src (glob)
93 source file:/*/$TESTTMP/svn-repo/src (glob)
94 revision 2
94 revision 2
95
95
96 change file in svn and hg, commit
96 change file in svn and hg, commit
97
97
98 $ echo a >> a
98 $ echo a >> a
99 $ echo alpha >> s/alpha
99 $ echo alpha >> s/alpha
100 $ hg sum
100 $ hg sum
101 parent: 1:* tip (glob)
101 parent: 1:* tip (glob)
102 1
102 1
103 branch: default
103 branch: default
104 commit: 1 modified, 1 subrepos
104 commit: 1 modified, 1 subrepos
105 update: (current)
105 update: (current)
106 phases: 2 draft
106 phases: 2 draft
107 $ hg commit --subrepos -m 'Message!' | filter_svn_output
107 $ hg commit --subrepos -m 'Message!' | filter_svn_output
108 committing subrepository s
108 committing subrepository s
109 Sending*s/alpha (glob)
109 Sending*s/alpha (glob)
110 Committed revision 3.
110 Committed revision 3.
111 Fetching external item into '*s/externals'* (glob)
111 Fetching external item into '*s/externals'* (glob)
112 External at revision 1.
112 External at revision 1.
113 At revision 3.
113 At revision 3.
114 $ hg debugsub
114 $ hg debugsub
115 path s
115 path s
116 source file:/*/$TESTTMP/svn-repo/src (glob)
116 source file:/*/$TESTTMP/svn-repo/src (glob)
117 revision 3
117 revision 3
118 path subdir/s
118 path subdir/s
119 source file:/*/$TESTTMP/svn-repo/src (glob)
119 source file:/*/$TESTTMP/svn-repo/src (glob)
120 revision 2
120 revision 2
121
121
122 missing svn file, commit should fail
122 missing svn file, commit should fail
123
123
124 $ rm s/alpha
124 $ rm s/alpha
125 $ hg commit --subrepos -m 'abort on missing file'
125 $ hg commit --subrepos -m 'abort on missing file'
126 committing subrepository s
126 committing subrepository s
127 abort: cannot commit missing svn entries (in subrepository "s")
127 abort: cannot commit missing svn entries (in subrepository "s")
128 [255]
128 [255]
129 $ svn revert s/alpha > /dev/null
129 $ svn revert s/alpha > /dev/null
130
130
131 add an unrelated revision in svn and update the subrepo to without
131 add an unrelated revision in svn and update the subrepo to without
132 bringing any changes.
132 bringing any changes.
133
133
134 $ svn mkdir "$SVNREPOURL/unrelated" -qm 'create unrelated'
134 $ svn mkdir "$SVNREPOURL/unrelated" -qm 'create unrelated'
135 $ svn up -q s
135 $ svn up -q s
136 $ hg sum
136 $ hg sum
137 parent: 2:* tip (glob)
137 parent: 2:* tip (glob)
138 Message!
138 Message!
139 branch: default
139 branch: default
140 commit: (clean)
140 commit: (clean)
141 update: (current)
141 update: (current)
142 phases: 3 draft
142 phases: 3 draft
143
143
144 $ echo a > s/a
144 $ echo a > s/a
145
145
146 should be empty despite change to s/a
146 should be empty despite change to s/a
147
147
148 $ hg st
148 $ hg st
149
149
150 add a commit from svn
150 add a commit from svn
151
151
152 $ cd "$WCROOT/src"
152 $ cd "$WCROOT/src"
153 $ svn up -q
153 $ svn up -q
154 $ echo xyz >> alpha
154 $ echo xyz >> alpha
155 $ svn propset svn:mime-type 'text/xml' alpha
155 $ svn propset svn:mime-type 'text/xml' alpha
156 property 'svn:mime-type' set on 'alpha'
156 property 'svn:mime-type' set on 'alpha'
157 $ svn ci -qm 'amend a from svn'
157 $ svn ci -qm 'amend a from svn'
158 $ cd ../../sub/t
158 $ cd ../../sub/t
159
159
160 this commit from hg will fail
160 this commit from hg will fail
161
161
162 $ echo zzz >> s/alpha
162 $ echo zzz >> s/alpha
163 $ (hg ci --subrepos -m 'amend alpha from hg' 2>&1; echo "[$?]") | grep -vi 'out of date'
163 $ (hg ci --subrepos -m 'amend alpha from hg' 2>&1; echo "[$?]") | grep -vi 'out of date'
164 committing subrepository s
164 committing subrepository s
165 abort: svn:*Commit failed (details follow): (glob)
165 abort: svn:*Commit failed (details follow): (glob)
166 [255]
166 [255]
167 $ svn revert -q s/alpha
167 $ svn revert -q s/alpha
168
168
169 this commit fails because of meta changes
169 this commit fails because of meta changes
170
170
171 $ svn propset svn:mime-type 'text/html' s/alpha
171 $ svn propset svn:mime-type 'text/html' s/alpha
172 property 'svn:mime-type' set on 's/alpha'
172 property 'svn:mime-type' set on 's/alpha'
173 $ (hg ci --subrepos -m 'amend alpha from hg' 2>&1; echo "[$?]") | grep -vi 'out of date'
173 $ (hg ci --subrepos -m 'amend alpha from hg' 2>&1; echo "[$?]") | grep -vi 'out of date'
174 committing subrepository s
174 committing subrepository s
175 abort: svn:*Commit failed (details follow): (glob)
175 abort: svn:*Commit failed (details follow): (glob)
176 [255]
176 [255]
177 $ svn revert -q s/alpha
177 $ svn revert -q s/alpha
178
178
179 this commit fails because of externals changes
179 this commit fails because of externals changes
180
180
181 $ echo zzz > s/externals/other
181 $ echo zzz > s/externals/other
182 $ hg ci --subrepos -m 'amend externals from hg'
182 $ hg ci --subrepos -m 'amend externals from hg'
183 committing subrepository s
183 committing subrepository s
184 abort: cannot commit svn externals (in subrepository "s")
184 abort: cannot commit svn externals (in subrepository "s")
185 [255]
185 [255]
186 $ hg diff --subrepos -r 1:2 | grep -v diff
186 $ hg diff --subrepos -r 1:2 | grep -v diff
187 --- a/.hgsubstate Thu Jan 01 00:00:00 1970 +0000
187 --- a/.hgsubstate Thu Jan 01 00:00:00 1970 +0000
188 +++ b/.hgsubstate Thu Jan 01 00:00:00 1970 +0000
188 +++ b/.hgsubstate Thu Jan 01 00:00:00 1970 +0000
189 @@ -1,2 +1,2 @@
189 @@ -1,2 +1,2 @@
190 -2 s
190 -2 s
191 +3 s
191 +3 s
192 2 subdir/s
192 2 subdir/s
193 --- a/a Thu Jan 01 00:00:00 1970 +0000
193 --- a/a Thu Jan 01 00:00:00 1970 +0000
194 +++ b/a Thu Jan 01 00:00:00 1970 +0000
194 +++ b/a Thu Jan 01 00:00:00 1970 +0000
195 @@ -1,1 +1,2 @@
195 @@ -1,1 +1,2 @@
196 a
196 a
197 +a
197 +a
198 $ svn revert -q s/externals/other
198 $ svn revert -q s/externals/other
199
199
200 this commit fails because of externals meta changes
200 this commit fails because of externals meta changes
201
201
202 $ svn propset svn:mime-type 'text/html' s/externals/other
202 $ svn propset svn:mime-type 'text/html' s/externals/other
203 property 'svn:mime-type' set on 's/externals/other'
203 property 'svn:mime-type' set on 's/externals/other'
204 $ hg ci --subrepos -m 'amend externals from hg'
204 $ hg ci --subrepos -m 'amend externals from hg'
205 committing subrepository s
205 committing subrepository s
206 abort: cannot commit svn externals (in subrepository "s")
206 abort: cannot commit svn externals (in subrepository "s")
207 [255]
207 [255]
208 $ svn revert -q s/externals/other
208 $ svn revert -q s/externals/other
209
209
210 clone
210 clone
211
211
212 $ cd ..
212 $ cd ..
213 $ hg clone t tc
213 $ hg clone t tc
214 updating to branch default
214 updating to branch default
215 A tc/s/alpha
215 A tc/s/alpha
216 U tc/s
216 U tc/s
217
217
218 Fetching external item into 'tc/s/externals'* (glob)
218 Fetching external item into 'tc/s/externals'* (glob)
219 A tc/s/externals/other
219 A tc/s/externals/other
220 Checked out external at revision 1.
220 Checked out external at revision 1.
221
221
222 Checked out revision 3.
222 Checked out revision 3.
223 A tc/subdir/s/alpha
223 A tc/subdir/s/alpha
224 U tc/subdir/s
224 U tc/subdir/s
225
225
226 Fetching external item into 'tc/subdir/s/externals'* (glob)
226 Fetching external item into 'tc/subdir/s/externals'* (glob)
227 A tc/subdir/s/externals/other
227 A tc/subdir/s/externals/other
228 Checked out external at revision 1.
228 Checked out external at revision 1.
229
229
230 Checked out revision 2.
230 Checked out revision 2.
231 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
231 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
232 $ cd tc
232 $ cd tc
233
233
234 debugsub in clone
234 debugsub in clone
235
235
236 $ hg debugsub
236 $ hg debugsub
237 path s
237 path s
238 source file:/*/$TESTTMP/svn-repo/src (glob)
238 source file:/*/$TESTTMP/svn-repo/src (glob)
239 revision 3
239 revision 3
240 path subdir/s
240 path subdir/s
241 source file:/*/$TESTTMP/svn-repo/src (glob)
241 source file:/*/$TESTTMP/svn-repo/src (glob)
242 revision 2
242 revision 2
243
243
244 verify subrepo is contained within the repo directory
244 verify subrepo is contained within the repo directory
245
245
246 $ "$PYTHON" -c "from __future__ import print_function; import os.path; print(os.path.exists('s'))"
246 $ "$PYTHON" -c "from __future__ import print_function; import os.path; print(os.path.exists('s'))"
247 True
247 True
248
248
249 update to nullrev (must delete the subrepo)
249 update to nullrev (must delete the subrepo)
250
250
251 $ hg up null
251 $ hg up null
252 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
252 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
253 $ ls
253 $ ls
254
254
255 Check hg update --clean
255 Check hg update --clean
256 $ cd "$TESTTMP/sub/t"
256 $ cd "$TESTTMP/sub/t"
257 $ cd s
257 $ cd s
258 $ echo c0 > alpha
258 $ echo c0 > alpha
259 $ echo c1 > f1
259 $ echo c1 > f1
260 $ echo c1 > f2
260 $ echo c1 > f2
261 $ svn add f1 -q
261 $ svn add f1 -q
262 $ svn status | sort
262 $ svn status | sort
263
263
264 ? * a (glob)
264 ? * a (glob)
265 ? * f2 (glob)
265 ? * f2 (glob)
266 A * f1 (glob)
266 A * f1 (glob)
267 M * alpha (glob)
267 M * alpha (glob)
268 Performing status on external item at 'externals'* (glob)
268 Performing status on external item at 'externals'* (glob)
269 X * externals (glob)
269 X * externals (glob)
270 $ cd ../..
270 $ cd ../..
271 $ hg -R t update -C
271 $ hg -R t update -C
272
272
273 Fetching external item into 't/s/externals'* (glob)
273 Fetching external item into 't/s/externals'* (glob)
274 Checked out external at revision 1.
274 Checked out external at revision 1.
275
275
276 Checked out revision 3.
276 Checked out revision 3.
277 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
277 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
278 $ cd t/s
278 $ cd t/s
279 $ svn status | sort
279 $ svn status | sort
280
280
281 ? * a (glob)
281 ? * a (glob)
282 ? * f1 (glob)
282 ? * f1 (glob)
283 ? * f2 (glob)
283 ? * f2 (glob)
284 Performing status on external item at 'externals'* (glob)
284 Performing status on external item at 'externals'* (glob)
285 X * externals (glob)
285 X * externals (glob)
286
286
287 Sticky subrepositories, no changes
287 Sticky subrepositories, no changes
288 $ cd "$TESTTMP/sub/t"
288 $ cd "$TESTTMP/sub/t"
289 $ hg id -n
289 $ hg id -n
290 2
290 2
291 $ cd s
291 $ cd s
292 $ svnversion
292 $ svnversion
293 3
293 3
294 $ cd ..
294 $ cd ..
295 $ hg update 1
295 $ hg update 1
296 U *s/alpha (glob)
296 U *s/alpha (glob)
297
297
298 Fetching external item into '*s/externals'* (glob)
298 Fetching external item into '*s/externals'* (glob)
299 Checked out external at revision 1.
299 Checked out external at revision 1.
300
300
301 Checked out revision 2.
301 Checked out revision 2.
302 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
302 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
303 $ hg id -n
303 $ hg id -n
304 1
304 1
305 $ cd s
305 $ cd s
306 $ svnversion
306 $ svnversion
307 2
307 2
308 $ cd ..
308 $ cd ..
309
309
310 Sticky subrepositories, file changes
310 Sticky subrepositories, file changes
311 $ touch s/f1
311 $ touch s/f1
312 $ cd s
312 $ cd s
313 $ svn add f1
313 $ svn add f1
314 A f1
314 A f1
315 $ cd ..
315 $ cd ..
316 $ hg id -n
316 $ hg id -n
317 1+
317 1+
318 $ cd s
318 $ cd s
319 $ svnversion
319 $ svnversion
320 2M
320 2M
321 $ cd ..
321 $ cd ..
322 $ hg update tip
322 $ hg update tip
323 subrepository s diverged (local revision: 2, remote revision: 3)
323 subrepository s diverged (local revision: 2, remote revision: 3)
324 (M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
324 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [destination].
325 what do you want to do? m
325 subrepository sources for s differ
326 subrepository sources for s differ
326 use (l)ocal source (2) or (r)emote source (3)? l
327 you can use (l)ocal source (2) or (r)emote source (3).
328 what do you want to do? l
327 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
329 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
328 $ hg id -n
330 $ hg id -n
329 2+
331 2+
330 $ cd s
332 $ cd s
331 $ svnversion
333 $ svnversion
332 2M
334 2M
333 $ cd ..
335 $ cd ..
334 $ hg update --clean tip
336 $ hg update --clean tip
335 U *s/alpha (glob)
337 U *s/alpha (glob)
336
338
337 Fetching external item into '*s/externals'* (glob)
339 Fetching external item into '*s/externals'* (glob)
338 Checked out external at revision 1.
340 Checked out external at revision 1.
339
341
340 Checked out revision 3.
342 Checked out revision 3.
341 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
343 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
342
344
343 Sticky subrepository, revision updates
345 Sticky subrepository, revision updates
344 $ hg id -n
346 $ hg id -n
345 2
347 2
346 $ cd s
348 $ cd s
347 $ svnversion
349 $ svnversion
348 3
350 3
349 $ cd ..
351 $ cd ..
350 $ cd s
352 $ cd s
351 $ svn update -qr 1
353 $ svn update -qr 1
352 $ cd ..
354 $ cd ..
353 $ hg update 1
355 $ hg update 1
354 subrepository s diverged (local revision: 3, remote revision: 2)
356 subrepository s diverged (local revision: 3, remote revision: 2)
355 (M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
357 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [destination].
358 what do you want to do? m
356 subrepository sources for s differ (in checked out version)
359 subrepository sources for s differ (in checked out version)
357 use (l)ocal source (1) or (r)emote source (2)? l
360 you can use (l)ocal source (1) or (r)emote source (2).
361 what do you want to do? l
358 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
362 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
359 $ hg id -n
363 $ hg id -n
360 1+
364 1+
361 $ cd s
365 $ cd s
362 $ svnversion
366 $ svnversion
363 1
367 1
364 $ cd ..
368 $ cd ..
365
369
366 Sticky subrepository, file changes and revision updates
370 Sticky subrepository, file changes and revision updates
367 $ touch s/f1
371 $ touch s/f1
368 $ cd s
372 $ cd s
369 $ svn add f1
373 $ svn add f1
370 A f1
374 A f1
371 $ svnversion
375 $ svnversion
372 1M
376 1M
373 $ cd ..
377 $ cd ..
374 $ hg id -n
378 $ hg id -n
375 1+
379 1+
376 $ hg update tip
380 $ hg update tip
377 subrepository s diverged (local revision: 3, remote revision: 3)
381 subrepository s diverged (local revision: 3, remote revision: 3)
378 (M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
382 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [destination].
383 what do you want to do? m
379 subrepository sources for s differ
384 subrepository sources for s differ
380 use (l)ocal source (1) or (r)emote source (3)? l
385 you can use (l)ocal source (1) or (r)emote source (3).
386 what do you want to do? l
381 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
387 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
382 $ hg id -n
388 $ hg id -n
383 2+
389 2+
384 $ cd s
390 $ cd s
385 $ svnversion
391 $ svnversion
386 1M
392 1M
387 $ cd ..
393 $ cd ..
388
394
389 Sticky repository, update --clean
395 Sticky repository, update --clean
390 $ hg update --clean tip | grep -v 's[/\]externals[/\]other'
396 $ hg update --clean tip | grep -v 's[/\]externals[/\]other'
391 U *s/alpha (glob)
397 U *s/alpha (glob)
392 U *s (glob)
398 U *s (glob)
393
399
394 Fetching external item into '*s/externals'* (glob)
400 Fetching external item into '*s/externals'* (glob)
395 Checked out external at revision 1.
401 Checked out external at revision 1.
396
402
397 Checked out revision 3.
403 Checked out revision 3.
398 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
404 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
399 $ hg id -n
405 $ hg id -n
400 2
406 2
401 $ cd s
407 $ cd s
402 $ svnversion
408 $ svnversion
403 3
409 3
404 $ cd ..
410 $ cd ..
405
411
406 Test subrepo already at intended revision:
412 Test subrepo already at intended revision:
407 $ cd s
413 $ cd s
408 $ svn update -qr 2
414 $ svn update -qr 2
409 $ cd ..
415 $ cd ..
410 $ hg update 1
416 $ hg update 1
411 subrepository s diverged (local revision: 3, remote revision: 2)
417 subrepository s diverged (local revision: 3, remote revision: 2)
412 (M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
418 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [destination].
419 what do you want to do? m
413 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
420 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
414 $ hg id -n
421 $ hg id -n
415 1+
422 1+
416 $ cd s
423 $ cd s
417 $ svnversion
424 $ svnversion
418 2
425 2
419 $ cd ..
426 $ cd ..
420
427
421 Test case where subversion would fail to update the subrepo because there
428 Test case where subversion would fail to update the subrepo because there
422 are unknown directories being replaced by tracked ones (happens with rebase).
429 are unknown directories being replaced by tracked ones (happens with rebase).
423
430
424 $ cd "$WCROOT/src"
431 $ cd "$WCROOT/src"
425 $ mkdir dir
432 $ mkdir dir
426 $ echo epsilon.py > dir/epsilon.py
433 $ echo epsilon.py > dir/epsilon.py
427 $ svn add dir
434 $ svn add dir
428 A dir
435 A dir
429 A dir/epsilon.py
436 A dir/epsilon.py
430 $ svn ci -qm 'Add dir/epsilon.py'
437 $ svn ci -qm 'Add dir/epsilon.py'
431 $ cd ../..
438 $ cd ../..
432 $ hg init rebaserepo
439 $ hg init rebaserepo
433 $ cd rebaserepo
440 $ cd rebaserepo
434 $ svn co -r5 --quiet "$SVNREPOURL"/src s
441 $ svn co -r5 --quiet "$SVNREPOURL"/src s
435 $ echo "s = [svn] $SVNREPOURL/src" >> .hgsub
442 $ echo "s = [svn] $SVNREPOURL/src" >> .hgsub
436 $ hg add .hgsub
443 $ hg add .hgsub
437 $ hg ci -m addsub
444 $ hg ci -m addsub
438 $ echo a > a
445 $ echo a > a
439 $ hg add .
446 $ hg add .
440 adding a
447 adding a
441 $ hg ci -m adda
448 $ hg ci -m adda
442 $ hg up 0
449 $ hg up 0
443 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
450 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
444 $ svn up -qr6 s
451 $ svn up -qr6 s
445 $ hg ci -m updatesub
452 $ hg ci -m updatesub
446 created new head
453 created new head
447 $ echo pyc > s/dir/epsilon.pyc
454 $ echo pyc > s/dir/epsilon.pyc
448 $ hg up 1
455 $ hg up 1
449 D *s/dir (glob)
456 D *s/dir (glob)
450
457
451 Fetching external item into '*s/externals'* (glob)
458 Fetching external item into '*s/externals'* (glob)
452 Checked out external at revision 1.
459 Checked out external at revision 1.
453
460
454 Checked out revision 5.
461 Checked out revision 5.
455 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
462 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
456 $ hg up -q 2
463 $ hg up -q 2
457
464
458 Modify one of the externals to point to a different path so we can
465 Modify one of the externals to point to a different path so we can
459 test having obstructions when switching branches on checkout:
466 test having obstructions when switching branches on checkout:
460 $ hg checkout tip
467 $ hg checkout tip
461 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
468 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
462 $ echo "obstruct = [svn] $SVNREPOURL/externals" >> .hgsub
469 $ echo "obstruct = [svn] $SVNREPOURL/externals" >> .hgsub
463 $ svn co -r5 --quiet "$SVNREPOURL"/externals obstruct
470 $ svn co -r5 --quiet "$SVNREPOURL"/externals obstruct
464 $ hg commit -m 'Start making obstructed working copy'
471 $ hg commit -m 'Start making obstructed working copy'
465 $ hg book other
472 $ hg book other
466 $ hg co -r 'p1(tip)'
473 $ hg co -r 'p1(tip)'
467 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
474 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
468 (leaving bookmark other)
475 (leaving bookmark other)
469 $ echo "obstruct = [svn] $SVNREPOURL/src" >> .hgsub
476 $ echo "obstruct = [svn] $SVNREPOURL/src" >> .hgsub
470 $ svn co -r5 --quiet "$SVNREPOURL"/src obstruct
477 $ svn co -r5 --quiet "$SVNREPOURL"/src obstruct
471 $ hg commit -m 'Other branch which will be obstructed'
478 $ hg commit -m 'Other branch which will be obstructed'
472 created new head
479 created new head
473
480
474 Switching back to the head where we have another path mapped to the
481 Switching back to the head where we have another path mapped to the
475 same subrepo should work if the subrepo is clean.
482 same subrepo should work if the subrepo is clean.
476 $ hg co other
483 $ hg co other
477 A *obstruct/other (glob)
484 A *obstruct/other (glob)
478 Checked out revision 1.
485 Checked out revision 1.
479 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
486 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
480 (activating bookmark other)
487 (activating bookmark other)
481
488
482 This is surprising, but is also correct based on the current code:
489 This is surprising, but is also correct based on the current code:
483 $ echo "updating should (maybe) fail" > obstruct/other
490 $ echo "updating should (maybe) fail" > obstruct/other
484 $ hg co tip
491 $ hg co tip
485 abort: uncommitted changes
492 abort: uncommitted changes
486 (commit or update --clean to discard changes)
493 (commit or update --clean to discard changes)
487 [255]
494 [255]
488
495
489 Point to a Subversion branch which has since been deleted and recreated
496 Point to a Subversion branch which has since been deleted and recreated
490 First, create that condition in the repository.
497 First, create that condition in the repository.
491
498
492 $ hg ci --subrepos -m cleanup | filter_svn_output
499 $ hg ci --subrepos -m cleanup | filter_svn_output
493 committing subrepository obstruct
500 committing subrepository obstruct
494 Sending obstruct/other
501 Sending obstruct/other
495 Committed revision 7.
502 Committed revision 7.
496 At revision 7.
503 At revision 7.
497 $ svn mkdir -qm "baseline" $SVNREPOURL/trunk
504 $ svn mkdir -qm "baseline" $SVNREPOURL/trunk
498 $ svn copy -qm "initial branch" $SVNREPOURL/trunk $SVNREPOURL/branch
505 $ svn copy -qm "initial branch" $SVNREPOURL/trunk $SVNREPOURL/branch
499 $ svn co --quiet "$SVNREPOURL"/branch tempwc
506 $ svn co --quiet "$SVNREPOURL"/branch tempwc
500 $ cd tempwc
507 $ cd tempwc
501 $ echo "something old" > somethingold
508 $ echo "something old" > somethingold
502 $ svn add somethingold
509 $ svn add somethingold
503 A somethingold
510 A somethingold
504 $ svn ci -qm 'Something old'
511 $ svn ci -qm 'Something old'
505 $ svn rm -qm "remove branch" $SVNREPOURL/branch
512 $ svn rm -qm "remove branch" $SVNREPOURL/branch
506 $ svn copy -qm "recreate branch" $SVNREPOURL/trunk $SVNREPOURL/branch
513 $ svn copy -qm "recreate branch" $SVNREPOURL/trunk $SVNREPOURL/branch
507 $ svn up -q
514 $ svn up -q
508 $ echo "something new" > somethingnew
515 $ echo "something new" > somethingnew
509 $ svn add somethingnew
516 $ svn add somethingnew
510 A somethingnew
517 A somethingnew
511 $ svn ci -qm 'Something new'
518 $ svn ci -qm 'Something new'
512 $ cd ..
519 $ cd ..
513 $ rm -rf tempwc
520 $ rm -rf tempwc
514 $ svn co "$SVNREPOURL/branch"@10 recreated
521 $ svn co "$SVNREPOURL/branch"@10 recreated
515 A recreated/somethingold
522 A recreated/somethingold
516 Checked out revision 10.
523 Checked out revision 10.
517 $ echo "recreated = [svn] $SVNREPOURL/branch" >> .hgsub
524 $ echo "recreated = [svn] $SVNREPOURL/branch" >> .hgsub
518 $ hg ci -m addsub
525 $ hg ci -m addsub
519 $ cd recreated
526 $ cd recreated
520 $ svn up -q
527 $ svn up -q
521 $ cd ..
528 $ cd ..
522 $ hg ci -m updatesub
529 $ hg ci -m updatesub
523 $ hg up -r-2
530 $ hg up -r-2
524 D *recreated/somethingnew (glob)
531 D *recreated/somethingnew (glob)
525 A *recreated/somethingold (glob)
532 A *recreated/somethingold (glob)
526 Checked out revision 10.
533 Checked out revision 10.
527 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
534 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
528 (leaving bookmark other)
535 (leaving bookmark other)
529 $ test -f recreated/somethingold
536 $ test -f recreated/somethingold
530
537
531 Test archive
538 Test archive
532
539
533 $ hg archive -S ../archive-all --debug --config progress.debug=true
540 $ hg archive -S ../archive-all --debug --config progress.debug=true
534 archiving: 0/2 files (0.00%)
541 archiving: 0/2 files (0.00%)
535 archiving: .hgsub 1/2 files (50.00%)
542 archiving: .hgsub 1/2 files (50.00%)
536 archiving: .hgsubstate 2/2 files (100.00%)
543 archiving: .hgsubstate 2/2 files (100.00%)
537 archiving (obstruct): 0/1 files (0.00%)
544 archiving (obstruct): 0/1 files (0.00%)
538 archiving (obstruct): 1/1 files (100.00%)
545 archiving (obstruct): 1/1 files (100.00%)
539 archiving (recreated): 0/1 files (0.00%)
546 archiving (recreated): 0/1 files (0.00%)
540 archiving (recreated): 1/1 files (100.00%)
547 archiving (recreated): 1/1 files (100.00%)
541 archiving (s): 0/2 files (0.00%)
548 archiving (s): 0/2 files (0.00%)
542 archiving (s): 1/2 files (50.00%)
549 archiving (s): 1/2 files (50.00%)
543 archiving (s): 2/2 files (100.00%)
550 archiving (s): 2/2 files (100.00%)
544
551
545 $ hg archive -S ../archive-exclude --debug --config progress.debug=true -X **old
552 $ hg archive -S ../archive-exclude --debug --config progress.debug=true -X **old
546 archiving: 0/2 files (0.00%)
553 archiving: 0/2 files (0.00%)
547 archiving: .hgsub 1/2 files (50.00%)
554 archiving: .hgsub 1/2 files (50.00%)
548 archiving: .hgsubstate 2/2 files (100.00%)
555 archiving: .hgsubstate 2/2 files (100.00%)
549 archiving (obstruct): 0/1 files (0.00%)
556 archiving (obstruct): 0/1 files (0.00%)
550 archiving (obstruct): 1/1 files (100.00%)
557 archiving (obstruct): 1/1 files (100.00%)
551 archiving (recreated): 0 files
558 archiving (recreated): 0 files
552 archiving (s): 0/2 files (0.00%)
559 archiving (s): 0/2 files (0.00%)
553 archiving (s): 1/2 files (50.00%)
560 archiving (s): 1/2 files (50.00%)
554 archiving (s): 2/2 files (100.00%)
561 archiving (s): 2/2 files (100.00%)
555 $ find ../archive-exclude | sort
562 $ find ../archive-exclude | sort
556 ../archive-exclude
563 ../archive-exclude
557 ../archive-exclude/.hg_archival.txt
564 ../archive-exclude/.hg_archival.txt
558 ../archive-exclude/.hgsub
565 ../archive-exclude/.hgsub
559 ../archive-exclude/.hgsubstate
566 ../archive-exclude/.hgsubstate
560 ../archive-exclude/obstruct
567 ../archive-exclude/obstruct
561 ../archive-exclude/obstruct/other
568 ../archive-exclude/obstruct/other
562 ../archive-exclude/s
569 ../archive-exclude/s
563 ../archive-exclude/s/alpha
570 ../archive-exclude/s/alpha
564 ../archive-exclude/s/dir
571 ../archive-exclude/s/dir
565 ../archive-exclude/s/dir/epsilon.py
572 ../archive-exclude/s/dir/epsilon.py
566
573
567 Test forgetting files, not implemented in svn subrepo, used to
574 Test forgetting files, not implemented in svn subrepo, used to
568 traceback
575 traceback
569
576
570 $ hg forget 'notafile*'
577 $ hg forget 'notafile*'
571 notafile*: $ENOENT$
578 notafile*: $ENOENT$
572 [1]
579 [1]
573
580
574 Test a subrepo referencing a just moved svn path. Last commit rev will
581 Test a subrepo referencing a just moved svn path. Last commit rev will
575 be different from the revision, and the path will be different as
582 be different from the revision, and the path will be different as
576 well.
583 well.
577
584
578 $ cd "$WCROOT"
585 $ cd "$WCROOT"
579 $ svn up > /dev/null
586 $ svn up > /dev/null
580 $ mkdir trunk/subdir branches
587 $ mkdir trunk/subdir branches
581 $ echo a > trunk/subdir/a
588 $ echo a > trunk/subdir/a
582 $ svn add trunk/subdir branches
589 $ svn add trunk/subdir branches
583 A trunk/subdir
590 A trunk/subdir
584 A trunk/subdir/a
591 A trunk/subdir/a
585 A branches
592 A branches
586 $ svn ci -qm addsubdir
593 $ svn ci -qm addsubdir
587 $ svn cp -qm branchtrunk $SVNREPOURL/trunk $SVNREPOURL/branches/somebranch
594 $ svn cp -qm branchtrunk $SVNREPOURL/trunk $SVNREPOURL/branches/somebranch
588 $ cd ..
595 $ cd ..
589
596
590 $ hg init repo2
597 $ hg init repo2
591 $ cd repo2
598 $ cd repo2
592 $ svn co $SVNREPOURL/branches/somebranch/subdir
599 $ svn co $SVNREPOURL/branches/somebranch/subdir
593 A subdir/a
600 A subdir/a
594 Checked out revision 15.
601 Checked out revision 15.
595 $ echo "subdir = [svn] $SVNREPOURL/branches/somebranch/subdir" > .hgsub
602 $ echo "subdir = [svn] $SVNREPOURL/branches/somebranch/subdir" > .hgsub
596 $ hg add .hgsub
603 $ hg add .hgsub
597 $ hg ci -m addsub
604 $ hg ci -m addsub
598 $ hg up null
605 $ hg up null
599 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
606 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
600 $ hg up
607 $ hg up
601 A *subdir/a (glob)
608 A *subdir/a (glob)
602 Checked out revision 15.
609 Checked out revision 15.
603 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
610 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
604 $ cd ..
611 $ cd ..
605
612
606 Test sanitizing ".hg/hgrc" in subrepo
613 Test sanitizing ".hg/hgrc" in subrepo
607
614
608 $ cd sub/t
615 $ cd sub/t
609 $ hg update -q -C tip
616 $ hg update -q -C tip
610 $ cd s
617 $ cd s
611 $ mkdir .hg
618 $ mkdir .hg
612 $ echo '.hg/hgrc in svn repo' > .hg/hgrc
619 $ echo '.hg/hgrc in svn repo' > .hg/hgrc
613 $ mkdir -p sub/.hg
620 $ mkdir -p sub/.hg
614 $ echo 'sub/.hg/hgrc in svn repo' > sub/.hg/hgrc
621 $ echo 'sub/.hg/hgrc in svn repo' > sub/.hg/hgrc
615 $ svn add .hg sub
622 $ svn add .hg sub
616 A .hg
623 A .hg
617 A .hg/hgrc
624 A .hg/hgrc
618 A sub
625 A sub
619 A sub/.hg
626 A sub/.hg
620 A sub/.hg/hgrc
627 A sub/.hg/hgrc
621 $ svn ci -qm 'add .hg/hgrc to be sanitized at hg update'
628 $ svn ci -qm 'add .hg/hgrc to be sanitized at hg update'
622 $ svn up -q
629 $ svn up -q
623 $ cd ..
630 $ cd ..
624 $ hg commit -S -m 'commit with svn revision including .hg/hgrc'
631 $ hg commit -S -m 'commit with svn revision including .hg/hgrc'
625 $ grep ' s$' .hgsubstate
632 $ grep ' s$' .hgsubstate
626 16 s
633 16 s
627 $ cd ..
634 $ cd ..
628
635
629 $ hg -R tc pull -u -q 2>&1 | sort
636 $ hg -R tc pull -u -q 2>&1 | sort
630 warning: removing potentially hostile 'hgrc' in '$TESTTMP/sub/tc/s/.hg'
637 warning: removing potentially hostile 'hgrc' in '$TESTTMP/sub/tc/s/.hg'
631 warning: removing potentially hostile 'hgrc' in '$TESTTMP/sub/tc/s/sub/.hg'
638 warning: removing potentially hostile 'hgrc' in '$TESTTMP/sub/tc/s/sub/.hg'
632 $ cd tc
639 $ cd tc
633 $ grep ' s$' .hgsubstate
640 $ grep ' s$' .hgsubstate
634 16 s
641 16 s
635 $ test -f s/.hg/hgrc
642 $ test -f s/.hg/hgrc
636 [1]
643 [1]
637 $ test -f s/sub/.hg/hgrc
644 $ test -f s/sub/.hg/hgrc
638 [1]
645 [1]
639
646
640 Test that sanitizing is omitted in meta data area:
647 Test that sanitizing is omitted in meta data area:
641
648
642 $ mkdir s/.svn/.hg
649 $ mkdir s/.svn/.hg
643 $ echo '.hg/hgrc in svn metadata area' > s/.svn/.hg/hgrc
650 $ echo '.hg/hgrc in svn metadata area' > s/.svn/.hg/hgrc
644 $ hg update -q -C '.^1'
651 $ hg update -q -C '.^1'
645
652
646 $ cd ../..
653 $ cd ../..
647
654
648 SEC: test for ssh exploit
655 SEC: test for ssh exploit
649
656
650 $ hg init ssh-vuln
657 $ hg init ssh-vuln
651 $ cd ssh-vuln
658 $ cd ssh-vuln
652 $ echo "s = [svn]$SVNREPOURL/src" >> .hgsub
659 $ echo "s = [svn]$SVNREPOURL/src" >> .hgsub
653 $ svn co --quiet "$SVNREPOURL"/src s
660 $ svn co --quiet "$SVNREPOURL"/src s
654 $ hg add .hgsub
661 $ hg add .hgsub
655 $ hg ci -m1
662 $ hg ci -m1
656 $ echo "s = [svn]svn+ssh://-oProxyCommand=touch%20owned%20nested" > .hgsub
663 $ echo "s = [svn]svn+ssh://-oProxyCommand=touch%20owned%20nested" > .hgsub
657 $ hg ci -m2
664 $ hg ci -m2
658 $ cd ..
665 $ cd ..
659 $ hg clone ssh-vuln ssh-vuln-clone
666 $ hg clone ssh-vuln ssh-vuln-clone
660 updating to branch default
667 updating to branch default
661 abort: potentially unsafe url: 'svn+ssh://-oProxyCommand=touch owned nested' (in subrepository "s")
668 abort: potentially unsafe url: 'svn+ssh://-oProxyCommand=touch owned nested' (in subrepository "s")
662 [255]
669 [255]
663
670
664 also check that a percent encoded '-' (%2D) doesn't work
671 also check that a percent encoded '-' (%2D) doesn't work
665
672
666 $ cd ssh-vuln
673 $ cd ssh-vuln
667 $ echo "s = [svn]svn+ssh://%2DoProxyCommand=touch%20owned%20nested" > .hgsub
674 $ echo "s = [svn]svn+ssh://%2DoProxyCommand=touch%20owned%20nested" > .hgsub
668 $ hg ci -m3
675 $ hg ci -m3
669 $ cd ..
676 $ cd ..
670 $ rm -r ssh-vuln-clone
677 $ rm -r ssh-vuln-clone
671 $ hg clone ssh-vuln ssh-vuln-clone
678 $ hg clone ssh-vuln ssh-vuln-clone
672 updating to branch default
679 updating to branch default
673 abort: potentially unsafe url: 'svn+ssh://-oProxyCommand=touch owned nested' (in subrepository "s")
680 abort: potentially unsafe url: 'svn+ssh://-oProxyCommand=touch owned nested' (in subrepository "s")
674 [255]
681 [255]
675
682
676 also check that hiding the attack in the username doesn't work:
683 also check that hiding the attack in the username doesn't work:
677
684
678 $ cd ssh-vuln
685 $ cd ssh-vuln
679 $ echo "s = [svn]svn+ssh://%2DoProxyCommand=touch%20owned%20foo@example.com/nested" > .hgsub
686 $ echo "s = [svn]svn+ssh://%2DoProxyCommand=touch%20owned%20foo@example.com/nested" > .hgsub
680 $ hg ci -m3
687 $ hg ci -m3
681 $ cd ..
688 $ cd ..
682 $ rm -r ssh-vuln-clone
689 $ rm -r ssh-vuln-clone
683 $ hg clone ssh-vuln ssh-vuln-clone
690 $ hg clone ssh-vuln ssh-vuln-clone
684 updating to branch default
691 updating to branch default
685 abort: potentially unsafe url: 'svn+ssh://-oProxyCommand=touch owned foo@example.com/nested' (in subrepository "s")
692 abort: potentially unsafe url: 'svn+ssh://-oProxyCommand=touch owned foo@example.com/nested' (in subrepository "s")
686 [255]
693 [255]
@@ -1,2007 +1,2023 b''
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 add s/a
28 $ hg -R s add s/a
29 $ hg files -S
29 $ hg files -S
30 .hgsub
30 .hgsub
31 a
31 a
32 s/a
32 s/a
33
33
34 `hg files` respects ui.relative-paths
34 `hg files` respects ui.relative-paths
35 BROKEN: shows subrepo paths relative to the subrepo
35 BROKEN: shows subrepo paths relative to the subrepo
36 $ hg files -S --config ui.relative-paths=no
36 $ hg files -S --config ui.relative-paths=no
37 .hgsub
37 .hgsub
38 a
38 a
39 s/a
39 s/a
40
40
41 $ hg -R s ci -Ams0
41 $ hg -R s ci -Ams0
42 $ hg sum
42 $ hg sum
43 parent: 0:f7b1eb17ad24 tip
43 parent: 0:f7b1eb17ad24 tip
44 0
44 0
45 branch: default
45 branch: default
46 commit: 1 added, 1 subrepos
46 commit: 1 added, 1 subrepos
47 update: (current)
47 update: (current)
48 phases: 1 draft
48 phases: 1 draft
49 $ hg ci -m1
49 $ hg ci -m1
50
50
51 test handling .hgsubstate "added" explicitly.
51 test handling .hgsubstate "added" explicitly.
52
52
53 $ hg parents --template '{node}\n{files}\n'
53 $ hg parents --template '{node}\n{files}\n'
54 7cf8cfea66e410e8e3336508dfeec07b3192de51
54 7cf8cfea66e410e8e3336508dfeec07b3192de51
55 .hgsub .hgsubstate
55 .hgsub .hgsubstate
56 $ hg rollback -q
56 $ hg rollback -q
57 $ hg add .hgsubstate
57 $ hg add .hgsubstate
58 $ hg ci -m1
58 $ hg ci -m1
59 $ hg parents --template '{node}\n{files}\n'
59 $ hg parents --template '{node}\n{files}\n'
60 7cf8cfea66e410e8e3336508dfeec07b3192de51
60 7cf8cfea66e410e8e3336508dfeec07b3192de51
61 .hgsub .hgsubstate
61 .hgsub .hgsubstate
62
62
63 Subrepopath which overlaps with filepath, does not change warnings in remove()
63 Subrepopath which overlaps with filepath, does not change warnings in remove()
64
64
65 $ mkdir snot
65 $ mkdir snot
66 $ touch snot/file
66 $ touch snot/file
67 $ hg remove -S snot/file
67 $ hg remove -S snot/file
68 not removing snot/file: file is untracked
68 not removing snot/file: file is untracked
69 [1]
69 [1]
70 $ hg cat snot/filenot
70 $ hg cat snot/filenot
71 snot/filenot: no such file in rev 7cf8cfea66e4
71 snot/filenot: no such file in rev 7cf8cfea66e4
72 [1]
72 [1]
73 $ rm -r snot
73 $ rm -r snot
74
74
75 Revert subrepo and test subrepo fileset keyword:
75 Revert subrepo and test subrepo fileset keyword:
76
76
77 $ echo b > s/a
77 $ echo b > s/a
78 $ hg revert --dry-run "set:subrepo('glob:s*')"
78 $ hg revert --dry-run "set:subrepo('glob:s*')"
79 reverting subrepo s
79 reverting subrepo s
80 reverting s/a
80 reverting s/a
81 $ cat s/a
81 $ cat s/a
82 b
82 b
83 $ hg revert "set:subrepo('glob:s*')"
83 $ hg revert "set:subrepo('glob:s*')"
84 reverting subrepo s
84 reverting subrepo s
85 reverting s/a
85 reverting s/a
86 $ cat s/a
86 $ cat s/a
87 a
87 a
88 $ rm s/a.orig
88 $ rm s/a.orig
89
89
90 Revert subrepo with no backup. The "reverting s/a" line is gone since
90 Revert subrepo with no backup. The "reverting s/a" line is gone since
91 we're really running 'hg update' in the subrepo:
91 we're really running 'hg update' in the subrepo:
92
92
93 $ echo b > s/a
93 $ echo b > s/a
94 $ hg revert --no-backup s
94 $ hg revert --no-backup s
95 reverting subrepo s
95 reverting subrepo s
96
96
97 Issue2022: update -C
97 Issue2022: update -C
98
98
99 $ echo b > s/a
99 $ echo b > s/a
100 $ hg sum
100 $ hg sum
101 parent: 1:7cf8cfea66e4 tip
101 parent: 1:7cf8cfea66e4 tip
102 1
102 1
103 branch: default
103 branch: default
104 commit: 1 subrepos
104 commit: 1 subrepos
105 update: (current)
105 update: (current)
106 phases: 2 draft
106 phases: 2 draft
107 $ hg co -C 1
107 $ hg co -C 1
108 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
108 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 $ hg sum
109 $ hg sum
110 parent: 1:7cf8cfea66e4 tip
110 parent: 1:7cf8cfea66e4 tip
111 1
111 1
112 branch: default
112 branch: default
113 commit: (clean)
113 commit: (clean)
114 update: (current)
114 update: (current)
115 phases: 2 draft
115 phases: 2 draft
116
116
117 commands that require a clean repo should respect subrepos
117 commands that require a clean repo should respect subrepos
118
118
119 $ echo b >> s/a
119 $ echo b >> s/a
120 $ hg backout tip
120 $ hg backout tip
121 abort: uncommitted changes in subrepository "s"
121 abort: uncommitted changes in subrepository "s"
122 [255]
122 [255]
123 $ hg revert -C -R s s/a
123 $ hg revert -C -R s s/a
124
124
125 add sub sub
125 add sub sub
126
126
127 $ echo ss = ss > s/.hgsub
127 $ echo ss = ss > s/.hgsub
128 $ hg init s/ss
128 $ hg init s/ss
129 $ echo a > s/ss/a
129 $ echo a > s/ss/a
130 $ hg -R s add s/.hgsub
130 $ hg -R s add s/.hgsub
131 $ hg -R s/ss add s/ss/a
131 $ hg -R s/ss add s/ss/a
132 $ hg sum
132 $ hg sum
133 parent: 1:7cf8cfea66e4 tip
133 parent: 1:7cf8cfea66e4 tip
134 1
134 1
135 branch: default
135 branch: default
136 commit: 1 subrepos
136 commit: 1 subrepos
137 update: (current)
137 update: (current)
138 phases: 2 draft
138 phases: 2 draft
139 $ hg ci -m2
139 $ hg ci -m2
140 committing subrepository s
140 committing subrepository s
141 committing subrepository s/ss
141 committing subrepository s/ss
142 $ hg sum
142 $ hg sum
143 parent: 2:df30734270ae tip
143 parent: 2:df30734270ae tip
144 2
144 2
145 branch: default
145 branch: default
146 commit: (clean)
146 commit: (clean)
147 update: (current)
147 update: (current)
148 phases: 3 draft
148 phases: 3 draft
149
149
150 test handling .hgsubstate "modified" explicitly.
150 test handling .hgsubstate "modified" explicitly.
151
151
152 $ hg parents --template '{node}\n{files}\n'
152 $ hg parents --template '{node}\n{files}\n'
153 df30734270ae757feb35e643b7018e818e78a9aa
153 df30734270ae757feb35e643b7018e818e78a9aa
154 .hgsubstate
154 .hgsubstate
155 $ hg rollback -q
155 $ hg rollback -q
156 $ hg status -A .hgsubstate
156 $ hg status -A .hgsubstate
157 M .hgsubstate
157 M .hgsubstate
158 $ hg ci -m2
158 $ hg ci -m2
159 $ hg parents --template '{node}\n{files}\n'
159 $ hg parents --template '{node}\n{files}\n'
160 df30734270ae757feb35e643b7018e818e78a9aa
160 df30734270ae757feb35e643b7018e818e78a9aa
161 .hgsubstate
161 .hgsubstate
162
162
163 bump sub rev (and check it is ignored by ui.commitsubrepos)
163 bump sub rev (and check it is ignored by ui.commitsubrepos)
164
164
165 $ echo b > s/a
165 $ echo b > s/a
166 $ hg -R s ci -ms1
166 $ hg -R s ci -ms1
167 $ hg --config ui.commitsubrepos=no ci -m3
167 $ hg --config ui.commitsubrepos=no ci -m3
168
168
169 leave sub dirty (and check ui.commitsubrepos=no aborts the commit)
169 leave sub dirty (and check ui.commitsubrepos=no aborts the commit)
170
170
171 $ echo c > s/a
171 $ echo c > s/a
172 $ hg --config ui.commitsubrepos=no ci -m4
172 $ hg --config ui.commitsubrepos=no ci -m4
173 abort: uncommitted changes in subrepository "s"
173 abort: uncommitted changes in subrepository "s"
174 (use --subrepos for recursive commit)
174 (use --subrepos for recursive commit)
175 [255]
175 [255]
176 $ hg id
176 $ hg id
177 f6affe3fbfaa+ tip
177 f6affe3fbfaa+ tip
178 $ hg -R s ci -mc
178 $ hg -R s ci -mc
179 $ hg id
179 $ hg id
180 f6affe3fbfaa+ tip
180 f6affe3fbfaa+ tip
181 $ echo d > s/a
181 $ echo d > s/a
182 $ hg ci -m4
182 $ hg ci -m4
183 committing subrepository s
183 committing subrepository s
184 $ hg tip -R s
184 $ hg tip -R s
185 changeset: 4:02dcf1d70411
185 changeset: 4:02dcf1d70411
186 tag: tip
186 tag: tip
187 user: test
187 user: test
188 date: Thu Jan 01 00:00:00 1970 +0000
188 date: Thu Jan 01 00:00:00 1970 +0000
189 summary: 4
189 summary: 4
190
190
191
191
192 check caching
192 check caching
193
193
194 $ hg co 0
194 $ hg co 0
195 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
195 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
196 $ hg debugsub
196 $ hg debugsub
197
197
198 restore
198 restore
199
199
200 $ hg co
200 $ hg co
201 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
201 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
202 $ hg debugsub
202 $ hg debugsub
203 path s
203 path s
204 source s
204 source s
205 revision 02dcf1d704118aee3ee306ccfa1910850d5b05ef
205 revision 02dcf1d704118aee3ee306ccfa1910850d5b05ef
206
206
207 new branch for merge tests
207 new branch for merge tests
208
208
209 $ hg co 1
209 $ hg co 1
210 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
210 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
211 $ echo t = t >> .hgsub
211 $ echo t = t >> .hgsub
212 $ hg init t
212 $ hg init t
213 $ echo t > t/t
213 $ echo t > t/t
214 $ hg -R t add t
214 $ hg -R t add t
215 adding t/t
215 adding t/t
216
216
217 5
217 5
218
218
219 $ hg ci -m5 # add sub
219 $ hg ci -m5 # add sub
220 committing subrepository t
220 committing subrepository t
221 created new head
221 created new head
222 $ echo t2 > t/t
222 $ echo t2 > t/t
223
223
224 6
224 6
225
225
226 $ hg st -R s
226 $ hg st -R s
227 $ hg ci -m6 # change sub
227 $ hg ci -m6 # change sub
228 committing subrepository t
228 committing subrepository t
229 $ hg debugsub
229 $ hg debugsub
230 path s
230 path s
231 source s
231 source s
232 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
232 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
233 path t
233 path t
234 source t
234 source t
235 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
235 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
236 $ echo t3 > t/t
236 $ echo t3 > t/t
237
237
238 7
238 7
239
239
240 $ hg ci -m7 # change sub again for conflict test
240 $ hg ci -m7 # change sub again for conflict test
241 committing subrepository t
241 committing subrepository t
242 $ hg rm .hgsub
242 $ hg rm .hgsub
243
243
244 8
244 8
245
245
246 $ hg ci -m8 # remove sub
246 $ hg ci -m8 # remove sub
247
247
248 test handling .hgsubstate "removed" explicitly.
248 test handling .hgsubstate "removed" explicitly.
249
249
250 $ hg parents --template '{node}\n{files}\n'
250 $ hg parents --template '{node}\n{files}\n'
251 96615c1dad2dc8e3796d7332c77ce69156f7b78e
251 96615c1dad2dc8e3796d7332c77ce69156f7b78e
252 .hgsub .hgsubstate
252 .hgsub .hgsubstate
253 $ hg rollback -q
253 $ hg rollback -q
254 $ hg remove .hgsubstate
254 $ hg remove .hgsubstate
255 $ hg ci -m8
255 $ hg ci -m8
256 $ hg parents --template '{node}\n{files}\n'
256 $ hg parents --template '{node}\n{files}\n'
257 96615c1dad2dc8e3796d7332c77ce69156f7b78e
257 96615c1dad2dc8e3796d7332c77ce69156f7b78e
258 .hgsub .hgsubstate
258 .hgsub .hgsubstate
259
259
260 merge tests
260 merge tests
261
261
262 $ hg co -C 3
262 $ hg co -C 3
263 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
263 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
264 $ hg merge 5 # test adding
264 $ hg merge 5 # test adding
265 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
265 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
266 (branch merge, don't forget to commit)
266 (branch merge, don't forget to commit)
267 $ hg debugsub
267 $ hg debugsub
268 path s
268 path s
269 source s
269 source s
270 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
270 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
271 path t
271 path t
272 source t
272 source t
273 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
273 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
274 $ hg ci -m9
274 $ hg ci -m9
275 created new head
275 created new head
276 $ hg merge 6 --debug # test change
276 $ hg merge 6 --debug # test change
277 resolving manifests
277 resolving manifests
278 branchmerge: True, force: False, partial: False
278 branchmerge: True, force: False, partial: False
279 ancestor: 1f14a2e2d3ec, local: f0d2028bf86d+, remote: 1831e14459c4
279 ancestor: 1f14a2e2d3ec, local: f0d2028bf86d+, remote: 1831e14459c4
280 starting 4 threads for background file closing (?)
280 starting 4 threads for background file closing (?)
281 .hgsubstate: versions differ -> m (premerge)
281 .hgsubstate: versions differ -> m (premerge)
282 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
282 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
283 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
283 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
284 getting subrepo t
284 getting subrepo t
285 resolving manifests
285 resolving manifests
286 branchmerge: False, force: False, partial: False
286 branchmerge: False, force: False, partial: False
287 ancestor: 60ca1237c194, local: 60ca1237c194+, remote: 6747d179aa9a
287 ancestor: 60ca1237c194, local: 60ca1237c194+, remote: 6747d179aa9a
288 t: remote is newer -> g
288 t: remote is newer -> g
289 getting t
289 getting t
290 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
290 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
291 (branch merge, don't forget to commit)
291 (branch merge, don't forget to commit)
292 $ hg debugsub
292 $ hg debugsub
293 path s
293 path s
294 source s
294 source s
295 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
295 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
296 path t
296 path t
297 source t
297 source t
298 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
298 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
299 $ echo conflict > t/t
299 $ echo conflict > t/t
300 $ hg ci -m10
300 $ hg ci -m10
301 committing subrepository t
301 committing subrepository t
302 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
302 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
303 resolving manifests
303 resolving manifests
304 branchmerge: True, force: False, partial: False
304 branchmerge: True, force: False, partial: False
305 ancestor: 1831e14459c4, local: e45c8b14af55+, remote: f94576341bcf
305 ancestor: 1831e14459c4, local: e45c8b14af55+, remote: f94576341bcf
306 starting 4 threads for background file closing (?)
306 starting 4 threads for background file closing (?)
307 .hgsubstate: versions differ -> m (premerge)
307 .hgsubstate: versions differ -> m (premerge)
308 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
308 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
309 subrepo t: both sides changed
309 subrepo t: both sides changed
310 subrepository t diverged (local revision: 20a0db6fbf6c, remote revision: 7af322bc1198)
310 subrepository t diverged (local revision: 20a0db6fbf6c, remote revision: 7af322bc1198)
311 starting 4 threads for background file closing (?)
311 starting 4 threads for background file closing (?)
312 (M)erge, keep (l)ocal [working copy] or keep (r)emote [merge rev]? m
312 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [merge rev].
313 what do you want to do? m
313 merging subrepository "t"
314 merging subrepository "t"
314 resolving manifests
315 resolving manifests
315 branchmerge: True, force: False, partial: False
316 branchmerge: True, force: False, partial: False
316 ancestor: 6747d179aa9a, local: 20a0db6fbf6c+, remote: 7af322bc1198
317 ancestor: 6747d179aa9a, local: 20a0db6fbf6c+, remote: 7af322bc1198
318 starting 4 threads for background file closing (?)
317 preserving t for resolve of t
319 preserving t for resolve of t
318 starting 4 threads for background file closing (?)
319 t: versions differ -> m (premerge)
320 t: versions differ -> m (premerge)
320 picked tool ':merge' for t (binary False symlink False changedelete False)
321 picked tool ':merge' for t (binary False symlink False changedelete False)
321 merging t
322 merging t
322 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
323 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
323 t: versions differ -> m (merge)
324 t: versions differ -> m (merge)
324 picked tool ':merge' for t (binary False symlink False changedelete False)
325 picked tool ':merge' for t (binary False symlink False changedelete False)
325 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
326 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
326 warning: conflicts while merging t! (edit, then use 'hg resolve --mark')
327 warning: conflicts while merging t! (edit, then use 'hg resolve --mark')
327 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
328 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
328 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
329 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
329 subrepo t: merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
330 subrepo t: merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
330 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
331 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
331 (branch merge, don't forget to commit)
332 (branch merge, don't forget to commit)
332
333
333 should conflict
334 should conflict
334
335
335 $ cat t/t
336 $ cat t/t
336 <<<<<<< local: 20a0db6fbf6c - test: 10
337 <<<<<<< local: 20a0db6fbf6c - test: 10
337 conflict
338 conflict
338 =======
339 =======
339 t3
340 t3
340 >>>>>>> other: 7af322bc1198 - test: 7
341 >>>>>>> other: 7af322bc1198 - test: 7
341
342
342 11: remove subrepo t
343 11: remove subrepo t
343
344
344 $ hg co -C 5
345 $ hg co -C 5
345 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
346 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
346 $ hg revert -r 4 .hgsub # remove t
347 $ hg revert -r 4 .hgsub # remove t
347 $ hg ci -m11
348 $ hg ci -m11
348 created new head
349 created new head
349 $ hg debugsub
350 $ hg debugsub
350 path s
351 path s
351 source s
352 source s
352 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
353 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
353
354
354 local removed, remote changed, keep changed
355 local removed, remote changed, keep changed
355
356
356 $ hg merge 6
357 $ hg merge 6
357 remote [merge rev] changed subrepository t which local [working copy] removed
358 remote [merge rev] changed subrepository t which local [working copy] removed
358 use (c)hanged version or (d)elete? c
359 use (c)hanged version or (d)elete? c
359 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
360 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
360 (branch merge, don't forget to commit)
361 (branch merge, don't forget to commit)
361 BROKEN: should include subrepo t
362 BROKEN: should include subrepo t
362 $ hg debugsub
363 $ hg debugsub
363 path s
364 path s
364 source s
365 source s
365 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
366 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
366 $ cat .hgsubstate
367 $ cat .hgsubstate
367 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
368 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
368 6747d179aa9a688023c4b0cad32e4c92bb7f34ad t
369 6747d179aa9a688023c4b0cad32e4c92bb7f34ad t
369 $ hg ci -m 'local removed, remote changed, keep changed'
370 $ hg ci -m 'local removed, remote changed, keep changed'
370 BROKEN: should include subrepo t
371 BROKEN: should include subrepo t
371 $ hg debugsub
372 $ hg debugsub
372 path s
373 path s
373 source s
374 source s
374 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
375 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
375 BROKEN: should include subrepo t
376 BROKEN: should include subrepo t
376 $ cat .hgsubstate
377 $ cat .hgsubstate
377 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
378 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
378 $ cat t/t
379 $ cat t/t
379 t2
380 t2
380
381
381 local removed, remote changed, keep removed
382 local removed, remote changed, keep removed
382
383
383 $ hg co -C 11
384 $ hg co -C 11
384 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
385 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
385 $ hg merge --config ui.interactive=true 6 <<EOF
386 $ hg merge --config ui.interactive=true 6 <<EOF
386 > d
387 > d
387 > EOF
388 > EOF
388 remote [merge rev] changed subrepository t which local [working copy] removed
389 remote [merge rev] changed subrepository t which local [working copy] removed
389 use (c)hanged version or (d)elete? d
390 use (c)hanged version or (d)elete? d
390 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
391 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
391 (branch merge, don't forget to commit)
392 (branch merge, don't forget to commit)
392 $ hg debugsub
393 $ hg debugsub
393 path s
394 path s
394 source s
395 source s
395 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
396 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
396 $ cat .hgsubstate
397 $ cat .hgsubstate
397 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
398 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
398 $ hg ci -m 'local removed, remote changed, keep removed'
399 $ hg ci -m 'local removed, remote changed, keep removed'
399 created new head
400 created new head
400 $ hg debugsub
401 $ hg debugsub
401 path s
402 path s
402 source s
403 source s
403 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
404 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
404 $ cat .hgsubstate
405 $ cat .hgsubstate
405 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
406 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
406
407
407 local changed, remote removed, keep changed
408 local changed, remote removed, keep changed
408
409
409 $ hg co -C 6
410 $ hg co -C 6
410 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
411 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
411 $ hg merge 11
412 $ hg merge 11
412 local [working copy] changed subrepository t which remote [merge rev] removed
413 local [working copy] changed subrepository t which remote [merge rev] removed
413 use (c)hanged version or (d)elete? c
414 use (c)hanged version or (d)elete? c
414 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
415 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
415 (branch merge, don't forget to commit)
416 (branch merge, don't forget to commit)
416 BROKEN: should include subrepo t
417 BROKEN: should include subrepo t
417 $ hg debugsub
418 $ hg debugsub
418 path s
419 path s
419 source s
420 source s
420 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
421 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
421 BROKEN: should include subrepo t
422 BROKEN: should include subrepo t
422 $ cat .hgsubstate
423 $ cat .hgsubstate
423 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
424 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
424 $ hg ci -m 'local changed, remote removed, keep changed'
425 $ hg ci -m 'local changed, remote removed, keep changed'
425 created new head
426 created new head
426 BROKEN: should include subrepo t
427 BROKEN: should include subrepo t
427 $ hg debugsub
428 $ hg debugsub
428 path s
429 path s
429 source s
430 source s
430 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
431 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
431 BROKEN: should include subrepo t
432 BROKEN: should include subrepo t
432 $ cat .hgsubstate
433 $ cat .hgsubstate
433 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
434 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
434 $ cat t/t
435 $ cat t/t
435 t2
436 t2
436
437
437 local changed, remote removed, keep removed
438 local changed, remote removed, keep removed
438
439
439 $ hg co -C 6
440 $ hg co -C 6
440 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
441 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
441 $ hg merge --config ui.interactive=true 11 <<EOF
442 $ hg merge --config ui.interactive=true 11 <<EOF
442 > d
443 > d
443 > EOF
444 > EOF
444 local [working copy] changed subrepository t which remote [merge rev] removed
445 local [working copy] changed subrepository t which remote [merge rev] removed
445 use (c)hanged version or (d)elete? d
446 use (c)hanged version or (d)elete? d
446 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
447 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
447 (branch merge, don't forget to commit)
448 (branch merge, don't forget to commit)
448 $ hg debugsub
449 $ hg debugsub
449 path s
450 path s
450 source s
451 source s
451 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
452 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
452 $ cat .hgsubstate
453 $ cat .hgsubstate
453 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
454 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
454 $ hg ci -m 'local changed, remote removed, keep removed'
455 $ hg ci -m 'local changed, remote removed, keep removed'
455 created new head
456 created new head
456 $ hg debugsub
457 $ hg debugsub
457 path s
458 path s
458 source s
459 source s
459 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
460 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
460 $ cat .hgsubstate
461 $ cat .hgsubstate
461 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
462 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
462
463
463 clean up to avoid having to fix up the tests below
464 clean up to avoid having to fix up the tests below
464
465
465 $ hg co -C 10
466 $ hg co -C 10
466 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
467 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
467 $ cat >> $HGRCPATH <<EOF
468 $ cat >> $HGRCPATH <<EOF
468 > [extensions]
469 > [extensions]
469 > strip=
470 > strip=
470 > EOF
471 > EOF
471 $ hg strip -r 11:15
472 $ hg strip -r 11:15
472 saved backup bundle to $TESTTMP/t/.hg/strip-backup/*-backup.hg (glob)
473 saved backup bundle to $TESTTMP/t/.hg/strip-backup/*-backup.hg (glob)
473
474
474 clone
475 clone
475
476
476 $ cd ..
477 $ cd ..
477 $ hg clone t tc
478 $ hg clone t tc
478 updating to branch default
479 updating to branch default
479 cloning subrepo s from $TESTTMP/t/s
480 cloning subrepo s from $TESTTMP/t/s
480 cloning subrepo s/ss from $TESTTMP/t/s/ss
481 cloning subrepo s/ss from $TESTTMP/t/s/ss
481 cloning subrepo t from $TESTTMP/t/t
482 cloning subrepo t from $TESTTMP/t/t
482 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
483 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
483 $ cd tc
484 $ cd tc
484 $ hg debugsub
485 $ hg debugsub
485 path s
486 path s
486 source s
487 source s
487 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
488 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
488 path t
489 path t
489 source t
490 source t
490 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
491 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
491 $ cd ..
492 $ cd ..
492
493
493 clone with subrepo disabled (update should fail)
494 clone with subrepo disabled (update should fail)
494
495
495 $ hg clone t -U tc2 --config subrepos.allowed=false
496 $ hg clone t -U tc2 --config subrepos.allowed=false
496 $ hg update -R tc2 --config subrepos.allowed=false
497 $ hg update -R tc2 --config subrepos.allowed=false
497 abort: subrepos not enabled
498 abort: subrepos not enabled
498 (see 'hg help config.subrepos' for details)
499 (see 'hg help config.subrepos' for details)
499 [255]
500 [255]
500 $ ls tc2
501 $ ls tc2
501 a
502 a
502
503
503 $ hg clone t tc3 --config subrepos.allowed=false
504 $ hg clone t tc3 --config subrepos.allowed=false
504 updating to branch default
505 updating to branch default
505 abort: subrepos not enabled
506 abort: subrepos not enabled
506 (see 'hg help config.subrepos' for details)
507 (see 'hg help config.subrepos' for details)
507 [255]
508 [255]
508 $ ls tc3
509 $ ls tc3
509 a
510 a
510
511
511 And again with just the hg type disabled
512 And again with just the hg type disabled
512
513
513 $ hg clone t -U tc4 --config subrepos.hg:allowed=false
514 $ hg clone t -U tc4 --config subrepos.hg:allowed=false
514 $ hg update -R tc4 --config subrepos.hg:allowed=false
515 $ hg update -R tc4 --config subrepos.hg:allowed=false
515 abort: hg subrepos not allowed
516 abort: hg subrepos not allowed
516 (see 'hg help config.subrepos' for details)
517 (see 'hg help config.subrepos' for details)
517 [255]
518 [255]
518 $ ls tc4
519 $ ls tc4
519 a
520 a
520
521
521 $ hg clone t tc5 --config subrepos.hg:allowed=false
522 $ hg clone t tc5 --config subrepos.hg:allowed=false
522 updating to branch default
523 updating to branch default
523 abort: hg subrepos not allowed
524 abort: hg subrepos not allowed
524 (see 'hg help config.subrepos' for details)
525 (see 'hg help config.subrepos' for details)
525 [255]
526 [255]
526 $ ls tc5
527 $ ls tc5
527 a
528 a
528
529
529 push
530 push
530
531
531 $ cd tc
532 $ cd tc
532 $ echo bah > t/t
533 $ echo bah > t/t
533 $ hg ci -m11
534 $ hg ci -m11
534 committing subrepository t
535 committing subrepository t
535 $ hg push
536 $ hg push
536 pushing to $TESTTMP/t
537 pushing to $TESTTMP/t
537 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss
538 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss
538 no changes made to subrepo s since last push to $TESTTMP/t/s
539 no changes made to subrepo s since last push to $TESTTMP/t/s
539 pushing subrepo t to $TESTTMP/t/t
540 pushing subrepo t to $TESTTMP/t/t
540 searching for changes
541 searching for changes
541 adding changesets
542 adding changesets
542 adding manifests
543 adding manifests
543 adding file changes
544 adding file changes
544 added 1 changesets with 1 changes to 1 files
545 added 1 changesets with 1 changes to 1 files
545 searching for changes
546 searching for changes
546 adding changesets
547 adding changesets
547 adding manifests
548 adding manifests
548 adding file changes
549 adding file changes
549 added 1 changesets with 1 changes to 1 files
550 added 1 changesets with 1 changes to 1 files
550
551
551 push -f
552 push -f
552
553
553 $ echo bah > s/a
554 $ echo bah > s/a
554 $ hg ci -m12
555 $ hg ci -m12
555 committing subrepository s
556 committing subrepository s
556 $ hg push
557 $ hg push
557 pushing to $TESTTMP/t
558 pushing to $TESTTMP/t
558 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss
559 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss
559 pushing subrepo s to $TESTTMP/t/s
560 pushing subrepo s to $TESTTMP/t/s
560 searching for changes
561 searching for changes
561 abort: push creates new remote head 12a213df6fa9! (in subrepository "s")
562 abort: push creates new remote head 12a213df6fa9! (in subrepository "s")
562 (merge or see 'hg help push' for details about pushing new heads)
563 (merge or see 'hg help push' for details about pushing new heads)
563 [255]
564 [255]
564 $ hg push -f
565 $ hg push -f
565 pushing to $TESTTMP/t
566 pushing to $TESTTMP/t
566 pushing subrepo s/ss to $TESTTMP/t/s/ss
567 pushing subrepo s/ss to $TESTTMP/t/s/ss
567 searching for changes
568 searching for changes
568 no changes found
569 no changes found
569 pushing subrepo s to $TESTTMP/t/s
570 pushing subrepo s to $TESTTMP/t/s
570 searching for changes
571 searching for changes
571 adding changesets
572 adding changesets
572 adding manifests
573 adding manifests
573 adding file changes
574 adding file changes
574 added 1 changesets with 1 changes to 1 files (+1 heads)
575 added 1 changesets with 1 changes to 1 files (+1 heads)
575 pushing subrepo t to $TESTTMP/t/t
576 pushing subrepo t to $TESTTMP/t/t
576 searching for changes
577 searching for changes
577 no changes found
578 no changes found
578 searching for changes
579 searching for changes
579 adding changesets
580 adding changesets
580 adding manifests
581 adding manifests
581 adding file changes
582 adding file changes
582 added 1 changesets with 1 changes to 1 files
583 added 1 changesets with 1 changes to 1 files
583
584
584 check that unmodified subrepos are not pushed
585 check that unmodified subrepos are not pushed
585
586
586 $ hg clone . ../tcc
587 $ hg clone . ../tcc
587 updating to branch default
588 updating to branch default
588 cloning subrepo s from $TESTTMP/tc/s
589 cloning subrepo s from $TESTTMP/tc/s
589 cloning subrepo s/ss from $TESTTMP/tc/s/ss
590 cloning subrepo s/ss from $TESTTMP/tc/s/ss
590 cloning subrepo t from $TESTTMP/tc/t
591 cloning subrepo t from $TESTTMP/tc/t
591 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
592 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
592
593
593 the subrepos on the new clone have nothing to push to its source
594 the subrepos on the new clone have nothing to push to its source
594
595
595 $ hg push -R ../tcc .
596 $ hg push -R ../tcc .
596 pushing to .
597 pushing to .
597 no changes made to subrepo s/ss since last push to s/ss
598 no changes made to subrepo s/ss since last push to s/ss
598 no changes made to subrepo s since last push to s
599 no changes made to subrepo s since last push to s
599 no changes made to subrepo t since last push to t
600 no changes made to subrepo t since last push to t
600 searching for changes
601 searching for changes
601 no changes found
602 no changes found
602 [1]
603 [1]
603
604
604 the subrepos on the source do not have a clean store versus the clone target
605 the subrepos on the source do not have a clean store versus the clone target
605 because they were never explicitly pushed to the source
606 because they were never explicitly pushed to the source
606
607
607 $ hg push ../tcc
608 $ hg push ../tcc
608 pushing to ../tcc
609 pushing to ../tcc
609 pushing subrepo s/ss to ../tcc/s/ss
610 pushing subrepo s/ss to ../tcc/s/ss
610 searching for changes
611 searching for changes
611 no changes found
612 no changes found
612 pushing subrepo s to ../tcc/s
613 pushing subrepo s to ../tcc/s
613 searching for changes
614 searching for changes
614 no changes found
615 no changes found
615 pushing subrepo t to ../tcc/t
616 pushing subrepo t to ../tcc/t
616 searching for changes
617 searching for changes
617 no changes found
618 no changes found
618 searching for changes
619 searching for changes
619 no changes found
620 no changes found
620 [1]
621 [1]
621
622
622 after push their stores become clean
623 after push their stores become clean
623
624
624 $ hg push ../tcc
625 $ hg push ../tcc
625 pushing to ../tcc
626 pushing to ../tcc
626 no changes made to subrepo s/ss since last push to ../tcc/s/ss
627 no changes made to subrepo s/ss since last push to ../tcc/s/ss
627 no changes made to subrepo s since last push to ../tcc/s
628 no changes made to subrepo s since last push to ../tcc/s
628 no changes made to subrepo t since last push to ../tcc/t
629 no changes made to subrepo t since last push to ../tcc/t
629 searching for changes
630 searching for changes
630 no changes found
631 no changes found
631 [1]
632 [1]
632
633
633 updating a subrepo to a different revision or changing
634 updating a subrepo to a different revision or changing
634 its working directory does not make its store dirty
635 its working directory does not make its store dirty
635
636
636 $ hg -R s update '.^'
637 $ hg -R s update '.^'
637 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
638 $ hg push
639 $ hg push
639 pushing to $TESTTMP/t
640 pushing to $TESTTMP/t
640 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss
641 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss
641 no changes made to subrepo s since last push to $TESTTMP/t/s
642 no changes made to subrepo s since last push to $TESTTMP/t/s
642 no changes made to subrepo t since last push to $TESTTMP/t/t
643 no changes made to subrepo t since last push to $TESTTMP/t/t
643 searching for changes
644 searching for changes
644 no changes found
645 no changes found
645 [1]
646 [1]
646 $ echo foo >> s/a
647 $ echo foo >> s/a
647 $ hg push
648 $ hg push
648 pushing to $TESTTMP/t
649 pushing to $TESTTMP/t
649 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss
650 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss
650 no changes made to subrepo s since last push to $TESTTMP/t/s
651 no changes made to subrepo s since last push to $TESTTMP/t/s
651 no changes made to subrepo t since last push to $TESTTMP/t/t
652 no changes made to subrepo t since last push to $TESTTMP/t/t
652 searching for changes
653 searching for changes
653 no changes found
654 no changes found
654 [1]
655 [1]
655 $ hg -R s update -C tip
656 $ hg -R s update -C tip
656 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
657 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
657
658
658 committing into a subrepo makes its store (but not its parent's store) dirty
659 committing into a subrepo makes its store (but not its parent's store) dirty
659
660
660 $ echo foo >> s/ss/a
661 $ echo foo >> s/ss/a
661 $ hg -R s/ss commit -m 'test dirty store detection'
662 $ hg -R s/ss commit -m 'test dirty store detection'
662
663
663 $ hg out -S -r `hg log -r tip -T "{node|short}"`
664 $ hg out -S -r `hg log -r tip -T "{node|short}"`
664 comparing with $TESTTMP/t
665 comparing with $TESTTMP/t
665 searching for changes
666 searching for changes
666 no changes found
667 no changes found
667 comparing with $TESTTMP/t/s
668 comparing with $TESTTMP/t/s
668 searching for changes
669 searching for changes
669 no changes found
670 no changes found
670 comparing with $TESTTMP/t/s/ss
671 comparing with $TESTTMP/t/s/ss
671 searching for changes
672 searching for changes
672 changeset: 1:79ea5566a333
673 changeset: 1:79ea5566a333
673 tag: tip
674 tag: tip
674 user: test
675 user: test
675 date: Thu Jan 01 00:00:00 1970 +0000
676 date: Thu Jan 01 00:00:00 1970 +0000
676 summary: test dirty store detection
677 summary: test dirty store detection
677
678
678 comparing with $TESTTMP/t/t
679 comparing with $TESTTMP/t/t
679 searching for changes
680 searching for changes
680 no changes found
681 no changes found
681
682
682 $ hg push
683 $ hg push
683 pushing to $TESTTMP/t
684 pushing to $TESTTMP/t
684 pushing subrepo s/ss to $TESTTMP/t/s/ss
685 pushing subrepo s/ss to $TESTTMP/t/s/ss
685 searching for changes
686 searching for changes
686 adding changesets
687 adding changesets
687 adding manifests
688 adding manifests
688 adding file changes
689 adding file changes
689 added 1 changesets with 1 changes to 1 files
690 added 1 changesets with 1 changes to 1 files
690 no changes made to subrepo s since last push to $TESTTMP/t/s
691 no changes made to subrepo s since last push to $TESTTMP/t/s
691 no changes made to subrepo t since last push to $TESTTMP/t/t
692 no changes made to subrepo t since last push to $TESTTMP/t/t
692 searching for changes
693 searching for changes
693 no changes found
694 no changes found
694 [1]
695 [1]
695
696
696 a subrepo store may be clean versus one repo but not versus another
697 a subrepo store may be clean versus one repo but not versus another
697
698
698 $ hg push
699 $ hg push
699 pushing to $TESTTMP/t
700 pushing to $TESTTMP/t
700 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss
701 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss
701 no changes made to subrepo s since last push to $TESTTMP/t/s
702 no changes made to subrepo s since last push to $TESTTMP/t/s
702 no changes made to subrepo t since last push to $TESTTMP/t/t
703 no changes made to subrepo t since last push to $TESTTMP/t/t
703 searching for changes
704 searching for changes
704 no changes found
705 no changes found
705 [1]
706 [1]
706 $ hg push ../tcc
707 $ hg push ../tcc
707 pushing to ../tcc
708 pushing to ../tcc
708 pushing subrepo s/ss to ../tcc/s/ss
709 pushing subrepo s/ss to ../tcc/s/ss
709 searching for changes
710 searching for changes
710 adding changesets
711 adding changesets
711 adding manifests
712 adding manifests
712 adding file changes
713 adding file changes
713 added 1 changesets with 1 changes to 1 files
714 added 1 changesets with 1 changes to 1 files
714 no changes made to subrepo s since last push to ../tcc/s
715 no changes made to subrepo s since last push to ../tcc/s
715 no changes made to subrepo t since last push to ../tcc/t
716 no changes made to subrepo t since last push to ../tcc/t
716 searching for changes
717 searching for changes
717 no changes found
718 no changes found
718 [1]
719 [1]
719
720
720 update
721 update
721
722
722 $ cd ../t
723 $ cd ../t
723 $ hg up -C # discard our earlier merge
724 $ hg up -C # discard our earlier merge
724 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
725 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
725 updated to "c373c8102e68: 12"
726 updated to "c373c8102e68: 12"
726 2 other heads for branch "default"
727 2 other heads for branch "default"
727 $ echo blah > t/t
728 $ echo blah > t/t
728 $ hg ci -m13
729 $ hg ci -m13
729 committing subrepository t
730 committing subrepository t
730
731
731 backout calls revert internally with minimal opts, which should not raise
732 backout calls revert internally with minimal opts, which should not raise
732 KeyError
733 KeyError
733
734
734 $ hg backout ".^" --no-commit
735 $ hg backout ".^" --no-commit
735 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
736 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
736 changeset c373c8102e68 backed out, don't forget to commit.
737 changeset c373c8102e68 backed out, don't forget to commit.
737
738
738 $ hg up -C # discard changes
739 $ hg up -C # discard changes
739 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
740 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
740 updated to "925c17564ef8: 13"
741 updated to "925c17564ef8: 13"
741 2 other heads for branch "default"
742 2 other heads for branch "default"
742
743
743 pull
744 pull
744
745
745 $ cd ../tc
746 $ cd ../tc
746 $ hg pull
747 $ hg pull
747 pulling from $TESTTMP/t
748 pulling from $TESTTMP/t
748 searching for changes
749 searching for changes
749 adding changesets
750 adding changesets
750 adding manifests
751 adding manifests
751 adding file changes
752 adding file changes
752 added 1 changesets with 1 changes to 1 files
753 added 1 changesets with 1 changes to 1 files
753 new changesets 925c17564ef8
754 new changesets 925c17564ef8
754 (run 'hg update' to get a working copy)
755 (run 'hg update' to get a working copy)
755
756
756 should pull t
757 should pull t
757
758
758 $ hg incoming -S -r `hg log -r tip -T "{node|short}"`
759 $ hg incoming -S -r `hg log -r tip -T "{node|short}"`
759 comparing with $TESTTMP/t
760 comparing with $TESTTMP/t
760 no changes found
761 no changes found
761 comparing with $TESTTMP/t/s
762 comparing with $TESTTMP/t/s
762 searching for changes
763 searching for changes
763 no changes found
764 no changes found
764 comparing with $TESTTMP/t/s/ss
765 comparing with $TESTTMP/t/s/ss
765 searching for changes
766 searching for changes
766 no changes found
767 no changes found
767 comparing with $TESTTMP/t/t
768 comparing with $TESTTMP/t/t
768 searching for changes
769 searching for changes
769 changeset: 5:52c0adc0515a
770 changeset: 5:52c0adc0515a
770 tag: tip
771 tag: tip
771 user: test
772 user: test
772 date: Thu Jan 01 00:00:00 1970 +0000
773 date: Thu Jan 01 00:00:00 1970 +0000
773 summary: 13
774 summary: 13
774
775
775
776
776 $ hg up
777 $ hg up
777 pulling subrepo t from $TESTTMP/t/t
778 pulling subrepo t from $TESTTMP/t/t
778 searching for changes
779 searching for changes
779 adding changesets
780 adding changesets
780 adding manifests
781 adding manifests
781 adding file changes
782 adding file changes
782 added 1 changesets with 1 changes to 1 files
783 added 1 changesets with 1 changes to 1 files
783 new changesets 52c0adc0515a
784 new changesets 52c0adc0515a
784 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
785 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
785 updated to "925c17564ef8: 13"
786 updated to "925c17564ef8: 13"
786 2 other heads for branch "default"
787 2 other heads for branch "default"
787 $ cat t/t
788 $ cat t/t
788 blah
789 blah
789
790
790 bogus subrepo path aborts
791 bogus subrepo path aborts
791
792
792 $ echo 'bogus=[boguspath' >> .hgsub
793 $ echo 'bogus=[boguspath' >> .hgsub
793 $ hg ci -m 'bogus subrepo path'
794 $ hg ci -m 'bogus subrepo path'
794 abort: missing ] in subrepository source
795 abort: missing ] in subrepository source
795 [255]
796 [255]
796
797
797 Issue1986: merge aborts when trying to merge a subrepo that
798 Issue1986: merge aborts when trying to merge a subrepo that
798 shouldn't need merging
799 shouldn't need merging
799
800
800 # subrepo layout
801 # subrepo layout
801 #
802 #
802 # o 5 br
803 # o 5 br
803 # /|
804 # /|
804 # o | 4 default
805 # o | 4 default
805 # | |
806 # | |
806 # | o 3 br
807 # | o 3 br
807 # |/|
808 # |/|
808 # o | 2 default
809 # o | 2 default
809 # | |
810 # | |
810 # | o 1 br
811 # | o 1 br
811 # |/
812 # |/
812 # o 0 default
813 # o 0 default
813
814
814 $ cd ..
815 $ cd ..
815 $ rm -rf sub
816 $ rm -rf sub
816 $ hg init main
817 $ hg init main
817 $ cd main
818 $ cd main
818 $ hg init s
819 $ hg init s
819 $ cd s
820 $ cd s
820 $ echo a > a
821 $ echo a > a
821 $ hg ci -Am1
822 $ hg ci -Am1
822 adding a
823 adding a
823 $ hg branch br
824 $ hg branch br
824 marked working directory as branch br
825 marked working directory as branch br
825 (branches are permanent and global, did you want a bookmark?)
826 (branches are permanent and global, did you want a bookmark?)
826 $ echo a >> a
827 $ echo a >> a
827 $ hg ci -m1
828 $ hg ci -m1
828 $ hg up default
829 $ hg up default
829 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
830 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
830 $ echo b > b
831 $ echo b > b
831 $ hg ci -Am1
832 $ hg ci -Am1
832 adding b
833 adding b
833 $ hg up br
834 $ hg up br
834 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
835 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
835 $ hg merge tip
836 $ hg merge tip
836 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
837 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
837 (branch merge, don't forget to commit)
838 (branch merge, don't forget to commit)
838 $ hg ci -m1
839 $ hg ci -m1
839 $ hg up 2
840 $ hg up 2
840 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
841 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
841 $ echo c > c
842 $ echo c > c
842 $ hg ci -Am1
843 $ hg ci -Am1
843 adding c
844 adding c
844 $ hg up 3
845 $ hg up 3
845 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
846 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
846 $ hg merge 4
847 $ hg merge 4
847 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
848 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
848 (branch merge, don't forget to commit)
849 (branch merge, don't forget to commit)
849 $ hg ci -m1
850 $ hg ci -m1
850
851
851 # main repo layout:
852 # main repo layout:
852 #
853 #
853 # * <-- try to merge default into br again
854 # * <-- try to merge default into br again
854 # .`|
855 # .`|
855 # . o 5 br --> substate = 5
856 # . o 5 br --> substate = 5
856 # . |
857 # . |
857 # o | 4 default --> substate = 4
858 # o | 4 default --> substate = 4
858 # | |
859 # | |
859 # | o 3 br --> substate = 2
860 # | o 3 br --> substate = 2
860 # |/|
861 # |/|
861 # o | 2 default --> substate = 2
862 # o | 2 default --> substate = 2
862 # | |
863 # | |
863 # | o 1 br --> substate = 3
864 # | o 1 br --> substate = 3
864 # |/
865 # |/
865 # o 0 default --> substate = 2
866 # o 0 default --> substate = 2
866
867
867 $ cd ..
868 $ cd ..
868 $ echo 's = s' > .hgsub
869 $ echo 's = s' > .hgsub
869 $ hg -R s up 2
870 $ hg -R s up 2
870 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
871 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
871 $ hg ci -Am1
872 $ hg ci -Am1
872 adding .hgsub
873 adding .hgsub
873 $ hg branch br
874 $ hg branch br
874 marked working directory as branch br
875 marked working directory as branch br
875 (branches are permanent and global, did you want a bookmark?)
876 (branches are permanent and global, did you want a bookmark?)
876 $ echo b > b
877 $ echo b > b
877 $ hg -R s up 3
878 $ hg -R s up 3
878 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
879 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
879 $ hg ci -Am1
880 $ hg ci -Am1
880 adding b
881 adding b
881 $ hg up default
882 $ hg up default
882 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
883 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
883 $ echo c > c
884 $ echo c > c
884 $ hg ci -Am1
885 $ hg ci -Am1
885 adding c
886 adding c
886 $ hg up 1
887 $ hg up 1
887 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
888 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
888 $ hg merge 2
889 $ hg merge 2
889 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
890 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
890 (branch merge, don't forget to commit)
891 (branch merge, don't forget to commit)
891 $ hg ci -m1
892 $ hg ci -m1
892 $ hg up 2
893 $ hg up 2
893 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
894 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
894 $ hg -R s up 4
895 $ hg -R s up 4
895 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
896 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
896 $ echo d > d
897 $ echo d > d
897 $ hg ci -Am1
898 $ hg ci -Am1
898 adding d
899 adding d
899 $ hg up 3
900 $ hg up 3
900 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
901 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
901 $ hg -R s up 5
902 $ hg -R s up 5
902 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
903 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
903 $ echo e > e
904 $ echo e > e
904 $ hg ci -Am1
905 $ hg ci -Am1
905 adding e
906 adding e
906
907
907 $ hg up 5
908 $ hg up 5
908 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
909 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
909 $ hg merge 4 # try to merge default into br again
910 $ hg merge 4 # try to merge default into br again
910 subrepository s diverged (local revision: f8f13b33206e, remote revision: a3f9062a4f88)
911 subrepository s diverged (local revision: f8f13b33206e, remote revision: a3f9062a4f88)
911 (M)erge, keep (l)ocal [working copy] or keep (r)emote [merge rev]? m
912 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [merge rev].
913 what do you want to do? m
912 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
914 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
913 (branch merge, don't forget to commit)
915 (branch merge, don't forget to commit)
914 $ cd ..
916 $ cd ..
915
917
916 test subrepo delete from .hgsubstate
918 test subrepo delete from .hgsubstate
917
919
918 $ hg init testdelete
920 $ hg init testdelete
919 $ mkdir testdelete/nested testdelete/nested2
921 $ mkdir testdelete/nested testdelete/nested2
920 $ hg init testdelete/nested
922 $ hg init testdelete/nested
921 $ hg init testdelete/nested2
923 $ hg init testdelete/nested2
922 $ echo test > testdelete/nested/foo
924 $ echo test > testdelete/nested/foo
923 $ echo test > testdelete/nested2/foo
925 $ echo test > testdelete/nested2/foo
924 $ hg -R testdelete/nested add
926 $ hg -R testdelete/nested add
925 adding testdelete/nested/foo
927 adding testdelete/nested/foo
926 $ hg -R testdelete/nested2 add
928 $ hg -R testdelete/nested2 add
927 adding testdelete/nested2/foo
929 adding testdelete/nested2/foo
928 $ hg -R testdelete/nested ci -m test
930 $ hg -R testdelete/nested ci -m test
929 $ hg -R testdelete/nested2 ci -m test
931 $ hg -R testdelete/nested2 ci -m test
930 $ echo nested = nested > testdelete/.hgsub
932 $ echo nested = nested > testdelete/.hgsub
931 $ echo nested2 = nested2 >> testdelete/.hgsub
933 $ echo nested2 = nested2 >> testdelete/.hgsub
932 $ hg -R testdelete add
934 $ hg -R testdelete add
933 adding testdelete/.hgsub
935 adding testdelete/.hgsub
934 $ hg -R testdelete ci -m "nested 1 & 2 added"
936 $ hg -R testdelete ci -m "nested 1 & 2 added"
935 $ echo nested = nested > testdelete/.hgsub
937 $ echo nested = nested > testdelete/.hgsub
936 $ hg -R testdelete ci -m "nested 2 deleted"
938 $ hg -R testdelete ci -m "nested 2 deleted"
937 $ cat testdelete/.hgsubstate
939 $ cat testdelete/.hgsubstate
938 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
940 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
939 $ hg -R testdelete remove testdelete/.hgsub
941 $ hg -R testdelete remove testdelete/.hgsub
940 $ hg -R testdelete ci -m ".hgsub deleted"
942 $ hg -R testdelete ci -m ".hgsub deleted"
941 $ cat testdelete/.hgsubstate
943 $ cat testdelete/.hgsubstate
942 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
944 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
943
945
944 test repository cloning
946 test repository cloning
945
947
946 $ mkdir mercurial mercurial2
948 $ mkdir mercurial mercurial2
947 $ hg init nested_absolute
949 $ hg init nested_absolute
948 $ echo test > nested_absolute/foo
950 $ echo test > nested_absolute/foo
949 $ hg -R nested_absolute add
951 $ hg -R nested_absolute add
950 adding nested_absolute/foo
952 adding nested_absolute/foo
951 $ hg -R nested_absolute ci -mtest
953 $ hg -R nested_absolute ci -mtest
952 $ cd mercurial
954 $ cd mercurial
953 $ hg init nested_relative
955 $ hg init nested_relative
954 $ echo test2 > nested_relative/foo2
956 $ echo test2 > nested_relative/foo2
955 $ hg -R nested_relative add
957 $ hg -R nested_relative add
956 adding nested_relative/foo2
958 adding nested_relative/foo2
957 $ hg -R nested_relative ci -mtest2
959 $ hg -R nested_relative ci -mtest2
958 $ hg init main
960 $ hg init main
959 $ echo "nested_relative = ../nested_relative" > main/.hgsub
961 $ echo "nested_relative = ../nested_relative" > main/.hgsub
960 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
962 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
961 $ hg -R main add
963 $ hg -R main add
962 adding main/.hgsub
964 adding main/.hgsub
963 $ hg -R main ci -m "add subrepos"
965 $ hg -R main ci -m "add subrepos"
964 $ cd ..
966 $ cd ..
965 $ hg clone mercurial/main mercurial2/main
967 $ hg clone mercurial/main mercurial2/main
966 updating to branch default
968 updating to branch default
967 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
969 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
968 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
970 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
969 > mercurial2/main/nested_relative/.hg/hgrc
971 > mercurial2/main/nested_relative/.hg/hgrc
970 [paths]
972 [paths]
971 default = $TESTTMP/mercurial/nested_absolute
973 default = $TESTTMP/mercurial/nested_absolute
972 [paths]
974 [paths]
973 default = $TESTTMP/mercurial/nested_relative
975 default = $TESTTMP/mercurial/nested_relative
974 $ rm -rf mercurial mercurial2
976 $ rm -rf mercurial mercurial2
975
977
976 Issue1977: multirepo push should fail if subrepo push fails
978 Issue1977: multirepo push should fail if subrepo push fails
977
979
978 $ hg init repo
980 $ hg init repo
979 $ hg init repo/s
981 $ hg init repo/s
980 $ echo a > repo/s/a
982 $ echo a > repo/s/a
981 $ hg -R repo/s ci -Am0
983 $ hg -R repo/s ci -Am0
982 adding a
984 adding a
983 $ echo s = s > repo/.hgsub
985 $ echo s = s > repo/.hgsub
984 $ hg -R repo ci -Am1
986 $ hg -R repo ci -Am1
985 adding .hgsub
987 adding .hgsub
986 $ hg clone repo repo2
988 $ hg clone repo repo2
987 updating to branch default
989 updating to branch default
988 cloning subrepo s from $TESTTMP/repo/s
990 cloning subrepo s from $TESTTMP/repo/s
989 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
991 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
990 $ hg -q -R repo2 pull -u
992 $ hg -q -R repo2 pull -u
991 $ echo 1 > repo2/s/a
993 $ echo 1 > repo2/s/a
992 $ hg -R repo2/s ci -m2
994 $ hg -R repo2/s ci -m2
993 $ hg -q -R repo2/s push
995 $ hg -q -R repo2/s push
994 $ hg -R repo2/s up -C 0
996 $ hg -R repo2/s up -C 0
995 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
997 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
996 $ echo 2 > repo2/s/b
998 $ echo 2 > repo2/s/b
997 $ hg -R repo2/s ci -m3 -A
999 $ hg -R repo2/s ci -m3 -A
998 adding b
1000 adding b
999 created new head
1001 created new head
1000 $ hg -R repo2 ci -m3
1002 $ hg -R repo2 ci -m3
1001 $ hg -q -R repo2 push
1003 $ hg -q -R repo2 push
1002 abort: push creates new remote head cc505f09a8b2! (in subrepository "s")
1004 abort: push creates new remote head cc505f09a8b2! (in subrepository "s")
1003 (merge or see 'hg help push' for details about pushing new heads)
1005 (merge or see 'hg help push' for details about pushing new heads)
1004 [255]
1006 [255]
1005 $ hg -R repo update
1007 $ hg -R repo update
1006 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1008 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1007
1009
1008 test if untracked file is not overwritten
1010 test if untracked file is not overwritten
1009
1011
1010 (this also tests that updated .hgsubstate is treated as "modified",
1012 (this also tests that updated .hgsubstate is treated as "modified",
1011 when 'merge.update()' is aborted before 'merge.recordupdates()', even
1013 when 'merge.update()' is aborted before 'merge.recordupdates()', even
1012 if none of mode, size and timestamp of it isn't changed on the
1014 if none of mode, size and timestamp of it isn't changed on the
1013 filesystem (see also issue4583))
1015 filesystem (see also issue4583))
1014
1016
1015 $ echo issue3276_ok > repo/s/b
1017 $ echo issue3276_ok > repo/s/b
1016 $ hg -R repo2 push -f -q
1018 $ hg -R repo2 push -f -q
1017 $ touch -t 200001010000 repo/.hgsubstate
1019 $ touch -t 200001010000 repo/.hgsubstate
1018
1020
1019 $ cat >> repo/.hg/hgrc <<EOF
1021 $ cat >> repo/.hg/hgrc <<EOF
1020 > [fakedirstatewritetime]
1022 > [fakedirstatewritetime]
1021 > # emulate invoking dirstate.write() via repo.status()
1023 > # emulate invoking dirstate.write() via repo.status()
1022 > # at 2000-01-01 00:00
1024 > # at 2000-01-01 00:00
1023 > fakenow = 200001010000
1025 > fakenow = 200001010000
1024 >
1026 >
1025 > [extensions]
1027 > [extensions]
1026 > fakedirstatewritetime = $TESTDIR/fakedirstatewritetime.py
1028 > fakedirstatewritetime = $TESTDIR/fakedirstatewritetime.py
1027 > EOF
1029 > EOF
1028 $ hg -R repo update
1030 $ hg -R repo update
1029 b: untracked file differs
1031 b: untracked file differs
1030 abort: untracked files in working directory differ from files in requested revision (in subrepository "s")
1032 abort: untracked files in working directory differ from files in requested revision (in subrepository "s")
1031 [255]
1033 [255]
1032 $ cat >> repo/.hg/hgrc <<EOF
1034 $ cat >> repo/.hg/hgrc <<EOF
1033 > [extensions]
1035 > [extensions]
1034 > fakedirstatewritetime = !
1036 > fakedirstatewritetime = !
1035 > EOF
1037 > EOF
1036
1038
1037 $ cat repo/s/b
1039 $ cat repo/s/b
1038 issue3276_ok
1040 issue3276_ok
1039 $ rm repo/s/b
1041 $ rm repo/s/b
1040 $ touch -t 200001010000 repo/.hgsubstate
1042 $ touch -t 200001010000 repo/.hgsubstate
1041 $ hg -R repo revert --all
1043 $ hg -R repo revert --all
1042 reverting repo/.hgsubstate
1044 reverting repo/.hgsubstate
1043 reverting subrepo s
1045 reverting subrepo s
1044 $ hg -R repo update
1046 $ hg -R repo update
1045 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1047 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1046 $ cat repo/s/b
1048 $ cat repo/s/b
1047 2
1049 2
1048 $ rm -rf repo2 repo
1050 $ rm -rf repo2 repo
1049
1051
1050
1052
1051 Issue1852 subrepos with relative paths always push/pull relative to default
1053 Issue1852 subrepos with relative paths always push/pull relative to default
1052
1054
1053 Prepare a repo with subrepo
1055 Prepare a repo with subrepo
1054
1056
1055 $ hg init issue1852a
1057 $ hg init issue1852a
1056 $ cd issue1852a
1058 $ cd issue1852a
1057 $ hg init sub/repo
1059 $ hg init sub/repo
1058 $ echo test > sub/repo/foo
1060 $ echo test > sub/repo/foo
1059 $ hg -R sub/repo add sub/repo/foo
1061 $ hg -R sub/repo add sub/repo/foo
1060 $ echo sub/repo = sub/repo > .hgsub
1062 $ echo sub/repo = sub/repo > .hgsub
1061 $ hg add .hgsub
1063 $ hg add .hgsub
1062 $ hg ci -mtest
1064 $ hg ci -mtest
1063 committing subrepository sub/repo
1065 committing subrepository sub/repo
1064 $ echo test >> sub/repo/foo
1066 $ echo test >> sub/repo/foo
1065 $ hg ci -mtest
1067 $ hg ci -mtest
1066 committing subrepository sub/repo
1068 committing subrepository sub/repo
1067 $ hg cat sub/repo/foo
1069 $ hg cat sub/repo/foo
1068 test
1070 test
1069 test
1071 test
1070 $ hg cat sub/repo/foo -Tjson | sed 's|\\\\|/|g'
1072 $ hg cat sub/repo/foo -Tjson | sed 's|\\\\|/|g'
1071 [
1073 [
1072 {
1074 {
1073 "data": "test\ntest\n",
1075 "data": "test\ntest\n",
1074 "path": "foo"
1076 "path": "foo"
1075 }
1077 }
1076 ]
1078 ]
1077
1079
1078 non-exact match:
1080 non-exact match:
1079
1081
1080 $ hg cat -T '{path|relpath}\n' 'glob:**'
1082 $ hg cat -T '{path|relpath}\n' 'glob:**'
1081 .hgsub
1083 .hgsub
1082 .hgsubstate
1084 .hgsubstate
1083 sub/repo/foo
1085 sub/repo/foo
1084 $ hg cat -T '{path|relpath}\n' 're:^sub'
1086 $ hg cat -T '{path|relpath}\n' 're:^sub'
1085 sub/repo/foo
1087 sub/repo/foo
1086
1088
1087 missing subrepos in working directory:
1089 missing subrepos in working directory:
1088
1090
1089 $ mkdir -p tmp/sub/repo
1091 $ mkdir -p tmp/sub/repo
1090 $ hg cat -r 0 --output tmp/%p_p sub/repo/foo
1092 $ hg cat -r 0 --output tmp/%p_p sub/repo/foo
1091 $ cat tmp/sub/repo/foo_p
1093 $ cat tmp/sub/repo/foo_p
1092 test
1094 test
1093 $ mv sub/repo sub_
1095 $ mv sub/repo sub_
1094 $ hg cat sub/repo/baz
1096 $ hg cat sub/repo/baz
1095 skipping missing subrepository: sub/repo
1097 skipping missing subrepository: sub/repo
1096 [1]
1098 [1]
1097 $ rm -rf sub/repo
1099 $ rm -rf sub/repo
1098 $ mv sub_ sub/repo
1100 $ mv sub_ sub/repo
1099 $ cd ..
1101 $ cd ..
1100
1102
1101 Create repo without default path, pull top repo, and see what happens on update
1103 Create repo without default path, pull top repo, and see what happens on update
1102
1104
1103 $ hg init issue1852b
1105 $ hg init issue1852b
1104 $ hg -R issue1852b pull issue1852a
1106 $ hg -R issue1852b pull issue1852a
1105 pulling from issue1852a
1107 pulling from issue1852a
1106 requesting all changes
1108 requesting all changes
1107 adding changesets
1109 adding changesets
1108 adding manifests
1110 adding manifests
1109 adding file changes
1111 adding file changes
1110 added 2 changesets with 3 changes to 2 files
1112 added 2 changesets with 3 changes to 2 files
1111 new changesets 19487b456929:be5eb94e7215
1113 new changesets 19487b456929:be5eb94e7215
1112 (run 'hg update' to get a working copy)
1114 (run 'hg update' to get a working copy)
1113 $ hg -R issue1852b update
1115 $ hg -R issue1852b update
1114 abort: default path for subrepository not found (in subrepository "sub/repo")
1116 abort: default path for subrepository not found (in subrepository "sub/repo")
1115 [255]
1117 [255]
1116
1118
1117 Ensure a full traceback, not just the SubrepoAbort part
1119 Ensure a full traceback, not just the SubrepoAbort part
1118
1120
1119 $ hg -R issue1852b update --traceback 2>&1 | grep 'raise error\.Abort'
1121 $ hg -R issue1852b update --traceback 2>&1 | grep 'raise error\.Abort'
1120 raise error.Abort(_("default path for subrepository not found"))
1122 raise error.Abort(_("default path for subrepository not found"))
1121
1123
1122 Pull -u now doesn't help
1124 Pull -u now doesn't help
1123
1125
1124 $ hg -R issue1852b pull -u issue1852a
1126 $ hg -R issue1852b pull -u issue1852a
1125 pulling from issue1852a
1127 pulling from issue1852a
1126 searching for changes
1128 searching for changes
1127 no changes found
1129 no changes found
1128
1130
1129 Try the same, but with pull -u
1131 Try the same, but with pull -u
1130
1132
1131 $ hg init issue1852c
1133 $ hg init issue1852c
1132 $ hg -R issue1852c pull -r0 -u issue1852a
1134 $ hg -R issue1852c pull -r0 -u issue1852a
1133 pulling from issue1852a
1135 pulling from issue1852a
1134 adding changesets
1136 adding changesets
1135 adding manifests
1137 adding manifests
1136 adding file changes
1138 adding file changes
1137 added 1 changesets with 2 changes to 2 files
1139 added 1 changesets with 2 changes to 2 files
1138 new changesets 19487b456929
1140 new changesets 19487b456929
1139 cloning subrepo sub/repo from issue1852a/sub/repo
1141 cloning subrepo sub/repo from issue1852a/sub/repo
1140 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1142 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1141
1143
1142 Try to push from the other side
1144 Try to push from the other side
1143
1145
1144 $ hg -R issue1852a push `pwd`/issue1852c
1146 $ hg -R issue1852a push `pwd`/issue1852c
1145 pushing to $TESTTMP/issue1852c
1147 pushing to $TESTTMP/issue1852c
1146 pushing subrepo sub/repo to $TESTTMP/issue1852c/sub/repo
1148 pushing subrepo sub/repo to $TESTTMP/issue1852c/sub/repo
1147 searching for changes
1149 searching for changes
1148 no changes found
1150 no changes found
1149 searching for changes
1151 searching for changes
1150 adding changesets
1152 adding changesets
1151 adding manifests
1153 adding manifests
1152 adding file changes
1154 adding file changes
1153 added 1 changesets with 1 changes to 1 files
1155 added 1 changesets with 1 changes to 1 files
1154
1156
1155 Incoming and outgoing should not use the default path:
1157 Incoming and outgoing should not use the default path:
1156
1158
1157 $ hg clone -q issue1852a issue1852d
1159 $ hg clone -q issue1852a issue1852d
1158 $ hg -R issue1852d outgoing --subrepos issue1852c
1160 $ hg -R issue1852d outgoing --subrepos issue1852c
1159 comparing with issue1852c
1161 comparing with issue1852c
1160 searching for changes
1162 searching for changes
1161 no changes found
1163 no changes found
1162 comparing with issue1852c/sub/repo
1164 comparing with issue1852c/sub/repo
1163 searching for changes
1165 searching for changes
1164 no changes found
1166 no changes found
1165 [1]
1167 [1]
1166 $ hg -R issue1852d incoming --subrepos issue1852c
1168 $ hg -R issue1852d incoming --subrepos issue1852c
1167 comparing with issue1852c
1169 comparing with issue1852c
1168 searching for changes
1170 searching for changes
1169 no changes found
1171 no changes found
1170 comparing with issue1852c/sub/repo
1172 comparing with issue1852c/sub/repo
1171 searching for changes
1173 searching for changes
1172 no changes found
1174 no changes found
1173 [1]
1175 [1]
1174
1176
1175 Check that merge of a new subrepo doesn't write the uncommitted state to
1177 Check that merge of a new subrepo doesn't write the uncommitted state to
1176 .hgsubstate (issue4622)
1178 .hgsubstate (issue4622)
1177
1179
1178 $ hg init issue1852a/addedsub
1180 $ hg init issue1852a/addedsub
1179 $ echo zzz > issue1852a/addedsub/zz.txt
1181 $ echo zzz > issue1852a/addedsub/zz.txt
1180 $ hg -R issue1852a/addedsub ci -Aqm "initial ZZ"
1182 $ hg -R issue1852a/addedsub ci -Aqm "initial ZZ"
1181
1183
1182 $ hg clone issue1852a/addedsub issue1852d/addedsub
1184 $ hg clone issue1852a/addedsub issue1852d/addedsub
1183 updating to branch default
1185 updating to branch default
1184 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1186 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1185
1187
1186 $ echo def > issue1852a/sub/repo/foo
1188 $ echo def > issue1852a/sub/repo/foo
1187 $ hg -R issue1852a ci -SAm 'tweaked subrepo'
1189 $ hg -R issue1852a ci -SAm 'tweaked subrepo'
1188 adding tmp/sub/repo/foo_p
1190 adding tmp/sub/repo/foo_p
1189 committing subrepository sub/repo
1191 committing subrepository sub/repo
1190
1192
1191 $ echo 'addedsub = addedsub' >> issue1852d/.hgsub
1193 $ echo 'addedsub = addedsub' >> issue1852d/.hgsub
1192 $ echo xyz > issue1852d/sub/repo/foo
1194 $ echo xyz > issue1852d/sub/repo/foo
1193 $ hg -R issue1852d pull -u
1195 $ hg -R issue1852d pull -u
1194 pulling from $TESTTMP/issue1852a
1196 pulling from $TESTTMP/issue1852a
1195 searching for changes
1197 searching for changes
1196 adding changesets
1198 adding changesets
1197 adding manifests
1199 adding manifests
1198 adding file changes
1200 adding file changes
1199 added 1 changesets with 2 changes to 2 files
1201 added 1 changesets with 2 changes to 2 files
1200 new changesets c82b79fdcc5b
1202 new changesets c82b79fdcc5b
1201 subrepository sub/repo diverged (local revision: f42d5c7504a8, remote revision: 46cd4aac504c)
1203 subrepository sub/repo diverged (local revision: f42d5c7504a8, remote revision: 46cd4aac504c)
1202 (M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
1204 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [destination].
1205 what do you want to do? m
1203 pulling subrepo sub/repo from $TESTTMP/issue1852a/sub/repo
1206 pulling subrepo sub/repo from $TESTTMP/issue1852a/sub/repo
1204 searching for changes
1207 searching for changes
1205 adding changesets
1208 adding changesets
1206 adding manifests
1209 adding manifests
1207 adding file changes
1210 adding file changes
1208 added 1 changesets with 1 changes to 1 files
1211 added 1 changesets with 1 changes to 1 files
1209 new changesets 46cd4aac504c
1212 new changesets 46cd4aac504c
1210 subrepository sources for sub/repo differ
1213 subrepository sources for sub/repo differ
1211 use (l)ocal source (f42d5c7504a8) or (r)emote source (46cd4aac504c)? l
1214 you can use (l)ocal source (f42d5c7504a8) or (r)emote source (46cd4aac504c).
1215 what do you want to do? l
1212 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1216 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1213 $ cat issue1852d/.hgsubstate
1217 $ cat issue1852d/.hgsubstate
1214 f42d5c7504a811dda50f5cf3e5e16c3330b87172 sub/repo
1218 f42d5c7504a811dda50f5cf3e5e16c3330b87172 sub/repo
1215
1219
1216 Check status of files when none of them belong to the first
1220 Check status of files when none of them belong to the first
1217 subrepository:
1221 subrepository:
1218
1222
1219 $ hg init subrepo-status
1223 $ hg init subrepo-status
1220 $ cd subrepo-status
1224 $ cd subrepo-status
1221 $ hg init subrepo-1
1225 $ hg init subrepo-1
1222 $ hg init subrepo-2
1226 $ hg init subrepo-2
1223 $ cd subrepo-2
1227 $ cd subrepo-2
1224 $ touch file
1228 $ touch file
1225 $ hg add file
1229 $ hg add file
1226 $ cd ..
1230 $ cd ..
1227 $ echo subrepo-1 = subrepo-1 > .hgsub
1231 $ echo subrepo-1 = subrepo-1 > .hgsub
1228 $ echo subrepo-2 = subrepo-2 >> .hgsub
1232 $ echo subrepo-2 = subrepo-2 >> .hgsub
1229 $ hg add .hgsub
1233 $ hg add .hgsub
1230 $ hg ci -m 'Added subrepos'
1234 $ hg ci -m 'Added subrepos'
1231 committing subrepository subrepo-2
1235 committing subrepository subrepo-2
1232 $ hg st subrepo-2/file
1236 $ hg st subrepo-2/file
1233
1237
1234 Check that share works with subrepo
1238 Check that share works with subrepo
1235 $ hg --config extensions.share= share . ../shared
1239 $ hg --config extensions.share= share . ../shared
1236 updating working directory
1240 updating working directory
1237 sharing subrepo subrepo-1 from $TESTTMP/subrepo-status/subrepo-1
1241 sharing subrepo subrepo-1 from $TESTTMP/subrepo-status/subrepo-1
1238 sharing subrepo subrepo-2 from $TESTTMP/subrepo-status/subrepo-2
1242 sharing subrepo subrepo-2 from $TESTTMP/subrepo-status/subrepo-2
1239 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1243 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1240 $ find ../shared/* | sort
1244 $ find ../shared/* | sort
1241 ../shared/subrepo-1
1245 ../shared/subrepo-1
1242 ../shared/subrepo-1/.hg
1246 ../shared/subrepo-1/.hg
1243 ../shared/subrepo-1/.hg/cache
1247 ../shared/subrepo-1/.hg/cache
1244 ../shared/subrepo-1/.hg/cache/storehash
1248 ../shared/subrepo-1/.hg/cache/storehash
1245 ../shared/subrepo-1/.hg/cache/storehash/* (glob)
1249 ../shared/subrepo-1/.hg/cache/storehash/* (glob)
1246 ../shared/subrepo-1/.hg/hgrc
1250 ../shared/subrepo-1/.hg/hgrc
1247 ../shared/subrepo-1/.hg/requires
1251 ../shared/subrepo-1/.hg/requires
1248 ../shared/subrepo-1/.hg/sharedpath
1252 ../shared/subrepo-1/.hg/sharedpath
1249 ../shared/subrepo-1/.hg/wcache
1253 ../shared/subrepo-1/.hg/wcache
1250 ../shared/subrepo-2
1254 ../shared/subrepo-2
1251 ../shared/subrepo-2/.hg
1255 ../shared/subrepo-2/.hg
1252 ../shared/subrepo-2/.hg/branch
1256 ../shared/subrepo-2/.hg/branch
1253 ../shared/subrepo-2/.hg/cache
1257 ../shared/subrepo-2/.hg/cache
1254 ../shared/subrepo-2/.hg/cache/storehash
1258 ../shared/subrepo-2/.hg/cache/storehash
1255 ../shared/subrepo-2/.hg/cache/storehash/* (glob)
1259 ../shared/subrepo-2/.hg/cache/storehash/* (glob)
1256 ../shared/subrepo-2/.hg/dirstate
1260 ../shared/subrepo-2/.hg/dirstate
1257 ../shared/subrepo-2/.hg/hgrc
1261 ../shared/subrepo-2/.hg/hgrc
1258 ../shared/subrepo-2/.hg/requires
1262 ../shared/subrepo-2/.hg/requires
1259 ../shared/subrepo-2/.hg/sharedpath
1263 ../shared/subrepo-2/.hg/sharedpath
1260 ../shared/subrepo-2/.hg/wcache
1264 ../shared/subrepo-2/.hg/wcache
1261 ../shared/subrepo-2/.hg/wcache/checkisexec (execbit !)
1265 ../shared/subrepo-2/.hg/wcache/checkisexec (execbit !)
1262 ../shared/subrepo-2/.hg/wcache/checklink (symlink !)
1266 ../shared/subrepo-2/.hg/wcache/checklink (symlink !)
1263 ../shared/subrepo-2/.hg/wcache/checklink-target (symlink !)
1267 ../shared/subrepo-2/.hg/wcache/checklink-target (symlink !)
1264 ../shared/subrepo-2/.hg/wcache/manifestfulltextcache (reporevlogstore !)
1268 ../shared/subrepo-2/.hg/wcache/manifestfulltextcache (reporevlogstore !)
1265 ../shared/subrepo-2/file
1269 ../shared/subrepo-2/file
1266 $ hg -R ../shared in
1270 $ hg -R ../shared in
1267 abort: repository default not found!
1271 abort: repository default not found!
1268 [255]
1272 [255]
1269 $ hg -R ../shared/subrepo-2 showconfig paths
1273 $ hg -R ../shared/subrepo-2 showconfig paths
1270 paths.default=$TESTTMP/subrepo-status/subrepo-2
1274 paths.default=$TESTTMP/subrepo-status/subrepo-2
1271 $ hg -R ../shared/subrepo-1 sum --remote
1275 $ hg -R ../shared/subrepo-1 sum --remote
1272 parent: -1:000000000000 tip (empty repository)
1276 parent: -1:000000000000 tip (empty repository)
1273 branch: default
1277 branch: default
1274 commit: (clean)
1278 commit: (clean)
1275 update: (current)
1279 update: (current)
1276 remote: (synced)
1280 remote: (synced)
1277
1281
1278 Check hg update --clean
1282 Check hg update --clean
1279 $ cd $TESTTMP/t
1283 $ cd $TESTTMP/t
1280 $ rm -r t/t.orig
1284 $ rm -r t/t.orig
1281 $ hg status -S --all
1285 $ hg status -S --all
1282 C .hgsub
1286 C .hgsub
1283 C .hgsubstate
1287 C .hgsubstate
1284 C a
1288 C a
1285 C s/.hgsub
1289 C s/.hgsub
1286 C s/.hgsubstate
1290 C s/.hgsubstate
1287 C s/a
1291 C s/a
1288 C s/ss/a
1292 C s/ss/a
1289 C t/t
1293 C t/t
1290 $ echo c1 > s/a
1294 $ echo c1 > s/a
1291 $ cd s
1295 $ cd s
1292 $ echo c1 > b
1296 $ echo c1 > b
1293 $ echo c1 > c
1297 $ echo c1 > c
1294 $ hg add b
1298 $ hg add b
1295 $ cd ..
1299 $ cd ..
1296 $ hg status -S
1300 $ hg status -S
1297 M s/a
1301 M s/a
1298 A s/b
1302 A s/b
1299 ? s/c
1303 ? s/c
1300 $ hg update -C
1304 $ hg update -C
1301 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1305 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1302 updated to "925c17564ef8: 13"
1306 updated to "925c17564ef8: 13"
1303 2 other heads for branch "default"
1307 2 other heads for branch "default"
1304 $ hg status -S
1308 $ hg status -S
1305 ? s/b
1309 ? s/b
1306 ? s/c
1310 ? s/c
1307
1311
1308 Sticky subrepositories, no changes
1312 Sticky subrepositories, no changes
1309 $ cd $TESTTMP/t
1313 $ cd $TESTTMP/t
1310 $ hg id
1314 $ hg id
1311 925c17564ef8 tip
1315 925c17564ef8 tip
1312 $ hg -R s id
1316 $ hg -R s id
1313 12a213df6fa9 tip
1317 12a213df6fa9 tip
1314 $ hg -R t id
1318 $ hg -R t id
1315 52c0adc0515a tip
1319 52c0adc0515a tip
1316 $ hg update 11
1320 $ hg update 11
1317 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1321 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1318 $ hg id
1322 $ hg id
1319 365661e5936a
1323 365661e5936a
1320 $ hg -R s id
1324 $ hg -R s id
1321 fc627a69481f
1325 fc627a69481f
1322 $ hg -R t id
1326 $ hg -R t id
1323 e95bcfa18a35
1327 e95bcfa18a35
1324
1328
1325 Sticky subrepositories, file changes
1329 Sticky subrepositories, file changes
1326 $ touch s/f1
1330 $ touch s/f1
1327 $ touch t/f1
1331 $ touch t/f1
1328 $ hg add -S s/f1
1332 $ hg add -S s/f1
1329 $ hg add -S t/f1
1333 $ hg add -S t/f1
1330 $ hg id
1334 $ hg id
1331 365661e5936a+
1335 365661e5936a+
1332 $ hg -R s id
1336 $ hg -R s id
1333 fc627a69481f+
1337 fc627a69481f+
1334 $ hg -R t id
1338 $ hg -R t id
1335 e95bcfa18a35+
1339 e95bcfa18a35+
1336 $ hg update tip
1340 $ hg update tip
1337 subrepository s diverged (local revision: fc627a69481f, remote revision: 12a213df6fa9)
1341 subrepository s diverged (local revision: fc627a69481f, remote revision: 12a213df6fa9)
1338 (M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
1342 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [destination].
1343 what do you want to do? m
1339 subrepository sources for s differ
1344 subrepository sources for s differ
1340 use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9)? l
1345 you can use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9).
1346 what do you want to do? l
1341 subrepository t diverged (local revision: e95bcfa18a35, remote revision: 52c0adc0515a)
1347 subrepository t diverged (local revision: e95bcfa18a35, remote revision: 52c0adc0515a)
1342 (M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
1348 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [destination].
1349 what do you want to do? m
1343 subrepository sources for t differ
1350 subrepository sources for t differ
1344 use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a)? l
1351 you can use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a).
1352 what do you want to do? l
1345 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1353 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1346 $ hg id
1354 $ hg id
1347 925c17564ef8+ tip
1355 925c17564ef8+ tip
1348 $ hg -R s id
1356 $ hg -R s id
1349 fc627a69481f+
1357 fc627a69481f+
1350 $ hg -R t id
1358 $ hg -R t id
1351 e95bcfa18a35+
1359 e95bcfa18a35+
1352 $ hg update --clean tip
1360 $ hg update --clean tip
1353 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1361 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1354
1362
1355 Sticky subrepository, revision updates
1363 Sticky subrepository, revision updates
1356 $ hg id
1364 $ hg id
1357 925c17564ef8 tip
1365 925c17564ef8 tip
1358 $ hg -R s id
1366 $ hg -R s id
1359 12a213df6fa9 tip
1367 12a213df6fa9 tip
1360 $ hg -R t id
1368 $ hg -R t id
1361 52c0adc0515a tip
1369 52c0adc0515a tip
1362 $ cd s
1370 $ cd s
1363 $ hg update -r -2
1371 $ hg update -r -2
1364 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1372 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1365 $ cd ../t
1373 $ cd ../t
1366 $ hg update -r 2
1374 $ hg update -r 2
1367 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1375 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1368 $ cd ..
1376 $ cd ..
1369 $ hg update 10
1377 $ hg update 10
1370 subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
1378 subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
1371 (M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
1379 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [destination].
1380 what do you want to do? m
1372 subrepository t diverged (local revision: 52c0adc0515a, remote revision: 20a0db6fbf6c)
1381 subrepository t diverged (local revision: 52c0adc0515a, remote revision: 20a0db6fbf6c)
1373 (M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
1382 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [destination].
1383 what do you want to do? m
1374 subrepository sources for t differ (in checked out version)
1384 subrepository sources for t differ (in checked out version)
1375 use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c)? l
1385 you can use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c).
1386 what do you want to do? l
1376 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1387 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1377 $ hg id
1388 $ hg id
1378 e45c8b14af55+
1389 e45c8b14af55+
1379 $ hg -R s id
1390 $ hg -R s id
1380 02dcf1d70411
1391 02dcf1d70411
1381 $ hg -R t id
1392 $ hg -R t id
1382 7af322bc1198
1393 7af322bc1198
1383
1394
1384 Sticky subrepository, file changes and revision updates
1395 Sticky subrepository, file changes and revision updates
1385 $ touch s/f1
1396 $ touch s/f1
1386 $ touch t/f1
1397 $ touch t/f1
1387 $ hg add -S s/f1
1398 $ hg add -S s/f1
1388 $ hg add -S t/f1
1399 $ hg add -S t/f1
1389 $ hg id
1400 $ hg id
1390 e45c8b14af55+
1401 e45c8b14af55+
1391 $ hg -R s id
1402 $ hg -R s id
1392 02dcf1d70411+
1403 02dcf1d70411+
1393 $ hg -R t id
1404 $ hg -R t id
1394 7af322bc1198+
1405 7af322bc1198+
1395 $ hg update tip
1406 $ hg update tip
1396 subrepository s diverged (local revision: 12a213df6fa9, remote revision: 12a213df6fa9)
1407 subrepository s diverged (local revision: 12a213df6fa9, remote revision: 12a213df6fa9)
1397 (M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
1408 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [destination].
1409 what do you want to do? m
1398 subrepository sources for s differ
1410 subrepository sources for s differ
1399 use (l)ocal source (02dcf1d70411) or (r)emote source (12a213df6fa9)? l
1411 you can use (l)ocal source (02dcf1d70411) or (r)emote source (12a213df6fa9).
1412 what do you want to do? l
1400 subrepository t diverged (local revision: 52c0adc0515a, remote revision: 52c0adc0515a)
1413 subrepository t diverged (local revision: 52c0adc0515a, remote revision: 52c0adc0515a)
1401 (M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
1414 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [destination].
1415 what do you want to do? m
1402 subrepository sources for t differ
1416 subrepository sources for t differ
1403 use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a)? l
1417 you can use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a).
1418 what do you want to do? l
1404 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1419 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1405 $ hg id
1420 $ hg id
1406 925c17564ef8+ tip
1421 925c17564ef8+ tip
1407 $ hg -R s id
1422 $ hg -R s id
1408 02dcf1d70411+
1423 02dcf1d70411+
1409 $ hg -R t id
1424 $ hg -R t id
1410 7af322bc1198+
1425 7af322bc1198+
1411
1426
1412 Sticky repository, update --clean
1427 Sticky repository, update --clean
1413 $ hg update --clean tip
1428 $ hg update --clean tip
1414 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1429 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1415 $ hg id
1430 $ hg id
1416 925c17564ef8 tip
1431 925c17564ef8 tip
1417 $ hg -R s id
1432 $ hg -R s id
1418 12a213df6fa9 tip
1433 12a213df6fa9 tip
1419 $ hg -R t id
1434 $ hg -R t id
1420 52c0adc0515a tip
1435 52c0adc0515a tip
1421
1436
1422 Test subrepo already at intended revision:
1437 Test subrepo already at intended revision:
1423 $ cd s
1438 $ cd s
1424 $ hg update fc627a69481f
1439 $ hg update fc627a69481f
1425 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1440 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1426 $ cd ..
1441 $ cd ..
1427 $ hg update 11
1442 $ hg update 11
1428 subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
1443 subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
1429 (M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
1444 you can (m)erge, keep (l)ocal [working copy] or keep (r)emote [destination].
1445 what do you want to do? m
1430 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1446 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1431 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1447 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1432 $ hg id -n
1448 $ hg id -n
1433 11+
1449 11+
1434 $ hg -R s id
1450 $ hg -R s id
1435 fc627a69481f
1451 fc627a69481f
1436 $ hg -R t id
1452 $ hg -R t id
1437 e95bcfa18a35
1453 e95bcfa18a35
1438
1454
1439 Test that removing .hgsubstate doesn't break anything:
1455 Test that removing .hgsubstate doesn't break anything:
1440
1456
1441 $ hg rm -f .hgsubstate
1457 $ hg rm -f .hgsubstate
1442 $ hg ci -mrm
1458 $ hg ci -mrm
1443 nothing changed
1459 nothing changed
1444 [1]
1460 [1]
1445 $ hg log -vr tip
1461 $ hg log -vr tip
1446 changeset: 13:925c17564ef8
1462 changeset: 13:925c17564ef8
1447 tag: tip
1463 tag: tip
1448 user: test
1464 user: test
1449 date: Thu Jan 01 00:00:00 1970 +0000
1465 date: Thu Jan 01 00:00:00 1970 +0000
1450 files: .hgsubstate
1466 files: .hgsubstate
1451 description:
1467 description:
1452 13
1468 13
1453
1469
1454
1470
1455
1471
1456 Test that removing .hgsub removes .hgsubstate:
1472 Test that removing .hgsub removes .hgsubstate:
1457
1473
1458 $ hg rm .hgsub
1474 $ hg rm .hgsub
1459 $ hg ci -mrm2
1475 $ hg ci -mrm2
1460 created new head
1476 created new head
1461 $ hg log -vr tip
1477 $ hg log -vr tip
1462 changeset: 14:2400bccd50af
1478 changeset: 14:2400bccd50af
1463 tag: tip
1479 tag: tip
1464 parent: 11:365661e5936a
1480 parent: 11:365661e5936a
1465 user: test
1481 user: test
1466 date: Thu Jan 01 00:00:00 1970 +0000
1482 date: Thu Jan 01 00:00:00 1970 +0000
1467 files: .hgsub .hgsubstate
1483 files: .hgsub .hgsubstate
1468 description:
1484 description:
1469 rm2
1485 rm2
1470
1486
1471
1487
1472 Test issue3153: diff -S with deleted subrepos
1488 Test issue3153: diff -S with deleted subrepos
1473
1489
1474 $ hg diff --nodates -S -c .
1490 $ hg diff --nodates -S -c .
1475 diff -r 365661e5936a -r 2400bccd50af .hgsub
1491 diff -r 365661e5936a -r 2400bccd50af .hgsub
1476 --- a/.hgsub
1492 --- a/.hgsub
1477 +++ /dev/null
1493 +++ /dev/null
1478 @@ -1,2 +0,0 @@
1494 @@ -1,2 +0,0 @@
1479 -s = s
1495 -s = s
1480 -t = t
1496 -t = t
1481 diff -r 365661e5936a -r 2400bccd50af .hgsubstate
1497 diff -r 365661e5936a -r 2400bccd50af .hgsubstate
1482 --- a/.hgsubstate
1498 --- a/.hgsubstate
1483 +++ /dev/null
1499 +++ /dev/null
1484 @@ -1,2 +0,0 @@
1500 @@ -1,2 +0,0 @@
1485 -fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
1501 -fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
1486 -e95bcfa18a358dc4936da981ebf4147b4cad1362 t
1502 -e95bcfa18a358dc4936da981ebf4147b4cad1362 t
1487
1503
1488 Test behavior of add for explicit path in subrepo:
1504 Test behavior of add for explicit path in subrepo:
1489 $ cd ..
1505 $ cd ..
1490 $ hg init explicit
1506 $ hg init explicit
1491 $ cd explicit
1507 $ cd explicit
1492 $ echo s = s > .hgsub
1508 $ echo s = s > .hgsub
1493 $ hg add .hgsub
1509 $ hg add .hgsub
1494 $ hg init s
1510 $ hg init s
1495 $ hg ci -m0
1511 $ hg ci -m0
1496 Adding with an explicit path in a subrepo adds the file
1512 Adding with an explicit path in a subrepo adds the file
1497 $ echo c1 > f1
1513 $ echo c1 > f1
1498 $ echo c2 > s/f2
1514 $ echo c2 > s/f2
1499 $ hg st -S
1515 $ hg st -S
1500 ? f1
1516 ? f1
1501 ? s/f2
1517 ? s/f2
1502 $ hg add s/f2
1518 $ hg add s/f2
1503 $ hg st -S
1519 $ hg st -S
1504 A s/f2
1520 A s/f2
1505 ? f1
1521 ? f1
1506 $ hg ci -R s -m0
1522 $ hg ci -R s -m0
1507 $ hg ci -Am1
1523 $ hg ci -Am1
1508 adding f1
1524 adding f1
1509 Adding with an explicit path in a subrepo with -S has the same behavior
1525 Adding with an explicit path in a subrepo with -S has the same behavior
1510 $ echo c3 > f3
1526 $ echo c3 > f3
1511 $ echo c4 > s/f4
1527 $ echo c4 > s/f4
1512 $ hg st -S
1528 $ hg st -S
1513 ? f3
1529 ? f3
1514 ? s/f4
1530 ? s/f4
1515 $ hg add -S s/f4
1531 $ hg add -S s/f4
1516 $ hg st -S
1532 $ hg st -S
1517 A s/f4
1533 A s/f4
1518 ? f3
1534 ? f3
1519 $ hg ci -R s -m1
1535 $ hg ci -R s -m1
1520 $ hg ci -Ama2
1536 $ hg ci -Ama2
1521 adding f3
1537 adding f3
1522 Adding without a path or pattern silently ignores subrepos
1538 Adding without a path or pattern silently ignores subrepos
1523 $ echo c5 > f5
1539 $ echo c5 > f5
1524 $ echo c6 > s/f6
1540 $ echo c6 > s/f6
1525 $ echo c7 > s/f7
1541 $ echo c7 > s/f7
1526 $ hg st -S
1542 $ hg st -S
1527 ? f5
1543 ? f5
1528 ? s/f6
1544 ? s/f6
1529 ? s/f7
1545 ? s/f7
1530 $ hg add
1546 $ hg add
1531 adding f5
1547 adding f5
1532 $ hg st -S
1548 $ hg st -S
1533 A f5
1549 A f5
1534 ? s/f6
1550 ? s/f6
1535 ? s/f7
1551 ? s/f7
1536 $ hg ci -R s -Am2
1552 $ hg ci -R s -Am2
1537 adding f6
1553 adding f6
1538 adding f7
1554 adding f7
1539 $ hg ci -m3
1555 $ hg ci -m3
1540 Adding without a path or pattern with -S also adds files in subrepos
1556 Adding without a path or pattern with -S also adds files in subrepos
1541 $ echo c8 > f8
1557 $ echo c8 > f8
1542 $ echo c9 > s/f9
1558 $ echo c9 > s/f9
1543 $ echo c10 > s/f10
1559 $ echo c10 > s/f10
1544 $ hg st -S
1560 $ hg st -S
1545 ? f8
1561 ? f8
1546 ? s/f10
1562 ? s/f10
1547 ? s/f9
1563 ? s/f9
1548 $ hg add -S
1564 $ hg add -S
1549 adding f8
1565 adding f8
1550 adding s/f10
1566 adding s/f10
1551 adding s/f9
1567 adding s/f9
1552 $ hg st -S
1568 $ hg st -S
1553 A f8
1569 A f8
1554 A s/f10
1570 A s/f10
1555 A s/f9
1571 A s/f9
1556 $ hg ci -R s -m3
1572 $ hg ci -R s -m3
1557 $ hg ci -m4
1573 $ hg ci -m4
1558 Adding with a pattern silently ignores subrepos
1574 Adding with a pattern silently ignores subrepos
1559 $ echo c11 > fm11
1575 $ echo c11 > fm11
1560 $ echo c12 > fn12
1576 $ echo c12 > fn12
1561 $ echo c13 > s/fm13
1577 $ echo c13 > s/fm13
1562 $ echo c14 > s/fn14
1578 $ echo c14 > s/fn14
1563 $ hg st -S
1579 $ hg st -S
1564 ? fm11
1580 ? fm11
1565 ? fn12
1581 ? fn12
1566 ? s/fm13
1582 ? s/fm13
1567 ? s/fn14
1583 ? s/fn14
1568 $ hg add 'glob:**fm*'
1584 $ hg add 'glob:**fm*'
1569 adding fm11
1585 adding fm11
1570 $ hg st -S
1586 $ hg st -S
1571 A fm11
1587 A fm11
1572 ? fn12
1588 ? fn12
1573 ? s/fm13
1589 ? s/fm13
1574 ? s/fn14
1590 ? s/fn14
1575 $ hg ci -R s -Am4
1591 $ hg ci -R s -Am4
1576 adding fm13
1592 adding fm13
1577 adding fn14
1593 adding fn14
1578 $ hg ci -Am5
1594 $ hg ci -Am5
1579 adding fn12
1595 adding fn12
1580 Adding with a pattern with -S also adds matches in subrepos
1596 Adding with a pattern with -S also adds matches in subrepos
1581 $ echo c15 > fm15
1597 $ echo c15 > fm15
1582 $ echo c16 > fn16
1598 $ echo c16 > fn16
1583 $ echo c17 > s/fm17
1599 $ echo c17 > s/fm17
1584 $ echo c18 > s/fn18
1600 $ echo c18 > s/fn18
1585 $ hg st -S
1601 $ hg st -S
1586 ? fm15
1602 ? fm15
1587 ? fn16
1603 ? fn16
1588 ? s/fm17
1604 ? s/fm17
1589 ? s/fn18
1605 ? s/fn18
1590 $ hg add -S 'glob:**fm*'
1606 $ hg add -S 'glob:**fm*'
1591 adding fm15
1607 adding fm15
1592 adding s/fm17
1608 adding s/fm17
1593 $ hg st -S
1609 $ hg st -S
1594 A fm15
1610 A fm15
1595 A s/fm17
1611 A s/fm17
1596 ? fn16
1612 ? fn16
1597 ? s/fn18
1613 ? s/fn18
1598 $ hg ci -R s -Am5
1614 $ hg ci -R s -Am5
1599 adding fn18
1615 adding fn18
1600 $ hg ci -Am6
1616 $ hg ci -Am6
1601 adding fn16
1617 adding fn16
1602
1618
1603 Test behavior of forget for explicit path in subrepo:
1619 Test behavior of forget for explicit path in subrepo:
1604 Forgetting an explicit path in a subrepo untracks the file
1620 Forgetting an explicit path in a subrepo untracks the file
1605 $ echo c19 > s/f19
1621 $ echo c19 > s/f19
1606 $ hg add s/f19
1622 $ hg add s/f19
1607 $ hg st -S
1623 $ hg st -S
1608 A s/f19
1624 A s/f19
1609 $ hg forget s/f19
1625 $ hg forget s/f19
1610 $ hg st -S
1626 $ hg st -S
1611 ? s/f19
1627 ? s/f19
1612 $ rm s/f19
1628 $ rm s/f19
1613 $ cd ..
1629 $ cd ..
1614
1630
1615 Courtesy phases synchronisation to publishing server does not block the push
1631 Courtesy phases synchronisation to publishing server does not block the push
1616 (issue3781)
1632 (issue3781)
1617
1633
1618 $ cp -R main issue3781
1634 $ cp -R main issue3781
1619 $ cp -R main issue3781-dest
1635 $ cp -R main issue3781-dest
1620 $ cd issue3781-dest/s
1636 $ cd issue3781-dest/s
1621 $ hg phase tip # show we have draft changeset
1637 $ hg phase tip # show we have draft changeset
1622 5: draft
1638 5: draft
1623 $ chmod a-w .hg/store/phaseroots # prevent phase push
1639 $ chmod a-w .hg/store/phaseroots # prevent phase push
1624 $ cd ../../issue3781
1640 $ cd ../../issue3781
1625 $ cat >> .hg/hgrc << EOF
1641 $ cat >> .hg/hgrc << EOF
1626 > [paths]
1642 > [paths]
1627 > default=../issue3781-dest/
1643 > default=../issue3781-dest/
1628 > EOF
1644 > EOF
1629 $ hg push --config devel.legacy.exchange=bundle1
1645 $ hg push --config devel.legacy.exchange=bundle1
1630 pushing to $TESTTMP/issue3781-dest
1646 pushing to $TESTTMP/issue3781-dest
1631 pushing subrepo s to $TESTTMP/issue3781-dest/s
1647 pushing subrepo s to $TESTTMP/issue3781-dest/s
1632 searching for changes
1648 searching for changes
1633 no changes found
1649 no changes found
1634 searching for changes
1650 searching for changes
1635 no changes found
1651 no changes found
1636 [1]
1652 [1]
1637 # clean the push cache
1653 # clean the push cache
1638 $ rm s/.hg/cache/storehash/*
1654 $ rm s/.hg/cache/storehash/*
1639 $ hg push # bundle2+
1655 $ hg push # bundle2+
1640 pushing to $TESTTMP/issue3781-dest
1656 pushing to $TESTTMP/issue3781-dest
1641 pushing subrepo s to $TESTTMP/issue3781-dest/s
1657 pushing subrepo s to $TESTTMP/issue3781-dest/s
1642 searching for changes
1658 searching for changes
1643 no changes found
1659 no changes found
1644 searching for changes
1660 searching for changes
1645 no changes found
1661 no changes found
1646 [1]
1662 [1]
1647 $ cd ..
1663 $ cd ..
1648
1664
1649 Test phase choice for newly created commit with "phases.subrepochecks"
1665 Test phase choice for newly created commit with "phases.subrepochecks"
1650 configuration
1666 configuration
1651
1667
1652 $ cd t
1668 $ cd t
1653 $ hg update -q -r 12
1669 $ hg update -q -r 12
1654
1670
1655 $ cat >> s/ss/.hg/hgrc <<EOF
1671 $ cat >> s/ss/.hg/hgrc <<EOF
1656 > [phases]
1672 > [phases]
1657 > new-commit = secret
1673 > new-commit = secret
1658 > EOF
1674 > EOF
1659 $ cat >> s/.hg/hgrc <<EOF
1675 $ cat >> s/.hg/hgrc <<EOF
1660 > [phases]
1676 > [phases]
1661 > new-commit = draft
1677 > new-commit = draft
1662 > EOF
1678 > EOF
1663 $ echo phasecheck1 >> s/ss/a
1679 $ echo phasecheck1 >> s/ss/a
1664 $ hg -R s commit -S --config phases.checksubrepos=abort -m phasecheck1
1680 $ hg -R s commit -S --config phases.checksubrepos=abort -m phasecheck1
1665 committing subrepository ss
1681 committing subrepository ss
1666 transaction abort!
1682 transaction abort!
1667 rollback completed
1683 rollback completed
1668 abort: can't commit in draft phase conflicting secret from subrepository ss
1684 abort: can't commit in draft phase conflicting secret from subrepository ss
1669 [255]
1685 [255]
1670 $ echo phasecheck2 >> s/ss/a
1686 $ echo phasecheck2 >> s/ss/a
1671 $ hg -R s commit -S --config phases.checksubrepos=ignore -m phasecheck2
1687 $ hg -R s commit -S --config phases.checksubrepos=ignore -m phasecheck2
1672 committing subrepository ss
1688 committing subrepository ss
1673 $ hg -R s/ss phase tip
1689 $ hg -R s/ss phase tip
1674 3: secret
1690 3: secret
1675 $ hg -R s phase tip
1691 $ hg -R s phase tip
1676 6: draft
1692 6: draft
1677 $ echo phasecheck3 >> s/ss/a
1693 $ echo phasecheck3 >> s/ss/a
1678 $ hg -R s commit -S -m phasecheck3
1694 $ hg -R s commit -S -m phasecheck3
1679 committing subrepository ss
1695 committing subrepository ss
1680 warning: changes are committed in secret phase from subrepository ss
1696 warning: changes are committed in secret phase from subrepository ss
1681 $ hg -R s/ss phase tip
1697 $ hg -R s/ss phase tip
1682 4: secret
1698 4: secret
1683 $ hg -R s phase tip
1699 $ hg -R s phase tip
1684 7: secret
1700 7: secret
1685
1701
1686 $ cat >> t/.hg/hgrc <<EOF
1702 $ cat >> t/.hg/hgrc <<EOF
1687 > [phases]
1703 > [phases]
1688 > new-commit = draft
1704 > new-commit = draft
1689 > EOF
1705 > EOF
1690 $ cat >> .hg/hgrc <<EOF
1706 $ cat >> .hg/hgrc <<EOF
1691 > [phases]
1707 > [phases]
1692 > new-commit = public
1708 > new-commit = public
1693 > EOF
1709 > EOF
1694 $ echo phasecheck4 >> s/ss/a
1710 $ echo phasecheck4 >> s/ss/a
1695 $ echo phasecheck4 >> t/t
1711 $ echo phasecheck4 >> t/t
1696 $ hg commit -S -m phasecheck4
1712 $ hg commit -S -m phasecheck4
1697 committing subrepository s
1713 committing subrepository s
1698 committing subrepository s/ss
1714 committing subrepository s/ss
1699 warning: changes are committed in secret phase from subrepository ss
1715 warning: changes are committed in secret phase from subrepository ss
1700 committing subrepository t
1716 committing subrepository t
1701 warning: changes are committed in secret phase from subrepository s
1717 warning: changes are committed in secret phase from subrepository s
1702 created new head
1718 created new head
1703 $ hg -R s/ss phase tip
1719 $ hg -R s/ss phase tip
1704 5: secret
1720 5: secret
1705 $ hg -R s phase tip
1721 $ hg -R s phase tip
1706 8: secret
1722 8: secret
1707 $ hg -R t phase tip
1723 $ hg -R t phase tip
1708 6: draft
1724 6: draft
1709 $ hg phase tip
1725 $ hg phase tip
1710 15: secret
1726 15: secret
1711
1727
1712 $ cd ..
1728 $ cd ..
1713
1729
1714
1730
1715 Test that commit --secret works on both repo and subrepo (issue4182)
1731 Test that commit --secret works on both repo and subrepo (issue4182)
1716
1732
1717 $ cd main
1733 $ cd main
1718 $ echo secret >> b
1734 $ echo secret >> b
1719 $ echo secret >> s/b
1735 $ echo secret >> s/b
1720 $ hg commit --secret --subrepo -m "secret"
1736 $ hg commit --secret --subrepo -m "secret"
1721 committing subrepository s
1737 committing subrepository s
1722 $ hg phase -r .
1738 $ hg phase -r .
1723 6: secret
1739 6: secret
1724 $ cd s
1740 $ cd s
1725 $ hg phase -r .
1741 $ hg phase -r .
1726 6: secret
1742 6: secret
1727 $ cd ../../
1743 $ cd ../../
1728
1744
1729 Test "subrepos" template keyword
1745 Test "subrepos" template keyword
1730
1746
1731 $ cd t
1747 $ cd t
1732 $ hg update -q 15
1748 $ hg update -q 15
1733 $ cat > .hgsub <<EOF
1749 $ cat > .hgsub <<EOF
1734 > s = s
1750 > s = s
1735 > EOF
1751 > EOF
1736 $ hg commit -m "16"
1752 $ hg commit -m "16"
1737 warning: changes are committed in secret phase from subrepository s
1753 warning: changes are committed in secret phase from subrepository s
1738
1754
1739 (addition of ".hgsub" itself)
1755 (addition of ".hgsub" itself)
1740
1756
1741 $ hg diff --nodates -c 1 .hgsubstate
1757 $ hg diff --nodates -c 1 .hgsubstate
1742 diff -r f7b1eb17ad24 -r 7cf8cfea66e4 .hgsubstate
1758 diff -r f7b1eb17ad24 -r 7cf8cfea66e4 .hgsubstate
1743 --- /dev/null
1759 --- /dev/null
1744 +++ b/.hgsubstate
1760 +++ b/.hgsubstate
1745 @@ -0,0 +1,1 @@
1761 @@ -0,0 +1,1 @@
1746 +e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1762 +e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1747 $ hg log -r 1 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1763 $ hg log -r 1 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1748 f7b1eb17ad24 000000000000
1764 f7b1eb17ad24 000000000000
1749 s
1765 s
1750
1766
1751 (modification of existing entry)
1767 (modification of existing entry)
1752
1768
1753 $ hg diff --nodates -c 2 .hgsubstate
1769 $ hg diff --nodates -c 2 .hgsubstate
1754 diff -r 7cf8cfea66e4 -r df30734270ae .hgsubstate
1770 diff -r 7cf8cfea66e4 -r df30734270ae .hgsubstate
1755 --- a/.hgsubstate
1771 --- a/.hgsubstate
1756 +++ b/.hgsubstate
1772 +++ b/.hgsubstate
1757 @@ -1,1 +1,1 @@
1773 @@ -1,1 +1,1 @@
1758 -e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1774 -e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1759 +dc73e2e6d2675eb2e41e33c205f4bdab4ea5111d s
1775 +dc73e2e6d2675eb2e41e33c205f4bdab4ea5111d s
1760 $ hg log -r 2 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1776 $ hg log -r 2 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1761 7cf8cfea66e4 000000000000
1777 7cf8cfea66e4 000000000000
1762 s
1778 s
1763
1779
1764 (addition of entry)
1780 (addition of entry)
1765
1781
1766 $ hg diff --nodates -c 5 .hgsubstate
1782 $ hg diff --nodates -c 5 .hgsubstate
1767 diff -r 7cf8cfea66e4 -r 1f14a2e2d3ec .hgsubstate
1783 diff -r 7cf8cfea66e4 -r 1f14a2e2d3ec .hgsubstate
1768 --- a/.hgsubstate
1784 --- a/.hgsubstate
1769 +++ b/.hgsubstate
1785 +++ b/.hgsubstate
1770 @@ -1,1 +1,2 @@
1786 @@ -1,1 +1,2 @@
1771 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1787 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1772 +60ca1237c19474e7a3978b0dc1ca4e6f36d51382 t
1788 +60ca1237c19474e7a3978b0dc1ca4e6f36d51382 t
1773 $ hg log -r 5 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1789 $ hg log -r 5 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1774 7cf8cfea66e4 000000000000
1790 7cf8cfea66e4 000000000000
1775 t
1791 t
1776
1792
1777 (removal of existing entry)
1793 (removal of existing entry)
1778
1794
1779 $ hg diff --nodates -c 16 .hgsubstate
1795 $ hg diff --nodates -c 16 .hgsubstate
1780 diff -r 8bec38d2bd0b -r f2f70bc3d3c9 .hgsubstate
1796 diff -r 8bec38d2bd0b -r f2f70bc3d3c9 .hgsubstate
1781 --- a/.hgsubstate
1797 --- a/.hgsubstate
1782 +++ b/.hgsubstate
1798 +++ b/.hgsubstate
1783 @@ -1,2 +1,1 @@
1799 @@ -1,2 +1,1 @@
1784 0731af8ca9423976d3743119d0865097c07bdc1b s
1800 0731af8ca9423976d3743119d0865097c07bdc1b s
1785 -e202dc79b04c88a636ea8913d9182a1346d9b3dc t
1801 -e202dc79b04c88a636ea8913d9182a1346d9b3dc t
1786 $ hg log -r 16 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1802 $ hg log -r 16 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1787 8bec38d2bd0b 000000000000
1803 8bec38d2bd0b 000000000000
1788 t
1804 t
1789
1805
1790 (merging)
1806 (merging)
1791
1807
1792 $ hg diff --nodates -c 9 .hgsubstate
1808 $ hg diff --nodates -c 9 .hgsubstate
1793 diff -r f6affe3fbfaa -r f0d2028bf86d .hgsubstate
1809 diff -r f6affe3fbfaa -r f0d2028bf86d .hgsubstate
1794 --- a/.hgsubstate
1810 --- a/.hgsubstate
1795 +++ b/.hgsubstate
1811 +++ b/.hgsubstate
1796 @@ -1,1 +1,2 @@
1812 @@ -1,1 +1,2 @@
1797 fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
1813 fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
1798 +60ca1237c19474e7a3978b0dc1ca4e6f36d51382 t
1814 +60ca1237c19474e7a3978b0dc1ca4e6f36d51382 t
1799 $ hg log -r 9 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1815 $ hg log -r 9 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1800 f6affe3fbfaa 1f14a2e2d3ec
1816 f6affe3fbfaa 1f14a2e2d3ec
1801 t
1817 t
1802
1818
1803 (removal of ".hgsub" itself)
1819 (removal of ".hgsub" itself)
1804
1820
1805 $ hg diff --nodates -c 8 .hgsubstate
1821 $ hg diff --nodates -c 8 .hgsubstate
1806 diff -r f94576341bcf -r 96615c1dad2d .hgsubstate
1822 diff -r f94576341bcf -r 96615c1dad2d .hgsubstate
1807 --- a/.hgsubstate
1823 --- a/.hgsubstate
1808 +++ /dev/null
1824 +++ /dev/null
1809 @@ -1,2 +0,0 @@
1825 @@ -1,2 +0,0 @@
1810 -e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1826 -e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1811 -7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4 t
1827 -7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4 t
1812 $ hg log -r 8 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1828 $ hg log -r 8 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1813 f94576341bcf 000000000000
1829 f94576341bcf 000000000000
1814
1830
1815 Test that '[paths]' is configured correctly at subrepo creation
1831 Test that '[paths]' is configured correctly at subrepo creation
1816
1832
1817 $ cd $TESTTMP/tc
1833 $ cd $TESTTMP/tc
1818 $ cat > .hgsub <<EOF
1834 $ cat > .hgsub <<EOF
1819 > # to clear bogus subrepo path 'bogus=[boguspath'
1835 > # to clear bogus subrepo path 'bogus=[boguspath'
1820 > s = s
1836 > s = s
1821 > t = t
1837 > t = t
1822 > EOF
1838 > EOF
1823 $ hg update -q --clean null
1839 $ hg update -q --clean null
1824 $ rm -rf s t
1840 $ rm -rf s t
1825 $ cat >> .hg/hgrc <<EOF
1841 $ cat >> .hg/hgrc <<EOF
1826 > [paths]
1842 > [paths]
1827 > default-push = /foo/bar
1843 > default-push = /foo/bar
1828 > EOF
1844 > EOF
1829 $ hg update -q
1845 $ hg update -q
1830 $ cat s/.hg/hgrc
1846 $ cat s/.hg/hgrc
1831 [paths]
1847 [paths]
1832 default = $TESTTMP/t/s
1848 default = $TESTTMP/t/s
1833 default-push = /foo/bar/s
1849 default-push = /foo/bar/s
1834 $ cat s/ss/.hg/hgrc
1850 $ cat s/ss/.hg/hgrc
1835 [paths]
1851 [paths]
1836 default = $TESTTMP/t/s/ss
1852 default = $TESTTMP/t/s/ss
1837 default-push = /foo/bar/s/ss
1853 default-push = /foo/bar/s/ss
1838 $ cat t/.hg/hgrc
1854 $ cat t/.hg/hgrc
1839 [paths]
1855 [paths]
1840 default = $TESTTMP/t/t
1856 default = $TESTTMP/t/t
1841 default-push = /foo/bar/t
1857 default-push = /foo/bar/t
1842
1858
1843 $ cd $TESTTMP/t
1859 $ cd $TESTTMP/t
1844 $ hg up -qC 0
1860 $ hg up -qC 0
1845 $ echo 'bar' > bar.txt
1861 $ echo 'bar' > bar.txt
1846 $ hg ci -Am 'branch before subrepo add'
1862 $ hg ci -Am 'branch before subrepo add'
1847 adding bar.txt
1863 adding bar.txt
1848 created new head
1864 created new head
1849 $ hg merge -r "first(subrepo('s'))"
1865 $ hg merge -r "first(subrepo('s'))"
1850 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1866 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1851 (branch merge, don't forget to commit)
1867 (branch merge, don't forget to commit)
1852 $ hg status -S -X '.hgsub*'
1868 $ hg status -S -X '.hgsub*'
1853 A s/a
1869 A s/a
1854 ? s/b
1870 ? s/b
1855 ? s/c
1871 ? s/c
1856 ? s/f1
1872 ? s/f1
1857 $ hg status -S --rev 'p2()'
1873 $ hg status -S --rev 'p2()'
1858 A bar.txt
1874 A bar.txt
1859 ? s/b
1875 ? s/b
1860 ? s/c
1876 ? s/c
1861 ? s/f1
1877 ? s/f1
1862 $ hg diff -S -X '.hgsub*' --nodates
1878 $ hg diff -S -X '.hgsub*' --nodates
1863 diff -r 000000000000 s/a
1879 diff -r 000000000000 s/a
1864 --- /dev/null
1880 --- /dev/null
1865 +++ b/s/a
1881 +++ b/s/a
1866 @@ -0,0 +1,1 @@
1882 @@ -0,0 +1,1 @@
1867 +a
1883 +a
1868 $ hg diff -S --rev 'p2()' --nodates
1884 $ hg diff -S --rev 'p2()' --nodates
1869 diff -r 7cf8cfea66e4 bar.txt
1885 diff -r 7cf8cfea66e4 bar.txt
1870 --- /dev/null
1886 --- /dev/null
1871 +++ b/bar.txt
1887 +++ b/bar.txt
1872 @@ -0,0 +1,1 @@
1888 @@ -0,0 +1,1 @@
1873 +bar
1889 +bar
1874
1890
1875 $ hg diff -X '.hgsub*' --nodates s
1891 $ hg diff -X '.hgsub*' --nodates s
1876 diff -r 000000000000 s/a
1892 diff -r 000000000000 s/a
1877 --- /dev/null
1893 --- /dev/null
1878 +++ b/s/a
1894 +++ b/s/a
1879 @@ -0,0 +1,1 @@
1895 @@ -0,0 +1,1 @@
1880 +a
1896 +a
1881 $ hg diff -X '.hgsub*' --nodates s/a
1897 $ hg diff -X '.hgsub*' --nodates s/a
1882 diff -r 000000000000 s/a
1898 diff -r 000000000000 s/a
1883 --- /dev/null
1899 --- /dev/null
1884 +++ b/s/a
1900 +++ b/s/a
1885 @@ -0,0 +1,1 @@
1901 @@ -0,0 +1,1 @@
1886 +a
1902 +a
1887
1903
1888 $ cd ..
1904 $ cd ..
1889
1905
1890 test for ssh exploit 2017-07-25
1906 test for ssh exploit 2017-07-25
1891
1907
1892 $ cat >> $HGRCPATH << EOF
1908 $ cat >> $HGRCPATH << EOF
1893 > [ui]
1909 > [ui]
1894 > ssh = sh -c "read l; read l; read l"
1910 > ssh = sh -c "read l; read l; read l"
1895 > EOF
1911 > EOF
1896
1912
1897 $ hg init malicious-proxycommand
1913 $ hg init malicious-proxycommand
1898 $ cd malicious-proxycommand
1914 $ cd malicious-proxycommand
1899 $ echo 's = [hg]ssh://-oProxyCommand=touch${IFS}owned/path' > .hgsub
1915 $ echo 's = [hg]ssh://-oProxyCommand=touch${IFS}owned/path' > .hgsub
1900 $ hg init s
1916 $ hg init s
1901 $ cd s
1917 $ cd s
1902 $ echo init > init
1918 $ echo init > init
1903 $ hg add
1919 $ hg add
1904 adding init
1920 adding init
1905 $ hg commit -m init
1921 $ hg commit -m init
1906 $ cd ..
1922 $ cd ..
1907 $ hg add .hgsub
1923 $ hg add .hgsub
1908 $ hg ci -m 'add subrepo'
1924 $ hg ci -m 'add subrepo'
1909 $ cd ..
1925 $ cd ..
1910 $ hg clone malicious-proxycommand malicious-proxycommand-clone
1926 $ hg clone malicious-proxycommand malicious-proxycommand-clone
1911 updating to branch default
1927 updating to branch default
1912 cloning subrepo s from ssh://-oProxyCommand%3Dtouch%24%7BIFS%7Downed/path
1928 cloning subrepo s from ssh://-oProxyCommand%3Dtouch%24%7BIFS%7Downed/path
1913 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch${IFS}owned/path' (in subrepository "s")
1929 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch${IFS}owned/path' (in subrepository "s")
1914 [255]
1930 [255]
1915
1931
1916 also check that a percent encoded '-' (%2D) doesn't work
1932 also check that a percent encoded '-' (%2D) doesn't work
1917
1933
1918 $ cd malicious-proxycommand
1934 $ cd malicious-proxycommand
1919 $ echo 's = [hg]ssh://%2DoProxyCommand=touch${IFS}owned/path' > .hgsub
1935 $ echo 's = [hg]ssh://%2DoProxyCommand=touch${IFS}owned/path' > .hgsub
1920 $ hg ci -m 'change url to percent encoded'
1936 $ hg ci -m 'change url to percent encoded'
1921 $ cd ..
1937 $ cd ..
1922 $ rm -r malicious-proxycommand-clone
1938 $ rm -r malicious-proxycommand-clone
1923 $ hg clone malicious-proxycommand malicious-proxycommand-clone
1939 $ hg clone malicious-proxycommand malicious-proxycommand-clone
1924 updating to branch default
1940 updating to branch default
1925 cloning subrepo s from ssh://-oProxyCommand%3Dtouch%24%7BIFS%7Downed/path
1941 cloning subrepo s from ssh://-oProxyCommand%3Dtouch%24%7BIFS%7Downed/path
1926 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch${IFS}owned/path' (in subrepository "s")
1942 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch${IFS}owned/path' (in subrepository "s")
1927 [255]
1943 [255]
1928
1944
1929 also check for a pipe
1945 also check for a pipe
1930
1946
1931 $ cd malicious-proxycommand
1947 $ cd malicious-proxycommand
1932 $ echo 's = [hg]ssh://fakehost|touch${IFS}owned/path' > .hgsub
1948 $ echo 's = [hg]ssh://fakehost|touch${IFS}owned/path' > .hgsub
1933 $ hg ci -m 'change url to pipe'
1949 $ hg ci -m 'change url to pipe'
1934 $ cd ..
1950 $ cd ..
1935 $ rm -r malicious-proxycommand-clone
1951 $ rm -r malicious-proxycommand-clone
1936 $ hg clone malicious-proxycommand malicious-proxycommand-clone
1952 $ hg clone malicious-proxycommand malicious-proxycommand-clone
1937 updating to branch default
1953 updating to branch default
1938 cloning subrepo s from ssh://fakehost%7Ctouch%24%7BIFS%7Downed/path
1954 cloning subrepo s from ssh://fakehost%7Ctouch%24%7BIFS%7Downed/path
1939 abort: no suitable response from remote hg!
1955 abort: no suitable response from remote hg!
1940 [255]
1956 [255]
1941 $ [ ! -f owned ] || echo 'you got owned'
1957 $ [ ! -f owned ] || echo 'you got owned'
1942
1958
1943 also check that a percent encoded '|' (%7C) doesn't work
1959 also check that a percent encoded '|' (%7C) doesn't work
1944
1960
1945 $ cd malicious-proxycommand
1961 $ cd malicious-proxycommand
1946 $ echo 's = [hg]ssh://fakehost%7Ctouch%20owned/path' > .hgsub
1962 $ echo 's = [hg]ssh://fakehost%7Ctouch%20owned/path' > .hgsub
1947 $ hg ci -m 'change url to percent encoded pipe'
1963 $ hg ci -m 'change url to percent encoded pipe'
1948 $ cd ..
1964 $ cd ..
1949 $ rm -r malicious-proxycommand-clone
1965 $ rm -r malicious-proxycommand-clone
1950 $ hg clone malicious-proxycommand malicious-proxycommand-clone
1966 $ hg clone malicious-proxycommand malicious-proxycommand-clone
1951 updating to branch default
1967 updating to branch default
1952 cloning subrepo s from ssh://fakehost%7Ctouch%20owned/path
1968 cloning subrepo s from ssh://fakehost%7Ctouch%20owned/path
1953 abort: no suitable response from remote hg!
1969 abort: no suitable response from remote hg!
1954 [255]
1970 [255]
1955 $ [ ! -f owned ] || echo 'you got owned'
1971 $ [ ! -f owned ] || echo 'you got owned'
1956
1972
1957 and bad usernames:
1973 and bad usernames:
1958 $ cd malicious-proxycommand
1974 $ cd malicious-proxycommand
1959 $ echo 's = [hg]ssh://-oProxyCommand=touch owned@example.com/path' > .hgsub
1975 $ echo 's = [hg]ssh://-oProxyCommand=touch owned@example.com/path' > .hgsub
1960 $ hg ci -m 'owned username'
1976 $ hg ci -m 'owned username'
1961 $ cd ..
1977 $ cd ..
1962 $ rm -r malicious-proxycommand-clone
1978 $ rm -r malicious-proxycommand-clone
1963 $ hg clone malicious-proxycommand malicious-proxycommand-clone
1979 $ hg clone malicious-proxycommand malicious-proxycommand-clone
1964 updating to branch default
1980 updating to branch default
1965 cloning subrepo s from ssh://-oProxyCommand%3Dtouch%20owned@example.com/path
1981 cloning subrepo s from ssh://-oProxyCommand%3Dtouch%20owned@example.com/path
1966 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch owned@example.com/path' (in subrepository "s")
1982 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch owned@example.com/path' (in subrepository "s")
1967 [255]
1983 [255]
1968
1984
1969 Test convert subrepositories including merge (issue5526):
1985 Test convert subrepositories including merge (issue5526):
1970
1986
1971 $ hg init tconv
1987 $ hg init tconv
1972 $ hg convert --config extensions.convert= -q t/s tconv/s
1988 $ hg convert --config extensions.convert= -q t/s tconv/s
1973 $ hg convert --config extensions.convert= -q t/s/ss tconv/s/ss
1989 $ hg convert --config extensions.convert= -q t/s/ss tconv/s/ss
1974 $ hg convert --config extensions.convert= -q t/t tconv/t
1990 $ hg convert --config extensions.convert= -q t/t tconv/t
1975
1991
1976 convert shouldn't fail because of pseudo filenode:
1992 convert shouldn't fail because of pseudo filenode:
1977
1993
1978 $ hg convert --config extensions.convert= t tconv
1994 $ hg convert --config extensions.convert= t tconv
1979 scanning source...
1995 scanning source...
1980 sorting...
1996 sorting...
1981 converting...
1997 converting...
1982 17 0
1998 17 0
1983 16 1
1999 16 1
1984 15 2
2000 15 2
1985 14 3
2001 14 3
1986 13 4
2002 13 4
1987 12 5
2003 12 5
1988 11 6
2004 11 6
1989 10 7
2005 10 7
1990 9 8
2006 9 8
1991 8 9
2007 8 9
1992 7 10
2008 7 10
1993 6 11
2009 6 11
1994 5 12
2010 5 12
1995 4 13
2011 4 13
1996 3 rm2
2012 3 rm2
1997 2 phasecheck4
2013 2 phasecheck4
1998 1 16
2014 1 16
1999 0 branch before subrepo add
2015 0 branch before subrepo add
2000
2016
2001 converted .hgsubstate should point to valid nodes:
2017 converted .hgsubstate should point to valid nodes:
2002
2018
2003 $ hg up -R tconv 9
2019 $ hg up -R tconv 9
2004 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
2020 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
2005 $ cat tconv/.hgsubstate
2021 $ cat tconv/.hgsubstate
2006 fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
2022 fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
2007 60ca1237c19474e7a3978b0dc1ca4e6f36d51382 t
2023 60ca1237c19474e7a3978b0dc1ca4e6f36d51382 t
General Comments 0
You need to be logged in to leave comments. Login now