6 # |
6 # |
7 # This software may be used and distributed according to the terms |
7 # This software may be used and distributed according to the terms |
8 # of the GNU General Public License, incorporated herein by reference. |
8 # of the GNU General Public License, incorporated herein by reference. |
9 |
9 |
10 from i18n import _ |
10 from i18n import _ |
11 import changelog, httprangereader |
11 import changelog, byterange, url |
12 import repo, localrepo, manifest, util, store |
12 import repo, localrepo, manifest, util, store |
13 import urllib, urllib2, errno |
13 import urllib, urllib2, errno |
14 |
14 |
15 class rangereader(httprangereader.httprangereader): |
15 class httprangereader(object): |
16 def read(self, size=None): |
16 def __init__(self, url, opener): |
|
17 # we assume opener has HTTPRangeHandler |
|
18 self.url = url |
|
19 self.pos = 0 |
|
20 self.opener = opener |
|
21 def seek(self, pos): |
|
22 self.pos = pos |
|
23 def read(self, bytes=None): |
|
24 req = urllib2.Request(self.url) |
|
25 end = '' |
|
26 if bytes: |
|
27 end = self.pos + bytes - 1 |
|
28 req.add_header('Range', 'bytes=%d-%s' % (self.pos, end)) |
|
29 |
17 try: |
30 try: |
18 return httprangereader.httprangereader.read(self, size) |
31 f = self.opener.open(req) |
|
32 data = f.read() |
19 except urllib2.HTTPError, inst: |
33 except urllib2.HTTPError, inst: |
20 num = inst.code == 404 and errno.ENOENT or None |
34 num = inst.code == 404 and errno.ENOENT or None |
21 raise IOError(num, inst) |
35 raise IOError(num, inst) |
22 except urllib2.URLError, inst: |
36 except urllib2.URLError, inst: |
23 raise IOError(None, inst.reason[1]) |
37 raise IOError(None, inst.reason[1]) |
24 |
38 |
25 def opener(base): |
39 if bytes: |
26 """return a function that opens files over http""" |
40 data = data[:bytes] |
27 p = base |
41 return data |
28 def o(path, mode="r"): |
42 |
29 f = "/".join((p, urllib.quote(path))) |
43 def build_opener(ui, authinfo): |
30 return rangereader(f) |
44 # urllib cannot handle URLs with embedded user or passwd |
31 return o |
45 urlopener = url.opener(ui, authinfo) |
|
46 urlopener.add_handler(byterange.HTTPRangeHandler()) |
|
47 |
|
48 def opener(base): |
|
49 """return a function that opens files over http""" |
|
50 p = base |
|
51 def o(path, mode="r"): |
|
52 f = "/".join((p, urllib.quote(path))) |
|
53 return httprangereader(f, urlopener) |
|
54 return o |
|
55 |
|
56 return opener |
32 |
57 |
33 class statichttprepository(localrepo.localrepository): |
58 class statichttprepository(localrepo.localrepository): |
34 def __init__(self, ui, path): |
59 def __init__(self, ui, path): |
35 self._url = path |
60 self._url = path |
36 self.ui = ui |
61 self.ui = ui |
37 |
62 |
38 self.path = path.rstrip('/') + "/.hg" |
63 self.path, authinfo = url.getauthinfo(path.rstrip('/') + "/.hg") |
|
64 |
|
65 opener = build_opener(ui, authinfo) |
39 self.opener = opener(self.path) |
66 self.opener = opener(self.path) |
40 |
67 |
41 # find requirements |
68 # find requirements |
42 try: |
69 try: |
43 requirements = self.opener("requires").read().splitlines() |
70 requirements = self.opener("requires").read().splitlines() |