diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -75,3 +75,4 @@ a18445b85d407294da0b7f1d8be3bedef5ffdea6 da65398a62fff50f3d241796cbf17acdea2092ef 0.4.1 bfa0b0a814644f0af3f492d17a9ed169cc3b89fe 0.5.0 d01a8e92936dbd62c76505432f60efba432e9397 0.5.1 +aa0a637fa6f635a5e024fa56b19ed2a2dacca857 0.5.2 diff --git a/CONTRIBUTORS b/CONTRIBUTORS --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -2,6 +2,7 @@ List of contributors to Kallithea projec Thomas De Schampheleire 2014-2020 Mads Kiilerich 2016-2020 + Dennis Fink 2020 Andrej Shadura 2012 2014-2017 2019 Étienne Gilli 2015-2017 2019 Allan Nordhøy 2017-2019 diff --git a/kallithea/alembic/versions/4851d15bc437_db_migration_step_after_95c01895c006_.py b/kallithea/alembic/versions/4851d15bc437_db_migration_step_after_95c01895c006_.py --- a/kallithea/alembic/versions/4851d15bc437_db_migration_step_after_95c01895c006_.py +++ b/kallithea/alembic/versions/4851d15bc437_db_migration_step_after_95c01895c006_.py @@ -45,6 +45,7 @@ def upgrade(): def downgrade(): + meta = sa.MetaData() if any(i.name == 'usk_public_key_idx' for i in meta.tables['user_ssh_keys'].indexes): with op.batch_alter_table('user_ssh_keys', schema=None) as batch_op: batch_op.drop_index('usk_public_key_idx') diff --git a/kallithea/controllers/admin/repo_groups.py b/kallithea/controllers/admin/repo_groups.py --- a/kallithea/controllers/admin/repo_groups.py +++ b/kallithea/controllers/admin/repo_groups.py @@ -142,6 +142,7 @@ class RepoGroupsController(BaseControlle # permissions for can create group based on parent_id are checked # here in the Form repo_group_form = RepoGroupForm(repo_groups=c.repo_groups) + form_result = None try: form_result = repo_group_form.to_python(dict(request.POST)) gr = RepoGroupModel().create( @@ -165,6 +166,8 @@ class RepoGroupsController(BaseControlle log.error(traceback.format_exc()) h.flash(_('Error occurred during creation of repository group %s') % request.POST.get('group_name'), category='error') + if form_result is None: + raise parent_group_id = form_result['parent_group_id'] # TODO: maybe we should get back to the main view, not the admin one raise HTTPFound(location=url('repos_groups', parent_group=parent_group_id)) diff --git a/kallithea/controllers/pullrequests.py b/kallithea/controllers/pullrequests.py --- a/kallithea/controllers/pullrequests.py +++ b/kallithea/controllers/pullrequests.py @@ -473,14 +473,15 @@ class PullrequestsController(BaseRepoCon c.a_rev) = c.pull_request.other_ref.split(':') # a_rev is ancestor org_scm_instance = c.cs_repo.scm_instance # property with expensive cache invalidation check!!! - try: - c.cs_ranges = [] - for x in c.pull_request.revisions: + c.cs_ranges = [] + for x in c.pull_request.revisions: + try: c.cs_ranges.append(org_scm_instance.get_changeset(x)) - except ChangesetDoesNotExistError: - c.cs_ranges = [] - h.flash(_('Revision %s not found in %s') % (x, c.cs_repo.repo_name), - 'error') + except ChangesetDoesNotExistError: + c.cs_ranges = [] + h.flash(_('Revision %s not found in %s') % (x, c.cs_repo.repo_name), + 'error') + break c.cs_ranges_org = None # not stored and not important and moving target - could be calculated ... revs = [ctx.revision for ctx in reversed(c.cs_ranges)] c.jsdata = graph_data(org_scm_instance, revs) diff --git a/kallithea/i18n/lb/LC_MESSAGES/kallithea.po b/kallithea/i18n/lb/LC_MESSAGES/kallithea.po new file mode 100644 --- /dev/null +++ b/kallithea/i18n/lb/LC_MESSAGES/kallithea.po @@ -0,0 +1,17 @@ +# Copyright (C) 2020 Various authors, licensing as GPLv3 +# This file is distributed under the same license as the Kallithea project. + +msgid "" +msgstr "" +"Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" +"Language: lb\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgid "There are no changesets yet" +msgstr "Et sinn nach keng Ännerungen do" + +msgid "(closed)" +msgstr "(Zou)" diff --git a/kallithea/lib/diffs.py b/kallithea/lib/diffs.py --- a/kallithea/lib/diffs.py +++ b/kallithea/lib/diffs.py @@ -558,8 +558,8 @@ def _parse_lines(diff_lines): added = deleted = 0 old_line = old_end = new_line = new_end = None + chunks = [] try: - chunks = [] line = diff_lines.next() while True: diff --git a/kallithea/lib/utils2.py b/kallithea/lib/utils2.py --- a/kallithea/lib/utils2.py +++ b/kallithea/lib/utils2.py @@ -282,7 +282,7 @@ def uri_filter(uri): :returns: filtered list of strings """ if not uri: - return '' + return [] proto = '' @@ -449,11 +449,11 @@ def get_hook_environment(): raise HookEnvironmentError("Environment variable KALLITHEA_EXTRAS not found") extras = json.loads(kallithea_extras) - try: - for k in ['username', 'repository', 'scm', 'action', 'ip', 'config']: + for k in ['username', 'repository', 'scm', 'action', 'ip', 'config']: + try: extras[k] - except KeyError: - raise HookEnvironmentError('Missing key %s in KALLITHEA_EXTRAS %s' % (k, extras)) + except KeyError: + raise HookEnvironmentError('Missing key %s in KALLITHEA_EXTRAS %s' % (k, extras)) return AttributeDict(extras) diff --git a/kallithea/lib/vcs/backends/git/ssh.py b/kallithea/lib/vcs/backends/git/ssh.py --- a/kallithea/lib/vcs/backends/git/ssh.py +++ b/kallithea/lib/vcs/backends/git/ssh.py @@ -61,7 +61,7 @@ class GitSshHandler(BaseSshHandler): return None def __init__(self, repo_name, verb): - self.repo_name = repo_name + BaseSshHandler.__init__(self, repo_name) self.verb = verb def _serve(self): diff --git a/kallithea/lib/vcs/backends/hg/ssh.py b/kallithea/lib/vcs/backends/hg/ssh.py --- a/kallithea/lib/vcs/backends/hg/ssh.py +++ b/kallithea/lib/vcs/backends/hg/ssh.py @@ -51,9 +51,6 @@ class MercurialSshHandler(BaseSshHandler return None - def __init__(self, repo_name): - self.repo_name = repo_name - def _serve(self): # Note: we want a repo with config based on .hg/hgrc and can thus not use self.db_repo.scm_instance._repo.ui baseui = make_ui(repo_path=self.db_repo.repo_full_path) diff --git a/kallithea/lib/vcs/backends/ssh.py b/kallithea/lib/vcs/backends/ssh.py --- a/kallithea/lib/vcs/backends/ssh.py +++ b/kallithea/lib/vcs/backends/ssh.py @@ -56,6 +56,9 @@ class BaseSshHandler(object): """ raise NotImplementedError + def __init__(self, repo_name): + self.repo_name = repo_name.rstrip('/') + def serve(self, user_id, key_id, client_ip): """Verify basic sanity of the repository, and that the user is valid and has access - then serve the native VCS protocol for diff --git a/kallithea/lib/vcs/nodes.py b/kallithea/lib/vcs/nodes.py --- a/kallithea/lib/vcs/nodes.py +++ b/kallithea/lib/vcs/nodes.py @@ -321,8 +321,8 @@ class FileNode(Node): encoding = None # try with pygments + from pygments import lexers try: - from pygments import lexers mt = lexers.get_lexer_for_filename(self.name).mimetypes except lexers.ClassNotFound: mt = None diff --git a/kallithea/templates/about.html b/kallithea/templates/about.html --- a/kallithea/templates/about.html +++ b/kallithea/templates/about.html @@ -26,6 +26,7 @@
  • Copyright © 2012–2020, Mads Kiilerich
  • Copyright © 2014–2020, Thomas De Schampheleire
  • +
  • Copyright © 2020, Dennis Fink
  • Copyright © 2012, 2014–2017, 2019, Andrej Shadura
  • Copyright © 2015–2017, 2019, Étienne Gilli
  • Copyright © 2017–2019, Allan Nordhøy
  • diff --git a/kallithea/tests/functional/test_login.py b/kallithea/tests/functional/test_login.py --- a/kallithea/tests/functional/test_login.py +++ b/kallithea/tests/functional/test_login.py @@ -413,7 +413,8 @@ class TestLoginController(base.TestContr def mock_send_email(recipients, subject, body='', html_body='', headers=None, author=None): collected.append((recipients, subject, body, html_body)) - with mock.patch.object(kallithea.lib.celerylib.tasks, 'send_email', mock_send_email): + with mock.patch.object(kallithea.lib.celerylib.tasks, 'send_email', mock_send_email), \ + mock.patch.object(time, 'time', lambda: timestamp): response = self.app.post(base.url(controller='login', action='password_reset'), {'email': email, diff --git a/kallithea/tests/other/test_vcs_operations.py b/kallithea/tests/other/test_vcs_operations.py --- a/kallithea/tests/other/test_vcs_operations.py +++ b/kallithea/tests/other/test_vcs_operations.py @@ -414,6 +414,32 @@ class TestVCSOperations(base.TestControl action_parts = [ul.action for ul in UserLog.query().order_by(UserLog.user_log_id)] assert action_parts == [u'pull'] + # Test handling of URLs with extra '/' around repo_name + stdout, stderr = Command(dest_dir).execute(vt.repo_type, 'pull', clone_url.replace('/' + vt.repo_name, '/./%s/' % vt.repo_name), ignoreReturnCode=True) + if issubclass(vt, HttpVcsTest): + if vt.repo_type == 'git': + # NOTE: when pulling from http://hostname/./vcs_test_git/ , the git client will normalize that and issue an HTTP request to /vcs_test_git/info/refs + assert 'Already up to date.' in stdout + else: + assert vt.repo_type == 'hg' + assert "abort: HTTP Error 404: Not Found" in stderr + else: + assert issubclass(vt, SshVcsTest) + if vt.repo_type == 'git': + assert "abort: Access to './%s' denied" % vt.repo_name in stderr + else: + assert "abort: Access to './%s' denied" % vt.repo_name in stdout + + stdout, stderr = Command(dest_dir).execute(vt.repo_type, 'pull', clone_url.replace('/' + vt.repo_name, '/%s/' % vt.repo_name), ignoreReturnCode=True) + if vt.repo_type == 'git': + assert 'Already up to date.' in stdout + else: + assert vt.repo_type == 'hg' + assert "no changes found" in stdout + assert "denied" not in stderr + assert "denied" not in stdout + assert "404" not in stdout + @parametrize_vcs_test 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])] diff --git a/scripts/make-release b/scripts/make-release --- a/scripts/make-release +++ b/scripts/make-release @@ -74,7 +74,7 @@ read answer echo "Rebuild readthedocs for docs.kallithea-scm.org" xdg-open https://readthedocs.org/projects/kallithea/ curl -X POST http://readthedocs.org/build/kallithea -xdg-open https://readthedocs.org/builds/kallithea/ +xdg-open https://readthedocs.org/projects/kallithea/builds xdg-open http://docs.kallithea-scm.org/en/latest/ # or whatever the branch is twine upload dist/*