diff --git a/vcsserver/hook_utils/__init__.py b/vcsserver/hook_utils/__init__.py --- a/vcsserver/hook_utils/__init__.py +++ b/vcsserver/hook_utils/__init__.py @@ -142,9 +142,9 @@ def install_svn_hooks(repo_path, executa env_expand = str([ ('RC_CORE_BINARY_DIR', vcsserver.settings.BINARY_DIR), - ('RC_GIT_EXECUTABLE', vcsserver.settings.GIT_EXECUTABLE), - ('RC_SVN_EXECUTABLE', vcsserver.settings.SVN_EXECUTABLE), - ('RC_SVNLOOK_EXECUTABLE', vcsserver.settings.SVNLOOK_EXECUTABLE), + ('RC_GIT_EXECUTABLE', vcsserver.settings.GIT_EXECUTABLE()), + ('RC_SVN_EXECUTABLE', vcsserver.settings.SVN_EXECUTABLE()), + ('RC_SVNLOOK_EXECUTABLE', vcsserver.settings.SVNLOOK_EXECUTABLE()), ]) try: diff --git a/vcsserver/hooks.py b/vcsserver/hooks.py --- a/vcsserver/hooks.py +++ b/vcsserver/hooks.py @@ -31,7 +31,6 @@ from celery import Celery import mercurial.scmutil import mercurial.node -import vcsserver.settings from vcsserver.lib.rc_json import json from vcsserver import exceptions, subprocessio, settings from vcsserver.str_utils import ascii_str, safe_str @@ -294,20 +293,23 @@ def _get_hg_env(old_rev, new_rev, txnid, return [(k, v) for k, v in env.items()] -def _fix_hooks_executables(): +def _fix_hooks_executables(ini_path=''): """ This is a trick to set proper settings.EXECUTABLE paths for certain execution patterns especially for subversion where hooks strip entire env, and calling just 'svn' command will most likely fail because svn is not on PATH """ - vcsserver.settings.BINARY_DIR = ( - os.environ.get('RC_BINARY_DIR') or vcsserver.settings.BINARY_DIR) - vcsserver.settings.GIT_EXECUTABLE = ( - os.environ.get('RC_GIT_EXECUTABLE') or vcsserver.settings.GIT_EXECUTABLE) - vcsserver.settings.SVN_EXECUTABLE = ( - os.environ.get('RC_SVN_EXECUTABLE') or vcsserver.settings.SVN_EXECUTABLE) - vcsserver.settings.SVNLOOK_EXECUTABLE = ( - os.environ.get('RC_SVNLOOK_EXECUTABLE') or vcsserver.settings.SVNLOOK_EXECUTABLE) + from vcsserver.http_main import sanitize_settings_and_apply_defaults + from vcsserver.lib.config_utils import get_app_config_lightweight + + core_binary_dir = settings.BINARY_DIR or '/usr/local/bin/rhodecode_bin/vcs_bin' + if ini_path: + + ini_settings = get_app_config_lightweight(ini_path) + ini_settings = sanitize_settings_and_apply_defaults({'__file__': ini_path}, ini_settings) + core_binary_dir = ini_settings['core.binary_dir'] + + settings.BINARY_DIR = core_binary_dir def repo_size(ui, repo, **kwargs): @@ -568,10 +570,12 @@ def git_pre_receive(unused_repo_path, re rev_data = _parse_git_ref_lines(revision_lines) if 'push' not in extras['hooks']: return 0 + _fix_hooks_executables() + empty_commit_id = '0' * 40 detect_force_push = extras.get('detect_force_push') - _fix_hooks_executables() + for push_ref in rev_data: # store our git-env which holds the temp store push_ref['git_env'] = _get_git_env() @@ -586,7 +590,7 @@ def git_pre_receive(unused_repo_path, re if type_ == 'heads' and not (new_branch or delete_branch): old_rev = push_ref['old_rev'] new_rev = push_ref['new_rev'] - cmd = [settings.GIT_EXECUTABLE, 'rev-list', old_rev, f'^{new_rev}'] + cmd = [settings.GIT_EXECUTABLE(), 'rev-list', old_rev, f'^{new_rev}'] stdout, stderr = subprocessio.run_command( cmd, env=os.environ.copy()) # means we're having some non-reachable objects, this forced push was used @@ -611,6 +615,7 @@ def git_post_receive(unused_repo_path, r extras = json.loads(env['RC_SCM_DATA']) if 'push' not in extras['hooks']: return 0 + _fix_hooks_executables() rev_data = _parse_git_ref_lines(revision_lines) @@ -645,14 +650,14 @@ def git_post_receive(unused_repo_path, r repo.set_head(need_head_set) print(f"Setting default branch to {push_ref_name}") - cmd = [settings.GIT_EXECUTABLE, 'for-each-ref', '--format=%(refname)', 'refs/heads/*'] + cmd = [settings.GIT_EXECUTABLE(), 'for-each-ref', '--format=%(refname)', 'refs/heads/*'] stdout, stderr = subprocessio.run_command( cmd, env=os.environ.copy()) heads = safe_str(stdout) heads = heads.replace(push_ref['ref'], '') heads = ' '.join(head for head in heads.splitlines() if head) or '.' - cmd = [settings.GIT_EXECUTABLE, 'log', '--reverse', + cmd = [settings.GIT_EXECUTABLE(), 'log', '--reverse', '--pretty=format:%H', '--', push_ref['new_rev'], '--not', heads] stdout, stderr = subprocessio.run_command( @@ -666,7 +671,7 @@ def git_post_receive(unused_repo_path, r if push_ref['name'] not in branches: branches.append(push_ref['name']) - cmd = [settings.GIT_EXECUTABLE, 'log', + cmd = [settings.GIT_EXECUTABLE(), 'log', f'{push_ref["old_rev"]}..{push_ref["new_rev"]}', '--reverse', '--pretty=format:%H'] stdout, stderr = subprocessio.run_command( @@ -716,9 +721,11 @@ def git_post_receive(unused_repo_path, r def _get_extras_from_txn_id(path, txn_id): + _fix_hooks_executables() + extras = {} try: - cmd = [settings.SVNLOOK_EXECUTABLE, 'pget', + cmd = [settings.SVNLOOK_EXECUTABLE(), 'pget', '-t', txn_id, '--revprop', path, 'rc-scm-extras'] stdout, stderr = subprocessio.run_command( @@ -731,9 +738,11 @@ def _get_extras_from_txn_id(path, txn_id def _get_extras_from_commit_id(commit_id, path): + _fix_hooks_executables() + extras = {} try: - cmd = [settings.SVNLOOK_EXECUTABLE, 'pget', + cmd = [settings.SVNLOOK_EXECUTABLE(), 'pget', '-r', commit_id, '--revprop', path, 'rc-scm-extras'] stdout, stderr = subprocessio.run_command( @@ -746,11 +755,11 @@ def _get_extras_from_commit_id(commit_id def svn_pre_commit(repo_path, commit_data, env): + path, txn_id = commit_data branches = [] tags = [] - _fix_hooks_executables() if env.get('RC_SCM_DATA'): extras = json.loads(env['RC_SCM_DATA']) else: @@ -790,7 +799,6 @@ def svn_post_commit(repo_path, commit_da branches = [] tags = [] - _fix_hooks_executables() if env.get('RC_SCM_DATA'): extras = json.loads(env['RC_SCM_DATA']) else: diff --git a/vcsserver/http_main.py b/vcsserver/http_main.py --- a/vcsserver/http_main.py +++ b/vcsserver/http_main.py @@ -263,11 +263,6 @@ class HTTPApplication: settings.BINARY_DIR = binary_dir - # from core.binary dir we set executable paths - settings.GIT_EXECUTABLE = os.path.join(binary_dir, settings.GIT_EXECUTABLE) - settings.SVN_EXECUTABLE = os.path.join(binary_dir, settings.SVN_EXECUTABLE) - settings.SVNLOOK_EXECUTABLE = os.path.join(binary_dir, settings.SVNLOOK_EXECUTABLE) - # Store the settings to make them available to other modules. vcsserver.PYRAMID_SETTINGS = settings_merged vcsserver.CONFIG = settings_merged diff --git a/vcsserver/remote/git_remote.py b/vcsserver/remote/git_remote.py --- a/vcsserver/remote/git_remote.py +++ b/vcsserver/remote/git_remote.py @@ -1424,7 +1424,7 @@ class GitRemote(RemoteBase): gitenv['GIT_CONFIG_NOGLOBAL'] = '1' gitenv['GIT_DISCOVERY_ACROSS_FILESYSTEM'] = '1' - cmd = [settings.GIT_EXECUTABLE] + _copts + cmd + cmd = [settings.GIT_EXECUTABLE()] + _copts + cmd _opts = {'env': gitenv, 'shell': False} proc = None diff --git a/vcsserver/scm_app.py b/vcsserver/scm_app.py --- a/vcsserver/scm_app.py +++ b/vcsserver/scm_app.py @@ -214,7 +214,7 @@ def create_git_wsgi_app(repo_path, repo_ :param config: is a dictionary holding the extras. """ - git_path = settings.GIT_EXECUTABLE + git_path = settings.GIT_EXECUTABLE() update_server_info = config.pop('git_update_server_info') app = GitHandler( repo_path, repo_name, git_path, update_server_info, config) @@ -244,7 +244,7 @@ class GitLFSHandler: def create_git_lfs_wsgi_app(repo_path, repo_name, config): - git_path = settings.GIT_EXECUTABLE + git_path = settings.GIT_EXECUTABLE() update_server_info = config.pop('git_update_server_info') git_lfs_enabled = config.pop('git_lfs_enabled') git_lfs_store_path = config.pop('git_lfs_store_path') diff --git a/vcsserver/settings.py b/vcsserver/settings.py --- a/vcsserver/settings.py +++ b/vcsserver/settings.py @@ -14,9 +14,18 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +import os WIRE_ENCODING = 'UTF-8' -GIT_EXECUTABLE = 'git' -SVN_EXECUTABLE = 'svn' -SVNLOOK_EXECUTABLE = 'svnlook' + +# Path where we can find binary dir BINARY_DIR = '' + +def GIT_EXECUTABLE() -> str: + return os.environ.get('RC_GIT_EXECUTABLE') or os.path.join(BINARY_DIR, 'git') + +def SVN_EXECUTABLE() -> str: + return os.environ.get('RC_SVN_EXECUTABLE') or os.path.join(BINARY_DIR, 'svn') + +def SVNLOOK_EXECUTABLE() -> str: + return os.environ.get('RC_SVNLOOK_EXECUTABLE') or os.path.join(BINARY_DIR, 'svnlook')