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