##// END OF EJS Templates
hg: obtain lock when creating share from pooled repo (issue5104)...
Gregory Szorc -
r28289:d493d647 3.7.2 stable
parent child Browse files
Show More
@@ -0,0 +1,26 b''
1 # Dummy extension that adds a delay after acquiring a lock.
2 #
3 # This extension can be used to test race conditions between lock acquisition.
4
5 from __future__ import absolute_import
6
7 import os
8 import time
9
10 from mercurial import (
11 lock as lockmod,
12 )
13
14 class delaylock(lockmod.lock):
15 def lock(self):
16 delay = float(os.environ.get('HGPRELOCKDELAY', '0.0'))
17 if delay:
18 time.sleep(delay)
19 res = super(delaylock, self).lock()
20 delay = float(os.environ.get('HGPOSTLOCKDELAY', '0.0'))
21 if delay:
22 time.sleep(delay)
23 return res
24
25 def extsetup(ui):
26 lockmod.lock = delaylock
@@ -1,918 +1,931 b''
1 # hg.py - repository classes for mercurial
1 # hg.py - repository classes for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@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
14
15 from .i18n import _
15 from .i18n import _
16 from .node import nullid
16 from .node import nullid
17
17
18 from . import (
18 from . import (
19 bookmarks,
19 bookmarks,
20 bundlerepo,
20 bundlerepo,
21 cmdutil,
21 cmdutil,
22 discovery,
22 discovery,
23 error,
23 error,
24 exchange,
24 exchange,
25 extensions,
25 extensions,
26 httppeer,
26 httppeer,
27 localrepo,
27 localrepo,
28 lock,
28 lock,
29 merge as mergemod,
29 merge as mergemod,
30 node,
30 node,
31 phases,
31 phases,
32 repoview,
32 repoview,
33 scmutil,
33 scmutil,
34 sshpeer,
34 sshpeer,
35 statichttprepo,
35 statichttprepo,
36 ui as uimod,
36 ui as uimod,
37 unionrepo,
37 unionrepo,
38 url,
38 url,
39 util,
39 util,
40 verify as verifymod,
40 verify as verifymod,
41 )
41 )
42
42
43 release = lock.release
43 release = lock.release
44
44
45 def _local(path):
45 def _local(path):
46 path = util.expandpath(util.urllocalpath(path))
46 path = util.expandpath(util.urllocalpath(path))
47 return (os.path.isfile(path) and bundlerepo or localrepo)
47 return (os.path.isfile(path) and bundlerepo or localrepo)
48
48
49 def addbranchrevs(lrepo, other, branches, revs):
49 def addbranchrevs(lrepo, other, branches, revs):
50 peer = other.peer() # a courtesy to callers using a localrepo for other
50 peer = other.peer() # a courtesy to callers using a localrepo for other
51 hashbranch, branches = branches
51 hashbranch, branches = branches
52 if not hashbranch and not branches:
52 if not hashbranch and not branches:
53 x = revs or None
53 x = revs or None
54 if util.safehasattr(revs, 'first'):
54 if util.safehasattr(revs, 'first'):
55 y = revs.first()
55 y = revs.first()
56 elif revs:
56 elif revs:
57 y = revs[0]
57 y = revs[0]
58 else:
58 else:
59 y = None
59 y = None
60 return x, y
60 return x, y
61 if revs:
61 if revs:
62 revs = list(revs)
62 revs = list(revs)
63 else:
63 else:
64 revs = []
64 revs = []
65
65
66 if not peer.capable('branchmap'):
66 if not peer.capable('branchmap'):
67 if branches:
67 if branches:
68 raise error.Abort(_("remote branch lookup not supported"))
68 raise error.Abort(_("remote branch lookup not supported"))
69 revs.append(hashbranch)
69 revs.append(hashbranch)
70 return revs, revs[0]
70 return revs, revs[0]
71 branchmap = peer.branchmap()
71 branchmap = peer.branchmap()
72
72
73 def primary(branch):
73 def primary(branch):
74 if branch == '.':
74 if branch == '.':
75 if not lrepo:
75 if not lrepo:
76 raise error.Abort(_("dirstate branch not accessible"))
76 raise error.Abort(_("dirstate branch not accessible"))
77 branch = lrepo.dirstate.branch()
77 branch = lrepo.dirstate.branch()
78 if branch in branchmap:
78 if branch in branchmap:
79 revs.extend(node.hex(r) for r in reversed(branchmap[branch]))
79 revs.extend(node.hex(r) for r in reversed(branchmap[branch]))
80 return True
80 return True
81 else:
81 else:
82 return False
82 return False
83
83
84 for branch in branches:
84 for branch in branches:
85 if not primary(branch):
85 if not primary(branch):
86 raise error.RepoLookupError(_("unknown branch '%s'") % branch)
86 raise error.RepoLookupError(_("unknown branch '%s'") % branch)
87 if hashbranch:
87 if hashbranch:
88 if not primary(hashbranch):
88 if not primary(hashbranch):
89 revs.append(hashbranch)
89 revs.append(hashbranch)
90 return revs, revs[0]
90 return revs, revs[0]
91
91
92 def parseurl(path, branches=None):
92 def parseurl(path, branches=None):
93 '''parse url#branch, returning (url, (branch, branches))'''
93 '''parse url#branch, returning (url, (branch, branches))'''
94
94
95 u = util.url(path)
95 u = util.url(path)
96 branch = None
96 branch = None
97 if u.fragment:
97 if u.fragment:
98 branch = u.fragment
98 branch = u.fragment
99 u.fragment = None
99 u.fragment = None
100 return str(u), (branch, branches or [])
100 return str(u), (branch, branches or [])
101
101
102 schemes = {
102 schemes = {
103 'bundle': bundlerepo,
103 'bundle': bundlerepo,
104 'union': unionrepo,
104 'union': unionrepo,
105 'file': _local,
105 'file': _local,
106 'http': httppeer,
106 'http': httppeer,
107 'https': httppeer,
107 'https': httppeer,
108 'ssh': sshpeer,
108 'ssh': sshpeer,
109 'static-http': statichttprepo,
109 'static-http': statichttprepo,
110 }
110 }
111
111
112 def _peerlookup(path):
112 def _peerlookup(path):
113 u = util.url(path)
113 u = util.url(path)
114 scheme = u.scheme or 'file'
114 scheme = u.scheme or 'file'
115 thing = schemes.get(scheme) or schemes['file']
115 thing = schemes.get(scheme) or schemes['file']
116 try:
116 try:
117 return thing(path)
117 return thing(path)
118 except TypeError:
118 except TypeError:
119 # we can't test callable(thing) because 'thing' can be an unloaded
119 # we can't test callable(thing) because 'thing' can be an unloaded
120 # module that implements __call__
120 # module that implements __call__
121 if not util.safehasattr(thing, 'instance'):
121 if not util.safehasattr(thing, 'instance'):
122 raise
122 raise
123 return thing
123 return thing
124
124
125 def islocal(repo):
125 def islocal(repo):
126 '''return true if repo (or path pointing to repo) is local'''
126 '''return true if repo (or path pointing to repo) is local'''
127 if isinstance(repo, str):
127 if isinstance(repo, str):
128 try:
128 try:
129 return _peerlookup(repo).islocal(repo)
129 return _peerlookup(repo).islocal(repo)
130 except AttributeError:
130 except AttributeError:
131 return False
131 return False
132 return repo.local()
132 return repo.local()
133
133
134 def openpath(ui, path):
134 def openpath(ui, path):
135 '''open path with open if local, url.open if remote'''
135 '''open path with open if local, url.open if remote'''
136 pathurl = util.url(path, parsequery=False, parsefragment=False)
136 pathurl = util.url(path, parsequery=False, parsefragment=False)
137 if pathurl.islocal():
137 if pathurl.islocal():
138 return util.posixfile(pathurl.localpath(), 'rb')
138 return util.posixfile(pathurl.localpath(), 'rb')
139 else:
139 else:
140 return url.open(ui, path)
140 return url.open(ui, path)
141
141
142 # a list of (ui, repo) functions called for wire peer initialization
142 # a list of (ui, repo) functions called for wire peer initialization
143 wirepeersetupfuncs = []
143 wirepeersetupfuncs = []
144
144
145 def _peerorrepo(ui, path, create=False):
145 def _peerorrepo(ui, path, create=False):
146 """return a repository object for the specified path"""
146 """return a repository object for the specified path"""
147 obj = _peerlookup(path).instance(ui, path, create)
147 obj = _peerlookup(path).instance(ui, path, create)
148 ui = getattr(obj, "ui", ui)
148 ui = getattr(obj, "ui", ui)
149 for name, module in extensions.extensions(ui):
149 for name, module in extensions.extensions(ui):
150 hook = getattr(module, 'reposetup', None)
150 hook = getattr(module, 'reposetup', None)
151 if hook:
151 if hook:
152 hook(ui, obj)
152 hook(ui, obj)
153 if not obj.local():
153 if not obj.local():
154 for f in wirepeersetupfuncs:
154 for f in wirepeersetupfuncs:
155 f(ui, obj)
155 f(ui, obj)
156 return obj
156 return obj
157
157
158 def repository(ui, path='', create=False):
158 def repository(ui, path='', create=False):
159 """return a repository object for the specified path"""
159 """return a repository object for the specified path"""
160 peer = _peerorrepo(ui, path, create)
160 peer = _peerorrepo(ui, path, create)
161 repo = peer.local()
161 repo = peer.local()
162 if not repo:
162 if not repo:
163 raise error.Abort(_("repository '%s' is not local") %
163 raise error.Abort(_("repository '%s' is not local") %
164 (path or peer.url()))
164 (path or peer.url()))
165 return repo.filtered('visible')
165 return repo.filtered('visible')
166
166
167 def peer(uiorrepo, opts, path, create=False):
167 def peer(uiorrepo, opts, path, create=False):
168 '''return a repository peer for the specified path'''
168 '''return a repository peer for the specified path'''
169 rui = remoteui(uiorrepo, opts)
169 rui = remoteui(uiorrepo, opts)
170 return _peerorrepo(rui, path, create).peer()
170 return _peerorrepo(rui, path, create).peer()
171
171
172 def defaultdest(source):
172 def defaultdest(source):
173 '''return default destination of clone if none is given
173 '''return default destination of clone if none is given
174
174
175 >>> defaultdest('foo')
175 >>> defaultdest('foo')
176 'foo'
176 'foo'
177 >>> defaultdest('/foo/bar')
177 >>> defaultdest('/foo/bar')
178 'bar'
178 'bar'
179 >>> defaultdest('/')
179 >>> defaultdest('/')
180 ''
180 ''
181 >>> defaultdest('')
181 >>> defaultdest('')
182 ''
182 ''
183 >>> defaultdest('http://example.org/')
183 >>> defaultdest('http://example.org/')
184 ''
184 ''
185 >>> defaultdest('http://example.org/foo/')
185 >>> defaultdest('http://example.org/foo/')
186 'foo'
186 'foo'
187 '''
187 '''
188 path = util.url(source).path
188 path = util.url(source).path
189 if not path:
189 if not path:
190 return ''
190 return ''
191 return os.path.basename(os.path.normpath(path))
191 return os.path.basename(os.path.normpath(path))
192
192
193 def share(ui, source, dest=None, update=True, bookmarks=True):
193 def share(ui, source, dest=None, update=True, bookmarks=True):
194 '''create a shared repository'''
194 '''create a shared repository'''
195
195
196 if not islocal(source):
196 if not islocal(source):
197 raise error.Abort(_('can only share local repositories'))
197 raise error.Abort(_('can only share local repositories'))
198
198
199 if not dest:
199 if not dest:
200 dest = defaultdest(source)
200 dest = defaultdest(source)
201 else:
201 else:
202 dest = ui.expandpath(dest)
202 dest = ui.expandpath(dest)
203
203
204 if isinstance(source, str):
204 if isinstance(source, str):
205 origsource = ui.expandpath(source)
205 origsource = ui.expandpath(source)
206 source, branches = parseurl(origsource)
206 source, branches = parseurl(origsource)
207 srcrepo = repository(ui, source)
207 srcrepo = repository(ui, source)
208 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
208 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
209 else:
209 else:
210 srcrepo = source.local()
210 srcrepo = source.local()
211 origsource = source = srcrepo.url()
211 origsource = source = srcrepo.url()
212 checkout = None
212 checkout = None
213
213
214 sharedpath = srcrepo.sharedpath # if our source is already sharing
214 sharedpath = srcrepo.sharedpath # if our source is already sharing
215
215
216 destwvfs = scmutil.vfs(dest, realpath=True)
216 destwvfs = scmutil.vfs(dest, realpath=True)
217 destvfs = scmutil.vfs(os.path.join(destwvfs.base, '.hg'), realpath=True)
217 destvfs = scmutil.vfs(os.path.join(destwvfs.base, '.hg'), realpath=True)
218
218
219 if destvfs.lexists():
219 if destvfs.lexists():
220 raise error.Abort(_('destination already exists'))
220 raise error.Abort(_('destination already exists'))
221
221
222 if not destwvfs.isdir():
222 if not destwvfs.isdir():
223 destwvfs.mkdir()
223 destwvfs.mkdir()
224 destvfs.makedir()
224 destvfs.makedir()
225
225
226 requirements = ''
226 requirements = ''
227 try:
227 try:
228 requirements = srcrepo.vfs.read('requires')
228 requirements = srcrepo.vfs.read('requires')
229 except IOError as inst:
229 except IOError as inst:
230 if inst.errno != errno.ENOENT:
230 if inst.errno != errno.ENOENT:
231 raise
231 raise
232
232
233 requirements += 'shared\n'
233 requirements += 'shared\n'
234 destvfs.write('requires', requirements)
234 destvfs.write('requires', requirements)
235 destvfs.write('sharedpath', sharedpath)
235 destvfs.write('sharedpath', sharedpath)
236
236
237 r = repository(ui, destwvfs.base)
237 r = repository(ui, destwvfs.base)
238 postshare(srcrepo, r, bookmarks=bookmarks)
238 postshare(srcrepo, r, bookmarks=bookmarks)
239
239
240 if update:
240 if update:
241 r.ui.status(_("updating working directory\n"))
241 r.ui.status(_("updating working directory\n"))
242 if update is not True:
242 if update is not True:
243 checkout = update
243 checkout = update
244 for test in (checkout, 'default', 'tip'):
244 for test in (checkout, 'default', 'tip'):
245 if test is None:
245 if test is None:
246 continue
246 continue
247 try:
247 try:
248 uprev = r.lookup(test)
248 uprev = r.lookup(test)
249 break
249 break
250 except error.RepoLookupError:
250 except error.RepoLookupError:
251 continue
251 continue
252 _update(r, uprev)
252 _update(r, uprev)
253
253
254 def postshare(sourcerepo, destrepo, bookmarks=True):
254 def postshare(sourcerepo, destrepo, bookmarks=True):
255 """Called after a new shared repo is created.
255 """Called after a new shared repo is created.
256
256
257 The new repo only has a requirements file and pointer to the source.
257 The new repo only has a requirements file and pointer to the source.
258 This function configures additional shared data.
258 This function configures additional shared data.
259
259
260 Extensions can wrap this function and write additional entries to
260 Extensions can wrap this function and write additional entries to
261 destrepo/.hg/shared to indicate additional pieces of data to be shared.
261 destrepo/.hg/shared to indicate additional pieces of data to be shared.
262 """
262 """
263 default = sourcerepo.ui.config('paths', 'default')
263 default = sourcerepo.ui.config('paths', 'default')
264 if default:
264 if default:
265 fp = destrepo.vfs("hgrc", "w", text=True)
265 fp = destrepo.vfs("hgrc", "w", text=True)
266 fp.write("[paths]\n")
266 fp.write("[paths]\n")
267 fp.write("default = %s\n" % default)
267 fp.write("default = %s\n" % default)
268 fp.close()
268 fp.close()
269
269
270 if bookmarks:
270 if bookmarks:
271 fp = destrepo.vfs('shared', 'w')
271 fp = destrepo.vfs('shared', 'w')
272 fp.write('bookmarks\n')
272 fp.write('bookmarks\n')
273 fp.close()
273 fp.close()
274
274
275 def copystore(ui, srcrepo, destpath):
275 def copystore(ui, srcrepo, destpath):
276 '''copy files from store of srcrepo in destpath
276 '''copy files from store of srcrepo in destpath
277
277
278 returns destlock
278 returns destlock
279 '''
279 '''
280 destlock = None
280 destlock = None
281 try:
281 try:
282 hardlink = None
282 hardlink = None
283 num = 0
283 num = 0
284 closetopic = [None]
284 closetopic = [None]
285 def prog(topic, pos):
285 def prog(topic, pos):
286 if pos is None:
286 if pos is None:
287 closetopic[0] = topic
287 closetopic[0] = topic
288 else:
288 else:
289 ui.progress(topic, pos + num)
289 ui.progress(topic, pos + num)
290 srcpublishing = srcrepo.publishing()
290 srcpublishing = srcrepo.publishing()
291 srcvfs = scmutil.vfs(srcrepo.sharedpath)
291 srcvfs = scmutil.vfs(srcrepo.sharedpath)
292 dstvfs = scmutil.vfs(destpath)
292 dstvfs = scmutil.vfs(destpath)
293 for f in srcrepo.store.copylist():
293 for f in srcrepo.store.copylist():
294 if srcpublishing and f.endswith('phaseroots'):
294 if srcpublishing and f.endswith('phaseroots'):
295 continue
295 continue
296 dstbase = os.path.dirname(f)
296 dstbase = os.path.dirname(f)
297 if dstbase and not dstvfs.exists(dstbase):
297 if dstbase and not dstvfs.exists(dstbase):
298 dstvfs.mkdir(dstbase)
298 dstvfs.mkdir(dstbase)
299 if srcvfs.exists(f):
299 if srcvfs.exists(f):
300 if f.endswith('data'):
300 if f.endswith('data'):
301 # 'dstbase' may be empty (e.g. revlog format 0)
301 # 'dstbase' may be empty (e.g. revlog format 0)
302 lockfile = os.path.join(dstbase, "lock")
302 lockfile = os.path.join(dstbase, "lock")
303 # lock to avoid premature writing to the target
303 # lock to avoid premature writing to the target
304 destlock = lock.lock(dstvfs, lockfile)
304 destlock = lock.lock(dstvfs, lockfile)
305 hardlink, n = util.copyfiles(srcvfs.join(f), dstvfs.join(f),
305 hardlink, n = util.copyfiles(srcvfs.join(f), dstvfs.join(f),
306 hardlink, progress=prog)
306 hardlink, progress=prog)
307 num += n
307 num += n
308 if hardlink:
308 if hardlink:
309 ui.debug("linked %d files\n" % num)
309 ui.debug("linked %d files\n" % num)
310 if closetopic[0]:
310 if closetopic[0]:
311 ui.progress(closetopic[0], None)
311 ui.progress(closetopic[0], None)
312 else:
312 else:
313 ui.debug("copied %d files\n" % num)
313 ui.debug("copied %d files\n" % num)
314 if closetopic[0]:
314 if closetopic[0]:
315 ui.progress(closetopic[0], None)
315 ui.progress(closetopic[0], None)
316 return destlock
316 return destlock
317 except: # re-raises
317 except: # re-raises
318 release(destlock)
318 release(destlock)
319 raise
319 raise
320
320
321 def clonewithshare(ui, peeropts, sharepath, source, srcpeer, dest, pull=False,
321 def clonewithshare(ui, peeropts, sharepath, source, srcpeer, dest, pull=False,
322 rev=None, update=True, stream=False):
322 rev=None, update=True, stream=False):
323 """Perform a clone using a shared repo.
323 """Perform a clone using a shared repo.
324
324
325 The store for the repository will be located at <sharepath>/.hg. The
325 The store for the repository will be located at <sharepath>/.hg. The
326 specified revisions will be cloned or pulled from "source". A shared repo
326 specified revisions will be cloned or pulled from "source". A shared repo
327 will be created at "dest" and a working copy will be created if "update" is
327 will be created at "dest" and a working copy will be created if "update" is
328 True.
328 True.
329 """
329 """
330 revs = None
330 revs = None
331 if rev:
331 if rev:
332 if not srcpeer.capable('lookup'):
332 if not srcpeer.capable('lookup'):
333 raise error.Abort(_("src repository does not support "
333 raise error.Abort(_("src repository does not support "
334 "revision lookup and so doesn't "
334 "revision lookup and so doesn't "
335 "support clone by revision"))
335 "support clone by revision"))
336 revs = [srcpeer.lookup(r) for r in rev]
336 revs = [srcpeer.lookup(r) for r in rev]
337
337
338 # Obtain a lock before checking for or cloning the pooled repo otherwise
339 # 2 clients may race creating or populating it.
340 pooldir = os.path.dirname(sharepath)
341 # lock class requires the directory to exist.
342 try:
343 util.makedir(pooldir, False)
344 except OSError as e:
345 if e.errno != errno.EEXIST:
346 raise
347
348 poolvfs = scmutil.vfs(pooldir)
338 basename = os.path.basename(sharepath)
349 basename = os.path.basename(sharepath)
339
350
340 if os.path.exists(sharepath):
351 with lock.lock(poolvfs, '%s.lock' % basename):
341 ui.status(_('(sharing from existing pooled repository %s)\n') %
352 if os.path.exists(sharepath):
342 basename)
353 ui.status(_('(sharing from existing pooled repository %s)\n') %
343 else:
354 basename)
344 ui.status(_('(sharing from new pooled repository %s)\n') % basename)
355 else:
345 # Always use pull mode because hardlinks in share mode don't work well.
356 ui.status(_('(sharing from new pooled repository %s)\n') % basename)
346 # Never update because working copies aren't necessary in share mode.
357 # Always use pull mode because hardlinks in share mode don't work
347 clone(ui, peeropts, source, dest=sharepath, pull=True,
358 # well. Never update because working copies aren't necessary in
348 rev=rev, update=False, stream=stream)
359 # share mode.
360 clone(ui, peeropts, source, dest=sharepath, pull=True,
361 rev=rev, update=False, stream=stream)
349
362
350 sharerepo = repository(ui, path=sharepath)
363 sharerepo = repository(ui, path=sharepath)
351 share(ui, sharerepo, dest=dest, update=update, bookmarks=False)
364 share(ui, sharerepo, dest=dest, update=update, bookmarks=False)
352
365
353 # We need to perform a pull against the dest repo to fetch bookmarks
366 # We need to perform a pull against the dest repo to fetch bookmarks
354 # and other non-store data that isn't shared by default. In the case of
367 # and other non-store data that isn't shared by default. In the case of
355 # non-existing shared repo, this means we pull from the remote twice. This
368 # non-existing shared repo, this means we pull from the remote twice. This
356 # is a bit weird. But at the time it was implemented, there wasn't an easy
369 # is a bit weird. But at the time it was implemented, there wasn't an easy
357 # way to pull just non-changegroup data.
370 # way to pull just non-changegroup data.
358 destrepo = repository(ui, path=dest)
371 destrepo = repository(ui, path=dest)
359 exchange.pull(destrepo, srcpeer, heads=revs)
372 exchange.pull(destrepo, srcpeer, heads=revs)
360
373
361 return srcpeer, peer(ui, peeropts, dest)
374 return srcpeer, peer(ui, peeropts, dest)
362
375
363 def clone(ui, peeropts, source, dest=None, pull=False, rev=None,
376 def clone(ui, peeropts, source, dest=None, pull=False, rev=None,
364 update=True, stream=False, branch=None, shareopts=None):
377 update=True, stream=False, branch=None, shareopts=None):
365 """Make a copy of an existing repository.
378 """Make a copy of an existing repository.
366
379
367 Create a copy of an existing repository in a new directory. The
380 Create a copy of an existing repository in a new directory. The
368 source and destination are URLs, as passed to the repository
381 source and destination are URLs, as passed to the repository
369 function. Returns a pair of repository peers, the source and
382 function. Returns a pair of repository peers, the source and
370 newly created destination.
383 newly created destination.
371
384
372 The location of the source is added to the new repository's
385 The location of the source is added to the new repository's
373 .hg/hgrc file, as the default to be used for future pulls and
386 .hg/hgrc file, as the default to be used for future pulls and
374 pushes.
387 pushes.
375
388
376 If an exception is raised, the partly cloned/updated destination
389 If an exception is raised, the partly cloned/updated destination
377 repository will be deleted.
390 repository will be deleted.
378
391
379 Arguments:
392 Arguments:
380
393
381 source: repository object or URL
394 source: repository object or URL
382
395
383 dest: URL of destination repository to create (defaults to base
396 dest: URL of destination repository to create (defaults to base
384 name of source repository)
397 name of source repository)
385
398
386 pull: always pull from source repository, even in local case or if the
399 pull: always pull from source repository, even in local case or if the
387 server prefers streaming
400 server prefers streaming
388
401
389 stream: stream raw data uncompressed from repository (fast over
402 stream: stream raw data uncompressed from repository (fast over
390 LAN, slow over WAN)
403 LAN, slow over WAN)
391
404
392 rev: revision to clone up to (implies pull=True)
405 rev: revision to clone up to (implies pull=True)
393
406
394 update: update working directory after clone completes, if
407 update: update working directory after clone completes, if
395 destination is local repository (True means update to default rev,
408 destination is local repository (True means update to default rev,
396 anything else is treated as a revision)
409 anything else is treated as a revision)
397
410
398 branch: branches to clone
411 branch: branches to clone
399
412
400 shareopts: dict of options to control auto sharing behavior. The "pool" key
413 shareopts: dict of options to control auto sharing behavior. The "pool" key
401 activates auto sharing mode and defines the directory for stores. The
414 activates auto sharing mode and defines the directory for stores. The
402 "mode" key determines how to construct the directory name of the shared
415 "mode" key determines how to construct the directory name of the shared
403 repository. "identity" means the name is derived from the node of the first
416 repository. "identity" means the name is derived from the node of the first
404 changeset in the repository. "remote" means the name is derived from the
417 changeset in the repository. "remote" means the name is derived from the
405 remote's path/URL. Defaults to "identity."
418 remote's path/URL. Defaults to "identity."
406 """
419 """
407
420
408 if isinstance(source, str):
421 if isinstance(source, str):
409 origsource = ui.expandpath(source)
422 origsource = ui.expandpath(source)
410 source, branch = parseurl(origsource, branch)
423 source, branch = parseurl(origsource, branch)
411 srcpeer = peer(ui, peeropts, source)
424 srcpeer = peer(ui, peeropts, source)
412 else:
425 else:
413 srcpeer = source.peer() # in case we were called with a localrepo
426 srcpeer = source.peer() # in case we were called with a localrepo
414 branch = (None, branch or [])
427 branch = (None, branch or [])
415 origsource = source = srcpeer.url()
428 origsource = source = srcpeer.url()
416 rev, checkout = addbranchrevs(srcpeer, srcpeer, branch, rev)
429 rev, checkout = addbranchrevs(srcpeer, srcpeer, branch, rev)
417
430
418 if dest is None:
431 if dest is None:
419 dest = defaultdest(source)
432 dest = defaultdest(source)
420 if dest:
433 if dest:
421 ui.status(_("destination directory: %s\n") % dest)
434 ui.status(_("destination directory: %s\n") % dest)
422 else:
435 else:
423 dest = ui.expandpath(dest)
436 dest = ui.expandpath(dest)
424
437
425 dest = util.urllocalpath(dest)
438 dest = util.urllocalpath(dest)
426 source = util.urllocalpath(source)
439 source = util.urllocalpath(source)
427
440
428 if not dest:
441 if not dest:
429 raise error.Abort(_("empty destination path is not valid"))
442 raise error.Abort(_("empty destination path is not valid"))
430
443
431 destvfs = scmutil.vfs(dest, expandpath=True)
444 destvfs = scmutil.vfs(dest, expandpath=True)
432 if destvfs.lexists():
445 if destvfs.lexists():
433 if not destvfs.isdir():
446 if not destvfs.isdir():
434 raise error.Abort(_("destination '%s' already exists") % dest)
447 raise error.Abort(_("destination '%s' already exists") % dest)
435 elif destvfs.listdir():
448 elif destvfs.listdir():
436 raise error.Abort(_("destination '%s' is not empty") % dest)
449 raise error.Abort(_("destination '%s' is not empty") % dest)
437
450
438 shareopts = shareopts or {}
451 shareopts = shareopts or {}
439 sharepool = shareopts.get('pool')
452 sharepool = shareopts.get('pool')
440 sharenamemode = shareopts.get('mode')
453 sharenamemode = shareopts.get('mode')
441 if sharepool and islocal(dest):
454 if sharepool and islocal(dest):
442 sharepath = None
455 sharepath = None
443 if sharenamemode == 'identity':
456 if sharenamemode == 'identity':
444 # Resolve the name from the initial changeset in the remote
457 # Resolve the name from the initial changeset in the remote
445 # repository. This returns nullid when the remote is empty. It
458 # repository. This returns nullid when the remote is empty. It
446 # raises RepoLookupError if revision 0 is filtered or otherwise
459 # raises RepoLookupError if revision 0 is filtered or otherwise
447 # not available. If we fail to resolve, sharing is not enabled.
460 # not available. If we fail to resolve, sharing is not enabled.
448 try:
461 try:
449 rootnode = srcpeer.lookup('0')
462 rootnode = srcpeer.lookup('0')
450 if rootnode != node.nullid:
463 if rootnode != node.nullid:
451 sharepath = os.path.join(sharepool, node.hex(rootnode))
464 sharepath = os.path.join(sharepool, node.hex(rootnode))
452 else:
465 else:
453 ui.status(_('(not using pooled storage: '
466 ui.status(_('(not using pooled storage: '
454 'remote appears to be empty)\n'))
467 'remote appears to be empty)\n'))
455 except error.RepoLookupError:
468 except error.RepoLookupError:
456 ui.status(_('(not using pooled storage: '
469 ui.status(_('(not using pooled storage: '
457 'unable to resolve identity of remote)\n'))
470 'unable to resolve identity of remote)\n'))
458 elif sharenamemode == 'remote':
471 elif sharenamemode == 'remote':
459 sharepath = os.path.join(sharepool, util.sha1(source).hexdigest())
472 sharepath = os.path.join(sharepool, util.sha1(source).hexdigest())
460 else:
473 else:
461 raise error.Abort('unknown share naming mode: %s' % sharenamemode)
474 raise error.Abort('unknown share naming mode: %s' % sharenamemode)
462
475
463 if sharepath:
476 if sharepath:
464 return clonewithshare(ui, peeropts, sharepath, source, srcpeer,
477 return clonewithshare(ui, peeropts, sharepath, source, srcpeer,
465 dest, pull=pull, rev=rev, update=update,
478 dest, pull=pull, rev=rev, update=update,
466 stream=stream)
479 stream=stream)
467
480
468 srclock = destlock = cleandir = None
481 srclock = destlock = cleandir = None
469 srcrepo = srcpeer.local()
482 srcrepo = srcpeer.local()
470 try:
483 try:
471 abspath = origsource
484 abspath = origsource
472 if islocal(origsource):
485 if islocal(origsource):
473 abspath = os.path.abspath(util.urllocalpath(origsource))
486 abspath = os.path.abspath(util.urllocalpath(origsource))
474
487
475 if islocal(dest):
488 if islocal(dest):
476 cleandir = dest
489 cleandir = dest
477
490
478 copy = False
491 copy = False
479 if (srcrepo and srcrepo.cancopy() and islocal(dest)
492 if (srcrepo and srcrepo.cancopy() and islocal(dest)
480 and not phases.hassecret(srcrepo)):
493 and not phases.hassecret(srcrepo)):
481 copy = not pull and not rev
494 copy = not pull and not rev
482
495
483 if copy:
496 if copy:
484 try:
497 try:
485 # we use a lock here because if we race with commit, we
498 # we use a lock here because if we race with commit, we
486 # can end up with extra data in the cloned revlogs that's
499 # can end up with extra data in the cloned revlogs that's
487 # not pointed to by changesets, thus causing verify to
500 # not pointed to by changesets, thus causing verify to
488 # fail
501 # fail
489 srclock = srcrepo.lock(wait=False)
502 srclock = srcrepo.lock(wait=False)
490 except error.LockError:
503 except error.LockError:
491 copy = False
504 copy = False
492
505
493 if copy:
506 if copy:
494 srcrepo.hook('preoutgoing', throw=True, source='clone')
507 srcrepo.hook('preoutgoing', throw=True, source='clone')
495 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
508 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
496 if not os.path.exists(dest):
509 if not os.path.exists(dest):
497 os.mkdir(dest)
510 os.mkdir(dest)
498 else:
511 else:
499 # only clean up directories we create ourselves
512 # only clean up directories we create ourselves
500 cleandir = hgdir
513 cleandir = hgdir
501 try:
514 try:
502 destpath = hgdir
515 destpath = hgdir
503 util.makedir(destpath, notindexed=True)
516 util.makedir(destpath, notindexed=True)
504 except OSError as inst:
517 except OSError as inst:
505 if inst.errno == errno.EEXIST:
518 if inst.errno == errno.EEXIST:
506 cleandir = None
519 cleandir = None
507 raise error.Abort(_("destination '%s' already exists")
520 raise error.Abort(_("destination '%s' already exists")
508 % dest)
521 % dest)
509 raise
522 raise
510
523
511 destlock = copystore(ui, srcrepo, destpath)
524 destlock = copystore(ui, srcrepo, destpath)
512 # copy bookmarks over
525 # copy bookmarks over
513 srcbookmarks = srcrepo.join('bookmarks')
526 srcbookmarks = srcrepo.join('bookmarks')
514 dstbookmarks = os.path.join(destpath, 'bookmarks')
527 dstbookmarks = os.path.join(destpath, 'bookmarks')
515 if os.path.exists(srcbookmarks):
528 if os.path.exists(srcbookmarks):
516 util.copyfile(srcbookmarks, dstbookmarks)
529 util.copyfile(srcbookmarks, dstbookmarks)
517
530
518 # Recomputing branch cache might be slow on big repos,
531 # Recomputing branch cache might be slow on big repos,
519 # so just copy it
532 # so just copy it
520 def copybranchcache(fname):
533 def copybranchcache(fname):
521 srcbranchcache = srcrepo.join('cache/%s' % fname)
534 srcbranchcache = srcrepo.join('cache/%s' % fname)
522 dstbranchcache = os.path.join(dstcachedir, fname)
535 dstbranchcache = os.path.join(dstcachedir, fname)
523 if os.path.exists(srcbranchcache):
536 if os.path.exists(srcbranchcache):
524 if not os.path.exists(dstcachedir):
537 if not os.path.exists(dstcachedir):
525 os.mkdir(dstcachedir)
538 os.mkdir(dstcachedir)
526 util.copyfile(srcbranchcache, dstbranchcache)
539 util.copyfile(srcbranchcache, dstbranchcache)
527
540
528 dstcachedir = os.path.join(destpath, 'cache')
541 dstcachedir = os.path.join(destpath, 'cache')
529 # In local clones we're copying all nodes, not just served
542 # In local clones we're copying all nodes, not just served
530 # ones. Therefore copy all branch caches over.
543 # ones. Therefore copy all branch caches over.
531 copybranchcache('branch2')
544 copybranchcache('branch2')
532 for cachename in repoview.filtertable:
545 for cachename in repoview.filtertable:
533 copybranchcache('branch2-%s' % cachename)
546 copybranchcache('branch2-%s' % cachename)
534
547
535 # we need to re-init the repo after manually copying the data
548 # we need to re-init the repo after manually copying the data
536 # into it
549 # into it
537 destpeer = peer(srcrepo, peeropts, dest)
550 destpeer = peer(srcrepo, peeropts, dest)
538 srcrepo.hook('outgoing', source='clone',
551 srcrepo.hook('outgoing', source='clone',
539 node=node.hex(node.nullid))
552 node=node.hex(node.nullid))
540 else:
553 else:
541 try:
554 try:
542 destpeer = peer(srcrepo or ui, peeropts, dest, create=True)
555 destpeer = peer(srcrepo or ui, peeropts, dest, create=True)
543 # only pass ui when no srcrepo
556 # only pass ui when no srcrepo
544 except OSError as inst:
557 except OSError as inst:
545 if inst.errno == errno.EEXIST:
558 if inst.errno == errno.EEXIST:
546 cleandir = None
559 cleandir = None
547 raise error.Abort(_("destination '%s' already exists")
560 raise error.Abort(_("destination '%s' already exists")
548 % dest)
561 % dest)
549 raise
562 raise
550
563
551 revs = None
564 revs = None
552 if rev:
565 if rev:
553 if not srcpeer.capable('lookup'):
566 if not srcpeer.capable('lookup'):
554 raise error.Abort(_("src repository does not support "
567 raise error.Abort(_("src repository does not support "
555 "revision lookup and so doesn't "
568 "revision lookup and so doesn't "
556 "support clone by revision"))
569 "support clone by revision"))
557 revs = [srcpeer.lookup(r) for r in rev]
570 revs = [srcpeer.lookup(r) for r in rev]
558 checkout = revs[0]
571 checkout = revs[0]
559 local = destpeer.local()
572 local = destpeer.local()
560 if local:
573 if local:
561 if not stream:
574 if not stream:
562 if pull:
575 if pull:
563 stream = False
576 stream = False
564 else:
577 else:
565 stream = None
578 stream = None
566 # internal config: ui.quietbookmarkmove
579 # internal config: ui.quietbookmarkmove
567 quiet = local.ui.backupconfig('ui', 'quietbookmarkmove')
580 quiet = local.ui.backupconfig('ui', 'quietbookmarkmove')
568 try:
581 try:
569 local.ui.setconfig(
582 local.ui.setconfig(
570 'ui', 'quietbookmarkmove', True, 'clone')
583 'ui', 'quietbookmarkmove', True, 'clone')
571 exchange.pull(local, srcpeer, revs,
584 exchange.pull(local, srcpeer, revs,
572 streamclonerequested=stream)
585 streamclonerequested=stream)
573 finally:
586 finally:
574 local.ui.restoreconfig(quiet)
587 local.ui.restoreconfig(quiet)
575 elif srcrepo:
588 elif srcrepo:
576 exchange.push(srcrepo, destpeer, revs=revs,
589 exchange.push(srcrepo, destpeer, revs=revs,
577 bookmarks=srcrepo._bookmarks.keys())
590 bookmarks=srcrepo._bookmarks.keys())
578 else:
591 else:
579 raise error.Abort(_("clone from remote to remote not supported")
592 raise error.Abort(_("clone from remote to remote not supported")
580 )
593 )
581
594
582 cleandir = None
595 cleandir = None
583
596
584 destrepo = destpeer.local()
597 destrepo = destpeer.local()
585 if destrepo:
598 if destrepo:
586 template = uimod.samplehgrcs['cloned']
599 template = uimod.samplehgrcs['cloned']
587 fp = destrepo.vfs("hgrc", "w", text=True)
600 fp = destrepo.vfs("hgrc", "w", text=True)
588 u = util.url(abspath)
601 u = util.url(abspath)
589 u.passwd = None
602 u.passwd = None
590 defaulturl = str(u)
603 defaulturl = str(u)
591 fp.write(template % defaulturl)
604 fp.write(template % defaulturl)
592 fp.close()
605 fp.close()
593
606
594 destrepo.ui.setconfig('paths', 'default', defaulturl, 'clone')
607 destrepo.ui.setconfig('paths', 'default', defaulturl, 'clone')
595
608
596 if update:
609 if update:
597 if update is not True:
610 if update is not True:
598 checkout = srcpeer.lookup(update)
611 checkout = srcpeer.lookup(update)
599 uprev = None
612 uprev = None
600 status = None
613 status = None
601 if checkout is not None:
614 if checkout is not None:
602 try:
615 try:
603 uprev = destrepo.lookup(checkout)
616 uprev = destrepo.lookup(checkout)
604 except error.RepoLookupError:
617 except error.RepoLookupError:
605 if update is not True:
618 if update is not True:
606 try:
619 try:
607 uprev = destrepo.lookup(update)
620 uprev = destrepo.lookup(update)
608 except error.RepoLookupError:
621 except error.RepoLookupError:
609 pass
622 pass
610 if uprev is None:
623 if uprev is None:
611 try:
624 try:
612 uprev = destrepo._bookmarks['@']
625 uprev = destrepo._bookmarks['@']
613 update = '@'
626 update = '@'
614 bn = destrepo[uprev].branch()
627 bn = destrepo[uprev].branch()
615 if bn == 'default':
628 if bn == 'default':
616 status = _("updating to bookmark @\n")
629 status = _("updating to bookmark @\n")
617 else:
630 else:
618 status = (_("updating to bookmark @ on branch %s\n")
631 status = (_("updating to bookmark @ on branch %s\n")
619 % bn)
632 % bn)
620 except KeyError:
633 except KeyError:
621 try:
634 try:
622 uprev = destrepo.branchtip('default')
635 uprev = destrepo.branchtip('default')
623 except error.RepoLookupError:
636 except error.RepoLookupError:
624 uprev = destrepo.lookup('tip')
637 uprev = destrepo.lookup('tip')
625 if not status:
638 if not status:
626 bn = destrepo[uprev].branch()
639 bn = destrepo[uprev].branch()
627 status = _("updating to branch %s\n") % bn
640 status = _("updating to branch %s\n") % bn
628 destrepo.ui.status(status)
641 destrepo.ui.status(status)
629 _update(destrepo, uprev)
642 _update(destrepo, uprev)
630 if update in destrepo._bookmarks:
643 if update in destrepo._bookmarks:
631 bookmarks.activate(destrepo, update)
644 bookmarks.activate(destrepo, update)
632 finally:
645 finally:
633 release(srclock, destlock)
646 release(srclock, destlock)
634 if cleandir is not None:
647 if cleandir is not None:
635 shutil.rmtree(cleandir, True)
648 shutil.rmtree(cleandir, True)
636 if srcpeer is not None:
649 if srcpeer is not None:
637 srcpeer.close()
650 srcpeer.close()
638 return srcpeer, destpeer
651 return srcpeer, destpeer
639
652
640 def _showstats(repo, stats, quietempty=False):
653 def _showstats(repo, stats, quietempty=False):
641 if quietempty and not any(stats):
654 if quietempty and not any(stats):
642 return
655 return
643 repo.ui.status(_("%d files updated, %d files merged, "
656 repo.ui.status(_("%d files updated, %d files merged, "
644 "%d files removed, %d files unresolved\n") % stats)
657 "%d files removed, %d files unresolved\n") % stats)
645
658
646 def updaterepo(repo, node, overwrite):
659 def updaterepo(repo, node, overwrite):
647 """Update the working directory to node.
660 """Update the working directory to node.
648
661
649 When overwrite is set, changes are clobbered, merged else
662 When overwrite is set, changes are clobbered, merged else
650
663
651 returns stats (see pydoc mercurial.merge.applyupdates)"""
664 returns stats (see pydoc mercurial.merge.applyupdates)"""
652 return mergemod.update(repo, node, False, overwrite,
665 return mergemod.update(repo, node, False, overwrite,
653 labels=['working copy', 'destination'])
666 labels=['working copy', 'destination'])
654
667
655 def update(repo, node, quietempty=False):
668 def update(repo, node, quietempty=False):
656 """update the working directory to node, merging linear changes"""
669 """update the working directory to node, merging linear changes"""
657 stats = updaterepo(repo, node, False)
670 stats = updaterepo(repo, node, False)
658 _showstats(repo, stats, quietempty)
671 _showstats(repo, stats, quietempty)
659 if stats[3]:
672 if stats[3]:
660 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
673 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
661 return stats[3] > 0
674 return stats[3] > 0
662
675
663 # naming conflict in clone()
676 # naming conflict in clone()
664 _update = update
677 _update = update
665
678
666 def clean(repo, node, show_stats=True, quietempty=False):
679 def clean(repo, node, show_stats=True, quietempty=False):
667 """forcibly switch the working directory to node, clobbering changes"""
680 """forcibly switch the working directory to node, clobbering changes"""
668 stats = updaterepo(repo, node, True)
681 stats = updaterepo(repo, node, True)
669 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
682 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
670 if show_stats:
683 if show_stats:
671 _showstats(repo, stats, quietempty)
684 _showstats(repo, stats, quietempty)
672 return stats[3] > 0
685 return stats[3] > 0
673
686
674 def merge(repo, node, force=None, remind=True):
687 def merge(repo, node, force=None, remind=True):
675 """Branch merge with node, resolving changes. Return true if any
688 """Branch merge with node, resolving changes. Return true if any
676 unresolved conflicts."""
689 unresolved conflicts."""
677 stats = mergemod.update(repo, node, True, force)
690 stats = mergemod.update(repo, node, True, force)
678 _showstats(repo, stats)
691 _showstats(repo, stats)
679 if stats[3]:
692 if stats[3]:
680 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
693 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
681 "or 'hg update -C .' to abandon\n"))
694 "or 'hg update -C .' to abandon\n"))
682 elif remind:
695 elif remind:
683 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
696 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
684 return stats[3] > 0
697 return stats[3] > 0
685
698
686 def _incoming(displaychlist, subreporecurse, ui, repo, source,
699 def _incoming(displaychlist, subreporecurse, ui, repo, source,
687 opts, buffered=False):
700 opts, buffered=False):
688 """
701 """
689 Helper for incoming / gincoming.
702 Helper for incoming / gincoming.
690 displaychlist gets called with
703 displaychlist gets called with
691 (remoterepo, incomingchangesetlist, displayer) parameters,
704 (remoterepo, incomingchangesetlist, displayer) parameters,
692 and is supposed to contain only code that can't be unified.
705 and is supposed to contain only code that can't be unified.
693 """
706 """
694 source, branches = parseurl(ui.expandpath(source), opts.get('branch'))
707 source, branches = parseurl(ui.expandpath(source), opts.get('branch'))
695 other = peer(repo, opts, source)
708 other = peer(repo, opts, source)
696 ui.status(_('comparing with %s\n') % util.hidepassword(source))
709 ui.status(_('comparing with %s\n') % util.hidepassword(source))
697 revs, checkout = addbranchrevs(repo, other, branches, opts.get('rev'))
710 revs, checkout = addbranchrevs(repo, other, branches, opts.get('rev'))
698
711
699 if revs:
712 if revs:
700 revs = [other.lookup(rev) for rev in revs]
713 revs = [other.lookup(rev) for rev in revs]
701 other, chlist, cleanupfn = bundlerepo.getremotechanges(ui, repo, other,
714 other, chlist, cleanupfn = bundlerepo.getremotechanges(ui, repo, other,
702 revs, opts["bundle"], opts["force"])
715 revs, opts["bundle"], opts["force"])
703 try:
716 try:
704 if not chlist:
717 if not chlist:
705 ui.status(_("no changes found\n"))
718 ui.status(_("no changes found\n"))
706 return subreporecurse()
719 return subreporecurse()
707
720
708 displayer = cmdutil.show_changeset(ui, other, opts, buffered)
721 displayer = cmdutil.show_changeset(ui, other, opts, buffered)
709 displaychlist(other, chlist, displayer)
722 displaychlist(other, chlist, displayer)
710 displayer.close()
723 displayer.close()
711 finally:
724 finally:
712 cleanupfn()
725 cleanupfn()
713 subreporecurse()
726 subreporecurse()
714 return 0 # exit code is zero since we found incoming changes
727 return 0 # exit code is zero since we found incoming changes
715
728
716 def incoming(ui, repo, source, opts):
729 def incoming(ui, repo, source, opts):
717 def subreporecurse():
730 def subreporecurse():
718 ret = 1
731 ret = 1
719 if opts.get('subrepos'):
732 if opts.get('subrepos'):
720 ctx = repo[None]
733 ctx = repo[None]
721 for subpath in sorted(ctx.substate):
734 for subpath in sorted(ctx.substate):
722 sub = ctx.sub(subpath)
735 sub = ctx.sub(subpath)
723 ret = min(ret, sub.incoming(ui, source, opts))
736 ret = min(ret, sub.incoming(ui, source, opts))
724 return ret
737 return ret
725
738
726 def display(other, chlist, displayer):
739 def display(other, chlist, displayer):
727 limit = cmdutil.loglimit(opts)
740 limit = cmdutil.loglimit(opts)
728 if opts.get('newest_first'):
741 if opts.get('newest_first'):
729 chlist.reverse()
742 chlist.reverse()
730 count = 0
743 count = 0
731 for n in chlist:
744 for n in chlist:
732 if limit is not None and count >= limit:
745 if limit is not None and count >= limit:
733 break
746 break
734 parents = [p for p in other.changelog.parents(n) if p != nullid]
747 parents = [p for p in other.changelog.parents(n) if p != nullid]
735 if opts.get('no_merges') and len(parents) == 2:
748 if opts.get('no_merges') and len(parents) == 2:
736 continue
749 continue
737 count += 1
750 count += 1
738 displayer.show(other[n])
751 displayer.show(other[n])
739 return _incoming(display, subreporecurse, ui, repo, source, opts)
752 return _incoming(display, subreporecurse, ui, repo, source, opts)
740
753
741 def _outgoing(ui, repo, dest, opts):
754 def _outgoing(ui, repo, dest, opts):
742 dest = ui.expandpath(dest or 'default-push', dest or 'default')
755 dest = ui.expandpath(dest or 'default-push', dest or 'default')
743 dest, branches = parseurl(dest, opts.get('branch'))
756 dest, branches = parseurl(dest, opts.get('branch'))
744 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
757 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
745 revs, checkout = addbranchrevs(repo, repo, branches, opts.get('rev'))
758 revs, checkout = addbranchrevs(repo, repo, branches, opts.get('rev'))
746 if revs:
759 if revs:
747 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
760 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
748
761
749 other = peer(repo, opts, dest)
762 other = peer(repo, opts, dest)
750 outgoing = discovery.findcommonoutgoing(repo.unfiltered(), other, revs,
763 outgoing = discovery.findcommonoutgoing(repo.unfiltered(), other, revs,
751 force=opts.get('force'))
764 force=opts.get('force'))
752 o = outgoing.missing
765 o = outgoing.missing
753 if not o:
766 if not o:
754 scmutil.nochangesfound(repo.ui, repo, outgoing.excluded)
767 scmutil.nochangesfound(repo.ui, repo, outgoing.excluded)
755 return o, other
768 return o, other
756
769
757 def outgoing(ui, repo, dest, opts):
770 def outgoing(ui, repo, dest, opts):
758 def recurse():
771 def recurse():
759 ret = 1
772 ret = 1
760 if opts.get('subrepos'):
773 if opts.get('subrepos'):
761 ctx = repo[None]
774 ctx = repo[None]
762 for subpath in sorted(ctx.substate):
775 for subpath in sorted(ctx.substate):
763 sub = ctx.sub(subpath)
776 sub = ctx.sub(subpath)
764 ret = min(ret, sub.outgoing(ui, dest, opts))
777 ret = min(ret, sub.outgoing(ui, dest, opts))
765 return ret
778 return ret
766
779
767 limit = cmdutil.loglimit(opts)
780 limit = cmdutil.loglimit(opts)
768 o, other = _outgoing(ui, repo, dest, opts)
781 o, other = _outgoing(ui, repo, dest, opts)
769 if not o:
782 if not o:
770 cmdutil.outgoinghooks(ui, repo, other, opts, o)
783 cmdutil.outgoinghooks(ui, repo, other, opts, o)
771 return recurse()
784 return recurse()
772
785
773 if opts.get('newest_first'):
786 if opts.get('newest_first'):
774 o.reverse()
787 o.reverse()
775 displayer = cmdutil.show_changeset(ui, repo, opts)
788 displayer = cmdutil.show_changeset(ui, repo, opts)
776 count = 0
789 count = 0
777 for n in o:
790 for n in o:
778 if limit is not None and count >= limit:
791 if limit is not None and count >= limit:
779 break
792 break
780 parents = [p for p in repo.changelog.parents(n) if p != nullid]
793 parents = [p for p in repo.changelog.parents(n) if p != nullid]
781 if opts.get('no_merges') and len(parents) == 2:
794 if opts.get('no_merges') and len(parents) == 2:
782 continue
795 continue
783 count += 1
796 count += 1
784 displayer.show(repo[n])
797 displayer.show(repo[n])
785 displayer.close()
798 displayer.close()
786 cmdutil.outgoinghooks(ui, repo, other, opts, o)
799 cmdutil.outgoinghooks(ui, repo, other, opts, o)
787 recurse()
800 recurse()
788 return 0 # exit code is zero since we found outgoing changes
801 return 0 # exit code is zero since we found outgoing changes
789
802
790 def verify(repo):
803 def verify(repo):
791 """verify the consistency of a repository"""
804 """verify the consistency of a repository"""
792 ret = verifymod.verify(repo)
805 ret = verifymod.verify(repo)
793
806
794 # Broken subrepo references in hidden csets don't seem worth worrying about,
807 # Broken subrepo references in hidden csets don't seem worth worrying about,
795 # since they can't be pushed/pulled, and --hidden can be used if they are a
808 # since they can't be pushed/pulled, and --hidden can be used if they are a
796 # concern.
809 # concern.
797
810
798 # pathto() is needed for -R case
811 # pathto() is needed for -R case
799 revs = repo.revs("filelog(%s)",
812 revs = repo.revs("filelog(%s)",
800 util.pathto(repo.root, repo.getcwd(), '.hgsubstate'))
813 util.pathto(repo.root, repo.getcwd(), '.hgsubstate'))
801
814
802 if revs:
815 if revs:
803 repo.ui.status(_('checking subrepo links\n'))
816 repo.ui.status(_('checking subrepo links\n'))
804 for rev in revs:
817 for rev in revs:
805 ctx = repo[rev]
818 ctx = repo[rev]
806 try:
819 try:
807 for subpath in ctx.substate:
820 for subpath in ctx.substate:
808 ret = ctx.sub(subpath).verify() or ret
821 ret = ctx.sub(subpath).verify() or ret
809 except Exception:
822 except Exception:
810 repo.ui.warn(_('.hgsubstate is corrupt in revision %s\n') %
823 repo.ui.warn(_('.hgsubstate is corrupt in revision %s\n') %
811 node.short(ctx.node()))
824 node.short(ctx.node()))
812
825
813 return ret
826 return ret
814
827
815 def remoteui(src, opts):
828 def remoteui(src, opts):
816 'build a remote ui from ui or repo and opts'
829 'build a remote ui from ui or repo and opts'
817 if util.safehasattr(src, 'baseui'): # looks like a repository
830 if util.safehasattr(src, 'baseui'): # looks like a repository
818 dst = src.baseui.copy() # drop repo-specific config
831 dst = src.baseui.copy() # drop repo-specific config
819 src = src.ui # copy target options from repo
832 src = src.ui # copy target options from repo
820 else: # assume it's a global ui object
833 else: # assume it's a global ui object
821 dst = src.copy() # keep all global options
834 dst = src.copy() # keep all global options
822
835
823 # copy ssh-specific options
836 # copy ssh-specific options
824 for o in 'ssh', 'remotecmd':
837 for o in 'ssh', 'remotecmd':
825 v = opts.get(o) or src.config('ui', o)
838 v = opts.get(o) or src.config('ui', o)
826 if v:
839 if v:
827 dst.setconfig("ui", o, v, 'copied')
840 dst.setconfig("ui", o, v, 'copied')
828
841
829 # copy bundle-specific options
842 # copy bundle-specific options
830 r = src.config('bundle', 'mainreporoot')
843 r = src.config('bundle', 'mainreporoot')
831 if r:
844 if r:
832 dst.setconfig('bundle', 'mainreporoot', r, 'copied')
845 dst.setconfig('bundle', 'mainreporoot', r, 'copied')
833
846
834 # copy selected local settings to the remote ui
847 # copy selected local settings to the remote ui
835 for sect in ('auth', 'hostfingerprints', 'http_proxy'):
848 for sect in ('auth', 'hostfingerprints', 'http_proxy'):
836 for key, val in src.configitems(sect):
849 for key, val in src.configitems(sect):
837 dst.setconfig(sect, key, val, 'copied')
850 dst.setconfig(sect, key, val, 'copied')
838 v = src.config('web', 'cacerts')
851 v = src.config('web', 'cacerts')
839 if v == '!':
852 if v == '!':
840 dst.setconfig('web', 'cacerts', v, 'copied')
853 dst.setconfig('web', 'cacerts', v, 'copied')
841 elif v:
854 elif v:
842 dst.setconfig('web', 'cacerts', util.expandpath(v), 'copied')
855 dst.setconfig('web', 'cacerts', util.expandpath(v), 'copied')
843
856
844 return dst
857 return dst
845
858
846 # Files of interest
859 # Files of interest
847 # Used to check if the repository has changed looking at mtime and size of
860 # Used to check if the repository has changed looking at mtime and size of
848 # these files.
861 # these files.
849 foi = [('spath', '00changelog.i'),
862 foi = [('spath', '00changelog.i'),
850 ('spath', 'phaseroots'), # ! phase can change content at the same size
863 ('spath', 'phaseroots'), # ! phase can change content at the same size
851 ('spath', 'obsstore'),
864 ('spath', 'obsstore'),
852 ('path', 'bookmarks'), # ! bookmark can change content at the same size
865 ('path', 'bookmarks'), # ! bookmark can change content at the same size
853 ]
866 ]
854
867
855 class cachedlocalrepo(object):
868 class cachedlocalrepo(object):
856 """Holds a localrepository that can be cached and reused."""
869 """Holds a localrepository that can be cached and reused."""
857
870
858 def __init__(self, repo):
871 def __init__(self, repo):
859 """Create a new cached repo from an existing repo.
872 """Create a new cached repo from an existing repo.
860
873
861 We assume the passed in repo was recently created. If the
874 We assume the passed in repo was recently created. If the
862 repo has changed between when it was created and when it was
875 repo has changed between when it was created and when it was
863 turned into a cache, it may not refresh properly.
876 turned into a cache, it may not refresh properly.
864 """
877 """
865 assert isinstance(repo, localrepo.localrepository)
878 assert isinstance(repo, localrepo.localrepository)
866 self._repo = repo
879 self._repo = repo
867 self._state, self.mtime = self._repostate()
880 self._state, self.mtime = self._repostate()
868
881
869 def fetch(self):
882 def fetch(self):
870 """Refresh (if necessary) and return a repository.
883 """Refresh (if necessary) and return a repository.
871
884
872 If the cached instance is out of date, it will be recreated
885 If the cached instance is out of date, it will be recreated
873 automatically and returned.
886 automatically and returned.
874
887
875 Returns a tuple of the repo and a boolean indicating whether a new
888 Returns a tuple of the repo and a boolean indicating whether a new
876 repo instance was created.
889 repo instance was created.
877 """
890 """
878 # We compare the mtimes and sizes of some well-known files to
891 # We compare the mtimes and sizes of some well-known files to
879 # determine if the repo changed. This is not precise, as mtimes
892 # determine if the repo changed. This is not precise, as mtimes
880 # are susceptible to clock skew and imprecise filesystems and
893 # are susceptible to clock skew and imprecise filesystems and
881 # file content can change while maintaining the same size.
894 # file content can change while maintaining the same size.
882
895
883 state, mtime = self._repostate()
896 state, mtime = self._repostate()
884 if state == self._state:
897 if state == self._state:
885 return self._repo, False
898 return self._repo, False
886
899
887 self._repo = repository(self._repo.baseui, self._repo.url())
900 self._repo = repository(self._repo.baseui, self._repo.url())
888 self._state = state
901 self._state = state
889 self.mtime = mtime
902 self.mtime = mtime
890
903
891 return self._repo, True
904 return self._repo, True
892
905
893 def _repostate(self):
906 def _repostate(self):
894 state = []
907 state = []
895 maxmtime = -1
908 maxmtime = -1
896 for attr, fname in foi:
909 for attr, fname in foi:
897 prefix = getattr(self._repo, attr)
910 prefix = getattr(self._repo, attr)
898 p = os.path.join(prefix, fname)
911 p = os.path.join(prefix, fname)
899 try:
912 try:
900 st = os.stat(p)
913 st = os.stat(p)
901 except OSError:
914 except OSError:
902 st = os.stat(prefix)
915 st = os.stat(prefix)
903 state.append((st.st_mtime, st.st_size))
916 state.append((st.st_mtime, st.st_size))
904 maxmtime = max(maxmtime, st.st_mtime)
917 maxmtime = max(maxmtime, st.st_mtime)
905
918
906 return tuple(state), maxmtime
919 return tuple(state), maxmtime
907
920
908 def copy(self):
921 def copy(self):
909 """Obtain a copy of this class instance.
922 """Obtain a copy of this class instance.
910
923
911 A new localrepository instance is obtained. The new instance should be
924 A new localrepository instance is obtained. The new instance should be
912 completely independent of the original.
925 completely independent of the original.
913 """
926 """
914 repo = repository(self._repo.baseui, self._repo.origroot)
927 repo = repository(self._repo.baseui, self._repo.origroot)
915 c = cachedlocalrepo(repo)
928 c = cachedlocalrepo(repo)
916 c._state = self._state
929 c._state = self._state
917 c.mtime = self.mtime
930 c.mtime = self.mtime
918 return c
931 return c
@@ -1,1027 +1,1073 b''
1 Prepare repo a:
1 Prepare repo a:
2
2
3 $ hg init a
3 $ hg init a
4 $ cd a
4 $ cd a
5 $ echo a > a
5 $ echo a > a
6 $ hg add a
6 $ hg add a
7 $ hg commit -m test
7 $ hg commit -m test
8 $ echo first line > b
8 $ echo first line > b
9 $ hg add b
9 $ hg add b
10
10
11 Create a non-inlined filelog:
11 Create a non-inlined filelog:
12
12
13 $ $PYTHON -c 'file("data1", "wb").write("".join("%s\n" % x for x in range(10000)))'
13 $ $PYTHON -c 'file("data1", "wb").write("".join("%s\n" % x for x in range(10000)))'
14 $ for j in 0 1 2 3 4 5 6 7 8 9; do
14 $ for j in 0 1 2 3 4 5 6 7 8 9; do
15 > cat data1 >> b
15 > cat data1 >> b
16 > hg commit -m test
16 > hg commit -m test
17 > done
17 > done
18
18
19 List files in store/data (should show a 'b.d'):
19 List files in store/data (should show a 'b.d'):
20
20
21 $ for i in .hg/store/data/*; do
21 $ for i in .hg/store/data/*; do
22 > echo $i
22 > echo $i
23 > done
23 > done
24 .hg/store/data/a.i
24 .hg/store/data/a.i
25 .hg/store/data/b.d
25 .hg/store/data/b.d
26 .hg/store/data/b.i
26 .hg/store/data/b.i
27
27
28 Trigger branchcache creation:
28 Trigger branchcache creation:
29
29
30 $ hg branches
30 $ hg branches
31 default 10:a7949464abda
31 default 10:a7949464abda
32 $ ls .hg/cache
32 $ ls .hg/cache
33 branch2-served
33 branch2-served
34 rbc-names-v1
34 rbc-names-v1
35 rbc-revs-v1
35 rbc-revs-v1
36
36
37 Default operation:
37 Default operation:
38
38
39 $ hg clone . ../b
39 $ hg clone . ../b
40 updating to branch default
40 updating to branch default
41 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
41 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
42 $ cd ../b
42 $ cd ../b
43
43
44 Ensure branchcache got copied over:
44 Ensure branchcache got copied over:
45
45
46 $ ls .hg/cache
46 $ ls .hg/cache
47 branch2-served
47 branch2-served
48
48
49 $ cat a
49 $ cat a
50 a
50 a
51 $ hg verify
51 $ hg verify
52 checking changesets
52 checking changesets
53 checking manifests
53 checking manifests
54 crosschecking files in changesets and manifests
54 crosschecking files in changesets and manifests
55 checking files
55 checking files
56 2 files, 11 changesets, 11 total revisions
56 2 files, 11 changesets, 11 total revisions
57
57
58 Invalid dest '' must abort:
58 Invalid dest '' must abort:
59
59
60 $ hg clone . ''
60 $ hg clone . ''
61 abort: empty destination path is not valid
61 abort: empty destination path is not valid
62 [255]
62 [255]
63
63
64 No update, with debug option:
64 No update, with debug option:
65
65
66 #if hardlink
66 #if hardlink
67 $ hg --debug clone -U . ../c --config progress.debug=true
67 $ hg --debug clone -U . ../c --config progress.debug=true
68 linking: 1
68 linking: 1
69 linking: 2
69 linking: 2
70 linking: 3
70 linking: 3
71 linking: 4
71 linking: 4
72 linking: 5
72 linking: 5
73 linking: 6
73 linking: 6
74 linking: 7
74 linking: 7
75 linking: 8
75 linking: 8
76 linked 8 files
76 linked 8 files
77 #else
77 #else
78 $ hg --debug clone -U . ../c --config progress.debug=true
78 $ hg --debug clone -U . ../c --config progress.debug=true
79 linking: 1
79 linking: 1
80 copying: 2
80 copying: 2
81 copying: 3
81 copying: 3
82 copying: 4
82 copying: 4
83 copying: 5
83 copying: 5
84 copying: 6
84 copying: 6
85 copying: 7
85 copying: 7
86 copying: 8
86 copying: 8
87 copied 8 files
87 copied 8 files
88 #endif
88 #endif
89 $ cd ../c
89 $ cd ../c
90
90
91 Ensure branchcache got copied over:
91 Ensure branchcache got copied over:
92
92
93 $ ls .hg/cache
93 $ ls .hg/cache
94 branch2-served
94 branch2-served
95
95
96 $ cat a 2>/dev/null || echo "a not present"
96 $ cat a 2>/dev/null || echo "a not present"
97 a not present
97 a not present
98 $ hg verify
98 $ hg verify
99 checking changesets
99 checking changesets
100 checking manifests
100 checking manifests
101 crosschecking files in changesets and manifests
101 crosschecking files in changesets and manifests
102 checking files
102 checking files
103 2 files, 11 changesets, 11 total revisions
103 2 files, 11 changesets, 11 total revisions
104
104
105 Default destination:
105 Default destination:
106
106
107 $ mkdir ../d
107 $ mkdir ../d
108 $ cd ../d
108 $ cd ../d
109 $ hg clone ../a
109 $ hg clone ../a
110 destination directory: a
110 destination directory: a
111 updating to branch default
111 updating to branch default
112 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
112 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
113 $ cd a
113 $ cd a
114 $ hg cat a
114 $ hg cat a
115 a
115 a
116 $ cd ../..
116 $ cd ../..
117
117
118 Check that we drop the 'file:' from the path before writing the .hgrc:
118 Check that we drop the 'file:' from the path before writing the .hgrc:
119
119
120 $ hg clone file:a e
120 $ hg clone file:a e
121 updating to branch default
121 updating to branch default
122 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
122 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
123 $ grep 'file:' e/.hg/hgrc
123 $ grep 'file:' e/.hg/hgrc
124 [1]
124 [1]
125
125
126 Check that path aliases are expanded:
126 Check that path aliases are expanded:
127
127
128 $ hg clone -q -U --config 'paths.foobar=a#0' foobar f
128 $ hg clone -q -U --config 'paths.foobar=a#0' foobar f
129 $ hg -R f showconfig paths.default
129 $ hg -R f showconfig paths.default
130 $TESTTMP/a#0 (glob)
130 $TESTTMP/a#0 (glob)
131
131
132 Use --pull:
132 Use --pull:
133
133
134 $ hg clone --pull a g
134 $ hg clone --pull a g
135 requesting all changes
135 requesting all changes
136 adding changesets
136 adding changesets
137 adding manifests
137 adding manifests
138 adding file changes
138 adding file changes
139 added 11 changesets with 11 changes to 2 files
139 added 11 changesets with 11 changes to 2 files
140 updating to branch default
140 updating to branch default
141 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
142 $ hg -R g verify
142 $ hg -R g verify
143 checking changesets
143 checking changesets
144 checking manifests
144 checking manifests
145 crosschecking files in changesets and manifests
145 crosschecking files in changesets and manifests
146 checking files
146 checking files
147 2 files, 11 changesets, 11 total revisions
147 2 files, 11 changesets, 11 total revisions
148
148
149 Invalid dest '' with --pull must abort (issue2528):
149 Invalid dest '' with --pull must abort (issue2528):
150
150
151 $ hg clone --pull a ''
151 $ hg clone --pull a ''
152 abort: empty destination path is not valid
152 abort: empty destination path is not valid
153 [255]
153 [255]
154
154
155 Clone to '.':
155 Clone to '.':
156
156
157 $ mkdir h
157 $ mkdir h
158 $ cd h
158 $ cd h
159 $ hg clone ../a .
159 $ hg clone ../a .
160 updating to branch default
160 updating to branch default
161 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
161 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
162 $ cd ..
162 $ cd ..
163
163
164
164
165 *** Tests for option -u ***
165 *** Tests for option -u ***
166
166
167 Adding some more history to repo a:
167 Adding some more history to repo a:
168
168
169 $ cd a
169 $ cd a
170 $ hg tag ref1
170 $ hg tag ref1
171 $ echo the quick brown fox >a
171 $ echo the quick brown fox >a
172 $ hg ci -m "hacked default"
172 $ hg ci -m "hacked default"
173 $ hg up ref1
173 $ hg up ref1
174 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
174 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
175 $ hg branch stable
175 $ hg branch stable
176 marked working directory as branch stable
176 marked working directory as branch stable
177 (branches are permanent and global, did you want a bookmark?)
177 (branches are permanent and global, did you want a bookmark?)
178 $ echo some text >a
178 $ echo some text >a
179 $ hg ci -m "starting branch stable"
179 $ hg ci -m "starting branch stable"
180 $ hg tag ref2
180 $ hg tag ref2
181 $ echo some more text >a
181 $ echo some more text >a
182 $ hg ci -m "another change for branch stable"
182 $ hg ci -m "another change for branch stable"
183 $ hg up ref2
183 $ hg up ref2
184 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
184 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
185 $ hg parents
185 $ hg parents
186 changeset: 13:e8ece76546a6
186 changeset: 13:e8ece76546a6
187 branch: stable
187 branch: stable
188 tag: ref2
188 tag: ref2
189 parent: 10:a7949464abda
189 parent: 10:a7949464abda
190 user: test
190 user: test
191 date: Thu Jan 01 00:00:00 1970 +0000
191 date: Thu Jan 01 00:00:00 1970 +0000
192 summary: starting branch stable
192 summary: starting branch stable
193
193
194
194
195 Repo a has two heads:
195 Repo a has two heads:
196
196
197 $ hg heads
197 $ hg heads
198 changeset: 15:0aae7cf88f0d
198 changeset: 15:0aae7cf88f0d
199 branch: stable
199 branch: stable
200 tag: tip
200 tag: tip
201 user: test
201 user: test
202 date: Thu Jan 01 00:00:00 1970 +0000
202 date: Thu Jan 01 00:00:00 1970 +0000
203 summary: another change for branch stable
203 summary: another change for branch stable
204
204
205 changeset: 12:f21241060d6a
205 changeset: 12:f21241060d6a
206 user: test
206 user: test
207 date: Thu Jan 01 00:00:00 1970 +0000
207 date: Thu Jan 01 00:00:00 1970 +0000
208 summary: hacked default
208 summary: hacked default
209
209
210
210
211 $ cd ..
211 $ cd ..
212
212
213
213
214 Testing --noupdate with --updaterev (must abort):
214 Testing --noupdate with --updaterev (must abort):
215
215
216 $ hg clone --noupdate --updaterev 1 a ua
216 $ hg clone --noupdate --updaterev 1 a ua
217 abort: cannot specify both --noupdate and --updaterev
217 abort: cannot specify both --noupdate and --updaterev
218 [255]
218 [255]
219
219
220
220
221 Testing clone -u:
221 Testing clone -u:
222
222
223 $ hg clone -u . a ua
223 $ hg clone -u . a ua
224 updating to branch stable
224 updating to branch stable
225 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
225 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
226
226
227 Repo ua has both heads:
227 Repo ua has both heads:
228
228
229 $ hg -R ua heads
229 $ hg -R ua heads
230 changeset: 15:0aae7cf88f0d
230 changeset: 15:0aae7cf88f0d
231 branch: stable
231 branch: stable
232 tag: tip
232 tag: tip
233 user: test
233 user: test
234 date: Thu Jan 01 00:00:00 1970 +0000
234 date: Thu Jan 01 00:00:00 1970 +0000
235 summary: another change for branch stable
235 summary: another change for branch stable
236
236
237 changeset: 12:f21241060d6a
237 changeset: 12:f21241060d6a
238 user: test
238 user: test
239 date: Thu Jan 01 00:00:00 1970 +0000
239 date: Thu Jan 01 00:00:00 1970 +0000
240 summary: hacked default
240 summary: hacked default
241
241
242
242
243 Same revision checked out in repo a and ua:
243 Same revision checked out in repo a and ua:
244
244
245 $ hg -R a parents --template "{node|short}\n"
245 $ hg -R a parents --template "{node|short}\n"
246 e8ece76546a6
246 e8ece76546a6
247 $ hg -R ua parents --template "{node|short}\n"
247 $ hg -R ua parents --template "{node|short}\n"
248 e8ece76546a6
248 e8ece76546a6
249
249
250 $ rm -r ua
250 $ rm -r ua
251
251
252
252
253 Testing clone --pull -u:
253 Testing clone --pull -u:
254
254
255 $ hg clone --pull -u . a ua
255 $ hg clone --pull -u . a ua
256 requesting all changes
256 requesting all changes
257 adding changesets
257 adding changesets
258 adding manifests
258 adding manifests
259 adding file changes
259 adding file changes
260 added 16 changesets with 16 changes to 3 files (+1 heads)
260 added 16 changesets with 16 changes to 3 files (+1 heads)
261 updating to branch stable
261 updating to branch stable
262 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
262 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
263
263
264 Repo ua has both heads:
264 Repo ua has both heads:
265
265
266 $ hg -R ua heads
266 $ hg -R ua heads
267 changeset: 15:0aae7cf88f0d
267 changeset: 15:0aae7cf88f0d
268 branch: stable
268 branch: stable
269 tag: tip
269 tag: tip
270 user: test
270 user: test
271 date: Thu Jan 01 00:00:00 1970 +0000
271 date: Thu Jan 01 00:00:00 1970 +0000
272 summary: another change for branch stable
272 summary: another change for branch stable
273
273
274 changeset: 12:f21241060d6a
274 changeset: 12:f21241060d6a
275 user: test
275 user: test
276 date: Thu Jan 01 00:00:00 1970 +0000
276 date: Thu Jan 01 00:00:00 1970 +0000
277 summary: hacked default
277 summary: hacked default
278
278
279
279
280 Same revision checked out in repo a and ua:
280 Same revision checked out in repo a and ua:
281
281
282 $ hg -R a parents --template "{node|short}\n"
282 $ hg -R a parents --template "{node|short}\n"
283 e8ece76546a6
283 e8ece76546a6
284 $ hg -R ua parents --template "{node|short}\n"
284 $ hg -R ua parents --template "{node|short}\n"
285 e8ece76546a6
285 e8ece76546a6
286
286
287 $ rm -r ua
287 $ rm -r ua
288
288
289
289
290 Testing clone -u <branch>:
290 Testing clone -u <branch>:
291
291
292 $ hg clone -u stable a ua
292 $ hg clone -u stable a ua
293 updating to branch stable
293 updating to branch stable
294 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
294 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
295
295
296 Repo ua has both heads:
296 Repo ua has both heads:
297
297
298 $ hg -R ua heads
298 $ hg -R ua heads
299 changeset: 15:0aae7cf88f0d
299 changeset: 15:0aae7cf88f0d
300 branch: stable
300 branch: stable
301 tag: tip
301 tag: tip
302 user: test
302 user: test
303 date: Thu Jan 01 00:00:00 1970 +0000
303 date: Thu Jan 01 00:00:00 1970 +0000
304 summary: another change for branch stable
304 summary: another change for branch stable
305
305
306 changeset: 12:f21241060d6a
306 changeset: 12:f21241060d6a
307 user: test
307 user: test
308 date: Thu Jan 01 00:00:00 1970 +0000
308 date: Thu Jan 01 00:00:00 1970 +0000
309 summary: hacked default
309 summary: hacked default
310
310
311
311
312 Branch 'stable' is checked out:
312 Branch 'stable' is checked out:
313
313
314 $ hg -R ua parents
314 $ hg -R ua parents
315 changeset: 15:0aae7cf88f0d
315 changeset: 15:0aae7cf88f0d
316 branch: stable
316 branch: stable
317 tag: tip
317 tag: tip
318 user: test
318 user: test
319 date: Thu Jan 01 00:00:00 1970 +0000
319 date: Thu Jan 01 00:00:00 1970 +0000
320 summary: another change for branch stable
320 summary: another change for branch stable
321
321
322
322
323 $ rm -r ua
323 $ rm -r ua
324
324
325
325
326 Testing default checkout:
326 Testing default checkout:
327
327
328 $ hg clone a ua
328 $ hg clone a ua
329 updating to branch default
329 updating to branch default
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 Repo ua has both heads:
332 Repo ua has both heads:
333
333
334 $ hg -R ua heads
334 $ hg -R ua heads
335 changeset: 15:0aae7cf88f0d
335 changeset: 15:0aae7cf88f0d
336 branch: stable
336 branch: stable
337 tag: tip
337 tag: tip
338 user: test
338 user: test
339 date: Thu Jan 01 00:00:00 1970 +0000
339 date: Thu Jan 01 00:00:00 1970 +0000
340 summary: another change for branch stable
340 summary: another change for branch stable
341
341
342 changeset: 12:f21241060d6a
342 changeset: 12:f21241060d6a
343 user: test
343 user: test
344 date: Thu Jan 01 00:00:00 1970 +0000
344 date: Thu Jan 01 00:00:00 1970 +0000
345 summary: hacked default
345 summary: hacked default
346
346
347
347
348 Branch 'default' is checked out:
348 Branch 'default' is checked out:
349
349
350 $ hg -R ua parents
350 $ hg -R ua parents
351 changeset: 12:f21241060d6a
351 changeset: 12:f21241060d6a
352 user: test
352 user: test
353 date: Thu Jan 01 00:00:00 1970 +0000
353 date: Thu Jan 01 00:00:00 1970 +0000
354 summary: hacked default
354 summary: hacked default
355
355
356 Test clone with a branch named "@" (issue3677)
356 Test clone with a branch named "@" (issue3677)
357
357
358 $ hg -R ua branch @
358 $ hg -R ua branch @
359 marked working directory as branch @
359 marked working directory as branch @
360 $ hg -R ua commit -m 'created branch @'
360 $ hg -R ua commit -m 'created branch @'
361 $ hg clone ua atbranch
361 $ hg clone ua atbranch
362 updating to branch default
362 updating to branch default
363 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
363 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
364 $ hg -R atbranch heads
364 $ hg -R atbranch heads
365 changeset: 16:798b6d97153e
365 changeset: 16:798b6d97153e
366 branch: @
366 branch: @
367 tag: tip
367 tag: tip
368 parent: 12:f21241060d6a
368 parent: 12:f21241060d6a
369 user: test
369 user: test
370 date: Thu Jan 01 00:00:00 1970 +0000
370 date: Thu Jan 01 00:00:00 1970 +0000
371 summary: created branch @
371 summary: created branch @
372
372
373 changeset: 15:0aae7cf88f0d
373 changeset: 15:0aae7cf88f0d
374 branch: stable
374 branch: stable
375 user: test
375 user: test
376 date: Thu Jan 01 00:00:00 1970 +0000
376 date: Thu Jan 01 00:00:00 1970 +0000
377 summary: another change for branch stable
377 summary: another change for branch stable
378
378
379 changeset: 12:f21241060d6a
379 changeset: 12:f21241060d6a
380 user: test
380 user: test
381 date: Thu Jan 01 00:00:00 1970 +0000
381 date: Thu Jan 01 00:00:00 1970 +0000
382 summary: hacked default
382 summary: hacked default
383
383
384 $ hg -R atbranch parents
384 $ hg -R atbranch parents
385 changeset: 12:f21241060d6a
385 changeset: 12:f21241060d6a
386 user: test
386 user: test
387 date: Thu Jan 01 00:00:00 1970 +0000
387 date: Thu Jan 01 00:00:00 1970 +0000
388 summary: hacked default
388 summary: hacked default
389
389
390
390
391 $ rm -r ua atbranch
391 $ rm -r ua atbranch
392
392
393
393
394 Testing #<branch>:
394 Testing #<branch>:
395
395
396 $ hg clone -u . a#stable ua
396 $ hg clone -u . a#stable ua
397 adding changesets
397 adding changesets
398 adding manifests
398 adding manifests
399 adding file changes
399 adding file changes
400 added 14 changesets with 14 changes to 3 files
400 added 14 changesets with 14 changes to 3 files
401 updating to branch stable
401 updating to branch stable
402 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
402 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
403
403
404 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
404 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
405
405
406 $ hg -R ua heads
406 $ hg -R ua heads
407 changeset: 13:0aae7cf88f0d
407 changeset: 13:0aae7cf88f0d
408 branch: stable
408 branch: stable
409 tag: tip
409 tag: tip
410 user: test
410 user: test
411 date: Thu Jan 01 00:00:00 1970 +0000
411 date: Thu Jan 01 00:00:00 1970 +0000
412 summary: another change for branch stable
412 summary: another change for branch stable
413
413
414 changeset: 10:a7949464abda
414 changeset: 10:a7949464abda
415 user: test
415 user: test
416 date: Thu Jan 01 00:00:00 1970 +0000
416 date: Thu Jan 01 00:00:00 1970 +0000
417 summary: test
417 summary: test
418
418
419
419
420 Same revision checked out in repo a and ua:
420 Same revision checked out in repo a and ua:
421
421
422 $ hg -R a parents --template "{node|short}\n"
422 $ hg -R a parents --template "{node|short}\n"
423 e8ece76546a6
423 e8ece76546a6
424 $ hg -R ua parents --template "{node|short}\n"
424 $ hg -R ua parents --template "{node|short}\n"
425 e8ece76546a6
425 e8ece76546a6
426
426
427 $ rm -r ua
427 $ rm -r ua
428
428
429
429
430 Testing -u -r <branch>:
430 Testing -u -r <branch>:
431
431
432 $ hg clone -u . -r stable a ua
432 $ hg clone -u . -r stable a ua
433 adding changesets
433 adding changesets
434 adding manifests
434 adding manifests
435 adding file changes
435 adding file changes
436 added 14 changesets with 14 changes to 3 files
436 added 14 changesets with 14 changes to 3 files
437 updating to branch stable
437 updating to branch stable
438 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
438 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
439
439
440 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
440 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
441
441
442 $ hg -R ua heads
442 $ hg -R ua heads
443 changeset: 13:0aae7cf88f0d
443 changeset: 13:0aae7cf88f0d
444 branch: stable
444 branch: stable
445 tag: tip
445 tag: tip
446 user: test
446 user: test
447 date: Thu Jan 01 00:00:00 1970 +0000
447 date: Thu Jan 01 00:00:00 1970 +0000
448 summary: another change for branch stable
448 summary: another change for branch stable
449
449
450 changeset: 10:a7949464abda
450 changeset: 10:a7949464abda
451 user: test
451 user: test
452 date: Thu Jan 01 00:00:00 1970 +0000
452 date: Thu Jan 01 00:00:00 1970 +0000
453 summary: test
453 summary: test
454
454
455
455
456 Same revision checked out in repo a and ua:
456 Same revision checked out in repo a and ua:
457
457
458 $ hg -R a parents --template "{node|short}\n"
458 $ hg -R a parents --template "{node|short}\n"
459 e8ece76546a6
459 e8ece76546a6
460 $ hg -R ua parents --template "{node|short}\n"
460 $ hg -R ua parents --template "{node|short}\n"
461 e8ece76546a6
461 e8ece76546a6
462
462
463 $ rm -r ua
463 $ rm -r ua
464
464
465
465
466 Testing -r <branch>:
466 Testing -r <branch>:
467
467
468 $ hg clone -r stable a ua
468 $ hg clone -r stable a ua
469 adding changesets
469 adding changesets
470 adding manifests
470 adding manifests
471 adding file changes
471 adding file changes
472 added 14 changesets with 14 changes to 3 files
472 added 14 changesets with 14 changes to 3 files
473 updating to branch stable
473 updating to branch stable
474 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
474 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
475
475
476 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
476 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
477
477
478 $ hg -R ua heads
478 $ hg -R ua heads
479 changeset: 13:0aae7cf88f0d
479 changeset: 13:0aae7cf88f0d
480 branch: stable
480 branch: stable
481 tag: tip
481 tag: tip
482 user: test
482 user: test
483 date: Thu Jan 01 00:00:00 1970 +0000
483 date: Thu Jan 01 00:00:00 1970 +0000
484 summary: another change for branch stable
484 summary: another change for branch stable
485
485
486 changeset: 10:a7949464abda
486 changeset: 10:a7949464abda
487 user: test
487 user: test
488 date: Thu Jan 01 00:00:00 1970 +0000
488 date: Thu Jan 01 00:00:00 1970 +0000
489 summary: test
489 summary: test
490
490
491
491
492 Branch 'stable' is checked out:
492 Branch 'stable' is checked out:
493
493
494 $ hg -R ua parents
494 $ hg -R ua parents
495 changeset: 13:0aae7cf88f0d
495 changeset: 13:0aae7cf88f0d
496 branch: stable
496 branch: stable
497 tag: tip
497 tag: tip
498 user: test
498 user: test
499 date: Thu Jan 01 00:00:00 1970 +0000
499 date: Thu Jan 01 00:00:00 1970 +0000
500 summary: another change for branch stable
500 summary: another change for branch stable
501
501
502
502
503 $ rm -r ua
503 $ rm -r ua
504
504
505
505
506 Issue2267: Error in 1.6 hg.py: TypeError: 'NoneType' object is not
506 Issue2267: Error in 1.6 hg.py: TypeError: 'NoneType' object is not
507 iterable in addbranchrevs()
507 iterable in addbranchrevs()
508
508
509 $ cat <<EOF > simpleclone.py
509 $ cat <<EOF > simpleclone.py
510 > from mercurial import ui, hg
510 > from mercurial import ui, hg
511 > myui = ui.ui()
511 > myui = ui.ui()
512 > repo = hg.repository(myui, 'a')
512 > repo = hg.repository(myui, 'a')
513 > hg.clone(myui, {}, repo, dest="ua")
513 > hg.clone(myui, {}, repo, dest="ua")
514 > EOF
514 > EOF
515
515
516 $ python simpleclone.py
516 $ python simpleclone.py
517 updating to branch default
517 updating to branch default
518 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
518 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
519
519
520 $ rm -r ua
520 $ rm -r ua
521
521
522 $ cat <<EOF > branchclone.py
522 $ cat <<EOF > branchclone.py
523 > from mercurial import ui, hg, extensions
523 > from mercurial import ui, hg, extensions
524 > myui = ui.ui()
524 > myui = ui.ui()
525 > extensions.loadall(myui)
525 > extensions.loadall(myui)
526 > repo = hg.repository(myui, 'a')
526 > repo = hg.repository(myui, 'a')
527 > hg.clone(myui, {}, repo, dest="ua", branch=["stable",])
527 > hg.clone(myui, {}, repo, dest="ua", branch=["stable",])
528 > EOF
528 > EOF
529
529
530 $ python branchclone.py
530 $ python branchclone.py
531 adding changesets
531 adding changesets
532 adding manifests
532 adding manifests
533 adding file changes
533 adding file changes
534 added 14 changesets with 14 changes to 3 files
534 added 14 changesets with 14 changes to 3 files
535 updating to branch stable
535 updating to branch stable
536 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
536 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
537 $ rm -r ua
537 $ rm -r ua
538
538
539
539
540 Test clone with special '@' bookmark:
540 Test clone with special '@' bookmark:
541 $ cd a
541 $ cd a
542 $ hg bookmark -r a7949464abda @ # branch point of stable from default
542 $ hg bookmark -r a7949464abda @ # branch point of stable from default
543 $ hg clone . ../i
543 $ hg clone . ../i
544 updating to bookmark @
544 updating to bookmark @
545 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
545 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
546 $ hg id -i ../i
546 $ hg id -i ../i
547 a7949464abda
547 a7949464abda
548 $ rm -r ../i
548 $ rm -r ../i
549
549
550 $ hg bookmark -f -r stable @
550 $ hg bookmark -f -r stable @
551 $ hg bookmarks
551 $ hg bookmarks
552 @ 15:0aae7cf88f0d
552 @ 15:0aae7cf88f0d
553 $ hg clone . ../i
553 $ hg clone . ../i
554 updating to bookmark @ on branch stable
554 updating to bookmark @ on branch stable
555 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
555 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
556 $ hg id -i ../i
556 $ hg id -i ../i
557 0aae7cf88f0d
557 0aae7cf88f0d
558 $ cd "$TESTTMP"
558 $ cd "$TESTTMP"
559
559
560
560
561 Testing failures:
561 Testing failures:
562
562
563 $ mkdir fail
563 $ mkdir fail
564 $ cd fail
564 $ cd fail
565
565
566 No local source
566 No local source
567
567
568 $ hg clone a b
568 $ hg clone a b
569 abort: repository a not found!
569 abort: repository a not found!
570 [255]
570 [255]
571
571
572 No remote source
572 No remote source
573
573
574 #if windows
574 #if windows
575 $ hg clone http://127.0.0.1:3121/a b
575 $ hg clone http://127.0.0.1:3121/a b
576 abort: error: * (glob)
576 abort: error: * (glob)
577 [255]
577 [255]
578 #else
578 #else
579 $ hg clone http://127.0.0.1:3121/a b
579 $ hg clone http://127.0.0.1:3121/a b
580 abort: error: *refused* (glob)
580 abort: error: *refused* (glob)
581 [255]
581 [255]
582 #endif
582 #endif
583 $ rm -rf b # work around bug with http clone
583 $ rm -rf b # work around bug with http clone
584
584
585
585
586 #if unix-permissions no-root
586 #if unix-permissions no-root
587
587
588 Inaccessible source
588 Inaccessible source
589
589
590 $ mkdir a
590 $ mkdir a
591 $ chmod 000 a
591 $ chmod 000 a
592 $ hg clone a b
592 $ hg clone a b
593 abort: repository a not found!
593 abort: repository a not found!
594 [255]
594 [255]
595
595
596 Inaccessible destination
596 Inaccessible destination
597
597
598 $ hg init b
598 $ hg init b
599 $ cd b
599 $ cd b
600 $ hg clone . ../a
600 $ hg clone . ../a
601 abort: Permission denied: '../a'
601 abort: Permission denied: '../a'
602 [255]
602 [255]
603 $ cd ..
603 $ cd ..
604 $ chmod 700 a
604 $ chmod 700 a
605 $ rm -r a b
605 $ rm -r a b
606
606
607 #endif
607 #endif
608
608
609
609
610 #if fifo
610 #if fifo
611
611
612 Source of wrong type
612 Source of wrong type
613
613
614 $ mkfifo a
614 $ mkfifo a
615 $ hg clone a b
615 $ hg clone a b
616 abort: repository a not found!
616 abort: repository a not found!
617 [255]
617 [255]
618 $ rm a
618 $ rm a
619
619
620 #endif
620 #endif
621
621
622 Default destination, same directory
622 Default destination, same directory
623
623
624 $ hg init q
624 $ hg init q
625 $ hg clone q
625 $ hg clone q
626 destination directory: q
626 destination directory: q
627 abort: destination 'q' is not empty
627 abort: destination 'q' is not empty
628 [255]
628 [255]
629
629
630 destination directory not empty
630 destination directory not empty
631
631
632 $ mkdir a
632 $ mkdir a
633 $ echo stuff > a/a
633 $ echo stuff > a/a
634 $ hg clone q a
634 $ hg clone q a
635 abort: destination 'a' is not empty
635 abort: destination 'a' is not empty
636 [255]
636 [255]
637
637
638
638
639 #if unix-permissions no-root
639 #if unix-permissions no-root
640
640
641 leave existing directory in place after clone failure
641 leave existing directory in place after clone failure
642
642
643 $ hg init c
643 $ hg init c
644 $ cd c
644 $ cd c
645 $ echo c > c
645 $ echo c > c
646 $ hg commit -A -m test
646 $ hg commit -A -m test
647 adding c
647 adding c
648 $ chmod -rx .hg/store/data
648 $ chmod -rx .hg/store/data
649 $ cd ..
649 $ cd ..
650 $ mkdir d
650 $ mkdir d
651 $ hg clone c d 2> err
651 $ hg clone c d 2> err
652 [255]
652 [255]
653 $ test -d d
653 $ test -d d
654 $ test -d d/.hg
654 $ test -d d/.hg
655 [1]
655 [1]
656
656
657 re-enable perm to allow deletion
657 re-enable perm to allow deletion
658
658
659 $ chmod +rx c/.hg/store/data
659 $ chmod +rx c/.hg/store/data
660
660
661 #endif
661 #endif
662
662
663 $ cd ..
663 $ cd ..
664
664
665 Test clone from the repository in (emulated) revlog format 0 (issue4203):
665 Test clone from the repository in (emulated) revlog format 0 (issue4203):
666
666
667 $ mkdir issue4203
667 $ mkdir issue4203
668 $ mkdir -p src/.hg
668 $ mkdir -p src/.hg
669 $ echo foo > src/foo
669 $ echo foo > src/foo
670 $ hg -R src add src/foo
670 $ hg -R src add src/foo
671 $ hg -R src commit -m '#0'
671 $ hg -R src commit -m '#0'
672 $ hg -R src log -q
672 $ hg -R src log -q
673 0:e1bab28bca43
673 0:e1bab28bca43
674 $ hg clone -U -q src dst
674 $ hg clone -U -q src dst
675 $ hg -R dst log -q
675 $ hg -R dst log -q
676 0:e1bab28bca43
676 0:e1bab28bca43
677
677
678 Create repositories to test auto sharing functionality
678 Create repositories to test auto sharing functionality
679
679
680 $ cat >> $HGRCPATH << EOF
680 $ cat >> $HGRCPATH << EOF
681 > [extensions]
681 > [extensions]
682 > share=
682 > share=
683 > EOF
683 > EOF
684
684
685 $ hg init empty
685 $ hg init empty
686 $ hg init source1a
686 $ hg init source1a
687 $ cd source1a
687 $ cd source1a
688 $ echo initial1 > foo
688 $ echo initial1 > foo
689 $ hg -q commit -A -m initial
689 $ hg -q commit -A -m initial
690 $ echo second > foo
690 $ echo second > foo
691 $ hg commit -m second
691 $ hg commit -m second
692 $ cd ..
692 $ cd ..
693
693
694 $ hg init filteredrev0
694 $ hg init filteredrev0
695 $ cd filteredrev0
695 $ cd filteredrev0
696 $ cat >> .hg/hgrc << EOF
696 $ cat >> .hg/hgrc << EOF
697 > [experimental]
697 > [experimental]
698 > evolution=createmarkers
698 > evolution=createmarkers
699 > EOF
699 > EOF
700 $ echo initial1 > foo
700 $ echo initial1 > foo
701 $ hg -q commit -A -m initial0
701 $ hg -q commit -A -m initial0
702 $ hg -q up -r null
702 $ hg -q up -r null
703 $ echo initial2 > foo
703 $ echo initial2 > foo
704 $ hg -q commit -A -m initial1
704 $ hg -q commit -A -m initial1
705 $ hg debugobsolete c05d5c47a5cf81401869999f3d05f7d699d2b29a e082c1832e09a7d1e78b7fd49a592d372de854c8
705 $ hg debugobsolete c05d5c47a5cf81401869999f3d05f7d699d2b29a e082c1832e09a7d1e78b7fd49a592d372de854c8
706 $ cd ..
706 $ cd ..
707
707
708 $ hg -q clone --pull source1a source1b
708 $ hg -q clone --pull source1a source1b
709 $ cd source1a
709 $ cd source1a
710 $ hg bookmark bookA
710 $ hg bookmark bookA
711 $ echo 1a > foo
711 $ echo 1a > foo
712 $ hg commit -m 1a
712 $ hg commit -m 1a
713 $ cd ../source1b
713 $ cd ../source1b
714 $ hg -q up -r 0
714 $ hg -q up -r 0
715 $ echo head1 > foo
715 $ echo head1 > foo
716 $ hg commit -m head1
716 $ hg commit -m head1
717 created new head
717 created new head
718 $ hg bookmark head1
718 $ hg bookmark head1
719 $ hg -q up -r 0
719 $ hg -q up -r 0
720 $ echo head2 > foo
720 $ echo head2 > foo
721 $ hg commit -m head2
721 $ hg commit -m head2
722 created new head
722 created new head
723 $ hg bookmark head2
723 $ hg bookmark head2
724 $ hg -q up -r 0
724 $ hg -q up -r 0
725 $ hg branch branch1
725 $ hg branch branch1
726 marked working directory as branch branch1
726 marked working directory as branch branch1
727 (branches are permanent and global, did you want a bookmark?)
727 (branches are permanent and global, did you want a bookmark?)
728 $ echo branch1 > foo
728 $ echo branch1 > foo
729 $ hg commit -m branch1
729 $ hg commit -m branch1
730 $ hg -q up -r 0
730 $ hg -q up -r 0
731 $ hg branch branch2
731 $ hg branch branch2
732 marked working directory as branch branch2
732 marked working directory as branch branch2
733 $ echo branch2 > foo
733 $ echo branch2 > foo
734 $ hg commit -m branch2
734 $ hg commit -m branch2
735 $ cd ..
735 $ cd ..
736 $ hg init source2
736 $ hg init source2
737 $ cd source2
737 $ cd source2
738 $ echo initial2 > foo
738 $ echo initial2 > foo
739 $ hg -q commit -A -m initial2
739 $ hg -q commit -A -m initial2
740 $ echo second > foo
740 $ echo second > foo
741 $ hg commit -m second
741 $ hg commit -m second
742 $ cd ..
742 $ cd ..
743
743
744 Clone with auto share from an empty repo should not result in share
744 Clone with auto share from an empty repo should not result in share
745
745
746 $ mkdir share
746 $ mkdir share
747 $ hg --config share.pool=share clone empty share-empty
747 $ hg --config share.pool=share clone empty share-empty
748 (not using pooled storage: remote appears to be empty)
748 (not using pooled storage: remote appears to be empty)
749 updating to branch default
749 updating to branch default
750 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
750 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
751 $ ls share
751 $ ls share
752 $ test -d share-empty/.hg/store
752 $ test -d share-empty/.hg/store
753 $ test -f share-empty/.hg/sharedpath
753 $ test -f share-empty/.hg/sharedpath
754 [1]
754 [1]
755
755
756 Clone with auto share from a repo with filtered revision 0 should not result in share
756 Clone with auto share from a repo with filtered revision 0 should not result in share
757
757
758 $ hg --config share.pool=share clone filteredrev0 share-filtered
758 $ hg --config share.pool=share clone filteredrev0 share-filtered
759 (not using pooled storage: unable to resolve identity of remote)
759 (not using pooled storage: unable to resolve identity of remote)
760 requesting all changes
760 requesting all changes
761 adding changesets
761 adding changesets
762 adding manifests
762 adding manifests
763 adding file changes
763 adding file changes
764 added 1 changesets with 1 changes to 1 files
764 added 1 changesets with 1 changes to 1 files
765 updating to branch default
765 updating to branch default
766 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
766 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
767
767
768 Clone from repo with content should result in shared store being created
768 Clone from repo with content should result in shared store being created
769
769
770 $ hg --config share.pool=share clone source1a share-dest1a
770 $ hg --config share.pool=share clone source1a share-dest1a
771 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
771 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
772 requesting all changes
772 requesting all changes
773 adding changesets
773 adding changesets
774 adding manifests
774 adding manifests
775 adding file changes
775 adding file changes
776 added 3 changesets with 3 changes to 1 files
776 added 3 changesets with 3 changes to 1 files
777 updating working directory
777 updating working directory
778 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
778 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
779 searching for changes
779 searching for changes
780 no changes found
780 no changes found
781 adding remote bookmark bookA
781 adding remote bookmark bookA
782
782
783 The shared repo should have been created
783 The shared repo should have been created
784
784
785 $ ls share
785 $ ls share
786 b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1
786 b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1
787
787
788 The destination should point to it
788 The destination should point to it
789
789
790 $ cat share-dest1a/.hg/sharedpath; echo
790 $ cat share-dest1a/.hg/sharedpath; echo
791 $TESTTMP/share/b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1/.hg (glob)
791 $TESTTMP/share/b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1/.hg (glob)
792
792
793 The destination should have bookmarks
793 The destination should have bookmarks
794
794
795 $ hg -R share-dest1a bookmarks
795 $ hg -R share-dest1a bookmarks
796 bookA 2:e5bfe23c0b47
796 bookA 2:e5bfe23c0b47
797
797
798 The default path should be the remote, not the share
798 The default path should be the remote, not the share
799
799
800 $ hg -R share-dest1a config paths.default
800 $ hg -R share-dest1a config paths.default
801 $TESTTMP/source1a (glob)
801 $TESTTMP/source1a (glob)
802
802
803 Clone with existing share dir should result in pull + share
803 Clone with existing share dir should result in pull + share
804
804
805 $ hg --config share.pool=share clone source1b share-dest1b
805 $ hg --config share.pool=share clone source1b share-dest1b
806 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
806 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
807 updating working directory
807 updating working directory
808 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
808 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
809 searching for changes
809 searching for changes
810 adding changesets
810 adding changesets
811 adding manifests
811 adding manifests
812 adding file changes
812 adding file changes
813 added 4 changesets with 4 changes to 1 files (+4 heads)
813 added 4 changesets with 4 changes to 1 files (+4 heads)
814 adding remote bookmark head1
814 adding remote bookmark head1
815 adding remote bookmark head2
815 adding remote bookmark head2
816
816
817 $ ls share
817 $ ls share
818 b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1
818 b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1
819
819
820 $ cat share-dest1b/.hg/sharedpath; echo
820 $ cat share-dest1b/.hg/sharedpath; echo
821 $TESTTMP/share/b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1/.hg (glob)
821 $TESTTMP/share/b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1/.hg (glob)
822
822
823 We only get bookmarks from the remote, not everything in the share
823 We only get bookmarks from the remote, not everything in the share
824
824
825 $ hg -R share-dest1b bookmarks
825 $ hg -R share-dest1b bookmarks
826 head1 3:4a8dc1ab4c13
826 head1 3:4a8dc1ab4c13
827 head2 4:99f71071f117
827 head2 4:99f71071f117
828
828
829 Default path should be source, not share.
829 Default path should be source, not share.
830
830
831 $ hg -R share-dest1b config paths.default
831 $ hg -R share-dest1b config paths.default
832 $TESTTMP/source1a (glob)
832 $TESTTMP/source1a (glob)
833
833
834 Clone from unrelated repo should result in new share
834 Clone from unrelated repo should result in new share
835
835
836 $ hg --config share.pool=share clone source2 share-dest2
836 $ hg --config share.pool=share clone source2 share-dest2
837 (sharing from new pooled repository 22aeff664783fd44c6d9b435618173c118c3448e)
837 (sharing from new pooled repository 22aeff664783fd44c6d9b435618173c118c3448e)
838 requesting all changes
838 requesting all changes
839 adding changesets
839 adding changesets
840 adding manifests
840 adding manifests
841 adding file changes
841 adding file changes
842 added 2 changesets with 2 changes to 1 files
842 added 2 changesets with 2 changes to 1 files
843 updating working directory
843 updating working directory
844 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
844 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
845 searching for changes
845 searching for changes
846 no changes found
846 no changes found
847
847
848 $ ls share
848 $ ls share
849 22aeff664783fd44c6d9b435618173c118c3448e
849 22aeff664783fd44c6d9b435618173c118c3448e
850 b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1
850 b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1
851
851
852 remote naming mode works as advertised
852 remote naming mode works as advertised
853
853
854 $ hg --config share.pool=shareremote --config share.poolnaming=remote clone source1a share-remote1a
854 $ hg --config share.pool=shareremote --config share.poolnaming=remote clone source1a share-remote1a
855 (sharing from new pooled repository 195bb1fcdb595c14a6c13e0269129ed78f6debde)
855 (sharing from new pooled repository 195bb1fcdb595c14a6c13e0269129ed78f6debde)
856 requesting all changes
856 requesting all changes
857 adding changesets
857 adding changesets
858 adding manifests
858 adding manifests
859 adding file changes
859 adding file changes
860 added 3 changesets with 3 changes to 1 files
860 added 3 changesets with 3 changes to 1 files
861 updating working directory
861 updating working directory
862 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
862 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
863 searching for changes
863 searching for changes
864 no changes found
864 no changes found
865 adding remote bookmark bookA
865 adding remote bookmark bookA
866
866
867 $ ls shareremote
867 $ ls shareremote
868 195bb1fcdb595c14a6c13e0269129ed78f6debde
868 195bb1fcdb595c14a6c13e0269129ed78f6debde
869
869
870 $ hg --config share.pool=shareremote --config share.poolnaming=remote clone source1b share-remote1b
870 $ hg --config share.pool=shareremote --config share.poolnaming=remote clone source1b share-remote1b
871 (sharing from new pooled repository c0d4f83847ca2a873741feb7048a45085fd47c46)
871 (sharing from new pooled repository c0d4f83847ca2a873741feb7048a45085fd47c46)
872 requesting all changes
872 requesting all changes
873 adding changesets
873 adding changesets
874 adding manifests
874 adding manifests
875 adding file changes
875 adding file changes
876 added 6 changesets with 6 changes to 1 files (+4 heads)
876 added 6 changesets with 6 changes to 1 files (+4 heads)
877 updating working directory
877 updating working directory
878 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
878 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
879 searching for changes
879 searching for changes
880 no changes found
880 no changes found
881 adding remote bookmark head1
881 adding remote bookmark head1
882 adding remote bookmark head2
882 adding remote bookmark head2
883
883
884 $ ls shareremote
884 $ ls shareremote
885 195bb1fcdb595c14a6c13e0269129ed78f6debde
885 195bb1fcdb595c14a6c13e0269129ed78f6debde
886 c0d4f83847ca2a873741feb7048a45085fd47c46
886 c0d4f83847ca2a873741feb7048a45085fd47c46
887
887
888 request to clone a single revision is respected in sharing mode
888 request to clone a single revision is respected in sharing mode
889
889
890 $ hg --config share.pool=sharerevs clone -r 4a8dc1ab4c13 source1b share-1arev
890 $ hg --config share.pool=sharerevs clone -r 4a8dc1ab4c13 source1b share-1arev
891 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
891 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
892 adding changesets
892 adding changesets
893 adding manifests
893 adding manifests
894 adding file changes
894 adding file changes
895 added 2 changesets with 2 changes to 1 files
895 added 2 changesets with 2 changes to 1 files
896 updating working directory
896 updating working directory
897 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
897 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
898 no changes found
898 no changes found
899 adding remote bookmark head1
899 adding remote bookmark head1
900
900
901 $ hg -R share-1arev log -G
901 $ hg -R share-1arev log -G
902 @ changeset: 1:4a8dc1ab4c13
902 @ changeset: 1:4a8dc1ab4c13
903 | bookmark: head1
903 | bookmark: head1
904 | tag: tip
904 | tag: tip
905 | user: test
905 | user: test
906 | date: Thu Jan 01 00:00:00 1970 +0000
906 | date: Thu Jan 01 00:00:00 1970 +0000
907 | summary: head1
907 | summary: head1
908 |
908 |
909 o changeset: 0:b5f04eac9d8f
909 o changeset: 0:b5f04eac9d8f
910 user: test
910 user: test
911 date: Thu Jan 01 00:00:00 1970 +0000
911 date: Thu Jan 01 00:00:00 1970 +0000
912 summary: initial
912 summary: initial
913
913
914
914
915 making another clone should only pull down requested rev
915 making another clone should only pull down requested rev
916
916
917 $ hg --config share.pool=sharerevs clone -r 99f71071f117 source1b share-1brev
917 $ hg --config share.pool=sharerevs clone -r 99f71071f117 source1b share-1brev
918 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
918 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
919 updating working directory
919 updating working directory
920 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
920 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
921 searching for changes
921 searching for changes
922 adding changesets
922 adding changesets
923 adding manifests
923 adding manifests
924 adding file changes
924 adding file changes
925 added 1 changesets with 1 changes to 1 files (+1 heads)
925 added 1 changesets with 1 changes to 1 files (+1 heads)
926 adding remote bookmark head1
926 adding remote bookmark head1
927 adding remote bookmark head2
927 adding remote bookmark head2
928
928
929 $ hg -R share-1brev log -G
929 $ hg -R share-1brev log -G
930 o changeset: 2:99f71071f117
930 o changeset: 2:99f71071f117
931 | bookmark: head2
931 | bookmark: head2
932 | tag: tip
932 | tag: tip
933 | parent: 0:b5f04eac9d8f
933 | parent: 0:b5f04eac9d8f
934 | user: test
934 | user: test
935 | date: Thu Jan 01 00:00:00 1970 +0000
935 | date: Thu Jan 01 00:00:00 1970 +0000
936 | summary: head2
936 | summary: head2
937 |
937 |
938 | @ changeset: 1:4a8dc1ab4c13
938 | @ changeset: 1:4a8dc1ab4c13
939 |/ bookmark: head1
939 |/ bookmark: head1
940 | user: test
940 | user: test
941 | date: Thu Jan 01 00:00:00 1970 +0000
941 | date: Thu Jan 01 00:00:00 1970 +0000
942 | summary: head1
942 | summary: head1
943 |
943 |
944 o changeset: 0:b5f04eac9d8f
944 o changeset: 0:b5f04eac9d8f
945 user: test
945 user: test
946 date: Thu Jan 01 00:00:00 1970 +0000
946 date: Thu Jan 01 00:00:00 1970 +0000
947 summary: initial
947 summary: initial
948
948
949
949
950 Request to clone a single branch is respected in sharing mode
950 Request to clone a single branch is respected in sharing mode
951
951
952 $ hg --config share.pool=sharebranch clone -b branch1 source1b share-1bbranch1
952 $ hg --config share.pool=sharebranch clone -b branch1 source1b share-1bbranch1
953 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
953 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
954 adding changesets
954 adding changesets
955 adding manifests
955 adding manifests
956 adding file changes
956 adding file changes
957 added 2 changesets with 2 changes to 1 files
957 added 2 changesets with 2 changes to 1 files
958 updating working directory
958 updating working directory
959 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
959 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
960 no changes found
960 no changes found
961
961
962 $ hg -R share-1bbranch1 log -G
962 $ hg -R share-1bbranch1 log -G
963 o changeset: 1:5f92a6c1a1b1
963 o changeset: 1:5f92a6c1a1b1
964 | branch: branch1
964 | branch: branch1
965 | tag: tip
965 | tag: tip
966 | user: test
966 | user: test
967 | date: Thu Jan 01 00:00:00 1970 +0000
967 | date: Thu Jan 01 00:00:00 1970 +0000
968 | summary: branch1
968 | summary: branch1
969 |
969 |
970 @ changeset: 0:b5f04eac9d8f
970 @ changeset: 0:b5f04eac9d8f
971 user: test
971 user: test
972 date: Thu Jan 01 00:00:00 1970 +0000
972 date: Thu Jan 01 00:00:00 1970 +0000
973 summary: initial
973 summary: initial
974
974
975
975
976 $ hg --config share.pool=sharebranch clone -b branch2 source1b share-1bbranch2
976 $ hg --config share.pool=sharebranch clone -b branch2 source1b share-1bbranch2
977 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
977 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
978 updating working directory
978 updating working directory
979 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
979 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
980 searching for changes
980 searching for changes
981 adding changesets
981 adding changesets
982 adding manifests
982 adding manifests
983 adding file changes
983 adding file changes
984 added 1 changesets with 1 changes to 1 files (+1 heads)
984 added 1 changesets with 1 changes to 1 files (+1 heads)
985
985
986 $ hg -R share-1bbranch2 log -G
986 $ hg -R share-1bbranch2 log -G
987 o changeset: 2:6bacf4683960
987 o changeset: 2:6bacf4683960
988 | branch: branch2
988 | branch: branch2
989 | tag: tip
989 | tag: tip
990 | parent: 0:b5f04eac9d8f
990 | parent: 0:b5f04eac9d8f
991 | user: test
991 | user: test
992 | date: Thu Jan 01 00:00:00 1970 +0000
992 | date: Thu Jan 01 00:00:00 1970 +0000
993 | summary: branch2
993 | summary: branch2
994 |
994 |
995 | o changeset: 1:5f92a6c1a1b1
995 | o changeset: 1:5f92a6c1a1b1
996 |/ branch: branch1
996 |/ branch: branch1
997 | user: test
997 | user: test
998 | date: Thu Jan 01 00:00:00 1970 +0000
998 | date: Thu Jan 01 00:00:00 1970 +0000
999 | summary: branch1
999 | summary: branch1
1000 |
1000 |
1001 @ changeset: 0:b5f04eac9d8f
1001 @ changeset: 0:b5f04eac9d8f
1002 user: test
1002 user: test
1003 date: Thu Jan 01 00:00:00 1970 +0000
1003 date: Thu Jan 01 00:00:00 1970 +0000
1004 summary: initial
1004 summary: initial
1005
1005
1006
1006
1007 -U is respected in share clone mode
1007 -U is respected in share clone mode
1008
1008
1009 $ hg --config share.pool=share clone -U source1a share-1anowc
1009 $ hg --config share.pool=share clone -U source1a share-1anowc
1010 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1010 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1011 searching for changes
1011 searching for changes
1012 no changes found
1012 no changes found
1013 adding remote bookmark bookA
1013 adding remote bookmark bookA
1014
1014
1015 $ ls share-1anowc
1015 $ ls share-1anowc
1016
1016
1017 Test that auto sharing doesn't cause failure of "hg clone local remote"
1017 Test that auto sharing doesn't cause failure of "hg clone local remote"
1018
1018
1019 $ cd $TESTTMP
1019 $ cd $TESTTMP
1020 $ hg -R a id -r 0
1020 $ hg -R a id -r 0
1021 acb14030fe0a
1021 acb14030fe0a
1022 $ hg id -R remote -r 0
1022 $ hg id -R remote -r 0
1023 abort: repository remote not found!
1023 abort: repository remote not found!
1024 [255]
1024 [255]
1025 $ hg --config share.pool=share -q clone -e "python \"$TESTDIR/dummyssh\"" a ssh://user@dummy/remote
1025 $ hg --config share.pool=share -q clone -e "python \"$TESTDIR/dummyssh\"" a ssh://user@dummy/remote
1026 $ hg -R remote id -r 0
1026 $ hg -R remote id -r 0
1027 acb14030fe0a
1027 acb14030fe0a
1028
1029 Cloning into pooled storage doesn't race (issue5104)
1030
1031 $ HGPOSTLOCKDELAY=2.0 hg --config share.pool=racepool --config extensions.lockdelay=$TESTDIR/lockdelay.py clone source1a share-destrace1 > race1.log 2>&1 &
1032 $ HGPRELOCKDELAY=1.0 hg --config share.pool=racepool --config extensions.lockdelay=$TESTDIR/lockdelay.py clone source1a share-destrace2 > race2.log 2>&1
1033 $ wait
1034
1035 $ hg -R share-destrace1 log -r tip
1036 changeset: 2:e5bfe23c0b47
1037 bookmark: bookA
1038 tag: tip
1039 user: test
1040 date: Thu Jan 01 00:00:00 1970 +0000
1041 summary: 1a
1042
1043
1044 $ hg -R share-destrace2 log -r tip
1045 changeset: 2:e5bfe23c0b47
1046 bookmark: bookA
1047 tag: tip
1048 user: test
1049 date: Thu Jan 01 00:00:00 1970 +0000
1050 summary: 1a
1051
1052 $ cat race1.log
1053 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1054 requesting all changes
1055 adding changesets
1056 adding manifests
1057 adding file changes
1058 added 3 changesets with 3 changes to 1 files
1059 updating working directory
1060 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1061 searching for changes
1062 no changes found
1063 adding remote bookmark bookA
1064
1065 $ cat race2.log
1066 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1067 updating working directory
1068 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1069 waiting for lock on repository share-destrace2 held by * (glob)
1070 got lock after \d+ seconds (re)
1071 searching for changes
1072 no changes found
1073 adding remote bookmark bookA
General Comments 1
Approved

Looks good

You need to be logged in to leave comments. Login now