##// END OF EJS Templates
i18n: updated translation for Polish...
i18n: updated translation for Polish Currently translated at 56.5% (614 of 1087 strings)

File last commit:

r8076:e51ad2cd default
r8092:7fef5132 default
Show More
scm.py
767 lines | 27.8 KiB | text/x-python | PythonLexer
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 # -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# 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
~~~~~~~~~~~~~~~~~~~
Bradley M. Kuhn
General renaming to Kallithea
r4212 Scm model for Kallithea
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Bradley M. Kuhn
RhodeCode GmbH is not the sole author of this work
r4211 This file was forked by the Kallithea project in July 2014.
Original author and date, and relevant copyright and licensing information is below:
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 :created_on: Apr 9, 2010
:author: marcink
Bradley M. Kuhn
RhodeCode GmbH is not the sole author of this work
r4211 :copyright: (c) 2013 RhodeCode GmbH, and others.
Bradley M. Kuhn
Correct licensing information in individual files....
r4208 :license: GPLv3, see LICENSE.md for more details.
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 """
Mads Kiilerich
scripts: initial run of import cleanup using isort
r7718 import logging
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 import os
domruf
windows: node paths should always use posixpath - avoid \ in repo internal paths on windows...
r5716 import posixpath
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 import re
Mads Kiilerich
scripts: initial run of import cleanup using isort
r7718 import sys
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 import traceback
Mads Kiilerich
scripts: initial run of import cleanup using isort
r7718
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 import pkg_resources
Mads Kiilerich
tg: minimize future diff by some mocking and replacing some pylons imports with tg...
r6508 from tg.i18n import ugettext as _
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
import kallithea
from kallithea import BACKENDS
Mads Kiilerich
scripts: initial run of import cleanup using isort
r7718 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
Mads Kiilerich
py3: drop the last uses of safe_str - they are no longer relevant when we don't have a separate unicode type
r8076 from kallithea.lib.utils2 import safe_bytes, set_hook_environment
Mads Kiilerich
scripts: initial run of import cleanup using isort
r7718 from kallithea.lib.vcs import get_backend
from kallithea.lib.vcs.backends.base import EmptyChangeset
from kallithea.lib.vcs.exceptions import RepositoryError
from kallithea.lib.vcs.nodes import FileNode
from kallithea.lib.vcs.utils.lazy import LazyProperty
Mads Kiilerich
model: use repo.set_invalidate() instead of accesssing CacheInvalidation directly...
r7828 from kallithea.model.db import PullRequest, RepoGroup, Repository, Session, Ui, User, UserFollowing, UserLog
Mads Kiilerich
scripts: initial run of import cleanup using isort
r7718
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
log = logging.getLogger(__name__)
class UserTemp(object):
def __init__(self, user_id):
self.user_id = user_id
def __repr__(self):
return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
class RepoTemp(object):
def __init__(self, repo_id):
self.repo_id = repo_id
def __repr__(self):
return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
class _PermCheckIterator(object):
def __init__(self, obj_list, obj_attr, perm_set, perm_checker, extra_kwargs=None):
"""
Creates iterator from given list of objects, additionally
checking permission for them from perm_set var
:param obj_list: list of db objects
:param obj_attr: attribute of object to pass into perm_checker
:param perm_set: list of permissions to check
:param perm_checker: callable to check permissions against
"""
self.obj_list = obj_list
self.obj_attr = obj_attr
self.perm_set = perm_set
self.perm_checker = perm_checker
self.extra_kwargs = extra_kwargs or {}
def __len__(self):
return len(self.obj_list)
def __repr__(self):
return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
def __iter__(self):
for db_obj in self.obj_list:
# check permission at this level
name = getattr(db_obj, self.obj_attr, None)
if not self.perm_checker(*self.perm_set)(
name, self.__class__.__name__, **self.extra_kwargs):
continue
yield db_obj
class RepoList(_PermCheckIterator):
Søren Løvborg
auth: simplify repository permission checks...
r6471 def __init__(self, db_repo_list, perm_level, extra_kwargs=None):
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 super(RepoList, self).__init__(obj_list=db_repo_list,
Søren Løvborg
auth: simplify repository permission checks...
r6471 obj_attr='repo_name', perm_set=[perm_level],
perm_checker=HasRepoPermissionLevel,
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 extra_kwargs=extra_kwargs)
class RepoGroupList(_PermCheckIterator):
Søren Løvborg
auth: simplify repository group permission checks...
r6472 def __init__(self, db_repo_group_list, perm_level, extra_kwargs=None):
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 super(RepoGroupList, self).__init__(obj_list=db_repo_group_list,
Søren Løvborg
auth: simplify repository group permission checks...
r6472 obj_attr='group_name', perm_set=[perm_level],
perm_checker=HasRepoGroupPermissionLevel,
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 extra_kwargs=extra_kwargs)
class UserGroupList(_PermCheckIterator):
Søren Løvborg
auth: simplify user group permission checks...
r6473 def __init__(self, db_user_group_list, perm_level, extra_kwargs=None):
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 super(UserGroupList, self).__init__(obj_list=db_user_group_list,
Søren Løvborg
auth: simplify user group permission checks...
r6473 obj_attr='users_group_name', perm_set=[perm_level],
perm_checker=HasUserGroupPermissionLevel,
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 extra_kwargs=extra_kwargs)
Søren Løvborg
model: remove BaseModel class...
r6483 class ScmModel(object):
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 """
Generic Scm Model
"""
def __get_repo(self, instance):
cls = Repository
if isinstance(instance, cls):
return instance
Mads Kiilerich
cleanup: drop some unnecessary use of safe_str
r7908 elif isinstance(instance, int):
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 return cls.get(instance)
Mads Kiilerich
py3: automatic migration with 2to3 -f basestring
r8064 elif isinstance(instance, str):
Mads Kiilerich
cleanup: drop some unnecessary use of safe_str
r7908 if instance.isdigit():
return cls.get(int(instance))
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 return cls.get_by_repo_name(instance)
Mads Kiilerich
cleanup: check for None object identity in cases where that is what the 'contract' says...
r5306 elif instance is not None:
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 raise Exception('given object must be int, basestr or Instance'
' of %s got %s' % (type(cls), type(instance)))
@LazyProperty
def repos_path(self):
"""
Gets the repositories root path from database
"""
Søren Løvborg
model: remove BaseModel class...
r6483 q = Ui.query().filter(Ui.ui_key == '/').one()
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
return q.ui_value
def repo_scan(self, repos_path=None):
"""
Listing of repositories in given path. This path should not be a
Mads Kiilerich
lib: clarify that repo2db_mapper actually takes a dict
r7946 repository itself. Return a dictionary of repository objects mapping to
vcs instances.
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
:param repos_path: path to directory containing repositories
"""
if repos_path is None:
repos_path = self.repos_path
Mads Kiilerich
cleanup: pass log strings unformatted - avoid unnecessary % formatting when not logging
r5375 log.info('scanning for repositories in %s', repos_path)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
utils: refactor make_ui to always read from db, optionally also augmenting with hgrc content...
r7580 baseui = make_ui()
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 repos = {}
Mads Kiilerich
repo-scan: rewrite get_filesystem_repos to use os.walk instead of stupid recursion...
r6014 for name, path in get_filesystem_repos(repos_path):
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 # name need to be decomposed and put back together using the /
Bradley M. Kuhn
General renaming to Kallithea
r4212 # since this is internal storage separator for kallithea
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 name = Repository.normalize_repo_name(name)
try:
if name in repos:
raise RepositoryError('Duplicate repository name %s '
'found in %s' % (name, path))
else:
klass = get_backend(path[0])
Mads Kiilerich
cleanup: minor refactorings and simplification of dict usage...
r7906 if path[0] == 'hg' and path[0] in BACKENDS:
Mads Kiilerich
py3: drop the last uses of safe_str - they are no longer relevant when we don't have a separate unicode type
r8076 repos[name] = klass(path[1], baseui=baseui)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
cleanup: minor refactorings and simplification of dict usage...
r7906 if path[0] == 'git' and path[0] in BACKENDS:
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 repos[name] = klass(path[1])
except OSError:
continue
Mads Kiilerich
cleanup: pass log strings unformatted - avoid unnecessary % formatting when not logging
r5375 log.debug('found %s paths with repositories', len(repos))
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 return repos
Mads Kiilerich
scm: simplify get_repos and get rid of RepoList overloads...
r5734 def get_repos(self, repos):
"""Return the repos the user has access to"""
Søren Løvborg
auth: simplify repository permission checks...
r6471 return RepoList(repos, perm_level='read')
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
scm: simplify get_repos and get rid of RepoList overloads...
r5734 def get_repo_groups(self, groups=None):
"""Return the repo groups the user has access to
If no groups are specified, use top level groups.
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 """
Mads Kiilerich
scm: simplify get_repos and get rid of RepoList overloads...
r5734 if groups is None:
groups = RepoGroup.query() \
Søren Løvborg
db: rename RepoGroup.group_parent_id to parent_group_id...
r6280 .filter(RepoGroup.parent_group_id == None).all()
Søren Løvborg
auth: simplify repository group permission checks...
r6472 return RepoGroupList(groups, perm_level='read')
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
cache: when invalidating a cache, always just delete all 'live cache' records instead of marking them inactive...
r5533 def mark_for_invalidation(self, repo_name):
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 """
Mark caches of this repo invalid in the database.
:param repo_name: the repo for which caches should be marked invalid
"""
Mads Kiilerich
scm: remove redundant cache invalidations - hook invocations will usually do the work
r7635 log.debug("Marking %s as invalidated and update cache", repo_name)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 repo = Repository.get_by_repo_name(repo_name)
Mads Kiilerich
cleanup: check for None object identity in cases where that is what the 'contract' says...
r5306 if repo is not None:
Mads Kiilerich
model: use repo.set_invalidate() instead of accesssing CacheInvalidation directly...
r7828 repo.set_invalidate()
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 repo.update_changeset_cache()
def toggle_following_repo(self, follow_repo_id, user_id):
Søren Løvborg
model: remove BaseModel class...
r6483 f = UserFollowing.query() \
Søren Løvborg
db: rename UserFollowing.follows_repo_id to follows_repository_id...
r6281 .filter(UserFollowing.follows_repository_id == follow_repo_id) \
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 .filter(UserFollowing.user_id == user_id).scalar()
if f is not None:
try:
Søren Løvborg
model: remove BaseModel class...
r6483 Session().delete(f)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 action_logger(UserTemp(user_id),
'stopped_following_repo',
RepoTemp(follow_repo_id))
return
except Exception:
log.error(traceback.format_exc())
raise
try:
f = UserFollowing()
f.user_id = user_id
Søren Løvborg
db: rename UserFollowing.follows_repo_id to follows_repository_id...
r6281 f.follows_repository_id = follow_repo_id
Søren Løvborg
model: remove BaseModel class...
r6483 Session().add(f)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
action_logger(UserTemp(user_id),
'started_following_repo',
RepoTemp(follow_repo_id))
except Exception:
log.error(traceback.format_exc())
raise
def toggle_following_user(self, follow_user_id, user_id):
Søren Løvborg
model: remove BaseModel class...
r6483 f = UserFollowing.query() \
Mads Kiilerich
cleanup: consistent space before line continuation backslash
r5585 .filter(UserFollowing.follows_user_id == follow_user_id) \
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 .filter(UserFollowing.user_id == user_id).scalar()
if f is not None:
try:
Søren Løvborg
model: remove BaseModel class...
r6483 Session().delete(f)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 return
except Exception:
log.error(traceback.format_exc())
raise
try:
f = UserFollowing()
f.user_id = user_id
f.follows_user_id = follow_user_id
Søren Løvborg
model: remove BaseModel class...
r6483 Session().add(f)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 except Exception:
log.error(traceback.format_exc())
raise
Mads Kiilerich
caching: drop unused cache control arguments to getters
r7829 def is_following_repo(self, repo_name, user_id):
Søren Løvborg
model: remove BaseModel class...
r6483 r = Repository.query() \
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 .filter(Repository.repo_name == repo_name).scalar()
Søren Løvborg
model: remove BaseModel class...
r6483 f = UserFollowing.query() \
Mads Kiilerich
cleanup: consistent space before line continuation backslash
r5585 .filter(UserFollowing.follows_repository == r) \
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 .filter(UserFollowing.user_id == user_id).scalar()
return f is not None
Mads Kiilerich
caching: drop unused cache control arguments to getters
r7829 def is_following_user(self, username, user_id):
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 u = User.get_by_username(username)
Søren Løvborg
model: remove BaseModel class...
r6483 f = UserFollowing.query() \
Mads Kiilerich
cleanup: consistent space before line continuation backslash
r5585 .filter(UserFollowing.follows_user == u) \
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 .filter(UserFollowing.user_id == user_id).scalar()
return f is not None
def get_followers(self, repo):
Søren Løvborg
model: inline calls to BaseModel._get_repo
r6424 repo = Repository.guess_instance(repo)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Søren Løvborg
model: remove BaseModel class...
r6483 return UserFollowing.query() \
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 .filter(UserFollowing.follows_repository == repo).count()
def get_forks(self, repo):
Søren Løvborg
model: inline calls to BaseModel._get_repo
r6424 repo = Repository.guess_instance(repo)
Søren Løvborg
model: remove BaseModel class...
r6483 return Repository.query() \
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 .filter(Repository.fork == repo).count()
def get_pull_requests(self, repo):
Søren Løvborg
model: inline calls to BaseModel._get_repo
r6424 repo = Repository.guess_instance(repo)
Søren Løvborg
model: remove BaseModel class...
r6483 return PullRequest.query() \
Mads Kiilerich
cleanup: consistent space before line continuation backslash
r5585 .filter(PullRequest.other_repo == repo) \
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 .filter(PullRequest.status != PullRequest.STATUS_CLOSED).count()
def mark_as_fork(self, repo, fork, user):
repo = self.__get_repo(repo)
fork = self.__get_repo(fork)
if fork and repo.repo_id == fork.repo_id:
raise Exception("Cannot set repository as fork of itself")
if fork and repo.repo_type != fork.repo_type:
raise RepositoryError("Cannot set repository as fork of repository with other type")
repo.fork = fork
return repo
Mads Kiilerich
scm: don't try to get IP address from web request in model...
r7632 def _handle_push(self, repo, username, ip_addr, action, repo_name, revisions):
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 """
Mads Kiilerich
hooks: refactor log_push_action...
r7581 Handle that the repository has changed.
Adds an action log entry with the new revisions, and the head revision
cache and in-memory caches are invalidated/updated.
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
:param username: username who pushes
Thomas De Schampheleire
model: trivial typo fixes
r4919 :param action: push/push_local/push_remote
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 :param repo_name: name of repo
:param revisions: list of revisions that we pushed
"""
Mads Kiilerich
hooks: move _handle_rc_scm_extras to utils2 as set_hook_environment and get_hook_environment...
r7634 set_hook_environment(username, ip_addr, repo_name, repo_alias=repo.alias, action=action)
Mads Kiilerich
hooks: refactor log_push_action...
r7581 process_pushed_raw_ids(revisions) # also calls mark_for_invalidation
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
def _get_IMC_module(self, scm_type):
"""
Returns InMemoryCommit class based on scm_type
:param scm_type:
"""
if scm_type == 'hg':
from kallithea.lib.vcs.backends.hg import MercurialInMemoryChangeset
return MercurialInMemoryChangeset
if scm_type == 'git':
from kallithea.lib.vcs.backends.git import GitInMemoryChangeset
return GitInMemoryChangeset
raise Exception('Invalid scm_type, must be one of hg,git got %s'
% (scm_type,))
Mads Kiilerich
scm: don't try to get IP address from web request in model...
r7632 def pull_changes(self, repo, username, ip_addr, clone_uri=None):
Mads Kiilerich
hooks: add some docstrings
r5415 """
domruf
repositories: allow to pull changes from forked repo...
r6603 Pull from "clone URL" or fork origin.
Mads Kiilerich
hooks: add some docstrings
r5415 """
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 dbrepo = self.__get_repo(repo)
Thomas De Schampheleire
api: allow pulling from a custom remote...
r7053 if clone_uri is None:
clone_uri = dbrepo.clone_uri or dbrepo.fork and dbrepo.fork.repo_full_path
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 if not clone_uri:
raise Exception("This repository doesn't have a clone uri")
repo = dbrepo.scm_instance
repo_name = dbrepo.repo_name
try:
if repo.alias == 'git':
repo.fetch(clone_uri)
# git doesn't really have something like post-fetch action
Mads Kiilerich
hooks: refactor log_push_action...
r7581 # we fake that now.
# TODO: extract fetched revisions ... somehow ...
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 self._handle_push(repo,
username=username,
Mads Kiilerich
scm: don't try to get IP address from web request in model...
r7632 ip_addr=ip_addr,
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 action='push_remote',
repo_name=repo_name,
revisions=[])
else:
Mads Kiilerich
hooks: move _handle_rc_scm_extras to utils2 as set_hook_environment and get_hook_environment...
r7634 set_hook_environment(username, ip_addr, dbrepo.repo_name,
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 repo.alias, action='push_remote')
repo.pull(clone_uri)
except Exception:
log.error(traceback.format_exc())
raise
Mads Kiilerich
scm: don't try to get IP address from web request in model...
r7632 def commit_change(self, repo, repo_name, cs, user, ip_addr, author, message,
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 content, f_path):
"""
Mads Kiilerich
hooks: add some docstrings
r5415 Commit a change to a single file
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
hooks: add some docstrings
r5415 :param repo: a db_repo.scm_instance
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 """
Søren Løvborg
model: inline BaseModel._get_user calls
r6423 user = User.guess_instance(user)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 IMC = self._get_IMC_module(repo.alias)
imc = IMC(repo)
Mads Kiilerich
py3: drop the last uses of safe_str - they are no longer relevant when we don't have a separate unicode type
r8076 imc.change(FileNode(f_path, content, mode=cs.get_file_mode(f_path)))
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 try:
tip = imc.commit(message=message, author=author,
parents=[cs], branch=cs.branch)
Mads Kiilerich
cleanup: consistently use 'except ... as ...:'...
r5374 except Exception as e:
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 log.error(traceback.format_exc())
Mads Kiilerich
scm: remove redundant cache invalidations - hook invocations will usually do the work
r7635 # clear caches - we also want a fresh object if commit fails
self.mark_for_invalidation(repo_name)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 raise IMCCommitError(str(e))
self._handle_push(repo,
username=user.username,
Mads Kiilerich
scm: don't try to get IP address from web request in model...
r7632 ip_addr=ip_addr,
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 action='push_local',
repo_name=repo_name,
revisions=[tip.raw_id])
return tip
def _sanitize_path(self, f_path):
if f_path.startswith('/') or f_path.startswith('.') or '../' in f_path:
raise NonRelativePathError('%s is not an relative path' % f_path)
if f_path:
domruf
windows: node paths should always use posixpath - avoid \ in repo internal paths on windows...
r5716 f_path = posixpath.normpath(f_path)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 return f_path
def get_nodes(self, repo_name, revision, root_path='/', flat=True):
"""
Na'Tosha Bard
Fix readability issues in comments
r4526 Recursively walk root dir and return a set of all paths found.
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
:param repo_name: name of repository
:param revision: revision for which to list nodes
:param root_path: root path to list
Na'Tosha Bard
Fix typos in comments
r4525 :param flat: return as a list, if False returns a dict with description
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
"""
_files = list()
_dirs = list()
try:
_repo = self.__get_repo(repo_name)
changeset = _repo.scm_instance.get_changeset(revision)
root_path = root_path.lstrip('/')
for topnode, dirs, files in changeset.walk(root_path):
for f in files:
_files.append(f.path if flat else {"name": f.path,
"type": "file"})
for d in dirs:
_dirs.append(d.path if flat else {"name": d.path,
"type": "dir"})
except RepositoryError:
log.debug(traceback.format_exc())
raise
return _dirs, _files
Mads Kiilerich
scm: don't try to get IP address from web request in model...
r7632 def create_nodes(self, user, ip_addr, repo, message, nodes, parent_cs=None,
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 author=None, trigger_push_hook=True):
"""
Na'Tosha Bard
Fix readability issues in comments
r4526 Commits specified nodes to repo.
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Thomas De Schampheleire
model: trivial typo fixes
r4919 :param user: Kallithea User object or user_id, the committer
Bradley M. Kuhn
General renaming to Kallithea
r4212 :param repo: Kallithea Repository object
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 :param message: commit message
:param nodes: mapping {filename:{'content':content},...}
:param parent_cs: parent changeset, can be empty than it's initial commit
Thomas De Schampheleire
model: trivial typo fixes
r4919 :param author: author of commit, cna be different that committer only for git
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 :param trigger_push_hook: trigger push hooks
Thomas De Schampheleire
model: trivial typo fixes
r4919 :returns: new committed changeset
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 """
Søren Løvborg
model: inline BaseModel._get_user calls
r6423 user = User.guess_instance(user)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 scm_instance = repo.scm_instance_no_cache()
processed_nodes = []
for f_path in nodes:
domruf
scm: don't fail if create_nodes paths actually need normalization - don't look f_path up with the wrong normalized name
r5712 content = nodes[f_path]['content']
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 f_path = self._sanitize_path(f_path)
Mads Kiilerich
py3: drop the last uses of safe_str - they are no longer relevant when we don't have a separate unicode type
r8076 if not isinstance(content, str) and not isinstance(content, bytes):
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 content = content.read()
processed_nodes.append((f_path, content))
Mads Kiilerich
py3: remove safe_unicode in places where it no longer is needed because all strings (except bytes) already *are* unicode strings...
r8075 message = message
Thomas De Schampheleire
model: trivial typo fixes
r4919 committer = user.full_contact
Mads Kiilerich
py3: remove safe_unicode in places where it no longer is needed because all strings (except bytes) already *are* unicode strings...
r8075 if not author:
author = committer
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
IMC = self._get_IMC_module(scm_instance.alias)
imc = IMC(scm_instance)
if not parent_cs:
parent_cs = EmptyChangeset(alias=scm_instance.alias)
if isinstance(parent_cs, EmptyChangeset):
# EmptyChangeset means we we're editing empty repository
parents = None
else:
parents = [parent_cs]
# add multiple nodes
for path, content in processed_nodes:
imc.add(FileNode(path, content=content))
tip = imc.commit(message=message,
author=author,
parents=parents,
branch=parent_cs.branch)
if trigger_push_hook:
self._handle_push(scm_instance,
username=user.username,
Mads Kiilerich
scm: don't try to get IP address from web request in model...
r7632 ip_addr=ip_addr,
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 action='push_local',
repo_name=repo.repo_name,
revisions=[tip.raw_id])
Mads Kiilerich
scm: remove redundant cache invalidations - hook invocations will usually do the work
r7635 else:
self.mark_for_invalidation(repo.repo_name)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 return tip
Mads Kiilerich
scm: don't try to get IP address from web request in model...
r7632 def update_nodes(self, user, ip_addr, repo, message, nodes, parent_cs=None,
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 author=None, trigger_push_hook=True):
Mads Kiilerich
hooks: add some docstrings
r5415 """
Commits specified nodes to repo. Again.
"""
Søren Løvborg
model: inline BaseModel._get_user calls
r6423 user = User.guess_instance(user)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 scm_instance = repo.scm_instance_no_cache()
Mads Kiilerich
py3: remove safe_unicode in places where it no longer is needed because all strings (except bytes) already *are* unicode strings...
r8075 message = message
Thomas De Schampheleire
model: trivial typo fixes
r4919 committer = user.full_contact
Mads Kiilerich
py3: remove safe_unicode in places where it no longer is needed because all strings (except bytes) already *are* unicode strings...
r8075 if not author:
author = committer
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
imc_class = self._get_IMC_module(scm_instance.alias)
imc = imc_class(scm_instance)
if not parent_cs:
parent_cs = EmptyChangeset(alias=scm_instance.alias)
if isinstance(parent_cs, EmptyChangeset):
# EmptyChangeset means we we're editing empty repository
parents = None
else:
parents = [parent_cs]
# add multiple nodes
for _filename, data in nodes.items():
# new filename, can be renamed from the old one
filename = self._sanitize_path(data['filename'])
old_filename = self._sanitize_path(_filename)
content = data['content']
filenode = FileNode(old_filename, content=content)
op = data['op']
if op == 'add':
imc.add(filenode)
elif op == 'del':
imc.remove(filenode)
elif op == 'mod':
if filename != old_filename:
Lars Kruse
codingstyle: trivial whitespace fixes...
r6789 # TODO: handle renames, needs vcs lib changes
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 imc.remove(filenode)
imc.add(FileNode(filename, content=content))
else:
imc.change(filenode)
# commit changes
tip = imc.commit(message=message,
author=author,
parents=parents,
branch=parent_cs.branch)
if trigger_push_hook:
self._handle_push(scm_instance,
username=user.username,
Mads Kiilerich
scm: don't try to get IP address from web request in model...
r7632 ip_addr=ip_addr,
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 action='push_local',
repo_name=repo.repo_name,
revisions=[tip.raw_id])
Mads Kiilerich
scm: remove redundant cache invalidations - hook invocations will usually do the work
r7635 else:
self.mark_for_invalidation(repo.repo_name)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
scm: don't try to get IP address from web request in model...
r7632 def delete_nodes(self, user, ip_addr, repo, message, nodes, parent_cs=None,
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 author=None, trigger_push_hook=True):
"""
Na'Tosha Bard
Fix readability issues in comments
r4526 Deletes specified nodes from repo.
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Thomas De Schampheleire
model: trivial typo fixes
r4919 :param user: Kallithea User object or user_id, the committer
Bradley M. Kuhn
General renaming to Kallithea
r4212 :param repo: Kallithea Repository object
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 :param message: commit message
:param nodes: mapping {filename:{'content':content},...}
:param parent_cs: parent changeset, can be empty than it's initial commit
Thomas De Schampheleire
model: trivial typo fixes
r4919 :param author: author of commit, cna be different that committer only for git
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 :param trigger_push_hook: trigger push hooks
Thomas De Schampheleire
model: trivial typo fixes
r4919 :returns: new committed changeset after deletion
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 """
Søren Løvborg
model: inline BaseModel._get_user calls
r6423 user = User.guess_instance(user)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 scm_instance = repo.scm_instance_no_cache()
processed_nodes = []
for f_path in nodes:
f_path = self._sanitize_path(f_path)
Na'Tosha Bard
Fix typos in comments
r4525 # content can be empty but for compatibility it allows same dicts
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 # structure as add_nodes
content = nodes[f_path].get('content')
processed_nodes.append((f_path, content))
Mads Kiilerich
py3: remove safe_unicode in places where it no longer is needed because all strings (except bytes) already *are* unicode strings...
r8075 message = message
Thomas De Schampheleire
model: trivial typo fixes
r4919 committer = user.full_contact
Mads Kiilerich
py3: remove safe_unicode in places where it no longer is needed because all strings (except bytes) already *are* unicode strings...
r8075 if not author:
author = committer
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
IMC = self._get_IMC_module(scm_instance.alias)
imc = IMC(scm_instance)
if not parent_cs:
parent_cs = EmptyChangeset(alias=scm_instance.alias)
if isinstance(parent_cs, EmptyChangeset):
# EmptyChangeset means we we're editing empty repository
parents = None
else:
parents = [parent_cs]
# add multiple nodes
for path, content in processed_nodes:
imc.remove(FileNode(path, content=content))
tip = imc.commit(message=message,
author=author,
parents=parents,
branch=parent_cs.branch)
if trigger_push_hook:
self._handle_push(scm_instance,
username=user.username,
Mads Kiilerich
scm: don't try to get IP address from web request in model...
r7632 ip_addr=ip_addr,
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 action='push_local',
repo_name=repo.repo_name,
revisions=[tip.raw_id])
Mads Kiilerich
scm: remove redundant cache invalidations - hook invocations will usually do the work
r7635 else:
self.mark_for_invalidation(repo.repo_name)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 return tip
def get_unread_journal(self):
Søren Løvborg
model: remove BaseModel class...
r6483 return UserLog.query().count()
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
def get_repo_landing_revs(self, repo=None):
"""
Generates select option with tags branches and bookmarks (for hg only)
grouped by type
:param repo:
"""
hist_l = []
choices = []
repo = self.__get_repo(repo)
Mads Kiilerich
scm: select options should be tuples - not lists with 2 elements...
r7740 hist_l.append(('rev:tip', _('latest tip')))
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 choices.append('rev:tip')
Mads Kiilerich
cleanup: check for None object identity in cases where that is what the 'contract' says...
r5306 if repo is None:
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 return choices, hist_l
repo = repo.scm_instance
branches_group = ([(u'branch:%s' % k, k) for k, v in
Mads Kiilerich
py3: trivial renaming of .iteritems() to .items()...
r8059 repo.branches.items()], _("Branches"))
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 hist_l.append(branches_group)
choices.extend([x[0] for x in branches_group[0]])
if repo.alias == 'hg':
bookmarks_group = ([(u'book:%s' % k, k) for k, v in
Mads Kiilerich
py3: trivial renaming of .iteritems() to .items()...
r8059 repo.bookmarks.items()], _("Bookmarks"))
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 hist_l.append(bookmarks_group)
choices.extend([x[0] for x in bookmarks_group[0]])
tags_group = ([(u'tag:%s' % k, k) for k, v in
Mads Kiilerich
py3: trivial renaming of .iteritems() to .items()...
r8059 repo.tags.items()], _("Tags"))
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 hist_l.append(tags_group)
choices.extend([x[0] for x in tags_group[0]])
return choices, hist_l
Thomas De Schampheleire
hooks: add intermediate function _get_git_hook_interpreter...
r7536 def _get_git_hook_interpreter(self):
"""Return a suitable interpreter for Git hooks.
Return a suitable string to be written in the POSIX #! shebang line for
Git hook scripts so they invoke Kallithea code with the right Python
interpreter and in the right environment.
"""
Thomas De Schampheleire
hooks: make the Python interpreter for Git hooks configurable as 'git_hook_interpreter' (Issue #333)...
r7538 # Note: sys.executable might not point at a usable Python interpreter. For
# example, when using uwsgi, it will point at the uwsgi program itself.
Thomas De Schampheleire
hooks: add intermediate function _get_git_hook_interpreter...
r7536 # FIXME This may not work on Windows and may need a shell wrapper script.
Thomas De Schampheleire
hooks: make the Python interpreter for Git hooks configurable as 'git_hook_interpreter' (Issue #333)...
r7538 return (kallithea.CONFIG.get('git_hook_interpreter')
or sys.executable
Mads Kiilerich
py3: switch to use Python 3 interpreter, temporarily leaving many things very broken until they have been migrated/fixed in a reviewable way...
r8053 or '/usr/bin/env python3')
Thomas De Schampheleire
hooks: add intermediate function _get_git_hook_interpreter...
r7536
Branko Majic
git: add option for forcing overwrite of Git hooks when remapping and rescanning the repositories. (Issue #153)...
r5452 def install_git_hooks(self, repo, force_create=False):
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 """
Bradley M. Kuhn
General renaming to Kallithea
r4212 Creates a kallithea hook inside a git repository
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
:param repo: Instance of VCS repo
:param force_create: Create even if same name hook exists
"""
domruf
cleanup: get rid of jn as shortcut for os.path.join...
r5960 loc = os.path.join(repo.path, 'hooks')
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 if not repo.bare:
domruf
cleanup: get rid of jn as shortcut for os.path.join...
r5960 loc = os.path.join(repo.path, '.git', 'hooks')
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 if not os.path.isdir(loc):
os.makedirs(loc)
Mads Kiilerich
py3: add safe_bytes in places where we will need it and where it doesn't do any harm
r7992 tmpl_post = b"#!%s\n" % safe_bytes(self._get_git_hook_interpreter())
domruf
hooks: if available, use sys.executable as executable for git hooks...
r5927 tmpl_post += pkg_resources.resource_string(
domruf
cleanup: get rid of jn as shortcut for os.path.join...
r5960 'kallithea', os.path.join('config', 'post_receive_tmpl.py')
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 )
Mads Kiilerich
py3: add safe_bytes in places where we will need it and where it doesn't do any harm
r7992 tmpl_pre = b"#!%s\n" % safe_bytes(self._get_git_hook_interpreter())
domruf
hooks: if available, use sys.executable as executable for git hooks...
r5927 tmpl_pre += pkg_resources.resource_string(
domruf
cleanup: get rid of jn as shortcut for os.path.join...
r5960 'kallithea', os.path.join('config', 'pre_receive_tmpl.py')
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 )
for h_type, tmpl in [('pre', tmpl_pre), ('post', tmpl_post)]:
domruf
cleanup: get rid of jn as shortcut for os.path.join...
r5960 _hook_file = os.path.join(loc, '%s-receive' % h_type)
Bradley M. Kuhn
Cleanup of git hook installation
r4205 has_hook = False
Mads Kiilerich
cleanup: pass log strings unformatted - avoid unnecessary % formatting when not logging
r5375 log.debug('Installing git hook in repo %s', repo)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 if os.path.exists(_hook_file):
Bradley M. Kuhn
General renaming to Kallithea
r4212 # let's take a look at this hook, maybe it's kallithea ?
log.debug('hook exists, checking if it is from kallithea')
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 with open(_hook_file, 'rb') as f:
data = f.read()
Mads Kiilerich
git: clean up safety check for overwriting hooks
r7952 matches = re.search(br'^KALLITHEA_HOOK_VER\s*=\s*(.*)$', data, flags=re.MULTILINE)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 if matches:
try:
ver = matches.groups()[0]
Mads Kiilerich
git: clean up safety check for overwriting hooks
r7952 log.debug('Found Kallithea hook - it has KALLITHEA_HOOK_VER %r', ver)
Bradley M. Kuhn
Cleanup of git hook installation
r4205 has_hook = True
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 except Exception:
log.error(traceback.format_exc())
else:
# there is no hook in this dir, so we want to create one
Bradley M. Kuhn
Cleanup of git hook installation
r4205 has_hook = True
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Bradley M. Kuhn
Cleanup of git hook installation
r4205 if has_hook or force_create:
Mads Kiilerich
cleanup: pass log strings unformatted - avoid unnecessary % formatting when not logging
r5375 log.debug('writing %s hook file !', h_type)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 try:
with open(_hook_file, 'wb') as f:
Mads Kiilerich
py3: add safe_bytes in places where we will need it and where it doesn't do any harm
r7992 tmpl = tmpl.replace(b'_TMPL_', safe_bytes(kallithea.__version__))
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 f.write(tmpl)
Mads Kiilerich
py3: use explicit octal literals...
r7890 os.chmod(_hook_file, 0o755)
Mads Kiilerich
cleanup: consistently use 'except ... as ...:'...
r5374 except IOError as e:
Mads Kiilerich
cleanup: pass log strings unformatted - avoid unnecessary % formatting when not logging
r5375 log.error('error writing %s: %s', _hook_file, e)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 else:
log.debug('skipping writing hook file')
Mads Kiilerich
scm: introduce AvailableRepoGroupChoices...
r5289
Lars Kruse
codingstyle: trivial whitespace fixes...
r6789
Søren Løvborg
auth: simplify repository group permission checks...
r6472 def AvailableRepoGroupChoices(top_perms, repo_group_perm_level, extras=()):
Mads Kiilerich
scm: introduce AvailableRepoGroupChoices...
r5289 """Return group_id,string tuples with choices for all the repo groups where
the user has the necessary permissions.
Top level is -1.
"""
groups = RepoGroup.query().all()
Søren Løvborg
auth: remove HasPermissionAll and variants...
r6026 if HasPermissionAny('hg.admin')('available repo groups'):
Mads Kiilerich
scm: introduce AvailableRepoGroupChoices...
r5289 groups.append(None)
else:
Søren Løvborg
auth: simplify repository group permission checks...
r6472 groups = list(RepoGroupList(groups, perm_level=repo_group_perm_level))
Mads Kiilerich
scm: introduce AvailableRepoGroupChoices...
r5289 if top_perms and HasPermissionAny(*top_perms)('available repo groups'):
groups.append(None)
for extra in extras:
if not any(rg == extra for rg in groups):
groups.append(extra)
Mads Kiilerich
db: remove unused repository groups_choices parameter show_empty_group
r5293 return RepoGroup.groups_choices(groups=groups)