##// END OF EJS Templates
hooks: make sure exist_ok is used for multiprocess errors
super-admin -
r1120:29f87dc0 python3
parent child Browse files
Show More
@@ -1,202 +1,202 b''
1 # RhodeCode VCSServer provides access to different vcs backends via network.
1 # RhodeCode VCSServer provides access to different vcs backends via network.
2 # Copyright (C) 2014-2020 RhodeCode GmbH
2 # Copyright (C) 2014-2020 RhodeCode GmbH
3 #
3 #
4 # This program is free software; you can redistribute it and/or modify
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
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
6 # the Free Software Foundation; either version 3 of the License, or
7 # (at your option) any later version.
7 # (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
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
17
18 import re
18 import re
19 import os
19 import os
20 import sys
20 import sys
21 import datetime
21 import datetime
22 import logging
22 import logging
23 import pkg_resources
23 import pkg_resources
24
24
25 import vcsserver
25 import vcsserver
26 from vcsserver.str_utils import safe_bytes
26 from vcsserver.str_utils import safe_bytes
27
27
28 log = logging.getLogger(__name__)
28 log = logging.getLogger(__name__)
29
29
30
30
31 def get_git_hooks_path(repo_path, bare):
31 def get_git_hooks_path(repo_path, bare):
32 hooks_path = os.path.join(repo_path, 'hooks')
32 hooks_path = os.path.join(repo_path, 'hooks')
33 if not bare:
33 if not bare:
34 hooks_path = os.path.join(repo_path, '.git', 'hooks')
34 hooks_path = os.path.join(repo_path, '.git', 'hooks')
35
35
36 return hooks_path
36 return hooks_path
37
37
38
38
39 def install_git_hooks(repo_path, bare, executable=None, force_create=False):
39 def install_git_hooks(repo_path, bare, executable=None, force_create=False):
40 """
40 """
41 Creates a RhodeCode hook inside a git repository
41 Creates a RhodeCode hook inside a git repository
42
42
43 :param repo_path: path to repository
43 :param repo_path: path to repository
44 :param executable: binary executable to put in the hooks
44 :param executable: binary executable to put in the hooks
45 :param force_create: Create even if same name hook exists
45 :param force_create: Create even if same name hook exists
46 """
46 """
47 executable = executable or sys.executable
47 executable = executable or sys.executable
48 hooks_path = get_git_hooks_path(repo_path, bare)
48 hooks_path = get_git_hooks_path(repo_path, bare)
49
49
50 if not os.path.isdir(hooks_path):
50 if not os.path.isdir(hooks_path):
51 os.makedirs(hooks_path, mode=0o777)
51 os.makedirs(hooks_path, mode=0o777, exist_ok=True)
52
52
53 tmpl_post = pkg_resources.resource_string(
53 tmpl_post = pkg_resources.resource_string(
54 'vcsserver', '/'.join(
54 'vcsserver', '/'.join(
55 ('hook_utils', 'hook_templates', 'git_post_receive.py.tmpl')))
55 ('hook_utils', 'hook_templates', 'git_post_receive.py.tmpl')))
56 tmpl_pre = pkg_resources.resource_string(
56 tmpl_pre = pkg_resources.resource_string(
57 'vcsserver', '/'.join(
57 'vcsserver', '/'.join(
58 ('hook_utils', 'hook_templates', 'git_pre_receive.py.tmpl')))
58 ('hook_utils', 'hook_templates', 'git_pre_receive.py.tmpl')))
59
59
60 path = '' # not used for now
60 path = '' # not used for now
61 timestamp = datetime.datetime.utcnow().isoformat()
61 timestamp = datetime.datetime.utcnow().isoformat()
62
62
63 for h_type, template in [('pre', tmpl_pre), ('post', tmpl_post)]:
63 for h_type, template in [('pre', tmpl_pre), ('post', tmpl_post)]:
64 log.debug('Installing git hook in repo %s', repo_path)
64 log.debug('Installing git hook in repo %s', repo_path)
65 _hook_file = os.path.join(hooks_path, '%s-receive' % h_type)
65 _hook_file = os.path.join(hooks_path, '%s-receive' % h_type)
66 _rhodecode_hook = check_rhodecode_hook(_hook_file)
66 _rhodecode_hook = check_rhodecode_hook(_hook_file)
67
67
68 if _rhodecode_hook or force_create:
68 if _rhodecode_hook or force_create:
69 log.debug('writing git %s hook file at %s !', h_type, _hook_file)
69 log.debug('writing git %s hook file at %s !', h_type, _hook_file)
70 try:
70 try:
71 with open(_hook_file, 'wb') as f:
71 with open(_hook_file, 'wb') as f:
72 template = template.replace(b'_TMPL_', safe_bytes(vcsserver.__version__))
72 template = template.replace(b'_TMPL_', safe_bytes(vcsserver.__version__))
73 template = template.replace(b'_DATE_', safe_bytes(timestamp))
73 template = template.replace(b'_DATE_', safe_bytes(timestamp))
74 template = template.replace(b'_ENV_', safe_bytes(executable))
74 template = template.replace(b'_ENV_', safe_bytes(executable))
75 template = template.replace(b'_PATH_', safe_bytes(path))
75 template = template.replace(b'_PATH_', safe_bytes(path))
76 f.write(template)
76 f.write(template)
77 os.chmod(_hook_file, 0o755)
77 os.chmod(_hook_file, 0o755)
78 except IOError:
78 except IOError:
79 log.exception('error writing hook file %s', _hook_file)
79 log.exception('error writing hook file %s', _hook_file)
80 else:
80 else:
81 log.debug('skipping writing hook file')
81 log.debug('skipping writing hook file')
82
82
83 return True
83 return True
84
84
85
85
86 def get_svn_hooks_path(repo_path):
86 def get_svn_hooks_path(repo_path):
87 hooks_path = os.path.join(repo_path, 'hooks')
87 hooks_path = os.path.join(repo_path, 'hooks')
88
88
89 return hooks_path
89 return hooks_path
90
90
91
91
92 def install_svn_hooks(repo_path, executable=None, force_create=False):
92 def install_svn_hooks(repo_path, executable=None, force_create=False):
93 """
93 """
94 Creates RhodeCode hooks inside a svn repository
94 Creates RhodeCode hooks inside a svn repository
95
95
96 :param repo_path: path to repository
96 :param repo_path: path to repository
97 :param executable: binary executable to put in the hooks
97 :param executable: binary executable to put in the hooks
98 :param force_create: Create even if same name hook exists
98 :param force_create: Create even if same name hook exists
99 """
99 """
100 executable = executable or sys.executable
100 executable = executable or sys.executable
101 hooks_path = get_svn_hooks_path(repo_path)
101 hooks_path = get_svn_hooks_path(repo_path)
102 if not os.path.isdir(hooks_path):
102 if not os.path.isdir(hooks_path):
103 os.makedirs(hooks_path, mode=0o777)
103 os.makedirs(hooks_path, mode=0o777, exist_ok=True)
104
104
105 tmpl_post = pkg_resources.resource_string(
105 tmpl_post = pkg_resources.resource_string(
106 'vcsserver', '/'.join(
106 'vcsserver', '/'.join(
107 ('hook_utils', 'hook_templates', 'svn_post_commit_hook.py.tmpl')))
107 ('hook_utils', 'hook_templates', 'svn_post_commit_hook.py.tmpl')))
108 tmpl_pre = pkg_resources.resource_string(
108 tmpl_pre = pkg_resources.resource_string(
109 'vcsserver', '/'.join(
109 'vcsserver', '/'.join(
110 ('hook_utils', 'hook_templates', 'svn_pre_commit_hook.py.tmpl')))
110 ('hook_utils', 'hook_templates', 'svn_pre_commit_hook.py.tmpl')))
111
111
112 path = '' # not used for now
112 path = '' # not used for now
113 timestamp = datetime.datetime.utcnow().isoformat()
113 timestamp = datetime.datetime.utcnow().isoformat()
114
114
115 for h_type, template in [('pre', tmpl_pre), ('post', tmpl_post)]:
115 for h_type, template in [('pre', tmpl_pre), ('post', tmpl_post)]:
116 log.debug('Installing svn hook in repo %s', repo_path)
116 log.debug('Installing svn hook in repo %s', repo_path)
117 _hook_file = os.path.join(hooks_path, '%s-commit' % h_type)
117 _hook_file = os.path.join(hooks_path, '%s-commit' % h_type)
118 _rhodecode_hook = check_rhodecode_hook(_hook_file)
118 _rhodecode_hook = check_rhodecode_hook(_hook_file)
119
119
120 if _rhodecode_hook or force_create:
120 if _rhodecode_hook or force_create:
121 log.debug('writing svn %s hook file at %s !', h_type, _hook_file)
121 log.debug('writing svn %s hook file at %s !', h_type, _hook_file)
122
122
123 try:
123 try:
124 with open(_hook_file, 'wb') as f:
124 with open(_hook_file, 'wb') as f:
125 template = template.replace(b'_TMPL_', safe_bytes(vcsserver.__version__))
125 template = template.replace(b'_TMPL_', safe_bytes(vcsserver.__version__))
126 template = template.replace(b'_DATE_', safe_bytes(timestamp))
126 template = template.replace(b'_DATE_', safe_bytes(timestamp))
127 template = template.replace(b'_ENV_', safe_bytes(executable))
127 template = template.replace(b'_ENV_', safe_bytes(executable))
128 template = template.replace(b'_PATH_', safe_bytes(path))
128 template = template.replace(b'_PATH_', safe_bytes(path))
129
129
130 f.write(template)
130 f.write(template)
131 os.chmod(_hook_file, 0o755)
131 os.chmod(_hook_file, 0o755)
132 except IOError:
132 except IOError:
133 log.exception('error writing hook file %s', _hook_file)
133 log.exception('error writing hook file %s', _hook_file)
134 else:
134 else:
135 log.debug('skipping writing hook file')
135 log.debug('skipping writing hook file')
136
136
137 return True
137 return True
138
138
139
139
140 def get_version_from_hook(hook_path):
140 def get_version_from_hook(hook_path):
141 version = b''
141 version = b''
142 hook_content = read_hook_content(hook_path)
142 hook_content = read_hook_content(hook_path)
143 matches = re.search(rb'(?:RC_HOOK_VER)\s*=\s*(.*)', hook_content)
143 matches = re.search(rb'RC_HOOK_VER\s*=\s*(.*)', hook_content)
144 if matches:
144 if matches:
145 try:
145 try:
146 version = matches.groups()[0]
146 version = matches.groups()[0]
147 log.debug('got version %s from hooks.', version)
147 log.debug('got version %s from hooks.', version)
148 except Exception:
148 except Exception:
149 log.exception("Exception while reading the hook version.")
149 log.exception("Exception while reading the hook version.")
150 return version.replace(b"'", b"")
150 return version.replace(b"'", b"")
151
151
152
152
153 def check_rhodecode_hook(hook_path):
153 def check_rhodecode_hook(hook_path):
154 """
154 """
155 Check if the hook was created by RhodeCode
155 Check if the hook was created by RhodeCode
156 """
156 """
157 if not os.path.exists(hook_path):
157 if not os.path.exists(hook_path):
158 return True
158 return True
159
159
160 log.debug('hook exists, checking if it is from RhodeCode')
160 log.debug('hook exists, checking if it is from RhodeCode')
161
161
162 version = get_version_from_hook(hook_path)
162 version = get_version_from_hook(hook_path)
163 if version:
163 if version:
164 return True
164 return True
165
165
166 return False
166 return False
167
167
168
168
169 def read_hook_content(hook_path) -> bytes:
169 def read_hook_content(hook_path) -> bytes:
170 content = b''
170 content = b''
171 if os.path.isfile(hook_path):
171 if os.path.isfile(hook_path):
172 with open(hook_path, 'rb') as f:
172 with open(hook_path, 'rb') as f:
173 content = f.read()
173 content = f.read()
174 return content
174 return content
175
175
176
176
177 def get_git_pre_hook_version(repo_path, bare):
177 def get_git_pre_hook_version(repo_path, bare):
178 hooks_path = get_git_hooks_path(repo_path, bare)
178 hooks_path = get_git_hooks_path(repo_path, bare)
179 _hook_file = os.path.join(hooks_path, 'pre-receive')
179 _hook_file = os.path.join(hooks_path, 'pre-receive')
180 version = get_version_from_hook(_hook_file)
180 version = get_version_from_hook(_hook_file)
181 return version
181 return version
182
182
183
183
184 def get_git_post_hook_version(repo_path, bare):
184 def get_git_post_hook_version(repo_path, bare):
185 hooks_path = get_git_hooks_path(repo_path, bare)
185 hooks_path = get_git_hooks_path(repo_path, bare)
186 _hook_file = os.path.join(hooks_path, 'post-receive')
186 _hook_file = os.path.join(hooks_path, 'post-receive')
187 version = get_version_from_hook(_hook_file)
187 version = get_version_from_hook(_hook_file)
188 return version
188 return version
189
189
190
190
191 def get_svn_pre_hook_version(repo_path):
191 def get_svn_pre_hook_version(repo_path):
192 hooks_path = get_svn_hooks_path(repo_path)
192 hooks_path = get_svn_hooks_path(repo_path)
193 _hook_file = os.path.join(hooks_path, 'pre-commit')
193 _hook_file = os.path.join(hooks_path, 'pre-commit')
194 version = get_version_from_hook(_hook_file)
194 version = get_version_from_hook(_hook_file)
195 return version
195 return version
196
196
197
197
198 def get_svn_post_hook_version(repo_path):
198 def get_svn_post_hook_version(repo_path):
199 hooks_path = get_svn_hooks_path(repo_path)
199 hooks_path = get_svn_hooks_path(repo_path)
200 _hook_file = os.path.join(hooks_path, 'post-commit')
200 _hook_file = os.path.join(hooks_path, 'post-commit')
201 version = get_version_from_hook(_hook_file)
201 version = get_version_from_hook(_hook_file)
202 return version
202 return version
General Comments 0
You need to be logged in to leave comments. Login now