Show More
@@ -25,15 +25,10 b' Provides the implementation of various c' | |||||
25 |
|
25 | |||
26 | import copy |
|
26 | import copy | |
27 | import logging |
|
27 | import logging | |
28 | import threading |
|
|||
29 | import urlparse |
|
|||
30 | import uuid |
|
28 | import uuid | |
31 | import weakref |
|
29 | import weakref | |
32 | from urllib2 import URLError |
|
|||
33 |
|
30 | |||
34 | import msgpack |
|
|||
35 | import Pyro4 |
|
31 | import Pyro4 | |
36 | import requests |
|
|||
37 | from pyramid.threadlocal import get_current_request |
|
32 | from pyramid.threadlocal import get_current_request | |
38 | from Pyro4.errors import CommunicationError, ConnectionClosedError, DaemonError |
|
33 | from Pyro4.errors import CommunicationError, ConnectionClosedError, DaemonError | |
39 |
|
34 | |||
@@ -43,137 +38,6 b' from rhodecode.lib.vcs.conf import setti' | |||||
43 | log = logging.getLogger(__name__) |
|
38 | log = logging.getLogger(__name__) | |
44 |
|
39 | |||
45 |
|
40 | |||
46 | # TODO: mikhail: Keep it in sync with vcsserver's |
|
|||
47 | # HTTPApplication.ALLOWED_EXCEPTIONS |
|
|||
48 | EXCEPTIONS_MAP = { |
|
|||
49 | 'KeyError': KeyError, |
|
|||
50 | 'URLError': URLError, |
|
|||
51 | } |
|
|||
52 |
|
||||
53 |
|
||||
54 | class HTTPRepoMaker(object): |
|
|||
55 | def __init__(self, server_and_port, backend_endpoint): |
|
|||
56 | self.url = urlparse.urljoin( |
|
|||
57 | 'http://%s' % server_and_port, backend_endpoint) |
|
|||
58 |
|
||||
59 | def __call__(self, path, config, with_wire=None): |
|
|||
60 | log.debug('HTTPRepoMaker call on %s', path) |
|
|||
61 | return HTTPRemoteRepo(path, config, self.url, with_wire=with_wire) |
|
|||
62 |
|
||||
63 | def __getattr__(self, name): |
|
|||
64 | def f(*args, **kwargs): |
|
|||
65 | return self._call(name, *args, **kwargs) |
|
|||
66 | return f |
|
|||
67 |
|
||||
68 | @exceptions.map_vcs_exceptions |
|
|||
69 | def _call(self, name, *args, **kwargs): |
|
|||
70 | payload = { |
|
|||
71 | 'id': str(uuid.uuid4()), |
|
|||
72 | 'method': name, |
|
|||
73 | 'params': {'args': args, 'kwargs': kwargs} |
|
|||
74 | } |
|
|||
75 | return _remote_call(self.url, payload, EXCEPTIONS_MAP) |
|
|||
76 |
|
||||
77 |
|
||||
78 | class VcsHttpProxy(object): |
|
|||
79 |
|
||||
80 | CHUNK_SIZE = 16384 |
|
|||
81 |
|
||||
82 | def __init__(self, server_and_port, backend_endpoint): |
|
|||
83 | adapter = requests.adapters.HTTPAdapter(max_retries=5) |
|
|||
84 | self.base_url = urlparse.urljoin( |
|
|||
85 | 'http://%s' % server_and_port, backend_endpoint) |
|
|||
86 | self.session = requests.Session() |
|
|||
87 | self.session.mount('http://', adapter) |
|
|||
88 |
|
||||
89 | def handle(self, environment, input_data, *args, **kwargs): |
|
|||
90 | data = { |
|
|||
91 | 'environment': environment, |
|
|||
92 | 'input_data': input_data, |
|
|||
93 | 'args': args, |
|
|||
94 | 'kwargs': kwargs |
|
|||
95 | } |
|
|||
96 | result = self.session.post( |
|
|||
97 | self.base_url, msgpack.packb(data), stream=True) |
|
|||
98 | return self._get_result(result) |
|
|||
99 |
|
||||
100 | def _deserialize_and_raise(self, error): |
|
|||
101 | exception = Exception(error['message']) |
|
|||
102 | try: |
|
|||
103 | exception._vcs_kind = error['_vcs_kind'] |
|
|||
104 | except KeyError: |
|
|||
105 | pass |
|
|||
106 | raise exception |
|
|||
107 |
|
||||
108 | def _iterate(self, result): |
|
|||
109 | unpacker = msgpack.Unpacker() |
|
|||
110 | for line in result.iter_content(chunk_size=self.CHUNK_SIZE): |
|
|||
111 | unpacker.feed(line) |
|
|||
112 | for chunk in unpacker: |
|
|||
113 | yield chunk |
|
|||
114 |
|
||||
115 | def _get_result(self, result): |
|
|||
116 | iterator = self._iterate(result) |
|
|||
117 | error = iterator.next() |
|
|||
118 | if error: |
|
|||
119 | self._deserialize_and_raise(error) |
|
|||
120 |
|
||||
121 | status = iterator.next() |
|
|||
122 | headers = iterator.next() |
|
|||
123 |
|
||||
124 | return iterator, status, headers |
|
|||
125 |
|
||||
126 |
|
||||
127 | class HTTPRemoteRepo(object): |
|
|||
128 | def __init__(self, path, config, url, with_wire=None): |
|
|||
129 | self.url = url |
|
|||
130 | self._wire = { |
|
|||
131 | "path": path, |
|
|||
132 | "config": config, |
|
|||
133 | "context": str(uuid.uuid4()), |
|
|||
134 | } |
|
|||
135 | if with_wire: |
|
|||
136 | self._wire.update(with_wire) |
|
|||
137 |
|
||||
138 | def __getattr__(self, name): |
|
|||
139 | def f(*args, **kwargs): |
|
|||
140 | return self._call(name, *args, **kwargs) |
|
|||
141 | return f |
|
|||
142 |
|
||||
143 | @exceptions.map_vcs_exceptions |
|
|||
144 | def _call(self, name, *args, **kwargs): |
|
|||
145 | log.debug('Calling %s@%s', self.url, name) |
|
|||
146 | # TODO: oliver: This is currently necessary pre-call since the |
|
|||
147 | # config object is being changed for hooking scenarios |
|
|||
148 | wire = copy.deepcopy(self._wire) |
|
|||
149 | wire["config"] = wire["config"].serialize() |
|
|||
150 | payload = { |
|
|||
151 | 'id': str(uuid.uuid4()), |
|
|||
152 | 'method': name, |
|
|||
153 | 'params': {'wire': wire, 'args': args, 'kwargs': kwargs} |
|
|||
154 | } |
|
|||
155 | return _remote_call(self.url, payload, EXCEPTIONS_MAP) |
|
|||
156 |
|
||||
157 | def __getitem__(self, key): |
|
|||
158 | return self.revision(key) |
|
|||
159 |
|
||||
160 |
|
||||
161 | def _remote_call(url, payload, exceptions_map): |
|
|||
162 | response = requests.post(url, data=msgpack.packb(payload)) |
|
|||
163 | response = msgpack.unpackb(response.content) |
|
|||
164 | error = response.get('error') |
|
|||
165 | if error: |
|
|||
166 | type_ = error.get('type', 'Exception') |
|
|||
167 | exc = exceptions_map.get(type_, Exception) |
|
|||
168 | exc = exc(error.get('message')) |
|
|||
169 | try: |
|
|||
170 | exc._vcs_kind = error['_vcs_kind'] |
|
|||
171 | except KeyError: |
|
|||
172 | pass |
|
|||
173 | raise exc |
|
|||
174 | return response.get('result') |
|
|||
175 |
|
||||
176 |
|
||||
177 | class RepoMaker(object): |
|
41 | class RepoMaker(object): | |
178 |
|
42 | |||
179 | def __init__(self, proxy_factory): |
|
43 | def __init__(self, proxy_factory): |
General Comments 0
You need to be logged in to leave comments.
Login now