def test_push_unlocks_repository_git(self, webserver): # enable locking fork_name = '%s_fork%s' % (GIT_REPO, _RandomNameSequence().next()) fixture.create_fork(GIT_REPO, fork_name) r = Repository.get_by_repo_name(fork_name) r.enable_locking = True Session().commit() #clone some temp DEST = _get_tmp_dir() clone_url = webserver.repo_url(fork_name) stdout, stderr = Command(TESTS_TMP_PATH).execute( 'git clone', clone_url, DEST) #check for lock repo after clone r = Repository.get_by_repo_name(fork_name) assert r.locked[0] == User.get_by_username( TEST_USER_ADMIN_LOGIN).user_id #push is ok and repo is now unlocked stdout, stderr = _add_files_and_push(webserver, 'git', DEST, clone_url=clone_url) _check_proper_git_push(stdout, stderr) assert ('remote: Released lock on repo `%s`' % fork_name) in stderr #we need to cleanup the Session Here ! Session.remove() r = Repository.get_by_repo_name(fork_name) assert r.locked == [None, None]
def test_push_invalidates_cache(self, webserver, testfork, vt): pre_cached_tip = [ repo.get_api_data()['last_changeset']['short_id'] for repo in Repository.query().filter( Repository.repo_name == testfork[vt.repo_type]) ] dest_dir = _get_tmp_dir() clone_url = vt.repo_url_param(webserver, testfork[vt.repo_type]) stdout, stderr = Command(base.TESTS_TMP_PATH).execute( vt.repo_type, 'clone', clone_url, dest_dir) stdout, stderr = _add_files_and_push(webserver, vt, dest_dir, files_no=1, clone_url=clone_url) Session().commit( ) # expire test session to make sure SA fetch new Repository instances after last_changeset has been updated server side hook in other process if vt.repo_type == 'git': _check_proper_git_push(stdout, stderr) post_cached_tip = [ repo.get_api_data()['last_changeset']['short_id'] for repo in Repository.query().filter( Repository.repo_name == testfork[vt.repo_type]) ] assert pre_cached_tip != post_cached_tip
def repo_update_metadata(repositories): """ Update repository metadata in database from repository content. In normal operation, Kallithea will keep caches up-to-date automatically. However, if repositories are externally modified, e.g. by a direct push via the filesystem rather than via a Kallithea URL, Kallithea is not aware of it. In this case, you should manually run this command to update the repository cache. If no repositories are specified, the caches of all repositories are updated. """ if not repositories: repo_list = Repository.query().all() else: repo_names = [n.strip() for n in repositories] repo_list = list(Repository.query().filter( Repository.repo_name.in_(repo_names))) for repo in repo_list: # update latest revision metadata in database repo.update_changeset_cache() # invalidate in-memory VCS object cache... will be repopulated on # first access repo.set_invalidate() Session().commit() click.echo( 'Updated database with information about latest change in the following %s repositories:' % (len(repo_list))) click.echo('\n'.join(repo.repo_name for repo in repo_list))
def test_push_on_locked_repo_by_other_user_hg(self, webserver): #clone some temp DEST = _get_tmp_dir() clone_url = webserver.repo_url(HG_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute( 'hg clone', clone_url, DEST) #lock repo r = Repository.get_by_repo_name(HG_REPO) # let this user actually push ! RepoModel().grant_user_permission(repo=r, user=TEST_USER_REGULAR_LOGIN, perm='repository.write') Session().commit() Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) #push fails repo is locked by other user ! stdout, stderr = _add_files_and_push(webserver, 'hg', DEST, username=TEST_USER_REGULAR_LOGIN, password=TEST_USER_REGULAR_PASS, ignoreReturnCode=True) msg = ( """abort: HTTP Error 423: Repository `%s` locked by user `%s`""" % (HG_REPO, TEST_USER_ADMIN_LOGIN)) assert msg in stderr
def log_pull_action(ui, repo, **kwargs): """ Logs user last pull action :param ui: :param repo: """ ex = _extract_extras() user = User.get_by_username(ex.username) action = 'pull' action_logger(user, action, ex.repository, ex.ip, commit=True) # extension hook call from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'PULL_HOOK', None) if callable(callback): kw = {} kw.update(ex) callback(**kw) if ex.make_lock is not None and ex.make_lock: Repository.lock(Repository.get_by_repo_name(ex.repository), user.user_id) #msg = 'Made lock on repo `%s`' % repository #sys.stdout.write(msg) if ex.locked_by[0]: locked_by = User.get(ex.locked_by[0]).username _http_ret = HTTPLockedRC(ex.repository, locked_by) if str(_http_ret.code).startswith('2'): #2xx Codes don't raise exceptions sys.stdout.write(_http_ret.title) return 0
def test_remove_repo_detach_forks(self): repo = fixture.create_repo(name='test-repo-1') Session().commit() fork = fixture.create_fork(repo.repo_name, 'test-repo-fork-1') Session().commit() #fork of fork fixture.create_fork(fork.repo_name, 'test-repo-fork-fork-1') Session().commit() RepoModel().delete(repo=repo, forks='detach') Session().commit() try: self.assertEqual( None, Repository.get_by_repo_name(repo_name='test-repo-1')) self.assertNotEqual( None, Repository.get_by_repo_name(repo_name='test-repo-fork-1')) self.assertNotEqual( None, Repository.get_by_repo_name(repo_name='test-repo-fork-fork-1')) finally: RepoModel().delete(repo='test-repo-fork-fork-1') RepoModel().delete(repo='test-repo-fork-1') Session().commit()
def test_push_on_locked_repo_by_other_user_git(self, webserver): # Note: Git hooks must be executable on unix. This test will thus fail # for example on Linux if /tmp is mounted noexec. #clone some temp DEST = _get_tmp_dir() clone_url = webserver.repo_url(GIT_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, DEST) #lock repo r = Repository.get_by_repo_name(GIT_REPO) # let this user actually push ! RepoModel().grant_user_permission(repo=r, user=TEST_USER_REGULAR_LOGIN, perm='repository.write') Session().commit() Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) #push fails repo is locked by other user ! stdout, stderr = _add_files_and_push(webserver, 'git', DEST, username=TEST_USER_REGULAR_LOGIN, password=TEST_USER_REGULAR_PASS, ignoreReturnCode=True) err = 'Repository `%s` locked by user `%s`' % (GIT_REPO, TEST_USER_ADMIN_LOGIN) assert err in stderr #TODO: fix this somehow later on Git, Git is stupid and even if we throw #back 423 to it, it makes ANOTHER request and we fail there with 405 :/ msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`""" % (GIT_REPO, TEST_USER_ADMIN_LOGIN))
def test_push_on_locked_repo_by_other_user_git(self): #clone some temp DEST = _get_tmp_dir() clone_url = _construct_url(GIT_REPO, dest=DEST) stdout, stderr = Command('/tmp').execute('git clone', clone_url) #lock repo r = Repository.get_by_repo_name(GIT_REPO) # let this user actually push ! RepoModel().grant_user_permission(repo=r, user=TEST_USER_REGULAR_LOGIN, perm='repository.write') Session().commit() Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) #push fails repo is locked by other user ! stdout, stderr = _add_files_and_push('git', DEST, user=TEST_USER_REGULAR_LOGIN, passwd=TEST_USER_REGULAR_PASS) err = 'Repository `%s` locked by user `%s`' % (GIT_REPO, TEST_USER_ADMIN_LOGIN) assert err in stderr #TODO: fix this somehow later on Git, Git is stupid and even if we throw #back 423 to it, it makes ANOTHER request and we fail there with 405 :/ msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`""" % (GIT_REPO, TEST_USER_ADMIN_LOGIN))
def test_push_unlocks_repository_git(self, webserver): # enable locking fork_name = '%s_fork%s' % (GIT_REPO, _RandomNameSequence().next()) fixture.create_fork(GIT_REPO, fork_name) r = Repository.get_by_repo_name(fork_name) r.enable_locking = True Session().commit() #clone some temp DEST = _get_tmp_dir() clone_url = webserver.repo_url(fork_name) stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, DEST) #check for lock repo after clone r = Repository.get_by_repo_name(fork_name) assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id #push is ok and repo is now unlocked stdout, stderr = _add_files_and_push(webserver, 'git', DEST, clone_url=clone_url) _check_proper_git_push(stdout, stderr) assert ('remote: Released lock on repo `%s`' % fork_name) in stderr #we need to cleanup the Session Here ! Session.remove() r = Repository.get_by_repo_name(fork_name) assert r.locked == [None, None]
def log_pull_action(ui, repo, **kwargs): """ Logs user last pull action :param ui: :param repo: """ ex = _extract_extras() user = User.get_by_username(ex.username) action = 'pull' action_logger(user, action, ex.repository, ex.ip, commit=True) # extension hook call from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'PULL_HOOK', None) if callable(callback): kw = {} kw.update(ex) callback(**kw) if ex.make_lock is not None and ex.make_lock: Repository.lock(Repository.get_by_repo_name(ex.repository), user.user_id) #msg = 'Made lock on repo `%s`' % repository #ui.status(msg) if ex.locked_by[0]: locked_by = User.get(ex.locked_by[0]).username _http_ret = HTTPLockedRC(ex.repository, locked_by) if str(_http_ret.code).startswith('2'): #2xx Codes don't raise exceptions ui.status(safe_str(_http_ret.title)) return 0
def test_set_fork_of_other_repo(self): self.log_user() other_repo = 'other_%s' % self.REPO_TYPE fixture.create_repo(other_repo, repo_type=self.REPO_TYPE) repo = Repository.get_by_repo_name(self.REPO) repo2 = Repository.get_by_repo_name(other_repo) response = self.app.post( base.url('edit_repo_advanced_fork', repo_name=self.REPO), params=dict( id_fork_of=repo2.repo_id, _session_csrf_secret_token=self.session_csrf_secret_token())) repo = Repository.get_by_repo_name(self.REPO) repo2 = Repository.get_by_repo_name(other_repo) self.checkSessionFlash( response, 'Marked repository %s as fork of %s' % (repo.repo_name, repo2.repo_name)) assert repo.fork == repo2 response = response.follow() # check if given repo is selected opt = """<option value="%s" selected="selected">%s</option>""" % ( repo2.repo_id, repo2.repo_name) response.mustcontain(opt) fixture.destroy_repo(other_repo, forks='detach')
def set_status(self, repo, status, user, comment, revision=None, pull_request=None, dont_allow_on_closed_pull_request=False): """ Creates new status for changeset or updates the old ones bumping their version, leaving the current status at the value of 'status'. :param repo: :param status: :param user: :param comment: :param revision: :param pull_request: :param dont_allow_on_closed_pull_request: don't allow a status change if last status was for pull request and it's closed. We shouldn't mess around this manually """ repo = Repository.guess_instance(repo) q = ChangesetStatus.query() if revision is not None: assert pull_request is None q = q.filter(ChangesetStatus.repo == repo) q = q.filter(ChangesetStatus.revision == revision) revisions = [revision] else: assert pull_request is not None pull_request = PullRequest.guess_instance(pull_request) repo = pull_request.org_repo q = q.filter(ChangesetStatus.repo == repo) q = q.filter(ChangesetStatus.revision.in_(pull_request.revisions)) revisions = pull_request.revisions cur_statuses = q.all() #if statuses exists and last is associated with a closed pull request # we need to check if we can allow this status change if (dont_allow_on_closed_pull_request and cur_statuses and getattr(cur_statuses[0].pull_request, 'status', '') == PullRequest.STATUS_CLOSED): raise StatusChangeOnClosedPullRequestError( 'Changing status on closed pull request is not allowed' ) #update all current statuses with older version for st in cur_statuses: st.version += 1 new_statuses = [] for rev in revisions: new_status = ChangesetStatus() new_status.version = 0 # default new_status.author = User.guess_instance(user) new_status.repo = Repository.guess_instance(repo) new_status.status = status new_status.comment = comment new_status.revision = rev new_status.pull_request = pull_request new_statuses.append(new_status) Session().add(new_status) return new_statuses
def index(self, repo_name): c.compare_home = True org_repo = c.db_repo.repo_name other_repo = request.GET.get('other_repo', org_repo) c.a_repo = Repository.get_by_repo_name(org_repo) c.cs_repo = Repository.get_by_repo_name(other_repo) c.a_ref_name = c.cs_ref_name = _('Select changeset') return render('compare/compare_diff.html')
def log_push_action(ui, repo, **kwargs): """ Maps user last push action to new changeset id, from mercurial :param ui: :param repo: repo object containing the `ui` object """ ex = _extract_extras() action_tmpl = ex.action + ':%s' revs = [] if ex.scm == 'hg': node = kwargs['node'] def get_revs(repo, rev_opt): if rev_opt: revs = revrange(repo, rev_opt) if len(revs) == 0: return (nullrev, nullrev) return max(revs), min(revs) else: return len(repo) - 1, 0 stop, start = get_revs(repo, [node + ':']) _h = binascii.hexlify revs = [_h(repo[r].node()) for r in xrange(start, stop + 1)] elif ex.scm == 'git': revs = kwargs.get('_git_revs', []) if '_git_revs' in kwargs: kwargs.pop('_git_revs') action = action_tmpl % ','.join(revs) action_logger(ex.username, action, ex.repository, ex.ip, commit=True) # extension hook call from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'PUSH_HOOK', None) if callable(callback): kw = {'pushed_revs': revs} kw.update(ex) callback(**kw) if ex.make_lock is not None and not ex.make_lock: Repository.unlock(Repository.get_by_repo_name(ex.repository)) msg = 'Released lock on repo `%s`\n' % ex.repository sys.stdout.write(msg) if ex.locked_by[0]: locked_by = User.get(ex.locked_by[0]).username _http_ret = HTTPLockedRC(ex.repository, locked_by) if str(_http_ret.code).startswith('2'): #2xx Codes don't raise exceptions sys.stdout.write(_http_ret.title) return 0
def test_clone_after_repo_was_locked_git(self): #lock repo r = Repository.get_by_repo_name(GIT_REPO) Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) #pull fails since repo is locked clone_url = _construct_url(GIT_REPO) stdout, stderr = Command('/tmp').execute('git clone', clone_url) msg = ("""The requested URL returned error: 423""") assert msg in stderr
def test_clone_after_repo_was_locked_git(self, webserver): #lock repo r = Repository.get_by_repo_name(GIT_REPO) Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) #pull fails since repo is locked clone_url = webserver.repo_url(GIT_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) msg = ("""The requested URL returned error: 423""") assert msg in stderr
def test_clone_after_repo_was_locked_hg(self): #lock repo r = Repository.get_by_repo_name(HG_REPO) Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) #pull fails since repo is locked clone_url = _construct_url(HG_REPO) stdout, stderr = Command('/tmp').execute('hg clone', clone_url) msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`""" % (HG_REPO, TEST_USER_ADMIN_LOGIN)) assert msg in stderr
def test_set_fork_of_other_type_repo(self): self.log_user() repo = Repository.get_by_repo_name(self.REPO) repo2 = Repository.get_by_repo_name(self.OTHER_TYPE_REPO) response = self.app.put(url('edit_repo_advanced_fork', repo_name=self.REPO), params=dict(id_fork_of=repo2.repo_id, _authentication_token=self.authentication_token())) repo = Repository.get_by_repo_name(self.REPO) repo2 = Repository.get_by_repo_name(self.OTHER_TYPE_REPO) self.checkSessionFlash(response, 'Cannot set repository as fork of repository with other type')
def test_clone_after_repo_was_locked_hg(self, webserver): #lock repo r = Repository.get_by_repo_name(HG_REPO) Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) #pull fails since repo is locked clone_url = webserver.repo_url(HG_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`""" % (HG_REPO, TEST_USER_ADMIN_LOGIN)) assert msg in stderr
def test_set_fork_of_other_type_repo(self): self.log_user() repo = Repository.get_by_repo_name(self.REPO) repo2 = Repository.get_by_repo_name(self.OTHER_TYPE_REPO) response = self.app.post(url('edit_repo_advanced_fork', repo_name=self.REPO), params=dict(id_fork_of=repo2.repo_id, _authentication_token=self.authentication_token())) repo = Repository.get_by_repo_name(self.REPO) repo2 = Repository.get_by_repo_name(self.OTHER_TYPE_REPO) self.checkSessionFlash(response, 'Cannot set repository as fork of repository with other type')
def action_logger(user, action, repo, ipaddr='', sa=None, commit=False): """ Action logger for various actions made by users :param user: user that made this action, can be a unique username string or object containing user_id attribute :param action: action to log, should be on of predefined unique actions for easy translations :param repo: string name of repository or object containing repo_id, that action was made on :param ipaddr: optional IP address from what the action was made :param sa: optional sqlalchemy session """ if not sa: sa = meta.Session() # if we don't get explicit IP address try to get one from registered user # in tmpl context var if not ipaddr: ipaddr = getattr(get_current_authuser(), 'ip_addr', '') if getattr(user, 'user_id', None): user_obj = User.get(user.user_id) elif isinstance(user, basestring): user_obj = User.get_by_username(user) else: raise Exception('You have to provide a user object or a username') if getattr(repo, 'repo_id', None): repo_obj = Repository.get(repo.repo_id) repo_name = repo_obj.repo_name elif isinstance(repo, basestring): repo_name = repo.lstrip('/') repo_obj = Repository.get_by_repo_name(repo_name) else: repo_obj = None repo_name = u'' user_log = UserLog() user_log.user_id = user_obj.user_id user_log.username = user_obj.username user_log.action = safe_unicode(action) user_log.repository = repo_obj user_log.repository_name = repo_name user_log.action_date = datetime.datetime.now() user_log.user_ip = ipaddr sa.add(user_log) log.info('Logging action:%s on %s by user:%s ip:%s', action, safe_unicode(repo), user_obj, ipaddr) if commit: sa.commit()
def action_logger(user, action, repo, ipaddr='', sa=None, commit=False): """ Action logger for various actions made by users :param user: user that made this action, can be a unique username string or object containing user_id attribute :param action: action to log, should be on of predefined unique actions for easy translations :param repo: string name of repository or object containing repo_id, that action was made on :param ipaddr: optional ip address from what the action was made :param sa: optional sqlalchemy session """ if not sa: sa = meta.Session() # if we don't get explicit IP address try to get one from registered user # in tmpl context var if not ipaddr: ipaddr = getattr(get_current_authuser(), 'ip_addr', '') if getattr(user, 'user_id', None): user_obj = User.get(user.user_id) elif isinstance(user, basestring): user_obj = User.get_by_username(user) else: raise Exception('You have to provide a user object or a username') if getattr(repo, 'repo_id', None): repo_obj = Repository.get(repo.repo_id) repo_name = repo_obj.repo_name elif isinstance(repo, basestring): repo_name = repo.lstrip('/') repo_obj = Repository.get_by_repo_name(repo_name) else: repo_obj = None repo_name = '' user_log = UserLog() user_log.user_id = user_obj.user_id user_log.username = user_obj.username user_log.action = safe_unicode(action) user_log.repository = repo_obj user_log.repository_name = repo_name user_log.action_date = datetime.datetime.now() user_log.user_ip = ipaddr sa.add(user_log) log.info('Logging action:%s on %s by user:%s ip:%s' % (action, safe_unicode(repo), user_obj, ipaddr)) if commit: sa.commit()
def log_push_action(ui, repo, **kwargs): """ Register that changes have been pushed. Mercurial invokes this directly as a hook, git uses handle_git_receive. """ ex = _extract_extras() action_tmpl = ex.action + ':%s' revs = [] if ex.scm == 'hg': node = kwargs['node'] def get_revs(repo, rev_opt): if rev_opt: revs = revrange(repo, rev_opt) if len(revs) == 0: return (nullrev, nullrev) return max(revs), min(revs) else: return len(repo) - 1, 0 stop, start = get_revs(repo, [node + ':']) _h = binascii.hexlify revs = [_h(repo[r].node()) for r in xrange(start, stop + 1)] elif ex.scm == 'git': revs = kwargs.get('_git_revs', []) if '_git_revs' in kwargs: kwargs.pop('_git_revs') action = action_tmpl % ','.join(revs) action_logger(ex.username, action, ex.repository, ex.ip, commit=True) # extension hook call from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'PUSH_HOOK', None) if callable(callback): kw = {'pushed_revs': revs} kw.update(ex) callback(**kw) if ex.make_lock is not None and not ex.make_lock: Repository.unlock(Repository.get_by_repo_name(ex.repository)) ui.status(safe_str('Released lock on repo `%s`\n' % ex.repository)) if ex.locked_by[0]: locked_by = User.get(ex.locked_by[0]).username _http_ret = HTTPLockedRC(ex.repository, locked_by) if str(_http_ret.code).startswith('2'): #2xx Codes don't raise exceptions ui.status(safe_str(_http_ret.title)) return 0
def test_set_fork_of_none(self): self.log_user() ## mark it as None response = self.app.post(url('edit_repo_advanced_fork', repo_name=self.REPO), params=dict(id_fork_of=None, _authentication_token=self.authentication_token())) repo = Repository.get_by_repo_name(self.REPO) repo2 = Repository.get_by_repo_name(self.OTHER_TYPE_REPO) self.checkSessionFlash(response, 'Marked repository %s as fork of %s' % (repo.repo_name, "Nothing")) assert repo.fork is None
def test_set_fork_of_none(self): self.log_user() ## mark it as None response = self.app.put(url('edit_repo_advanced_fork', repo_name=self.REPO), params=dict(id_fork_of=None, _authentication_token=self.authentication_token())) repo = Repository.get_by_repo_name(self.REPO) repo2 = Repository.get_by_repo_name(self.OTHER_TYPE_REPO) self.checkSessionFlash(response, 'Marked repo %s as fork of %s' % (repo.repo_name, "Nothing")) assert repo.fork is None
def test_fork_unicode(self): self.log_user() # create a fork repo_name = self.REPO org_repo = Repository.get_by_repo_name(repo_name) fork_name = safe_str(self.REPO_FORK + u'-rødgrød') creation_args = { 'repo_name': fork_name, 'repo_group': u'-1', 'fork_parent_id': org_repo.repo_id, 'repo_type': self.REPO_TYPE, 'description': 'unicode repo 1', 'private': 'False', 'landing_rev': 'rev:tip', '_authentication_token': self.authentication_token() } self.app.post( url(controller='forks', action='fork_create', repo_name=repo_name), creation_args) response = self.app.get( url(controller='forks', action='forks', repo_name=repo_name)) response.mustcontain("""<a href="/%s">%s</a>""" % (urllib.quote(fork_name), fork_name)) fork_repo = Repository.get_by_repo_name(safe_unicode(fork_name)) assert fork_repo # fork the fork fork_name_2 = safe_str(self.REPO_FORK + u'-blåbærgrød') creation_args = { 'repo_name': fork_name_2, 'repo_group': u'-1', 'fork_parent_id': fork_repo.repo_id, 'repo_type': self.REPO_TYPE, 'description': 'unicode repo 2', 'private': 'False', 'landing_rev': 'rev:tip', '_authentication_token': self.authentication_token() } self.app.post( url(controller='forks', action='fork_create', repo_name=fork_name), creation_args) response = self.app.get( url(controller='forks', action='forks', repo_name=fork_name)) response.mustcontain("""<a href="/%s">%s</a>""" % (urllib.quote(fork_name_2), fork_name_2)) # remove these forks response = self.app.post( url('delete_repo', repo_name=fork_name_2), params={'_authentication_token': self.authentication_token()}) response = self.app.post( url('delete_repo', repo_name=fork_name), params={'_authentication_token': self.authentication_token()})
def test_clone_and_create_lock_git(self, webserver): # enable locking r = Repository.get_by_repo_name(GIT_REPO) r.enable_locking = True Session().commit() # clone clone_url = webserver.repo_url(GIT_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir()) #check if lock was made r = Repository.get_by_repo_name(GIT_REPO) assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id
def set_status(self, repo, status, user, comment, revision=None, pull_request=None): """ Creates new status for changeset or updates the old ones bumping their version, leaving the current status at the value of 'status'. :param repo: :param status: :param user: :param comment: :param revision: :param pull_request: """ repo = Repository.guess_instance(repo) q = ChangesetStatus.query() if revision is not None: assert pull_request is None q = q.filter(ChangesetStatus.repo == repo) q = q.filter(ChangesetStatus.revision == revision) revisions = [revision] else: assert pull_request is not None pull_request = PullRequest.guess_instance(pull_request) repo = pull_request.org_repo q = q.filter(ChangesetStatus.repo == repo) q = q.filter(ChangesetStatus.revision.in_(pull_request.revisions)) revisions = pull_request.revisions cur_statuses = q.all() # update all current statuses with older version for st in cur_statuses: st.version += 1 new_statuses = [] for rev in revisions: new_status = ChangesetStatus() new_status.version = 0 # default new_status.author = User.guess_instance(user) new_status.repo = Repository.guess_instance(repo) new_status.status = status new_status.comment = comment new_status.revision = rev new_status.pull_request = pull_request new_statuses.append(new_status) Session().add(new_status) return new_statuses
def test_clone_and_create_lock_git(self): # enable locking r = Repository.get_by_repo_name(GIT_REPO) r.enable_locking = True Session().add(r) Session().commit() # clone clone_url = _construct_url(GIT_REPO) stdout, stderr = Command('/tmp').execute('git clone', clone_url) #check if lock was made r = Repository.get_by_repo_name(GIT_REPO) assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id
def test_fork_create_into_group(self): self.log_user() group = fixture.create_repo_group('vc') group_id = group.group_id fork_name = self.REPO_FORK fork_name_full = 'vc/%s' % fork_name description = 'fork of vcs test' repo_name = self.REPO org_repo = Repository.get_by_repo_name(repo_name) creation_args = { 'repo_name': fork_name, 'repo_group': group_id, 'fork_parent_id': org_repo.repo_id, 'repo_type': self.REPO_TYPE, 'description': description, 'private': 'False', 'landing_rev': 'rev:tip', '_session_csrf_secret_token': self.session_csrf_secret_token() } self.app.post( base.url(controller='forks', action='fork_create', repo_name=repo_name), creation_args) repo = Repository.get_by_repo_name(fork_name_full) assert repo.fork.repo_name == self.REPO ## run the check page that triggers the flash message response = self.app.get( base.url('repo_check_home', repo_name=fork_name_full)) # test if we have a message that fork is ok self.checkSessionFlash( response, 'Forked repository %s as <a href="/%s">%s</a>' % (repo_name, fork_name_full, fork_name_full)) # test if the fork was created in the database fork_repo = Session().query(Repository) \ .filter(Repository.repo_name == fork_name_full).one() assert fork_repo.repo_name == fork_name_full assert fork_repo.fork.repo_name == repo_name # test if the repository is visible in the list ? response = self.app.get( base.url('summary_home', repo_name=fork_name_full)) response.mustcontain(fork_name_full) response.mustcontain(self.REPO_TYPE) response.mustcontain('Fork of "<a href="/%s">%s</a>"' % (repo_name, repo_name)) fixture.destroy_repo(fork_name_full) fixture.destroy_repo_group(group_id)
def test_clone_after_repo_was_locked_hg(self, webserver): #lock repo r = Repository.get_by_repo_name(HG_REPO) Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) #pull fails since repo is locked clone_url = webserver.repo_url(HG_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) msg = ( """abort: HTTP Error 423: Repository `%s` locked by user `%s`""" % (HG_REPO, TEST_USER_ADMIN_LOGIN)) assert msg in stderr
def test_fork_unicode(self): self.log_user() # create a fork repo_name = self.REPO org_repo = Repository.get_by_repo_name(repo_name) fork_name = safe_str(self.REPO_FORK + u'-rødgrød') creation_args = { 'repo_name': fork_name, 'repo_group': u'-1', 'fork_parent_id': org_repo.repo_id, 'repo_type': self.REPO_TYPE, 'description': 'unicode repo 1', 'private': 'False', 'landing_rev': 'rev:tip', '_authentication_token': self.authentication_token()} self.app.post(url(controller='forks', action='fork_create', repo_name=repo_name), creation_args) response = self.app.get(url(controller='forks', action='forks', repo_name=repo_name)) response.mustcontain( """<a href="/%s">%s</a>""" % (urllib.quote(fork_name), fork_name) ) fork_repo = Repository.get_by_repo_name(safe_unicode(fork_name)) assert fork_repo # fork the fork fork_name_2 = safe_str(self.REPO_FORK + u'-blåbærgrød') creation_args = { 'repo_name': fork_name_2, 'repo_group': u'-1', 'fork_parent_id': fork_repo.repo_id, 'repo_type': self.REPO_TYPE, 'description': 'unicode repo 2', 'private': 'False', 'landing_rev': 'rev:tip', '_authentication_token': self.authentication_token()} self.app.post(url(controller='forks', action='fork_create', repo_name=fork_name), creation_args) response = self.app.get(url(controller='forks', action='forks', repo_name=fork_name)) response.mustcontain( """<a href="/%s">%s</a>""" % (urllib.quote(fork_name_2), fork_name_2) ) # remove these forks response = self.app.post(url('delete_repo', repo_name=fork_name_2), params={'_authentication_token': self.authentication_token()}) response = self.app.post(url('delete_repo', repo_name=fork_name), params={'_authentication_token': self.authentication_token()})
def test_clone_and_create_lock_git(self, webserver): # enable locking r = Repository.get_by_repo_name(GIT_REPO) r.enable_locking = True Session().commit() # clone clone_url = webserver.repo_url(GIT_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute( 'git clone', clone_url, _get_tmp_dir()) #check if lock was made r = Repository.get_by_repo_name(GIT_REPO) assert r.locked[0] == User.get_by_username( TEST_USER_ADMIN_LOGIN).user_id
def create_repo(self, name, **kwargs): if 'skip_if_exists' in kwargs: del kwargs['skip_if_exists'] r = Repository.get_by_repo_name(name) if r: return r if isinstance(kwargs.get('repo_group'), RepoGroup): kwargs['repo_group'] = kwargs['repo_group'].group_id form_data = self._get_repo_create_params(repo_name=name, **kwargs) cur_user = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN) RepoModel().create(form_data, cur_user) Session().commit() return Repository.get_by_repo_name(name)
def show(self, group_name): """GET /repo_groups/group_name: Show a specific item""" # url('repos_group', group_name=GROUP_NAME) c.active = 'settings' c.group = c.repo_group = RepoGroupModel()._get_repo_group(group_name) c.group_repos = c.group.repositories.all() #overwrite our cached list with current filter c.repo_cnt = 0 groups = RepoGroup.query().order_by(RepoGroup.group_name)\ .filter(RepoGroup.group_parent_id == c.group.group_id).all() c.groups = self.scm_model.get_repo_groups(groups) c.repos_list = Repository.query()\ .filter(Repository.group_id == c.group.group_id)\ .order_by(func.lower(Repository.repo_name))\ .all() repos_data = RepoModel().get_repos_as_dict(repos_list=c.repos_list, admin=False) #json used to render the grid c.data = json.dumps(repos_data) return render('admin/repo_groups/repo_group_show.html')
def _get_permission_for_user(user, repo): perm = UserRepoToPerm.query()\ .filter(UserRepoToPerm.repository == Repository.get_by_repo_name(repo))\ .filter(UserRepoToPerm.user == User.get_by_username(user))\ .all() return perm
def grant_user_group_permission(self, repo, group_name, perm): """ Grant permission for user group on given repository, or update existing one if found :param repo: Instance of Repository, repository_id, or repository name :param group_name: Instance of UserGroup, users_group_id, or user group name :param perm: Instance of Permission, or permission_name """ repo = Repository.guess_instance(repo) group_name = UserGroup.guess_instance(group_name) permission = Permission.guess_instance(perm) # check if we have that permission already obj = UserGroupRepoToPerm.query() \ .filter(UserGroupRepoToPerm.users_group == group_name) \ .filter(UserGroupRepoToPerm.repository == repo) \ .scalar() if obj is None: # create new obj = UserGroupRepoToPerm() Session().add(obj) obj.repository = repo obj.users_group = group_name obj.permission = permission log.debug('Granted perm %s to %s on %s', perm, group_name, repo) return obj
def grant_user_permission(self, repo, user, perm): """ Grant permission for user on given repository, or update existing one if found :param repo: Instance of Repository, repository_id, or repository name :param user: Instance of User, user_id or username :param perm: Instance of Permission, or permission_name """ user = User.guess_instance(user) repo = Repository.guess_instance(repo) permission = Permission.guess_instance(perm) # check if we have that permission already obj = UserRepoToPerm.query() \ .filter(UserRepoToPerm.user == user) \ .filter(UserRepoToPerm.repository == repo) \ .scalar() if obj is None: # create new ! obj = UserRepoToPerm() Session().add(obj) obj.repository = repo obj.user = user obj.permission = permission log.debug('Granted perm %s to %s on %s', perm, user, repo) return obj
def repo_check(self, repo_name): c.repo = repo_name task_id = request.GET.get('task_id') if task_id and task_id not in ['None']: if kallithea.CELERY_APP: task_result = celery.result.AsyncResult( task_id, app=kallithea.CELERY_APP) if task_result.failed(): raise HTTPInternalServerError(task_result.traceback) repo = Repository.get_by_repo_name(repo_name) if repo and repo.repo_state == Repository.STATE_CREATED: if repo.clone_uri: h.flash(_('Created repository %s from %s') % (repo.repo_name, repo.clone_uri_hidden), category='success') else: repo_url = h.link_to( repo.repo_name, h.url('summary_home', repo_name=repo.repo_name)) fork = repo.fork if fork is not None: fork_name = fork.repo_name h.flash(h.HTML(_('Forked repository %s as %s')) % (fork_name, repo_url), category='success') else: h.flash(h.HTML(_('Created repository %s')) % repo_url, category='success') return {'result': True} return {'result': False}
def branch_tag_switcher(self, repo_name): if request.is_xhr: c.db_repo = Repository.get_by_repo_name(repo_name) if c.db_repo: c.db_repo_scm_instance = c.db_repo.scm_instance return render('/switch_to_list.html') raise HTTPBadRequest()
def test_index_hg(self): self.log_user() ID = Repository.get_by_repo_name(HG_REPO).repo_id response = self.app.get(url(controller='summary', action='index', repo_name=HG_REPO)) #repo type response.mustcontain( """<span class="repotag">hg""" ) #public/private response.mustcontain( """<i class="icon-globe">""" ) # clone url... response.mustcontain( '''<input class="form-control" size="80" readonly="readonly" value="http://%s@localhost:80/%s"/>''' % (TEST_USER_ADMIN_LOGIN, HG_REPO) ) response.mustcontain( '''<input class="form-control" size="80" readonly="readonly" value="http://%s@localhost:80/_%s"/>''' % (TEST_USER_ADMIN_LOGIN, ID) )
def edit_advanced(self, repo_name): """GET /repo_name/settings: Form to edit an existing item""" # url('edit_repo', repo_name=ID) c.repo_info = self._load_repo(repo_name) c.default_user_id = User.get_default_user().user_id c.in_public_journal = UserFollowing.query()\ .filter(UserFollowing.user_id == c.default_user_id)\ .filter(UserFollowing.follows_repository == c.repo_info).scalar() _repos = Repository.query().order_by(Repository.repo_name).all() read_access_repos = RepoList(_repos) c.repos_list = [(None, _('-- Not a fork --'))] c.repos_list += [(x.repo_id, x.repo_name) for x in read_access_repos if x.repo_id != c.repo_info.repo_id] defaults = { 'id_fork_of': c.repo_info.fork.repo_id if c.repo_info.fork else '' } c.active = 'advanced' if request.POST: return redirect(url('repo_edit_advanced')) return htmlfill.render( render('admin/repos/repo_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def repo_check(self, repo_name): c.repo = repo_name task_id = request.GET.get('task_id') if task_id and task_id not in ['None']: from kallithea import CELERY_ON from celery.result import AsyncResult if CELERY_ON: task = AsyncResult(task_id) if task.failed(): raise HTTPInternalServerError(task.traceback) repo = Repository.get_by_repo_name(repo_name) if repo and repo.repo_state == Repository.STATE_CREATED: if repo.clone_uri: clone_uri = repo.clone_uri_hidden h.flash(_('Created repository %s from %s') % (repo.repo_name, clone_uri), category='success') else: repo_url = h.link_to(repo.repo_name, h.url('summary_home', repo_name=repo.repo_name)) fork = repo.fork if fork: fork_name = fork.repo_name h.flash(h.literal(_('Forked repository %s as %s') % (fork_name, repo_url)), category='success') else: h.flash(h.literal(_('Created repository %s') % repo_url), category='success') return {'result': True} return {'result': False}
def repo_refs_data(self, repo_name): repo = Repository.get_by_repo_name(repo_name).scm_instance res = [] _branches = repo.branches.items() if _branches: res.append({ 'text': _('Branch'), 'children': [{'id': rev, 'text': name, 'type': 'branch'} for name, rev in _branches] }) _tags = repo.tags.items() if _tags: res.append({ 'text': _('Tag'), 'children': [{'id': rev, 'text': name, 'type': 'tag'} for name, rev in _tags] }) _bookmarks = repo.bookmarks.items() if _bookmarks: res.append({ 'text': _('Bookmark'), 'children': [{'id': rev, 'text': name, 'type': 'book'} for name, rev in _bookmarks] }) data = { 'more': False, 'results': res } return data
def test_set_fork_of_same_repo(self): self.log_user() repo = Repository.get_by_repo_name(self.REPO) response = self.app.put(url('edit_repo_advanced_fork', repo_name=self.REPO), params=dict(id_fork_of=repo.repo_id, _authentication_token=self.authentication_token())) self.checkSessionFlash(response, 'An error occurred during this operation')
def edit_advanced(self, repo_name): c.repo_info = self._load_repo() c.default_user_id = kallithea.DEFAULT_USER_ID c.in_public_journal = UserFollowing.query() \ .filter(UserFollowing.user_id == c.default_user_id) \ .filter(UserFollowing.follows_repository == c.repo_info).scalar() _repos = Repository.query(sorted=True).all() read_access_repos = RepoList(_repos, perm_level='read') c.repos_list = [(None, _('-- Not a fork --'))] c.repos_list += [(x.repo_id, x.repo_name) for x in read_access_repos if x.repo_id != c.repo_info.repo_id and x.repo_type == c.repo_info.repo_type] defaults = { 'id_fork_of': c.repo_info.fork_id if c.repo_info.fork_id else '' } c.active = 'advanced' if request.POST: raise HTTPFound(location=url('repo_edit_advanced')) return htmlfill.render(render('admin/repos/repo_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def test_index_with_fork(self): self.log_user() # create a fork fork_name = self.REPO_FORK description = 'fork of vcs test' repo_name = self.REPO org_repo = Repository.get_by_repo_name(repo_name) creation_args = { 'repo_name': fork_name, 'repo_group': u'-1', 'fork_parent_id': org_repo.repo_id, 'repo_type': self.REPO_TYPE, 'description': description, 'private': 'False', 'landing_rev': 'rev:tip', '_authentication_token': self.authentication_token()} self.app.post(url(controller='forks', action='fork_create', repo_name=repo_name), creation_args) response = self.app.get(url(controller='forks', action='forks', repo_name=repo_name)) response.mustcontain( """<a href="/%s">%s</a>""" % (fork_name, fork_name) ) # remove this fork response = self.app.post(url('delete_repo', repo_name=fork_name), params={'_authentication_token': self.authentication_token()})
def delete(self, repo, forks=None, fs_remove=True, cur_user=None): """ Delete given repository, forks parameter defines what do do with attached forks. Throws AttachedForksError if deleted repo has attached forks :param repo: :param forks: str 'delete' or 'detach' :param fs_remove: remove(archive) repo from filesystem """ if not cur_user: cur_user = getattr(get_current_authuser(), 'username', None) repo = Repository.guess_instance(repo) if repo is not None: if forks == 'detach': for r in repo.forks: r.fork = None elif forks == 'delete': for r in repo.forks: self.delete(r, forks='delete') elif [f for f in repo.forks]: raise AttachedForksError() old_repo_dict = repo.get_dict() try: Session().delete(repo) if fs_remove: self._delete_filesystem_repo(repo) else: log.debug('skipping removal from filesystem') log_delete_repository(old_repo_dict, deleted_by=cur_user) except Exception: log.error(traceback.format_exc()) raise
def index(self): # Return a rendered template p = safe_int(request.GET.get('page'), 1) c.user = User.get(request.authuser.user_id) c.following = UserFollowing.query() \ .filter(UserFollowing.user_id == request.authuser.user_id) \ .options(joinedload(UserFollowing.follows_repository)) \ .all() journal = self._get_journal_data(c.following) def url_generator(**kw): return url.current(filter=c.search_term, **kw) c.journal_pager = Page(journal, page=p, items_per_page=20, url=url_generator) c.journal_day_aggregate = self._get_daily_aggregate(c.journal_pager) if request.environ.get('HTTP_X_PARTIAL_XHR'): return render('journal/journal_data.html') repos_list = Repository.query(sorted=True) \ .filter_by(owner_id=request.authuser.user_id).all() repos_data = RepoModel().get_repos_as_dict(repos_list=repos_list, admin=True) #data used to render the grid c.data = repos_data return render('journal/journal.html')
def edit_advanced(self, repo_name): c.repo_info = self._load_repo() c.default_user_id = User.get_default_user().user_id c.in_public_journal = UserFollowing.query() \ .filter(UserFollowing.user_id == c.default_user_id) \ .filter(UserFollowing.follows_repository == c.repo_info).scalar() _repos = Repository.query(sorted=True).all() read_access_repos = RepoList(_repos, perm_level='read') c.repos_list = [(None, _('-- Not a fork --'))] c.repos_list += [(x.repo_id, x.repo_name) for x in read_access_repos if x.repo_id != c.repo_info.repo_id] defaults = { 'id_fork_of': c.repo_info.fork_id if c.repo_info.fork_id else '' } c.active = 'advanced' if request.POST: raise HTTPFound(location=url('repo_edit_advanced')) return htmlfill.render( render('admin/repos/repo_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)