##// END OF EJS Templates
clone: reuse the stream clone logic for local clone...
marmoute -
r48625:377d8fc2 default
parent child Browse files
Show More
@@ -1,1599 +1,1590 b''
1 # hg.py - repository classes for mercurial
1 # hg.py - repository classes for mercurial
2 #
2 #
3 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
3 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 from __future__ import absolute_import
9 from __future__ import absolute_import
10
10
11 import errno
11 import errno
12 import os
12 import os
13 import shutil
13 import shutil
14 import stat
14 import stat
15
15
16 from .i18n import _
16 from .i18n import _
17 from .node import (
17 from .node import (
18 hex,
18 hex,
19 sha1nodeconstants,
19 sha1nodeconstants,
20 short,
20 short,
21 )
21 )
22 from .pycompat import getattr
22 from .pycompat import getattr
23
23
24 from . import (
24 from . import (
25 bookmarks,
25 bookmarks,
26 bundlerepo,
26 bundlerepo,
27 cacheutil,
28 cmdutil,
27 cmdutil,
29 destutil,
28 destutil,
30 discovery,
29 discovery,
31 error,
30 error,
32 exchange,
31 exchange,
33 extensions,
32 extensions,
34 graphmod,
33 graphmod,
35 httppeer,
34 httppeer,
36 localrepo,
35 localrepo,
37 lock,
36 lock,
38 logcmdutil,
37 logcmdutil,
39 logexchange,
38 logexchange,
40 merge as mergemod,
39 merge as mergemod,
41 mergestate as mergestatemod,
40 mergestate as mergestatemod,
42 narrowspec,
41 narrowspec,
43 phases,
42 phases,
44 requirements,
43 requirements,
45 scmutil,
44 scmutil,
46 sshpeer,
45 sshpeer,
47 statichttprepo,
46 statichttprepo,
48 ui as uimod,
47 ui as uimod,
49 unionrepo,
48 unionrepo,
50 url,
49 url,
51 util,
50 util,
52 verify as verifymod,
51 verify as verifymod,
53 vfs as vfsmod,
52 vfs as vfsmod,
54 )
53 )
55 from .interfaces import repository as repositorymod
54 from .interfaces import repository as repositorymod
56 from .utils import (
55 from .utils import (
57 hashutil,
56 hashutil,
58 stringutil,
57 stringutil,
59 urlutil,
58 urlutil,
60 )
59 )
61
60
62
61
63 release = lock.release
62 release = lock.release
64
63
65 # shared features
64 # shared features
66 sharedbookmarks = b'bookmarks'
65 sharedbookmarks = b'bookmarks'
67
66
68
67
69 def _local(path):
68 def _local(path):
70 path = util.expandpath(urlutil.urllocalpath(path))
69 path = util.expandpath(urlutil.urllocalpath(path))
71
70
72 try:
71 try:
73 # we use os.stat() directly here instead of os.path.isfile()
72 # we use os.stat() directly here instead of os.path.isfile()
74 # because the latter started returning `False` on invalid path
73 # because the latter started returning `False` on invalid path
75 # exceptions starting in 3.8 and we care about handling
74 # exceptions starting in 3.8 and we care about handling
76 # invalid paths specially here.
75 # invalid paths specially here.
77 st = os.stat(path)
76 st = os.stat(path)
78 isfile = stat.S_ISREG(st.st_mode)
77 isfile = stat.S_ISREG(st.st_mode)
79 # Python 2 raises TypeError, Python 3 ValueError.
78 # Python 2 raises TypeError, Python 3 ValueError.
80 except (TypeError, ValueError) as e:
79 except (TypeError, ValueError) as e:
81 raise error.Abort(
80 raise error.Abort(
82 _(b'invalid path %s: %s') % (path, stringutil.forcebytestr(e))
81 _(b'invalid path %s: %s') % (path, stringutil.forcebytestr(e))
83 )
82 )
84 except OSError:
83 except OSError:
85 isfile = False
84 isfile = False
86
85
87 return isfile and bundlerepo or localrepo
86 return isfile and bundlerepo or localrepo
88
87
89
88
90 def addbranchrevs(lrepo, other, branches, revs):
89 def addbranchrevs(lrepo, other, branches, revs):
91 peer = other.peer() # a courtesy to callers using a localrepo for other
90 peer = other.peer() # a courtesy to callers using a localrepo for other
92 hashbranch, branches = branches
91 hashbranch, branches = branches
93 if not hashbranch and not branches:
92 if not hashbranch and not branches:
94 x = revs or None
93 x = revs or None
95 if revs:
94 if revs:
96 y = revs[0]
95 y = revs[0]
97 else:
96 else:
98 y = None
97 y = None
99 return x, y
98 return x, y
100 if revs:
99 if revs:
101 revs = list(revs)
100 revs = list(revs)
102 else:
101 else:
103 revs = []
102 revs = []
104
103
105 if not peer.capable(b'branchmap'):
104 if not peer.capable(b'branchmap'):
106 if branches:
105 if branches:
107 raise error.Abort(_(b"remote branch lookup not supported"))
106 raise error.Abort(_(b"remote branch lookup not supported"))
108 revs.append(hashbranch)
107 revs.append(hashbranch)
109 return revs, revs[0]
108 return revs, revs[0]
110
109
111 with peer.commandexecutor() as e:
110 with peer.commandexecutor() as e:
112 branchmap = e.callcommand(b'branchmap', {}).result()
111 branchmap = e.callcommand(b'branchmap', {}).result()
113
112
114 def primary(branch):
113 def primary(branch):
115 if branch == b'.':
114 if branch == b'.':
116 if not lrepo:
115 if not lrepo:
117 raise error.Abort(_(b"dirstate branch not accessible"))
116 raise error.Abort(_(b"dirstate branch not accessible"))
118 branch = lrepo.dirstate.branch()
117 branch = lrepo.dirstate.branch()
119 if branch in branchmap:
118 if branch in branchmap:
120 revs.extend(hex(r) for r in reversed(branchmap[branch]))
119 revs.extend(hex(r) for r in reversed(branchmap[branch]))
121 return True
120 return True
122 else:
121 else:
123 return False
122 return False
124
123
125 for branch in branches:
124 for branch in branches:
126 if not primary(branch):
125 if not primary(branch):
127 raise error.RepoLookupError(_(b"unknown branch '%s'") % branch)
126 raise error.RepoLookupError(_(b"unknown branch '%s'") % branch)
128 if hashbranch:
127 if hashbranch:
129 if not primary(hashbranch):
128 if not primary(hashbranch):
130 revs.append(hashbranch)
129 revs.append(hashbranch)
131 return revs, revs[0]
130 return revs, revs[0]
132
131
133
132
134 def parseurl(path, branches=None):
133 def parseurl(path, branches=None):
135 '''parse url#branch, returning (url, (branch, branches))'''
134 '''parse url#branch, returning (url, (branch, branches))'''
136 msg = b'parseurl(...) moved to mercurial.utils.urlutil'
135 msg = b'parseurl(...) moved to mercurial.utils.urlutil'
137 util.nouideprecwarn(msg, b'6.0', stacklevel=2)
136 util.nouideprecwarn(msg, b'6.0', stacklevel=2)
138 return urlutil.parseurl(path, branches=branches)
137 return urlutil.parseurl(path, branches=branches)
139
138
140
139
141 schemes = {
140 schemes = {
142 b'bundle': bundlerepo,
141 b'bundle': bundlerepo,
143 b'union': unionrepo,
142 b'union': unionrepo,
144 b'file': _local,
143 b'file': _local,
145 b'http': httppeer,
144 b'http': httppeer,
146 b'https': httppeer,
145 b'https': httppeer,
147 b'ssh': sshpeer,
146 b'ssh': sshpeer,
148 b'static-http': statichttprepo,
147 b'static-http': statichttprepo,
149 }
148 }
150
149
151
150
152 def _peerlookup(path):
151 def _peerlookup(path):
153 u = urlutil.url(path)
152 u = urlutil.url(path)
154 scheme = u.scheme or b'file'
153 scheme = u.scheme or b'file'
155 thing = schemes.get(scheme) or schemes[b'file']
154 thing = schemes.get(scheme) or schemes[b'file']
156 try:
155 try:
157 return thing(path)
156 return thing(path)
158 except TypeError:
157 except TypeError:
159 # we can't test callable(thing) because 'thing' can be an unloaded
158 # we can't test callable(thing) because 'thing' can be an unloaded
160 # module that implements __call__
159 # module that implements __call__
161 if not util.safehasattr(thing, b'instance'):
160 if not util.safehasattr(thing, b'instance'):
162 raise
161 raise
163 return thing
162 return thing
164
163
165
164
166 def islocal(repo):
165 def islocal(repo):
167 '''return true if repo (or path pointing to repo) is local'''
166 '''return true if repo (or path pointing to repo) is local'''
168 if isinstance(repo, bytes):
167 if isinstance(repo, bytes):
169 try:
168 try:
170 return _peerlookup(repo).islocal(repo)
169 return _peerlookup(repo).islocal(repo)
171 except AttributeError:
170 except AttributeError:
172 return False
171 return False
173 return repo.local()
172 return repo.local()
174
173
175
174
176 def openpath(ui, path, sendaccept=True):
175 def openpath(ui, path, sendaccept=True):
177 '''open path with open if local, url.open if remote'''
176 '''open path with open if local, url.open if remote'''
178 pathurl = urlutil.url(path, parsequery=False, parsefragment=False)
177 pathurl = urlutil.url(path, parsequery=False, parsefragment=False)
179 if pathurl.islocal():
178 if pathurl.islocal():
180 return util.posixfile(pathurl.localpath(), b'rb')
179 return util.posixfile(pathurl.localpath(), b'rb')
181 else:
180 else:
182 return url.open(ui, path, sendaccept=sendaccept)
181 return url.open(ui, path, sendaccept=sendaccept)
183
182
184
183
185 # a list of (ui, repo) functions called for wire peer initialization
184 # a list of (ui, repo) functions called for wire peer initialization
186 wirepeersetupfuncs = []
185 wirepeersetupfuncs = []
187
186
188
187
189 def _peerorrepo(
188 def _peerorrepo(
190 ui, path, create=False, presetupfuncs=None, intents=None, createopts=None
189 ui, path, create=False, presetupfuncs=None, intents=None, createopts=None
191 ):
190 ):
192 """return a repository object for the specified path"""
191 """return a repository object for the specified path"""
193 obj = _peerlookup(path).instance(
192 obj = _peerlookup(path).instance(
194 ui, path, create, intents=intents, createopts=createopts
193 ui, path, create, intents=intents, createopts=createopts
195 )
194 )
196 ui = getattr(obj, "ui", ui)
195 ui = getattr(obj, "ui", ui)
197 for f in presetupfuncs or []:
196 for f in presetupfuncs or []:
198 f(ui, obj)
197 f(ui, obj)
199 ui.log(b'extension', b'- executing reposetup hooks\n')
198 ui.log(b'extension', b'- executing reposetup hooks\n')
200 with util.timedcm('all reposetup') as allreposetupstats:
199 with util.timedcm('all reposetup') as allreposetupstats:
201 for name, module in extensions.extensions(ui):
200 for name, module in extensions.extensions(ui):
202 ui.log(b'extension', b' - running reposetup for %s\n', name)
201 ui.log(b'extension', b' - running reposetup for %s\n', name)
203 hook = getattr(module, 'reposetup', None)
202 hook = getattr(module, 'reposetup', None)
204 if hook:
203 if hook:
205 with util.timedcm('reposetup %r', name) as stats:
204 with util.timedcm('reposetup %r', name) as stats:
206 hook(ui, obj)
205 hook(ui, obj)
207 ui.log(
206 ui.log(
208 b'extension', b' > reposetup for %s took %s\n', name, stats
207 b'extension', b' > reposetup for %s took %s\n', name, stats
209 )
208 )
210 ui.log(b'extension', b'> all reposetup took %s\n', allreposetupstats)
209 ui.log(b'extension', b'> all reposetup took %s\n', allreposetupstats)
211 if not obj.local():
210 if not obj.local():
212 for f in wirepeersetupfuncs:
211 for f in wirepeersetupfuncs:
213 f(ui, obj)
212 f(ui, obj)
214 return obj
213 return obj
215
214
216
215
217 def repository(
216 def repository(
218 ui,
217 ui,
219 path=b'',
218 path=b'',
220 create=False,
219 create=False,
221 presetupfuncs=None,
220 presetupfuncs=None,
222 intents=None,
221 intents=None,
223 createopts=None,
222 createopts=None,
224 ):
223 ):
225 """return a repository object for the specified path"""
224 """return a repository object for the specified path"""
226 peer = _peerorrepo(
225 peer = _peerorrepo(
227 ui,
226 ui,
228 path,
227 path,
229 create,
228 create,
230 presetupfuncs=presetupfuncs,
229 presetupfuncs=presetupfuncs,
231 intents=intents,
230 intents=intents,
232 createopts=createopts,
231 createopts=createopts,
233 )
232 )
234 repo = peer.local()
233 repo = peer.local()
235 if not repo:
234 if not repo:
236 raise error.Abort(
235 raise error.Abort(
237 _(b"repository '%s' is not local") % (path or peer.url())
236 _(b"repository '%s' is not local") % (path or peer.url())
238 )
237 )
239 return repo.filtered(b'visible')
238 return repo.filtered(b'visible')
240
239
241
240
242 def peer(uiorrepo, opts, path, create=False, intents=None, createopts=None):
241 def peer(uiorrepo, opts, path, create=False, intents=None, createopts=None):
243 '''return a repository peer for the specified path'''
242 '''return a repository peer for the specified path'''
244 rui = remoteui(uiorrepo, opts)
243 rui = remoteui(uiorrepo, opts)
245 return _peerorrepo(
244 return _peerorrepo(
246 rui, path, create, intents=intents, createopts=createopts
245 rui, path, create, intents=intents, createopts=createopts
247 ).peer()
246 ).peer()
248
247
249
248
250 def defaultdest(source):
249 def defaultdest(source):
251 """return default destination of clone if none is given
250 """return default destination of clone if none is given
252
251
253 >>> defaultdest(b'foo')
252 >>> defaultdest(b'foo')
254 'foo'
253 'foo'
255 >>> defaultdest(b'/foo/bar')
254 >>> defaultdest(b'/foo/bar')
256 'bar'
255 'bar'
257 >>> defaultdest(b'/')
256 >>> defaultdest(b'/')
258 ''
257 ''
259 >>> defaultdest(b'')
258 >>> defaultdest(b'')
260 ''
259 ''
261 >>> defaultdest(b'http://example.org/')
260 >>> defaultdest(b'http://example.org/')
262 ''
261 ''
263 >>> defaultdest(b'http://example.org/foo/')
262 >>> defaultdest(b'http://example.org/foo/')
264 'foo'
263 'foo'
265 """
264 """
266 path = urlutil.url(source).path
265 path = urlutil.url(source).path
267 if not path:
266 if not path:
268 return b''
267 return b''
269 return os.path.basename(os.path.normpath(path))
268 return os.path.basename(os.path.normpath(path))
270
269
271
270
272 def sharedreposource(repo):
271 def sharedreposource(repo):
273 """Returns repository object for source repository of a shared repo.
272 """Returns repository object for source repository of a shared repo.
274
273
275 If repo is not a shared repository, returns None.
274 If repo is not a shared repository, returns None.
276 """
275 """
277 if repo.sharedpath == repo.path:
276 if repo.sharedpath == repo.path:
278 return None
277 return None
279
278
280 if util.safehasattr(repo, b'srcrepo') and repo.srcrepo:
279 if util.safehasattr(repo, b'srcrepo') and repo.srcrepo:
281 return repo.srcrepo
280 return repo.srcrepo
282
281
283 # the sharedpath always ends in the .hg; we want the path to the repo
282 # the sharedpath always ends in the .hg; we want the path to the repo
284 source = repo.vfs.split(repo.sharedpath)[0]
283 source = repo.vfs.split(repo.sharedpath)[0]
285 srcurl, branches = urlutil.parseurl(source)
284 srcurl, branches = urlutil.parseurl(source)
286 srcrepo = repository(repo.ui, srcurl)
285 srcrepo = repository(repo.ui, srcurl)
287 repo.srcrepo = srcrepo
286 repo.srcrepo = srcrepo
288 return srcrepo
287 return srcrepo
289
288
290
289
291 def share(
290 def share(
292 ui,
291 ui,
293 source,
292 source,
294 dest=None,
293 dest=None,
295 update=True,
294 update=True,
296 bookmarks=True,
295 bookmarks=True,
297 defaultpath=None,
296 defaultpath=None,
298 relative=False,
297 relative=False,
299 ):
298 ):
300 '''create a shared repository'''
299 '''create a shared repository'''
301
300
302 if not islocal(source):
301 if not islocal(source):
303 raise error.Abort(_(b'can only share local repositories'))
302 raise error.Abort(_(b'can only share local repositories'))
304
303
305 if not dest:
304 if not dest:
306 dest = defaultdest(source)
305 dest = defaultdest(source)
307 else:
306 else:
308 dest = urlutil.get_clone_path(ui, dest)[1]
307 dest = urlutil.get_clone_path(ui, dest)[1]
309
308
310 if isinstance(source, bytes):
309 if isinstance(source, bytes):
311 origsource, source, branches = urlutil.get_clone_path(ui, source)
310 origsource, source, branches = urlutil.get_clone_path(ui, source)
312 srcrepo = repository(ui, source)
311 srcrepo = repository(ui, source)
313 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
312 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
314 else:
313 else:
315 srcrepo = source.local()
314 srcrepo = source.local()
316 checkout = None
315 checkout = None
317
316
318 shareditems = set()
317 shareditems = set()
319 if bookmarks:
318 if bookmarks:
320 shareditems.add(sharedbookmarks)
319 shareditems.add(sharedbookmarks)
321
320
322 r = repository(
321 r = repository(
323 ui,
322 ui,
324 dest,
323 dest,
325 create=True,
324 create=True,
326 createopts={
325 createopts={
327 b'sharedrepo': srcrepo,
326 b'sharedrepo': srcrepo,
328 b'sharedrelative': relative,
327 b'sharedrelative': relative,
329 b'shareditems': shareditems,
328 b'shareditems': shareditems,
330 },
329 },
331 )
330 )
332
331
333 postshare(srcrepo, r, defaultpath=defaultpath)
332 postshare(srcrepo, r, defaultpath=defaultpath)
334 r = repository(ui, dest)
333 r = repository(ui, dest)
335 _postshareupdate(r, update, checkout=checkout)
334 _postshareupdate(r, update, checkout=checkout)
336 return r
335 return r
337
336
338
337
339 def _prependsourcehgrc(repo):
338 def _prependsourcehgrc(repo):
340 """copies the source repo config and prepend it in current repo .hg/hgrc
339 """copies the source repo config and prepend it in current repo .hg/hgrc
341 on unshare. This is only done if the share was perfomed using share safe
340 on unshare. This is only done if the share was perfomed using share safe
342 method where we share config of source in shares"""
341 method where we share config of source in shares"""
343 srcvfs = vfsmod.vfs(repo.sharedpath)
342 srcvfs = vfsmod.vfs(repo.sharedpath)
344 dstvfs = vfsmod.vfs(repo.path)
343 dstvfs = vfsmod.vfs(repo.path)
345
344
346 if not srcvfs.exists(b'hgrc'):
345 if not srcvfs.exists(b'hgrc'):
347 return
346 return
348
347
349 currentconfig = b''
348 currentconfig = b''
350 if dstvfs.exists(b'hgrc'):
349 if dstvfs.exists(b'hgrc'):
351 currentconfig = dstvfs.read(b'hgrc')
350 currentconfig = dstvfs.read(b'hgrc')
352
351
353 with dstvfs(b'hgrc', b'wb') as fp:
352 with dstvfs(b'hgrc', b'wb') as fp:
354 sourceconfig = srcvfs.read(b'hgrc')
353 sourceconfig = srcvfs.read(b'hgrc')
355 fp.write(b"# Config copied from shared source\n")
354 fp.write(b"# Config copied from shared source\n")
356 fp.write(sourceconfig)
355 fp.write(sourceconfig)
357 fp.write(b'\n')
356 fp.write(b'\n')
358 fp.write(currentconfig)
357 fp.write(currentconfig)
359
358
360
359
361 def unshare(ui, repo):
360 def unshare(ui, repo):
362 """convert a shared repository to a normal one
361 """convert a shared repository to a normal one
363
362
364 Copy the store data to the repo and remove the sharedpath data.
363 Copy the store data to the repo and remove the sharedpath data.
365
364
366 Returns a new repository object representing the unshared repository.
365 Returns a new repository object representing the unshared repository.
367
366
368 The passed repository object is not usable after this function is
367 The passed repository object is not usable after this function is
369 called.
368 called.
370 """
369 """
371
370
372 with repo.lock():
371 with repo.lock():
373 # we use locks here because if we race with commit, we
372 # we use locks here because if we race with commit, we
374 # can end up with extra data in the cloned revlogs that's
373 # can end up with extra data in the cloned revlogs that's
375 # not pointed to by changesets, thus causing verify to
374 # not pointed to by changesets, thus causing verify to
376 # fail
375 # fail
377 destlock = copystore(ui, repo, repo.path)
376 destlock = copystore(ui, repo, repo.path)
378 with destlock or util.nullcontextmanager():
377 with destlock or util.nullcontextmanager():
379 if requirements.SHARESAFE_REQUIREMENT in repo.requirements:
378 if requirements.SHARESAFE_REQUIREMENT in repo.requirements:
380 # we were sharing .hg/hgrc of the share source with the current
379 # we were sharing .hg/hgrc of the share source with the current
381 # repo. We need to copy that while unsharing otherwise it can
380 # repo. We need to copy that while unsharing otherwise it can
382 # disable hooks and other checks
381 # disable hooks and other checks
383 _prependsourcehgrc(repo)
382 _prependsourcehgrc(repo)
384
383
385 sharefile = repo.vfs.join(b'sharedpath')
384 sharefile = repo.vfs.join(b'sharedpath')
386 util.rename(sharefile, sharefile + b'.old')
385 util.rename(sharefile, sharefile + b'.old')
387
386
388 repo.requirements.discard(requirements.SHARED_REQUIREMENT)
387 repo.requirements.discard(requirements.SHARED_REQUIREMENT)
389 repo.requirements.discard(requirements.RELATIVE_SHARED_REQUIREMENT)
388 repo.requirements.discard(requirements.RELATIVE_SHARED_REQUIREMENT)
390 scmutil.writereporequirements(repo)
389 scmutil.writereporequirements(repo)
391
390
392 # Removing share changes some fundamental properties of the repo instance.
391 # Removing share changes some fundamental properties of the repo instance.
393 # So we instantiate a new repo object and operate on it rather than
392 # So we instantiate a new repo object and operate on it rather than
394 # try to keep the existing repo usable.
393 # try to keep the existing repo usable.
395 newrepo = repository(repo.baseui, repo.root, create=False)
394 newrepo = repository(repo.baseui, repo.root, create=False)
396
395
397 # TODO: figure out how to access subrepos that exist, but were previously
396 # TODO: figure out how to access subrepos that exist, but were previously
398 # removed from .hgsub
397 # removed from .hgsub
399 c = newrepo[b'.']
398 c = newrepo[b'.']
400 subs = c.substate
399 subs = c.substate
401 for s in sorted(subs):
400 for s in sorted(subs):
402 c.sub(s).unshare()
401 c.sub(s).unshare()
403
402
404 localrepo.poisonrepository(repo)
403 localrepo.poisonrepository(repo)
405
404
406 return newrepo
405 return newrepo
407
406
408
407
409 def postshare(sourcerepo, destrepo, defaultpath=None):
408 def postshare(sourcerepo, destrepo, defaultpath=None):
410 """Called after a new shared repo is created.
409 """Called after a new shared repo is created.
411
410
412 The new repo only has a requirements file and pointer to the source.
411 The new repo only has a requirements file and pointer to the source.
413 This function configures additional shared data.
412 This function configures additional shared data.
414
413
415 Extensions can wrap this function and write additional entries to
414 Extensions can wrap this function and write additional entries to
416 destrepo/.hg/shared to indicate additional pieces of data to be shared.
415 destrepo/.hg/shared to indicate additional pieces of data to be shared.
417 """
416 """
418 default = defaultpath or sourcerepo.ui.config(b'paths', b'default')
417 default = defaultpath or sourcerepo.ui.config(b'paths', b'default')
419 if default:
418 if default:
420 template = b'[paths]\ndefault = %s\n'
419 template = b'[paths]\ndefault = %s\n'
421 destrepo.vfs.write(b'hgrc', util.tonativeeol(template % default))
420 destrepo.vfs.write(b'hgrc', util.tonativeeol(template % default))
422 if requirements.NARROW_REQUIREMENT in sourcerepo.requirements:
421 if requirements.NARROW_REQUIREMENT in sourcerepo.requirements:
423 with destrepo.wlock():
422 with destrepo.wlock():
424 narrowspec.copytoworkingcopy(destrepo)
423 narrowspec.copytoworkingcopy(destrepo)
425
424
426
425
427 def _postshareupdate(repo, update, checkout=None):
426 def _postshareupdate(repo, update, checkout=None):
428 """Maybe perform a working directory update after a shared repo is created.
427 """Maybe perform a working directory update after a shared repo is created.
429
428
430 ``update`` can be a boolean or a revision to update to.
429 ``update`` can be a boolean or a revision to update to.
431 """
430 """
432 if not update:
431 if not update:
433 return
432 return
434
433
435 repo.ui.status(_(b"updating working directory\n"))
434 repo.ui.status(_(b"updating working directory\n"))
436 if update is not True:
435 if update is not True:
437 checkout = update
436 checkout = update
438 for test in (checkout, b'default', b'tip'):
437 for test in (checkout, b'default', b'tip'):
439 if test is None:
438 if test is None:
440 continue
439 continue
441 try:
440 try:
442 uprev = repo.lookup(test)
441 uprev = repo.lookup(test)
443 break
442 break
444 except error.RepoLookupError:
443 except error.RepoLookupError:
445 continue
444 continue
446 _update(repo, uprev)
445 _update(repo, uprev)
447
446
448
447
449 def copystore(ui, srcrepo, destpath):
448 def copystore(ui, srcrepo, destpath):
450 """copy files from store of srcrepo in destpath
449 """copy files from store of srcrepo in destpath
451
450
452 returns destlock
451 returns destlock
453 """
452 """
454 destlock = None
453 destlock = None
455 try:
454 try:
456 hardlink = None
455 hardlink = None
457 topic = _(b'linking') if hardlink else _(b'copying')
456 topic = _(b'linking') if hardlink else _(b'copying')
458 with ui.makeprogress(topic, unit=_(b'files')) as progress:
457 with ui.makeprogress(topic, unit=_(b'files')) as progress:
459 num = 0
458 num = 0
460 srcpublishing = srcrepo.publishing()
459 srcpublishing = srcrepo.publishing()
461 srcvfs = vfsmod.vfs(srcrepo.sharedpath)
460 srcvfs = vfsmod.vfs(srcrepo.sharedpath)
462 dstvfs = vfsmod.vfs(destpath)
461 dstvfs = vfsmod.vfs(destpath)
463 for f in srcrepo.store.copylist():
462 for f in srcrepo.store.copylist():
464 if srcpublishing and f.endswith(b'phaseroots'):
463 if srcpublishing and f.endswith(b'phaseroots'):
465 continue
464 continue
466 dstbase = os.path.dirname(f)
465 dstbase = os.path.dirname(f)
467 if dstbase and not dstvfs.exists(dstbase):
466 if dstbase and not dstvfs.exists(dstbase):
468 dstvfs.mkdir(dstbase)
467 dstvfs.mkdir(dstbase)
469 if srcvfs.exists(f):
468 if srcvfs.exists(f):
470 if f.endswith(b'data'):
469 if f.endswith(b'data'):
471 # 'dstbase' may be empty (e.g. revlog format 0)
470 # 'dstbase' may be empty (e.g. revlog format 0)
472 lockfile = os.path.join(dstbase, b"lock")
471 lockfile = os.path.join(dstbase, b"lock")
473 # lock to avoid premature writing to the target
472 # lock to avoid premature writing to the target
474 destlock = lock.lock(dstvfs, lockfile)
473 destlock = lock.lock(dstvfs, lockfile)
475 hardlink, n = util.copyfiles(
474 hardlink, n = util.copyfiles(
476 srcvfs.join(f), dstvfs.join(f), hardlink, progress
475 srcvfs.join(f), dstvfs.join(f), hardlink, progress
477 )
476 )
478 num += n
477 num += n
479 if hardlink:
478 if hardlink:
480 ui.debug(b"linked %d files\n" % num)
479 ui.debug(b"linked %d files\n" % num)
481 else:
480 else:
482 ui.debug(b"copied %d files\n" % num)
481 ui.debug(b"copied %d files\n" % num)
483 return destlock
482 return destlock
484 except: # re-raises
483 except: # re-raises
485 release(destlock)
484 release(destlock)
486 raise
485 raise
487
486
488
487
489 def clonewithshare(
488 def clonewithshare(
490 ui,
489 ui,
491 peeropts,
490 peeropts,
492 sharepath,
491 sharepath,
493 source,
492 source,
494 srcpeer,
493 srcpeer,
495 dest,
494 dest,
496 pull=False,
495 pull=False,
497 rev=None,
496 rev=None,
498 update=True,
497 update=True,
499 stream=False,
498 stream=False,
500 ):
499 ):
501 """Perform a clone using a shared repo.
500 """Perform a clone using a shared repo.
502
501
503 The store for the repository will be located at <sharepath>/.hg. The
502 The store for the repository will be located at <sharepath>/.hg. The
504 specified revisions will be cloned or pulled from "source". A shared repo
503 specified revisions will be cloned or pulled from "source". A shared repo
505 will be created at "dest" and a working copy will be created if "update" is
504 will be created at "dest" and a working copy will be created if "update" is
506 True.
505 True.
507 """
506 """
508 revs = None
507 revs = None
509 if rev:
508 if rev:
510 if not srcpeer.capable(b'lookup'):
509 if not srcpeer.capable(b'lookup'):
511 raise error.Abort(
510 raise error.Abort(
512 _(
511 _(
513 b"src repository does not support "
512 b"src repository does not support "
514 b"revision lookup and so doesn't "
513 b"revision lookup and so doesn't "
515 b"support clone by revision"
514 b"support clone by revision"
516 )
515 )
517 )
516 )
518
517
519 # TODO this is batchable.
518 # TODO this is batchable.
520 remoterevs = []
519 remoterevs = []
521 for r in rev:
520 for r in rev:
522 with srcpeer.commandexecutor() as e:
521 with srcpeer.commandexecutor() as e:
523 remoterevs.append(
522 remoterevs.append(
524 e.callcommand(
523 e.callcommand(
525 b'lookup',
524 b'lookup',
526 {
525 {
527 b'key': r,
526 b'key': r,
528 },
527 },
529 ).result()
528 ).result()
530 )
529 )
531 revs = remoterevs
530 revs = remoterevs
532
531
533 # Obtain a lock before checking for or cloning the pooled repo otherwise
532 # Obtain a lock before checking for or cloning the pooled repo otherwise
534 # 2 clients may race creating or populating it.
533 # 2 clients may race creating or populating it.
535 pooldir = os.path.dirname(sharepath)
534 pooldir = os.path.dirname(sharepath)
536 # lock class requires the directory to exist.
535 # lock class requires the directory to exist.
537 try:
536 try:
538 util.makedir(pooldir, False)
537 util.makedir(pooldir, False)
539 except OSError as e:
538 except OSError as e:
540 if e.errno != errno.EEXIST:
539 if e.errno != errno.EEXIST:
541 raise
540 raise
542
541
543 poolvfs = vfsmod.vfs(pooldir)
542 poolvfs = vfsmod.vfs(pooldir)
544 basename = os.path.basename(sharepath)
543 basename = os.path.basename(sharepath)
545
544
546 with lock.lock(poolvfs, b'%s.lock' % basename):
545 with lock.lock(poolvfs, b'%s.lock' % basename):
547 if os.path.exists(sharepath):
546 if os.path.exists(sharepath):
548 ui.status(
547 ui.status(
549 _(b'(sharing from existing pooled repository %s)\n') % basename
548 _(b'(sharing from existing pooled repository %s)\n') % basename
550 )
549 )
551 else:
550 else:
552 ui.status(
551 ui.status(
553 _(b'(sharing from new pooled repository %s)\n') % basename
552 _(b'(sharing from new pooled repository %s)\n') % basename
554 )
553 )
555 # Always use pull mode because hardlinks in share mode don't work
554 # Always use pull mode because hardlinks in share mode don't work
556 # well. Never update because working copies aren't necessary in
555 # well. Never update because working copies aren't necessary in
557 # share mode.
556 # share mode.
558 clone(
557 clone(
559 ui,
558 ui,
560 peeropts,
559 peeropts,
561 source,
560 source,
562 dest=sharepath,
561 dest=sharepath,
563 pull=True,
562 pull=True,
564 revs=rev,
563 revs=rev,
565 update=False,
564 update=False,
566 stream=stream,
565 stream=stream,
567 )
566 )
568
567
569 # Resolve the value to put in [paths] section for the source.
568 # Resolve the value to put in [paths] section for the source.
570 if islocal(source):
569 if islocal(source):
571 defaultpath = os.path.abspath(urlutil.urllocalpath(source))
570 defaultpath = os.path.abspath(urlutil.urllocalpath(source))
572 else:
571 else:
573 defaultpath = source
572 defaultpath = source
574
573
575 sharerepo = repository(ui, path=sharepath)
574 sharerepo = repository(ui, path=sharepath)
576 destrepo = share(
575 destrepo = share(
577 ui,
576 ui,
578 sharerepo,
577 sharerepo,
579 dest=dest,
578 dest=dest,
580 update=False,
579 update=False,
581 bookmarks=False,
580 bookmarks=False,
582 defaultpath=defaultpath,
581 defaultpath=defaultpath,
583 )
582 )
584
583
585 # We need to perform a pull against the dest repo to fetch bookmarks
584 # We need to perform a pull against the dest repo to fetch bookmarks
586 # and other non-store data that isn't shared by default. In the case of
585 # and other non-store data that isn't shared by default. In the case of
587 # non-existing shared repo, this means we pull from the remote twice. This
586 # non-existing shared repo, this means we pull from the remote twice. This
588 # is a bit weird. But at the time it was implemented, there wasn't an easy
587 # is a bit weird. But at the time it was implemented, there wasn't an easy
589 # way to pull just non-changegroup data.
588 # way to pull just non-changegroup data.
590 exchange.pull(destrepo, srcpeer, heads=revs)
589 exchange.pull(destrepo, srcpeer, heads=revs)
591
590
592 _postshareupdate(destrepo, update)
591 _postshareupdate(destrepo, update)
593
592
594 return srcpeer, peer(ui, peeropts, dest)
593 return srcpeer, peer(ui, peeropts, dest)
595
594
596
595
597 # Recomputing caches is often slow on big repos, so copy them.
596 # Recomputing caches is often slow on big repos, so copy them.
598 def _copycache(srcrepo, dstcachedir, fname):
597 def _copycache(srcrepo, dstcachedir, fname):
599 """copy a cache from srcrepo to destcachedir (if it exists)"""
598 """copy a cache from srcrepo to destcachedir (if it exists)"""
600 srcfname = srcrepo.cachevfs.join(fname)
599 srcfname = srcrepo.cachevfs.join(fname)
601 dstfname = os.path.join(dstcachedir, fname)
600 dstfname = os.path.join(dstcachedir, fname)
602 if os.path.exists(srcfname):
601 if os.path.exists(srcfname):
603 if not os.path.exists(dstcachedir):
602 if not os.path.exists(dstcachedir):
604 os.mkdir(dstcachedir)
603 os.mkdir(dstcachedir)
605 util.copyfile(srcfname, dstfname)
604 util.copyfile(srcfname, dstfname)
606
605
607
606
608 def clone(
607 def clone(
609 ui,
608 ui,
610 peeropts,
609 peeropts,
611 source,
610 source,
612 dest=None,
611 dest=None,
613 pull=False,
612 pull=False,
614 revs=None,
613 revs=None,
615 update=True,
614 update=True,
616 stream=False,
615 stream=False,
617 branch=None,
616 branch=None,
618 shareopts=None,
617 shareopts=None,
619 storeincludepats=None,
618 storeincludepats=None,
620 storeexcludepats=None,
619 storeexcludepats=None,
621 depth=None,
620 depth=None,
622 ):
621 ):
623 """Make a copy of an existing repository.
622 """Make a copy of an existing repository.
624
623
625 Create a copy of an existing repository in a new directory. The
624 Create a copy of an existing repository in a new directory. The
626 source and destination are URLs, as passed to the repository
625 source and destination are URLs, as passed to the repository
627 function. Returns a pair of repository peers, the source and
626 function. Returns a pair of repository peers, the source and
628 newly created destination.
627 newly created destination.
629
628
630 The location of the source is added to the new repository's
629 The location of the source is added to the new repository's
631 .hg/hgrc file, as the default to be used for future pulls and
630 .hg/hgrc file, as the default to be used for future pulls and
632 pushes.
631 pushes.
633
632
634 If an exception is raised, the partly cloned/updated destination
633 If an exception is raised, the partly cloned/updated destination
635 repository will be deleted.
634 repository will be deleted.
636
635
637 Arguments:
636 Arguments:
638
637
639 source: repository object or URL
638 source: repository object or URL
640
639
641 dest: URL of destination repository to create (defaults to base
640 dest: URL of destination repository to create (defaults to base
642 name of source repository)
641 name of source repository)
643
642
644 pull: always pull from source repository, even in local case or if the
643 pull: always pull from source repository, even in local case or if the
645 server prefers streaming
644 server prefers streaming
646
645
647 stream: stream raw data uncompressed from repository (fast over
646 stream: stream raw data uncompressed from repository (fast over
648 LAN, slow over WAN)
647 LAN, slow over WAN)
649
648
650 revs: revision to clone up to (implies pull=True)
649 revs: revision to clone up to (implies pull=True)
651
650
652 update: update working directory after clone completes, if
651 update: update working directory after clone completes, if
653 destination is local repository (True means update to default rev,
652 destination is local repository (True means update to default rev,
654 anything else is treated as a revision)
653 anything else is treated as a revision)
655
654
656 branch: branches to clone
655 branch: branches to clone
657
656
658 shareopts: dict of options to control auto sharing behavior. The "pool" key
657 shareopts: dict of options to control auto sharing behavior. The "pool" key
659 activates auto sharing mode and defines the directory for stores. The
658 activates auto sharing mode and defines the directory for stores. The
660 "mode" key determines how to construct the directory name of the shared
659 "mode" key determines how to construct the directory name of the shared
661 repository. "identity" means the name is derived from the node of the first
660 repository. "identity" means the name is derived from the node of the first
662 changeset in the repository. "remote" means the name is derived from the
661 changeset in the repository. "remote" means the name is derived from the
663 remote's path/URL. Defaults to "identity."
662 remote's path/URL. Defaults to "identity."
664
663
665 storeincludepats and storeexcludepats: sets of file patterns to include and
664 storeincludepats and storeexcludepats: sets of file patterns to include and
666 exclude in the repository copy, respectively. If not defined, all files
665 exclude in the repository copy, respectively. If not defined, all files
667 will be included (a "full" clone). Otherwise a "narrow" clone containing
666 will be included (a "full" clone). Otherwise a "narrow" clone containing
668 only the requested files will be performed. If ``storeincludepats`` is not
667 only the requested files will be performed. If ``storeincludepats`` is not
669 defined but ``storeexcludepats`` is, ``storeincludepats`` is assumed to be
668 defined but ``storeexcludepats`` is, ``storeincludepats`` is assumed to be
670 ``path:.``. If both are empty sets, no files will be cloned.
669 ``path:.``. If both are empty sets, no files will be cloned.
671 """
670 """
672
671
673 if isinstance(source, bytes):
672 if isinstance(source, bytes):
674 src = urlutil.get_clone_path(ui, source, branch)
673 src = urlutil.get_clone_path(ui, source, branch)
675 origsource, source, branches = src
674 origsource, source, branches = src
676 srcpeer = peer(ui, peeropts, source)
675 srcpeer = peer(ui, peeropts, source)
677 else:
676 else:
678 srcpeer = source.peer() # in case we were called with a localrepo
677 srcpeer = source.peer() # in case we were called with a localrepo
679 branches = (None, branch or [])
678 branches = (None, branch or [])
680 origsource = source = srcpeer.url()
679 origsource = source = srcpeer.url()
681 srclock = destlock = cleandir = None
680 srclock = destlock = cleandir = None
682 destpeer = None
681 destpeer = None
683 try:
682 try:
684 revs, checkout = addbranchrevs(srcpeer, srcpeer, branches, revs)
683 revs, checkout = addbranchrevs(srcpeer, srcpeer, branches, revs)
685
684
686 if dest is None:
685 if dest is None:
687 dest = defaultdest(source)
686 dest = defaultdest(source)
688 if dest:
687 if dest:
689 ui.status(_(b"destination directory: %s\n") % dest)
688 ui.status(_(b"destination directory: %s\n") % dest)
690 else:
689 else:
691 dest = urlutil.get_clone_path(ui, dest)[0]
690 dest = urlutil.get_clone_path(ui, dest)[0]
692
691
693 dest = urlutil.urllocalpath(dest)
692 dest = urlutil.urllocalpath(dest)
694 source = urlutil.urllocalpath(source)
693 source = urlutil.urllocalpath(source)
695
694
696 if not dest:
695 if not dest:
697 raise error.InputError(_(b"empty destination path is not valid"))
696 raise error.InputError(_(b"empty destination path is not valid"))
698
697
699 destvfs = vfsmod.vfs(dest, expandpath=True)
698 destvfs = vfsmod.vfs(dest, expandpath=True)
700 if destvfs.lexists():
699 if destvfs.lexists():
701 if not destvfs.isdir():
700 if not destvfs.isdir():
702 raise error.InputError(
701 raise error.InputError(
703 _(b"destination '%s' already exists") % dest
702 _(b"destination '%s' already exists") % dest
704 )
703 )
705 elif destvfs.listdir():
704 elif destvfs.listdir():
706 raise error.InputError(
705 raise error.InputError(
707 _(b"destination '%s' is not empty") % dest
706 _(b"destination '%s' is not empty") % dest
708 )
707 )
709
708
710 createopts = {}
709 createopts = {}
711 narrow = False
710 narrow = False
712
711
713 if storeincludepats is not None:
712 if storeincludepats is not None:
714 narrowspec.validatepatterns(storeincludepats)
713 narrowspec.validatepatterns(storeincludepats)
715 narrow = True
714 narrow = True
716
715
717 if storeexcludepats is not None:
716 if storeexcludepats is not None:
718 narrowspec.validatepatterns(storeexcludepats)
717 narrowspec.validatepatterns(storeexcludepats)
719 narrow = True
718 narrow = True
720
719
721 if narrow:
720 if narrow:
722 # Include everything by default if only exclusion patterns defined.
721 # Include everything by default if only exclusion patterns defined.
723 if storeexcludepats and not storeincludepats:
722 if storeexcludepats and not storeincludepats:
724 storeincludepats = {b'path:.'}
723 storeincludepats = {b'path:.'}
725
724
726 createopts[b'narrowfiles'] = True
725 createopts[b'narrowfiles'] = True
727
726
728 if depth:
727 if depth:
729 createopts[b'shallowfilestore'] = True
728 createopts[b'shallowfilestore'] = True
730
729
731 if srcpeer.capable(b'lfs-serve'):
730 if srcpeer.capable(b'lfs-serve'):
732 # Repository creation honors the config if it disabled the extension, so
731 # Repository creation honors the config if it disabled the extension, so
733 # we can't just announce that lfs will be enabled. This check avoids
732 # we can't just announce that lfs will be enabled. This check avoids
734 # saying that lfs will be enabled, and then saying it's an unknown
733 # saying that lfs will be enabled, and then saying it's an unknown
735 # feature. The lfs creation option is set in either case so that a
734 # feature. The lfs creation option is set in either case so that a
736 # requirement is added. If the extension is explicitly disabled but the
735 # requirement is added. If the extension is explicitly disabled but the
737 # requirement is set, the clone aborts early, before transferring any
736 # requirement is set, the clone aborts early, before transferring any
738 # data.
737 # data.
739 createopts[b'lfs'] = True
738 createopts[b'lfs'] = True
740
739
741 if extensions.disabled_help(b'lfs'):
740 if extensions.disabled_help(b'lfs'):
742 ui.status(
741 ui.status(
743 _(
742 _(
744 b'(remote is using large file support (lfs), but it is '
743 b'(remote is using large file support (lfs), but it is '
745 b'explicitly disabled in the local configuration)\n'
744 b'explicitly disabled in the local configuration)\n'
746 )
745 )
747 )
746 )
748 else:
747 else:
749 ui.status(
748 ui.status(
750 _(
749 _(
751 b'(remote is using large file support (lfs); lfs will '
750 b'(remote is using large file support (lfs); lfs will '
752 b'be enabled for this repository)\n'
751 b'be enabled for this repository)\n'
753 )
752 )
754 )
753 )
755
754
756 shareopts = shareopts or {}
755 shareopts = shareopts or {}
757 sharepool = shareopts.get(b'pool')
756 sharepool = shareopts.get(b'pool')
758 sharenamemode = shareopts.get(b'mode')
757 sharenamemode = shareopts.get(b'mode')
759 if sharepool and islocal(dest):
758 if sharepool and islocal(dest):
760 sharepath = None
759 sharepath = None
761 if sharenamemode == b'identity':
760 if sharenamemode == b'identity':
762 # Resolve the name from the initial changeset in the remote
761 # Resolve the name from the initial changeset in the remote
763 # repository. This returns nullid when the remote is empty. It
762 # repository. This returns nullid when the remote is empty. It
764 # raises RepoLookupError if revision 0 is filtered or otherwise
763 # raises RepoLookupError if revision 0 is filtered or otherwise
765 # not available. If we fail to resolve, sharing is not enabled.
764 # not available. If we fail to resolve, sharing is not enabled.
766 try:
765 try:
767 with srcpeer.commandexecutor() as e:
766 with srcpeer.commandexecutor() as e:
768 rootnode = e.callcommand(
767 rootnode = e.callcommand(
769 b'lookup',
768 b'lookup',
770 {
769 {
771 b'key': b'0',
770 b'key': b'0',
772 },
771 },
773 ).result()
772 ).result()
774
773
775 if rootnode != sha1nodeconstants.nullid:
774 if rootnode != sha1nodeconstants.nullid:
776 sharepath = os.path.join(sharepool, hex(rootnode))
775 sharepath = os.path.join(sharepool, hex(rootnode))
777 else:
776 else:
778 ui.status(
777 ui.status(
779 _(
778 _(
780 b'(not using pooled storage: '
779 b'(not using pooled storage: '
781 b'remote appears to be empty)\n'
780 b'remote appears to be empty)\n'
782 )
781 )
783 )
782 )
784 except error.RepoLookupError:
783 except error.RepoLookupError:
785 ui.status(
784 ui.status(
786 _(
785 _(
787 b'(not using pooled storage: '
786 b'(not using pooled storage: '
788 b'unable to resolve identity of remote)\n'
787 b'unable to resolve identity of remote)\n'
789 )
788 )
790 )
789 )
791 elif sharenamemode == b'remote':
790 elif sharenamemode == b'remote':
792 sharepath = os.path.join(
791 sharepath = os.path.join(
793 sharepool, hex(hashutil.sha1(source).digest())
792 sharepool, hex(hashutil.sha1(source).digest())
794 )
793 )
795 else:
794 else:
796 raise error.Abort(
795 raise error.Abort(
797 _(b'unknown share naming mode: %s') % sharenamemode
796 _(b'unknown share naming mode: %s') % sharenamemode
798 )
797 )
799
798
800 # TODO this is a somewhat arbitrary restriction.
799 # TODO this is a somewhat arbitrary restriction.
801 if narrow:
800 if narrow:
802 ui.status(
801 ui.status(
803 _(b'(pooled storage not supported for narrow clones)\n')
802 _(b'(pooled storage not supported for narrow clones)\n')
804 )
803 )
805 sharepath = None
804 sharepath = None
806
805
807 if sharepath:
806 if sharepath:
808 return clonewithshare(
807 return clonewithshare(
809 ui,
808 ui,
810 peeropts,
809 peeropts,
811 sharepath,
810 sharepath,
812 source,
811 source,
813 srcpeer,
812 srcpeer,
814 dest,
813 dest,
815 pull=pull,
814 pull=pull,
816 rev=revs,
815 rev=revs,
817 update=update,
816 update=update,
818 stream=stream,
817 stream=stream,
819 )
818 )
820
819
821 srcrepo = srcpeer.local()
820 srcrepo = srcpeer.local()
822
821
823 abspath = origsource
822 abspath = origsource
824 if islocal(origsource):
823 if islocal(origsource):
825 abspath = os.path.abspath(urlutil.urllocalpath(origsource))
824 abspath = os.path.abspath(urlutil.urllocalpath(origsource))
826
825
827 if islocal(dest):
826 if islocal(dest):
828 if os.path.exists(dest):
827 if os.path.exists(dest):
829 # only clean up directories we create ourselves
828 # only clean up directories we create ourselves
830 hgdir = os.path.realpath(os.path.join(dest, b".hg"))
829 hgdir = os.path.realpath(os.path.join(dest, b".hg"))
831 cleandir = hgdir
830 cleandir = hgdir
832 else:
831 else:
833 cleandir = dest
832 cleandir = dest
834
833
835 copy = False
834 copy = False
836 if (
835 if (
837 srcrepo
836 srcrepo
838 and srcrepo.cancopy()
837 and srcrepo.cancopy()
839 and islocal(dest)
838 and islocal(dest)
840 and not phases.hassecret(srcrepo)
839 and not phases.hassecret(srcrepo)
841 ):
840 ):
842 copy = not pull and not revs
841 copy = not pull and not revs
843
842
844 # TODO this is a somewhat arbitrary restriction.
843 # TODO this is a somewhat arbitrary restriction.
845 if narrow:
844 if narrow:
846 copy = False
845 copy = False
847
846
848 if copy:
847 if copy:
849 try:
848 try:
850 # we use a lock here because if we race with commit, we
849 # we use a lock here because if we race with commit, we
851 # can end up with extra data in the cloned revlogs that's
850 # can end up with extra data in the cloned revlogs that's
852 # not pointed to by changesets, thus causing verify to
851 # not pointed to by changesets, thus causing verify to
853 # fail
852 # fail
854 srclock = srcrepo.lock(wait=False)
853 srclock = srcrepo.lock(wait=False)
855 except error.LockError:
854 except error.LockError:
856 copy = False
855 copy = False
857
856
858 if copy:
857 if copy:
859 srcrepo.hook(b'preoutgoing', throw=True, source=b'clone')
858 srcrepo.hook(b'preoutgoing', throw=True, source=b'clone')
860
859
861 destrootpath = urlutil.urllocalpath(dest)
860 destrootpath = urlutil.urllocalpath(dest)
862 dest_reqs = localrepo.clone_requirements(ui, createopts, srcrepo)
861 dest_reqs = localrepo.clone_requirements(ui, createopts, srcrepo)
863 localrepo.createrepository(
862 localrepo.createrepository(
864 ui,
863 ui,
865 destrootpath,
864 destrootpath,
866 requirements=dest_reqs,
865 requirements=dest_reqs,
867 )
866 )
868 destrepo = localrepo.makelocalrepository(ui, destrootpath)
867 destrepo = localrepo.makelocalrepository(ui, destrootpath)
868 destlock = destrepo.lock()
869 from . import streamclone # avoid cycle
869
870
870 destpath = destrepo.vfs.base
871 streamclone.local_copy(srcrepo, destrepo)
871 destlock = copystore(ui, srcrepo, destpath)
872 # copy bookmarks over
873 srcbookmarks = srcrepo.vfs.join(b'bookmarks')
874 dstbookmarks = os.path.join(destpath, b'bookmarks')
875 if os.path.exists(srcbookmarks):
876 util.copyfile(srcbookmarks, dstbookmarks)
877
878 dstcachedir = os.path.join(destpath, b'cache')
879 for cache in cacheutil.cachetocopy(srcrepo):
880 _copycache(srcrepo, dstcachedir, cache)
881
872
882 # we need to re-init the repo after manually copying the data
873 # we need to re-init the repo after manually copying the data
883 # into it
874 # into it
884 destpeer = peer(srcrepo, peeropts, dest)
875 destpeer = peer(srcrepo, peeropts, dest)
885 srcrepo.hook(
876 srcrepo.hook(
886 b'outgoing', source=b'clone', node=srcrepo.nodeconstants.nullhex
877 b'outgoing', source=b'clone', node=srcrepo.nodeconstants.nullhex
887 )
878 )
888 else:
879 else:
889 try:
880 try:
890 # only pass ui when no srcrepo
881 # only pass ui when no srcrepo
891 destpeer = peer(
882 destpeer = peer(
892 srcrepo or ui,
883 srcrepo or ui,
893 peeropts,
884 peeropts,
894 dest,
885 dest,
895 create=True,
886 create=True,
896 createopts=createopts,
887 createopts=createopts,
897 )
888 )
898 except OSError as inst:
889 except OSError as inst:
899 if inst.errno == errno.EEXIST:
890 if inst.errno == errno.EEXIST:
900 cleandir = None
891 cleandir = None
901 raise error.Abort(
892 raise error.Abort(
902 _(b"destination '%s' already exists") % dest
893 _(b"destination '%s' already exists") % dest
903 )
894 )
904 raise
895 raise
905
896
906 if revs:
897 if revs:
907 if not srcpeer.capable(b'lookup'):
898 if not srcpeer.capable(b'lookup'):
908 raise error.Abort(
899 raise error.Abort(
909 _(
900 _(
910 b"src repository does not support "
901 b"src repository does not support "
911 b"revision lookup and so doesn't "
902 b"revision lookup and so doesn't "
912 b"support clone by revision"
903 b"support clone by revision"
913 )
904 )
914 )
905 )
915
906
916 # TODO this is batchable.
907 # TODO this is batchable.
917 remoterevs = []
908 remoterevs = []
918 for rev in revs:
909 for rev in revs:
919 with srcpeer.commandexecutor() as e:
910 with srcpeer.commandexecutor() as e:
920 remoterevs.append(
911 remoterevs.append(
921 e.callcommand(
912 e.callcommand(
922 b'lookup',
913 b'lookup',
923 {
914 {
924 b'key': rev,
915 b'key': rev,
925 },
916 },
926 ).result()
917 ).result()
927 )
918 )
928 revs = remoterevs
919 revs = remoterevs
929
920
930 checkout = revs[0]
921 checkout = revs[0]
931 else:
922 else:
932 revs = None
923 revs = None
933 local = destpeer.local()
924 local = destpeer.local()
934 if local:
925 if local:
935 if narrow:
926 if narrow:
936 with local.wlock(), local.lock():
927 with local.wlock(), local.lock():
937 local.setnarrowpats(storeincludepats, storeexcludepats)
928 local.setnarrowpats(storeincludepats, storeexcludepats)
938 narrowspec.copytoworkingcopy(local)
929 narrowspec.copytoworkingcopy(local)
939
930
940 u = urlutil.url(abspath)
931 u = urlutil.url(abspath)
941 defaulturl = bytes(u)
932 defaulturl = bytes(u)
942 local.ui.setconfig(b'paths', b'default', defaulturl, b'clone')
933 local.ui.setconfig(b'paths', b'default', defaulturl, b'clone')
943 if not stream:
934 if not stream:
944 if pull:
935 if pull:
945 stream = False
936 stream = False
946 else:
937 else:
947 stream = None
938 stream = None
948 # internal config: ui.quietbookmarkmove
939 # internal config: ui.quietbookmarkmove
949 overrides = {(b'ui', b'quietbookmarkmove'): True}
940 overrides = {(b'ui', b'quietbookmarkmove'): True}
950 with local.ui.configoverride(overrides, b'clone'):
941 with local.ui.configoverride(overrides, b'clone'):
951 exchange.pull(
942 exchange.pull(
952 local,
943 local,
953 srcpeer,
944 srcpeer,
954 revs,
945 revs,
955 streamclonerequested=stream,
946 streamclonerequested=stream,
956 includepats=storeincludepats,
947 includepats=storeincludepats,
957 excludepats=storeexcludepats,
948 excludepats=storeexcludepats,
958 depth=depth,
949 depth=depth,
959 )
950 )
960 elif srcrepo:
951 elif srcrepo:
961 # TODO lift restriction once exchange.push() accepts narrow
952 # TODO lift restriction once exchange.push() accepts narrow
962 # push.
953 # push.
963 if narrow:
954 if narrow:
964 raise error.Abort(
955 raise error.Abort(
965 _(
956 _(
966 b'narrow clone not available for '
957 b'narrow clone not available for '
967 b'remote destinations'
958 b'remote destinations'
968 )
959 )
969 )
960 )
970
961
971 exchange.push(
962 exchange.push(
972 srcrepo,
963 srcrepo,
973 destpeer,
964 destpeer,
974 revs=revs,
965 revs=revs,
975 bookmarks=srcrepo._bookmarks.keys(),
966 bookmarks=srcrepo._bookmarks.keys(),
976 )
967 )
977 else:
968 else:
978 raise error.Abort(
969 raise error.Abort(
979 _(b"clone from remote to remote not supported")
970 _(b"clone from remote to remote not supported")
980 )
971 )
981
972
982 cleandir = None
973 cleandir = None
983
974
984 destrepo = destpeer.local()
975 destrepo = destpeer.local()
985 if destrepo:
976 if destrepo:
986 template = uimod.samplehgrcs[b'cloned']
977 template = uimod.samplehgrcs[b'cloned']
987 u = urlutil.url(abspath)
978 u = urlutil.url(abspath)
988 u.passwd = None
979 u.passwd = None
989 defaulturl = bytes(u)
980 defaulturl = bytes(u)
990 destrepo.vfs.write(b'hgrc', util.tonativeeol(template % defaulturl))
981 destrepo.vfs.write(b'hgrc', util.tonativeeol(template % defaulturl))
991 destrepo.ui.setconfig(b'paths', b'default', defaulturl, b'clone')
982 destrepo.ui.setconfig(b'paths', b'default', defaulturl, b'clone')
992
983
993 if ui.configbool(b'experimental', b'remotenames'):
984 if ui.configbool(b'experimental', b'remotenames'):
994 logexchange.pullremotenames(destrepo, srcpeer)
985 logexchange.pullremotenames(destrepo, srcpeer)
995
986
996 if update:
987 if update:
997 if update is not True:
988 if update is not True:
998 with srcpeer.commandexecutor() as e:
989 with srcpeer.commandexecutor() as e:
999 checkout = e.callcommand(
990 checkout = e.callcommand(
1000 b'lookup',
991 b'lookup',
1001 {
992 {
1002 b'key': update,
993 b'key': update,
1003 },
994 },
1004 ).result()
995 ).result()
1005
996
1006 uprev = None
997 uprev = None
1007 status = None
998 status = None
1008 if checkout is not None:
999 if checkout is not None:
1009 # Some extensions (at least hg-git and hg-subversion) have
1000 # Some extensions (at least hg-git and hg-subversion) have
1010 # a peer.lookup() implementation that returns a name instead
1001 # a peer.lookup() implementation that returns a name instead
1011 # of a nodeid. We work around it here until we've figured
1002 # of a nodeid. We work around it here until we've figured
1012 # out a better solution.
1003 # out a better solution.
1013 if len(checkout) == 20 and checkout in destrepo:
1004 if len(checkout) == 20 and checkout in destrepo:
1014 uprev = checkout
1005 uprev = checkout
1015 elif scmutil.isrevsymbol(destrepo, checkout):
1006 elif scmutil.isrevsymbol(destrepo, checkout):
1016 uprev = scmutil.revsymbol(destrepo, checkout).node()
1007 uprev = scmutil.revsymbol(destrepo, checkout).node()
1017 else:
1008 else:
1018 if update is not True:
1009 if update is not True:
1019 try:
1010 try:
1020 uprev = destrepo.lookup(update)
1011 uprev = destrepo.lookup(update)
1021 except error.RepoLookupError:
1012 except error.RepoLookupError:
1022 pass
1013 pass
1023 if uprev is None:
1014 if uprev is None:
1024 try:
1015 try:
1025 if destrepo._activebookmark:
1016 if destrepo._activebookmark:
1026 uprev = destrepo.lookup(destrepo._activebookmark)
1017 uprev = destrepo.lookup(destrepo._activebookmark)
1027 update = destrepo._activebookmark
1018 update = destrepo._activebookmark
1028 else:
1019 else:
1029 uprev = destrepo._bookmarks[b'@']
1020 uprev = destrepo._bookmarks[b'@']
1030 update = b'@'
1021 update = b'@'
1031 bn = destrepo[uprev].branch()
1022 bn = destrepo[uprev].branch()
1032 if bn == b'default':
1023 if bn == b'default':
1033 status = _(b"updating to bookmark %s\n" % update)
1024 status = _(b"updating to bookmark %s\n" % update)
1034 else:
1025 else:
1035 status = (
1026 status = (
1036 _(b"updating to bookmark %s on branch %s\n")
1027 _(b"updating to bookmark %s on branch %s\n")
1037 ) % (update, bn)
1028 ) % (update, bn)
1038 except KeyError:
1029 except KeyError:
1039 try:
1030 try:
1040 uprev = destrepo.branchtip(b'default')
1031 uprev = destrepo.branchtip(b'default')
1041 except error.RepoLookupError:
1032 except error.RepoLookupError:
1042 uprev = destrepo.lookup(b'tip')
1033 uprev = destrepo.lookup(b'tip')
1043 if not status:
1034 if not status:
1044 bn = destrepo[uprev].branch()
1035 bn = destrepo[uprev].branch()
1045 status = _(b"updating to branch %s\n") % bn
1036 status = _(b"updating to branch %s\n") % bn
1046 destrepo.ui.status(status)
1037 destrepo.ui.status(status)
1047 _update(destrepo, uprev)
1038 _update(destrepo, uprev)
1048 if update in destrepo._bookmarks:
1039 if update in destrepo._bookmarks:
1049 bookmarks.activate(destrepo, update)
1040 bookmarks.activate(destrepo, update)
1050 if destlock is not None:
1041 if destlock is not None:
1051 release(destlock)
1042 release(destlock)
1052 # here is a tiny windows were someone could end up writing the
1043 # here is a tiny windows were someone could end up writing the
1053 # repository before the cache are sure to be warm. This is "fine"
1044 # repository before the cache are sure to be warm. This is "fine"
1054 # as the only "bad" outcome would be some slowness. That potential
1045 # as the only "bad" outcome would be some slowness. That potential
1055 # slowness already affect reader.
1046 # slowness already affect reader.
1056 with destrepo.lock():
1047 with destrepo.lock():
1057 destrepo.updatecaches(caches=repositorymod.CACHES_POST_CLONE)
1048 destrepo.updatecaches(caches=repositorymod.CACHES_POST_CLONE)
1058 finally:
1049 finally:
1059 release(srclock, destlock)
1050 release(srclock, destlock)
1060 if cleandir is not None:
1051 if cleandir is not None:
1061 shutil.rmtree(cleandir, True)
1052 shutil.rmtree(cleandir, True)
1062 if srcpeer is not None:
1053 if srcpeer is not None:
1063 srcpeer.close()
1054 srcpeer.close()
1064 if destpeer and destpeer.local() is None:
1055 if destpeer and destpeer.local() is None:
1065 destpeer.close()
1056 destpeer.close()
1066 return srcpeer, destpeer
1057 return srcpeer, destpeer
1067
1058
1068
1059
1069 def _showstats(repo, stats, quietempty=False):
1060 def _showstats(repo, stats, quietempty=False):
1070 if quietempty and stats.isempty():
1061 if quietempty and stats.isempty():
1071 return
1062 return
1072 repo.ui.status(
1063 repo.ui.status(
1073 _(
1064 _(
1074 b"%d files updated, %d files merged, "
1065 b"%d files updated, %d files merged, "
1075 b"%d files removed, %d files unresolved\n"
1066 b"%d files removed, %d files unresolved\n"
1076 )
1067 )
1077 % (
1068 % (
1078 stats.updatedcount,
1069 stats.updatedcount,
1079 stats.mergedcount,
1070 stats.mergedcount,
1080 stats.removedcount,
1071 stats.removedcount,
1081 stats.unresolvedcount,
1072 stats.unresolvedcount,
1082 )
1073 )
1083 )
1074 )
1084
1075
1085
1076
1086 def updaterepo(repo, node, overwrite, updatecheck=None):
1077 def updaterepo(repo, node, overwrite, updatecheck=None):
1087 """Update the working directory to node.
1078 """Update the working directory to node.
1088
1079
1089 When overwrite is set, changes are clobbered, merged else
1080 When overwrite is set, changes are clobbered, merged else
1090
1081
1091 returns stats (see pydoc mercurial.merge.applyupdates)"""
1082 returns stats (see pydoc mercurial.merge.applyupdates)"""
1092 repo.ui.deprecwarn(
1083 repo.ui.deprecwarn(
1093 b'prefer merge.update() or merge.clean_update() over hg.updaterepo()',
1084 b'prefer merge.update() or merge.clean_update() over hg.updaterepo()',
1094 b'5.7',
1085 b'5.7',
1095 )
1086 )
1096 return mergemod._update(
1087 return mergemod._update(
1097 repo,
1088 repo,
1098 node,
1089 node,
1099 branchmerge=False,
1090 branchmerge=False,
1100 force=overwrite,
1091 force=overwrite,
1101 labels=[b'working copy', b'destination'],
1092 labels=[b'working copy', b'destination'],
1102 updatecheck=updatecheck,
1093 updatecheck=updatecheck,
1103 )
1094 )
1104
1095
1105
1096
1106 def update(repo, node, quietempty=False, updatecheck=None):
1097 def update(repo, node, quietempty=False, updatecheck=None):
1107 """update the working directory to node"""
1098 """update the working directory to node"""
1108 stats = mergemod.update(repo[node], updatecheck=updatecheck)
1099 stats = mergemod.update(repo[node], updatecheck=updatecheck)
1109 _showstats(repo, stats, quietempty)
1100 _showstats(repo, stats, quietempty)
1110 if stats.unresolvedcount:
1101 if stats.unresolvedcount:
1111 repo.ui.status(_(b"use 'hg resolve' to retry unresolved file merges\n"))
1102 repo.ui.status(_(b"use 'hg resolve' to retry unresolved file merges\n"))
1112 return stats.unresolvedcount > 0
1103 return stats.unresolvedcount > 0
1113
1104
1114
1105
1115 # naming conflict in clone()
1106 # naming conflict in clone()
1116 _update = update
1107 _update = update
1117
1108
1118
1109
1119 def clean(repo, node, show_stats=True, quietempty=False):
1110 def clean(repo, node, show_stats=True, quietempty=False):
1120 """forcibly switch the working directory to node, clobbering changes"""
1111 """forcibly switch the working directory to node, clobbering changes"""
1121 stats = mergemod.clean_update(repo[node])
1112 stats = mergemod.clean_update(repo[node])
1122 assert stats.unresolvedcount == 0
1113 assert stats.unresolvedcount == 0
1123 if show_stats:
1114 if show_stats:
1124 _showstats(repo, stats, quietempty)
1115 _showstats(repo, stats, quietempty)
1125 return False
1116 return False
1126
1117
1127
1118
1128 # naming conflict in updatetotally()
1119 # naming conflict in updatetotally()
1129 _clean = clean
1120 _clean = clean
1130
1121
1131 _VALID_UPDATECHECKS = {
1122 _VALID_UPDATECHECKS = {
1132 mergemod.UPDATECHECK_ABORT,
1123 mergemod.UPDATECHECK_ABORT,
1133 mergemod.UPDATECHECK_NONE,
1124 mergemod.UPDATECHECK_NONE,
1134 mergemod.UPDATECHECK_LINEAR,
1125 mergemod.UPDATECHECK_LINEAR,
1135 mergemod.UPDATECHECK_NO_CONFLICT,
1126 mergemod.UPDATECHECK_NO_CONFLICT,
1136 }
1127 }
1137
1128
1138
1129
1139 def updatetotally(ui, repo, checkout, brev, clean=False, updatecheck=None):
1130 def updatetotally(ui, repo, checkout, brev, clean=False, updatecheck=None):
1140 """Update the working directory with extra care for non-file components
1131 """Update the working directory with extra care for non-file components
1141
1132
1142 This takes care of non-file components below:
1133 This takes care of non-file components below:
1143
1134
1144 :bookmark: might be advanced or (in)activated
1135 :bookmark: might be advanced or (in)activated
1145
1136
1146 This takes arguments below:
1137 This takes arguments below:
1147
1138
1148 :checkout: to which revision the working directory is updated
1139 :checkout: to which revision the working directory is updated
1149 :brev: a name, which might be a bookmark to be activated after updating
1140 :brev: a name, which might be a bookmark to be activated after updating
1150 :clean: whether changes in the working directory can be discarded
1141 :clean: whether changes in the working directory can be discarded
1151 :updatecheck: how to deal with a dirty working directory
1142 :updatecheck: how to deal with a dirty working directory
1152
1143
1153 Valid values for updatecheck are the UPDATECHECK_* constants
1144 Valid values for updatecheck are the UPDATECHECK_* constants
1154 defined in the merge module. Passing `None` will result in using the
1145 defined in the merge module. Passing `None` will result in using the
1155 configured default.
1146 configured default.
1156
1147
1157 * ABORT: abort if the working directory is dirty
1148 * ABORT: abort if the working directory is dirty
1158 * NONE: don't check (merge working directory changes into destination)
1149 * NONE: don't check (merge working directory changes into destination)
1159 * LINEAR: check that update is linear before merging working directory
1150 * LINEAR: check that update is linear before merging working directory
1160 changes into destination
1151 changes into destination
1161 * NO_CONFLICT: check that the update does not result in file merges
1152 * NO_CONFLICT: check that the update does not result in file merges
1162
1153
1163 This returns whether conflict is detected at updating or not.
1154 This returns whether conflict is detected at updating or not.
1164 """
1155 """
1165 if updatecheck is None:
1156 if updatecheck is None:
1166 updatecheck = ui.config(b'commands', b'update.check')
1157 updatecheck = ui.config(b'commands', b'update.check')
1167 if updatecheck not in _VALID_UPDATECHECKS:
1158 if updatecheck not in _VALID_UPDATECHECKS:
1168 # If not configured, or invalid value configured
1159 # If not configured, or invalid value configured
1169 updatecheck = mergemod.UPDATECHECK_LINEAR
1160 updatecheck = mergemod.UPDATECHECK_LINEAR
1170 if updatecheck not in _VALID_UPDATECHECKS:
1161 if updatecheck not in _VALID_UPDATECHECKS:
1171 raise ValueError(
1162 raise ValueError(
1172 r'Invalid updatecheck value %r (can accept %r)'
1163 r'Invalid updatecheck value %r (can accept %r)'
1173 % (updatecheck, _VALID_UPDATECHECKS)
1164 % (updatecheck, _VALID_UPDATECHECKS)
1174 )
1165 )
1175 with repo.wlock():
1166 with repo.wlock():
1176 movemarkfrom = None
1167 movemarkfrom = None
1177 warndest = False
1168 warndest = False
1178 if checkout is None:
1169 if checkout is None:
1179 updata = destutil.destupdate(repo, clean=clean)
1170 updata = destutil.destupdate(repo, clean=clean)
1180 checkout, movemarkfrom, brev = updata
1171 checkout, movemarkfrom, brev = updata
1181 warndest = True
1172 warndest = True
1182
1173
1183 if clean:
1174 if clean:
1184 ret = _clean(repo, checkout)
1175 ret = _clean(repo, checkout)
1185 else:
1176 else:
1186 if updatecheck == mergemod.UPDATECHECK_ABORT:
1177 if updatecheck == mergemod.UPDATECHECK_ABORT:
1187 cmdutil.bailifchanged(repo, merge=False)
1178 cmdutil.bailifchanged(repo, merge=False)
1188 updatecheck = mergemod.UPDATECHECK_NONE
1179 updatecheck = mergemod.UPDATECHECK_NONE
1189 ret = _update(repo, checkout, updatecheck=updatecheck)
1180 ret = _update(repo, checkout, updatecheck=updatecheck)
1190
1181
1191 if not ret and movemarkfrom:
1182 if not ret and movemarkfrom:
1192 if movemarkfrom == repo[b'.'].node():
1183 if movemarkfrom == repo[b'.'].node():
1193 pass # no-op update
1184 pass # no-op update
1194 elif bookmarks.update(repo, [movemarkfrom], repo[b'.'].node()):
1185 elif bookmarks.update(repo, [movemarkfrom], repo[b'.'].node()):
1195 b = ui.label(repo._activebookmark, b'bookmarks.active')
1186 b = ui.label(repo._activebookmark, b'bookmarks.active')
1196 ui.status(_(b"updating bookmark %s\n") % b)
1187 ui.status(_(b"updating bookmark %s\n") % b)
1197 else:
1188 else:
1198 # this can happen with a non-linear update
1189 # this can happen with a non-linear update
1199 b = ui.label(repo._activebookmark, b'bookmarks')
1190 b = ui.label(repo._activebookmark, b'bookmarks')
1200 ui.status(_(b"(leaving bookmark %s)\n") % b)
1191 ui.status(_(b"(leaving bookmark %s)\n") % b)
1201 bookmarks.deactivate(repo)
1192 bookmarks.deactivate(repo)
1202 elif brev in repo._bookmarks:
1193 elif brev in repo._bookmarks:
1203 if brev != repo._activebookmark:
1194 if brev != repo._activebookmark:
1204 b = ui.label(brev, b'bookmarks.active')
1195 b = ui.label(brev, b'bookmarks.active')
1205 ui.status(_(b"(activating bookmark %s)\n") % b)
1196 ui.status(_(b"(activating bookmark %s)\n") % b)
1206 bookmarks.activate(repo, brev)
1197 bookmarks.activate(repo, brev)
1207 elif brev:
1198 elif brev:
1208 if repo._activebookmark:
1199 if repo._activebookmark:
1209 b = ui.label(repo._activebookmark, b'bookmarks')
1200 b = ui.label(repo._activebookmark, b'bookmarks')
1210 ui.status(_(b"(leaving bookmark %s)\n") % b)
1201 ui.status(_(b"(leaving bookmark %s)\n") % b)
1211 bookmarks.deactivate(repo)
1202 bookmarks.deactivate(repo)
1212
1203
1213 if warndest:
1204 if warndest:
1214 destutil.statusotherdests(ui, repo)
1205 destutil.statusotherdests(ui, repo)
1215
1206
1216 return ret
1207 return ret
1217
1208
1218
1209
1219 def merge(
1210 def merge(
1220 ctx,
1211 ctx,
1221 force=False,
1212 force=False,
1222 remind=True,
1213 remind=True,
1223 labels=None,
1214 labels=None,
1224 ):
1215 ):
1225 """Branch merge with node, resolving changes. Return true if any
1216 """Branch merge with node, resolving changes. Return true if any
1226 unresolved conflicts."""
1217 unresolved conflicts."""
1227 repo = ctx.repo()
1218 repo = ctx.repo()
1228 stats = mergemod.merge(ctx, force=force, labels=labels)
1219 stats = mergemod.merge(ctx, force=force, labels=labels)
1229 _showstats(repo, stats)
1220 _showstats(repo, stats)
1230 if stats.unresolvedcount:
1221 if stats.unresolvedcount:
1231 repo.ui.status(
1222 repo.ui.status(
1232 _(
1223 _(
1233 b"use 'hg resolve' to retry unresolved file merges "
1224 b"use 'hg resolve' to retry unresolved file merges "
1234 b"or 'hg merge --abort' to abandon\n"
1225 b"or 'hg merge --abort' to abandon\n"
1235 )
1226 )
1236 )
1227 )
1237 elif remind:
1228 elif remind:
1238 repo.ui.status(_(b"(branch merge, don't forget to commit)\n"))
1229 repo.ui.status(_(b"(branch merge, don't forget to commit)\n"))
1239 return stats.unresolvedcount > 0
1230 return stats.unresolvedcount > 0
1240
1231
1241
1232
1242 def abortmerge(ui, repo):
1233 def abortmerge(ui, repo):
1243 ms = mergestatemod.mergestate.read(repo)
1234 ms = mergestatemod.mergestate.read(repo)
1244 if ms.active():
1235 if ms.active():
1245 # there were conflicts
1236 # there were conflicts
1246 node = ms.localctx.hex()
1237 node = ms.localctx.hex()
1247 else:
1238 else:
1248 # there were no conficts, mergestate was not stored
1239 # there were no conficts, mergestate was not stored
1249 node = repo[b'.'].hex()
1240 node = repo[b'.'].hex()
1250
1241
1251 repo.ui.status(_(b"aborting the merge, updating back to %s\n") % node[:12])
1242 repo.ui.status(_(b"aborting the merge, updating back to %s\n") % node[:12])
1252 stats = mergemod.clean_update(repo[node])
1243 stats = mergemod.clean_update(repo[node])
1253 assert stats.unresolvedcount == 0
1244 assert stats.unresolvedcount == 0
1254 _showstats(repo, stats)
1245 _showstats(repo, stats)
1255
1246
1256
1247
1257 def _incoming(
1248 def _incoming(
1258 displaychlist,
1249 displaychlist,
1259 subreporecurse,
1250 subreporecurse,
1260 ui,
1251 ui,
1261 repo,
1252 repo,
1262 source,
1253 source,
1263 opts,
1254 opts,
1264 buffered=False,
1255 buffered=False,
1265 subpath=None,
1256 subpath=None,
1266 ):
1257 ):
1267 """
1258 """
1268 Helper for incoming / gincoming.
1259 Helper for incoming / gincoming.
1269 displaychlist gets called with
1260 displaychlist gets called with
1270 (remoterepo, incomingchangesetlist, displayer) parameters,
1261 (remoterepo, incomingchangesetlist, displayer) parameters,
1271 and is supposed to contain only code that can't be unified.
1262 and is supposed to contain only code that can't be unified.
1272 """
1263 """
1273 srcs = urlutil.get_pull_paths(repo, ui, [source], opts.get(b'branch'))
1264 srcs = urlutil.get_pull_paths(repo, ui, [source], opts.get(b'branch'))
1274 srcs = list(srcs)
1265 srcs = list(srcs)
1275 if len(srcs) != 1:
1266 if len(srcs) != 1:
1276 msg = _(b'for now, incoming supports only a single source, %d provided')
1267 msg = _(b'for now, incoming supports only a single source, %d provided')
1277 msg %= len(srcs)
1268 msg %= len(srcs)
1278 raise error.Abort(msg)
1269 raise error.Abort(msg)
1279 source, branches = srcs[0]
1270 source, branches = srcs[0]
1280 if subpath is not None:
1271 if subpath is not None:
1281 subpath = urlutil.url(subpath)
1272 subpath = urlutil.url(subpath)
1282 if subpath.isabs():
1273 if subpath.isabs():
1283 source = bytes(subpath)
1274 source = bytes(subpath)
1284 else:
1275 else:
1285 p = urlutil.url(source)
1276 p = urlutil.url(source)
1286 p.path = os.path.normpath(b'%s/%s' % (p.path, subpath))
1277 p.path = os.path.normpath(b'%s/%s' % (p.path, subpath))
1287 source = bytes(p)
1278 source = bytes(p)
1288 other = peer(repo, opts, source)
1279 other = peer(repo, opts, source)
1289 cleanupfn = other.close
1280 cleanupfn = other.close
1290 try:
1281 try:
1291 ui.status(_(b'comparing with %s\n') % urlutil.hidepassword(source))
1282 ui.status(_(b'comparing with %s\n') % urlutil.hidepassword(source))
1292 revs, checkout = addbranchrevs(repo, other, branches, opts.get(b'rev'))
1283 revs, checkout = addbranchrevs(repo, other, branches, opts.get(b'rev'))
1293
1284
1294 if revs:
1285 if revs:
1295 revs = [other.lookup(rev) for rev in revs]
1286 revs = [other.lookup(rev) for rev in revs]
1296 other, chlist, cleanupfn = bundlerepo.getremotechanges(
1287 other, chlist, cleanupfn = bundlerepo.getremotechanges(
1297 ui, repo, other, revs, opts[b"bundle"], opts[b"force"]
1288 ui, repo, other, revs, opts[b"bundle"], opts[b"force"]
1298 )
1289 )
1299
1290
1300 if not chlist:
1291 if not chlist:
1301 ui.status(_(b"no changes found\n"))
1292 ui.status(_(b"no changes found\n"))
1302 return subreporecurse()
1293 return subreporecurse()
1303 ui.pager(b'incoming')
1294 ui.pager(b'incoming')
1304 displayer = logcmdutil.changesetdisplayer(
1295 displayer = logcmdutil.changesetdisplayer(
1305 ui, other, opts, buffered=buffered
1296 ui, other, opts, buffered=buffered
1306 )
1297 )
1307 displaychlist(other, chlist, displayer)
1298 displaychlist(other, chlist, displayer)
1308 displayer.close()
1299 displayer.close()
1309 finally:
1300 finally:
1310 cleanupfn()
1301 cleanupfn()
1311 subreporecurse()
1302 subreporecurse()
1312 return 0 # exit code is zero since we found incoming changes
1303 return 0 # exit code is zero since we found incoming changes
1313
1304
1314
1305
1315 def incoming(ui, repo, source, opts, subpath=None):
1306 def incoming(ui, repo, source, opts, subpath=None):
1316 def subreporecurse():
1307 def subreporecurse():
1317 ret = 1
1308 ret = 1
1318 if opts.get(b'subrepos'):
1309 if opts.get(b'subrepos'):
1319 ctx = repo[None]
1310 ctx = repo[None]
1320 for subpath in sorted(ctx.substate):
1311 for subpath in sorted(ctx.substate):
1321 sub = ctx.sub(subpath)
1312 sub = ctx.sub(subpath)
1322 ret = min(ret, sub.incoming(ui, source, opts))
1313 ret = min(ret, sub.incoming(ui, source, opts))
1323 return ret
1314 return ret
1324
1315
1325 def display(other, chlist, displayer):
1316 def display(other, chlist, displayer):
1326 limit = logcmdutil.getlimit(opts)
1317 limit = logcmdutil.getlimit(opts)
1327 if opts.get(b'newest_first'):
1318 if opts.get(b'newest_first'):
1328 chlist.reverse()
1319 chlist.reverse()
1329 count = 0
1320 count = 0
1330 for n in chlist:
1321 for n in chlist:
1331 if limit is not None and count >= limit:
1322 if limit is not None and count >= limit:
1332 break
1323 break
1333 parents = [
1324 parents = [
1334 p for p in other.changelog.parents(n) if p != repo.nullid
1325 p for p in other.changelog.parents(n) if p != repo.nullid
1335 ]
1326 ]
1336 if opts.get(b'no_merges') and len(parents) == 2:
1327 if opts.get(b'no_merges') and len(parents) == 2:
1337 continue
1328 continue
1338 count += 1
1329 count += 1
1339 displayer.show(other[n])
1330 displayer.show(other[n])
1340
1331
1341 return _incoming(
1332 return _incoming(
1342 display, subreporecurse, ui, repo, source, opts, subpath=subpath
1333 display, subreporecurse, ui, repo, source, opts, subpath=subpath
1343 )
1334 )
1344
1335
1345
1336
1346 def _outgoing(ui, repo, dests, opts, subpath=None):
1337 def _outgoing(ui, repo, dests, opts, subpath=None):
1347 out = set()
1338 out = set()
1348 others = []
1339 others = []
1349 for path in urlutil.get_push_paths(repo, ui, dests):
1340 for path in urlutil.get_push_paths(repo, ui, dests):
1350 dest = path.pushloc or path.loc
1341 dest = path.pushloc or path.loc
1351 if subpath is not None:
1342 if subpath is not None:
1352 subpath = urlutil.url(subpath)
1343 subpath = urlutil.url(subpath)
1353 if subpath.isabs():
1344 if subpath.isabs():
1354 dest = bytes(subpath)
1345 dest = bytes(subpath)
1355 else:
1346 else:
1356 p = urlutil.url(dest)
1347 p = urlutil.url(dest)
1357 p.path = os.path.normpath(b'%s/%s' % (p.path, subpath))
1348 p.path = os.path.normpath(b'%s/%s' % (p.path, subpath))
1358 dest = bytes(p)
1349 dest = bytes(p)
1359 branches = path.branch, opts.get(b'branch') or []
1350 branches = path.branch, opts.get(b'branch') or []
1360
1351
1361 ui.status(_(b'comparing with %s\n') % urlutil.hidepassword(dest))
1352 ui.status(_(b'comparing with %s\n') % urlutil.hidepassword(dest))
1362 revs, checkout = addbranchrevs(repo, repo, branches, opts.get(b'rev'))
1353 revs, checkout = addbranchrevs(repo, repo, branches, opts.get(b'rev'))
1363 if revs:
1354 if revs:
1364 revs = [repo[rev].node() for rev in scmutil.revrange(repo, revs)]
1355 revs = [repo[rev].node() for rev in scmutil.revrange(repo, revs)]
1365
1356
1366 other = peer(repo, opts, dest)
1357 other = peer(repo, opts, dest)
1367 try:
1358 try:
1368 outgoing = discovery.findcommonoutgoing(
1359 outgoing = discovery.findcommonoutgoing(
1369 repo, other, revs, force=opts.get(b'force')
1360 repo, other, revs, force=opts.get(b'force')
1370 )
1361 )
1371 o = outgoing.missing
1362 o = outgoing.missing
1372 out.update(o)
1363 out.update(o)
1373 if not o:
1364 if not o:
1374 scmutil.nochangesfound(repo.ui, repo, outgoing.excluded)
1365 scmutil.nochangesfound(repo.ui, repo, outgoing.excluded)
1375 others.append(other)
1366 others.append(other)
1376 except: # re-raises
1367 except: # re-raises
1377 other.close()
1368 other.close()
1378 raise
1369 raise
1379 # make sure this is ordered by revision number
1370 # make sure this is ordered by revision number
1380 outgoing_revs = list(out)
1371 outgoing_revs = list(out)
1381 cl = repo.changelog
1372 cl = repo.changelog
1382 outgoing_revs.sort(key=cl.rev)
1373 outgoing_revs.sort(key=cl.rev)
1383 return outgoing_revs, others
1374 return outgoing_revs, others
1384
1375
1385
1376
1386 def _outgoing_recurse(ui, repo, dests, opts):
1377 def _outgoing_recurse(ui, repo, dests, opts):
1387 ret = 1
1378 ret = 1
1388 if opts.get(b'subrepos'):
1379 if opts.get(b'subrepos'):
1389 ctx = repo[None]
1380 ctx = repo[None]
1390 for subpath in sorted(ctx.substate):
1381 for subpath in sorted(ctx.substate):
1391 sub = ctx.sub(subpath)
1382 sub = ctx.sub(subpath)
1392 ret = min(ret, sub.outgoing(ui, dests, opts))
1383 ret = min(ret, sub.outgoing(ui, dests, opts))
1393 return ret
1384 return ret
1394
1385
1395
1386
1396 def _outgoing_filter(repo, revs, opts):
1387 def _outgoing_filter(repo, revs, opts):
1397 """apply revision filtering/ordering option for outgoing"""
1388 """apply revision filtering/ordering option for outgoing"""
1398 limit = logcmdutil.getlimit(opts)
1389 limit = logcmdutil.getlimit(opts)
1399 no_merges = opts.get(b'no_merges')
1390 no_merges = opts.get(b'no_merges')
1400 if opts.get(b'newest_first'):
1391 if opts.get(b'newest_first'):
1401 revs.reverse()
1392 revs.reverse()
1402 if limit is None and not no_merges:
1393 if limit is None and not no_merges:
1403 for r in revs:
1394 for r in revs:
1404 yield r
1395 yield r
1405 return
1396 return
1406
1397
1407 count = 0
1398 count = 0
1408 cl = repo.changelog
1399 cl = repo.changelog
1409 for n in revs:
1400 for n in revs:
1410 if limit is not None and count >= limit:
1401 if limit is not None and count >= limit:
1411 break
1402 break
1412 parents = [p for p in cl.parents(n) if p != repo.nullid]
1403 parents = [p for p in cl.parents(n) if p != repo.nullid]
1413 if no_merges and len(parents) == 2:
1404 if no_merges and len(parents) == 2:
1414 continue
1405 continue
1415 count += 1
1406 count += 1
1416 yield n
1407 yield n
1417
1408
1418
1409
1419 def outgoing(ui, repo, dests, opts, subpath=None):
1410 def outgoing(ui, repo, dests, opts, subpath=None):
1420 if opts.get(b'graph'):
1411 if opts.get(b'graph'):
1421 logcmdutil.checkunsupportedgraphflags([], opts)
1412 logcmdutil.checkunsupportedgraphflags([], opts)
1422 o, others = _outgoing(ui, repo, dests, opts, subpath=subpath)
1413 o, others = _outgoing(ui, repo, dests, opts, subpath=subpath)
1423 ret = 1
1414 ret = 1
1424 try:
1415 try:
1425 if o:
1416 if o:
1426 ret = 0
1417 ret = 0
1427
1418
1428 if opts.get(b'graph'):
1419 if opts.get(b'graph'):
1429 revdag = logcmdutil.graphrevs(repo, o, opts)
1420 revdag = logcmdutil.graphrevs(repo, o, opts)
1430 ui.pager(b'outgoing')
1421 ui.pager(b'outgoing')
1431 displayer = logcmdutil.changesetdisplayer(
1422 displayer = logcmdutil.changesetdisplayer(
1432 ui, repo, opts, buffered=True
1423 ui, repo, opts, buffered=True
1433 )
1424 )
1434 logcmdutil.displaygraph(
1425 logcmdutil.displaygraph(
1435 ui, repo, revdag, displayer, graphmod.asciiedges
1426 ui, repo, revdag, displayer, graphmod.asciiedges
1436 )
1427 )
1437 else:
1428 else:
1438 ui.pager(b'outgoing')
1429 ui.pager(b'outgoing')
1439 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
1430 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
1440 for n in _outgoing_filter(repo, o, opts):
1431 for n in _outgoing_filter(repo, o, opts):
1441 displayer.show(repo[n])
1432 displayer.show(repo[n])
1442 displayer.close()
1433 displayer.close()
1443 for oth in others:
1434 for oth in others:
1444 cmdutil.outgoinghooks(ui, repo, oth, opts, o)
1435 cmdutil.outgoinghooks(ui, repo, oth, opts, o)
1445 ret = min(ret, _outgoing_recurse(ui, repo, dests, opts))
1436 ret = min(ret, _outgoing_recurse(ui, repo, dests, opts))
1446 return ret # exit code is zero since we found outgoing changes
1437 return ret # exit code is zero since we found outgoing changes
1447 finally:
1438 finally:
1448 for oth in others:
1439 for oth in others:
1449 oth.close()
1440 oth.close()
1450
1441
1451
1442
1452 def verify(repo, level=None):
1443 def verify(repo, level=None):
1453 """verify the consistency of a repository"""
1444 """verify the consistency of a repository"""
1454 ret = verifymod.verify(repo, level=level)
1445 ret = verifymod.verify(repo, level=level)
1455
1446
1456 # Broken subrepo references in hidden csets don't seem worth worrying about,
1447 # Broken subrepo references in hidden csets don't seem worth worrying about,
1457 # since they can't be pushed/pulled, and --hidden can be used if they are a
1448 # since they can't be pushed/pulled, and --hidden can be used if they are a
1458 # concern.
1449 # concern.
1459
1450
1460 # pathto() is needed for -R case
1451 # pathto() is needed for -R case
1461 revs = repo.revs(
1452 revs = repo.revs(
1462 b"filelog(%s)", util.pathto(repo.root, repo.getcwd(), b'.hgsubstate')
1453 b"filelog(%s)", util.pathto(repo.root, repo.getcwd(), b'.hgsubstate')
1463 )
1454 )
1464
1455
1465 if revs:
1456 if revs:
1466 repo.ui.status(_(b'checking subrepo links\n'))
1457 repo.ui.status(_(b'checking subrepo links\n'))
1467 for rev in revs:
1458 for rev in revs:
1468 ctx = repo[rev]
1459 ctx = repo[rev]
1469 try:
1460 try:
1470 for subpath in ctx.substate:
1461 for subpath in ctx.substate:
1471 try:
1462 try:
1472 ret = (
1463 ret = (
1473 ctx.sub(subpath, allowcreate=False).verify() or ret
1464 ctx.sub(subpath, allowcreate=False).verify() or ret
1474 )
1465 )
1475 except error.RepoError as e:
1466 except error.RepoError as e:
1476 repo.ui.warn(b'%d: %s\n' % (rev, e))
1467 repo.ui.warn(b'%d: %s\n' % (rev, e))
1477 except Exception:
1468 except Exception:
1478 repo.ui.warn(
1469 repo.ui.warn(
1479 _(b'.hgsubstate is corrupt in revision %s\n')
1470 _(b'.hgsubstate is corrupt in revision %s\n')
1480 % short(ctx.node())
1471 % short(ctx.node())
1481 )
1472 )
1482
1473
1483 return ret
1474 return ret
1484
1475
1485
1476
1486 def remoteui(src, opts):
1477 def remoteui(src, opts):
1487 """build a remote ui from ui or repo and opts"""
1478 """build a remote ui from ui or repo and opts"""
1488 if util.safehasattr(src, b'baseui'): # looks like a repository
1479 if util.safehasattr(src, b'baseui'): # looks like a repository
1489 dst = src.baseui.copy() # drop repo-specific config
1480 dst = src.baseui.copy() # drop repo-specific config
1490 src = src.ui # copy target options from repo
1481 src = src.ui # copy target options from repo
1491 else: # assume it's a global ui object
1482 else: # assume it's a global ui object
1492 dst = src.copy() # keep all global options
1483 dst = src.copy() # keep all global options
1493
1484
1494 # copy ssh-specific options
1485 # copy ssh-specific options
1495 for o in b'ssh', b'remotecmd':
1486 for o in b'ssh', b'remotecmd':
1496 v = opts.get(o) or src.config(b'ui', o)
1487 v = opts.get(o) or src.config(b'ui', o)
1497 if v:
1488 if v:
1498 dst.setconfig(b"ui", o, v, b'copied')
1489 dst.setconfig(b"ui", o, v, b'copied')
1499
1490
1500 # copy bundle-specific options
1491 # copy bundle-specific options
1501 r = src.config(b'bundle', b'mainreporoot')
1492 r = src.config(b'bundle', b'mainreporoot')
1502 if r:
1493 if r:
1503 dst.setconfig(b'bundle', b'mainreporoot', r, b'copied')
1494 dst.setconfig(b'bundle', b'mainreporoot', r, b'copied')
1504
1495
1505 # copy selected local settings to the remote ui
1496 # copy selected local settings to the remote ui
1506 for sect in (b'auth', b'hostfingerprints', b'hostsecurity', b'http_proxy'):
1497 for sect in (b'auth', b'hostfingerprints', b'hostsecurity', b'http_proxy'):
1507 for key, val in src.configitems(sect):
1498 for key, val in src.configitems(sect):
1508 dst.setconfig(sect, key, val, b'copied')
1499 dst.setconfig(sect, key, val, b'copied')
1509 v = src.config(b'web', b'cacerts')
1500 v = src.config(b'web', b'cacerts')
1510 if v:
1501 if v:
1511 dst.setconfig(b'web', b'cacerts', util.expandpath(v), b'copied')
1502 dst.setconfig(b'web', b'cacerts', util.expandpath(v), b'copied')
1512
1503
1513 return dst
1504 return dst
1514
1505
1515
1506
1516 # Files of interest
1507 # Files of interest
1517 # Used to check if the repository has changed looking at mtime and size of
1508 # Used to check if the repository has changed looking at mtime and size of
1518 # these files.
1509 # these files.
1519 foi = [
1510 foi = [
1520 (b'spath', b'00changelog.i'),
1511 (b'spath', b'00changelog.i'),
1521 (b'spath', b'phaseroots'), # ! phase can change content at the same size
1512 (b'spath', b'phaseroots'), # ! phase can change content at the same size
1522 (b'spath', b'obsstore'),
1513 (b'spath', b'obsstore'),
1523 (b'path', b'bookmarks'), # ! bookmark can change content at the same size
1514 (b'path', b'bookmarks'), # ! bookmark can change content at the same size
1524 ]
1515 ]
1525
1516
1526
1517
1527 class cachedlocalrepo(object):
1518 class cachedlocalrepo(object):
1528 """Holds a localrepository that can be cached and reused."""
1519 """Holds a localrepository that can be cached and reused."""
1529
1520
1530 def __init__(self, repo):
1521 def __init__(self, repo):
1531 """Create a new cached repo from an existing repo.
1522 """Create a new cached repo from an existing repo.
1532
1523
1533 We assume the passed in repo was recently created. If the
1524 We assume the passed in repo was recently created. If the
1534 repo has changed between when it was created and when it was
1525 repo has changed between when it was created and when it was
1535 turned into a cache, it may not refresh properly.
1526 turned into a cache, it may not refresh properly.
1536 """
1527 """
1537 assert isinstance(repo, localrepo.localrepository)
1528 assert isinstance(repo, localrepo.localrepository)
1538 self._repo = repo
1529 self._repo = repo
1539 self._state, self.mtime = self._repostate()
1530 self._state, self.mtime = self._repostate()
1540 self._filtername = repo.filtername
1531 self._filtername = repo.filtername
1541
1532
1542 def fetch(self):
1533 def fetch(self):
1543 """Refresh (if necessary) and return a repository.
1534 """Refresh (if necessary) and return a repository.
1544
1535
1545 If the cached instance is out of date, it will be recreated
1536 If the cached instance is out of date, it will be recreated
1546 automatically and returned.
1537 automatically and returned.
1547
1538
1548 Returns a tuple of the repo and a boolean indicating whether a new
1539 Returns a tuple of the repo and a boolean indicating whether a new
1549 repo instance was created.
1540 repo instance was created.
1550 """
1541 """
1551 # We compare the mtimes and sizes of some well-known files to
1542 # We compare the mtimes and sizes of some well-known files to
1552 # determine if the repo changed. This is not precise, as mtimes
1543 # determine if the repo changed. This is not precise, as mtimes
1553 # are susceptible to clock skew and imprecise filesystems and
1544 # are susceptible to clock skew and imprecise filesystems and
1554 # file content can change while maintaining the same size.
1545 # file content can change while maintaining the same size.
1555
1546
1556 state, mtime = self._repostate()
1547 state, mtime = self._repostate()
1557 if state == self._state:
1548 if state == self._state:
1558 return self._repo, False
1549 return self._repo, False
1559
1550
1560 repo = repository(self._repo.baseui, self._repo.url())
1551 repo = repository(self._repo.baseui, self._repo.url())
1561 if self._filtername:
1552 if self._filtername:
1562 self._repo = repo.filtered(self._filtername)
1553 self._repo = repo.filtered(self._filtername)
1563 else:
1554 else:
1564 self._repo = repo.unfiltered()
1555 self._repo = repo.unfiltered()
1565 self._state = state
1556 self._state = state
1566 self.mtime = mtime
1557 self.mtime = mtime
1567
1558
1568 return self._repo, True
1559 return self._repo, True
1569
1560
1570 def _repostate(self):
1561 def _repostate(self):
1571 state = []
1562 state = []
1572 maxmtime = -1
1563 maxmtime = -1
1573 for attr, fname in foi:
1564 for attr, fname in foi:
1574 prefix = getattr(self._repo, attr)
1565 prefix = getattr(self._repo, attr)
1575 p = os.path.join(prefix, fname)
1566 p = os.path.join(prefix, fname)
1576 try:
1567 try:
1577 st = os.stat(p)
1568 st = os.stat(p)
1578 except OSError:
1569 except OSError:
1579 st = os.stat(prefix)
1570 st = os.stat(prefix)
1580 state.append((st[stat.ST_MTIME], st.st_size))
1571 state.append((st[stat.ST_MTIME], st.st_size))
1581 maxmtime = max(maxmtime, st[stat.ST_MTIME])
1572 maxmtime = max(maxmtime, st[stat.ST_MTIME])
1582
1573
1583 return tuple(state), maxmtime
1574 return tuple(state), maxmtime
1584
1575
1585 def copy(self):
1576 def copy(self):
1586 """Obtain a copy of this class instance.
1577 """Obtain a copy of this class instance.
1587
1578
1588 A new localrepository instance is obtained. The new instance should be
1579 A new localrepository instance is obtained. The new instance should be
1589 completely independent of the original.
1580 completely independent of the original.
1590 """
1581 """
1591 repo = repository(self._repo.baseui, self._repo.origroot)
1582 repo = repository(self._repo.baseui, self._repo.origroot)
1592 if self._filtername:
1583 if self._filtername:
1593 repo = repo.filtered(self._filtername)
1584 repo = repo.filtered(self._filtername)
1594 else:
1585 else:
1595 repo = repo.unfiltered()
1586 repo = repo.unfiltered()
1596 c = cachedlocalrepo(repo)
1587 c = cachedlocalrepo(repo)
1597 c._state = self._state
1588 c._state = self._state
1598 c.mtime = self.mtime
1589 c.mtime = self.mtime
1599 return c
1590 return c
@@ -1,773 +1,879 b''
1 # streamclone.py - producing and consuming streaming repository data
1 # streamclone.py - producing and consuming streaming repository data
2 #
2 #
3 # Copyright 2015 Gregory Szorc <gregory.szorc@gmail.com>
3 # Copyright 2015 Gregory Szorc <gregory.szorc@gmail.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 contextlib
10 import contextlib
11 import errno
11 import os
12 import os
12 import struct
13 import struct
13
14
14 from .i18n import _
15 from .i18n import _
15 from .pycompat import open
16 from .pycompat import open
16 from .interfaces import repository
17 from .interfaces import repository
17 from . import (
18 from . import (
19 bookmarks,
18 cacheutil,
20 cacheutil,
19 error,
21 error,
20 narrowspec,
22 narrowspec,
21 phases,
23 phases,
22 pycompat,
24 pycompat,
23 requirements as requirementsmod,
25 requirements as requirementsmod,
24 scmutil,
26 scmutil,
25 store,
27 store,
26 util,
28 util,
27 )
29 )
30 from .utils import (
31 stringutil,
32 )
28
33
29
34
30 def canperformstreamclone(pullop, bundle2=False):
35 def canperformstreamclone(pullop, bundle2=False):
31 """Whether it is possible to perform a streaming clone as part of pull.
36 """Whether it is possible to perform a streaming clone as part of pull.
32
37
33 ``bundle2`` will cause the function to consider stream clone through
38 ``bundle2`` will cause the function to consider stream clone through
34 bundle2 and only through bundle2.
39 bundle2 and only through bundle2.
35
40
36 Returns a tuple of (supported, requirements). ``supported`` is True if
41 Returns a tuple of (supported, requirements). ``supported`` is True if
37 streaming clone is supported and False otherwise. ``requirements`` is
42 streaming clone is supported and False otherwise. ``requirements`` is
38 a set of repo requirements from the remote, or ``None`` if stream clone
43 a set of repo requirements from the remote, or ``None`` if stream clone
39 isn't supported.
44 isn't supported.
40 """
45 """
41 repo = pullop.repo
46 repo = pullop.repo
42 remote = pullop.remote
47 remote = pullop.remote
43
48
44 bundle2supported = False
49 bundle2supported = False
45 if pullop.canusebundle2:
50 if pullop.canusebundle2:
46 if b'v2' in pullop.remotebundle2caps.get(b'stream', []):
51 if b'v2' in pullop.remotebundle2caps.get(b'stream', []):
47 bundle2supported = True
52 bundle2supported = True
48 # else
53 # else
49 # Server doesn't support bundle2 stream clone or doesn't support
54 # Server doesn't support bundle2 stream clone or doesn't support
50 # the versions we support. Fall back and possibly allow legacy.
55 # the versions we support. Fall back and possibly allow legacy.
51
56
52 # Ensures legacy code path uses available bundle2.
57 # Ensures legacy code path uses available bundle2.
53 if bundle2supported and not bundle2:
58 if bundle2supported and not bundle2:
54 return False, None
59 return False, None
55 # Ensures bundle2 doesn't try to do a stream clone if it isn't supported.
60 # Ensures bundle2 doesn't try to do a stream clone if it isn't supported.
56 elif bundle2 and not bundle2supported:
61 elif bundle2 and not bundle2supported:
57 return False, None
62 return False, None
58
63
59 # Streaming clone only works on empty repositories.
64 # Streaming clone only works on empty repositories.
60 if len(repo):
65 if len(repo):
61 return False, None
66 return False, None
62
67
63 # Streaming clone only works if all data is being requested.
68 # Streaming clone only works if all data is being requested.
64 if pullop.heads:
69 if pullop.heads:
65 return False, None
70 return False, None
66
71
67 streamrequested = pullop.streamclonerequested
72 streamrequested = pullop.streamclonerequested
68
73
69 # If we don't have a preference, let the server decide for us. This
74 # If we don't have a preference, let the server decide for us. This
70 # likely only comes into play in LANs.
75 # likely only comes into play in LANs.
71 if streamrequested is None:
76 if streamrequested is None:
72 # The server can advertise whether to prefer streaming clone.
77 # The server can advertise whether to prefer streaming clone.
73 streamrequested = remote.capable(b'stream-preferred')
78 streamrequested = remote.capable(b'stream-preferred')
74
79
75 if not streamrequested:
80 if not streamrequested:
76 return False, None
81 return False, None
77
82
78 # In order for stream clone to work, the client has to support all the
83 # In order for stream clone to work, the client has to support all the
79 # requirements advertised by the server.
84 # requirements advertised by the server.
80 #
85 #
81 # The server advertises its requirements via the "stream" and "streamreqs"
86 # The server advertises its requirements via the "stream" and "streamreqs"
82 # capability. "stream" (a value-less capability) is advertised if and only
87 # capability. "stream" (a value-less capability) is advertised if and only
83 # if the only requirement is "revlogv1." Else, the "streamreqs" capability
88 # if the only requirement is "revlogv1." Else, the "streamreqs" capability
84 # is advertised and contains a comma-delimited list of requirements.
89 # is advertised and contains a comma-delimited list of requirements.
85 requirements = set()
90 requirements = set()
86 if remote.capable(b'stream'):
91 if remote.capable(b'stream'):
87 requirements.add(requirementsmod.REVLOGV1_REQUIREMENT)
92 requirements.add(requirementsmod.REVLOGV1_REQUIREMENT)
88 else:
93 else:
89 streamreqs = remote.capable(b'streamreqs')
94 streamreqs = remote.capable(b'streamreqs')
90 # This is weird and shouldn't happen with modern servers.
95 # This is weird and shouldn't happen with modern servers.
91 if not streamreqs:
96 if not streamreqs:
92 pullop.repo.ui.warn(
97 pullop.repo.ui.warn(
93 _(
98 _(
94 b'warning: stream clone requested but server has them '
99 b'warning: stream clone requested but server has them '
95 b'disabled\n'
100 b'disabled\n'
96 )
101 )
97 )
102 )
98 return False, None
103 return False, None
99
104
100 streamreqs = set(streamreqs.split(b','))
105 streamreqs = set(streamreqs.split(b','))
101 # Server requires something we don't support. Bail.
106 # Server requires something we don't support. Bail.
102 missingreqs = streamreqs - repo.supportedformats
107 missingreqs = streamreqs - repo.supportedformats
103 if missingreqs:
108 if missingreqs:
104 pullop.repo.ui.warn(
109 pullop.repo.ui.warn(
105 _(
110 _(
106 b'warning: stream clone requested but client is missing '
111 b'warning: stream clone requested but client is missing '
107 b'requirements: %s\n'
112 b'requirements: %s\n'
108 )
113 )
109 % b', '.join(sorted(missingreqs))
114 % b', '.join(sorted(missingreqs))
110 )
115 )
111 pullop.repo.ui.warn(
116 pullop.repo.ui.warn(
112 _(
117 _(
113 b'(see https://www.mercurial-scm.org/wiki/MissingRequirement '
118 b'(see https://www.mercurial-scm.org/wiki/MissingRequirement '
114 b'for more information)\n'
119 b'for more information)\n'
115 )
120 )
116 )
121 )
117 return False, None
122 return False, None
118 requirements = streamreqs
123 requirements = streamreqs
119
124
120 return True, requirements
125 return True, requirements
121
126
122
127
123 def maybeperformlegacystreamclone(pullop):
128 def maybeperformlegacystreamclone(pullop):
124 """Possibly perform a legacy stream clone operation.
129 """Possibly perform a legacy stream clone operation.
125
130
126 Legacy stream clones are performed as part of pull but before all other
131 Legacy stream clones are performed as part of pull but before all other
127 operations.
132 operations.
128
133
129 A legacy stream clone will not be performed if a bundle2 stream clone is
134 A legacy stream clone will not be performed if a bundle2 stream clone is
130 supported.
135 supported.
131 """
136 """
132 from . import localrepo
137 from . import localrepo
133
138
134 supported, requirements = canperformstreamclone(pullop)
139 supported, requirements = canperformstreamclone(pullop)
135
140
136 if not supported:
141 if not supported:
137 return
142 return
138
143
139 repo = pullop.repo
144 repo = pullop.repo
140 remote = pullop.remote
145 remote = pullop.remote
141
146
142 # Save remote branchmap. We will use it later to speed up branchcache
147 # Save remote branchmap. We will use it later to speed up branchcache
143 # creation.
148 # creation.
144 rbranchmap = None
149 rbranchmap = None
145 if remote.capable(b'branchmap'):
150 if remote.capable(b'branchmap'):
146 with remote.commandexecutor() as e:
151 with remote.commandexecutor() as e:
147 rbranchmap = e.callcommand(b'branchmap', {}).result()
152 rbranchmap = e.callcommand(b'branchmap', {}).result()
148
153
149 repo.ui.status(_(b'streaming all changes\n'))
154 repo.ui.status(_(b'streaming all changes\n'))
150
155
151 with remote.commandexecutor() as e:
156 with remote.commandexecutor() as e:
152 fp = e.callcommand(b'stream_out', {}).result()
157 fp = e.callcommand(b'stream_out', {}).result()
153
158
154 # TODO strictly speaking, this code should all be inside the context
159 # TODO strictly speaking, this code should all be inside the context
155 # manager because the context manager is supposed to ensure all wire state
160 # manager because the context manager is supposed to ensure all wire state
156 # is flushed when exiting. But the legacy peers don't do this, so it
161 # is flushed when exiting. But the legacy peers don't do this, so it
157 # doesn't matter.
162 # doesn't matter.
158 l = fp.readline()
163 l = fp.readline()
159 try:
164 try:
160 resp = int(l)
165 resp = int(l)
161 except ValueError:
166 except ValueError:
162 raise error.ResponseError(
167 raise error.ResponseError(
163 _(b'unexpected response from remote server:'), l
168 _(b'unexpected response from remote server:'), l
164 )
169 )
165 if resp == 1:
170 if resp == 1:
166 raise error.Abort(_(b'operation forbidden by server'))
171 raise error.Abort(_(b'operation forbidden by server'))
167 elif resp == 2:
172 elif resp == 2:
168 raise error.Abort(_(b'locking the remote repository failed'))
173 raise error.Abort(_(b'locking the remote repository failed'))
169 elif resp != 0:
174 elif resp != 0:
170 raise error.Abort(_(b'the server sent an unknown error code'))
175 raise error.Abort(_(b'the server sent an unknown error code'))
171
176
172 l = fp.readline()
177 l = fp.readline()
173 try:
178 try:
174 filecount, bytecount = map(int, l.split(b' ', 1))
179 filecount, bytecount = map(int, l.split(b' ', 1))
175 except (ValueError, TypeError):
180 except (ValueError, TypeError):
176 raise error.ResponseError(
181 raise error.ResponseError(
177 _(b'unexpected response from remote server:'), l
182 _(b'unexpected response from remote server:'), l
178 )
183 )
179
184
180 with repo.lock():
185 with repo.lock():
181 consumev1(repo, fp, filecount, bytecount)
186 consumev1(repo, fp, filecount, bytecount)
182
187
183 # new requirements = old non-format requirements +
188 # new requirements = old non-format requirements +
184 # new format-related remote requirements
189 # new format-related remote requirements
185 # requirements from the streamed-in repository
190 # requirements from the streamed-in repository
186 repo.requirements = requirements | (
191 repo.requirements = requirements | (
187 repo.requirements - repo.supportedformats
192 repo.requirements - repo.supportedformats
188 )
193 )
189 repo.svfs.options = localrepo.resolvestorevfsoptions(
194 repo.svfs.options = localrepo.resolvestorevfsoptions(
190 repo.ui, repo.requirements, repo.features
195 repo.ui, repo.requirements, repo.features
191 )
196 )
192 scmutil.writereporequirements(repo)
197 scmutil.writereporequirements(repo)
193
198
194 if rbranchmap:
199 if rbranchmap:
195 repo._branchcaches.replace(repo, rbranchmap)
200 repo._branchcaches.replace(repo, rbranchmap)
196
201
197 repo.invalidate()
202 repo.invalidate()
198
203
199
204
200 def allowservergeneration(repo):
205 def allowservergeneration(repo):
201 """Whether streaming clones are allowed from the server."""
206 """Whether streaming clones are allowed from the server."""
202 if repository.REPO_FEATURE_STREAM_CLONE not in repo.features:
207 if repository.REPO_FEATURE_STREAM_CLONE not in repo.features:
203 return False
208 return False
204
209
205 if not repo.ui.configbool(b'server', b'uncompressed', untrusted=True):
210 if not repo.ui.configbool(b'server', b'uncompressed', untrusted=True):
206 return False
211 return False
207
212
208 # The way stream clone works makes it impossible to hide secret changesets.
213 # The way stream clone works makes it impossible to hide secret changesets.
209 # So don't allow this by default.
214 # So don't allow this by default.
210 secret = phases.hassecret(repo)
215 secret = phases.hassecret(repo)
211 if secret:
216 if secret:
212 return repo.ui.configbool(b'server', b'uncompressedallowsecret')
217 return repo.ui.configbool(b'server', b'uncompressedallowsecret')
213
218
214 return True
219 return True
215
220
216
221
217 # This is it's own function so extensions can override it.
222 # This is it's own function so extensions can override it.
218 def _walkstreamfiles(repo, matcher=None):
223 def _walkstreamfiles(repo, matcher=None):
219 return repo.store.walk(matcher)
224 return repo.store.walk(matcher)
220
225
221
226
222 def generatev1(repo):
227 def generatev1(repo):
223 """Emit content for version 1 of a streaming clone.
228 """Emit content for version 1 of a streaming clone.
224
229
225 This returns a 3-tuple of (file count, byte size, data iterator).
230 This returns a 3-tuple of (file count, byte size, data iterator).
226
231
227 The data iterator consists of N entries for each file being transferred.
232 The data iterator consists of N entries for each file being transferred.
228 Each file entry starts as a line with the file name and integer size
233 Each file entry starts as a line with the file name and integer size
229 delimited by a null byte.
234 delimited by a null byte.
230
235
231 The raw file data follows. Following the raw file data is the next file
236 The raw file data follows. Following the raw file data is the next file
232 entry, or EOF.
237 entry, or EOF.
233
238
234 When used on the wire protocol, an additional line indicating protocol
239 When used on the wire protocol, an additional line indicating protocol
235 success will be prepended to the stream. This function is not responsible
240 success will be prepended to the stream. This function is not responsible
236 for adding it.
241 for adding it.
237
242
238 This function will obtain a repository lock to ensure a consistent view of
243 This function will obtain a repository lock to ensure a consistent view of
239 the store is captured. It therefore may raise LockError.
244 the store is captured. It therefore may raise LockError.
240 """
245 """
241 entries = []
246 entries = []
242 total_bytes = 0
247 total_bytes = 0
243 # Get consistent snapshot of repo, lock during scan.
248 # Get consistent snapshot of repo, lock during scan.
244 with repo.lock():
249 with repo.lock():
245 repo.ui.debug(b'scanning\n')
250 repo.ui.debug(b'scanning\n')
246 for file_type, name, ename, size in _walkstreamfiles(repo):
251 for file_type, name, ename, size in _walkstreamfiles(repo):
247 if size:
252 if size:
248 entries.append((name, size))
253 entries.append((name, size))
249 total_bytes += size
254 total_bytes += size
250 _test_sync_point_walk_1(repo)
255 _test_sync_point_walk_1(repo)
251 _test_sync_point_walk_2(repo)
256 _test_sync_point_walk_2(repo)
252
257
253 repo.ui.debug(
258 repo.ui.debug(
254 b'%d files, %d bytes to transfer\n' % (len(entries), total_bytes)
259 b'%d files, %d bytes to transfer\n' % (len(entries), total_bytes)
255 )
260 )
256
261
257 svfs = repo.svfs
262 svfs = repo.svfs
258 debugflag = repo.ui.debugflag
263 debugflag = repo.ui.debugflag
259
264
260 def emitrevlogdata():
265 def emitrevlogdata():
261 for name, size in entries:
266 for name, size in entries:
262 if debugflag:
267 if debugflag:
263 repo.ui.debug(b'sending %s (%d bytes)\n' % (name, size))
268 repo.ui.debug(b'sending %s (%d bytes)\n' % (name, size))
264 # partially encode name over the wire for backwards compat
269 # partially encode name over the wire for backwards compat
265 yield b'%s\0%d\n' % (store.encodedir(name), size)
270 yield b'%s\0%d\n' % (store.encodedir(name), size)
266 # auditing at this stage is both pointless (paths are already
271 # auditing at this stage is both pointless (paths are already
267 # trusted by the local repo) and expensive
272 # trusted by the local repo) and expensive
268 with svfs(name, b'rb', auditpath=False) as fp:
273 with svfs(name, b'rb', auditpath=False) as fp:
269 if size <= 65536:
274 if size <= 65536:
270 yield fp.read(size)
275 yield fp.read(size)
271 else:
276 else:
272 for chunk in util.filechunkiter(fp, limit=size):
277 for chunk in util.filechunkiter(fp, limit=size):
273 yield chunk
278 yield chunk
274
279
275 return len(entries), total_bytes, emitrevlogdata()
280 return len(entries), total_bytes, emitrevlogdata()
276
281
277
282
278 def generatev1wireproto(repo):
283 def generatev1wireproto(repo):
279 """Emit content for version 1 of streaming clone suitable for the wire.
284 """Emit content for version 1 of streaming clone suitable for the wire.
280
285
281 This is the data output from ``generatev1()`` with 2 header lines. The
286 This is the data output from ``generatev1()`` with 2 header lines. The
282 first line indicates overall success. The 2nd contains the file count and
287 first line indicates overall success. The 2nd contains the file count and
283 byte size of payload.
288 byte size of payload.
284
289
285 The success line contains "0" for success, "1" for stream generation not
290 The success line contains "0" for success, "1" for stream generation not
286 allowed, and "2" for error locking the repository (possibly indicating
291 allowed, and "2" for error locking the repository (possibly indicating
287 a permissions error for the server process).
292 a permissions error for the server process).
288 """
293 """
289 if not allowservergeneration(repo):
294 if not allowservergeneration(repo):
290 yield b'1\n'
295 yield b'1\n'
291 return
296 return
292
297
293 try:
298 try:
294 filecount, bytecount, it = generatev1(repo)
299 filecount, bytecount, it = generatev1(repo)
295 except error.LockError:
300 except error.LockError:
296 yield b'2\n'
301 yield b'2\n'
297 return
302 return
298
303
299 # Indicates successful response.
304 # Indicates successful response.
300 yield b'0\n'
305 yield b'0\n'
301 yield b'%d %d\n' % (filecount, bytecount)
306 yield b'%d %d\n' % (filecount, bytecount)
302 for chunk in it:
307 for chunk in it:
303 yield chunk
308 yield chunk
304
309
305
310
306 def generatebundlev1(repo, compression=b'UN'):
311 def generatebundlev1(repo, compression=b'UN'):
307 """Emit content for version 1 of a stream clone bundle.
312 """Emit content for version 1 of a stream clone bundle.
308
313
309 The first 4 bytes of the output ("HGS1") denote this as stream clone
314 The first 4 bytes of the output ("HGS1") denote this as stream clone
310 bundle version 1.
315 bundle version 1.
311
316
312 The next 2 bytes indicate the compression type. Only "UN" is currently
317 The next 2 bytes indicate the compression type. Only "UN" is currently
313 supported.
318 supported.
314
319
315 The next 16 bytes are two 64-bit big endian unsigned integers indicating
320 The next 16 bytes are two 64-bit big endian unsigned integers indicating
316 file count and byte count, respectively.
321 file count and byte count, respectively.
317
322
318 The next 2 bytes is a 16-bit big endian unsigned short declaring the length
323 The next 2 bytes is a 16-bit big endian unsigned short declaring the length
319 of the requirements string, including a trailing \0. The following N bytes
324 of the requirements string, including a trailing \0. The following N bytes
320 are the requirements string, which is ASCII containing a comma-delimited
325 are the requirements string, which is ASCII containing a comma-delimited
321 list of repo requirements that are needed to support the data.
326 list of repo requirements that are needed to support the data.
322
327
323 The remaining content is the output of ``generatev1()`` (which may be
328 The remaining content is the output of ``generatev1()`` (which may be
324 compressed in the future).
329 compressed in the future).
325
330
326 Returns a tuple of (requirements, data generator).
331 Returns a tuple of (requirements, data generator).
327 """
332 """
328 if compression != b'UN':
333 if compression != b'UN':
329 raise ValueError(b'we do not support the compression argument yet')
334 raise ValueError(b'we do not support the compression argument yet')
330
335
331 requirements = repo.requirements & repo.supportedformats
336 requirements = repo.requirements & repo.supportedformats
332 requires = b','.join(sorted(requirements))
337 requires = b','.join(sorted(requirements))
333
338
334 def gen():
339 def gen():
335 yield b'HGS1'
340 yield b'HGS1'
336 yield compression
341 yield compression
337
342
338 filecount, bytecount, it = generatev1(repo)
343 filecount, bytecount, it = generatev1(repo)
339 repo.ui.status(
344 repo.ui.status(
340 _(b'writing %d bytes for %d files\n') % (bytecount, filecount)
345 _(b'writing %d bytes for %d files\n') % (bytecount, filecount)
341 )
346 )
342
347
343 yield struct.pack(b'>QQ', filecount, bytecount)
348 yield struct.pack(b'>QQ', filecount, bytecount)
344 yield struct.pack(b'>H', len(requires) + 1)
349 yield struct.pack(b'>H', len(requires) + 1)
345 yield requires + b'\0'
350 yield requires + b'\0'
346
351
347 # This is where we'll add compression in the future.
352 # This is where we'll add compression in the future.
348 assert compression == b'UN'
353 assert compression == b'UN'
349
354
350 progress = repo.ui.makeprogress(
355 progress = repo.ui.makeprogress(
351 _(b'bundle'), total=bytecount, unit=_(b'bytes')
356 _(b'bundle'), total=bytecount, unit=_(b'bytes')
352 )
357 )
353 progress.update(0)
358 progress.update(0)
354
359
355 for chunk in it:
360 for chunk in it:
356 progress.increment(step=len(chunk))
361 progress.increment(step=len(chunk))
357 yield chunk
362 yield chunk
358
363
359 progress.complete()
364 progress.complete()
360
365
361 return requirements, gen()
366 return requirements, gen()
362
367
363
368
364 def consumev1(repo, fp, filecount, bytecount):
369 def consumev1(repo, fp, filecount, bytecount):
365 """Apply the contents from version 1 of a streaming clone file handle.
370 """Apply the contents from version 1 of a streaming clone file handle.
366
371
367 This takes the output from "stream_out" and applies it to the specified
372 This takes the output from "stream_out" and applies it to the specified
368 repository.
373 repository.
369
374
370 Like "stream_out," the status line added by the wire protocol is not
375 Like "stream_out," the status line added by the wire protocol is not
371 handled by this function.
376 handled by this function.
372 """
377 """
373 with repo.lock():
378 with repo.lock():
374 repo.ui.status(
379 repo.ui.status(
375 _(b'%d files to transfer, %s of data\n')
380 _(b'%d files to transfer, %s of data\n')
376 % (filecount, util.bytecount(bytecount))
381 % (filecount, util.bytecount(bytecount))
377 )
382 )
378 progress = repo.ui.makeprogress(
383 progress = repo.ui.makeprogress(
379 _(b'clone'), total=bytecount, unit=_(b'bytes')
384 _(b'clone'), total=bytecount, unit=_(b'bytes')
380 )
385 )
381 progress.update(0)
386 progress.update(0)
382 start = util.timer()
387 start = util.timer()
383
388
384 # TODO: get rid of (potential) inconsistency
389 # TODO: get rid of (potential) inconsistency
385 #
390 #
386 # If transaction is started and any @filecache property is
391 # If transaction is started and any @filecache property is
387 # changed at this point, it causes inconsistency between
392 # changed at this point, it causes inconsistency between
388 # in-memory cached property and streamclone-ed file on the
393 # in-memory cached property and streamclone-ed file on the
389 # disk. Nested transaction prevents transaction scope "clone"
394 # disk. Nested transaction prevents transaction scope "clone"
390 # below from writing in-memory changes out at the end of it,
395 # below from writing in-memory changes out at the end of it,
391 # even though in-memory changes are discarded at the end of it
396 # even though in-memory changes are discarded at the end of it
392 # regardless of transaction nesting.
397 # regardless of transaction nesting.
393 #
398 #
394 # But transaction nesting can't be simply prohibited, because
399 # But transaction nesting can't be simply prohibited, because
395 # nesting occurs also in ordinary case (e.g. enabling
400 # nesting occurs also in ordinary case (e.g. enabling
396 # clonebundles).
401 # clonebundles).
397
402
398 with repo.transaction(b'clone'):
403 with repo.transaction(b'clone'):
399 with repo.svfs.backgroundclosing(repo.ui, expectedcount=filecount):
404 with repo.svfs.backgroundclosing(repo.ui, expectedcount=filecount):
400 for i in pycompat.xrange(filecount):
405 for i in pycompat.xrange(filecount):
401 # XXX doesn't support '\n' or '\r' in filenames
406 # XXX doesn't support '\n' or '\r' in filenames
402 l = fp.readline()
407 l = fp.readline()
403 try:
408 try:
404 name, size = l.split(b'\0', 1)
409 name, size = l.split(b'\0', 1)
405 size = int(size)
410 size = int(size)
406 except (ValueError, TypeError):
411 except (ValueError, TypeError):
407 raise error.ResponseError(
412 raise error.ResponseError(
408 _(b'unexpected response from remote server:'), l
413 _(b'unexpected response from remote server:'), l
409 )
414 )
410 if repo.ui.debugflag:
415 if repo.ui.debugflag:
411 repo.ui.debug(
416 repo.ui.debug(
412 b'adding %s (%s)\n' % (name, util.bytecount(size))
417 b'adding %s (%s)\n' % (name, util.bytecount(size))
413 )
418 )
414 # for backwards compat, name was partially encoded
419 # for backwards compat, name was partially encoded
415 path = store.decodedir(name)
420 path = store.decodedir(name)
416 with repo.svfs(path, b'w', backgroundclose=True) as ofp:
421 with repo.svfs(path, b'w', backgroundclose=True) as ofp:
417 for chunk in util.filechunkiter(fp, limit=size):
422 for chunk in util.filechunkiter(fp, limit=size):
418 progress.increment(step=len(chunk))
423 progress.increment(step=len(chunk))
419 ofp.write(chunk)
424 ofp.write(chunk)
420
425
421 # force @filecache properties to be reloaded from
426 # force @filecache properties to be reloaded from
422 # streamclone-ed file at next access
427 # streamclone-ed file at next access
423 repo.invalidate(clearfilecache=True)
428 repo.invalidate(clearfilecache=True)
424
429
425 elapsed = util.timer() - start
430 elapsed = util.timer() - start
426 if elapsed <= 0:
431 if elapsed <= 0:
427 elapsed = 0.001
432 elapsed = 0.001
428 progress.complete()
433 progress.complete()
429 repo.ui.status(
434 repo.ui.status(
430 _(b'transferred %s in %.1f seconds (%s/sec)\n')
435 _(b'transferred %s in %.1f seconds (%s/sec)\n')
431 % (
436 % (
432 util.bytecount(bytecount),
437 util.bytecount(bytecount),
433 elapsed,
438 elapsed,
434 util.bytecount(bytecount / elapsed),
439 util.bytecount(bytecount / elapsed),
435 )
440 )
436 )
441 )
437
442
438
443
439 def readbundle1header(fp):
444 def readbundle1header(fp):
440 compression = fp.read(2)
445 compression = fp.read(2)
441 if compression != b'UN':
446 if compression != b'UN':
442 raise error.Abort(
447 raise error.Abort(
443 _(
448 _(
444 b'only uncompressed stream clone bundles are '
449 b'only uncompressed stream clone bundles are '
445 b'supported; got %s'
450 b'supported; got %s'
446 )
451 )
447 % compression
452 % compression
448 )
453 )
449
454
450 filecount, bytecount = struct.unpack(b'>QQ', fp.read(16))
455 filecount, bytecount = struct.unpack(b'>QQ', fp.read(16))
451 requireslen = struct.unpack(b'>H', fp.read(2))[0]
456 requireslen = struct.unpack(b'>H', fp.read(2))[0]
452 requires = fp.read(requireslen)
457 requires = fp.read(requireslen)
453
458
454 if not requires.endswith(b'\0'):
459 if not requires.endswith(b'\0'):
455 raise error.Abort(
460 raise error.Abort(
456 _(
461 _(
457 b'malformed stream clone bundle: '
462 b'malformed stream clone bundle: '
458 b'requirements not properly encoded'
463 b'requirements not properly encoded'
459 )
464 )
460 )
465 )
461
466
462 requirements = set(requires.rstrip(b'\0').split(b','))
467 requirements = set(requires.rstrip(b'\0').split(b','))
463
468
464 return filecount, bytecount, requirements
469 return filecount, bytecount, requirements
465
470
466
471
467 def applybundlev1(repo, fp):
472 def applybundlev1(repo, fp):
468 """Apply the content from a stream clone bundle version 1.
473 """Apply the content from a stream clone bundle version 1.
469
474
470 We assume the 4 byte header has been read and validated and the file handle
475 We assume the 4 byte header has been read and validated and the file handle
471 is at the 2 byte compression identifier.
476 is at the 2 byte compression identifier.
472 """
477 """
473 if len(repo):
478 if len(repo):
474 raise error.Abort(
479 raise error.Abort(
475 _(b'cannot apply stream clone bundle on non-empty repo')
480 _(b'cannot apply stream clone bundle on non-empty repo')
476 )
481 )
477
482
478 filecount, bytecount, requirements = readbundle1header(fp)
483 filecount, bytecount, requirements = readbundle1header(fp)
479 missingreqs = requirements - repo.supportedformats
484 missingreqs = requirements - repo.supportedformats
480 if missingreqs:
485 if missingreqs:
481 raise error.Abort(
486 raise error.Abort(
482 _(b'unable to apply stream clone: unsupported format: %s')
487 _(b'unable to apply stream clone: unsupported format: %s')
483 % b', '.join(sorted(missingreqs))
488 % b', '.join(sorted(missingreqs))
484 )
489 )
485
490
486 consumev1(repo, fp, filecount, bytecount)
491 consumev1(repo, fp, filecount, bytecount)
487
492
488
493
489 class streamcloneapplier(object):
494 class streamcloneapplier(object):
490 """Class to manage applying streaming clone bundles.
495 """Class to manage applying streaming clone bundles.
491
496
492 We need to wrap ``applybundlev1()`` in a dedicated type to enable bundle
497 We need to wrap ``applybundlev1()`` in a dedicated type to enable bundle
493 readers to perform bundle type-specific functionality.
498 readers to perform bundle type-specific functionality.
494 """
499 """
495
500
496 def __init__(self, fh):
501 def __init__(self, fh):
497 self._fh = fh
502 self._fh = fh
498
503
499 def apply(self, repo):
504 def apply(self, repo):
500 return applybundlev1(repo, self._fh)
505 return applybundlev1(repo, self._fh)
501
506
502
507
503 # type of file to stream
508 # type of file to stream
504 _fileappend = 0 # append only file
509 _fileappend = 0 # append only file
505 _filefull = 1 # full snapshot file
510 _filefull = 1 # full snapshot file
506
511
507 # Source of the file
512 # Source of the file
508 _srcstore = b's' # store (svfs)
513 _srcstore = b's' # store (svfs)
509 _srccache = b'c' # cache (cache)
514 _srccache = b'c' # cache (cache)
510
515
511 # This is it's own function so extensions can override it.
516 # This is it's own function so extensions can override it.
512 def _walkstreamfullstorefiles(repo):
517 def _walkstreamfullstorefiles(repo):
513 """list snapshot file from the store"""
518 """list snapshot file from the store"""
514 fnames = []
519 fnames = []
515 if not repo.publishing():
520 if not repo.publishing():
516 fnames.append(b'phaseroots')
521 fnames.append(b'phaseroots')
517 return fnames
522 return fnames
518
523
519
524
520 def _filterfull(entry, copy, vfsmap):
525 def _filterfull(entry, copy, vfsmap):
521 """actually copy the snapshot files"""
526 """actually copy the snapshot files"""
522 src, name, ftype, data = entry
527 src, name, ftype, data = entry
523 if ftype != _filefull:
528 if ftype != _filefull:
524 return entry
529 return entry
525 return (src, name, ftype, copy(vfsmap[src].join(name)))
530 return (src, name, ftype, copy(vfsmap[src].join(name)))
526
531
527
532
528 @contextlib.contextmanager
533 @contextlib.contextmanager
529 def maketempcopies():
534 def maketempcopies():
530 """return a function to temporary copy file"""
535 """return a function to temporary copy file"""
531 files = []
536 files = []
532 try:
537 try:
533
538
534 def copy(src):
539 def copy(src):
535 fd, dst = pycompat.mkstemp()
540 fd, dst = pycompat.mkstemp()
536 os.close(fd)
541 os.close(fd)
537 files.append(dst)
542 files.append(dst)
538 util.copyfiles(src, dst, hardlink=True)
543 util.copyfiles(src, dst, hardlink=True)
539 return dst
544 return dst
540
545
541 yield copy
546 yield copy
542 finally:
547 finally:
543 for tmp in files:
548 for tmp in files:
544 util.tryunlink(tmp)
549 util.tryunlink(tmp)
545
550
546
551
547 def _makemap(repo):
552 def _makemap(repo):
548 """make a (src -> vfs) map for the repo"""
553 """make a (src -> vfs) map for the repo"""
549 vfsmap = {
554 vfsmap = {
550 _srcstore: repo.svfs,
555 _srcstore: repo.svfs,
551 _srccache: repo.cachevfs,
556 _srccache: repo.cachevfs,
552 }
557 }
553 # we keep repo.vfs out of the on purpose, ther are too many danger there
558 # we keep repo.vfs out of the on purpose, ther are too many danger there
554 # (eg: .hg/hgrc)
559 # (eg: .hg/hgrc)
555 assert repo.vfs not in vfsmap.values()
560 assert repo.vfs not in vfsmap.values()
556
561
557 return vfsmap
562 return vfsmap
558
563
559
564
560 def _emit2(repo, entries, totalfilesize):
565 def _emit2(repo, entries, totalfilesize):
561 """actually emit the stream bundle"""
566 """actually emit the stream bundle"""
562 vfsmap = _makemap(repo)
567 vfsmap = _makemap(repo)
563 progress = repo.ui.makeprogress(
568 progress = repo.ui.makeprogress(
564 _(b'bundle'), total=totalfilesize, unit=_(b'bytes')
569 _(b'bundle'), total=totalfilesize, unit=_(b'bytes')
565 )
570 )
566 progress.update(0)
571 progress.update(0)
567 with maketempcopies() as copy, progress:
572 with maketempcopies() as copy, progress:
568 # copy is delayed until we are in the try
573 # copy is delayed until we are in the try
569 entries = [_filterfull(e, copy, vfsmap) for e in entries]
574 entries = [_filterfull(e, copy, vfsmap) for e in entries]
570 yield None # this release the lock on the repository
575 yield None # this release the lock on the repository
571 seen = 0
576 seen = 0
572
577
573 for src, name, ftype, data in entries:
578 for src, name, ftype, data in entries:
574 vfs = vfsmap[src]
579 vfs = vfsmap[src]
575 yield src
580 yield src
576 yield util.uvarintencode(len(name))
581 yield util.uvarintencode(len(name))
577 if ftype == _fileappend:
582 if ftype == _fileappend:
578 fp = vfs(name)
583 fp = vfs(name)
579 size = data
584 size = data
580 elif ftype == _filefull:
585 elif ftype == _filefull:
581 fp = open(data, b'rb')
586 fp = open(data, b'rb')
582 size = util.fstat(fp).st_size
587 size = util.fstat(fp).st_size
583 try:
588 try:
584 yield util.uvarintencode(size)
589 yield util.uvarintencode(size)
585 yield name
590 yield name
586 if size <= 65536:
591 if size <= 65536:
587 chunks = (fp.read(size),)
592 chunks = (fp.read(size),)
588 else:
593 else:
589 chunks = util.filechunkiter(fp, limit=size)
594 chunks = util.filechunkiter(fp, limit=size)
590 for chunk in chunks:
595 for chunk in chunks:
591 seen += len(chunk)
596 seen += len(chunk)
592 progress.update(seen)
597 progress.update(seen)
593 yield chunk
598 yield chunk
594 finally:
599 finally:
595 fp.close()
600 fp.close()
596
601
597
602
598 def _test_sync_point_walk_1(repo):
603 def _test_sync_point_walk_1(repo):
599 """a function for synchronisation during tests"""
604 """a function for synchronisation during tests"""
600
605
601
606
602 def _test_sync_point_walk_2(repo):
607 def _test_sync_point_walk_2(repo):
603 """a function for synchronisation during tests"""
608 """a function for synchronisation during tests"""
604
609
605
610
606 def _v2_walk(repo, includes, excludes, includeobsmarkers):
611 def _v2_walk(repo, includes, excludes, includeobsmarkers):
607 """emit a seris of files information useful to clone a repo
612 """emit a seris of files information useful to clone a repo
608
613
609 return (entries, totalfilesize)
614 return (entries, totalfilesize)
610
615
611 entries is a list of tuple (vfs-key, file-path, file-type, size)
616 entries is a list of tuple (vfs-key, file-path, file-type, size)
612
617
613 - `vfs-key`: is a key to the right vfs to write the file (see _makemap)
618 - `vfs-key`: is a key to the right vfs to write the file (see _makemap)
614 - `name`: file path of the file to copy (to be feed to the vfss)
619 - `name`: file path of the file to copy (to be feed to the vfss)
615 - `file-type`: do this file need to be copied with the source lock ?
620 - `file-type`: do this file need to be copied with the source lock ?
616 - `size`: the size of the file (or None)
621 - `size`: the size of the file (or None)
617 """
622 """
618 assert repo._currentlock(repo._lockref) is not None
623 assert repo._currentlock(repo._lockref) is not None
619 entries = []
624 entries = []
620 totalfilesize = 0
625 totalfilesize = 0
621
626
622 matcher = None
627 matcher = None
623 if includes or excludes:
628 if includes or excludes:
624 matcher = narrowspec.match(repo.root, includes, excludes)
629 matcher = narrowspec.match(repo.root, includes, excludes)
625
630
626 for rl_type, name, ename, size in _walkstreamfiles(repo, matcher):
631 for rl_type, name, ename, size in _walkstreamfiles(repo, matcher):
627 if size:
632 if size:
628 ft = _fileappend
633 ft = _fileappend
629 if rl_type & store.FILEFLAGS_VOLATILE:
634 if rl_type & store.FILEFLAGS_VOLATILE:
630 ft = _filefull
635 ft = _filefull
631 entries.append((_srcstore, name, ft, size))
636 entries.append((_srcstore, name, ft, size))
632 totalfilesize += size
637 totalfilesize += size
633 for name in _walkstreamfullstorefiles(repo):
638 for name in _walkstreamfullstorefiles(repo):
634 if repo.svfs.exists(name):
639 if repo.svfs.exists(name):
635 totalfilesize += repo.svfs.lstat(name).st_size
640 totalfilesize += repo.svfs.lstat(name).st_size
636 entries.append((_srcstore, name, _filefull, None))
641 entries.append((_srcstore, name, _filefull, None))
637 if includeobsmarkers and repo.svfs.exists(b'obsstore'):
642 if includeobsmarkers and repo.svfs.exists(b'obsstore'):
638 totalfilesize += repo.svfs.lstat(b'obsstore').st_size
643 totalfilesize += repo.svfs.lstat(b'obsstore').st_size
639 entries.append((_srcstore, b'obsstore', _filefull, None))
644 entries.append((_srcstore, b'obsstore', _filefull, None))
640 for name in cacheutil.cachetocopy(repo):
645 for name in cacheutil.cachetocopy(repo):
641 if repo.cachevfs.exists(name):
646 if repo.cachevfs.exists(name):
642 totalfilesize += repo.cachevfs.lstat(name).st_size
647 totalfilesize += repo.cachevfs.lstat(name).st_size
643 entries.append((_srccache, name, _filefull, None))
648 entries.append((_srccache, name, _filefull, None))
644 return entries, totalfilesize
649 return entries, totalfilesize
645
650
646
651
647 def generatev2(repo, includes, excludes, includeobsmarkers):
652 def generatev2(repo, includes, excludes, includeobsmarkers):
648 """Emit content for version 2 of a streaming clone.
653 """Emit content for version 2 of a streaming clone.
649
654
650 the data stream consists the following entries:
655 the data stream consists the following entries:
651 1) A char representing the file destination (eg: store or cache)
656 1) A char representing the file destination (eg: store or cache)
652 2) A varint containing the length of the filename
657 2) A varint containing the length of the filename
653 3) A varint containing the length of file data
658 3) A varint containing the length of file data
654 4) N bytes containing the filename (the internal, store-agnostic form)
659 4) N bytes containing the filename (the internal, store-agnostic form)
655 5) N bytes containing the file data
660 5) N bytes containing the file data
656
661
657 Returns a 3-tuple of (file count, file size, data iterator).
662 Returns a 3-tuple of (file count, file size, data iterator).
658 """
663 """
659
664
660 with repo.lock():
665 with repo.lock():
661
666
662 repo.ui.debug(b'scanning\n')
667 repo.ui.debug(b'scanning\n')
663
668
664 entries, totalfilesize = _v2_walk(
669 entries, totalfilesize = _v2_walk(
665 repo,
670 repo,
666 includes=includes,
671 includes=includes,
667 excludes=excludes,
672 excludes=excludes,
668 includeobsmarkers=includeobsmarkers,
673 includeobsmarkers=includeobsmarkers,
669 )
674 )
670
675
671 chunks = _emit2(repo, entries, totalfilesize)
676 chunks = _emit2(repo, entries, totalfilesize)
672 first = next(chunks)
677 first = next(chunks)
673 assert first is None
678 assert first is None
674 _test_sync_point_walk_1(repo)
679 _test_sync_point_walk_1(repo)
675 _test_sync_point_walk_2(repo)
680 _test_sync_point_walk_2(repo)
676
681
677 return len(entries), totalfilesize, chunks
682 return len(entries), totalfilesize, chunks
678
683
679
684
680 @contextlib.contextmanager
685 @contextlib.contextmanager
681 def nested(*ctxs):
686 def nested(*ctxs):
682 this = ctxs[0]
687 this = ctxs[0]
683 rest = ctxs[1:]
688 rest = ctxs[1:]
684 with this:
689 with this:
685 if rest:
690 if rest:
686 with nested(*rest):
691 with nested(*rest):
687 yield
692 yield
688 else:
693 else:
689 yield
694 yield
690
695
691
696
692 def consumev2(repo, fp, filecount, filesize):
697 def consumev2(repo, fp, filecount, filesize):
693 """Apply the contents from a version 2 streaming clone.
698 """Apply the contents from a version 2 streaming clone.
694
699
695 Data is read from an object that only needs to provide a ``read(size)``
700 Data is read from an object that only needs to provide a ``read(size)``
696 method.
701 method.
697 """
702 """
698 with repo.lock():
703 with repo.lock():
699 repo.ui.status(
704 repo.ui.status(
700 _(b'%d files to transfer, %s of data\n')
705 _(b'%d files to transfer, %s of data\n')
701 % (filecount, util.bytecount(filesize))
706 % (filecount, util.bytecount(filesize))
702 )
707 )
703
708
704 start = util.timer()
709 start = util.timer()
705 progress = repo.ui.makeprogress(
710 progress = repo.ui.makeprogress(
706 _(b'clone'), total=filesize, unit=_(b'bytes')
711 _(b'clone'), total=filesize, unit=_(b'bytes')
707 )
712 )
708 progress.update(0)
713 progress.update(0)
709
714
710 vfsmap = _makemap(repo)
715 vfsmap = _makemap(repo)
711
716
712 with repo.transaction(b'clone'):
717 with repo.transaction(b'clone'):
713 ctxs = (vfs.backgroundclosing(repo.ui) for vfs in vfsmap.values())
718 ctxs = (vfs.backgroundclosing(repo.ui) for vfs in vfsmap.values())
714 with nested(*ctxs):
719 with nested(*ctxs):
715 for i in range(filecount):
720 for i in range(filecount):
716 src = util.readexactly(fp, 1)
721 src = util.readexactly(fp, 1)
717 vfs = vfsmap[src]
722 vfs = vfsmap[src]
718 namelen = util.uvarintdecodestream(fp)
723 namelen = util.uvarintdecodestream(fp)
719 datalen = util.uvarintdecodestream(fp)
724 datalen = util.uvarintdecodestream(fp)
720
725
721 name = util.readexactly(fp, namelen)
726 name = util.readexactly(fp, namelen)
722
727
723 if repo.ui.debugflag:
728 if repo.ui.debugflag:
724 repo.ui.debug(
729 repo.ui.debug(
725 b'adding [%s] %s (%s)\n'
730 b'adding [%s] %s (%s)\n'
726 % (src, name, util.bytecount(datalen))
731 % (src, name, util.bytecount(datalen))
727 )
732 )
728
733
729 with vfs(name, b'w') as ofp:
734 with vfs(name, b'w') as ofp:
730 for chunk in util.filechunkiter(fp, limit=datalen):
735 for chunk in util.filechunkiter(fp, limit=datalen):
731 progress.increment(step=len(chunk))
736 progress.increment(step=len(chunk))
732 ofp.write(chunk)
737 ofp.write(chunk)
733
738
734 # force @filecache properties to be reloaded from
739 # force @filecache properties to be reloaded from
735 # streamclone-ed file at next access
740 # streamclone-ed file at next access
736 repo.invalidate(clearfilecache=True)
741 repo.invalidate(clearfilecache=True)
737
742
738 elapsed = util.timer() - start
743 elapsed = util.timer() - start
739 if elapsed <= 0:
744 if elapsed <= 0:
740 elapsed = 0.001
745 elapsed = 0.001
741 repo.ui.status(
746 repo.ui.status(
742 _(b'transferred %s in %.1f seconds (%s/sec)\n')
747 _(b'transferred %s in %.1f seconds (%s/sec)\n')
743 % (
748 % (
744 util.bytecount(progress.pos),
749 util.bytecount(progress.pos),
745 elapsed,
750 elapsed,
746 util.bytecount(progress.pos / elapsed),
751 util.bytecount(progress.pos / elapsed),
747 )
752 )
748 )
753 )
749 progress.complete()
754 progress.complete()
750
755
751
756
752 def applybundlev2(repo, fp, filecount, filesize, requirements):
757 def applybundlev2(repo, fp, filecount, filesize, requirements):
753 from . import localrepo
758 from . import localrepo
754
759
755 missingreqs = [r for r in requirements if r not in repo.supported]
760 missingreqs = [r for r in requirements if r not in repo.supported]
756 if missingreqs:
761 if missingreqs:
757 raise error.Abort(
762 raise error.Abort(
758 _(b'unable to apply stream clone: unsupported format: %s')
763 _(b'unable to apply stream clone: unsupported format: %s')
759 % b', '.join(sorted(missingreqs))
764 % b', '.join(sorted(missingreqs))
760 )
765 )
761
766
762 consumev2(repo, fp, filecount, filesize)
767 consumev2(repo, fp, filecount, filesize)
763
768
764 # new requirements = old non-format requirements +
769 # new requirements = old non-format requirements +
765 # new format-related remote requirements
770 # new format-related remote requirements
766 # requirements from the streamed-in repository
771 # requirements from the streamed-in repository
767 repo.requirements = set(requirements) | (
772 repo.requirements = set(requirements) | (
768 repo.requirements - repo.supportedformats
773 repo.requirements - repo.supportedformats
769 )
774 )
770 repo.svfs.options = localrepo.resolvestorevfsoptions(
775 repo.svfs.options = localrepo.resolvestorevfsoptions(
771 repo.ui, repo.requirements, repo.features
776 repo.ui, repo.requirements, repo.features
772 )
777 )
773 scmutil.writereporequirements(repo)
778 scmutil.writereporequirements(repo)
779
780
781 def _copy_files(src_vfs_map, dst_vfs_map, entries, progress):
782 hardlink = [True]
783
784 def copy_used():
785 hardlink[0] = False
786 progress.topic = _(b'copying')
787
788 for k, path, size in entries:
789 src_vfs = src_vfs_map[k]
790 dst_vfs = dst_vfs_map[k]
791 src_path = src_vfs.join(path)
792 dst_path = dst_vfs.join(path)
793 dirname = dst_vfs.dirname(path)
794 if not dst_vfs.exists(dirname):
795 dst_vfs.makedirs(dirname)
796 dst_vfs.register_file(path)
797 # XXX we could use the #nb_bytes argument.
798 util.copyfile(
799 src_path,
800 dst_path,
801 hardlink=hardlink[0],
802 no_hardlink_cb=copy_used,
803 check_fs_hardlink=False,
804 )
805 progress.increment()
806 return hardlink[0]
807
808
809 def local_copy(src_repo, dest_repo):
810 """copy all content from one local repository to another
811
812 This is useful for local clone"""
813 src_store_requirements = {
814 r
815 for r in src_repo.requirements
816 if r not in requirementsmod.WORKING_DIR_REQUIREMENTS
817 }
818 dest_store_requirements = {
819 r
820 for r in dest_repo.requirements
821 if r not in requirementsmod.WORKING_DIR_REQUIREMENTS
822 }
823 assert src_store_requirements == dest_store_requirements
824
825 with dest_repo.lock():
826 with src_repo.lock():
827 entries, totalfilesize = _v2_walk(
828 src_repo,
829 includes=None,
830 excludes=None,
831 includeobsmarkers=True,
832 )
833 src_vfs_map = _makemap(src_repo)
834 dest_vfs_map = _makemap(dest_repo)
835 progress = src_repo.ui.makeprogress(
836 topic=_(b'linking'),
837 total=len(entries),
838 unit=_(b'files'),
839 )
840 # copy files
841 #
842 # We could copy the full file while the source repository is locked
843 # and the other one without the lock. However, in the linking case,
844 # this would also requires checks that nobody is appending any data
845 # to the files while we do the clone, so this is not done yet. We
846 # could do this blindly when copying files.
847 files = ((k, path, size) for k, path, ftype, size in entries)
848 hardlink = _copy_files(src_vfs_map, dest_vfs_map, files, progress)
849
850 # copy bookmarks over
851 src_book_vfs = bookmarks.bookmarksvfs(src_repo)
852 srcbookmarks = src_book_vfs.join(b'bookmarks')
853 dst_book_vfs = bookmarks.bookmarksvfs(dest_repo)
854 dstbookmarks = dst_book_vfs.join(b'bookmarks')
855 if os.path.exists(srcbookmarks):
856 util.copyfile(srcbookmarks, dstbookmarks)
857 progress.complete()
858 if hardlink:
859 msg = b'linked %d files\n'
860 else:
861 msg = b'copied %d files\n'
862 src_repo.ui.debug(msg % len(entries))
863
864 with dest_repo.transaction(b"localclone") as tr:
865 dest_repo.store.write(tr)
866
867 # clean up transaction file as they do not make sense
868 undo_files = [(dest_repo.svfs, b'undo.backupfiles')]
869 undo_files.extend(dest_repo.undofiles())
870 for undovfs, undofile in undo_files:
871 try:
872 undovfs.unlink(undofile)
873 except OSError as e:
874 if e.errno != errno.ENOENT:
875 msg = _(b'error removing %s: %s\n')
876 path = undovfs.join(undofile)
877 e_msg = stringutil.forcebytestr(e)
878 msg %= (path, e_msg)
879 dest_repo.ui.warn(msg)
@@ -1,1324 +1,1308 b''
1 #testcases sshv1 sshv2
1 #testcases sshv1 sshv2
2
2
3 #if sshv2
3 #if sshv2
4 $ cat >> $HGRCPATH << EOF
4 $ cat >> $HGRCPATH << EOF
5 > [experimental]
5 > [experimental]
6 > sshpeer.advertise-v2 = true
6 > sshpeer.advertise-v2 = true
7 > sshserver.support-v2 = true
7 > sshserver.support-v2 = true
8 > EOF
8 > EOF
9 #endif
9 #endif
10
10
11 Prepare repo a:
11 Prepare repo a:
12
12
13 $ hg init a
13 $ hg init a
14 $ cd a
14 $ cd a
15 $ echo a > a
15 $ echo a > a
16 $ hg add a
16 $ hg add a
17 $ hg commit -m test
17 $ hg commit -m test
18 $ echo first line > b
18 $ echo first line > b
19 $ hg add b
19 $ hg add b
20
20
21 Create a non-inlined filelog:
21 Create a non-inlined filelog:
22
22
23 $ "$PYTHON" -c 'open("data1", "wb").write(b"".join(b"%d\n" % x for x in range(10000)))'
23 $ "$PYTHON" -c 'open("data1", "wb").write(b"".join(b"%d\n" % x for x in range(10000)))'
24 $ for j in 0 1 2 3 4 5 6 7 8 9; do
24 $ for j in 0 1 2 3 4 5 6 7 8 9; do
25 > cat data1 >> b
25 > cat data1 >> b
26 > hg commit -m test
26 > hg commit -m test
27 > done
27 > done
28
28
29 List files in store/data (should show a 'b.d'):
29 List files in store/data (should show a 'b.d'):
30
30
31 #if reporevlogstore
31 #if reporevlogstore
32 $ for i in .hg/store/data/*; do
32 $ for i in .hg/store/data/*; do
33 > echo $i
33 > echo $i
34 > done
34 > done
35 .hg/store/data/a.i
35 .hg/store/data/a.i
36 .hg/store/data/b.d
36 .hg/store/data/b.d
37 .hg/store/data/b.i
37 .hg/store/data/b.i
38 #endif
38 #endif
39
39
40 Trigger branchcache creation:
40 Trigger branchcache creation:
41
41
42 $ hg branches
42 $ hg branches
43 default 10:a7949464abda
43 default 10:a7949464abda
44 $ ls .hg/cache
44 $ ls .hg/cache
45 branch2-served
45 branch2-served
46 rbc-names-v1
46 rbc-names-v1
47 rbc-revs-v1
47 rbc-revs-v1
48
48
49 Default operation:
49 Default operation:
50
50
51 $ hg clone . ../b
51 $ hg clone . ../b
52 updating to branch default
52 updating to branch default
53 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
53 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
54 $ cd ../b
54 $ cd ../b
55
55
56 Ensure branchcache got copied over:
56 Ensure branchcache got copied over:
57
57
58 $ ls .hg/cache
58 $ ls .hg/cache
59 branch2-base
59 branch2-base
60 branch2-immutable
60 branch2-immutable
61 branch2-served
61 branch2-served
62 branch2-served.hidden
62 branch2-served.hidden
63 branch2-visible
63 branch2-visible
64 branch2-visible-hidden
64 branch2-visible-hidden
65 rbc-names-v1
65 rbc-names-v1
66 rbc-revs-v1
66 rbc-revs-v1
67 tags2
67 tags2
68 tags2-served
68 tags2-served
69
69
70 $ cat a
70 $ cat a
71 a
71 a
72 $ hg verify
72 $ hg verify
73 checking changesets
73 checking changesets
74 checking manifests
74 checking manifests
75 crosschecking files in changesets and manifests
75 crosschecking files in changesets and manifests
76 checking files
76 checking files
77 checked 11 changesets with 11 changes to 2 files
77 checked 11 changesets with 11 changes to 2 files
78
78
79 Invalid dest '' must abort:
79 Invalid dest '' must abort:
80
80
81 $ hg clone . ''
81 $ hg clone . ''
82 abort: empty destination path is not valid
82 abort: empty destination path is not valid
83 [10]
83 [10]
84
84
85 No update, with debug option:
85 No update, with debug option:
86
86
87 #if hardlink
87 #if hardlink
88 $ hg --debug clone -U . ../c --config progress.debug=true
88 $ hg --debug clone -U . ../c --config progress.debug=true
89 linking: 1 files
89 linking: 1/15 files (6.67%)
90 linking: 2 files
90 linking: 2/15 files (13.33%)
91 linking: 3 files
91 linking: 3/15 files (20.00%)
92 linking: 4 files
92 linking: 4/15 files (26.67%)
93 linking: 5 files
93 linking: 5/15 files (33.33%)
94 linking: 6 files
94 linking: 6/15 files (40.00%)
95 linking: 7 files
95 linking: 7/15 files (46.67%)
96 linking: 8 files
96 linking: 8/15 files (53.33%)
97 linked 8 files (reporevlogstore !)
97 linking: 9/15 files (60.00%)
98 linking: 9 files (reposimplestore !)
98 linking: 10/15 files (66.67%)
99 linking: 10 files (reposimplestore !)
99 linking: 11/15 files (73.33%)
100 linking: 11 files (reposimplestore !)
100 linking: 12/15 files (80.00%)
101 linking: 12 files (reposimplestore !)
101 linking: 13/15 files (86.67%)
102 linking: 13 files (reposimplestore !)
102 linking: 14/15 files (93.33%)
103 linking: 14 files (reposimplestore !)
103 linking: 15/15 files (100.00%)
104 linking: 15 files (reposimplestore !)
104 linked 15 files
105 linking: 16 files (reposimplestore !)
106 linking: 17 files (reposimplestore !)
107 linking: 18 files (reposimplestore !)
108 linked 18 files (reposimplestore !)
109 updating the branch cache
105 updating the branch cache
110 #else
106 #else
111 $ hg --debug clone -U . ../c --config progress.debug=true
107 $ hg --debug clone -U . ../c --config progress.debug=true
112 linking: 1 files
108 linking: 1 files
113 copying: 2 files
109 copying: 2 files
114 copying: 3 files
110 copying: 3 files
115 copying: 4 files
111 copying: 4 files
116 copying: 5 files
112 copying: 5 files
117 copying: 6 files
113 copying: 6 files
118 copying: 7 files
114 copying: 7 files
119 copying: 8 files
115 copying: 8 files
120 copied 8 files (reporevlogstore !)
121 copying: 9 files (reposimplestore !)
122 copying: 10 files (reposimplestore !)
123 copying: 11 files (reposimplestore !)
124 copying: 12 files (reposimplestore !)
125 copying: 13 files (reposimplestore !)
126 copying: 14 files (reposimplestore !)
127 copying: 15 files (reposimplestore !)
128 copying: 16 files (reposimplestore !)
129 copying: 17 files (reposimplestore !)
130 copying: 18 files (reposimplestore !)
131 copied 18 files (reposimplestore !)
132 #endif
116 #endif
133 $ cd ../c
117 $ cd ../c
134
118
135 Ensure branchcache got copied over:
119 Ensure branchcache got copied over:
136
120
137 $ ls .hg/cache
121 $ ls .hg/cache
138 branch2-base
122 branch2-base
139 branch2-immutable
123 branch2-immutable
140 branch2-served
124 branch2-served
141 branch2-served.hidden
125 branch2-served.hidden
142 branch2-visible
126 branch2-visible
143 branch2-visible-hidden
127 branch2-visible-hidden
144 rbc-names-v1
128 rbc-names-v1
145 rbc-revs-v1
129 rbc-revs-v1
146 tags2
130 tags2
147 tags2-served
131 tags2-served
148
132
149 $ cat a 2>/dev/null || echo "a not present"
133 $ cat a 2>/dev/null || echo "a not present"
150 a not present
134 a not present
151 $ hg verify
135 $ hg verify
152 checking changesets
136 checking changesets
153 checking manifests
137 checking manifests
154 crosschecking files in changesets and manifests
138 crosschecking files in changesets and manifests
155 checking files
139 checking files
156 checked 11 changesets with 11 changes to 2 files
140 checked 11 changesets with 11 changes to 2 files
157
141
158 Default destination:
142 Default destination:
159
143
160 $ mkdir ../d
144 $ mkdir ../d
161 $ cd ../d
145 $ cd ../d
162 $ hg clone ../a
146 $ hg clone ../a
163 destination directory: a
147 destination directory: a
164 updating to branch default
148 updating to branch default
165 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
149 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
166 $ cd a
150 $ cd a
167 $ hg cat a
151 $ hg cat a
168 a
152 a
169 $ cd ../..
153 $ cd ../..
170
154
171 Check that we drop the 'file:' from the path before writing the .hgrc:
155 Check that we drop the 'file:' from the path before writing the .hgrc:
172
156
173 $ hg clone file:a e
157 $ hg clone file:a e
174 updating to branch default
158 updating to branch default
175 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
159 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
176 $ grep 'file:' e/.hg/hgrc
160 $ grep 'file:' e/.hg/hgrc
177 [1]
161 [1]
178
162
179 Check that path aliases are expanded:
163 Check that path aliases are expanded:
180
164
181 $ hg clone -q -U --config 'paths.foobar=a#0' foobar f
165 $ hg clone -q -U --config 'paths.foobar=a#0' foobar f
182 $ hg -R f showconfig paths.default
166 $ hg -R f showconfig paths.default
183 $TESTTMP/a#0
167 $TESTTMP/a#0
184
168
185 Use --pull:
169 Use --pull:
186
170
187 $ hg clone --pull a g
171 $ hg clone --pull a g
188 requesting all changes
172 requesting all changes
189 adding changesets
173 adding changesets
190 adding manifests
174 adding manifests
191 adding file changes
175 adding file changes
192 added 11 changesets with 11 changes to 2 files
176 added 11 changesets with 11 changes to 2 files
193 new changesets acb14030fe0a:a7949464abda
177 new changesets acb14030fe0a:a7949464abda
194 updating to branch default
178 updating to branch default
195 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
179 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
196 $ hg -R g verify
180 $ hg -R g verify
197 checking changesets
181 checking changesets
198 checking manifests
182 checking manifests
199 crosschecking files in changesets and manifests
183 crosschecking files in changesets and manifests
200 checking files
184 checking files
201 checked 11 changesets with 11 changes to 2 files
185 checked 11 changesets with 11 changes to 2 files
202
186
203 Invalid dest '' with --pull must abort (issue2528):
187 Invalid dest '' with --pull must abort (issue2528):
204
188
205 $ hg clone --pull a ''
189 $ hg clone --pull a ''
206 abort: empty destination path is not valid
190 abort: empty destination path is not valid
207 [10]
191 [10]
208
192
209 Clone to '.':
193 Clone to '.':
210
194
211 $ mkdir h
195 $ mkdir h
212 $ cd h
196 $ cd h
213 $ hg clone ../a .
197 $ hg clone ../a .
214 updating to branch default
198 updating to branch default
215 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
199 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
216 $ cd ..
200 $ cd ..
217
201
218
202
219 *** Tests for option -u ***
203 *** Tests for option -u ***
220
204
221 Adding some more history to repo a:
205 Adding some more history to repo a:
222
206
223 $ cd a
207 $ cd a
224 $ hg tag ref1
208 $ hg tag ref1
225 $ echo the quick brown fox >a
209 $ echo the quick brown fox >a
226 $ hg ci -m "hacked default"
210 $ hg ci -m "hacked default"
227 $ hg up ref1
211 $ hg up ref1
228 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
212 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
229 $ hg branch stable
213 $ hg branch stable
230 marked working directory as branch stable
214 marked working directory as branch stable
231 (branches are permanent and global, did you want a bookmark?)
215 (branches are permanent and global, did you want a bookmark?)
232 $ echo some text >a
216 $ echo some text >a
233 $ hg ci -m "starting branch stable"
217 $ hg ci -m "starting branch stable"
234 $ hg tag ref2
218 $ hg tag ref2
235 $ echo some more text >a
219 $ echo some more text >a
236 $ hg ci -m "another change for branch stable"
220 $ hg ci -m "another change for branch stable"
237 $ hg up ref2
221 $ hg up ref2
238 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
222 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
239 $ hg parents
223 $ hg parents
240 changeset: 13:e8ece76546a6
224 changeset: 13:e8ece76546a6
241 branch: stable
225 branch: stable
242 tag: ref2
226 tag: ref2
243 parent: 10:a7949464abda
227 parent: 10:a7949464abda
244 user: test
228 user: test
245 date: Thu Jan 01 00:00:00 1970 +0000
229 date: Thu Jan 01 00:00:00 1970 +0000
246 summary: starting branch stable
230 summary: starting branch stable
247
231
248
232
249 Repo a has two heads:
233 Repo a has two heads:
250
234
251 $ hg heads
235 $ hg heads
252 changeset: 15:0aae7cf88f0d
236 changeset: 15:0aae7cf88f0d
253 branch: stable
237 branch: stable
254 tag: tip
238 tag: tip
255 user: test
239 user: test
256 date: Thu Jan 01 00:00:00 1970 +0000
240 date: Thu Jan 01 00:00:00 1970 +0000
257 summary: another change for branch stable
241 summary: another change for branch stable
258
242
259 changeset: 12:f21241060d6a
243 changeset: 12:f21241060d6a
260 user: test
244 user: test
261 date: Thu Jan 01 00:00:00 1970 +0000
245 date: Thu Jan 01 00:00:00 1970 +0000
262 summary: hacked default
246 summary: hacked default
263
247
264
248
265 $ cd ..
249 $ cd ..
266
250
267
251
268 Testing --noupdate with --updaterev (must abort):
252 Testing --noupdate with --updaterev (must abort):
269
253
270 $ hg clone --noupdate --updaterev 1 a ua
254 $ hg clone --noupdate --updaterev 1 a ua
271 abort: cannot specify both --noupdate and --updaterev
255 abort: cannot specify both --noupdate and --updaterev
272 [10]
256 [10]
273
257
274
258
275 Testing clone -u:
259 Testing clone -u:
276
260
277 $ hg clone -u . a ua
261 $ hg clone -u . a ua
278 updating to branch stable
262 updating to branch stable
279 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
280
264
281 Repo ua has both heads:
265 Repo ua has both heads:
282
266
283 $ hg -R ua heads
267 $ hg -R ua heads
284 changeset: 15:0aae7cf88f0d
268 changeset: 15:0aae7cf88f0d
285 branch: stable
269 branch: stable
286 tag: tip
270 tag: tip
287 user: test
271 user: test
288 date: Thu Jan 01 00:00:00 1970 +0000
272 date: Thu Jan 01 00:00:00 1970 +0000
289 summary: another change for branch stable
273 summary: another change for branch stable
290
274
291 changeset: 12:f21241060d6a
275 changeset: 12:f21241060d6a
292 user: test
276 user: test
293 date: Thu Jan 01 00:00:00 1970 +0000
277 date: Thu Jan 01 00:00:00 1970 +0000
294 summary: hacked default
278 summary: hacked default
295
279
296
280
297 Same revision checked out in repo a and ua:
281 Same revision checked out in repo a and ua:
298
282
299 $ hg -R a parents --template "{node|short}\n"
283 $ hg -R a parents --template "{node|short}\n"
300 e8ece76546a6
284 e8ece76546a6
301 $ hg -R ua parents --template "{node|short}\n"
285 $ hg -R ua parents --template "{node|short}\n"
302 e8ece76546a6
286 e8ece76546a6
303
287
304 $ rm -r ua
288 $ rm -r ua
305
289
306
290
307 Testing clone --pull -u:
291 Testing clone --pull -u:
308
292
309 $ hg clone --pull -u . a ua
293 $ hg clone --pull -u . a ua
310 requesting all changes
294 requesting all changes
311 adding changesets
295 adding changesets
312 adding manifests
296 adding manifests
313 adding file changes
297 adding file changes
314 added 16 changesets with 16 changes to 3 files (+1 heads)
298 added 16 changesets with 16 changes to 3 files (+1 heads)
315 new changesets acb14030fe0a:0aae7cf88f0d
299 new changesets acb14030fe0a:0aae7cf88f0d
316 updating to branch stable
300 updating to branch stable
317 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
301 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
318
302
319 Repo ua has both heads:
303 Repo ua has both heads:
320
304
321 $ hg -R ua heads
305 $ hg -R ua heads
322 changeset: 15:0aae7cf88f0d
306 changeset: 15:0aae7cf88f0d
323 branch: stable
307 branch: stable
324 tag: tip
308 tag: tip
325 user: test
309 user: test
326 date: Thu Jan 01 00:00:00 1970 +0000
310 date: Thu Jan 01 00:00:00 1970 +0000
327 summary: another change for branch stable
311 summary: another change for branch stable
328
312
329 changeset: 12:f21241060d6a
313 changeset: 12:f21241060d6a
330 user: test
314 user: test
331 date: Thu Jan 01 00:00:00 1970 +0000
315 date: Thu Jan 01 00:00:00 1970 +0000
332 summary: hacked default
316 summary: hacked default
333
317
334
318
335 Same revision checked out in repo a and ua:
319 Same revision checked out in repo a and ua:
336
320
337 $ hg -R a parents --template "{node|short}\n"
321 $ hg -R a parents --template "{node|short}\n"
338 e8ece76546a6
322 e8ece76546a6
339 $ hg -R ua parents --template "{node|short}\n"
323 $ hg -R ua parents --template "{node|short}\n"
340 e8ece76546a6
324 e8ece76546a6
341
325
342 $ rm -r ua
326 $ rm -r ua
343
327
344
328
345 Testing clone -u <branch>:
329 Testing clone -u <branch>:
346
330
347 $ hg clone -u stable a ua
331 $ hg clone -u stable a ua
348 updating to branch stable
332 updating to branch stable
349 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
333 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
350
334
351 Repo ua has both heads:
335 Repo ua has both heads:
352
336
353 $ hg -R ua heads
337 $ hg -R ua heads
354 changeset: 15:0aae7cf88f0d
338 changeset: 15:0aae7cf88f0d
355 branch: stable
339 branch: stable
356 tag: tip
340 tag: tip
357 user: test
341 user: test
358 date: Thu Jan 01 00:00:00 1970 +0000
342 date: Thu Jan 01 00:00:00 1970 +0000
359 summary: another change for branch stable
343 summary: another change for branch stable
360
344
361 changeset: 12:f21241060d6a
345 changeset: 12:f21241060d6a
362 user: test
346 user: test
363 date: Thu Jan 01 00:00:00 1970 +0000
347 date: Thu Jan 01 00:00:00 1970 +0000
364 summary: hacked default
348 summary: hacked default
365
349
366
350
367 Branch 'stable' is checked out:
351 Branch 'stable' is checked out:
368
352
369 $ hg -R ua parents
353 $ hg -R ua parents
370 changeset: 15:0aae7cf88f0d
354 changeset: 15:0aae7cf88f0d
371 branch: stable
355 branch: stable
372 tag: tip
356 tag: tip
373 user: test
357 user: test
374 date: Thu Jan 01 00:00:00 1970 +0000
358 date: Thu Jan 01 00:00:00 1970 +0000
375 summary: another change for branch stable
359 summary: another change for branch stable
376
360
377
361
378 $ rm -r ua
362 $ rm -r ua
379
363
380
364
381 Testing default checkout:
365 Testing default checkout:
382
366
383 $ hg clone a ua
367 $ hg clone a ua
384 updating to branch default
368 updating to branch default
385 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
369 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
386
370
387 Repo ua has both heads:
371 Repo ua has both heads:
388
372
389 $ hg -R ua heads
373 $ hg -R ua heads
390 changeset: 15:0aae7cf88f0d
374 changeset: 15:0aae7cf88f0d
391 branch: stable
375 branch: stable
392 tag: tip
376 tag: tip
393 user: test
377 user: test
394 date: Thu Jan 01 00:00:00 1970 +0000
378 date: Thu Jan 01 00:00:00 1970 +0000
395 summary: another change for branch stable
379 summary: another change for branch stable
396
380
397 changeset: 12:f21241060d6a
381 changeset: 12:f21241060d6a
398 user: test
382 user: test
399 date: Thu Jan 01 00:00:00 1970 +0000
383 date: Thu Jan 01 00:00:00 1970 +0000
400 summary: hacked default
384 summary: hacked default
401
385
402
386
403 Branch 'default' is checked out:
387 Branch 'default' is checked out:
404
388
405 $ hg -R ua parents
389 $ hg -R ua parents
406 changeset: 12:f21241060d6a
390 changeset: 12:f21241060d6a
407 user: test
391 user: test
408 date: Thu Jan 01 00:00:00 1970 +0000
392 date: Thu Jan 01 00:00:00 1970 +0000
409 summary: hacked default
393 summary: hacked default
410
394
411 Test clone with a branch named "@" (issue3677)
395 Test clone with a branch named "@" (issue3677)
412
396
413 $ hg -R ua branch @
397 $ hg -R ua branch @
414 marked working directory as branch @
398 marked working directory as branch @
415 $ hg -R ua commit -m 'created branch @'
399 $ hg -R ua commit -m 'created branch @'
416 $ hg clone ua atbranch
400 $ hg clone ua atbranch
417 updating to branch default
401 updating to branch default
418 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
402 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
419 $ hg -R atbranch heads
403 $ hg -R atbranch heads
420 changeset: 16:798b6d97153e
404 changeset: 16:798b6d97153e
421 branch: @
405 branch: @
422 tag: tip
406 tag: tip
423 parent: 12:f21241060d6a
407 parent: 12:f21241060d6a
424 user: test
408 user: test
425 date: Thu Jan 01 00:00:00 1970 +0000
409 date: Thu Jan 01 00:00:00 1970 +0000
426 summary: created branch @
410 summary: created branch @
427
411
428 changeset: 15:0aae7cf88f0d
412 changeset: 15:0aae7cf88f0d
429 branch: stable
413 branch: stable
430 user: test
414 user: test
431 date: Thu Jan 01 00:00:00 1970 +0000
415 date: Thu Jan 01 00:00:00 1970 +0000
432 summary: another change for branch stable
416 summary: another change for branch stable
433
417
434 changeset: 12:f21241060d6a
418 changeset: 12:f21241060d6a
435 user: test
419 user: test
436 date: Thu Jan 01 00:00:00 1970 +0000
420 date: Thu Jan 01 00:00:00 1970 +0000
437 summary: hacked default
421 summary: hacked default
438
422
439 $ hg -R atbranch parents
423 $ hg -R atbranch parents
440 changeset: 12:f21241060d6a
424 changeset: 12:f21241060d6a
441 user: test
425 user: test
442 date: Thu Jan 01 00:00:00 1970 +0000
426 date: Thu Jan 01 00:00:00 1970 +0000
443 summary: hacked default
427 summary: hacked default
444
428
445
429
446 $ rm -r ua atbranch
430 $ rm -r ua atbranch
447
431
448
432
449 Testing #<branch>:
433 Testing #<branch>:
450
434
451 $ hg clone -u . a#stable ua
435 $ hg clone -u . a#stable ua
452 adding changesets
436 adding changesets
453 adding manifests
437 adding manifests
454 adding file changes
438 adding file changes
455 added 14 changesets with 14 changes to 3 files
439 added 14 changesets with 14 changes to 3 files
456 new changesets acb14030fe0a:0aae7cf88f0d
440 new changesets acb14030fe0a:0aae7cf88f0d
457 updating to branch stable
441 updating to branch stable
458 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
442 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
459
443
460 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
444 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
461
445
462 $ hg -R ua heads
446 $ hg -R ua heads
463 changeset: 13:0aae7cf88f0d
447 changeset: 13:0aae7cf88f0d
464 branch: stable
448 branch: stable
465 tag: tip
449 tag: tip
466 user: test
450 user: test
467 date: Thu Jan 01 00:00:00 1970 +0000
451 date: Thu Jan 01 00:00:00 1970 +0000
468 summary: another change for branch stable
452 summary: another change for branch stable
469
453
470 changeset: 10:a7949464abda
454 changeset: 10:a7949464abda
471 user: test
455 user: test
472 date: Thu Jan 01 00:00:00 1970 +0000
456 date: Thu Jan 01 00:00:00 1970 +0000
473 summary: test
457 summary: test
474
458
475
459
476 Same revision checked out in repo a and ua:
460 Same revision checked out in repo a and ua:
477
461
478 $ hg -R a parents --template "{node|short}\n"
462 $ hg -R a parents --template "{node|short}\n"
479 e8ece76546a6
463 e8ece76546a6
480 $ hg -R ua parents --template "{node|short}\n"
464 $ hg -R ua parents --template "{node|short}\n"
481 e8ece76546a6
465 e8ece76546a6
482
466
483 $ rm -r ua
467 $ rm -r ua
484
468
485
469
486 Testing -u -r <branch>:
470 Testing -u -r <branch>:
487
471
488 $ hg clone -u . -r stable a ua
472 $ hg clone -u . -r stable a ua
489 adding changesets
473 adding changesets
490 adding manifests
474 adding manifests
491 adding file changes
475 adding file changes
492 added 14 changesets with 14 changes to 3 files
476 added 14 changesets with 14 changes to 3 files
493 new changesets acb14030fe0a:0aae7cf88f0d
477 new changesets acb14030fe0a:0aae7cf88f0d
494 updating to branch stable
478 updating to branch stable
495 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
479 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
496
480
497 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
481 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
498
482
499 $ hg -R ua heads
483 $ hg -R ua heads
500 changeset: 13:0aae7cf88f0d
484 changeset: 13:0aae7cf88f0d
501 branch: stable
485 branch: stable
502 tag: tip
486 tag: tip
503 user: test
487 user: test
504 date: Thu Jan 01 00:00:00 1970 +0000
488 date: Thu Jan 01 00:00:00 1970 +0000
505 summary: another change for branch stable
489 summary: another change for branch stable
506
490
507 changeset: 10:a7949464abda
491 changeset: 10:a7949464abda
508 user: test
492 user: test
509 date: Thu Jan 01 00:00:00 1970 +0000
493 date: Thu Jan 01 00:00:00 1970 +0000
510 summary: test
494 summary: test
511
495
512
496
513 Same revision checked out in repo a and ua:
497 Same revision checked out in repo a and ua:
514
498
515 $ hg -R a parents --template "{node|short}\n"
499 $ hg -R a parents --template "{node|short}\n"
516 e8ece76546a6
500 e8ece76546a6
517 $ hg -R ua parents --template "{node|short}\n"
501 $ hg -R ua parents --template "{node|short}\n"
518 e8ece76546a6
502 e8ece76546a6
519
503
520 $ rm -r ua
504 $ rm -r ua
521
505
522
506
523 Testing -r <branch>:
507 Testing -r <branch>:
524
508
525 $ hg clone -r stable a ua
509 $ hg clone -r stable a ua
526 adding changesets
510 adding changesets
527 adding manifests
511 adding manifests
528 adding file changes
512 adding file changes
529 added 14 changesets with 14 changes to 3 files
513 added 14 changesets with 14 changes to 3 files
530 new changesets acb14030fe0a:0aae7cf88f0d
514 new changesets acb14030fe0a:0aae7cf88f0d
531 updating to branch stable
515 updating to branch stable
532 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
516 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
533
517
534 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
518 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
535
519
536 $ hg -R ua heads
520 $ hg -R ua heads
537 changeset: 13:0aae7cf88f0d
521 changeset: 13:0aae7cf88f0d
538 branch: stable
522 branch: stable
539 tag: tip
523 tag: tip
540 user: test
524 user: test
541 date: Thu Jan 01 00:00:00 1970 +0000
525 date: Thu Jan 01 00:00:00 1970 +0000
542 summary: another change for branch stable
526 summary: another change for branch stable
543
527
544 changeset: 10:a7949464abda
528 changeset: 10:a7949464abda
545 user: test
529 user: test
546 date: Thu Jan 01 00:00:00 1970 +0000
530 date: Thu Jan 01 00:00:00 1970 +0000
547 summary: test
531 summary: test
548
532
549
533
550 Branch 'stable' is checked out:
534 Branch 'stable' is checked out:
551
535
552 $ hg -R ua parents
536 $ hg -R ua parents
553 changeset: 13:0aae7cf88f0d
537 changeset: 13:0aae7cf88f0d
554 branch: stable
538 branch: stable
555 tag: tip
539 tag: tip
556 user: test
540 user: test
557 date: Thu Jan 01 00:00:00 1970 +0000
541 date: Thu Jan 01 00:00:00 1970 +0000
558 summary: another change for branch stable
542 summary: another change for branch stable
559
543
560
544
561 $ rm -r ua
545 $ rm -r ua
562
546
563
547
564 Issue2267: Error in 1.6 hg.py: TypeError: 'NoneType' object is not
548 Issue2267: Error in 1.6 hg.py: TypeError: 'NoneType' object is not
565 iterable in addbranchrevs()
549 iterable in addbranchrevs()
566
550
567 $ cat <<EOF > simpleclone.py
551 $ cat <<EOF > simpleclone.py
568 > from mercurial import hg, ui as uimod
552 > from mercurial import hg, ui as uimod
569 > myui = uimod.ui.load()
553 > myui = uimod.ui.load()
570 > repo = hg.repository(myui, b'a')
554 > repo = hg.repository(myui, b'a')
571 > hg.clone(myui, {}, repo, dest=b"ua")
555 > hg.clone(myui, {}, repo, dest=b"ua")
572 > EOF
556 > EOF
573
557
574 $ "$PYTHON" simpleclone.py
558 $ "$PYTHON" simpleclone.py
575 updating to branch default
559 updating to branch default
576 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
560 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
577
561
578 $ rm -r ua
562 $ rm -r ua
579
563
580 $ cat <<EOF > branchclone.py
564 $ cat <<EOF > branchclone.py
581 > from mercurial import extensions, hg, ui as uimod
565 > from mercurial import extensions, hg, ui as uimod
582 > myui = uimod.ui.load()
566 > myui = uimod.ui.load()
583 > extensions.loadall(myui)
567 > extensions.loadall(myui)
584 > extensions.populateui(myui)
568 > extensions.populateui(myui)
585 > repo = hg.repository(myui, b'a')
569 > repo = hg.repository(myui, b'a')
586 > hg.clone(myui, {}, repo, dest=b"ua", branch=[b"stable"])
570 > hg.clone(myui, {}, repo, dest=b"ua", branch=[b"stable"])
587 > EOF
571 > EOF
588
572
589 $ "$PYTHON" branchclone.py
573 $ "$PYTHON" branchclone.py
590 adding changesets
574 adding changesets
591 adding manifests
575 adding manifests
592 adding file changes
576 adding file changes
593 added 14 changesets with 14 changes to 3 files
577 added 14 changesets with 14 changes to 3 files
594 new changesets acb14030fe0a:0aae7cf88f0d
578 new changesets acb14030fe0a:0aae7cf88f0d
595 updating to branch stable
579 updating to branch stable
596 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
580 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
597 $ rm -r ua
581 $ rm -r ua
598
582
599
583
600 Test clone with special '@' bookmark:
584 Test clone with special '@' bookmark:
601 $ cd a
585 $ cd a
602 $ hg bookmark -r a7949464abda @ # branch point of stable from default
586 $ hg bookmark -r a7949464abda @ # branch point of stable from default
603 $ hg clone . ../i
587 $ hg clone . ../i
604 updating to bookmark @
588 updating to bookmark @
605 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
589 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
606 $ hg id -i ../i
590 $ hg id -i ../i
607 a7949464abda
591 a7949464abda
608 $ rm -r ../i
592 $ rm -r ../i
609
593
610 $ hg bookmark -f -r stable @
594 $ hg bookmark -f -r stable @
611 $ hg bookmarks
595 $ hg bookmarks
612 @ 15:0aae7cf88f0d
596 @ 15:0aae7cf88f0d
613 $ hg clone . ../i
597 $ hg clone . ../i
614 updating to bookmark @ on branch stable
598 updating to bookmark @ on branch stable
615 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
599 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
616 $ hg id -i ../i
600 $ hg id -i ../i
617 0aae7cf88f0d
601 0aae7cf88f0d
618 $ cd "$TESTTMP"
602 $ cd "$TESTTMP"
619
603
620
604
621 Testing failures:
605 Testing failures:
622
606
623 $ mkdir fail
607 $ mkdir fail
624 $ cd fail
608 $ cd fail
625
609
626 No local source
610 No local source
627
611
628 $ hg clone a b
612 $ hg clone a b
629 abort: repository a not found
613 abort: repository a not found
630 [255]
614 [255]
631
615
632 Invalid URL
616 Invalid URL
633
617
634 $ hg clone http://invalid:url/a b
618 $ hg clone http://invalid:url/a b
635 abort: error: nonnumeric port: 'url'
619 abort: error: nonnumeric port: 'url'
636 [100]
620 [100]
637
621
638 No remote source
622 No remote source
639
623
640 #if windows
624 #if windows
641 $ hg clone http://$LOCALIP:3121/a b
625 $ hg clone http://$LOCALIP:3121/a b
642 abort: error: * (glob)
626 abort: error: * (glob)
643 [100]
627 [100]
644 #else
628 #else
645 $ hg clone http://$LOCALIP:3121/a b
629 $ hg clone http://$LOCALIP:3121/a b
646 abort: error: *refused* (glob)
630 abort: error: *refused* (glob)
647 [100]
631 [100]
648 #endif
632 #endif
649 $ rm -rf b # work around bug with http clone
633 $ rm -rf b # work around bug with http clone
650
634
651
635
652 #if unix-permissions no-root
636 #if unix-permissions no-root
653
637
654 Inaccessible source
638 Inaccessible source
655
639
656 $ mkdir a
640 $ mkdir a
657 $ chmod 000 a
641 $ chmod 000 a
658 $ hg clone a b
642 $ hg clone a b
659 abort: Permission denied: *$TESTTMP/fail/a/.hg* (glob)
643 abort: Permission denied: *$TESTTMP/fail/a/.hg* (glob)
660 [255]
644 [255]
661
645
662 Inaccessible destination
646 Inaccessible destination
663
647
664 $ hg init b
648 $ hg init b
665 $ cd b
649 $ cd b
666 $ hg clone . ../a
650 $ hg clone . ../a
667 abort: Permission denied: *../a* (glob)
651 abort: Permission denied: *../a* (glob)
668 [255]
652 [255]
669 $ cd ..
653 $ cd ..
670 $ chmod 700 a
654 $ chmod 700 a
671 $ rm -r a b
655 $ rm -r a b
672
656
673 #endif
657 #endif
674
658
675
659
676 #if fifo
660 #if fifo
677
661
678 Source of wrong type
662 Source of wrong type
679
663
680 $ mkfifo a
664 $ mkfifo a
681 $ hg clone a b
665 $ hg clone a b
682 abort: $ENOTDIR$: *$TESTTMP/fail/a/.hg* (glob)
666 abort: $ENOTDIR$: *$TESTTMP/fail/a/.hg* (glob)
683 [255]
667 [255]
684 $ rm a
668 $ rm a
685
669
686 #endif
670 #endif
687
671
688 Default destination, same directory
672 Default destination, same directory
689
673
690 $ hg init q
674 $ hg init q
691 $ hg clone q
675 $ hg clone q
692 destination directory: q
676 destination directory: q
693 abort: destination 'q' is not empty
677 abort: destination 'q' is not empty
694 [10]
678 [10]
695
679
696 destination directory not empty
680 destination directory not empty
697
681
698 $ mkdir a
682 $ mkdir a
699 $ echo stuff > a/a
683 $ echo stuff > a/a
700 $ hg clone q a
684 $ hg clone q a
701 abort: destination 'a' is not empty
685 abort: destination 'a' is not empty
702 [10]
686 [10]
703
687
704
688
705 #if unix-permissions no-root
689 #if unix-permissions no-root
706
690
707 leave existing directory in place after clone failure
691 leave existing directory in place after clone failure
708
692
709 $ hg init c
693 $ hg init c
710 $ cd c
694 $ cd c
711 $ echo c > c
695 $ echo c > c
712 $ hg commit -A -m test
696 $ hg commit -A -m test
713 adding c
697 adding c
714 $ chmod -rx .hg/store/data
698 $ chmod -rx .hg/store/data
715 $ cd ..
699 $ cd ..
716 $ mkdir d
700 $ mkdir d
717 $ hg clone c d 2> err
701 $ hg clone c d 2> err
718 [255]
702 [255]
719 $ test -d d
703 $ test -d d
720 $ test -d d/.hg
704 $ test -d d/.hg
721 [1]
705 [1]
722
706
723 re-enable perm to allow deletion
707 re-enable perm to allow deletion
724
708
725 $ chmod +rx c/.hg/store/data
709 $ chmod +rx c/.hg/store/data
726
710
727 #endif
711 #endif
728
712
729 $ cd ..
713 $ cd ..
730
714
731 Test clone from the repository in (emulated) revlog format 0 (issue4203):
715 Test clone from the repository in (emulated) revlog format 0 (issue4203):
732
716
733 $ mkdir issue4203
717 $ mkdir issue4203
734 $ mkdir -p src/.hg
718 $ mkdir -p src/.hg
735 $ echo foo > src/foo
719 $ echo foo > src/foo
736 $ hg -R src add src/foo
720 $ hg -R src add src/foo
737 $ hg -R src commit -m '#0'
721 $ hg -R src commit -m '#0'
738 $ hg -R src log -q
722 $ hg -R src log -q
739 0:e1bab28bca43
723 0:e1bab28bca43
740 $ hg -R src debugrevlog -c | egrep 'format|flags'
724 $ hg -R src debugrevlog -c | egrep 'format|flags'
741 format : 0
725 format : 0
742 flags : (none)
726 flags : (none)
743 $ hg root -R src -T json | sed 's|\\\\|\\|g'
727 $ hg root -R src -T json | sed 's|\\\\|\\|g'
744 [
728 [
745 {
729 {
746 "hgpath": "$TESTTMP/src/.hg",
730 "hgpath": "$TESTTMP/src/.hg",
747 "reporoot": "$TESTTMP/src",
731 "reporoot": "$TESTTMP/src",
748 "storepath": "$TESTTMP/src/.hg"
732 "storepath": "$TESTTMP/src/.hg"
749 }
733 }
750 ]
734 ]
751 $ hg clone -U -q src dst
735 $ hg clone -U -q src dst
752 $ hg -R dst log -q
736 $ hg -R dst log -q
753 0:e1bab28bca43
737 0:e1bab28bca43
754
738
755 Create repositories to test auto sharing functionality
739 Create repositories to test auto sharing functionality
756
740
757 $ cat >> $HGRCPATH << EOF
741 $ cat >> $HGRCPATH << EOF
758 > [extensions]
742 > [extensions]
759 > share=
743 > share=
760 > EOF
744 > EOF
761
745
762 $ hg init empty
746 $ hg init empty
763 $ hg init source1a
747 $ hg init source1a
764 $ cd source1a
748 $ cd source1a
765 $ echo initial1 > foo
749 $ echo initial1 > foo
766 $ hg -q commit -A -m initial
750 $ hg -q commit -A -m initial
767 $ echo second > foo
751 $ echo second > foo
768 $ hg commit -m second
752 $ hg commit -m second
769 $ cd ..
753 $ cd ..
770
754
771 $ hg init filteredrev0
755 $ hg init filteredrev0
772 $ cd filteredrev0
756 $ cd filteredrev0
773 $ cat >> .hg/hgrc << EOF
757 $ cat >> .hg/hgrc << EOF
774 > [experimental]
758 > [experimental]
775 > evolution.createmarkers=True
759 > evolution.createmarkers=True
776 > EOF
760 > EOF
777 $ echo initial1 > foo
761 $ echo initial1 > foo
778 $ hg -q commit -A -m initial0
762 $ hg -q commit -A -m initial0
779 $ hg -q up -r null
763 $ hg -q up -r null
780 $ echo initial2 > foo
764 $ echo initial2 > foo
781 $ hg -q commit -A -m initial1
765 $ hg -q commit -A -m initial1
782 $ hg debugobsolete c05d5c47a5cf81401869999f3d05f7d699d2b29a e082c1832e09a7d1e78b7fd49a592d372de854c8
766 $ hg debugobsolete c05d5c47a5cf81401869999f3d05f7d699d2b29a e082c1832e09a7d1e78b7fd49a592d372de854c8
783 1 new obsolescence markers
767 1 new obsolescence markers
784 obsoleted 1 changesets
768 obsoleted 1 changesets
785 $ cd ..
769 $ cd ..
786
770
787 $ hg -q clone --pull source1a source1b
771 $ hg -q clone --pull source1a source1b
788 $ cd source1a
772 $ cd source1a
789 $ hg bookmark bookA
773 $ hg bookmark bookA
790 $ echo 1a > foo
774 $ echo 1a > foo
791 $ hg commit -m 1a
775 $ hg commit -m 1a
792 $ cd ../source1b
776 $ cd ../source1b
793 $ hg -q up -r 0
777 $ hg -q up -r 0
794 $ echo head1 > foo
778 $ echo head1 > foo
795 $ hg commit -m head1
779 $ hg commit -m head1
796 created new head
780 created new head
797 $ hg bookmark head1
781 $ hg bookmark head1
798 $ hg -q up -r 0
782 $ hg -q up -r 0
799 $ echo head2 > foo
783 $ echo head2 > foo
800 $ hg commit -m head2
784 $ hg commit -m head2
801 created new head
785 created new head
802 $ hg bookmark head2
786 $ hg bookmark head2
803 $ hg -q up -r 0
787 $ hg -q up -r 0
804 $ hg branch branch1
788 $ hg branch branch1
805 marked working directory as branch branch1
789 marked working directory as branch branch1
806 (branches are permanent and global, did you want a bookmark?)
790 (branches are permanent and global, did you want a bookmark?)
807 $ echo branch1 > foo
791 $ echo branch1 > foo
808 $ hg commit -m branch1
792 $ hg commit -m branch1
809 $ hg -q up -r 0
793 $ hg -q up -r 0
810 $ hg branch branch2
794 $ hg branch branch2
811 marked working directory as branch branch2
795 marked working directory as branch branch2
812 $ echo branch2 > foo
796 $ echo branch2 > foo
813 $ hg commit -m branch2
797 $ hg commit -m branch2
814 $ cd ..
798 $ cd ..
815 $ hg init source2
799 $ hg init source2
816 $ cd source2
800 $ cd source2
817 $ echo initial2 > foo
801 $ echo initial2 > foo
818 $ hg -q commit -A -m initial2
802 $ hg -q commit -A -m initial2
819 $ echo second > foo
803 $ echo second > foo
820 $ hg commit -m second
804 $ hg commit -m second
821 $ cd ..
805 $ cd ..
822
806
823 Clone with auto share from an empty repo should not result in share
807 Clone with auto share from an empty repo should not result in share
824
808
825 $ mkdir share
809 $ mkdir share
826 $ hg --config share.pool=share clone empty share-empty
810 $ hg --config share.pool=share clone empty share-empty
827 (not using pooled storage: remote appears to be empty)
811 (not using pooled storage: remote appears to be empty)
828 updating to branch default
812 updating to branch default
829 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
813 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
830 $ ls share
814 $ ls share
831 $ test -d share-empty/.hg/store
815 $ test -d share-empty/.hg/store
832 $ test -f share-empty/.hg/sharedpath
816 $ test -f share-empty/.hg/sharedpath
833 [1]
817 [1]
834
818
835 Clone with auto share from a repo with filtered revision 0 should not result in share
819 Clone with auto share from a repo with filtered revision 0 should not result in share
836
820
837 $ hg --config share.pool=share clone filteredrev0 share-filtered
821 $ hg --config share.pool=share clone filteredrev0 share-filtered
838 (not using pooled storage: unable to resolve identity of remote)
822 (not using pooled storage: unable to resolve identity of remote)
839 requesting all changes
823 requesting all changes
840 adding changesets
824 adding changesets
841 adding manifests
825 adding manifests
842 adding file changes
826 adding file changes
843 added 1 changesets with 1 changes to 1 files
827 added 1 changesets with 1 changes to 1 files
844 new changesets e082c1832e09
828 new changesets e082c1832e09
845 updating to branch default
829 updating to branch default
846 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
847
831
848 Clone from repo with content should result in shared store being created
832 Clone from repo with content should result in shared store being created
849
833
850 $ hg --config share.pool=share clone source1a share-dest1a
834 $ hg --config share.pool=share clone source1a share-dest1a
851 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
835 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
852 requesting all changes
836 requesting all changes
853 adding changesets
837 adding changesets
854 adding manifests
838 adding manifests
855 adding file changes
839 adding file changes
856 added 3 changesets with 3 changes to 1 files
840 added 3 changesets with 3 changes to 1 files
857 new changesets b5f04eac9d8f:e5bfe23c0b47
841 new changesets b5f04eac9d8f:e5bfe23c0b47
858 searching for changes
842 searching for changes
859 no changes found
843 no changes found
860 adding remote bookmark bookA
844 adding remote bookmark bookA
861 updating working directory
845 updating working directory
862 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
846 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
863
847
864 The shared repo should have been created
848 The shared repo should have been created
865
849
866 $ ls share
850 $ ls share
867 b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1
851 b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1
868
852
869 The destination should point to it
853 The destination should point to it
870
854
871 $ cat share-dest1a/.hg/sharedpath; echo
855 $ cat share-dest1a/.hg/sharedpath; echo
872 $TESTTMP/share/b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1/.hg
856 $TESTTMP/share/b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1/.hg
873
857
874 The destination should have bookmarks
858 The destination should have bookmarks
875
859
876 $ hg -R share-dest1a bookmarks
860 $ hg -R share-dest1a bookmarks
877 bookA 2:e5bfe23c0b47
861 bookA 2:e5bfe23c0b47
878
862
879 The default path should be the remote, not the share
863 The default path should be the remote, not the share
880
864
881 $ hg -R share-dest1a config paths.default
865 $ hg -R share-dest1a config paths.default
882 $TESTTMP/source1a
866 $TESTTMP/source1a
883
867
884 Clone with existing share dir should result in pull + share
868 Clone with existing share dir should result in pull + share
885
869
886 $ hg --config share.pool=share clone source1b share-dest1b
870 $ hg --config share.pool=share clone source1b share-dest1b
887 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
871 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
888 searching for changes
872 searching for changes
889 adding changesets
873 adding changesets
890 adding manifests
874 adding manifests
891 adding file changes
875 adding file changes
892 adding remote bookmark head1
876 adding remote bookmark head1
893 adding remote bookmark head2
877 adding remote bookmark head2
894 added 4 changesets with 4 changes to 1 files (+4 heads)
878 added 4 changesets with 4 changes to 1 files (+4 heads)
895 new changesets 4a8dc1ab4c13:6bacf4683960
879 new changesets 4a8dc1ab4c13:6bacf4683960
896 updating working directory
880 updating working directory
897 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
881 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
898
882
899 $ ls share
883 $ ls share
900 b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1
884 b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1
901
885
902 $ cat share-dest1b/.hg/sharedpath; echo
886 $ cat share-dest1b/.hg/sharedpath; echo
903 $TESTTMP/share/b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1/.hg
887 $TESTTMP/share/b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1/.hg
904
888
905 We only get bookmarks from the remote, not everything in the share
889 We only get bookmarks from the remote, not everything in the share
906
890
907 $ hg -R share-dest1b bookmarks
891 $ hg -R share-dest1b bookmarks
908 head1 3:4a8dc1ab4c13
892 head1 3:4a8dc1ab4c13
909 head2 4:99f71071f117
893 head2 4:99f71071f117
910
894
911 Default path should be source, not share.
895 Default path should be source, not share.
912
896
913 $ hg -R share-dest1b config paths.default
897 $ hg -R share-dest1b config paths.default
914 $TESTTMP/source1b
898 $TESTTMP/source1b
915
899
916 Checked out revision should be head of default branch
900 Checked out revision should be head of default branch
917
901
918 $ hg -R share-dest1b log -r .
902 $ hg -R share-dest1b log -r .
919 changeset: 4:99f71071f117
903 changeset: 4:99f71071f117
920 bookmark: head2
904 bookmark: head2
921 parent: 0:b5f04eac9d8f
905 parent: 0:b5f04eac9d8f
922 user: test
906 user: test
923 date: Thu Jan 01 00:00:00 1970 +0000
907 date: Thu Jan 01 00:00:00 1970 +0000
924 summary: head2
908 summary: head2
925
909
926
910
927 Clone from unrelated repo should result in new share
911 Clone from unrelated repo should result in new share
928
912
929 $ hg --config share.pool=share clone source2 share-dest2
913 $ hg --config share.pool=share clone source2 share-dest2
930 (sharing from new pooled repository 22aeff664783fd44c6d9b435618173c118c3448e)
914 (sharing from new pooled repository 22aeff664783fd44c6d9b435618173c118c3448e)
931 requesting all changes
915 requesting all changes
932 adding changesets
916 adding changesets
933 adding manifests
917 adding manifests
934 adding file changes
918 adding file changes
935 added 2 changesets with 2 changes to 1 files
919 added 2 changesets with 2 changes to 1 files
936 new changesets 22aeff664783:63cf6c3dba4a
920 new changesets 22aeff664783:63cf6c3dba4a
937 searching for changes
921 searching for changes
938 no changes found
922 no changes found
939 updating working directory
923 updating working directory
940 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
924 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
941
925
942 $ ls share
926 $ ls share
943 22aeff664783fd44c6d9b435618173c118c3448e
927 22aeff664783fd44c6d9b435618173c118c3448e
944 b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1
928 b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1
945
929
946 remote naming mode works as advertised
930 remote naming mode works as advertised
947
931
948 $ hg --config share.pool=shareremote --config share.poolnaming=remote clone source1a share-remote1a
932 $ hg --config share.pool=shareremote --config share.poolnaming=remote clone source1a share-remote1a
949 (sharing from new pooled repository 195bb1fcdb595c14a6c13e0269129ed78f6debde)
933 (sharing from new pooled repository 195bb1fcdb595c14a6c13e0269129ed78f6debde)
950 requesting all changes
934 requesting all changes
951 adding changesets
935 adding changesets
952 adding manifests
936 adding manifests
953 adding file changes
937 adding file changes
954 added 3 changesets with 3 changes to 1 files
938 added 3 changesets with 3 changes to 1 files
955 new changesets b5f04eac9d8f:e5bfe23c0b47
939 new changesets b5f04eac9d8f:e5bfe23c0b47
956 searching for changes
940 searching for changes
957 no changes found
941 no changes found
958 adding remote bookmark bookA
942 adding remote bookmark bookA
959 updating working directory
943 updating working directory
960 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
944 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
961
945
962 $ ls shareremote
946 $ ls shareremote
963 195bb1fcdb595c14a6c13e0269129ed78f6debde
947 195bb1fcdb595c14a6c13e0269129ed78f6debde
964
948
965 $ hg --config share.pool=shareremote --config share.poolnaming=remote clone source1b share-remote1b
949 $ hg --config share.pool=shareremote --config share.poolnaming=remote clone source1b share-remote1b
966 (sharing from new pooled repository c0d4f83847ca2a873741feb7048a45085fd47c46)
950 (sharing from new pooled repository c0d4f83847ca2a873741feb7048a45085fd47c46)
967 requesting all changes
951 requesting all changes
968 adding changesets
952 adding changesets
969 adding manifests
953 adding manifests
970 adding file changes
954 adding file changes
971 added 6 changesets with 6 changes to 1 files (+4 heads)
955 added 6 changesets with 6 changes to 1 files (+4 heads)
972 new changesets b5f04eac9d8f:6bacf4683960
956 new changesets b5f04eac9d8f:6bacf4683960
973 searching for changes
957 searching for changes
974 no changes found
958 no changes found
975 adding remote bookmark head1
959 adding remote bookmark head1
976 adding remote bookmark head2
960 adding remote bookmark head2
977 updating working directory
961 updating working directory
978 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
962 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
979
963
980 $ ls shareremote
964 $ ls shareremote
981 195bb1fcdb595c14a6c13e0269129ed78f6debde
965 195bb1fcdb595c14a6c13e0269129ed78f6debde
982 c0d4f83847ca2a873741feb7048a45085fd47c46
966 c0d4f83847ca2a873741feb7048a45085fd47c46
983
967
984 request to clone a single revision is respected in sharing mode
968 request to clone a single revision is respected in sharing mode
985
969
986 $ hg --config share.pool=sharerevs clone -r 4a8dc1ab4c13 source1b share-1arev
970 $ hg --config share.pool=sharerevs clone -r 4a8dc1ab4c13 source1b share-1arev
987 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
971 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
988 adding changesets
972 adding changesets
989 adding manifests
973 adding manifests
990 adding file changes
974 adding file changes
991 added 2 changesets with 2 changes to 1 files
975 added 2 changesets with 2 changes to 1 files
992 new changesets b5f04eac9d8f:4a8dc1ab4c13
976 new changesets b5f04eac9d8f:4a8dc1ab4c13
993 no changes found
977 no changes found
994 adding remote bookmark head1
978 adding remote bookmark head1
995 updating working directory
979 updating working directory
996 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
980 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
997
981
998 $ hg -R share-1arev log -G
982 $ hg -R share-1arev log -G
999 @ changeset: 1:4a8dc1ab4c13
983 @ changeset: 1:4a8dc1ab4c13
1000 | bookmark: head1
984 | bookmark: head1
1001 | tag: tip
985 | tag: tip
1002 | user: test
986 | user: test
1003 | date: Thu Jan 01 00:00:00 1970 +0000
987 | date: Thu Jan 01 00:00:00 1970 +0000
1004 | summary: head1
988 | summary: head1
1005 |
989 |
1006 o changeset: 0:b5f04eac9d8f
990 o changeset: 0:b5f04eac9d8f
1007 user: test
991 user: test
1008 date: Thu Jan 01 00:00:00 1970 +0000
992 date: Thu Jan 01 00:00:00 1970 +0000
1009 summary: initial
993 summary: initial
1010
994
1011
995
1012 making another clone should only pull down requested rev
996 making another clone should only pull down requested rev
1013
997
1014 $ hg --config share.pool=sharerevs clone -r 99f71071f117 source1b share-1brev
998 $ hg --config share.pool=sharerevs clone -r 99f71071f117 source1b share-1brev
1015 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
999 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1016 searching for changes
1000 searching for changes
1017 adding changesets
1001 adding changesets
1018 adding manifests
1002 adding manifests
1019 adding file changes
1003 adding file changes
1020 adding remote bookmark head1
1004 adding remote bookmark head1
1021 adding remote bookmark head2
1005 adding remote bookmark head2
1022 added 1 changesets with 1 changes to 1 files (+1 heads)
1006 added 1 changesets with 1 changes to 1 files (+1 heads)
1023 new changesets 99f71071f117
1007 new changesets 99f71071f117
1024 updating working directory
1008 updating working directory
1025 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1009 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1026
1010
1027 $ hg -R share-1brev log -G
1011 $ hg -R share-1brev log -G
1028 @ changeset: 2:99f71071f117
1012 @ changeset: 2:99f71071f117
1029 | bookmark: head2
1013 | bookmark: head2
1030 | tag: tip
1014 | tag: tip
1031 | parent: 0:b5f04eac9d8f
1015 | parent: 0:b5f04eac9d8f
1032 | user: test
1016 | user: test
1033 | date: Thu Jan 01 00:00:00 1970 +0000
1017 | date: Thu Jan 01 00:00:00 1970 +0000
1034 | summary: head2
1018 | summary: head2
1035 |
1019 |
1036 | o changeset: 1:4a8dc1ab4c13
1020 | o changeset: 1:4a8dc1ab4c13
1037 |/ bookmark: head1
1021 |/ bookmark: head1
1038 | user: test
1022 | user: test
1039 | date: Thu Jan 01 00:00:00 1970 +0000
1023 | date: Thu Jan 01 00:00:00 1970 +0000
1040 | summary: head1
1024 | summary: head1
1041 |
1025 |
1042 o changeset: 0:b5f04eac9d8f
1026 o changeset: 0:b5f04eac9d8f
1043 user: test
1027 user: test
1044 date: Thu Jan 01 00:00:00 1970 +0000
1028 date: Thu Jan 01 00:00:00 1970 +0000
1045 summary: initial
1029 summary: initial
1046
1030
1047
1031
1048 Request to clone a single branch is respected in sharing mode
1032 Request to clone a single branch is respected in sharing mode
1049
1033
1050 $ hg --config share.pool=sharebranch clone -b branch1 source1b share-1bbranch1
1034 $ hg --config share.pool=sharebranch clone -b branch1 source1b share-1bbranch1
1051 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1035 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1052 adding changesets
1036 adding changesets
1053 adding manifests
1037 adding manifests
1054 adding file changes
1038 adding file changes
1055 added 2 changesets with 2 changes to 1 files
1039 added 2 changesets with 2 changes to 1 files
1056 new changesets b5f04eac9d8f:5f92a6c1a1b1
1040 new changesets b5f04eac9d8f:5f92a6c1a1b1
1057 no changes found
1041 no changes found
1058 updating working directory
1042 updating working directory
1059 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1043 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1060
1044
1061 $ hg -R share-1bbranch1 log -G
1045 $ hg -R share-1bbranch1 log -G
1062 o changeset: 1:5f92a6c1a1b1
1046 o changeset: 1:5f92a6c1a1b1
1063 | branch: branch1
1047 | branch: branch1
1064 | tag: tip
1048 | tag: tip
1065 | user: test
1049 | user: test
1066 | date: Thu Jan 01 00:00:00 1970 +0000
1050 | date: Thu Jan 01 00:00:00 1970 +0000
1067 | summary: branch1
1051 | summary: branch1
1068 |
1052 |
1069 @ changeset: 0:b5f04eac9d8f
1053 @ changeset: 0:b5f04eac9d8f
1070 user: test
1054 user: test
1071 date: Thu Jan 01 00:00:00 1970 +0000
1055 date: Thu Jan 01 00:00:00 1970 +0000
1072 summary: initial
1056 summary: initial
1073
1057
1074
1058
1075 $ hg --config share.pool=sharebranch clone -b branch2 source1b share-1bbranch2
1059 $ hg --config share.pool=sharebranch clone -b branch2 source1b share-1bbranch2
1076 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1060 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1077 searching for changes
1061 searching for changes
1078 adding changesets
1062 adding changesets
1079 adding manifests
1063 adding manifests
1080 adding file changes
1064 adding file changes
1081 added 1 changesets with 1 changes to 1 files (+1 heads)
1065 added 1 changesets with 1 changes to 1 files (+1 heads)
1082 new changesets 6bacf4683960
1066 new changesets 6bacf4683960
1083 updating working directory
1067 updating working directory
1084 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1068 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1085
1069
1086 $ hg -R share-1bbranch2 log -G
1070 $ hg -R share-1bbranch2 log -G
1087 o changeset: 2:6bacf4683960
1071 o changeset: 2:6bacf4683960
1088 | branch: branch2
1072 | branch: branch2
1089 | tag: tip
1073 | tag: tip
1090 | parent: 0:b5f04eac9d8f
1074 | parent: 0:b5f04eac9d8f
1091 | user: test
1075 | user: test
1092 | date: Thu Jan 01 00:00:00 1970 +0000
1076 | date: Thu Jan 01 00:00:00 1970 +0000
1093 | summary: branch2
1077 | summary: branch2
1094 |
1078 |
1095 | o changeset: 1:5f92a6c1a1b1
1079 | o changeset: 1:5f92a6c1a1b1
1096 |/ branch: branch1
1080 |/ branch: branch1
1097 | user: test
1081 | user: test
1098 | date: Thu Jan 01 00:00:00 1970 +0000
1082 | date: Thu Jan 01 00:00:00 1970 +0000
1099 | summary: branch1
1083 | summary: branch1
1100 |
1084 |
1101 @ changeset: 0:b5f04eac9d8f
1085 @ changeset: 0:b5f04eac9d8f
1102 user: test
1086 user: test
1103 date: Thu Jan 01 00:00:00 1970 +0000
1087 date: Thu Jan 01 00:00:00 1970 +0000
1104 summary: initial
1088 summary: initial
1105
1089
1106
1090
1107 -U is respected in share clone mode
1091 -U is respected in share clone mode
1108
1092
1109 $ hg --config share.pool=share clone -U source1a share-1anowc
1093 $ hg --config share.pool=share clone -U source1a share-1anowc
1110 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1094 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1111 searching for changes
1095 searching for changes
1112 no changes found
1096 no changes found
1113 adding remote bookmark bookA
1097 adding remote bookmark bookA
1114
1098
1115 $ ls -A share-1anowc
1099 $ ls -A share-1anowc
1116 .hg
1100 .hg
1117
1101
1118 Test that auto sharing doesn't cause failure of "hg clone local remote"
1102 Test that auto sharing doesn't cause failure of "hg clone local remote"
1119
1103
1120 $ cd $TESTTMP
1104 $ cd $TESTTMP
1121 $ hg -R a id -r 0
1105 $ hg -R a id -r 0
1122 acb14030fe0a
1106 acb14030fe0a
1123 $ hg id -R remote -r 0
1107 $ hg id -R remote -r 0
1124 abort: repository remote not found
1108 abort: repository remote not found
1125 [255]
1109 [255]
1126 $ hg --config share.pool=share -q clone -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" a ssh://user@dummy/remote
1110 $ hg --config share.pool=share -q clone -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" a ssh://user@dummy/remote
1127 $ hg -R remote id -r 0
1111 $ hg -R remote id -r 0
1128 acb14030fe0a
1112 acb14030fe0a
1129
1113
1130 Cloning into pooled storage doesn't race (issue5104)
1114 Cloning into pooled storage doesn't race (issue5104)
1131
1115
1132 $ HGPOSTLOCKDELAY=2.0 hg --config share.pool=racepool --config extensions.lockdelay=$TESTDIR/lockdelay.py clone source1a share-destrace1 > race1.log 2>&1 &
1116 $ HGPOSTLOCKDELAY=2.0 hg --config share.pool=racepool --config extensions.lockdelay=$TESTDIR/lockdelay.py clone source1a share-destrace1 > race1.log 2>&1 &
1133 $ HGPRELOCKDELAY=1.0 hg --config share.pool=racepool --config extensions.lockdelay=$TESTDIR/lockdelay.py clone source1a share-destrace2 > race2.log 2>&1
1117 $ HGPRELOCKDELAY=1.0 hg --config share.pool=racepool --config extensions.lockdelay=$TESTDIR/lockdelay.py clone source1a share-destrace2 > race2.log 2>&1
1134 $ wait
1118 $ wait
1135
1119
1136 $ hg -R share-destrace1 log -r tip
1120 $ hg -R share-destrace1 log -r tip
1137 changeset: 2:e5bfe23c0b47
1121 changeset: 2:e5bfe23c0b47
1138 bookmark: bookA
1122 bookmark: bookA
1139 tag: tip
1123 tag: tip
1140 user: test
1124 user: test
1141 date: Thu Jan 01 00:00:00 1970 +0000
1125 date: Thu Jan 01 00:00:00 1970 +0000
1142 summary: 1a
1126 summary: 1a
1143
1127
1144
1128
1145 $ hg -R share-destrace2 log -r tip
1129 $ hg -R share-destrace2 log -r tip
1146 changeset: 2:e5bfe23c0b47
1130 changeset: 2:e5bfe23c0b47
1147 bookmark: bookA
1131 bookmark: bookA
1148 tag: tip
1132 tag: tip
1149 user: test
1133 user: test
1150 date: Thu Jan 01 00:00:00 1970 +0000
1134 date: Thu Jan 01 00:00:00 1970 +0000
1151 summary: 1a
1135 summary: 1a
1152
1136
1153 One repo should be new, the other should be shared from the pool. We
1137 One repo should be new, the other should be shared from the pool. We
1154 don't care which is which, so we just make sure we always print the
1138 don't care which is which, so we just make sure we always print the
1155 one containing "new pooled" first, then one one containing "existing
1139 one containing "new pooled" first, then one one containing "existing
1156 pooled".
1140 pooled".
1157
1141
1158 $ (grep 'new pooled' race1.log > /dev/null && cat race1.log || cat race2.log) | grep -v lock
1142 $ (grep 'new pooled' race1.log > /dev/null && cat race1.log || cat race2.log) | grep -v lock
1159 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1143 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1160 requesting all changes
1144 requesting all changes
1161 adding changesets
1145 adding changesets
1162 adding manifests
1146 adding manifests
1163 adding file changes
1147 adding file changes
1164 added 3 changesets with 3 changes to 1 files
1148 added 3 changesets with 3 changes to 1 files
1165 new changesets b5f04eac9d8f:e5bfe23c0b47
1149 new changesets b5f04eac9d8f:e5bfe23c0b47
1166 searching for changes
1150 searching for changes
1167 no changes found
1151 no changes found
1168 adding remote bookmark bookA
1152 adding remote bookmark bookA
1169 updating working directory
1153 updating working directory
1170 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1154 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1171
1155
1172 $ (grep 'existing pooled' race1.log > /dev/null && cat race1.log || cat race2.log) | grep -v lock
1156 $ (grep 'existing pooled' race1.log > /dev/null && cat race1.log || cat race2.log) | grep -v lock
1173 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1157 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1174 searching for changes
1158 searching for changes
1175 no changes found
1159 no changes found
1176 adding remote bookmark bookA
1160 adding remote bookmark bookA
1177 updating working directory
1161 updating working directory
1178 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1162 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1179
1163
1180 SEC: check for unsafe ssh url
1164 SEC: check for unsafe ssh url
1181
1165
1182 $ cat >> $HGRCPATH << EOF
1166 $ cat >> $HGRCPATH << EOF
1183 > [ui]
1167 > [ui]
1184 > ssh = sh -c "read l; read l; read l"
1168 > ssh = sh -c "read l; read l; read l"
1185 > EOF
1169 > EOF
1186
1170
1187 $ hg clone 'ssh://-oProxyCommand=touch${IFS}owned/path'
1171 $ hg clone 'ssh://-oProxyCommand=touch${IFS}owned/path'
1188 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch${IFS}owned/path'
1172 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch${IFS}owned/path'
1189 [255]
1173 [255]
1190 $ hg clone 'ssh://%2DoProxyCommand=touch${IFS}owned/path'
1174 $ hg clone 'ssh://%2DoProxyCommand=touch${IFS}owned/path'
1191 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch${IFS}owned/path'
1175 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch${IFS}owned/path'
1192 [255]
1176 [255]
1193 $ hg clone 'ssh://fakehost|touch%20owned/path'
1177 $ hg clone 'ssh://fakehost|touch%20owned/path'
1194 abort: no suitable response from remote hg
1178 abort: no suitable response from remote hg
1195 [255]
1179 [255]
1196 $ hg clone 'ssh://fakehost%7Ctouch%20owned/path'
1180 $ hg clone 'ssh://fakehost%7Ctouch%20owned/path'
1197 abort: no suitable response from remote hg
1181 abort: no suitable response from remote hg
1198 [255]
1182 [255]
1199
1183
1200 $ hg clone 'ssh://-oProxyCommand=touch owned%20foo@example.com/nonexistent/path'
1184 $ hg clone 'ssh://-oProxyCommand=touch owned%20foo@example.com/nonexistent/path'
1201 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch owned foo@example.com/nonexistent/path'
1185 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch owned foo@example.com/nonexistent/path'
1202 [255]
1186 [255]
1203
1187
1204 #if windows
1188 #if windows
1205 $ hg clone "ssh://%26touch%20owned%20/" --debug
1189 $ hg clone "ssh://%26touch%20owned%20/" --debug
1206 running sh -c "read l; read l; read l" "&touch owned " "hg -R . serve --stdio"
1190 running sh -c "read l; read l; read l" "&touch owned " "hg -R . serve --stdio"
1207 sending upgrade request: * proto=exp-ssh-v2-0003 (glob) (sshv2 !)
1191 sending upgrade request: * proto=exp-ssh-v2-0003 (glob) (sshv2 !)
1208 sending hello command
1192 sending hello command
1209 sending between command
1193 sending between command
1210 abort: no suitable response from remote hg
1194 abort: no suitable response from remote hg
1211 [255]
1195 [255]
1212 $ hg clone "ssh://example.com:%26touch%20owned%20/" --debug
1196 $ hg clone "ssh://example.com:%26touch%20owned%20/" --debug
1213 running sh -c "read l; read l; read l" -p "&touch owned " example.com "hg -R . serve --stdio"
1197 running sh -c "read l; read l; read l" -p "&touch owned " example.com "hg -R . serve --stdio"
1214 sending upgrade request: * proto=exp-ssh-v2-0003 (glob) (sshv2 !)
1198 sending upgrade request: * proto=exp-ssh-v2-0003 (glob) (sshv2 !)
1215 sending hello command
1199 sending hello command
1216 sending between command
1200 sending between command
1217 abort: no suitable response from remote hg
1201 abort: no suitable response from remote hg
1218 [255]
1202 [255]
1219 #else
1203 #else
1220 $ hg clone "ssh://%3btouch%20owned%20/" --debug
1204 $ hg clone "ssh://%3btouch%20owned%20/" --debug
1221 running sh -c "read l; read l; read l" ';touch owned ' 'hg -R . serve --stdio'
1205 running sh -c "read l; read l; read l" ';touch owned ' 'hg -R . serve --stdio'
1222 sending upgrade request: * proto=exp-ssh-v2-0003 (glob) (sshv2 !)
1206 sending upgrade request: * proto=exp-ssh-v2-0003 (glob) (sshv2 !)
1223 sending hello command
1207 sending hello command
1224 sending between command
1208 sending between command
1225 abort: no suitable response from remote hg
1209 abort: no suitable response from remote hg
1226 [255]
1210 [255]
1227 $ hg clone "ssh://example.com:%3btouch%20owned%20/" --debug
1211 $ hg clone "ssh://example.com:%3btouch%20owned%20/" --debug
1228 running sh -c "read l; read l; read l" -p ';touch owned ' example.com 'hg -R . serve --stdio'
1212 running sh -c "read l; read l; read l" -p ';touch owned ' example.com 'hg -R . serve --stdio'
1229 sending upgrade request: * proto=exp-ssh-v2-0003 (glob) (sshv2 !)
1213 sending upgrade request: * proto=exp-ssh-v2-0003 (glob) (sshv2 !)
1230 sending hello command
1214 sending hello command
1231 sending between command
1215 sending between command
1232 abort: no suitable response from remote hg
1216 abort: no suitable response from remote hg
1233 [255]
1217 [255]
1234 #endif
1218 #endif
1235
1219
1236 $ hg clone "ssh://v-alid.example.com/" --debug
1220 $ hg clone "ssh://v-alid.example.com/" --debug
1237 running sh -c "read l; read l; read l" v-alid\.example\.com ['"]hg -R \. serve --stdio['"] (re)
1221 running sh -c "read l; read l; read l" v-alid\.example\.com ['"]hg -R \. serve --stdio['"] (re)
1238 sending upgrade request: * proto=exp-ssh-v2-0003 (glob) (sshv2 !)
1222 sending upgrade request: * proto=exp-ssh-v2-0003 (glob) (sshv2 !)
1239 sending hello command
1223 sending hello command
1240 sending between command
1224 sending between command
1241 abort: no suitable response from remote hg
1225 abort: no suitable response from remote hg
1242 [255]
1226 [255]
1243
1227
1244 We should not have created a file named owned - if it exists, the
1228 We should not have created a file named owned - if it exists, the
1245 attack succeeded.
1229 attack succeeded.
1246 $ if test -f owned; then echo 'you got owned'; fi
1230 $ if test -f owned; then echo 'you got owned'; fi
1247
1231
1248 Cloning without fsmonitor enabled does not print a warning for small repos
1232 Cloning without fsmonitor enabled does not print a warning for small repos
1249
1233
1250 $ hg clone a fsmonitor-default
1234 $ hg clone a fsmonitor-default
1251 updating to bookmark @ on branch stable
1235 updating to bookmark @ on branch stable
1252 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1236 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1253
1237
1254 Lower the warning threshold to simulate a large repo
1238 Lower the warning threshold to simulate a large repo
1255
1239
1256 $ cat >> $HGRCPATH << EOF
1240 $ cat >> $HGRCPATH << EOF
1257 > [fsmonitor]
1241 > [fsmonitor]
1258 > warn_update_file_count = 2
1242 > warn_update_file_count = 2
1259 > warn_update_file_count_rust = 2
1243 > warn_update_file_count_rust = 2
1260 > EOF
1244 > EOF
1261
1245
1262 We should see a warning about no fsmonitor on supported platforms
1246 We should see a warning about no fsmonitor on supported platforms
1263
1247
1264 #if linuxormacos no-fsmonitor
1248 #if linuxormacos no-fsmonitor
1265 $ hg clone a nofsmonitor
1249 $ hg clone a nofsmonitor
1266 updating to bookmark @ on branch stable
1250 updating to bookmark @ on branch stable
1267 (warning: large working directory being used without fsmonitor enabled; enable fsmonitor to improve performance; see "hg help -e fsmonitor")
1251 (warning: large working directory being used without fsmonitor enabled; enable fsmonitor to improve performance; see "hg help -e fsmonitor")
1268 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1252 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1269 #else
1253 #else
1270 $ hg clone a nofsmonitor
1254 $ hg clone a nofsmonitor
1271 updating to bookmark @ on branch stable
1255 updating to bookmark @ on branch stable
1272 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1256 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1273 #endif
1257 #endif
1274
1258
1275 We should not see warning about fsmonitor when it is enabled
1259 We should not see warning about fsmonitor when it is enabled
1276
1260
1277 #if fsmonitor
1261 #if fsmonitor
1278 $ hg clone a fsmonitor-enabled
1262 $ hg clone a fsmonitor-enabled
1279 updating to bookmark @ on branch stable
1263 updating to bookmark @ on branch stable
1280 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1264 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1281 #endif
1265 #endif
1282
1266
1283 We can disable the fsmonitor warning
1267 We can disable the fsmonitor warning
1284
1268
1285 $ hg --config fsmonitor.warn_when_unused=false clone a fsmonitor-disable-warning
1269 $ hg --config fsmonitor.warn_when_unused=false clone a fsmonitor-disable-warning
1286 updating to bookmark @ on branch stable
1270 updating to bookmark @ on branch stable
1287 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1271 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1288
1272
1289 Loaded fsmonitor but disabled in config should still print warning
1273 Loaded fsmonitor but disabled in config should still print warning
1290
1274
1291 #if linuxormacos fsmonitor
1275 #if linuxormacos fsmonitor
1292 $ hg --config fsmonitor.mode=off clone a fsmonitor-mode-off
1276 $ hg --config fsmonitor.mode=off clone a fsmonitor-mode-off
1293 updating to bookmark @ on branch stable
1277 updating to bookmark @ on branch stable
1294 (warning: large working directory being used without fsmonitor enabled; enable fsmonitor to improve performance; see "hg help -e fsmonitor") (fsmonitor !)
1278 (warning: large working directory being used without fsmonitor enabled; enable fsmonitor to improve performance; see "hg help -e fsmonitor") (fsmonitor !)
1295 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1279 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1296 #endif
1280 #endif
1297
1281
1298 Warning not printed if working directory isn't empty
1282 Warning not printed if working directory isn't empty
1299
1283
1300 $ hg -q clone a fsmonitor-update
1284 $ hg -q clone a fsmonitor-update
1301 (warning: large working directory being used without fsmonitor enabled; enable fsmonitor to improve performance; see "hg help -e fsmonitor") (?)
1285 (warning: large working directory being used without fsmonitor enabled; enable fsmonitor to improve performance; see "hg help -e fsmonitor") (?)
1302 $ cd fsmonitor-update
1286 $ cd fsmonitor-update
1303 $ hg up acb14030fe0a
1287 $ hg up acb14030fe0a
1304 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
1288 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
1305 (leaving bookmark @)
1289 (leaving bookmark @)
1306 $ hg up cf0fe1914066
1290 $ hg up cf0fe1914066
1307 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1291 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1308
1292
1309 `hg update` from null revision also prints
1293 `hg update` from null revision also prints
1310
1294
1311 $ hg up null
1295 $ hg up null
1312 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1296 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1313
1297
1314 #if linuxormacos no-fsmonitor
1298 #if linuxormacos no-fsmonitor
1315 $ hg up cf0fe1914066
1299 $ hg up cf0fe1914066
1316 (warning: large working directory being used without fsmonitor enabled; enable fsmonitor to improve performance; see "hg help -e fsmonitor")
1300 (warning: large working directory being used without fsmonitor enabled; enable fsmonitor to improve performance; see "hg help -e fsmonitor")
1317 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1301 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1318 #else
1302 #else
1319 $ hg up cf0fe1914066
1303 $ hg up cf0fe1914066
1320 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1304 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1321 #endif
1305 #endif
1322
1306
1323 $ cd ..
1307 $ cd ..
1324
1308
@@ -1,57 +1,58 b''
1 Create an empty repo:
1 Create an empty repo:
2
2
3 $ hg init a
3 $ hg init a
4 $ cd a
4 $ cd a
5
5
6 Try some commands:
6 Try some commands:
7
7
8 $ hg log
8 $ hg log
9 $ hg grep wah
9 $ hg grep wah
10 [1]
10 [1]
11 $ hg manifest
11 $ hg manifest
12 $ hg verify
12 $ hg verify
13 checking changesets
13 checking changesets
14 checking manifests
14 checking manifests
15 crosschecking files in changesets and manifests
15 crosschecking files in changesets and manifests
16 checking files
16 checking files
17 checked 0 changesets with 0 changes to 0 files
17 checked 0 changesets with 0 changes to 0 files
18
18
19 Check the basic files created:
19 Check the basic files created:
20
20
21 $ ls .hg
21 $ ls .hg
22 00changelog.i
22 00changelog.i
23 cache
23 cache
24 requires
24 requires
25 store
25 store
26 wcache
26 wcache
27
27
28 Should be empty:
28 Should be empty:
29
29
30 $ ls .hg/store
30 $ ls .hg/store
31
31
32 Poke at a clone:
32 Poke at a clone:
33
33
34 $ cd ..
34 $ cd ..
35 $ hg clone a b
35 $ hg clone a b
36 updating to branch default
36 updating to branch default
37 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
37 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
38 $ cd b
38 $ cd b
39 $ hg verify
39 $ hg verify
40 checking changesets
40 checking changesets
41 checking manifests
41 checking manifests
42 crosschecking files in changesets and manifests
42 crosschecking files in changesets and manifests
43 checking files
43 checking files
44 checked 0 changesets with 0 changes to 0 files
44 checked 0 changesets with 0 changes to 0 files
45 $ ls .hg
45 $ ls .hg
46 00changelog.i
46 00changelog.i
47 cache
47 cache
48 dirstate
48 hgrc
49 hgrc
49 requires
50 requires
50 store
51 store
51 wcache
52 wcache
52
53
53 Should be empty:
54 Should be empty:
54
55
55 $ ls .hg/store
56 $ ls .hg/store
56
57
57 $ cd ..
58 $ cd ..
@@ -1,545 +1,549 b''
1 #require repofncache
1 #require repofncache
2
2
3 An extension which will set fncache chunksize to 1 byte to make sure that logic
3 An extension which will set fncache chunksize to 1 byte to make sure that logic
4 does not break
4 does not break
5
5
6 $ cat > chunksize.py <<EOF
6 $ cat > chunksize.py <<EOF
7 > from __future__ import absolute_import
7 > from __future__ import absolute_import
8 > from mercurial import store
8 > from mercurial import store
9 > store.fncache_chunksize = 1
9 > store.fncache_chunksize = 1
10 > EOF
10 > EOF
11
11
12 $ cat >> $HGRCPATH <<EOF
12 $ cat >> $HGRCPATH <<EOF
13 > [extensions]
13 > [extensions]
14 > chunksize = $TESTTMP/chunksize.py
14 > chunksize = $TESTTMP/chunksize.py
15 > EOF
15 > EOF
16
16
17 Init repo1:
17 Init repo1:
18
18
19 $ hg init repo1
19 $ hg init repo1
20 $ cd repo1
20 $ cd repo1
21 $ echo "some text" > a
21 $ echo "some text" > a
22 $ hg add
22 $ hg add
23 adding a
23 adding a
24 $ hg ci -m first
24 $ hg ci -m first
25 $ cat .hg/store/fncache | sort
25 $ cat .hg/store/fncache | sort
26 data/a.i
26 data/a.i
27
27
28 Testing a.i/b:
28 Testing a.i/b:
29
29
30 $ mkdir a.i
30 $ mkdir a.i
31 $ echo "some other text" > a.i/b
31 $ echo "some other text" > a.i/b
32 $ hg add
32 $ hg add
33 adding a.i/b
33 adding a.i/b
34 $ hg ci -m second
34 $ hg ci -m second
35 $ cat .hg/store/fncache | sort
35 $ cat .hg/store/fncache | sort
36 data/a.i
36 data/a.i
37 data/a.i.hg/b.i
37 data/a.i.hg/b.i
38
38
39 Testing a.i.hg/c:
39 Testing a.i.hg/c:
40
40
41 $ mkdir a.i.hg
41 $ mkdir a.i.hg
42 $ echo "yet another text" > a.i.hg/c
42 $ echo "yet another text" > a.i.hg/c
43 $ hg add
43 $ hg add
44 adding a.i.hg/c
44 adding a.i.hg/c
45 $ hg ci -m third
45 $ hg ci -m third
46 $ cat .hg/store/fncache | sort
46 $ cat .hg/store/fncache | sort
47 data/a.i
47 data/a.i
48 data/a.i.hg.hg/c.i
48 data/a.i.hg.hg/c.i
49 data/a.i.hg/b.i
49 data/a.i.hg/b.i
50
50
51 Testing verify:
51 Testing verify:
52
52
53 $ hg verify
53 $ hg verify
54 checking changesets
54 checking changesets
55 checking manifests
55 checking manifests
56 crosschecking files in changesets and manifests
56 crosschecking files in changesets and manifests
57 checking files
57 checking files
58 checked 3 changesets with 3 changes to 3 files
58 checked 3 changesets with 3 changes to 3 files
59
59
60 $ rm .hg/store/fncache
60 $ rm .hg/store/fncache
61
61
62 $ hg verify
62 $ hg verify
63 checking changesets
63 checking changesets
64 checking manifests
64 checking manifests
65 crosschecking files in changesets and manifests
65 crosschecking files in changesets and manifests
66 checking files
66 checking files
67 warning: revlog 'data/a.i' not in fncache!
67 warning: revlog 'data/a.i' not in fncache!
68 warning: revlog 'data/a.i.hg/c.i' not in fncache!
68 warning: revlog 'data/a.i.hg/c.i' not in fncache!
69 warning: revlog 'data/a.i/b.i' not in fncache!
69 warning: revlog 'data/a.i/b.i' not in fncache!
70 checked 3 changesets with 3 changes to 3 files
70 checked 3 changesets with 3 changes to 3 files
71 3 warnings encountered!
71 3 warnings encountered!
72 hint: run "hg debugrebuildfncache" to recover from corrupt fncache
72 hint: run "hg debugrebuildfncache" to recover from corrupt fncache
73
73
74 Follow the hint to make sure it works
74 Follow the hint to make sure it works
75
75
76 $ hg debugrebuildfncache
76 $ hg debugrebuildfncache
77 adding data/a.i
77 adding data/a.i
78 adding data/a.i.hg/c.i
78 adding data/a.i.hg/c.i
79 adding data/a.i/b.i
79 adding data/a.i/b.i
80 3 items added, 0 removed from fncache
80 3 items added, 0 removed from fncache
81
81
82 $ hg verify
82 $ hg verify
83 checking changesets
83 checking changesets
84 checking manifests
84 checking manifests
85 crosschecking files in changesets and manifests
85 crosschecking files in changesets and manifests
86 checking files
86 checking files
87 checked 3 changesets with 3 changes to 3 files
87 checked 3 changesets with 3 changes to 3 files
88
88
89 $ cd ..
89 $ cd ..
90
90
91 Non store repo:
91 Non store repo:
92
92
93 $ hg --config format.usestore=False init foo
93 $ hg --config format.usestore=False init foo
94 $ cd foo
94 $ cd foo
95 $ mkdir tst.d
95 $ mkdir tst.d
96 $ echo foo > tst.d/foo
96 $ echo foo > tst.d/foo
97 $ hg ci -Amfoo
97 $ hg ci -Amfoo
98 adding tst.d/foo
98 adding tst.d/foo
99 $ find .hg | sort
99 $ find .hg | sort
100 .hg
100 .hg
101 .hg/00changelog.i
101 .hg/00changelog.i
102 .hg/00manifest.i
102 .hg/00manifest.i
103 .hg/cache
103 .hg/cache
104 .hg/cache/branch2-served
104 .hg/cache/branch2-served
105 .hg/cache/rbc-names-v1
105 .hg/cache/rbc-names-v1
106 .hg/cache/rbc-revs-v1
106 .hg/cache/rbc-revs-v1
107 .hg/data
107 .hg/data
108 .hg/data/tst.d.hg
108 .hg/data/tst.d.hg
109 .hg/data/tst.d.hg/foo.i
109 .hg/data/tst.d.hg/foo.i
110 .hg/dirstate
110 .hg/dirstate
111 .hg/fsmonitor.state (fsmonitor !)
111 .hg/fsmonitor.state (fsmonitor !)
112 .hg/last-message.txt
112 .hg/last-message.txt
113 .hg/phaseroots
113 .hg/phaseroots
114 .hg/requires
114 .hg/requires
115 .hg/undo
115 .hg/undo
116 .hg/undo.backup.dirstate
116 .hg/undo.backup.dirstate
117 .hg/undo.backupfiles
117 .hg/undo.backupfiles
118 .hg/undo.bookmarks
118 .hg/undo.bookmarks
119 .hg/undo.branch
119 .hg/undo.branch
120 .hg/undo.desc
120 .hg/undo.desc
121 .hg/undo.dirstate
121 .hg/undo.dirstate
122 .hg/undo.phaseroots
122 .hg/undo.phaseroots
123 .hg/wcache
123 .hg/wcache
124 .hg/wcache/checkisexec (execbit !)
124 .hg/wcache/checkisexec (execbit !)
125 .hg/wcache/checklink (symlink !)
125 .hg/wcache/checklink (symlink !)
126 .hg/wcache/checklink-target (symlink !)
126 .hg/wcache/checklink-target (symlink !)
127 .hg/wcache/manifestfulltextcache (reporevlogstore !)
127 .hg/wcache/manifestfulltextcache (reporevlogstore !)
128 $ cd ..
128 $ cd ..
129
129
130 Non fncache repo:
130 Non fncache repo:
131
131
132 $ hg --config format.usefncache=False init bar
132 $ hg --config format.usefncache=False init bar
133 $ cd bar
133 $ cd bar
134 $ mkdir tst.d
134 $ mkdir tst.d
135 $ echo foo > tst.d/Foo
135 $ echo foo > tst.d/Foo
136 $ hg ci -Amfoo
136 $ hg ci -Amfoo
137 adding tst.d/Foo
137 adding tst.d/Foo
138 $ find .hg | sort
138 $ find .hg | sort
139 .hg
139 .hg
140 .hg/00changelog.i
140 .hg/00changelog.i
141 .hg/cache
141 .hg/cache
142 .hg/cache/branch2-served
142 .hg/cache/branch2-served
143 .hg/cache/rbc-names-v1
143 .hg/cache/rbc-names-v1
144 .hg/cache/rbc-revs-v1
144 .hg/cache/rbc-revs-v1
145 .hg/dirstate
145 .hg/dirstate
146 .hg/fsmonitor.state (fsmonitor !)
146 .hg/fsmonitor.state (fsmonitor !)
147 .hg/last-message.txt
147 .hg/last-message.txt
148 .hg/requires
148 .hg/requires
149 .hg/store
149 .hg/store
150 .hg/store/00changelog.i
150 .hg/store/00changelog.i
151 .hg/store/00manifest.i
151 .hg/store/00manifest.i
152 .hg/store/data
152 .hg/store/data
153 .hg/store/data/tst.d.hg
153 .hg/store/data/tst.d.hg
154 .hg/store/data/tst.d.hg/_foo.i
154 .hg/store/data/tst.d.hg/_foo.i
155 .hg/store/phaseroots
155 .hg/store/phaseroots
156 .hg/store/undo
156 .hg/store/undo
157 .hg/store/undo.backupfiles
157 .hg/store/undo.backupfiles
158 .hg/store/undo.phaseroots
158 .hg/store/undo.phaseroots
159 .hg/undo.backup.dirstate
159 .hg/undo.backup.dirstate
160 .hg/undo.bookmarks
160 .hg/undo.bookmarks
161 .hg/undo.branch
161 .hg/undo.branch
162 .hg/undo.desc
162 .hg/undo.desc
163 .hg/undo.dirstate
163 .hg/undo.dirstate
164 .hg/wcache
164 .hg/wcache
165 .hg/wcache/checkisexec (execbit !)
165 .hg/wcache/checkisexec (execbit !)
166 .hg/wcache/checklink (symlink !)
166 .hg/wcache/checklink (symlink !)
167 .hg/wcache/checklink-target (symlink !)
167 .hg/wcache/checklink-target (symlink !)
168 .hg/wcache/manifestfulltextcache (reporevlogstore !)
168 .hg/wcache/manifestfulltextcache (reporevlogstore !)
169 $ cd ..
169 $ cd ..
170
170
171 Encoding of reserved / long paths in the store
171 Encoding of reserved / long paths in the store
172
172
173 $ hg init r2
173 $ hg init r2
174 $ cd r2
174 $ cd r2
175 $ cat <<EOF > .hg/hgrc
175 $ cat <<EOF > .hg/hgrc
176 > [ui]
176 > [ui]
177 > portablefilenames = ignore
177 > portablefilenames = ignore
178 > EOF
178 > EOF
179
179
180 $ hg import -q --bypass - <<EOF
180 $ hg import -q --bypass - <<EOF
181 > # HG changeset patch
181 > # HG changeset patch
182 > # User test
182 > # User test
183 > # Date 0 0
183 > # Date 0 0
184 > # Node ID 1c7a2f7cb77be1a0def34e4c7cabc562ad98fbd7
184 > # Node ID 1c7a2f7cb77be1a0def34e4c7cabc562ad98fbd7
185 > # Parent 0000000000000000000000000000000000000000
185 > # Parent 0000000000000000000000000000000000000000
186 > 1
186 > 1
187 >
187 >
188 > diff --git a/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz b/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz
188 > diff --git a/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz b/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz
189 > new file mode 100644
189 > new file mode 100644
190 > --- /dev/null
190 > --- /dev/null
191 > +++ b/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz
191 > +++ b/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz
192 > @@ -0,0 +1,1 @@
192 > @@ -0,0 +1,1 @@
193 > +foo
193 > +foo
194 > diff --git a/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT b/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT
194 > diff --git a/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT b/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT
195 > new file mode 100644
195 > new file mode 100644
196 > --- /dev/null
196 > --- /dev/null
197 > +++ b/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT
197 > +++ b/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT
198 > @@ -0,0 +1,1 @@
198 > @@ -0,0 +1,1 @@
199 > +foo
199 > +foo
200 > diff --git a/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt b/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt
200 > diff --git a/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt b/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt
201 > new file mode 100644
201 > new file mode 100644
202 > --- /dev/null
202 > --- /dev/null
203 > +++ b/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt
203 > +++ b/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt
204 > @@ -0,0 +1,1 @@
204 > @@ -0,0 +1,1 @@
205 > +foo
205 > +foo
206 > diff --git a/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c b/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c
206 > diff --git a/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c b/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c
207 > new file mode 100644
207 > new file mode 100644
208 > --- /dev/null
208 > --- /dev/null
209 > +++ b/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c
209 > +++ b/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c
210 > @@ -0,0 +1,1 @@
210 > @@ -0,0 +1,1 @@
211 > +foo
211 > +foo
212 > diff --git a/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider b/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider
212 > diff --git a/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider b/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider
213 > new file mode 100644
213 > new file mode 100644
214 > --- /dev/null
214 > --- /dev/null
215 > +++ b/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider
215 > +++ b/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider
216 > @@ -0,0 +1,1 @@
216 > @@ -0,0 +1,1 @@
217 > +foo
217 > +foo
218 > EOF
218 > EOF
219
219
220 $ find .hg/store -name *.i | sort
220 $ find .hg/store -name *.i | sort
221 .hg/store/00changelog.i
221 .hg/store/00changelog.i
222 .hg/store/00manifest.i
222 .hg/store/00manifest.i
223 .hg/store/data/bla.aux/pr~6e/_p_r_n/lpt/co~6d3/nu~6c/coma/foo._n_u_l/normal.c.i
223 .hg/store/data/bla.aux/pr~6e/_p_r_n/lpt/co~6d3/nu~6c/coma/foo._n_u_l/normal.c.i
224 .hg/store/dh/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxx168e07b38e65eff86ab579afaaa8e30bfbe0f35f.i
224 .hg/store/dh/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxx168e07b38e65eff86ab579afaaa8e30bfbe0f35f.i
225 .hg/store/dh/au~78/second/x.prn/fourth/fi~3afth/sixth/seventh/eighth/nineth/tenth/loremia20419e358ddff1bf8751e38288aff1d7c32ec05.i
225 .hg/store/dh/au~78/second/x.prn/fourth/fi~3afth/sixth/seventh/eighth/nineth/tenth/loremia20419e358ddff1bf8751e38288aff1d7c32ec05.i
226 .hg/store/dh/enterpri/openesba/contrib-/corba-bc/netbeans/wsdlexte/src/main/java/org.net7018f27961fdf338a598a40c4683429e7ffb9743.i
226 .hg/store/dh/enterpri/openesba/contrib-/corba-bc/netbeans/wsdlexte/src/main/java/org.net7018f27961fdf338a598a40c4683429e7ffb9743.i
227 .hg/store/dh/project_/resource/anotherl/followed/andanoth/andthenanextremelylongfilename0d8e1f4187c650e2f1fdca9fd90f786bc0976b6b.i
227 .hg/store/dh/project_/resource/anotherl/followed/andanoth/andthenanextremelylongfilename0d8e1f4187c650e2f1fdca9fd90f786bc0976b6b.i
228
228
229 $ cd ..
229 $ cd ..
230
230
231 Aborting lock does not prevent fncache writes
231 Aborting lock does not prevent fncache writes
232
232
233 $ cat > exceptionext.py <<EOF
233 $ cat > exceptionext.py <<EOF
234 > from __future__ import absolute_import
234 > from __future__ import absolute_import
235 > import os
235 > import os
236 > from mercurial import commands, error, extensions
236 > from mercurial import commands, error, extensions
237 >
237 >
238 > def lockexception(orig, vfs, lockname, wait, releasefn, *args, **kwargs):
238 > def lockexception(orig, vfs, lockname, wait, releasefn, *args, **kwargs):
239 > def releasewrap():
239 > def releasewrap():
240 > l.held = False # ensure __del__ is a noop
240 > l.held = False # ensure __del__ is a noop
241 > raise error.Abort(b"forced lock failure")
241 > raise error.Abort(b"forced lock failure")
242 > l = orig(vfs, lockname, wait, releasewrap, *args, **kwargs)
242 > l = orig(vfs, lockname, wait, releasewrap, *args, **kwargs)
243 > return l
243 > return l
244 >
244 >
245 > def reposetup(ui, repo):
245 > def reposetup(ui, repo):
246 > extensions.wrapfunction(repo, '_lock', lockexception)
246 > extensions.wrapfunction(repo, '_lock', lockexception)
247 >
247 >
248 > cmdtable = {}
248 > cmdtable = {}
249 >
249 >
250 > # wrap "commit" command to prevent wlock from being '__del__()'-ed
250 > # wrap "commit" command to prevent wlock from being '__del__()'-ed
251 > # at the end of dispatching (for intentional "forced lcok failure")
251 > # at the end of dispatching (for intentional "forced lcok failure")
252 > def commitwrap(orig, ui, repo, *pats, **opts):
252 > def commitwrap(orig, ui, repo, *pats, **opts):
253 > repo = repo.unfiltered() # to use replaced repo._lock certainly
253 > repo = repo.unfiltered() # to use replaced repo._lock certainly
254 > wlock = repo.wlock()
254 > wlock = repo.wlock()
255 > try:
255 > try:
256 > return orig(ui, repo, *pats, **opts)
256 > return orig(ui, repo, *pats, **opts)
257 > finally:
257 > finally:
258 > # multiple 'relase()' is needed for complete releasing wlock,
258 > # multiple 'relase()' is needed for complete releasing wlock,
259 > # because "forced" abort at last releasing store lock
259 > # because "forced" abort at last releasing store lock
260 > # prevents wlock from being released at same 'lockmod.release()'
260 > # prevents wlock from being released at same 'lockmod.release()'
261 > for i in range(wlock.held):
261 > for i in range(wlock.held):
262 > wlock.release()
262 > wlock.release()
263 >
263 >
264 > def extsetup(ui):
264 > def extsetup(ui):
265 > extensions.wrapcommand(commands.table, b"commit", commitwrap)
265 > extensions.wrapcommand(commands.table, b"commit", commitwrap)
266 > EOF
266 > EOF
267 $ extpath=`pwd`/exceptionext.py
267 $ extpath=`pwd`/exceptionext.py
268 $ hg init fncachetxn
268 $ hg init fncachetxn
269 $ cd fncachetxn
269 $ cd fncachetxn
270 $ printf "[extensions]\nexceptionext=$extpath\n" >> .hg/hgrc
270 $ printf "[extensions]\nexceptionext=$extpath\n" >> .hg/hgrc
271 $ touch y
271 $ touch y
272 $ hg ci -qAm y
272 $ hg ci -qAm y
273 abort: forced lock failure
273 abort: forced lock failure
274 [255]
274 [255]
275 $ cat .hg/store/fncache
275 $ cat .hg/store/fncache
276 data/y.i
276 data/y.i
277
277
278 Aborting transaction prevents fncache change
278 Aborting transaction prevents fncache change
279
279
280 $ cat > ../exceptionext.py <<EOF
280 $ cat > ../exceptionext.py <<EOF
281 > from __future__ import absolute_import
281 > from __future__ import absolute_import
282 > import os
282 > import os
283 > from mercurial import commands, error, extensions, localrepo
283 > from mercurial import commands, error, extensions, localrepo
284 >
284 >
285 > def wrapper(orig, self, *args, **kwargs):
285 > def wrapper(orig, self, *args, **kwargs):
286 > tr = orig(self, *args, **kwargs)
286 > tr = orig(self, *args, **kwargs)
287 > def fail(tr):
287 > def fail(tr):
288 > raise error.Abort(b"forced transaction failure")
288 > raise error.Abort(b"forced transaction failure")
289 > # zzz prefix to ensure it sorted after store.write
289 > # zzz prefix to ensure it sorted after store.write
290 > tr.addfinalize(b'zzz-forcefails', fail)
290 > tr.addfinalize(b'zzz-forcefails', fail)
291 > return tr
291 > return tr
292 >
292 >
293 > def uisetup(ui):
293 > def uisetup(ui):
294 > extensions.wrapfunction(
294 > extensions.wrapfunction(
295 > localrepo.localrepository, b'transaction', wrapper)
295 > localrepo.localrepository, b'transaction', wrapper)
296 >
296 >
297 > cmdtable = {}
297 > cmdtable = {}
298 >
298 >
299 > EOF
299 > EOF
300
300
301 Clean cached version
301 Clean cached version
302 $ rm -f "${extpath}c"
302 $ rm -f "${extpath}c"
303 $ rm -Rf "`dirname $extpath`/__pycache__"
303 $ rm -Rf "`dirname $extpath`/__pycache__"
304
304
305 $ touch z
305 $ touch z
306 $ hg ci -qAm z
306 $ hg ci -qAm z
307 transaction abort!
307 transaction abort!
308 rollback completed
308 rollback completed
309 abort: forced transaction failure
309 abort: forced transaction failure
310 [255]
310 [255]
311 $ cat .hg/store/fncache
311 $ cat .hg/store/fncache
312 data/y.i
312 data/y.i
313
313
314 Aborted transactions can be recovered later
314 Aborted transactions can be recovered later
315
315
316 $ cat > ../exceptionext.py <<EOF
316 $ cat > ../exceptionext.py <<EOF
317 > from __future__ import absolute_import
317 > from __future__ import absolute_import
318 > import os
318 > import os
319 > from mercurial import (
319 > from mercurial import (
320 > commands,
320 > commands,
321 > error,
321 > error,
322 > extensions,
322 > extensions,
323 > localrepo,
323 > localrepo,
324 > transaction,
324 > transaction,
325 > )
325 > )
326 >
326 >
327 > def trwrapper(orig, self, *args, **kwargs):
327 > def trwrapper(orig, self, *args, **kwargs):
328 > tr = orig(self, *args, **kwargs)
328 > tr = orig(self, *args, **kwargs)
329 > def fail(tr):
329 > def fail(tr):
330 > raise error.Abort(b"forced transaction failure")
330 > raise error.Abort(b"forced transaction failure")
331 > # zzz prefix to ensure it sorted after store.write
331 > # zzz prefix to ensure it sorted after store.write
332 > tr.addfinalize(b'zzz-forcefails', fail)
332 > tr.addfinalize(b'zzz-forcefails', fail)
333 > return tr
333 > return tr
334 >
334 >
335 > def abortwrapper(orig, self, *args, **kwargs):
335 > def abortwrapper(orig, self, *args, **kwargs):
336 > raise error.Abort(b"forced transaction failure")
336 > raise error.Abort(b"forced transaction failure")
337 >
337 >
338 > def uisetup(ui):
338 > def uisetup(ui):
339 > extensions.wrapfunction(localrepo.localrepository, 'transaction',
339 > extensions.wrapfunction(localrepo.localrepository, 'transaction',
340 > trwrapper)
340 > trwrapper)
341 > extensions.wrapfunction(transaction.transaction, '_abort',
341 > extensions.wrapfunction(transaction.transaction, '_abort',
342 > abortwrapper)
342 > abortwrapper)
343 >
343 >
344 > cmdtable = {}
344 > cmdtable = {}
345 >
345 >
346 > EOF
346 > EOF
347
347
348 Clean cached versions
348 Clean cached versions
349 $ rm -f "${extpath}c"
349 $ rm -f "${extpath}c"
350 $ rm -Rf "`dirname $extpath`/__pycache__"
350 $ rm -Rf "`dirname $extpath`/__pycache__"
351
351
352 $ hg up -q 1
352 $ hg up -q 1
353 $ touch z
353 $ touch z
354 $ hg ci -qAm z 2>/dev/null
354 $ hg ci -qAm z 2>/dev/null
355 [255]
355 [255]
356 $ cat .hg/store/fncache | sort
356 $ cat .hg/store/fncache | sort
357 data/y.i
357 data/y.i
358 data/z.i
358 data/z.i
359 $ hg recover --verify
359 $ hg recover --verify
360 rolling back interrupted transaction
360 rolling back interrupted transaction
361 checking changesets
361 checking changesets
362 checking manifests
362 checking manifests
363 crosschecking files in changesets and manifests
363 crosschecking files in changesets and manifests
364 checking files
364 checking files
365 checked 1 changesets with 1 changes to 1 files
365 checked 1 changesets with 1 changes to 1 files
366 $ cat .hg/store/fncache
366 $ cat .hg/store/fncache
367 data/y.i
367 data/y.i
368
368
369 $ cd ..
369 $ cd ..
370
370
371 debugrebuildfncache does nothing unless repo has fncache requirement
371 debugrebuildfncache does nothing unless repo has fncache requirement
372
372
373 $ hg --config format.usefncache=false init nofncache
373 $ hg --config format.usefncache=false init nofncache
374 $ cd nofncache
374 $ cd nofncache
375 $ hg debugrebuildfncache
375 $ hg debugrebuildfncache
376 (not rebuilding fncache because repository does not support fncache)
376 (not rebuilding fncache because repository does not support fncache)
377
377
378 $ cd ..
378 $ cd ..
379
379
380 debugrebuildfncache works on empty repository
380 debugrebuildfncache works on empty repository
381
381
382 $ hg init empty
382 $ hg init empty
383 $ cd empty
383 $ cd empty
384 $ hg debugrebuildfncache
384 $ hg debugrebuildfncache
385 fncache already up to date
385 fncache already up to date
386 $ cd ..
386 $ cd ..
387
387
388 debugrebuildfncache on an up to date repository no-ops
388 debugrebuildfncache on an up to date repository no-ops
389
389
390 $ hg init repo
390 $ hg init repo
391 $ cd repo
391 $ cd repo
392 $ echo initial > foo
392 $ echo initial > foo
393 $ echo initial > .bar
393 $ echo initial > .bar
394 $ hg commit -A -m initial
394 $ hg commit -A -m initial
395 adding .bar
395 adding .bar
396 adding foo
396 adding foo
397
397
398 $ cat .hg/store/fncache | sort
398 $ cat .hg/store/fncache | sort
399 data/.bar.i
399 data/.bar.i
400 data/foo.i
400 data/foo.i
401
401
402 $ hg debugrebuildfncache
402 $ hg debugrebuildfncache
403 fncache already up to date
403 fncache already up to date
404
404
405 debugrebuildfncache restores deleted fncache file
405 debugrebuildfncache restores deleted fncache file
406
406
407 $ rm -f .hg/store/fncache
407 $ rm -f .hg/store/fncache
408 $ hg debugrebuildfncache
408 $ hg debugrebuildfncache
409 adding data/.bar.i
409 adding data/.bar.i
410 adding data/foo.i
410 adding data/foo.i
411 2 items added, 0 removed from fncache
411 2 items added, 0 removed from fncache
412
412
413 $ cat .hg/store/fncache | sort
413 $ cat .hg/store/fncache | sort
414 data/.bar.i
414 data/.bar.i
415 data/foo.i
415 data/foo.i
416
416
417 Rebuild after rebuild should no-op
417 Rebuild after rebuild should no-op
418
418
419 $ hg debugrebuildfncache
419 $ hg debugrebuildfncache
420 fncache already up to date
420 fncache already up to date
421
421
422 A single missing file should get restored, an extra file should be removed
422 A single missing file should get restored, an extra file should be removed
423
423
424 $ cat > .hg/store/fncache << EOF
424 $ cat > .hg/store/fncache << EOF
425 > data/foo.i
425 > data/foo.i
426 > data/bad-entry.i
426 > data/bad-entry.i
427 > EOF
427 > EOF
428
428
429 $ hg debugrebuildfncache
429 $ hg debugrebuildfncache
430 removing data/bad-entry.i
430 removing data/bad-entry.i
431 adding data/.bar.i
431 adding data/.bar.i
432 1 items added, 1 removed from fncache
432 1 items added, 1 removed from fncache
433
433
434 $ cat .hg/store/fncache | sort
434 $ cat .hg/store/fncache | sort
435 data/.bar.i
435 data/.bar.i
436 data/foo.i
436 data/foo.i
437
437
438 debugrebuildfncache recovers from truncated line in fncache
438 debugrebuildfncache recovers from truncated line in fncache
439
439
440 $ printf a > .hg/store/fncache
440 $ printf a > .hg/store/fncache
441 $ hg debugrebuildfncache
441 $ hg debugrebuildfncache
442 fncache does not ends with a newline
442 fncache does not ends with a newline
443 adding data/.bar.i
443 adding data/.bar.i
444 adding data/foo.i
444 adding data/foo.i
445 2 items added, 0 removed from fncache
445 2 items added, 0 removed from fncache
446
446
447 $ cat .hg/store/fncache | sort
447 $ cat .hg/store/fncache | sort
448 data/.bar.i
448 data/.bar.i
449 data/foo.i
449 data/foo.i
450
450
451 $ cd ..
451 $ cd ..
452
452
453 Try a simple variation without dotencode to ensure fncache is ignorant of encoding
453 Try a simple variation without dotencode to ensure fncache is ignorant of encoding
454
454
455 $ hg --config format.dotencode=false init nodotencode
455 $ hg --config format.dotencode=false init nodotencode
456 $ cd nodotencode
456 $ cd nodotencode
457 $ echo initial > foo
457 $ echo initial > foo
458 $ echo initial > .bar
458 $ echo initial > .bar
459 $ hg commit -A -m initial
459 $ hg commit -A -m initial
460 adding .bar
460 adding .bar
461 adding foo
461 adding foo
462
462
463 $ cat .hg/store/fncache | sort
463 $ cat .hg/store/fncache | sort
464 data/.bar.i
464 data/.bar.i
465 data/foo.i
465 data/foo.i
466
466
467 $ rm .hg/store/fncache
467 $ rm .hg/store/fncache
468 $ hg debugrebuildfncache
468 $ hg debugrebuildfncache
469 adding data/.bar.i
469 adding data/.bar.i
470 adding data/foo.i
470 adding data/foo.i
471 2 items added, 0 removed from fncache
471 2 items added, 0 removed from fncache
472
472
473 $ cat .hg/store/fncache | sort
473 $ cat .hg/store/fncache | sort
474 data/.bar.i
474 data/.bar.i
475 data/foo.i
475 data/foo.i
476
476
477 $ cd ..
477 $ cd ..
478
478
479 In repositories that have accumulated a large number of files over time, the
479 In repositories that have accumulated a large number of files over time, the
480 fncache file is going to be large. If we possibly can avoid loading it, so much the better.
480 fncache file is going to be large. If we possibly can avoid loading it, so much the better.
481 The cache should not loaded when committing changes to existing files, or when unbundling
481 The cache should not loaded when committing changes to existing files, or when unbundling
482 changesets that only contain changes to existing files:
482 changesets that only contain changes to existing files:
483
483
484 $ cat > fncacheloadwarn.py << EOF
484 $ cat > fncacheloadwarn.py << EOF
485 > from __future__ import absolute_import
485 > from __future__ import absolute_import
486 > from mercurial import extensions, localrepo
486 > from mercurial import extensions, localrepo
487 >
487 >
488 > def extsetup(ui):
488 > def extsetup(ui):
489 > def wrapstore(orig, requirements, *args):
489 > def wrapstore(orig, requirements, *args):
490 > store = orig(requirements, *args)
490 > store = orig(requirements, *args)
491 > if b'store' in requirements and b'fncache' in requirements:
491 > if b'store' in requirements and b'fncache' in requirements:
492 > instrumentfncachestore(store, ui)
492 > instrumentfncachestore(store, ui)
493 > return store
493 > return store
494 > extensions.wrapfunction(localrepo, 'makestore', wrapstore)
494 > extensions.wrapfunction(localrepo, 'makestore', wrapstore)
495 >
495 >
496 > def instrumentfncachestore(fncachestore, ui):
496 > def instrumentfncachestore(fncachestore, ui):
497 > class instrumentedfncache(type(fncachestore.fncache)):
497 > class instrumentedfncache(type(fncachestore.fncache)):
498 > def _load(self):
498 > def _load(self):
499 > ui.warn(b'fncache load triggered!\n')
499 > ui.warn(b'fncache load triggered!\n')
500 > super(instrumentedfncache, self)._load()
500 > super(instrumentedfncache, self)._load()
501 > fncachestore.fncache.__class__ = instrumentedfncache
501 > fncachestore.fncache.__class__ = instrumentedfncache
502 > EOF
502 > EOF
503
503
504 $ fncachextpath=`pwd`/fncacheloadwarn.py
504 $ fncachextpath=`pwd`/fncacheloadwarn.py
505 $ hg init nofncacheload
505 $ hg init nofncacheload
506 $ cd nofncacheload
506 $ cd nofncacheload
507 $ printf "[extensions]\nfncacheloadwarn=$fncachextpath\n" >> .hg/hgrc
507 $ printf "[extensions]\nfncacheloadwarn=$fncachextpath\n" >> .hg/hgrc
508
508
509 A new file should trigger a load, as we'd want to update the fncache set in that case:
509 A new file should trigger a load, as we'd want to update the fncache set in that case:
510
510
511 $ touch foo
511 $ touch foo
512 $ hg ci -qAm foo
512 $ hg ci -qAm foo
513 fncache load triggered!
513 fncache load triggered!
514
514
515 But modifying that file should not:
515 But modifying that file should not:
516
516
517 $ echo bar >> foo
517 $ echo bar >> foo
518 $ hg ci -qm foo
518 $ hg ci -qm foo
519
519
520 If a transaction has been aborted, the zero-size truncated index file will
520 If a transaction has been aborted, the zero-size truncated index file will
521 not prevent the fncache from being loaded; rather than actually abort
521 not prevent the fncache from being loaded; rather than actually abort
522 a transaction, we simulate the situation by creating a zero-size index file:
522 a transaction, we simulate the situation by creating a zero-size index file:
523
523
524 $ touch .hg/store/data/bar.i
524 $ touch .hg/store/data/bar.i
525 $ touch bar
525 $ touch bar
526 $ hg ci -qAm bar
526 $ hg ci -qAm bar
527 fncache load triggered!
527 fncache load triggered!
528
528
529 Unbundling should follow the same rules; existing files should not cause a load:
529 Unbundling should follow the same rules; existing files should not cause a load:
530
530
531 (loading during the clone is expected)
531 $ hg clone -q . tobundle
532 $ hg clone -q . tobundle
533 fncache load triggered!
534 fncache load triggered!
535
532 $ echo 'new line' > tobundle/bar
536 $ echo 'new line' > tobundle/bar
533 $ hg -R tobundle ci -qm bar
537 $ hg -R tobundle ci -qm bar
534 $ hg -R tobundle bundle -q barupdated.hg
538 $ hg -R tobundle bundle -q barupdated.hg
535 $ hg unbundle -q barupdated.hg
539 $ hg unbundle -q barupdated.hg
536
540
537 but adding new files should:
541 but adding new files should:
538
542
539 $ touch tobundle/newfile
543 $ touch tobundle/newfile
540 $ hg -R tobundle ci -qAm newfile
544 $ hg -R tobundle ci -qAm newfile
541 $ hg -R tobundle bundle -q newfile.hg
545 $ hg -R tobundle bundle -q newfile.hg
542 $ hg unbundle -q newfile.hg
546 $ hg unbundle -q newfile.hg
543 fncache load triggered!
547 fncache load triggered!
544
548
545 $ cd ..
549 $ cd ..
@@ -1,445 +1,445 b''
1 #require hardlink reporevlogstore
1 #require hardlink reporevlogstore
2
2
3 $ cat > nlinks.py <<EOF
3 $ cat > nlinks.py <<EOF
4 > from __future__ import print_function
4 > from __future__ import print_function
5 > import sys
5 > import sys
6 > from mercurial import pycompat, util
6 > from mercurial import pycompat, util
7 > for f in sorted(sys.stdin.readlines()):
7 > for f in sorted(sys.stdin.readlines()):
8 > f = f[:-1]
8 > f = f[:-1]
9 > print(util.nlinks(pycompat.fsencode(f)), f)
9 > print(util.nlinks(pycompat.fsencode(f)), f)
10 > EOF
10 > EOF
11
11
12 $ nlinksdir()
12 $ nlinksdir()
13 > {
13 > {
14 > find "$@" -type f | "$PYTHON" $TESTTMP/nlinks.py
14 > find "$@" -type f | "$PYTHON" $TESTTMP/nlinks.py
15 > }
15 > }
16
16
17 Some implementations of cp can't create hardlinks (replaces 'cp -al' on Linux):
17 Some implementations of cp can't create hardlinks (replaces 'cp -al' on Linux):
18
18
19 $ cat > linkcp.py <<EOF
19 $ cat > linkcp.py <<EOF
20 > from __future__ import absolute_import
20 > from __future__ import absolute_import
21 > import sys
21 > import sys
22 > from mercurial import pycompat, util
22 > from mercurial import pycompat, util
23 > util.copyfiles(pycompat.fsencode(sys.argv[1]),
23 > util.copyfiles(pycompat.fsencode(sys.argv[1]),
24 > pycompat.fsencode(sys.argv[2]), hardlink=True)
24 > pycompat.fsencode(sys.argv[2]), hardlink=True)
25 > EOF
25 > EOF
26
26
27 $ linkcp()
27 $ linkcp()
28 > {
28 > {
29 > "$PYTHON" $TESTTMP/linkcp.py $1 $2
29 > "$PYTHON" $TESTTMP/linkcp.py $1 $2
30 > }
30 > }
31
31
32 Prepare repo r1:
32 Prepare repo r1:
33
33
34 $ hg init r1
34 $ hg init r1
35 $ cd r1
35 $ cd r1
36
36
37 $ echo c1 > f1
37 $ echo c1 > f1
38 $ hg add f1
38 $ hg add f1
39 $ hg ci -m0
39 $ hg ci -m0
40
40
41 $ mkdir d1
41 $ mkdir d1
42 $ cd d1
42 $ cd d1
43 $ echo c2 > f2
43 $ echo c2 > f2
44 $ hg add f2
44 $ hg add f2
45 $ hg ci -m1
45 $ hg ci -m1
46 $ cd ../..
46 $ cd ../..
47
47
48 $ nlinksdir r1/.hg/store
48 $ nlinksdir r1/.hg/store
49 1 r1/.hg/store/00changelog.i
49 1 r1/.hg/store/00changelog.i
50 1 r1/.hg/store/00manifest.i
50 1 r1/.hg/store/00manifest.i
51 1 r1/.hg/store/data/d1/f2.i
51 1 r1/.hg/store/data/d1/f2.i
52 1 r1/.hg/store/data/f1.i
52 1 r1/.hg/store/data/f1.i
53 1 r1/.hg/store/fncache (repofncache !)
53 1 r1/.hg/store/fncache (repofncache !)
54 1 r1/.hg/store/phaseroots
54 1 r1/.hg/store/phaseroots
55 1 r1/.hg/store/undo
55 1 r1/.hg/store/undo
56 1 r1/.hg/store/undo.backup.fncache (repofncache !)
56 1 r1/.hg/store/undo.backup.fncache (repofncache !)
57 1 r1/.hg/store/undo.backupfiles
57 1 r1/.hg/store/undo.backupfiles
58 1 r1/.hg/store/undo.phaseroots
58 1 r1/.hg/store/undo.phaseroots
59
59
60
60
61 Create hardlinked clone r2:
61 Create hardlinked clone r2:
62
62
63 $ hg clone -U --debug r1 r2 --config progress.debug=true
63 $ hg clone -U --debug r1 r2 --config progress.debug=true
64 linking: 1 files
64 linking: 1/7 files (14.29%)
65 linking: 2 files
65 linking: 2/7 files (28.57%)
66 linking: 3 files
66 linking: 3/7 files (42.86%)
67 linking: 4 files
67 linking: 4/7 files (57.14%)
68 linking: 5 files
68 linking: 5/7 files (71.43%)
69 linking: 6 files
69 linking: 6/7 files (85.71%)
70 linking: 7 files
70 linking: 7/7 files (100.00%)
71 linked 7 files
71 linked 7 files
72 updating the branch cache
72 updating the branch cache
73
73
74 Create non-hardlinked clone r3:
74 Create non-hardlinked clone r3:
75
75
76 $ hg clone --pull r1 r3
76 $ hg clone --pull r1 r3
77 requesting all changes
77 requesting all changes
78 adding changesets
78 adding changesets
79 adding manifests
79 adding manifests
80 adding file changes
80 adding file changes
81 added 2 changesets with 2 changes to 2 files
81 added 2 changesets with 2 changes to 2 files
82 new changesets 40d85e9847f2:7069c422939c
82 new changesets 40d85e9847f2:7069c422939c
83 updating to branch default
83 updating to branch default
84 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
84 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
85
85
86
86
87 Repos r1 and r2 should now contain hardlinked files:
87 Repos r1 and r2 should now contain hardlinked files:
88
88
89 $ nlinksdir r1/.hg/store
89 $ nlinksdir r1/.hg/store
90 2 r1/.hg/store/00changelog.i
90 2 r1/.hg/store/00changelog.i
91 2 r1/.hg/store/00manifest.i
91 2 r1/.hg/store/00manifest.i
92 2 r1/.hg/store/data/d1/f2.i
92 2 r1/.hg/store/data/d1/f2.i
93 2 r1/.hg/store/data/f1.i
93 2 r1/.hg/store/data/f1.i
94 2 r1/.hg/store/fncache (repofncache !)
94 1 r1/.hg/store/fncache (repofncache !)
95 1 r1/.hg/store/phaseroots
95 1 r1/.hg/store/phaseroots
96 1 r1/.hg/store/undo
96 1 r1/.hg/store/undo
97 1 r1/.hg/store/undo.backup.fncache (repofncache !)
97 1 r1/.hg/store/undo.backup.fncache (repofncache !)
98 1 r1/.hg/store/undo.backupfiles
98 1 r1/.hg/store/undo.backupfiles
99 1 r1/.hg/store/undo.phaseroots
99 1 r1/.hg/store/undo.phaseroots
100
100
101 $ nlinksdir r2/.hg/store
101 $ nlinksdir r2/.hg/store
102 2 r2/.hg/store/00changelog.i
102 2 r2/.hg/store/00changelog.i
103 2 r2/.hg/store/00manifest.i
103 2 r2/.hg/store/00manifest.i
104 2 r2/.hg/store/data/d1/f2.i
104 2 r2/.hg/store/data/d1/f2.i
105 2 r2/.hg/store/data/f1.i
105 2 r2/.hg/store/data/f1.i
106 2 r2/.hg/store/fncache (repofncache !)
106 1 r2/.hg/store/fncache (repofncache !)
107
107
108 Repo r3 should not be hardlinked:
108 Repo r3 should not be hardlinked:
109
109
110 $ nlinksdir r3/.hg/store
110 $ nlinksdir r3/.hg/store
111 1 r3/.hg/store/00changelog.i
111 1 r3/.hg/store/00changelog.i
112 1 r3/.hg/store/00manifest.i
112 1 r3/.hg/store/00manifest.i
113 1 r3/.hg/store/data/d1/f2.i
113 1 r3/.hg/store/data/d1/f2.i
114 1 r3/.hg/store/data/f1.i
114 1 r3/.hg/store/data/f1.i
115 1 r3/.hg/store/fncache (repofncache !)
115 1 r3/.hg/store/fncache (repofncache !)
116 1 r3/.hg/store/phaseroots
116 1 r3/.hg/store/phaseroots
117 1 r3/.hg/store/undo
117 1 r3/.hg/store/undo
118 1 r3/.hg/store/undo.backupfiles
118 1 r3/.hg/store/undo.backupfiles
119 1 r3/.hg/store/undo.phaseroots
119 1 r3/.hg/store/undo.phaseroots
120
120
121
121
122 Create a non-inlined filelog in r3:
122 Create a non-inlined filelog in r3:
123
123
124 $ cd r3/d1
124 $ cd r3/d1
125 >>> f = open('data1', 'wb')
125 >>> f = open('data1', 'wb')
126 >>> for x in range(10000):
126 >>> for x in range(10000):
127 ... f.write(b"%d\n" % x) and None
127 ... f.write(b"%d\n" % x) and None
128 >>> f.close()
128 >>> f.close()
129 $ for j in 0 1 2 3 4 5 6 7 8 9; do
129 $ for j in 0 1 2 3 4 5 6 7 8 9; do
130 > cat data1 >> f2
130 > cat data1 >> f2
131 > hg commit -m$j
131 > hg commit -m$j
132 > done
132 > done
133 $ cd ../..
133 $ cd ../..
134
134
135 $ nlinksdir r3/.hg/store
135 $ nlinksdir r3/.hg/store
136 1 r3/.hg/store/00changelog.i
136 1 r3/.hg/store/00changelog.i
137 1 r3/.hg/store/00manifest.i
137 1 r3/.hg/store/00manifest.i
138 1 r3/.hg/store/data/d1/f2.d
138 1 r3/.hg/store/data/d1/f2.d
139 1 r3/.hg/store/data/d1/f2.i
139 1 r3/.hg/store/data/d1/f2.i
140 1 r3/.hg/store/data/f1.i
140 1 r3/.hg/store/data/f1.i
141 1 r3/.hg/store/fncache (repofncache !)
141 1 r3/.hg/store/fncache (repofncache !)
142 1 r3/.hg/store/phaseroots
142 1 r3/.hg/store/phaseroots
143 1 r3/.hg/store/undo
143 1 r3/.hg/store/undo
144 1 r3/.hg/store/undo.backup.fncache (repofncache !)
144 1 r3/.hg/store/undo.backup.fncache (repofncache !)
145 1 r3/.hg/store/undo.backup.phaseroots
145 1 r3/.hg/store/undo.backup.phaseroots
146 1 r3/.hg/store/undo.backupfiles
146 1 r3/.hg/store/undo.backupfiles
147 1 r3/.hg/store/undo.phaseroots
147 1 r3/.hg/store/undo.phaseroots
148
148
149 Push to repo r1 should break up most hardlinks in r2:
149 Push to repo r1 should break up most hardlinks in r2:
150
150
151 $ hg -R r2 verify
151 $ hg -R r2 verify
152 checking changesets
152 checking changesets
153 checking manifests
153 checking manifests
154 crosschecking files in changesets and manifests
154 crosschecking files in changesets and manifests
155 checking files
155 checking files
156 checked 2 changesets with 2 changes to 2 files
156 checked 2 changesets with 2 changes to 2 files
157
157
158 $ cd r3
158 $ cd r3
159 $ hg push
159 $ hg push
160 pushing to $TESTTMP/r1
160 pushing to $TESTTMP/r1
161 searching for changes
161 searching for changes
162 adding changesets
162 adding changesets
163 adding manifests
163 adding manifests
164 adding file changes
164 adding file changes
165 added 10 changesets with 10 changes to 1 files
165 added 10 changesets with 10 changes to 1 files
166
166
167 $ cd ..
167 $ cd ..
168
168
169 $ nlinksdir r2/.hg/store
169 $ nlinksdir r2/.hg/store
170 1 r2/.hg/store/00changelog.i
170 1 r2/.hg/store/00changelog.i
171 1 r2/.hg/store/00manifest.i
171 1 r2/.hg/store/00manifest.i
172 1 r2/.hg/store/data/d1/f2.i
172 1 r2/.hg/store/data/d1/f2.i
173 2 r2/.hg/store/data/f1.i
173 2 r2/.hg/store/data/f1.i
174 [12] r2/\.hg/store/fncache (re) (repofncache !)
174 [12] r2/\.hg/store/fncache (re) (repofncache !)
175
175
176 #if hardlink-whitelisted repofncache
176 #if hardlink-whitelisted repofncache
177 $ nlinksdir r2/.hg/store/fncache
177 $ nlinksdir r2/.hg/store/fncache
178 2 r2/.hg/store/fncache
178 1 r2/.hg/store/fncache
179 #endif
179 #endif
180
180
181 $ hg -R r2 verify
181 $ hg -R r2 verify
182 checking changesets
182 checking changesets
183 checking manifests
183 checking manifests
184 crosschecking files in changesets and manifests
184 crosschecking files in changesets and manifests
185 checking files
185 checking files
186 checked 2 changesets with 2 changes to 2 files
186 checked 2 changesets with 2 changes to 2 files
187
187
188
188
189 $ cd r1
189 $ cd r1
190 $ hg up
190 $ hg up
191 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
191 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
192
192
193 Committing a change to f1 in r1 must break up hardlink f1.i in r2:
193 Committing a change to f1 in r1 must break up hardlink f1.i in r2:
194
194
195 $ echo c1c1 >> f1
195 $ echo c1c1 >> f1
196 $ hg ci -m00
196 $ hg ci -m00
197 $ cd ..
197 $ cd ..
198
198
199 $ nlinksdir r2/.hg/store
199 $ nlinksdir r2/.hg/store
200 1 r2/.hg/store/00changelog.i
200 1 r2/.hg/store/00changelog.i
201 1 r2/.hg/store/00manifest.i
201 1 r2/.hg/store/00manifest.i
202 1 r2/.hg/store/data/d1/f2.i
202 1 r2/.hg/store/data/d1/f2.i
203 1 r2/.hg/store/data/f1.i
203 1 r2/.hg/store/data/f1.i
204 [12] r2/\.hg/store/fncache (re) (repofncache !)
204 1 r2/.hg/store/fncache (repofncache !)
205
205
206 #if hardlink-whitelisted repofncache
206 #if hardlink-whitelisted repofncache
207 $ nlinksdir r2/.hg/store/fncache
207 $ nlinksdir r2/.hg/store/fncache
208 2 r2/.hg/store/fncache
208 1 r2/.hg/store/fncache
209 #endif
209 #endif
210
210
211 Create a file which exec permissions we will change
211 Create a file which exec permissions we will change
212 $ cd r3
212 $ cd r3
213 $ echo "echo hello world" > f3
213 $ echo "echo hello world" > f3
214 $ hg add f3
214 $ hg add f3
215 $ hg ci -mf3
215 $ hg ci -mf3
216 $ cd ..
216 $ cd ..
217
217
218 $ cd r3
218 $ cd r3
219 $ hg tip --template '{rev}:{node|short}\n'
219 $ hg tip --template '{rev}:{node|short}\n'
220 12:d3b77733a28a
220 12:d3b77733a28a
221 $ echo bla > f1
221 $ echo bla > f1
222 $ chmod +x f3
222 $ chmod +x f3
223 $ hg ci -m1
223 $ hg ci -m1
224 $ cd ..
224 $ cd ..
225
225
226 Create hardlinked copy r4 of r3 (on Linux, we would call 'cp -al'):
226 Create hardlinked copy r4 of r3 (on Linux, we would call 'cp -al'):
227
227
228 $ linkcp r3 r4
228 $ linkcp r3 r4
229
229
230 'checklink' is produced by hardlinking a symlink, which is undefined whether
230 'checklink' is produced by hardlinking a symlink, which is undefined whether
231 the symlink should be followed or not. It does behave differently on Linux and
231 the symlink should be followed or not. It does behave differently on Linux and
232 BSD. Just remove it so the test pass on both platforms.
232 BSD. Just remove it so the test pass on both platforms.
233
233
234 $ rm -f r4/.hg/wcache/checklink
234 $ rm -f r4/.hg/wcache/checklink
235
235
236 r4 has hardlinks in the working dir (not just inside .hg):
236 r4 has hardlinks in the working dir (not just inside .hg):
237
237
238 $ nlinksdir r4
238 $ nlinksdir r4
239 2 r4/.hg/00changelog.i
239 2 r4/.hg/00changelog.i
240 2 r4/.hg/branch
240 2 r4/.hg/branch
241 2 r4/.hg/cache/branch2-base
241 2 r4/.hg/cache/branch2-base
242 2 r4/.hg/cache/branch2-immutable
242 2 r4/.hg/cache/branch2-immutable
243 2 r4/.hg/cache/branch2-served
243 2 r4/.hg/cache/branch2-served
244 2 r4/.hg/cache/branch2-served.hidden
244 2 r4/.hg/cache/branch2-served.hidden
245 2 r4/.hg/cache/branch2-visible
245 2 r4/.hg/cache/branch2-visible
246 2 r4/.hg/cache/branch2-visible-hidden
246 2 r4/.hg/cache/branch2-visible-hidden
247 2 r4/.hg/cache/rbc-names-v1
247 2 r4/.hg/cache/rbc-names-v1
248 2 r4/.hg/cache/rbc-revs-v1
248 2 r4/.hg/cache/rbc-revs-v1
249 2 r4/.hg/cache/tags2
249 2 r4/.hg/cache/tags2
250 2 r4/.hg/cache/tags2-served
250 2 r4/.hg/cache/tags2-served
251 2 r4/.hg/dirstate
251 2 r4/.hg/dirstate
252 2 r4/.hg/fsmonitor.state (fsmonitor !)
252 2 r4/.hg/fsmonitor.state (fsmonitor !)
253 2 r4/.hg/hgrc
253 2 r4/.hg/hgrc
254 2 r4/.hg/last-message.txt
254 2 r4/.hg/last-message.txt
255 2 r4/.hg/requires
255 2 r4/.hg/requires
256 2 r4/.hg/store/00changelog.i
256 2 r4/.hg/store/00changelog.i
257 2 r4/.hg/store/00manifest.i
257 2 r4/.hg/store/00manifest.i
258 2 r4/.hg/store/data/d1/f2.d
258 2 r4/.hg/store/data/d1/f2.d
259 2 r4/.hg/store/data/d1/f2.i
259 2 r4/.hg/store/data/d1/f2.i
260 2 r4/.hg/store/data/f1.i
260 2 r4/.hg/store/data/f1.i
261 2 r4/.hg/store/data/f3.i
261 2 r4/.hg/store/data/f3.i
262 2 r4/.hg/store/fncache (repofncache !)
262 2 r4/.hg/store/fncache (repofncache !)
263 2 r4/.hg/store/phaseroots
263 2 r4/.hg/store/phaseroots
264 2 r4/.hg/store/undo
264 2 r4/.hg/store/undo
265 2 r4/.hg/store/undo.backup.fncache (repofncache !)
265 2 r4/.hg/store/undo.backup.fncache (repofncache !)
266 2 r4/.hg/store/undo.backup.phaseroots
266 2 r4/.hg/store/undo.backup.phaseroots
267 2 r4/.hg/store/undo.backupfiles
267 2 r4/.hg/store/undo.backupfiles
268 2 r4/.hg/store/undo.phaseroots
268 2 r4/.hg/store/undo.phaseroots
269 [24] r4/\.hg/undo\.backup\.dirstate (re)
269 [24] r4/\.hg/undo\.backup\.dirstate (re)
270 2 r4/.hg/undo.bookmarks
270 2 r4/.hg/undo.bookmarks
271 2 r4/.hg/undo.branch
271 2 r4/.hg/undo.branch
272 2 r4/.hg/undo.desc
272 2 r4/.hg/undo.desc
273 [24] r4/\.hg/undo\.dirstate (re)
273 [24] r4/\.hg/undo\.dirstate (re)
274 2 r4/.hg/wcache/checkisexec (execbit !)
274 2 r4/.hg/wcache/checkisexec (execbit !)
275 2 r4/.hg/wcache/checklink-target (symlink !)
275 2 r4/.hg/wcache/checklink-target (symlink !)
276 2 r4/.hg/wcache/checknoexec (execbit !)
276 2 r4/.hg/wcache/checknoexec (execbit !)
277 2 r4/.hg/wcache/manifestfulltextcache (reporevlogstore !)
277 2 r4/.hg/wcache/manifestfulltextcache (reporevlogstore !)
278 2 r4/d1/data1
278 2 r4/d1/data1
279 2 r4/d1/f2
279 2 r4/d1/f2
280 2 r4/f1
280 2 r4/f1
281 2 r4/f3
281 2 r4/f3
282
282
283 Update back to revision 12 in r4 should break hardlink of file f1 and f3:
283 Update back to revision 12 in r4 should break hardlink of file f1 and f3:
284 #if hardlink-whitelisted
284 #if hardlink-whitelisted
285 $ nlinksdir r4/.hg/undo.backup.dirstate r4/.hg/undo.dirstate
285 $ nlinksdir r4/.hg/undo.backup.dirstate r4/.hg/undo.dirstate
286 4 r4/.hg/undo.backup.dirstate
286 4 r4/.hg/undo.backup.dirstate
287 4 r4/.hg/undo.dirstate
287 4 r4/.hg/undo.dirstate
288 #endif
288 #endif
289
289
290
290
291 $ hg -R r4 up 12
291 $ hg -R r4 up 12
292 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (execbit !)
292 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (execbit !)
293 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-execbit !)
293 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-execbit !)
294
294
295 $ nlinksdir r4
295 $ nlinksdir r4
296 2 r4/.hg/00changelog.i
296 2 r4/.hg/00changelog.i
297 1 r4/.hg/branch
297 1 r4/.hg/branch
298 2 r4/.hg/cache/branch2-base
298 2 r4/.hg/cache/branch2-base
299 2 r4/.hg/cache/branch2-immutable
299 2 r4/.hg/cache/branch2-immutable
300 2 r4/.hg/cache/branch2-served
300 2 r4/.hg/cache/branch2-served
301 2 r4/.hg/cache/branch2-served.hidden
301 2 r4/.hg/cache/branch2-served.hidden
302 2 r4/.hg/cache/branch2-visible
302 2 r4/.hg/cache/branch2-visible
303 2 r4/.hg/cache/branch2-visible-hidden
303 2 r4/.hg/cache/branch2-visible-hidden
304 2 r4/.hg/cache/rbc-names-v1
304 2 r4/.hg/cache/rbc-names-v1
305 2 r4/.hg/cache/rbc-revs-v1
305 2 r4/.hg/cache/rbc-revs-v1
306 2 r4/.hg/cache/tags2
306 2 r4/.hg/cache/tags2
307 2 r4/.hg/cache/tags2-served
307 2 r4/.hg/cache/tags2-served
308 1 r4/.hg/dirstate
308 1 r4/.hg/dirstate
309 1 r4/.hg/fsmonitor.state (fsmonitor !)
309 1 r4/.hg/fsmonitor.state (fsmonitor !)
310 2 r4/.hg/hgrc
310 2 r4/.hg/hgrc
311 2 r4/.hg/last-message.txt
311 2 r4/.hg/last-message.txt
312 2 r4/.hg/requires
312 2 r4/.hg/requires
313 2 r4/.hg/store/00changelog.i
313 2 r4/.hg/store/00changelog.i
314 2 r4/.hg/store/00manifest.i
314 2 r4/.hg/store/00manifest.i
315 2 r4/.hg/store/data/d1/f2.d
315 2 r4/.hg/store/data/d1/f2.d
316 2 r4/.hg/store/data/d1/f2.i
316 2 r4/.hg/store/data/d1/f2.i
317 2 r4/.hg/store/data/f1.i
317 2 r4/.hg/store/data/f1.i
318 2 r4/.hg/store/data/f3.i
318 2 r4/.hg/store/data/f3.i
319 2 r4/.hg/store/fncache
319 2 r4/.hg/store/fncache
320 2 r4/.hg/store/phaseroots
320 2 r4/.hg/store/phaseroots
321 2 r4/.hg/store/undo
321 2 r4/.hg/store/undo
322 2 r4/.hg/store/undo.backup.fncache (repofncache !)
322 2 r4/.hg/store/undo.backup.fncache (repofncache !)
323 2 r4/.hg/store/undo.backup.phaseroots
323 2 r4/.hg/store/undo.backup.phaseroots
324 2 r4/.hg/store/undo.backupfiles
324 2 r4/.hg/store/undo.backupfiles
325 2 r4/.hg/store/undo.phaseroots
325 2 r4/.hg/store/undo.phaseroots
326 [24] r4/\.hg/undo\.backup\.dirstate (re)
326 [24] r4/\.hg/undo\.backup\.dirstate (re)
327 2 r4/.hg/undo.bookmarks
327 2 r4/.hg/undo.bookmarks
328 2 r4/.hg/undo.branch
328 2 r4/.hg/undo.branch
329 2 r4/.hg/undo.desc
329 2 r4/.hg/undo.desc
330 [24] r4/\.hg/undo\.dirstate (re)
330 [24] r4/\.hg/undo\.dirstate (re)
331 2 r4/.hg/wcache/checkisexec (execbit !)
331 2 r4/.hg/wcache/checkisexec (execbit !)
332 2 r4/.hg/wcache/checklink-target (symlink !)
332 2 r4/.hg/wcache/checklink-target (symlink !)
333 2 r4/.hg/wcache/checknoexec (execbit !)
333 2 r4/.hg/wcache/checknoexec (execbit !)
334 1 r4/.hg/wcache/manifestfulltextcache (reporevlogstore !)
334 1 r4/.hg/wcache/manifestfulltextcache (reporevlogstore !)
335 2 r4/d1/data1
335 2 r4/d1/data1
336 2 r4/d1/f2
336 2 r4/d1/f2
337 1 r4/f1
337 1 r4/f1
338 1 r4/f3 (execbit !)
338 1 r4/f3 (execbit !)
339 2 r4/f3 (no-execbit !)
339 2 r4/f3 (no-execbit !)
340
340
341 #if hardlink-whitelisted
341 #if hardlink-whitelisted
342 $ nlinksdir r4/.hg/undo.backup.dirstate r4/.hg/undo.dirstate
342 $ nlinksdir r4/.hg/undo.backup.dirstate r4/.hg/undo.dirstate
343 4 r4/.hg/undo.backup.dirstate
343 4 r4/.hg/undo.backup.dirstate
344 4 r4/.hg/undo.dirstate
344 4 r4/.hg/undo.dirstate
345 #endif
345 #endif
346
346
347 Test hardlinking outside hg:
347 Test hardlinking outside hg:
348
348
349 $ mkdir x
349 $ mkdir x
350 $ echo foo > x/a
350 $ echo foo > x/a
351
351
352 $ linkcp x y
352 $ linkcp x y
353 $ echo bar >> y/a
353 $ echo bar >> y/a
354
354
355 No diff if hardlink:
355 No diff if hardlink:
356
356
357 $ diff x/a y/a
357 $ diff x/a y/a
358
358
359 Test mq hardlinking:
359 Test mq hardlinking:
360
360
361 $ echo "[extensions]" >> $HGRCPATH
361 $ echo "[extensions]" >> $HGRCPATH
362 $ echo "mq=" >> $HGRCPATH
362 $ echo "mq=" >> $HGRCPATH
363
363
364 $ hg init a
364 $ hg init a
365 $ cd a
365 $ cd a
366
366
367 $ hg qimport -n foo - << EOF
367 $ hg qimport -n foo - << EOF
368 > # HG changeset patch
368 > # HG changeset patch
369 > # Date 1 0
369 > # Date 1 0
370 > diff -r 2588a8b53d66 a
370 > diff -r 2588a8b53d66 a
371 > --- /dev/null Thu Jan 01 00:00:00 1970 +0000
371 > --- /dev/null Thu Jan 01 00:00:00 1970 +0000
372 > +++ b/a Wed Jul 23 15:54:29 2008 +0200
372 > +++ b/a Wed Jul 23 15:54:29 2008 +0200
373 > @@ -0,0 +1,1 @@
373 > @@ -0,0 +1,1 @@
374 > +a
374 > +a
375 > EOF
375 > EOF
376 adding foo to series file
376 adding foo to series file
377
377
378 $ hg qpush
378 $ hg qpush
379 applying foo
379 applying foo
380 now at: foo
380 now at: foo
381
381
382 $ cd ..
382 $ cd ..
383 $ linkcp a b
383 $ linkcp a b
384 $ cd b
384 $ cd b
385
385
386 $ hg qimport -n bar - << EOF
386 $ hg qimport -n bar - << EOF
387 > # HG changeset patch
387 > # HG changeset patch
388 > # Date 2 0
388 > # Date 2 0
389 > diff -r 2588a8b53d66 a
389 > diff -r 2588a8b53d66 a
390 > --- /dev/null Thu Jan 01 00:00:00 1970 +0000
390 > --- /dev/null Thu Jan 01 00:00:00 1970 +0000
391 > +++ b/b Wed Jul 23 15:54:29 2008 +0200
391 > +++ b/b Wed Jul 23 15:54:29 2008 +0200
392 > @@ -0,0 +1,1 @@
392 > @@ -0,0 +1,1 @@
393 > +b
393 > +b
394 > EOF
394 > EOF
395 adding bar to series file
395 adding bar to series file
396
396
397 $ hg qpush
397 $ hg qpush
398 applying bar
398 applying bar
399 now at: bar
399 now at: bar
400
400
401 $ cat .hg/patches/status
401 $ cat .hg/patches/status
402 430ed4828a74fa4047bc816a25500f7472ab4bfe:foo
402 430ed4828a74fa4047bc816a25500f7472ab4bfe:foo
403 4e7abb4840c46a910f6d7b4d3c3fc7e5209e684c:bar
403 4e7abb4840c46a910f6d7b4d3c3fc7e5209e684c:bar
404
404
405 $ cat .hg/patches/series
405 $ cat .hg/patches/series
406 foo
406 foo
407 bar
407 bar
408
408
409 $ cat ../a/.hg/patches/status
409 $ cat ../a/.hg/patches/status
410 430ed4828a74fa4047bc816a25500f7472ab4bfe:foo
410 430ed4828a74fa4047bc816a25500f7472ab4bfe:foo
411
411
412 $ cat ../a/.hg/patches/series
412 $ cat ../a/.hg/patches/series
413 foo
413 foo
414
414
415 Test tags hardlinking:
415 Test tags hardlinking:
416
416
417 $ hg qdel -r qbase:qtip
417 $ hg qdel -r qbase:qtip
418 patch foo finalized without changeset message
418 patch foo finalized without changeset message
419 patch bar finalized without changeset message
419 patch bar finalized without changeset message
420
420
421 $ hg tag -l lfoo
421 $ hg tag -l lfoo
422 $ hg tag foo
422 $ hg tag foo
423
423
424 $ cd ..
424 $ cd ..
425 $ linkcp b c
425 $ linkcp b c
426 $ cd c
426 $ cd c
427
427
428 $ hg tag -l -r 0 lbar
428 $ hg tag -l -r 0 lbar
429 $ hg tag -r 0 bar
429 $ hg tag -r 0 bar
430
430
431 $ cat .hgtags
431 $ cat .hgtags
432 4e7abb4840c46a910f6d7b4d3c3fc7e5209e684c foo
432 4e7abb4840c46a910f6d7b4d3c3fc7e5209e684c foo
433 430ed4828a74fa4047bc816a25500f7472ab4bfe bar
433 430ed4828a74fa4047bc816a25500f7472ab4bfe bar
434
434
435 $ cat .hg/localtags
435 $ cat .hg/localtags
436 4e7abb4840c46a910f6d7b4d3c3fc7e5209e684c lfoo
436 4e7abb4840c46a910f6d7b4d3c3fc7e5209e684c lfoo
437 430ed4828a74fa4047bc816a25500f7472ab4bfe lbar
437 430ed4828a74fa4047bc816a25500f7472ab4bfe lbar
438
438
439 $ cat ../b/.hgtags
439 $ cat ../b/.hgtags
440 4e7abb4840c46a910f6d7b4d3c3fc7e5209e684c foo
440 4e7abb4840c46a910f6d7b4d3c3fc7e5209e684c foo
441
441
442 $ cat ../b/.hg/localtags
442 $ cat ../b/.hg/localtags
443 4e7abb4840c46a910f6d7b4d3c3fc7e5209e684c lfoo
443 4e7abb4840c46a910f6d7b4d3c3fc7e5209e684c lfoo
444
444
445 $ cd ..
445 $ cd ..
@@ -1,1182 +1,1170 b''
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [extdiff]
2 > [extdiff]
3 > # for portability:
3 > # for portability:
4 > pdiff = sh "$RUNTESTDIR/pdiff"
4 > pdiff = sh "$RUNTESTDIR/pdiff"
5 > [progress]
5 > [progress]
6 > disable=False
6 > disable=False
7 > assume-tty = 1
7 > assume-tty = 1
8 > delay = 0
8 > delay = 0
9 > # set changedelay really large so we don't see nested topics
9 > # set changedelay really large so we don't see nested topics
10 > changedelay = 30000
10 > changedelay = 30000
11 > format = topic bar number
11 > format = topic bar number
12 > refresh = 0
12 > refresh = 0
13 > width = 60
13 > width = 60
14 > EOF
14 > EOF
15
15
16 Preparing the subrepository 'sub2'
16 Preparing the subrepository 'sub2'
17
17
18 $ hg init sub2
18 $ hg init sub2
19 $ echo sub2 > sub2/sub2
19 $ echo sub2 > sub2/sub2
20 $ hg add -R sub2
20 $ hg add -R sub2
21 adding sub2/sub2
21 adding sub2/sub2
22 $ hg commit -R sub2 -m "sub2 import"
22 $ hg commit -R sub2 -m "sub2 import"
23
23
24 Preparing the 'sub1' repo which depends on the subrepo 'sub2'
24 Preparing the 'sub1' repo which depends on the subrepo 'sub2'
25
25
26 $ hg init sub1
26 $ hg init sub1
27 $ echo sub1 > sub1/sub1
27 $ echo sub1 > sub1/sub1
28 $ echo "sub2 = ../sub2" > sub1/.hgsub
28 $ echo "sub2 = ../sub2" > sub1/.hgsub
29 $ hg clone sub2 sub1/sub2
29 $ hg clone sub2 sub1/sub2
30 \r (no-eol) (esc)
30 \r (no-eol) (esc)
31 linking [ <=> ] 1\r (no-eol) (esc)
31 linking [======> ] 1/6\r (no-eol) (esc)
32 linking [ <=> ] 2\r (no-eol) (esc)
32 linking [==============> ] 2/6\r (no-eol) (esc)
33 linking [ <=> ] 3\r (no-eol) (esc)
33 linking [=====================> ] 3/6\r (no-eol) (esc)
34 linking [ <=> ] 4\r (no-eol) (esc)
34 linking [=============================> ] 4/6\r (no-eol) (esc)
35 linking [ <=> ] 5\r (no-eol) (esc)
35 linking [====================================> ] 5/6\r (no-eol) (esc)
36 linking [ <=> ] 6\r (no-eol) (esc)
36 linking [============================================>] 6/6\r (no-eol) (esc)
37 \r (no-eol) (esc)
37 \r (no-eol) (esc)
38 \r (no-eol) (esc)
38 \r (no-eol) (esc)
39 updating [===========================================>] 1/1\r (no-eol) (esc)
39 updating [===========================================>] 1/1\r (no-eol) (esc)
40 \r (no-eol) (esc)
40 \r (no-eol) (esc)
41 updating to branch default
41 updating to branch default
42 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
42 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
43 $ hg add -R sub1
43 $ hg add -R sub1
44 adding sub1/.hgsub
44 adding sub1/.hgsub
45 adding sub1/sub1
45 adding sub1/sub1
46 $ hg commit -R sub1 -m "sub1 import"
46 $ hg commit -R sub1 -m "sub1 import"
47
47
48 Preparing the 'main' repo which depends on the subrepo 'sub1'
48 Preparing the 'main' repo which depends on the subrepo 'sub1'
49
49
50 $ hg init main
50 $ hg init main
51 $ echo main > main/main
51 $ echo main > main/main
52 $ echo "sub1 = ../sub1" > main/.hgsub
52 $ echo "sub1 = ../sub1" > main/.hgsub
53 $ hg clone sub1 main/sub1
53 $ hg clone sub1 main/sub1
54 \r (no-eol) (esc)
54 \r (no-eol) (esc)
55 linking [ <=> ] 1\r (no-eol) (esc)
55 linking [====> ] 1/8\r (no-eol) (esc)
56 linking [ <=> ] 2\r (no-eol) (esc)
56 linking [==========> ] 2/8\r (no-eol) (esc)
57 linking [ <=> ] 3\r (no-eol) (esc)
57 linking [===============> ] 3/8\r (no-eol) (esc)
58 linking [ <=> ] 4\r (no-eol) (esc)
58 linking [=====================> ] 4/8\r (no-eol) (esc)
59 linking [ <=> ] 5\r (no-eol) (esc)
59 linking [===========================> ] 5/8\r (no-eol) (esc)
60 linking [ <=> ] 6\r (no-eol) (esc)
60 linking [================================> ] 6/8\r (no-eol) (esc)
61 linking [ <=> ] 7\r (no-eol) (esc)
61 linking [======================================> ] 7/8\r (no-eol) (esc)
62 linking [ <=> ] 8\r (no-eol) (esc)
62 linking [============================================>] 8/8\r (no-eol) (esc)
63 linking [ <=> ] 9\r (no-eol) (esc) (reposimplestore !)
64 linking [ <=> ] 10\r (no-eol) (esc) (reposimplestore !)
65 \r (no-eol) (esc)
63 \r (no-eol) (esc)
66 \r (no-eol) (esc)
64 \r (no-eol) (esc)
67 updating [===========================================>] 3/3\r (no-eol) (esc)
65 updating [===========================================>] 3/3\r (no-eol) (esc)
68 \r (no-eol) (esc)
66 \r (no-eol) (esc)
69 \r (no-eol) (esc)
67 \r (no-eol) (esc)
70 linking [ <=> ] 1\r (no-eol) (esc)
68 linking [======> ] 1/6\r (no-eol) (esc)
71 linking [ <=> ] 2\r (no-eol) (esc)
69 linking [==============> ] 2/6\r (no-eol) (esc)
72 linking [ <=> ] 3\r (no-eol) (esc)
70 linking [=====================> ] 3/6\r (no-eol) (esc)
73 linking [ <=> ] 4\r (no-eol) (esc)
71 linking [=============================> ] 4/6\r (no-eol) (esc)
74 linking [ <=> ] 5\r (no-eol) (esc)
72 linking [====================================> ] 5/6\r (no-eol) (esc)
75 linking [ <=> ] 6\r (no-eol) (esc)
73 linking [============================================>] 6/6\r (no-eol) (esc)
76 updating [===========================================>] 1/1\r (no-eol) (esc)
74 updating [===========================================>] 1/1\r (no-eol) (esc)
77 \r (no-eol) (esc)
75 \r (no-eol) (esc)
78 updating to branch default
76 updating to branch default
79 cloning subrepo sub2 from $TESTTMP/sub2
77 cloning subrepo sub2 from $TESTTMP/sub2
80 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
78 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
81 $ hg add -R main
79 $ hg add -R main
82 adding main/.hgsub
80 adding main/.hgsub
83 adding main/main
81 adding main/main
84 $ hg commit -R main -m "main import"
82 $ hg commit -R main -m "main import"
85
83
86 #if serve
84 #if serve
87
85
88 Unfortunately, subrepos not at their nominal location cannot be cloned. But
86 Unfortunately, subrepos not at their nominal location cannot be cloned. But
89 they are still served from their location within the local repository. The only
87 they are still served from their location within the local repository. The only
90 reason why 'main' can be cloned via the filesystem is because 'sub1' and 'sub2'
88 reason why 'main' can be cloned via the filesystem is because 'sub1' and 'sub2'
91 are also available as siblings of 'main'.
89 are also available as siblings of 'main'.
92
90
93 $ hg serve -R main --debug -S -p $HGPORT -d --pid-file=hg1.pid -E error.log -A access.log
91 $ hg serve -R main --debug -S -p $HGPORT -d --pid-file=hg1.pid -E error.log -A access.log
94 adding = $TESTTMP/main
92 adding = $TESTTMP/main
95 adding sub1 = $TESTTMP/main/sub1
93 adding sub1 = $TESTTMP/main/sub1
96 adding sub1/sub2 = $TESTTMP/main/sub1/sub2
94 adding sub1/sub2 = $TESTTMP/main/sub1/sub2
97 listening at http://*:$HGPORT/ (bound to *:$HGPORT) (glob) (?)
95 listening at http://*:$HGPORT/ (bound to *:$HGPORT) (glob) (?)
98 adding = $TESTTMP/main (?)
96 adding = $TESTTMP/main (?)
99 adding sub1 = $TESTTMP/main/sub1 (?)
97 adding sub1 = $TESTTMP/main/sub1 (?)
100 adding sub1/sub2 = $TESTTMP/main/sub1/sub2 (?)
98 adding sub1/sub2 = $TESTTMP/main/sub1/sub2 (?)
101 $ cat hg1.pid >> $DAEMON_PIDS
99 $ cat hg1.pid >> $DAEMON_PIDS
102
100
103 $ hg clone http://localhost:$HGPORT httpclone --config progress.disable=True
101 $ hg clone http://localhost:$HGPORT httpclone --config progress.disable=True
104 requesting all changes
102 requesting all changes
105 adding changesets
103 adding changesets
106 adding manifests
104 adding manifests
107 adding file changes
105 adding file changes
108 added 1 changesets with 3 changes to 3 files
106 added 1 changesets with 3 changes to 3 files
109 new changesets 7f491f53a367
107 new changesets 7f491f53a367
110 updating to branch default
108 updating to branch default
111 cloning subrepo sub1 from http://localhost:$HGPORT/../sub1
109 cloning subrepo sub1 from http://localhost:$HGPORT/../sub1
112 abort: HTTP Error 404: Not Found
110 abort: HTTP Error 404: Not Found
113 [100]
111 [100]
114
112
115 $ cat access.log
113 $ cat access.log
116 * "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
114 * "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
117 * "GET /?cmd=batch HTTP/1.1" 200 - * (glob)
115 * "GET /?cmd=batch HTTP/1.1" 200 - * (glob)
118 * "GET /?cmd=getbundle HTTP/1.1" 200 - * (glob)
116 * "GET /?cmd=getbundle HTTP/1.1" 200 - * (glob)
119 * "GET /../sub1?cmd=capabilities HTTP/1.1" 404 - (glob)
117 * "GET /../sub1?cmd=capabilities HTTP/1.1" 404 - (glob)
120 $ cat error.log
118 $ cat error.log
121
119
122 $ killdaemons.py
120 $ killdaemons.py
123 $ rm hg1.pid error.log access.log
121 $ rm hg1.pid error.log access.log
124 #endif
122 #endif
125
123
126 Cleaning both repositories, just as a clone -U
124 Cleaning both repositories, just as a clone -U
127
125
128 $ hg up -C -R sub2 null
126 $ hg up -C -R sub2 null
129 \r (no-eol) (esc)
127 \r (no-eol) (esc)
130 updating [===========================================>] 1/1\r (no-eol) (esc)
128 updating [===========================================>] 1/1\r (no-eol) (esc)
131 \r (no-eol) (esc)
129 \r (no-eol) (esc)
132 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
130 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
133 $ hg up -C -R sub1 null
131 $ hg up -C -R sub1 null
134 \r (no-eol) (esc)
132 \r (no-eol) (esc)
135 updating [===========================================>] 1/1\r (no-eol) (esc)
133 updating [===========================================>] 1/1\r (no-eol) (esc)
136 \r (no-eol) (esc)
134 \r (no-eol) (esc)
137 \r (no-eol) (esc)
135 \r (no-eol) (esc)
138 updating [===========================================>] 3/3\r (no-eol) (esc)
136 updating [===========================================>] 3/3\r (no-eol) (esc)
139 \r (no-eol) (esc)
137 \r (no-eol) (esc)
140 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
138 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
141 $ hg up -C -R main null
139 $ hg up -C -R main null
142 \r (no-eol) (esc)
140 \r (no-eol) (esc)
143 updating [===========================================>] 1/1\r (no-eol) (esc)
141 updating [===========================================>] 1/1\r (no-eol) (esc)
144 \r (no-eol) (esc)
142 \r (no-eol) (esc)
145 \r (no-eol) (esc)
143 \r (no-eol) (esc)
146 updating [===========================================>] 3/3\r (no-eol) (esc)
144 updating [===========================================>] 3/3\r (no-eol) (esc)
147 \r (no-eol) (esc)
145 \r (no-eol) (esc)
148 \r (no-eol) (esc)
146 \r (no-eol) (esc)
149 updating [===========================================>] 3/3\r (no-eol) (esc)
147 updating [===========================================>] 3/3\r (no-eol) (esc)
150 \r (no-eol) (esc)
148 \r (no-eol) (esc)
151 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
149 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
152 $ rm -rf main/sub1
150 $ rm -rf main/sub1
153 $ rm -rf sub1/sub2
151 $ rm -rf sub1/sub2
154
152
155 Clone main
153 Clone main
156
154
157 $ hg --config extensions.largefiles= clone main cloned
155 $ hg --config extensions.largefiles= clone main cloned
158 \r (no-eol) (esc)
156 \r (no-eol) (esc)
159 linking [ <=> ] 1\r (no-eol) (esc)
157 linking [====> ] 1/8\r (no-eol) (esc)
160 linking [ <=> ] 2\r (no-eol) (esc)
158 linking [==========> ] 2/8\r (no-eol) (esc)
161 linking [ <=> ] 3\r (no-eol) (esc)
159 linking [===============> ] 3/8\r (no-eol) (esc)
162 linking [ <=> ] 4\r (no-eol) (esc)
160 linking [=====================> ] 4/8\r (no-eol) (esc)
163 linking [ <=> ] 5\r (no-eol) (esc)
161 linking [===========================> ] 5/8\r (no-eol) (esc)
164 linking [ <=> ] 6\r (no-eol) (esc)
162 linking [================================> ] 6/8\r (no-eol) (esc)
165 linking [ <=> ] 7\r (no-eol) (esc)
163 linking [======================================> ] 7/8\r (no-eol) (esc)
166 linking [ <=> ] 8\r (no-eol) (esc)
164 linking [============================================>] 8/8\r (no-eol) (esc)
167 linking [ <=> ] 9\r (no-eol) (esc) (reposimplestore !)
168 linking [ <=> ] 10\r (no-eol) (esc) (reposimplestore !)
169 \r (no-eol) (esc)
165 \r (no-eol) (esc)
170 \r (no-eol) (esc)
166 \r (no-eol) (esc)
171 updating [===========================================>] 3/3\r (no-eol) (esc)
167 updating [===========================================>] 3/3\r (no-eol) (esc)
172 \r (no-eol) (esc)
168 \r (no-eol) (esc)
173 \r (no-eol) (esc)
169 \r (no-eol) (esc)
174 linking [ <=> ] 1\r (no-eol) (esc)
170 linking [====> ] 1/8\r (no-eol) (esc)
175 linking [ <=> ] 2\r (no-eol) (esc)
171 linking [==========> ] 2/8\r (no-eol) (esc)
176 linking [ <=> ] 3\r (no-eol) (esc)
172 linking [===============> ] 3/8\r (no-eol) (esc)
177 linking [ <=> ] 4\r (no-eol) (esc)
173 linking [=====================> ] 4/8\r (no-eol) (esc)
178 linking [ <=> ] 5\r (no-eol) (esc)
174 linking [===========================> ] 5/8\r (no-eol) (esc)
179 linking [ <=> ] 6\r (no-eol) (esc)
175 linking [================================> ] 6/8\r (no-eol) (esc)
180 linking [ <=> ] 7\r (no-eol) (esc)
176 linking [======================================> ] 7/8\r (no-eol) (esc)
181 linking [ <=> ] 8\r (no-eol) (esc)
177 linking [============================================>] 8/8\r (no-eol) (esc)
182 linking [ <=> ] 9\r (no-eol) (esc) (reposimplestore !)
183 linking [ <=> ] 10\r (no-eol) (esc) (reposimplestore !)
184 updating [===========================================>] 3/3\r (no-eol) (esc)
178 updating [===========================================>] 3/3\r (no-eol) (esc)
185 \r (no-eol) (esc)
179 \r (no-eol) (esc)
186 \r (no-eol) (esc)
180 \r (no-eol) (esc)
187 linking [ <=> ] 1\r (no-eol) (esc) (reporevlogstore !)
181 linking [======> ] 1/6\r (no-eol) (esc)
188 linking [ <=> ] 2\r (no-eol) (esc) (reporevlogstore !)
182 linking [==============> ] 2/6\r (no-eol) (esc)
189 linking [ <=> ] 3\r (no-eol) (esc) (reporevlogstore !)
183 linking [=====================> ] 3/6\r (no-eol) (esc)
190 linking [ <=> ] 4\r (no-eol) (esc) (reporevlogstore !)
184 linking [=============================> ] 4/6\r (no-eol) (esc)
191 linking [ <=> ] 5\r (no-eol) (esc) (reporevlogstore !)
185 linking [====================================> ] 5/6\r (no-eol) (esc)
192 linking [ <=> ] 6\r (no-eol) (esc) (reporevlogstore !)
186 linking [============================================>] 6/6\r (no-eol) (esc)
193 linking [ <=> ] 1\r (no-eol) (esc) (reposimplestore !)
194 linking [ <=> ] 2\r (no-eol) (esc) (reposimplestore !)
195 linking [ <=> ] 3\r (no-eol) (esc) (reposimplestore !)
196 linking [ <=> ] 4\r (no-eol) (esc) (reposimplestore !)
197 linking [ <=> ] 5\r (no-eol) (esc) (reposimplestore !)
198 linking [ <=> ] 6\r (no-eol) (esc) (reposimplestore !)
199 updating [===========================================>] 1/1\r (no-eol) (esc)
187 updating [===========================================>] 1/1\r (no-eol) (esc)
200 \r (no-eol) (esc)
188 \r (no-eol) (esc)
201 updating to branch default
189 updating to branch default
202 cloning subrepo sub1 from $TESTTMP/sub1
190 cloning subrepo sub1 from $TESTTMP/sub1
203 cloning subrepo sub1/sub2 from $TESTTMP/sub2
191 cloning subrepo sub1/sub2 from $TESTTMP/sub2
204 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
192 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
205
193
206 Largefiles is NOT enabled in the clone if the source repo doesn't require it
194 Largefiles is NOT enabled in the clone if the source repo doesn't require it
207 $ grep largefiles cloned/.hg/hgrc
195 $ grep largefiles cloned/.hg/hgrc
208 [1]
196 [1]
209
197
210 Checking cloned repo ids
198 Checking cloned repo ids
211
199
212 $ printf "cloned " ; hg id -R cloned
200 $ printf "cloned " ; hg id -R cloned
213 cloned 7f491f53a367 tip
201 cloned 7f491f53a367 tip
214 $ printf "cloned/sub1 " ; hg id -R cloned/sub1
202 $ printf "cloned/sub1 " ; hg id -R cloned/sub1
215 cloned/sub1 fc3b4ce2696f tip
203 cloned/sub1 fc3b4ce2696f tip
216 $ printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
204 $ printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
217 cloned/sub1/sub2 c57a0840e3ba tip
205 cloned/sub1/sub2 c57a0840e3ba tip
218
206
219 debugsub output for main and sub1
207 debugsub output for main and sub1
220
208
221 $ hg debugsub -R cloned
209 $ hg debugsub -R cloned
222 path sub1
210 path sub1
223 source ../sub1
211 source ../sub1
224 revision fc3b4ce2696f7741438c79207583768f2ce6b0dd
212 revision fc3b4ce2696f7741438c79207583768f2ce6b0dd
225 $ hg debugsub -R cloned/sub1
213 $ hg debugsub -R cloned/sub1
226 path sub2
214 path sub2
227 source ../sub2
215 source ../sub2
228 revision c57a0840e3badd667ef3c3ef65471609acb2ba3c
216 revision c57a0840e3badd667ef3c3ef65471609acb2ba3c
229
217
230 Modifying deeply nested 'sub2'
218 Modifying deeply nested 'sub2'
231
219
232 $ echo modified > cloned/sub1/sub2/sub2
220 $ echo modified > cloned/sub1/sub2/sub2
233 $ hg commit --subrepos -m "deep nested modif should trigger a commit" -R cloned
221 $ hg commit --subrepos -m "deep nested modif should trigger a commit" -R cloned
234 committing subrepository sub1
222 committing subrepository sub1
235 committing subrepository sub1/sub2
223 committing subrepository sub1/sub2
236
224
237 Checking modified node ids
225 Checking modified node ids
238
226
239 $ printf "cloned " ; hg id -R cloned
227 $ printf "cloned " ; hg id -R cloned
240 cloned ffe6649062fe tip
228 cloned ffe6649062fe tip
241 $ printf "cloned/sub1 " ; hg id -R cloned/sub1
229 $ printf "cloned/sub1 " ; hg id -R cloned/sub1
242 cloned/sub1 2ecb03bf44a9 tip
230 cloned/sub1 2ecb03bf44a9 tip
243 $ printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
231 $ printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
244 cloned/sub1/sub2 53dd3430bcaf tip
232 cloned/sub1/sub2 53dd3430bcaf tip
245
233
246 debugsub output for main and sub1
234 debugsub output for main and sub1
247
235
248 $ hg debugsub -R cloned
236 $ hg debugsub -R cloned
249 path sub1
237 path sub1
250 source ../sub1
238 source ../sub1
251 revision 2ecb03bf44a94e749e8669481dd9069526ce7cb9
239 revision 2ecb03bf44a94e749e8669481dd9069526ce7cb9
252 $ hg debugsub -R cloned/sub1
240 $ hg debugsub -R cloned/sub1
253 path sub2
241 path sub2
254 source ../sub2
242 source ../sub2
255 revision 53dd3430bcaf5ab4a7c48262bcad6d441f510487
243 revision 53dd3430bcaf5ab4a7c48262bcad6d441f510487
256
244
257 Check that deep archiving works
245 Check that deep archiving works
258
246
259 $ cd cloned
247 $ cd cloned
260 $ echo 'test' > sub1/sub2/test.txt
248 $ echo 'test' > sub1/sub2/test.txt
261 $ hg --config extensions.largefiles=! add sub1/sub2/test.txt
249 $ hg --config extensions.largefiles=! add sub1/sub2/test.txt
262 $ mkdir sub1/sub2/folder
250 $ mkdir sub1/sub2/folder
263 $ echo 'subfolder' > sub1/sub2/folder/test.txt
251 $ echo 'subfolder' > sub1/sub2/folder/test.txt
264 $ hg ci -ASm "add test.txt"
252 $ hg ci -ASm "add test.txt"
265 adding sub1/sub2/folder/test.txt
253 adding sub1/sub2/folder/test.txt
266 committing subrepository sub1
254 committing subrepository sub1
267 committing subrepository sub1/sub2
255 committing subrepository sub1/sub2
268
256
269 $ rm -r main
257 $ rm -r main
270 $ hg archive -S -qr 'wdir()' ../wdir
258 $ hg archive -S -qr 'wdir()' ../wdir
271 $ cat ../wdir/.hg_archival.txt
259 $ cat ../wdir/.hg_archival.txt
272 repo: 7f491f53a367861f47ee64a80eb997d1f341b77a
260 repo: 7f491f53a367861f47ee64a80eb997d1f341b77a
273 node: 9bb10eebee29dc0f1201dcf5977b811a540255fd+
261 node: 9bb10eebee29dc0f1201dcf5977b811a540255fd+
274 branch: default
262 branch: default
275 latesttag: null
263 latesttag: null
276 latesttagdistance: 4
264 latesttagdistance: 4
277 changessincelatesttag: 4
265 changessincelatesttag: 4
278 $ hg update -Cq .
266 $ hg update -Cq .
279
267
280 A deleted subrepo file is flagged as dirty, like the top level repo
268 A deleted subrepo file is flagged as dirty, like the top level repo
281
269
282 $ rm -r ../wdir sub1/sub2/folder/test.txt
270 $ rm -r ../wdir sub1/sub2/folder/test.txt
283 $ hg archive -S -qr 'wdir()' ../wdir
271 $ hg archive -S -qr 'wdir()' ../wdir
284 $ cat ../wdir/.hg_archival.txt
272 $ cat ../wdir/.hg_archival.txt
285 repo: 7f491f53a367861f47ee64a80eb997d1f341b77a
273 repo: 7f491f53a367861f47ee64a80eb997d1f341b77a
286 node: 9bb10eebee29dc0f1201dcf5977b811a540255fd+
274 node: 9bb10eebee29dc0f1201dcf5977b811a540255fd+
287 branch: default
275 branch: default
288 latesttag: null
276 latesttag: null
289 latesttagdistance: 4
277 latesttagdistance: 4
290 changessincelatesttag: 4
278 changessincelatesttag: 4
291 $ hg update -Cq .
279 $ hg update -Cq .
292 $ rm -r ../wdir
280 $ rm -r ../wdir
293
281
294 $ hg archive -S -qr 'wdir()' ../wdir \
282 $ hg archive -S -qr 'wdir()' ../wdir \
295 > --config 'experimental.archivemetatemplate=archived {node|short}\n'
283 > --config 'experimental.archivemetatemplate=archived {node|short}\n'
296 $ cat ../wdir/.hg_archival.txt
284 $ cat ../wdir/.hg_archival.txt
297 archived ffffffffffff
285 archived ffffffffffff
298 $ rm -r ../wdir
286 $ rm -r ../wdir
299
287
300 .. but first take a detour through some deep removal testing
288 .. but first take a detour through some deep removal testing
301
289
302 $ hg remove -S -I 're:.*.txt' .
290 $ hg remove -S -I 're:.*.txt' .
303 \r (no-eol) (esc)
291 \r (no-eol) (esc)
304 searching [==========================================>] 1/1\r (no-eol) (esc)
292 searching [==========================================>] 1/1\r (no-eol) (esc)
305 searching [==========================================>] 1/1\r (no-eol) (esc)
293 searching [==========================================>] 1/1\r (no-eol) (esc)
306 \r (no-eol) (esc)
294 \r (no-eol) (esc)
307 \r (no-eol) (esc)
295 \r (no-eol) (esc)
308 deleting [=====================> ] 1/2\r (no-eol) (esc)
296 deleting [=====================> ] 1/2\r (no-eol) (esc)
309 \r (no-eol) (esc)
297 \r (no-eol) (esc)
310 \r (no-eol) (esc)
298 \r (no-eol) (esc)
311 deleting [===========================================>] 2/2\r (no-eol) (esc)
299 deleting [===========================================>] 2/2\r (no-eol) (esc)
312 \r (no-eol) (esc)
300 \r (no-eol) (esc)
313 removing sub1/sub2/folder/test.txt
301 removing sub1/sub2/folder/test.txt
314 removing sub1/sub2/test.txt
302 removing sub1/sub2/test.txt
315 $ hg status -S
303 $ hg status -S
316 R sub1/sub2/folder/test.txt
304 R sub1/sub2/folder/test.txt
317 R sub1/sub2/test.txt
305 R sub1/sub2/test.txt
318 $ hg update -Cq
306 $ hg update -Cq
319 $ hg remove -I 're:.*.txt' sub1
307 $ hg remove -I 're:.*.txt' sub1
320 \r (no-eol) (esc)
308 \r (no-eol) (esc)
321 searching [==========================================>] 1/1\r (no-eol) (esc)
309 searching [==========================================>] 1/1\r (no-eol) (esc)
322 \r (no-eol) (esc)
310 \r (no-eol) (esc)
323 \r (no-eol) (esc)
311 \r (no-eol) (esc)
324 deleting [===========================================>] 1/1\r (no-eol) (esc)
312 deleting [===========================================>] 1/1\r (no-eol) (esc)
325 \r (no-eol) (esc)
313 \r (no-eol) (esc)
326 $ hg status -S
314 $ hg status -S
327 $ hg remove sub1/sub2/folder/test.txt
315 $ hg remove sub1/sub2/folder/test.txt
328 \r (no-eol) (esc)
316 \r (no-eol) (esc)
329 searching [==========================================>] 1/1\r (no-eol) (esc)
317 searching [==========================================>] 1/1\r (no-eol) (esc)
330 searching [==========================================>] 1/1\r (no-eol) (esc)
318 searching [==========================================>] 1/1\r (no-eol) (esc)
331 \r (no-eol) (esc)
319 \r (no-eol) (esc)
332 \r (no-eol) (esc)
320 \r (no-eol) (esc)
333 deleting [===========================================>] 1/1\r (no-eol) (esc)
321 deleting [===========================================>] 1/1\r (no-eol) (esc)
334 \r (no-eol) (esc)
322 \r (no-eol) (esc)
335 \r (no-eol) (esc)
323 \r (no-eol) (esc)
336 deleting [===========================================>] 1/1\r (no-eol) (esc)
324 deleting [===========================================>] 1/1\r (no-eol) (esc)
337 \r (no-eol) (esc)
325 \r (no-eol) (esc)
338 \r (no-eol) (esc)
326 \r (no-eol) (esc)
339 deleting [===========================================>] 1/1\r (no-eol) (esc)
327 deleting [===========================================>] 1/1\r (no-eol) (esc)
340 \r (no-eol) (esc)
328 \r (no-eol) (esc)
341 $ hg remove sub1/.hgsubstate
329 $ hg remove sub1/.hgsubstate
342 \r (no-eol) (esc)
330 \r (no-eol) (esc)
343 searching [==========================================>] 1/1\r (no-eol) (esc)
331 searching [==========================================>] 1/1\r (no-eol) (esc)
344 \r (no-eol) (esc)
332 \r (no-eol) (esc)
345 \r (no-eol) (esc)
333 \r (no-eol) (esc)
346 deleting [===========================================>] 1/1\r (no-eol) (esc)
334 deleting [===========================================>] 1/1\r (no-eol) (esc)
347 \r (no-eol) (esc)
335 \r (no-eol) (esc)
348 \r (no-eol) (esc)
336 \r (no-eol) (esc)
349 deleting [===========================================>] 1/1\r (no-eol) (esc)
337 deleting [===========================================>] 1/1\r (no-eol) (esc)
350 \r (no-eol) (esc)
338 \r (no-eol) (esc)
351 $ mv sub1/.hgsub sub1/x.hgsub
339 $ mv sub1/.hgsub sub1/x.hgsub
352 $ hg status -S
340 $ hg status -S
353 warning: subrepo spec file 'sub1/.hgsub' not found
341 warning: subrepo spec file 'sub1/.hgsub' not found
354 R sub1/.hgsubstate
342 R sub1/.hgsubstate
355 R sub1/sub2/folder/test.txt
343 R sub1/sub2/folder/test.txt
356 ! sub1/.hgsub
344 ! sub1/.hgsub
357 ? sub1/x.hgsub
345 ? sub1/x.hgsub
358 $ hg status -R sub1
346 $ hg status -R sub1
359 warning: subrepo spec file 'sub1/.hgsub' not found
347 warning: subrepo spec file 'sub1/.hgsub' not found
360 R .hgsubstate
348 R .hgsubstate
361 ! .hgsub
349 ! .hgsub
362 ? x.hgsub
350 ? x.hgsub
363 $ mv sub1/x.hgsub sub1/.hgsub
351 $ mv sub1/x.hgsub sub1/.hgsub
364 $ hg update -Cq
352 $ hg update -Cq
365 $ touch sub1/foo
353 $ touch sub1/foo
366 $ hg forget sub1/sub2/folder/test.txt
354 $ hg forget sub1/sub2/folder/test.txt
367 $ rm sub1/sub2/test.txt
355 $ rm sub1/sub2/test.txt
368
356
369 Test relative path printing + subrepos
357 Test relative path printing + subrepos
370 $ mkdir -p foo/bar
358 $ mkdir -p foo/bar
371 $ cd foo
359 $ cd foo
372 $ touch bar/abc
360 $ touch bar/abc
373 $ hg addremove -S ..
361 $ hg addremove -S ..
374 \r (no-eol) (esc)
362 \r (no-eol) (esc)
375 searching for exact renames [========================>] 1/1\r (no-eol) (esc)
363 searching for exact renames [========================>] 1/1\r (no-eol) (esc)
376 \r (no-eol) (esc)
364 \r (no-eol) (esc)
377 adding ../sub1/sub2/folder/test.txt
365 adding ../sub1/sub2/folder/test.txt
378 removing ../sub1/sub2/test.txt
366 removing ../sub1/sub2/test.txt
379 adding ../sub1/foo
367 adding ../sub1/foo
380 adding bar/abc
368 adding bar/abc
381 $ cd ..
369 $ cd ..
382 $ hg status -S
370 $ hg status -S
383 A foo/bar/abc
371 A foo/bar/abc
384 A sub1/foo
372 A sub1/foo
385 R sub1/sub2/test.txt
373 R sub1/sub2/test.txt
386
374
387 Archive wdir() with subrepos
375 Archive wdir() with subrepos
388 $ hg rm main
376 $ hg rm main
389 \r (no-eol) (esc)
377 \r (no-eol) (esc)
390 deleting [===========================================>] 1/1\r (no-eol) (esc)
378 deleting [===========================================>] 1/1\r (no-eol) (esc)
391 \r (no-eol) (esc)
379 \r (no-eol) (esc)
392 $ hg archive -S -r 'wdir()' ../wdir
380 $ hg archive -S -r 'wdir()' ../wdir
393 \r (no-eol) (esc)
381 \r (no-eol) (esc)
394 archiving [ ] 0/3\r (no-eol) (esc)
382 archiving [ ] 0/3\r (no-eol) (esc)
395 archiving [=============> ] 1/3\r (no-eol) (esc)
383 archiving [=============> ] 1/3\r (no-eol) (esc)
396 archiving [===========================> ] 2/3\r (no-eol) (esc)
384 archiving [===========================> ] 2/3\r (no-eol) (esc)
397 archiving [==========================================>] 3/3\r (no-eol) (esc)
385 archiving [==========================================>] 3/3\r (no-eol) (esc)
398 \r (no-eol) (esc)
386 \r (no-eol) (esc)
399 \r (no-eol) (esc)
387 \r (no-eol) (esc)
400 archiving (sub1) [ ] 0/4\r (no-eol) (esc)
388 archiving (sub1) [ ] 0/4\r (no-eol) (esc)
401 archiving (sub1) [========> ] 1/4\r (no-eol) (esc)
389 archiving (sub1) [========> ] 1/4\r (no-eol) (esc)
402 archiving (sub1) [=================> ] 2/4\r (no-eol) (esc)
390 archiving (sub1) [=================> ] 2/4\r (no-eol) (esc)
403 archiving (sub1) [==========================> ] 3/4\r (no-eol) (esc)
391 archiving (sub1) [==========================> ] 3/4\r (no-eol) (esc)
404 archiving (sub1) [===================================>] 4/4\r (no-eol) (esc)
392 archiving (sub1) [===================================>] 4/4\r (no-eol) (esc)
405 \r (no-eol) (esc)
393 \r (no-eol) (esc)
406 \r (no-eol) (esc)
394 \r (no-eol) (esc)
407 archiving (sub1/sub2) [ ] 0/2\r (no-eol) (esc)
395 archiving (sub1/sub2) [ ] 0/2\r (no-eol) (esc)
408 archiving (sub1/sub2) [==============> ] 1/2\r (no-eol) (esc)
396 archiving (sub1/sub2) [==============> ] 1/2\r (no-eol) (esc)
409 archiving (sub1/sub2) [==============================>] 2/2\r (no-eol) (esc)
397 archiving (sub1/sub2) [==============================>] 2/2\r (no-eol) (esc)
410 \r (no-eol) (esc)
398 \r (no-eol) (esc)
411 $ diff -r . ../wdir | egrep -v '\.hg$|^Common subdirectories:'
399 $ diff -r . ../wdir | egrep -v '\.hg$|^Common subdirectories:'
412 Only in ../wdir: .hg_archival.txt
400 Only in ../wdir: .hg_archival.txt
413
401
414 $ find ../wdir -type f | sort
402 $ find ../wdir -type f | sort
415 ../wdir/.hg_archival.txt
403 ../wdir/.hg_archival.txt
416 ../wdir/.hgsub
404 ../wdir/.hgsub
417 ../wdir/.hgsubstate
405 ../wdir/.hgsubstate
418 ../wdir/foo/bar/abc
406 ../wdir/foo/bar/abc
419 ../wdir/sub1/.hgsub
407 ../wdir/sub1/.hgsub
420 ../wdir/sub1/.hgsubstate
408 ../wdir/sub1/.hgsubstate
421 ../wdir/sub1/foo
409 ../wdir/sub1/foo
422 ../wdir/sub1/sub1
410 ../wdir/sub1/sub1
423 ../wdir/sub1/sub2/folder/test.txt
411 ../wdir/sub1/sub2/folder/test.txt
424 ../wdir/sub1/sub2/sub2
412 ../wdir/sub1/sub2/sub2
425
413
426 $ cat ../wdir/.hg_archival.txt
414 $ cat ../wdir/.hg_archival.txt
427 repo: 7f491f53a367861f47ee64a80eb997d1f341b77a
415 repo: 7f491f53a367861f47ee64a80eb997d1f341b77a
428 node: 9bb10eebee29dc0f1201dcf5977b811a540255fd+
416 node: 9bb10eebee29dc0f1201dcf5977b811a540255fd+
429 branch: default
417 branch: default
430 latesttag: null
418 latesttag: null
431 latesttagdistance: 4
419 latesttagdistance: 4
432 changessincelatesttag: 4
420 changessincelatesttag: 4
433
421
434 Attempting to archive 'wdir()' with a missing file is handled gracefully
422 Attempting to archive 'wdir()' with a missing file is handled gracefully
435 $ rm sub1/sub1
423 $ rm sub1/sub1
436 $ rm -r ../wdir
424 $ rm -r ../wdir
437 $ hg archive -v -S -r 'wdir()' ../wdir
425 $ hg archive -v -S -r 'wdir()' ../wdir
438 \r (no-eol) (esc)
426 \r (no-eol) (esc)
439 archiving [ ] 0/3\r (no-eol) (esc)
427 archiving [ ] 0/3\r (no-eol) (esc)
440 archiving [=============> ] 1/3\r (no-eol) (esc)
428 archiving [=============> ] 1/3\r (no-eol) (esc)
441 archiving [===========================> ] 2/3\r (no-eol) (esc)
429 archiving [===========================> ] 2/3\r (no-eol) (esc)
442 archiving [==========================================>] 3/3\r (no-eol) (esc)
430 archiving [==========================================>] 3/3\r (no-eol) (esc)
443 \r (no-eol) (esc)
431 \r (no-eol) (esc)
444 \r (no-eol) (esc)
432 \r (no-eol) (esc)
445 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
433 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
446 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
434 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
447 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
435 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
448 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
436 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
449 \r (no-eol) (esc)
437 \r (no-eol) (esc)
450 \r (no-eol) (esc)
438 \r (no-eol) (esc)
451 archiving (sub1/sub2) [ ] 0/2\r (no-eol) (esc)
439 archiving (sub1/sub2) [ ] 0/2\r (no-eol) (esc)
452 archiving (sub1/sub2) [==============> ] 1/2\r (no-eol) (esc)
440 archiving (sub1/sub2) [==============> ] 1/2\r (no-eol) (esc)
453 archiving (sub1/sub2) [==============================>] 2/2\r (no-eol) (esc)
441 archiving (sub1/sub2) [==============================>] 2/2\r (no-eol) (esc)
454 \r (no-eol) (esc)
442 \r (no-eol) (esc)
455 $ find ../wdir -type f | sort
443 $ find ../wdir -type f | sort
456 ../wdir/.hg_archival.txt
444 ../wdir/.hg_archival.txt
457 ../wdir/.hgsub
445 ../wdir/.hgsub
458 ../wdir/.hgsubstate
446 ../wdir/.hgsubstate
459 ../wdir/foo/bar/abc
447 ../wdir/foo/bar/abc
460 ../wdir/sub1/.hgsub
448 ../wdir/sub1/.hgsub
461 ../wdir/sub1/.hgsubstate
449 ../wdir/sub1/.hgsubstate
462 ../wdir/sub1/foo
450 ../wdir/sub1/foo
463 ../wdir/sub1/sub2/folder/test.txt
451 ../wdir/sub1/sub2/folder/test.txt
464 ../wdir/sub1/sub2/sub2
452 ../wdir/sub1/sub2/sub2
465
453
466 Continue relative path printing + subrepos
454 Continue relative path printing + subrepos
467 $ hg update -Cq
455 $ hg update -Cq
468 $ rm -r ../wdir
456 $ rm -r ../wdir
469 $ hg archive -S -r 'wdir()' ../wdir
457 $ hg archive -S -r 'wdir()' ../wdir
470 \r (no-eol) (esc)
458 \r (no-eol) (esc)
471 archiving [ ] 0/3\r (no-eol) (esc)
459 archiving [ ] 0/3\r (no-eol) (esc)
472 archiving [=============> ] 1/3\r (no-eol) (esc)
460 archiving [=============> ] 1/3\r (no-eol) (esc)
473 archiving [===========================> ] 2/3\r (no-eol) (esc)
461 archiving [===========================> ] 2/3\r (no-eol) (esc)
474 archiving [==========================================>] 3/3\r (no-eol) (esc)
462 archiving [==========================================>] 3/3\r (no-eol) (esc)
475 \r (no-eol) (esc)
463 \r (no-eol) (esc)
476 \r (no-eol) (esc)
464 \r (no-eol) (esc)
477 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
465 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
478 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
466 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
479 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
467 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
480 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
468 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
481 \r (no-eol) (esc)
469 \r (no-eol) (esc)
482 \r (no-eol) (esc)
470 \r (no-eol) (esc)
483 archiving (sub1/sub2) [ ] 0/3\r (no-eol) (esc)
471 archiving (sub1/sub2) [ ] 0/3\r (no-eol) (esc)
484 archiving (sub1/sub2) [=========> ] 1/3\r (no-eol) (esc)
472 archiving (sub1/sub2) [=========> ] 1/3\r (no-eol) (esc)
485 archiving (sub1/sub2) [===================> ] 2/3\r (no-eol) (esc)
473 archiving (sub1/sub2) [===================> ] 2/3\r (no-eol) (esc)
486 archiving (sub1/sub2) [==============================>] 3/3\r (no-eol) (esc)
474 archiving (sub1/sub2) [==============================>] 3/3\r (no-eol) (esc)
487 \r (no-eol) (esc)
475 \r (no-eol) (esc)
488 $ cat ../wdir/.hg_archival.txt
476 $ cat ../wdir/.hg_archival.txt
489 repo: 7f491f53a367861f47ee64a80eb997d1f341b77a
477 repo: 7f491f53a367861f47ee64a80eb997d1f341b77a
490 node: 9bb10eebee29dc0f1201dcf5977b811a540255fd
478 node: 9bb10eebee29dc0f1201dcf5977b811a540255fd
491 branch: default
479 branch: default
492 latesttag: null
480 latesttag: null
493 latesttagdistance: 4
481 latesttagdistance: 4
494 changessincelatesttag: 4
482 changessincelatesttag: 4
495
483
496 $ touch sub1/sub2/folder/bar
484 $ touch sub1/sub2/folder/bar
497 $ hg addremove sub1/sub2
485 $ hg addremove sub1/sub2
498 adding sub1/sub2/folder/bar
486 adding sub1/sub2/folder/bar
499 $ hg status -S
487 $ hg status -S
500 A sub1/sub2/folder/bar
488 A sub1/sub2/folder/bar
501 ? foo/bar/abc
489 ? foo/bar/abc
502 ? sub1/foo
490 ? sub1/foo
503 $ hg update -Cq
491 $ hg update -Cq
504 $ hg addremove sub1
492 $ hg addremove sub1
505 adding sub1/sub2/folder/bar
493 adding sub1/sub2/folder/bar
506 adding sub1/foo
494 adding sub1/foo
507 $ hg update -Cq
495 $ hg update -Cq
508 $ rm sub1/sub2/folder/test.txt
496 $ rm sub1/sub2/folder/test.txt
509 $ rm sub1/sub2/test.txt
497 $ rm sub1/sub2/test.txt
510 $ hg ci -ASm "remove test.txt"
498 $ hg ci -ASm "remove test.txt"
511 adding sub1/sub2/folder/bar
499 adding sub1/sub2/folder/bar
512 removing sub1/sub2/folder/test.txt
500 removing sub1/sub2/folder/test.txt
513 removing sub1/sub2/test.txt
501 removing sub1/sub2/test.txt
514 adding sub1/foo
502 adding sub1/foo
515 adding foo/bar/abc
503 adding foo/bar/abc
516 committing subrepository sub1
504 committing subrepository sub1
517 committing subrepository sub1/sub2
505 committing subrepository sub1/sub2
518
506
519 $ hg forget sub1/sub2/sub2
507 $ hg forget sub1/sub2/sub2
520 $ echo x > sub1/sub2/x.txt
508 $ echo x > sub1/sub2/x.txt
521 $ hg add sub1/sub2/x.txt
509 $ hg add sub1/sub2/x.txt
522
510
523 Files sees uncommitted adds and removes in subrepos
511 Files sees uncommitted adds and removes in subrepos
524 $ hg files -S
512 $ hg files -S
525 .hgsub
513 .hgsub
526 .hgsubstate
514 .hgsubstate
527 foo/bar/abc
515 foo/bar/abc
528 main
516 main
529 sub1/.hgsub
517 sub1/.hgsub
530 sub1/.hgsubstate
518 sub1/.hgsubstate
531 sub1/foo
519 sub1/foo
532 sub1/sub1
520 sub1/sub1
533 sub1/sub2/folder/bar
521 sub1/sub2/folder/bar
534 sub1/sub2/x.txt
522 sub1/sub2/x.txt
535
523
536 $ hg files -S "set:eol('dos') or eol('unix') or size('<= 0')"
524 $ hg files -S "set:eol('dos') or eol('unix') or size('<= 0')"
537 .hgsub
525 .hgsub
538 .hgsubstate
526 .hgsubstate
539 foo/bar/abc
527 foo/bar/abc
540 main
528 main
541 sub1/.hgsub
529 sub1/.hgsub
542 sub1/.hgsubstate
530 sub1/.hgsubstate
543 sub1/foo
531 sub1/foo
544 sub1/sub1
532 sub1/sub1
545 sub1/sub2/folder/bar
533 sub1/sub2/folder/bar
546 sub1/sub2/x.txt
534 sub1/sub2/x.txt
547
535
548 $ hg files -r '.^' -S "set:eol('dos') or eol('unix')"
536 $ hg files -r '.^' -S "set:eol('dos') or eol('unix')"
549 .hgsub
537 .hgsub
550 .hgsubstate
538 .hgsubstate
551 main
539 main
552 sub1/.hgsub
540 sub1/.hgsub
553 sub1/.hgsubstate
541 sub1/.hgsubstate
554 sub1/sub1
542 sub1/sub1
555 sub1/sub2/folder/test.txt
543 sub1/sub2/folder/test.txt
556 sub1/sub2/sub2
544 sub1/sub2/sub2
557 sub1/sub2/test.txt
545 sub1/sub2/test.txt
558
546
559 $ hg files sub1
547 $ hg files sub1
560 sub1/.hgsub
548 sub1/.hgsub
561 sub1/.hgsubstate
549 sub1/.hgsubstate
562 sub1/foo
550 sub1/foo
563 sub1/sub1
551 sub1/sub1
564 sub1/sub2/folder/bar
552 sub1/sub2/folder/bar
565 sub1/sub2/x.txt
553 sub1/sub2/x.txt
566
554
567 $ hg files sub1/sub2
555 $ hg files sub1/sub2
568 sub1/sub2/folder/bar
556 sub1/sub2/folder/bar
569 sub1/sub2/x.txt
557 sub1/sub2/x.txt
570
558
571 $ hg files
559 $ hg files
572 .hgsub
560 .hgsub
573 .hgsubstate
561 .hgsubstate
574 foo/bar/abc
562 foo/bar/abc
575 main
563 main
576
564
577 $ hg files -S -r '.^' sub1/sub2/folder
565 $ hg files -S -r '.^' sub1/sub2/folder
578 sub1/sub2/folder/test.txt
566 sub1/sub2/folder/test.txt
579
567
580 $ hg files -S -r '.^' sub1/sub2/missing
568 $ hg files -S -r '.^' sub1/sub2/missing
581 sub1/sub2/missing: no such file in rev 78026e779ea6
569 sub1/sub2/missing: no such file in rev 78026e779ea6
582 [1]
570 [1]
583
571
584 $ hg files -r '.^' sub1/
572 $ hg files -r '.^' sub1/
585 sub1/.hgsub
573 sub1/.hgsub
586 sub1/.hgsubstate
574 sub1/.hgsubstate
587 sub1/sub1
575 sub1/sub1
588 sub1/sub2/folder/test.txt
576 sub1/sub2/folder/test.txt
589 sub1/sub2/sub2
577 sub1/sub2/sub2
590 sub1/sub2/test.txt
578 sub1/sub2/test.txt
591
579
592 $ hg files -r '.^' sub1/sub2
580 $ hg files -r '.^' sub1/sub2
593 sub1/sub2/folder/test.txt
581 sub1/sub2/folder/test.txt
594 sub1/sub2/sub2
582 sub1/sub2/sub2
595 sub1/sub2/test.txt
583 sub1/sub2/test.txt
596
584
597 $ hg rollback -q
585 $ hg rollback -q
598 $ hg up -Cq
586 $ hg up -Cq
599
587
600 $ hg --config extensions.largefiles=! archive -S ../archive_all
588 $ hg --config extensions.largefiles=! archive -S ../archive_all
601 \r (no-eol) (esc)
589 \r (no-eol) (esc)
602 archiving [ ] 0/3\r (no-eol) (esc)
590 archiving [ ] 0/3\r (no-eol) (esc)
603 archiving [=============> ] 1/3\r (no-eol) (esc)
591 archiving [=============> ] 1/3\r (no-eol) (esc)
604 archiving [===========================> ] 2/3\r (no-eol) (esc)
592 archiving [===========================> ] 2/3\r (no-eol) (esc)
605 archiving [==========================================>] 3/3\r (no-eol) (esc)
593 archiving [==========================================>] 3/3\r (no-eol) (esc)
606 \r (no-eol) (esc)
594 \r (no-eol) (esc)
607 \r (no-eol) (esc)
595 \r (no-eol) (esc)
608 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
596 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
609 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
597 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
610 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
598 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
611 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
599 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
612 \r (no-eol) (esc)
600 \r (no-eol) (esc)
613 \r (no-eol) (esc)
601 \r (no-eol) (esc)
614 archiving (sub1/sub2) [ ] 0/3\r (no-eol) (esc)
602 archiving (sub1/sub2) [ ] 0/3\r (no-eol) (esc)
615 archiving (sub1/sub2) [=========> ] 1/3\r (no-eol) (esc)
603 archiving (sub1/sub2) [=========> ] 1/3\r (no-eol) (esc)
616 archiving (sub1/sub2) [===================> ] 2/3\r (no-eol) (esc)
604 archiving (sub1/sub2) [===================> ] 2/3\r (no-eol) (esc)
617 archiving (sub1/sub2) [==============================>] 3/3\r (no-eol) (esc)
605 archiving (sub1/sub2) [==============================>] 3/3\r (no-eol) (esc)
618 \r (no-eol) (esc)
606 \r (no-eol) (esc)
619 $ find ../archive_all | sort
607 $ find ../archive_all | sort
620 ../archive_all
608 ../archive_all
621 ../archive_all/.hg_archival.txt
609 ../archive_all/.hg_archival.txt
622 ../archive_all/.hgsub
610 ../archive_all/.hgsub
623 ../archive_all/.hgsubstate
611 ../archive_all/.hgsubstate
624 ../archive_all/main
612 ../archive_all/main
625 ../archive_all/sub1
613 ../archive_all/sub1
626 ../archive_all/sub1/.hgsub
614 ../archive_all/sub1/.hgsub
627 ../archive_all/sub1/.hgsubstate
615 ../archive_all/sub1/.hgsubstate
628 ../archive_all/sub1/sub1
616 ../archive_all/sub1/sub1
629 ../archive_all/sub1/sub2
617 ../archive_all/sub1/sub2
630 ../archive_all/sub1/sub2/folder
618 ../archive_all/sub1/sub2/folder
631 ../archive_all/sub1/sub2/folder/test.txt
619 ../archive_all/sub1/sub2/folder/test.txt
632 ../archive_all/sub1/sub2/sub2
620 ../archive_all/sub1/sub2/sub2
633 ../archive_all/sub1/sub2/test.txt
621 ../archive_all/sub1/sub2/test.txt
634
622
635 Check that archive -X works in deep subrepos
623 Check that archive -X works in deep subrepos
636
624
637 $ hg --config extensions.largefiles=! archive -S -X '**test*' ../archive_exclude
625 $ hg --config extensions.largefiles=! archive -S -X '**test*' ../archive_exclude
638 \r (no-eol) (esc)
626 \r (no-eol) (esc)
639 archiving [ ] 0/3\r (no-eol) (esc)
627 archiving [ ] 0/3\r (no-eol) (esc)
640 archiving [=============> ] 1/3\r (no-eol) (esc)
628 archiving [=============> ] 1/3\r (no-eol) (esc)
641 archiving [===========================> ] 2/3\r (no-eol) (esc)
629 archiving [===========================> ] 2/3\r (no-eol) (esc)
642 archiving [==========================================>] 3/3\r (no-eol) (esc)
630 archiving [==========================================>] 3/3\r (no-eol) (esc)
643 \r (no-eol) (esc)
631 \r (no-eol) (esc)
644 \r (no-eol) (esc)
632 \r (no-eol) (esc)
645 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
633 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
646 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
634 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
647 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
635 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
648 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
636 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
649 \r (no-eol) (esc)
637 \r (no-eol) (esc)
650 \r (no-eol) (esc)
638 \r (no-eol) (esc)
651 archiving (sub1/sub2) [ ] 0/1\r (no-eol) (esc)
639 archiving (sub1/sub2) [ ] 0/1\r (no-eol) (esc)
652 archiving (sub1/sub2) [==============================>] 1/1\r (no-eol) (esc)
640 archiving (sub1/sub2) [==============================>] 1/1\r (no-eol) (esc)
653 \r (no-eol) (esc)
641 \r (no-eol) (esc)
654 $ find ../archive_exclude | sort
642 $ find ../archive_exclude | sort
655 ../archive_exclude
643 ../archive_exclude
656 ../archive_exclude/.hg_archival.txt
644 ../archive_exclude/.hg_archival.txt
657 ../archive_exclude/.hgsub
645 ../archive_exclude/.hgsub
658 ../archive_exclude/.hgsubstate
646 ../archive_exclude/.hgsubstate
659 ../archive_exclude/main
647 ../archive_exclude/main
660 ../archive_exclude/sub1
648 ../archive_exclude/sub1
661 ../archive_exclude/sub1/.hgsub
649 ../archive_exclude/sub1/.hgsub
662 ../archive_exclude/sub1/.hgsubstate
650 ../archive_exclude/sub1/.hgsubstate
663 ../archive_exclude/sub1/sub1
651 ../archive_exclude/sub1/sub1
664 ../archive_exclude/sub1/sub2
652 ../archive_exclude/sub1/sub2
665 ../archive_exclude/sub1/sub2/sub2
653 ../archive_exclude/sub1/sub2/sub2
666
654
667 $ hg --config extensions.largefiles=! archive -S -I '**test*' ../archive_include
655 $ hg --config extensions.largefiles=! archive -S -I '**test*' ../archive_include
668 \r (no-eol) (esc)
656 \r (no-eol) (esc)
669 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
657 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
670 \r (no-eol) (esc)
658 \r (no-eol) (esc)
671 \r (no-eol) (esc)
659 \r (no-eol) (esc)
672 archiving (sub1/sub2) [ ] 0/2\r (no-eol) (esc)
660 archiving (sub1/sub2) [ ] 0/2\r (no-eol) (esc)
673 archiving (sub1/sub2) [==============> ] 1/2\r (no-eol) (esc)
661 archiving (sub1/sub2) [==============> ] 1/2\r (no-eol) (esc)
674 archiving (sub1/sub2) [==============================>] 2/2\r (no-eol) (esc)
662 archiving (sub1/sub2) [==============================>] 2/2\r (no-eol) (esc)
675 \r (no-eol) (esc)
663 \r (no-eol) (esc)
676 $ find ../archive_include | sort
664 $ find ../archive_include | sort
677 ../archive_include
665 ../archive_include
678 ../archive_include/sub1
666 ../archive_include/sub1
679 ../archive_include/sub1/sub2
667 ../archive_include/sub1/sub2
680 ../archive_include/sub1/sub2/folder
668 ../archive_include/sub1/sub2/folder
681 ../archive_include/sub1/sub2/folder/test.txt
669 ../archive_include/sub1/sub2/folder/test.txt
682 ../archive_include/sub1/sub2/test.txt
670 ../archive_include/sub1/sub2/test.txt
683
671
684 Check that deep archive works with largefiles (which overrides hgsubrepo impl)
672 Check that deep archive works with largefiles (which overrides hgsubrepo impl)
685 This also tests the repo.ui regression in 43fb170a23bd, and that lf subrepo
673 This also tests the repo.ui regression in 43fb170a23bd, and that lf subrepo
686 subrepos are archived properly.
674 subrepos are archived properly.
687 Note that add --large through a subrepo currently adds the file as a normal file
675 Note that add --large through a subrepo currently adds the file as a normal file
688
676
689 $ echo "large" > sub1/sub2/large.bin
677 $ echo "large" > sub1/sub2/large.bin
690 $ hg --config extensions.largefiles= add --large -R sub1/sub2 sub1/sub2/large.bin
678 $ hg --config extensions.largefiles= add --large -R sub1/sub2 sub1/sub2/large.bin
691 $ echo "large" > large.bin
679 $ echo "large" > large.bin
692 $ hg --config extensions.largefiles= add --large large.bin
680 $ hg --config extensions.largefiles= add --large large.bin
693 $ hg --config extensions.largefiles= ci -S -m "add large files"
681 $ hg --config extensions.largefiles= ci -S -m "add large files"
694 committing subrepository sub1
682 committing subrepository sub1
695 committing subrepository sub1/sub2
683 committing subrepository sub1/sub2
696
684
697 $ hg --config extensions.largefiles= archive -S ../archive_lf
685 $ hg --config extensions.largefiles= archive -S ../archive_lf
698 $ find ../archive_lf | sort
686 $ find ../archive_lf | sort
699 ../archive_lf
687 ../archive_lf
700 ../archive_lf/.hg_archival.txt
688 ../archive_lf/.hg_archival.txt
701 ../archive_lf/.hgsub
689 ../archive_lf/.hgsub
702 ../archive_lf/.hgsubstate
690 ../archive_lf/.hgsubstate
703 ../archive_lf/large.bin
691 ../archive_lf/large.bin
704 ../archive_lf/main
692 ../archive_lf/main
705 ../archive_lf/sub1
693 ../archive_lf/sub1
706 ../archive_lf/sub1/.hgsub
694 ../archive_lf/sub1/.hgsub
707 ../archive_lf/sub1/.hgsubstate
695 ../archive_lf/sub1/.hgsubstate
708 ../archive_lf/sub1/sub1
696 ../archive_lf/sub1/sub1
709 ../archive_lf/sub1/sub2
697 ../archive_lf/sub1/sub2
710 ../archive_lf/sub1/sub2/folder
698 ../archive_lf/sub1/sub2/folder
711 ../archive_lf/sub1/sub2/folder/test.txt
699 ../archive_lf/sub1/sub2/folder/test.txt
712 ../archive_lf/sub1/sub2/large.bin
700 ../archive_lf/sub1/sub2/large.bin
713 ../archive_lf/sub1/sub2/sub2
701 ../archive_lf/sub1/sub2/sub2
714 ../archive_lf/sub1/sub2/test.txt
702 ../archive_lf/sub1/sub2/test.txt
715 $ rm -rf ../archive_lf
703 $ rm -rf ../archive_lf
716
704
717 Exclude large files from main and sub-sub repo
705 Exclude large files from main and sub-sub repo
718
706
719 $ hg --config extensions.largefiles= archive -S -X '**.bin' ../archive_lf
707 $ hg --config extensions.largefiles= archive -S -X '**.bin' ../archive_lf
720 $ find ../archive_lf | sort
708 $ find ../archive_lf | sort
721 ../archive_lf
709 ../archive_lf
722 ../archive_lf/.hg_archival.txt
710 ../archive_lf/.hg_archival.txt
723 ../archive_lf/.hgsub
711 ../archive_lf/.hgsub
724 ../archive_lf/.hgsubstate
712 ../archive_lf/.hgsubstate
725 ../archive_lf/main
713 ../archive_lf/main
726 ../archive_lf/sub1
714 ../archive_lf/sub1
727 ../archive_lf/sub1/.hgsub
715 ../archive_lf/sub1/.hgsub
728 ../archive_lf/sub1/.hgsubstate
716 ../archive_lf/sub1/.hgsubstate
729 ../archive_lf/sub1/sub1
717 ../archive_lf/sub1/sub1
730 ../archive_lf/sub1/sub2
718 ../archive_lf/sub1/sub2
731 ../archive_lf/sub1/sub2/folder
719 ../archive_lf/sub1/sub2/folder
732 ../archive_lf/sub1/sub2/folder/test.txt
720 ../archive_lf/sub1/sub2/folder/test.txt
733 ../archive_lf/sub1/sub2/sub2
721 ../archive_lf/sub1/sub2/sub2
734 ../archive_lf/sub1/sub2/test.txt
722 ../archive_lf/sub1/sub2/test.txt
735 $ rm -rf ../archive_lf
723 $ rm -rf ../archive_lf
736
724
737 Exclude normal files from main and sub-sub repo
725 Exclude normal files from main and sub-sub repo
738
726
739 $ hg --config extensions.largefiles= archive -S -X '**.txt' -p '.' ../archive_lf.tgz
727 $ hg --config extensions.largefiles= archive -S -X '**.txt' -p '.' ../archive_lf.tgz
740 $ tar -tzf ../archive_lf.tgz | sort
728 $ tar -tzf ../archive_lf.tgz | sort
741 .hgsub
729 .hgsub
742 .hgsubstate
730 .hgsubstate
743 large.bin
731 large.bin
744 main
732 main
745 sub1/.hgsub
733 sub1/.hgsub
746 sub1/.hgsubstate
734 sub1/.hgsubstate
747 sub1/sub1
735 sub1/sub1
748 sub1/sub2/large.bin
736 sub1/sub2/large.bin
749 sub1/sub2/sub2
737 sub1/sub2/sub2
750
738
751 Include normal files from within a largefiles subrepo
739 Include normal files from within a largefiles subrepo
752
740
753 $ hg --config extensions.largefiles= archive -S -I '**.txt' ../archive_lf
741 $ hg --config extensions.largefiles= archive -S -I '**.txt' ../archive_lf
754 $ find ../archive_lf | sort
742 $ find ../archive_lf | sort
755 ../archive_lf
743 ../archive_lf
756 ../archive_lf/.hg_archival.txt
744 ../archive_lf/.hg_archival.txt
757 ../archive_lf/sub1
745 ../archive_lf/sub1
758 ../archive_lf/sub1/sub2
746 ../archive_lf/sub1/sub2
759 ../archive_lf/sub1/sub2/folder
747 ../archive_lf/sub1/sub2/folder
760 ../archive_lf/sub1/sub2/folder/test.txt
748 ../archive_lf/sub1/sub2/folder/test.txt
761 ../archive_lf/sub1/sub2/test.txt
749 ../archive_lf/sub1/sub2/test.txt
762 $ rm -rf ../archive_lf
750 $ rm -rf ../archive_lf
763
751
764 Include large files from within a largefiles subrepo
752 Include large files from within a largefiles subrepo
765
753
766 $ hg --config extensions.largefiles= archive -S -I '**.bin' ../archive_lf
754 $ hg --config extensions.largefiles= archive -S -I '**.bin' ../archive_lf
767 $ find ../archive_lf | sort
755 $ find ../archive_lf | sort
768 ../archive_lf
756 ../archive_lf
769 ../archive_lf/large.bin
757 ../archive_lf/large.bin
770 ../archive_lf/sub1
758 ../archive_lf/sub1
771 ../archive_lf/sub1/sub2
759 ../archive_lf/sub1/sub2
772 ../archive_lf/sub1/sub2/large.bin
760 ../archive_lf/sub1/sub2/large.bin
773 $ rm -rf ../archive_lf
761 $ rm -rf ../archive_lf
774
762
775 Find an exact largefile match in a largefiles subrepo
763 Find an exact largefile match in a largefiles subrepo
776
764
777 $ hg --config extensions.largefiles= archive -S -I 'sub1/sub2/large.bin' ../archive_lf
765 $ hg --config extensions.largefiles= archive -S -I 'sub1/sub2/large.bin' ../archive_lf
778 $ find ../archive_lf | sort
766 $ find ../archive_lf | sort
779 ../archive_lf
767 ../archive_lf
780 ../archive_lf/sub1
768 ../archive_lf/sub1
781 ../archive_lf/sub1/sub2
769 ../archive_lf/sub1/sub2
782 ../archive_lf/sub1/sub2/large.bin
770 ../archive_lf/sub1/sub2/large.bin
783 $ rm -rf ../archive_lf
771 $ rm -rf ../archive_lf
784
772
785 The local repo enables largefiles if a largefiles repo is cloned
773 The local repo enables largefiles if a largefiles repo is cloned
786
774
787 $ hg showconfig extensions
775 $ hg showconfig extensions
788 extensions.largefiles=
776 extensions.largefiles=
789
777
790 $ hg --config extensions.largefiles= clone -qU . ../lfclone
778 $ hg --config extensions.largefiles= clone -qU . ../lfclone
791 $ grep largefiles ../lfclone/.hg/requires
779 $ grep largefiles ../lfclone/.hg/requires
792 largefiles
780 largefiles
793
781
794 Find an exact match to a standin (should archive nothing)
782 Find an exact match to a standin (should archive nothing)
795 $ hg --config extensions.largefiles= archive -S -I 'sub/sub2/.hglf/large.bin' ../archive_lf
783 $ hg --config extensions.largefiles= archive -S -I 'sub/sub2/.hglf/large.bin' ../archive_lf
796 $ find ../archive_lf 2> /dev/null | sort
784 $ find ../archive_lf 2> /dev/null | sort
797
785
798 $ cat >> $HGRCPATH <<EOF
786 $ cat >> $HGRCPATH <<EOF
799 > [extensions]
787 > [extensions]
800 > largefiles=
788 > largefiles=
801 > [largefiles]
789 > [largefiles]
802 > patterns=glob:**.dat
790 > patterns=glob:**.dat
803 > EOF
791 > EOF
804
792
805 Test forget through a deep subrepo with the largefiles extension, both a
793 Test forget through a deep subrepo with the largefiles extension, both a
806 largefile and a normal file. Then a largefile that hasn't been committed yet.
794 largefile and a normal file. Then a largefile that hasn't been committed yet.
807 $ touch sub1/sub2/untracked.txt
795 $ touch sub1/sub2/untracked.txt
808 $ touch sub1/sub2/large.dat
796 $ touch sub1/sub2/large.dat
809 $ hg forget sub1/sub2/large.bin sub1/sub2/test.txt sub1/sub2/untracked.txt
797 $ hg forget sub1/sub2/large.bin sub1/sub2/test.txt sub1/sub2/untracked.txt
810 not removing sub1/sub2/untracked.txt: file is already untracked
798 not removing sub1/sub2/untracked.txt: file is already untracked
811 [1]
799 [1]
812 $ hg add --large --dry-run -v sub1/sub2/untracked.txt
800 $ hg add --large --dry-run -v sub1/sub2/untracked.txt
813 adding sub1/sub2/untracked.txt as a largefile
801 adding sub1/sub2/untracked.txt as a largefile
814 $ hg add --large -v sub1/sub2/untracked.txt
802 $ hg add --large -v sub1/sub2/untracked.txt
815 adding sub1/sub2/untracked.txt as a largefile
803 adding sub1/sub2/untracked.txt as a largefile
816 $ hg add --normal -v sub1/sub2/large.dat
804 $ hg add --normal -v sub1/sub2/large.dat
817 adding sub1/sub2/large.dat
805 adding sub1/sub2/large.dat
818 $ hg forget -v sub1/sub2/untracked.txt
806 $ hg forget -v sub1/sub2/untracked.txt
819 removing sub1/sub2/untracked.txt
807 removing sub1/sub2/untracked.txt
820 $ hg status -S
808 $ hg status -S
821 A sub1/sub2/large.dat
809 A sub1/sub2/large.dat
822 R sub1/sub2/large.bin
810 R sub1/sub2/large.bin
823 R sub1/sub2/test.txt
811 R sub1/sub2/test.txt
824 ? foo/bar/abc
812 ? foo/bar/abc
825 ? sub1/sub2/untracked.txt
813 ? sub1/sub2/untracked.txt
826 ? sub1/sub2/x.txt
814 ? sub1/sub2/x.txt
827 $ hg add sub1/sub2
815 $ hg add sub1/sub2
828
816
829 $ hg archive -S -r 'wdir()' ../wdir2
817 $ hg archive -S -r 'wdir()' ../wdir2
830 $ diff -r . ../wdir2 | egrep -v '\.hg$|^Common subdirectories:'
818 $ diff -r . ../wdir2 | egrep -v '\.hg$|^Common subdirectories:'
831 Only in ../wdir2: .hg_archival.txt
819 Only in ../wdir2: .hg_archival.txt
832 Only in .: .hglf
820 Only in .: .hglf
833 Only in .: foo
821 Only in .: foo
834 Only in ./sub1/sub2: large.bin
822 Only in ./sub1/sub2: large.bin
835 Only in ./sub1/sub2: test.txt
823 Only in ./sub1/sub2: test.txt
836 Only in ./sub1/sub2: untracked.txt
824 Only in ./sub1/sub2: untracked.txt
837 Only in ./sub1/sub2: x.txt
825 Only in ./sub1/sub2: x.txt
838 $ find ../wdir2 -type f | sort
826 $ find ../wdir2 -type f | sort
839 ../wdir2/.hg_archival.txt
827 ../wdir2/.hg_archival.txt
840 ../wdir2/.hgsub
828 ../wdir2/.hgsub
841 ../wdir2/.hgsubstate
829 ../wdir2/.hgsubstate
842 ../wdir2/large.bin
830 ../wdir2/large.bin
843 ../wdir2/main
831 ../wdir2/main
844 ../wdir2/sub1/.hgsub
832 ../wdir2/sub1/.hgsub
845 ../wdir2/sub1/.hgsubstate
833 ../wdir2/sub1/.hgsubstate
846 ../wdir2/sub1/sub1
834 ../wdir2/sub1/sub1
847 ../wdir2/sub1/sub2/folder/test.txt
835 ../wdir2/sub1/sub2/folder/test.txt
848 ../wdir2/sub1/sub2/large.dat
836 ../wdir2/sub1/sub2/large.dat
849 ../wdir2/sub1/sub2/sub2
837 ../wdir2/sub1/sub2/sub2
850 $ hg status -S -mac -n | sort
838 $ hg status -S -mac -n | sort
851 .hgsub
839 .hgsub
852 .hgsubstate
840 .hgsubstate
853 large.bin
841 large.bin
854 main
842 main
855 sub1/.hgsub
843 sub1/.hgsub
856 sub1/.hgsubstate
844 sub1/.hgsubstate
857 sub1/sub1
845 sub1/sub1
858 sub1/sub2/folder/test.txt
846 sub1/sub2/folder/test.txt
859 sub1/sub2/large.dat
847 sub1/sub2/large.dat
860 sub1/sub2/sub2
848 sub1/sub2/sub2
861
849
862 $ hg ci -Sqm 'forget testing'
850 $ hg ci -Sqm 'forget testing'
863
851
864 Test 'wdir()' modified file archiving with largefiles
852 Test 'wdir()' modified file archiving with largefiles
865 $ echo 'mod' > main
853 $ echo 'mod' > main
866 $ echo 'mod' > large.bin
854 $ echo 'mod' > large.bin
867 $ echo 'mod' > sub1/sub2/large.dat
855 $ echo 'mod' > sub1/sub2/large.dat
868 $ hg archive -S -r 'wdir()' ../wdir3
856 $ hg archive -S -r 'wdir()' ../wdir3
869 $ diff -r . ../wdir3 | egrep -v '\.hg$|^Common subdirectories'
857 $ diff -r . ../wdir3 | egrep -v '\.hg$|^Common subdirectories'
870 Only in ../wdir3: .hg_archival.txt
858 Only in ../wdir3: .hg_archival.txt
871 Only in .: .hglf
859 Only in .: .hglf
872 Only in .: foo
860 Only in .: foo
873 Only in ./sub1/sub2: large.bin
861 Only in ./sub1/sub2: large.bin
874 Only in ./sub1/sub2: test.txt
862 Only in ./sub1/sub2: test.txt
875 Only in ./sub1/sub2: untracked.txt
863 Only in ./sub1/sub2: untracked.txt
876 Only in ./sub1/sub2: x.txt
864 Only in ./sub1/sub2: x.txt
877 $ find ../wdir3 -type f | sort
865 $ find ../wdir3 -type f | sort
878 ../wdir3/.hg_archival.txt
866 ../wdir3/.hg_archival.txt
879 ../wdir3/.hgsub
867 ../wdir3/.hgsub
880 ../wdir3/.hgsubstate
868 ../wdir3/.hgsubstate
881 ../wdir3/large.bin
869 ../wdir3/large.bin
882 ../wdir3/main
870 ../wdir3/main
883 ../wdir3/sub1/.hgsub
871 ../wdir3/sub1/.hgsub
884 ../wdir3/sub1/.hgsubstate
872 ../wdir3/sub1/.hgsubstate
885 ../wdir3/sub1/sub1
873 ../wdir3/sub1/sub1
886 ../wdir3/sub1/sub2/folder/test.txt
874 ../wdir3/sub1/sub2/folder/test.txt
887 ../wdir3/sub1/sub2/large.dat
875 ../wdir3/sub1/sub2/large.dat
888 ../wdir3/sub1/sub2/sub2
876 ../wdir3/sub1/sub2/sub2
889 $ hg up -Cq
877 $ hg up -Cq
890
878
891 Test issue4330: commit a directory where only normal files have changed
879 Test issue4330: commit a directory where only normal files have changed
892 $ touch foo/bar/large.dat
880 $ touch foo/bar/large.dat
893 $ hg add --large foo/bar/large.dat
881 $ hg add --large foo/bar/large.dat
894 $ hg ci -m 'add foo/bar/large.dat'
882 $ hg ci -m 'add foo/bar/large.dat'
895 $ touch a.txt
883 $ touch a.txt
896 $ touch a.dat
884 $ touch a.dat
897 $ hg add -v foo/bar/abc a.txt a.dat
885 $ hg add -v foo/bar/abc a.txt a.dat
898 adding a.dat as a largefile
886 adding a.dat as a largefile
899 adding a.txt
887 adding a.txt
900 adding foo/bar/abc
888 adding foo/bar/abc
901 $ hg ci -m 'dir commit with only normal file deltas' foo/bar
889 $ hg ci -m 'dir commit with only normal file deltas' foo/bar
902 $ hg status
890 $ hg status
903 A a.dat
891 A a.dat
904 A a.txt
892 A a.txt
905
893
906 Test a directory commit with a changed largefile and a changed normal file
894 Test a directory commit with a changed largefile and a changed normal file
907 $ echo changed > foo/bar/large.dat
895 $ echo changed > foo/bar/large.dat
908 $ echo changed > foo/bar/abc
896 $ echo changed > foo/bar/abc
909 $ hg ci -m 'dir commit with normal and lf file deltas' foo
897 $ hg ci -m 'dir commit with normal and lf file deltas' foo
910 $ hg status
898 $ hg status
911 A a.dat
899 A a.dat
912 A a.txt
900 A a.txt
913
901
914 $ hg ci -m "add a.*"
902 $ hg ci -m "add a.*"
915 $ hg mv a.dat b.dat
903 $ hg mv a.dat b.dat
916 $ hg mv foo/bar/abc foo/bar/def
904 $ hg mv foo/bar/abc foo/bar/def
917 $ hg status -C
905 $ hg status -C
918 A b.dat
906 A b.dat
919 a.dat
907 a.dat
920 A foo/bar/def
908 A foo/bar/def
921 foo/bar/abc
909 foo/bar/abc
922 R a.dat
910 R a.dat
923 R foo/bar/abc
911 R foo/bar/abc
924
912
925 $ hg ci -m "move large and normal"
913 $ hg ci -m "move large and normal"
926 $ hg status -C --rev '.^' --rev .
914 $ hg status -C --rev '.^' --rev .
927 A b.dat
915 A b.dat
928 a.dat
916 a.dat
929 A foo/bar/def
917 A foo/bar/def
930 foo/bar/abc
918 foo/bar/abc
931 R a.dat
919 R a.dat
932 R foo/bar/abc
920 R foo/bar/abc
933
921
934
922
935 $ echo foo > main
923 $ echo foo > main
936 $ hg ci -m "mod parent only"
924 $ hg ci -m "mod parent only"
937 $ hg init sub3
925 $ hg init sub3
938 $ echo "sub3 = sub3" >> .hgsub
926 $ echo "sub3 = sub3" >> .hgsub
939 $ echo xyz > sub3/a.txt
927 $ echo xyz > sub3/a.txt
940 $ hg add sub3/a.txt
928 $ hg add sub3/a.txt
941 $ hg ci -Sm "add sub3"
929 $ hg ci -Sm "add sub3"
942 committing subrepository sub3
930 committing subrepository sub3
943 $ cat .hgsub | grep -v sub3 > .hgsub1
931 $ cat .hgsub | grep -v sub3 > .hgsub1
944 $ mv .hgsub1 .hgsub
932 $ mv .hgsub1 .hgsub
945 $ hg ci -m "remove sub3"
933 $ hg ci -m "remove sub3"
946
934
947 $ hg log -r "subrepo()" --style compact
935 $ hg log -r "subrepo()" --style compact
948 0 7f491f53a367 1970-01-01 00:00 +0000 test
936 0 7f491f53a367 1970-01-01 00:00 +0000 test
949 main import
937 main import
950
938
951 1 ffe6649062fe 1970-01-01 00:00 +0000 test
939 1 ffe6649062fe 1970-01-01 00:00 +0000 test
952 deep nested modif should trigger a commit
940 deep nested modif should trigger a commit
953
941
954 2 9bb10eebee29 1970-01-01 00:00 +0000 test
942 2 9bb10eebee29 1970-01-01 00:00 +0000 test
955 add test.txt
943 add test.txt
956
944
957 3 7c64f035294f 1970-01-01 00:00 +0000 test
945 3 7c64f035294f 1970-01-01 00:00 +0000 test
958 add large files
946 add large files
959
947
960 4 f734a59e2e35 1970-01-01 00:00 +0000 test
948 4 f734a59e2e35 1970-01-01 00:00 +0000 test
961 forget testing
949 forget testing
962
950
963 11 9685a22af5db 1970-01-01 00:00 +0000 test
951 11 9685a22af5db 1970-01-01 00:00 +0000 test
964 add sub3
952 add sub3
965
953
966 12[tip] 2e0485b475b9 1970-01-01 00:00 +0000 test
954 12[tip] 2e0485b475b9 1970-01-01 00:00 +0000 test
967 remove sub3
955 remove sub3
968
956
969 $ hg log -r "subrepo('sub3')" --style compact
957 $ hg log -r "subrepo('sub3')" --style compact
970 11 9685a22af5db 1970-01-01 00:00 +0000 test
958 11 9685a22af5db 1970-01-01 00:00 +0000 test
971 add sub3
959 add sub3
972
960
973 12[tip] 2e0485b475b9 1970-01-01 00:00 +0000 test
961 12[tip] 2e0485b475b9 1970-01-01 00:00 +0000 test
974 remove sub3
962 remove sub3
975
963
976 $ hg log -r "subrepo('bogus')" --style compact
964 $ hg log -r "subrepo('bogus')" --style compact
977
965
978
966
979 Test .hgsubstate in the R state
967 Test .hgsubstate in the R state
980
968
981 $ hg rm .hgsub .hgsubstate
969 $ hg rm .hgsub .hgsubstate
982 \r (no-eol) (esc)
970 \r (no-eol) (esc)
983 deleting [=====================> ] 1/2\r (no-eol) (esc)
971 deleting [=====================> ] 1/2\r (no-eol) (esc)
984 deleting [===========================================>] 2/2\r (no-eol) (esc)
972 deleting [===========================================>] 2/2\r (no-eol) (esc)
985 \r (no-eol) (esc)
973 \r (no-eol) (esc)
986 $ hg ci -m 'trash subrepo tracking'
974 $ hg ci -m 'trash subrepo tracking'
987
975
988 $ hg log -r "subrepo('re:sub\d+')" --style compact
976 $ hg log -r "subrepo('re:sub\d+')" --style compact
989 0 7f491f53a367 1970-01-01 00:00 +0000 test
977 0 7f491f53a367 1970-01-01 00:00 +0000 test
990 main import
978 main import
991
979
992 1 ffe6649062fe 1970-01-01 00:00 +0000 test
980 1 ffe6649062fe 1970-01-01 00:00 +0000 test
993 deep nested modif should trigger a commit
981 deep nested modif should trigger a commit
994
982
995 2 9bb10eebee29 1970-01-01 00:00 +0000 test
983 2 9bb10eebee29 1970-01-01 00:00 +0000 test
996 add test.txt
984 add test.txt
997
985
998 3 7c64f035294f 1970-01-01 00:00 +0000 test
986 3 7c64f035294f 1970-01-01 00:00 +0000 test
999 add large files
987 add large files
1000
988
1001 4 f734a59e2e35 1970-01-01 00:00 +0000 test
989 4 f734a59e2e35 1970-01-01 00:00 +0000 test
1002 forget testing
990 forget testing
1003
991
1004 11 9685a22af5db 1970-01-01 00:00 +0000 test
992 11 9685a22af5db 1970-01-01 00:00 +0000 test
1005 add sub3
993 add sub3
1006
994
1007 12 2e0485b475b9 1970-01-01 00:00 +0000 test
995 12 2e0485b475b9 1970-01-01 00:00 +0000 test
1008 remove sub3
996 remove sub3
1009
997
1010 13[tip] a68b2c361653 1970-01-01 00:00 +0000 test
998 13[tip] a68b2c361653 1970-01-01 00:00 +0000 test
1011 trash subrepo tracking
999 trash subrepo tracking
1012
1000
1013
1001
1014 Restore the trashed subrepo tracking
1002 Restore the trashed subrepo tracking
1015
1003
1016 $ hg rollback -q
1004 $ hg rollback -q
1017 $ hg update -Cq .
1005 $ hg update -Cq .
1018
1006
1019 Interaction with extdiff, largefiles and subrepos
1007 Interaction with extdiff, largefiles and subrepos
1020
1008
1021 $ hg --config extensions.extdiff= pdiff -S
1009 $ hg --config extensions.extdiff= pdiff -S
1022
1010
1023 $ hg --config extensions.extdiff= pdiff -r '.^' -S
1011 $ hg --config extensions.extdiff= pdiff -r '.^' -S
1024 \r (no-eol) (esc)
1012 \r (no-eol) (esc)
1025 archiving [ ] 0/2\r (no-eol) (esc)
1013 archiving [ ] 0/2\r (no-eol) (esc)
1026 archiving [====================> ] 1/2\r (no-eol) (esc)
1014 archiving [====================> ] 1/2\r (no-eol) (esc)
1027 archiving [==========================================>] 2/2\r (no-eol) (esc)
1015 archiving [==========================================>] 2/2\r (no-eol) (esc)
1028 \r (no-eol) (esc)
1016 \r (no-eol) (esc)
1029 \r (no-eol) (esc)
1017 \r (no-eol) (esc)
1030 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
1018 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
1031 \r (no-eol) (esc)
1019 \r (no-eol) (esc)
1032 \r (no-eol) (esc)
1020 \r (no-eol) (esc)
1033 archiving (sub1/sub2) [ <=> ] 0\r (no-eol) (esc)
1021 archiving (sub1/sub2) [ <=> ] 0\r (no-eol) (esc)
1034 \r (no-eol) (esc)
1022 \r (no-eol) (esc)
1035 \r (no-eol) (esc)
1023 \r (no-eol) (esc)
1036 archiving (sub3) [ <=> ] 0\r (no-eol) (esc)
1024 archiving (sub3) [ <=> ] 0\r (no-eol) (esc)
1037 \r (no-eol) (esc)
1025 \r (no-eol) (esc)
1038 \r (no-eol) (esc)
1026 \r (no-eol) (esc)
1039 archiving [ ] 0/2\r (no-eol) (esc)
1027 archiving [ ] 0/2\r (no-eol) (esc)
1040 archiving [====================> ] 1/2\r (no-eol) (esc)
1028 archiving [====================> ] 1/2\r (no-eol) (esc)
1041 archiving [==========================================>] 2/2\r (no-eol) (esc)
1029 archiving [==========================================>] 2/2\r (no-eol) (esc)
1042 \r (no-eol) (esc)
1030 \r (no-eol) (esc)
1043 \r (no-eol) (esc)
1031 \r (no-eol) (esc)
1044 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
1032 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
1045 \r (no-eol) (esc)
1033 \r (no-eol) (esc)
1046 \r (no-eol) (esc)
1034 \r (no-eol) (esc)
1047 archiving (sub1/sub2) [ <=> ] 0\r (no-eol) (esc)
1035 archiving (sub1/sub2) [ <=> ] 0\r (no-eol) (esc)
1048 \r (no-eol) (esc)
1036 \r (no-eol) (esc)
1049 diff -Nru cloned.*/.hgsub cloned/.hgsub (glob)
1037 diff -Nru cloned.*/.hgsub cloned/.hgsub (glob)
1050 --- cloned.*/.hgsub * (glob)
1038 --- cloned.*/.hgsub * (glob)
1051 +++ cloned/.hgsub * (glob)
1039 +++ cloned/.hgsub * (glob)
1052 @@ -1,2 +1* @@ (glob)
1040 @@ -1,2 +1* @@ (glob)
1053 sub1 = ../sub1
1041 sub1 = ../sub1
1054 -sub3 = sub3
1042 -sub3 = sub3
1055 diff -Nru cloned.*/.hgsubstate cloned/.hgsubstate (glob)
1043 diff -Nru cloned.*/.hgsubstate cloned/.hgsubstate (glob)
1056 --- cloned.*/.hgsubstate * (glob)
1044 --- cloned.*/.hgsubstate * (glob)
1057 +++ cloned/.hgsubstate * (glob)
1045 +++ cloned/.hgsubstate * (glob)
1058 @@ -1,2 +1* @@ (glob)
1046 @@ -1,2 +1* @@ (glob)
1059 7a36fa02b66e61f27f3d4a822809f159479b8ab2 sub1
1047 7a36fa02b66e61f27f3d4a822809f159479b8ab2 sub1
1060 -b1a26de6f2a045a9f079323693614ee322f1ff7e sub3
1048 -b1a26de6f2a045a9f079323693614ee322f1ff7e sub3
1061 [1]
1049 [1]
1062
1050
1063 $ hg --config extensions.extdiff= pdiff -r 0 -r '.^' -S
1051 $ hg --config extensions.extdiff= pdiff -r 0 -r '.^' -S
1064 \r (no-eol) (esc)
1052 \r (no-eol) (esc)
1065 archiving [ ] 0/3\r (no-eol) (esc)
1053 archiving [ ] 0/3\r (no-eol) (esc)
1066 archiving [=============> ] 1/3\r (no-eol) (esc)
1054 archiving [=============> ] 1/3\r (no-eol) (esc)
1067 archiving [===========================> ] 2/3\r (no-eol) (esc)
1055 archiving [===========================> ] 2/3\r (no-eol) (esc)
1068 archiving [==========================================>] 3/3\r (no-eol) (esc)
1056 archiving [==========================================>] 3/3\r (no-eol) (esc)
1069 \r (no-eol) (esc)
1057 \r (no-eol) (esc)
1070 \r (no-eol) (esc)
1058 \r (no-eol) (esc)
1071 archiving (sub1) [ ] 0/1\r (no-eol) (esc)
1059 archiving (sub1) [ ] 0/1\r (no-eol) (esc)
1072 archiving (sub1) [===================================>] 1/1\r (no-eol) (esc)
1060 archiving (sub1) [===================================>] 1/1\r (no-eol) (esc)
1073 \r (no-eol) (esc)
1061 \r (no-eol) (esc)
1074 \r (no-eol) (esc)
1062 \r (no-eol) (esc)
1075 archiving (sub1/sub2) [ ] 0/1\r (no-eol) (esc)
1063 archiving (sub1/sub2) [ ] 0/1\r (no-eol) (esc)
1076 archiving (sub1/sub2) [==============================>] 1/1\r (no-eol) (esc)
1064 archiving (sub1/sub2) [==============================>] 1/1\r (no-eol) (esc)
1077 \r (no-eol) (esc)
1065 \r (no-eol) (esc)
1078 \r (no-eol) (esc)
1066 \r (no-eol) (esc)
1079 archiving [ ] 0/8\r (no-eol) (esc)
1067 archiving [ ] 0/8\r (no-eol) (esc)
1080 archiving [====> ] 1/8\r (no-eol) (esc)
1068 archiving [====> ] 1/8\r (no-eol) (esc)
1081 archiving [=========> ] 2/8\r (no-eol) (esc)
1069 archiving [=========> ] 2/8\r (no-eol) (esc)
1082 archiving [===============> ] 3/8\r (no-eol) (esc)
1070 archiving [===============> ] 3/8\r (no-eol) (esc)
1083 archiving [====================> ] 4/8\r (no-eol) (esc)
1071 archiving [====================> ] 4/8\r (no-eol) (esc)
1084 archiving [=========================> ] 5/8\r (no-eol) (esc)
1072 archiving [=========================> ] 5/8\r (no-eol) (esc)
1085 archiving [===============================> ] 6/8\r (no-eol) (esc)
1073 archiving [===============================> ] 6/8\r (no-eol) (esc)
1086 archiving [====================================> ] 7/8\r (no-eol) (esc)
1074 archiving [====================================> ] 7/8\r (no-eol) (esc)
1087 archiving [==========================================>] 8/8\r (no-eol) (esc)
1075 archiving [==========================================>] 8/8\r (no-eol) (esc)
1088 \r (no-eol) (esc)
1076 \r (no-eol) (esc)
1089 \r (no-eol) (esc)
1077 \r (no-eol) (esc)
1090 archiving (sub1) [ ] 0/1\r (no-eol) (esc)
1078 archiving (sub1) [ ] 0/1\r (no-eol) (esc)
1091 archiving (sub1) [===================================>] 1/1\r (no-eol) (esc)
1079 archiving (sub1) [===================================>] 1/1\r (no-eol) (esc)
1092 \r (no-eol) (esc)
1080 \r (no-eol) (esc)
1093 \r (no-eol) (esc)
1081 \r (no-eol) (esc)
1094 archiving (sub1/sub2) [ ] 0/3\r (no-eol) (esc)
1082 archiving (sub1/sub2) [ ] 0/3\r (no-eol) (esc)
1095 archiving (sub1/sub2) [=========> ] 1/3\r (no-eol) (esc)
1083 archiving (sub1/sub2) [=========> ] 1/3\r (no-eol) (esc)
1096 archiving (sub1/sub2) [===================> ] 2/3\r (no-eol) (esc)
1084 archiving (sub1/sub2) [===================> ] 2/3\r (no-eol) (esc)
1097 archiving (sub1/sub2) [==============================>] 3/3\r (no-eol) (esc)
1085 archiving (sub1/sub2) [==============================>] 3/3\r (no-eol) (esc)
1098 \r (no-eol) (esc)
1086 \r (no-eol) (esc)
1099 \r (no-eol) (esc)
1087 \r (no-eol) (esc)
1100 archiving (sub3) [ ] 0/1\r (no-eol) (esc)
1088 archiving (sub3) [ ] 0/1\r (no-eol) (esc)
1101 archiving (sub3) [===================================>] 1/1\r (no-eol) (esc)
1089 archiving (sub3) [===================================>] 1/1\r (no-eol) (esc)
1102 \r (no-eol) (esc)
1090 \r (no-eol) (esc)
1103 diff -Nru cloned.*/.hglf/b.dat cloned.*/.hglf/b.dat (glob)
1091 diff -Nru cloned.*/.hglf/b.dat cloned.*/.hglf/b.dat (glob)
1104 --- cloned.*/.hglf/b.dat * (glob)
1092 --- cloned.*/.hglf/b.dat * (glob)
1105 +++ cloned.*/.hglf/b.dat * (glob)
1093 +++ cloned.*/.hglf/b.dat * (glob)
1106 @@ -*,0 +1* @@ (glob)
1094 @@ -*,0 +1* @@ (glob)
1107 +da39a3ee5e6b4b0d3255bfef95601890afd80709
1095 +da39a3ee5e6b4b0d3255bfef95601890afd80709
1108 diff -Nru cloned.*/.hglf/foo/bar/large.dat cloned.*/.hglf/foo/bar/large.dat (glob)
1096 diff -Nru cloned.*/.hglf/foo/bar/large.dat cloned.*/.hglf/foo/bar/large.dat (glob)
1109 --- cloned.*/.hglf/foo/bar/large.dat * (glob)
1097 --- cloned.*/.hglf/foo/bar/large.dat * (glob)
1110 +++ cloned.*/.hglf/foo/bar/large.dat * (glob)
1098 +++ cloned.*/.hglf/foo/bar/large.dat * (glob)
1111 @@ -*,0 +1* @@ (glob)
1099 @@ -*,0 +1* @@ (glob)
1112 +2f6933b5ee0f5fdd823d9717d8729f3c2523811b
1100 +2f6933b5ee0f5fdd823d9717d8729f3c2523811b
1113 diff -Nru cloned.*/.hglf/large.bin cloned.*/.hglf/large.bin (glob)
1101 diff -Nru cloned.*/.hglf/large.bin cloned.*/.hglf/large.bin (glob)
1114 --- cloned.*/.hglf/large.bin * (glob)
1102 --- cloned.*/.hglf/large.bin * (glob)
1115 +++ cloned.*/.hglf/large.bin * (glob)
1103 +++ cloned.*/.hglf/large.bin * (glob)
1116 @@ -*,0 +1* @@ (glob)
1104 @@ -*,0 +1* @@ (glob)
1117 +7f7097b041ccf68cc5561e9600da4655d21c6d18
1105 +7f7097b041ccf68cc5561e9600da4655d21c6d18
1118 diff -Nru cloned.*/.hgsub cloned.*/.hgsub (glob)
1106 diff -Nru cloned.*/.hgsub cloned.*/.hgsub (glob)
1119 --- cloned.*/.hgsub * (glob)
1107 --- cloned.*/.hgsub * (glob)
1120 +++ cloned.*/.hgsub * (glob)
1108 +++ cloned.*/.hgsub * (glob)
1121 @@ -1* +1,2 @@ (glob)
1109 @@ -1* +1,2 @@ (glob)
1122 sub1 = ../sub1
1110 sub1 = ../sub1
1123 +sub3 = sub3
1111 +sub3 = sub3
1124 diff -Nru cloned.*/.hgsubstate cloned.*/.hgsubstate (glob)
1112 diff -Nru cloned.*/.hgsubstate cloned.*/.hgsubstate (glob)
1125 --- cloned.*/.hgsubstate * (glob)
1113 --- cloned.*/.hgsubstate * (glob)
1126 +++ cloned.*/.hgsubstate * (glob)
1114 +++ cloned.*/.hgsubstate * (glob)
1127 @@ -1* +1,2 @@ (glob)
1115 @@ -1* +1,2 @@ (glob)
1128 -fc3b4ce2696f7741438c79207583768f2ce6b0dd sub1
1116 -fc3b4ce2696f7741438c79207583768f2ce6b0dd sub1
1129 +7a36fa02b66e61f27f3d4a822809f159479b8ab2 sub1
1117 +7a36fa02b66e61f27f3d4a822809f159479b8ab2 sub1
1130 +b1a26de6f2a045a9f079323693614ee322f1ff7e sub3
1118 +b1a26de6f2a045a9f079323693614ee322f1ff7e sub3
1131 diff -Nru cloned.*/foo/bar/def cloned.*/foo/bar/def (glob)
1119 diff -Nru cloned.*/foo/bar/def cloned.*/foo/bar/def (glob)
1132 --- cloned.*/foo/bar/def * (glob)
1120 --- cloned.*/foo/bar/def * (glob)
1133 +++ cloned.*/foo/bar/def * (glob)
1121 +++ cloned.*/foo/bar/def * (glob)
1134 @@ -*,0 +1* @@ (glob)
1122 @@ -*,0 +1* @@ (glob)
1135 +changed
1123 +changed
1136 diff -Nru cloned.*/main cloned.*/main (glob)
1124 diff -Nru cloned.*/main cloned.*/main (glob)
1137 --- cloned.*/main * (glob)
1125 --- cloned.*/main * (glob)
1138 +++ cloned.*/main * (glob)
1126 +++ cloned.*/main * (glob)
1139 @@ -1* +1* @@ (glob)
1127 @@ -1* +1* @@ (glob)
1140 -main
1128 -main
1141 +foo
1129 +foo
1142 diff -Nru cloned.*/sub1/.hgsubstate cloned.*/sub1/.hgsubstate (glob)
1130 diff -Nru cloned.*/sub1/.hgsubstate cloned.*/sub1/.hgsubstate (glob)
1143 --- cloned.*/sub1/.hgsubstate * (glob)
1131 --- cloned.*/sub1/.hgsubstate * (glob)
1144 +++ cloned.*/sub1/.hgsubstate * (glob)
1132 +++ cloned.*/sub1/.hgsubstate * (glob)
1145 @@ -1* +1* @@ (glob)
1133 @@ -1* +1* @@ (glob)
1146 -c57a0840e3badd667ef3c3ef65471609acb2ba3c sub2
1134 -c57a0840e3badd667ef3c3ef65471609acb2ba3c sub2
1147 +c77908c81ccea3794a896c79e98b0e004aee2e9e sub2
1135 +c77908c81ccea3794a896c79e98b0e004aee2e9e sub2
1148 diff -Nru cloned.*/sub1/sub2/folder/test.txt cloned.*/sub1/sub2/folder/test.txt (glob)
1136 diff -Nru cloned.*/sub1/sub2/folder/test.txt cloned.*/sub1/sub2/folder/test.txt (glob)
1149 --- cloned.*/sub1/sub2/folder/test.txt * (glob)
1137 --- cloned.*/sub1/sub2/folder/test.txt * (glob)
1150 +++ cloned.*/sub1/sub2/folder/test.txt * (glob)
1138 +++ cloned.*/sub1/sub2/folder/test.txt * (glob)
1151 @@ -*,0 +1* @@ (glob)
1139 @@ -*,0 +1* @@ (glob)
1152 +subfolder
1140 +subfolder
1153 diff -Nru cloned.*/sub1/sub2/sub2 cloned.*/sub1/sub2/sub2 (glob)
1141 diff -Nru cloned.*/sub1/sub2/sub2 cloned.*/sub1/sub2/sub2 (glob)
1154 --- cloned.*/sub1/sub2/sub2 * (glob)
1142 --- cloned.*/sub1/sub2/sub2 * (glob)
1155 +++ cloned.*/sub1/sub2/sub2 * (glob)
1143 +++ cloned.*/sub1/sub2/sub2 * (glob)
1156 @@ -1* +1* @@ (glob)
1144 @@ -1* +1* @@ (glob)
1157 -sub2
1145 -sub2
1158 +modified
1146 +modified
1159 diff -Nru cloned.*/sub3/a.txt cloned.*/sub3/a.txt (glob)
1147 diff -Nru cloned.*/sub3/a.txt cloned.*/sub3/a.txt (glob)
1160 --- cloned.*/sub3/a.txt * (glob)
1148 --- cloned.*/sub3/a.txt * (glob)
1161 +++ cloned.*/sub3/a.txt * (glob)
1149 +++ cloned.*/sub3/a.txt * (glob)
1162 @@ -*,0 +1* @@ (glob)
1150 @@ -*,0 +1* @@ (glob)
1163 +xyz
1151 +xyz
1164 [1]
1152 [1]
1165
1153
1166 $ echo mod > sub1/sub2/sub2
1154 $ echo mod > sub1/sub2/sub2
1167 $ hg --config extensions.extdiff= pdiff -S
1155 $ hg --config extensions.extdiff= pdiff -S
1168 \r (no-eol) (esc)
1156 \r (no-eol) (esc)
1169 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
1157 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
1170 \r (no-eol) (esc)
1158 \r (no-eol) (esc)
1171 \r (no-eol) (esc)
1159 \r (no-eol) (esc)
1172 archiving (sub1/sub2) [ ] 0/1\r (no-eol) (esc)
1160 archiving (sub1/sub2) [ ] 0/1\r (no-eol) (esc)
1173 archiving (sub1/sub2) [==============================>] 1/1\r (no-eol) (esc)
1161 archiving (sub1/sub2) [==============================>] 1/1\r (no-eol) (esc)
1174 \r (no-eol) (esc)
1162 \r (no-eol) (esc)
1175 --- */cloned.*/sub1/sub2/sub2 * (glob)
1163 --- */cloned.*/sub1/sub2/sub2 * (glob)
1176 +++ */cloned/sub1/sub2/sub2 * (glob)
1164 +++ */cloned/sub1/sub2/sub2 * (glob)
1177 @@ -1* +1* @@ (glob)
1165 @@ -1* +1* @@ (glob)
1178 -modified
1166 -modified
1179 +mod
1167 +mod
1180 [1]
1168 [1]
1181
1169
1182 $ cd ..
1170 $ cd ..
@@ -1,715 +1,700 b''
1 Create test repository:
1 Create test repository:
2
2
3 $ hg init repo
3 $ hg init repo
4 $ cd repo
4 $ cd repo
5 $ echo x1 > x.txt
5 $ echo x1 > x.txt
6
6
7 $ hg init foo
7 $ hg init foo
8 $ cd foo
8 $ cd foo
9 $ echo y1 > y.txt
9 $ echo y1 > y.txt
10
10
11 $ hg init bar
11 $ hg init bar
12 $ cd bar
12 $ cd bar
13 $ echo z1 > z.txt
13 $ echo z1 > z.txt
14
14
15 $ cd ..
15 $ cd ..
16 $ echo 'bar = bar' > .hgsub
16 $ echo 'bar = bar' > .hgsub
17
17
18 $ cd ..
18 $ cd ..
19 $ echo 'foo = foo' > .hgsub
19 $ echo 'foo = foo' > .hgsub
20
20
21 Add files --- .hgsub files must go first to trigger subrepos:
21 Add files --- .hgsub files must go first to trigger subrepos:
22
22
23 $ hg add -S .hgsub
23 $ hg add -S .hgsub
24 $ hg add -S foo/.hgsub
24 $ hg add -S foo/.hgsub
25 $ hg add -S foo/bar
25 $ hg add -S foo/bar
26 adding foo/bar/z.txt
26 adding foo/bar/z.txt
27 $ hg add -S
27 $ hg add -S
28 adding x.txt
28 adding x.txt
29 adding foo/y.txt
29 adding foo/y.txt
30
30
31 Test recursive status without committing anything:
31 Test recursive status without committing anything:
32
32
33 $ hg status -S
33 $ hg status -S
34 A .hgsub
34 A .hgsub
35 A foo/.hgsub
35 A foo/.hgsub
36 A foo/bar/z.txt
36 A foo/bar/z.txt
37 A foo/y.txt
37 A foo/y.txt
38 A x.txt
38 A x.txt
39
39
40 Test recursive diff without committing anything:
40 Test recursive diff without committing anything:
41
41
42 $ hg diff --nodates -S foo
42 $ hg diff --nodates -S foo
43 diff -r 000000000000 foo/.hgsub
43 diff -r 000000000000 foo/.hgsub
44 --- /dev/null
44 --- /dev/null
45 +++ b/foo/.hgsub
45 +++ b/foo/.hgsub
46 @@ -0,0 +1,1 @@
46 @@ -0,0 +1,1 @@
47 +bar = bar
47 +bar = bar
48 diff -r 000000000000 foo/y.txt
48 diff -r 000000000000 foo/y.txt
49 --- /dev/null
49 --- /dev/null
50 +++ b/foo/y.txt
50 +++ b/foo/y.txt
51 @@ -0,0 +1,1 @@
51 @@ -0,0 +1,1 @@
52 +y1
52 +y1
53 diff -r 000000000000 foo/bar/z.txt
53 diff -r 000000000000 foo/bar/z.txt
54 --- /dev/null
54 --- /dev/null
55 +++ b/foo/bar/z.txt
55 +++ b/foo/bar/z.txt
56 @@ -0,0 +1,1 @@
56 @@ -0,0 +1,1 @@
57 +z1
57 +z1
58
58
59 Commits:
59 Commits:
60
60
61 $ hg commit -m fails
61 $ hg commit -m fails
62 abort: uncommitted changes in subrepository "foo"
62 abort: uncommitted changes in subrepository "foo"
63 (use --subrepos for recursive commit)
63 (use --subrepos for recursive commit)
64 [255]
64 [255]
65
65
66 The --subrepos flag overwrite the config setting:
66 The --subrepos flag overwrite the config setting:
67
67
68 $ hg commit -m 0-0-0 --config ui.commitsubrepos=No --subrepos
68 $ hg commit -m 0-0-0 --config ui.commitsubrepos=No --subrepos
69 committing subrepository foo
69 committing subrepository foo
70 committing subrepository foo/bar
70 committing subrepository foo/bar
71
71
72 $ cd foo
72 $ cd foo
73 $ echo y2 >> y.txt
73 $ echo y2 >> y.txt
74 $ hg commit -m 0-1-0
74 $ hg commit -m 0-1-0
75
75
76 $ cd bar
76 $ cd bar
77 $ echo z2 >> z.txt
77 $ echo z2 >> z.txt
78 $ hg commit -m 0-1-1
78 $ hg commit -m 0-1-1
79
79
80 $ cd ..
80 $ cd ..
81 $ hg commit -m 0-2-1
81 $ hg commit -m 0-2-1
82
82
83 $ cd ..
83 $ cd ..
84 $ hg commit -m 1-2-1
84 $ hg commit -m 1-2-1
85
85
86 Change working directory:
86 Change working directory:
87
87
88 $ echo y3 >> foo/y.txt
88 $ echo y3 >> foo/y.txt
89 $ echo z3 >> foo/bar/z.txt
89 $ echo z3 >> foo/bar/z.txt
90 $ hg status -S
90 $ hg status -S
91 M foo/bar/z.txt
91 M foo/bar/z.txt
92 M foo/y.txt
92 M foo/y.txt
93 $ hg diff --nodates -S
93 $ hg diff --nodates -S
94 diff -r d254738c5f5e foo/y.txt
94 diff -r d254738c5f5e foo/y.txt
95 --- a/foo/y.txt
95 --- a/foo/y.txt
96 +++ b/foo/y.txt
96 +++ b/foo/y.txt
97 @@ -1,2 +1,3 @@
97 @@ -1,2 +1,3 @@
98 y1
98 y1
99 y2
99 y2
100 +y3
100 +y3
101 diff -r 9647f22de499 foo/bar/z.txt
101 diff -r 9647f22de499 foo/bar/z.txt
102 --- a/foo/bar/z.txt
102 --- a/foo/bar/z.txt
103 +++ b/foo/bar/z.txt
103 +++ b/foo/bar/z.txt
104 @@ -1,2 +1,3 @@
104 @@ -1,2 +1,3 @@
105 z1
105 z1
106 z2
106 z2
107 +z3
107 +z3
108
108
109 Status call crossing repository boundaries:
109 Status call crossing repository boundaries:
110
110
111 $ hg status -S foo/bar/z.txt
111 $ hg status -S foo/bar/z.txt
112 M foo/bar/z.txt
112 M foo/bar/z.txt
113 $ hg status -S -I 'foo/?.txt'
113 $ hg status -S -I 'foo/?.txt'
114 M foo/y.txt
114 M foo/y.txt
115 $ hg status -S -I '**/?.txt'
115 $ hg status -S -I '**/?.txt'
116 M foo/bar/z.txt
116 M foo/bar/z.txt
117 M foo/y.txt
117 M foo/y.txt
118 $ hg diff --nodates -S -I '**/?.txt'
118 $ hg diff --nodates -S -I '**/?.txt'
119 diff -r d254738c5f5e foo/y.txt
119 diff -r d254738c5f5e foo/y.txt
120 --- a/foo/y.txt
120 --- a/foo/y.txt
121 +++ b/foo/y.txt
121 +++ b/foo/y.txt
122 @@ -1,2 +1,3 @@
122 @@ -1,2 +1,3 @@
123 y1
123 y1
124 y2
124 y2
125 +y3
125 +y3
126 diff -r 9647f22de499 foo/bar/z.txt
126 diff -r 9647f22de499 foo/bar/z.txt
127 --- a/foo/bar/z.txt
127 --- a/foo/bar/z.txt
128 +++ b/foo/bar/z.txt
128 +++ b/foo/bar/z.txt
129 @@ -1,2 +1,3 @@
129 @@ -1,2 +1,3 @@
130 z1
130 z1
131 z2
131 z2
132 +z3
132 +z3
133
133
134 Status from within a subdirectory:
134 Status from within a subdirectory:
135
135
136 $ mkdir dir
136 $ mkdir dir
137 $ cd dir
137 $ cd dir
138 $ echo a1 > a.txt
138 $ echo a1 > a.txt
139 $ hg status -S
139 $ hg status -S
140 M foo/bar/z.txt
140 M foo/bar/z.txt
141 M foo/y.txt
141 M foo/y.txt
142 ? dir/a.txt
142 ? dir/a.txt
143 $ hg diff --nodates -S
143 $ hg diff --nodates -S
144 diff -r d254738c5f5e foo/y.txt
144 diff -r d254738c5f5e foo/y.txt
145 --- a/foo/y.txt
145 --- a/foo/y.txt
146 +++ b/foo/y.txt
146 +++ b/foo/y.txt
147 @@ -1,2 +1,3 @@
147 @@ -1,2 +1,3 @@
148 y1
148 y1
149 y2
149 y2
150 +y3
150 +y3
151 diff -r 9647f22de499 foo/bar/z.txt
151 diff -r 9647f22de499 foo/bar/z.txt
152 --- a/foo/bar/z.txt
152 --- a/foo/bar/z.txt
153 +++ b/foo/bar/z.txt
153 +++ b/foo/bar/z.txt
154 @@ -1,2 +1,3 @@
154 @@ -1,2 +1,3 @@
155 z1
155 z1
156 z2
156 z2
157 +z3
157 +z3
158
158
159 Status with relative path:
159 Status with relative path:
160
160
161 $ hg status -S ..
161 $ hg status -S ..
162 M ../foo/bar/z.txt
162 M ../foo/bar/z.txt
163 M ../foo/y.txt
163 M ../foo/y.txt
164 ? a.txt
164 ? a.txt
165
165
166 XXX: filtering lfilesrepo.status() in 3.3-rc causes these files to be listed as
166 XXX: filtering lfilesrepo.status() in 3.3-rc causes these files to be listed as
167 added instead of modified.
167 added instead of modified.
168 $ hg status -S .. --config extensions.largefiles=
168 $ hg status -S .. --config extensions.largefiles=
169 M ../foo/bar/z.txt
169 M ../foo/bar/z.txt
170 M ../foo/y.txt
170 M ../foo/y.txt
171 ? a.txt
171 ? a.txt
172
172
173 $ hg diff --nodates -S ..
173 $ hg diff --nodates -S ..
174 diff -r d254738c5f5e foo/y.txt
174 diff -r d254738c5f5e foo/y.txt
175 --- a/foo/y.txt
175 --- a/foo/y.txt
176 +++ b/foo/y.txt
176 +++ b/foo/y.txt
177 @@ -1,2 +1,3 @@
177 @@ -1,2 +1,3 @@
178 y1
178 y1
179 y2
179 y2
180 +y3
180 +y3
181 diff -r 9647f22de499 foo/bar/z.txt
181 diff -r 9647f22de499 foo/bar/z.txt
182 --- a/foo/bar/z.txt
182 --- a/foo/bar/z.txt
183 +++ b/foo/bar/z.txt
183 +++ b/foo/bar/z.txt
184 @@ -1,2 +1,3 @@
184 @@ -1,2 +1,3 @@
185 z1
185 z1
186 z2
186 z2
187 +z3
187 +z3
188 $ cd ..
188 $ cd ..
189
189
190 Cleanup and final commit:
190 Cleanup and final commit:
191
191
192 $ rm -r dir
192 $ rm -r dir
193 $ hg commit --subrepos -m 2-3-2
193 $ hg commit --subrepos -m 2-3-2
194 committing subrepository foo
194 committing subrepository foo
195 committing subrepository foo/bar
195 committing subrepository foo/bar
196
196
197 Test explicit path commands within subrepos: add/forget
197 Test explicit path commands within subrepos: add/forget
198 $ echo z1 > foo/bar/z2.txt
198 $ echo z1 > foo/bar/z2.txt
199 $ hg status -S
199 $ hg status -S
200 ? foo/bar/z2.txt
200 ? foo/bar/z2.txt
201 $ hg add foo/bar/z2.txt
201 $ hg add foo/bar/z2.txt
202 $ hg status -S
202 $ hg status -S
203 A foo/bar/z2.txt
203 A foo/bar/z2.txt
204 $ hg forget foo/bar/z2.txt
204 $ hg forget foo/bar/z2.txt
205 $ hg status -S
205 $ hg status -S
206 ? foo/bar/z2.txt
206 ? foo/bar/z2.txt
207 $ hg forget foo/bar/z2.txt
207 $ hg forget foo/bar/z2.txt
208 not removing foo/bar/z2.txt: file is already untracked
208 not removing foo/bar/z2.txt: file is already untracked
209 [1]
209 [1]
210 $ hg status -S
210 $ hg status -S
211 ? foo/bar/z2.txt
211 ? foo/bar/z2.txt
212 $ rm foo/bar/z2.txt
212 $ rm foo/bar/z2.txt
213
213
214 Log with the relationships between repo and its subrepo:
214 Log with the relationships between repo and its subrepo:
215
215
216 $ hg log --template '{rev}:{node|short} {desc}\n'
216 $ hg log --template '{rev}:{node|short} {desc}\n'
217 2:1326fa26d0c0 2-3-2
217 2:1326fa26d0c0 2-3-2
218 1:4b3c9ff4f66b 1-2-1
218 1:4b3c9ff4f66b 1-2-1
219 0:23376cbba0d8 0-0-0
219 0:23376cbba0d8 0-0-0
220
220
221 $ hg -R foo log --template '{rev}:{node|short} {desc}\n'
221 $ hg -R foo log --template '{rev}:{node|short} {desc}\n'
222 3:65903cebad86 2-3-2
222 3:65903cebad86 2-3-2
223 2:d254738c5f5e 0-2-1
223 2:d254738c5f5e 0-2-1
224 1:8629ce7dcc39 0-1-0
224 1:8629ce7dcc39 0-1-0
225 0:af048e97ade2 0-0-0
225 0:af048e97ade2 0-0-0
226
226
227 $ hg -R foo/bar log --template '{rev}:{node|short} {desc}\n'
227 $ hg -R foo/bar log --template '{rev}:{node|short} {desc}\n'
228 2:31ecbdafd357 2-3-2
228 2:31ecbdafd357 2-3-2
229 1:9647f22de499 0-1-1
229 1:9647f22de499 0-1-1
230 0:4904098473f9 0-0-0
230 0:4904098473f9 0-0-0
231
231
232 Status between revisions:
232 Status between revisions:
233
233
234 $ hg status -S
234 $ hg status -S
235 $ hg status -S --rev 0:1
235 $ hg status -S --rev 0:1
236 M .hgsubstate
236 M .hgsubstate
237 M foo/.hgsubstate
237 M foo/.hgsubstate
238 M foo/bar/z.txt
238 M foo/bar/z.txt
239 M foo/y.txt
239 M foo/y.txt
240 $ hg diff --nodates -S -I '**/?.txt' --rev 0:1
240 $ hg diff --nodates -S -I '**/?.txt' --rev 0:1
241 diff -r af048e97ade2 -r d254738c5f5e foo/y.txt
241 diff -r af048e97ade2 -r d254738c5f5e foo/y.txt
242 --- a/foo/y.txt
242 --- a/foo/y.txt
243 +++ b/foo/y.txt
243 +++ b/foo/y.txt
244 @@ -1,1 +1,2 @@
244 @@ -1,1 +1,2 @@
245 y1
245 y1
246 +y2
246 +y2
247 diff -r 4904098473f9 -r 9647f22de499 foo/bar/z.txt
247 diff -r 4904098473f9 -r 9647f22de499 foo/bar/z.txt
248 --- a/foo/bar/z.txt
248 --- a/foo/bar/z.txt
249 +++ b/foo/bar/z.txt
249 +++ b/foo/bar/z.txt
250 @@ -1,1 +1,2 @@
250 @@ -1,1 +1,2 @@
251 z1
251 z1
252 +z2
252 +z2
253
253
254 #if serve
254 #if serve
255 $ cd ..
255 $ cd ..
256 $ hg serve -R repo --debug -S -p $HGPORT -d --pid-file=hg1.pid -E error.log -A access.log
256 $ hg serve -R repo --debug -S -p $HGPORT -d --pid-file=hg1.pid -E error.log -A access.log
257 adding = $TESTTMP/repo
257 adding = $TESTTMP/repo
258 adding foo = $TESTTMP/repo/foo
258 adding foo = $TESTTMP/repo/foo
259 adding foo/bar = $TESTTMP/repo/foo/bar
259 adding foo/bar = $TESTTMP/repo/foo/bar
260 listening at http://*:$HGPORT/ (bound to *:$HGPORT) (glob) (?)
260 listening at http://*:$HGPORT/ (bound to *:$HGPORT) (glob) (?)
261 adding = $TESTTMP/repo (?)
261 adding = $TESTTMP/repo (?)
262 adding foo = $TESTTMP/repo/foo (?)
262 adding foo = $TESTTMP/repo/foo (?)
263 adding foo/bar = $TESTTMP/repo/foo/bar (?)
263 adding foo/bar = $TESTTMP/repo/foo/bar (?)
264 $ cat hg1.pid >> $DAEMON_PIDS
264 $ cat hg1.pid >> $DAEMON_PIDS
265
265
266 $ hg clone http://localhost:$HGPORT clone --config progress.disable=True
266 $ hg clone http://localhost:$HGPORT clone --config progress.disable=True
267 requesting all changes
267 requesting all changes
268 adding changesets
268 adding changesets
269 adding manifests
269 adding manifests
270 adding file changes
270 adding file changes
271 added 3 changesets with 5 changes to 3 files
271 added 3 changesets with 5 changes to 3 files
272 new changesets 23376cbba0d8:1326fa26d0c0
272 new changesets 23376cbba0d8:1326fa26d0c0
273 updating to branch default
273 updating to branch default
274 cloning subrepo foo from http://localhost:$HGPORT/foo
274 cloning subrepo foo from http://localhost:$HGPORT/foo
275 requesting all changes
275 requesting all changes
276 adding changesets
276 adding changesets
277 adding manifests
277 adding manifests
278 adding file changes
278 adding file changes
279 added 4 changesets with 7 changes to 3 files
279 added 4 changesets with 7 changes to 3 files
280 new changesets af048e97ade2:65903cebad86
280 new changesets af048e97ade2:65903cebad86
281 cloning subrepo foo/bar from http://localhost:$HGPORT/foo/bar
281 cloning subrepo foo/bar from http://localhost:$HGPORT/foo/bar
282 requesting all changes
282 requesting all changes
283 adding changesets
283 adding changesets
284 adding manifests
284 adding manifests
285 adding file changes
285 adding file changes
286 added 3 changesets with 3 changes to 1 files
286 added 3 changesets with 3 changes to 1 files
287 new changesets 4904098473f9:31ecbdafd357
287 new changesets 4904098473f9:31ecbdafd357
288 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
288 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
289
289
290 $ cat clone/foo/bar/z.txt
290 $ cat clone/foo/bar/z.txt
291 z1
291 z1
292 z2
292 z2
293 z3
293 z3
294
294
295 Clone pooling from a remote URL will share the top level repo and the subrepos,
295 Clone pooling from a remote URL will share the top level repo and the subrepos,
296 even if they are referenced by remote URL.
296 even if they are referenced by remote URL.
297
297
298 $ hg --config extensions.share= --config share.pool=$TESTTMP/pool \
298 $ hg --config extensions.share= --config share.pool=$TESTTMP/pool \
299 > clone http://localhost:$HGPORT shared
299 > clone http://localhost:$HGPORT shared
300 (sharing from new pooled repository 23376cbba0d87c15906bb3652584927c140907bf)
300 (sharing from new pooled repository 23376cbba0d87c15906bb3652584927c140907bf)
301 requesting all changes
301 requesting all changes
302 adding changesets
302 adding changesets
303 adding manifests
303 adding manifests
304 adding file changes
304 adding file changes
305 added 3 changesets with 5 changes to 3 files
305 added 3 changesets with 5 changes to 3 files
306 new changesets 23376cbba0d8:1326fa26d0c0
306 new changesets 23376cbba0d8:1326fa26d0c0
307 searching for changes
307 searching for changes
308 no changes found
308 no changes found
309 updating working directory
309 updating working directory
310 cloning subrepo foo from http://localhost:$HGPORT/foo
310 cloning subrepo foo from http://localhost:$HGPORT/foo
311 (sharing from new pooled repository af048e97ade2e236f754f05d07013e586af0f8bf)
311 (sharing from new pooled repository af048e97ade2e236f754f05d07013e586af0f8bf)
312 requesting all changes
312 requesting all changes
313 adding changesets
313 adding changesets
314 adding manifests
314 adding manifests
315 adding file changes
315 adding file changes
316 added 4 changesets with 7 changes to 3 files
316 added 4 changesets with 7 changes to 3 files
317 new changesets af048e97ade2:65903cebad86
317 new changesets af048e97ade2:65903cebad86
318 searching for changes
318 searching for changes
319 no changes found
319 no changes found
320 cloning subrepo foo/bar from http://localhost:$HGPORT/foo/bar
320 cloning subrepo foo/bar from http://localhost:$HGPORT/foo/bar
321 (sharing from new pooled repository 4904098473f96c900fec436dad267edd4da59fad)
321 (sharing from new pooled repository 4904098473f96c900fec436dad267edd4da59fad)
322 requesting all changes
322 requesting all changes
323 adding changesets
323 adding changesets
324 adding manifests
324 adding manifests
325 adding file changes
325 adding file changes
326 added 3 changesets with 3 changes to 1 files
326 added 3 changesets with 3 changes to 1 files
327 new changesets 4904098473f9:31ecbdafd357
327 new changesets 4904098473f9:31ecbdafd357
328 searching for changes
328 searching for changes
329 no changes found
329 no changes found
330 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
330 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
331
331
332 $ cat access.log
332 $ cat access.log
333 * "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
333 * "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
334 * "GET /?cmd=batch HTTP/1.1" 200 - * (glob)
334 * "GET /?cmd=batch HTTP/1.1" 200 - * (glob)
335 * "GET /?cmd=getbundle HTTP/1.1" 200 - * (glob)
335 * "GET /?cmd=getbundle HTTP/1.1" 200 - * (glob)
336 * "GET /foo?cmd=capabilities HTTP/1.1" 200 - (glob)
336 * "GET /foo?cmd=capabilities HTTP/1.1" 200 - (glob)
337 * "GET /foo?cmd=batch HTTP/1.1" 200 - * (glob)
337 * "GET /foo?cmd=batch HTTP/1.1" 200 - * (glob)
338 * "GET /foo?cmd=getbundle HTTP/1.1" 200 - * (glob)
338 * "GET /foo?cmd=getbundle HTTP/1.1" 200 - * (glob)
339 * "GET /foo/bar?cmd=capabilities HTTP/1.1" 200 - (glob)
339 * "GET /foo/bar?cmd=capabilities HTTP/1.1" 200 - (glob)
340 * "GET /foo/bar?cmd=batch HTTP/1.1" 200 - * (glob)
340 * "GET /foo/bar?cmd=batch HTTP/1.1" 200 - * (glob)
341 * "GET /foo/bar?cmd=getbundle HTTP/1.1" 200 - * (glob)
341 * "GET /foo/bar?cmd=getbundle HTTP/1.1" 200 - * (glob)
342 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
342 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
343 $LOCALIP - - [$LOGDATE$] "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=0 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
343 $LOCALIP - - [$LOGDATE$] "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=0 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
344 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
344 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
345 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
345 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
346 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=1326fa26d0c00d2146c63b56bb6a45149d7325ac&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
346 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=1326fa26d0c00d2146c63b56bb6a45149d7325ac&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
347 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D1326fa26d0c00d2146c63b56bb6a45149d7325ac x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
347 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D1326fa26d0c00d2146c63b56bb6a45149d7325ac x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
348 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=0&common=1326fa26d0c00d2146c63b56bb6a45149d7325ac&heads=1326fa26d0c00d2146c63b56bb6a45149d7325ac&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
348 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=0&common=1326fa26d0c00d2146c63b56bb6a45149d7325ac&heads=1326fa26d0c00d2146c63b56bb6a45149d7325ac&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
349 $LOCALIP - - [$LOGDATE$] "GET /foo?cmd=capabilities HTTP/1.1" 200 - (glob)
349 $LOCALIP - - [$LOGDATE$] "GET /foo?cmd=capabilities HTTP/1.1" 200 - (glob)
350 $LOCALIP - - [$LOGDATE$] "GET /foo?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=0 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
350 $LOCALIP - - [$LOGDATE$] "GET /foo?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=0 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
351 $LOCALIP - - [$LOGDATE$] "GET /foo?cmd=capabilities HTTP/1.1" 200 - (glob)
351 $LOCALIP - - [$LOGDATE$] "GET /foo?cmd=capabilities HTTP/1.1" 200 - (glob)
352 $LOCALIP - - [$LOGDATE$] "GET /foo?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
352 $LOCALIP - - [$LOGDATE$] "GET /foo?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
353 $LOCALIP - - [$LOGDATE$] "GET /foo?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=65903cebad86f1a84bd4f1134f62fa7dcb7a1c98&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
353 $LOCALIP - - [$LOGDATE$] "GET /foo?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=65903cebad86f1a84bd4f1134f62fa7dcb7a1c98&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
354 $LOCALIP - - [$LOGDATE$] "GET /foo?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D65903cebad86f1a84bd4f1134f62fa7dcb7a1c98 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
354 $LOCALIP - - [$LOGDATE$] "GET /foo?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D65903cebad86f1a84bd4f1134f62fa7dcb7a1c98 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
355 $LOCALIP - - [$LOGDATE$] "GET /foo?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=0&common=65903cebad86f1a84bd4f1134f62fa7dcb7a1c98&heads=65903cebad86f1a84bd4f1134f62fa7dcb7a1c98&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
355 $LOCALIP - - [$LOGDATE$] "GET /foo?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=0&common=65903cebad86f1a84bd4f1134f62fa7dcb7a1c98&heads=65903cebad86f1a84bd4f1134f62fa7dcb7a1c98&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
356 $LOCALIP - - [$LOGDATE$] "GET /foo/bar?cmd=capabilities HTTP/1.1" 200 - (glob)
356 $LOCALIP - - [$LOGDATE$] "GET /foo/bar?cmd=capabilities HTTP/1.1" 200 - (glob)
357 $LOCALIP - - [$LOGDATE$] "GET /foo/bar?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=0 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
357 $LOCALIP - - [$LOGDATE$] "GET /foo/bar?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=0 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
358 $LOCALIP - - [$LOGDATE$] "GET /foo/bar?cmd=capabilities HTTP/1.1" 200 - (glob)
358 $LOCALIP - - [$LOGDATE$] "GET /foo/bar?cmd=capabilities HTTP/1.1" 200 - (glob)
359 $LOCALIP - - [$LOGDATE$] "GET /foo/bar?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
359 $LOCALIP - - [$LOGDATE$] "GET /foo/bar?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
360 $LOCALIP - - [$LOGDATE$] "GET /foo/bar?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=31ecbdafd357f54b281c9bd1d681bb90de219e22&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
360 $LOCALIP - - [$LOGDATE$] "GET /foo/bar?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=31ecbdafd357f54b281c9bd1d681bb90de219e22&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
361 $LOCALIP - - [$LOGDATE$] "GET /foo/bar?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D31ecbdafd357f54b281c9bd1d681bb90de219e22 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
361 $LOCALIP - - [$LOGDATE$] "GET /foo/bar?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D31ecbdafd357f54b281c9bd1d681bb90de219e22 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
362 $LOCALIP - - [$LOGDATE$] "GET /foo/bar?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=0&common=31ecbdafd357f54b281c9bd1d681bb90de219e22&heads=31ecbdafd357f54b281c9bd1d681bb90de219e22&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
362 $LOCALIP - - [$LOGDATE$] "GET /foo/bar?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=0&common=31ecbdafd357f54b281c9bd1d681bb90de219e22&heads=31ecbdafd357f54b281c9bd1d681bb90de219e22&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
363
363
364 $ killdaemons.py
364 $ killdaemons.py
365 $ rm hg1.pid error.log access.log
365 $ rm hg1.pid error.log access.log
366 $ cd repo
366 $ cd repo
367 #endif
367 #endif
368
368
369 Enable progress extension for archive tests:
369 Enable progress extension for archive tests:
370
370
371 $ cp $HGRCPATH $HGRCPATH.no-progress
371 $ cp $HGRCPATH $HGRCPATH.no-progress
372 $ cat >> $HGRCPATH <<EOF
372 $ cat >> $HGRCPATH <<EOF
373 > [progress]
373 > [progress]
374 > disable=False
374 > disable=False
375 > assume-tty = 1
375 > assume-tty = 1
376 > delay = 0
376 > delay = 0
377 > # set changedelay really large so we don't see nested topics
377 > # set changedelay really large so we don't see nested topics
378 > changedelay = 30000
378 > changedelay = 30000
379 > format = topic bar number
379 > format = topic bar number
380 > refresh = 0
380 > refresh = 0
381 > width = 60
381 > width = 60
382 > EOF
382 > EOF
383
383
384 Test archiving to a directory tree (the doubled lines in the output
384 Test archiving to a directory tree (the doubled lines in the output
385 only show up in the test output, not in real usage):
385 only show up in the test output, not in real usage):
386
386
387 $ hg archive --subrepos ../archive
387 $ hg archive --subrepos ../archive
388 \r (no-eol) (esc)
388 \r (no-eol) (esc)
389 archiving [ ] 0/3\r (no-eol) (esc)
389 archiving [ ] 0/3\r (no-eol) (esc)
390 archiving [=============> ] 1/3\r (no-eol) (esc)
390 archiving [=============> ] 1/3\r (no-eol) (esc)
391 archiving [===========================> ] 2/3\r (no-eol) (esc)
391 archiving [===========================> ] 2/3\r (no-eol) (esc)
392 archiving [==========================================>] 3/3\r (no-eol) (esc)
392 archiving [==========================================>] 3/3\r (no-eol) (esc)
393 \r (no-eol) (esc)
393 \r (no-eol) (esc)
394 \r (no-eol) (esc)
394 \r (no-eol) (esc)
395 archiving (foo) [ ] 0/3\r (no-eol) (esc)
395 archiving (foo) [ ] 0/3\r (no-eol) (esc)
396 archiving (foo) [===========> ] 1/3\r (no-eol) (esc)
396 archiving (foo) [===========> ] 1/3\r (no-eol) (esc)
397 archiving (foo) [=======================> ] 2/3\r (no-eol) (esc)
397 archiving (foo) [=======================> ] 2/3\r (no-eol) (esc)
398 archiving (foo) [====================================>] 3/3\r (no-eol) (esc)
398 archiving (foo) [====================================>] 3/3\r (no-eol) (esc)
399 \r (no-eol) (esc)
399 \r (no-eol) (esc)
400 \r (no-eol) (esc)
400 \r (no-eol) (esc)
401 archiving (foo/bar) [ ] 0/1\r (no-eol) (esc)
401 archiving (foo/bar) [ ] 0/1\r (no-eol) (esc)
402 archiving (foo/bar) [================================>] 1/1\r (no-eol) (esc)
402 archiving (foo/bar) [================================>] 1/1\r (no-eol) (esc)
403 \r (no-eol) (esc)
403 \r (no-eol) (esc)
404 $ find ../archive | sort
404 $ find ../archive | sort
405 ../archive
405 ../archive
406 ../archive/.hg_archival.txt
406 ../archive/.hg_archival.txt
407 ../archive/.hgsub
407 ../archive/.hgsub
408 ../archive/.hgsubstate
408 ../archive/.hgsubstate
409 ../archive/foo
409 ../archive/foo
410 ../archive/foo/.hgsub
410 ../archive/foo/.hgsub
411 ../archive/foo/.hgsubstate
411 ../archive/foo/.hgsubstate
412 ../archive/foo/bar
412 ../archive/foo/bar
413 ../archive/foo/bar/z.txt
413 ../archive/foo/bar/z.txt
414 ../archive/foo/y.txt
414 ../archive/foo/y.txt
415 ../archive/x.txt
415 ../archive/x.txt
416
416
417 Test archiving to zip file (unzip output is unstable):
417 Test archiving to zip file (unzip output is unstable):
418
418
419 $ hg archive --subrepos --prefix '.' ../archive.zip
419 $ hg archive --subrepos --prefix '.' ../archive.zip
420 \r (no-eol) (esc)
420 \r (no-eol) (esc)
421 archiving [ ] 0/3\r (no-eol) (esc)
421 archiving [ ] 0/3\r (no-eol) (esc)
422 archiving [=============> ] 1/3\r (no-eol) (esc)
422 archiving [=============> ] 1/3\r (no-eol) (esc)
423 archiving [===========================> ] 2/3\r (no-eol) (esc)
423 archiving [===========================> ] 2/3\r (no-eol) (esc)
424 archiving [==========================================>] 3/3\r (no-eol) (esc)
424 archiving [==========================================>] 3/3\r (no-eol) (esc)
425 \r (no-eol) (esc)
425 \r (no-eol) (esc)
426 \r (no-eol) (esc)
426 \r (no-eol) (esc)
427 archiving (foo) [ ] 0/3\r (no-eol) (esc)
427 archiving (foo) [ ] 0/3\r (no-eol) (esc)
428 archiving (foo) [===========> ] 1/3\r (no-eol) (esc)
428 archiving (foo) [===========> ] 1/3\r (no-eol) (esc)
429 archiving (foo) [=======================> ] 2/3\r (no-eol) (esc)
429 archiving (foo) [=======================> ] 2/3\r (no-eol) (esc)
430 archiving (foo) [====================================>] 3/3\r (no-eol) (esc)
430 archiving (foo) [====================================>] 3/3\r (no-eol) (esc)
431 \r (no-eol) (esc)
431 \r (no-eol) (esc)
432 \r (no-eol) (esc)
432 \r (no-eol) (esc)
433 archiving (foo/bar) [ ] 0/1\r (no-eol) (esc)
433 archiving (foo/bar) [ ] 0/1\r (no-eol) (esc)
434 archiving (foo/bar) [================================>] 1/1\r (no-eol) (esc)
434 archiving (foo/bar) [================================>] 1/1\r (no-eol) (esc)
435 \r (no-eol) (esc)
435 \r (no-eol) (esc)
436
436
437 (unzip date formating is unstable, we do not care about it and glob it out)
437 (unzip date formating is unstable, we do not care about it and glob it out)
438
438
439 $ unzip -l ../archive.zip | grep -v -- ----- | egrep -v files$
439 $ unzip -l ../archive.zip | grep -v -- ----- | egrep -v files$
440 Archive: ../archive.zip
440 Archive: ../archive.zip
441 Length [ ]* Date [ ]* Time [ ]* Name (re)
441 Length [ ]* Date [ ]* Time [ ]* Name (re)
442 172 [0-9:\- ]* .hg_archival.txt (re)
442 172 [0-9:\- ]* .hg_archival.txt (re)
443 10 [0-9:\- ]* .hgsub (re)
443 10 [0-9:\- ]* .hgsub (re)
444 45 [0-9:\- ]* .hgsubstate (re)
444 45 [0-9:\- ]* .hgsubstate (re)
445 3 [0-9:\- ]* x.txt (re)
445 3 [0-9:\- ]* x.txt (re)
446 10 [0-9:\- ]* foo/.hgsub (re)
446 10 [0-9:\- ]* foo/.hgsub (re)
447 45 [0-9:\- ]* foo/.hgsubstate (re)
447 45 [0-9:\- ]* foo/.hgsubstate (re)
448 9 [0-9:\- ]* foo/y.txt (re)
448 9 [0-9:\- ]* foo/y.txt (re)
449 9 [0-9:\- ]* foo/bar/z.txt (re)
449 9 [0-9:\- ]* foo/bar/z.txt (re)
450
450
451 Test archiving a revision that references a subrepo that is not yet
451 Test archiving a revision that references a subrepo that is not yet
452 cloned:
452 cloned:
453
453
454 #if hardlink
454 #if hardlink
455 $ hg clone -U . ../empty
455 $ hg clone -U . ../empty
456 \r (no-eol) (esc)
456 \r (no-eol) (esc)
457 linking [ <=> ] 1\r (no-eol) (esc)
457 linking [====> ] 1/9\r (no-eol) (esc)
458 linking [ <=> ] 2\r (no-eol) (esc)
458 linking [=========> ] 2/9\r (no-eol) (esc)
459 linking [ <=> ] 3\r (no-eol) (esc)
459 linking [==============> ] 3/9\r (no-eol) (esc)
460 linking [ <=> ] 4\r (no-eol) (esc)
460 linking [===================> ] 4/9\r (no-eol) (esc)
461 linking [ <=> ] 5\r (no-eol) (esc)
461 linking [========================> ] 5/9\r (no-eol) (esc)
462 linking [ <=> ] 6\r (no-eol) (esc)
462 linking [=============================> ] 6/9\r (no-eol) (esc)
463 linking [ <=> ] 7\r (no-eol) (esc)
463 linking [==================================> ] 7/9\r (no-eol) (esc)
464 linking [ <=> ] 8\r (no-eol) (esc)
464 linking [=======================================> ] 8/9\r (no-eol) (esc)
465 linking [ <=> ] 9\r (no-eol) (esc) (reposimplestore !)
465 linking [============================================>] 9/9\r (no-eol) (esc)
466 linking [ <=> ] 10\r (no-eol) (esc) (reposimplestore !)
467 linking [ <=> ] 11\r (no-eol) (esc) (reposimplestore !)
468 linking [ <=> ] 12\r (no-eol) (esc) (reposimplestore !)
469 linking [ <=> ] 13\r (no-eol) (esc) (reposimplestore !)
470 \r (no-eol) (esc)
466 \r (no-eol) (esc)
471 #else
467 #else
472 $ hg clone -U . ../empty
468 $ hg clone -U . ../empty
473 \r (no-eol) (esc)
469 \r (no-eol) (esc)
474 linking [ <=> ] 1 (no-eol)
470 linking [ <=> ] 1 (no-eol)
475 #endif
471 #endif
476
472
477 $ cd ../empty
473 $ cd ../empty
478 #if hardlink
474 #if hardlink
479 $ hg archive --subrepos -r tip --prefix './' ../archive.tar.gz
475 $ hg archive --subrepos -r tip --prefix './' ../archive.tar.gz
480 \r (no-eol) (esc)
476 \r (no-eol) (esc)
481 archiving [ ] 0/3\r (no-eol) (esc)
477 archiving [ ] 0/3\r (no-eol) (esc)
482 archiving [=============> ] 1/3\r (no-eol) (esc)
478 archiving [=============> ] 1/3\r (no-eol) (esc)
483 archiving [===========================> ] 2/3\r (no-eol) (esc)
479 archiving [===========================> ] 2/3\r (no-eol) (esc)
484 archiving [==========================================>] 3/3\r (no-eol) (esc)
480 archiving [==========================================>] 3/3\r (no-eol) (esc)
485 \r (no-eol) (esc)
481 \r (no-eol) (esc)
486 \r (no-eol) (esc)
482 \r (no-eol) (esc)
487 linking [ <=> ] 1\r (no-eol) (esc)
483 linking [====> ] 1/8\r (no-eol) (esc)
488 linking [ <=> ] 2\r (no-eol) (esc)
484 linking [==========> ] 2/8\r (no-eol) (esc)
489 linking [ <=> ] 3\r (no-eol) (esc)
485 linking [===============> ] 3/8\r (no-eol) (esc)
490 linking [ <=> ] 4\r (no-eol) (esc)
486 linking [=====================> ] 4/8\r (no-eol) (esc)
491 linking [ <=> ] 5\r (no-eol) (esc)
487 linking [===========================> ] 5/8\r (no-eol) (esc)
492 linking [ <=> ] 6\r (no-eol) (esc)
488 linking [================================> ] 6/8\r (no-eol) (esc)
493 linking [ <=> ] 7\r (no-eol) (esc)
489 linking [======================================> ] 7/8\r (no-eol) (esc)
494 linking [ <=> ] 8\r (no-eol) (esc)
490 linking [============================================>] 8/8\r (no-eol) (esc)
495 linking [ <=> ] 9\r (no-eol) (esc) (reposimplestore !)
496 linking [ <=> ] 10\r (no-eol) (esc) (reposimplestore !)
497 linking [ <=> ] 11\r (no-eol) (esc) (reposimplestore !)
498 linking [ <=> ] 12\r (no-eol) (esc) (reposimplestore !)
499 linking [ <=> ] 13\r (no-eol) (esc) (reposimplestore !)
500 linking [ <=> ] 14\r (no-eol) (esc) (reposimplestore !)
501 linking [ <=> ] 15\r (no-eol) (esc) (reposimplestore !)
502 linking [ <=> ] 16\r (no-eol) (esc) (reposimplestore !)
503 \r (no-eol) (esc)
491 \r (no-eol) (esc)
504 \r (no-eol) (esc)
492 \r (no-eol) (esc)
505 archiving (foo) [ ] 0/3\r (no-eol) (esc)
493 archiving (foo) [ ] 0/3\r (no-eol) (esc)
506 archiving (foo) [===========> ] 1/3\r (no-eol) (esc)
494 archiving (foo) [===========> ] 1/3\r (no-eol) (esc)
507 archiving (foo) [=======================> ] 2/3\r (no-eol) (esc)
495 archiving (foo) [=======================> ] 2/3\r (no-eol) (esc)
508 archiving (foo) [====================================>] 3/3\r (no-eol) (esc)
496 archiving (foo) [====================================>] 3/3\r (no-eol) (esc)
509 \r (no-eol) (esc)
497 \r (no-eol) (esc)
510 \r (no-eol) (esc)
498 \r (no-eol) (esc)
511 linking [ <=> ] 1\r (no-eol) (esc)
499 linking [======> ] 1/6\r (no-eol) (esc)
512 linking [ <=> ] 2\r (no-eol) (esc)
500 linking [==============> ] 2/6\r (no-eol) (esc)
513 linking [ <=> ] 3\r (no-eol) (esc)
501 linking [=====================> ] 3/6\r (no-eol) (esc)
514 linking [ <=> ] 4\r (no-eol) (esc)
502 linking [=============================> ] 4/6\r (no-eol) (esc)
515 linking [ <=> ] 5\r (no-eol) (esc)
503 linking [====================================> ] 5/6\r (no-eol) (esc)
516 linking [ <=> ] 6\r (no-eol) (esc)
504 linking [============================================>] 6/6\r (no-eol) (esc)
517 linking [ <=> ] 7\r (no-eol) (esc) (reposimplestore !)
518 linking [ <=> ] 8\r (no-eol) (esc) (reposimplestore !)
519 linking [ <=> ] 9\r (no-eol) (esc) (reposimplestore !)
520 \r (no-eol) (esc)
505 \r (no-eol) (esc)
521 \r (no-eol) (esc)
506 \r (no-eol) (esc)
522 archiving (foo/bar) [ ] 0/1\r (no-eol) (esc)
507 archiving (foo/bar) [ ] 0/1\r (no-eol) (esc)
523 archiving (foo/bar) [================================>] 1/1\r (no-eol) (esc)
508 archiving (foo/bar) [================================>] 1/1\r (no-eol) (esc)
524 \r (no-eol) (esc)
509 \r (no-eol) (esc)
525 cloning subrepo foo from $TESTTMP/repo/foo
510 cloning subrepo foo from $TESTTMP/repo/foo
526 cloning subrepo foo/bar from $TESTTMP/repo/foo/bar
511 cloning subrepo foo/bar from $TESTTMP/repo/foo/bar
527 #else
512 #else
528 Note there's a slight output glitch on non-hardlink systems: the last
513 Note there's a slight output glitch on non-hardlink systems: the last
529 "linking" progress topic never gets closed, leading to slight output corruption on that platform.
514 "linking" progress topic never gets closed, leading to slight output corruption on that platform.
530 $ hg archive --subrepos -r tip --prefix './' ../archive.tar.gz
515 $ hg archive --subrepos -r tip --prefix './' ../archive.tar.gz
531 \r (no-eol) (esc)
516 \r (no-eol) (esc)
532 archiving [ ] 0/3\r (no-eol) (esc)
517 archiving [ ] 0/3\r (no-eol) (esc)
533 archiving [=============> ] 1/3\r (no-eol) (esc)
518 archiving [=============> ] 1/3\r (no-eol) (esc)
534 archiving [===========================> ] 2/3\r (no-eol) (esc)
519 archiving [===========================> ] 2/3\r (no-eol) (esc)
535 archiving [==========================================>] 3/3\r (no-eol) (esc)
520 archiving [==========================================>] 3/3\r (no-eol) (esc)
536 \r (no-eol) (esc)
521 \r (no-eol) (esc)
537 \r (no-eol) (esc)
522 \r (no-eol) (esc)
538 linking [ <=> ] 1\r (no-eol) (esc)
523 linking [ <=> ] 1\r (no-eol) (esc)
539 cloning subrepo foo/bar from $TESTTMP/repo/foo/bar
524 cloning subrepo foo/bar from $TESTTMP/repo/foo/bar
540 #endif
525 #endif
541
526
542 Archive + subrepos uses '/' for all component separators
527 Archive + subrepos uses '/' for all component separators
543
528
544 $ tar -tzf ../archive.tar.gz | sort
529 $ tar -tzf ../archive.tar.gz | sort
545 .hg_archival.txt
530 .hg_archival.txt
546 .hgsub
531 .hgsub
547 .hgsubstate
532 .hgsubstate
548 foo/.hgsub
533 foo/.hgsub
549 foo/.hgsubstate
534 foo/.hgsubstate
550 foo/bar/z.txt
535 foo/bar/z.txt
551 foo/y.txt
536 foo/y.txt
552 x.txt
537 x.txt
553
538
554 The newly cloned subrepos contain no working copy:
539 The newly cloned subrepos contain no working copy:
555
540
556 $ hg -R foo summary
541 $ hg -R foo summary
557 parent: -1:000000000000 (no revision checked out)
542 parent: -1:000000000000 (no revision checked out)
558 branch: default
543 branch: default
559 commit: (clean)
544 commit: (clean)
560 update: 4 new changesets (update)
545 update: 4 new changesets (update)
561
546
562 Sharing a local repo with missing local subrepos (i.e. it was never updated
547 Sharing a local repo with missing local subrepos (i.e. it was never updated
563 from null) works because the default path is copied from the source repo,
548 from null) works because the default path is copied from the source repo,
564 whereas clone should fail.
549 whereas clone should fail.
565
550
566 $ hg --config progress.disable=True clone -U ../empty ../empty2
551 $ hg --config progress.disable=True clone -U ../empty ../empty2
567
552
568 $ hg --config extensions.share= --config progress.disable=True \
553 $ hg --config extensions.share= --config progress.disable=True \
569 > share ../empty2 ../empty_share
554 > share ../empty2 ../empty_share
570 updating working directory
555 updating working directory
571 sharing subrepo foo from $TESTTMP/empty/foo
556 sharing subrepo foo from $TESTTMP/empty/foo
572 sharing subrepo foo/bar from $TESTTMP/empty/foo/bar
557 sharing subrepo foo/bar from $TESTTMP/empty/foo/bar
573 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
558 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
574
559
575 $ hg --config progress.disable=True clone ../empty2 ../empty_clone
560 $ hg --config progress.disable=True clone ../empty2 ../empty_clone
576 updating to branch default
561 updating to branch default
577 cloning subrepo foo from $TESTTMP/empty2/foo
562 cloning subrepo foo from $TESTTMP/empty2/foo
578 abort: repository $TESTTMP/empty2/foo not found
563 abort: repository $TESTTMP/empty2/foo not found
579 [255]
564 [255]
580
565
581 Disable progress extension and cleanup:
566 Disable progress extension and cleanup:
582
567
583 $ mv $HGRCPATH.no-progress $HGRCPATH
568 $ mv $HGRCPATH.no-progress $HGRCPATH
584
569
585 Test archiving when there is a directory in the way for a subrepo
570 Test archiving when there is a directory in the way for a subrepo
586 created by archive:
571 created by archive:
587
572
588 $ hg clone -U . ../almost-empty
573 $ hg clone -U . ../almost-empty
589 $ cd ../almost-empty
574 $ cd ../almost-empty
590 $ mkdir foo
575 $ mkdir foo
591 $ echo f > foo/f
576 $ echo f > foo/f
592 $ hg archive --subrepos -r tip archive
577 $ hg archive --subrepos -r tip archive
593 cloning subrepo foo from $TESTTMP/empty/foo
578 cloning subrepo foo from $TESTTMP/empty/foo
594 abort: destination '$TESTTMP/almost-empty/foo' is not empty (in subrepository "foo")
579 abort: destination '$TESTTMP/almost-empty/foo' is not empty (in subrepository "foo")
595 [255]
580 [255]
596
581
597 Clone and test outgoing:
582 Clone and test outgoing:
598
583
599 $ cd ..
584 $ cd ..
600 $ hg clone repo repo2
585 $ hg clone repo repo2
601 updating to branch default
586 updating to branch default
602 cloning subrepo foo from $TESTTMP/repo/foo
587 cloning subrepo foo from $TESTTMP/repo/foo
603 cloning subrepo foo/bar from $TESTTMP/repo/foo/bar
588 cloning subrepo foo/bar from $TESTTMP/repo/foo/bar
604 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
589 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
605 $ cd repo2
590 $ cd repo2
606 $ hg outgoing -S
591 $ hg outgoing -S
607 comparing with $TESTTMP/repo
592 comparing with $TESTTMP/repo
608 searching for changes
593 searching for changes
609 no changes found
594 no changes found
610 comparing with $TESTTMP/repo/foo
595 comparing with $TESTTMP/repo/foo
611 searching for changes
596 searching for changes
612 no changes found
597 no changes found
613 comparing with $TESTTMP/repo/foo/bar
598 comparing with $TESTTMP/repo/foo/bar
614 searching for changes
599 searching for changes
615 no changes found
600 no changes found
616 [1]
601 [1]
617
602
618 Make nested change:
603 Make nested change:
619
604
620 $ echo y4 >> foo/y.txt
605 $ echo y4 >> foo/y.txt
621 $ hg diff --nodates -S
606 $ hg diff --nodates -S
622 diff -r 65903cebad86 foo/y.txt
607 diff -r 65903cebad86 foo/y.txt
623 --- a/foo/y.txt
608 --- a/foo/y.txt
624 +++ b/foo/y.txt
609 +++ b/foo/y.txt
625 @@ -1,3 +1,4 @@
610 @@ -1,3 +1,4 @@
626 y1
611 y1
627 y2
612 y2
628 y3
613 y3
629 +y4
614 +y4
630 $ hg commit --subrepos -m 3-4-2
615 $ hg commit --subrepos -m 3-4-2
631 committing subrepository foo
616 committing subrepository foo
632 $ hg outgoing -S
617 $ hg outgoing -S
633 comparing with $TESTTMP/repo
618 comparing with $TESTTMP/repo
634 searching for changes
619 searching for changes
635 changeset: 3:2655b8ecc4ee
620 changeset: 3:2655b8ecc4ee
636 tag: tip
621 tag: tip
637 user: test
622 user: test
638 date: Thu Jan 01 00:00:00 1970 +0000
623 date: Thu Jan 01 00:00:00 1970 +0000
639 summary: 3-4-2
624 summary: 3-4-2
640
625
641 comparing with $TESTTMP/repo/foo
626 comparing with $TESTTMP/repo/foo
642 searching for changes
627 searching for changes
643 changeset: 4:e96193d6cb36
628 changeset: 4:e96193d6cb36
644 tag: tip
629 tag: tip
645 user: test
630 user: test
646 date: Thu Jan 01 00:00:00 1970 +0000
631 date: Thu Jan 01 00:00:00 1970 +0000
647 summary: 3-4-2
632 summary: 3-4-2
648
633
649 comparing with $TESTTMP/repo/foo/bar
634 comparing with $TESTTMP/repo/foo/bar
650 searching for changes
635 searching for changes
651 no changes found
636 no changes found
652
637
653
638
654 Switch to original repo and setup default path:
639 Switch to original repo and setup default path:
655
640
656 $ cd ../repo
641 $ cd ../repo
657 $ echo '[paths]' >> .hg/hgrc
642 $ echo '[paths]' >> .hg/hgrc
658 $ echo 'default = ../repo2' >> .hg/hgrc
643 $ echo 'default = ../repo2' >> .hg/hgrc
659
644
660 Test incoming:
645 Test incoming:
661
646
662 $ hg incoming -S
647 $ hg incoming -S
663 comparing with $TESTTMP/repo2
648 comparing with $TESTTMP/repo2
664 searching for changes
649 searching for changes
665 changeset: 3:2655b8ecc4ee
650 changeset: 3:2655b8ecc4ee
666 tag: tip
651 tag: tip
667 user: test
652 user: test
668 date: Thu Jan 01 00:00:00 1970 +0000
653 date: Thu Jan 01 00:00:00 1970 +0000
669 summary: 3-4-2
654 summary: 3-4-2
670
655
671 comparing with $TESTTMP/repo2/foo
656 comparing with $TESTTMP/repo2/foo
672 searching for changes
657 searching for changes
673 changeset: 4:e96193d6cb36
658 changeset: 4:e96193d6cb36
674 tag: tip
659 tag: tip
675 user: test
660 user: test
676 date: Thu Jan 01 00:00:00 1970 +0000
661 date: Thu Jan 01 00:00:00 1970 +0000
677 summary: 3-4-2
662 summary: 3-4-2
678
663
679 comparing with $TESTTMP/repo2/foo/bar
664 comparing with $TESTTMP/repo2/foo/bar
680 searching for changes
665 searching for changes
681 no changes found
666 no changes found
682
667
683 $ hg incoming -S --bundle incoming.hg
668 $ hg incoming -S --bundle incoming.hg
684 abort: cannot specify both --subrepos and --bundle
669 abort: cannot specify both --subrepos and --bundle
685 [10]
670 [10]
686
671
687 Test missing subrepo:
672 Test missing subrepo:
688
673
689 $ rm -r foo
674 $ rm -r foo
690 $ hg status -S
675 $ hg status -S
691 warning: error "unknown revision '65903cebad86f1a84bd4f1134f62fa7dcb7a1c98'" in subrepository "foo"
676 warning: error "unknown revision '65903cebad86f1a84bd4f1134f62fa7dcb7a1c98'" in subrepository "foo"
692
677
693 Issue2619: IndexError: list index out of range on hg add with subrepos
678 Issue2619: IndexError: list index out of range on hg add with subrepos
694 The subrepo must sorts after the explicit filename.
679 The subrepo must sorts after the explicit filename.
695
680
696 $ cd ..
681 $ cd ..
697 $ hg init test
682 $ hg init test
698 $ cd test
683 $ cd test
699 $ hg init x
684 $ hg init x
700 $ echo abc > abc.txt
685 $ echo abc > abc.txt
701 $ hg ci -Am "abc"
686 $ hg ci -Am "abc"
702 adding abc.txt
687 adding abc.txt
703 $ echo "x = x" >> .hgsub
688 $ echo "x = x" >> .hgsub
704 $ hg add .hgsub
689 $ hg add .hgsub
705 $ touch a x/a
690 $ touch a x/a
706 $ hg add a x/a
691 $ hg add a x/a
707
692
708 $ hg ci -Sm "added x"
693 $ hg ci -Sm "added x"
709 committing subrepository x
694 committing subrepository x
710 $ echo abc > x/a
695 $ echo abc > x/a
711 $ hg revert --rev '.^' "set:subrepo('glob:x*')"
696 $ hg revert --rev '.^' "set:subrepo('glob:x*')"
712 abort: subrepository 'x' does not exist in 25ac2c9b3180!
697 abort: subrepository 'x' does not exist in 25ac2c9b3180!
713 [255]
698 [255]
714
699
715 $ cd ..
700 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now