##// END OF EJS Templates
tests: move test.ini to kallithea/tests/
Mads Kiilerich -
r5416:19267f23 default
parent child Browse files
Show More
@@ -1,29 +1,30 b''
1 1 syntax: glob
2 2 *.pyc
3 3 *.swp
4 4 *.sqlite
5 5 *.tox
6 6 *.egg-info
7 7 *.egg
8 8 *.mo
9 9 .eggs/
10 10 tarballcache/
11 11
12 12 syntax: regexp
13 13 ^rcextensions
14 14 ^build
15 15 ^dist/
16 16 ^docs/build/
17 17 ^docs/_build/
18 18 ^data$
19 ^kallithea/tests/data$
19 20 ^sql_dumps/
20 21 ^\.settings$
21 22 ^\.project$
22 23 ^\.pydevproject$
23 24 ^\.coverage$
24 25 ^kallithea\.db$
25 26 ^test\.db$
26 27 ^Kallithea\.egg-info$
27 28 ^my\.ini$
28 29 ^fabfile.py
29 30 ^\.idea$
@@ -1,21 +1,21 b''
1 1 include Apache-License-2.0.txt
2 2 include CONTRIBUTORS
3 3 include COPYING
4 4 include LICENSE-MERGELY.html
5 5 include LICENSE.md
6 6 include MIT-Permissive-License.txt
7 7 include README.rst
8 8 include development.ini
9 9 recursive-include docs *
10 10 recursive-include init.d *
11 11 include kallithea/bin/ldap_sync.conf
12 12 include kallithea/bin/template.ini.mako
13 13 include kallithea/config/deployment.ini_tmpl
14 14 recursive-include kallithea/i18n *
15 15 recursive-include kallithea/lib/dbmigrate *.py_tmpl README migrate.cfg
16 16 recursive-include kallithea/public *
17 17 recursive-include kallithea/templates *
18 18 recursive-include kallithea/tests/fixtures *
19 19 recursive-include kallithea/tests/scripts *
20 include kallithea/tests/test.ini
20 21 include kallithea/tests/vcs/aconfig
21 include test.ini
@@ -1,149 +1,149 b''
1 1 .. _contributing:
2 2
3 3 =========================
4 4 Contributing to Kallithea
5 5 =========================
6 6
7 7 Kallithea is developed and maintained by its users. Please join us and scratch
8 8 your own itch.
9 9
10 10
11 11 Infrastructure
12 12 --------------
13 13
14 14 The main repository is hosted at Our Own Kallithea (aka OOK) on
15 15 https://kallithea-scm.org/repos/kallithea/ (which is our self-hosted instance
16 16 of Kallithea).
17 17
18 18 For now, we use Bitbucket_ for `Pull Requests`_ and `Issue Tracker`_ services. The
19 19 issue tracker is for tracking bugs, not for support, discussion, or ideas -
20 20 please use the `mailing list`_ to reach the community.
21 21
22 22 We use Weblate_ to translate the user interface messages into languages other
23 23 than English. Join our project on `Hosted Weblate`_ to help us.
24 24 To register, you can use your Bitbucket or GitHub account. See :ref:`translations`
25 25 for more details.
26 26
27 27 Getting started
28 28 ---------------
29 29
30 30 To get started with development::
31 31
32 32 hg clone https://kallithea-scm.org/repos/kallithea
33 33 cd kallithea
34 34 virtualenv ../kallithea-venv
35 35 source ../kallithea-venv/bin/activate
36 36 python setup.py develop
37 37 paster make-config Kallithea my.ini
38 38 paster setup-db my.ini --user=user --email=user@example.com --password=password --repos=/tmp
39 39 paster serve my.ini --reload &
40 40 firefox http://127.0.0.1:5000/
41 41
42 42 You can also start out by forking https://bitbucket.org/conservancy/kallithea
43 43 on Bitbucket_ and create a local clone of your own fork.
44 44
45 45
46 46 Running tests
47 47 -------------
48 48
49 49 After finishing your changes make sure all tests pass cleanly. You can run
50 50 the testsuite running ``nosetests`` from the project root, or if you use tox
51 51 run ``tox`` for python2.6-2.7 with multiple database test.
52 52
53 When using `nosetests`, the `test.ini` file is used with an SQLite database. Edit
54 this file to change your testing enviroment.
53 When running tests, Kallithea uses `kallithea/tests/test.ini` and populates the
54 SQLite database specified there.
55 55
56 56 It is possible to avoid recreating the full test database on each invocation of
57 57 the tests, thus eliminating the initial delay. To achieve this, run the tests as::
58 58
59 paster serve test.ini --pid-file=test.pid --daemon
59 paster serve kallithea/tests/test.ini --pid-file=test.pid --daemon
60 60 KALLITHEA_WHOOSH_TEST_DISABLE=1 KALLITHEA_NO_TMP_PATH=1 nosetests
61 61 kill -9 $(cat test.pid)
62 62
63 63 You can run individual tests by specifying their path as argument to nosetests.
64 64 nosetests also has many more options, see `nosetests -h`. Some useful options
65 65 are::
66 66
67 67 -x, --stop Stop running tests after the first error or failure
68 68 -s, --nocapture Don't capture stdout (any stdout output will be
69 69 printed immediately) [NOSE_NOCAPTURE]
70 70 --failed Run the tests that failed in the last test run.
71 71
72 72 Coding/contribution guidelines
73 73 ------------------------------
74 74
75 75 Kallithea is GPLv3 and we assume all contributions are made by the
76 76 committer/contributor and under GPLv3 unless explicitly stated. We do care a
77 77 lot about preservation of copyright and license information for existing code
78 78 that is brought into the project.
79 79
80 80 We don't have a formal coding/formatting standard. We are currently using a mix
81 81 of Mercurial (http://mercurial.selenic.com/wiki/CodingStyle), pep8, and
82 82 consistency with existing code. Run whitespacecleanup.sh to avoid stupid
83 83 whitespace noise in your patches.
84 84
85 85 We support both Python 2.6.x and 2.7.x and nothing else. For now we don't care
86 86 about Python 3 compatibility.
87 87
88 88 We try to support the most common modern web browsers. IE9 is still supported
89 89 to the extent it is feasible, IE8 is not.
90 90
91 91 We primarily support Linux and OS X on the server side but Windows should also work.
92 92
93 93 Html templates should use 2 spaces for indentation ... but be pragmatic. We
94 94 should use templates cleverly and avoid duplication. We should use reasonable
95 95 semantic markup with classes and ids that can be used for styling and testing.
96 96 We should only use inline styles in places where it really is semantic (such as
97 97 display:none).
98 98
99 99 JavaScript must use ';' between/after statements. Indentation 4 spaces. Inline
100 100 multiline functions should be indented two levels - one for the () and one for
101 101 {}. jQuery value arrays should have a leading $.
102 102
103 103 Commit messages should have a leading short line summarizing the changes. For
104 104 bug fixes, put "(Issue #123)" at the end of this line.
105 105
106 106 Contributions will be accepted in most formats - such as pull requests on
107 107 bitbucket, something hosted on your own Kallithea instance, or patches sent by
108 108 email to the kallithea-general mailing list.
109 109
110 110 Make sure to test your changes both manually and with the automatic tests
111 111 before posting.
112 112
113 113 We care about quality and review and keeping a clean repository history. We
114 114 might give feedback that requests polishing contributions until they are
115 115 "perfect". We might also rebase and collapse and make minor adjustments to your
116 116 changes when we apply them.
117 117
118 118 We try to make sure we have consensus on the direction the project is taking.
119 119 Everything non-sensitive should be discussed in public - preferably on the
120 120 mailing list. We aim at having all non-trivial changes reviewed by at least
121 121 one other core developer before pushing. Obvious non-controversial changes will
122 122 be handled more casually.
123 123
124 124 For now we just have one official branch ("default") and will keep it so stable
125 125 that it can be (and is) used in production. Experimental changes should live
126 126 elsewhere (for example in a pull request) until they are ready.
127 127
128 128 .. _translations:
129 129 .. include:: ./../kallithea/i18n/how_to
130 130
131 131 "Roadmap"
132 132 ---------
133 133
134 134 We do not have a road map but are waiting for your contributions. Refer to the
135 135 wiki_ for some ideas of places we might want to go - contributions in these
136 136 areas are very welcome.
137 137
138 138
139 139 Thank you for your contribution!
140 140 --------------------------------
141 141
142 142
143 143 .. _Weblate: http://weblate.org/
144 144 .. _Issue Tracker: https://bitbucket.org/conservancy/kallithea/issues?status=new&status=open
145 145 .. _Pull Requests: https://bitbucket.org/conservancy/kallithea/pull-requests
146 146 .. _bitbucket: http://bitbucket.org/
147 147 .. _mailing list: http://lists.sfconservancy.org/mailman/listinfo/kallithea-general
148 148 .. _Hosted Weblate: https://hosted.weblate.org/projects/kallithea/kallithea/
149 149 .. _wiki: https://bitbucket.org/conservancy/kallithea/wiki/Home
@@ -1,92 +1,92 b''
1 1 ============
2 2 Translations
3 3 ============
4 4
5 5 Translations are available on Hosted Weblate at the following URL:
6 6
7 7 https://hosted.weblate.org/projects/kallithea/kallithea/
8 8
9 9 Registered users may contribute to the existing languages, or request a new
10 10 language translations.
11 11
12 12 Translating using Weblate
13 13 -------------------------
14 14
15 15 Weblate_ offers a simple and easy to use interface featuring glossary, machine
16 16 translation, suggestions based on similar translations in other projects,
17 17 automatic checks etc. Weblate imports the source code tree directly from
18 18 the version control system, and commits edits back from time to time.
19 19
20 20 When registering at Weblate, make sure you name and email address you prefer to
21 21 be used when your changes are committed. We can and probably will amend changesets
22 22 coming from Weblate, but having things right from the beginning makes things easier.
23 23
24 24 Weblate performs sanity checks all the time and tries to prevent you from ignoring
25 25 them. Most common mistakes are inconsistent punctuation, whitespaces, missing or extra
26 26 format parameters, untranslated strings copied into the translation. Please perform
27 27 necessary corrections when they're needed, or override the false positives.
28 28
29 29 Merging translations from Weblate
30 30 ---------------------------------
31 31
32 32 Weblate rebases its changes every time it pulls from our repository. Pulls are triggered
33 33 by a web hook from Our Own Kallithea every time it receives new commits. Usually merging
34 34 the new translations is a straightforward process consisting of a pull from Weblate-hosted
35 35 repository which is available under Data Exports tab in Weblate interface.
36 36
37 37 Weblate tries to minimise the number of commits, but that's not always work, especially
38 38 when two translators work with different languages at more or less the same time.
39 39 It makes sense sometimes to re-order or fold commits by the same author when they touch
40 40 just the same language translation. That, however, may confuse Weblate sometimes, in
41 41 which case it should be manually convinced it has to discard the commits it created by
42 42 using its administrative interface.
43 43
44 44 Manual creation of a new language translation
45 45 ---------------------------------------------
46 46
47 47 In the prepared development environment, run the following to ensure
48 48 all translation strings are extracted and up-to-date::
49 49
50 50 python setup.py extract_messages
51 51
52 52 Create new language by executing following command::
53 53
54 54 python setup.py init_catalog -l <new_language_code>
55 55
56 56 This creates a new translation under directory `kallithea/i18n/<new_language_code>`
57 57 based on the translation template file, `kallithea/i18n/kallithea.pot`.
58 58
59 59 Edit the new PO file located in `LC_MESSAGES` directory with poedit or your
60 60 favorite PO files editor. After you finished with the translations, check the
61 61 translation file for errors by executing::
62 62
63 63 msgfmt -f -c kallithea/i18n/<new_language_code>/LC_MESSAGES/<updated_file.po>
64 64
65 65 Finally, compile the translations::
66 66
67 67 python setup.py compile_catalog -l <new_language_code>
68 68
69 69 Updating translations
70 70 ---------------------
71 71
72 72 Extract the latest versions of strings for translation by running::
73 73
74 74 python setup.py extract_messages
75 75
76 76 Update the PO file by doing::
77 77
78 78 python setup.py update_catalog -l <new_language_code>
79 79
80 80 Edit the new updated translation file. Repeat all steps after `init_catalog` step from
81 81 new translation instructions
82 82
83 83 Testing translations
84 84 --------------------
85 85
86 Edit test.ini file and set lang attribute to::
86 Edit kallithea/tests/test.ini file and set lang attribute to::
87 87
88 88 lang=<new_language_code>
89 89
90 90 Run Kallithea tests by executing::
91 91
92 92 nosetests
@@ -1,34 +1,34 b''
1 1 import os
2 2 import sys
3 3 import logging
4 4
5 5 import pkg_resources
6 6 from paste.deploy import loadapp
7 7 import pylons.test
8 8 from pylons.i18n.translation import _get_translator
9 9
10 10
11 11 def pytest_configure():
12 12 path = os.getcwd()
13 13 sys.path.insert(0, path)
14 14 pkg_resources.working_set.add_entry(path)
15 15
16 16 # Disable INFO logging of test database creation, restore with NOTSET
17 17 logging.disable(logging.INFO)
18 pylons.test.pylonsapp = loadapp('config:test.ini', relative_to=path)
18 pylons.test.pylonsapp = loadapp('config:kallithea/tests/test.ini', relative_to=path)
19 19 logging.disable(logging.NOTSET)
20 20
21 21 # Setup the config and app_globals, only works if we can get
22 22 # to the config object
23 23 conf = getattr(pylons.test.pylonsapp, 'config')
24 24 if conf:
25 25 pylons.config._push_object(conf)
26 26
27 27 if 'pylons.app_globals' in conf:
28 28 pylons.app_globals._push_object(conf['pylons.app_globals'])
29 29
30 30 # Initialize a translator for tests that utilize i18n
31 31 translator = _get_translator(pylons.config.get('lang'))
32 32 pylons.translator._push_object(translator)
33 33
34 34 return pylons.test.pylonsapp
@@ -1,537 +1,537 b''
1 1 # -*- coding: utf-8 -*-
2 2 # This program is free software: you can redistribute it and/or modify
3 3 # it under the terms of the GNU General Public License as published by
4 4 # the Free Software Foundation, either version 3 of the License, or
5 5 # (at your option) any later version.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 """
15 15 kallithea.tests.other.manual_test_vcs_operations
16 16 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17 17
18 18 Test suite for making push/pull operations.
19 19
20 20 Run it in two terminals::
21 paster serve test.ini
21 paster serve kallithea/tests/test.ini
22 22 KALLITHEA_WHOOSH_TEST_DISABLE=1 KALLITHEA_NO_TMP_PATH=1 nosetests kallithea/tests/other/manual_test_vcs_operations.py
23 23
24 24 You must have git > 1.8.1 for tests to work fine
25 25
26 26 This file was forked by the Kallithea project in July 2014.
27 27 Original author and date, and relevant copyright and licensing information is below:
28 28 :created_on: Dec 30, 2010
29 29 :author: marcink
30 30 :copyright: (c) 2013 RhodeCode GmbH, and others.
31 31 :license: GPLv3, see LICENSE.md for more details.
32 32
33 33 """
34 34
35 35 import re
36 36 import tempfile
37 37 import time
38 38 from os.path import join as jn
39 39
40 40 from tempfile import _RandomNameSequence
41 41 from subprocess import Popen, PIPE
42 42
43 43 from kallithea.tests import *
44 44 from kallithea.model.db import User, Repository, UserIpMap, CacheInvalidation
45 45 from kallithea.model.meta import Session
46 46 from kallithea.model.repo import RepoModel
47 47 from kallithea.model.user import UserModel
48 48
49 49 DEBUG = True
50 50 HOST = '127.0.0.1:4999' # test host
51 51
52 52
53 53 class Command(object):
54 54
55 55 def __init__(self, cwd):
56 56 self.cwd = cwd
57 57
58 58 def execute(self, cmd, *args):
59 59 """
60 60 Runs command on the system with given ``args``.
61 61 """
62 62
63 63 command = cmd + ' ' + ' '.join(args)
64 64 if DEBUG:
65 65 print '*** CMD %s ***' % command
66 66 p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE, cwd=self.cwd)
67 67 stdout, stderr = p.communicate()
68 68 if DEBUG:
69 69 print 'stdout:', repr(stdout)
70 70 print 'stderr:', repr(stderr)
71 71 return stdout, stderr
72 72
73 73
74 74 def _get_tmp_dir():
75 75 return tempfile.mkdtemp(prefix='rc_integration_test')
76 76
77 77
78 78 def _construct_url(repo, dest=None, **kwargs):
79 79 if dest is None:
80 80 #make temp clone
81 81 dest = _get_tmp_dir()
82 82 params = {
83 83 'user': TEST_USER_ADMIN_LOGIN,
84 84 'passwd': TEST_USER_ADMIN_PASS,
85 85 'host': HOST,
86 86 'cloned_repo': repo,
87 87 'dest': dest
88 88 }
89 89 params.update(**kwargs)
90 90 if params['user'] and params['passwd']:
91 91 _url = 'http://%(user)s:%(passwd)s@%(host)s/%(cloned_repo)s %(dest)s' % params
92 92 else:
93 93 _url = 'http://(host)s/%(cloned_repo)s %(dest)s' % params
94 94 return _url
95 95
96 96
97 97 def _add_files_and_push(vcs, DEST, **kwargs):
98 98 """
99 99 Generate some files, add it to DEST repo and push back
100 100 vcs is git or hg and defines what VCS we want to make those files for
101 101
102 102 :param vcs:
103 103 :param DEST:
104 104 """
105 105 # commit some stuff into this repo
106 106 cwd = path = jn(DEST)
107 107 #added_file = jn(path, '%ssetupΔ…ΕΌΕΊΔ‡.py' % _RandomNameSequence().next())
108 108 added_file = jn(path, '%ssetup.py' % _RandomNameSequence().next())
109 109 Command(cwd).execute('touch %s' % added_file)
110 110 Command(cwd).execute('%s add %s' % (vcs, added_file))
111 111
112 112 for i in xrange(kwargs.get('files_no', 3)):
113 113 cmd = """echo 'added_line%s' >> %s""" % (i, added_file)
114 114 Command(cwd).execute(cmd)
115 115 author_str = 'User ǝɯɐᴎ <me@email.com>'
116 116 if vcs == 'hg':
117 117 cmd = """hg commit -m 'commited new %s' -u '%s' %s """ % (
118 118 i, author_str, added_file
119 119 )
120 120 elif vcs == 'git':
121 121 cmd = """EMAIL="me@email.com" git commit -m 'commited new %s' --author '%s' %s """ % (
122 122 i, author_str, added_file
123 123 )
124 124 Command(cwd).execute(cmd)
125 125
126 126 # PUSH it back
127 127 _REPO = None
128 128 if vcs == 'hg':
129 129 _REPO = HG_REPO
130 130 elif vcs == 'git':
131 131 _REPO = GIT_REPO
132 132
133 133 kwargs['dest'] = ''
134 134 clone_url = _construct_url(_REPO, **kwargs)
135 135 if 'clone_url' in kwargs:
136 136 clone_url = kwargs['clone_url']
137 137 stdout = stderr = None
138 138 if vcs == 'hg':
139 139 stdout, stderr = Command(cwd).execute('hg push --verbose', clone_url)
140 140 elif vcs == 'git':
141 141 stdout, stderr = Command(cwd).execute('git push --verbose', clone_url + " master")
142 142
143 143 return stdout, stderr
144 144
145 145
146 146 def set_anonymous_access(enable=True):
147 147 user = User.get_by_username(User.DEFAULT_USER)
148 148 user.active = enable
149 149 Session().add(user)
150 150 Session().commit()
151 151 print '\tanonymous access is now:', enable
152 152 if enable != User.get_by_username(User.DEFAULT_USER).active:
153 153 raise Exception('Cannot set anonymous access')
154 154
155 155
156 156 #==============================================================================
157 157 # TESTS
158 158 #==============================================================================
159 159
160 160
161 161 def _check_proper_git_push(stdout, stderr):
162 162 #WTF Git stderr is output ?!
163 163 assert 'fatal' not in stderr
164 164 assert 'rejected' not in stderr
165 165 assert 'Pushing to' in stderr
166 166 assert 'master -> master' in stderr
167 167
168 168
169 169 class TestVCSOperations(BaseTestCase):
170 170
171 171 @classmethod
172 172 def setup_class(cls):
173 173 #DISABLE ANONYMOUS ACCESS
174 174 set_anonymous_access(False)
175 175
176 176 def setUp(self):
177 177 r = Repository.get_by_repo_name(GIT_REPO)
178 178 Repository.unlock(r)
179 179 r.enable_locking = False
180 180 Session().add(r)
181 181 Session().commit()
182 182
183 183 r = Repository.get_by_repo_name(HG_REPO)
184 184 Repository.unlock(r)
185 185 r.enable_locking = False
186 186 Session().add(r)
187 187 Session().commit()
188 188
189 189 def test_clone_hg_repo_by_admin(self):
190 190 clone_url = _construct_url(HG_REPO)
191 191 stdout, stderr = Command('/tmp').execute('hg clone', clone_url)
192 192
193 193 assert 'requesting all changes' in stdout
194 194 assert 'adding changesets' in stdout
195 195 assert 'adding manifests' in stdout
196 196 assert 'adding file changes' in stdout
197 197
198 198 assert stderr == ''
199 199
200 200 def test_clone_git_repo_by_admin(self):
201 201 clone_url = _construct_url(GIT_REPO)
202 202 stdout, stderr = Command('/tmp').execute('git clone', clone_url)
203 203
204 204 assert 'Cloning into' in stdout + stderr
205 205 assert stderr == '' or stdout == ''
206 206
207 207 def test_clone_wrong_credentials_hg(self):
208 208 clone_url = _construct_url(HG_REPO, passwd='bad!')
209 209 stdout, stderr = Command('/tmp').execute('hg clone', clone_url)
210 210 assert 'abort: authorization failed' in stderr
211 211
212 212 def test_clone_wrong_credentials_git(self):
213 213 clone_url = _construct_url(GIT_REPO, passwd='bad!')
214 214 stdout, stderr = Command('/tmp').execute('git clone', clone_url)
215 215 assert 'fatal: Authentication failed' in stderr
216 216
217 217 def test_clone_git_dir_as_hg(self):
218 218 clone_url = _construct_url(GIT_REPO)
219 219 stdout, stderr = Command('/tmp').execute('hg clone', clone_url)
220 220 assert 'HTTP Error 404: Not Found' in stderr
221 221
222 222 def test_clone_hg_repo_as_git(self):
223 223 clone_url = _construct_url(HG_REPO)
224 224 stdout, stderr = Command('/tmp').execute('git clone', clone_url)
225 225 assert 'not found' in stderr
226 226
227 227 def test_clone_non_existing_path_hg(self):
228 228 clone_url = _construct_url('trololo')
229 229 stdout, stderr = Command('/tmp').execute('hg clone', clone_url)
230 230 assert 'HTTP Error 404: Not Found' in stderr
231 231
232 232 def test_clone_non_existing_path_git(self):
233 233 clone_url = _construct_url('trololo')
234 234 stdout, stderr = Command('/tmp').execute('git clone', clone_url)
235 235 assert 'not found' in stderr
236 236
237 237 def test_push_new_file_hg(self):
238 238 DEST = _get_tmp_dir()
239 239 clone_url = _construct_url(HG_REPO, dest=DEST)
240 240 stdout, stderr = Command('/tmp').execute('hg clone', clone_url)
241 241
242 242 stdout, stderr = _add_files_and_push('hg', DEST)
243 243
244 244 assert 'pushing to' in stdout
245 245 assert 'Repository size' in stdout
246 246 assert 'Last revision is now' in stdout
247 247
248 248 def test_push_new_file_git(self):
249 249 DEST = _get_tmp_dir()
250 250 clone_url = _construct_url(GIT_REPO, dest=DEST)
251 251 stdout, stderr = Command('/tmp').execute('git clone', clone_url)
252 252
253 253 # commit some stuff into this repo
254 254 stdout, stderr = _add_files_and_push('git', DEST)
255 255
256 256 print [(x.repo_full_path,x.repo_path) for x in Repository.get_all()]
257 257 _check_proper_git_push(stdout, stderr)
258 258
259 259 def test_push_invalidates_cache_hg(self):
260 260 key = CacheInvalidation.query().filter(CacheInvalidation.cache_key
261 261 ==HG_REPO).scalar()
262 262 if not key:
263 263 key = CacheInvalidation(HG_REPO, HG_REPO)
264 264
265 265 key.cache_active = True
266 266 Session().add(key)
267 267 Session().commit()
268 268
269 269 DEST = _get_tmp_dir()
270 270 clone_url = _construct_url(HG_REPO, dest=DEST)
271 271 stdout, stderr = Command('/tmp').execute('hg clone', clone_url)
272 272
273 273 stdout, stderr = _add_files_and_push('hg', DEST, files_no=1)
274 274
275 275 key = CacheInvalidation.query().filter(CacheInvalidation.cache_key
276 276 ==HG_REPO).one()
277 277 self.assertEqual(key.cache_active, False)
278 278
279 279 def test_push_invalidates_cache_git(self):
280 280 key = CacheInvalidation.query().filter(CacheInvalidation.cache_key
281 281 ==GIT_REPO).scalar()
282 282 if not key:
283 283 key = CacheInvalidation(GIT_REPO, GIT_REPO)
284 284
285 285 key.cache_active = True
286 286 Session().add(key)
287 287 Session().commit()
288 288
289 289 DEST = _get_tmp_dir()
290 290 clone_url = _construct_url(GIT_REPO, dest=DEST)
291 291 stdout, stderr = Command('/tmp').execute('git clone', clone_url)
292 292
293 293 # commit some stuff into this repo
294 294 stdout, stderr = _add_files_and_push('git', DEST, files_no=1)
295 295 _check_proper_git_push(stdout, stderr)
296 296
297 297 key = CacheInvalidation.query().filter(CacheInvalidation.cache_key
298 298 ==GIT_REPO).one()
299 299 print CacheInvalidation.get_all()
300 300 self.assertEqual(key.cache_active, False)
301 301
302 302 def test_push_wrong_credentials_hg(self):
303 303 DEST = _get_tmp_dir()
304 304 clone_url = _construct_url(HG_REPO, dest=DEST)
305 305 stdout, stderr = Command('/tmp').execute('hg clone', clone_url)
306 306
307 307 stdout, stderr = _add_files_and_push('hg', DEST, user='bad',
308 308 passwd='name')
309 309
310 310 assert 'abort: authorization failed' in stderr
311 311
312 312 def test_push_wrong_credentials_git(self):
313 313 DEST = _get_tmp_dir()
314 314 clone_url = _construct_url(GIT_REPO, dest=DEST)
315 315 stdout, stderr = Command('/tmp').execute('git clone', clone_url)
316 316
317 317 stdout, stderr = _add_files_and_push('git', DEST, user='bad',
318 318 passwd='name')
319 319
320 320 assert 'fatal: Authentication failed' in stderr
321 321
322 322 def test_push_back_to_wrong_url_hg(self):
323 323 DEST = _get_tmp_dir()
324 324 clone_url = _construct_url(HG_REPO, dest=DEST)
325 325 stdout, stderr = Command('/tmp').execute('hg clone', clone_url)
326 326
327 327 stdout, stderr = _add_files_and_push('hg', DEST,
328 328 clone_url='http://%s/tmp' % HOST)
329 329
330 330 assert 'HTTP Error 404: Not Found' in stderr
331 331
332 332 def test_push_back_to_wrong_url_git(self):
333 333 DEST = _get_tmp_dir()
334 334 clone_url = _construct_url(GIT_REPO, dest=DEST)
335 335 stdout, stderr = Command('/tmp').execute('git clone', clone_url)
336 336
337 337 stdout, stderr = _add_files_and_push('git', DEST,
338 338 clone_url='http://%s/tmp' % HOST)
339 339
340 340 assert 'not found' in stderr
341 341
342 342 def test_clone_and_create_lock_hg(self):
343 343 # enable locking
344 344 r = Repository.get_by_repo_name(HG_REPO)
345 345 r.enable_locking = True
346 346 Session().add(r)
347 347 Session().commit()
348 348 # clone
349 349 clone_url = _construct_url(HG_REPO)
350 350 stdout, stderr = Command('/tmp').execute('hg clone', clone_url)
351 351
352 352 #check if lock was made
353 353 r = Repository.get_by_repo_name(HG_REPO)
354 354 assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id
355 355
356 356 def test_clone_and_create_lock_git(self):
357 357 # enable locking
358 358 r = Repository.get_by_repo_name(GIT_REPO)
359 359 r.enable_locking = True
360 360 Session().add(r)
361 361 Session().commit()
362 362 # clone
363 363 clone_url = _construct_url(GIT_REPO)
364 364 stdout, stderr = Command('/tmp').execute('git clone', clone_url)
365 365
366 366 #check if lock was made
367 367 r = Repository.get_by_repo_name(GIT_REPO)
368 368 assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id
369 369
370 370 def test_clone_after_repo_was_locked_hg(self):
371 371 #lock repo
372 372 r = Repository.get_by_repo_name(HG_REPO)
373 373 Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id)
374 374 #pull fails since repo is locked
375 375 clone_url = _construct_url(HG_REPO)
376 376 stdout, stderr = Command('/tmp').execute('hg clone', clone_url)
377 377 msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`"""
378 378 % (HG_REPO, TEST_USER_ADMIN_LOGIN))
379 379 assert msg in stderr
380 380
381 381 def test_clone_after_repo_was_locked_git(self):
382 382 #lock repo
383 383 r = Repository.get_by_repo_name(GIT_REPO)
384 384 Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id)
385 385 #pull fails since repo is locked
386 386 clone_url = _construct_url(GIT_REPO)
387 387 stdout, stderr = Command('/tmp').execute('git clone', clone_url)
388 388 msg = ("""The requested URL returned error: 423""")
389 389 assert msg in stderr
390 390
391 391 def test_push_on_locked_repo_by_other_user_hg(self):
392 392 #clone some temp
393 393 DEST = _get_tmp_dir()
394 394 clone_url = _construct_url(HG_REPO, dest=DEST)
395 395 stdout, stderr = Command('/tmp').execute('hg clone', clone_url)
396 396
397 397 #lock repo
398 398 r = Repository.get_by_repo_name(HG_REPO)
399 399 # let this user actually push !
400 400 RepoModel().grant_user_permission(repo=r, user=TEST_USER_REGULAR_LOGIN,
401 401 perm='repository.write')
402 402 Session().commit()
403 403 Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id)
404 404
405 405 #push fails repo is locked by other user !
406 406 stdout, stderr = _add_files_and_push('hg', DEST,
407 407 user=TEST_USER_REGULAR_LOGIN,
408 408 passwd=TEST_USER_REGULAR_PASS)
409 409 msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`"""
410 410 % (HG_REPO, TEST_USER_ADMIN_LOGIN))
411 411 assert msg in stderr
412 412
413 413 def test_push_on_locked_repo_by_other_user_git(self):
414 414 #clone some temp
415 415 DEST = _get_tmp_dir()
416 416 clone_url = _construct_url(GIT_REPO, dest=DEST)
417 417 stdout, stderr = Command('/tmp').execute('git clone', clone_url)
418 418
419 419 #lock repo
420 420 r = Repository.get_by_repo_name(GIT_REPO)
421 421 # let this user actually push !
422 422 RepoModel().grant_user_permission(repo=r, user=TEST_USER_REGULAR_LOGIN,
423 423 perm='repository.write')
424 424 Session().commit()
425 425 Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id)
426 426
427 427 #push fails repo is locked by other user !
428 428 stdout, stderr = _add_files_and_push('git', DEST,
429 429 user=TEST_USER_REGULAR_LOGIN,
430 430 passwd=TEST_USER_REGULAR_PASS)
431 431 err = 'Repository `%s` locked by user `%s`' % (GIT_REPO, TEST_USER_ADMIN_LOGIN)
432 432 assert err in stderr
433 433
434 434 #TODO: fix this somehow later on Git, Git is stupid and even if we throw
435 435 #back 423 to it, it makes ANOTHER request and we fail there with 405 :/
436 436
437 437 msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`"""
438 438 % (GIT_REPO, TEST_USER_ADMIN_LOGIN))
439 439 #msg = "405 Method Not Allowed"
440 440 #assert msg in stderr
441 441
442 442 def test_push_unlocks_repository_hg(self):
443 443 # enable locking
444 444 r = Repository.get_by_repo_name(HG_REPO)
445 445 r.enable_locking = True
446 446 Session().add(r)
447 447 Session().commit()
448 448 #clone some temp
449 449 DEST = _get_tmp_dir()
450 450 clone_url = _construct_url(HG_REPO, dest=DEST)
451 451 stdout, stderr = Command('/tmp').execute('hg clone', clone_url)
452 452
453 453 #check for lock repo after clone
454 454 r = Repository.get_by_repo_name(HG_REPO)
455 455 uid = User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id
456 456 assert r.locked[0] == uid
457 457
458 458 #push is ok and repo is now unlocked
459 459 stdout, stderr = _add_files_and_push('hg', DEST)
460 460 assert ('remote: Released lock on repo `%s`' % HG_REPO) in stdout
461 461 #we need to cleanup the Session Here !
462 462 Session.remove()
463 463 r = Repository.get_by_repo_name(HG_REPO)
464 464 assert r.locked == [None, None]
465 465
466 466 #TODO: fix me ! somehow during tests hooks don't get called on Git
467 467 def test_push_unlocks_repository_git(self):
468 468 # enable locking
469 469 r = Repository.get_by_repo_name(GIT_REPO)
470 470 r.enable_locking = True
471 471 Session().add(r)
472 472 Session().commit()
473 473 #clone some temp
474 474 DEST = _get_tmp_dir()
475 475 clone_url = _construct_url(GIT_REPO, dest=DEST)
476 476 stdout, stderr = Command('/tmp').execute('git clone', clone_url)
477 477
478 478 #check for lock repo after clone
479 479 r = Repository.get_by_repo_name(GIT_REPO)
480 480 assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id
481 481
482 482 #push is ok and repo is now unlocked
483 483 stdout, stderr = _add_files_and_push('git', DEST)
484 484 _check_proper_git_push(stdout, stderr)
485 485
486 486 #assert ('remote: Released lock on repo `%s`' % GIT_REPO) in stdout
487 487 #we need to cleanup the Session Here !
488 488 Session.remove()
489 489 r = Repository.get_by_repo_name(GIT_REPO)
490 490 assert r.locked == [None, None]
491 491
492 492 def test_ip_restriction_hg(self):
493 493 user_model = UserModel()
494 494 try:
495 495 user_model.add_extra_ip(TEST_USER_ADMIN_LOGIN, '10.10.10.10/32')
496 496 Session().commit()
497 497 clone_url = _construct_url(HG_REPO)
498 498 stdout, stderr = Command('/tmp').execute('hg clone', clone_url)
499 499 assert 'abort: HTTP Error 403: Forbidden' in stderr
500 500 finally:
501 501 #release IP restrictions
502 502 for ip in UserIpMap.getAll():
503 503 UserIpMap.delete(ip.ip_id)
504 504 Session().commit()
505 505
506 506 time.sleep(2)
507 507 clone_url = _construct_url(HG_REPO)
508 508 stdout, stderr = Command('/tmp').execute('hg clone', clone_url)
509 509
510 510 assert 'requesting all changes' in stdout
511 511 assert 'adding changesets' in stdout
512 512 assert 'adding manifests' in stdout
513 513 assert 'adding file changes' in stdout
514 514
515 515 assert stderr == ''
516 516
517 517 def test_ip_restriction_git(self):
518 518 user_model = UserModel()
519 519 try:
520 520 user_model.add_extra_ip(TEST_USER_ADMIN_LOGIN, '10.10.10.10/32')
521 521 Session().commit()
522 522 clone_url = _construct_url(GIT_REPO)
523 523 stdout, stderr = Command('/tmp').execute('git clone', clone_url)
524 524 # The message apparently changed in Git 1.8.3, so match it loosely.
525 525 assert re.search(r'\b403\b', stderr)
526 526 finally:
527 527 #release IP restrictions
528 528 for ip in UserIpMap.getAll():
529 529 UserIpMap.delete(ip.ip_id)
530 530 Session().commit()
531 531
532 532 time.sleep(2)
533 533 clone_url = _construct_url(GIT_REPO)
534 534 stdout, stderr = Command('/tmp').execute('git clone', clone_url)
535 535
536 536 assert 'Cloning into' in stdout + stderr
537 537 assert stderr == '' or stdout == ''
1 NO CONTENT: file renamed from test.ini to kallithea/tests/test.ini
@@ -1,52 +1,52 b''
1 1 [egg_info]
2 2 tag_build =
3 3 tag_svn_revision = 0
4 4 tag_date = 0
5 5
6 6 [nosetests]
7 7 verbose = True
8 8 verbosity = 2
9 with-pylons = test.ini
9 with-pylons = kallithea/tests/test.ini
10 10 detailed-errors = 1
11 11 nologcapture = 1
12 12
13 13 [pytest]
14 14 # only look for tests in kallithea/tests
15 15 python_files = kallithea/tests/**/test_*.py
16 16 addopts =
17 17 # --verbose
18 18 # show extra test summary info as specified by chars (f)ailed, (E)error, (s)skipped, (x)failed, (X)passed, (w)warnings.
19 19 -rfEsxXw
20 20 # Shorter scrollbacks; less stuff to scroll through
21 21 --tb=short
22 22
23 23 [compile_catalog]
24 24 domain = kallithea
25 25 directory = kallithea/i18n
26 26 statistics = true
27 27
28 28 [extract_messages]
29 29 add_comments = TRANSLATORS:
30 30 output_file = kallithea/i18n/kallithea.pot
31 31 msgid-bugs-address = translations@kallithea-scm.org
32 32 copyright-holder = Various authors, licensing as GPLv3
33 33 no-wrap = true
34 34
35 35 [init_catalog]
36 36 domain = kallithea
37 37 input_file = kallithea/i18n/kallithea.pot
38 38 output_dir = kallithea/i18n
39 39
40 40 [update_catalog]
41 41 domain = kallithea
42 42 input_file = kallithea/i18n/kallithea.pot
43 43 output_dir = kallithea/i18n
44 44 previous = true
45 45
46 46 [build_sphinx]
47 47 source-dir = docs/
48 48 build-dir = docs/_build
49 49 all_files = 1
50 50
51 51 [upload_sphinx]
52 52 upload-dir = docs/_build/html
General Comments 0
You need to be logged in to leave comments. Login now