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