Show More
@@ -0,0 +1,20 b'' | |||||
|
1 | diff -rup Beaker-1.9.1-orig/beaker/container.py Beaker-1.9.1/beaker/container.py | |||
|
2 | --- Beaker-1.9.1-orig/beaker/container.py 2018-04-10 10:23:04.000000000 +0200 | |||
|
3 | +++ Beaker-1.9.1/beaker/container.py 2018-04-10 10:23:34.000000000 +0200 | |||
|
4 | @@ -353,13 +353,13 @@ class Value(object): | |||
|
5 | debug("get_value returning old value while new one is created") | |||
|
6 | return value | |||
|
7 | else: | |||
|
8 | - debug("lock_creatfunc (didnt wait)") | |||
|
9 | + debug("lock_creatfunc `%s` (didnt wait)", self.createfunc.__name__) | |||
|
10 | has_createlock = True | |||
|
11 | ||||
|
12 | if not has_createlock: | |||
|
13 | - debug("lock_createfunc (waiting)") | |||
|
14 | + debug("lock_createfunc `%s` (waiting)", self.createfunc.__name__) | |||
|
15 | creation_lock.acquire() | |||
|
16 | - debug("lock_createfunc (waited)") | |||
|
17 | + debug("lock_createfunc `%s` (waited)", self.createfunc.__name__) | |||
|
18 | ||||
|
19 | try: | |||
|
20 | # see if someone created the value already |
@@ -0,0 +1,154 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | ||||
|
3 | # RhodeCode VCSServer provides access to different vcs backends via network. | |||
|
4 | # Copyright (C) 2014-2018 RhodeCode GmbH | |||
|
5 | # | |||
|
6 | # This program is free software; you can redistribute it and/or modify | |||
|
7 | # it under the terms of the GNU General Public License as published by | |||
|
8 | # the Free Software Foundation; either version 3 of the License, or | |||
|
9 | # (at your option) any later version. | |||
|
10 | # | |||
|
11 | # This program is distributed in the hope that it will be useful, | |||
|
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
14 | # GNU General Public License for more details. | |||
|
15 | # | |||
|
16 | # You should have received a copy of the GNU General Public License | |||
|
17 | # along with this program; if not, write to the Free Software Foundation, | |||
|
18 | # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
|
19 | ||||
|
20 | import re | |||
|
21 | import os | |||
|
22 | import sys | |||
|
23 | import datetime | |||
|
24 | import logging | |||
|
25 | import pkg_resources | |||
|
26 | ||||
|
27 | import vcsserver | |||
|
28 | ||||
|
29 | log = logging.getLogger(__name__) | |||
|
30 | ||||
|
31 | ||||
|
32 | def install_git_hooks(repo_path, bare, executable=None, force_create=False): | |||
|
33 | """ | |||
|
34 | Creates a RhodeCode hook inside a git repository | |||
|
35 | ||||
|
36 | :param repo_path: path to repository | |||
|
37 | :param executable: binary executable to put in the hooks | |||
|
38 | :param force_create: Create even if same name hook exists | |||
|
39 | """ | |||
|
40 | executable = executable or sys.executable | |||
|
41 | hooks_path = os.path.join(repo_path, 'hooks') | |||
|
42 | if not bare: | |||
|
43 | hooks_path = os.path.join(repo_path, '.git', 'hooks') | |||
|
44 | if not os.path.isdir(hooks_path): | |||
|
45 | os.makedirs(hooks_path, mode=0777) | |||
|
46 | ||||
|
47 | tmpl_post = pkg_resources.resource_string( | |||
|
48 | 'vcsserver', '/'.join( | |||
|
49 | ('hook_utils', 'hook_templates', 'git_post_receive.py.tmpl'))) | |||
|
50 | tmpl_pre = pkg_resources.resource_string( | |||
|
51 | 'vcsserver', '/'.join( | |||
|
52 | ('hook_utils', 'hook_templates', 'git_pre_receive.py.tmpl'))) | |||
|
53 | ||||
|
54 | path = '' # not used for now | |||
|
55 | timestamp = datetime.datetime.utcnow().isoformat() | |||
|
56 | ||||
|
57 | for h_type, template in [('pre', tmpl_pre), ('post', tmpl_post)]: | |||
|
58 | log.debug('Installing git hook in repo %s', repo_path) | |||
|
59 | _hook_file = os.path.join(hooks_path, '%s-receive' % h_type) | |||
|
60 | _rhodecode_hook = check_rhodecode_hook(_hook_file) | |||
|
61 | ||||
|
62 | if _rhodecode_hook or force_create: | |||
|
63 | log.debug('writing git %s hook file at %s !', h_type, _hook_file) | |||
|
64 | try: | |||
|
65 | with open(_hook_file, 'wb') as f: | |||
|
66 | template = template.replace( | |||
|
67 | '_TMPL_', vcsserver.__version__) | |||
|
68 | template = template.replace('_DATE_', timestamp) | |||
|
69 | template = template.replace('_ENV_', executable) | |||
|
70 | template = template.replace('_PATH_', path) | |||
|
71 | f.write(template) | |||
|
72 | os.chmod(_hook_file, 0755) | |||
|
73 | except IOError: | |||
|
74 | log.exception('error writing hook file %s', _hook_file) | |||
|
75 | else: | |||
|
76 | log.debug('skipping writing hook file') | |||
|
77 | ||||
|
78 | return True | |||
|
79 | ||||
|
80 | ||||
|
81 | def install_svn_hooks(repo_path, executable=None, force_create=False): | |||
|
82 | """ | |||
|
83 | Creates RhodeCode hooks inside a svn repository | |||
|
84 | ||||
|
85 | :param repo_path: path to repository | |||
|
86 | :param executable: binary executable to put in the hooks | |||
|
87 | :param force_create: Create even if same name hook exists | |||
|
88 | """ | |||
|
89 | executable = executable or sys.executable | |||
|
90 | hooks_path = os.path.join(repo_path, 'hooks') | |||
|
91 | if not os.path.isdir(hooks_path): | |||
|
92 | os.makedirs(hooks_path, mode=0777) | |||
|
93 | ||||
|
94 | tmpl_post = pkg_resources.resource_string( | |||
|
95 | 'vcsserver', '/'.join( | |||
|
96 | ('hook_utils', 'hook_templates', 'svn_post_commit_hook.py.tmpl'))) | |||
|
97 | tmpl_pre = pkg_resources.resource_string( | |||
|
98 | 'vcsserver', '/'.join( | |||
|
99 | ('hook_utils', 'hook_templates', 'svn_pre_commit_hook.py.tmpl'))) | |||
|
100 | ||||
|
101 | path = '' # not used for now | |||
|
102 | timestamp = datetime.datetime.utcnow().isoformat() | |||
|
103 | ||||
|
104 | for h_type, template in [('pre', tmpl_pre), ('post', tmpl_post)]: | |||
|
105 | log.debug('Installing svn hook in repo %s', repo_path) | |||
|
106 | _hook_file = os.path.join(hooks_path, '%s-commit' % h_type) | |||
|
107 | _rhodecode_hook = check_rhodecode_hook(_hook_file) | |||
|
108 | ||||
|
109 | if _rhodecode_hook or force_create: | |||
|
110 | log.debug('writing svn %s hook file at %s !', h_type, _hook_file) | |||
|
111 | ||||
|
112 | try: | |||
|
113 | with open(_hook_file, 'wb') as f: | |||
|
114 | template = template.replace( | |||
|
115 | '_TMPL_', vcsserver.__version__) | |||
|
116 | template = template.replace('_DATE_', timestamp) | |||
|
117 | template = template.replace('_ENV_', executable) | |||
|
118 | template = template.replace('_PATH_', path) | |||
|
119 | ||||
|
120 | f.write(template) | |||
|
121 | os.chmod(_hook_file, 0755) | |||
|
122 | except IOError: | |||
|
123 | log.exception('error writing hook file %s', _hook_file) | |||
|
124 | else: | |||
|
125 | log.debug('skipping writing hook file') | |||
|
126 | ||||
|
127 | return True | |||
|
128 | ||||
|
129 | ||||
|
130 | def check_rhodecode_hook(hook_path): | |||
|
131 | """ | |||
|
132 | Check if the hook was created by RhodeCode | |||
|
133 | """ | |||
|
134 | if not os.path.exists(hook_path): | |||
|
135 | return True | |||
|
136 | ||||
|
137 | log.debug('hook exists, checking if it is from rhodecode') | |||
|
138 | hook_content = read_hook_content(hook_path) | |||
|
139 | matches = re.search(r'(?:RC_HOOK_VER)\s*=\s*(.*)', hook_content) | |||
|
140 | if matches: | |||
|
141 | try: | |||
|
142 | version = matches.groups()[0] | |||
|
143 | log.debug('got version %s from hooks.', version) | |||
|
144 | return True | |||
|
145 | except Exception: | |||
|
146 | log.exception("Exception while reading the hook version.") | |||
|
147 | ||||
|
148 | return False | |||
|
149 | ||||
|
150 | ||||
|
151 | def read_hook_content(hook_path): | |||
|
152 | with open(hook_path, 'rb') as f: | |||
|
153 | content = f.read() | |||
|
154 | return content |
@@ -0,0 +1,51 b'' | |||||
|
1 | #!_ENV_ | |||
|
2 | import os | |||
|
3 | import sys | |||
|
4 | path_adjust = [_PATH_] | |||
|
5 | ||||
|
6 | if path_adjust: | |||
|
7 | sys.path = path_adjust | |||
|
8 | ||||
|
9 | try: | |||
|
10 | from vcsserver import hooks | |||
|
11 | except ImportError: | |||
|
12 | if os.environ.get('RC_DEBUG_GIT_HOOK'): | |||
|
13 | import traceback | |||
|
14 | print traceback.format_exc() | |||
|
15 | hooks = None | |||
|
16 | ||||
|
17 | ||||
|
18 | # TIMESTAMP: _DATE_ | |||
|
19 | RC_HOOK_VER = '_TMPL_' | |||
|
20 | ||||
|
21 | ||||
|
22 | def main(): | |||
|
23 | if hooks is None: | |||
|
24 | # exit with success if we cannot import vcsserver.hooks !! | |||
|
25 | # this allows simply push to this repo even without rhodecode | |||
|
26 | sys.exit(0) | |||
|
27 | ||||
|
28 | if os.environ.get('RC_SKIP_HOOKS'): | |||
|
29 | sys.exit(0) | |||
|
30 | ||||
|
31 | repo_path = os.getcwd() | |||
|
32 | push_data = sys.stdin.readlines() | |||
|
33 | os.environ['RC_HOOK_VER'] = RC_HOOK_VER | |||
|
34 | # os.environ is modified here by a subprocess call that | |||
|
35 | # runs git and later git executes this hook. | |||
|
36 | # Environ gets some additional info from rhodecode system | |||
|
37 | # like IP or username from basic-auth | |||
|
38 | try: | |||
|
39 | result = hooks.git_post_receive(repo_path, push_data, os.environ) | |||
|
40 | sys.exit(result) | |||
|
41 | except Exception as error: | |||
|
42 | # TODO: johbo: Improve handling of this special case | |||
|
43 | if not getattr(error, '_vcs_kind', None) == 'repo_locked': | |||
|
44 | raise | |||
|
45 | print 'ERROR:', error | |||
|
46 | sys.exit(1) | |||
|
47 | sys.exit(0) | |||
|
48 | ||||
|
49 | ||||
|
50 | if __name__ == '__main__': | |||
|
51 | main() |
@@ -0,0 +1,51 b'' | |||||
|
1 | #!_ENV_ | |||
|
2 | import os | |||
|
3 | import sys | |||
|
4 | path_adjust = [_PATH_] | |||
|
5 | ||||
|
6 | if path_adjust: | |||
|
7 | sys.path = path_adjust | |||
|
8 | ||||
|
9 | try: | |||
|
10 | from vcsserver import hooks | |||
|
11 | except ImportError: | |||
|
12 | if os.environ.get('RC_DEBUG_GIT_HOOK'): | |||
|
13 | import traceback | |||
|
14 | print traceback.format_exc() | |||
|
15 | hooks = None | |||
|
16 | ||||
|
17 | ||||
|
18 | # TIMESTAMP: _DATE_ | |||
|
19 | RC_HOOK_VER = '_TMPL_' | |||
|
20 | ||||
|
21 | ||||
|
22 | def main(): | |||
|
23 | if hooks is None: | |||
|
24 | # exit with success if we cannot import vcsserver.hooks !! | |||
|
25 | # this allows simply push to this repo even without rhodecode | |||
|
26 | sys.exit(0) | |||
|
27 | ||||
|
28 | if os.environ.get('RC_SKIP_HOOKS'): | |||
|
29 | sys.exit(0) | |||
|
30 | ||||
|
31 | repo_path = os.getcwd() | |||
|
32 | push_data = sys.stdin.readlines() | |||
|
33 | os.environ['RC_HOOK_VER'] = RC_HOOK_VER | |||
|
34 | # os.environ is modified here by a subprocess call that | |||
|
35 | # runs git and later git executes this hook. | |||
|
36 | # Environ gets some additional info from rhodecode system | |||
|
37 | # like IP or username from basic-auth | |||
|
38 | try: | |||
|
39 | result = hooks.git_pre_receive(repo_path, push_data, os.environ) | |||
|
40 | sys.exit(result) | |||
|
41 | except Exception as error: | |||
|
42 | # TODO: johbo: Improve handling of this special case | |||
|
43 | if not getattr(error, '_vcs_kind', None) == 'repo_locked': | |||
|
44 | raise | |||
|
45 | print 'ERROR:', error | |||
|
46 | sys.exit(1) | |||
|
47 | sys.exit(0) | |||
|
48 | ||||
|
49 | ||||
|
50 | if __name__ == '__main__': | |||
|
51 | main() |
@@ -0,0 +1,50 b'' | |||||
|
1 | #!_ENV_ | |||
|
2 | ||||
|
3 | import os | |||
|
4 | import sys | |||
|
5 | path_adjust = [_PATH_] | |||
|
6 | ||||
|
7 | if path_adjust: | |||
|
8 | sys.path = path_adjust | |||
|
9 | ||||
|
10 | try: | |||
|
11 | from vcsserver import hooks | |||
|
12 | except ImportError: | |||
|
13 | if os.environ.get('RC_DEBUG_SVN_HOOK'): | |||
|
14 | import traceback | |||
|
15 | print traceback.format_exc() | |||
|
16 | hooks = None | |||
|
17 | ||||
|
18 | ||||
|
19 | # TIMESTAMP: _DATE_ | |||
|
20 | RC_HOOK_VER = '_TMPL_' | |||
|
21 | ||||
|
22 | ||||
|
23 | def main(): | |||
|
24 | if hooks is None: | |||
|
25 | # exit with success if we cannot import vcsserver.hooks !! | |||
|
26 | # this allows simply push to this repo even without rhodecode | |||
|
27 | sys.exit(0) | |||
|
28 | ||||
|
29 | if os.environ.get('RC_SKIP_HOOKS'): | |||
|
30 | sys.exit(0) | |||
|
31 | repo_path = os.getcwd() | |||
|
32 | push_data = sys.argv[1:] | |||
|
33 | ||||
|
34 | os.environ['RC_HOOK_VER'] = RC_HOOK_VER | |||
|
35 | ||||
|
36 | try: | |||
|
37 | result = hooks.svn_post_commit(repo_path, push_data, os.environ) | |||
|
38 | sys.exit(result) | |||
|
39 | except Exception as error: | |||
|
40 | # TODO: johbo: Improve handling of this special case | |||
|
41 | if not getattr(error, '_vcs_kind', None) == 'repo_locked': | |||
|
42 | raise | |||
|
43 | print 'ERROR:', error | |||
|
44 | sys.exit(1) | |||
|
45 | sys.exit(0) | |||
|
46 | ||||
|
47 | ||||
|
48 | ||||
|
49 | if __name__ == '__main__': | |||
|
50 | main() |
@@ -0,0 +1,52 b'' | |||||
|
1 | #!_ENV_ | |||
|
2 | ||||
|
3 | import os | |||
|
4 | import sys | |||
|
5 | path_adjust = [_PATH_] | |||
|
6 | ||||
|
7 | if path_adjust: | |||
|
8 | sys.path = path_adjust | |||
|
9 | ||||
|
10 | try: | |||
|
11 | from vcsserver import hooks | |||
|
12 | except ImportError: | |||
|
13 | if os.environ.get('RC_DEBUG_SVN_HOOK'): | |||
|
14 | import traceback | |||
|
15 | print traceback.format_exc() | |||
|
16 | hooks = None | |||
|
17 | ||||
|
18 | ||||
|
19 | # TIMESTAMP: _DATE_ | |||
|
20 | RC_HOOK_VER = '_TMPL_' | |||
|
21 | ||||
|
22 | ||||
|
23 | def main(): | |||
|
24 | if os.environ.get('SSH_READ_ONLY') == '1': | |||
|
25 | sys.stderr.write('Only read-only access is allowed') | |||
|
26 | sys.exit(1) | |||
|
27 | ||||
|
28 | if hooks is None: | |||
|
29 | # exit with success if we cannot import vcsserver.hooks !! | |||
|
30 | # this allows simply push to this repo even without rhodecode | |||
|
31 | sys.exit(0) | |||
|
32 | if os.environ.get('RC_SKIP_HOOKS'): | |||
|
33 | sys.exit(0) | |||
|
34 | repo_path = os.getcwd() | |||
|
35 | push_data = sys.argv[1:] | |||
|
36 | ||||
|
37 | os.environ['RC_HOOK_VER'] = RC_HOOK_VER | |||
|
38 | ||||
|
39 | try: | |||
|
40 | result = hooks.svn_pre_commit(repo_path, push_data, os.environ) | |||
|
41 | sys.exit(result) | |||
|
42 | except Exception as error: | |||
|
43 | # TODO: johbo: Improve handling of this special case | |||
|
44 | if not getattr(error, '_vcs_kind', None) == 'repo_locked': | |||
|
45 | raise | |||
|
46 | print 'ERROR:', error | |||
|
47 | sys.exit(1) | |||
|
48 | sys.exit(0) | |||
|
49 | ||||
|
50 | ||||
|
51 | if __name__ == '__main__': | |||
|
52 | main() |
@@ -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,206 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 sys | |||
|
20 | import stat | |||
|
21 | import pytest | |||
|
22 | import vcsserver | |||
|
23 | import tempfile | |||
|
24 | from vcsserver import hook_utils | |||
|
25 | from vcsserver.tests.fixture import no_newline_id_generator | |||
|
26 | from vcsserver.utils import AttributeDict | |||
|
27 | ||||
|
28 | ||||
|
29 | class TestCheckRhodecodeHook(object): | |||
|
30 | ||||
|
31 | def test_returns_false_when_hook_file_is_wrong_found(self, tmpdir): | |||
|
32 | hook = os.path.join(str(tmpdir), 'fake_hook_file.py') | |||
|
33 | with open(hook, 'wb') as f: | |||
|
34 | f.write('dummy test') | |||
|
35 | result = hook_utils.check_rhodecode_hook(hook) | |||
|
36 | assert result is False | |||
|
37 | ||||
|
38 | def test_returns_true_when_no_hook_file_found(self, tmpdir): | |||
|
39 | hook = os.path.join(str(tmpdir), 'fake_hook_file_not_existing.py') | |||
|
40 | result = hook_utils.check_rhodecode_hook(hook) | |||
|
41 | assert result | |||
|
42 | ||||
|
43 | @pytest.mark.parametrize("file_content, expected_result", [ | |||
|
44 | ("RC_HOOK_VER = '3.3.3'\n", True), | |||
|
45 | ("RC_HOOK = '3.3.3'\n", False), | |||
|
46 | ], ids=no_newline_id_generator) | |||
|
47 | def test_signatures(self, file_content, expected_result, tmpdir): | |||
|
48 | hook = os.path.join(str(tmpdir), 'fake_hook_file_1.py') | |||
|
49 | with open(hook, 'wb') as f: | |||
|
50 | f.write(file_content) | |||
|
51 | ||||
|
52 | result = hook_utils.check_rhodecode_hook(hook) | |||
|
53 | ||||
|
54 | assert result is expected_result | |||
|
55 | ||||
|
56 | ||||
|
57 | class BaseInstallHooks(object): | |||
|
58 | HOOK_FILES = () | |||
|
59 | ||||
|
60 | def _check_hook_file_mode(self, file_path): | |||
|
61 | assert os.path.exists(file_path), 'path %s missing' % file_path | |||
|
62 | stat_info = os.stat(file_path) | |||
|
63 | ||||
|
64 | file_mode = stat.S_IMODE(stat_info.st_mode) | |||
|
65 | expected_mode = int('755', 8) | |||
|
66 | assert expected_mode == file_mode | |||
|
67 | ||||
|
68 | def _check_hook_file_content(self, file_path, executable): | |||
|
69 | executable = executable or sys.executable | |||
|
70 | with open(file_path, 'rt') as hook_file: | |||
|
71 | content = hook_file.read() | |||
|
72 | ||||
|
73 | expected_env = '#!{}'.format(executable) | |||
|
74 | expected_rc_version = "\nRC_HOOK_VER = '{}'\n".format( | |||
|
75 | vcsserver.__version__) | |||
|
76 | assert content.strip().startswith(expected_env) | |||
|
77 | assert expected_rc_version in content | |||
|
78 | ||||
|
79 | def _create_fake_hook(self, file_path, content): | |||
|
80 | with open(file_path, 'w') as hook_file: | |||
|
81 | hook_file.write(content) | |||
|
82 | ||||
|
83 | def create_dummy_repo(self, repo_type): | |||
|
84 | tmpdir = tempfile.mkdtemp() | |||
|
85 | repo = AttributeDict() | |||
|
86 | if repo_type == 'git': | |||
|
87 | repo.path = os.path.join(tmpdir, 'test_git_hooks_installation_repo') | |||
|
88 | os.makedirs(repo.path) | |||
|
89 | os.makedirs(os.path.join(repo.path, 'hooks')) | |||
|
90 | repo.bare = True | |||
|
91 | ||||
|
92 | elif repo_type == 'svn': | |||
|
93 | repo.path = os.path.join(tmpdir, 'test_svn_hooks_installation_repo') | |||
|
94 | os.makedirs(repo.path) | |||
|
95 | os.makedirs(os.path.join(repo.path, 'hooks')) | |||
|
96 | ||||
|
97 | return repo | |||
|
98 | ||||
|
99 | def check_hooks(self, repo_path, repo_bare=True): | |||
|
100 | for file_name in self.HOOK_FILES: | |||
|
101 | if repo_bare: | |||
|
102 | file_path = os.path.join(repo_path, 'hooks', file_name) | |||
|
103 | else: | |||
|
104 | file_path = os.path.join(repo_path, '.git', 'hooks', file_name) | |||
|
105 | self._check_hook_file_mode(file_path) | |||
|
106 | self._check_hook_file_content(file_path, sys.executable) | |||
|
107 | ||||
|
108 | ||||
|
109 | class TestInstallGitHooks(BaseInstallHooks): | |||
|
110 | HOOK_FILES = ('pre-receive', 'post-receive') | |||
|
111 | ||||
|
112 | def test_hooks_are_installed(self): | |||
|
113 | repo = self.create_dummy_repo('git') | |||
|
114 | result = hook_utils.install_git_hooks(repo.path, repo.bare) | |||
|
115 | assert result | |||
|
116 | self.check_hooks(repo.path, repo.bare) | |||
|
117 | ||||
|
118 | def test_hooks_are_replaced(self): | |||
|
119 | repo = self.create_dummy_repo('git') | |||
|
120 | hooks_path = os.path.join(repo.path, 'hooks') | |||
|
121 | for file_path in [os.path.join(hooks_path, f) for f in self.HOOK_FILES]: | |||
|
122 | self._create_fake_hook( | |||
|
123 | file_path, content="RC_HOOK_VER = 'abcde'\n") | |||
|
124 | ||||
|
125 | result = hook_utils.install_git_hooks(repo.path, repo.bare) | |||
|
126 | assert result | |||
|
127 | self.check_hooks(repo.path, repo.bare) | |||
|
128 | ||||
|
129 | def test_non_rc_hooks_are_not_replaced(self): | |||
|
130 | repo = self.create_dummy_repo('git') | |||
|
131 | hooks_path = os.path.join(repo.path, 'hooks') | |||
|
132 | non_rc_content = 'echo "non rc hook"\n' | |||
|
133 | for file_path in [os.path.join(hooks_path, f) for f in self.HOOK_FILES]: | |||
|
134 | self._create_fake_hook( | |||
|
135 | file_path, content=non_rc_content) | |||
|
136 | ||||
|
137 | result = hook_utils.install_git_hooks(repo.path, repo.bare) | |||
|
138 | assert result | |||
|
139 | ||||
|
140 | for file_path in [os.path.join(hooks_path, f) for f in self.HOOK_FILES]: | |||
|
141 | with open(file_path, 'rt') as hook_file: | |||
|
142 | content = hook_file.read() | |||
|
143 | assert content == non_rc_content | |||
|
144 | ||||
|
145 | def test_non_rc_hooks_are_replaced_with_force_flag(self): | |||
|
146 | repo = self.create_dummy_repo('git') | |||
|
147 | hooks_path = os.path.join(repo.path, 'hooks') | |||
|
148 | non_rc_content = 'echo "non rc hook"\n' | |||
|
149 | for file_path in [os.path.join(hooks_path, f) for f in self.HOOK_FILES]: | |||
|
150 | self._create_fake_hook( | |||
|
151 | file_path, content=non_rc_content) | |||
|
152 | ||||
|
153 | result = hook_utils.install_git_hooks( | |||
|
154 | repo.path, repo.bare, force_create=True) | |||
|
155 | assert result | |||
|
156 | self.check_hooks(repo.path, repo.bare) | |||
|
157 | ||||
|
158 | ||||
|
159 | class TestInstallSvnHooks(BaseInstallHooks): | |||
|
160 | HOOK_FILES = ('pre-commit', 'post-commit') | |||
|
161 | ||||
|
162 | def test_hooks_are_installed(self): | |||
|
163 | repo = self.create_dummy_repo('svn') | |||
|
164 | result = hook_utils.install_svn_hooks(repo.path) | |||
|
165 | assert result | |||
|
166 | self.check_hooks(repo.path) | |||
|
167 | ||||
|
168 | def test_hooks_are_replaced(self): | |||
|
169 | repo = self.create_dummy_repo('svn') | |||
|
170 | hooks_path = os.path.join(repo.path, 'hooks') | |||
|
171 | for file_path in [os.path.join(hooks_path, f) for f in self.HOOK_FILES]: | |||
|
172 | self._create_fake_hook( | |||
|
173 | file_path, content="RC_HOOK_VER = 'abcde'\n") | |||
|
174 | ||||
|
175 | result = hook_utils.install_svn_hooks(repo.path) | |||
|
176 | assert result | |||
|
177 | self.check_hooks(repo.path) | |||
|
178 | ||||
|
179 | def test_non_rc_hooks_are_not_replaced(self): | |||
|
180 | repo = self.create_dummy_repo('svn') | |||
|
181 | hooks_path = os.path.join(repo.path, 'hooks') | |||
|
182 | non_rc_content = 'echo "non rc hook"\n' | |||
|
183 | for file_path in [os.path.join(hooks_path, f) for f in self.HOOK_FILES]: | |||
|
184 | self._create_fake_hook( | |||
|
185 | file_path, content=non_rc_content) | |||
|
186 | ||||
|
187 | result = hook_utils.install_svn_hooks(repo.path) | |||
|
188 | assert result | |||
|
189 | ||||
|
190 | for file_path in [os.path.join(hooks_path, f) for f in self.HOOK_FILES]: | |||
|
191 | with open(file_path, 'rt') as hook_file: | |||
|
192 | content = hook_file.read() | |||
|
193 | assert content == non_rc_content | |||
|
194 | ||||
|
195 | def test_non_rc_hooks_are_replaced_with_force_flag(self): | |||
|
196 | repo = self.create_dummy_repo('svn') | |||
|
197 | hooks_path = os.path.join(repo.path, 'hooks') | |||
|
198 | non_rc_content = 'echo "non rc hook"\n' | |||
|
199 | for file_path in [os.path.join(hooks_path, f) for f in self.HOOK_FILES]: | |||
|
200 | self._create_fake_hook( | |||
|
201 | file_path, content=non_rc_content) | |||
|
202 | ||||
|
203 | result = hook_utils.install_svn_hooks( | |||
|
204 | repo.path, force_create=True) | |||
|
205 | assert result | |||
|
206 | self.check_hooks(repo.path, ) |
@@ -1,5 +1,5 b'' | |||||
1 | [bumpversion] |
|
1 | [bumpversion] | |
2 |
current_version = 4.1 |
|
2 | current_version = 4.12.0 | |
3 | message = release: Bump version {current_version} to {new_version} |
|
3 | message = release: Bump version {current_version} to {new_version} | |
4 |
|
4 | |||
5 | [bumpversion:file:vcsserver/VERSION] |
|
5 | [bumpversion:file:vcsserver/VERSION] |
@@ -5,12 +5,10 b' done = false' | |||||
5 | done = true |
|
5 | done = true | |
6 |
|
6 | |||
7 | [task:fixes_on_stable] |
|
7 | [task:fixes_on_stable] | |
8 | done = true |
|
|||
9 |
|
8 | |||
10 | [task:pip2nix_generated] |
|
9 | [task:pip2nix_generated] | |
11 | done = true |
|
|||
12 |
|
10 | |||
13 | [release] |
|
11 | [release] | |
14 |
state = |
|
12 | state = in_progress | |
15 |
version = 4.1 |
|
13 | version = 4.12.0 | |
16 |
|
14 |
@@ -8,6 +8,9 b' include vcsserver/VERSION' | |||||
8 | # all config files |
|
8 | # all config files | |
9 | recursive-include configs * |
|
9 | recursive-include configs * | |
10 |
|
10 | |||
|
11 | # hook templates | |||
|
12 | recursive-include vcsserver/hook_utils/hook_templates * | |||
|
13 | ||||
11 | # skip any tests files |
|
14 | # skip any tests files | |
12 | recursive-exclude vcsserver/tests * |
|
15 | recursive-exclude vcsserver/tests * | |
13 |
|
16 |
@@ -20,6 +20,10 b' beaker.cache.repo_object.max_items = 100' | |||||
20 | beaker.cache.repo_object.expire = 300 |
|
20 | beaker.cache.repo_object.expire = 300 | |
21 | beaker.cache.repo_object.enabled = true |
|
21 | beaker.cache.repo_object.enabled = true | |
22 |
|
22 | |||
|
23 | # path to binaries for vcsserver, it should be set by the installer | |||
|
24 | # at installation time, e.g /home/user/vcsserver-1/profile/bin | |||
|
25 | core.binary_dir = "" | |||
|
26 | ||||
23 | [server:main] |
|
27 | [server:main] | |
24 | ## COMMON ## |
|
28 | ## COMMON ## | |
25 | host = 0.0.0.0 |
|
29 | host = 0.0.0.0 |
@@ -39,7 +39,7 b' use = egg:rhodecode-vcsserver' | |||||
39 | pyramid.default_locale_name = en |
|
39 | pyramid.default_locale_name = en | |
40 | pyramid.includes = |
|
40 | pyramid.includes = | |
41 |
|
41 | |||
42 |
|
|
42 | # default locale used by VCS systems | |
43 | locale = en_US.UTF-8 |
|
43 | locale = en_US.UTF-8 | |
44 |
|
44 | |||
45 | # cache regions, please don't change |
|
45 | # cache regions, please don't change | |
@@ -50,6 +50,10 b' beaker.cache.repo_object.max_items = 100' | |||||
50 | beaker.cache.repo_object.expire = 300 |
|
50 | beaker.cache.repo_object.expire = 300 | |
51 | beaker.cache.repo_object.enabled = true |
|
51 | beaker.cache.repo_object.enabled = true | |
52 |
|
52 | |||
|
53 | # path to binaries for vcsserver, it should be set by the installer | |||
|
54 | # at installation time, e.g /home/user/vcsserver-1/profile/bin | |||
|
55 | core.binary_dir = "" | |||
|
56 | ||||
53 |
|
57 | |||
54 | ################################ |
|
58 | ################################ | |
55 | ### LOGGING CONFIGURATION #### |
|
59 | ### LOGGING CONFIGURATION #### |
@@ -12,6 +12,12 b' in' | |||||
12 |
|
12 | |||
13 | self: super: { |
|
13 | self: super: { | |
14 |
|
14 | |||
|
15 | Beaker = super.Beaker.override (attrs: { | |||
|
16 | patches = [ | |||
|
17 | ./patch-beaker-lock-func-debug.diff | |||
|
18 | ]; | |||
|
19 | }); | |||
|
20 | ||||
15 | subvertpy = super.subvertpy.override (attrs: { |
|
21 | subvertpy = super.subvertpy.override (attrs: { | |
16 | # TODO: johbo: Remove the "or" once we drop 16.03 support |
|
22 | # TODO: johbo: Remove the "or" once we drop 16.03 support | |
17 | SVN_PREFIX = "${pkgs.subversion.dev or pkgs.subversion}"; |
|
23 | SVN_PREFIX = "${pkgs.subversion.dev or pkgs.subversion}"; |
@@ -3,26 +3,26 b'' | |||||
3 |
|
3 | |||
4 | { |
|
4 | { | |
5 | Beaker = super.buildPythonPackage { |
|
5 | Beaker = super.buildPythonPackage { | |
6 |
name = "Beaker-1.9. |
|
6 | name = "Beaker-1.9.1"; | |
7 | buildInputs = with self; []; |
|
7 | buildInputs = with self; []; | |
8 | doCheck = false; |
|
8 | doCheck = false; | |
9 | propagatedBuildInputs = with self; [funcsigs]; |
|
9 | propagatedBuildInputs = with self; [funcsigs]; | |
10 | src = fetchurl { |
|
10 | src = fetchurl { | |
11 |
url = "https://pypi.python.org/packages/ |
|
11 | url = "https://pypi.python.org/packages/ca/14/a626188d0d0c7b55dd7cf1902046c2743bd392a7078bb53073e13280eb1e/Beaker-1.9.1.tar.gz"; | |
12 | md5 = "38b3fcdfa24faf97c6cf66991eb54e9c"; |
|
12 | md5 = "46fda0a164e2b0d24ccbda51a2310301"; | |
13 | }; |
|
13 | }; | |
14 | meta = { |
|
14 | meta = { | |
15 | license = [ pkgs.lib.licenses.bsdOriginal ]; |
|
15 | license = [ pkgs.lib.licenses.bsdOriginal ]; | |
16 | }; |
|
16 | }; | |
17 | }; |
|
17 | }; | |
18 | Jinja2 = super.buildPythonPackage { |
|
18 | Jinja2 = super.buildPythonPackage { | |
19 |
name = "Jinja2-2. |
|
19 | name = "Jinja2-2.9.6"; | |
20 | buildInputs = with self; []; |
|
20 | buildInputs = with self; []; | |
21 | doCheck = false; |
|
21 | doCheck = false; | |
22 | propagatedBuildInputs = with self; [MarkupSafe]; |
|
22 | propagatedBuildInputs = with self; [MarkupSafe]; | |
23 | src = fetchurl { |
|
23 | src = fetchurl { | |
24 |
url = "https://pypi.python.org/packages/56 |
|
24 | url = "https://pypi.python.org/packages/90/61/f820ff0076a2599dd39406dcb858ecb239438c02ce706c8e91131ab9c7f1/Jinja2-2.9.6.tar.gz"; | |
25 | md5 = "61ef1117f945486472850819b8d1eb3d"; |
|
25 | md5 = "6411537324b4dba0956aaa8109f3c77b"; | |
26 | }; |
|
26 | }; | |
27 | meta = { |
|
27 | meta = { | |
28 | license = [ pkgs.lib.licenses.bsdOriginal ]; |
|
28 | license = [ pkgs.lib.licenses.bsdOriginal ]; | |
@@ -237,13 +237,13 b'' | |||||
237 | }; |
|
237 | }; | |
238 | }; |
|
238 | }; | |
239 | greenlet = super.buildPythonPackage { |
|
239 | greenlet = super.buildPythonPackage { | |
240 |
name = "greenlet-0.4.1 |
|
240 | name = "greenlet-0.4.13"; | |
241 | buildInputs = with self; []; |
|
241 | buildInputs = with self; []; | |
242 | doCheck = false; |
|
242 | doCheck = false; | |
243 | propagatedBuildInputs = with self; []; |
|
243 | propagatedBuildInputs = with self; []; | |
244 | src = fetchurl { |
|
244 | src = fetchurl { | |
245 |
url = "https://pypi.python.org/packages/ |
|
245 | url = "https://pypi.python.org/packages/13/de/ba92335e9e76040ca7274224942282a80d54f85e342a5e33c5277c7f87eb/greenlet-0.4.13.tar.gz"; | |
246 | md5 = "e8637647d58a26c4a1f51ca393e53c00"; |
|
246 | md5 = "6e0b9dd5385f81d478451ec8ed1d62b3"; | |
247 | }; |
|
247 | }; | |
248 | meta = { |
|
248 | meta = { | |
249 | license = [ pkgs.lib.licenses.mit ]; |
|
249 | license = [ pkgs.lib.licenses.mit ]; | |
@@ -372,8 +372,8 b'' | |||||
372 | doCheck = false; |
|
372 | doCheck = false; | |
373 | propagatedBuildInputs = with self; []; |
|
373 | propagatedBuildInputs = with self; []; | |
374 | src = fetchurl { |
|
374 | src = fetchurl { | |
375 | url = "https://pypi.python.org/packages/15/45/30273ee91feb60dabb8fbb2da7868520525f02cf910279b3047182feed80/mock-1.0.1.zip"; |
|
375 | url = "https://pypi.python.org/packages/a2/52/7edcd94f0afb721a2d559a5b9aae8af4f8f2c79bc63fdbe8a8a6c9b23bbe/mock-1.0.1.tar.gz"; | |
376 | md5 = "869f08d003c289a97c1a6610faf5e913"; |
|
376 | md5 = "c3971991738caa55ec7c356bbc154ee2"; | |
377 | }; |
|
377 | }; | |
378 | meta = { |
|
378 | meta = { | |
379 | license = [ pkgs.lib.licenses.bsdOriginal ]; |
|
379 | license = [ pkgs.lib.licenses.bsdOriginal ]; | |
@@ -406,13 +406,13 b'' | |||||
406 | }; |
|
406 | }; | |
407 | }; |
|
407 | }; | |
408 | pexpect = super.buildPythonPackage { |
|
408 | pexpect = super.buildPythonPackage { | |
409 |
name = "pexpect-4. |
|
409 | name = "pexpect-4.4.0"; | |
410 | buildInputs = with self; []; |
|
410 | buildInputs = with self; []; | |
411 | doCheck = false; |
|
411 | doCheck = false; | |
412 | propagatedBuildInputs = with self; [ptyprocess]; |
|
412 | propagatedBuildInputs = with self; [ptyprocess]; | |
413 | src = fetchurl { |
|
413 | src = fetchurl { | |
414 | url = "https://pypi.python.org/packages/f8/44/5466c30e49762bb92e442bbdf4472d6904608d211258eb3198a11f0309a4/pexpect-4.3.0.tar.gz"; |
|
414 | url = "https://pypi.python.org/packages/fa/c3/60c0cbf96f242d0b47a82e9ca634dcd6dcb043832cf05e17540812e1c707/pexpect-4.4.0.tar.gz"; | |
415 | md5 = "047a486dcd26134b74f2e67046bb61a0"; |
|
415 | md5 = "e9b07f0765df8245ac72201d757baaef"; | |
416 | }; |
|
416 | }; | |
417 | meta = { |
|
417 | meta = { | |
418 | license = [ pkgs.lib.licenses.isc { fullName = "ISC License (ISCL)"; } ]; |
|
418 | license = [ pkgs.lib.licenses.isc { fullName = "ISC License (ISCL)"; } ]; | |
@@ -653,7 +653,7 b'' | |||||
653 | }; |
|
653 | }; | |
654 | }; |
|
654 | }; | |
655 | rhodecode-vcsserver = super.buildPythonPackage { |
|
655 | rhodecode-vcsserver = super.buildPythonPackage { | |
656 |
name = "rhodecode-vcsserver-4.1 |
|
656 | name = "rhodecode-vcsserver-4.12.0"; | |
657 | buildInputs = with self; [pytest py pytest-cov pytest-sugar pytest-runner pytest-catchlog pytest-profiling gprof2dot pytest-timeout mock WebTest cov-core coverage configobj]; |
|
657 | buildInputs = with self; [pytest py pytest-cov pytest-sugar pytest-runner pytest-catchlog pytest-profiling gprof2dot pytest-timeout mock WebTest cov-core coverage configobj]; | |
658 | doCheck = true; |
|
658 | doCheck = true; | |
659 | propagatedBuildInputs = with self; [Beaker configobj decorator dulwich hgsubversion hg-evolve infrae.cache mercurial msgpack-python pyramid pyramid-jinja2 pyramid-mako repoze.lru simplejson subprocess32 subvertpy six translationstring WebOb wheel zope.deprecation zope.interface ipdb ipython gevent greenlet gunicorn waitress pytest py pytest-cov pytest-sugar pytest-runner pytest-catchlog pytest-profiling gprof2dot pytest-timeout mock WebTest cov-core coverage]; |
|
659 | propagatedBuildInputs = with self; [Beaker configobj decorator dulwich hgsubversion hg-evolve infrae.cache mercurial msgpack-python pyramid pyramid-jinja2 pyramid-mako repoze.lru simplejson subprocess32 subvertpy six translationstring WebOb wheel zope.deprecation zope.interface ipdb ipython gevent greenlet gunicorn waitress pytest py pytest-cov pytest-sugar pytest-runner pytest-catchlog pytest-profiling gprof2dot pytest-timeout mock WebTest cov-core coverage]; | |
@@ -663,13 +663,13 b'' | |||||
663 | }; |
|
663 | }; | |
664 | }; |
|
664 | }; | |
665 | scandir = super.buildPythonPackage { |
|
665 | scandir = super.buildPythonPackage { | |
666 |
name = "scandir-1. |
|
666 | name = "scandir-1.7"; | |
667 | buildInputs = with self; []; |
|
667 | buildInputs = with self; []; | |
668 | doCheck = false; |
|
668 | doCheck = false; | |
669 | propagatedBuildInputs = with self; []; |
|
669 | propagatedBuildInputs = with self; []; | |
670 | src = fetchurl { |
|
670 | src = fetchurl { | |
671 |
url = "https://pypi.python.org/packages/77 |
|
671 | url = "https://pypi.python.org/packages/13/bb/e541b74230bbf7a20a3949a2ee6631be299378a784f5445aa5d0047c192b/scandir-1.7.tar.gz"; | |
672 | md5 = "0180ddb97c96cbb2d4f25d2ae11c64ac"; |
|
672 | md5 = "037e5f24d1a0e78b17faca72dea9555f"; | |
673 | }; |
|
673 | }; | |
674 | meta = { |
|
674 | meta = { | |
675 | license = [ pkgs.lib.licenses.bsdOriginal { fullName = "New BSD License"; } ]; |
|
675 | license = [ pkgs.lib.licenses.bsdOriginal { fullName = "New BSD License"; } ]; | |
@@ -845,26 +845,26 b'' | |||||
845 | }; |
|
845 | }; | |
846 | }; |
|
846 | }; | |
847 | zope.deprecation = super.buildPythonPackage { |
|
847 | zope.deprecation = super.buildPythonPackage { | |
848 |
name = "zope.deprecation-4. |
|
848 | name = "zope.deprecation-4.3.0"; | |
849 | buildInputs = with self; []; |
|
849 | buildInputs = with self; []; | |
850 | doCheck = false; |
|
850 | doCheck = false; | |
851 | propagatedBuildInputs = with self; [setuptools]; |
|
851 | propagatedBuildInputs = with self; [setuptools]; | |
852 | src = fetchurl { |
|
852 | src = fetchurl { | |
853 |
url = "https://pypi.python.org/packages/ |
|
853 | url = "https://pypi.python.org/packages/a1/18/2dc5e6bfe64fdc3b79411b67464c55bb0b43b127051a20f7f492ab767758/zope.deprecation-4.3.0.tar.gz"; | |
854 | md5 = "e9a663ded58f4f9f7881beb56cae2782"; |
|
854 | md5 = "2166b2cb7e0e96a21104e6f8f9b696bb"; | |
855 | }; |
|
855 | }; | |
856 | meta = { |
|
856 | meta = { | |
857 | license = [ pkgs.lib.licenses.zpt21 ]; |
|
857 | license = [ pkgs.lib.licenses.zpt21 ]; | |
858 | }; |
|
858 | }; | |
859 | }; |
|
859 | }; | |
860 | zope.interface = super.buildPythonPackage { |
|
860 | zope.interface = super.buildPythonPackage { | |
861 |
name = "zope.interface-4. |
|
861 | name = "zope.interface-4.4.3"; | |
862 | buildInputs = with self; []; |
|
862 | buildInputs = with self; []; | |
863 | doCheck = false; |
|
863 | doCheck = false; | |
864 | propagatedBuildInputs = with self; [setuptools]; |
|
864 | propagatedBuildInputs = with self; [setuptools]; | |
865 | src = fetchurl { |
|
865 | src = fetchurl { | |
866 |
url = "https://pypi.python.org/packages/ |
|
866 | url = "https://pypi.python.org/packages/bd/d2/25349ed41f9dcff7b3baf87bd88a4c82396cf6e02f1f42bb68657a3132af/zope.interface-4.4.3.tar.gz"; | |
867 | md5 = "9ae3d24c0c7415deb249dd1a132f0f79"; |
|
867 | md5 = "8700a4f527c1203b34b10c2b4e7a6912"; | |
868 | }; |
|
868 | }; | |
869 | meta = { |
|
869 | meta = { | |
870 | license = [ pkgs.lib.licenses.zpt21 ]; |
|
870 | license = [ pkgs.lib.licenses.zpt21 ]; |
@@ -1,7 +1,7 b'' | |||||
1 | ## core |
|
1 | ## core | |
2 | setuptools==30.1.0 |
|
2 | setuptools==30.1.0 | |
3 |
|
3 | |||
4 |
Beaker==1.9. |
|
4 | Beaker==1.9.1 | |
5 | configobj==5.0.6 |
|
5 | configobj==5.0.6 | |
6 | decorator==4.1.2 |
|
6 | decorator==4.1.2 | |
7 | dulwich==0.13.0 |
|
7 | dulwich==0.13.0 | |
@@ -11,6 +11,7 b' infrae.cache==1.0.1' | |||||
11 | mercurial==4.4.2 |
|
11 | mercurial==4.4.2 | |
12 | msgpack-python==0.4.8 |
|
12 | msgpack-python==0.4.8 | |
13 | pyramid-jinja2==2.7 |
|
13 | pyramid-jinja2==2.7 | |
|
14 | Jinja2==2.9.6 | |||
14 | pyramid==1.9.1 |
|
15 | pyramid==1.9.1 | |
15 | pyramid-mako==1.0.2 |
|
16 | pyramid-mako==1.0.2 | |
16 | repoze.lru==0.7 |
|
17 | repoze.lru==0.7 | |
@@ -23,12 +24,12 b' six==1.11.0' | |||||
23 | translationstring==1.3 |
|
24 | translationstring==1.3 | |
24 | WebOb==1.7.4 |
|
25 | WebOb==1.7.4 | |
25 | wheel==0.29.0 |
|
26 | wheel==0.29.0 | |
26 |
zope.deprecation==4. |
|
27 | zope.deprecation==4.3.0 | |
27 |
zope.interface==4. |
|
28 | zope.interface==4.4.3 | |
28 |
|
29 | |||
29 | ## http servers |
|
30 | ## http servers | |
30 | gevent==1.2.2 |
|
31 | gevent==1.2.2 | |
31 |
greenlet==0.4.1 |
|
32 | greenlet==0.4.13 | |
32 | gunicorn==19.7.1 |
|
33 | gunicorn==19.7.1 | |
33 | waitress==1.1.0 |
|
34 | waitress==1.1.0 | |
34 |
|
35 |
@@ -451,8 +451,9 b' class GitRemote(object):' | |||||
451 | if self.check_url(url, wire): |
|
451 | if self.check_url(url, wire): | |
452 | repo = self._factory.repo(wire) |
|
452 | repo = self._factory.repo(wire) | |
453 | self.run_git_command( |
|
453 | self.run_git_command( | |
454 |
wire, ['push', url, '--mirror'], fail_on_stderr=False |
|
454 | wire, ['push', url, '--mirror'], fail_on_stderr=False, | |
455 |
|
455 | _copts=['-c', 'core.askpass=""'], | ||
|
456 | extra_env={'GIT_TERMINAL_PROMPT': '0'}) | |||
456 |
|
457 | |||
457 | @reraise_safe_exceptions |
|
458 | @reraise_safe_exceptions | |
458 | def get_remote_refs(self, wire, url): |
|
459 | def get_remote_refs(self, wire, url): | |
@@ -625,6 +626,10 b' class GitRemote(object):' | |||||
625 | del opts['_safe'] |
|
626 | del opts['_safe'] | |
626 | safe_call = True |
|
627 | safe_call = True | |
627 |
|
628 | |||
|
629 | if '_copts' in opts: | |||
|
630 | _copts.extend(opts['_copts'] or []) | |||
|
631 | del opts['_copts'] | |||
|
632 | ||||
628 | gitenv = os.environ.copy() |
|
633 | gitenv = os.environ.copy() | |
629 | gitenv.update(opts.pop('extra_env', {})) |
|
634 | gitenv.update(opts.pop('extra_env', {})) | |
630 | # need to clean fix GIT_DIR ! |
|
635 | # need to clean fix GIT_DIR ! | |
@@ -650,6 +655,12 b' class GitRemote(object):' | |||||
650 | else: |
|
655 | else: | |
651 | raise exceptions.VcsException(tb_err) |
|
656 | raise exceptions.VcsException(tb_err) | |
652 |
|
657 | |||
|
658 | @reraise_safe_exceptions | |||
|
659 | def install_hooks(self, wire, force=False): | |||
|
660 | from vcsserver.hook_utils import install_git_hooks | |||
|
661 | repo = self._factory.repo(wire) | |||
|
662 | return install_git_hooks(repo.path, repo.bare, force_create=force) | |||
|
663 | ||||
653 |
|
664 | |||
654 | def str_to_dulwich(value): |
|
665 | def str_to_dulwich(value): | |
655 | """ |
|
666 | """ |
@@ -553,7 +553,13 b' class HgRemote(object):' | |||||
553 | @reraise_safe_exceptions |
|
553 | @reraise_safe_exceptions | |
554 | def pull(self, wire, url, commit_ids=None): |
|
554 | def pull(self, wire, url, commit_ids=None): | |
555 | repo = self._factory.repo(wire) |
|
555 | repo = self._factory.repo(wire) | |
|
556 | # Disable any prompts for this repo | |||
|
557 | repo.ui.setconfig('ui', 'interactive', 'off', '-y') | |||
|
558 | ||||
556 | remote = peer(repo, {}, url) |
|
559 | remote = peer(repo, {}, url) | |
|
560 | # Disable any prompts for this remote | |||
|
561 | remote.ui.setconfig('ui', 'interactive', 'off', '-y') | |||
|
562 | ||||
557 | if commit_ids: |
|
563 | if commit_ids: | |
558 | commit_ids = [bin(commit_id) for commit_id in commit_ids] |
|
564 | commit_ids = [bin(commit_id) for commit_id in commit_ids] | |
559 |
|
565 | |||
@@ -564,8 +570,15 b' class HgRemote(object):' | |||||
564 | def sync_push(self, wire, url): |
|
570 | def sync_push(self, wire, url): | |
565 | if self.check_url(url, wire['config']): |
|
571 | if self.check_url(url, wire['config']): | |
566 | repo = self._factory.repo(wire) |
|
572 | repo = self._factory.repo(wire) | |
|
573 | ||||
|
574 | # Disable any prompts for this repo | |||
|
575 | repo.ui.setconfig('ui', 'interactive', 'off', '-y') | |||
|
576 | ||||
567 | bookmarks = dict(repo._bookmarks).keys() |
|
577 | bookmarks = dict(repo._bookmarks).keys() | |
568 | remote = peer(repo, {}, url) |
|
578 | remote = peer(repo, {}, url) | |
|
579 | # Disable any prompts for this remote | |||
|
580 | remote.ui.setconfig('ui', 'interactive', 'off', '-y') | |||
|
581 | ||||
569 | return exchange.push( |
|
582 | return exchange.push( | |
570 | repo, remote, newbranch=True, bookmarks=bookmarks).cgresult |
|
583 | repo, remote, newbranch=True, bookmarks=bookmarks).cgresult | |
571 |
|
584 | |||
@@ -756,3 +769,8 b' class HgRemote(object):' | |||||
756 | repo = self._factory.repo(wire) |
|
769 | repo = self._factory.repo(wire) | |
757 | baseui = self._factory._create_config(wire['config']) |
|
770 | baseui = self._factory._create_config(wire['config']) | |
758 | commands.bookmark(baseui, repo, bookmark, rev=revision, force=True) |
|
771 | commands.bookmark(baseui, repo, bookmark, rev=revision, force=True) | |
|
772 | ||||
|
773 | @reraise_safe_exceptions | |||
|
774 | def install_hooks(self, wire, force=False): | |||
|
775 | # we don't need any special hooks for Mercurial | |||
|
776 | pass |
@@ -87,7 +87,7 b' def patch_subrepo_type_mapping():' | |||||
87 | """ |
|
87 | """ | |
88 | return True |
|
88 | return True | |
89 |
|
89 | |||
90 | def dirty(self, ignoreupdate=False): |
|
90 | def dirty(self, ignoreupdate=False, missing=False): | |
91 | """returns true if the dirstate of the subrepo is dirty or does not |
|
91 | """returns true if the dirstate of the subrepo is dirty or does not | |
92 | match current stored state. If ignoreupdate is true, only check |
|
92 | match current stored state. If ignoreupdate is true, only check | |
93 | whether the subrepo has uncommitted changes in its dirstate. |
|
93 | whether the subrepo has uncommitted changes in its dirstate. |
@@ -20,10 +20,10 b'' | |||||
20 | import io |
|
20 | import io | |
21 | import os |
|
21 | import os | |
22 | import sys |
|
22 | import sys | |
23 | import json |
|
|||
24 | import logging |
|
23 | import logging | |
25 | import collections |
|
24 | import collections | |
26 | import importlib |
|
25 | import importlib | |
|
26 | import base64 | |||
27 |
|
27 | |||
28 | from httplib import HTTPConnection |
|
28 | from httplib import HTTPConnection | |
29 |
|
29 | |||
@@ -46,7 +46,11 b' class HooksHttpClient(object):' | |||||
46 | def __call__(self, method, extras): |
|
46 | def __call__(self, method, extras): | |
47 | connection = HTTPConnection(self.hooks_uri) |
|
47 | connection = HTTPConnection(self.hooks_uri) | |
48 | body = self._serialize(method, extras) |
|
48 | body = self._serialize(method, extras) | |
49 | connection.request('POST', '/', body) |
|
49 | try: | |
|
50 | connection.request('POST', '/', body) | |||
|
51 | except Exception: | |||
|
52 | log.error('Connection failed on %s', connection) | |||
|
53 | raise | |||
50 | response = connection.getresponse() |
|
54 | response = connection.getresponse() | |
51 | return json.loads(response.read()) |
|
55 | return json.loads(response.read()) | |
52 |
|
56 | |||
@@ -97,6 +101,17 b' class GitMessageWriter(RemoteMessageWrit' | |||||
97 | self.stdout.write(message.encode('utf-8')) |
|
101 | self.stdout.write(message.encode('utf-8')) | |
98 |
|
102 | |||
99 |
|
103 | |||
|
104 | class SvnMessageWriter(RemoteMessageWriter): | |||
|
105 | """Writer that knows how to send messages to svn clients.""" | |||
|
106 | ||||
|
107 | def __init__(self, stderr=None): | |||
|
108 | # SVN needs data sent to stderr for back-to-client messaging | |||
|
109 | self.stderr = stderr or sys.stderr | |||
|
110 | ||||
|
111 | def write(self, message): | |||
|
112 | self.stderr.write(message.encode('utf-8')) | |||
|
113 | ||||
|
114 | ||||
100 | def _handle_exception(result): |
|
115 | def _handle_exception(result): | |
101 | exception_class = result.get('exception') |
|
116 | exception_class = result.get('exception') | |
102 | exception_traceback = result.get('exception_traceback') |
|
117 | exception_traceback = result.get('exception_traceback') | |
@@ -122,8 +137,9 b' def _get_hooks_client(extras):' | |||||
122 |
|
137 | |||
123 |
|
138 | |||
124 | def _call_hook(hook_name, extras, writer): |
|
139 | def _call_hook(hook_name, extras, writer): | |
125 | hooks = _get_hooks_client(extras) |
|
140 | hooks_client = _get_hooks_client(extras) | |
126 | result = hooks(hook_name, extras) |
|
141 | log.debug('Hooks, using client:%s', hooks_client) | |
|
142 | result = hooks_client(hook_name, extras) | |||
127 | log.debug('Hooks got result: %s', result) |
|
143 | log.debug('Hooks got result: %s', result) | |
128 | writer.write(result['output']) |
|
144 | writer.write(result['output']) | |
129 | _handle_exception(result) |
|
145 | _handle_exception(result) | |
@@ -465,3 +481,61 b' def git_post_receive(unused_repo_path, r' | |||||
465 | pass |
|
481 | pass | |
466 |
|
482 | |||
467 | return _call_hook('post_push', extras, GitMessageWriter()) |
|
483 | return _call_hook('post_push', extras, GitMessageWriter()) | |
|
484 | ||||
|
485 | ||||
|
486 | def svn_pre_commit(repo_path, commit_data, env): | |||
|
487 | path, txn_id = commit_data | |||
|
488 | branches = [] | |||
|
489 | tags = [] | |||
|
490 | ||||
|
491 | cmd = ['svnlook', 'pget', | |||
|
492 | '-t', txn_id, | |||
|
493 | '--revprop', path, 'rc-scm-extras'] | |||
|
494 | stdout, stderr = subprocessio.run_command( | |||
|
495 | cmd, env=os.environ.copy()) | |||
|
496 | extras = json.loads(base64.urlsafe_b64decode(stdout)) | |||
|
497 | ||||
|
498 | extras['commit_ids'] = [] | |||
|
499 | extras['txn_id'] = txn_id | |||
|
500 | extras['new_refs'] = { | |||
|
501 | 'branches': branches, | |||
|
502 | 'bookmarks': [], | |||
|
503 | 'tags': tags, | |||
|
504 | } | |||
|
505 | sys.stderr.write(str(extras)) | |||
|
506 | return _call_hook('pre_push', extras, SvnMessageWriter()) | |||
|
507 | ||||
|
508 | ||||
|
509 | def svn_post_commit(repo_path, commit_data, env): | |||
|
510 | """ | |||
|
511 | commit_data is path, rev, txn_id | |||
|
512 | """ | |||
|
513 | path, commit_id, txn_id = commit_data | |||
|
514 | branches = [] | |||
|
515 | tags = [] | |||
|
516 | ||||
|
517 | cmd = ['svnlook', 'pget', | |||
|
518 | '-r', commit_id, | |||
|
519 | '--revprop', path, 'rc-scm-extras'] | |||
|
520 | stdout, stderr = subprocessio.run_command( | |||
|
521 | cmd, env=os.environ.copy()) | |||
|
522 | ||||
|
523 | extras = json.loads(base64.urlsafe_b64decode(stdout)) | |||
|
524 | ||||
|
525 | extras['commit_ids'] = [commit_id] | |||
|
526 | extras['txn_id'] = txn_id | |||
|
527 | extras['new_refs'] = { | |||
|
528 | 'branches': branches, | |||
|
529 | 'bookmarks': [], | |||
|
530 | 'tags': tags, | |||
|
531 | } | |||
|
532 | ||||
|
533 | if 'repo_size' in extras['hooks']: | |||
|
534 | try: | |||
|
535 | _call_hook('repo_size', extras, SvnMessageWriter()) | |||
|
536 | except: | |||
|
537 | pass | |||
|
538 | ||||
|
539 | return _call_hook('post_push', extras, SvnMessageWriter()) | |||
|
540 | ||||
|
541 |
@@ -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 |
|
17 | |||
|
18 | import os | |||
18 | import base64 |
|
19 | import base64 | |
19 | import locale |
|
20 | import locale | |
20 | import logging |
|
21 | import logging | |
@@ -29,6 +30,7 b' from beaker.cache import CacheManager' | |||||
29 | from beaker.util import parse_cache_config_options |
|
30 | from beaker.util import parse_cache_config_options | |
30 | from pyramid.config import Configurator |
|
31 | from pyramid.config import Configurator | |
31 | from pyramid.wsgi import wsgiapp |
|
32 | from pyramid.wsgi import wsgiapp | |
|
33 | from pyramid.compat import configparser | |||
32 |
|
34 | |||
33 | from vcsserver import remote_wsgi, scm_app, settings, hgpatches |
|
35 | from vcsserver import remote_wsgi, scm_app, settings, hgpatches | |
34 | from vcsserver.git_lfs.app import GIT_LFS_CONTENT_TYPE, GIT_LFS_PROTO_PAT |
|
36 | from vcsserver.git_lfs.app import GIT_LFS_CONTENT_TYPE, GIT_LFS_PROTO_PAT | |
@@ -90,6 +92,10 b' class VCS(object):' | |||||
90 | svn_repo_cache = self.cache.get_cache_region( |
|
92 | svn_repo_cache = self.cache.get_cache_region( | |
91 | 'svn', region='repo_object') |
|
93 | 'svn', region='repo_object') | |
92 | svn_factory = SubversionFactory(svn_repo_cache) |
|
94 | svn_factory = SubversionFactory(svn_repo_cache) | |
|
95 | # hg factory is used for svn url validation | |||
|
96 | hg_repo_cache = self.cache.get_cache_region( | |||
|
97 | 'hg', region='repo_object') | |||
|
98 | hg_factory = MercurialFactory(hg_repo_cache) | |||
93 | self._svn_remote = SvnRemote(svn_factory, hg_factory=hg_factory) |
|
99 | self._svn_remote = SvnRemote(svn_factory, hg_factory=hg_factory) | |
94 | else: |
|
100 | else: | |
95 | log.info("Subversion client import failed") |
|
101 | log.info("Subversion client import failed") | |
@@ -188,6 +194,9 b' class HTTPApplication(object):' | |||||
188 | git_path = app_settings.get('git_path', None) |
|
194 | git_path = app_settings.get('git_path', None) | |
189 | if git_path: |
|
195 | if git_path: | |
190 | settings.GIT_EXECUTABLE = git_path |
|
196 | settings.GIT_EXECUTABLE = git_path | |
|
197 | binary_dir = app_settings.get('core.binary_dir', None) | |||
|
198 | if binary_dir: | |||
|
199 | settings.BINARY_DIR = binary_dir | |||
191 |
|
200 | |||
192 | def _configure(self): |
|
201 | def _configure(self): | |
193 | self.config.add_renderer( |
|
202 | self.config.add_renderer( | |
@@ -276,11 +285,11 b' class HTTPApplication(object):' | |||||
276 |
|
285 | |||
277 | def status_view(self, request): |
|
286 | def status_view(self, request): | |
278 | import vcsserver |
|
287 | import vcsserver | |
279 |
return {'status': 'OK', 'vcsserver_version': vcsserver.__version__ |
|
288 | return {'status': 'OK', 'vcsserver_version': vcsserver.__version__, | |
|
289 | 'pid': os.getpid()} | |||
280 |
|
290 | |||
281 | def service_view(self, request): |
|
291 | def service_view(self, request): | |
282 | import vcsserver |
|
292 | import vcsserver | |
283 | import ConfigParser as configparser |
|
|||
284 |
|
293 | |||
285 | payload = msgpack.unpackb(request.body, use_list=True) |
|
294 | payload = msgpack.unpackb(request.body, use_list=True) | |
286 |
|
295 |
@@ -17,3 +17,4 b'' | |||||
17 |
|
17 | |||
18 | WIRE_ENCODING = 'UTF-8' |
|
18 | WIRE_ENCODING = 'UTF-8' | |
19 | GIT_EXECUTABLE = 'git' |
|
19 | GIT_EXECUTABLE = 'git' | |
|
20 | BINARY_DIR = '' |
@@ -32,7 +32,7 b' import svn.diff' | |||||
32 | import svn.fs |
|
32 | import svn.fs | |
33 | import svn.repos |
|
33 | import svn.repos | |
34 |
|
34 | |||
35 | from vcsserver import svn_diff, exceptions, subprocessio |
|
35 | from vcsserver import svn_diff, exceptions, subprocessio, settings | |
36 | from vcsserver.base import RepoFactory, raise_from_original |
|
36 | from vcsserver.base import RepoFactory, raise_from_original | |
37 |
|
37 | |||
38 | log = logging.getLogger(__name__) |
|
38 | log = logging.getLogger(__name__) | |
@@ -414,6 +414,17 b' class SvnRemote(object):' | |||||
414 | def is_large_file(self, wire, path): |
|
414 | def is_large_file(self, wire, path): | |
415 | return False |
|
415 | return False | |
416 |
|
416 | |||
|
417 | @reraise_safe_exceptions | |||
|
418 | def install_hooks(self, wire, force=False): | |||
|
419 | from vcsserver.hook_utils import install_svn_hooks | |||
|
420 | repo_path = wire['path'] | |||
|
421 | binary_dir = settings.BINARY_DIR | |||
|
422 | executable = None | |||
|
423 | if binary_dir: | |||
|
424 | executable = os.path.join(binary_dir, 'python') | |||
|
425 | return install_svn_hooks( | |||
|
426 | repo_path, executable=executable, force_create=force) | |||
|
427 | ||||
417 |
|
428 | |||
418 | class SvnDiffer(object): |
|
429 | class SvnDiffer(object): | |
419 | """ |
|
430 | """ | |
@@ -576,6 +587,7 b' class SvnDiffer(object):' | |||||
576 | return content.splitlines(True) |
|
587 | return content.splitlines(True) | |
577 |
|
588 | |||
578 |
|
589 | |||
|
590 | ||||
579 | class DiffChangeEditor(svn.delta.Editor): |
|
591 | class DiffChangeEditor(svn.delta.Editor): | |
580 | """ |
|
592 | """ | |
581 | Records changes between two given revisions |
|
593 | Records changes between two given revisions |
@@ -55,3 +55,4 b' def get_available_port():' | |||||
55 | mysocket.close() |
|
55 | mysocket.close() | |
56 | del mysocket |
|
56 | del mysocket | |
57 | return port |
|
57 | return port | |
|
58 |
@@ -69,3 +69,18 b' class ContextINI(object):' | |||||
69 | def __exit__(self, exc_type, exc_val, exc_tb): |
|
69 | def __exit__(self, exc_type, exc_val, exc_tb): | |
70 | if self.destroy: |
|
70 | if self.destroy: | |
71 | os.remove(self.new_path) |
|
71 | os.remove(self.new_path) | |
|
72 | ||||
|
73 | ||||
|
74 | def no_newline_id_generator(test_name): | |||
|
75 | """ | |||
|
76 | Generates a test name without spaces or newlines characters. Used for | |||
|
77 | nicer output of progress of test | |||
|
78 | """ | |||
|
79 | org_name = test_name | |||
|
80 | test_name = test_name\ | |||
|
81 | .replace('\n', '_N') \ | |||
|
82 | .replace('\r', '_N') \ | |||
|
83 | .replace('\t', '_T') \ | |||
|
84 | .replace(' ', '_S') | |||
|
85 | ||||
|
86 | return test_name or 'test-with-empty-name' |
@@ -14,6 +14,9 b'' | |||||
14 | # You should have received a copy of the GNU General Public License |
|
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, |
|
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 | |||
|
18 | ||||
|
19 | log = logging.getLogger(__name__) | |||
17 |
|
20 | |||
18 |
|
21 | |||
19 | def safe_int(val, default=None): |
|
22 | def safe_int(val, default=None): | |
@@ -70,3 +73,10 b" def safe_str(unicode_, to_encoding=['utf" | |||||
70 | return unicode_.encode(encoding) |
|
73 | return unicode_.encode(encoding) | |
71 | except (ImportError, UnicodeEncodeError): |
|
74 | except (ImportError, UnicodeEncodeError): | |
72 | return unicode_.encode(to_encoding[0], 'replace') |
|
75 | return unicode_.encode(to_encoding[0], 'replace') | |
|
76 | ||||
|
77 | ||||
|
78 | class AttributeDict(dict): | |||
|
79 | def __getattr__(self, attr): | |||
|
80 | return self.get(attr, None) | |||
|
81 | __setattr__ = dict.__setitem__ | |||
|
82 | __delattr__ = dict.__delitem__ |
General Comments 0
You need to be logged in to leave comments.
Login now