]> git.lizzy.rs Git - plan9front.git/blob - sys/lib/python/hgext/hgwebfs.py
hgwebfs: keep trying as long as we get needkey response
[plan9front.git] / sys / lib / python / hgext / hgwebfs.py
1 ''' webfs support '''
2
3 import mercurial.url
4 import re
5 import os
6
7 class Webconn:
8         def __init__(self, mnt, req):
9                 loop = True
10                 while loop:
11                         loop = False
12                         try:
13                                 self.open(mnt, req)
14                         except IOError, e:
15                                 try:
16                                         errstr = e.strerror
17                                         params = errstr[errstr.index("needkey ")+8:]
18                                         if params.find("!password?") < 0:
19                                                 raise e
20                                         if os.spawnl(os.P_WAIT, "/boot/factotum", "getkey", "-g", params) != 0:
21                                                 raise e
22                                         loop = True
23                                 except:
24                                         raise e
25
26         def open(self, mnt, req):
27                 if type(req) == str:
28                         self.url = req
29                 else:
30                         self.url = req.get_full_url()
31                 if self.url[0:5] == 'file:':
32                         path = self.url[5:]
33                         while path[0:2] == '//':
34                                 path = path[1:]
35                         self.dir = '/dev/null'
36                         self.body = open(path, 'r', 0)
37                         return
38                 ctl = open(mnt+'/clone', 'r+', 0)
39                 try:
40                         self.dir = mnt+'/'+ctl.readline().rstrip('\n')
41                         ctl.seek(0)
42                         ctl.write('url '+self.url)
43                         m = 'User-Agent: mercurial/proto-1.0\r\n';
44                         for h in req.headers:
45                                 m += h+': '+req.headers[h]+'\r\n'
46                         ctl.seek(0)
47                         ctl.write('headers '+m)
48                         if req.has_data():
49                                 data = req.get_data()
50                                 post = open(self.dir+'/postbody', 'w', 0);
51                                 try:
52                                         data.seek(0)
53                                         while True:
54                                                 buf = data.read(4096)
55                                                 if len(buf) == 0:
56                                                         break
57                                                 post.write(buf)
58                                 finally:
59                                         post.close()
60                         self.body = open(self.dir+'/body', 'r', 0)
61                 finally:        
62                         ctl.close()
63
64         def read(self, amt=4096):
65                 return self.body.read(amt);
66
67         def close(self):
68                 self.body.close()
69                 self.body = None
70                 self.dir = None
71
72         def geturl(self):
73                 return self.url
74
75         def getheader(self, key):
76                 name = re.sub(r'[^a-z]+', '', key.lower())
77                 try:
78                         f = open(self.dir+'/'+name, 'r', 0)
79                         try:
80                                 hdr = f.read()
81                         finally:
82                                 f.close()
83                         return hdr
84                 except:
85                         return None
86
87 class Webopener:
88         def __init__(self):
89                 self.handlers = []
90
91         def add_handler(self, handler):
92                 return
93
94         def open(self, req, data=None):
95                 return Webconn('/mnt/web', req)
96
97         def close(self):
98                 pass
99
100
101 def webopener(ui, authinfo=None):
102         return Webopener();
103
104 mercurial.url.has_https = 1
105 mercurial.url.opener = webopener