##// END OF EJS Templates
hg: move return statement after finally block...
simon@laptop-tosh -
r19313:3b96d6e4 default
parent child Browse files
Show More
@@ -1,633 +1,632 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, unionrepo, httppeer, sshpeer, statichttprepo
12 import localrepo, bundlerepo, unionrepo, httppeer, sshpeer, statichttprepo
13 import bookmarks, lock, util, extensions, error, node, scmutil, phases, url
13 import bookmarks, lock, util, extensions, error, node, scmutil, phases, url
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 'union': unionrepo,
67 'union': unionrepo,
68 'file': _local,
68 'file': _local,
69 'http': httppeer,
69 'http': httppeer,
70 'https': httppeer,
70 'https': httppeer,
71 'ssh': sshpeer,
71 'ssh': sshpeer,
72 'static-http': statichttprepo,
72 'static-http': statichttprepo,
73 }
73 }
74
74
75 def _peerlookup(path):
75 def _peerlookup(path):
76 u = util.url(path)
76 u = util.url(path)
77 scheme = u.scheme or 'file'
77 scheme = u.scheme or 'file'
78 thing = schemes.get(scheme) or schemes['file']
78 thing = schemes.get(scheme) or schemes['file']
79 try:
79 try:
80 return thing(path)
80 return thing(path)
81 except TypeError:
81 except TypeError:
82 return thing
82 return thing
83
83
84 def islocal(repo):
84 def islocal(repo):
85 '''return true if repo or path is local'''
85 '''return true if repo or path is local'''
86 if isinstance(repo, str):
86 if isinstance(repo, str):
87 try:
87 try:
88 return _peerlookup(repo).islocal(repo)
88 return _peerlookup(repo).islocal(repo)
89 except AttributeError:
89 except AttributeError:
90 return False
90 return False
91 return repo.local()
91 return repo.local()
92
92
93 def openpath(ui, path):
93 def openpath(ui, path):
94 '''open path with open if local, url.open if remote'''
94 '''open path with open if local, url.open if remote'''
95 if islocal(path):
95 if islocal(path):
96 return util.posixfile(util.urllocalpath(path), 'rb')
96 return util.posixfile(util.urllocalpath(path), 'rb')
97 else:
97 else:
98 return url.open(ui, path)
98 return url.open(ui, path)
99
99
100 def _peerorrepo(ui, path, create=False):
100 def _peerorrepo(ui, path, create=False):
101 """return a repository object for the specified path"""
101 """return a repository object for the specified path"""
102 obj = _peerlookup(path).instance(ui, path, create)
102 obj = _peerlookup(path).instance(ui, path, create)
103 ui = getattr(obj, "ui", ui)
103 ui = getattr(obj, "ui", ui)
104 for name, module in extensions.extensions():
104 for name, module in extensions.extensions():
105 hook = getattr(module, 'reposetup', None)
105 hook = getattr(module, 'reposetup', None)
106 if hook:
106 if hook:
107 hook(ui, obj)
107 hook(ui, obj)
108 return obj
108 return obj
109
109
110 def repository(ui, path='', create=False):
110 def repository(ui, path='', create=False):
111 """return a repository object for the specified path"""
111 """return a repository object for the specified path"""
112 peer = _peerorrepo(ui, path, create)
112 peer = _peerorrepo(ui, path, create)
113 repo = peer.local()
113 repo = peer.local()
114 if not repo:
114 if not repo:
115 raise util.Abort(_("repository '%s' is not local") %
115 raise util.Abort(_("repository '%s' is not local") %
116 (path or peer.url()))
116 (path or peer.url()))
117 return repo.filtered('visible')
117 return repo.filtered('visible')
118
118
119 def peer(uiorrepo, opts, path, create=False):
119 def peer(uiorrepo, opts, path, create=False):
120 '''return a repository peer for the specified path'''
120 '''return a repository peer for the specified path'''
121 rui = remoteui(uiorrepo, opts)
121 rui = remoteui(uiorrepo, opts)
122 return _peerorrepo(rui, path, create).peer()
122 return _peerorrepo(rui, path, create).peer()
123
123
124 def defaultdest(source):
124 def defaultdest(source):
125 '''return default destination of clone if none is given'''
125 '''return default destination of clone if none is given'''
126 return os.path.basename(os.path.normpath(util.url(source).path or ''))
126 return os.path.basename(os.path.normpath(util.url(source).path or ''))
127
127
128 def share(ui, source, dest=None, update=True):
128 def share(ui, source, dest=None, update=True):
129 '''create a shared repository'''
129 '''create a shared repository'''
130
130
131 if not islocal(source):
131 if not islocal(source):
132 raise util.Abort(_('can only share local repositories'))
132 raise util.Abort(_('can only share local repositories'))
133
133
134 if not dest:
134 if not dest:
135 dest = defaultdest(source)
135 dest = defaultdest(source)
136 else:
136 else:
137 dest = ui.expandpath(dest)
137 dest = ui.expandpath(dest)
138
138
139 if isinstance(source, str):
139 if isinstance(source, str):
140 origsource = ui.expandpath(source)
140 origsource = ui.expandpath(source)
141 source, branches = parseurl(origsource)
141 source, branches = parseurl(origsource)
142 srcrepo = repository(ui, source)
142 srcrepo = repository(ui, source)
143 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
143 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
144 else:
144 else:
145 srcrepo = source.local()
145 srcrepo = source.local()
146 origsource = source = srcrepo.url()
146 origsource = source = srcrepo.url()
147 checkout = None
147 checkout = None
148
148
149 sharedpath = srcrepo.sharedpath # if our source is already sharing
149 sharedpath = srcrepo.sharedpath # if our source is already sharing
150
150
151 root = os.path.realpath(dest)
151 root = os.path.realpath(dest)
152 roothg = os.path.join(root, '.hg')
152 roothg = os.path.join(root, '.hg')
153
153
154 if os.path.exists(roothg):
154 if os.path.exists(roothg):
155 raise util.Abort(_('destination already exists'))
155 raise util.Abort(_('destination already exists'))
156
156
157 if not os.path.isdir(root):
157 if not os.path.isdir(root):
158 os.mkdir(root)
158 os.mkdir(root)
159 util.makedir(roothg, notindexed=True)
159 util.makedir(roothg, notindexed=True)
160
160
161 requirements = ''
161 requirements = ''
162 try:
162 try:
163 requirements = srcrepo.opener.read('requires')
163 requirements = srcrepo.opener.read('requires')
164 except IOError, inst:
164 except IOError, inst:
165 if inst.errno != errno.ENOENT:
165 if inst.errno != errno.ENOENT:
166 raise
166 raise
167
167
168 requirements += 'shared\n'
168 requirements += 'shared\n'
169 util.writefile(os.path.join(roothg, 'requires'), requirements)
169 util.writefile(os.path.join(roothg, 'requires'), requirements)
170 util.writefile(os.path.join(roothg, 'sharedpath'), sharedpath)
170 util.writefile(os.path.join(roothg, 'sharedpath'), sharedpath)
171
171
172 r = repository(ui, root)
172 r = repository(ui, root)
173
173
174 default = srcrepo.ui.config('paths', 'default')
174 default = srcrepo.ui.config('paths', 'default')
175 if default:
175 if default:
176 fp = r.opener("hgrc", "w", text=True)
176 fp = r.opener("hgrc", "w", text=True)
177 fp.write("[paths]\n")
177 fp.write("[paths]\n")
178 fp.write("default = %s\n" % default)
178 fp.write("default = %s\n" % default)
179 fp.close()
179 fp.close()
180
180
181 if update:
181 if update:
182 r.ui.status(_("updating working directory\n"))
182 r.ui.status(_("updating working directory\n"))
183 if update is not True:
183 if update is not True:
184 checkout = update
184 checkout = update
185 for test in (checkout, 'default', 'tip'):
185 for test in (checkout, 'default', 'tip'):
186 if test is None:
186 if test is None:
187 continue
187 continue
188 try:
188 try:
189 uprev = r.lookup(test)
189 uprev = r.lookup(test)
190 break
190 break
191 except error.RepoLookupError:
191 except error.RepoLookupError:
192 continue
192 continue
193 _update(r, uprev)
193 _update(r, uprev)
194
194
195 def copystore(ui, srcrepo, destpath):
195 def copystore(ui, srcrepo, destpath):
196 '''copy files from store of srcrepo in destpath
196 '''copy files from store of srcrepo in destpath
197
197
198 returns destlock
198 returns destlock
199 '''
199 '''
200 destlock = None
200 destlock = None
201 try:
201 try:
202 hardlink = None
202 hardlink = None
203 num = 0
203 num = 0
204 srcpublishing = srcrepo.ui.configbool('phases', 'publish', True)
204 srcpublishing = srcrepo.ui.configbool('phases', 'publish', True)
205 for f in srcrepo.store.copylist():
205 for f in srcrepo.store.copylist():
206 if srcpublishing and f.endswith('phaseroots'):
206 if srcpublishing and f.endswith('phaseroots'):
207 continue
207 continue
208 src = os.path.join(srcrepo.sharedpath, f)
208 src = os.path.join(srcrepo.sharedpath, f)
209 dst = os.path.join(destpath, f)
209 dst = os.path.join(destpath, f)
210 dstbase = os.path.dirname(dst)
210 dstbase = os.path.dirname(dst)
211 if dstbase and not os.path.exists(dstbase):
211 if dstbase and not os.path.exists(dstbase):
212 os.mkdir(dstbase)
212 os.mkdir(dstbase)
213 if os.path.exists(src):
213 if os.path.exists(src):
214 if dst.endswith('data'):
214 if dst.endswith('data'):
215 # lock to avoid premature writing to the target
215 # lock to avoid premature writing to the target
216 destlock = lock.lock(os.path.join(dstbase, "lock"))
216 destlock = lock.lock(os.path.join(dstbase, "lock"))
217 hardlink, n = util.copyfiles(src, dst, hardlink)
217 hardlink, n = util.copyfiles(src, dst, hardlink)
218 num += n
218 num += n
219 if hardlink:
219 if hardlink:
220 ui.debug("linked %d files\n" % num)
220 ui.debug("linked %d files\n" % num)
221 else:
221 else:
222 ui.debug("copied %d files\n" % num)
222 ui.debug("copied %d files\n" % num)
223 return destlock
223 return destlock
224 except: # re-raises
224 except: # re-raises
225 release(destlock)
225 release(destlock)
226 raise
226 raise
227
227
228 def clone(ui, peeropts, source, dest=None, pull=False, rev=None,
228 def clone(ui, peeropts, source, dest=None, pull=False, rev=None,
229 update=True, stream=False, branch=None):
229 update=True, stream=False, branch=None):
230 """Make a copy of an existing repository.
230 """Make a copy of an existing repository.
231
231
232 Create a copy of an existing repository in a new directory. The
232 Create a copy of an existing repository in a new directory. The
233 source and destination are URLs, as passed to the repository
233 source and destination are URLs, as passed to the repository
234 function. Returns a pair of repository peers, the source and
234 function. Returns a pair of repository peers, the source and
235 newly created destination.
235 newly created destination.
236
236
237 The location of the source is added to the new repository's
237 The location of the source is added to the new repository's
238 .hg/hgrc file, as the default to be used for future pulls and
238 .hg/hgrc file, as the default to be used for future pulls and
239 pushes.
239 pushes.
240
240
241 If an exception is raised, the partly cloned/updated destination
241 If an exception is raised, the partly cloned/updated destination
242 repository will be deleted.
242 repository will be deleted.
243
243
244 Arguments:
244 Arguments:
245
245
246 source: repository object or URL
246 source: repository object or URL
247
247
248 dest: URL of destination repository to create (defaults to base
248 dest: URL of destination repository to create (defaults to base
249 name of source repository)
249 name of source repository)
250
250
251 pull: always pull from source repository, even in local case
251 pull: always pull from source repository, even in local case
252
252
253 stream: stream raw data uncompressed from repository (fast over
253 stream: stream raw data uncompressed from repository (fast over
254 LAN, slow over WAN)
254 LAN, slow over WAN)
255
255
256 rev: revision to clone up to (implies pull=True)
256 rev: revision to clone up to (implies pull=True)
257
257
258 update: update working directory after clone completes, if
258 update: update working directory after clone completes, if
259 destination is local repository (True means update to default rev,
259 destination is local repository (True means update to default rev,
260 anything else is treated as a revision)
260 anything else is treated as a revision)
261
261
262 branch: branches to clone
262 branch: branches to clone
263 """
263 """
264
264
265 if isinstance(source, str):
265 if isinstance(source, str):
266 origsource = ui.expandpath(source)
266 origsource = ui.expandpath(source)
267 source, branch = parseurl(origsource, branch)
267 source, branch = parseurl(origsource, branch)
268 srcpeer = peer(ui, peeropts, source)
268 srcpeer = peer(ui, peeropts, source)
269 else:
269 else:
270 srcpeer = source.peer() # in case we were called with a localrepo
270 srcpeer = source.peer() # in case we were called with a localrepo
271 branch = (None, branch or [])
271 branch = (None, branch or [])
272 origsource = source = srcpeer.url()
272 origsource = source = srcpeer.url()
273 rev, checkout = addbranchrevs(srcpeer, srcpeer, branch, rev)
273 rev, checkout = addbranchrevs(srcpeer, srcpeer, branch, rev)
274
274
275 if dest is None:
275 if dest is None:
276 dest = defaultdest(source)
276 dest = defaultdest(source)
277 ui.status(_("destination directory: %s\n") % dest)
277 ui.status(_("destination directory: %s\n") % dest)
278 else:
278 else:
279 dest = ui.expandpath(dest)
279 dest = ui.expandpath(dest)
280
280
281 dest = util.urllocalpath(dest)
281 dest = util.urllocalpath(dest)
282 source = util.urllocalpath(source)
282 source = util.urllocalpath(source)
283
283
284 if not dest:
284 if not dest:
285 raise util.Abort(_("empty destination path is not valid"))
285 raise util.Abort(_("empty destination path is not valid"))
286 if os.path.exists(dest):
286 if os.path.exists(dest):
287 if not os.path.isdir(dest):
287 if not os.path.isdir(dest):
288 raise util.Abort(_("destination '%s' already exists") % dest)
288 raise util.Abort(_("destination '%s' already exists") % dest)
289 elif os.listdir(dest):
289 elif os.listdir(dest):
290 raise util.Abort(_("destination '%s' is not empty") % dest)
290 raise util.Abort(_("destination '%s' is not empty") % dest)
291
291
292 srclock = destlock = cleandir = None
292 srclock = destlock = cleandir = None
293 srcrepo = srcpeer.local()
293 srcrepo = srcpeer.local()
294 try:
294 try:
295 abspath = origsource
295 abspath = origsource
296 if islocal(origsource):
296 if islocal(origsource):
297 abspath = os.path.abspath(util.urllocalpath(origsource))
297 abspath = os.path.abspath(util.urllocalpath(origsource))
298
298
299 if islocal(dest):
299 if islocal(dest):
300 cleandir = dest
300 cleandir = dest
301
301
302 copy = False
302 copy = False
303 if (srcrepo and srcrepo.cancopy() and islocal(dest)
303 if (srcrepo and srcrepo.cancopy() and islocal(dest)
304 and not phases.hassecret(srcrepo)):
304 and not phases.hassecret(srcrepo)):
305 copy = not pull and not rev
305 copy = not pull and not rev
306
306
307 if copy:
307 if copy:
308 try:
308 try:
309 # we use a lock here because if we race with commit, we
309 # we use a lock here because if we race with commit, we
310 # can end up with extra data in the cloned revlogs that's
310 # can end up with extra data in the cloned revlogs that's
311 # not pointed to by changesets, thus causing verify to
311 # not pointed to by changesets, thus causing verify to
312 # fail
312 # fail
313 srclock = srcrepo.lock(wait=False)
313 srclock = srcrepo.lock(wait=False)
314 except error.LockError:
314 except error.LockError:
315 copy = False
315 copy = False
316
316
317 if copy:
317 if copy:
318 srcrepo.hook('preoutgoing', throw=True, source='clone')
318 srcrepo.hook('preoutgoing', throw=True, source='clone')
319 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
319 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
320 if not os.path.exists(dest):
320 if not os.path.exists(dest):
321 os.mkdir(dest)
321 os.mkdir(dest)
322 else:
322 else:
323 # only clean up directories we create ourselves
323 # only clean up directories we create ourselves
324 cleandir = hgdir
324 cleandir = hgdir
325 try:
325 try:
326 destpath = hgdir
326 destpath = hgdir
327 util.makedir(destpath, notindexed=True)
327 util.makedir(destpath, notindexed=True)
328 except OSError, inst:
328 except OSError, inst:
329 if inst.errno == errno.EEXIST:
329 if inst.errno == errno.EEXIST:
330 cleandir = None
330 cleandir = None
331 raise util.Abort(_("destination '%s' already exists")
331 raise util.Abort(_("destination '%s' already exists")
332 % dest)
332 % dest)
333 raise
333 raise
334
334
335 destlock = copystore(ui, srcrepo, destpath)
335 destlock = copystore(ui, srcrepo, destpath)
336
336
337 # Recomputing branch cache might be slow on big repos,
337 # Recomputing branch cache might be slow on big repos,
338 # so just copy it
338 # so just copy it
339 dstcachedir = os.path.join(destpath, 'cache')
339 dstcachedir = os.path.join(destpath, 'cache')
340 srcbranchcache = srcrepo.sjoin('cache/branchheads')
340 srcbranchcache = srcrepo.sjoin('cache/branchheads')
341 dstbranchcache = os.path.join(dstcachedir, 'branchheads')
341 dstbranchcache = os.path.join(dstcachedir, 'branchheads')
342 if os.path.exists(srcbranchcache):
342 if os.path.exists(srcbranchcache):
343 if not os.path.exists(dstcachedir):
343 if not os.path.exists(dstcachedir):
344 os.mkdir(dstcachedir)
344 os.mkdir(dstcachedir)
345 util.copyfile(srcbranchcache, dstbranchcache)
345 util.copyfile(srcbranchcache, dstbranchcache)
346
346
347 # we need to re-init the repo after manually copying the data
347 # we need to re-init the repo after manually copying the data
348 # into it
348 # into it
349 destpeer = peer(srcrepo, peeropts, dest)
349 destpeer = peer(srcrepo, peeropts, dest)
350 srcrepo.hook('outgoing', source='clone',
350 srcrepo.hook('outgoing', source='clone',
351 node=node.hex(node.nullid))
351 node=node.hex(node.nullid))
352 else:
352 else:
353 try:
353 try:
354 destpeer = peer(srcrepo or ui, peeropts, dest, create=True)
354 destpeer = peer(srcrepo or ui, peeropts, dest, create=True)
355 # only pass ui when no srcrepo
355 # only pass ui when no srcrepo
356 except OSError, inst:
356 except OSError, inst:
357 if inst.errno == errno.EEXIST:
357 if inst.errno == errno.EEXIST:
358 cleandir = None
358 cleandir = None
359 raise util.Abort(_("destination '%s' already exists")
359 raise util.Abort(_("destination '%s' already exists")
360 % dest)
360 % dest)
361 raise
361 raise
362
362
363 revs = None
363 revs = None
364 if rev:
364 if rev:
365 if not srcpeer.capable('lookup'):
365 if not srcpeer.capable('lookup'):
366 raise util.Abort(_("src repository does not support "
366 raise util.Abort(_("src repository does not support "
367 "revision lookup and so doesn't "
367 "revision lookup and so doesn't "
368 "support clone by revision"))
368 "support clone by revision"))
369 revs = [srcpeer.lookup(r) for r in rev]
369 revs = [srcpeer.lookup(r) for r in rev]
370 checkout = revs[0]
370 checkout = revs[0]
371 if destpeer.local():
371 if destpeer.local():
372 destpeer.local().clone(srcpeer, heads=revs, stream=stream)
372 destpeer.local().clone(srcpeer, heads=revs, stream=stream)
373 elif srcrepo:
373 elif srcrepo:
374 srcrepo.push(destpeer, revs=revs)
374 srcrepo.push(destpeer, revs=revs)
375 else:
375 else:
376 raise util.Abort(_("clone from remote to remote not supported"))
376 raise util.Abort(_("clone from remote to remote not supported"))
377
377
378 cleandir = None
378 cleandir = None
379
379
380 # clone all bookmarks except divergent ones
380 # clone all bookmarks except divergent ones
381 destrepo = destpeer.local()
381 destrepo = destpeer.local()
382 if destrepo and srcpeer.capable("pushkey"):
382 if destrepo and srcpeer.capable("pushkey"):
383 rb = srcpeer.listkeys('bookmarks')
383 rb = srcpeer.listkeys('bookmarks')
384 marks = destrepo._bookmarks
384 marks = destrepo._bookmarks
385 for k, n in rb.iteritems():
385 for k, n in rb.iteritems():
386 try:
386 try:
387 m = destrepo.lookup(n)
387 m = destrepo.lookup(n)
388 marks[k] = m
388 marks[k] = m
389 except error.RepoLookupError:
389 except error.RepoLookupError:
390 pass
390 pass
391 if rb:
391 if rb:
392 marks.write()
392 marks.write()
393 elif srcrepo and destpeer.capable("pushkey"):
393 elif srcrepo and destpeer.capable("pushkey"):
394 for k, n in srcrepo._bookmarks.iteritems():
394 for k, n in srcrepo._bookmarks.iteritems():
395 destpeer.pushkey('bookmarks', k, '', hex(n))
395 destpeer.pushkey('bookmarks', k, '', hex(n))
396
396
397 if destrepo:
397 if destrepo:
398 fp = destrepo.opener("hgrc", "w", text=True)
398 fp = destrepo.opener("hgrc", "w", text=True)
399 fp.write("[paths]\n")
399 fp.write("[paths]\n")
400 u = util.url(abspath)
400 u = util.url(abspath)
401 u.passwd = None
401 u.passwd = None
402 defaulturl = str(u)
402 defaulturl = str(u)
403 fp.write("default = %s\n" % defaulturl)
403 fp.write("default = %s\n" % defaulturl)
404 fp.close()
404 fp.close()
405
405
406 destrepo.ui.setconfig('paths', 'default', defaulturl)
406 destrepo.ui.setconfig('paths', 'default', defaulturl)
407
407
408 if update:
408 if update:
409 if update is not True:
409 if update is not True:
410 checkout = srcpeer.lookup(update)
410 checkout = srcpeer.lookup(update)
411 uprev = None
411 uprev = None
412 status = None
412 status = None
413 if checkout is not None:
413 if checkout is not None:
414 try:
414 try:
415 uprev = destrepo.lookup(checkout)
415 uprev = destrepo.lookup(checkout)
416 except error.RepoLookupError:
416 except error.RepoLookupError:
417 pass
417 pass
418 if uprev is None:
418 if uprev is None:
419 try:
419 try:
420 uprev = destrepo._bookmarks['@']
420 uprev = destrepo._bookmarks['@']
421 update = '@'
421 update = '@'
422 bn = destrepo[uprev].branch()
422 bn = destrepo[uprev].branch()
423 if bn == 'default':
423 if bn == 'default':
424 status = _("updating to bookmark @\n")
424 status = _("updating to bookmark @\n")
425 else:
425 else:
426 status = _("updating to bookmark @ on branch %s\n"
426 status = _("updating to bookmark @ on branch %s\n"
427 % bn)
427 % bn)
428 except KeyError:
428 except KeyError:
429 try:
429 try:
430 uprev = destrepo.branchtip('default')
430 uprev = destrepo.branchtip('default')
431 except error.RepoLookupError:
431 except error.RepoLookupError:
432 uprev = destrepo.lookup('tip')
432 uprev = destrepo.lookup('tip')
433 if not status:
433 if not status:
434 bn = destrepo[uprev].branch()
434 bn = destrepo[uprev].branch()
435 status = _("updating to branch %s\n") % bn
435 status = _("updating to branch %s\n") % bn
436 destrepo.ui.status(status)
436 destrepo.ui.status(status)
437 _update(destrepo, uprev)
437 _update(destrepo, uprev)
438 if update in destrepo._bookmarks:
438 if update in destrepo._bookmarks:
439 bookmarks.setcurrent(destrepo, update)
439 bookmarks.setcurrent(destrepo, update)
440
441 return srcpeer, destpeer
442 finally:
440 finally:
443 release(srclock, destlock)
441 release(srclock, destlock)
444 if cleandir is not None:
442 if cleandir is not None:
445 shutil.rmtree(cleandir, True)
443 shutil.rmtree(cleandir, True)
446 if srcpeer is not None:
444 if srcpeer is not None:
447 srcpeer.close()
445 srcpeer.close()
446 return srcpeer, destpeer
448
447
449 def _showstats(repo, stats):
448 def _showstats(repo, stats):
450 repo.ui.status(_("%d files updated, %d files merged, "
449 repo.ui.status(_("%d files updated, %d files merged, "
451 "%d files removed, %d files unresolved\n") % stats)
450 "%d files removed, %d files unresolved\n") % stats)
452
451
453 def updaterepo(repo, node, overwrite):
452 def updaterepo(repo, node, overwrite):
454 """Update the working directory to node.
453 """Update the working directory to node.
455
454
456 When overwrite is set, changes are clobbered, merged else
455 When overwrite is set, changes are clobbered, merged else
457
456
458 returns stats (see pydoc mercurial.merge.applyupdates)"""
457 returns stats (see pydoc mercurial.merge.applyupdates)"""
459 return mergemod.update(repo, node, False, overwrite, None)
458 return mergemod.update(repo, node, False, overwrite, None)
460
459
461 def update(repo, node):
460 def update(repo, node):
462 """update the working directory to node, merging linear changes"""
461 """update the working directory to node, merging linear changes"""
463 stats = updaterepo(repo, node, False)
462 stats = updaterepo(repo, node, False)
464 _showstats(repo, stats)
463 _showstats(repo, stats)
465 if stats[3]:
464 if stats[3]:
466 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
465 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
467 return stats[3] > 0
466 return stats[3] > 0
468
467
469 # naming conflict in clone()
468 # naming conflict in clone()
470 _update = update
469 _update = update
471
470
472 def clean(repo, node, show_stats=True):
471 def clean(repo, node, show_stats=True):
473 """forcibly switch the working directory to node, clobbering changes"""
472 """forcibly switch the working directory to node, clobbering changes"""
474 stats = updaterepo(repo, node, True)
473 stats = updaterepo(repo, node, True)
475 if show_stats:
474 if show_stats:
476 _showstats(repo, stats)
475 _showstats(repo, stats)
477 return stats[3] > 0
476 return stats[3] > 0
478
477
479 def merge(repo, node, force=None, remind=True):
478 def merge(repo, node, force=None, remind=True):
480 """Branch merge with node, resolving changes. Return true if any
479 """Branch merge with node, resolving changes. Return true if any
481 unresolved conflicts."""
480 unresolved conflicts."""
482 stats = mergemod.update(repo, node, True, force, False)
481 stats = mergemod.update(repo, node, True, force, False)
483 _showstats(repo, stats)
482 _showstats(repo, stats)
484 if stats[3]:
483 if stats[3]:
485 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
484 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
486 "or 'hg update -C .' to abandon\n"))
485 "or 'hg update -C .' to abandon\n"))
487 elif remind:
486 elif remind:
488 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
487 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
489 return stats[3] > 0
488 return stats[3] > 0
490
489
491 def _incoming(displaychlist, subreporecurse, ui, repo, source,
490 def _incoming(displaychlist, subreporecurse, ui, repo, source,
492 opts, buffered=False):
491 opts, buffered=False):
493 """
492 """
494 Helper for incoming / gincoming.
493 Helper for incoming / gincoming.
495 displaychlist gets called with
494 displaychlist gets called with
496 (remoterepo, incomingchangesetlist, displayer) parameters,
495 (remoterepo, incomingchangesetlist, displayer) parameters,
497 and is supposed to contain only code that can't be unified.
496 and is supposed to contain only code that can't be unified.
498 """
497 """
499 source, branches = parseurl(ui.expandpath(source), opts.get('branch'))
498 source, branches = parseurl(ui.expandpath(source), opts.get('branch'))
500 other = peer(repo, opts, source)
499 other = peer(repo, opts, source)
501 ui.status(_('comparing with %s\n') % util.hidepassword(source))
500 ui.status(_('comparing with %s\n') % util.hidepassword(source))
502 revs, checkout = addbranchrevs(repo, other, branches, opts.get('rev'))
501 revs, checkout = addbranchrevs(repo, other, branches, opts.get('rev'))
503
502
504 if revs:
503 if revs:
505 revs = [other.lookup(rev) for rev in revs]
504 revs = [other.lookup(rev) for rev in revs]
506 other, chlist, cleanupfn = bundlerepo.getremotechanges(ui, repo, other,
505 other, chlist, cleanupfn = bundlerepo.getremotechanges(ui, repo, other,
507 revs, opts["bundle"], opts["force"])
506 revs, opts["bundle"], opts["force"])
508 try:
507 try:
509 if not chlist:
508 if not chlist:
510 ui.status(_("no changes found\n"))
509 ui.status(_("no changes found\n"))
511 return subreporecurse()
510 return subreporecurse()
512
511
513 displayer = cmdutil.show_changeset(ui, other, opts, buffered)
512 displayer = cmdutil.show_changeset(ui, other, opts, buffered)
514
513
515 # XXX once graphlog extension makes it into core,
514 # XXX once graphlog extension makes it into core,
516 # should be replaced by a if graph/else
515 # should be replaced by a if graph/else
517 displaychlist(other, chlist, displayer)
516 displaychlist(other, chlist, displayer)
518
517
519 displayer.close()
518 displayer.close()
520 finally:
519 finally:
521 cleanupfn()
520 cleanupfn()
522 subreporecurse()
521 subreporecurse()
523 return 0 # exit code is zero since we found incoming changes
522 return 0 # exit code is zero since we found incoming changes
524
523
525 def incoming(ui, repo, source, opts):
524 def incoming(ui, repo, source, opts):
526 def subreporecurse():
525 def subreporecurse():
527 ret = 1
526 ret = 1
528 if opts.get('subrepos'):
527 if opts.get('subrepos'):
529 ctx = repo[None]
528 ctx = repo[None]
530 for subpath in sorted(ctx.substate):
529 for subpath in sorted(ctx.substate):
531 sub = ctx.sub(subpath)
530 sub = ctx.sub(subpath)
532 ret = min(ret, sub.incoming(ui, source, opts))
531 ret = min(ret, sub.incoming(ui, source, opts))
533 return ret
532 return ret
534
533
535 def display(other, chlist, displayer):
534 def display(other, chlist, displayer):
536 limit = cmdutil.loglimit(opts)
535 limit = cmdutil.loglimit(opts)
537 if opts.get('newest_first'):
536 if opts.get('newest_first'):
538 chlist.reverse()
537 chlist.reverse()
539 count = 0
538 count = 0
540 for n in chlist:
539 for n in chlist:
541 if limit is not None and count >= limit:
540 if limit is not None and count >= limit:
542 break
541 break
543 parents = [p for p in other.changelog.parents(n) if p != nullid]
542 parents = [p for p in other.changelog.parents(n) if p != nullid]
544 if opts.get('no_merges') and len(parents) == 2:
543 if opts.get('no_merges') and len(parents) == 2:
545 continue
544 continue
546 count += 1
545 count += 1
547 displayer.show(other[n])
546 displayer.show(other[n])
548 return _incoming(display, subreporecurse, ui, repo, source, opts)
547 return _incoming(display, subreporecurse, ui, repo, source, opts)
549
548
550 def _outgoing(ui, repo, dest, opts):
549 def _outgoing(ui, repo, dest, opts):
551 dest = ui.expandpath(dest or 'default-push', dest or 'default')
550 dest = ui.expandpath(dest or 'default-push', dest or 'default')
552 dest, branches = parseurl(dest, opts.get('branch'))
551 dest, branches = parseurl(dest, opts.get('branch'))
553 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
552 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
554 revs, checkout = addbranchrevs(repo, repo, branches, opts.get('rev'))
553 revs, checkout = addbranchrevs(repo, repo, branches, opts.get('rev'))
555 if revs:
554 if revs:
556 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
555 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
557
556
558 other = peer(repo, opts, dest)
557 other = peer(repo, opts, dest)
559 outgoing = discovery.findcommonoutgoing(repo.unfiltered(), other, revs,
558 outgoing = discovery.findcommonoutgoing(repo.unfiltered(), other, revs,
560 force=opts.get('force'))
559 force=opts.get('force'))
561 o = outgoing.missing
560 o = outgoing.missing
562 if not o:
561 if not o:
563 scmutil.nochangesfound(repo.ui, repo, outgoing.excluded)
562 scmutil.nochangesfound(repo.ui, repo, outgoing.excluded)
564 return None
563 return None
565 return o
564 return o
566
565
567 def outgoing(ui, repo, dest, opts):
566 def outgoing(ui, repo, dest, opts):
568 def recurse():
567 def recurse():
569 ret = 1
568 ret = 1
570 if opts.get('subrepos'):
569 if opts.get('subrepos'):
571 ctx = repo[None]
570 ctx = repo[None]
572 for subpath in sorted(ctx.substate):
571 for subpath in sorted(ctx.substate):
573 sub = ctx.sub(subpath)
572 sub = ctx.sub(subpath)
574 ret = min(ret, sub.outgoing(ui, dest, opts))
573 ret = min(ret, sub.outgoing(ui, dest, opts))
575 return ret
574 return ret
576
575
577 limit = cmdutil.loglimit(opts)
576 limit = cmdutil.loglimit(opts)
578 o = _outgoing(ui, repo, dest, opts)
577 o = _outgoing(ui, repo, dest, opts)
579 if o is None:
578 if o is None:
580 return recurse()
579 return recurse()
581
580
582 if opts.get('newest_first'):
581 if opts.get('newest_first'):
583 o.reverse()
582 o.reverse()
584 displayer = cmdutil.show_changeset(ui, repo, opts)
583 displayer = cmdutil.show_changeset(ui, repo, opts)
585 count = 0
584 count = 0
586 for n in o:
585 for n in o:
587 if limit is not None and count >= limit:
586 if limit is not None and count >= limit:
588 break
587 break
589 parents = [p for p in repo.changelog.parents(n) if p != nullid]
588 parents = [p for p in repo.changelog.parents(n) if p != nullid]
590 if opts.get('no_merges') and len(parents) == 2:
589 if opts.get('no_merges') and len(parents) == 2:
591 continue
590 continue
592 count += 1
591 count += 1
593 displayer.show(repo[n])
592 displayer.show(repo[n])
594 displayer.close()
593 displayer.close()
595 recurse()
594 recurse()
596 return 0 # exit code is zero since we found outgoing changes
595 return 0 # exit code is zero since we found outgoing changes
597
596
598 def revert(repo, node, choose):
597 def revert(repo, node, choose):
599 """revert changes to revision in node without updating dirstate"""
598 """revert changes to revision in node without updating dirstate"""
600 return mergemod.update(repo, node, False, True, choose)[3] > 0
599 return mergemod.update(repo, node, False, True, choose)[3] > 0
601
600
602 def verify(repo):
601 def verify(repo):
603 """verify the consistency of a repository"""
602 """verify the consistency of a repository"""
604 return verifymod.verify(repo)
603 return verifymod.verify(repo)
605
604
606 def remoteui(src, opts):
605 def remoteui(src, opts):
607 'build a remote ui from ui or repo and opts'
606 'build a remote ui from ui or repo and opts'
608 if util.safehasattr(src, 'baseui'): # looks like a repository
607 if util.safehasattr(src, 'baseui'): # looks like a repository
609 dst = src.baseui.copy() # drop repo-specific config
608 dst = src.baseui.copy() # drop repo-specific config
610 src = src.ui # copy target options from repo
609 src = src.ui # copy target options from repo
611 else: # assume it's a global ui object
610 else: # assume it's a global ui object
612 dst = src.copy() # keep all global options
611 dst = src.copy() # keep all global options
613
612
614 # copy ssh-specific options
613 # copy ssh-specific options
615 for o in 'ssh', 'remotecmd':
614 for o in 'ssh', 'remotecmd':
616 v = opts.get(o) or src.config('ui', o)
615 v = opts.get(o) or src.config('ui', o)
617 if v:
616 if v:
618 dst.setconfig("ui", o, v)
617 dst.setconfig("ui", o, v)
619
618
620 # copy bundle-specific options
619 # copy bundle-specific options
621 r = src.config('bundle', 'mainreporoot')
620 r = src.config('bundle', 'mainreporoot')
622 if r:
621 if r:
623 dst.setconfig('bundle', 'mainreporoot', r)
622 dst.setconfig('bundle', 'mainreporoot', r)
624
623
625 # copy selected local settings to the remote ui
624 # copy selected local settings to the remote ui
626 for sect in ('auth', 'hostfingerprints', 'http_proxy'):
625 for sect in ('auth', 'hostfingerprints', 'http_proxy'):
627 for key, val in src.configitems(sect):
626 for key, val in src.configitems(sect):
628 dst.setconfig(sect, key, val)
627 dst.setconfig(sect, key, val)
629 v = src.config('web', 'cacerts')
628 v = src.config('web', 'cacerts')
630 if v:
629 if v:
631 dst.setconfig('web', 'cacerts', util.expandpath(v))
630 dst.setconfig('web', 'cacerts', util.expandpath(v))
632
631
633 return dst
632 return dst
General Comments 0
You need to be logged in to leave comments. Login now