##// END OF EJS Templates
Merge with stable
Matt Mackall -
r11312:3f140908 merge default
parent child Browse files
Show More
@@ -1,427 +1,429 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 import localrepo, bundlerepo, httprepo, sshrepo, statichttprepo
11 import localrepo, bundlerepo, httprepo, sshrepo, statichttprepo
12 import lock, util, extensions, error, encoding, node
12 import lock, util, extensions, error, encoding, node
13 import merge as mergemod
13 import merge as mergemod
14 import verify as verifymod
14 import verify as verifymod
15 import errno, os, shutil
15 import errno, os, shutil
16
16
17 def _local(path):
17 def _local(path):
18 path = util.expandpath(util.drop_scheme('file', path))
18 path = util.expandpath(util.drop_scheme('file', path))
19 return (os.path.isfile(path) and bundlerepo or localrepo)
19 return (os.path.isfile(path) and bundlerepo or localrepo)
20
20
21 def addbranchrevs(lrepo, repo, branches, revs):
21 def addbranchrevs(lrepo, repo, branches, revs):
22 if not branches:
22 if not branches:
23 return revs or None, revs and revs[0] or None
23 return revs or None, revs and revs[0] or None
24 revs = revs and list(revs) or []
24 revs = revs and list(revs) or []
25 if not repo.capable('branchmap'):
25 if not repo.capable('branchmap'):
26 revs.extend(branches)
26 revs.extend(branches)
27 return revs, revs[0]
27 return revs, revs[0]
28 branchmap = repo.branchmap()
28 branchmap = repo.branchmap()
29 for branch in branches:
29 for branch in branches:
30 if branch == '.':
30 if branch == '.':
31 if not lrepo or not lrepo.local():
31 if not lrepo or not lrepo.local():
32 raise util.Abort(_("dirstate branch not accessible"))
32 raise util.Abort(_("dirstate branch not accessible"))
33 branch = lrepo.dirstate.branch()
33 butf8 = lrepo.dirstate.branch()
34 branch = encoding.tolocal(butf8)
35 else:
34 butf8 = encoding.fromlocal(branch)
36 butf8 = encoding.fromlocal(branch)
35 if butf8 in branchmap:
37 if butf8 in branchmap:
36 revs.extend(node.hex(r) for r in reversed(branchmap[butf8]))
38 revs.extend(node.hex(r) for r in reversed(branchmap[butf8]))
37 else:
39 else:
38 revs.append(branch)
40 revs.append(branch)
39 return revs, revs[0]
41 return revs, revs[0]
40
42
41 def parseurl(url, branches=None):
43 def parseurl(url, branches=None):
42 '''parse url#branch, returning url, branches+[branch]'''
44 '''parse url#branch, returning url, branches+[branch]'''
43
45
44 if '#' not in url:
46 if '#' not in url:
45 return url, branches or []
47 return url, branches or []
46 url, branch = url.split('#', 1)
48 url, branch = url.split('#', 1)
47 return url, (branches or []) + [branch]
49 return url, (branches or []) + [branch]
48
50
49 schemes = {
51 schemes = {
50 'bundle': bundlerepo,
52 'bundle': bundlerepo,
51 'file': _local,
53 'file': _local,
52 'http': httprepo,
54 'http': httprepo,
53 'https': httprepo,
55 'https': httprepo,
54 'ssh': sshrepo,
56 'ssh': sshrepo,
55 'static-http': statichttprepo,
57 'static-http': statichttprepo,
56 }
58 }
57
59
58 def _lookup(path):
60 def _lookup(path):
59 scheme = 'file'
61 scheme = 'file'
60 if path:
62 if path:
61 c = path.find(':')
63 c = path.find(':')
62 if c > 0:
64 if c > 0:
63 scheme = path[:c]
65 scheme = path[:c]
64 thing = schemes.get(scheme) or schemes['file']
66 thing = schemes.get(scheme) or schemes['file']
65 try:
67 try:
66 return thing(path)
68 return thing(path)
67 except TypeError:
69 except TypeError:
68 return thing
70 return thing
69
71
70 def islocal(repo):
72 def islocal(repo):
71 '''return true if repo or path is local'''
73 '''return true if repo or path is local'''
72 if isinstance(repo, str):
74 if isinstance(repo, str):
73 try:
75 try:
74 return _lookup(repo).islocal(repo)
76 return _lookup(repo).islocal(repo)
75 except AttributeError:
77 except AttributeError:
76 return False
78 return False
77 return repo.local()
79 return repo.local()
78
80
79 def repository(ui, path='', create=False):
81 def repository(ui, path='', create=False):
80 """return a repository object for the specified path"""
82 """return a repository object for the specified path"""
81 repo = _lookup(path).instance(ui, path, create)
83 repo = _lookup(path).instance(ui, path, create)
82 ui = getattr(repo, "ui", ui)
84 ui = getattr(repo, "ui", ui)
83 for name, module in extensions.extensions():
85 for name, module in extensions.extensions():
84 hook = getattr(module, 'reposetup', None)
86 hook = getattr(module, 'reposetup', None)
85 if hook:
87 if hook:
86 hook(ui, repo)
88 hook(ui, repo)
87 return repo
89 return repo
88
90
89 def defaultdest(source):
91 def defaultdest(source):
90 '''return default destination of clone if none is given'''
92 '''return default destination of clone if none is given'''
91 return os.path.basename(os.path.normpath(source))
93 return os.path.basename(os.path.normpath(source))
92
94
93 def localpath(path):
95 def localpath(path):
94 if path.startswith('file://localhost/'):
96 if path.startswith('file://localhost/'):
95 return path[16:]
97 return path[16:]
96 if path.startswith('file://'):
98 if path.startswith('file://'):
97 return path[7:]
99 return path[7:]
98 if path.startswith('file:'):
100 if path.startswith('file:'):
99 return path[5:]
101 return path[5:]
100 return path
102 return path
101
103
102 def share(ui, source, dest=None, update=True):
104 def share(ui, source, dest=None, update=True):
103 '''create a shared repository'''
105 '''create a shared repository'''
104
106
105 if not islocal(source):
107 if not islocal(source):
106 raise util.Abort(_('can only share local repositories'))
108 raise util.Abort(_('can only share local repositories'))
107
109
108 if not dest:
110 if not dest:
109 dest = defaultdest(source)
111 dest = defaultdest(source)
110 else:
112 else:
111 dest = ui.expandpath(dest)
113 dest = ui.expandpath(dest)
112
114
113 if isinstance(source, str):
115 if isinstance(source, str):
114 origsource = ui.expandpath(source)
116 origsource = ui.expandpath(source)
115 source, branches = parseurl(origsource)
117 source, branches = parseurl(origsource)
116 srcrepo = repository(ui, source)
118 srcrepo = repository(ui, source)
117 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
119 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
118 else:
120 else:
119 srcrepo = source
121 srcrepo = source
120 origsource = source = srcrepo.url()
122 origsource = source = srcrepo.url()
121 checkout = None
123 checkout = None
122
124
123 sharedpath = srcrepo.sharedpath # if our source is already sharing
125 sharedpath = srcrepo.sharedpath # if our source is already sharing
124
126
125 root = os.path.realpath(dest)
127 root = os.path.realpath(dest)
126 roothg = os.path.join(root, '.hg')
128 roothg = os.path.join(root, '.hg')
127
129
128 if os.path.exists(roothg):
130 if os.path.exists(roothg):
129 raise util.Abort(_('destination already exists'))
131 raise util.Abort(_('destination already exists'))
130
132
131 if not os.path.isdir(root):
133 if not os.path.isdir(root):
132 os.mkdir(root)
134 os.mkdir(root)
133 os.mkdir(roothg)
135 os.mkdir(roothg)
134
136
135 requirements = ''
137 requirements = ''
136 try:
138 try:
137 requirements = srcrepo.opener('requires').read()
139 requirements = srcrepo.opener('requires').read()
138 except IOError, inst:
140 except IOError, inst:
139 if inst.errno != errno.ENOENT:
141 if inst.errno != errno.ENOENT:
140 raise
142 raise
141
143
142 requirements += 'shared\n'
144 requirements += 'shared\n'
143 file(os.path.join(roothg, 'requires'), 'w').write(requirements)
145 file(os.path.join(roothg, 'requires'), 'w').write(requirements)
144 file(os.path.join(roothg, 'sharedpath'), 'w').write(sharedpath)
146 file(os.path.join(roothg, 'sharedpath'), 'w').write(sharedpath)
145
147
146 default = srcrepo.ui.config('paths', 'default')
148 default = srcrepo.ui.config('paths', 'default')
147 if default:
149 if default:
148 f = file(os.path.join(roothg, 'hgrc'), 'w')
150 f = file(os.path.join(roothg, 'hgrc'), 'w')
149 f.write('[paths]\ndefault = %s\n' % default)
151 f.write('[paths]\ndefault = %s\n' % default)
150 f.close()
152 f.close()
151
153
152 r = repository(ui, root)
154 r = repository(ui, root)
153
155
154 if update:
156 if update:
155 r.ui.status(_("updating working directory\n"))
157 r.ui.status(_("updating working directory\n"))
156 if update is not True:
158 if update is not True:
157 checkout = update
159 checkout = update
158 for test in (checkout, 'default', 'tip'):
160 for test in (checkout, 'default', 'tip'):
159 if test is None:
161 if test is None:
160 continue
162 continue
161 try:
163 try:
162 uprev = r.lookup(test)
164 uprev = r.lookup(test)
163 break
165 break
164 except error.RepoLookupError:
166 except error.RepoLookupError:
165 continue
167 continue
166 _update(r, uprev)
168 _update(r, uprev)
167
169
168 def clone(ui, source, dest=None, pull=False, rev=None, update=True,
170 def clone(ui, source, dest=None, pull=False, rev=None, update=True,
169 stream=False, branch=None):
171 stream=False, branch=None):
170 """Make a copy of an existing repository.
172 """Make a copy of an existing repository.
171
173
172 Create a copy of an existing repository in a new directory. The
174 Create a copy of an existing repository in a new directory. The
173 source and destination are URLs, as passed to the repository
175 source and destination are URLs, as passed to the repository
174 function. Returns a pair of repository objects, the source and
176 function. Returns a pair of repository objects, the source and
175 newly created destination.
177 newly created destination.
176
178
177 The location of the source is added to the new repository's
179 The location of the source is added to the new repository's
178 .hg/hgrc file, as the default to be used for future pulls and
180 .hg/hgrc file, as the default to be used for future pulls and
179 pushes.
181 pushes.
180
182
181 If an exception is raised, the partly cloned/updated destination
183 If an exception is raised, the partly cloned/updated destination
182 repository will be deleted.
184 repository will be deleted.
183
185
184 Arguments:
186 Arguments:
185
187
186 source: repository object or URL
188 source: repository object or URL
187
189
188 dest: URL of destination repository to create (defaults to base
190 dest: URL of destination repository to create (defaults to base
189 name of source repository)
191 name of source repository)
190
192
191 pull: always pull from source repository, even in local case
193 pull: always pull from source repository, even in local case
192
194
193 stream: stream raw data uncompressed from repository (fast over
195 stream: stream raw data uncompressed from repository (fast over
194 LAN, slow over WAN)
196 LAN, slow over WAN)
195
197
196 rev: revision to clone up to (implies pull=True)
198 rev: revision to clone up to (implies pull=True)
197
199
198 update: update working directory after clone completes, if
200 update: update working directory after clone completes, if
199 destination is local repository (True means update to default rev,
201 destination is local repository (True means update to default rev,
200 anything else is treated as a revision)
202 anything else is treated as a revision)
201
203
202 branch: branches to clone
204 branch: branches to clone
203 """
205 """
204
206
205 if isinstance(source, str):
207 if isinstance(source, str):
206 origsource = ui.expandpath(source)
208 origsource = ui.expandpath(source)
207 source, branch = parseurl(origsource, branch)
209 source, branch = parseurl(origsource, branch)
208 src_repo = repository(ui, source)
210 src_repo = repository(ui, source)
209 else:
211 else:
210 src_repo = source
212 src_repo = source
211 branch = None
213 branch = None
212 origsource = source = src_repo.url()
214 origsource = source = src_repo.url()
213 rev, checkout = addbranchrevs(src_repo, src_repo, branch, rev)
215 rev, checkout = addbranchrevs(src_repo, src_repo, branch, rev)
214
216
215 if dest is None:
217 if dest is None:
216 dest = defaultdest(source)
218 dest = defaultdest(source)
217 ui.status(_("destination directory: %s\n") % dest)
219 ui.status(_("destination directory: %s\n") % dest)
218 else:
220 else:
219 dest = ui.expandpath(dest)
221 dest = ui.expandpath(dest)
220
222
221 dest = localpath(dest)
223 dest = localpath(dest)
222 source = localpath(source)
224 source = localpath(source)
223
225
224 if os.path.exists(dest):
226 if os.path.exists(dest):
225 if not os.path.isdir(dest):
227 if not os.path.isdir(dest):
226 raise util.Abort(_("destination '%s' already exists") % dest)
228 raise util.Abort(_("destination '%s' already exists") % dest)
227 elif os.listdir(dest):
229 elif os.listdir(dest):
228 raise util.Abort(_("destination '%s' is not empty") % dest)
230 raise util.Abort(_("destination '%s' is not empty") % dest)
229
231
230 class DirCleanup(object):
232 class DirCleanup(object):
231 def __init__(self, dir_):
233 def __init__(self, dir_):
232 self.rmtree = shutil.rmtree
234 self.rmtree = shutil.rmtree
233 self.dir_ = dir_
235 self.dir_ = dir_
234 def close(self):
236 def close(self):
235 self.dir_ = None
237 self.dir_ = None
236 def cleanup(self):
238 def cleanup(self):
237 if self.dir_:
239 if self.dir_:
238 self.rmtree(self.dir_, True)
240 self.rmtree(self.dir_, True)
239
241
240 src_lock = dest_lock = dir_cleanup = None
242 src_lock = dest_lock = dir_cleanup = None
241 try:
243 try:
242 if islocal(dest):
244 if islocal(dest):
243 dir_cleanup = DirCleanup(dest)
245 dir_cleanup = DirCleanup(dest)
244
246
245 abspath = origsource
247 abspath = origsource
246 copy = False
248 copy = False
247 if src_repo.cancopy() and islocal(dest):
249 if src_repo.cancopy() and islocal(dest):
248 abspath = os.path.abspath(util.drop_scheme('file', origsource))
250 abspath = os.path.abspath(util.drop_scheme('file', origsource))
249 copy = not pull and not rev
251 copy = not pull and not rev
250
252
251 if copy:
253 if copy:
252 try:
254 try:
253 # we use a lock here because if we race with commit, we
255 # we use a lock here because if we race with commit, we
254 # can end up with extra data in the cloned revlogs that's
256 # can end up with extra data in the cloned revlogs that's
255 # not pointed to by changesets, thus causing verify to
257 # not pointed to by changesets, thus causing verify to
256 # fail
258 # fail
257 src_lock = src_repo.lock(wait=False)
259 src_lock = src_repo.lock(wait=False)
258 except error.LockError:
260 except error.LockError:
259 copy = False
261 copy = False
260
262
261 if copy:
263 if copy:
262 src_repo.hook('preoutgoing', throw=True, source='clone')
264 src_repo.hook('preoutgoing', throw=True, source='clone')
263 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
265 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
264 if not os.path.exists(dest):
266 if not os.path.exists(dest):
265 os.mkdir(dest)
267 os.mkdir(dest)
266 else:
268 else:
267 # only clean up directories we create ourselves
269 # only clean up directories we create ourselves
268 dir_cleanup.dir_ = hgdir
270 dir_cleanup.dir_ = hgdir
269 try:
271 try:
270 dest_path = hgdir
272 dest_path = hgdir
271 os.mkdir(dest_path)
273 os.mkdir(dest_path)
272 except OSError, inst:
274 except OSError, inst:
273 if inst.errno == errno.EEXIST:
275 if inst.errno == errno.EEXIST:
274 dir_cleanup.close()
276 dir_cleanup.close()
275 raise util.Abort(_("destination '%s' already exists")
277 raise util.Abort(_("destination '%s' already exists")
276 % dest)
278 % dest)
277 raise
279 raise
278
280
279 hardlink = None
281 hardlink = None
280 num = 0
282 num = 0
281 for f in src_repo.store.copylist():
283 for f in src_repo.store.copylist():
282 src = os.path.join(src_repo.sharedpath, f)
284 src = os.path.join(src_repo.sharedpath, f)
283 dst = os.path.join(dest_path, f)
285 dst = os.path.join(dest_path, f)
284 dstbase = os.path.dirname(dst)
286 dstbase = os.path.dirname(dst)
285 if dstbase and not os.path.exists(dstbase):
287 if dstbase and not os.path.exists(dstbase):
286 os.mkdir(dstbase)
288 os.mkdir(dstbase)
287 if os.path.exists(src):
289 if os.path.exists(src):
288 if dst.endswith('data'):
290 if dst.endswith('data'):
289 # lock to avoid premature writing to the target
291 # lock to avoid premature writing to the target
290 dest_lock = lock.lock(os.path.join(dstbase, "lock"))
292 dest_lock = lock.lock(os.path.join(dstbase, "lock"))
291 hardlink, n = util.copyfiles(src, dst, hardlink)
293 hardlink, n = util.copyfiles(src, dst, hardlink)
292 num += n
294 num += n
293 if hardlink:
295 if hardlink:
294 ui.debug("linked %d files\n" % num)
296 ui.debug("linked %d files\n" % num)
295 else:
297 else:
296 ui.debug("copied %d files\n" % num)
298 ui.debug("copied %d files\n" % num)
297
299
298 # we need to re-init the repo after manually copying the data
300 # we need to re-init the repo after manually copying the data
299 # into it
301 # into it
300 dest_repo = repository(ui, dest)
302 dest_repo = repository(ui, dest)
301 src_repo.hook('outgoing', source='clone', node='0'*40)
303 src_repo.hook('outgoing', source='clone', node='0'*40)
302 else:
304 else:
303 try:
305 try:
304 dest_repo = repository(ui, dest, create=True)
306 dest_repo = repository(ui, dest, create=True)
305 except OSError, inst:
307 except OSError, inst:
306 if inst.errno == errno.EEXIST:
308 if inst.errno == errno.EEXIST:
307 dir_cleanup.close()
309 dir_cleanup.close()
308 raise util.Abort(_("destination '%s' already exists")
310 raise util.Abort(_("destination '%s' already exists")
309 % dest)
311 % dest)
310 raise
312 raise
311
313
312 revs = None
314 revs = None
313 if rev:
315 if rev:
314 if 'lookup' not in src_repo.capabilities:
316 if 'lookup' not in src_repo.capabilities:
315 raise util.Abort(_("src repository does not support "
317 raise util.Abort(_("src repository does not support "
316 "revision lookup and so doesn't "
318 "revision lookup and so doesn't "
317 "support clone by revision"))
319 "support clone by revision"))
318 revs = [src_repo.lookup(r) for r in rev]
320 revs = [src_repo.lookup(r) for r in rev]
319 checkout = revs[0]
321 checkout = revs[0]
320 if dest_repo.local():
322 if dest_repo.local():
321 dest_repo.clone(src_repo, heads=revs, stream=stream)
323 dest_repo.clone(src_repo, heads=revs, stream=stream)
322 elif src_repo.local():
324 elif src_repo.local():
323 src_repo.push(dest_repo, revs=revs)
325 src_repo.push(dest_repo, revs=revs)
324 else:
326 else:
325 raise util.Abort(_("clone from remote to remote not supported"))
327 raise util.Abort(_("clone from remote to remote not supported"))
326
328
327 if dir_cleanup:
329 if dir_cleanup:
328 dir_cleanup.close()
330 dir_cleanup.close()
329
331
330 if dest_repo.local():
332 if dest_repo.local():
331 fp = dest_repo.opener("hgrc", "w", text=True)
333 fp = dest_repo.opener("hgrc", "w", text=True)
332 fp.write("[paths]\n")
334 fp.write("[paths]\n")
333 fp.write("default = %s\n" % abspath)
335 fp.write("default = %s\n" % abspath)
334 fp.close()
336 fp.close()
335
337
336 dest_repo.ui.setconfig('paths', 'default', abspath)
338 dest_repo.ui.setconfig('paths', 'default', abspath)
337
339
338 if update:
340 if update:
339 if update is not True:
341 if update is not True:
340 checkout = update
342 checkout = update
341 if src_repo.local():
343 if src_repo.local():
342 checkout = src_repo.lookup(update)
344 checkout = src_repo.lookup(update)
343 for test in (checkout, 'default', 'tip'):
345 for test in (checkout, 'default', 'tip'):
344 if test is None:
346 if test is None:
345 continue
347 continue
346 try:
348 try:
347 uprev = dest_repo.lookup(test)
349 uprev = dest_repo.lookup(test)
348 break
350 break
349 except error.RepoLookupError:
351 except error.RepoLookupError:
350 continue
352 continue
351 bn = dest_repo[uprev].branch()
353 bn = dest_repo[uprev].branch()
352 dest_repo.ui.status(_("updating to branch %s\n")
354 dest_repo.ui.status(_("updating to branch %s\n")
353 % encoding.tolocal(bn))
355 % encoding.tolocal(bn))
354 _update(dest_repo, uprev)
356 _update(dest_repo, uprev)
355
357
356 return src_repo, dest_repo
358 return src_repo, dest_repo
357 finally:
359 finally:
358 release(src_lock, dest_lock)
360 release(src_lock, dest_lock)
359 if dir_cleanup is not None:
361 if dir_cleanup is not None:
360 dir_cleanup.cleanup()
362 dir_cleanup.cleanup()
361
363
362 def _showstats(repo, stats):
364 def _showstats(repo, stats):
363 repo.ui.status(_("%d files updated, %d files merged, "
365 repo.ui.status(_("%d files updated, %d files merged, "
364 "%d files removed, %d files unresolved\n") % stats)
366 "%d files removed, %d files unresolved\n") % stats)
365
367
366 def update(repo, node):
368 def update(repo, node):
367 """update the working directory to node, merging linear changes"""
369 """update the working directory to node, merging linear changes"""
368 stats = mergemod.update(repo, node, False, False, None)
370 stats = mergemod.update(repo, node, False, False, None)
369 _showstats(repo, stats)
371 _showstats(repo, stats)
370 if stats[3]:
372 if stats[3]:
371 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
373 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
372 return stats[3] > 0
374 return stats[3] > 0
373
375
374 # naming conflict in clone()
376 # naming conflict in clone()
375 _update = update
377 _update = update
376
378
377 def clean(repo, node, show_stats=True):
379 def clean(repo, node, show_stats=True):
378 """forcibly switch the working directory to node, clobbering changes"""
380 """forcibly switch the working directory to node, clobbering changes"""
379 stats = mergemod.update(repo, node, False, True, None)
381 stats = mergemod.update(repo, node, False, True, None)
380 if show_stats:
382 if show_stats:
381 _showstats(repo, stats)
383 _showstats(repo, stats)
382 return stats[3] > 0
384 return stats[3] > 0
383
385
384 def merge(repo, node, force=None, remind=True):
386 def merge(repo, node, force=None, remind=True):
385 """branch merge with node, resolving changes"""
387 """branch merge with node, resolving changes"""
386 stats = mergemod.update(repo, node, True, force, False)
388 stats = mergemod.update(repo, node, True, force, False)
387 _showstats(repo, stats)
389 _showstats(repo, stats)
388 if stats[3]:
390 if stats[3]:
389 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
391 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
390 "or 'hg update -C' to abandon\n"))
392 "or 'hg update -C' to abandon\n"))
391 elif remind:
393 elif remind:
392 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
394 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
393 return stats[3] > 0
395 return stats[3] > 0
394
396
395 def revert(repo, node, choose):
397 def revert(repo, node, choose):
396 """revert changes to revision in node without updating dirstate"""
398 """revert changes to revision in node without updating dirstate"""
397 return mergemod.update(repo, node, False, True, choose)[3] > 0
399 return mergemod.update(repo, node, False, True, choose)[3] > 0
398
400
399 def verify(repo):
401 def verify(repo):
400 """verify the consistency of a repository"""
402 """verify the consistency of a repository"""
401 return verifymod.verify(repo)
403 return verifymod.verify(repo)
402
404
403 def remoteui(src, opts):
405 def remoteui(src, opts):
404 'build a remote ui from ui or repo and opts'
406 'build a remote ui from ui or repo and opts'
405 if hasattr(src, 'baseui'): # looks like a repository
407 if hasattr(src, 'baseui'): # looks like a repository
406 dst = src.baseui.copy() # drop repo-specific config
408 dst = src.baseui.copy() # drop repo-specific config
407 src = src.ui # copy target options from repo
409 src = src.ui # copy target options from repo
408 else: # assume it's a global ui object
410 else: # assume it's a global ui object
409 dst = src.copy() # keep all global options
411 dst = src.copy() # keep all global options
410
412
411 # copy ssh-specific options
413 # copy ssh-specific options
412 for o in 'ssh', 'remotecmd':
414 for o in 'ssh', 'remotecmd':
413 v = opts.get(o) or src.config('ui', o)
415 v = opts.get(o) or src.config('ui', o)
414 if v:
416 if v:
415 dst.setconfig("ui", o, v)
417 dst.setconfig("ui", o, v)
416
418
417 # copy bundle-specific options
419 # copy bundle-specific options
418 r = src.config('bundle', 'mainreporoot')
420 r = src.config('bundle', 'mainreporoot')
419 if r:
421 if r:
420 dst.setconfig('bundle', 'mainreporoot', r)
422 dst.setconfig('bundle', 'mainreporoot', r)
421
423
422 # copy auth and http_proxy section settings
424 # copy auth and http_proxy section settings
423 for sect in ('auth', 'http_proxy'):
425 for sect in ('auth', 'http_proxy'):
424 for key, val in src.configitems(sect):
426 for key, val in src.configitems(sect):
425 dst.setconfig(sect, key, val)
427 dst.setconfig(sect, key, val)
426
428
427 return dst
429 return dst
@@ -1,43 +1,55 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 # test branch selection options
3 # test branch selection options
4 hg init branch
4 hg init branch
5 cd branch
5 cd branch
6 hg branch a
6 hg branch a
7 echo a > foo
7 echo a > foo
8 hg ci -d '0 0' -Ama
8 hg ci -d '0 0' -Ama
9 echo a2 > foo
9 echo a2 > foo
10 hg ci -d '0 0' -ma2
10 hg ci -d '0 0' -ma2
11 hg up 0
11 hg up 0
12 hg branch c
12 hg branch c
13 echo c > foo
13 echo c > foo
14 hg ci -d '0 0' -mc
14 hg ci -d '0 0' -mc
15 cd ..
15 cd ..
16 hg clone -r 0 branch branch2
16 hg clone -r 0 branch branch2
17 cd branch2
17 cd branch2
18 hg up 0
18 hg up 0
19 hg branch b
19 hg branch b
20 echo b > foo
20 echo b > foo
21 hg ci -d '0 0' -mb
21 hg ci -d '0 0' -mb
22 hg up 0
22 hg up 0
23 hg --encoding utf-8 branch Γ¦
24 echo ae1 > foo
25 hg ci -d '0 0' -mae1
26 hg up 0
27 hg --encoding utf-8 branch -f Γ¦
28 echo ae2 > foo
29 hg ci -d '0 0' -mae2
30 hg up 0
23 hg branch -f b
31 hg branch -f b
24 echo b2 > foo
32 echo b2 > foo
25 hg ci -d '0 0' -mb2
33 hg ci -d '0 0' -mb2
26
34
27 echo in rev c branch a
35 echo in rev c branch a
28 hg in -qr c ../branch#a
36 hg in -qr c ../branch#a
29 hg in -qr c -b a
37 hg in -qr c -b a
30 echo out branch .
38 echo out branch .
31 hg out -q ../branch#.
39 hg out -q ../branch#.
32 hg out -q -b .
40 hg out -q -b .
41 echo out branch . non-ascii
42 hg --encoding utf-8 up Γ¦
43 hg --encoding latin1 out -q ../branch#.
44 hg --encoding latin1 out -q -b .
33 echo clone branch b
45 echo clone branch b
34 cd ..
46 cd ..
35 hg clone branch2#b branch3
47 hg clone branch2#b branch3
36 hg -q -R branch3 heads b
48 hg -q -R branch3 heads b
37 hg -q -R branch3 parents
49 hg -q -R branch3 parents
38 rm -rf branch3
50 rm -rf branch3
39 echo clone rev a branch b
51 echo clone rev a branch b
40 hg clone -r a branch2#b branch3
52 hg clone -r a branch2#b branch3
41 hg -q -R branch3 heads b
53 hg -q -R branch3 heads b
42 hg -q -R branch3 parents
54 hg -q -R branch3 parents
43 rm -rf branch3
55 rm -rf branch3
@@ -1,47 +1,59 b''
1 marked working directory as branch a
1 marked working directory as branch a
2 adding foo
2 adding foo
3 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
3 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4 marked working directory as branch c
4 marked working directory as branch c
5 requesting all changes
5 requesting all changes
6 adding changesets
6 adding changesets
7 adding manifests
7 adding manifests
8 adding file changes
8 adding file changes
9 added 1 changesets with 1 changes to 1 files
9 added 1 changesets with 1 changes to 1 files
10 updating to branch a
10 updating to branch a
11 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
11 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
12 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
12 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
13 marked working directory as branch b
13 marked working directory as branch b
14 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
14 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
15 marked working directory as branch Γ¦
16 created new head
17 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
18 marked working directory as branch Γ¦
19 created new head
20 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
15 marked working directory as branch b
21 marked working directory as branch b
16 in rev c branch a
22 in rev c branch a
17 1:dd6e60a716c6
23 1:dd6e60a716c6
18 2:f25d57ab0566
24 2:f25d57ab0566
19 1:dd6e60a716c6
25 1:dd6e60a716c6
20 2:f25d57ab0566
26 2:f25d57ab0566
21 out branch .
27 out branch .
22 1:b84708d77ab7
28 1:b84708d77ab7
23 2:65511d0e2b55
29 4:65511d0e2b55
24 1:b84708d77ab7
30 1:b84708d77ab7
25 2:65511d0e2b55
31 4:65511d0e2b55
32 out branch . non-ascii
33 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
34 2:df5a44224d4e
35 3:4f4a5125ca10
36 2:df5a44224d4e
37 3:4f4a5125ca10
26 clone branch b
38 clone branch b
27 requesting all changes
39 requesting all changes
28 adding changesets
40 adding changesets
29 adding manifests
41 adding manifests
30 adding file changes
42 adding file changes
31 added 3 changesets with 3 changes to 1 files (+1 heads)
43 added 3 changesets with 3 changes to 1 files (+1 heads)
32 updating to branch b
44 updating to branch b
33 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
45 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
34 2:65511d0e2b55
46 2:65511d0e2b55
35 1:b84708d77ab7
47 1:b84708d77ab7
36 2:65511d0e2b55
48 2:65511d0e2b55
37 clone rev a branch b
49 clone rev a branch b
38 requesting all changes
50 requesting all changes
39 adding changesets
51 adding changesets
40 adding manifests
52 adding manifests
41 adding file changes
53 adding file changes
42 added 3 changesets with 3 changes to 1 files (+1 heads)
54 added 3 changesets with 3 changes to 1 files (+1 heads)
43 updating to branch a
55 updating to branch a
44 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
56 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
45 2:65511d0e2b55
57 2:65511d0e2b55
46 1:b84708d77ab7
58 1:b84708d77ab7
47 0:5b65ba7c951d
59 0:5b65ba7c951d
General Comments 0
You need to be logged in to leave comments. Login now