Show More
@@ -0,0 +1,16 b'' | |||||
|
1 | # RhodeCode VCSServer provides access to different vcs backends via network. | |||
|
2 | # Copyright (C) 2014-2018 RhodeCode GmbH | |||
|
3 | # | |||
|
4 | # This program is free software; you can redistribute it and/or modify | |||
|
5 | # it under the terms of the GNU General Public License as published by | |||
|
6 | # the Free Software Foundation; either version 3 of the License, or | |||
|
7 | # (at your option) any later version. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
14 | # You should have received a copy of the GNU General Public License | |||
|
15 | # along with this program; if not, write to the Free Software Foundation, | |||
|
16 | # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
@@ -0,0 +1,60 b'' | |||||
|
1 | # RhodeCode VCSServer provides access to different vcs backends via network. | |||
|
2 | # Copyright (C) 2014-2018 RhodeCode GmbH | |||
|
3 | # | |||
|
4 | # This program is free software; you can redistribute it and/or modify | |||
|
5 | # it under the terms of the GNU General Public License as published by | |||
|
6 | # the Free Software Foundation; either version 3 of the License, or | |||
|
7 | # (at your option) any later version. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
14 | # You should have received a copy of the GNU General Public License | |||
|
15 | # along with this program; if not, write to the Free Software Foundation, | |||
|
16 | # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
|
17 | ||||
|
18 | import logging | |||
|
19 | from dogpile.cache import register_backend | |||
|
20 | ||||
|
21 | register_backend( | |||
|
22 | "dogpile.cache.rc.memory_lru", "vcsserver.lib.rc_cache.backends", | |||
|
23 | "LRUMemoryBackend") | |||
|
24 | ||||
|
25 | log = logging.getLogger(__name__) | |||
|
26 | ||||
|
27 | from . import region_meta | |||
|
28 | from .util import key_generator, get_default_cache_settings, make_region | |||
|
29 | ||||
|
30 | ||||
|
31 | def configure_dogpile_cache(settings): | |||
|
32 | cache_dir = settings.get('cache_dir') | |||
|
33 | if cache_dir: | |||
|
34 | region_meta.dogpile_config_defaults['cache_dir'] = cache_dir | |||
|
35 | ||||
|
36 | rc_cache_data = get_default_cache_settings(settings, prefixes=['rc_cache.']) | |||
|
37 | ||||
|
38 | # inspect available namespaces | |||
|
39 | avail_regions = set() | |||
|
40 | for key in rc_cache_data.keys(): | |||
|
41 | namespace_name = key.split('.', 1)[0] | |||
|
42 | avail_regions.add(namespace_name) | |||
|
43 | log.debug('dogpile: found following cache regions: %s', avail_regions) | |||
|
44 | ||||
|
45 | # register them into namespace | |||
|
46 | for region_name in avail_regions: | |||
|
47 | new_region = make_region( | |||
|
48 | name=region_name, | |||
|
49 | function_key_generator=key_generator | |||
|
50 | ) | |||
|
51 | ||||
|
52 | new_region.configure_from_config(settings, 'rc_cache.{}.'.format(region_name)) | |||
|
53 | ||||
|
54 | log.debug('dogpile: registering a new region %s[%s]', | |||
|
55 | region_name, new_region.__dict__) | |||
|
56 | region_meta.dogpile_cache_regions[region_name] = new_region | |||
|
57 | ||||
|
58 | ||||
|
59 | def includeme(config): | |||
|
60 | configure_dogpile_cache(config.registry.settings) |
@@ -0,0 +1,51 b'' | |||||
|
1 | # RhodeCode VCSServer provides access to different vcs backends via network. | |||
|
2 | # Copyright (C) 2014-2018 RhodeCode GmbH | |||
|
3 | # | |||
|
4 | # This program is free software; you can redistribute it and/or modify | |||
|
5 | # it under the terms of the GNU General Public License as published by | |||
|
6 | # the Free Software Foundation; either version 3 of the License, or | |||
|
7 | # (at your option) any later version. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
14 | # You should have received a copy of the GNU General Public License | |||
|
15 | # along with this program; if not, write to the Free Software Foundation, | |||
|
16 | # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
|
17 | ||||
|
18 | import logging | |||
|
19 | ||||
|
20 | from dogpile.cache.backends import memory as memory_backend | |||
|
21 | from lru import LRU as LRUDict | |||
|
22 | ||||
|
23 | ||||
|
24 | _default_max_size = 1024 | |||
|
25 | ||||
|
26 | log = logging.getLogger(__name__) | |||
|
27 | ||||
|
28 | ||||
|
29 | class LRUMemoryBackend(memory_backend.MemoryBackend): | |||
|
30 | pickle_values = False | |||
|
31 | ||||
|
32 | def __init__(self, arguments): | |||
|
33 | max_size = arguments.pop('max_size', _default_max_size) | |||
|
34 | callback = None | |||
|
35 | if arguments.pop('log_max_size_reached', None): | |||
|
36 | def evicted(key, value): | |||
|
37 | log.debug( | |||
|
38 | 'LRU: evicting key `%s` due to max size %s reach', key, max_size) | |||
|
39 | callback = evicted | |||
|
40 | ||||
|
41 | arguments['cache_dict'] = LRUDict(max_size, callback=callback) | |||
|
42 | super(LRUMemoryBackend, self).__init__(arguments) | |||
|
43 | ||||
|
44 | def delete(self, key): | |||
|
45 | if self._cache.has_key(key): | |||
|
46 | del self._cache[key] | |||
|
47 | ||||
|
48 | def delete_multi(self, keys): | |||
|
49 | for key in keys: | |||
|
50 | if self._cache.has_key(key): | |||
|
51 | del self._cache[key] |
@@ -0,0 +1,26 b'' | |||||
|
1 | # RhodeCode VCSServer provides access to different vcs backends via network. | |||
|
2 | # Copyright (C) 2014-2018 RhodeCode GmbH | |||
|
3 | # | |||
|
4 | # This program is free software; you can redistribute it and/or modify | |||
|
5 | # it under the terms of the GNU General Public License as published by | |||
|
6 | # the Free Software Foundation; either version 3 of the License, or | |||
|
7 | # (at your option) any later version. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
14 | # You should have received a copy of the GNU General Public License | |||
|
15 | # along with this program; if not, write to the Free Software Foundation, | |||
|
16 | # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
|
17 | ||||
|
18 | import os | |||
|
19 | import tempfile | |||
|
20 | ||||
|
21 | dogpile_config_defaults = { | |||
|
22 | 'cache_dir': os.path.join(tempfile.gettempdir(), 'rc_cache') | |||
|
23 | } | |||
|
24 | ||||
|
25 | # GLOBAL TO STORE ALL REGISTERED REGIONS | |||
|
26 | dogpile_cache_regions = {} |
@@ -0,0 +1,136 b'' | |||||
|
1 | # RhodeCode VCSServer provides access to different vcs backends via network. | |||
|
2 | # Copyright (C) 2014-2018 RhodeCode GmbH | |||
|
3 | # | |||
|
4 | # This program is free software; you can redistribute it and/or modify | |||
|
5 | # it under the terms of the GNU General Public License as published by | |||
|
6 | # the Free Software Foundation; either version 3 of the License, or | |||
|
7 | # (at your option) any later version. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
14 | # You should have received a copy of the GNU General Public License | |||
|
15 | # along with this program; if not, write to the Free Software Foundation, | |||
|
16 | # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
|
17 | ||||
|
18 | import os | |||
|
19 | import logging | |||
|
20 | import functools | |||
|
21 | ||||
|
22 | from vcsserver.utils import safe_str, sha1 | |||
|
23 | from dogpile.cache import CacheRegion | |||
|
24 | from dogpile.cache.util import compat | |||
|
25 | ||||
|
26 | log = logging.getLogger(__name__) | |||
|
27 | ||||
|
28 | ||||
|
29 | class RhodeCodeCacheRegion(CacheRegion): | |||
|
30 | ||||
|
31 | def conditional_cache_on_arguments( | |||
|
32 | self, namespace=None, | |||
|
33 | expiration_time=None, | |||
|
34 | should_cache_fn=None, | |||
|
35 | to_str=compat.string_type, | |||
|
36 | function_key_generator=None, | |||
|
37 | condition=True): | |||
|
38 | """ | |||
|
39 | Custom conditional decorator, that will not touch any dogpile internals if | |||
|
40 | condition isn't meet. This works a bit different than should_cache_fn | |||
|
41 | And it's faster in cases we don't ever want to compute cached values | |||
|
42 | """ | |||
|
43 | expiration_time_is_callable = compat.callable(expiration_time) | |||
|
44 | ||||
|
45 | if function_key_generator is None: | |||
|
46 | function_key_generator = self.function_key_generator | |||
|
47 | ||||
|
48 | def decorator(fn): | |||
|
49 | if to_str is compat.string_type: | |||
|
50 | # backwards compatible | |||
|
51 | key_generator = function_key_generator(namespace, fn) | |||
|
52 | else: | |||
|
53 | key_generator = function_key_generator(namespace, fn, to_str=to_str) | |||
|
54 | ||||
|
55 | @functools.wraps(fn) | |||
|
56 | def decorate(*arg, **kw): | |||
|
57 | key = key_generator(*arg, **kw) | |||
|
58 | ||||
|
59 | @functools.wraps(fn) | |||
|
60 | def creator(): | |||
|
61 | return fn(*arg, **kw) | |||
|
62 | ||||
|
63 | if not condition: | |||
|
64 | return creator() | |||
|
65 | ||||
|
66 | timeout = expiration_time() if expiration_time_is_callable \ | |||
|
67 | else expiration_time | |||
|
68 | ||||
|
69 | return self.get_or_create(key, creator, timeout, should_cache_fn) | |||
|
70 | ||||
|
71 | def invalidate(*arg, **kw): | |||
|
72 | key = key_generator(*arg, **kw) | |||
|
73 | self.delete(key) | |||
|
74 | ||||
|
75 | def set_(value, *arg, **kw): | |||
|
76 | key = key_generator(*arg, **kw) | |||
|
77 | self.set(key, value) | |||
|
78 | ||||
|
79 | def get(*arg, **kw): | |||
|
80 | key = key_generator(*arg, **kw) | |||
|
81 | return self.get(key) | |||
|
82 | ||||
|
83 | def refresh(*arg, **kw): | |||
|
84 | key = key_generator(*arg, **kw) | |||
|
85 | value = fn(*arg, **kw) | |||
|
86 | self.set(key, value) | |||
|
87 | return value | |||
|
88 | ||||
|
89 | decorate.set = set_ | |||
|
90 | decorate.invalidate = invalidate | |||
|
91 | decorate.refresh = refresh | |||
|
92 | decorate.get = get | |||
|
93 | decorate.original = fn | |||
|
94 | decorate.key_generator = key_generator | |||
|
95 | ||||
|
96 | return decorate | |||
|
97 | ||||
|
98 | return decorator | |||
|
99 | ||||
|
100 | ||||
|
101 | def make_region(*arg, **kw): | |||
|
102 | return RhodeCodeCacheRegion(*arg, **kw) | |||
|
103 | ||||
|
104 | ||||
|
105 | def get_default_cache_settings(settings, prefixes=None): | |||
|
106 | prefixes = prefixes or [] | |||
|
107 | cache_settings = {} | |||
|
108 | for key in settings.keys(): | |||
|
109 | for prefix in prefixes: | |||
|
110 | if key.startswith(prefix): | |||
|
111 | name = key.split(prefix)[1].strip() | |||
|
112 | val = settings[key] | |||
|
113 | if isinstance(val, basestring): | |||
|
114 | val = val.strip() | |||
|
115 | cache_settings[name] = val | |||
|
116 | return cache_settings | |||
|
117 | ||||
|
118 | ||||
|
119 | def compute_key_from_params(*args): | |||
|
120 | """ | |||
|
121 | Helper to compute key from given params to be used in cache manager | |||
|
122 | """ | |||
|
123 | return sha1("_".join(map(safe_str, args))) | |||
|
124 | ||||
|
125 | ||||
|
126 | def key_generator(namespace, fn): | |||
|
127 | fname = fn.__name__ | |||
|
128 | ||||
|
129 | def generate_key(*args): | |||
|
130 | namespace_pref = namespace or 'default' | |||
|
131 | arg_key = compute_key_from_params(*args) | |||
|
132 | final_key = "{}:{}_{}".format(namespace_pref, fname, arg_key) | |||
|
133 | ||||
|
134 | return final_key | |||
|
135 | ||||
|
136 | return generate_key |
@@ -1,1 +1,79 b'' | |||||
1 | development_http.ini No newline at end of file |
|
1 | ################################################################################ | |
|
2 | # RhodeCode VCSServer with HTTP Backend - configuration # | |||
|
3 | # # | |||
|
4 | ################################################################################ | |||
|
5 | ||||
|
6 | ||||
|
7 | [server:main] | |||
|
8 | ## COMMON ## | |||
|
9 | host = 0.0.0.0 | |||
|
10 | port = 9900 | |||
|
11 | ||||
|
12 | use = egg:waitress#main | |||
|
13 | ||||
|
14 | ||||
|
15 | [app:main] | |||
|
16 | use = egg:rhodecode-vcsserver | |||
|
17 | ||||
|
18 | pyramid.default_locale_name = en | |||
|
19 | pyramid.includes = | |||
|
20 | ||||
|
21 | ## default locale used by VCS systems | |||
|
22 | locale = en_US.UTF-8 | |||
|
23 | ||||
|
24 | ||||
|
25 | ## path to binaries for vcsserver, it should be set by the installer | |||
|
26 | ## at installation time, e.g /home/user/vcsserver-1/profile/bin | |||
|
27 | core.binary_dir = "" | |||
|
28 | ||||
|
29 | ## cache region for storing repo_objects cache | |||
|
30 | rc_cache.repo_object.backend = dogpile.cache.rc.memory_lru | |||
|
31 | ## cache auto-expires after N seconds | |||
|
32 | rc_cache.repo_object.expiration_time = 300 | |||
|
33 | ## max size of LRU, old values will be discarded if the size of cache reaches max_size | |||
|
34 | rc_cache.repo_object.max_size = 100 | |||
|
35 | ||||
|
36 | ||||
|
37 | ################################ | |||
|
38 | ### LOGGING CONFIGURATION #### | |||
|
39 | ################################ | |||
|
40 | [loggers] | |||
|
41 | keys = root, vcsserver | |||
|
42 | ||||
|
43 | [handlers] | |||
|
44 | keys = console | |||
|
45 | ||||
|
46 | [formatters] | |||
|
47 | keys = generic | |||
|
48 | ||||
|
49 | ############# | |||
|
50 | ## LOGGERS ## | |||
|
51 | ############# | |||
|
52 | [logger_root] | |||
|
53 | level = NOTSET | |||
|
54 | handlers = console | |||
|
55 | ||||
|
56 | [logger_vcsserver] | |||
|
57 | level = DEBUG | |||
|
58 | handlers = | |||
|
59 | qualname = vcsserver | |||
|
60 | propagate = 1 | |||
|
61 | ||||
|
62 | ||||
|
63 | ############## | |||
|
64 | ## HANDLERS ## | |||
|
65 | ############## | |||
|
66 | ||||
|
67 | [handler_console] | |||
|
68 | class = StreamHandler | |||
|
69 | args = (sys.stderr,) | |||
|
70 | level = DEBUG | |||
|
71 | formatter = generic | |||
|
72 | ||||
|
73 | ################ | |||
|
74 | ## FORMATTERS ## | |||
|
75 | ################ | |||
|
76 | ||||
|
77 | [formatter_generic] | |||
|
78 | format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s | |||
|
79 | datefmt = %Y-%m-%d %H:%M:%S |
@@ -1,1 +1,100 b'' | |||||
1 | production_http.ini No newline at end of file |
|
1 | ################################################################################ | |
|
2 | # RhodeCode VCSServer with HTTP Backend - configuration # | |||
|
3 | # # | |||
|
4 | ################################################################################ | |||
|
5 | ||||
|
6 | ||||
|
7 | [server:main] | |||
|
8 | ## COMMON ## | |||
|
9 | host = 127.0.0.1 | |||
|
10 | port = 9900 | |||
|
11 | ||||
|
12 | ||||
|
13 | ########################## | |||
|
14 | ## GUNICORN WSGI SERVER ## | |||
|
15 | ########################## | |||
|
16 | ## run with gunicorn --log-config vcsserver.ini --paste vcsserver.ini | |||
|
17 | use = egg:gunicorn#main | |||
|
18 | ## Sets the number of process workers. Recommended | |||
|
19 | ## value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers | |||
|
20 | workers = 2 | |||
|
21 | ## process name | |||
|
22 | proc_name = rhodecode_vcsserver | |||
|
23 | ## type of worker class, currently `sync` is the only option allowed. | |||
|
24 | worker_class = sync | |||
|
25 | ## The maximum number of simultaneous clients. Valid only for Gevent | |||
|
26 | #worker_connections = 10 | |||
|
27 | ## max number of requests that worker will handle before being gracefully | |||
|
28 | ## restarted, could prevent memory leaks | |||
|
29 | max_requests = 1000 | |||
|
30 | max_requests_jitter = 30 | |||
|
31 | ## amount of time a worker can spend with handling a request before it | |||
|
32 | ## gets killed and restarted. Set to 6hrs | |||
|
33 | timeout = 21600 | |||
|
34 | ||||
|
35 | ||||
|
36 | [app:main] | |||
|
37 | use = egg:rhodecode-vcsserver | |||
|
38 | ||||
|
39 | pyramid.default_locale_name = en | |||
|
40 | pyramid.includes = | |||
|
41 | ||||
|
42 | ## default locale used by VCS systems | |||
|
43 | locale = en_US.UTF-8 | |||
|
44 | ||||
|
45 | ||||
|
46 | ## path to binaries for vcsserver, it should be set by the installer | |||
|
47 | ## at installation time, e.g /home/user/vcsserver-1/profile/bin | |||
|
48 | core.binary_dir = "" | |||
|
49 | ||||
|
50 | ## cache region for storing repo_objects cache | |||
|
51 | rc_cache.repo_object.backend = dogpile.cache.rc.memory_lru | |||
|
52 | ## cache auto-expires after N seconds | |||
|
53 | rc_cache.repo_object.expiration_time = 300 | |||
|
54 | ## max size of LRU, old values will be discarded if the size of cache reaches max_size | |||
|
55 | rc_cache.repo_object.max_size = 100 | |||
|
56 | ||||
|
57 | ||||
|
58 | ################################ | |||
|
59 | ### LOGGING CONFIGURATION #### | |||
|
60 | ################################ | |||
|
61 | [loggers] | |||
|
62 | keys = root, vcsserver | |||
|
63 | ||||
|
64 | [handlers] | |||
|
65 | keys = console | |||
|
66 | ||||
|
67 | [formatters] | |||
|
68 | keys = generic | |||
|
69 | ||||
|
70 | ############# | |||
|
71 | ## LOGGERS ## | |||
|
72 | ############# | |||
|
73 | [logger_root] | |||
|
74 | level = NOTSET | |||
|
75 | handlers = console | |||
|
76 | ||||
|
77 | [logger_vcsserver] | |||
|
78 | level = DEBUG | |||
|
79 | handlers = | |||
|
80 | qualname = vcsserver | |||
|
81 | propagate = 1 | |||
|
82 | ||||
|
83 | ||||
|
84 | ############## | |||
|
85 | ## HANDLERS ## | |||
|
86 | ############## | |||
|
87 | ||||
|
88 | [handler_console] | |||
|
89 | class = StreamHandler | |||
|
90 | args = (sys.stderr,) | |||
|
91 | level = DEBUG | |||
|
92 | formatter = generic | |||
|
93 | ||||
|
94 | ################ | |||
|
95 | ## FORMATTERS ## | |||
|
96 | ################ | |||
|
97 | ||||
|
98 | [formatter_generic] | |||
|
99 | format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s | |||
|
100 | datefmt = %Y-%m-%d %H:%M:%S |
@@ -15,13 +15,6 b' in' | |||||
15 |
|
15 | |||
16 | self: super: { |
|
16 | self: super: { | |
17 |
|
17 | |||
18 | "beaker" = super."beaker".override (attrs: { |
|
|||
19 | patches = [ |
|
|||
20 | ./patch_beaker/patch-beaker-lock-func-debug.diff |
|
|||
21 | ./patch_beaker/patch-beaker-metadata-reuse.diff |
|
|||
22 | ]; |
|
|||
23 | }); |
|
|||
24 |
|
||||
25 | "gevent" = super."gevent".override (attrs: { |
|
18 | "gevent" = super."gevent".override (attrs: { | |
26 | propagatedBuildInputs = attrs.propagatedBuildInputs ++ [ |
|
19 | propagatedBuildInputs = attrs.propagatedBuildInputs ++ [ | |
27 | # NOTE: (marcink) odd requirements from gevent aren't set properly, |
|
20 | # NOTE: (marcink) odd requirements from gevent aren't set properly, |
@@ -37,20 +37,6 b' self: super: {' | |||||
37 | license = [ pkgs.lib.licenses.mit ]; |
|
37 | license = [ pkgs.lib.licenses.mit ]; | |
38 | }; |
|
38 | }; | |
39 | }; |
|
39 | }; | |
40 | "beaker" = super.buildPythonPackage { |
|
|||
41 | name = "beaker-1.9.1"; |
|
|||
42 | doCheck = false; |
|
|||
43 | propagatedBuildInputs = [ |
|
|||
44 | self."funcsigs" |
|
|||
45 | ]; |
|
|||
46 | src = fetchurl { |
|
|||
47 | url = "https://files.pythonhosted.org/packages/ca/14/a626188d0d0c7b55dd7cf1902046c2743bd392a7078bb53073e13280eb1e/Beaker-1.9.1.tar.gz"; |
|
|||
48 | sha256 = "08arsn61r255lhz6hcpn2lsiqpg30clla805ysx06wmbhvb6w9rj"; |
|
|||
49 | }; |
|
|||
50 | meta = { |
|
|||
51 | license = [ pkgs.lib.licenses.bsdOriginal ]; |
|
|||
52 | }; |
|
|||
53 | }; |
|
|||
54 | "beautifulsoup4" = super.buildPythonPackage { |
|
40 | "beautifulsoup4" = super.buildPythonPackage { | |
55 | name = "beautifulsoup4-4.6.0"; |
|
41 | name = "beautifulsoup4-4.6.0"; | |
56 | doCheck = false; |
|
42 | doCheck = false; | |
@@ -112,6 +98,28 b' self: super: {' | |||||
112 | license = [ pkgs.lib.licenses.bsdOriginal { fullName = "new BSD License"; } ]; |
|
98 | license = [ pkgs.lib.licenses.bsdOriginal { fullName = "new BSD License"; } ]; | |
113 | }; |
|
99 | }; | |
114 | }; |
|
100 | }; | |
|
101 | "dogpile.cache" = super.buildPythonPackage { | |||
|
102 | name = "dogpile.cache-0.6.6"; | |||
|
103 | doCheck = false; | |||
|
104 | src = fetchurl { | |||
|
105 | url = "https://files.pythonhosted.org/packages/48/ca/604154d835c3668efb8a31bd979b0ea4bf39c2934a40ffecc0662296cb51/dogpile.cache-0.6.6.tar.gz"; | |||
|
106 | sha256 = "1h8n1lxd4l2qvahfkiinljkqz7pww7w3sgag0j8j9ixbl2h4wk84"; | |||
|
107 | }; | |||
|
108 | meta = { | |||
|
109 | license = [ pkgs.lib.licenses.bsdOriginal ]; | |||
|
110 | }; | |||
|
111 | }; | |||
|
112 | "dogpile.core" = super.buildPythonPackage { | |||
|
113 | name = "dogpile.core-0.4.1"; | |||
|
114 | doCheck = false; | |||
|
115 | src = fetchurl { | |||
|
116 | url = "https://files.pythonhosted.org/packages/0e/77/e72abc04c22aedf874301861e5c1e761231c288b5de369c18be8f4b5c9bb/dogpile.core-0.4.1.tar.gz"; | |||
|
117 | sha256 = "0xpdvg4kr1isfkrh1rfsh7za4q5a5s6l2kf9wpvndbwf3aqjyrdy"; | |||
|
118 | }; | |||
|
119 | meta = { | |||
|
120 | license = [ pkgs.lib.licenses.bsdOriginal ]; | |||
|
121 | }; | |||
|
122 | }; | |||
115 | "dulwich" = super.buildPythonPackage { |
|
123 | "dulwich" = super.buildPythonPackage { | |
116 | name = "dulwich-0.13.0"; |
|
124 | name = "dulwich-0.13.0"; | |
117 | doCheck = false; |
|
125 | doCheck = false; | |
@@ -229,21 +237,6 b' self: super: {' | |||||
229 | license = [ pkgs.lib.licenses.mit ]; |
|
237 | license = [ pkgs.lib.licenses.mit ]; | |
230 | }; |
|
238 | }; | |
231 | }; |
|
239 | }; | |
232 | "infrae.cache" = super.buildPythonPackage { |
|
|||
233 | name = "infrae.cache-1.0.1"; |
|
|||
234 | doCheck = false; |
|
|||
235 | propagatedBuildInputs = [ |
|
|||
236 | self."beaker" |
|
|||
237 | self."repoze.lru" |
|
|||
238 | ]; |
|
|||
239 | src = fetchurl { |
|
|||
240 | url = "https://files.pythonhosted.org/packages/bb/f0/e7d5e984cf6592fd2807dc7bc44a93f9d18e04e6a61f87fdfb2622422d74/infrae.cache-1.0.1.tar.gz"; |
|
|||
241 | sha256 = "1dvqsjn8vw253wz9d1pz17j79mf4bs53dvp2qxck2qdp1am1njw4"; |
|
|||
242 | }; |
|
|||
243 | meta = { |
|
|||
244 | license = [ pkgs.lib.licenses.zpl21 ]; |
|
|||
245 | }; |
|
|||
246 | }; |
|
|||
247 | "ipdb" = super.buildPythonPackage { |
|
240 | "ipdb" = super.buildPythonPackage { | |
248 | name = "ipdb-0.11"; |
|
241 | name = "ipdb-0.11"; | |
249 | doCheck = false; |
|
242 | doCheck = false; | |
@@ -294,6 +287,17 b' self: super: {' | |||||
294 | license = [ pkgs.lib.licenses.bsdOriginal ]; |
|
287 | license = [ pkgs.lib.licenses.bsdOriginal ]; | |
295 | }; |
|
288 | }; | |
296 | }; |
|
289 | }; | |
|
290 | "lru-dict" = super.buildPythonPackage { | |||
|
291 | name = "lru-dict-1.1.6"; | |||
|
292 | doCheck = false; | |||
|
293 | src = fetchurl { | |||
|
294 | url = "https://files.pythonhosted.org/packages/00/a5/32ed6e10246cd341ca8cc205acea5d208e4053f48a4dced2b1b31d45ba3f/lru-dict-1.1.6.tar.gz"; | |||
|
295 | sha256 = "1k2lhd4dpl6xa6iialbwx4l6bkdzxmzhygms39pvf19x1rk5fm1n"; | |||
|
296 | }; | |||
|
297 | meta = { | |||
|
298 | license = [ pkgs.lib.licenses.mit ]; | |||
|
299 | }; | |||
|
300 | }; | |||
297 | "mako" = super.buildPythonPackage { |
|
301 | "mako" = super.buildPythonPackage { | |
298 | name = "mako-1.0.7"; |
|
302 | name = "mako-1.0.7"; | |
299 | doCheck = false; |
|
303 | doCheck = false; | |
@@ -680,13 +684,14 b' self: super: {' | |||||
680 | ]; |
|
684 | ]; | |
681 | doCheck = true; |
|
685 | doCheck = true; | |
682 | propagatedBuildInputs = [ |
|
686 | propagatedBuildInputs = [ | |
683 | self."beaker" |
|
|||
684 | self."configobj" |
|
687 | self."configobj" | |
|
688 | self."dogpile.cache" | |||
|
689 | self."dogpile.core" | |||
685 | self."decorator" |
|
690 | self."decorator" | |
686 | self."dulwich" |
|
691 | self."dulwich" | |
687 | self."hgsubversion" |
|
692 | self."hgsubversion" | |
688 | self."hg-evolve" |
|
693 | self."hg-evolve" | |
689 |
self."i |
|
694 | self."lru-dict" | |
690 | self."mako" |
|
695 | self."mako" | |
691 | self."markupsafe" |
|
696 | self."markupsafe" | |
692 | self."mercurial" |
|
697 | self."mercurial" |
@@ -1,12 +1,13 b'' | |||||
1 | ## dependencies |
|
1 | ## dependencies | |
2 |
|
2 | |||
3 | beaker==1.9.1 |
|
|||
4 | configobj==5.0.6 |
|
3 | configobj==5.0.6 | |
|
4 | dogpile.cache==0.6.6 | |||
|
5 | dogpile.core==0.4.1 | |||
5 | decorator==4.1.2 |
|
6 | decorator==4.1.2 | |
6 | dulwich==0.13.0 |
|
7 | dulwich==0.13.0 | |
7 | hgsubversion==1.9.2 |
|
8 | hgsubversion==1.9.2 | |
8 | hg-evolve==8.0.1 |
|
9 | hg-evolve==8.0.1 | |
9 | infrae.cache==1.0.1 |
|
10 | lru-dict==1.1.6 | |
10 | mako==1.0.7 |
|
11 | mako==1.0.7 | |
11 | markupsafe==1.0.0 |
|
12 | markupsafe==1.0.0 | |
12 | mercurial==4.6.1 |
|
13 | mercurial==4.6.1 |
@@ -20,6 +20,7 b' import traceback' | |||||
20 | import logging |
|
20 | import logging | |
21 | import urlparse |
|
21 | import urlparse | |
22 |
|
22 | |||
|
23 | from vcsserver.lib.rc_cache import region_meta | |||
23 | log = logging.getLogger(__name__) |
|
24 | log = logging.getLogger(__name__) | |
24 |
|
25 | |||
25 |
|
26 | |||
@@ -30,9 +31,10 b' class RepoFactory(object):' | |||||
30 | It provides internal caching of the `repo` object based on |
|
31 | It provides internal caching of the `repo` object based on | |
31 | the :term:`call context`. |
|
32 | the :term:`call context`. | |
32 | """ |
|
33 | """ | |
|
34 | repo_type = None | |||
33 |
|
35 | |||
34 |
def __init__(self |
|
36 | def __init__(self): | |
35 | self._cache = repo_cache |
|
37 | self._cache_region = region_meta.dogpile_cache_regions['repo_object'] | |
36 |
|
38 | |||
37 | def _create_config(self, path, config): |
|
39 | def _create_config(self, path, config): | |
38 | config = {} |
|
40 | config = {} | |
@@ -48,26 +50,19 b' class RepoFactory(object):' | |||||
48 | Uses internally the low level beaker API since the decorators introduce |
|
50 | Uses internally the low level beaker API since the decorators introduce | |
49 | significant overhead. |
|
51 | significant overhead. | |
50 | """ |
|
52 | """ | |
51 | def create_new_repo(): |
|
53 | region = self._cache_region | |
|
54 | context = wire.get('context', None) | |||
|
55 | repo_path = wire.get('path', '') | |||
|
56 | context_uid = '{}'.format(context) | |||
|
57 | cache = wire.get('cache', True) | |||
|
58 | cache_on = context and cache | |||
|
59 | ||||
|
60 | @region.conditional_cache_on_arguments(condition=cache_on) | |||
|
61 | def create_new_repo(_repo_type, _repo_path, _context_uid): | |||
52 | return self._create_repo(wire, create) |
|
62 | return self._create_repo(wire, create) | |
53 |
|
63 | |||
54 | return self._repo(wire, create_new_repo) |
|
64 | repo = create_new_repo(self.repo_type, repo_path, context_uid) | |
55 |
|
65 | return repo | ||
56 | def _repo(self, wire, createfunc): |
|
|||
57 | context = wire.get('context', None) |
|
|||
58 | cache = wire.get('cache', True) |
|
|||
59 |
|
||||
60 | if context and cache: |
|
|||
61 | cache_key = (context, wire['path']) |
|
|||
62 | log.debug( |
|
|||
63 | 'FETCH %s@%s repo object from cache. Context: %s', |
|
|||
64 | self.__class__.__name__, wire['path'], context) |
|
|||
65 | return self._cache.get(key=cache_key, createfunc=createfunc) |
|
|||
66 | else: |
|
|||
67 | log.debug( |
|
|||
68 | 'INIT %s@%s repo object based on wire %s. Context: %s', |
|
|||
69 | self.__class__.__name__, wire['path'], wire, context) |
|
|||
70 | return createfunc() |
|
|||
71 |
|
66 | |||
72 |
|
67 | |||
73 | def obfuscate_qs(query_string): |
|
68 | def obfuscate_qs(query_string): |
@@ -87,6 +87,7 b' class Repo(DulwichRepo):' | |||||
87 |
|
87 | |||
88 |
|
88 | |||
89 | class GitFactory(RepoFactory): |
|
89 | class GitFactory(RepoFactory): | |
|
90 | repo_type = 'git' | |||
90 |
|
91 | |||
91 | def _create_repo(self, wire, create): |
|
92 | def _create_repo(self, wire, create): | |
92 | repo_path = str_to_dulwich(wire['path']) |
|
93 | repo_path = str_to_dulwich(wire['path']) |
@@ -93,6 +93,7 b' def reraise_safe_exceptions(func):' | |||||
93 |
|
93 | |||
94 |
|
94 | |||
95 | class MercurialFactory(RepoFactory): |
|
95 | class MercurialFactory(RepoFactory): | |
|
96 | repo_type = 'hg' | |||
96 |
|
97 | |||
97 | def _create_config(self, config, hooks=True): |
|
98 | def _create_config(self, config, hooks=True): | |
98 | if not hooks: |
|
99 | if not hooks: |
@@ -26,9 +26,8 b' from itertools import chain' | |||||
26 |
|
26 | |||
27 | import simplejson as json |
|
27 | import simplejson as json | |
28 | import msgpack |
|
28 | import msgpack | |
29 | from beaker.cache import CacheManager |
|
|||
30 | from beaker.util import parse_cache_config_options |
|
|||
31 | from pyramid.config import Configurator |
|
29 | from pyramid.config import Configurator | |
|
30 | from pyramid.settings import asbool, aslist | |||
32 | from pyramid.wsgi import wsgiapp |
|
31 | from pyramid.wsgi import wsgiapp | |
33 | from pyramid.compat import configparser |
|
32 | from pyramid.compat import configparser | |
34 |
|
33 | |||
@@ -65,48 +64,60 b' def _is_request_chunked(environ):' | |||||
65 | return stream |
|
64 | return stream | |
66 |
|
65 | |||
67 |
|
66 | |||
|
67 | def _int_setting(settings, name, default): | |||
|
68 | settings[name] = int(settings.get(name, default)) | |||
|
69 | ||||
|
70 | ||||
|
71 | def _bool_setting(settings, name, default): | |||
|
72 | input_val = settings.get(name, default) | |||
|
73 | if isinstance(input_val, unicode): | |||
|
74 | input_val = input_val.encode('utf8') | |||
|
75 | settings[name] = asbool(input_val) | |||
|
76 | ||||
|
77 | ||||
|
78 | def _list_setting(settings, name, default): | |||
|
79 | raw_value = settings.get(name, default) | |||
|
80 | ||||
|
81 | # Otherwise we assume it uses pyramids space/newline separation. | |||
|
82 | settings[name] = aslist(raw_value) | |||
|
83 | ||||
|
84 | ||||
|
85 | def _string_setting(settings, name, default, lower=True): | |||
|
86 | value = settings.get(name, default) | |||
|
87 | if lower: | |||
|
88 | value = value.lower() | |||
|
89 | settings[name] = value | |||
|
90 | ||||
|
91 | ||||
68 | class VCS(object): |
|
92 | class VCS(object): | |
69 | def __init__(self, locale=None, cache_config=None): |
|
93 | def __init__(self, locale=None, cache_config=None): | |
70 | self.locale = locale |
|
94 | self.locale = locale | |
71 | self.cache_config = cache_config |
|
95 | self.cache_config = cache_config | |
72 | self._configure_locale() |
|
96 | self._configure_locale() | |
73 | self._initialize_cache() |
|
|||
74 |
|
97 | |||
75 | if GitFactory and GitRemote: |
|
98 | if GitFactory and GitRemote: | |
76 | git_repo_cache = self.cache.get_cache_region( |
|
99 | git_factory = GitFactory() | |
77 | 'git', region='repo_object') |
|
|||
78 | git_factory = GitFactory(git_repo_cache) |
|
|||
79 | self._git_remote = GitRemote(git_factory) |
|
100 | self._git_remote = GitRemote(git_factory) | |
80 | else: |
|
101 | else: | |
81 | log.info("Git client import failed") |
|
102 | log.info("Git client import failed") | |
82 |
|
103 | |||
83 | if MercurialFactory and HgRemote: |
|
104 | if MercurialFactory and HgRemote: | |
84 | hg_repo_cache = self.cache.get_cache_region( |
|
105 | hg_factory = MercurialFactory() | |
85 | 'hg', region='repo_object') |
|
|||
86 | hg_factory = MercurialFactory(hg_repo_cache) |
|
|||
87 | self._hg_remote = HgRemote(hg_factory) |
|
106 | self._hg_remote = HgRemote(hg_factory) | |
88 | else: |
|
107 | else: | |
89 | log.info("Mercurial client import failed") |
|
108 | log.info("Mercurial client import failed") | |
90 |
|
109 | |||
91 | if SubversionFactory and SvnRemote: |
|
110 | if SubversionFactory and SvnRemote: | |
92 | svn_repo_cache = self.cache.get_cache_region( |
|
111 | svn_factory = SubversionFactory() | |
93 | 'svn', region='repo_object') |
|
112 | ||
94 | svn_factory = SubversionFactory(svn_repo_cache) |
|
|||
95 | # hg factory is used for svn url validation |
|
113 | # hg factory is used for svn url validation | |
96 | hg_repo_cache = self.cache.get_cache_region( |
|
114 | hg_factory = MercurialFactory() | |
97 | 'hg', region='repo_object') |
|
|||
98 | hg_factory = MercurialFactory(hg_repo_cache) |
|
|||
99 | self._svn_remote = SvnRemote(svn_factory, hg_factory=hg_factory) |
|
115 | self._svn_remote = SvnRemote(svn_factory, hg_factory=hg_factory) | |
100 | else: |
|
116 | else: | |
101 | log.info("Subversion client import failed") |
|
117 | log.info("Subversion client import failed") | |
102 |
|
118 | |||
103 | self._vcsserver = VcsServer() |
|
119 | self._vcsserver = VcsServer() | |
104 |
|
120 | |||
105 | def _initialize_cache(self): |
|
|||
106 | cache_config = parse_cache_config_options(self.cache_config) |
|
|||
107 | log.info('Initializing beaker cache: %s' % cache_config) |
|
|||
108 | self.cache = CacheManager(**cache_config) |
|
|||
109 |
|
||||
110 | def _configure_locale(self): |
|
121 | def _configure_locale(self): | |
111 | if self.locale: |
|
122 | if self.locale: | |
112 | log.info('Settings locale: `LC_ALL` to %s' % self.locale) |
|
123 | log.info('Settings locale: `LC_ALL` to %s' % self.locale) | |
@@ -169,8 +180,11 b' class HTTPApplication(object):' | |||||
169 | _use_echo_app = False |
|
180 | _use_echo_app = False | |
170 |
|
181 | |||
171 | def __init__(self, settings=None, global_config=None): |
|
182 | def __init__(self, settings=None, global_config=None): | |
|
183 | self._sanitize_settings_and_apply_defaults(settings) | |||
|
184 | ||||
172 | self.config = Configurator(settings=settings) |
|
185 | self.config = Configurator(settings=settings) | |
173 | self.global_config = global_config |
|
186 | self.global_config = global_config | |
|
187 | self.config.include('vcsserver.lib.rc_cache') | |||
174 |
|
188 | |||
175 | locale = settings.get('locale', '') or 'en_US.UTF-8' |
|
189 | locale = settings.get('locale', '') or 'en_US.UTF-8' | |
176 | vcs = VCS(locale=locale, cache_config=settings) |
|
190 | vcs = VCS(locale=locale, cache_config=settings) | |
@@ -198,6 +212,21 b' class HTTPApplication(object):' | |||||
198 | if binary_dir: |
|
212 | if binary_dir: | |
199 | settings.BINARY_DIR = binary_dir |
|
213 | settings.BINARY_DIR = binary_dir | |
200 |
|
214 | |||
|
215 | def _sanitize_settings_and_apply_defaults(self, settings): | |||
|
216 | # repo_object cache | |||
|
217 | _string_setting( | |||
|
218 | settings, | |||
|
219 | 'rc_cache.repo_object.backend', | |||
|
220 | 'dogpile.cache.rc.memory_lru') | |||
|
221 | _int_setting( | |||
|
222 | settings, | |||
|
223 | 'rc_cache.repo_object.expiration_time', | |||
|
224 | 300) | |||
|
225 | _int_setting( | |||
|
226 | settings, | |||
|
227 | 'rc_cache.repo_object.max_size', | |||
|
228 | 1024) | |||
|
229 | ||||
201 | def _configure(self): |
|
230 | def _configure(self): | |
202 | self.config.add_renderer( |
|
231 | self.config.add_renderer( | |
203 | name='msgpack', |
|
232 | name='msgpack', | |
@@ -246,14 +275,17 b' class HTTPApplication(object):' | |||||
246 | wire = params.get('wire') |
|
275 | wire = params.get('wire') | |
247 | args = params.get('args') |
|
276 | args = params.get('args') | |
248 | kwargs = params.get('kwargs') |
|
277 | kwargs = params.get('kwargs') | |
|
278 | context_uid = None | |||
|
279 | ||||
249 | if wire: |
|
280 | if wire: | |
250 | try: |
|
281 | try: | |
251 | wire['context'] = uuid.UUID(wire['context']) |
|
282 | wire['context'] = context_uid = uuid.UUID(wire['context']) | |
252 | except KeyError: |
|
283 | except KeyError: | |
253 | pass |
|
284 | pass | |
254 | args.insert(0, wire) |
|
285 | args.insert(0, wire) | |
255 |
|
286 | |||
256 |
log.debug('method called:%s with kwargs:%s', |
|
287 | log.debug('method called:%s with kwargs:%s context_uid: %s', | |
|
288 | method, kwargs, context_uid) | |||
257 | try: |
|
289 | try: | |
258 | resp = getattr(remote, method)(*args, **kwargs) |
|
290 | resp = getattr(remote, method)(*args, **kwargs) | |
259 | except Exception as e: |
|
291 | except Exception as e: | |
@@ -272,7 +304,7 b' class HTTPApplication(object):' | |||||
272 | } |
|
304 | } | |
273 | } |
|
305 | } | |
274 | try: |
|
306 | try: | |
275 |
resp['error']['_vcs_kind'] = e |
|
307 | resp['error']['_vcs_kind'] = getattr(e, '_vcs_kind', None) | |
276 | except AttributeError: |
|
308 | except AttributeError: | |
277 | pass |
|
309 | pass | |
278 | else: |
|
310 | else: | |
@@ -486,5 +518,6 b' def main(global_config, **settings):' | |||||
486 | if MercurialFactory: |
|
518 | if MercurialFactory: | |
487 | hgpatches.patch_largefiles_capabilities() |
|
519 | hgpatches.patch_largefiles_capabilities() | |
488 | hgpatches.patch_subrepo_type_mapping() |
|
520 | hgpatches.patch_subrepo_type_mapping() | |
|
521 | ||||
489 | app = HTTPApplication(settings=settings, global_config=global_config) |
|
522 | app = HTTPApplication(settings=settings, global_config=global_config) | |
490 | return app.wsgi_app() |
|
523 | return app.wsgi_app() |
@@ -40,13 +40,13 b' log = logging.getLogger(__name__)' | |||||
40 |
|
40 | |||
41 | # Set of svn compatible version flags. |
|
41 | # Set of svn compatible version flags. | |
42 | # Compare with subversion/svnadmin/svnadmin.c |
|
42 | # Compare with subversion/svnadmin/svnadmin.c | |
43 |
svn_compatible_versions = |
|
43 | svn_compatible_versions = { | |
44 | 'pre-1.4-compatible', |
|
44 | 'pre-1.4-compatible', | |
45 | 'pre-1.5-compatible', |
|
45 | 'pre-1.5-compatible', | |
46 | 'pre-1.6-compatible', |
|
46 | 'pre-1.6-compatible', | |
47 | 'pre-1.8-compatible', |
|
47 | 'pre-1.8-compatible', | |
48 |
'pre-1.9-compatible' |
|
48 | 'pre-1.9-compatible' | |
49 | ]) |
|
49 | } | |
50 |
|
50 | |||
51 | svn_compatible_versions_map = { |
|
51 | svn_compatible_versions_map = { | |
52 | 'pre-1.4-compatible': '1.3', |
|
52 | 'pre-1.4-compatible': '1.3', | |
@@ -71,6 +71,7 b' def reraise_safe_exceptions(func):' | |||||
71 |
|
71 | |||
72 |
|
72 | |||
73 | class SubversionFactory(RepoFactory): |
|
73 | class SubversionFactory(RepoFactory): | |
|
74 | repo_type = 'svn' | |||
74 |
|
75 | |||
75 | def _create_repo(self, wire, create, compatible_version): |
|
76 | def _create_repo(self, wire, create, compatible_version): | |
76 | path = svn.core.svn_path_canonicalize(wire['path']) |
|
77 | path = svn.core.svn_path_canonicalize(wire['path']) | |
@@ -92,10 +93,25 b' class SubversionFactory(RepoFactory):' | |||||
92 | return repo |
|
93 | return repo | |
93 |
|
94 | |||
94 | def repo(self, wire, create=False, compatible_version=None): |
|
95 | def repo(self, wire, create=False, compatible_version=None): | |
95 | def create_new_repo(): |
|
96 | """ | |
|
97 | Get a repository instance for the given path. | |||
|
98 | ||||
|
99 | Uses internally the low level beaker API since the decorators introduce | |||
|
100 | significant overhead. | |||
|
101 | """ | |||
|
102 | region = self._cache_region | |||
|
103 | context = wire.get('context', None) | |||
|
104 | repo_path = wire.get('path', '') | |||
|
105 | context_uid = '{}'.format(context) | |||
|
106 | cache = wire.get('cache', True) | |||
|
107 | cache_on = context and cache | |||
|
108 | ||||
|
109 | @region.conditional_cache_on_arguments(condition=cache_on) | |||
|
110 | def create_new_repo(_repo_type, _repo_path, _context_uid, compatible_version_id): | |||
96 | return self._create_repo(wire, create, compatible_version) |
|
111 | return self._create_repo(wire, create, compatible_version) | |
97 |
|
112 | |||
98 | return self._repo(wire, create_new_repo) |
|
113 | return create_new_repo(self.repo_type, repo_path, context_uid, | |
|
114 | compatible_version) | |||
99 |
|
115 | |||
100 |
|
116 | |||
101 | NODE_TYPE_MAPPING = { |
|
117 | NODE_TYPE_MAPPING = { |
@@ -40,7 +40,7 b' def repeat(request):' | |||||
40 | @pytest.fixture(scope='session') |
|
40 | @pytest.fixture(scope='session') | |
41 | def vcsserver_port(request): |
|
41 | def vcsserver_port(request): | |
42 | port = get_available_port() |
|
42 | port = get_available_port() | |
43 |
print |
|
43 | print('Using vcsserver port %s' % (port, )) | |
44 | return port |
|
44 | return port | |
45 |
|
45 | |||
46 |
|
46 | |||
@@ -55,4 +55,3 b' def get_available_port():' | |||||
55 | mysocket.close() |
|
55 | mysocket.close() | |
56 | del mysocket |
|
56 | del mysocket | |
57 | return port |
|
57 | return port | |
58 |
|
@@ -152,11 +152,14 b' class TestDulwichRepoWrapper(object):' | |||||
152 |
|
152 | |||
153 | class TestGitFactory(object): |
|
153 | class TestGitFactory(object): | |
154 | def test_create_repo_returns_dulwich_wrapper(self): |
|
154 | def test_create_repo_returns_dulwich_wrapper(self): | |
155 | factory = git.GitFactory(repo_cache=Mock()) |
|
155 | ||
156 | wire = { |
|
156 | with patch('vcsserver.lib.rc_cache.region_meta.dogpile_cache_regions') as mock: | |
157 | 'path': '/tmp/abcde' |
|
157 | mock.side_effect = {'repo_objects': ''} | |
158 | } |
|
158 | factory = git.GitFactory() | |
159 | isdir_patcher = patch('dulwich.repo.os.path.isdir', return_value=True) |
|
159 | wire = { | |
160 | with isdir_patcher: |
|
160 | 'path': '/tmp/abcde' | |
161 | result = factory._create_repo(wire, True) |
|
161 | } | |
162 | assert isinstance(result, git.Repo) |
|
162 | isdir_patcher = patch('dulwich.repo.os.path.isdir', return_value=True) | |
|
163 | with isdir_patcher: | |||
|
164 | result = factory._create_repo(wire, True) | |||
|
165 | assert isinstance(result, git.Repo) |
@@ -12,11 +12,6 b' from vcsserver.http_main import main' | |||||
12 | def vcs_app(): |
|
12 | def vcs_app(): | |
13 | stub_settings = { |
|
13 | stub_settings = { | |
14 | 'dev.use_echo_app': 'true', |
|
14 | 'dev.use_echo_app': 'true', | |
15 | 'beaker.cache.regions': 'repo_object', |
|
|||
16 | 'beaker.cache.repo_object.type': 'memorylru', |
|
|||
17 | 'beaker.cache.repo_object.max_items': '100', |
|
|||
18 | 'beaker.cache.repo_object.expire': '300', |
|
|||
19 | 'beaker.cache.repo_object.enabled': 'true', |
|
|||
20 | 'locale': 'en_US.UTF-8', |
|
15 | 'locale': 'en_US.UTF-8', | |
21 | } |
|
16 | } | |
22 | vcs_app = main({}, **stub_settings) |
|
17 | vcs_app = main({}, **stub_settings) |
@@ -15,6 +15,7 b'' | |||||
15 | # along with this program; if not, write to the Free Software Foundation, |
|
15 | # along with this program; if not, write to the Free Software Foundation, | |
16 | # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
16 | # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
17 | import logging |
|
17 | import logging | |
|
18 | import hashlib | |||
18 |
|
19 | |||
19 | log = logging.getLogger(__name__) |
|
20 | log = logging.getLogger(__name__) | |
20 |
|
21 | |||
@@ -80,3 +81,9 b' class AttributeDict(dict):' | |||||
80 | return self.get(attr, None) |
|
81 | return self.get(attr, None) | |
81 | __setattr__ = dict.__setitem__ |
|
82 | __setattr__ = dict.__setitem__ | |
82 | __delattr__ = dict.__delitem__ |
|
83 | __delattr__ = dict.__delitem__ | |
|
84 | ||||
|
85 | ||||
|
86 | def sha1(val): | |||
|
87 | return hashlib.sha1(val).hexdigest() | |||
|
88 | ||||
|
89 |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now