##// END OF EJS Templates
vcs-lib: code cleanup
marcink -
r2928:ee7f8502 default
parent child Browse files
Show More
@@ -1,191 +1,186 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2014-2018 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 Various version Control System version lib (vcs) management abstraction layer
23 23 for Python. Build with server client architecture.
24 24 """
25 import atexit
26 import logging
27 import urlparse
28 from cStringIO import StringIO
25 29
30 from rhodecode.lib.vcs.conf import settings
31 from rhodecode.lib.vcs.backends import get_vcs_instance, get_backend
32 from rhodecode.lib.vcs.exceptions import (
33 VCSError, RepositoryError, CommitError, VCSCommunicationError)
26 34
27 35 VERSION = (0, 5, 0, 'dev')
28 36
29 37 __version__ = '.'.join((str(each) for each in VERSION[:4]))
30 38
31 39 __all__ = [
32 40 'get_version', 'get_vcs_instance', 'get_backend',
33 'VCSError', 'RepositoryError', 'CommitError'
34 ]
35
36 import atexit
37 import logging
38 import subprocess32
39 import time
40 import urlparse
41 from cStringIO import StringIO
42
43
44 from rhodecode.lib.vcs.conf import settings
45 from rhodecode.lib.vcs.backends import get_vcs_instance, get_backend
46 from rhodecode.lib.vcs.exceptions import (
47 VCSError, RepositoryError, CommitError, VCSCommunicationError)
41 'VCSError', 'RepositoryError', 'CommitError', 'VCSCommunicationError'
42 ]
48 43
49 44 log = logging.getLogger(__name__)
50 45
51 46 # The pycurl library directly accesses C API functions and is not patched by
52 47 # gevent. This will potentially lead to deadlocks due to incompatibility to
53 48 # gevent. Therefore we check if gevent is active and import a gevent compatible
54 49 # wrapper in that case.
55 50 try:
56 51 from gevent import monkey
57 52 if monkey.is_module_patched('__builtin__'):
58 53 import geventcurl as pycurl
59 54 log.debug('Using gevent comapatible pycurl: %s', pycurl)
60 55 else:
61 56 import pycurl
62 57 except ImportError:
63 58 import pycurl
64 59
65 60
66 61 def get_version():
67 62 """
68 63 Returns shorter version (digit parts only) as string.
69 64 """
70 65 return '.'.join((str(each) for each in VERSION[:3]))
71 66
72 67
73 68 def connect_http(server_and_port):
74 69 from rhodecode.lib.vcs import connection, client_http
75 70 from rhodecode.lib.middleware.utils import scm_app
76 71
77 72 session_factory = client_http.ThreadlocalSessionFactory()
78 73
79 74 connection.Git = client_http.RepoMaker(
80 75 server_and_port, '/git', 'git', session_factory)
81 76 connection.Hg = client_http.RepoMaker(
82 77 server_and_port, '/hg', 'hg', session_factory)
83 78 connection.Svn = client_http.RepoMaker(
84 79 server_and_port, '/svn', 'svn', session_factory)
85 80 connection.Service = client_http.ServiceConnection(
86 81 server_and_port, '/_service', session_factory)
87 82
88 83 scm_app.HG_REMOTE_WSGI = client_http.VcsHttpProxy(
89 84 server_and_port, '/proxy/hg')
90 85 scm_app.GIT_REMOTE_WSGI = client_http.VcsHttpProxy(
91 86 server_and_port, '/proxy/git')
92 87
93 88 @atexit.register
94 89 def free_connection_resources():
95 90 connection.Git = None
96 91 connection.Hg = None
97 92 connection.Svn = None
98 93 connection.Service = None
99 94
100 95
101 96 def connect_vcs(server_and_port, protocol):
102 97 """
103 98 Initializes the connection to the vcs server.
104 99
105 100 :param server_and_port: str, e.g. "localhost:9900"
106 101 :param protocol: str or "http"
107 102 """
108 103 if protocol == 'http':
109 104 connect_http(server_and_port)
110 105 else:
111 106 raise Exception('Invalid vcs server protocol "{}"'.format(protocol))
112 107
113 108
114 109 def create_vcsserver_proxy(server_and_port, protocol):
115 110 if protocol == 'http':
116 111 return _create_vcsserver_proxy_http(server_and_port)
117 112 else:
118 113 raise Exception('Invalid vcs server protocol "{}"'.format(protocol))
119 114
120 115
121 116 def _create_vcsserver_proxy_http(server_and_port):
122 117 from rhodecode.lib.vcs import client_http
123 118
124 119 session = _create_http_rpc_session()
125 120 url = urlparse.urljoin('http://%s' % server_and_port, '/server')
126 121 return client_http.RemoteObject(url, session)
127 122
128 123
129 124 class CurlSession(object):
130 125 """
131 126 Modeled so that it provides a subset of the requests interface.
132 127
133 128 This has been created so that it does only provide a minimal API for our
134 129 needs. The parts which it provides are based on the API of the library
135 130 `requests` which allows us to easily benchmark against it.
136 131
137 132 Please have a look at the class :class:`requests.Session` when you extend
138 133 it.
139 134 """
140 135
141 136 def __init__(self):
142 137 curl = pycurl.Curl()
143 138 # TODO: johbo: I did test with 7.19 of libcurl. This version has
144 139 # trouble with 100 - continue being set in the expect header. This
145 140 # can lead to massive performance drops, switching it off here.
146 141 curl.setopt(curl.HTTPHEADER, ["Expect:"])
147 142 curl.setopt(curl.TCP_NODELAY, True)
148 143 curl.setopt(curl.PROTOCOLS, curl.PROTO_HTTP)
149 144 self._curl = curl
150 145
151 146 def post(self, url, data, allow_redirects=False):
152 147 response_buffer = StringIO()
153 148
154 149 curl = self._curl
155 150 curl.setopt(curl.URL, url)
156 151 curl.setopt(curl.POST, True)
157 152 curl.setopt(curl.POSTFIELDS, data)
158 153 curl.setopt(curl.FOLLOWLOCATION, allow_redirects)
159 154 curl.setopt(curl.WRITEDATA, response_buffer)
160 155 curl.perform()
161 156
162 157 status_code = curl.getinfo(pycurl.HTTP_CODE)
163 158
164 159 return CurlResponse(response_buffer, status_code)
165 160
166 161
167 162 class CurlResponse(object):
168 163 """
169 164 The response of a request, modeled after the requests API.
170 165
171 166 This class provides a subset of the response interface known from the
172 167 library `requests`. It is intentionally kept similar, so that we can use
173 168 `requests` as a drop in replacement for benchmarking purposes.
174 169 """
175 170
176 171 def __init__(self, response_buffer, status_code):
177 172 self._response_buffer = response_buffer
178 173 self._status_code = status_code
179 174
180 175 @property
181 176 def content(self):
182 177 return self._response_buffer.getvalue()
183 178
184 179 @property
185 180 def status_code(self):
186 181 return self._status_code
187 182
188 183
189 184 def _create_http_rpc_session():
190 185 session = CurlSession()
191 186 return session
General Comments 0
You need to be logged in to leave comments. Login now