Changeset - 6a90b1ebea2c
[Not reviewed]
default
0 1 0
Mads Kiilerich (mads) - 5 years ago 2020-11-04 13:19:18
mads@kiilerich.com
Grafted from: 501bdf382118
git: write Git hook files atomically

Make sure we don't follow symlinks or inherit permissions from previously
installed hook.
1 file changed with 7 insertions and 4 deletions:
0 comments (0 inline, 0 general)
kallithea/model/scm.py
Show inline comments
 
@@ -9,48 +9,49 @@
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
"""
 
kallithea.model.scm
 
~~~~~~~~~~~~~~~~~~~
 

	
 
Scm model for Kallithea
 

	
 
This file was forked by the Kallithea project in July 2014.
 
Original author and date, and relevant copyright and licensing information is below:
 
:created_on: Apr 9, 2010
 
:author: marcink
 
:copyright: (c) 2013 RhodeCode GmbH, and others.
 
:license: GPLv3, see LICENSE.md for more details.
 
"""
 

	
 
import logging
 
import os
 
import posixpath
 
import re
 
import sys
 
import tempfile
 
import traceback
 

	
 
import pkg_resources
 
from tg.i18n import ugettext as _
 

	
 
import kallithea
 
from kallithea.lib.auth import HasPermissionAny, HasRepoGroupPermissionLevel, HasRepoPermissionLevel, HasUserGroupPermissionLevel
 
from kallithea.lib.exceptions import IMCCommitError, NonRelativePathError
 
from kallithea.lib.hooks import process_pushed_raw_ids
 
from kallithea.lib.utils import action_logger, get_filesystem_repos, make_ui
 
from kallithea.lib.utils2 import safe_bytes, safe_str, set_hook_environment
 
from kallithea.lib.vcs import get_repo
 
from kallithea.lib.vcs.backends.base import EmptyChangeset
 
from kallithea.lib.vcs.exceptions import RepositoryError, VCSError
 
from kallithea.lib.vcs.nodes import FileNode
 
from kallithea.lib.vcs.utils.lazy import LazyProperty
 
from kallithea.model import db, meta
 

	
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class UserTemp(object):
 
    def __init__(self, user_id):
 
@@ -681,48 +682,50 @@ class ScmModel(object):
 
            'kallithea', os.path.join('templates', 'py', 'git_pre_receive_hook.py')
 
        )
 

	
 
        for h_type, tmpl in [('pre-receive', tmpl_pre), ('post-receive', tmpl_post)]:
 
            hook_file = os.path.join(hooks_path, h_type)
 
            other_hook = False
 
            log.debug('Installing git hook in repo %s', repo)
 
            if os.path.exists(hook_file):
 
                log.debug('hook exists, checking if it is from kallithea')
 
                with open(hook_file, 'rb') as f:
 
                    data = f.read()
 
                    matches = re.search(br'^KALLITHEA_HOOK_VER\s*=\s*(.*)$', data, flags=re.MULTILINE)
 
                    if matches:
 
                        ver = safe_str(matches.group(1))
 
                        log.debug('Found Kallithea hook - it has KALLITHEA_HOOK_VER %s', ver)
 
                    else:
 
                        log.debug('Found non-Kallithea hook at %s', hook_file)
 
                        other_hook = True
 

	
 
            if other_hook and not force:
 
                log.warning('skipping overwriting hook file %s', hook_file)
 
            else:
 
                log.debug('writing %s hook file !', h_type)
 
                try:
 
                    with open(hook_file, 'wb') as f:
 
                        f.write(tmpl.replace(b'_TMPL_', safe_bytes(kallithea.__version__)))
 
                    os.chmod(hook_file, 0o755)
 
                except IOError as e:
 
                    fh, fn = tempfile.mkstemp(prefix=hook_file + '.tmp.')
 
                    os.write(fh, tmpl.replace(b'_TMPL_', safe_bytes(kallithea.__version__)))
 
                    os.close(fh)
 
                    os.chmod(fn, 0o755)
 
                    os.rename(fn, hook_file)
 
                except (OSError, IOError) as e:
 
                    log.error('error writing hook %s: %s', hook_file, e)
 

	
 

	
 
def AvailableRepoGroupChoices(repo_group_perm_level, extras=()):
 
    """Return group_id,string tuples with choices for all the repo groups where
 
    the user has the necessary permissions.
 

	
 
    Top level is -1.
 
    """
 
    groups = db.RepoGroup.query().all()
 
    if HasPermissionAny('hg.admin')('available repo groups'):
 
        groups.append(None)
 
    else:
 
        groups = list(RepoGroupList(groups, perm_level=repo_group_perm_level))
 
        if HasPermissionAny('hg.create.repository')('available repo groups'):
 
            groups.append(None)
 
        for extra in extras:
 
            if not any(rg == extra for rg in groups):
 
                groups.append(extra)
 
    return db.RepoGroup.groups_choices(groups=groups)
0 comments (0 inline, 0 general)