##// END OF EJS Templates
codingstyle: use spaces instead of tabs
Benoit Boissinot -
r2631:8f564a87 default
parent child Browse files
Show More
@@ -1,209 +1,209
1 1 # hg.py - repository classes for mercurial
2 2 #
3 3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms
6 6 # of the GNU General Public License, incorporated herein by reference.
7 7
8 8 from node import *
9 9 from repo import *
10 10 from demandload import *
11 11 from i18n import gettext as _
12 12 demandload(globals(), "localrepo bundlerepo httprepo sshrepo statichttprepo")
13 13 demandload(globals(), "errno lock os shutil util")
14 14
15 15 def bundle(ui, path):
16 16 if path.startswith('bundle://'):
17 17 path = path[9:]
18 18 else:
19 19 path = path[7:]
20 20 s = path.split("+", 1)
21 21 if len(s) == 1:
22 22 repopath, bundlename = "", s[0]
23 23 else:
24 24 repopath, bundlename = s
25 25 return bundlerepo.bundlerepository(ui, repopath, bundlename)
26 26
27 27 def hg(ui, path):
28 28 ui.warn(_("hg:// syntax is deprecated, please use http:// instead\n"))
29 29 return httprepo.httprepository(ui, path.replace("hg://", "http://"))
30 30
31 31 def local_(ui, path, create=0):
32 32 if path.startswith('file:'):
33 33 path = path[5:]
34 34 return localrepo.localrepository(ui, path, create)
35 35
36 36 def ssh_(ui, path, create=0):
37 37 return sshrepo.sshrepository(ui, path, create)
38 38
39 39 def old_http(ui, path):
40 40 ui.warn(_("old-http:// syntax is deprecated, "
41 41 "please use static-http:// instead\n"))
42 42 return statichttprepo.statichttprepository(
43 43 ui, path.replace("old-http://", "http://"))
44 44
45 45 def static_http(ui, path):
46 46 return statichttprepo.statichttprepository(
47 47 ui, path.replace("static-http://", "http://"))
48 48
49 49 schemes = {
50 50 'bundle': bundle,
51 51 'file': local_,
52 52 'hg': hg,
53 53 'http': lambda ui, path: httprepo.httprepository(ui, path),
54 54 'https': lambda ui, path: httprepo.httpsrepository(ui, path),
55 55 'old-http': old_http,
56 56 'ssh': ssh_,
57 57 'static-http': static_http,
58 58 }
59 59
60 60 def repository(ui, path=None, create=0):
61 61 scheme = None
62 62 if path:
63 63 c = path.find(':')
64 64 if c > 0:
65 65 scheme = schemes.get(path[:c])
66 66 else:
67 67 path = ''
68 68 ctor = scheme or schemes['file']
69 69 if create:
70 70 try:
71 71 return ctor(ui, path, create)
72 72 except TypeError:
73 73 raise util.Abort(_('cannot create new repository over "%s" protocol') %
74 74 scheme)
75 75 return ctor(ui, path)
76 76
77 77 def clone(ui, source, dest=None, pull=False, rev=None, update=True,
78 78 stream=False):
79 79 """Make a copy of an existing repository.
80 80
81 81 Create a copy of an existing repository in a new directory. The
82 82 source and destination are URLs, as passed to the repository
83 83 function. Returns a pair of repository objects, the source and
84 84 newly created destination.
85 85
86 86 The location of the source is added to the new repository's
87 87 .hg/hgrc file, as the default to be used for future pulls and
88 88 pushes.
89 89
90 90 If an exception is raised, the partly cloned/updated destination
91 91 repository will be deleted.
92 92
93 93 Keyword arguments:
94 94
95 95 dest: URL of destination repository to create (defaults to base
96 96 name of source repository)
97 97
98 98 pull: always pull from source repository, even in local case
99 99
100 100 stream: stream raw data uncompressed from repository (fast over
101 101 LAN, slow over WAN)
102 102
103 103 rev: revision to clone up to (implies pull=True)
104 104
105 105 update: update working directory after clone completes, if
106 106 destination is local repository
107 107 """
108 108 if dest is None:
109 109 dest = os.path.basename(os.path.normpath(source))
110 110
111 111 if os.path.exists(dest):
112 112 raise util.Abort(_("destination '%s' already exists"), dest)
113 113
114 114 class DirCleanup(object):
115 115 def __init__(self, dir_):
116 116 self.rmtree = shutil.rmtree
117 117 self.dir_ = dir_
118 118 def close(self):
119 119 self.dir_ = None
120 120 def __del__(self):
121 121 if self.dir_:
122 122 self.rmtree(self.dir_, True)
123 123
124 124 src_repo = repository(ui, source)
125 125
126 126 dest_repo = None
127 127 try:
128 128 dest_repo = repository(ui, dest)
129 129 raise util.Abort(_("destination '%s' already exists." % dest))
130 130 except RepoError:
131 131 dest_repo = repository(ui, dest, create=True)
132 132
133 133 dest_path = None
134 134 dir_cleanup = None
135 135 if dest_repo.local():
136 136 dest_path = os.path.realpath(dest)
137 137 dir_cleanup = DirCleanup(dest_path)
138 138
139 139 abspath = source
140 140 copy = False
141 141 if src_repo.local() and dest_repo.local():
142 142 abspath = os.path.abspath(source)
143 143 copy = not pull and not rev
144 144
145 145 src_lock, dest_lock = None, None
146 146 if copy:
147 147 try:
148 148 # we use a lock here because if we race with commit, we
149 149 # can end up with extra data in the cloned revlogs that's
150 150 # not pointed to by changesets, thus causing verify to
151 151 # fail
152 152 src_lock = src_repo.lock()
153 153 except lock.LockException:
154 154 copy = False
155 155
156 156 if copy:
157 157 # we lock here to avoid premature writing to the target
158 158 dest_lock = lock.lock(os.path.join(dest_path, ".hg", "lock"))
159 159
160 # we need to remove the (empty) data dir in dest so copyfiles
161 # can do its work
162 os.rmdir(os.path.join(dest_path, ".hg", "data"))
160 # we need to remove the (empty) data dir in dest so copyfiles
161 # can do its work
162 os.rmdir(os.path.join(dest_path, ".hg", "data"))
163 163 files = "data 00manifest.d 00manifest.i 00changelog.d 00changelog.i"
164 164 for f in files.split():
165 165 src = os.path.join(source, ".hg", f)
166 166 dst = os.path.join(dest_path, ".hg", f)
167 167 try:
168 168 util.copyfiles(src, dst)
169 169 except OSError, inst:
170 170 if inst.errno != errno.ENOENT:
171 171 raise
172 172
173 # we need to re-init the repo after manually copying the data
174 # into it
173 # we need to re-init the repo after manually copying the data
174 # into it
175 175 dest_repo = repository(ui, dest)
176 176
177 177 else:
178 178 revs = None
179 179 if rev:
180 180 if not src_repo.local():
181 181 raise util.Abort(_("clone by revision not supported yet "
182 182 "for remote repositories"))
183 183 revs = [src_repo.lookup(r) for r in rev]
184 184
185 185 if dest_repo.local():
186 186 dest_repo.clone(src_repo, heads=revs, stream=stream)
187 187 elif src_repo.local():
188 188 src_repo.push(dest_repo, revs=revs)
189 189 else:
190 190 raise util.Abort(_("clone from remote to remote not supported"))
191 191
192 192 if src_lock:
193 193 src_lock.release()
194 194
195 195 if dest_repo.local():
196 196 fp = dest_repo.opener("hgrc", "w", text=True)
197 197 fp.write("[paths]\n")
198 198 fp.write("default = %s\n" % abspath)
199 199 fp.close()
200 200
201 201 if dest_lock:
202 202 dest_lock.release()
203 203
204 204 if update:
205 205 dest_repo.update(dest_repo.changelog.tip())
206 206 if dir_cleanup:
207 207 dir_cleanup.close()
208 208
209 209 return src_repo, dest_repo
General Comments 0
You need to be logged in to leave comments. Login now