comparison mercurial/hg.py @ 2956:6dddcba7596a

merge.
author Vadim Gelfer <vadim.gelfer@gmail.com>
date Fri, 18 Aug 2006 21:17:28 -0700
parents 345bac2bc4ec
children 3acb76f0124d
comparison
equal deleted inserted replaced
2955:9d1c3529ebbc 2956:6dddcba7596a
1 # hg.py - repository classes for mercurial 1 # hg.py - repository classes for mercurial
2 # 2 #
3 # Copyright 2005 Matt Mackall <mpm@selenic.com> 3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
4 # 5 #
5 # This software may be used and distributed according to the terms 6 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference. 7 # of the GNU General Public License, incorporated herein by reference.
7 8
8 from node import * 9 from node import *
9 from repo import * 10 from repo import *
10 from demandload import * 11 from demandload import *
11 from i18n import gettext as _ 12 from i18n import gettext as _
12 demandload(globals(), "localrepo bundlerepo httprepo sshrepo statichttprepo") 13 demandload(globals(), "localrepo bundlerepo httprepo sshrepo statichttprepo")
13 demandload(globals(), "errno lock os shutil util") 14 demandload(globals(), "errno lock os shutil util merge@_merge verify@_verify")
14 15
15 def bundle(ui, path): 16 def _local(path):
16 if path.startswith('bundle://'): 17 return (os.path.isfile(path and util.drop_scheme('file', path)) and
17 path = path[9:] 18 bundlerepo or localrepo)
18 else:
19 path = path[7:]
20 s = path.split("+", 1)
21 if len(s) == 1:
22 repopath, bundlename = "", s[0]
23 else:
24 repopath, bundlename = s
25 return bundlerepo.bundlerepository(ui, repopath, bundlename)
26
27 def hg(ui, path):
28 ui.warn(_("hg:// syntax is deprecated, please use http:// instead\n"))
29 return httprepo.httprepository(ui, path.replace("hg://", "http://"))
30
31 def local_(ui, path, create=0):
32 if path.startswith('file:'):
33 path = path[5:]
34 return localrepo.localrepository(ui, path, create)
35
36 def ssh_(ui, path, create=0):
37 return sshrepo.sshrepository(ui, path, create)
38
39 def old_http(ui, path):
40 ui.warn(_("old-http:// syntax is deprecated, "
41 "please use static-http:// instead\n"))
42 return statichttprepo.statichttprepository(
43 ui, path.replace("old-http://", "http://"))
44
45 def static_http(ui, path):
46 return statichttprepo.statichttprepository(
47 ui, path.replace("static-http://", "http://"))
48 19
49 schemes = { 20 schemes = {
50 'bundle': bundle, 21 'bundle': bundlerepo,
51 'file': local_, 22 'file': _local,
52 'hg': hg, 23 'hg': httprepo,
53 'http': lambda ui, path: httprepo.httprepository(ui, path), 24 'http': httprepo,
54 'https': lambda ui, path: httprepo.httpsrepository(ui, path), 25 'https': httprepo,
55 'old-http': old_http, 26 'old-http': statichttprepo,
56 'ssh': ssh_, 27 'ssh': sshrepo,
57 'static-http': static_http, 28 'static-http': statichttprepo,
58 } 29 }
59 30
60 def repository(ui, path=None, create=0): 31 def _lookup(path):
61 scheme = None 32 scheme = 'file'
62 if path: 33 if path:
63 c = path.find(':') 34 c = path.find(':')
64 if c > 0: 35 if c > 0:
65 scheme = schemes.get(path[:c]) 36 scheme = path[:c]
66 else: 37 thing = schemes.get(scheme) or schemes['file']
67 path = '' 38 try:
68 ctor = scheme or schemes['file'] 39 return thing(path)
69 if create: 40 except TypeError:
41 return thing
42
43 def islocal(repo):
44 '''return true if repo or path is local'''
45 if isinstance(repo, str):
70 try: 46 try:
71 return ctor(ui, path, create) 47 return _lookup(repo).islocal(repo)
72 except TypeError: 48 except AttributeError:
73 raise util.Abort(_('cannot create new repository over "%s" protocol') % 49 return False
74 scheme) 50 return repo.local()
75 return ctor(ui, path) 51
52 repo_setup_hooks = []
53
54 def repository(ui, path=None, create=False):
55 """return a repository object for the specified path"""
56 repo = _lookup(path).instance(ui, path, create)
57 for hook in repo_setup_hooks:
58 hook(ui, repo)
59 return repo
60
61 def defaultdest(source):
62 '''return default destination of clone if none is given'''
63 return os.path.basename(os.path.normpath(source))
76 64
77 def clone(ui, source, dest=None, pull=False, rev=None, update=True, 65 def clone(ui, source, dest=None, pull=False, rev=None, update=True,
78 stream=False): 66 stream=False):
79 """Make a copy of an existing repository. 67 """Make a copy of an existing repository.
80 68
88 pushes. 76 pushes.
89 77
90 If an exception is raised, the partly cloned/updated destination 78 If an exception is raised, the partly cloned/updated destination
91 repository will be deleted. 79 repository will be deleted.
92 80
93 Keyword arguments: 81 Arguments:
82
83 source: repository object or URL
94 84
95 dest: URL of destination repository to create (defaults to base 85 dest: URL of destination repository to create (defaults to base
96 name of source repository) 86 name of source repository)
97 87
98 pull: always pull from source repository, even in local case 88 pull: always pull from source repository, even in local case
103 rev: revision to clone up to (implies pull=True) 93 rev: revision to clone up to (implies pull=True)
104 94
105 update: update working directory after clone completes, if 95 update: update working directory after clone completes, if
106 destination is local repository 96 destination is local repository
107 """ 97 """
98 if isinstance(source, str):
99 src_repo = repository(ui, source)
100 else:
101 src_repo = source
102 source = src_repo.url()
103
108 if dest is None: 104 if dest is None:
109 dest = os.path.basename(os.path.normpath(source)) 105 dest = defaultdest(source)
106
107 def localpath(path):
108 if path.startswith('file://'):
109 return path[7:]
110 if path.startswith('file:'):
111 return path[5:]
112 return path
113
114 dest = localpath(dest)
115 source = localpath(source)
110 116
111 if os.path.exists(dest): 117 if os.path.exists(dest):
112 raise util.Abort(_("destination '%s' already exists"), dest) 118 raise util.Abort(_("destination '%s' already exists"), dest)
113 119
114 class DirCleanup(object): 120 class DirCleanup(object):
119 self.dir_ = None 125 self.dir_ = None
120 def __del__(self): 126 def __del__(self):
121 if self.dir_: 127 if self.dir_:
122 self.rmtree(self.dir_, True) 128 self.rmtree(self.dir_, True)
123 129
124 src_repo = repository(ui, source)
125
126 dest_repo = None 130 dest_repo = None
127 try: 131 try:
128 dest_repo = repository(ui, dest) 132 dest_repo = repository(ui, dest)
129 raise util.Abort(_("destination '%s' already exists." % dest)) 133 raise util.Abort(_("destination '%s' already exists." % dest))
130 except RepoError: 134 except RepoError:
131 dest_repo = repository(ui, dest, create=True) 135 dest_repo = repository(ui, dest, create=True)
132 136
133 dest_path = None 137 dest_path = None
134 dir_cleanup = None 138 dir_cleanup = None
135 if dest_repo.local(): 139 if dest_repo.local():
136 dest_path = os.path.realpath(dest) 140 dest_path = os.path.realpath(dest_repo.root)
137 dir_cleanup = DirCleanup(dest_path) 141 dir_cleanup = DirCleanup(dest_path)
138 142
139 abspath = source 143 abspath = source
140 copy = False 144 copy = False
141 if src_repo.local() and dest_repo.local(): 145 if src_repo.local() and dest_repo.local():
200 204
201 if dest_lock: 205 if dest_lock:
202 dest_lock.release() 206 dest_lock.release()
203 207
204 if update: 208 if update:
205 dest_repo.update(dest_repo.changelog.tip()) 209 _merge.update(dest_repo, dest_repo.changelog.tip())
206 if dir_cleanup: 210 if dir_cleanup:
207 dir_cleanup.close() 211 dir_cleanup.close()
208 212
209 return src_repo, dest_repo 213 return src_repo, dest_repo
214
215 def update(repo, node):
216 """update the working directory to node, merging linear changes"""
217 return _merge.update(repo, node)
218
219 def clean(repo, node, wlock=None, show_stats=True):
220 """forcibly switch the working directory to node, clobbering changes"""
221 return _merge.update(repo, node, force=True, wlock=wlock,
222 show_stats=show_stats)
223
224 def merge(repo, node, force=None, remind=True, wlock=None):
225 """branch merge with node, resolving changes"""
226 return _merge.update(repo, node, branchmerge=True, force=force,
227 remind=remind, wlock=wlock)
228
229 def revert(repo, node, choose, wlock):
230 """revert changes to revision in node without updating dirstate"""
231 return _merge.update(repo, node, force=True, partial=choose,
232 show_stats=False, wlock=wlock)
233
234 def verify(repo):
235 """verify the consistency of a repository"""
236 return _verify.verify(repo)