##// END OF EJS Templates
clone: get a list of files to clone from store
Matt Mackall -
r6903:0642d9d7 default
parent child Browse files
Show More
@@ -1,303 +1,286 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
6 # This software may be used and distributed according to the terms
7 # of the GNU General Public License, incorporated herein by reference.
7 # of the GNU General Public License, incorporated herein by reference.
8
8
9 from i18n import _
9 from i18n import _
10 import localrepo, bundlerepo, httprepo, sshrepo, statichttprepo
10 import localrepo, bundlerepo, httprepo, sshrepo, statichttprepo
11 import errno, lock, os, shutil, util, extensions
11 import errno, lock, os, shutil, util, extensions
12 import merge as _merge
12 import merge as _merge
13 import verify as _verify
13 import verify as _verify
14
14
15 def _local(path):
15 def _local(path):
16 return (os.path.isfile(util.drop_scheme('file', path)) and
16 return (os.path.isfile(util.drop_scheme('file', path)) and
17 bundlerepo or localrepo)
17 bundlerepo or localrepo)
18
18
19 def parseurl(url, revs=[]):
19 def parseurl(url, revs=[]):
20 '''parse url#branch, returning url, branch + revs'''
20 '''parse url#branch, returning url, branch + revs'''
21
21
22 if '#' not in url:
22 if '#' not in url:
23 return url, (revs or None), None
23 return url, (revs or None), None
24
24
25 url, rev = url.split('#', 1)
25 url, rev = url.split('#', 1)
26 return url, revs + [rev], rev
26 return url, revs + [rev], rev
27
27
28 schemes = {
28 schemes = {
29 'bundle': bundlerepo,
29 'bundle': bundlerepo,
30 'file': _local,
30 'file': _local,
31 'http': httprepo,
31 'http': httprepo,
32 'https': httprepo,
32 'https': httprepo,
33 'ssh': sshrepo,
33 'ssh': sshrepo,
34 'static-http': statichttprepo,
34 'static-http': statichttprepo,
35 }
35 }
36
36
37 def _lookup(path):
37 def _lookup(path):
38 scheme = 'file'
38 scheme = 'file'
39 if path:
39 if path:
40 c = path.find(':')
40 c = path.find(':')
41 if c > 0:
41 if c > 0:
42 scheme = path[:c]
42 scheme = path[:c]
43 thing = schemes.get(scheme) or schemes['file']
43 thing = schemes.get(scheme) or schemes['file']
44 try:
44 try:
45 return thing(path)
45 return thing(path)
46 except TypeError:
46 except TypeError:
47 return thing
47 return thing
48
48
49 def islocal(repo):
49 def islocal(repo):
50 '''return true if repo or path is local'''
50 '''return true if repo or path is local'''
51 if isinstance(repo, str):
51 if isinstance(repo, str):
52 try:
52 try:
53 return _lookup(repo).islocal(repo)
53 return _lookup(repo).islocal(repo)
54 except AttributeError:
54 except AttributeError:
55 return False
55 return False
56 return repo.local()
56 return repo.local()
57
57
58 def repository(ui, path='', create=False):
58 def repository(ui, path='', create=False):
59 """return a repository object for the specified path"""
59 """return a repository object for the specified path"""
60 repo = _lookup(path).instance(ui, path, create)
60 repo = _lookup(path).instance(ui, path, create)
61 ui = getattr(repo, "ui", ui)
61 ui = getattr(repo, "ui", ui)
62 for name, module in extensions.extensions():
62 for name, module in extensions.extensions():
63 hook = getattr(module, 'reposetup', None)
63 hook = getattr(module, 'reposetup', None)
64 if hook:
64 if hook:
65 hook(ui, repo)
65 hook(ui, repo)
66 return repo
66 return repo
67
67
68 def defaultdest(source):
68 def defaultdest(source):
69 '''return default destination of clone if none is given'''
69 '''return default destination of clone if none is given'''
70 return os.path.basename(os.path.normpath(source))
70 return os.path.basename(os.path.normpath(source))
71
71
72 def localpath(path):
72 def localpath(path):
73 if path.startswith('file://localhost/'):
73 if path.startswith('file://localhost/'):
74 return path[16:]
74 return path[16:]
75 if path.startswith('file://'):
75 if path.startswith('file://'):
76 return path[7:]
76 return path[7:]
77 if path.startswith('file:'):
77 if path.startswith('file:'):
78 return path[5:]
78 return path[5:]
79 return path
79 return path
80
80
81 def clone(ui, source, dest=None, pull=False, rev=None, update=True,
81 def clone(ui, source, dest=None, pull=False, rev=None, update=True,
82 stream=False):
82 stream=False):
83 """Make a copy of an existing repository.
83 """Make a copy of an existing repository.
84
84
85 Create a copy of an existing repository in a new directory. The
85 Create a copy of an existing repository in a new directory. The
86 source and destination are URLs, as passed to the repository
86 source and destination are URLs, as passed to the repository
87 function. Returns a pair of repository objects, the source and
87 function. Returns a pair of repository objects, the source and
88 newly created destination.
88 newly created destination.
89
89
90 The location of the source is added to the new repository's
90 The location of the source is added to the new repository's
91 .hg/hgrc file, as the default to be used for future pulls and
91 .hg/hgrc file, as the default to be used for future pulls and
92 pushes.
92 pushes.
93
93
94 If an exception is raised, the partly cloned/updated destination
94 If an exception is raised, the partly cloned/updated destination
95 repository will be deleted.
95 repository will be deleted.
96
96
97 Arguments:
97 Arguments:
98
98
99 source: repository object or URL
99 source: repository object or URL
100
100
101 dest: URL of destination repository to create (defaults to base
101 dest: URL of destination repository to create (defaults to base
102 name of source repository)
102 name of source repository)
103
103
104 pull: always pull from source repository, even in local case
104 pull: always pull from source repository, even in local case
105
105
106 stream: stream raw data uncompressed from repository (fast over
106 stream: stream raw data uncompressed from repository (fast over
107 LAN, slow over WAN)
107 LAN, slow over WAN)
108
108
109 rev: revision to clone up to (implies pull=True)
109 rev: revision to clone up to (implies pull=True)
110
110
111 update: update working directory after clone completes, if
111 update: update working directory after clone completes, if
112 destination is local repository (True means update to default rev,
112 destination is local repository (True means update to default rev,
113 anything else is treated as a revision)
113 anything else is treated as a revision)
114 """
114 """
115
115
116 if isinstance(source, str):
116 if isinstance(source, str):
117 origsource = ui.expandpath(source)
117 origsource = ui.expandpath(source)
118 source, rev, checkout = parseurl(origsource, rev)
118 source, rev, checkout = parseurl(origsource, rev)
119 src_repo = repository(ui, source)
119 src_repo = repository(ui, source)
120 else:
120 else:
121 src_repo = source
121 src_repo = source
122 origsource = source = src_repo.url()
122 origsource = source = src_repo.url()
123 checkout = None
123 checkout = None
124
124
125 if dest is None:
125 if dest is None:
126 dest = defaultdest(source)
126 dest = defaultdest(source)
127 ui.status(_("destination directory: %s\n") % dest)
127 ui.status(_("destination directory: %s\n") % dest)
128
128
129 dest = localpath(dest)
129 dest = localpath(dest)
130 source = localpath(source)
130 source = localpath(source)
131
131
132 if os.path.exists(dest):
132 if os.path.exists(dest):
133 raise util.Abort(_("destination '%s' already exists") % dest)
133 raise util.Abort(_("destination '%s' already exists") % dest)
134
134
135 class DirCleanup(object):
135 class DirCleanup(object):
136 def __init__(self, dir_):
136 def __init__(self, dir_):
137 self.rmtree = shutil.rmtree
137 self.rmtree = shutil.rmtree
138 self.dir_ = dir_
138 self.dir_ = dir_
139 def close(self):
139 def close(self):
140 self.dir_ = None
140 self.dir_ = None
141 def __del__(self):
141 def __del__(self):
142 if self.dir_:
142 if self.dir_:
143 self.rmtree(self.dir_, True)
143 self.rmtree(self.dir_, True)
144
144
145 src_lock = dest_lock = dir_cleanup = None
145 src_lock = dest_lock = dir_cleanup = None
146 try:
146 try:
147 if islocal(dest):
147 if islocal(dest):
148 dir_cleanup = DirCleanup(dest)
148 dir_cleanup = DirCleanup(dest)
149
149
150 abspath = origsource
150 abspath = origsource
151 copy = False
151 copy = False
152 if src_repo.cancopy() and islocal(dest):
152 if src_repo.cancopy() and islocal(dest):
153 abspath = os.path.abspath(util.drop_scheme('file', origsource))
153 abspath = os.path.abspath(util.drop_scheme('file', origsource))
154 copy = not pull and not rev
154 copy = not pull and not rev
155
155
156 if copy:
156 if copy:
157 try:
157 try:
158 # we use a lock here because if we race with commit, we
158 # we use a lock here because if we race with commit, we
159 # can end up with extra data in the cloned revlogs that's
159 # can end up with extra data in the cloned revlogs that's
160 # not pointed to by changesets, thus causing verify to
160 # not pointed to by changesets, thus causing verify to
161 # fail
161 # fail
162 src_lock = src_repo.lock()
162 src_lock = src_repo.lock()
163 except lock.LockException:
163 except lock.LockException:
164 copy = False
164 copy = False
165
165
166 if copy:
166 if copy:
167 def force_copy(src, dst):
168 if not os.path.exists(src):
169 # Tolerate empty source repository and optional files
170 return
171 util.copyfiles(src, dst)
172
173 src_store = os.path.realpath(src_repo.spath)
174 if not os.path.exists(dest):
167 if not os.path.exists(dest):
175 os.mkdir(dest)
168 os.mkdir(dest)
176 try:
169 try:
177 dest_path = os.path.realpath(os.path.join(dest, ".hg"))
170 dest_path = os.path.realpath(os.path.join(dest, ".hg"))
178 os.mkdir(dest_path)
171 os.mkdir(dest_path)
179 except OSError, inst:
172 except OSError, inst:
180 if inst.errno == errno.EEXIST:
173 if inst.errno == errno.EEXIST:
181 dir_cleanup.close()
174 dir_cleanup.close()
182 raise util.Abort(_("destination '%s' already exists")
175 raise util.Abort(_("destination '%s' already exists")
183 % dest)
176 % dest)
184 raise
177 raise
185 if src_repo.spath != src_repo.path:
186 # XXX racy
187 dummy_changelog = os.path.join(dest_path, "00changelog.i")
188 # copy the dummy changelog
189 force_copy(src_repo.join("00changelog.i"), dummy_changelog)
190 dest_store = os.path.join(dest_path, "store")
191 os.mkdir(dest_store)
192 else:
193 dest_store = dest_path
194 # copy the requires file
195 force_copy(src_repo.join("requires"),
196 os.path.join(dest_path, "requires"))
197 # we lock here to avoid premature writing to the target
198 dest_lock = lock.lock(os.path.join(dest_store, "lock"))
199
178
200 files = ("data",
179 for f in src_repo.store.copylist():
201 "00manifest.d", "00manifest.i",
180 src = os.path.join(src_repo.path, f)
202 "00changelog.d", "00changelog.i")
181 if os.path.exists(src):
203 for f in files:
182 dst = os.path.join(dest_path, f)
204 src = os.path.join(src_store, f)
183 dstbase = os.path.dirname(dst)
205 dst = os.path.join(dest_store, f)
184 if not os.path.exists(dstbase):
206 force_copy(src, dst)
185 os.mkdir(dstbase)
186 if dst.endswith('data'):
187 # lock to avoid premature writing to the target
188 dest_lock = lock.lock(os.path.join(dstbase, "lock"))
189 util.copyfiles(src, dst)
207
190
208 # we need to re-init the repo after manually copying the data
191 # we need to re-init the repo after manually copying the data
209 # into it
192 # into it
210 dest_repo = repository(ui, dest)
193 dest_repo = repository(ui, dest)
211
194
212 else:
195 else:
213 try:
196 try:
214 dest_repo = repository(ui, dest, create=True)
197 dest_repo = repository(ui, dest, create=True)
215 except OSError, inst:
198 except OSError, inst:
216 if inst.errno == errno.EEXIST:
199 if inst.errno == errno.EEXIST:
217 dir_cleanup.close()
200 dir_cleanup.close()
218 raise util.Abort(_("destination '%s' already exists")
201 raise util.Abort(_("destination '%s' already exists")
219 % dest)
202 % dest)
220 raise
203 raise
221
204
222 revs = None
205 revs = None
223 if rev:
206 if rev:
224 if 'lookup' not in src_repo.capabilities:
207 if 'lookup' not in src_repo.capabilities:
225 raise util.Abort(_("src repository does not support revision "
208 raise util.Abort(_("src repository does not support revision "
226 "lookup and so doesn't support clone by "
209 "lookup and so doesn't support clone by "
227 "revision"))
210 "revision"))
228 revs = [src_repo.lookup(r) for r in rev]
211 revs = [src_repo.lookup(r) for r in rev]
229
212
230 if dest_repo.local():
213 if dest_repo.local():
231 dest_repo.clone(src_repo, heads=revs, stream=stream)
214 dest_repo.clone(src_repo, heads=revs, stream=stream)
232 elif src_repo.local():
215 elif src_repo.local():
233 src_repo.push(dest_repo, revs=revs)
216 src_repo.push(dest_repo, revs=revs)
234 else:
217 else:
235 raise util.Abort(_("clone from remote to remote not supported"))
218 raise util.Abort(_("clone from remote to remote not supported"))
236
219
237 if dir_cleanup:
220 if dir_cleanup:
238 dir_cleanup.close()
221 dir_cleanup.close()
239
222
240 if dest_repo.local():
223 if dest_repo.local():
241 fp = dest_repo.opener("hgrc", "w", text=True)
224 fp = dest_repo.opener("hgrc", "w", text=True)
242 fp.write("[paths]\n")
225 fp.write("[paths]\n")
243 fp.write("default = %s\n" % abspath)
226 fp.write("default = %s\n" % abspath)
244 fp.close()
227 fp.close()
245
228
246 if update:
229 if update:
247 dest_repo.ui.status(_("updating working directory\n"))
230 dest_repo.ui.status(_("updating working directory\n"))
248 if update is not True:
231 if update is not True:
249 checkout = update
232 checkout = update
250 elif not checkout:
233 elif not checkout:
251 try:
234 try:
252 checkout = dest_repo.lookup("default")
235 checkout = dest_repo.lookup("default")
253 except:
236 except:
254 checkout = dest_repo.changelog.tip()
237 checkout = dest_repo.changelog.tip()
255 _update(dest_repo, checkout)
238 _update(dest_repo, checkout)
256
239
257 return src_repo, dest_repo
240 return src_repo, dest_repo
258 finally:
241 finally:
259 del src_lock, dest_lock, dir_cleanup
242 del src_lock, dest_lock, dir_cleanup
260
243
261 def _showstats(repo, stats):
244 def _showstats(repo, stats):
262 stats = ((stats[0], _("updated")),
245 stats = ((stats[0], _("updated")),
263 (stats[1], _("merged")),
246 (stats[1], _("merged")),
264 (stats[2], _("removed")),
247 (stats[2], _("removed")),
265 (stats[3], _("unresolved")))
248 (stats[3], _("unresolved")))
266 note = ", ".join([_("%d files %s") % s for s in stats])
249 note = ", ".join([_("%d files %s") % s for s in stats])
267 repo.ui.status("%s\n" % note)
250 repo.ui.status("%s\n" % note)
268
251
269 def _update(repo, node): return update(repo, node)
252 def _update(repo, node): return update(repo, node)
270
253
271 def update(repo, node):
254 def update(repo, node):
272 """update the working directory to node, merging linear changes"""
255 """update the working directory to node, merging linear changes"""
273 pl = repo.parents()
256 pl = repo.parents()
274 stats = _merge.update(repo, node, False, False, None)
257 stats = _merge.update(repo, node, False, False, None)
275 _showstats(repo, stats)
258 _showstats(repo, stats)
276 if stats[3]:
259 if stats[3]:
277 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
260 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
278 return stats[3] > 0
261 return stats[3] > 0
279
262
280 def clean(repo, node, show_stats=True):
263 def clean(repo, node, show_stats=True):
281 """forcibly switch the working directory to node, clobbering changes"""
264 """forcibly switch the working directory to node, clobbering changes"""
282 stats = _merge.update(repo, node, False, True, None)
265 stats = _merge.update(repo, node, False, True, None)
283 if show_stats: _showstats(repo, stats)
266 if show_stats: _showstats(repo, stats)
284 return stats[3] > 0
267 return stats[3] > 0
285
268
286 def merge(repo, node, force=None, remind=True):
269 def merge(repo, node, force=None, remind=True):
287 """branch merge with node, resolving changes"""
270 """branch merge with node, resolving changes"""
288 stats = _merge.update(repo, node, True, force, False)
271 stats = _merge.update(repo, node, True, force, False)
289 _showstats(repo, stats)
272 _showstats(repo, stats)
290 if stats[3]:
273 if stats[3]:
291 pl = repo.parents()
274 pl = repo.parents()
292 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
275 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
293 elif remind:
276 elif remind:
294 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
277 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
295 return stats[3] > 0
278 return stats[3] > 0
296
279
297 def revert(repo, node, choose):
280 def revert(repo, node, choose):
298 """revert changes to revision in node without updating dirstate"""
281 """revert changes to revision in node without updating dirstate"""
299 return _merge.update(repo, node, False, True, choose)[3] > 0
282 return _merge.update(repo, node, False, True, choose)[3] > 0
300
283
301 def verify(repo):
284 def verify(repo):
302 """verify the consistency of a repository"""
285 """verify the consistency of a repository"""
303 return _verify.verify(repo)
286 return _verify.verify(repo)
@@ -1,115 +1,124 b''
1 # store.py - repository store handling for Mercurial
1 # store.py - repository store handling for Mercurial
2 #
2 #
3 # Copyright 2008 Matt Mackall <mpm@selenic.com>
3 # Copyright 2008 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 import os, stat, osutil, util
8 import os, stat, osutil, util
9
9
10 def _buildencodefun():
10 def _buildencodefun():
11 e = '_'
11 e = '_'
12 win_reserved = [ord(x) for x in '\\:*?"<>|']
12 win_reserved = [ord(x) for x in '\\:*?"<>|']
13 cmap = dict([ (chr(x), chr(x)) for x in xrange(127) ])
13 cmap = dict([ (chr(x), chr(x)) for x in xrange(127) ])
14 for x in (range(32) + range(126, 256) + win_reserved):
14 for x in (range(32) + range(126, 256) + win_reserved):
15 cmap[chr(x)] = "~%02x" % x
15 cmap[chr(x)] = "~%02x" % x
16 for x in range(ord("A"), ord("Z")+1) + [ord(e)]:
16 for x in range(ord("A"), ord("Z")+1) + [ord(e)]:
17 cmap[chr(x)] = e + chr(x).lower()
17 cmap[chr(x)] = e + chr(x).lower()
18 dmap = {}
18 dmap = {}
19 for k, v in cmap.iteritems():
19 for k, v in cmap.iteritems():
20 dmap[v] = k
20 dmap[v] = k
21 def decode(s):
21 def decode(s):
22 i = 0
22 i = 0
23 while i < len(s):
23 while i < len(s):
24 for l in xrange(1, 4):
24 for l in xrange(1, 4):
25 try:
25 try:
26 yield dmap[s[i:i+l]]
26 yield dmap[s[i:i+l]]
27 i += l
27 i += l
28 break
28 break
29 except KeyError:
29 except KeyError:
30 pass
30 pass
31 else:
31 else:
32 raise KeyError
32 raise KeyError
33 return (lambda s: "".join([cmap[c] for c in s]),
33 return (lambda s: "".join([cmap[c] for c in s]),
34 lambda s: "".join(list(decode(s))))
34 lambda s: "".join(list(decode(s))))
35
35
36 encodefilename, decodefilename = _buildencodefun()
36 encodefilename, decodefilename = _buildencodefun()
37
37
38 def _calcmode(path):
38 def _calcmode(path):
39 try:
39 try:
40 # files in .hg/ will be created using this mode
40 # files in .hg/ will be created using this mode
41 mode = os.stat(path).st_mode
41 mode = os.stat(path).st_mode
42 # avoid some useless chmods
42 # avoid some useless chmods
43 if (0777 & ~util._umask) == (0777 & mode):
43 if (0777 & ~util._umask) == (0777 & mode):
44 mode = None
44 mode = None
45 except OSError:
45 except OSError:
46 mode = None
46 mode = None
47 return mode
47 return mode
48
48
49 _data = 'data 00manifest.d 00manifest.i 00changelog.d 00changelog.i'
50
49 class basicstore:
51 class basicstore:
50 '''base class for local repository stores'''
52 '''base class for local repository stores'''
51 def __init__(self, path, opener):
53 def __init__(self, path, opener):
52 self.path = path
54 self.path = path
53 self.createmode = _calcmode(path)
55 self.createmode = _calcmode(path)
54 self.opener = opener(self.path)
56 self.opener = opener(self.path)
55 self.opener.createmode = self.createmode
57 self.opener.createmode = self.createmode
56
58
57 def join(self, f):
59 def join(self, f):
58 return os.path.join(self.path, f)
60 return os.path.join(self.path, f)
59
61
60 def _walk(self, relpath, recurse):
62 def _walk(self, relpath, recurse):
61 '''yields (unencoded, encoded, size)'''
63 '''yields (unencoded, encoded, size)'''
62 path = os.path.join(self.path, relpath)
64 path = os.path.join(self.path, relpath)
63 striplen = len(self.path) + len(os.sep)
65 striplen = len(self.path) + len(os.sep)
64 prefix = path[striplen:]
66 prefix = path[striplen:]
65 l = []
67 l = []
66 if os.path.isdir(path):
68 if os.path.isdir(path):
67 visit = [path]
69 visit = [path]
68 while visit:
70 while visit:
69 p = visit.pop()
71 p = visit.pop()
70 for f, kind, st in osutil.listdir(p, stat=True):
72 for f, kind, st in osutil.listdir(p, stat=True):
71 fp = os.path.join(p, f)
73 fp = os.path.join(p, f)
72 if kind == stat.S_IFREG and f[-2:] in ('.d', '.i'):
74 if kind == stat.S_IFREG and f[-2:] in ('.d', '.i'):
73 n = util.pconvert(fp[striplen:])
75 n = util.pconvert(fp[striplen:])
74 l.append((n, n, st.st_size))
76 l.append((n, n, st.st_size))
75 elif kind == stat.S_IFDIR and recurse:
77 elif kind == stat.S_IFDIR and recurse:
76 visit.append(fp)
78 visit.append(fp)
77 return util.sort(l)
79 return util.sort(l)
78
80
79 def datafiles(self):
81 def datafiles(self):
80 return self._walk('data', True)
82 return self._walk('data', True)
81
83
82 def walk(self):
84 def walk(self):
83 '''yields (unencoded, encoded, size)'''
85 '''yields (unencoded, encoded, size)'''
84 # yield data files first
86 # yield data files first
85 for x in self.datafiles():
87 for x in self.datafiles():
86 yield x
88 yield x
87 # yield manifest before changelog
89 # yield manifest before changelog
88 meta = self._walk('', False)
90 meta = self._walk('', False)
89 meta.reverse()
91 meta.reverse()
90 for x in meta:
92 for x in meta:
91 yield x
93 yield x
92
94
95 def copylist(self):
96 return ['requires'] + _data.split()
97
93 class encodedstore(basicstore):
98 class encodedstore(basicstore):
94 def __init__(self, path, opener):
99 def __init__(self, path, opener):
95 self.path = os.path.join(path, 'store')
100 self.path = os.path.join(path, 'store')
96 self.createmode = _calcmode(self.path)
101 self.createmode = _calcmode(self.path)
97 op = opener(self.path)
102 op = opener(self.path)
98 op.createmode = self.createmode
103 op.createmode = self.createmode
99 self.opener = lambda f, *args, **kw: op(encodefilename(f), *args, **kw)
104 self.opener = lambda f, *args, **kw: op(encodefilename(f), *args, **kw)
100
105
101 def datafiles(self):
106 def datafiles(self):
102 for a, b, size in self._walk('data', True):
107 for a, b, size in self._walk('data', True):
103 try:
108 try:
104 a = decodefilename(a)
109 a = decodefilename(a)
105 except KeyError:
110 except KeyError:
106 a = None
111 a = None
107 yield a, b, size
112 yield a, b, size
108
113
109 def join(self, f):
114 def join(self, f):
110 return os.path.join(self.path, encodefilename(f))
115 return os.path.join(self.path, encodefilename(f))
111
116
117 def copylist(self):
118 return (['requires', '00changelog.i'] +
119 ['store/' + f for f in _data.split()])
120
112 def store(requirements, path, opener):
121 def store(requirements, path, opener):
113 if 'store' in requirements:
122 if 'store' in requirements:
114 return encodedstore(path, opener)
123 return encodedstore(path, opener)
115 return basicstore(path, opener)
124 return basicstore(path, opener)
General Comments 0
You need to be logged in to leave comments. Login now