##// END OF EJS Templates
clone: update to @ bookmark if it exists
Kevin Bullock -
r17756:92980a8d default
parent child Browse files
Show More
@@ -1,610 +1,610 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 i18n import _
9 from i18n import _
10 from lock import release
10 from lock import release
11 from node import hex, nullid
11 from node import hex, nullid
12 import localrepo, bundlerepo, httppeer, sshpeer, statichttprepo, bookmarks
12 import localrepo, bundlerepo, httppeer, sshpeer, statichttprepo, bookmarks
13 import lock, util, extensions, error, node, scmutil, phases
13 import lock, util, extensions, error, node, scmutil, phases
14 import cmdutil, discovery
14 import cmdutil, discovery
15 import merge as mergemod
15 import merge as mergemod
16 import verify as verifymod
16 import verify as verifymod
17 import errno, os, shutil
17 import errno, os, shutil
18
18
19 def _local(path):
19 def _local(path):
20 path = util.expandpath(util.urllocalpath(path))
20 path = util.expandpath(util.urllocalpath(path))
21 return (os.path.isfile(path) and bundlerepo or localrepo)
21 return (os.path.isfile(path) and bundlerepo or localrepo)
22
22
23 def addbranchrevs(lrepo, other, branches, revs):
23 def addbranchrevs(lrepo, other, branches, revs):
24 peer = other.peer() # a courtesy to callers using a localrepo for other
24 peer = other.peer() # a courtesy to callers using a localrepo for other
25 hashbranch, branches = branches
25 hashbranch, branches = branches
26 if not hashbranch and not branches:
26 if not hashbranch and not branches:
27 return revs or None, revs and revs[0] or None
27 return revs or None, revs and revs[0] or None
28 revs = revs and list(revs) or []
28 revs = revs and list(revs) or []
29 if not peer.capable('branchmap'):
29 if not peer.capable('branchmap'):
30 if branches:
30 if branches:
31 raise util.Abort(_("remote branch lookup not supported"))
31 raise util.Abort(_("remote branch lookup not supported"))
32 revs.append(hashbranch)
32 revs.append(hashbranch)
33 return revs, revs[0]
33 return revs, revs[0]
34 branchmap = peer.branchmap()
34 branchmap = peer.branchmap()
35
35
36 def primary(branch):
36 def primary(branch):
37 if branch == '.':
37 if branch == '.':
38 if not lrepo:
38 if not lrepo:
39 raise util.Abort(_("dirstate branch not accessible"))
39 raise util.Abort(_("dirstate branch not accessible"))
40 branch = lrepo.dirstate.branch()
40 branch = lrepo.dirstate.branch()
41 if branch in branchmap:
41 if branch in branchmap:
42 revs.extend(node.hex(r) for r in reversed(branchmap[branch]))
42 revs.extend(node.hex(r) for r in reversed(branchmap[branch]))
43 return True
43 return True
44 else:
44 else:
45 return False
45 return False
46
46
47 for branch in branches:
47 for branch in branches:
48 if not primary(branch):
48 if not primary(branch):
49 raise error.RepoLookupError(_("unknown branch '%s'") % branch)
49 raise error.RepoLookupError(_("unknown branch '%s'") % branch)
50 if hashbranch:
50 if hashbranch:
51 if not primary(hashbranch):
51 if not primary(hashbranch):
52 revs.append(hashbranch)
52 revs.append(hashbranch)
53 return revs, revs[0]
53 return revs, revs[0]
54
54
55 def parseurl(path, branches=None):
55 def parseurl(path, branches=None):
56 '''parse url#branch, returning (url, (branch, branches))'''
56 '''parse url#branch, returning (url, (branch, branches))'''
57
57
58 u = util.url(path)
58 u = util.url(path)
59 branch = None
59 branch = None
60 if u.fragment:
60 if u.fragment:
61 branch = u.fragment
61 branch = u.fragment
62 u.fragment = None
62 u.fragment = None
63 return str(u), (branch, branches or [])
63 return str(u), (branch, branches or [])
64
64
65 schemes = {
65 schemes = {
66 'bundle': bundlerepo,
66 'bundle': bundlerepo,
67 'file': _local,
67 'file': _local,
68 'http': httppeer,
68 'http': httppeer,
69 'https': httppeer,
69 'https': httppeer,
70 'ssh': sshpeer,
70 'ssh': sshpeer,
71 'static-http': statichttprepo,
71 'static-http': statichttprepo,
72 }
72 }
73
73
74 def _peerlookup(path):
74 def _peerlookup(path):
75 u = util.url(path)
75 u = util.url(path)
76 scheme = u.scheme or 'file'
76 scheme = u.scheme or 'file'
77 thing = schemes.get(scheme) or schemes['file']
77 thing = schemes.get(scheme) or schemes['file']
78 try:
78 try:
79 return thing(path)
79 return thing(path)
80 except TypeError:
80 except TypeError:
81 return thing
81 return thing
82
82
83 def islocal(repo):
83 def islocal(repo):
84 '''return true if repo or path is local'''
84 '''return true if repo or path is local'''
85 if isinstance(repo, str):
85 if isinstance(repo, str):
86 try:
86 try:
87 return _peerlookup(repo).islocal(repo)
87 return _peerlookup(repo).islocal(repo)
88 except AttributeError:
88 except AttributeError:
89 return False
89 return False
90 return repo.local()
90 return repo.local()
91
91
92 def _peerorrepo(ui, path, create=False):
92 def _peerorrepo(ui, path, create=False):
93 """return a repository object for the specified path"""
93 """return a repository object for the specified path"""
94 obj = _peerlookup(path).instance(ui, path, create)
94 obj = _peerlookup(path).instance(ui, path, create)
95 ui = getattr(obj, "ui", ui)
95 ui = getattr(obj, "ui", ui)
96 for name, module in extensions.extensions():
96 for name, module in extensions.extensions():
97 hook = getattr(module, 'reposetup', None)
97 hook = getattr(module, 'reposetup', None)
98 if hook:
98 if hook:
99 hook(ui, obj)
99 hook(ui, obj)
100 return obj
100 return obj
101
101
102 def repository(ui, path='', create=False):
102 def repository(ui, path='', create=False):
103 """return a repository object for the specified path"""
103 """return a repository object for the specified path"""
104 peer = _peerorrepo(ui, path, create)
104 peer = _peerorrepo(ui, path, create)
105 repo = peer.local()
105 repo = peer.local()
106 if not repo:
106 if not repo:
107 raise util.Abort(_("repository '%s' is not local") %
107 raise util.Abort(_("repository '%s' is not local") %
108 (path or peer.url()))
108 (path or peer.url()))
109 return repo
109 return repo
110
110
111 def peer(uiorrepo, opts, path, create=False):
111 def peer(uiorrepo, opts, path, create=False):
112 '''return a repository peer for the specified path'''
112 '''return a repository peer for the specified path'''
113 rui = remoteui(uiorrepo, opts)
113 rui = remoteui(uiorrepo, opts)
114 return _peerorrepo(rui, path, create).peer()
114 return _peerorrepo(rui, path, create).peer()
115
115
116 def defaultdest(source):
116 def defaultdest(source):
117 '''return default destination of clone if none is given'''
117 '''return default destination of clone if none is given'''
118 return os.path.basename(os.path.normpath(source))
118 return os.path.basename(os.path.normpath(source))
119
119
120 def share(ui, source, dest=None, update=True):
120 def share(ui, source, dest=None, update=True):
121 '''create a shared repository'''
121 '''create a shared repository'''
122
122
123 if not islocal(source):
123 if not islocal(source):
124 raise util.Abort(_('can only share local repositories'))
124 raise util.Abort(_('can only share local repositories'))
125
125
126 if not dest:
126 if not dest:
127 dest = defaultdest(source)
127 dest = defaultdest(source)
128 else:
128 else:
129 dest = ui.expandpath(dest)
129 dest = ui.expandpath(dest)
130
130
131 if isinstance(source, str):
131 if isinstance(source, str):
132 origsource = ui.expandpath(source)
132 origsource = ui.expandpath(source)
133 source, branches = parseurl(origsource)
133 source, branches = parseurl(origsource)
134 srcrepo = repository(ui, source)
134 srcrepo = repository(ui, source)
135 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
135 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
136 else:
136 else:
137 srcrepo = source.local()
137 srcrepo = source.local()
138 origsource = source = srcrepo.url()
138 origsource = source = srcrepo.url()
139 checkout = None
139 checkout = None
140
140
141 sharedpath = srcrepo.sharedpath # if our source is already sharing
141 sharedpath = srcrepo.sharedpath # if our source is already sharing
142
142
143 root = os.path.realpath(dest)
143 root = os.path.realpath(dest)
144 roothg = os.path.join(root, '.hg')
144 roothg = os.path.join(root, '.hg')
145
145
146 if os.path.exists(roothg):
146 if os.path.exists(roothg):
147 raise util.Abort(_('destination already exists'))
147 raise util.Abort(_('destination already exists'))
148
148
149 if not os.path.isdir(root):
149 if not os.path.isdir(root):
150 os.mkdir(root)
150 os.mkdir(root)
151 util.makedir(roothg, notindexed=True)
151 util.makedir(roothg, notindexed=True)
152
152
153 requirements = ''
153 requirements = ''
154 try:
154 try:
155 requirements = srcrepo.opener.read('requires')
155 requirements = srcrepo.opener.read('requires')
156 except IOError, inst:
156 except IOError, inst:
157 if inst.errno != errno.ENOENT:
157 if inst.errno != errno.ENOENT:
158 raise
158 raise
159
159
160 requirements += 'shared\n'
160 requirements += 'shared\n'
161 util.writefile(os.path.join(roothg, 'requires'), requirements)
161 util.writefile(os.path.join(roothg, 'requires'), requirements)
162 util.writefile(os.path.join(roothg, 'sharedpath'), sharedpath)
162 util.writefile(os.path.join(roothg, 'sharedpath'), sharedpath)
163
163
164 r = repository(ui, root)
164 r = repository(ui, root)
165
165
166 default = srcrepo.ui.config('paths', 'default')
166 default = srcrepo.ui.config('paths', 'default')
167 if default:
167 if default:
168 fp = r.opener("hgrc", "w", text=True)
168 fp = r.opener("hgrc", "w", text=True)
169 fp.write("[paths]\n")
169 fp.write("[paths]\n")
170 fp.write("default = %s\n" % default)
170 fp.write("default = %s\n" % default)
171 fp.close()
171 fp.close()
172
172
173 if update:
173 if update:
174 r.ui.status(_("updating working directory\n"))
174 r.ui.status(_("updating working directory\n"))
175 if update is not True:
175 if update is not True:
176 checkout = update
176 checkout = update
177 for test in (checkout, 'default', 'tip'):
177 for test in (checkout, 'default', 'tip'):
178 if test is None:
178 if test is None:
179 continue
179 continue
180 try:
180 try:
181 uprev = r.lookup(test)
181 uprev = r.lookup(test)
182 break
182 break
183 except error.RepoLookupError:
183 except error.RepoLookupError:
184 continue
184 continue
185 _update(r, uprev)
185 _update(r, uprev)
186
186
187 def copystore(ui, srcrepo, destpath):
187 def copystore(ui, srcrepo, destpath):
188 '''copy files from store of srcrepo in destpath
188 '''copy files from store of srcrepo in destpath
189
189
190 returns destlock
190 returns destlock
191 '''
191 '''
192 destlock = None
192 destlock = None
193 try:
193 try:
194 hardlink = None
194 hardlink = None
195 num = 0
195 num = 0
196 srcpublishing = srcrepo.ui.configbool('phases', 'publish', True)
196 srcpublishing = srcrepo.ui.configbool('phases', 'publish', True)
197 for f in srcrepo.store.copylist():
197 for f in srcrepo.store.copylist():
198 if srcpublishing and f.endswith('phaseroots'):
198 if srcpublishing and f.endswith('phaseroots'):
199 continue
199 continue
200 src = os.path.join(srcrepo.sharedpath, f)
200 src = os.path.join(srcrepo.sharedpath, f)
201 dst = os.path.join(destpath, f)
201 dst = os.path.join(destpath, f)
202 dstbase = os.path.dirname(dst)
202 dstbase = os.path.dirname(dst)
203 if dstbase and not os.path.exists(dstbase):
203 if dstbase and not os.path.exists(dstbase):
204 os.mkdir(dstbase)
204 os.mkdir(dstbase)
205 if os.path.exists(src):
205 if os.path.exists(src):
206 if dst.endswith('data'):
206 if dst.endswith('data'):
207 # lock to avoid premature writing to the target
207 # lock to avoid premature writing to the target
208 destlock = lock.lock(os.path.join(dstbase, "lock"))
208 destlock = lock.lock(os.path.join(dstbase, "lock"))
209 hardlink, n = util.copyfiles(src, dst, hardlink)
209 hardlink, n = util.copyfiles(src, dst, hardlink)
210 num += n
210 num += n
211 if hardlink:
211 if hardlink:
212 ui.debug("linked %d files\n" % num)
212 ui.debug("linked %d files\n" % num)
213 else:
213 else:
214 ui.debug("copied %d files\n" % num)
214 ui.debug("copied %d files\n" % num)
215 return destlock
215 return destlock
216 except: # re-raises
216 except: # re-raises
217 release(destlock)
217 release(destlock)
218 raise
218 raise
219
219
220 def clone(ui, peeropts, source, dest=None, pull=False, rev=None,
220 def clone(ui, peeropts, source, dest=None, pull=False, rev=None,
221 update=True, stream=False, branch=None):
221 update=True, stream=False, branch=None):
222 """Make a copy of an existing repository.
222 """Make a copy of an existing repository.
223
223
224 Create a copy of an existing repository in a new directory. The
224 Create a copy of an existing repository in a new directory. The
225 source and destination are URLs, as passed to the repository
225 source and destination are URLs, as passed to the repository
226 function. Returns a pair of repository peers, the source and
226 function. Returns a pair of repository peers, the source and
227 newly created destination.
227 newly created destination.
228
228
229 The location of the source is added to the new repository's
229 The location of the source is added to the new repository's
230 .hg/hgrc file, as the default to be used for future pulls and
230 .hg/hgrc file, as the default to be used for future pulls and
231 pushes.
231 pushes.
232
232
233 If an exception is raised, the partly cloned/updated destination
233 If an exception is raised, the partly cloned/updated destination
234 repository will be deleted.
234 repository will be deleted.
235
235
236 Arguments:
236 Arguments:
237
237
238 source: repository object or URL
238 source: repository object or URL
239
239
240 dest: URL of destination repository to create (defaults to base
240 dest: URL of destination repository to create (defaults to base
241 name of source repository)
241 name of source repository)
242
242
243 pull: always pull from source repository, even in local case
243 pull: always pull from source repository, even in local case
244
244
245 stream: stream raw data uncompressed from repository (fast over
245 stream: stream raw data uncompressed from repository (fast over
246 LAN, slow over WAN)
246 LAN, slow over WAN)
247
247
248 rev: revision to clone up to (implies pull=True)
248 rev: revision to clone up to (implies pull=True)
249
249
250 update: update working directory after clone completes, if
250 update: update working directory after clone completes, if
251 destination is local repository (True means update to default rev,
251 destination is local repository (True means update to default rev,
252 anything else is treated as a revision)
252 anything else is treated as a revision)
253
253
254 branch: branches to clone
254 branch: branches to clone
255 """
255 """
256
256
257 if isinstance(source, str):
257 if isinstance(source, str):
258 origsource = ui.expandpath(source)
258 origsource = ui.expandpath(source)
259 source, branch = parseurl(origsource, branch)
259 source, branch = parseurl(origsource, branch)
260 srcpeer = peer(ui, peeropts, source)
260 srcpeer = peer(ui, peeropts, source)
261 else:
261 else:
262 srcpeer = source.peer() # in case we were called with a localrepo
262 srcpeer = source.peer() # in case we were called with a localrepo
263 branch = (None, branch or [])
263 branch = (None, branch or [])
264 origsource = source = srcpeer.url()
264 origsource = source = srcpeer.url()
265 rev, checkout = addbranchrevs(srcpeer, srcpeer, branch, rev)
265 rev, checkout = addbranchrevs(srcpeer, srcpeer, branch, rev)
266
266
267 if dest is None:
267 if dest is None:
268 dest = defaultdest(source)
268 dest = defaultdest(source)
269 ui.status(_("destination directory: %s\n") % dest)
269 ui.status(_("destination directory: %s\n") % dest)
270 else:
270 else:
271 dest = ui.expandpath(dest)
271 dest = ui.expandpath(dest)
272
272
273 dest = util.urllocalpath(dest)
273 dest = util.urllocalpath(dest)
274 source = util.urllocalpath(source)
274 source = util.urllocalpath(source)
275
275
276 if not dest:
276 if not dest:
277 raise util.Abort(_("empty destination path is not valid"))
277 raise util.Abort(_("empty destination path is not valid"))
278 if os.path.exists(dest):
278 if os.path.exists(dest):
279 if not os.path.isdir(dest):
279 if not os.path.isdir(dest):
280 raise util.Abort(_("destination '%s' already exists") % dest)
280 raise util.Abort(_("destination '%s' already exists") % dest)
281 elif os.listdir(dest):
281 elif os.listdir(dest):
282 raise util.Abort(_("destination '%s' is not empty") % dest)
282 raise util.Abort(_("destination '%s' is not empty") % dest)
283
283
284 class DirCleanup(object):
284 class DirCleanup(object):
285 def __init__(self, dir_):
285 def __init__(self, dir_):
286 self.rmtree = shutil.rmtree
286 self.rmtree = shutil.rmtree
287 self.dir_ = dir_
287 self.dir_ = dir_
288 def close(self):
288 def close(self):
289 self.dir_ = None
289 self.dir_ = None
290 def cleanup(self):
290 def cleanup(self):
291 if self.dir_:
291 if self.dir_:
292 self.rmtree(self.dir_, True)
292 self.rmtree(self.dir_, True)
293
293
294 srclock = destlock = dircleanup = None
294 srclock = destlock = dircleanup = None
295 srcrepo = srcpeer.local()
295 srcrepo = srcpeer.local()
296 try:
296 try:
297 abspath = origsource
297 abspath = origsource
298 if islocal(origsource):
298 if islocal(origsource):
299 abspath = os.path.abspath(util.urllocalpath(origsource))
299 abspath = os.path.abspath(util.urllocalpath(origsource))
300
300
301 if islocal(dest):
301 if islocal(dest):
302 dircleanup = DirCleanup(dest)
302 dircleanup = DirCleanup(dest)
303
303
304 copy = False
304 copy = False
305 if (srcrepo and srcrepo.cancopy() and islocal(dest)
305 if (srcrepo and srcrepo.cancopy() and islocal(dest)
306 and not phases.hassecret(srcrepo)):
306 and not phases.hassecret(srcrepo)):
307 copy = not pull and not rev
307 copy = not pull and not rev
308
308
309 if copy:
309 if copy:
310 try:
310 try:
311 # we use a lock here because if we race with commit, we
311 # we use a lock here because if we race with commit, we
312 # can end up with extra data in the cloned revlogs that's
312 # can end up with extra data in the cloned revlogs that's
313 # not pointed to by changesets, thus causing verify to
313 # not pointed to by changesets, thus causing verify to
314 # fail
314 # fail
315 srclock = srcrepo.lock(wait=False)
315 srclock = srcrepo.lock(wait=False)
316 except error.LockError:
316 except error.LockError:
317 copy = False
317 copy = False
318
318
319 if copy:
319 if copy:
320 srcrepo.hook('preoutgoing', throw=True, source='clone')
320 srcrepo.hook('preoutgoing', throw=True, source='clone')
321 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
321 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
322 if not os.path.exists(dest):
322 if not os.path.exists(dest):
323 os.mkdir(dest)
323 os.mkdir(dest)
324 else:
324 else:
325 # only clean up directories we create ourselves
325 # only clean up directories we create ourselves
326 dircleanup.dir_ = hgdir
326 dircleanup.dir_ = hgdir
327 try:
327 try:
328 destpath = hgdir
328 destpath = hgdir
329 util.makedir(destpath, notindexed=True)
329 util.makedir(destpath, notindexed=True)
330 except OSError, inst:
330 except OSError, inst:
331 if inst.errno == errno.EEXIST:
331 if inst.errno == errno.EEXIST:
332 dircleanup.close()
332 dircleanup.close()
333 raise util.Abort(_("destination '%s' already exists")
333 raise util.Abort(_("destination '%s' already exists")
334 % dest)
334 % dest)
335 raise
335 raise
336
336
337 destlock = copystore(ui, srcrepo, destpath)
337 destlock = copystore(ui, srcrepo, destpath)
338
338
339 # Recomputing branch cache might be slow on big repos,
339 # Recomputing branch cache might be slow on big repos,
340 # so just copy it
340 # so just copy it
341 dstcachedir = os.path.join(destpath, 'cache')
341 dstcachedir = os.path.join(destpath, 'cache')
342 srcbranchcache = srcrepo.sjoin('cache/branchheads')
342 srcbranchcache = srcrepo.sjoin('cache/branchheads')
343 dstbranchcache = os.path.join(dstcachedir, 'branchheads')
343 dstbranchcache = os.path.join(dstcachedir, 'branchheads')
344 if os.path.exists(srcbranchcache):
344 if os.path.exists(srcbranchcache):
345 if not os.path.exists(dstcachedir):
345 if not os.path.exists(dstcachedir):
346 os.mkdir(dstcachedir)
346 os.mkdir(dstcachedir)
347 util.copyfile(srcbranchcache, dstbranchcache)
347 util.copyfile(srcbranchcache, dstbranchcache)
348
348
349 # we need to re-init the repo after manually copying the data
349 # we need to re-init the repo after manually copying the data
350 # into it
350 # into it
351 destpeer = peer(ui, peeropts, dest)
351 destpeer = peer(ui, peeropts, dest)
352 srcrepo.hook('outgoing', source='clone',
352 srcrepo.hook('outgoing', source='clone',
353 node=node.hex(node.nullid))
353 node=node.hex(node.nullid))
354 else:
354 else:
355 try:
355 try:
356 destpeer = peer(ui, peeropts, dest, create=True)
356 destpeer = peer(ui, peeropts, dest, create=True)
357 except OSError, inst:
357 except OSError, inst:
358 if inst.errno == errno.EEXIST:
358 if inst.errno == errno.EEXIST:
359 dircleanup.close()
359 dircleanup.close()
360 raise util.Abort(_("destination '%s' already exists")
360 raise util.Abort(_("destination '%s' already exists")
361 % dest)
361 % dest)
362 raise
362 raise
363
363
364 revs = None
364 revs = None
365 if rev:
365 if rev:
366 if not srcpeer.capable('lookup'):
366 if not srcpeer.capable('lookup'):
367 raise util.Abort(_("src repository does not support "
367 raise util.Abort(_("src repository does not support "
368 "revision lookup and so doesn't "
368 "revision lookup and so doesn't "
369 "support clone by revision"))
369 "support clone by revision"))
370 revs = [srcpeer.lookup(r) for r in rev]
370 revs = [srcpeer.lookup(r) for r in rev]
371 checkout = revs[0]
371 checkout = revs[0]
372 if destpeer.local():
372 if destpeer.local():
373 destpeer.local().clone(srcpeer, heads=revs, stream=stream)
373 destpeer.local().clone(srcpeer, heads=revs, stream=stream)
374 elif srcrepo:
374 elif srcrepo:
375 srcrepo.push(destpeer, revs=revs)
375 srcrepo.push(destpeer, revs=revs)
376 else:
376 else:
377 raise util.Abort(_("clone from remote to remote not supported"))
377 raise util.Abort(_("clone from remote to remote not supported"))
378
378
379 if dircleanup:
379 if dircleanup:
380 dircleanup.close()
380 dircleanup.close()
381
381
382 # clone all bookmarks except divergent ones
382 # clone all bookmarks except divergent ones
383 destrepo = destpeer.local()
383 destrepo = destpeer.local()
384 if destrepo and srcpeer.capable("pushkey"):
384 if destrepo and srcpeer.capable("pushkey"):
385 rb = srcpeer.listkeys('bookmarks')
385 rb = srcpeer.listkeys('bookmarks')
386 for k, n in rb.iteritems():
386 for k, n in rb.iteritems():
387 try:
387 try:
388 m = destrepo.lookup(n)
388 m = destrepo.lookup(n)
389 destrepo._bookmarks[k] = m
389 destrepo._bookmarks[k] = m
390 except error.RepoLookupError:
390 except error.RepoLookupError:
391 pass
391 pass
392 if rb:
392 if rb:
393 bookmarks.write(destrepo)
393 bookmarks.write(destrepo)
394 elif srcrepo and destpeer.capable("pushkey"):
394 elif srcrepo and destpeer.capable("pushkey"):
395 for k, n in srcrepo._bookmarks.iteritems():
395 for k, n in srcrepo._bookmarks.iteritems():
396 destpeer.pushkey('bookmarks', k, '', hex(n))
396 destpeer.pushkey('bookmarks', k, '', hex(n))
397
397
398 if destrepo:
398 if destrepo:
399 fp = destrepo.opener("hgrc", "w", text=True)
399 fp = destrepo.opener("hgrc", "w", text=True)
400 fp.write("[paths]\n")
400 fp.write("[paths]\n")
401 u = util.url(abspath)
401 u = util.url(abspath)
402 u.passwd = None
402 u.passwd = None
403 defaulturl = str(u)
403 defaulturl = str(u)
404 fp.write("default = %s\n" % defaulturl)
404 fp.write("default = %s\n" % defaulturl)
405 fp.close()
405 fp.close()
406
406
407 destrepo.ui.setconfig('paths', 'default', defaulturl)
407 destrepo.ui.setconfig('paths', 'default', defaulturl)
408
408
409 if update:
409 if update:
410 if update is not True:
410 if update is not True:
411 checkout = srcpeer.lookup(update)
411 checkout = srcpeer.lookup(update)
412 for test in (checkout, 'default', 'tip'):
412 for test in (checkout, '@', 'default', 'tip'):
413 if test is None:
413 if test is None:
414 continue
414 continue
415 try:
415 try:
416 uprev = destrepo.lookup(test)
416 uprev = destrepo.lookup(test)
417 break
417 break
418 except error.RepoLookupError:
418 except error.RepoLookupError:
419 continue
419 continue
420 bn = destrepo[uprev].branch()
420 bn = destrepo[uprev].branch()
421 destrepo.ui.status(_("updating to branch %s\n") % bn)
421 destrepo.ui.status(_("updating to branch %s\n") % bn)
422 _update(destrepo, uprev)
422 _update(destrepo, uprev)
423 if update in destrepo._bookmarks:
423 if update in destrepo._bookmarks:
424 bookmarks.setcurrent(destrepo, update)
424 bookmarks.setcurrent(destrepo, update)
425
425
426 return srcpeer, destpeer
426 return srcpeer, destpeer
427 finally:
427 finally:
428 release(srclock, destlock)
428 release(srclock, destlock)
429 if dircleanup is not None:
429 if dircleanup is not None:
430 dircleanup.cleanup()
430 dircleanup.cleanup()
431 if srcpeer is not None:
431 if srcpeer is not None:
432 srcpeer.close()
432 srcpeer.close()
433
433
434 def _showstats(repo, stats):
434 def _showstats(repo, stats):
435 repo.ui.status(_("%d files updated, %d files merged, "
435 repo.ui.status(_("%d files updated, %d files merged, "
436 "%d files removed, %d files unresolved\n") % stats)
436 "%d files removed, %d files unresolved\n") % stats)
437
437
438 def update(repo, node):
438 def update(repo, node):
439 """update the working directory to node, merging linear changes"""
439 """update the working directory to node, merging linear changes"""
440 stats = mergemod.update(repo, node, False, False, None)
440 stats = mergemod.update(repo, node, False, False, None)
441 _showstats(repo, stats)
441 _showstats(repo, stats)
442 if stats[3]:
442 if stats[3]:
443 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
443 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
444 return stats[3] > 0
444 return stats[3] > 0
445
445
446 # naming conflict in clone()
446 # naming conflict in clone()
447 _update = update
447 _update = update
448
448
449 def clean(repo, node, show_stats=True):
449 def clean(repo, node, show_stats=True):
450 """forcibly switch the working directory to node, clobbering changes"""
450 """forcibly switch the working directory to node, clobbering changes"""
451 stats = mergemod.update(repo, node, False, True, None)
451 stats = mergemod.update(repo, node, False, True, None)
452 if show_stats:
452 if show_stats:
453 _showstats(repo, stats)
453 _showstats(repo, stats)
454 return stats[3] > 0
454 return stats[3] > 0
455
455
456 def merge(repo, node, force=None, remind=True):
456 def merge(repo, node, force=None, remind=True):
457 """Branch merge with node, resolving changes. Return true if any
457 """Branch merge with node, resolving changes. Return true if any
458 unresolved conflicts."""
458 unresolved conflicts."""
459 stats = mergemod.update(repo, node, True, force, False)
459 stats = mergemod.update(repo, node, True, force, False)
460 _showstats(repo, stats)
460 _showstats(repo, stats)
461 if stats[3]:
461 if stats[3]:
462 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
462 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
463 "or 'hg update -C .' to abandon\n"))
463 "or 'hg update -C .' to abandon\n"))
464 elif remind:
464 elif remind:
465 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
465 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
466 return stats[3] > 0
466 return stats[3] > 0
467
467
468 def _incoming(displaychlist, subreporecurse, ui, repo, source,
468 def _incoming(displaychlist, subreporecurse, ui, repo, source,
469 opts, buffered=False):
469 opts, buffered=False):
470 """
470 """
471 Helper for incoming / gincoming.
471 Helper for incoming / gincoming.
472 displaychlist gets called with
472 displaychlist gets called with
473 (remoterepo, incomingchangesetlist, displayer) parameters,
473 (remoterepo, incomingchangesetlist, displayer) parameters,
474 and is supposed to contain only code that can't be unified.
474 and is supposed to contain only code that can't be unified.
475 """
475 """
476 source, branches = parseurl(ui.expandpath(source), opts.get('branch'))
476 source, branches = parseurl(ui.expandpath(source), opts.get('branch'))
477 other = peer(repo, opts, source)
477 other = peer(repo, opts, source)
478 ui.status(_('comparing with %s\n') % util.hidepassword(source))
478 ui.status(_('comparing with %s\n') % util.hidepassword(source))
479 revs, checkout = addbranchrevs(repo, other, branches, opts.get('rev'))
479 revs, checkout = addbranchrevs(repo, other, branches, opts.get('rev'))
480
480
481 if revs:
481 if revs:
482 revs = [other.lookup(rev) for rev in revs]
482 revs = [other.lookup(rev) for rev in revs]
483 other, chlist, cleanupfn = bundlerepo.getremotechanges(ui, repo, other,
483 other, chlist, cleanupfn = bundlerepo.getremotechanges(ui, repo, other,
484 revs, opts["bundle"], opts["force"])
484 revs, opts["bundle"], opts["force"])
485 try:
485 try:
486 if not chlist:
486 if not chlist:
487 ui.status(_("no changes found\n"))
487 ui.status(_("no changes found\n"))
488 return subreporecurse()
488 return subreporecurse()
489
489
490 displayer = cmdutil.show_changeset(ui, other, opts, buffered)
490 displayer = cmdutil.show_changeset(ui, other, opts, buffered)
491
491
492 # XXX once graphlog extension makes it into core,
492 # XXX once graphlog extension makes it into core,
493 # should be replaced by a if graph/else
493 # should be replaced by a if graph/else
494 displaychlist(other, chlist, displayer)
494 displaychlist(other, chlist, displayer)
495
495
496 displayer.close()
496 displayer.close()
497 finally:
497 finally:
498 cleanupfn()
498 cleanupfn()
499 subreporecurse()
499 subreporecurse()
500 return 0 # exit code is zero since we found incoming changes
500 return 0 # exit code is zero since we found incoming changes
501
501
502 def incoming(ui, repo, source, opts):
502 def incoming(ui, repo, source, opts):
503 def subreporecurse():
503 def subreporecurse():
504 ret = 1
504 ret = 1
505 if opts.get('subrepos'):
505 if opts.get('subrepos'):
506 ctx = repo[None]
506 ctx = repo[None]
507 for subpath in sorted(ctx.substate):
507 for subpath in sorted(ctx.substate):
508 sub = ctx.sub(subpath)
508 sub = ctx.sub(subpath)
509 ret = min(ret, sub.incoming(ui, source, opts))
509 ret = min(ret, sub.incoming(ui, source, opts))
510 return ret
510 return ret
511
511
512 def display(other, chlist, displayer):
512 def display(other, chlist, displayer):
513 limit = cmdutil.loglimit(opts)
513 limit = cmdutil.loglimit(opts)
514 if opts.get('newest_first'):
514 if opts.get('newest_first'):
515 chlist.reverse()
515 chlist.reverse()
516 count = 0
516 count = 0
517 for n in chlist:
517 for n in chlist:
518 if limit is not None and count >= limit:
518 if limit is not None and count >= limit:
519 break
519 break
520 parents = [p for p in other.changelog.parents(n) if p != nullid]
520 parents = [p for p in other.changelog.parents(n) if p != nullid]
521 if opts.get('no_merges') and len(parents) == 2:
521 if opts.get('no_merges') and len(parents) == 2:
522 continue
522 continue
523 count += 1
523 count += 1
524 displayer.show(other[n])
524 displayer.show(other[n])
525 return _incoming(display, subreporecurse, ui, repo, source, opts)
525 return _incoming(display, subreporecurse, ui, repo, source, opts)
526
526
527 def _outgoing(ui, repo, dest, opts):
527 def _outgoing(ui, repo, dest, opts):
528 dest = ui.expandpath(dest or 'default-push', dest or 'default')
528 dest = ui.expandpath(dest or 'default-push', dest or 'default')
529 dest, branches = parseurl(dest, opts.get('branch'))
529 dest, branches = parseurl(dest, opts.get('branch'))
530 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
530 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
531 revs, checkout = addbranchrevs(repo, repo, branches, opts.get('rev'))
531 revs, checkout = addbranchrevs(repo, repo, branches, opts.get('rev'))
532 if revs:
532 if revs:
533 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
533 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
534
534
535 other = peer(repo, opts, dest)
535 other = peer(repo, opts, dest)
536 outgoing = discovery.findcommonoutgoing(repo, other, revs,
536 outgoing = discovery.findcommonoutgoing(repo, other, revs,
537 force=opts.get('force'))
537 force=opts.get('force'))
538 o = outgoing.missing
538 o = outgoing.missing
539 if not o:
539 if not o:
540 scmutil.nochangesfound(repo.ui, repo, outgoing.excluded)
540 scmutil.nochangesfound(repo.ui, repo, outgoing.excluded)
541 return None
541 return None
542 return o
542 return o
543
543
544 def outgoing(ui, repo, dest, opts):
544 def outgoing(ui, repo, dest, opts):
545 def recurse():
545 def recurse():
546 ret = 1
546 ret = 1
547 if opts.get('subrepos'):
547 if opts.get('subrepos'):
548 ctx = repo[None]
548 ctx = repo[None]
549 for subpath in sorted(ctx.substate):
549 for subpath in sorted(ctx.substate):
550 sub = ctx.sub(subpath)
550 sub = ctx.sub(subpath)
551 ret = min(ret, sub.outgoing(ui, dest, opts))
551 ret = min(ret, sub.outgoing(ui, dest, opts))
552 return ret
552 return ret
553
553
554 limit = cmdutil.loglimit(opts)
554 limit = cmdutil.loglimit(opts)
555 o = _outgoing(ui, repo, dest, opts)
555 o = _outgoing(ui, repo, dest, opts)
556 if o is None:
556 if o is None:
557 return recurse()
557 return recurse()
558
558
559 if opts.get('newest_first'):
559 if opts.get('newest_first'):
560 o.reverse()
560 o.reverse()
561 displayer = cmdutil.show_changeset(ui, repo, opts)
561 displayer = cmdutil.show_changeset(ui, repo, opts)
562 count = 0
562 count = 0
563 for n in o:
563 for n in o:
564 if limit is not None and count >= limit:
564 if limit is not None and count >= limit:
565 break
565 break
566 parents = [p for p in repo.changelog.parents(n) if p != nullid]
566 parents = [p for p in repo.changelog.parents(n) if p != nullid]
567 if opts.get('no_merges') and len(parents) == 2:
567 if opts.get('no_merges') and len(parents) == 2:
568 continue
568 continue
569 count += 1
569 count += 1
570 displayer.show(repo[n])
570 displayer.show(repo[n])
571 displayer.close()
571 displayer.close()
572 recurse()
572 recurse()
573 return 0 # exit code is zero since we found outgoing changes
573 return 0 # exit code is zero since we found outgoing changes
574
574
575 def revert(repo, node, choose):
575 def revert(repo, node, choose):
576 """revert changes to revision in node without updating dirstate"""
576 """revert changes to revision in node without updating dirstate"""
577 return mergemod.update(repo, node, False, True, choose)[3] > 0
577 return mergemod.update(repo, node, False, True, choose)[3] > 0
578
578
579 def verify(repo):
579 def verify(repo):
580 """verify the consistency of a repository"""
580 """verify the consistency of a repository"""
581 return verifymod.verify(repo)
581 return verifymod.verify(repo)
582
582
583 def remoteui(src, opts):
583 def remoteui(src, opts):
584 'build a remote ui from ui or repo and opts'
584 'build a remote ui from ui or repo and opts'
585 if util.safehasattr(src, 'baseui'): # looks like a repository
585 if util.safehasattr(src, 'baseui'): # looks like a repository
586 dst = src.baseui.copy() # drop repo-specific config
586 dst = src.baseui.copy() # drop repo-specific config
587 src = src.ui # copy target options from repo
587 src = src.ui # copy target options from repo
588 else: # assume it's a global ui object
588 else: # assume it's a global ui object
589 dst = src.copy() # keep all global options
589 dst = src.copy() # keep all global options
590
590
591 # copy ssh-specific options
591 # copy ssh-specific options
592 for o in 'ssh', 'remotecmd':
592 for o in 'ssh', 'remotecmd':
593 v = opts.get(o) or src.config('ui', o)
593 v = opts.get(o) or src.config('ui', o)
594 if v:
594 if v:
595 dst.setconfig("ui", o, v)
595 dst.setconfig("ui", o, v)
596
596
597 # copy bundle-specific options
597 # copy bundle-specific options
598 r = src.config('bundle', 'mainreporoot')
598 r = src.config('bundle', 'mainreporoot')
599 if r:
599 if r:
600 dst.setconfig('bundle', 'mainreporoot', r)
600 dst.setconfig('bundle', 'mainreporoot', r)
601
601
602 # copy selected local settings to the remote ui
602 # copy selected local settings to the remote ui
603 for sect in ('auth', 'hostfingerprints', 'http_proxy'):
603 for sect in ('auth', 'hostfingerprints', 'http_proxy'):
604 for key, val in src.configitems(sect):
604 for key, val in src.configitems(sect):
605 dst.setconfig(sect, key, val)
605 dst.setconfig(sect, key, val)
606 v = src.config('web', 'cacerts')
606 v = src.config('web', 'cacerts')
607 if v:
607 if v:
608 dst.setconfig('web', 'cacerts', util.expandpath(v))
608 dst.setconfig('web', 'cacerts', util.expandpath(v))
609
609
610 return dst
610 return dst
@@ -1,567 +1,577 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 Default operation:
28 Default operation:
29
29
30 $ hg clone . ../b
30 $ hg clone . ../b
31 updating to branch default
31 updating to branch default
32 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
32 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
33 $ cd ../b
33 $ cd ../b
34 $ cat a
34 $ cat a
35 a
35 a
36 $ hg verify
36 $ hg verify
37 checking changesets
37 checking changesets
38 checking manifests
38 checking manifests
39 crosschecking files in changesets and manifests
39 crosschecking files in changesets and manifests
40 checking files
40 checking files
41 2 files, 11 changesets, 11 total revisions
41 2 files, 11 changesets, 11 total revisions
42
42
43 Invalid dest '' must abort:
43 Invalid dest '' must abort:
44
44
45 $ hg clone . ''
45 $ hg clone . ''
46 abort: empty destination path is not valid
46 abort: empty destination path is not valid
47 [255]
47 [255]
48
48
49 No update, with debug option:
49 No update, with debug option:
50
50
51 #if hardlink
51 #if hardlink
52 $ hg --debug clone -U . ../c
52 $ hg --debug clone -U . ../c
53 linked 8 files
53 linked 8 files
54 listing keys for "bookmarks"
54 listing keys for "bookmarks"
55 #else
55 #else
56 $ hg --debug clone -U . ../c
56 $ hg --debug clone -U . ../c
57 copied 8 files
57 copied 8 files
58 listing keys for "bookmarks"
58 listing keys for "bookmarks"
59 #endif
59 #endif
60 $ cd ../c
60 $ cd ../c
61 $ cat a 2>/dev/null || echo "a not present"
61 $ cat a 2>/dev/null || echo "a not present"
62 a not present
62 a not present
63 $ hg verify
63 $ hg verify
64 checking changesets
64 checking changesets
65 checking manifests
65 checking manifests
66 crosschecking files in changesets and manifests
66 crosschecking files in changesets and manifests
67 checking files
67 checking files
68 2 files, 11 changesets, 11 total revisions
68 2 files, 11 changesets, 11 total revisions
69
69
70 Default destination:
70 Default destination:
71
71
72 $ mkdir ../d
72 $ mkdir ../d
73 $ cd ../d
73 $ cd ../d
74 $ hg clone ../a
74 $ hg clone ../a
75 destination directory: a
75 destination directory: a
76 updating to branch default
76 updating to branch default
77 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
77 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
78 $ cd a
78 $ cd a
79 $ hg cat a
79 $ hg cat a
80 a
80 a
81 $ cd ../..
81 $ cd ../..
82
82
83 Check that we drop the 'file:' from the path before writing the .hgrc:
83 Check that we drop the 'file:' from the path before writing the .hgrc:
84
84
85 $ hg clone file:a e
85 $ hg clone file:a e
86 updating to branch default
86 updating to branch default
87 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 $ grep 'file:' e/.hg/hgrc
88 $ grep 'file:' e/.hg/hgrc
89 [1]
89 [1]
90
90
91 Check that path aliases are expanded:
91 Check that path aliases are expanded:
92
92
93 $ hg clone -q -U --config 'paths.foobar=a#0' foobar f
93 $ hg clone -q -U --config 'paths.foobar=a#0' foobar f
94 $ hg -R f showconfig paths.default
94 $ hg -R f showconfig paths.default
95 $TESTTMP/a#0 (glob)
95 $TESTTMP/a#0 (glob)
96
96
97 Use --pull:
97 Use --pull:
98
98
99 $ hg clone --pull a g
99 $ hg clone --pull a g
100 requesting all changes
100 requesting all changes
101 adding changesets
101 adding changesets
102 adding manifests
102 adding manifests
103 adding file changes
103 adding file changes
104 added 11 changesets with 11 changes to 2 files
104 added 11 changesets with 11 changes to 2 files
105 updating to branch default
105 updating to branch default
106 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
106 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 $ hg -R g verify
107 $ hg -R g verify
108 checking changesets
108 checking changesets
109 checking manifests
109 checking manifests
110 crosschecking files in changesets and manifests
110 crosschecking files in changesets and manifests
111 checking files
111 checking files
112 2 files, 11 changesets, 11 total revisions
112 2 files, 11 changesets, 11 total revisions
113
113
114 Invalid dest '' with --pull must abort (issue2528):
114 Invalid dest '' with --pull must abort (issue2528):
115
115
116 $ hg clone --pull a ''
116 $ hg clone --pull a ''
117 abort: empty destination path is not valid
117 abort: empty destination path is not valid
118 [255]
118 [255]
119
119
120 Clone to '.':
120 Clone to '.':
121
121
122 $ mkdir h
122 $ mkdir h
123 $ cd h
123 $ cd h
124 $ hg clone ../a .
124 $ hg clone ../a .
125 updating to branch default
125 updating to branch default
126 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
126 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
127 $ cd ..
127 $ cd ..
128
128
129
129
130 *** Tests for option -u ***
130 *** Tests for option -u ***
131
131
132 Adding some more history to repo a:
132 Adding some more history to repo a:
133
133
134 $ cd a
134 $ cd a
135 $ hg tag ref1
135 $ hg tag ref1
136 $ echo the quick brown fox >a
136 $ echo the quick brown fox >a
137 $ hg ci -m "hacked default"
137 $ hg ci -m "hacked default"
138 $ hg up ref1
138 $ hg up ref1
139 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
139 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
140 $ hg branch stable
140 $ hg branch stable
141 marked working directory as branch stable
141 marked working directory as branch stable
142 (branches are permanent and global, did you want a bookmark?)
142 (branches are permanent and global, did you want a bookmark?)
143 $ echo some text >a
143 $ echo some text >a
144 $ hg ci -m "starting branch stable"
144 $ hg ci -m "starting branch stable"
145 $ hg tag ref2
145 $ hg tag ref2
146 $ echo some more text >a
146 $ echo some more text >a
147 $ hg ci -m "another change for branch stable"
147 $ hg ci -m "another change for branch stable"
148 $ hg up ref2
148 $ hg up ref2
149 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
149 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
150 $ hg parents
150 $ hg parents
151 changeset: 13:e8ece76546a6
151 changeset: 13:e8ece76546a6
152 branch: stable
152 branch: stable
153 tag: ref2
153 tag: ref2
154 parent: 10:a7949464abda
154 parent: 10:a7949464abda
155 user: test
155 user: test
156 date: Thu Jan 01 00:00:00 1970 +0000
156 date: Thu Jan 01 00:00:00 1970 +0000
157 summary: starting branch stable
157 summary: starting branch stable
158
158
159
159
160 Repo a has two heads:
160 Repo a has two heads:
161
161
162 $ hg heads
162 $ hg heads
163 changeset: 15:0aae7cf88f0d
163 changeset: 15:0aae7cf88f0d
164 branch: stable
164 branch: stable
165 tag: tip
165 tag: tip
166 user: test
166 user: test
167 date: Thu Jan 01 00:00:00 1970 +0000
167 date: Thu Jan 01 00:00:00 1970 +0000
168 summary: another change for branch stable
168 summary: another change for branch stable
169
169
170 changeset: 12:f21241060d6a
170 changeset: 12:f21241060d6a
171 user: test
171 user: test
172 date: Thu Jan 01 00:00:00 1970 +0000
172 date: Thu Jan 01 00:00:00 1970 +0000
173 summary: hacked default
173 summary: hacked default
174
174
175
175
176 $ cd ..
176 $ cd ..
177
177
178
178
179 Testing --noupdate with --updaterev (must abort):
179 Testing --noupdate with --updaterev (must abort):
180
180
181 $ hg clone --noupdate --updaterev 1 a ua
181 $ hg clone --noupdate --updaterev 1 a ua
182 abort: cannot specify both --noupdate and --updaterev
182 abort: cannot specify both --noupdate and --updaterev
183 [255]
183 [255]
184
184
185
185
186 Testing clone -u:
186 Testing clone -u:
187
187
188 $ hg clone -u . a ua
188 $ hg clone -u . a ua
189 updating to branch stable
189 updating to branch stable
190 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
191
191
192 Repo ua has both heads:
192 Repo ua has both heads:
193
193
194 $ hg -R ua heads
194 $ hg -R ua heads
195 changeset: 15:0aae7cf88f0d
195 changeset: 15:0aae7cf88f0d
196 branch: stable
196 branch: stable
197 tag: tip
197 tag: tip
198 user: test
198 user: test
199 date: Thu Jan 01 00:00:00 1970 +0000
199 date: Thu Jan 01 00:00:00 1970 +0000
200 summary: another change for branch stable
200 summary: another change for branch stable
201
201
202 changeset: 12:f21241060d6a
202 changeset: 12:f21241060d6a
203 user: test
203 user: test
204 date: Thu Jan 01 00:00:00 1970 +0000
204 date: Thu Jan 01 00:00:00 1970 +0000
205 summary: hacked default
205 summary: hacked default
206
206
207
207
208 Same revision checked out in repo a and ua:
208 Same revision checked out in repo a and ua:
209
209
210 $ hg -R a parents --template "{node|short}\n"
210 $ hg -R a parents --template "{node|short}\n"
211 e8ece76546a6
211 e8ece76546a6
212 $ hg -R ua parents --template "{node|short}\n"
212 $ hg -R ua parents --template "{node|short}\n"
213 e8ece76546a6
213 e8ece76546a6
214
214
215 $ rm -r ua
215 $ rm -r ua
216
216
217
217
218 Testing clone --pull -u:
218 Testing clone --pull -u:
219
219
220 $ hg clone --pull -u . a ua
220 $ hg clone --pull -u . a ua
221 requesting all changes
221 requesting all changes
222 adding changesets
222 adding changesets
223 adding manifests
223 adding manifests
224 adding file changes
224 adding file changes
225 added 16 changesets with 16 changes to 3 files (+1 heads)
225 added 16 changesets with 16 changes to 3 files (+1 heads)
226 updating to branch stable
226 updating to branch stable
227 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
227 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
228
228
229 Repo ua has both heads:
229 Repo ua has both heads:
230
230
231 $ hg -R ua heads
231 $ hg -R ua heads
232 changeset: 15:0aae7cf88f0d
232 changeset: 15:0aae7cf88f0d
233 branch: stable
233 branch: stable
234 tag: tip
234 tag: tip
235 user: test
235 user: test
236 date: Thu Jan 01 00:00:00 1970 +0000
236 date: Thu Jan 01 00:00:00 1970 +0000
237 summary: another change for branch stable
237 summary: another change for branch stable
238
238
239 changeset: 12:f21241060d6a
239 changeset: 12:f21241060d6a
240 user: test
240 user: test
241 date: Thu Jan 01 00:00:00 1970 +0000
241 date: Thu Jan 01 00:00:00 1970 +0000
242 summary: hacked default
242 summary: hacked default
243
243
244
244
245 Same revision checked out in repo a and ua:
245 Same revision checked out in repo a and ua:
246
246
247 $ hg -R a parents --template "{node|short}\n"
247 $ hg -R a parents --template "{node|short}\n"
248 e8ece76546a6
248 e8ece76546a6
249 $ hg -R ua parents --template "{node|short}\n"
249 $ hg -R ua parents --template "{node|short}\n"
250 e8ece76546a6
250 e8ece76546a6
251
251
252 $ rm -r ua
252 $ rm -r ua
253
253
254
254
255 Testing clone -u <branch>:
255 Testing clone -u <branch>:
256
256
257 $ hg clone -u stable a ua
257 $ hg clone -u stable a ua
258 updating to branch stable
258 updating to branch stable
259 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
259 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
260
260
261 Repo ua has both heads:
261 Repo ua has both heads:
262
262
263 $ hg -R ua heads
263 $ hg -R ua heads
264 changeset: 15:0aae7cf88f0d
264 changeset: 15:0aae7cf88f0d
265 branch: stable
265 branch: stable
266 tag: tip
266 tag: tip
267 user: test
267 user: test
268 date: Thu Jan 01 00:00:00 1970 +0000
268 date: Thu Jan 01 00:00:00 1970 +0000
269 summary: another change for branch stable
269 summary: another change for branch stable
270
270
271 changeset: 12:f21241060d6a
271 changeset: 12:f21241060d6a
272 user: test
272 user: test
273 date: Thu Jan 01 00:00:00 1970 +0000
273 date: Thu Jan 01 00:00:00 1970 +0000
274 summary: hacked default
274 summary: hacked default
275
275
276
276
277 Branch 'stable' is checked out:
277 Branch 'stable' is checked out:
278
278
279 $ hg -R ua parents
279 $ hg -R ua parents
280 changeset: 15:0aae7cf88f0d
280 changeset: 15:0aae7cf88f0d
281 branch: stable
281 branch: stable
282 tag: tip
282 tag: tip
283 user: test
283 user: test
284 date: Thu Jan 01 00:00:00 1970 +0000
284 date: Thu Jan 01 00:00:00 1970 +0000
285 summary: another change for branch stable
285 summary: another change for branch stable
286
286
287
287
288 $ rm -r ua
288 $ rm -r ua
289
289
290
290
291 Testing default checkout:
291 Testing default checkout:
292
292
293 $ hg clone a ua
293 $ hg clone a ua
294 updating to branch default
294 updating to branch default
295 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
295 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
296
296
297 Repo ua has both heads:
297 Repo ua has both heads:
298
298
299 $ hg -R ua heads
299 $ hg -R ua heads
300 changeset: 15:0aae7cf88f0d
300 changeset: 15:0aae7cf88f0d
301 branch: stable
301 branch: stable
302 tag: tip
302 tag: tip
303 user: test
303 user: test
304 date: Thu Jan 01 00:00:00 1970 +0000
304 date: Thu Jan 01 00:00:00 1970 +0000
305 summary: another change for branch stable
305 summary: another change for branch stable
306
306
307 changeset: 12:f21241060d6a
307 changeset: 12:f21241060d6a
308 user: test
308 user: test
309 date: Thu Jan 01 00:00:00 1970 +0000
309 date: Thu Jan 01 00:00:00 1970 +0000
310 summary: hacked default
310 summary: hacked default
311
311
312
312
313 Branch 'default' is checked out:
313 Branch 'default' is checked out:
314
314
315 $ hg -R ua parents
315 $ hg -R ua parents
316 changeset: 12:f21241060d6a
316 changeset: 12:f21241060d6a
317 user: test
317 user: test
318 date: Thu Jan 01 00:00:00 1970 +0000
318 date: Thu Jan 01 00:00:00 1970 +0000
319 summary: hacked default
319 summary: hacked default
320
320
321
321
322 $ rm -r ua
322 $ rm -r ua
323
323
324
324
325 Testing #<branch>:
325 Testing #<branch>:
326
326
327 $ hg clone -u . a#stable ua
327 $ hg clone -u . a#stable ua
328 adding changesets
328 adding changesets
329 adding manifests
329 adding manifests
330 adding file changes
330 adding file changes
331 added 14 changesets with 14 changes to 3 files
331 added 14 changesets with 14 changes to 3 files
332 updating to branch stable
332 updating to branch stable
333 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
333 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
334
334
335 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
335 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
336
336
337 $ hg -R ua heads
337 $ hg -R ua heads
338 changeset: 13:0aae7cf88f0d
338 changeset: 13:0aae7cf88f0d
339 branch: stable
339 branch: stable
340 tag: tip
340 tag: tip
341 user: test
341 user: test
342 date: Thu Jan 01 00:00:00 1970 +0000
342 date: Thu Jan 01 00:00:00 1970 +0000
343 summary: another change for branch stable
343 summary: another change for branch stable
344
344
345 changeset: 10:a7949464abda
345 changeset: 10:a7949464abda
346 user: test
346 user: test
347 date: Thu Jan 01 00:00:00 1970 +0000
347 date: Thu Jan 01 00:00:00 1970 +0000
348 summary: test
348 summary: test
349
349
350
350
351 Same revision checked out in repo a and ua:
351 Same revision checked out in repo a and ua:
352
352
353 $ hg -R a parents --template "{node|short}\n"
353 $ hg -R a parents --template "{node|short}\n"
354 e8ece76546a6
354 e8ece76546a6
355 $ hg -R ua parents --template "{node|short}\n"
355 $ hg -R ua parents --template "{node|short}\n"
356 e8ece76546a6
356 e8ece76546a6
357
357
358 $ rm -r ua
358 $ rm -r ua
359
359
360
360
361 Testing -u -r <branch>:
361 Testing -u -r <branch>:
362
362
363 $ hg clone -u . -r stable a ua
363 $ hg clone -u . -r stable a ua
364 adding changesets
364 adding changesets
365 adding manifests
365 adding manifests
366 adding file changes
366 adding file changes
367 added 14 changesets with 14 changes to 3 files
367 added 14 changesets with 14 changes to 3 files
368 updating to branch stable
368 updating to branch stable
369 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
369 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
370
370
371 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
371 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
372
372
373 $ hg -R ua heads
373 $ hg -R ua heads
374 changeset: 13:0aae7cf88f0d
374 changeset: 13:0aae7cf88f0d
375 branch: stable
375 branch: stable
376 tag: tip
376 tag: tip
377 user: test
377 user: test
378 date: Thu Jan 01 00:00:00 1970 +0000
378 date: Thu Jan 01 00:00:00 1970 +0000
379 summary: another change for branch stable
379 summary: another change for branch stable
380
380
381 changeset: 10:a7949464abda
381 changeset: 10:a7949464abda
382 user: test
382 user: test
383 date: Thu Jan 01 00:00:00 1970 +0000
383 date: Thu Jan 01 00:00:00 1970 +0000
384 summary: test
384 summary: test
385
385
386
386
387 Same revision checked out in repo a and ua:
387 Same revision checked out in repo a and ua:
388
388
389 $ hg -R a parents --template "{node|short}\n"
389 $ hg -R a parents --template "{node|short}\n"
390 e8ece76546a6
390 e8ece76546a6
391 $ hg -R ua parents --template "{node|short}\n"
391 $ hg -R ua parents --template "{node|short}\n"
392 e8ece76546a6
392 e8ece76546a6
393
393
394 $ rm -r ua
394 $ rm -r ua
395
395
396
396
397 Testing -r <branch>:
397 Testing -r <branch>:
398
398
399 $ hg clone -r stable a ua
399 $ hg clone -r stable a ua
400 adding changesets
400 adding changesets
401 adding manifests
401 adding manifests
402 adding file changes
402 adding file changes
403 added 14 changesets with 14 changes to 3 files
403 added 14 changesets with 14 changes to 3 files
404 updating to branch stable
404 updating to branch stable
405 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
405 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
406
406
407 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
407 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
408
408
409 $ hg -R ua heads
409 $ hg -R ua heads
410 changeset: 13:0aae7cf88f0d
410 changeset: 13:0aae7cf88f0d
411 branch: stable
411 branch: stable
412 tag: tip
412 tag: tip
413 user: test
413 user: test
414 date: Thu Jan 01 00:00:00 1970 +0000
414 date: Thu Jan 01 00:00:00 1970 +0000
415 summary: another change for branch stable
415 summary: another change for branch stable
416
416
417 changeset: 10:a7949464abda
417 changeset: 10:a7949464abda
418 user: test
418 user: test
419 date: Thu Jan 01 00:00:00 1970 +0000
419 date: Thu Jan 01 00:00:00 1970 +0000
420 summary: test
420 summary: test
421
421
422
422
423 Branch 'stable' is checked out:
423 Branch 'stable' is checked out:
424
424
425 $ hg -R ua parents
425 $ hg -R ua parents
426 changeset: 13:0aae7cf88f0d
426 changeset: 13:0aae7cf88f0d
427 branch: stable
427 branch: stable
428 tag: tip
428 tag: tip
429 user: test
429 user: test
430 date: Thu Jan 01 00:00:00 1970 +0000
430 date: Thu Jan 01 00:00:00 1970 +0000
431 summary: another change for branch stable
431 summary: another change for branch stable
432
432
433
433
434 $ rm -r ua
434 $ rm -r ua
435
435
436
436
437 Issue2267: Error in 1.6 hg.py: TypeError: 'NoneType' object is not
437 Issue2267: Error in 1.6 hg.py: TypeError: 'NoneType' object is not
438 iterable in addbranchrevs()
438 iterable in addbranchrevs()
439
439
440 $ cat <<EOF > simpleclone.py
440 $ cat <<EOF > simpleclone.py
441 > from mercurial import ui, hg
441 > from mercurial import ui, hg
442 > myui = ui.ui()
442 > myui = ui.ui()
443 > repo = hg.repository(myui, 'a')
443 > repo = hg.repository(myui, 'a')
444 > hg.clone(myui, {}, repo, dest="ua")
444 > hg.clone(myui, {}, repo, dest="ua")
445 > EOF
445 > EOF
446
446
447 $ python simpleclone.py
447 $ python simpleclone.py
448 updating to branch default
448 updating to branch default
449 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
449 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
450
450
451 $ rm -r ua
451 $ rm -r ua
452
452
453 $ cat <<EOF > branchclone.py
453 $ cat <<EOF > branchclone.py
454 > from mercurial import ui, hg, extensions
454 > from mercurial import ui, hg, extensions
455 > myui = ui.ui()
455 > myui = ui.ui()
456 > extensions.loadall(myui)
456 > extensions.loadall(myui)
457 > repo = hg.repository(myui, 'a')
457 > repo = hg.repository(myui, 'a')
458 > hg.clone(myui, {}, repo, dest="ua", branch=["stable",])
458 > hg.clone(myui, {}, repo, dest="ua", branch=["stable",])
459 > EOF
459 > EOF
460
460
461 $ python branchclone.py
461 $ python branchclone.py
462 adding changesets
462 adding changesets
463 adding manifests
463 adding manifests
464 adding file changes
464 adding file changes
465 added 14 changesets with 14 changes to 3 files
465 added 14 changesets with 14 changes to 3 files
466 updating to branch stable
466 updating to branch stable
467 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
467 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
468 $ rm -r ua
468 $ rm -r ua
469
469
470
470
471 Test clone with special '@' bookmark:
472 $ cd a
473 $ hg bookmark -r a7949464abda @ # branch point of stable from default
474 $ hg clone . ../i
475 updating to branch default
476 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
477 $ hg id -i ../i
478 a7949464abda
479
480
471 Testing failures:
481 Testing failures:
472
482
473 $ mkdir fail
483 $ mkdir fail
474 $ cd fail
484 $ cd fail
475
485
476 No local source
486 No local source
477
487
478 $ hg clone a b
488 $ hg clone a b
479 abort: repository a not found!
489 abort: repository a not found!
480 [255]
490 [255]
481
491
482 No remote source
492 No remote source
483
493
484 $ hg clone http://127.0.0.1:3121/a b
494 $ hg clone http://127.0.0.1:3121/a b
485 abort: error: *refused* (glob)
495 abort: error: *refused* (glob)
486 [255]
496 [255]
487 $ rm -rf b # work around bug with http clone
497 $ rm -rf b # work around bug with http clone
488
498
489
499
490 #if unix-permissions
500 #if unix-permissions
491
501
492 Inaccessible source
502 Inaccessible source
493
503
494 $ mkdir a
504 $ mkdir a
495 $ chmod 000 a
505 $ chmod 000 a
496 $ hg clone a b
506 $ hg clone a b
497 abort: repository a not found!
507 abort: repository a not found!
498 [255]
508 [255]
499
509
500 Inaccessible destination
510 Inaccessible destination
501
511
502 $ hg init b
512 $ hg init b
503 $ cd b
513 $ cd b
504 $ hg clone . ../a
514 $ hg clone . ../a
505 abort: Permission denied: ../a
515 abort: Permission denied: ../a
506 [255]
516 [255]
507 $ cd ..
517 $ cd ..
508 $ chmod 700 a
518 $ chmod 700 a
509 $ rm -r a b
519 $ rm -r a b
510
520
511 #endif
521 #endif
512
522
513
523
514 #if fifo
524 #if fifo
515
525
516 Source of wrong type
526 Source of wrong type
517
527
518 $ mkfifo a
528 $ mkfifo a
519 $ hg clone a b
529 $ hg clone a b
520 abort: repository a not found!
530 abort: repository a not found!
521 [255]
531 [255]
522 $ rm a
532 $ rm a
523
533
524 #endif
534 #endif
525
535
526 Default destination, same directory
536 Default destination, same directory
527
537
528 $ hg init q
538 $ hg init q
529 $ hg clone q
539 $ hg clone q
530 destination directory: q
540 destination directory: q
531 abort: destination 'q' is not empty
541 abort: destination 'q' is not empty
532 [255]
542 [255]
533
543
534 destination directory not empty
544 destination directory not empty
535
545
536 $ mkdir a
546 $ mkdir a
537 $ echo stuff > a/a
547 $ echo stuff > a/a
538 $ hg clone q a
548 $ hg clone q a
539 abort: destination 'a' is not empty
549 abort: destination 'a' is not empty
540 [255]
550 [255]
541
551
542
552
543 #if unix-permissions
553 #if unix-permissions
544
554
545 leave existing directory in place after clone failure
555 leave existing directory in place after clone failure
546
556
547 $ hg init c
557 $ hg init c
548 $ cd c
558 $ cd c
549 $ echo c > c
559 $ echo c > c
550 $ hg commit -A -m test
560 $ hg commit -A -m test
551 adding c
561 adding c
552 $ chmod -rx .hg/store/data
562 $ chmod -rx .hg/store/data
553 $ cd ..
563 $ cd ..
554 $ mkdir d
564 $ mkdir d
555 $ hg clone c d 2> err
565 $ hg clone c d 2> err
556 [255]
566 [255]
557 $ test -d d
567 $ test -d d
558 $ test -d d/.hg
568 $ test -d d/.hg
559 [1]
569 [1]
560
570
561 re-enable perm to allow deletion
571 re-enable perm to allow deletion
562
572
563 $ chmod +rx c/.hg/store/data
573 $ chmod +rx c/.hg/store/data
564
574
565 #endif
575 #endif
566
576
567 $ cd ..
577 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now