##// END OF EJS Templates
vfs: use 'vfs' module directly in 'mercurial.statichttprepo'...
Pierre-Yves David -
r31241:591fda75 default
parent child Browse files
Show More
@@ -1,189 +1,190 b''
1 1 # statichttprepo.py - simple http repository class for mercurial
2 2 #
3 3 # This provides read-only repo access to repositories exported via static http
4 4 #
5 5 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
6 6 #
7 7 # This software may be used and distributed according to the terms of the
8 8 # GNU General Public License version 2 or any later version.
9 9
10 10 from __future__ import absolute_import
11 11
12 12 import errno
13 13 import os
14 14
15 15 from .i18n import _
16 16 from . import (
17 17 byterange,
18 18 changelog,
19 19 error,
20 20 localrepo,
21 21 manifest,
22 22 namespaces,
23 23 scmutil,
24 24 store,
25 25 url,
26 26 util,
27 vfs as vfsmod,
27 28 )
28 29
29 30 urlerr = util.urlerr
30 31 urlreq = util.urlreq
31 32
32 33 class httprangereader(object):
33 34 def __init__(self, url, opener):
34 35 # we assume opener has HTTPRangeHandler
35 36 self.url = url
36 37 self.pos = 0
37 38 self.opener = opener
38 39 self.name = url
39 40
40 41 def __enter__(self):
41 42 return self
42 43
43 44 def __exit__(self, exc_type, exc_value, traceback):
44 45 self.close()
45 46
46 47 def seek(self, pos):
47 48 self.pos = pos
48 49 def read(self, bytes=None):
49 50 req = urlreq.request(self.url)
50 51 end = ''
51 52 if bytes:
52 53 end = self.pos + bytes - 1
53 54 if self.pos or end:
54 55 req.add_header('Range', 'bytes=%d-%s' % (self.pos, end))
55 56
56 57 try:
57 58 f = self.opener.open(req)
58 59 data = f.read()
59 60 code = f.code
60 61 except urlerr.httperror as inst:
61 62 num = inst.code == 404 and errno.ENOENT or None
62 63 raise IOError(num, inst)
63 64 except urlerr.urlerror as inst:
64 65 raise IOError(None, inst.reason[1])
65 66
66 67 if code == 200:
67 68 # HTTPRangeHandler does nothing if remote does not support
68 69 # Range headers and returns the full entity. Let's slice it.
69 70 if bytes:
70 71 data = data[self.pos:self.pos + bytes]
71 72 else:
72 73 data = data[self.pos:]
73 74 elif bytes:
74 75 data = data[:bytes]
75 76 self.pos += len(data)
76 77 return data
77 78 def readlines(self):
78 79 return self.read().splitlines(True)
79 80 def __iter__(self):
80 81 return iter(self.readlines())
81 82 def close(self):
82 83 pass
83 84
84 85 def build_opener(ui, authinfo):
85 86 # urllib cannot handle URLs with embedded user or passwd
86 87 urlopener = url.opener(ui, authinfo)
87 88 urlopener.add_handler(byterange.HTTPRangeHandler())
88 89
89 class statichttpvfs(scmutil.abstractvfs):
90 class statichttpvfs(vfsmod.abstractvfs):
90 91 def __init__(self, base):
91 92 self.base = base
92 93
93 94 def __call__(self, path, mode='r', *args, **kw):
94 95 if mode not in ('r', 'rb'):
95 96 raise IOError('Permission denied')
96 97 f = "/".join((self.base, urlreq.quote(path)))
97 98 return httprangereader(f, urlopener)
98 99
99 100 def join(self, path):
100 101 if path:
101 102 return os.path.join(self.base, path)
102 103 else:
103 104 return self.base
104 105
105 106 return statichttpvfs
106 107
107 108 class statichttppeer(localrepo.localpeer):
108 109 def local(self):
109 110 return None
110 111 def canpush(self):
111 112 return False
112 113
113 114 class statichttprepository(localrepo.localrepository):
114 115 supported = localrepo.localrepository._basesupported
115 116
116 117 def __init__(self, ui, path):
117 118 self._url = path
118 119 self.ui = ui
119 120
120 121 self.root = path
121 122 u = util.url(path.rstrip('/') + "/.hg")
122 123 self.path, authinfo = u.authinfo()
123 124
124 125 vfsclass = build_opener(ui, authinfo)
125 126 self.vfs = vfsclass(self.path)
126 127 self._phasedefaults = []
127 128
128 129 self.names = namespaces.namespaces()
129 130
130 131 try:
131 132 requirements = scmutil.readrequires(self.vfs, self.supported)
132 133 except IOError as inst:
133 134 if inst.errno != errno.ENOENT:
134 135 raise
135 136 requirements = set()
136 137
137 138 # check if it is a non-empty old-style repository
138 139 try:
139 140 fp = self.vfs("00changelog.i")
140 141 fp.read(1)
141 142 fp.close()
142 143 except IOError as inst:
143 144 if inst.errno != errno.ENOENT:
144 145 raise
145 146 # we do not care about empty old-style repositories here
146 147 msg = _("'%s' does not appear to be an hg repository") % path
147 148 raise error.RepoError(msg)
148 149
149 150 # setup store
150 151 self.store = store.store(requirements, self.path, vfsclass)
151 152 self.spath = self.store.path
152 153 self.svfs = self.store.opener
153 154 self.sjoin = self.store.join
154 155 self._filecache = {}
155 156 self.requirements = requirements
156 157
157 158 self.manifestlog = manifest.manifestlog(self.svfs, self)
158 159 self.changelog = changelog.changelog(self.svfs)
159 160 self._tags = None
160 161 self.nodetagscache = None
161 162 self._branchcaches = {}
162 163 self._revbranchcache = None
163 164 self.encodepats = None
164 165 self.decodepats = None
165 166 self._transref = None
166 167
167 168 def _restrictcapabilities(self, caps):
168 169 caps = super(statichttprepository, self)._restrictcapabilities(caps)
169 170 return caps.difference(["pushkey"])
170 171
171 172 def url(self):
172 173 return self._url
173 174
174 175 def local(self):
175 176 return False
176 177
177 178 def peer(self):
178 179 return statichttppeer(self)
179 180
180 181 def lock(self, wait=True):
181 182 raise error.Abort(_('cannot lock static-http repository'))
182 183
183 184 def _writecaches(self):
184 185 pass # statichttprepository are read only
185 186
186 187 def instance(ui, path, create):
187 188 if create:
188 189 raise error.Abort(_('cannot create new static-http repository'))
189 190 return statichttprepository(ui, path[7:])
General Comments 0
You need to be logged in to leave comments. Login now