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