Show More
@@ -0,0 +1,54 b'' | |||||
|
1 | |RCE| 4.23.0 |RNS| | |||
|
2 | ------------------ | |||
|
3 | ||||
|
4 | Release Date | |||
|
5 | ^^^^^^^^^^^^ | |||
|
6 | ||||
|
7 | - 2021-01-10 | |||
|
8 | ||||
|
9 | ||||
|
10 | New Features | |||
|
11 | ^^^^^^^^^^^^ | |||
|
12 | ||||
|
13 | - Artifacts: expose additional headers, and content-disposition for downloads from artifacts exposing the real name of the file. | |||
|
14 | - Token access: allow token in headers not only in GET/URL. | |||
|
15 | - File-store: added a stream upload endpoint, it allows to upload GBs of data into artifact store efficiently. | |||
|
16 | Can be used for backups etc. | |||
|
17 | - Pull requests: expose commit versions in the pull-request commit list. | |||
|
18 | ||||
|
19 | General | |||
|
20 | ^^^^^^^ | |||
|
21 | ||||
|
22 | - Deps: bumped redis to 3.5.3 | |||
|
23 | - rcextensions: improve examples | |||
|
24 | - Setup: added optional parameters to apply a default license, or skip re-creation of database at install. | |||
|
25 | - Docs: update headers for NGINX | |||
|
26 | - Beaker cache: remove no longer used beaker cache init | |||
|
27 | ||||
|
28 | ||||
|
29 | Security | |||
|
30 | ^^^^^^^^ | |||
|
31 | ||||
|
32 | ||||
|
33 | ||||
|
34 | Performance | |||
|
35 | ^^^^^^^^^^^ | |||
|
36 | ||||
|
37 | - Core: speed up cache loading on application startup. | |||
|
38 | - Core: allow loading all auth plugins in once place for CE/EE code. | |||
|
39 | - Application: not use config.scan(), and replace all @add_view decorator into a explicit add_view call for faster app start. | |||
|
40 | ||||
|
41 | ||||
|
42 | Fixes | |||
|
43 | ^^^^^ | |||
|
44 | ||||
|
45 | - Svn: don't print exceptions in case of safe calls | |||
|
46 | - Vcsserver: use safer maxfd reporting, some linux systems get a problem with this | |||
|
47 | - Hooks-daemon: fixed problem with lost hooks value from .ini file. | |||
|
48 | - Exceptions: fixed truncated exception text | |||
|
49 | ||||
|
50 | ||||
|
51 | Upgrade notes | |||
|
52 | ^^^^^^^^^^^^^ | |||
|
53 | ||||
|
54 | - Scheduled release 4.24.0 |
@@ -1,6 +1,5 b'' | |||||
1 | [bumpversion] |
|
1 | [bumpversion] | |
2 |
current_version = 4.2 |
|
2 | current_version = 4.24.0 | |
3 | message = release: Bump version {current_version} to {new_version} |
|
3 | message = release: Bump version {current_version} to {new_version} | |
4 |
|
4 | |||
5 | [bumpversion:file:rhodecode/VERSION] |
|
5 | [bumpversion:file:rhodecode/VERSION] | |
6 |
|
@@ -5,25 +5,20 b' done = false' | |||||
5 | done = true |
|
5 | done = true | |
6 |
|
6 | |||
7 | [task:rc_tools_pinned] |
|
7 | [task:rc_tools_pinned] | |
8 | done = true |
|
|||
9 |
|
8 | |||
10 | [task:fixes_on_stable] |
|
9 | [task:fixes_on_stable] | |
11 | done = true |
|
|||
12 |
|
10 | |||
13 | [task:pip2nix_generated] |
|
11 | [task:pip2nix_generated] | |
14 | done = true |
|
|||
15 |
|
12 | |||
16 | [task:changelog_updated] |
|
13 | [task:changelog_updated] | |
17 | done = true |
|
|||
18 |
|
14 | |||
19 | [task:generate_api_docs] |
|
15 | [task:generate_api_docs] | |
20 | done = true |
|
16 | ||
|
17 | [task:updated_translation] | |||
21 |
|
18 | |||
22 | [release] |
|
19 | [release] | |
23 |
state = |
|
20 | state = in_progress | |
24 |
version = 4.2 |
|
21 | version = 4.24.0 | |
25 |
|
||||
26 | [task:updated_translation] |
|
|||
27 |
|
22 | |||
28 | [task:generate_js_routes] |
|
23 | [task:generate_js_routes] | |
29 |
|
24 |
@@ -1,69 +1,98 b'' | |||||
|
1 | .DEFAULT_GOAL := help | |||
1 |
|
2 | |||
2 | .PHONY: clean docs docs-clean docs-cleanup test test-clean test-only test-only-postgres test-only-mysql web-build generate-pkgs pip-packages |
|
3 | # set by: PATH_TO_OUTDATED_PACKAGES=/some/path/outdated_packages.py | |
|
4 | OUTDATED_PACKAGES = ${PATH_TO_OUTDATED_PACKAGES} | |||
3 |
|
5 | |||
4 | NODE_PATH=./node_modules |
|
6 | NODE_PATH=./node_modules | |
5 | WEBPACK=./node_binaries/webpack |
|
7 | WEBPACK=./node_binaries/webpack | |
6 | GRUNT=./node_binaries/grunt |
|
8 | GRUNT=./node_binaries/grunt | |
7 | # set by: PATH_TO_OUTDATED_PACKAGES=/some/path/outdated_packages.py |
|
|||
8 | OUTDATED_PACKAGES = ${PATH_TO_OUTDATED_PACKAGES} |
|
|||
9 |
|
9 | |||
10 | clean: |
|
10 | .PHONY: clean | |
|
11 | clean: ## full clean | |||
11 | make test-clean |
|
12 | make test-clean | |
12 | find . -type f \( -iname '*.c' -o -iname '*.pyc' -o -iname '*.so' -o -iname '*.orig' \) -exec rm '{}' ';' |
|
13 | find . -type f \( -iname '*.c' -o -iname '*.pyc' -o -iname '*.so' -o -iname '*.orig' \) -exec rm '{}' ';' | |
13 |
|
14 | |||
14 | test: |
|
15 | ||
|
16 | .PHONY: test | |||
|
17 | test: ## run test-clean and tests | |||
15 | make test-clean |
|
18 | make test-clean | |
16 | make test-only |
|
19 | make test-only | |
17 |
|
20 | |||
18 | test-clean: |
|
21 | ||
|
22 | .PHONY:test-clean | |||
|
23 | test-clean: ## run test-clean and tests | |||
19 | rm -rf coverage.xml htmlcov junit.xml pylint.log result |
|
24 | rm -rf coverage.xml htmlcov junit.xml pylint.log result | |
20 | find . -type d -name "__pycache__" -prune -exec rm -rf '{}' ';' |
|
25 | find . -type d -name "__pycache__" -prune -exec rm -rf '{}' ';' | |
21 | find . -type f \( -iname '.coverage.*' \) -exec rm '{}' ';' |
|
26 | find . -type f \( -iname '.coverage.*' \) -exec rm '{}' ';' | |
22 |
|
27 | |||
23 | test-only: |
|
28 | ||
|
29 | .PHONY: test-only | |||
|
30 | test-only: ## run tests | |||
24 | PYTHONHASHSEED=random \ |
|
31 | PYTHONHASHSEED=random \ | |
25 |
py.test -x -vv -r xw -p no:sugar |
|
32 | py.test -x -vv -r xw -p no:sugar \ | |
26 |
|
|
33 | --cov=rhodecode --cov-report=term-missing --cov-report=html \ | |
27 | rhodecode |
|
34 | rhodecode | |
28 |
|
35 | |||
29 | test-only-mysql: |
|
36 | ||
|
37 | .PHONY: test-only-mysql | |||
|
38 | test-only-mysql: ## run tests against mysql | |||
30 | PYTHONHASHSEED=random \ |
|
39 | PYTHONHASHSEED=random \ | |
31 |
py.test -x -vv -r xw -p no:sugar |
|
40 | py.test -x -vv -r xw -p no:sugar \ | |
32 |
|
|
41 | --cov=rhodecode --cov-report=term-missing --cov-report=html \ | |
33 | --ini-config-override='{"app:main": {"sqlalchemy.db1.url": "mysql://root:qweqwe@localhost/rhodecode_test?charset=utf8"}}' \ |
|
42 | --ini-config-override='{"app:main": {"sqlalchemy.db1.url": "mysql://root:qweqwe@localhost/rhodecode_test?charset=utf8"}}' \ | |
34 | rhodecode |
|
43 | rhodecode | |
35 |
|
44 | |||
36 | test-only-postgres: |
|
45 | ||
|
46 | .PHONY: test-only-postgres | |||
|
47 | test-only-postgres: ## run tests against postgres | |||
37 | PYTHONHASHSEED=random \ |
|
48 | PYTHONHASHSEED=random \ | |
38 |
py.test -x -vv -r xw -p no:sugar |
|
49 | py.test -x -vv -r xw -p no:sugar \ | |
39 |
|
|
50 | --cov=rhodecode --cov-report=term-missing --cov-report=html \ | |
40 | --ini-config-override='{"app:main": {"sqlalchemy.db1.url": "postgresql://postgres:qweqwe@localhost/rhodecode_test"}}' \ |
|
51 | --ini-config-override='{"app:main": {"sqlalchemy.db1.url": "postgresql://postgres:qweqwe@localhost/rhodecode_test"}}' \ | |
41 | rhodecode |
|
52 | rhodecode | |
42 |
|
53 | |||
43 |
|
54 | .PHONY: docs | ||
44 | docs: |
|
55 | docs: ## build docs | |
45 | (cd docs; nix-build default.nix -o result; make clean html) |
|
56 | (cd docs; nix-build default.nix -o result; make clean html) | |
46 |
|
57 | |||
47 | docs-clean: |
|
58 | ||
|
59 | .PHONY: docs-clean | |||
|
60 | docs-clean: ## Cleanup docs | |||
48 | (cd docs; make clean) |
|
61 | (cd docs; make clean) | |
49 |
|
62 | |||
50 | docs-cleanup: |
|
63 | ||
|
64 | .PHONY: docs-cleanup | |||
|
65 | docs-cleanup: ## Cleanup docs | |||
51 | (cd docs; make cleanup) |
|
66 | (cd docs; make cleanup) | |
52 |
|
67 | |||
53 | web-build: |
|
68 | ||
|
69 | .PHONY: web-build | |||
|
70 | web-build: ## Build static/js | |||
54 | NODE_PATH=$(NODE_PATH) $(GRUNT) |
|
71 | NODE_PATH=$(NODE_PATH) $(GRUNT) | |
55 |
|
72 | |||
56 | generate-pkgs: |
|
73 | ||
|
74 | .PHONY: generate-pkgs | |||
|
75 | generate-pkgs: ## generate new python packages | |||
57 | nix-shell pkgs/shell-generate.nix --command "pip2nix generate --licenses" |
|
76 | nix-shell pkgs/shell-generate.nix --command "pip2nix generate --licenses" | |
58 |
|
77 | |||
59 | pip-packages: |
|
78 | ||
|
79 | .PHONY: pip-packages | |||
|
80 | pip-packages: ## show outdated packages | |||
60 | python ${OUTDATED_PACKAGES} |
|
81 | python ${OUTDATED_PACKAGES} | |
61 |
|
82 | |||
62 | generate-js-pkgs: |
|
83 | ||
|
84 | .PHONY: generate-js-pkgs | |||
|
85 | generate-js-pkgs: ## generate js packages | |||
63 | rm -rf node_modules && \ |
|
86 | rm -rf node_modules && \ | |
64 | nix-shell pkgs/shell-generate.nix --command "node2nix --input package.json -o pkgs/node-packages.nix -e pkgs/node-env.nix -c pkgs/node-default.nix -d --flatten --nodejs-8" && \ |
|
87 | nix-shell pkgs/shell-generate.nix --command "node2nix --input package.json -o pkgs/node-packages.nix -e pkgs/node-env.nix -c pkgs/node-default.nix -d --flatten --nodejs-8" && \ | |
65 | sed -i -e 's/http:\/\//https:\/\//g' pkgs/node-packages.nix |
|
88 | sed -i -e 's/http:\/\//https:\/\//g' pkgs/node-packages.nix | |
66 |
|
89 | |||
67 | generate-license-meta: |
|
90 | ||
|
91 | .PHONY: generate-license-meta | |||
|
92 | generate-license-meta: ## Generate license metadata | |||
68 | nix-build pkgs/license-generate.nix -o result-license && \ |
|
93 | nix-build pkgs/license-generate.nix -o result-license && \ | |
69 | cat result-license/licenses.json | python -m json.tool > rhodecode/config/licenses.json No newline at end of file |
|
94 | cat result-license/licenses.json | python -m json.tool > rhodecode/config/licenses.json | |
|
95 | ||||
|
96 | .PHONY: help | |||
|
97 | help: | |||
|
98 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-24s\033[0m %s\n", $$1, $$2}' |
@@ -9,6 +9,7 b' Release Notes' | |||||
9 | .. toctree:: |
|
9 | .. toctree:: | |
10 | :maxdepth: 1 |
|
10 | :maxdepth: 1 | |
11 |
|
11 | |||
|
12 | release-notes-4.24.0.rst | |||
12 | release-notes-4.23.2.rst |
|
13 | release-notes-4.23.2.rst | |
13 | release-notes-4.23.1.rst |
|
14 | release-notes-4.23.1.rst | |
14 | release-notes-4.23.0.rst |
|
15 | release-notes-4.23.0.rst |
@@ -1828,11 +1828,11 b' self: super: {' | |||||
1828 | }; |
|
1828 | }; | |
1829 | }; |
|
1829 | }; | |
1830 | "redis" = super.buildPythonPackage { |
|
1830 | "redis" = super.buildPythonPackage { | |
1831 |
name = "redis-3. |
|
1831 | name = "redis-3.5.3"; | |
1832 | doCheck = false; |
|
1832 | doCheck = false; | |
1833 | src = fetchurl { |
|
1833 | src = fetchurl { | |
1834 |
url = "https://files.pythonhosted.org/packages/ef |
|
1834 | url = "https://files.pythonhosted.org/packages/b3/17/1e567ff78c83854e16b98694411fe6e08c3426af866ad11397cddceb80d3/redis-3.5.3.tar.gz"; | |
1835 | sha256 = "07yaj0j9fs7xdkg5bg926fa990khyigjbp31si8ai20vj8sv7kqd"; |
|
1835 | sha256 = "0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2"; | |
1836 | }; |
|
1836 | }; | |
1837 | meta = { |
|
1837 | meta = { | |
1838 | license = [ pkgs.lib.licenses.mit ]; |
|
1838 | license = [ pkgs.lib.licenses.mit ]; | |
@@ -1883,7 +1883,7 b' self: super: {' | |||||
1883 | }; |
|
1883 | }; | |
1884 | }; |
|
1884 | }; | |
1885 | "rhodecode-enterprise-ce" = super.buildPythonPackage { |
|
1885 | "rhodecode-enterprise-ce" = super.buildPythonPackage { | |
1886 |
name = "rhodecode-enterprise-ce-4.2 |
|
1886 | name = "rhodecode-enterprise-ce-4.24.0"; | |
1887 | buildInputs = [ |
|
1887 | buildInputs = [ | |
1888 | self."pytest" |
|
1888 | self."pytest" | |
1889 | self."py" |
|
1889 | self."py" |
@@ -57,7 +57,7 b' tzlocal==1.5.1' | |||||
57 | pyzmq==14.6.0 |
|
57 | pyzmq==14.6.0 | |
58 | py-gfm==0.1.4 |
|
58 | py-gfm==0.1.4 | |
59 | regex==2020.9.27 |
|
59 | regex==2020.9.27 | |
60 |
redis==3. |
|
60 | redis==3.5.3 | |
61 | repoze.lru==0.7 |
|
61 | repoze.lru==0.7 | |
62 | requests==2.22.0 |
|
62 | requests==2.22.0 | |
63 | routes==2.4.1 |
|
63 | routes==2.4.1 |
@@ -23,23 +23,23 b' import pytest' | |||||
23 | from rhodecode.apps._base import ADMIN_PREFIX |
|
23 | from rhodecode.apps._base import ADMIN_PREFIX | |
24 | from rhodecode.model.db import User |
|
24 | from rhodecode.model.db import User | |
25 | from rhodecode.tests import ( |
|
25 | from rhodecode.tests import ( | |
26 | TestController, TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS, |
|
26 | TestController, route_path_generator, assert_session_flash) | |
27 | TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, assert_session_flash) |
|
|||
28 | from rhodecode.tests.fixture import Fixture |
|
27 | from rhodecode.tests.fixture import Fixture | |
29 | from rhodecode.tests.utils import AssertResponse |
|
28 | from rhodecode.tests.utils import AssertResponse | |
30 |
|
29 | |||
31 | fixture = Fixture() |
|
30 | fixture = Fixture() | |
32 |
|
31 | |||
33 |
|
32 | |||
34 | def route_path(name, **kwargs): |
|
33 | def route_path(name, params=None, **kwargs): | |
35 | return { |
|
34 | url_defs = { | |
36 | 'my_account_auth_tokens': |
|
35 | 'my_account_auth_tokens': | |
37 | ADMIN_PREFIX + '/my_account/auth_tokens', |
|
36 | ADMIN_PREFIX + '/my_account/auth_tokens', | |
38 | 'my_account_auth_tokens_add': |
|
37 | 'my_account_auth_tokens_add': | |
39 | ADMIN_PREFIX + '/my_account/auth_tokens/new', |
|
38 | ADMIN_PREFIX + '/my_account/auth_tokens/new', | |
40 | 'my_account_auth_tokens_delete': |
|
39 | 'my_account_auth_tokens_delete': | |
41 | ADMIN_PREFIX + '/my_account/auth_tokens/delete', |
|
40 | ADMIN_PREFIX + '/my_account/auth_tokens/delete', | |
42 | }[name].format(**kwargs) |
|
41 | } | |
|
42 | return route_path_generator(url_defs, name=name, params=params, **kwargs) | |||
43 |
|
43 | |||
44 |
|
44 | |||
45 | class TestMyAccountAuthTokens(TestController): |
|
45 | class TestMyAccountAuthTokens(TestController): |
@@ -357,6 +357,9 b' class RepoPullRequestsView(RepoAppView, ' | |||||
357 | pull_request_id=pull_request_id)) |
|
357 | pull_request_id=pull_request_id)) | |
358 |
|
358 | |||
359 | versions = pull_request_display_obj.versions() |
|
359 | versions = pull_request_display_obj.versions() | |
|
360 | ||||
|
361 | c.commit_versions = PullRequestModel().pr_commits_versions(versions) | |||
|
362 | ||||
360 | # used to store per-commit range diffs |
|
363 | # used to store per-commit range diffs | |
361 | c.changes = collections.OrderedDict() |
|
364 | c.changes = collections.OrderedDict() | |
362 |
|
365 |
@@ -25,20 +25,20 b' import pytest' | |||||
25 | from whoosh import query |
|
25 | from whoosh import query | |
26 |
|
26 | |||
27 | from rhodecode.tests import ( |
|
27 | from rhodecode.tests import ( | |
28 | TestController, HG_REPO, |
|
28 | TestController, route_path_generator, HG_REPO, | |
29 | TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) |
|
29 | TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) | |
30 | from rhodecode.tests.utils import AssertResponse |
|
30 | from rhodecode.tests.utils import AssertResponse | |
31 |
|
31 | |||
32 |
|
32 | |||
33 | def route_path(name, **kwargs): |
|
33 | def route_path(name, params=None, **kwargs): | |
34 | from rhodecode.apps._base import ADMIN_PREFIX |
|
34 | from rhodecode.apps._base import ADMIN_PREFIX | |
35 | return { |
|
35 | url_defs = { | |
36 | 'search': |
|
36 | 'search': | |
37 | ADMIN_PREFIX + '/search', |
|
37 | ADMIN_PREFIX + '/search', | |
38 | 'search_repo': |
|
38 | 'search_repo': | |
39 | '/{repo_name}/search', |
|
39 | '/{repo_name}/search', | |
40 |
|
40 | } | ||
41 | }[name].format(**kwargs) |
|
41 | return route_path_generator(url_defs, name=name, params=params, **kwargs) | |
42 |
|
42 | |||
43 |
|
43 | |||
44 | class TestSearchController(TestController): |
|
44 | class TestSearchController(TestController): |
@@ -47,7 +47,6 b' from rhodecode.lib.vcs import VCSCommuni' | |||||
47 | from rhodecode.lib.exceptions import VCSServerUnavailable |
|
47 | from rhodecode.lib.exceptions import VCSServerUnavailable | |
48 | from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled |
|
48 | from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled | |
49 | from rhodecode.lib.middleware.https_fixup import HttpsFixup |
|
49 | from rhodecode.lib.middleware.https_fixup import HttpsFixup | |
50 | from rhodecode.lib.celerylib.loader import configure_celery |
|
|||
51 | from rhodecode.lib.plugins.utils import register_rhodecode_plugin |
|
50 | from rhodecode.lib.plugins.utils import register_rhodecode_plugin | |
52 | from rhodecode.lib.utils2 import aslist as rhodecode_aslist, AttributeDict |
|
51 | from rhodecode.lib.utils2 import aslist as rhodecode_aslist, AttributeDict | |
53 | from rhodecode.lib.exc_tracking import store_exception |
|
52 | from rhodecode.lib.exc_tracking import store_exception | |
@@ -237,6 +236,7 b' def includeme_first(config):' | |||||
237 |
|
236 | |||
238 |
|
237 | |||
239 | def includeme(config, auth_resources=None): |
|
238 | def includeme(config, auth_resources=None): | |
|
239 | from rhodecode.lib.celerylib.loader import configure_celery | |||
240 | log.debug('Initializing main includeme from %s', os.path.basename(__file__)) |
|
240 | log.debug('Initializing main includeme from %s', os.path.basename(__file__)) | |
241 | settings = config.registry.settings |
|
241 | settings = config.registry.settings | |
242 | config.set_request_factory(Request) |
|
242 | config.set_request_factory(Request) |
@@ -66,11 +66,23 b' class DbManage(object):' | |||||
66 | self.root = root |
|
66 | self.root = root | |
67 | self.dburi = dbconf |
|
67 | self.dburi = dbconf | |
68 | self.log_sql = log_sql |
|
68 | self.log_sql = log_sql | |
69 | self.db_exists = False |
|
|||
70 | self.cli_args = cli_args or {} |
|
69 | self.cli_args = cli_args or {} | |
71 | self.init_db(SESSION=SESSION) |
|
70 | self.init_db(SESSION=SESSION) | |
72 | self.ask_ok = self.get_ask_ok_func(self.cli_args.get('force_ask')) |
|
71 | self.ask_ok = self.get_ask_ok_func(self.cli_args.get('force_ask')) | |
73 |
|
72 | |||
|
73 | def db_exists(self): | |||
|
74 | if not self.sa: | |||
|
75 | self.init_db() | |||
|
76 | try: | |||
|
77 | self.sa.query(RhodeCodeUi)\ | |||
|
78 | .filter(RhodeCodeUi.ui_key == '/')\ | |||
|
79 | .scalar() | |||
|
80 | return True | |||
|
81 | except Exception: | |||
|
82 | return False | |||
|
83 | finally: | |||
|
84 | self.sa.rollback() | |||
|
85 | ||||
74 | def get_ask_ok_func(self, param): |
|
86 | def get_ask_ok_func(self, param): | |
75 | if param not in [None]: |
|
87 | if param not in [None]: | |
76 | # return a function lambda that has a default set to param |
|
88 | # return a function lambda that has a default set to param |
@@ -120,7 +120,7 b' class ThreadedHookCallbackDaemon(object)' | |||||
120 | _done = False |
|
120 | _done = False | |
121 |
|
121 | |||
122 | def __init__(self, txn_id=None, host=None, port=None): |
|
122 | def __init__(self, txn_id=None, host=None, port=None): | |
123 |
self._prepare(txn_id=txn_id, host= |
|
123 | self._prepare(txn_id=txn_id, host=host, port=port) | |
124 |
|
124 | |||
125 | def __enter__(self): |
|
125 | def __enter__(self): | |
126 | log.debug('Running `%s` callback daemon', self.__class__.__name__) |
|
126 | log.debug('Running `%s` callback daemon', self.__class__.__name__) |
@@ -60,14 +60,24 b' log = logging.getLogger(__name__)' | |||||
60 | default=None, |
|
60 | default=None, | |
61 | help='Enable public access on this installation. ' |
|
61 | help='Enable public access on this installation. ' | |
62 | 'Default is public access enabled.') |
|
62 | 'Default is public access enabled.') | |
|
63 | @click.option( | |||
|
64 | '--skip-existing-db', | |||
|
65 | default=False, | |||
|
66 | is_flag=True, | |||
|
67 | help='Do not destroy and re-initialize the database if it already exist.') | |||
|
68 | @click.option( | |||
|
69 | '--apply-license-key', | |||
|
70 | default=False, | |||
|
71 | is_flag=True, | |||
|
72 | help='Get the license key from a license file or ENV and apply during DB creation.') | |||
63 | def main(ini_path, force_yes, user, email, password, api_key, repos, |
|
73 | def main(ini_path, force_yes, user, email, password, api_key, repos, | |
64 | public_access): |
|
74 | public_access, skip_existing_db, apply_license_key): | |
65 | return command(ini_path, force_yes, user, email, password, api_key, |
|
75 | return command(ini_path, force_yes, user, email, password, api_key, | |
66 | repos, public_access) |
|
76 | repos, public_access, skip_existing_db, apply_license_key) | |
67 |
|
77 | |||
68 |
|
78 | |||
69 | def command(ini_path, force_yes, user, email, password, api_key, repos, |
|
79 | def command(ini_path, force_yes, user, email, password, api_key, repos, | |
70 | public_access): |
|
80 | public_access, skip_existing_db, apply_license_key): | |
71 | # mapping of old parameters to new CLI from click |
|
81 | # mapping of old parameters to new CLI from click | |
72 | options = dict( |
|
82 | options = dict( | |
73 | username=user, |
|
83 | username=user, | |
@@ -85,6 +95,9 b' def command(ini_path, force_yes, user, e' | |||||
85 | db_uri = config['sqlalchemy.db1.url'] |
|
95 | db_uri = config['sqlalchemy.db1.url'] | |
86 | dbmanage = DbManage(log_sql=True, dbconf=db_uri, root='.', |
|
96 | dbmanage = DbManage(log_sql=True, dbconf=db_uri, root='.', | |
87 | tests=False, cli_args=options) |
|
97 | tests=False, cli_args=options) | |
|
98 | if skip_existing_db and dbmanage.db_exists(): | |||
|
99 | return | |||
|
100 | ||||
88 | dbmanage.create_tables(override=True) |
|
101 | dbmanage.create_tables(override=True) | |
89 | dbmanage.set_db_version() |
|
102 | dbmanage.set_db_version() | |
90 | opts = dbmanage.config_prompt(None) |
|
103 | opts = dbmanage.config_prompt(None) | |
@@ -93,6 +106,13 b' def command(ini_path, force_yes, user, e' | |||||
93 | dbmanage.create_admin_and_prompt() |
|
106 | dbmanage.create_admin_and_prompt() | |
94 | dbmanage.create_permissions() |
|
107 | dbmanage.create_permissions() | |
95 | dbmanage.populate_default_permissions() |
|
108 | dbmanage.populate_default_permissions() | |
|
109 | if apply_license_key: | |||
|
110 | try: | |||
|
111 | from rc_license.models import apply_trial_license_if_missing | |||
|
112 | apply_trial_license_if_missing(force=True) | |||
|
113 | except ImportError: | |||
|
114 | pass | |||
|
115 | ||||
96 | Session().commit() |
|
116 | Session().commit() | |
97 |
|
117 | |||
98 | with bootstrap(ini_path, env={'RC_CMD_SETUP_RC': '1'}) as env: |
|
118 | with bootstrap(ini_path, env={'RC_CMD_SETUP_RC': '1'}) as env: |
@@ -3821,8 +3821,12 b' class ChangesetComment(Base, BaseModel):' | |||||
3821 | return q.all() |
|
3821 | return q.all() | |
3822 |
|
3822 | |||
3823 | @classmethod |
|
3823 | @classmethod | |
3824 | def get_index_from_version(cls, pr_version, versions): |
|
3824 | def get_index_from_version(cls, pr_version, versions=None, num_versions=None): | |
3825 | num_versions = [x.pull_request_version_id for x in versions] |
|
3825 | ||
|
3826 | if versions is not None: | |||
|
3827 | num_versions = [x.pull_request_version_id for x in versions] | |||
|
3828 | ||||
|
3829 | num_versions = num_versions or [] | |||
3826 | try: |
|
3830 | try: | |
3827 | return num_versions.index(pr_version) + 1 |
|
3831 | return num_versions.index(pr_version) + 1 | |
3828 | except (IndexError, ValueError): |
|
3832 | except (IndexError, ValueError): |
@@ -610,6 +610,20 b' class PullRequestModel(BaseModel):' | |||||
610 | return _org_pull_request_obj, pull_request_obj, \ |
|
610 | return _org_pull_request_obj, pull_request_obj, \ | |
611 | pull_request_display_obj, at_version |
|
611 | pull_request_display_obj, at_version | |
612 |
|
612 | |||
|
613 | def pr_commits_versions(self, versions): | |||
|
614 | """ | |||
|
615 | Maps the pull-request commits into all known PR versions. This way we can obtain | |||
|
616 | each pr version the commit was introduced in. | |||
|
617 | """ | |||
|
618 | commit_versions = collections.defaultdict(list) | |||
|
619 | num_versions = [x.pull_request_version_id for x in versions] | |||
|
620 | for ver in versions: | |||
|
621 | for commit_id in ver.revisions: | |||
|
622 | ver_idx = ChangesetComment.get_index_from_version( | |||
|
623 | ver.pull_request_version_id, num_versions=num_versions) | |||
|
624 | commit_versions[commit_id].append(ver_idx) | |||
|
625 | return commit_versions | |||
|
626 | ||||
613 | def create(self, created_by, source_repo, source_ref, target_repo, |
|
627 | def create(self, created_by, source_repo, source_ref, target_repo, | |
614 | target_ref, revisions, reviewers, observers, title, description=None, |
|
628 | target_ref, revisions, reviewers, observers, title, description=None, | |
615 | common_ancestor_id=None, |
|
629 | common_ancestor_id=None, |
@@ -12,6 +12,9 b'' | |||||
12 | <input type="hidden" name="__start__" value="revisions:sequence"> |
|
12 | <input type="hidden" name="__start__" value="revisions:sequence"> | |
13 | <table class="rctable compare_view_commits"> |
|
13 | <table class="rctable compare_view_commits"> | |
14 | <tr> |
|
14 | <tr> | |
|
15 | % if hasattr(c, 'commit_versions'): | |||
|
16 | <th>ver</th> | |||
|
17 | % endif | |||
15 | <th>${_('Time')}</th> |
|
18 | <th>${_('Time')}</th> | |
16 | <th>${_('Author')}</th> |
|
19 | <th>${_('Author')}</th> | |
17 | <th>${_('Commit')}</th> |
|
20 | <th>${_('Commit')}</th> | |
@@ -30,6 +33,11 b'' | |||||
30 | class="compare_select" |
|
33 | class="compare_select" | |
31 | style="${'display: none' if c.collapse_all_commits else ''}" |
|
34 | style="${'display: none' if c.collapse_all_commits else ''}" | |
32 | > |
|
35 | > | |
|
36 | % if hasattr(c, 'commit_versions'): | |||
|
37 | <td class="tooltip" title="${_('Pull request version this commit was introduced')}"> | |||
|
38 | <code>${('v{}'.format(c.commit_versions[commit.raw_id][0]) if c.commit_versions[commit.raw_id] else 'latest')}</code> | |||
|
39 | </td> | |||
|
40 | % endif | |||
33 | <td class="td-time"> |
|
41 | <td class="td-time"> | |
34 | ${h.age_component(commit.date)} |
|
42 | ${h.age_component(commit.date)} | |
35 | </td> |
|
43 | </td> |
@@ -33,15 +33,15 b' import pytest' | |||||
33 | from rhodecode.model.db import User |
|
33 | from rhodecode.model.db import User | |
34 | from rhodecode.lib import auth |
|
34 | from rhodecode.lib import auth | |
35 | from rhodecode.lib import helpers as h |
|
35 | from rhodecode.lib import helpers as h | |
36 |
from rhodecode.lib.helpers import flash |
|
36 | from rhodecode.lib.helpers import flash | |
37 | from rhodecode.lib.utils2 import safe_str |
|
37 | from rhodecode.lib.utils2 import safe_str | |
38 |
|
38 | |||
39 |
|
39 | |||
40 | log = logging.getLogger(__name__) |
|
40 | log = logging.getLogger(__name__) | |
41 |
|
41 | |||
42 | __all__ = [ |
|
42 | __all__ = [ | |
43 | 'get_new_dir', 'TestController', |
|
43 | 'get_new_dir', 'TestController', 'route_path_generator', | |
44 |
|
|
44 | 'clear_cache_regions', | |
45 | 'assert_session_flash', 'login_user', 'no_newline_id_generator', |
|
45 | 'assert_session_flash', 'login_user', 'no_newline_id_generator', | |
46 | 'TESTS_TMP_PATH', 'HG_REPO', 'GIT_REPO', 'SVN_REPO', |
|
46 | 'TESTS_TMP_PATH', 'HG_REPO', 'GIT_REPO', 'SVN_REPO', | |
47 | 'NEW_HG_REPO', 'NEW_GIT_REPO', |
|
47 | 'NEW_HG_REPO', 'NEW_GIT_REPO', | |
@@ -243,3 +243,13 b' def no_newline_id_generator(test_name):' | |||||
243 | .replace(' ', '_S') |
|
243 | .replace(' ', '_S') | |
244 |
|
244 | |||
245 | return test_name or 'test-with-empty-name' |
|
245 | return test_name or 'test-with-empty-name' | |
|
246 | ||||
|
247 | ||||
|
248 | def route_path_generator(url_defs, name, params=None, **kwargs): | |||
|
249 | import urllib | |||
|
250 | ||||
|
251 | base_url = url_defs[name].format(**kwargs) | |||
|
252 | ||||
|
253 | if params: | |||
|
254 | base_url = '{}?{}'.format(base_url, urllib.urlencode(params)) | |||
|
255 | return base_url |
General Comments 0
You need to be logged in to leave comments.
Login now