##// END OF EJS Templates
statichttprepo: remove wrong getattr ladder...
Augie Fackler -
r25196:7a1af58a default
parent child Browse files
Show More
@@ -1,168 +1,164
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 i18n import _
11 11 import changelog, byterange, url, error, namespaces
12 12 import localrepo, manifest, util, scmutil, store
13 13 import urllib, urllib2, errno, os
14 14
15 15 class httprangereader(object):
16 16 def __init__(self, url, opener):
17 17 # we assume opener has HTTPRangeHandler
18 18 self.url = url
19 19 self.pos = 0
20 20 self.opener = opener
21 21 self.name = url
22 22 def seek(self, pos):
23 23 self.pos = pos
24 24 def read(self, bytes=None):
25 25 req = urllib2.Request(self.url)
26 26 end = ''
27 27 if bytes:
28 28 end = self.pos + bytes - 1
29 29 if self.pos or end:
30 30 req.add_header('Range', 'bytes=%d-%s' % (self.pos, end))
31 31
32 32 try:
33 33 f = self.opener.open(req)
34 34 data = f.read()
35 # Python 2.6+ defines a getcode() function, and 2.4 and
36 # 2.5 appear to always have an undocumented code attribute
37 # set. If we can't read either of those, fall back to 206
38 # and hope for the best.
39 code = getattr(f, 'getcode', lambda : getattr(f, 'code', 206))()
35 code = f.code
40 36 except urllib2.HTTPError, inst:
41 37 num = inst.code == 404 and errno.ENOENT or None
42 38 raise IOError(num, inst)
43 39 except urllib2.URLError, inst:
44 40 raise IOError(None, inst.reason[1])
45 41
46 42 if code == 200:
47 43 # HTTPRangeHandler does nothing if remote does not support
48 44 # Range headers and returns the full entity. Let's slice it.
49 45 if bytes:
50 46 data = data[self.pos:self.pos + bytes]
51 47 else:
52 48 data = data[self.pos:]
53 49 elif bytes:
54 50 data = data[:bytes]
55 51 self.pos += len(data)
56 52 return data
57 53 def readlines(self):
58 54 return self.read().splitlines(True)
59 55 def __iter__(self):
60 56 return iter(self.readlines())
61 57 def close(self):
62 58 pass
63 59
64 60 def build_opener(ui, authinfo):
65 61 # urllib cannot handle URLs with embedded user or passwd
66 62 urlopener = url.opener(ui, authinfo)
67 63 urlopener.add_handler(byterange.HTTPRangeHandler())
68 64
69 65 class statichttpvfs(scmutil.abstractvfs):
70 66 def __init__(self, base):
71 67 self.base = base
72 68
73 69 def __call__(self, path, mode='r', *args, **kw):
74 70 if mode not in ('r', 'rb'):
75 71 raise IOError('Permission denied')
76 72 f = "/".join((self.base, urllib.quote(path)))
77 73 return httprangereader(f, urlopener)
78 74
79 75 def join(self, path):
80 76 if path:
81 77 return os.path.join(self.base, path)
82 78 else:
83 79 return self.base
84 80
85 81 return statichttpvfs
86 82
87 83 class statichttppeer(localrepo.localpeer):
88 84 def local(self):
89 85 return None
90 86 def canpush(self):
91 87 return False
92 88
93 89 class statichttprepository(localrepo.localrepository):
94 90 supported = localrepo.localrepository._basesupported
95 91
96 92 def __init__(self, ui, path):
97 93 self._url = path
98 94 self.ui = ui
99 95
100 96 self.root = path
101 97 u = util.url(path.rstrip('/') + "/.hg")
102 98 self.path, authinfo = u.authinfo()
103 99
104 100 opener = build_opener(ui, authinfo)
105 101 self.opener = opener(self.path)
106 102 self.vfs = self.opener
107 103 self._phasedefaults = []
108 104
109 105 self.names = namespaces.namespaces()
110 106
111 107 try:
112 108 requirements = scmutil.readrequires(self.vfs, self.supported)
113 109 except IOError, inst:
114 110 if inst.errno != errno.ENOENT:
115 111 raise
116 112 requirements = set()
117 113
118 114 # check if it is a non-empty old-style repository
119 115 try:
120 116 fp = self.vfs("00changelog.i")
121 117 fp.read(1)
122 118 fp.close()
123 119 except IOError, inst:
124 120 if inst.errno != errno.ENOENT:
125 121 raise
126 122 # we do not care about empty old-style repositories here
127 123 msg = _("'%s' does not appear to be an hg repository") % path
128 124 raise error.RepoError(msg)
129 125
130 126 # setup store
131 127 self.store = store.store(requirements, self.path, opener)
132 128 self.spath = self.store.path
133 129 self.svfs = self.store.opener
134 130 self.sopener = self.svfs
135 131 self.sjoin = self.store.join
136 132 self._filecache = {}
137 133 self.requirements = requirements
138 134
139 135 self.manifest = manifest.manifest(self.svfs)
140 136 self.changelog = changelog.changelog(self.svfs)
141 137 self._tags = None
142 138 self.nodetagscache = None
143 139 self._branchcaches = {}
144 140 self._revbranchcache = None
145 141 self.encodepats = None
146 142 self.decodepats = None
147 143 self._transref = None
148 144
149 145 def _restrictcapabilities(self, caps):
150 146 caps = super(statichttprepository, self)._restrictcapabilities(caps)
151 147 return caps.difference(["pushkey"])
152 148
153 149 def url(self):
154 150 return self._url
155 151
156 152 def local(self):
157 153 return False
158 154
159 155 def peer(self):
160 156 return statichttppeer(self)
161 157
162 158 def lock(self, wait=True):
163 159 raise util.Abort(_('cannot lock static-http repository'))
164 160
165 161 def instance(ui, path, create):
166 162 if create:
167 163 raise util.Abort(_('cannot create new static-http repository'))
168 164 return statichttprepository(ui, path[7:])
General Comments 0
You need to be logged in to leave comments. Login now