##// END OF EJS Templates
release: Merge default into stable for release preparation
marcink -
r3786:3da01d04 merge stable
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -0,0 +1,28 b''
1 .. _repo-admin-set:
2 .. _permissions-info-add-group-ref:
3
4 Repository Administration
5 =========================
6
7 Repository permissions in |RCE| can be managed in a number of different ways.
8 This overview should give you an insight into how you could adopt particular
9 settings for your needs:
10
11 * Global |repo| permissions: This allows you to set the default permissions
12 for each new |repo| created within |RCE|, see :ref:`repo-default-ref`. All
13 |repos| created will inherit these permissions unless explicitly configured.
14 * Individual |repo| permissions: To set individual |repo| permissions,
15 see :ref:`set-repo-perms`.
16 * Repository Group permissions: This allows you to define the permissions for
17 a group, and all |repos| created within that group will inherit the same
18 permissions.
19
20 .. toctree::
21
22 repo_admin/repo-perm-steps
23 repo_admin/repo-extra-fields
24 repo_admin/repo-hooks
25 repo_admin/repo-issue-tracker
26 repo_admin/repo-vcs
27 repo_admin/restore-deleted-repositories
28 repo_admin/repo-admin-tasks No newline at end of file
@@ -0,0 +1,24 b''
1 .. _repo-admin-tasks:
2
3 Common Admin Tasks for Repositories
4 -----------------------------------
5
6
7 Manually Force Delete Repository
8 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9
10 In case of attached forks or pull-requests repositories should be archived.
11 Here is how to force delete a repository and remove all dependent objects
12
13
14 .. code-block:: bash
15
16 # starts the ishell interactive prompt
17 $ rccontrol ishell enterprise-1
18
19 .. code-block:: python
20
21 In [4]: from rhodecode.model.repo import RepoModel
22 In [3]: repo = Repository.get_by_repo_name('test_repos/repo_with_prs')
23 In [5]: RepoModel().delete(repo, forks='detach', pull_requests='delete')
24 In [6]: Session().commit()
@@ -0,0 +1,24 b''
1 .. _user-admin-tasks:
2
3 Common Admin Tasks for Users
4 ----------------------------
5
6
7 Manually Set Personal Repository Group
8 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9
10 Here is how to set a repository group as personal for a user using ishell.
11
12
13 .. code-block:: bash
14
15 # starts the ishell interactive prompt
16 $ rccontrol ishell enterprise-1
17
18 .. code-block:: python
19
20 In [1]: repo_group = RepoGroup.get_by_group_name('some_group_name')
21 In [2]: user = User.get_by_username('some_user')
22 In [3]: repo_group.user = user
23 In [4]: repo_group.personal = True
24 In [5]: Session().add(repo_group);Session().commit()
@@ -0,0 +1,35 b''
1 .. _search-methods-ref:
2
3 search methods
4 ==============
5
6 search
7 ------
8
9 .. py:function:: search(apiuser, search_query, search_type, page_limit=<Optional:10>, page=<Optional:1>, search_sort=<Optional:'newfirst'>, repo_name=<Optional:None>, repo_group_name=<Optional:None>)
10
11 Fetch Full Text Search results using API.
12
13 :param apiuser: This is filled automatically from the |authtoken|.
14 :type apiuser: AuthUser
15 :param search_query: Search query.
16 :type search_query: str
17 :param search_type: Search type. The following are valid options:
18 * commit
19 * content
20 * path
21 :type search_type: str
22 :param page_limit: Page item limit, from 1 to 500. Default 10 items.
23 :type page_limit: Optional(int)
24 :param page: Page number. Default first page.
25 :type page: Optional(int)
26 :param search_sort: Search sort order. Default newfirst. The following are valid options:
27 * newfirst
28 * oldfirst
29 :type search_sort: Optional(str)
30 :param repo_name: Filter by one repo. Default is all.
31 :type repo_name: Optional(str)
32 :param repo_group_name: Filter by one repo group. Default is all.
33 :type repo_group_name: Optional(str)
34
35
@@ -0,0 +1,85 b''
1 |RCE| 4.17.0 |RNS|
2 ------------------
3
4 Release Date
5 ^^^^^^^^^^^^
6
7 - 2019-07-04
8
9
10 New Features
11 ^^^^^^^^^^^^
12
13 - New artifacts feature.
14 Ability to store binary artifacts for repository with ACL
15 - UI/UX refresh for most of the pages. This includes multiple fixes and improvements.
16 - Diffs: store wide-diff mode in user sessions to store user preference for diff display.
17 - Mercurial: added support for Mercurial 4.9
18 - API: Added search API methods
19 - Files: adding/editing allows previews for generated content.
20 - Files: allowed multi file upload using UI.
21 - Repository Groups: last change is now smartly calculated based on latest change
22 from all it's children repositories.
23 - Archives: it's now currently possible to download partial directories from files view.
24 - SVN: allowed executing pre-commit code with rcextensions, also added example to
25 validate SVN file size and paths on pre-commit level.
26
27
28 General
29 ^^^^^^^
30 - Exception store: add filter for display and deletion.
31 - Files: loading history doesn't display hidden and obsolete commits anymore.
32 - Repositories: bring back missing watch action in summary view.
33 - Admin: user groups is now using pure DB filtering to speed up display
34 for large number of groups.
35 - Mercurial: enabled full evolve+topic extensions when evolve is enabled.
36 - Dependencies: bumped evolve to 8.5.1
37 - Dependencies: bumped pyramid to 1.10.4
38 - Dependencies: bumped psutil to 5.5.1
39 - Dependencies: bumped pygments to 2.4.2
40 - Dependencies: bumped pyramid to 1.10.4
41 - Dependencies: bumped psycopg2 to 2.8.3
42 - Dependencies [security]: updated colander to 1.7.0
43
44
45 Security
46 ^^^^^^^^
47
48 - SSH: replaced pycrypto with cryptography to generate SSH keys as pycrypto isn't
49 considered safe anymore.
50
51
52 Performance
53 ^^^^^^^^^^^
54
55 - Config: updated header limits on gunicorn to prevent errors on large Mercurial repositories.
56 - User sessions: added option to cleanup redis based sessions in user session interface.
57 - Authentication: reduced usage of raw auth calls inside templates to speed up rendering.
58 - Sessions: don't touch session for API calls. Before each API call created new session
59 object which wasn't required.
60
61
62 Fixes
63 ^^^^^
64
65 - hHooks: fixed more unicode problems with new pull-request link generator.
66 - Mercurial: fix ssh-server support for mercurial custom options.
67 - Pull requests: updated metadata information for failed merges with multiple heads.
68 - Pull requests: calculate ancestor in the same way as creation mode.
69 Fixed problem with updates generating wrong diffs in case of merges.
70 - Pull requests: fixed a bug in removal of multiple reviewers at once.
71 - Summary: fix timeout issues loading summary page without styling.
72 - SSH: fix invocation of custom hgrc.
73 - SSH: call custom hooks via SSH backend
74 - Markup: fix styling for check-lists.
75 - Archives: allows downloading refs that have slashes and special refs. e.g f/feat1 branch names.
76 - Files: ensure we generate archives with consistent hashing (except for .tar.gz which uses temp files names in header)
77 - Files: fixed rendering of readme files under non-ascii paths.
78
79
80 Upgrade notes
81 ^^^^^^^^^^^^^
82
83 - In this release we introduced new UI across the application.
84 In case of problems with the display on your systems please send us info to support@rhodecode.com.
85
@@ -0,0 +1,19 b''
1 # contains not directly required libraries we want to pin the version.
2
3 atomicwrites==1.2.1
4 attrs==18.2.0
5 billiard==3.5.0.3
6 chameleon==2.24
7 cffi==1.12.2
8 ecdsa==0.13.2
9 hupper==1.6.1
10 gnureadline==6.3.8
11 jinja2==2.9.6
12 jsonschema==2.6.0
13 pyramid-jinja2==2.7
14 pluggy==0.11.0
15 setproctitle==1.1.10
16 scandir==1.10.0
17 tempita==0.5.2
18 vine==1.3.0
19 configparser==3.7.4
@@ -0,0 +1,93 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import pytest
22 from rhodecode.tests import HG_REPO
23 from rhodecode.api.tests.utils import (
24 build_data, api_call, assert_error, assert_ok)
25
26
27 @pytest.mark.usefixtures("testuser_api", "app")
28 class TestApiSearch(object):
29
30 @pytest.mark.parametrize("query, expected_hits, expected_paths", [
31 ('todo', 23, [
32 'vcs/backends/hg/inmemory.py',
33 'vcs/tests/test_git.py']),
34 ('extension:rst installation', 6, [
35 'docs/index.rst',
36 'docs/installation.rst']),
37 ('def repo', 87, [
38 'vcs/tests/test_git.py',
39 'vcs/tests/test_changesets.py']),
40 ('repository:%s def test' % HG_REPO, 18, [
41 'vcs/tests/test_git.py',
42 'vcs/tests/test_changesets.py']),
43 ('"def main"', 9, [
44 'vcs/__init__.py',
45 'vcs/tests/__init__.py',
46 'vcs/utils/progressbar.py']),
47 ('owner:test_admin', 358, [
48 'vcs/tests/base.py',
49 'MANIFEST.in',
50 'vcs/utils/termcolors.py',
51 'docs/theme/ADC/static/documentation.png']),
52 ('owner:test_admin def main', 72, [
53 'vcs/__init__.py',
54 'vcs/tests/test_utils_filesize.py',
55 'vcs/tests/test_cli.py']),
56 ('owner:michał test', 0, []),
57 ])
58 def test_search_content_results(self, query, expected_hits, expected_paths):
59 id_, params = build_data(
60 self.apikey_regular, 'search',
61 search_query=query,
62 search_type='content')
63
64 response = api_call(self.app, params)
65 json_response = response.json
66
67 assert json_response['result']['item_count'] == expected_hits
68 paths = [x['f_path'] for x in json_response['result']['results']]
69
70 for expected_path in expected_paths:
71 assert expected_path in paths
72
73 @pytest.mark.parametrize("query, expected_hits, expected_paths", [
74 ('readme.rst', 3, []),
75 ('test*', 75, []),
76 ('*model*', 1, []),
77 ('extension:rst', 48, []),
78 ('extension:rst api', 24, []),
79 ])
80 def test_search_file_paths(self, query, expected_hits, expected_paths):
81 id_, params = build_data(
82 self.apikey_regular, 'search',
83 search_query=query,
84 search_type='path')
85
86 response = api_call(self.app, params)
87 json_response = response.json
88
89 assert json_response['result']['item_count'] == expected_hits
90 paths = [x['f_path'] for x in json_response['result']['results']]
91
92 for expected_path in expected_paths:
93 assert expected_path in paths
@@ -0,0 +1,112 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 import logging
23
24 from rhodecode.api import jsonrpc_method
25 from rhodecode.api.exc import JSONRPCValidationError
26 from rhodecode.api.utils import Optional
27 from rhodecode.lib.index import searcher_from_config
28 from rhodecode.model import validation_schema
29 from rhodecode.model.validation_schema.schemas import search_schema
30
31 log = logging.getLogger(__name__)
32
33
34 @jsonrpc_method()
35 def search(request, apiuser, search_query, search_type, page_limit=Optional(10),
36 page=Optional(1), search_sort=Optional('newfirst'),
37 repo_name=Optional(None), repo_group_name=Optional(None)):
38 """
39 Fetch Full Text Search results using API.
40
41 :param apiuser: This is filled automatically from the |authtoken|.
42 :type apiuser: AuthUser
43 :param search_query: Search query.
44 :type search_query: str
45 :param search_type: Search type. The following are valid options:
46 * commit
47 * content
48 * path
49 :type search_type: str
50 :param page_limit: Page item limit, from 1 to 500. Default 10 items.
51 :type page_limit: Optional(int)
52 :param page: Page number. Default first page.
53 :type page: Optional(int)
54 :param search_sort: Search sort order. Default newfirst. The following are valid options:
55 * newfirst
56 * oldfirst
57 :type search_sort: Optional(str)
58 :param repo_name: Filter by one repo. Default is all.
59 :type repo_name: Optional(str)
60 :param repo_group_name: Filter by one repo group. Default is all.
61 :type repo_group_name: Optional(str)
62 """
63
64 data = {'execution_time': ''}
65 repo_name = Optional.extract(repo_name)
66 repo_group_name = Optional.extract(repo_group_name)
67
68 schema = search_schema.SearchParamsSchema()
69
70 try:
71 search_params = schema.deserialize(
72 dict(search_query=search_query,
73 search_type=search_type,
74 search_sort=Optional.extract(search_sort),
75 page_limit=Optional.extract(page_limit),
76 requested_page=Optional.extract(page))
77 )
78 except validation_schema.Invalid as err:
79 raise JSONRPCValidationError(colander_exc=err)
80
81 search_query = search_params.get('search_query')
82 search_type = search_params.get('search_type')
83 search_sort = search_params.get('search_sort')
84
85 if search_params.get('search_query'):
86 page_limit = search_params['page_limit']
87 requested_page = search_params['requested_page']
88
89 searcher = searcher_from_config(request.registry.settings)
90
91 try:
92 search_result = searcher.search(
93 search_query, search_type, apiuser, repo_name, repo_group_name,
94 requested_page=requested_page, page_limit=page_limit, sort=search_sort)
95
96 data.update(dict(
97 results=list(search_result['results']), page=requested_page,
98 item_count=search_result['count'],
99 items_per_page=page_limit))
100 finally:
101 searcher.cleanup()
102
103 if not search_result['error']:
104 data['execution_time'] = '%s results (%.3f seconds)' % (
105 search_result['count'],
106 search_result['runtime'])
107 else:
108 node = schema['search_query']
109 raise JSONRPCValidationError(
110 colander_exc=validation_schema.Invalid(node, search_result['error']))
111
112 return data
@@ -0,0 +1,48 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import logging
22
23 from pyramid.view import view_config
24
25 from rhodecode.apps._base import RepoAppView
26 from rhodecode.lib.auth import (
27 LoginRequired, HasRepoPermissionAnyDecorator)
28
29 log = logging.getLogger(__name__)
30
31
32 class RepoArtifactsView(RepoAppView):
33
34 def load_default_context(self):
35 c = self._get_local_tmpl_context(include_app_defaults=True)
36 c.rhodecode_repo = self.rhodecode_vcs_repo
37 return c
38
39 @LoginRequired()
40 @HasRepoPermissionAnyDecorator(
41 'repository.read', 'repository.write', 'repository.admin')
42 @view_config(
43 route_name='repo_artifacts_list', request_method='GET',
44 renderer='rhodecode:templates/artifacts/artifact_list.mako')
45 def repo_artifacts(self):
46 c = self.load_default_context()
47 c.active = 'artifacts'
48 return self._get_template_context(c)
@@ -0,0 +1,55 b''
1 # -*- coding: utf-8 -*-
2
3 import logging
4
5 from alembic.migration import MigrationContext
6 from alembic.operations import Operations
7 from sqlalchemy import String, Column
8 from sqlalchemy.sql import text
9
10 from rhodecode.lib.dbmigrate.versions import _reset_base
11 from rhodecode.lib.utils2 import safe_str
12 from rhodecode.model import meta, init_model_encryption
13 from rhodecode.model.db import RepoGroup
14
15
16 log = logging.getLogger(__name__)
17
18
19 def upgrade(migrate_engine):
20 """
21 Upgrade operations go here.
22 Don't create your own engine; bind migrate_engine to your metadata
23 """
24 _reset_base(migrate_engine)
25 from rhodecode.lib.dbmigrate.schema import db_4_16_0_2
26
27 init_model_encryption(db_4_16_0_2)
28
29 context = MigrationContext.configure(migrate_engine.connect())
30 op = Operations(context)
31
32 repo_group = db_4_16_0_2.RepoGroup.__table__
33
34 with op.batch_alter_table(repo_group.name) as batch_op:
35 batch_op.add_column(
36 Column("repo_group_name_hash", String(1024), nullable=True, unique=False))
37
38 _generate_repo_group_name_hashes(db_4_16_0_2, op, meta.Session)
39
40
41 def downgrade(migrate_engine):
42 pass
43
44
45 def _generate_repo_group_name_hashes(models, op, session):
46 repo_groups = models.RepoGroup.get_all()
47 for repo_group in repo_groups:
48 print(safe_str(repo_group.group_name))
49 hash_ = RepoGroup.hash_repo_group_name(repo_group.group_name)
50 params = {'hash': hash_, 'id': repo_group.group_id}
51 query = text(
52 'UPDATE groups SET repo_group_name_hash = :hash'
53 ' WHERE group_id = :id').bindparams(**params)
54 op.execute(query)
55 session().commit()
@@ -0,0 +1,35 b''
1 # -*- coding: utf-8 -*-
2
3 import logging
4
5 from alembic.migration import MigrationContext
6 from alembic.operations import Operations
7
8 from rhodecode.lib.dbmigrate.versions import _reset_base
9 from rhodecode.model import init_model_encryption
10
11
12 log = logging.getLogger(__name__)
13
14
15 def upgrade(migrate_engine):
16 """
17 Upgrade operations go here.
18 Don't create your own engine; bind migrate_engine to your metadata
19 """
20 _reset_base(migrate_engine)
21 from rhodecode.lib.dbmigrate.schema import db_4_16_0_2
22
23 init_model_encryption(db_4_16_0_2)
24
25 context = MigrationContext.configure(migrate_engine.connect())
26 op = Operations(context)
27
28 repo_group = db_4_16_0_2.RepoGroup.__table__
29
30 with op.batch_alter_table(repo_group.name) as batch_op:
31 batch_op.alter_column("repo_group_name_hash", nullable=False)
32
33
34 def downgrade(migrate_engine):
35 pass
@@ -0,0 +1,37 b''
1 # -*- coding: utf-8 -*-
2
3 import logging
4
5 from alembic.migration import MigrationContext
6 from alembic.operations import Operations
7 from sqlalchemy import Column, LargeBinary
8
9 from rhodecode.lib.dbmigrate.versions import _reset_base
10 from rhodecode.model import init_model_encryption
11
12
13 log = logging.getLogger(__name__)
14
15
16 def upgrade(migrate_engine):
17 """
18 Upgrade operations go here.
19 Don't create your own engine; bind migrate_engine to your metadata
20 """
21 _reset_base(migrate_engine)
22 from rhodecode.lib.dbmigrate.schema import db_4_16_0_2
23
24 init_model_encryption(db_4_16_0_2)
25
26 context = MigrationContext.configure(migrate_engine.connect())
27 op = Operations(context)
28
29 repo_group = db_4_16_0_2.RepoGroup.__table__
30
31 with op.batch_alter_table(repo_group.name) as batch_op:
32 batch_op.add_column(
33 Column("changeset_cache", LargeBinary(1024), nullable=True))
34
35
36 def downgrade(migrate_engine):
37 pass
@@ -0,0 +1,69 b''
1 import os
2 import base64
3 from cryptography.fernet import Fernet, InvalidToken
4 from cryptography.hazmat.backends import default_backend
5 from cryptography.hazmat.primitives import hashes
6 from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
7
8
9 class Encryptor(object):
10 key_format = 'enc2$salt:{}$data:{}'
11 pref_len = 5 # salt:, data:
12
13 def __init__(self, enc_key):
14 self.enc_key = enc_key
15
16 def b64_encode(self, data):
17 return base64.urlsafe_b64encode(data)
18
19 def b64_decode(self, data):
20 return base64.urlsafe_b64decode(data)
21
22 def get_encryptor(self, salt):
23 """
24 Uses Fernet as encryptor with HMAC signature
25 :param salt: random salt used for encrypting the data
26 """
27 kdf = PBKDF2HMAC(
28 algorithm=hashes.SHA512(),
29 length=32,
30 salt=salt,
31 iterations=100000,
32 backend=default_backend()
33 )
34 key = self.b64_encode(kdf.derive(self.enc_key))
35 return Fernet(key)
36
37 def _get_parts(self, enc_data):
38 parts = enc_data.split('$', 3)
39 if len(parts) != 3:
40 raise ValueError('Encrypted Data has invalid format, expected {}'.format(self.key_format))
41 prefix, salt, enc_data = parts
42
43 try:
44 salt = self.b64_decode(salt[self.pref_len:])
45 except TypeError:
46 # bad base64
47 raise ValueError('Encrypted Data salt invalid format, expected base64 format')
48
49 enc_data = enc_data[self.pref_len:]
50 return prefix, salt, enc_data
51
52 def encrypt(self, data):
53 salt = os.urandom(64)
54 encryptor = self.get_encryptor(salt)
55 enc_data = encryptor.encrypt(data)
56 return self.key_format.format(self.b64_encode(salt), enc_data)
57
58 def decrypt(self, data, safe=True):
59 parts = self._get_parts(data)
60 salt = parts[1]
61 enc_data = parts[2]
62 encryptor = self.get_encryptor(salt)
63 try:
64 return encryptor.decrypt(enc_data)
65 except (InvalidToken,):
66 if safe:
67 return ''
68 else:
69 raise
@@ -0,0 +1,200 b''
1 # Copyright (c) 2010 Agendaless Consulting and Contributors.
2 # (http://www.agendaless.com), All Rights Reserved
3 # License: BSD-derived (http://www.repoze.org/LICENSE.txt)
4 # With Patches from RhodeCode GmBH
5
6
7 import os
8
9 from beaker import cache
10 from beaker.session import SessionObject
11 from beaker.util import coerce_cache_params
12 from beaker.util import coerce_session_params
13
14 from pyramid.interfaces import ISession
15 from pyramid.settings import asbool
16 from zope.interface import implementer
17
18 from binascii import hexlify
19
20
21 def BeakerSessionFactoryConfig(**options):
22 """ Return a Pyramid session factory using Beaker session settings
23 supplied directly as ``**options``"""
24
25 class PyramidBeakerSessionObject(SessionObject):
26 _options = options
27 _cookie_on_exception = _options.pop('cookie_on_exception', True)
28 _constant_csrf_token = _options.pop('constant_csrf_token', False)
29
30 def __init__(self, request):
31 SessionObject.__init__(self, request.environ, **self._options)
32
33 def session_callback(request, response):
34 exception = getattr(request, 'exception', None)
35 if (exception is None or self._cookie_on_exception) and self.accessed():
36 self.persist()
37 headers = self.__dict__['_headers']
38 if headers['set_cookie'] and headers['cookie_out']:
39 response.headerlist.append(('Set-Cookie', headers['cookie_out']))
40 request.add_response_callback(session_callback)
41
42 # ISession API
43
44 @property
45 def id(self):
46 # this is as inspected in SessionObject.__init__
47 if self.__dict__['_params'].get('type') != 'cookie':
48 return self._session().id
49 return None
50
51 @property
52 def new(self):
53 return self.last_accessed is None
54
55 changed = SessionObject.save
56
57 # modifying dictionary methods
58
59 @call_save
60 def clear(self):
61 return self._session().clear()
62
63 @call_save
64 def update(self, d, **kw):
65 return self._session().update(d, **kw)
66
67 @call_save
68 def setdefault(self, k, d=None):
69 return self._session().setdefault(k, d)
70
71 @call_save
72 def pop(self, k, d=None):
73 return self._session().pop(k, d)
74
75 @call_save
76 def popitem(self):
77 return self._session().popitem()
78
79 __setitem__ = call_save(SessionObject.__setitem__)
80 __delitem__ = call_save(SessionObject.__delitem__)
81
82 # Flash API methods
83 def flash(self, msg, queue='', allow_duplicate=True):
84 storage = self.setdefault('_f_' + queue, [])
85 if allow_duplicate or (msg not in storage):
86 storage.append(msg)
87
88 def pop_flash(self, queue=''):
89 storage = self.pop('_f_' + queue, [])
90 return storage
91
92 def peek_flash(self, queue=''):
93 storage = self.get('_f_' + queue, [])
94 return storage
95
96 # CSRF API methods
97 def new_csrf_token(self):
98 token = (self._constant_csrf_token
99 or hexlify(os.urandom(20)).decode('ascii'))
100 self['_csrft_'] = token
101 return token
102
103 def get_csrf_token(self):
104 token = self.get('_csrft_', None)
105 if token is None:
106 token = self.new_csrf_token()
107 return token
108
109 return implementer(ISession)(PyramidBeakerSessionObject)
110
111
112 def call_save(wrapped):
113 """ By default, in non-auto-mode beaker badly wants people to
114 call save even though it should know something has changed when
115 a mutating method is called. This hack should be removed if
116 Beaker ever starts to do this by default. """
117 def save(session, *arg, **kw):
118 value = wrapped(session, *arg, **kw)
119 session.save()
120 return value
121 save.__doc__ = wrapped.__doc__
122 return save
123
124
125 def session_factory_from_settings(settings):
126 """ Return a Pyramid session factory using Beaker session settings
127 supplied from a Paste configuration file"""
128 prefixes = ('session.', 'beaker.session.')
129 options = {}
130
131 # Pull out any config args meant for beaker session. if there are any
132 for k, v in settings.items():
133 for prefix in prefixes:
134 if k.startswith(prefix):
135 option_name = k[len(prefix):]
136 if option_name == 'cookie_on_exception':
137 v = asbool(v)
138 options[option_name] = v
139
140 options = coerce_session_params(options)
141 return BeakerSessionFactoryConfig(**options)
142
143
144 def set_cache_regions_from_settings(settings):
145 """ Add cache support to the Pylons application.
146
147 The ``settings`` passed to the configurator are used to setup
148 the cache options. Cache options in the settings should start
149 with either 'beaker.cache.' or 'cache.'.
150
151 """
152 cache_settings = {'regions': []}
153 for key in settings.keys():
154 for prefix in ['beaker.cache.', 'cache.']:
155 if key.startswith(prefix):
156 name = key.split(prefix)[1].strip()
157 cache_settings[name] = settings[key].strip()
158
159 if ('expire' in cache_settings
160 and isinstance(cache_settings['expire'], basestring)
161 and cache_settings['expire'].lower() in ['none', 'no']):
162 cache_settings['expire'] = None
163
164 coerce_cache_params(cache_settings)
165
166 if 'enabled' not in cache_settings:
167 cache_settings['enabled'] = True
168
169 regions = cache_settings['regions']
170 if regions:
171 for region in regions:
172 if not region:
173 continue
174
175 region_settings = {
176 'data_dir': cache_settings.get('data_dir'),
177 'lock_dir': cache_settings.get('lock_dir'),
178 'expire': cache_settings.get('expire', 60),
179 'enabled': cache_settings['enabled'],
180 'key_length': cache_settings.get('key_length', 250),
181 'type': cache_settings.get('type'),
182 'url': cache_settings.get('url'),
183 }
184 region_prefix = '%s.' % region
185 region_len = len(region_prefix)
186 for key in list(cache_settings.keys()):
187 if key.startswith(region_prefix):
188 region_settings[key[region_len:]] = cache_settings.pop(key)
189
190 if (isinstance(region_settings['expire'], basestring)
191 and region_settings['expire'].lower() in ['none', 'no']):
192 region_settings['expire'] = None
193 coerce_cache_params(region_settings)
194 cache.cache_regions[region] = region_settings
195
196
197 def includeme(config):
198 session_factory = session_factory_from_settings(config.registry.settings)
199 config.set_session_factory(session_factory)
200 set_cache_regions_from_settings(config.registry.settings)
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100755
NO CONTENT: new file 100755
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,5 +1,5 b''
1 [bumpversion]
1 [bumpversion]
2 current_version = 4.16.2
2 current_version = 4.17.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]
@@ -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 = prepared
20 state = in_progress
24 version = 4.16.2
21 version = 4.17.0
25
26 [task:updated_translation]
27
22
28 [task:generate_js_routes]
23 [task:generate_js_routes]
29
24
@@ -53,3 +53,12 b' web-build:'
53
53
54 generate-pkgs:
54 generate-pkgs:
55 nix-shell pkgs/shell-generate.nix --command "pip2nix generate --licenses"
55 nix-shell pkgs/shell-generate.nix --command "pip2nix generate --licenses"
56
57 generate-js-pkgs:
58 rm -rf node_modules && \
59 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" && \
60 sed -i -e 's/http:\/\//https:\/\//g' pkgs/node-packages.nix
61
62 generate-license-meta:
63 nix-build pkgs/license-generate.nix -o result-license && \
64 cat result-license/licenses.json | python -m json.tool > rhodecode/config/licenses.json No newline at end of file
@@ -133,6 +133,11 b' rhodecode.api.url = /_admin/api'
133 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
133 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
134 #rhodecode.encrypted_values.strict = false
134 #rhodecode.encrypted_values.strict = false
135
135
136 ## Pick algorithm for encryption. Either fernet (more secure) or aes (default)
137 ## fernet is safer, and we strongly recommend switching to it.
138 ## Due to backward compatibility aes is used as default.
139 #rhodecode.encrypted_values.algorithm = fernet
140
136 ## return gzipped responses from RhodeCode (static files/application)
141 ## return gzipped responses from RhodeCode (static files/application)
137 gzip_responses = false
142 gzip_responses = false
138
143
@@ -374,6 +379,10 b' rc_cache.cache_repo_longterm.max_size = '
374 beaker.session.type = file
379 beaker.session.type = file
375 beaker.session.data_dir = %(here)s/data/sessions
380 beaker.session.data_dir = %(here)s/data/sessions
376
381
382 ## redis sessions
383 #beaker.session.type = ext:redis
384 #beaker.session.url = redis://127.0.0.1:6379/2
385
377 ## db based session, fast, and allows easy management over logged in users
386 ## db based session, fast, and allows easy management over logged in users
378 #beaker.session.type = ext:database
387 #beaker.session.type = ext:database
379 #beaker.session.table_name = db_session
388 #beaker.session.table_name = db_session
@@ -30,10 +30,12 b" loglevel = 'debug'"
30 # SECURITY
30 # SECURITY
31
31
32 # The maximum size of HTTP request line in bytes.
32 # The maximum size of HTTP request line in bytes.
33 limit_request_line = 4094
33 # 0 for unlimited
34 limit_request_line = 0
34
35
35 # Limit the number of HTTP headers fields in a request.
36 # Limit the number of HTTP headers fields in a request.
36 limit_request_fields = 1024
37 # By default this value is 100 and can’t be larger than 32768.
38 limit_request_fields = 10240
37
39
38 # Limit the allowed size of an HTTP request header field.
40 # Limit the allowed size of an HTTP request header field.
39 # Value is a positive number or 0.
41 # Value is a positive number or 0.
@@ -108,6 +108,11 b' use = egg:rhodecode-enterprise-ce'
108 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
108 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
109 #rhodecode.encrypted_values.strict = false
109 #rhodecode.encrypted_values.strict = false
110
110
111 ## Pick algorithm for encryption. Either fernet (more secure) or aes (default)
112 ## fernet is safer, and we strongly recommend switching to it.
113 ## Due to backward compatibility aes is used as default.
114 #rhodecode.encrypted_values.algorithm = fernet
115
111 ## return gzipped responses from RhodeCode (static files/application)
116 ## return gzipped responses from RhodeCode (static files/application)
112 gzip_responses = false
117 gzip_responses = false
113
118
@@ -349,6 +354,10 b' rc_cache.cache_repo_longterm.max_size = '
349 beaker.session.type = file
354 beaker.session.type = file
350 beaker.session.data_dir = %(here)s/data/sessions
355 beaker.session.data_dir = %(here)s/data/sessions
351
356
357 ## redis sessions
358 #beaker.session.type = ext:redis
359 #beaker.session.url = redis://127.0.0.1:6379/2
360
352 ## db based session, fast, and allows easy management over logged in users
361 ## db based session, fast, and allows easy management over logged in users
353 #beaker.session.type = ext:database
362 #beaker.session.type = ext:database
354 #beaker.session.table_name = db_session
363 #beaker.session.table_name = db_session
@@ -191,7 +191,7 b' let'
191 # check required files
191 # check required files
192 STATIC_CHECK="/robots.txt /502.html
192 STATIC_CHECK="/robots.txt /502.html
193 /js/scripts.js /js/rhodecode-components.js
193 /js/scripts.js /js/rhodecode-components.js
194 /css/style.css /css/style-polymer.css"
194 /css/style.css /css/style-polymer.css /css/style-ipython.css"
195
195
196 for file in $STATIC_CHECK;
196 for file in $STATIC_CHECK;
197 do
197 do
@@ -29,7 +29,7 b' 1. Go to :menuselection:`Admin --> Repos'
29 beside the |repo| to which you wish to add extra fields.
29 beside the |repo| to which you wish to add extra fields.
30 2. On the |repo| settings page, select the :guilabel:`Extra fields` tab.
30 2. On the |repo| settings page, select the :guilabel:`Extra fields` tab.
31
31
32 .. image:: ../images/extra-repo-fields.png
32 .. image:: ../../images/extra-repo-fields.png
33
33
34 The most important is the `New field key` variable which under the value will
34 The most important is the `New field key` variable which under the value will
35 be stored. It needs to be unique for each repository. The label and description
35 be stored. It needs to be unique for each repository. The label and description
1 NO CONTENT: file renamed from docs/admin/repo-hooks.rst to docs/admin/repo_admin/repo-hooks.rst
NO CONTENT: file renamed from docs/admin/repo-hooks.rst to docs/admin/repo_admin/repo-hooks.rst
1 NO CONTENT: file renamed from docs/admin/repo-issue-tracker.rst to docs/admin/repo_admin/repo-issue-tracker.rst
NO CONTENT: file renamed from docs/admin/repo-issue-tracker.rst to docs/admin/repo_admin/repo-issue-tracker.rst
1 NO CONTENT: file renamed from docs/admin/repo-perm-steps.rst to docs/admin/repo_admin/repo-perm-steps.rst
NO CONTENT: file renamed from docs/admin/repo-perm-steps.rst to docs/admin/repo_admin/repo-perm-steps.rst
1 NO CONTENT: file renamed from docs/admin/repo-vcs.rst to docs/admin/repo_admin/repo-vcs.rst
NO CONTENT: file renamed from docs/admin/repo-vcs.rst to docs/admin/repo_admin/repo-vcs.rst
1 NO CONTENT: file renamed from docs/admin/restore-deleted-repositories.rst to docs/admin/repo_admin/restore-deleted-repositories.rst
NO CONTENT: file renamed from docs/admin/restore-deleted-repositories.rst to docs/admin/repo_admin/restore-deleted-repositories.rst
@@ -16,19 +16,17 b' The following are the most common system'
16
16
17 .. toctree::
17 .. toctree::
18
18
19 config-files-overview
19 system_admin/config-files-overview
20 vcs-server
20 system_admin/vcs-server
21 svn-http
21 system_admin/svn-http
22 svn-path-permissions
22 system_admin/svn-path-permissions
23 gunicorn-ssl-support
23 system_admin/gunicorn-ssl-support
24 apache-config
24 system_admin/apache-config
25 nginx-config
25 system_admin/nginx-config
26 backup-restore
26 system_admin/backup-restore
27 tuning-rhodecode
27 system_admin/tuning-rhodecode
28 indexing
28 system_admin/indexing
29 reset-information
29 system_admin/reset-information
30 enable-debug
30 system_admin/enable-debug
31 admin-tricks
31 system_admin/admin-tricks
32 cleanup-cmds
32 system_admin/cleanup-cmds
33 restore-deleted-repositories
34
@@ -57,7 +57,7 b' 2. To add a message that will be display'
57 3. Select :guilabel:`Save`, and you will see the message once your page
57 3. Select :guilabel:`Save`, and you will see the message once your page
58 refreshes.
58 refreshes.
59
59
60 .. image:: ../images/server-wide-announcement.png
60 .. image:: ../../images/server-wide-announcement.png
61 :alt: Server Wide Announcement
61 :alt: Server Wide Announcement
62
62
63 .. _md-rst:
63 .. _md-rst:
@@ -207,7 +207,7 b' 2. Restart the |RCE| instance and check '
207 Instance "enterprise-2" successfully stopped.
207 Instance "enterprise-2" successfully stopped.
208 Instance "enterprise-2" successfully started.
208 Instance "enterprise-2" successfully started.
209
209
210 .. image:: ../images/language.png
210 .. image:: ../../images/language.png
211
211
212 .. _set-repo-pub:
212 .. _set-repo-pub:
213
213
@@ -239,3 +239,26 b' following URL: ``{instance-URL}/_admin/p'
239
239
240 .. _Markdown: http://daringfireball.net/projects/markdown/
240 .. _Markdown: http://daringfireball.net/projects/markdown/
241 .. _reStructured Text: http://docutils.sourceforge.net/docs/index.html
241 .. _reStructured Text: http://docutils.sourceforge.net/docs/index.html
242
243
244 Unarchiving a repository
245 ^^^^^^^^^^^^^^^^^^^^^^^^^
246
247 Archive operation for the repository is similar as delete. Archive keeps the data for future references
248 but makes the repository read-only. After archiving the repository it shouldn't be modified in any way.
249 This is why repository settings are disabled for an archived repository.
250
251 If there's a need for unarchiving a repository for some reasons, the interactive
252 ishell interface should be used.
253
254 .. code-block:: bash
255
256 # Open iShell from the terminal
257 $ rccontrol ishell enterprise-1/community-1
258
259 .. code-block:: python
260
261 # Set repository as un-archived
262 In [1]: repo = Repository.get_by_repo_name('SOME_REPO_NAME')
263 In [2]: repo.archived = False
264 In [3]: Session().add(repo);Session().commit()
@@ -8,7 +8,7 b' the information in the following section'
8
8
9 .. toctree::
9 .. toctree::
10
10
11 apache-conf-example
11 apache/apache-conf-example
12 apache-diffie-hellman
12 apache/apache-diffie-hellman
13 apache-subdirectory
13 apache/apache-subdirectory
14 apache-wsgi-coding
14 apache/apache-wsgi-coding
@@ -66,14 +66,18 b' Below config if for an Apache Reverse Pr'
66 # Directive to properly generate url (clone url) for RhodeCode
66 # Directive to properly generate url (clone url) for RhodeCode
67 ProxyPreserveHost On
67 ProxyPreserveHost On
68
68
69 # It allows request bodies to be sent to the backend using chunked transfer encoding.
70 SetEnv proxy-sendchunked 1
71
72 # Increase headers size for large Mercurial headers sent with many branches
73 LimitRequestLine 16380
74
69 # Url to running RhodeCode instance. This is shown as `- URL:` when
75 # Url to running RhodeCode instance. This is shown as `- URL:` when
70 # running rccontrol status.
76 # running rccontrol status.
77
71 ProxyPass / http://127.0.0.1:10002/ timeout=7200 Keepalive=On
78 ProxyPass / http://127.0.0.1:10002/ timeout=7200 Keepalive=On
72 ProxyPassReverse / http://127.0.0.1:10002/
79 ProxyPassReverse / http://127.0.0.1:10002/
73
80
74 # Increase headers for large Mercurial headers
75 LimitRequestLine 16380
76
77 # strict http prevents from https -> http downgrade
81 # strict http prevents from https -> http downgrade
78 Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"
82 Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"
79
83
1 NO CONTENT: file renamed from docs/admin/apache-diffie-hellman.rst to docs/admin/system_admin/apache/apache-diffie-hellman.rst
NO CONTENT: file renamed from docs/admin/apache-diffie-hellman.rst to docs/admin/system_admin/apache/apache-diffie-hellman.rst
1 NO CONTENT: file renamed from docs/admin/apache-subdirectory.rst to docs/admin/system_admin/apache/apache-subdirectory.rst
NO CONTENT: file renamed from docs/admin/apache-subdirectory.rst to docs/admin/system_admin/apache/apache-subdirectory.rst
1 NO CONTENT: file renamed from docs/admin/apache-wsgi-coding.rst to docs/admin/system_admin/apache/apache-wsgi-coding.rst
NO CONTENT: file renamed from docs/admin/apache-wsgi-coding.rst to docs/admin/system_admin/apache/apache-wsgi-coding.rst
1 NO CONTENT: file renamed from docs/admin/backup-restore.rst to docs/admin/system_admin/backup-restore.rst
NO CONTENT: file renamed from docs/admin/backup-restore.rst to docs/admin/system_admin/backup-restore.rst
1 NO CONTENT: file renamed from docs/admin/cleanup-cmds.rst to docs/admin/system_admin/cleanup-cmds.rst
NO CONTENT: file renamed from docs/admin/cleanup-cmds.rst to docs/admin/system_admin/cleanup-cmds.rst
1 NO CONTENT: file renamed from docs/admin/config-files-overview.rst to docs/admin/system_admin/config-files-overview.rst
NO CONTENT: file renamed from docs/admin/config-files-overview.rst to docs/admin/system_admin/config-files-overview.rst
1 NO CONTENT: file renamed from docs/admin/enable-debug.rst to docs/admin/system_admin/enable-debug.rst
NO CONTENT: file renamed from docs/admin/enable-debug.rst to docs/admin/system_admin/enable-debug.rst
1 NO CONTENT: file renamed from docs/admin/gunicorn-ssl-support.rst to docs/admin/system_admin/gunicorn-ssl-support.rst
NO CONTENT: file renamed from docs/admin/gunicorn-ssl-support.rst to docs/admin/system_admin/gunicorn-ssl-support.rst
1 NO CONTENT: file renamed from docs/admin/indexing.rst to docs/admin/system_admin/indexing.rst
NO CONTENT: file renamed from docs/admin/indexing.rst to docs/admin/system_admin/indexing.rst
@@ -8,7 +8,7 b' the information in the following section'
8
8
9 .. toctree::
9 .. toctree::
10
10
11 nginx-config-example
11 nginx/nginx-config-example
12 nginx-diffie-hellman
12 nginx/nginx-diffie-hellman
13 nginx-proxy-conf
13 nginx/nginx-proxy-conf
14 nginx-url-prefix
14 nginx/nginx-url-prefix
1 NO CONTENT: file renamed from docs/admin/nginx-config-example.rst to docs/admin/system_admin/nginx/nginx-config-example.rst
NO CONTENT: file renamed from docs/admin/nginx-config-example.rst to docs/admin/system_admin/nginx/nginx-config-example.rst
1 NO CONTENT: file renamed from docs/admin/nginx-diffie-hellman.rst to docs/admin/system_admin/nginx/nginx-diffie-hellman.rst
NO CONTENT: file renamed from docs/admin/nginx-diffie-hellman.rst to docs/admin/system_admin/nginx/nginx-diffie-hellman.rst
1 NO CONTENT: file renamed from docs/admin/nginx-proxy-conf.rst to docs/admin/system_admin/nginx/nginx-proxy-conf.rst
NO CONTENT: file renamed from docs/admin/nginx-proxy-conf.rst to docs/admin/system_admin/nginx/nginx-proxy-conf.rst
1 NO CONTENT: file renamed from docs/admin/nginx-url-prefix.rst to docs/admin/system_admin/nginx/nginx-url-prefix.rst
NO CONTENT: file renamed from docs/admin/nginx-url-prefix.rst to docs/admin/system_admin/nginx/nginx-url-prefix.rst
1 NO CONTENT: file renamed from docs/admin/reset-information.rst to docs/admin/system_admin/reset-information.rst
NO CONTENT: file renamed from docs/admin/reset-information.rst to docs/admin/system_admin/reset-information.rst
1 NO CONTENT: file renamed from docs/admin/svn-http.rst to docs/admin/system_admin/svn-http.rst
NO CONTENT: file renamed from docs/admin/svn-http.rst to docs/admin/system_admin/svn-http.rst
1 NO CONTENT: file renamed from docs/admin/svn-path-permissions.rst to docs/admin/system_admin/svn-path-permissions.rst
NO CONTENT: file renamed from docs/admin/svn-path-permissions.rst to docs/admin/system_admin/svn-path-permissions.rst
@@ -8,14 +8,14 b' may find some of the following methods u'
8
8
9 .. toctree::
9 .. toctree::
10
10
11 tuning-gunicorn
11 tuning/tuning-gunicorn
12 tuning-vcs-memory-cache
12 tuning/tuning-vcs-memory-cache
13 tuning-user-sessions-performance
13 tuning/tuning-user-sessions-performance
14 tuning-increase-db-performance
14 tuning/tuning-increase-db-performance
15 tuning-scale-horizontally-cluster
15 tuning/tuning-scale-horizontally-cluster
16 tuning-mount-cache-memory
16 tuning/tuning-mount-cache-memory
17 tuning-change-encoding
17 tuning/tuning-change-encoding
18 tuning-change-large-file-dir
18 tuning/tuning-change-large-file-dir
19 tuning-change-lfs-dir
19 tuning/tuning-change-lfs-dir
20 tuning-hg-auth-loop
20 tuning/tuning-hg-auth-loop
21
21
1 NO CONTENT: file renamed from docs/admin/tuning-change-encoding.rst to docs/admin/system_admin/tuning/tuning-change-encoding.rst
NO CONTENT: file renamed from docs/admin/tuning-change-encoding.rst to docs/admin/system_admin/tuning/tuning-change-encoding.rst
1 NO CONTENT: file renamed from docs/admin/tuning-change-large-file-dir.rst to docs/admin/system_admin/tuning/tuning-change-large-file-dir.rst
NO CONTENT: file renamed from docs/admin/tuning-change-large-file-dir.rst to docs/admin/system_admin/tuning/tuning-change-large-file-dir.rst
1 NO CONTENT: file renamed from docs/admin/tuning-change-lfs-dir.rst to docs/admin/system_admin/tuning/tuning-change-lfs-dir.rst
NO CONTENT: file renamed from docs/admin/tuning-change-lfs-dir.rst to docs/admin/system_admin/tuning/tuning-change-lfs-dir.rst
@@ -42,7 +42,7 b' 2. In the ``[server:main]`` section, cha'
42 ## restarted, could prevent memory leaks
42 ## restarted, could prevent memory leaks
43 max_requests = 1000
43 max_requests = 1000
44 max_requests_jitter = 30
44 max_requests_jitter = 30
45 ## amount of time a worker can spend with handling a request before it
45 ## amount of time a worker can spend with handling a request tuning-change-lfs-dir.before it
46 ## gets killed and restarted. Set to 6hrs
46 ## gets killed and restarted. Set to 6hrs
47 timeout = 21600
47 timeout = 21600
48
48
1 NO CONTENT: file renamed from docs/admin/tuning-hg-auth-loop.rst to docs/admin/system_admin/tuning/tuning-hg-auth-loop.rst
NO CONTENT: file renamed from docs/admin/tuning-hg-auth-loop.rst to docs/admin/system_admin/tuning/tuning-hg-auth-loop.rst
1 NO CONTENT: file renamed from docs/admin/tuning-increase-db-performance.rst to docs/admin/system_admin/tuning/tuning-increase-db-performance.rst
NO CONTENT: file renamed from docs/admin/tuning-increase-db-performance.rst to docs/admin/system_admin/tuning/tuning-increase-db-performance.rst
1 NO CONTENT: file renamed from docs/admin/tuning-mount-cache-memory.rst to docs/admin/system_admin/tuning/tuning-mount-cache-memory.rst
NO CONTENT: file renamed from docs/admin/tuning-mount-cache-memory.rst to docs/admin/system_admin/tuning/tuning-mount-cache-memory.rst
1 NO CONTENT: file renamed from docs/admin/tuning-scale-horizontally-cluster.rst to docs/admin/system_admin/tuning/tuning-scale-horizontally-cluster.rst
NO CONTENT: file renamed from docs/admin/tuning-scale-horizontally-cluster.rst to docs/admin/system_admin/tuning/tuning-scale-horizontally-cluster.rst
1 NO CONTENT: file renamed from docs/admin/tuning-user-sessions-performance.rst to docs/admin/system_admin/tuning/tuning-user-sessions-performance.rst
NO CONTENT: file renamed from docs/admin/tuning-user-sessions-performance.rst to docs/admin/system_admin/tuning/tuning-user-sessions-performance.rst
1 NO CONTENT: file renamed from docs/admin/tuning-vcs-memory-cache.rst to docs/admin/system_admin/tuning/tuning-vcs-memory-cache.rst
NO CONTENT: file renamed from docs/admin/tuning-vcs-memory-cache.rst to docs/admin/system_admin/tuning/tuning-vcs-memory-cache.rst
1 NO CONTENT: file renamed from docs/admin/vcs-server.rst to docs/admin/system_admin/vcs-server.rst
NO CONTENT: file renamed from docs/admin/vcs-server.rst to docs/admin/system_admin/vcs-server.rst
@@ -13,11 +13,12 b' permissions applied to it; |perm|.'
13
13
14 .. toctree::
14 .. toctree::
15
15
16 public-access
16 user_admin/public-access
17 default-user-perms
17 user_admin/default-user-perms
18 adding-anonymous-user
18 user_admin/adding-anonymous-user
19 adding-new-user
19 user_admin/adding-new-user
20 setting-default-permissions
20 user_admin/setting-default-permissions
21 setting-usergroup-permissions
21 user_admin/setting-usergroup-permissions
22 user_admin/user-admin-tasks
22
23
23 .. |perm| replace:: **None**, **Read**, **Write**, or **Admin** No newline at end of file
24 .. |perm| replace:: **None**, **Read**, **Write**, or **Admin**
1 NO CONTENT: file renamed from docs/admin/adding-anonymous-user.rst to docs/admin/user_admin/adding-anonymous-user.rst
NO CONTENT: file renamed from docs/admin/adding-anonymous-user.rst to docs/admin/user_admin/adding-anonymous-user.rst
1 NO CONTENT: file renamed from docs/admin/adding-new-user.rst to docs/admin/user_admin/adding-new-user.rst
NO CONTENT: file renamed from docs/admin/adding-new-user.rst to docs/admin/user_admin/adding-new-user.rst
1 NO CONTENT: file renamed from docs/admin/default-user-perms.rst to docs/admin/user_admin/default-user-perms.rst
NO CONTENT: file renamed from docs/admin/default-user-perms.rst to docs/admin/user_admin/default-user-perms.rst
1 NO CONTENT: file renamed from docs/admin/public-access.rst to docs/admin/user_admin/public-access.rst
NO CONTENT: file renamed from docs/admin/public-access.rst to docs/admin/user_admin/public-access.rst
1 NO CONTENT: file renamed from docs/admin/setting-default-permissions.rst to docs/admin/user_admin/setting-default-permissions.rst
NO CONTENT: file renamed from docs/admin/setting-default-permissions.rst to docs/admin/user_admin/setting-default-permissions.rst
1 NO CONTENT: file renamed from docs/admin/setting-usergroup-permissions.rst to docs/admin/user_admin/setting-usergroup-permissions.rst
NO CONTENT: file renamed from docs/admin/setting-usergroup-permissions.rst to docs/admin/user_admin/setting-usergroup-permissions.rst
@@ -204,6 +204,7 b' are not required in args.'
204 methods/pull-request-methods
204 methods/pull-request-methods
205 methods/repo-methods
205 methods/repo-methods
206 methods/repo-group-methods
206 methods/repo-group-methods
207 methods/search-methods
207 methods/server-methods
208 methods/server-methods
208 methods/user-methods
209 methods/user-methods
209 methods/user-group-methods
210 methods/user-group-methods
@@ -462,6 +462,7 b' get_repo_file'
462 :param cache: Use internal caches for fetching files. If disabled fetching
462 :param cache: Use internal caches for fetching files. If disabled fetching
463 files is slower but more memory efficient
463 files is slower but more memory efficient
464 :type cache: Optional(bool)
464 :type cache: Optional(bool)
465
465 Example output:
466 Example output:
466
467
467 .. code-block:: bash
468 .. code-block:: bash
@@ -499,53 +500,51 b' get_repo_nodes'
499 .. py:function:: get_repo_nodes(apiuser, repoid, revision, root_path, ret_type=<Optional:'all'>, details=<Optional:'basic'>, max_file_bytes=<Optional:None>)
500 .. py:function:: get_repo_nodes(apiuser, repoid, revision, root_path, ret_type=<Optional:'all'>, details=<Optional:'basic'>, max_file_bytes=<Optional:None>)
500
501
501 Returns a list of nodes and children in a flat list for a given
502 Returns a list of nodes and children in a flat list for a given
502 path at given revision.
503 path at given revision.
503
504
504 It's possible to specify ret_type to show only `files` or `dirs`.
505 It's possible to specify ret_type to show only `files` or `dirs`.
505
506
506 This command can only be run using an |authtoken| with admin rights,
507 This command can only be run using an |authtoken| with admin rights,
507 or users with at least read rights to |repos|.
508 or users with at least read rights to |repos|.
508
509
509 :param apiuser: This is filled automatically from the |authtoken|.
510 :param apiuser: This is filled automatically from the |authtoken|.
510 :type apiuser: AuthUser
511 :type apiuser: AuthUser
511 :param repoid: The repository name or repository ID.
512 :param repoid: The repository name or repository ID.
512 :type repoid: str or int
513 :type repoid: str or int
513 :param revision: The revision for which listing should be done.
514 :param revision: The revision for which listing should be done.
514 :type revision: str
515 :type revision: str
515 :param root_path: The path from which to start displaying.
516 :param root_path: The path from which to start displaying.
516 :type root_path: str
517 :type root_path: str
517 :param ret_type: Set the return type. Valid options are
518 :param ret_type: Set the return type. Valid options are
518 ``all`` (default), ``files`` and ``dirs``.
519 ``all`` (default), ``files`` and ``dirs``.
519 :type ret_type: Optional(str)
520 :type ret_type: Optional(str)
520 :param details: Returns extended information about nodes, such as
521 :param details: Returns extended information about nodes, such as
521 md5, binary, and or content.
522 md5, binary, and or content.
522 The valid options are ``basic`` and ``full``.
523 The valid options are ``basic`` and ``full``.
523 :type details: Optional(str)
524 :type details: Optional(str)
524 :param max_file_bytes: Only return file content under this file size bytes
525 :param max_file_bytes: Only return file content under this file size bytes
525 :type details: Optional(int)
526 :type details: Optional(int)
526
527 Example output:
528
527
529 .. code-block:: bash
528 Example output:
529
530 .. code-block:: bash
530
531
531 id : <id_given_in_input>
532 id : <id_given_in_input>
532 result: [
533 result: [
533 {
534 {
534 "binary": false,
535 "binary": false,
535 "content": "File line
536 "content": "File line",
536 Line2
537 "extension": "md",
537 ",
538 "lines": 2,
538 "extension": "md",
539 "md5": "059fa5d29b19c0657e384749480f6422",
539 "lines": 2,
540 "mimetype": "text/x-minidsrc",
540 "md5": "059fa5d29b19c0657e384749480f6422",
541 "name": "file.md",
541 "mimetype": "text/x-minidsrc",
542 "size": 580,
542 "name": "file.md",
543 "type": "file"
543 "size": 580,
544 },
544 "type": "file"
545 ...
545 },
546 ]
546 ...
547 error: null
547 ]
548 error: null
549
548
550
549
551 get_repo_refs
550 get_repo_refs
@@ -32,9 +32,9 b' The most important this id needs to be u'
32
32
33 In [1]: saml2user = {
33 In [1]: saml2user = {
34 ...: # OneLogin, uses externalID available to read from in the UI
34 ...: # OneLogin, uses externalID available to read from in the UI
35 ...: 123: {'id: '48253211'},
35 ...: 123: {'id': '48253211'},
36 ...: # for Google/DuoSecurity email is also an option for unique ID
36 ...: # for Google/DuoSecurity email is also an option for unique ID
37 ...: 124: {'id: 'email@domain.com'},
37 ...: 124: {'id': 'email@domain.com'},
38 ...: }
38 ...: }
39
39
40
40
@@ -70,7 +70,7 b' Enter in the ishell prompt'
70 ...: new_external_identity.external_id = external_id
70 ...: new_external_identity.external_id = external_id
71 ...: new_external_identity.external_username = '{}-saml-{}'.format(user.username, user.user_id)
71 ...: new_external_identity.external_username = '{}-saml-{}'.format(user.username, user.user_id)
72 ...: new_external_identity.provider_name = provider
72 ...: new_external_identity.provider_name = provider
73 ...: new_external_identity.local_user_id = user_id
73 ...: new_external_identity.local_user_id = user.user_id
74 ...: new_external_identity.access_token = ''
74 ...: new_external_identity.access_token = ''
75 ...: new_external_identity.token_secret = ''
75 ...: new_external_identity.token_secret = ''
76 ...: new_external_identity.alt_token = ''
76 ...: new_external_identity.alt_token = ''
@@ -46,7 +46,7 b' and commit files and |repos| while manag'
46 nix/default-env
46 nix/default-env
47 admin/system-admin
47 admin/system-admin
48 admin/user-admin
48 admin/user-admin
49 admin/setting-repo-perms
49 admin/repo-admin
50 admin/security-tips
50 admin/security-tips
51 auth/auth
51 auth/auth
52 issue-trackers/issue-trackers
52 issue-trackers/issue-trackers
@@ -64,6 +64,13 b' and commit files and |repos| while manag'
64
64
65 .. toctree::
65 .. toctree::
66 :maxdepth: 1
66 :maxdepth: 1
67 :caption: User Documentation
68
69 usage/basic-usage
70 tutorials/tutorials
71
72 .. toctree::
73 :maxdepth: 1
67 :caption: Developer Documentation
74 :caption: Developer Documentation
68
75
69 api/api
76 api/api
@@ -73,13 +80,6 b' and commit files and |repos| while manag'
73
80
74 .. toctree::
81 .. toctree::
75 :maxdepth: 1
82 :maxdepth: 1
76 :caption: User Documentation
77
78 usage/basic-usage
79 tutorials/tutorials
80
81 .. toctree::
82 :maxdepth: 1
83 :caption: About
83 :caption: About
84
84
85 known-issues/known-issues
85 known-issues/known-issues
@@ -9,6 +9,7 b' Release Notes'
9 .. toctree::
9 .. toctree::
10 :maxdepth: 1
10 :maxdepth: 1
11
11
12 release-notes-4.17.0.rst
12 release-notes-4.16.2.rst
13 release-notes-4.16.2.rst
13 release-notes-4.16.1.rst
14 release-notes-4.16.1.rst
14 release-notes-4.16.0.rst
15 release-notes-4.16.0.rst
@@ -35,6 +35,7 b''
35 "<%= dirs.js.node_modules %>/moment/min/moment.min.js",
35 "<%= dirs.js.node_modules %>/moment/min/moment.min.js",
36 "<%= dirs.js.node_modules %>/clipboard/dist/clipboard.min.js",
36 "<%= dirs.js.node_modules %>/clipboard/dist/clipboard.min.js",
37 "<%= dirs.js.node_modules %>/favico.js/favico-0.3.10.min.js",
37 "<%= dirs.js.node_modules %>/favico.js/favico-0.3.10.min.js",
38 "<%= dirs.js.node_modules %>/dropzone/dist/dropzone.js",
38 "<%= dirs.js.node_modules %>/sticky-sidebar/dist/sticky-sidebar.min.js",
39 "<%= dirs.js.node_modules %>/sticky-sidebar/dist/sticky-sidebar.min.js",
39 "<%= dirs.js.node_modules %>/sticky-sidebar/dist/jquery.sticky-sidebar.min.js",
40 "<%= dirs.js.node_modules %>/sticky-sidebar/dist/jquery.sticky-sidebar.min.js",
40 "<%= dirs.js.node_modules %>/waypoints/lib/noframework.waypoints.min.js",
41 "<%= dirs.js.node_modules %>/waypoints/lib/noframework.waypoints.min.js",
@@ -107,7 +108,8 b''
107 },
108 },
108 "files": {
109 "files": {
109 "<%= dirs.css.dest %>/style.css": "<%= dirs.css.src %>/main.less",
110 "<%= dirs.css.dest %>/style.css": "<%= dirs.css.src %>/main.less",
110 "<%= dirs.css.dest %>/style-polymer.css": "<%= dirs.css.src %>/polymer.less"
111 "<%= dirs.css.dest %>/style-polymer.css": "<%= dirs.css.src %>/polymer.less",
112 "<%= dirs.css.dest %>/style-ipython.css": "<%= dirs.css.src %>/ipython.less"
111 }
113 }
112 },
114 },
113 "production": {
115 "production": {
@@ -118,7 +120,8 b''
118 },
120 },
119 "files": {
121 "files": {
120 "<%= dirs.css.dest %>/style.css": "<%= dirs.css.src %>/main.less",
122 "<%= dirs.css.dest %>/style.css": "<%= dirs.css.src %>/main.less",
121 "<%= dirs.css.dest %>/style-polymer.css": "<%= dirs.css.src %>/polymer.less"
123 "<%= dirs.css.dest %>/style-polymer.css": "<%= dirs.css.src %>/polymer.less",
124 "<%= dirs.css.dest %>/style-ipython.css": "<%= dirs.css.src %>/ipython.less"
122 }
125 }
123 },
126 },
124 "components": {
127 "components": {
@@ -13,6 +13,7 b''
13 "clipboard": "^2.0.1",
13 "clipboard": "^2.0.1",
14 "exports-loader": "^0.6.4",
14 "exports-loader": "^0.6.4",
15 "favico.js": "^0.3.10",
15 "favico.js": "^0.3.10",
16 "dropzone": "^5.5.0",
16 "grunt": "^0.4.5",
17 "grunt": "^0.4.5",
17 "grunt-cli": "^1.3.1",
18 "grunt-cli": "^1.3.1",
18 "grunt-contrib-concat": "^0.5.1",
19 "grunt-contrib-concat": "^0.5.1",
@@ -1,3 +1,3 b''
1 [pip2nix]
1 [pip2nix]
2 requirements = ., -r ./requirements.txt
2 requirements = ., -r ./requirements.txt, -r ./requirements_pinned.txt
3 output = ./pkgs/python-packages.nix
3 output = ./pkgs/python-packages.nix
This diff has been collapsed as it changes many lines, (990 lines changed) Show them Hide them
@@ -166,13 +166,13 b' let'
166 sha512 = "dgOe12GyCF1VZBLUQqnzGWlf3xb255FajNCVB1VFj/AtskYtoamnafa7m3a+1vs+C8qbg4Benn5KwgxVDSW4cg==";
166 sha512 = "dgOe12GyCF1VZBLUQqnzGWlf3xb255FajNCVB1VFj/AtskYtoamnafa7m3a+1vs+C8qbg4Benn5KwgxVDSW4cg==";
167 };
167 };
168 };
168 };
169 "@polymer/paper-spinner-3.0.1" = {
169 "@polymer/paper-spinner-3.0.2" = {
170 name = "_at_polymer_slash_paper-spinner";
170 name = "_at_polymer_slash_paper-spinner";
171 packageName = "@polymer/paper-spinner";
171 packageName = "@polymer/paper-spinner";
172 version = "3.0.1";
172 version = "3.0.2";
173 src = fetchurl {
173 src = fetchurl {
174 url = "https://registry.npmjs.org/@polymer/paper-spinner/-/paper-spinner-3.0.1.tgz";
174 url = "https://registry.npmjs.org/@polymer/paper-spinner/-/paper-spinner-3.0.2.tgz";
175 sha512 = "MYIU6qWZnhZ5yNFOBzROPgBteGfxKEnDZ6bCgjrvUtJkBuQEz0MQZzSE/zmZc0oaJ9u5QK5xAFuYdudsGv7+sQ==";
175 sha512 = "XUzu8/4NH+pnNZUTI2MxtOKFAr0EOsW7eGhTg3VBhTh7DDW/q3ewzwYRWnqNJokX9BEnxKMiXXaIeTEBq4k2dw==";
176 };
176 };
177 };
177 };
178 "@polymer/paper-styles-3.0.1" = {
178 "@polymer/paper-styles-3.0.1" = {
@@ -211,13 +211,13 b' let'
211 sha512 = "yiUk09opTEnE1lK+tb501ENb+yQBi4p++Ep0eGJAHesVYKVMPNgPphVKkIizkDaU+n0SE+zXfTsRbYyOMDYXSg==";
211 sha512 = "yiUk09opTEnE1lK+tb501ENb+yQBi4p++Ep0eGJAHesVYKVMPNgPphVKkIizkDaU+n0SE+zXfTsRbYyOMDYXSg==";
212 };
212 };
213 };
213 };
214 "@polymer/polymer-3.1.0" = {
214 "@polymer/polymer-3.2.0" = {
215 name = "_at_polymer_slash_polymer";
215 name = "_at_polymer_slash_polymer";
216 packageName = "@polymer/polymer";
216 packageName = "@polymer/polymer";
217 version = "3.1.0";
217 version = "3.2.0";
218 src = fetchurl {
218 src = fetchurl {
219 url = "https://registry.npmjs.org/@polymer/polymer/-/polymer-3.1.0.tgz";
219 url = "https://registry.npmjs.org/@polymer/polymer/-/polymer-3.2.0.tgz";
220 sha512 = "hwN8IMERsFATz/9dSMxYHL+84J9uBkPuuarxJWlTsppZ4CAYTZKnepBfNrKoyNsafBmA3yXBiiKPPf+fJtza7A==";
220 sha512 = "L6uV1oM6T6xbwbVx6t3biG5T2VSSB03LxnIrUd9M2pr6RkHVPFHJ37pC5MUwBAEhkGFJif7eks7fdMMSGZTeEQ==";
221 };
221 };
222 };
222 };
223 "@types/clone-0.1.30" = {
223 "@types/clone-0.1.30" = {
@@ -229,13 +229,13 b' let'
229 sha1 = "e7365648c1b42136a59c7d5040637b3b5c83b614";
229 sha1 = "e7365648c1b42136a59c7d5040637b3b5c83b614";
230 };
230 };
231 };
231 };
232 "@types/node-6.14.2" = {
232 "@types/node-6.14.6" = {
233 name = "_at_types_slash_node";
233 name = "_at_types_slash_node";
234 packageName = "@types/node";
234 packageName = "@types/node";
235 version = "6.14.2";
235 version = "6.14.6";
236 src = fetchurl {
236 src = fetchurl {
237 url = "https://registry.npmjs.org/@types/node/-/node-6.14.2.tgz";
237 url = "https://registry.npmjs.org/@types/node/-/node-6.14.6.tgz";
238 sha512 = "JWB3xaVfsfnFY8Ofc9rTB/op0fqqTSqy4vBcVk1LuRJvta7KTX+D//fCkiTMeLGhdr2EbFZzQjC97gvmPilk9Q==";
238 sha512 = "rFs9zCFtSHuseiNXxYxFlun8ibu+jtZPgRM+2ILCmeLiGeGLiIGxuOzD+cNyHegI1GD+da3R/cIbs9+xCLp13w==";
239 };
239 };
240 };
240 };
241 "@types/parse5-2.2.34" = {
241 "@types/parse5-2.2.34" = {
@@ -409,22 +409,22 b' let'
409 sha512 = "mJ3QKWtCchL1vhU/kZlJnLPuQZnlDOdZsyP0bbLWPGdYsQDnSBvyTLhzwBA3QAMlzEL9V4JHygEmK6/OTEyytA==";
409 sha512 = "mJ3QKWtCchL1vhU/kZlJnLPuQZnlDOdZsyP0bbLWPGdYsQDnSBvyTLhzwBA3QAMlzEL9V4JHygEmK6/OTEyytA==";
410 };
410 };
411 };
411 };
412 "@webcomponents/shadycss-1.7.1" = {
412 "@webcomponents/shadycss-1.9.1" = {
413 name = "_at_webcomponents_slash_shadycss";
413 name = "_at_webcomponents_slash_shadycss";
414 packageName = "@webcomponents/shadycss";
414 packageName = "@webcomponents/shadycss";
415 version = "1.7.1";
415 version = "1.9.1";
416 src = fetchurl {
416 src = fetchurl {
417 url = "https://registry.npmjs.org/@webcomponents/shadycss/-/shadycss-1.7.1.tgz";
417 url = "https://registry.npmjs.org/@webcomponents/shadycss/-/shadycss-1.9.1.tgz";
418 sha512 = "6SZqLajRPWL0rrKDZOGF8PCBq5B9JqgFmE5rX5psk6i8WrqiMkSCuO8+rnirzViTsU5CqnjQPFC3OvG4YJdMrQ==";
418 sha512 = "IaZOnWOKXHghqk/WfPNDRIgDBi3RsVPY2IFAw6tYiL9UBGvQRy5R6uC+Fk7qTZsReTJ0xh5MTT8yAcb3MUR4mQ==";
419 };
419 };
420 };
420 };
421 "@webcomponents/webcomponentsjs-2.2.1" = {
421 "@webcomponents/webcomponentsjs-2.2.10" = {
422 name = "_at_webcomponents_slash_webcomponentsjs";
422 name = "_at_webcomponents_slash_webcomponentsjs";
423 packageName = "@webcomponents/webcomponentsjs";
423 packageName = "@webcomponents/webcomponentsjs";
424 version = "2.2.1";
424 version = "2.2.10";
425 src = fetchurl {
425 src = fetchurl {
426 url = "https://registry.npmjs.org/@webcomponents/webcomponentsjs/-/webcomponentsjs-2.2.1.tgz";
426 url = "https://registry.npmjs.org/@webcomponents/webcomponentsjs/-/webcomponentsjs-2.2.10.tgz";
427 sha512 = "lZZ+Lkke6JhsJcQQqSVk1Pny6/8y4qhJ98LO7a/MwBSRO8WqHqK1X2vscfeL8vOnYGFnmBUyVG95lwYv/AXyLQ==";
427 sha512 = "5dzhUhP+h0qMiK0IWb7VNb0OGBoXO3AuI6Qi8t9PoKT50s5L1jv0xnwnLq+cFgPuTB8FLTNP8xIDmyoOsKBy9Q==";
428 };
428 };
429 };
429 };
430 "@xtuc/ieee754-1.2.0" = {
430 "@xtuc/ieee754-1.2.0" = {
@@ -499,22 +499,22 b' let'
499 sha1 = "82ffb02b29e662ae53bdc20af15947706739c536";
499 sha1 = "82ffb02b29e662ae53bdc20af15947706739c536";
500 };
500 };
501 };
501 };
502 "ajv-6.6.2" = {
502 "ajv-6.10.0" = {
503 name = "ajv";
503 name = "ajv";
504 packageName = "ajv";
504 packageName = "ajv";
505 version = "6.6.2";
505 version = "6.10.0";
506 src = fetchurl {
506 src = fetchurl {
507 url = "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz";
507 url = "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz";
508 sha512 = "FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==";
508 sha512 = "nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==";
509 };
509 };
510 };
510 };
511 "ajv-keywords-3.2.0" = {
511 "ajv-keywords-3.4.0" = {
512 name = "ajv-keywords";
512 name = "ajv-keywords";
513 packageName = "ajv-keywords";
513 packageName = "ajv-keywords";
514 version = "3.2.0";
514 version = "3.4.0";
515 src = fetchurl {
515 src = fetchurl {
516 url = "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz";
516 url = "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz";
517 sha1 = "e86b819c602cf8821ad637413698f1dec021847a";
517 sha512 = "aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==";
518 };
518 };
519 };
519 };
520 "align-text-0.1.4" = {
520 "align-text-0.1.4" = {
@@ -716,15 +716,6 b' let'
716 sha1 = "a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428";
716 sha1 = "a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428";
717 };
717 };
718 };
718 };
719 "arrify-1.0.1" = {
720 name = "arrify";
721 packageName = "arrify";
722 version = "1.0.1";
723 src = fetchurl {
724 url = "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz";
725 sha1 = "898508da2226f380df904728456849c1501a4b0d";
726 };
727 };
728 "asap-2.0.6" = {
719 "asap-2.0.6" = {
729 name = "asap";
720 name = "asap";
730 packageName = "asap";
721 packageName = "asap";
@@ -752,13 +743,13 b' let'
752 sha512 = "p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==";
743 sha512 = "p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==";
753 };
744 };
754 };
745 };
755 "assert-1.4.1" = {
746 "assert-1.5.0" = {
756 name = "assert";
747 name = "assert";
757 packageName = "assert";
748 packageName = "assert";
758 version = "1.4.1";
749 version = "1.5.0";
759 src = fetchurl {
750 src = fetchurl {
760 url = "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz";
751 url = "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz";
761 sha1 = "99912d591836b5a6f5b345c0f07eefc08fc65d91";
752 sha512 = "EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==";
762 };
753 };
763 };
754 };
764 "assert-plus-0.2.0" = {
755 "assert-plus-0.2.0" = {
@@ -815,22 +806,22 b' let'
815 sha1 = "b6bbe0b0674b9d719708ca38de8c237cb526c3d1";
806 sha1 = "b6bbe0b0674b9d719708ca38de8c237cb526c3d1";
816 };
807 };
817 };
808 };
818 "async-2.6.1" = {
809 "async-2.6.2" = {
819 name = "async";
810 name = "async";
820 packageName = "async";
811 packageName = "async";
821 version = "2.6.1";
812 version = "2.6.2";
822 src = fetchurl {
813 src = fetchurl {
823 url = "https://registry.npmjs.org/async/-/async-2.6.1.tgz";
814 url = "https://registry.npmjs.org/async/-/async-2.6.2.tgz";
824 sha512 = "fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==";
815 sha512 = "H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==";
825 };
816 };
826 };
817 };
827 "async-each-1.0.1" = {
818 "async-each-1.0.3" = {
828 name = "async-each";
819 name = "async-each";
829 packageName = "async-each";
820 packageName = "async-each";
830 version = "1.0.1";
821 version = "1.0.3";
831 src = fetchurl {
822 src = fetchurl {
832 url = "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz";
823 url = "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz";
833 sha1 = "19d386a1d9edc6e7c1c85d388aedbcc56d33602d";
824 sha512 = "z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==";
834 };
825 };
835 };
826 };
836 "asynckit-0.4.0" = {
827 "asynckit-0.4.0" = {
@@ -1445,22 +1436,22 b' let'
1445 sha512 = "vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==";
1436 sha512 = "vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==";
1446 };
1437 };
1447 };
1438 };
1448 "binary-extensions-1.12.0" = {
1439 "binary-extensions-1.13.1" = {
1449 name = "binary-extensions";
1440 name = "binary-extensions";
1450 packageName = "binary-extensions";
1441 packageName = "binary-extensions";
1451 version = "1.12.0";
1442 version = "1.13.1";
1452 src = fetchurl {
1443 src = fetchurl {
1453 url = "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz";
1444 url = "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz";
1454 sha512 = "DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==";
1445 sha512 = "Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==";
1455 };
1446 };
1456 };
1447 };
1457 "bluebird-3.5.3" = {
1448 "bluebird-3.5.4" = {
1458 name = "bluebird";
1449 name = "bluebird";
1459 packageName = "bluebird";
1450 packageName = "bluebird";
1460 version = "3.5.3";
1451 version = "3.5.4";
1461 src = fetchurl {
1452 src = fetchurl {
1462 url = "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz";
1453 url = "https://registry.npmjs.org/bluebird/-/bluebird-3.5.4.tgz";
1463 sha512 = "/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==";
1454 sha512 = "FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==";
1464 };
1455 };
1465 };
1456 };
1466 "bn.js-4.11.8" = {
1457 "bn.js-4.11.8" = {
@@ -1661,13 +1652,13 b' let'
1661 sha1 = "9bb5304d2e0b56698b2c758b08a3eaa9daa58a39";
1652 sha1 = "9bb5304d2e0b56698b2c758b08a3eaa9daa58a39";
1662 };
1653 };
1663 };
1654 };
1664 "camelcase-5.0.0" = {
1655 "camelcase-5.3.1" = {
1665 name = "camelcase";
1656 name = "camelcase";
1666 packageName = "camelcase";
1657 packageName = "camelcase";
1667 version = "5.0.0";
1658 version = "5.3.1";
1668 src = fetchurl {
1659 src = fetchurl {
1669 url = "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz";
1660 url = "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz";
1670 sha512 = "faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==";
1661 sha512 = "L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==";
1671 };
1662 };
1672 };
1663 };
1673 "caniuse-api-1.6.1" = {
1664 "caniuse-api-1.6.1" = {
@@ -1679,22 +1670,22 b' let'
1679 sha1 = "b534e7c734c4f81ec5fbe8aca2ad24354b962c6c";
1670 sha1 = "b534e7c734c4f81ec5fbe8aca2ad24354b962c6c";
1680 };
1671 };
1681 };
1672 };
1682 "caniuse-db-1.0.30000927" = {
1673 "caniuse-db-1.0.30000967" = {
1683 name = "caniuse-db";
1674 name = "caniuse-db";
1684 packageName = "caniuse-db";
1675 packageName = "caniuse-db";
1685 version = "1.0.30000927";
1676 version = "1.0.30000967";
1686 src = fetchurl {
1677 src = fetchurl {
1687 url = "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000927.tgz";
1678 url = "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000967.tgz";
1688 sha512 = "CX/QvLA8oh7kQ9cHCCzFm0UZW4KwSyQSRJ5A1XtH42HaMJQ0yh+9fEVWagMqv9I1vSCtaqA5Mb8k0uKfv7jhDw==";
1679 sha512 = "70gk6cLSD5rItxnZ7WUxyCpM9LAjEb1tVzlENQfXQXZS/IiGnfAC6u32G5cZFlDBKjNPBIta/QSx5CZLZepxRA==";
1689 };
1680 };
1690 };
1681 };
1691 "caniuse-lite-1.0.30000927" = {
1682 "caniuse-lite-1.0.30000967" = {
1692 name = "caniuse-lite";
1683 name = "caniuse-lite";
1693 packageName = "caniuse-lite";
1684 packageName = "caniuse-lite";
1694 version = "1.0.30000927";
1685 version = "1.0.30000967";
1695 src = fetchurl {
1686 src = fetchurl {
1696 url = "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000927.tgz";
1687 url = "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000967.tgz";
1697 sha512 = "ogq4NbUWf1uG/j66k0AmiO3GjqJAlQyF8n4w8a954cbCyFKmYGvRtgz6qkq2fWuduTXHibX7GyYL5Pg58Aks2g==";
1688 sha512 = "rUBIbap+VJfxTzrM4akJ00lkvVb5/n5v3EGXfWzSH5zT8aJmGzjA8HWhJ4U6kCpzxozUSnB+yvAYDRPY6mRpgQ==";
1698 };
1689 };
1699 };
1690 };
1700 "caseless-0.12.0" = {
1691 "caseless-0.12.0" = {
@@ -1742,13 +1733,13 b' let'
1742 sha512 = "Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==";
1733 sha512 = "Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==";
1743 };
1734 };
1744 };
1735 };
1745 "chokidar-2.0.4" = {
1736 "chokidar-2.1.5" = {
1746 name = "chokidar";
1737 name = "chokidar";
1747 packageName = "chokidar";
1738 packageName = "chokidar";
1748 version = "2.0.4";
1739 version = "2.1.5";
1749 src = fetchurl {
1740 src = fetchurl {
1750 url = "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz";
1741 url = "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz";
1751 sha512 = "z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==";
1742 sha512 = "i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==";
1752 };
1743 };
1753 };
1744 };
1754 "chownr-1.1.1" = {
1745 "chownr-1.1.1" = {
@@ -1976,13 +1967,13 b' let'
1976 sha512 = "mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==";
1967 sha512 = "mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==";
1977 };
1968 };
1978 };
1969 };
1979 "combined-stream-1.0.7" = {
1970 "combined-stream-1.0.8" = {
1980 name = "combined-stream";
1971 name = "combined-stream";
1981 packageName = "combined-stream";
1972 packageName = "combined-stream";
1982 version = "1.0.7";
1973 version = "1.0.8";
1983 src = fetchurl {
1974 src = fetchurl {
1984 url = "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz";
1975 url = "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz";
1985 sha512 = "brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==";
1976 sha512 = "FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==";
1986 };
1977 };
1987 };
1978 };
1988 "commander-2.14.1" = {
1979 "commander-2.14.1" = {
@@ -2003,6 +1994,15 b' let'
2003 sha512 = "wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==";
1994 sha512 = "wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==";
2004 };
1995 };
2005 };
1996 };
1997 "commander-2.19.0" = {
1998 name = "commander";
1999 packageName = "commander";
2000 version = "2.19.0";
2001 src = fetchurl {
2002 url = "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz";
2003 sha512 = "6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==";
2004 };
2005 };
2006 "commondir-1.0.1" = {
2006 "commondir-1.0.1" = {
2007 name = "commondir";
2007 name = "commondir";
2008 packageName = "commondir";
2008 packageName = "commondir";
@@ -2012,13 +2012,13 b' let'
2012 sha1 = "ddd800da0c66127393cca5950ea968a3aaf1253b";
2012 sha1 = "ddd800da0c66127393cca5950ea968a3aaf1253b";
2013 };
2013 };
2014 };
2014 };
2015 "component-emitter-1.2.1" = {
2015 "component-emitter-1.3.0" = {
2016 name = "component-emitter";
2016 name = "component-emitter";
2017 packageName = "component-emitter";
2017 packageName = "component-emitter";
2018 version = "1.2.1";
2018 version = "1.3.0";
2019 src = fetchurl {
2019 src = fetchurl {
2020 url = "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz";
2020 url = "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz";
2021 sha1 = "137918d6d78283f7df7a6b7c5a63e140e69425e6";
2021 sha512 = "Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==";
2022 };
2022 };
2023 };
2023 };
2024 "concat-map-0.0.1" = {
2024 "concat-map-0.0.1" = {
@@ -2093,13 +2093,13 b' let'
2093 sha512 = "Y+SQCF+0NoWQryez2zXn5J5knmr9z/9qSQt7fbL78u83rxmigOy8X5+BFn8CFSuX+nKT8gpYwJX68ekqtQt6ZA==";
2093 sha512 = "Y+SQCF+0NoWQryez2zXn5J5knmr9z/9qSQt7fbL78u83rxmigOy8X5+BFn8CFSuX+nKT8gpYwJX68ekqtQt6ZA==";
2094 };
2094 };
2095 };
2095 };
2096 "core-js-2.6.1" = {
2096 "core-js-2.6.5" = {
2097 name = "core-js";
2097 name = "core-js";
2098 packageName = "core-js";
2098 packageName = "core-js";
2099 version = "2.6.1";
2099 version = "2.6.5";
2100 src = fetchurl {
2100 src = fetchurl {
2101 url = "https://registry.npmjs.org/core-js/-/core-js-2.6.1.tgz";
2101 url = "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz";
2102 sha512 = "L72mmmEayPJBejKIWe2pYtGis5r0tQ5NaJekdhyXgeMQTpJoBsH0NL4ElY2LfSoV15xeQWKQ+XTTOZdyero5Xg==";
2102 sha512 = "klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==";
2103 };
2103 };
2104 };
2104 };
2105 "core-util-is-1.0.2" = {
2105 "core-util-is-1.0.2" = {
@@ -2201,13 +2201,13 b' let'
2201 sha512 = "xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==";
2201 sha512 = "xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==";
2202 };
2202 };
2203 };
2203 };
2204 "css-what-2.1.2" = {
2204 "css-what-2.1.3" = {
2205 name = "css-what";
2205 name = "css-what";
2206 packageName = "css-what";
2206 packageName = "css-what";
2207 version = "2.1.2";
2207 version = "2.1.3";
2208 src = fetchurl {
2208 src = fetchurl {
2209 url = "https://registry.npmjs.org/css-what/-/css-what-2.1.2.tgz";
2209 url = "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz";
2210 sha512 = "wan8dMWQ0GUeF7DGEPVjhHemVW/vy6xUYmFzRY8RYqgA0JtXC9rJmbScBjqSu6dg9q0lwPQy6ZAmJVr3PPTvqQ==";
2210 sha512 = "a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==";
2211 };
2211 };
2212 };
2212 };
2213 "cssesc-0.1.0" = {
2213 "cssesc-0.1.0" = {
@@ -2417,13 +2417,13 b' let'
2417 sha512 = "kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==";
2417 sha512 = "kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==";
2418 };
2418 };
2419 };
2419 };
2420 "dir-glob-2.0.0" = {
2420 "dir-glob-2.2.2" = {
2421 name = "dir-glob";
2421 name = "dir-glob";
2422 packageName = "dir-glob";
2422 packageName = "dir-glob";
2423 version = "2.0.0";
2423 version = "2.2.2";
2424 src = fetchurl {
2424 src = fetchurl {
2425 url = "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz";
2425 url = "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz";
2426 sha512 = "37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==";
2426 sha512 = "f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==";
2427 };
2427 };
2428 };
2428 };
2429 "dom-converter-0.2.0" = {
2429 "dom-converter-0.2.0" = {
@@ -2435,13 +2435,13 b' let'
2435 sha512 = "gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==";
2435 sha512 = "gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==";
2436 };
2436 };
2437 };
2437 };
2438 "dom-serializer-0.1.0" = {
2438 "dom-serializer-0.1.1" = {
2439 name = "dom-serializer";
2439 name = "dom-serializer";
2440 packageName = "dom-serializer";
2440 packageName = "dom-serializer";
2441 version = "0.1.0";
2441 version = "0.1.1";
2442 src = fetchurl {
2442 src = fetchurl {
2443 url = "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz";
2443 url = "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz";
2444 sha1 = "073c697546ce0780ce23be4a28e293e40bc30c82";
2444 sha512 = "l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==";
2445 };
2445 };
2446 };
2446 };
2447 "dom5-2.3.0" = {
2447 "dom5-2.3.0" = {
@@ -2462,15 +2462,6 b' let'
2462 sha512 = "jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==";
2462 sha512 = "jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==";
2463 };
2463 };
2464 };
2464 };
2465 "domelementtype-1.1.3" = {
2466 name = "domelementtype";
2467 packageName = "domelementtype";
2468 version = "1.1.3";
2469 src = fetchurl {
2470 url = "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz";
2471 sha1 = "bd28773e2642881aec51544924299c5cd822185b";
2472 };
2473 };
2474 "domelementtype-1.3.1" = {
2465 "domelementtype-1.3.1" = {
2475 name = "domelementtype";
2466 name = "domelementtype";
2476 packageName = "domelementtype";
2467 packageName = "domelementtype";
@@ -2480,15 +2471,6 b' let'
2480 sha512 = "BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==";
2471 sha512 = "BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==";
2481 };
2472 };
2482 };
2473 };
2483 "domhandler-2.1.0" = {
2484 name = "domhandler";
2485 packageName = "domhandler";
2486 version = "2.1.0";
2487 src = fetchurl {
2488 url = "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz";
2489 sha1 = "d2646f5e57f6c3bab11cf6cb05d3c0acf7412594";
2490 };
2491 };
2492 "domhandler-2.3.0" = {
2474 "domhandler-2.3.0" = {
2493 name = "domhandler";
2475 name = "domhandler";
2494 packageName = "domhandler";
2476 packageName = "domhandler";
@@ -2498,15 +2480,6 b' let'
2498 sha1 = "2de59a0822d5027fabff6f032c2b25a2a8abe738";
2480 sha1 = "2de59a0822d5027fabff6f032c2b25a2a8abe738";
2499 };
2481 };
2500 };
2482 };
2501 "domutils-1.1.6" = {
2502 name = "domutils";
2503 packageName = "domutils";
2504 version = "1.1.6";
2505 src = fetchurl {
2506 url = "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz";
2507 sha1 = "bddc3de099b9a2efacc51c623f28f416ecc57485";
2508 };
2509 };
2510 "domutils-1.5.1" = {
2483 "domutils-1.5.1" = {
2511 name = "domutils";
2484 name = "domutils";
2512 packageName = "domutils";
2485 packageName = "domutils";
@@ -2516,13 +2489,22 b' let'
2516 sha1 = "dcd8488a26f563d61079e48c9f7b7e32373682cf";
2489 sha1 = "dcd8488a26f563d61079e48c9f7b7e32373682cf";
2517 };
2490 };
2518 };
2491 };
2519 "duplexify-3.6.1" = {
2492 "dropzone-5.5.1" = {
2493 name = "dropzone";
2494 packageName = "dropzone";
2495 version = "5.5.1";
2496 src = fetchurl {
2497 url = "https://registry.npmjs.org/dropzone/-/dropzone-5.5.1.tgz";
2498 sha512 = "3VduRWLxx9hbVr42QieQN25mx/I61/mRdUSuxAmDGdDqZIN8qtP7tcKMa3KfpJjuGjOJGYYUzzeq6eGDnkzesA==";
2499 };
2500 };
2501 "duplexify-3.7.1" = {
2520 name = "duplexify";
2502 name = "duplexify";
2521 packageName = "duplexify";
2503 packageName = "duplexify";
2522 version = "3.6.1";
2504 version = "3.7.1";
2523 src = fetchurl {
2505 src = fetchurl {
2524 url = "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz";
2506 url = "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz";
2525 sha512 = "vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==";
2507 sha512 = "07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==";
2526 };
2508 };
2527 };
2509 };
2528 "ecc-jsbn-0.1.2" = {
2510 "ecc-jsbn-0.1.2" = {
@@ -2534,13 +2516,13 b' let'
2534 sha1 = "3a83a904e54353287874c564b7549386849a98c9";
2516 sha1 = "3a83a904e54353287874c564b7549386849a98c9";
2535 };
2517 };
2536 };
2518 };
2537 "electron-to-chromium-1.3.98" = {
2519 "electron-to-chromium-1.3.133" = {
2538 name = "electron-to-chromium";
2520 name = "electron-to-chromium";
2539 packageName = "electron-to-chromium";
2521 packageName = "electron-to-chromium";
2540 version = "1.3.98";
2522 version = "1.3.133";
2541 src = fetchurl {
2523 src = fetchurl {
2542 url = "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.98.tgz";
2524 url = "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.133.tgz";
2543 sha512 = "WIZdNuvE3dFr6kkPgv4d/cfswNZD6XbeLBM8baOIQTsnbf4xWrVEaLvp7oNnbnMWWXDqq7Tbv+H5JfciLTJm4Q==";
2525 sha512 = "lyoC8aoqbbDqsprb6aPdt9n3DpOZZzdz/T4IZKsR0/dkZIxnJVUjjcpOSwA66jPRIOyDAamCTAUqweU05kKNSg==";
2544 };
2526 };
2545 };
2527 };
2546 "elliptic-6.4.1" = {
2528 "elliptic-6.4.1" = {
@@ -2651,13 +2633,13 b' let'
2651 sha1 = "1b61c0562190a8dff6ae3bb2cf0200ca130b86d4";
2633 sha1 = "1b61c0562190a8dff6ae3bb2cf0200ca130b86d4";
2652 };
2634 };
2653 };
2635 };
2654 "eslint-scope-4.0.0" = {
2636 "eslint-scope-4.0.3" = {
2655 name = "eslint-scope";
2637 name = "eslint-scope";
2656 packageName = "eslint-scope";
2638 packageName = "eslint-scope";
2657 version = "4.0.0";
2639 version = "4.0.3";
2658 src = fetchurl {
2640 src = fetchurl {
2659 url = "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz";
2641 url = "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz";
2660 sha512 = "1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==";
2642 sha512 = "p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==";
2661 };
2643 };
2662 };
2644 };
2663 "espree-3.5.4" = {
2645 "espree-3.5.4" = {
@@ -2732,13 +2714,13 b' let'
2732 sha1 = "8f61b75cde012b2e9eb284d4545583b5643b61ab";
2714 sha1 = "8f61b75cde012b2e9eb284d4545583b5643b61ab";
2733 };
2715 };
2734 };
2716 };
2735 "events-1.1.1" = {
2717 "events-3.0.0" = {
2736 name = "events";
2718 name = "events";
2737 packageName = "events";
2719 packageName = "events";
2738 version = "1.1.1";
2720 version = "3.0.0";
2739 src = fetchurl {
2721 src = fetchurl {
2740 url = "https://registry.npmjs.org/events/-/events-1.1.1.tgz";
2722 url = "https://registry.npmjs.org/events/-/events-3.0.0.tgz";
2741 sha1 = "9ebdb7635ad099c70dcc4c2a1f5004288e8bd924";
2723 sha512 = "Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==";
2742 };
2724 };
2743 };
2725 };
2744 "evp_bytestokey-1.0.3" = {
2726 "evp_bytestokey-1.0.3" = {
@@ -2948,13 +2930,13 b' let'
2948 sha1 = "9326b1488c22d1a6088650a86901b2d9a90a2cbc";
2930 sha1 = "9326b1488c22d1a6088650a86901b2d9a90a2cbc";
2949 };
2931 };
2950 };
2932 };
2951 "fined-1.1.1" = {
2933 "fined-1.2.0" = {
2952 name = "fined";
2934 name = "fined";
2953 packageName = "fined";
2935 packageName = "fined";
2954 version = "1.1.1";
2936 version = "1.2.0";
2955 src = fetchurl {
2937 src = fetchurl {
2956 url = "https://registry.npmjs.org/fined/-/fined-1.1.1.tgz";
2938 url = "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz";
2957 sha512 = "jQp949ZmEbiYHk3gkbdtpJ0G1+kgtLQBNdP5edFP7Fh+WAYceLQz6yO1SBj72Xkg8GVyTB3bBzAYrHJVh5Xd5g==";
2939 sha512 = "ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==";
2958 };
2940 };
2959 };
2941 };
2960 "flagged-respawn-1.0.1" = {
2942 "flagged-respawn-1.0.1" = {
@@ -2975,13 +2957,13 b' let'
2975 sha1 = "dae46a9d78fbe25292258cc1e780a41d95c03782";
2957 sha1 = "dae46a9d78fbe25292258cc1e780a41d95c03782";
2976 };
2958 };
2977 };
2959 };
2978 "flush-write-stream-1.0.3" = {
2960 "flush-write-stream-1.1.1" = {
2979 name = "flush-write-stream";
2961 name = "flush-write-stream";
2980 packageName = "flush-write-stream";
2962 packageName = "flush-write-stream";
2981 version = "1.0.3";
2963 version = "1.1.1";
2982 src = fetchurl {
2964 src = fetchurl {
2983 url = "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz";
2965 url = "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz";
2984 sha512 = "calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==";
2966 sha512 = "3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==";
2985 };
2967 };
2986 };
2968 };
2987 "for-in-1.0.2" = {
2969 "for-in-1.0.2" = {
@@ -3056,13 +3038,13 b' let'
3056 sha1 = "1504ad2523158caa40db4a2787cb01411994ea4f";
3038 sha1 = "1504ad2523158caa40db4a2787cb01411994ea4f";
3057 };
3039 };
3058 };
3040 };
3059 "fsevents-1.2.4" = {
3041 "fsevents-1.2.9" = {
3060 name = "fsevents";
3042 name = "fsevents";
3061 packageName = "fsevents";
3043 packageName = "fsevents";
3062 version = "1.2.4";
3044 version = "1.2.9";
3063 src = fetchurl {
3045 src = fetchurl {
3064 url = "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz";
3046 url = "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz";
3065 sha512 = "z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==";
3047 sha512 = "oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==";
3066 };
3048 };
3067 };
3049 };
3068 "function-bind-1.1.1" = {
3050 "function-bind-1.1.1" = {
@@ -3146,13 +3128,13 b' let'
3146 sha1 = "4a973f635b9190f715d10987d5c00fd2815ebe3d";
3128 sha1 = "4a973f635b9190f715d10987d5c00fd2815ebe3d";
3147 };
3129 };
3148 };
3130 };
3149 "glob-7.1.3" = {
3131 "glob-7.1.4" = {
3150 name = "glob";
3132 name = "glob";
3151 packageName = "glob";
3133 packageName = "glob";
3152 version = "7.1.3";
3134 version = "7.1.4";
3153 src = fetchurl {
3135 src = fetchurl {
3154 url = "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz";
3136 url = "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz";
3155 sha512 = "vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==";
3137 sha512 = "hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==";
3156 };
3138 };
3157 };
3139 };
3158 "glob-parent-3.1.0" = {
3140 "glob-parent-3.1.0" = {
@@ -3524,13 +3506,13 b' let'
3524 sha1 = "e36c3f2d2cae7d746a857e38d18d5f32a7882db8";
3506 sha1 = "e36c3f2d2cae7d746a857e38d18d5f32a7882db8";
3525 };
3507 };
3526 };
3508 };
3527 "homedir-polyfill-1.0.1" = {
3509 "homedir-polyfill-1.0.3" = {
3528 name = "homedir-polyfill";
3510 name = "homedir-polyfill";
3529 packageName = "homedir-polyfill";
3511 packageName = "homedir-polyfill";
3530 version = "1.0.1";
3512 version = "1.0.3";
3531 src = fetchurl {
3513 src = fetchurl {
3532 url = "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz";
3514 url = "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz";
3533 sha1 = "4c2bbc8a758998feebf5ed68580f76d46768b4bc";
3515 sha512 = "eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==";
3534 };
3516 };
3535 };
3517 };
3536 "hooker-0.2.3" = {
3518 "hooker-0.2.3" = {
@@ -3587,15 +3569,6 b' let'
3587 sha1 = "b01abbd723acaaa7b37b6af4492ebda03d9dd37b";
3569 sha1 = "b01abbd723acaaa7b37b6af4492ebda03d9dd37b";
3588 };
3570 };
3589 };
3571 };
3590 "htmlparser2-3.3.0" = {
3591 name = "htmlparser2";
3592 packageName = "htmlparser2";
3593 version = "3.3.0";
3594 src = fetchurl {
3595 url = "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz";
3596 sha1 = "cc70d05a59f6542e43f0e685c982e14c924a9efe";
3597 };
3598 };
3599 "htmlparser2-3.8.3" = {
3572 "htmlparser2-3.8.3" = {
3600 name = "htmlparser2";
3573 name = "htmlparser2";
3601 packageName = "htmlparser2";
3574 packageName = "htmlparser2";
@@ -3650,13 +3623,13 b' let'
3650 sha1 = "83f0a0ec378bf3246178b6c2ad9136f135b1c962";
3623 sha1 = "83f0a0ec378bf3246178b6c2ad9136f135b1c962";
3651 };
3624 };
3652 };
3625 };
3653 "ieee754-1.1.12" = {
3626 "ieee754-1.1.13" = {
3654 name = "ieee754";
3627 name = "ieee754";
3655 packageName = "ieee754";
3628 packageName = "ieee754";
3656 version = "1.1.12";
3629 version = "1.1.13";
3657 src = fetchurl {
3630 src = fetchurl {
3658 url = "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz";
3631 url = "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz";
3659 sha512 = "GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==";
3632 sha512 = "4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==";
3660 };
3633 };
3661 };
3634 };
3662 "iferr-0.1.5" = {
3635 "iferr-0.1.5" = {
@@ -3974,13 +3947,13 b' let'
3974 sha1 = "7ba5ae24217804ac70707b96922567486cc3e84a";
3947 sha1 = "7ba5ae24217804ac70707b96922567486cc3e84a";
3975 };
3948 };
3976 };
3949 };
3977 "is-glob-4.0.0" = {
3950 "is-glob-4.0.1" = {
3978 name = "is-glob";
3951 name = "is-glob";
3979 packageName = "is-glob";
3952 packageName = "is-glob";
3980 version = "4.0.0";
3953 version = "4.0.1";
3981 src = fetchurl {
3954 src = fetchurl {
3982 url = "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz";
3955 url = "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz";
3983 sha1 = "9521c76845cc2610a85203ddf080a958c2ffabc0";
3956 sha512 = "5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==";
3984 };
3957 };
3985 };
3958 };
3986 "is-number-3.0.0" = {
3959 "is-number-3.0.0" = {
@@ -4145,13 +4118,13 b' let'
4145 sha1 = "dd8b74278b27102d29df63eae28308a8cfa1b583";
4118 sha1 = "dd8b74278b27102d29df63eae28308a8cfa1b583";
4146 };
4119 };
4147 };
4120 };
4148 "js-base64-2.5.0" = {
4121 "js-base64-2.5.1" = {
4149 name = "js-base64";
4122 name = "js-base64";
4150 packageName = "js-base64";
4123 packageName = "js-base64";
4151 version = "2.5.0";
4124 version = "2.5.1";
4152 src = fetchurl {
4125 src = fetchurl {
4153 url = "https://registry.npmjs.org/js-base64/-/js-base64-2.5.0.tgz";
4126 url = "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz";
4154 sha512 = "wlEBIZ5LP8usDylWbDNhKPEFVFdI5hCHpnVoT/Ysvoi/PRhJENm/Rlh9TvjYB38HFfKZN7OzEbRjmjvLkFw11g==";
4127 sha512 = "M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==";
4155 };
4128 };
4156 };
4129 };
4157 "js-tokens-3.0.2" = {
4130 "js-tokens-3.0.2" = {
@@ -4208,6 +4181,15 b' let'
4208 sha1 = "46c3fec8c1892b12b0833db9bc7622176dbab34b";
4181 sha1 = "46c3fec8c1892b12b0833db9bc7622176dbab34b";
4209 };
4182 };
4210 };
4183 };
4184 "jshint-2.10.2" = {
4185 name = "jshint";
4186 packageName = "jshint";
4187 version = "2.10.2";
4188 src = fetchurl {
4189 url = "https://registry.npmjs.org/jshint/-/jshint-2.10.2.tgz";
4190 sha512 = "e7KZgCSXMJxznE/4WULzybCMNXNAd/bf5TSrvVEq78Q/K8ZwFpmBqQeDtNiHc3l49nV4E/+YeHU/JZjSUIrLAA==";
4191 };
4192 };
4211 "jshint-2.9.7" = {
4193 "jshint-2.9.7" = {
4212 name = "jshint";
4194 name = "jshint";
4213 packageName = "jshint";
4195 packageName = "jshint";
@@ -4370,13 +4352,13 b' let'
4370 sha1 = "2009291bb31cea861bbf10a7c15a28caf75c31ec";
4352 sha1 = "2009291bb31cea861bbf10a7c15a28caf75c31ec";
4371 };
4353 };
4372 };
4354 };
4373 "loader-runner-2.3.1" = {
4355 "loader-runner-2.4.0" = {
4374 name = "loader-runner";
4356 name = "loader-runner";
4375 packageName = "loader-runner";
4357 packageName = "loader-runner";
4376 version = "2.3.1";
4358 version = "2.4.0";
4377 src = fetchurl {
4359 src = fetchurl {
4378 url = "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.1.tgz";
4360 url = "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz";
4379 sha512 = "By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw==";
4361 sha512 = "Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==";
4380 };
4362 };
4381 };
4363 };
4382 "loader-utils-0.2.17" = {
4364 "loader-utils-0.2.17" = {
@@ -4460,15 +4442,6 b' let'
4460 sha1 = "b28aa6288a2b9fc651035c7711f65ab6190331a6";
4442 sha1 = "b28aa6288a2b9fc651035c7711f65ab6190331a6";
4461 };
4443 };
4462 };
4444 };
4463 "lodash.debounce-4.0.8" = {
4464 name = "lodash.debounce";
4465 packageName = "lodash.debounce";
4466 version = "4.0.8";
4467 src = fetchurl {
4468 url = "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz";
4469 sha1 = "82d79bff30a67c4005ffd5e2515300ad9ca4d7af";
4470 };
4471 };
4472 "lodash.isplainobject-4.0.6" = {
4445 "lodash.isplainobject-4.0.6" = {
4473 name = "lodash.isplainobject";
4446 name = "lodash.isplainobject";
4474 packageName = "lodash.isplainobject";
4447 packageName = "lodash.isplainobject";
@@ -4613,13 +4586,13 b' let'
4613 sha512 = "xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==";
4586 sha512 = "xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==";
4614 };
4587 };
4615 };
4588 };
4616 "mem-4.0.0" = {
4589 "mem-4.3.0" = {
4617 name = "mem";
4590 name = "mem";
4618 packageName = "mem";
4591 packageName = "mem";
4619 version = "4.0.0";
4592 version = "4.3.0";
4620 src = fetchurl {
4593 src = fetchurl {
4621 url = "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz";
4594 url = "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz";
4622 sha512 = "WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==";
4595 sha512 = "qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==";
4623 };
4596 };
4624 };
4597 };
4625 "memory-fs-0.4.1" = {
4598 "memory-fs-0.4.1" = {
@@ -4658,31 +4631,31 b' let'
4658 sha512 = "x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==";
4631 sha512 = "x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==";
4659 };
4632 };
4660 };
4633 };
4661 "mime-db-1.37.0" = {
4634 "mime-db-1.40.0" = {
4662 name = "mime-db";
4635 name = "mime-db";
4663 packageName = "mime-db";
4636 packageName = "mime-db";
4664 version = "1.37.0";
4637 version = "1.40.0";
4665 src = fetchurl {
4638 src = fetchurl {
4666 url = "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz";
4639 url = "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz";
4667 sha512 = "R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==";
4640 sha512 = "jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==";
4668 };
4641 };
4669 };
4642 };
4670 "mime-types-2.1.21" = {
4643 "mime-types-2.1.24" = {
4671 name = "mime-types";
4644 name = "mime-types";
4672 packageName = "mime-types";
4645 packageName = "mime-types";
4673 version = "2.1.21";
4646 version = "2.1.24";
4674 src = fetchurl {
4647 src = fetchurl {
4675 url = "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz";
4648 url = "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz";
4676 sha512 = "3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==";
4649 sha512 = "WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==";
4677 };
4650 };
4678 };
4651 };
4679 "mimic-fn-1.2.0" = {
4652 "mimic-fn-2.1.0" = {
4680 name = "mimic-fn";
4653 name = "mimic-fn";
4681 packageName = "mimic-fn";
4654 packageName = "mimic-fn";
4682 version = "1.2.0";
4655 version = "2.1.0";
4683 src = fetchurl {
4656 src = fetchurl {
4684 url = "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz";
4657 url = "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz";
4685 sha512 = "jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==";
4658 sha512 = "OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==";
4686 };
4659 };
4687 };
4660 };
4688 "minimalistic-assert-1.0.1" = {
4661 "minimalistic-assert-1.0.1" = {
@@ -4775,22 +4748,22 b' let'
4775 sha1 = "30057438eac6cf7f8c4767f38648d6697d75c903";
4748 sha1 = "30057438eac6cf7f8c4767f38648d6697d75c903";
4776 };
4749 };
4777 };
4750 };
4778 "moment-2.23.0" = {
4751 "moment-2.24.0" = {
4779 name = "moment";
4752 name = "moment";
4780 packageName = "moment";
4753 packageName = "moment";
4781 version = "2.23.0";
4754 version = "2.24.0";
4782 src = fetchurl {
4755 src = fetchurl {
4783 url = "https://registry.npmjs.org/moment/-/moment-2.23.0.tgz";
4756 url = "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz";
4784 sha512 = "3IE39bHVqFbWWaPOMHZF98Q9c3LDKGTmypMiTM2QygGXXElkFWIH7GxfmlwmY2vwa+wmNsoYZmG2iusf1ZjJoA==";
4757 sha512 = "bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==";
4785 };
4758 };
4786 };
4759 };
4787 "mousetrap-1.6.2" = {
4760 "mousetrap-1.6.3" = {
4788 name = "mousetrap";
4761 name = "mousetrap";
4789 packageName = "mousetrap";
4762 packageName = "mousetrap";
4790 version = "1.6.2";
4763 version = "1.6.3";
4791 src = fetchurl {
4764 src = fetchurl {
4792 url = "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.2.tgz";
4765 url = "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.3.tgz";
4793 sha512 = "jDjhi7wlHwdO6q6DS7YRmSHcuI+RVxadBkLt3KHrhd3C2b+w5pKefg3oj5beTcHZyVFA9Aksf+yEE1y5jxUjVA==";
4766 sha512 = "bd+nzwhhs9ifsUrC2tWaSgm24/oo2c83zaRyZQF06hYA6sANfsXHtnZ19AbbbDXCDzeH5nZBSQ4NvCjgD62tJA==";
4794 };
4767 };
4795 };
4768 };
4796 "move-concurrently-1.0.1" = {
4769 "move-concurrently-1.0.1" = {
@@ -4811,13 +4784,13 b' let'
4811 sha1 = "5608aeadfc00be6c2901df5f9861788de0d597c8";
4784 sha1 = "5608aeadfc00be6c2901df5f9861788de0d597c8";
4812 };
4785 };
4813 };
4786 };
4814 "nan-2.12.1" = {
4787 "nan-2.13.2" = {
4815 name = "nan";
4788 name = "nan";
4816 packageName = "nan";
4789 packageName = "nan";
4817 version = "2.12.1";
4790 version = "2.13.2";
4818 src = fetchurl {
4791 src = fetchurl {
4819 url = "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz";
4792 url = "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz";
4820 sha512 = "JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==";
4793 sha512 = "TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==";
4821 };
4794 };
4822 };
4795 };
4823 "nanomatch-1.2.13" = {
4796 "nanomatch-1.2.13" = {
@@ -4829,13 +4802,13 b' let'
4829 sha512 = "fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==";
4802 sha512 = "fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==";
4830 };
4803 };
4831 };
4804 };
4832 "neo-async-2.6.0" = {
4805 "neo-async-2.6.1" = {
4833 name = "neo-async";
4806 name = "neo-async";
4834 packageName = "neo-async";
4807 packageName = "neo-async";
4835 version = "2.6.0";
4808 version = "2.6.1";
4836 src = fetchurl {
4809 src = fetchurl {
4837 url = "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz";
4810 url = "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz";
4838 sha512 = "MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==";
4811 sha512 = "iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==";
4839 };
4812 };
4840 };
4813 };
4841 "nice-try-1.0.5" = {
4814 "nice-try-1.0.5" = {
@@ -4856,13 +4829,13 b' let'
4856 sha512 = "rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==";
4829 sha512 = "rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==";
4857 };
4830 };
4858 };
4831 };
4859 "node-libs-browser-2.1.0" = {
4832 "node-libs-browser-2.2.0" = {
4860 name = "node-libs-browser";
4833 name = "node-libs-browser";
4861 packageName = "node-libs-browser";
4834 packageName = "node-libs-browser";
4862 version = "2.1.0";
4835 version = "2.2.0";
4863 src = fetchurl {
4836 src = fetchurl {
4864 url = "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz";
4837 url = "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.0.tgz";
4865 sha512 = "5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==";
4838 sha512 = "5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA==";
4866 };
4839 };
4867 };
4840 };
4868 "nopt-1.0.10" = {
4841 "nopt-1.0.10" = {
@@ -4910,6 +4883,15 b' let'
4910 sha1 = "1ab28b556e198363a8c1a6f7e6fa20137fe6aed9";
4883 sha1 = "1ab28b556e198363a8c1a6f7e6fa20137fe6aed9";
4911 };
4884 };
4912 };
4885 };
4886 "normalize-path-3.0.0" = {
4887 name = "normalize-path";
4888 packageName = "normalize-path";
4889 version = "3.0.0";
4890 src = fetchurl {
4891 url = "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz";
4892 sha512 = "6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==";
4893 };
4894 };
4913 "normalize-range-0.1.2" = {
4895 "normalize-range-0.1.2" = {
4914 name = "normalize-range";
4896 name = "normalize-range";
4915 packageName = "normalize-range";
4897 packageName = "normalize-range";
@@ -4991,13 +4973,13 b' let'
4991 sha1 = "7e7d858b781bd7c991a41ba975ed3812754e998c";
4973 sha1 = "7e7d858b781bd7c991a41ba975ed3812754e998c";
4992 };
4974 };
4993 };
4975 };
4994 "object-keys-1.0.12" = {
4976 "object-keys-1.1.1" = {
4995 name = "object-keys";
4977 name = "object-keys";
4996 packageName = "object-keys";
4978 packageName = "object-keys";
4997 version = "1.0.12";
4979 version = "1.1.1";
4998 src = fetchurl {
4980 src = fetchurl {
4999 url = "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz";
4981 url = "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz";
5000 sha512 = "FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==";
4982 sha512 = "NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==";
5001 };
4983 };
5002 };
4984 };
5003 "object-visit-1.0.1" = {
4985 "object-visit-1.0.1" = {
@@ -5117,13 +5099,13 b' let'
5117 sha1 = "3fbcfb15b899a44123b34b6dcc18b724336a2cae";
5099 sha1 = "3fbcfb15b899a44123b34b6dcc18b724336a2cae";
5118 };
5100 };
5119 };
5101 };
5120 "p-is-promise-1.1.0" = {
5102 "p-is-promise-2.1.0" = {
5121 name = "p-is-promise";
5103 name = "p-is-promise";
5122 packageName = "p-is-promise";
5104 packageName = "p-is-promise";
5123 version = "1.1.0";
5105 version = "2.1.0";
5124 src = fetchurl {
5106 src = fetchurl {
5125 url = "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz";
5107 url = "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz";
5126 sha1 = "9c9456989e9f6588017b0434d56097675c3da05e";
5108 sha512 = "Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==";
5127 };
5109 };
5128 };
5110 };
5129 "p-limit-1.3.0" = {
5111 "p-limit-1.3.0" = {
@@ -5135,13 +5117,13 b' let'
5135 sha512 = "vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==";
5117 sha512 = "vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==";
5136 };
5118 };
5137 };
5119 };
5138 "p-limit-2.1.0" = {
5120 "p-limit-2.2.0" = {
5139 name = "p-limit";
5121 name = "p-limit";
5140 packageName = "p-limit";
5122 packageName = "p-limit";
5141 version = "2.1.0";
5123 version = "2.2.0";
5142 src = fetchurl {
5124 src = fetchurl {
5143 url = "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz";
5125 url = "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz";
5144 sha512 = "NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==";
5126 sha512 = "pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==";
5145 };
5127 };
5146 };
5128 };
5147 "p-locate-2.0.0" = {
5129 "p-locate-2.0.0" = {
@@ -5171,22 +5153,22 b' let'
5171 sha1 = "cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3";
5153 sha1 = "cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3";
5172 };
5154 };
5173 };
5155 };
5174 "p-try-2.0.0" = {
5156 "p-try-2.2.0" = {
5175 name = "p-try";
5157 name = "p-try";
5176 packageName = "p-try";
5158 packageName = "p-try";
5177 version = "2.0.0";
5159 version = "2.2.0";
5178 src = fetchurl {
5160 src = fetchurl {
5179 url = "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz";
5161 url = "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz";
5180 sha512 = "hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==";
5162 sha512 = "R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==";
5181 };
5163 };
5182 };
5164 };
5183 "pako-1.0.7" = {
5165 "pako-1.0.10" = {
5184 name = "pako";
5166 name = "pako";
5185 packageName = "pako";
5167 packageName = "pako";
5186 version = "1.0.7";
5168 version = "1.0.10";
5187 src = fetchurl {
5169 src = fetchurl {
5188 url = "https://registry.npmjs.org/pako/-/pako-1.0.7.tgz";
5170 url = "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz";
5189 sha512 = "3HNK5tW4x8o5mO8RuHZp3Ydw9icZXx0RANAOMzlMzx7LVXhMJ4mo3MOBpzyd7r/+RUu8BmndP47LXT+vzjtWcQ==";
5171 sha512 = "0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==";
5190 };
5172 };
5191 };
5173 };
5192 "parallel-transform-1.1.0" = {
5174 "parallel-transform-1.1.0" = {
@@ -5207,13 +5189,13 b' let'
5207 sha1 = "df94fd8cf6531ecf75e6bef9a0858fbc72be2247";
5189 sha1 = "df94fd8cf6531ecf75e6bef9a0858fbc72be2247";
5208 };
5190 };
5209 };
5191 };
5210 "parse-asn1-5.1.1" = {
5192 "parse-asn1-5.1.4" = {
5211 name = "parse-asn1";
5193 name = "parse-asn1";
5212 packageName = "parse-asn1";
5194 packageName = "parse-asn1";
5213 version = "5.1.1";
5195 version = "5.1.4";
5214 src = fetchurl {
5196 src = fetchurl {
5215 url = "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz";
5197 url = "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz";
5216 sha512 = "KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==";
5198 sha512 = "Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==";
5217 };
5199 };
5218 };
5200 };
5219 "parse-filepath-1.0.2" = {
5201 "parse-filepath-1.0.2" = {
@@ -5927,13 +5909,13 b' let'
5927 sha1 = "9ec61f79049875707d69414596fd907a4d711e73";
5909 sha1 = "9ec61f79049875707d69414596fd907a4d711e73";
5928 };
5910 };
5929 };
5911 };
5930 "randombytes-2.0.6" = {
5912 "randombytes-2.1.0" = {
5931 name = "randombytes";
5913 name = "randombytes";
5932 packageName = "randombytes";
5914 packageName = "randombytes";
5933 version = "2.0.6";
5915 version = "2.1.0";
5934 src = fetchurl {
5916 src = fetchurl {
5935 url = "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz";
5917 url = "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz";
5936 sha512 = "CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==";
5918 sha512 = "vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==";
5937 };
5919 };
5938 };
5920 };
5939 "randomfill-1.0.4" = {
5921 "randomfill-1.0.4" = {
@@ -5954,15 +5936,6 b' let'
5954 sha512 = "guh4ZNAf96f+CDwfnPbFeFiO5YcfPllUmZrgcoOmx6iqZPq+DcKbnyjPuBxEAtQ3tqqd++qChsQfQB+VBzFT0Q==";
5936 sha512 = "guh4ZNAf96f+CDwfnPbFeFiO5YcfPllUmZrgcoOmx6iqZPq+DcKbnyjPuBxEAtQ3tqqd++qChsQfQB+VBzFT0Q==";
5955 };
5937 };
5956 };
5938 };
5957 "readable-stream-1.0.34" = {
5958 name = "readable-stream";
5959 packageName = "readable-stream";
5960 version = "1.0.34";
5961 src = fetchurl {
5962 url = "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz";
5963 sha1 = "125820e34bc842d2f2aaafafe4c2916ee32c157c";
5964 };
5965 };
5966 "readable-stream-1.1.14" = {
5939 "readable-stream-1.1.14" = {
5967 name = "readable-stream";
5940 name = "readable-stream";
5968 packageName = "readable-stream";
5941 packageName = "readable-stream";
@@ -6116,13 +6089,13 b' let'
6116 sha1 = "c24bce2a283adad5bc3f58e0d48249b92379d8ef";
6089 sha1 = "c24bce2a283adad5bc3f58e0d48249b92379d8ef";
6117 };
6090 };
6118 };
6091 };
6119 "renderkid-2.0.2" = {
6092 "renderkid-2.0.3" = {
6120 name = "renderkid";
6093 name = "renderkid";
6121 packageName = "renderkid";
6094 packageName = "renderkid";
6122 version = "2.0.2";
6095 version = "2.0.3";
6123 src = fetchurl {
6096 src = fetchurl {
6124 url = "https://registry.npmjs.org/renderkid/-/renderkid-2.0.2.tgz";
6097 url = "https://registry.npmjs.org/renderkid/-/renderkid-2.0.3.tgz";
6125 sha512 = "FsygIxevi1jSiPY9h7vZmBFUbAOcbYm9UwyiLNdVsLRs/5We9Ob5NMPbGYUTWiLq5L+ezlVdE0A8bbME5CWTpg==";
6098 sha512 = "z8CLQp7EZBPCwCnncgf9C4XAi3WR0dv+uWu/PjIyhhAb5d6IJ/QZqlHFprHeKT+59//V6BNUsLbvN8+2LarxGA==";
6126 };
6099 };
6127 };
6100 };
6128 "repeat-element-1.1.3" = {
6101 "repeat-element-1.1.3" = {
@@ -6179,13 +6152,13 b' let'
6179 sha1 = "97f717b69d48784f5f526a6c5aa8ffdda055a4d1";
6152 sha1 = "97f717b69d48784f5f526a6c5aa8ffdda055a4d1";
6180 };
6153 };
6181 };
6154 };
6182 "resolve-1.9.0" = {
6155 "resolve-1.10.1" = {
6183 name = "resolve";
6156 name = "resolve";
6184 packageName = "resolve";
6157 packageName = "resolve";
6185 version = "1.9.0";
6158 version = "1.10.1";
6186 src = fetchurl {
6159 src = fetchurl {
6187 url = "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz";
6160 url = "https://registry.npmjs.org/resolve/-/resolve-1.10.1.tgz";
6188 sha512 = "TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==";
6161 sha512 = "KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA==";
6189 };
6162 };
6190 };
6163 };
6191 "resolve-cwd-2.0.0" = {
6164 "resolve-cwd-2.0.0" = {
@@ -6332,22 +6305,22 b' let'
6332 sha1 = "0e7350acdec80b1108528786ec1d4418d11b396d";
6305 sha1 = "0e7350acdec80b1108528786ec1d4418d11b396d";
6333 };
6306 };
6334 };
6307 };
6335 "semver-5.6.0" = {
6308 "semver-5.7.0" = {
6336 name = "semver";
6309 name = "semver";
6337 packageName = "semver";
6310 packageName = "semver";
6338 version = "5.6.0";
6311 version = "5.7.0";
6339 src = fetchurl {
6312 src = fetchurl {
6340 url = "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz";
6313 url = "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz";
6341 sha512 = "RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==";
6314 sha512 = "Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==";
6342 };
6315 };
6343 };
6316 };
6344 "serialize-javascript-1.6.1" = {
6317 "serialize-javascript-1.7.0" = {
6345 name = "serialize-javascript";
6318 name = "serialize-javascript";
6346 packageName = "serialize-javascript";
6319 packageName = "serialize-javascript";
6347 version = "1.6.1";
6320 version = "1.7.0";
6348 src = fetchurl {
6321 src = fetchurl {
6349 url = "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.6.1.tgz";
6322 url = "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz";
6350 sha512 = "A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw==";
6323 sha512 = "ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==";
6351 };
6324 };
6352 };
6325 };
6353 "set-blocking-2.0.0" = {
6326 "set-blocking-2.0.0" = {
@@ -6593,13 +6566,13 b' let'
6593 sha1 = "04e6926f662895354f3dd015203633b857297e2c";
6566 sha1 = "04e6926f662895354f3dd015203633b857297e2c";
6594 };
6567 };
6595 };
6568 };
6596 "sshpk-1.16.0" = {
6569 "sshpk-1.16.1" = {
6597 name = "sshpk";
6570 name = "sshpk";
6598 packageName = "sshpk";
6571 packageName = "sshpk";
6599 version = "1.16.0";
6572 version = "1.16.1";
6600 src = fetchurl {
6573 src = fetchurl {
6601 url = "https://registry.npmjs.org/sshpk/-/sshpk-1.16.0.tgz";
6574 url = "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz";
6602 sha512 = "Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ==";
6575 sha512 = "HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==";
6603 };
6576 };
6604 };
6577 };
6605 "ssri-5.3.0" = {
6578 "ssri-5.3.0" = {
@@ -6629,13 +6602,13 b' let'
6629 sha1 = "142bf6b64c2b416e4b707ebf8f09b8b5a5043877";
6602 sha1 = "142bf6b64c2b416e4b707ebf8f09b8b5a5043877";
6630 };
6603 };
6631 };
6604 };
6632 "stream-browserify-2.0.1" = {
6605 "stream-browserify-2.0.2" = {
6633 name = "stream-browserify";
6606 name = "stream-browserify";
6634 packageName = "stream-browserify";
6607 packageName = "stream-browserify";
6635 version = "2.0.1";
6608 version = "2.0.2";
6636 src = fetchurl {
6609 src = fetchurl {
6637 url = "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz";
6610 url = "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz";
6638 sha1 = "66266ee5f9bdb9940a4e4514cafb43bb71e5c9db";
6611 sha512 = "nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==";
6639 };
6612 };
6640 };
6613 };
6641 "stream-each-1.2.3" = {
6614 "stream-each-1.2.3" = {
@@ -6836,13 +6809,13 b' let'
6836 sha512 = "2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A==";
6809 sha512 = "2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A==";
6837 };
6810 };
6838 };
6811 };
6839 "tapable-1.1.1" = {
6812 "tapable-1.1.3" = {
6840 name = "tapable";
6813 name = "tapable";
6841 packageName = "tapable";
6814 packageName = "tapable";
6842 version = "1.1.1";
6815 version = "1.1.3";
6843 src = fetchurl {
6816 src = fetchurl {
6844 url = "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz";
6817 url = "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz";
6845 sha512 = "9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA==";
6818 sha512 = "4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==";
6846 };
6819 };
6847 };
6820 };
6848 "through-2.3.8" = {
6821 "through-2.3.8" = {
@@ -6872,13 +6845,13 b' let'
6872 sha512 = "YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==";
6845 sha512 = "YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==";
6873 };
6846 };
6874 };
6847 };
6875 "tiny-emitter-2.0.2" = {
6848 "tiny-emitter-2.1.0" = {
6876 name = "tiny-emitter";
6849 name = "tiny-emitter";
6877 packageName = "tiny-emitter";
6850 packageName = "tiny-emitter";
6878 version = "2.0.2";
6851 version = "2.1.0";
6879 src = fetchurl {
6852 src = fetchurl {
6880 url = "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.0.2.tgz";
6853 url = "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz";
6881 sha512 = "2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow==";
6854 sha512 = "NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==";
6882 };
6855 };
6883 };
6856 };
6884 "tiny-lr-fork-0.0.5" = {
6857 "tiny-lr-fork-0.0.5" = {
@@ -7034,13 +7007,13 b' let'
7034 sha1 = "29c5733148057bb4e1f75df35b7a9cb72e6a59dd";
7007 sha1 = "29c5733148057bb4e1f75df35b7a9cb72e6a59dd";
7035 };
7008 };
7036 };
7009 };
7037 "uglify-js-3.4.9" = {
7010 "uglify-js-3.4.10" = {
7038 name = "uglify-js";
7011 name = "uglify-js";
7039 packageName = "uglify-js";
7012 packageName = "uglify-js";
7040 version = "3.4.9";
7013 version = "3.4.10";
7041 src = fetchurl {
7014 src = fetchurl {
7042 url = "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz";
7015 url = "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz";
7043 sha512 = "8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==";
7016 sha512 = "Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==";
7044 };
7017 };
7045 };
7018 };
7046 "uglify-to-browserify-1.0.2" = {
7019 "uglify-to-browserify-1.0.2" = {
@@ -7160,13 +7133,13 b' let'
7160 sha1 = "8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559";
7133 sha1 = "8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559";
7161 };
7134 };
7162 };
7135 };
7163 "upath-1.1.0" = {
7136 "upath-1.1.2" = {
7164 name = "upath";
7137 name = "upath";
7165 packageName = "upath";
7138 packageName = "upath";
7166 version = "1.1.0";
7139 version = "1.1.2";
7167 src = fetchurl {
7140 src = fetchurl {
7168 url = "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz";
7141 url = "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz";
7169 sha512 = "bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==";
7142 sha512 = "kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==";
7170 };
7143 };
7171 };
7144 };
7172 "upper-case-1.1.3" = {
7145 "upper-case-1.1.3" = {
@@ -7223,13 +7196,13 b' let'
7223 sha1 = "7afb1afe50805246489e3db7fe0ed379336ac0f9";
7196 sha1 = "7afb1afe50805246489e3db7fe0ed379336ac0f9";
7224 };
7197 };
7225 };
7198 };
7226 "util-0.10.4" = {
7199 "util-0.11.1" = {
7227 name = "util";
7200 name = "util";
7228 packageName = "util";
7201 packageName = "util";
7229 version = "0.10.4";
7202 version = "0.11.1";
7230 src = fetchurl {
7203 src = fetchurl {
7231 url = "https://registry.npmjs.org/util/-/util-0.10.4.tgz";
7204 url = "https://registry.npmjs.org/util/-/util-0.11.1.tgz";
7232 sha512 = "0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==";
7205 sha512 = "HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==";
7233 };
7206 };
7234 };
7207 };
7235 "util-deprecate-1.0.2" = {
7208 "util-deprecate-1.0.2" = {
@@ -7268,31 +7241,31 b' let'
7268 sha512 = "yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==";
7241 sha512 = "yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==";
7269 };
7242 };
7270 };
7243 };
7271 "v8-compile-cache-2.0.2" = {
7244 "v8-compile-cache-2.0.3" = {
7272 name = "v8-compile-cache";
7245 name = "v8-compile-cache";
7273 packageName = "v8-compile-cache";
7246 packageName = "v8-compile-cache";
7274 version = "2.0.2";
7247 version = "2.0.3";
7275 src = fetchurl {
7248 src = fetchurl {
7276 url = "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz";
7249 url = "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz";
7277 sha512 = "1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==";
7250 sha512 = "CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==";
7278 };
7251 };
7279 };
7252 };
7280 "v8flags-3.1.2" = {
7253 "v8flags-3.1.3" = {
7281 name = "v8flags";
7254 name = "v8flags";
7282 packageName = "v8flags";
7255 packageName = "v8flags";
7283 version = "3.1.2";
7256 version = "3.1.3";
7284 src = fetchurl {
7257 src = fetchurl {
7285 url = "https://registry.npmjs.org/v8flags/-/v8flags-3.1.2.tgz";
7258 url = "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz";
7286 sha512 = "MtivA7GF24yMPte9Rp/BWGCYQNaUj86zeYxV/x2RRJMKagImbbv3u8iJC57lNhWLPcGLJmHcHmFWkNsplbbLWw==";
7259 sha512 = "amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==";
7287 };
7260 };
7288 };
7261 };
7289 "vendors-1.0.2" = {
7262 "vendors-1.0.3" = {
7290 name = "vendors";
7263 name = "vendors";
7291 packageName = "vendors";
7264 packageName = "vendors";
7292 version = "1.0.2";
7265 version = "1.0.3";
7293 src = fetchurl {
7266 src = fetchurl {
7294 url = "https://registry.npmjs.org/vendors/-/vendors-1.0.2.tgz";
7267 url = "https://registry.npmjs.org/vendors/-/vendors-1.0.3.tgz";
7295 sha512 = "w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ==";
7268 sha512 = "fOi47nsJP5Wqefa43kyWSg80qF+Q3XA6MUkgi7Hp1HQaKDQW4cQrK2D0P7mmbFtsV1N89am55Yru/nyEwRubcw==";
7296 };
7269 };
7297 };
7270 };
7298 "verror-1.10.0" = {
7271 "verror-1.10.0" = {
@@ -7430,13 +7403,13 b' let'
7430 sha1 = "b79669bb42ecb409f83d583cad52ca17eaa1643f";
7403 sha1 = "b79669bb42ecb409f83d583cad52ca17eaa1643f";
7431 };
7404 };
7432 };
7405 };
7433 "worker-farm-1.6.0" = {
7406 "worker-farm-1.7.0" = {
7434 name = "worker-farm";
7407 name = "worker-farm";
7435 packageName = "worker-farm";
7408 packageName = "worker-farm";
7436 version = "1.6.0";
7409 version = "1.7.0";
7437 src = fetchurl {
7410 src = fetchurl {
7438 url = "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz";
7411 url = "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz";
7439 sha512 = "6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==";
7412 sha512 = "rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==";
7440 };
7413 };
7441 };
7414 };
7442 "wrap-ansi-2.1.0" = {
7415 "wrap-ansi-2.1.0" = {
@@ -7536,14 +7509,14 b' let'
7536 sources."@polymer/paper-behaviors-3.0.1"
7509 sources."@polymer/paper-behaviors-3.0.1"
7537 sources."@polymer/paper-button-3.0.1"
7510 sources."@polymer/paper-button-3.0.1"
7538 sources."@polymer/paper-ripple-3.0.1"
7511 sources."@polymer/paper-ripple-3.0.1"
7539 sources."@polymer/paper-spinner-3.0.1"
7512 sources."@polymer/paper-spinner-3.0.2"
7540 sources."@polymer/paper-styles-3.0.1"
7513 sources."@polymer/paper-styles-3.0.1"
7541 sources."@polymer/paper-toast-3.0.1"
7514 sources."@polymer/paper-toast-3.0.1"
7542 sources."@polymer/paper-toggle-button-3.0.1"
7515 sources."@polymer/paper-toggle-button-3.0.1"
7543 sources."@polymer/paper-tooltip-3.0.1"
7516 sources."@polymer/paper-tooltip-3.0.1"
7544 sources."@polymer/polymer-3.1.0"
7517 sources."@polymer/polymer-3.2.0"
7545 sources."@types/clone-0.1.30"
7518 sources."@types/clone-0.1.30"
7546 sources."@types/node-6.14.2"
7519 sources."@types/node-6.14.6"
7547 sources."@types/parse5-2.2.34"
7520 sources."@types/parse5-2.2.34"
7548 sources."@webassemblyjs/ast-1.7.10"
7521 sources."@webassemblyjs/ast-1.7.10"
7549 sources."@webassemblyjs/floating-point-hex-parser-1.7.10"
7522 sources."@webassemblyjs/floating-point-hex-parser-1.7.10"
@@ -7563,8 +7536,8 b' let'
7563 sources."@webassemblyjs/wasm-parser-1.7.10"
7536 sources."@webassemblyjs/wasm-parser-1.7.10"
7564 sources."@webassemblyjs/wast-parser-1.7.10"
7537 sources."@webassemblyjs/wast-parser-1.7.10"
7565 sources."@webassemblyjs/wast-printer-1.7.10"
7538 sources."@webassemblyjs/wast-printer-1.7.10"
7566 sources."@webcomponents/shadycss-1.7.1"
7539 sources."@webcomponents/shadycss-1.9.1"
7567 sources."@webcomponents/webcomponentsjs-2.2.1"
7540 sources."@webcomponents/webcomponentsjs-2.2.10"
7568 sources."@xtuc/ieee754-1.2.0"
7541 sources."@xtuc/ieee754-1.2.0"
7569 sources."@xtuc/long-4.2.1"
7542 sources."@xtuc/long-4.2.1"
7570 sources."abbrev-1.1.1"
7543 sources."abbrev-1.1.1"
@@ -7576,7 +7549,7 b' let'
7576 ];
7549 ];
7577 })
7550 })
7578 sources."ajv-4.11.8"
7551 sources."ajv-4.11.8"
7579 sources."ajv-keywords-3.2.0"
7552 sources."ajv-keywords-3.4.0"
7580 (sources."align-text-0.1.4" // {
7553 (sources."align-text-0.1.4" // {
7581 dependencies = [
7554 dependencies = [
7582 sources."kind-of-3.2.2"
7555 sources."kind-of-3.2.2"
@@ -7586,7 +7559,11 b' let'
7586 sources."amdefine-1.0.1"
7559 sources."amdefine-1.0.1"
7587 sources."ansi-regex-0.2.1"
7560 sources."ansi-regex-0.2.1"
7588 sources."ansi-styles-1.1.0"
7561 sources."ansi-styles-1.1.0"
7589 sources."anymatch-2.0.0"
7562 (sources."anymatch-2.0.0" // {
7563 dependencies = [
7564 sources."normalize-path-2.1.1"
7565 ];
7566 })
7590 sources."appenlight-client-git+https://git@github.com/AppEnlight/appenlight-client-js.git#0.5.1"
7567 sources."appenlight-client-git+https://git@github.com/AppEnlight/appenlight-client-js.git#0.5.1"
7591 sources."aproba-1.2.0"
7568 sources."aproba-1.2.0"
7592 (sources."argparse-0.1.16" // {
7569 (sources."argparse-0.1.16" // {
@@ -7602,11 +7579,10 b' let'
7602 sources."array-union-1.0.2"
7579 sources."array-union-1.0.2"
7603 sources."array-uniq-1.0.3"
7580 sources."array-uniq-1.0.3"
7604 sources."array-unique-0.3.2"
7581 sources."array-unique-0.3.2"
7605 sources."arrify-1.0.1"
7606 sources."asap-2.0.6"
7582 sources."asap-2.0.6"
7607 sources."asn1-0.2.4"
7583 sources."asn1-0.2.4"
7608 sources."asn1.js-4.10.1"
7584 sources."asn1.js-4.10.1"
7609 (sources."assert-1.4.1" // {
7585 (sources."assert-1.5.0" // {
7610 dependencies = [
7586 dependencies = [
7611 sources."inherits-2.0.1"
7587 sources."inherits-2.0.1"
7612 sources."util-0.10.3"
7588 sources."util-0.10.3"
@@ -7616,7 +7592,7 b' let'
7616 sources."assign-symbols-1.0.0"
7592 sources."assign-symbols-1.0.0"
7617 sources."ast-types-0.9.6"
7593 sources."ast-types-0.9.6"
7618 sources."async-0.1.22"
7594 sources."async-0.1.22"
7619 sources."async-each-1.0.1"
7595 sources."async-each-1.0.3"
7620 sources."asynckit-0.4.0"
7596 sources."asynckit-0.4.0"
7621 sources."atob-2.1.2"
7597 sources."atob-2.1.2"
7622 (sources."autoprefixer-6.7.7" // {
7598 (sources."autoprefixer-6.7.7" // {
@@ -7738,8 +7714,8 b' let'
7738 sources."base64-js-1.3.0"
7714 sources."base64-js-1.3.0"
7739 sources."bcrypt-pbkdf-1.0.2"
7715 sources."bcrypt-pbkdf-1.0.2"
7740 sources."big.js-5.2.2"
7716 sources."big.js-5.2.2"
7741 sources."binary-extensions-1.12.0"
7717 sources."binary-extensions-1.13.1"
7742 sources."bluebird-3.5.3"
7718 sources."bluebird-3.5.4"
7743 sources."bn.js-4.11.8"
7719 sources."bn.js-4.11.8"
7744 sources."boolbase-1.0.0"
7720 sources."boolbase-1.0.0"
7745 sources."boom-2.10.1"
7721 sources."boom-2.10.1"
@@ -7763,7 +7739,7 b' let'
7763 sources."builtin-status-codes-3.0.0"
7739 sources."builtin-status-codes-3.0.0"
7764 (sources."cacache-10.0.4" // {
7740 (sources."cacache-10.0.4" // {
7765 dependencies = [
7741 dependencies = [
7766 sources."glob-7.1.3"
7742 sources."glob-7.1.4"
7767 sources."graceful-fs-4.1.15"
7743 sources."graceful-fs-4.1.15"
7768 sources."lru-cache-4.1.5"
7744 sources."lru-cache-4.1.5"
7769 sources."minimatch-3.0.4"
7745 sources."minimatch-3.0.4"
@@ -7772,20 +7748,20 b' let'
7772 })
7748 })
7773 sources."cache-base-1.0.1"
7749 sources."cache-base-1.0.1"
7774 sources."camel-case-3.0.0"
7750 sources."camel-case-3.0.0"
7775 sources."camelcase-5.0.0"
7751 sources."camelcase-5.3.1"
7776 (sources."caniuse-api-1.6.1" // {
7752 (sources."caniuse-api-1.6.1" // {
7777 dependencies = [
7753 dependencies = [
7778 sources."browserslist-1.7.7"
7754 sources."browserslist-1.7.7"
7779 ];
7755 ];
7780 })
7756 })
7781 sources."caniuse-db-1.0.30000927"
7757 sources."caniuse-db-1.0.30000967"
7782 sources."caniuse-lite-1.0.30000927"
7758 sources."caniuse-lite-1.0.30000967"
7783 sources."caseless-0.12.0"
7759 sources."caseless-0.12.0"
7784 sources."center-align-0.1.3"
7760 sources."center-align-0.1.3"
7785 sources."chalk-0.5.1"
7761 sources."chalk-0.5.1"
7786 (sources."chokidar-2.0.4" // {
7762 (sources."chokidar-2.1.5" // {
7787 dependencies = [
7763 dependencies = [
7788 sources."is-glob-4.0.0"
7764 sources."is-glob-4.0.1"
7789 ];
7765 ];
7790 })
7766 })
7791 sources."chownr-1.1.1"
7767 sources."chownr-1.1.1"
@@ -7825,7 +7801,7 b' let'
7825 })
7801 })
7826 (sources."cli-1.0.1" // {
7802 (sources."cli-1.0.1" // {
7827 dependencies = [
7803 dependencies = [
7828 sources."glob-7.1.3"
7804 sources."glob-7.1.4"
7829 sources."minimatch-3.0.4"
7805 sources."minimatch-3.0.4"
7830 ];
7806 ];
7831 })
7807 })
@@ -7848,10 +7824,10 b' let'
7848 sources."color-string-0.3.0"
7824 sources."color-string-0.3.0"
7849 sources."colormin-1.1.2"
7825 sources."colormin-1.1.2"
7850 sources."colors-0.6.2"
7826 sources."colors-0.6.2"
7851 sources."combined-stream-1.0.7"
7827 sources."combined-stream-1.0.8"
7852 sources."commander-2.14.1"
7828 sources."commander-2.14.1"
7853 sources."commondir-1.0.1"
7829 sources."commondir-1.0.1"
7854 sources."component-emitter-1.2.1"
7830 sources."component-emitter-1.3.0"
7855 sources."concat-map-0.0.1"
7831 sources."concat-map-0.0.1"
7856 (sources."concat-stream-1.6.2" // {
7832 (sources."concat-stream-1.6.2" // {
7857 dependencies = [
7833 dependencies = [
@@ -7864,7 +7840,7 b' let'
7864 sources."convert-source-map-1.6.0"
7840 sources."convert-source-map-1.6.0"
7865 (sources."copy-concurrently-1.0.5" // {
7841 (sources."copy-concurrently-1.0.5" // {
7866 dependencies = [
7842 dependencies = [
7867 sources."glob-7.1.3"
7843 sources."glob-7.1.4"
7868 sources."minimatch-3.0.4"
7844 sources."minimatch-3.0.4"
7869 sources."rimraf-2.6.3"
7845 sources."rimraf-2.6.3"
7870 ];
7846 ];
@@ -7872,11 +7848,11 b' let'
7872 sources."copy-descriptor-0.1.1"
7848 sources."copy-descriptor-0.1.1"
7873 (sources."copy-webpack-plugin-4.6.0" // {
7849 (sources."copy-webpack-plugin-4.6.0" // {
7874 dependencies = [
7850 dependencies = [
7875 sources."is-glob-4.0.0"
7851 sources."is-glob-4.0.1"
7876 sources."minimatch-3.0.4"
7852 sources."minimatch-3.0.4"
7877 ];
7853 ];
7878 })
7854 })
7879 sources."core-js-2.6.1"
7855 sources."core-js-2.6.5"
7880 sources."core-util-is-1.0.2"
7856 sources."core-util-is-1.0.2"
7881 sources."create-ecdh-4.0.3"
7857 sources."create-ecdh-4.0.3"
7882 sources."create-hash-1.2.0"
7858 sources."create-hash-1.2.0"
@@ -7896,7 +7872,7 b' let'
7896 sources."regexpu-core-1.0.0"
7872 sources."regexpu-core-1.0.0"
7897 ];
7873 ];
7898 })
7874 })
7899 sources."css-what-2.1.2"
7875 sources."css-what-2.1.3"
7900 sources."cssesc-0.1.0"
7876 sources."cssesc-0.1.0"
7901 sources."cssnano-3.10.0"
7877 sources."cssnano-3.10.0"
7902 sources."csso-2.3.2"
7878 sources."csso-2.3.2"
@@ -7921,11 +7897,10 b' let'
7921 sources."detect-file-1.0.0"
7897 sources."detect-file-1.0.0"
7922 sources."detect-indent-4.0.0"
7898 sources."detect-indent-4.0.0"
7923 sources."diffie-hellman-5.0.3"
7899 sources."diffie-hellman-5.0.3"
7924 sources."dir-glob-2.0.0"
7900 sources."dir-glob-2.2.2"
7925 sources."dom-converter-0.2.0"
7901 sources."dom-converter-0.2.0"
7926 (sources."dom-serializer-0.1.0" // {
7902 (sources."dom-serializer-0.1.1" // {
7927 dependencies = [
7903 dependencies = [
7928 sources."domelementtype-1.1.3"
7929 sources."entities-1.1.2"
7904 sources."entities-1.1.2"
7930 ];
7905 ];
7931 })
7906 })
@@ -7939,14 +7914,15 b' let'
7939 sources."domelementtype-1.3.1"
7914 sources."domelementtype-1.3.1"
7940 sources."domhandler-2.3.0"
7915 sources."domhandler-2.3.0"
7941 sources."domutils-1.5.1"
7916 sources."domutils-1.5.1"
7942 (sources."duplexify-3.6.1" // {
7917 sources."dropzone-5.5.1"
7918 (sources."duplexify-3.7.1" // {
7943 dependencies = [
7919 dependencies = [
7944 sources."readable-stream-2.3.6"
7920 sources."readable-stream-2.3.6"
7945 sources."string_decoder-1.1.1"
7921 sources."string_decoder-1.1.1"
7946 ];
7922 ];
7947 })
7923 })
7948 sources."ecc-jsbn-0.1.2"
7924 sources."ecc-jsbn-0.1.2"
7949 sources."electron-to-chromium-1.3.98"
7925 sources."electron-to-chromium-1.3.133"
7950 sources."elliptic-6.4.1"
7926 sources."elliptic-6.4.1"
7951 sources."emojis-list-2.1.0"
7927 sources."emojis-list-2.1.0"
7952 sources."end-of-stream-1.4.1"
7928 sources."end-of-stream-1.4.1"
@@ -7961,14 +7937,14 b' let'
7961 sources."es-to-primitive-1.2.0"
7937 sources."es-to-primitive-1.2.0"
7962 sources."es6-templates-0.2.3"
7938 sources."es6-templates-0.2.3"
7963 sources."escape-string-regexp-1.0.5"
7939 sources."escape-string-regexp-1.0.5"
7964 sources."eslint-scope-4.0.0"
7940 sources."eslint-scope-4.0.3"
7965 sources."espree-3.5.4"
7941 sources."espree-3.5.4"
7966 sources."esprima-1.0.4"
7942 sources."esprima-1.0.4"
7967 sources."esrecurse-4.2.1"
7943 sources."esrecurse-4.2.1"
7968 sources."estraverse-4.2.0"
7944 sources."estraverse-4.2.0"
7969 sources."esutils-2.0.2"
7945 sources."esutils-2.0.2"
7970 sources."eventemitter2-0.4.14"
7946 sources."eventemitter2-0.4.14"
7971 sources."events-1.1.1"
7947 sources."events-3.0.0"
7972 sources."evp_bytestokey-1.0.3"
7948 sources."evp_bytestokey-1.0.3"
7973 sources."execa-1.0.0"
7949 sources."execa-1.0.0"
7974 sources."exit-0.1.2"
7950 sources."exit-0.1.2"
@@ -8025,10 +8001,10 b' let'
8025 sources."minimatch-0.3.0"
8001 sources."minimatch-0.3.0"
8026 ];
8002 ];
8027 })
8003 })
8028 sources."fined-1.1.1"
8004 sources."fined-1.2.0"
8029 sources."flagged-respawn-1.0.1"
8005 sources."flagged-respawn-1.0.1"
8030 sources."flatten-1.0.2"
8006 sources."flatten-1.0.2"
8031 (sources."flush-write-stream-1.0.3" // {
8007 (sources."flush-write-stream-1.1.1" // {
8032 dependencies = [
8008 dependencies = [
8033 sources."readable-stream-2.3.6"
8009 sources."readable-stream-2.3.6"
8034 sources."string_decoder-1.1.1"
8010 sources."string_decoder-1.1.1"
@@ -8051,7 +8027,7 b' let'
8051 ];
8027 ];
8052 })
8028 })
8053 sources."fs.realpath-1.0.0"
8029 sources."fs.realpath-1.0.0"
8054 sources."fsevents-1.2.4"
8030 sources."fsevents-1.2.9"
8055 sources."function-bind-1.1.1"
8031 sources."function-bind-1.1.1"
8056 sources."gaze-0.5.2"
8032 sources."gaze-0.5.2"
8057 sources."get-caller-file-1.0.3"
8033 sources."get-caller-file-1.0.3"
@@ -8083,7 +8059,7 b' let'
8083 sources."globals-9.18.0"
8059 sources."globals-9.18.0"
8084 (sources."globby-7.1.1" // {
8060 (sources."globby-7.1.1" // {
8085 dependencies = [
8061 dependencies = [
8086 sources."glob-7.1.3"
8062 sources."glob-7.1.4"
8087 sources."minimatch-3.0.4"
8063 sources."minimatch-3.0.4"
8088 ];
8064 ];
8089 })
8065 })
@@ -8115,12 +8091,18 b' let'
8115 sources."supports-color-2.0.0"
8091 sources."supports-color-2.0.0"
8116 ];
8092 ];
8117 })
8093 })
8118 sources."grunt-contrib-jshint-0.12.0"
8094 (sources."grunt-contrib-jshint-0.12.0" // {
8095 dependencies = [
8096 sources."jshint-2.9.7"
8097 sources."lodash-4.17.11"
8098 sources."minimatch-3.0.4"
8099 ];
8100 })
8119 (sources."grunt-contrib-less-1.4.1" // {
8101 (sources."grunt-contrib-less-1.4.1" // {
8120 dependencies = [
8102 dependencies = [
8121 sources."ansi-regex-2.1.1"
8103 sources."ansi-regex-2.1.1"
8122 sources."ansi-styles-2.2.1"
8104 sources."ansi-styles-2.2.1"
8123 sources."async-2.6.1"
8105 sources."async-2.6.2"
8124 sources."chalk-1.1.3"
8106 sources."chalk-1.1.3"
8125 sources."has-ansi-2.0.0"
8107 sources."has-ansi-2.0.0"
8126 sources."lodash-4.17.11"
8108 sources."lodash-4.17.11"
@@ -8172,7 +8154,7 b' let'
8172 sources."hmac-drbg-1.0.1"
8154 sources."hmac-drbg-1.0.1"
8173 sources."hoek-2.16.3"
8155 sources."hoek-2.16.3"
8174 sources."home-or-tmp-2.0.0"
8156 sources."home-or-tmp-2.0.0"
8175 sources."homedir-polyfill-1.0.1"
8157 sources."homedir-polyfill-1.0.3"
8176 sources."hooker-0.2.3"
8158 sources."hooker-0.2.3"
8177 sources."html-comment-regex-1.1.2"
8159 sources."html-comment-regex-1.1.2"
8178 sources."html-loader-0.4.5"
8160 sources."html-loader-0.4.5"
@@ -8203,7 +8185,7 b' let'
8203 sources."supports-color-5.5.0"
8185 sources."supports-color-5.5.0"
8204 ];
8186 ];
8205 })
8187 })
8206 sources."ieee754-1.1.12"
8188 sources."ieee754-1.1.13"
8207 sources."iferr-0.1.5"
8189 sources."iferr-0.1.5"
8208 sources."ignore-3.3.10"
8190 sources."ignore-3.3.10"
8209 sources."image-size-0.5.5"
8191 sources."image-size-0.5.5"
@@ -8211,9 +8193,9 b' let'
8211 dependencies = [
8193 dependencies = [
8212 sources."find-up-3.0.0"
8194 sources."find-up-3.0.0"
8213 sources."locate-path-3.0.0"
8195 sources."locate-path-3.0.0"
8214 sources."p-limit-2.1.0"
8196 sources."p-limit-2.2.0"
8215 sources."p-locate-3.0.0"
8197 sources."p-locate-3.0.0"
8216 sources."p-try-2.0.0"
8198 sources."p-try-2.2.0"
8217 sources."pkg-dir-3.0.0"
8199 sources."pkg-dir-3.0.0"
8218 ];
8200 ];
8219 })
8201 })
@@ -8261,12 +8243,12 b' let'
8261 sources."isobject-3.0.1"
8243 sources."isobject-3.0.1"
8262 sources."isstream-0.1.2"
8244 sources."isstream-0.1.2"
8263 sources."jquery-1.11.3"
8245 sources."jquery-1.11.3"
8264 sources."js-base64-2.5.0"
8246 sources."js-base64-2.5.1"
8265 sources."js-tokens-3.0.2"
8247 sources."js-tokens-3.0.2"
8266 sources."js-yaml-2.0.5"
8248 sources."js-yaml-2.0.5"
8267 sources."jsbn-0.1.1"
8249 sources."jsbn-0.1.1"
8268 sources."jsesc-1.3.0"
8250 sources."jsesc-1.3.0"
8269 (sources."jshint-2.9.7" // {
8251 (sources."jshint-2.10.2" // {
8270 dependencies = [
8252 dependencies = [
8271 sources."lodash-4.17.11"
8253 sources."lodash-4.17.11"
8272 sources."minimatch-3.0.4"
8254 sources."minimatch-3.0.4"
@@ -8297,12 +8279,11 b' let'
8297 sources."findup-sync-2.0.0"
8279 sources."findup-sync-2.0.0"
8298 ];
8280 ];
8299 })
8281 })
8300 sources."loader-runner-2.3.1"
8282 sources."loader-runner-2.4.0"
8301 sources."loader-utils-1.2.3"
8283 sources."loader-utils-1.2.3"
8302 sources."locate-path-2.0.0"
8284 sources."locate-path-2.0.0"
8303 sources."lodash-0.9.2"
8285 sources."lodash-0.9.2"
8304 sources."lodash.camelcase-4.3.0"
8286 sources."lodash.camelcase-4.3.0"
8305 sources."lodash.debounce-4.0.8"
8306 sources."lodash.isplainobject-4.0.6"
8287 sources."lodash.isplainobject-4.0.6"
8307 sources."lodash.memoize-4.1.2"
8288 sources."lodash.memoize-4.1.2"
8308 sources."lodash.uniq-4.5.0"
8289 sources."lodash.uniq-4.5.0"
@@ -8318,7 +8299,7 b' let'
8318 sources."mark.js-8.11.1"
8299 sources."mark.js-8.11.1"
8319 sources."math-expression-evaluator-1.2.17"
8300 sources."math-expression-evaluator-1.2.17"
8320 sources."md5.js-1.3.5"
8301 sources."md5.js-1.3.5"
8321 sources."mem-4.0.0"
8302 sources."mem-4.3.0"
8322 (sources."memory-fs-0.4.1" // {
8303 (sources."memory-fs-0.4.1" // {
8323 dependencies = [
8304 dependencies = [
8324 sources."readable-stream-2.3.6"
8305 sources."readable-stream-2.3.6"
@@ -8328,9 +8309,9 b' let'
8328 sources."micromatch-3.1.10"
8309 sources."micromatch-3.1.10"
8329 sources."miller-rabin-4.0.1"
8310 sources."miller-rabin-4.0.1"
8330 sources."mime-1.6.0"
8311 sources."mime-1.6.0"
8331 sources."mime-db-1.37.0"
8312 sources."mime-db-1.40.0"
8332 sources."mime-types-2.1.21"
8313 sources."mime-types-2.1.24"
8333 sources."mimic-fn-1.2.0"
8314 sources."mimic-fn-2.1.0"
8334 sources."minimalistic-assert-1.0.1"
8315 sources."minimalistic-assert-1.0.1"
8335 sources."minimalistic-crypto-utils-1.0.1"
8316 sources."minimalistic-crypto-utils-1.0.1"
8336 sources."minimatch-0.2.14"
8317 sources."minimatch-0.2.14"
@@ -8346,22 +8327,22 b' let'
8346 sources."minimist-0.0.8"
8327 sources."minimist-0.0.8"
8347 ];
8328 ];
8348 })
8329 })
8349 sources."moment-2.23.0"
8330 sources."moment-2.24.0"
8350 sources."mousetrap-1.6.2"
8331 sources."mousetrap-1.6.3"
8351 (sources."move-concurrently-1.0.1" // {
8332 (sources."move-concurrently-1.0.1" // {
8352 dependencies = [
8333 dependencies = [
8353 sources."glob-7.1.3"
8334 sources."glob-7.1.4"
8354 sources."minimatch-3.0.4"
8335 sources."minimatch-3.0.4"
8355 sources."rimraf-2.6.3"
8336 sources."rimraf-2.6.3"
8356 ];
8337 ];
8357 })
8338 })
8358 sources."ms-2.0.0"
8339 sources."ms-2.0.0"
8359 sources."nan-2.12.1"
8340 sources."nan-2.13.2"
8360 sources."nanomatch-1.2.13"
8341 sources."nanomatch-1.2.13"
8361 sources."neo-async-2.6.0"
8342 sources."neo-async-2.6.1"
8362 sources."nice-try-1.0.5"
8343 sources."nice-try-1.0.5"
8363 sources."no-case-2.3.2"
8344 sources."no-case-2.3.2"
8364 (sources."node-libs-browser-2.1.0" // {
8345 (sources."node-libs-browser-2.2.0" // {
8365 dependencies = [
8346 dependencies = [
8366 (sources."readable-stream-2.3.6" // {
8347 (sources."readable-stream-2.3.6" // {
8367 dependencies = [
8348 dependencies = [
@@ -8377,7 +8358,7 b' let'
8377 sources."nopt-2.0.0"
8358 sources."nopt-2.0.0"
8378 ];
8359 ];
8379 })
8360 })
8380 sources."normalize-path-2.1.1"
8361 sources."normalize-path-3.0.0"
8381 sources."normalize-range-0.1.2"
8362 sources."normalize-range-0.1.2"
8382 sources."normalize-url-1.9.1"
8363 sources."normalize-url-1.9.1"
8383 sources."npm-run-path-2.0.2"
8364 sources."npm-run-path-2.0.2"
@@ -8399,7 +8380,7 b' let'
8399 sources."kind-of-3.2.2"
8380 sources."kind-of-3.2.2"
8400 ];
8381 ];
8401 })
8382 })
8402 sources."object-keys-1.0.12"
8383 sources."object-keys-1.1.1"
8403 sources."object-visit-1.0.1"
8384 sources."object-visit-1.0.1"
8404 sources."object.defaults-1.1.0"
8385 sources."object.defaults-1.1.0"
8405 sources."object.getownpropertydescriptors-2.0.3"
8386 sources."object.getownpropertydescriptors-2.0.3"
@@ -8413,11 +8394,11 b' let'
8413 sources."osenv-0.1.5"
8394 sources."osenv-0.1.5"
8414 sources."p-defer-1.0.0"
8395 sources."p-defer-1.0.0"
8415 sources."p-finally-1.0.0"
8396 sources."p-finally-1.0.0"
8416 sources."p-is-promise-1.1.0"
8397 sources."p-is-promise-2.1.0"
8417 sources."p-limit-1.3.0"
8398 sources."p-limit-1.3.0"
8418 sources."p-locate-2.0.0"
8399 sources."p-locate-2.0.0"
8419 sources."p-try-1.0.0"
8400 sources."p-try-1.0.0"
8420 sources."pako-1.0.7"
8401 sources."pako-1.0.10"
8421 (sources."parallel-transform-1.1.0" // {
8402 (sources."parallel-transform-1.1.0" // {
8422 dependencies = [
8403 dependencies = [
8423 sources."readable-stream-2.3.6"
8404 sources."readable-stream-2.3.6"
@@ -8425,7 +8406,7 b' let'
8425 ];
8406 ];
8426 })
8407 })
8427 sources."param-case-2.1.1"
8408 sources."param-case-2.1.1"
8428 sources."parse-asn1-5.1.1"
8409 sources."parse-asn1-5.1.4"
8429 sources."parse-filepath-1.0.2"
8410 sources."parse-filepath-1.0.2"
8430 sources."parse-passwd-1.0.0"
8411 sources."parse-passwd-1.0.0"
8431 sources."parse5-3.0.3"
8412 sources."parse5-3.0.3"
@@ -8564,7 +8545,7 b' let'
8564 sources."query-string-4.3.4"
8545 sources."query-string-4.3.4"
8565 sources."querystring-0.2.0"
8546 sources."querystring-0.2.0"
8566 sources."querystring-es3-0.2.1"
8547 sources."querystring-es3-0.2.1"
8567 sources."randombytes-2.0.6"
8548 sources."randombytes-2.1.0"
8568 sources."randomfill-1.0.4"
8549 sources."randomfill-1.0.4"
8569 sources."raw-loader-1.0.0-beta.0"
8550 sources."raw-loader-1.0.0-beta.0"
8570 (sources."readable-stream-1.1.14" // {
8551 (sources."readable-stream-1.1.14" // {
@@ -8608,14 +8589,9 b' let'
8608 })
8589 })
8609 sources."relateurl-0.2.7"
8590 sources."relateurl-0.2.7"
8610 sources."remove-trailing-separator-1.1.0"
8591 sources."remove-trailing-separator-1.1.0"
8611 (sources."renderkid-2.0.2" // {
8592 (sources."renderkid-2.0.3" // {
8612 dependencies = [
8593 dependencies = [
8613 sources."ansi-regex-2.1.1"
8594 sources."ansi-regex-2.1.1"
8614 sources."domhandler-2.1.0"
8615 sources."domutils-1.1.6"
8616 sources."htmlparser2-3.3.0"
8617 sources."isarray-0.0.1"
8618 sources."readable-stream-1.0.34"
8619 sources."strip-ansi-3.0.1"
8595 sources."strip-ansi-3.0.1"
8620 ];
8596 ];
8621 })
8597 })
@@ -8625,7 +8601,7 b' let'
8625 sources."request-2.81.0"
8601 sources."request-2.81.0"
8626 sources."require-directory-2.1.1"
8602 sources."require-directory-2.1.1"
8627 sources."require-main-filename-1.0.1"
8603 sources."require-main-filename-1.0.1"
8628 sources."resolve-1.9.0"
8604 sources."resolve-1.10.1"
8629 sources."resolve-cwd-2.0.0"
8605 sources."resolve-cwd-2.0.0"
8630 sources."resolve-dir-1.0.1"
8606 sources."resolve-dir-1.0.1"
8631 sources."resolve-from-3.0.0"
8607 sources."resolve-from-3.0.0"
@@ -8641,12 +8617,12 b' let'
8641 sources."sax-1.2.4"
8617 sources."sax-1.2.4"
8642 (sources."schema-utils-0.4.7" // {
8618 (sources."schema-utils-0.4.7" // {
8643 dependencies = [
8619 dependencies = [
8644 sources."ajv-6.6.2"
8620 sources."ajv-6.10.0"
8645 ];
8621 ];
8646 })
8622 })
8647 sources."select-1.1.2"
8623 sources."select-1.1.2"
8648 sources."semver-5.6.0"
8624 sources."semver-5.7.0"
8649 sources."serialize-javascript-1.6.1"
8625 sources."serialize-javascript-1.7.0"
8650 sources."set-blocking-2.0.0"
8626 sources."set-blocking-2.0.0"
8651 (sources."set-value-2.0.0" // {
8627 (sources."set-value-2.0.0" // {
8652 dependencies = [
8628 dependencies = [
@@ -8698,7 +8674,7 b' let'
8698 sources."source-map-url-0.4.0"
8674 sources."source-map-url-0.4.0"
8699 sources."split-string-3.1.0"
8675 sources."split-string-3.1.0"
8700 sources."sprintf-js-1.0.3"
8676 sources."sprintf-js-1.0.3"
8701 (sources."sshpk-1.16.0" // {
8677 (sources."sshpk-1.16.1" // {
8702 dependencies = [
8678 dependencies = [
8703 sources."assert-plus-1.0.0"
8679 sources."assert-plus-1.0.0"
8704 ];
8680 ];
@@ -8722,7 +8698,7 b' let'
8722 ];
8698 ];
8723 })
8699 })
8724 sources."sticky-sidebar-3.3.1"
8700 sources."sticky-sidebar-3.3.1"
8725 (sources."stream-browserify-2.0.1" // {
8701 (sources."stream-browserify-2.0.2" // {
8726 dependencies = [
8702 dependencies = [
8727 sources."readable-stream-2.3.6"
8703 sources."readable-stream-2.3.6"
8728 sources."string_decoder-1.1.1"
8704 sources."string_decoder-1.1.1"
@@ -8759,7 +8735,7 b' let'
8759 sources."js-yaml-3.7.0"
8735 sources."js-yaml-3.7.0"
8760 ];
8736 ];
8761 })
8737 })
8762 sources."tapable-1.1.1"
8738 sources."tapable-1.1.3"
8763 sources."through-2.3.8"
8739 sources."through-2.3.8"
8764 (sources."through2-2.0.5" // {
8740 (sources."through2-2.0.5" // {
8765 dependencies = [
8741 dependencies = [
@@ -8768,7 +8744,7 b' let'
8768 ];
8744 ];
8769 })
8745 })
8770 sources."timers-browserify-2.0.10"
8746 sources."timers-browserify-2.0.10"
8771 sources."tiny-emitter-2.0.2"
8747 sources."tiny-emitter-2.1.0"
8772 (sources."tiny-lr-fork-0.0.5" // {
8748 (sources."tiny-lr-fork-0.0.5" // {
8773 dependencies = [
8749 dependencies = [
8774 sources."debug-0.7.4"
8750 sources."debug-0.7.4"
@@ -8808,9 +8784,9 b' let'
8808 sources."source-map-0.6.1"
8784 sources."source-map-0.6.1"
8809 ];
8785 ];
8810 })
8786 })
8811 (sources."uglify-js-3.4.9" // {
8787 (sources."uglify-js-3.4.10" // {
8812 dependencies = [
8788 dependencies = [
8813 sources."commander-2.17.1"
8789 sources."commander-2.19.0"
8814 sources."source-map-0.6.1"
8790 sources."source-map-0.6.1"
8815 ];
8791 ];
8816 })
8792 })
@@ -8843,7 +8819,7 b' let'
8843 sources."has-values-0.1.4"
8819 sources."has-values-0.1.4"
8844 ];
8820 ];
8845 })
8821 })
8846 sources."upath-1.1.0"
8822 sources."upath-1.1.2"
8847 sources."upper-case-1.1.3"
8823 sources."upper-case-1.1.3"
8848 (sources."uri-js-4.2.2" // {
8824 (sources."uri-js-4.2.2" // {
8849 dependencies = [
8825 dependencies = [
@@ -8857,14 +8833,14 b' let'
8857 ];
8833 ];
8858 })
8834 })
8859 sources."use-3.1.1"
8835 sources."use-3.1.1"
8860 sources."util-0.10.4"
8836 sources."util-0.11.1"
8861 sources."util-deprecate-1.0.2"
8837 sources."util-deprecate-1.0.2"
8862 sources."util.promisify-1.0.0"
8838 sources."util.promisify-1.0.0"
8863 sources."utila-0.4.0"
8839 sources."utila-0.4.0"
8864 sources."uuid-3.3.2"
8840 sources."uuid-3.3.2"
8865 sources."v8-compile-cache-2.0.2"
8841 sources."v8-compile-cache-2.0.3"
8866 sources."v8flags-3.1.2"
8842 sources."v8flags-3.1.3"
8867 sources."vendors-1.0.2"
8843 sources."vendors-1.0.3"
8868 (sources."verror-1.10.0" // {
8844 (sources."verror-1.10.0" // {
8869 dependencies = [
8845 dependencies = [
8870 sources."assert-plus-1.0.0"
8846 sources."assert-plus-1.0.0"
@@ -8879,7 +8855,7 b' let'
8879 sources."waypoints-4.0.1"
8855 sources."waypoints-4.0.1"
8880 (sources."webpack-4.23.1" // {
8856 (sources."webpack-4.23.1" // {
8881 dependencies = [
8857 dependencies = [
8882 sources."ajv-6.6.2"
8858 sources."ajv-6.10.0"
8883 ];
8859 ];
8884 })
8860 })
8885 (sources."webpack-cli-3.1.2" // {
8861 (sources."webpack-cli-3.1.2" // {
@@ -8919,7 +8895,7 b' let'
8919 sources."which-module-2.0.0"
8895 sources."which-module-2.0.0"
8920 sources."window-size-0.1.0"
8896 sources."window-size-0.1.0"
8921 sources."wordwrap-0.0.2"
8897 sources."wordwrap-0.0.2"
8922 sources."worker-farm-1.6.0"
8898 sources."worker-farm-1.7.0"
8923 (sources."wrap-ansi-2.1.0" // {
8899 (sources."wrap-ansi-2.1.0" // {
8924 dependencies = [
8900 dependencies = [
8925 sources."ansi-regex-2.1.1"
8901 sources."ansi-regex-2.1.1"
@@ -8935,9 +8911,9 b' let'
8935 dependencies = [
8911 dependencies = [
8936 sources."find-up-3.0.0"
8912 sources."find-up-3.0.0"
8937 sources."locate-path-3.0.0"
8913 sources."locate-path-3.0.0"
8938 sources."p-limit-2.1.0"
8914 sources."p-limit-2.2.0"
8939 sources."p-locate-3.0.0"
8915 sources."p-locate-3.0.0"
8940 sources."p-try-2.0.0"
8916 sources."p-try-2.2.0"
8941 ];
8917 ];
8942 })
8918 })
8943 sources."yargs-parser-11.1.1"
8919 sources."yargs-parser-11.1.1"
@@ -35,6 +35,18 b' self: super: {'
35 ];
35 ];
36 });
36 });
37
37
38 "cffi" = super."cffi".override (attrs: {
39 buildInputs = [
40 pkgs.libffi
41 ];
42 });
43
44 "cryptography" = super."cryptography".override (attrs: {
45 buildInputs = [
46 pkgs.openssl
47 ];
48 });
49
38 "gevent" = super."gevent".override (attrs: {
50 "gevent" = super."gevent".override (attrs: {
39 propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
51 propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
40 # NOTE: (marcink) odd requirements from gevent aren't set properly,
52 # NOTE: (marcink) odd requirements from gevent aren't set properly,
@@ -152,12 +164,6 b' self: super: {'
152 };
164 };
153 });
165 });
154
166
155 "pytest-runner" = super."pytest-runner".override (attrs: {
156 propagatedBuildInputs = [
157 self."setuptools-scm"
158 ];
159 });
160
161 "python-ldap" = super."python-ldap".override (attrs: {
167 "python-ldap" = super."python-ldap".override (attrs: {
162 propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
168 propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
163 pkgs.openldap
169 pkgs.openldap
@@ -5,7 +5,7 b''
5
5
6 self: super: {
6 self: super: {
7 "alembic" = super.buildPythonPackage {
7 "alembic" = super.buildPythonPackage {
8 name = "alembic-1.0.5";
8 name = "alembic-1.0.10";
9 doCheck = false;
9 doCheck = false;
10 propagatedBuildInputs = [
10 propagatedBuildInputs = [
11 self."sqlalchemy"
11 self."sqlalchemy"
@@ -14,8 +14,8 b' self: super: {'
14 self."python-dateutil"
14 self."python-dateutil"
15 ];
15 ];
16 src = fetchurl {
16 src = fetchurl {
17 url = "https://files.pythonhosted.org/packages/1c/65/b8e4f5b2f345bb13b5e0a3fddd892b0b3f0e8ad4880e954fdc6a50d00d84/alembic-1.0.5.tar.gz";
17 url = "https://files.pythonhosted.org/packages/6e/8b/fa3bd058cccd5e9177fea4efa26bfb769228fdd3178436ad5e05830ef6ef/alembic-1.0.10.tar.gz";
18 sha256 = "0rpjqp2iq6p49x1nli18ivak1izz547nnjxi110mzrgc1v7dxzz9";
18 sha256 = "1dwl0264r6ri2jyrjr68am04x538ab26xwy4crqjnnhm4alwm3c2";
19 };
19 };
20 meta = {
20 meta = {
21 license = [ pkgs.lib.licenses.mit ];
21 license = [ pkgs.lib.licenses.mit ];
@@ -51,6 +51,17 b' self: super: {'
51 license = [ pkgs.lib.licenses.bsdOriginal ];
51 license = [ pkgs.lib.licenses.bsdOriginal ];
52 };
52 };
53 };
53 };
54 "asn1crypto" = super.buildPythonPackage {
55 name = "asn1crypto-0.24.0";
56 doCheck = false;
57 src = fetchurl {
58 url = "https://files.pythonhosted.org/packages/fc/f1/8db7daa71f414ddabfa056c4ef792e1461ff655c2ae2928a2b675bfed6b4/asn1crypto-0.24.0.tar.gz";
59 sha256 = "0jaf8rf9dx1lf23xfv2cdd5h52f1qr3w8k63985bc35g3d220p4x";
60 };
61 meta = {
62 license = [ pkgs.lib.licenses.mit ];
63 };
64 };
54 "atomicwrites" = super.buildPythonPackage {
65 "atomicwrites" = super.buildPythonPackage {
55 name = "atomicwrites-1.2.1";
66 name = "atomicwrites-1.2.1";
56 doCheck = false;
67 doCheck = false;
@@ -77,8 +88,8 b' self: super: {'
77 name = "authomatic-0.1.0.post1";
88 name = "authomatic-0.1.0.post1";
78 doCheck = false;
89 doCheck = false;
79 src = fetchurl {
90 src = fetchurl {
80 url = "https://code.rhodecode.com/upstream/authomatic/archive/90a9ce60cc405ae8a2bf5c3713acd5d78579a04e.tar.gz?md5=3c68720a1322b25254009518d1ff6801";
91 url = "https://code.rhodecode.com/upstream/authomatic/artifacts/download/0-4fe9c041-a567-4f84-be4c-7efa2a606d3c.tar.gz?md5=f6bdc3c769688212db68233e8d2b0383";
81 sha256 = "1cgk0a86sbsjbri06gf5z5l4npwkjdxw6fdnwl4vvfmxs2sx9yxw";
92 sha256 = "0pc716mva0ym6xd8jwzjbjp8dqxy9069wwwv2aqwb8lyhl4757ab";
82 };
93 };
83 meta = {
94 meta = {
84 license = [ pkgs.lib.licenses.mit ];
95 license = [ pkgs.lib.licenses.mit ];
@@ -146,15 +157,15 b' self: super: {'
146 };
157 };
147 };
158 };
148 "bleach" = super.buildPythonPackage {
159 "bleach" = super.buildPythonPackage {
149 name = "bleach-3.0.2";
160 name = "bleach-3.1.0";
150 doCheck = false;
161 doCheck = false;
151 propagatedBuildInputs = [
162 propagatedBuildInputs = [
152 self."six"
163 self."six"
153 self."webencodings"
164 self."webencodings"
154 ];
165 ];
155 src = fetchurl {
166 src = fetchurl {
156 url = "https://files.pythonhosted.org/packages/ae/31/680afc7d44040004296a2d8f0584983c2f2386448cd9d0964197e6c1160e/bleach-3.0.2.tar.gz";
167 url = "https://files.pythonhosted.org/packages/78/5a/0df03e8735cd9c75167528299c738702437589b9c71a849489d00ffa82e8/bleach-3.1.0.tar.gz";
157 sha256 = "06474zg7f73hv8h1xw2wcsmvn2ygj73zxgxxqg8zcx8ap1srdls8";
168 sha256 = "1yhrgrhkln8bd6gn3imj69g1h4xqah9gaz9q26crqr6gmmvpzprz";
158 };
169 };
159 meta = {
170 meta = {
160 license = [ pkgs.lib.licenses.asl20 ];
171 license = [ pkgs.lib.licenses.asl20 ];
@@ -187,6 +198,20 b' self: super: {'
187 license = [ pkgs.lib.licenses.bsdOriginal ];
198 license = [ pkgs.lib.licenses.bsdOriginal ];
188 };
199 };
189 };
200 };
201 "cffi" = super.buildPythonPackage {
202 name = "cffi-1.12.2";
203 doCheck = false;
204 propagatedBuildInputs = [
205 self."pycparser"
206 ];
207 src = fetchurl {
208 url = "https://files.pythonhosted.org/packages/64/7c/27367b38e6cc3e1f49f193deb761fe75cda9f95da37b67b422e62281fcac/cffi-1.12.2.tar.gz";
209 sha256 = "19qfks2djya8vix95bmg3xzipjb8w9b8mbj4j5k2hqkc8j58f4z1";
210 };
211 meta = {
212 license = [ pkgs.lib.licenses.mit ];
213 };
214 };
190 "chameleon" = super.buildPythonPackage {
215 "chameleon" = super.buildPythonPackage {
191 name = "chameleon-2.24";
216 name = "chameleon-2.24";
192 doCheck = false;
217 doCheck = false;
@@ -230,7 +255,7 b' self: super: {'
230 };
255 };
231 };
256 };
232 "colander" = super.buildPythonPackage {
257 "colander" = super.buildPythonPackage {
233 name = "colander-1.5.1";
258 name = "colander-1.7.0";
234 doCheck = false;
259 doCheck = false;
235 propagatedBuildInputs = [
260 propagatedBuildInputs = [
236 self."translationstring"
261 self."translationstring"
@@ -238,8 +263,8 b' self: super: {'
238 self."enum34"
263 self."enum34"
239 ];
264 ];
240 src = fetchurl {
265 src = fetchurl {
241 url = "https://files.pythonhosted.org/packages/ec/d1/fcca811a0a692c69d27e36b4d11a73acb98b4bab48323442642b6fd4386d/colander-1.5.1.tar.gz";
266 url = "https://files.pythonhosted.org/packages/db/e4/74ab06f54211917b41865cafc987ce511e35503de48da9bfe9358a1bdc3e/colander-1.7.0.tar.gz";
242 sha256 = "18ah4cwwxnpm6qxi6x9ipy51dal4spd343h44s5wd01cnhgrwsyq";
267 sha256 = "1wl1bqab307lbbcjx81i28s3yl6dlm4rf15fxawkjb6j48x1cn6p";
243 };
268 };
244 meta = {
269 meta = {
245 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
270 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
@@ -252,19 +277,19 b' self: super: {'
252 self."six"
277 self."six"
253 ];
278 ];
254 src = fetchurl {
279 src = fetchurl {
255 url = "https://code.rhodecode.com/upstream/configobj/archive/a11ff0a0bd4fbda9e3a91267e720f88329efb4a6.tar.gz?md5=9916c524ea11a6c418217af6b28d4b3c";
280 url = "https://code.rhodecode.com/upstream/configobj/artifacts/download/0-012de99a-b1e1-4f64-a5c0-07a98a41b324.tar.gz?md5=6a513f51fe04b2c18cf84c1395a7c626";
256 sha256 = "1hhcxirwvg58grlfr177b3awhbq8hlx1l3lh69ifl1ki7lfd1s1x";
281 sha256 = "0kqfrdfr14mw8yd8qwq14dv2xghpkjmd3yjsy8dfcbvpcc17xnxp";
257 };
282 };
258 meta = {
283 meta = {
259 license = [ pkgs.lib.licenses.bsdOriginal ];
284 license = [ pkgs.lib.licenses.bsdOriginal ];
260 };
285 };
261 };
286 };
262 "configparser" = super.buildPythonPackage {
287 "configparser" = super.buildPythonPackage {
263 name = "configparser-3.7.1";
288 name = "configparser-3.7.4";
264 doCheck = false;
289 doCheck = false;
265 src = fetchurl {
290 src = fetchurl {
266 url = "https://files.pythonhosted.org/packages/b6/a6/eceea7c5a5dbcf56815bed411c38cabd8a879386be10717b160e7362b5a2/configparser-3.7.1.tar.gz";
291 url = "https://files.pythonhosted.org/packages/e2/1c/83fd53748d8245cb9a3399f705c251d3fc0ce7df04450aac1cfc49dd6a0f/configparser-3.7.4.tar.gz";
267 sha256 = "0cnz213il9lhgda6x70fw7mfqr8da43s3wm343lwzhqx94mgmmav";
292 sha256 = "0xac32886ihs2xg7w1gppcq2sgin5qsm8lqwijs5xifq9w0x0q6s";
268 };
293 };
269 meta = {
294 meta = {
270 license = [ pkgs.lib.licenses.mit ];
295 license = [ pkgs.lib.licenses.mit ];
@@ -285,16 +310,34 b' self: super: {'
285 };
310 };
286 };
311 };
287 "coverage" = super.buildPythonPackage {
312 "coverage" = super.buildPythonPackage {
288 name = "coverage-4.5.1";
313 name = "coverage-4.5.3";
289 doCheck = false;
314 doCheck = false;
290 src = fetchurl {
315 src = fetchurl {
291 url = "https://files.pythonhosted.org/packages/35/fe/e7df7289d717426093c68d156e0fd9117c8f4872b6588e8a8928a0f68424/coverage-4.5.1.tar.gz";
316 url = "https://files.pythonhosted.org/packages/82/70/2280b5b29a0352519bb95ab0ef1ea942d40466ca71c53a2085bdeff7b0eb/coverage-4.5.3.tar.gz";
292 sha256 = "1wbrzpxka3xd4nmmkc6q0ir343d91kymwsm8pbmwa0d2a7q4ir2n";
317 sha256 = "02f6m073qdispn96rc616hg0rnmw1pgqzw3bgxwiwza4zf9hirlx";
293 };
318 };
294 meta = {
319 meta = {
295 license = [ pkgs.lib.licenses.asl20 ];
320 license = [ pkgs.lib.licenses.asl20 ];
296 };
321 };
297 };
322 };
323 "cryptography" = super.buildPythonPackage {
324 name = "cryptography-2.6.1";
325 doCheck = false;
326 propagatedBuildInputs = [
327 self."asn1crypto"
328 self."six"
329 self."cffi"
330 self."enum34"
331 self."ipaddress"
332 ];
333 src = fetchurl {
334 url = "https://files.pythonhosted.org/packages/07/ca/bc827c5e55918ad223d59d299fff92f3563476c3b00d0a9157d9c0217449/cryptography-2.6.1.tar.gz";
335 sha256 = "19iwz5avym5zl6jrrrkym1rdaa9h61j20ph4cswsqgv8xg5j3j16";
336 };
337 meta = {
338 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "BSD or Apache License, Version 2.0"; } pkgs.lib.licenses.asl20 ];
339 };
340 };
298 "cssselect" = super.buildPythonPackage {
341 "cssselect" = super.buildPythonPackage {
299 name = "cssselect-1.0.3";
342 name = "cssselect-1.0.3";
300 doCheck = false;
343 doCheck = false;
@@ -337,11 +380,11 b' self: super: {'
337 };
380 };
338 };
381 };
339 "defusedxml" = super.buildPythonPackage {
382 "defusedxml" = super.buildPythonPackage {
340 name = "defusedxml-0.5.0";
383 name = "defusedxml-0.6.0";
341 doCheck = false;
384 doCheck = false;
342 src = fetchurl {
385 src = fetchurl {
343 url = "https://files.pythonhosted.org/packages/74/ba/4ba4e89e21b5a2e267d80736ea674609a0a33cc4435a6d748ef04f1f9374/defusedxml-0.5.0.tar.gz";
386 url = "https://files.pythonhosted.org/packages/a4/5f/f8aa58ca0cf01cbcee728abc9d88bfeb74e95e6cb4334cfd5bed5673ea77/defusedxml-0.6.0.tar.gz";
344 sha256 = "1x54n0h8hl92vvwyymx883fbqpqjwn2mc8fb383bcg3z9zwz5mr4";
387 sha256 = "1xbp8fivl3wlbyg2jrvs4lalaqv1xp9a9f29p75wdx2s2d6h717n";
345 };
388 };
346 meta = {
389 meta = {
347 license = [ pkgs.lib.licenses.psfl ];
390 license = [ pkgs.lib.licenses.psfl ];
@@ -399,11 +442,11 b' self: super: {'
399 };
442 };
400 };
443 };
401 "ecdsa" = super.buildPythonPackage {
444 "ecdsa" = super.buildPythonPackage {
402 name = "ecdsa-0.13";
445 name = "ecdsa-0.13.2";
403 doCheck = false;
446 doCheck = false;
404 src = fetchurl {
447 src = fetchurl {
405 url = "https://files.pythonhosted.org/packages/f9/e5/99ebb176e47f150ac115ffeda5fedb6a3dbb3c00c74a59fd84ddf12f5857/ecdsa-0.13.tar.gz";
448 url = "https://files.pythonhosted.org/packages/51/76/139bf6e9b7b6684d5891212cdbd9e0739f2bfc03f380a1a6ffa700f392ac/ecdsa-0.13.2.tar.gz";
406 sha256 = "1yj31j0asmrx4an9xvsaj2icdmzy6pw0glfpqrrkrphwdpi1xkv4";
449 sha256 = "116qaq7bh4lcynzi613960jhsnn19v0kmsqwahiwjfj14gx4y0sw";
407 };
450 };
408 meta = {
451 meta = {
409 license = [ pkgs.lib.licenses.mit ];
452 license = [ pkgs.lib.licenses.mit ];
@@ -491,8 +534,8 b' self: super: {'
491 self."configparser"
534 self."configparser"
492 ];
535 ];
493 src = fetchurl {
536 src = fetchurl {
494 url = "https://code.rhodecode.com/upstream/entrypoints/archive/96e6d645684e1af3d7df5b5272f3fe85a546b233.tar.gz?md5=7db37771aea9ac9fefe093e5d6987313";
537 url = "https://code.rhodecode.com/upstream/entrypoints/artifacts/download/0-8e9ee9e4-c4db-409c-b07e-81568fd1832d.tar.gz?md5=3a027b8ff1d257b91fe257de6c43357d";
495 sha256 = "0bihrdp8ahsys437kxdhk52gz6kib8rxjv71i93wkw7594fcaxll";
538 sha256 = "0qih72n2myclanplqipqxpgpj9d2yhff1pz5d02zq1cfqyd173w5";
496 };
539 };
497 meta = {
540 meta = {
498 license = [ pkgs.lib.licenses.mit ];
541 license = [ pkgs.lib.licenses.mit ];
@@ -623,11 +666,11 b' self: super: {'
623 };
666 };
624 };
667 };
625 "hupper" = super.buildPythonPackage {
668 "hupper" = super.buildPythonPackage {
626 name = "hupper-1.4.2";
669 name = "hupper-1.6.1";
627 doCheck = false;
670 doCheck = false;
628 src = fetchurl {
671 src = fetchurl {
629 url = "https://files.pythonhosted.org/packages/f1/75/1915dc7650b4867fa3049256e24ca8eddb5989998fcec788cf52b9812dfc/hupper-1.4.2.tar.gz";
672 url = "https://files.pythonhosted.org/packages/85/d9/e005d357b11249c5d70ddf5b7adab2e4c0da4e8b0531ff146917a04fe6c0/hupper-1.6.1.tar.gz";
630 sha256 = "16vb9fkiaakdpcp6pn56h3w0dwvm67bxq2k2dv4i382qhqwphdzb";
673 sha256 = "0d3cvkc8ssgwk54wvhbifj56ry97qi10pfzwfk8vwzzcikbfp3zy";
631 };
674 };
632 meta = {
675 meta = {
633 license = [ pkgs.lib.licenses.mit ];
676 license = [ pkgs.lib.licenses.mit ];
@@ -671,15 +714,15 b' self: super: {'
671 };
714 };
672 };
715 };
673 "ipdb" = super.buildPythonPackage {
716 "ipdb" = super.buildPythonPackage {
674 name = "ipdb-0.11";
717 name = "ipdb-0.12";
675 doCheck = false;
718 doCheck = false;
676 propagatedBuildInputs = [
719 propagatedBuildInputs = [
677 self."setuptools"
720 self."setuptools"
678 self."ipython"
721 self."ipython"
679 ];
722 ];
680 src = fetchurl {
723 src = fetchurl {
681 url = "https://files.pythonhosted.org/packages/80/fe/4564de08f174f3846364b3add8426d14cebee228f741c27e702b2877e85b/ipdb-0.11.tar.gz";
724 url = "https://files.pythonhosted.org/packages/6d/43/c3c2e866a8803e196d6209595020a4a6db1a3c5d07c01455669497ae23d0/ipdb-0.12.tar.gz";
682 sha256 = "02m0l8wrhhd3z7dg3czn5ys1g5pxib516hpshdzp7rxzsxgcd0bh";
725 sha256 = "1khr2n7xfy8hg65kj1bsrjq9g7656pp0ybfa8abpbzpdawji3qnw";
683 };
726 };
684 meta = {
727 meta = {
685 license = [ pkgs.lib.licenses.bsdOriginal ];
728 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -802,14 +845,14 b' self: super: {'
802 };
845 };
803 };
846 };
804 "jupyter-core" = super.buildPythonPackage {
847 "jupyter-core" = super.buildPythonPackage {
805 name = "jupyter-core-4.4.0";
848 name = "jupyter-core-4.5.0";
806 doCheck = false;
849 doCheck = false;
807 propagatedBuildInputs = [
850 propagatedBuildInputs = [
808 self."traitlets"
851 self."traitlets"
809 ];
852 ];
810 src = fetchurl {
853 src = fetchurl {
811 url = "https://files.pythonhosted.org/packages/b6/2d/2804f4de3a95583f65e5dcb4d7c8c7183124882323758996e867f47e72af/jupyter_core-4.4.0.tar.gz";
854 url = "https://files.pythonhosted.org/packages/4a/de/ff4ca734656d17ebe0450807b59d728f45277e2e7f4b82bc9aae6cb82961/jupyter_core-4.5.0.tar.gz";
812 sha256 = "1dy083rarba8prn9f9srxq3c7n7vyql02ycrqq306c40lr57aw5s";
855 sha256 = "1xr4pbghwk5hayn5wwnhb7z95380r45p79gf5if5pi1akwg7qvic";
813 };
856 };
814 meta = {
857 meta = {
815 license = [ pkgs.lib.licenses.bsdOriginal ];
858 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -1008,14 +1051,14 b' self: super: {'
1008 };
1051 };
1009 };
1052 };
1010 "paste" = super.buildPythonPackage {
1053 "paste" = super.buildPythonPackage {
1011 name = "paste-3.0.5";
1054 name = "paste-3.0.8";
1012 doCheck = false;
1055 doCheck = false;
1013 propagatedBuildInputs = [
1056 propagatedBuildInputs = [
1014 self."six"
1057 self."six"
1015 ];
1058 ];
1016 src = fetchurl {
1059 src = fetchurl {
1017 url = "https://files.pythonhosted.org/packages/d4/41/91bde422400786b1b06357c1e6e3a5379f54dc3002aeb337cb767233304e/Paste-3.0.5.tar.gz";
1060 url = "https://files.pythonhosted.org/packages/66/65/e3acf1663438483c1f6ced0b6c6f3b90da9f0faacb0a6e2aa0f3f9f4b235/Paste-3.0.8.tar.gz";
1018 sha256 = "1a6i8fh1fg8r4x800fvy9r82m15clwjim6yf2g9r4dff0y40dchv";
1061 sha256 = "05w1sh6ky4d7pmdb8nv82n13w22jcn3qsagg5ih3hjmbws9kkwf4";
1019 };
1062 };
1020 meta = {
1063 meta = {
1021 license = [ pkgs.lib.licenses.mit ];
1064 license = [ pkgs.lib.licenses.mit ];
@@ -1033,7 +1076,7 b' self: super: {'
1033 };
1076 };
1034 };
1077 };
1035 "pastescript" = super.buildPythonPackage {
1078 "pastescript" = super.buildPythonPackage {
1036 name = "pastescript-3.0.0";
1079 name = "pastescript-3.1.0";
1037 doCheck = false;
1080 doCheck = false;
1038 propagatedBuildInputs = [
1081 propagatedBuildInputs = [
1039 self."paste"
1082 self."paste"
@@ -1041,23 +1084,23 b' self: super: {'
1041 self."six"
1084 self."six"
1042 ];
1085 ];
1043 src = fetchurl {
1086 src = fetchurl {
1044 url = "https://files.pythonhosted.org/packages/08/2a/3797377a884ab9a064ad4d564ed612e54d26d7997caa8229c9c9df4eac31/PasteScript-3.0.0.tar.gz";
1087 url = "https://files.pythonhosted.org/packages/9e/1d/14db1c283eb21a5d36b6ba1114c13b709629711e64acab653d9994fe346f/PasteScript-3.1.0.tar.gz";
1045 sha256 = "1hvmyz1sbn7ws1syw567ph7km9fi0wi75r3vlyzx6sk0z26xkm6r";
1088 sha256 = "02qcxjjr32ks7a6d4f533wl34ysc7yhwlrfcyqwqbzr52250v4fs";
1046 };
1089 };
1047 meta = {
1090 meta = {
1048 license = [ pkgs.lib.licenses.mit ];
1091 license = [ pkgs.lib.licenses.mit ];
1049 };
1092 };
1050 };
1093 };
1051 "pathlib2" = super.buildPythonPackage {
1094 "pathlib2" = super.buildPythonPackage {
1052 name = "pathlib2-2.3.3";
1095 name = "pathlib2-2.3.4";
1053 doCheck = false;
1096 doCheck = false;
1054 propagatedBuildInputs = [
1097 propagatedBuildInputs = [
1055 self."six"
1098 self."six"
1056 self."scandir"
1099 self."scandir"
1057 ];
1100 ];
1058 src = fetchurl {
1101 src = fetchurl {
1059 url = "https://files.pythonhosted.org/packages/bf/d7/a2568f4596b75d2c6e2b4094a7e64f620decc7887f69a1f2811931ea15b9/pathlib2-2.3.3.tar.gz";
1102 url = "https://files.pythonhosted.org/packages/b5/f4/9c7cc726ece2498b6c8b62d3262aa43f59039b953fe23c9964ac5e18d40b/pathlib2-2.3.4.tar.gz";
1060 sha256 = "0hpp92vqqgcd8h92msm9slv161b1q160igjwnkf2ag6cx0c96695";
1103 sha256 = "1y0f9rkm1924zrc5dn4bwxlhgdkbml82lkcc28l5rgmr7d918q24";
1061 };
1104 };
1062 meta = {
1105 meta = {
1063 license = [ pkgs.lib.licenses.mit ];
1106 license = [ pkgs.lib.licenses.mit ];
@@ -1075,14 +1118,14 b' self: super: {'
1075 };
1118 };
1076 };
1119 };
1077 "pexpect" = super.buildPythonPackage {
1120 "pexpect" = super.buildPythonPackage {
1078 name = "pexpect-4.6.0";
1121 name = "pexpect-4.7.0";
1079 doCheck = false;
1122 doCheck = false;
1080 propagatedBuildInputs = [
1123 propagatedBuildInputs = [
1081 self."ptyprocess"
1124 self."ptyprocess"
1082 ];
1125 ];
1083 src = fetchurl {
1126 src = fetchurl {
1084 url = "https://files.pythonhosted.org/packages/89/43/07d07654ee3e25235d8cea4164cdee0ec39d1fda8e9203156ebe403ffda4/pexpect-4.6.0.tar.gz";
1127 url = "https://files.pythonhosted.org/packages/1c/b1/362a0d4235496cb42c33d1d8732b5e2c607b0129ad5fdd76f5a583b9fcb3/pexpect-4.7.0.tar.gz";
1085 sha256 = "1fla85g47iaxxpjhp9vkxdnv4pgc7rplfy6ja491smrrk0jqi3ia";
1128 sha256 = "1sv2rri15zwhds85a4kamwh9pj49qcxv7m4miyr4jfpfwv81yb4y";
1086 };
1129 };
1087 meta = {
1130 meta = {
1088 license = [ pkgs.lib.licenses.isc { fullName = "ISC License (ISCL)"; } ];
1131 license = [ pkgs.lib.licenses.isc { fullName = "ISC License (ISCL)"; } ];
@@ -1117,63 +1160,63 b' self: super: {'
1117 };
1160 };
1118 };
1161 };
1119 "plaster-pastedeploy" = super.buildPythonPackage {
1162 "plaster-pastedeploy" = super.buildPythonPackage {
1120 name = "plaster-pastedeploy-0.6";
1163 name = "plaster-pastedeploy-0.7";
1121 doCheck = false;
1164 doCheck = false;
1122 propagatedBuildInputs = [
1165 propagatedBuildInputs = [
1123 self."pastedeploy"
1166 self."pastedeploy"
1124 self."plaster"
1167 self."plaster"
1125 ];
1168 ];
1126 src = fetchurl {
1169 src = fetchurl {
1127 url = "https://files.pythonhosted.org/packages/3f/e7/6a6833158d2038ec40085433308a1e164fd1dac595513f6dd556d5669bb8/plaster_pastedeploy-0.6.tar.gz";
1170 url = "https://files.pythonhosted.org/packages/99/69/2d3bc33091249266a1bd3cf24499e40ab31d54dffb4a7d76fe647950b98c/plaster_pastedeploy-0.7.tar.gz";
1128 sha256 = "1bkggk18f4z2bmsmxyxabvf62znvjwbivzh880419r3ap0616cf2";
1171 sha256 = "1zg7gcsvc1kzay1ry5p699rg2qavfsxqwl17mqxzr0gzw6j9679r";
1129 };
1172 };
1130 meta = {
1173 meta = {
1131 license = [ pkgs.lib.licenses.mit ];
1174 license = [ pkgs.lib.licenses.mit ];
1132 };
1175 };
1133 };
1176 };
1134 "pluggy" = super.buildPythonPackage {
1177 "pluggy" = super.buildPythonPackage {
1135 name = "pluggy-0.8.1";
1178 name = "pluggy-0.11.0";
1136 doCheck = false;
1179 doCheck = false;
1137 src = fetchurl {
1180 src = fetchurl {
1138 url = "https://files.pythonhosted.org/packages/38/e1/83b10c17688af7b2998fa5342fec58ecbd2a5a7499f31e606ae6640b71ac/pluggy-0.8.1.tar.gz";
1181 url = "https://files.pythonhosted.org/packages/0d/a1/862ab336e8128fde20981d2c1aa8506693412daf5083b1911d539412676b/pluggy-0.11.0.tar.gz";
1139 sha256 = "05l6g42p9ilmabw0hlbiyxy6gyzjri41m5l11a8dzgvi77q35p4d";
1182 sha256 = "10511a54dvafw1jrk75mrhml53c7b7w4yaw7241696lc2hfvr895";
1140 };
1183 };
1141 meta = {
1184 meta = {
1142 license = [ pkgs.lib.licenses.mit ];
1185 license = [ pkgs.lib.licenses.mit ];
1143 };
1186 };
1144 };
1187 };
1145 "prompt-toolkit" = super.buildPythonPackage {
1188 "prompt-toolkit" = super.buildPythonPackage {
1146 name = "prompt-toolkit-1.0.15";
1189 name = "prompt-toolkit-1.0.16";
1147 doCheck = false;
1190 doCheck = false;
1148 propagatedBuildInputs = [
1191 propagatedBuildInputs = [
1149 self."six"
1192 self."six"
1150 self."wcwidth"
1193 self."wcwidth"
1151 ];
1194 ];
1152 src = fetchurl {
1195 src = fetchurl {
1153 url = "https://files.pythonhosted.org/packages/8a/ad/cf6b128866e78ad6d7f1dc5b7f99885fb813393d9860778b2984582e81b5/prompt_toolkit-1.0.15.tar.gz";
1196 url = "https://files.pythonhosted.org/packages/f1/03/bb36771dc9fa7553ac4bdc639a9ecdf6fda0ff4176faf940d97e3c16e41d/prompt_toolkit-1.0.16.tar.gz";
1154 sha256 = "05v9h5nydljwpj5nm8n804ms0glajwfy1zagrzqrg91wk3qqi1c5";
1197 sha256 = "1d65hm6nf0cbq0q0121m60zzy4s1fpg9fn761s1yxf08dridvkn1";
1155 };
1198 };
1156 meta = {
1199 meta = {
1157 license = [ pkgs.lib.licenses.bsdOriginal ];
1200 license = [ pkgs.lib.licenses.bsdOriginal ];
1158 };
1201 };
1159 };
1202 };
1160 "psutil" = super.buildPythonPackage {
1203 "psutil" = super.buildPythonPackage {
1161 name = "psutil-5.4.8";
1204 name = "psutil-5.5.1";
1162 doCheck = false;
1205 doCheck = false;
1163 src = fetchurl {
1206 src = fetchurl {
1164 url = "https://files.pythonhosted.org/packages/e3/58/0eae6e4466e5abf779d7e2b71fac7fba5f59e00ea36ddb3ed690419ccb0f/psutil-5.4.8.tar.gz";
1207 url = "https://files.pythonhosted.org/packages/c7/01/7c30b247cdc5ba29623faa5c8cf1f1bbf7e041783c340414b0ed7e067c64/psutil-5.5.1.tar.gz";
1165 sha256 = "1hyna338sml2cl1mfb2gs89np18z27mvyhmq4ifh22x07n7mq9kf";
1208 sha256 = "045qaqvn6k90bj5bcy259yrwcd2afgznaav3sfhphy9b8ambzkkj";
1166 };
1209 };
1167 meta = {
1210 meta = {
1168 license = [ pkgs.lib.licenses.bsdOriginal ];
1211 license = [ pkgs.lib.licenses.bsdOriginal ];
1169 };
1212 };
1170 };
1213 };
1171 "psycopg2" = super.buildPythonPackage {
1214 "psycopg2" = super.buildPythonPackage {
1172 name = "psycopg2-2.7.5";
1215 name = "psycopg2-2.8.3";
1173 doCheck = false;
1216 doCheck = false;
1174 src = fetchurl {
1217 src = fetchurl {
1175 url = "https://files.pythonhosted.org/packages/b2/c1/7bf6c464e903ffc4f3f5907c389e5a4199666bf57f6cd6bf46c17912a1f9/psycopg2-2.7.5.tar.gz";
1218 url = "https://files.pythonhosted.org/packages/5c/1c/6997288da181277a0c29bc39a5f9143ff20b8c99f2a7d059cfb55163e165/psycopg2-2.8.3.tar.gz";
1176 sha256 = "17klx964gw8z0znl0raz3by8vdc7cq5gxj4pdcrfcina84nrdkzc";
1219 sha256 = "0ms4kx0p5n281l89awccix4d05ybmdngnjjpi9jbzd0rhf1nwyl9";
1177 };
1220 };
1178 meta = {
1221 meta = {
1179 license = [ pkgs.lib.licenses.zpl21 { fullName = "GNU Library or Lesser General Public License (LGPL)"; } { fullName = "LGPL with exceptions or ZPL"; } ];
1222 license = [ pkgs.lib.licenses.zpl21 { fullName = "GNU Library or Lesser General Public License (LGPL)"; } { fullName = "LGPL with exceptions or ZPL"; } ];
@@ -1239,14 +1282,25 b' self: super: {'
1239 };
1282 };
1240 };
1283 };
1241 "pyasn1-modules" = super.buildPythonPackage {
1284 "pyasn1-modules" = super.buildPythonPackage {
1242 name = "pyasn1-modules-0.2.4";
1285 name = "pyasn1-modules-0.2.5";
1243 doCheck = false;
1286 doCheck = false;
1244 propagatedBuildInputs = [
1287 propagatedBuildInputs = [
1245 self."pyasn1"
1288 self."pyasn1"
1246 ];
1289 ];
1247 src = fetchurl {
1290 src = fetchurl {
1248 url = "https://files.pythonhosted.org/packages/bd/a5/ef7bf693e8a8f015386c9167483199f54f8a8ec01d1c737e05524f16e792/pyasn1-modules-0.2.4.tar.gz";
1291 url = "https://files.pythonhosted.org/packages/ec/0b/69620cb04a016e4a1e8e352e8a42717862129b574b3479adb2358a1f12f7/pyasn1-modules-0.2.5.tar.gz";
1249 sha256 = "0z3w5dqrrvdplg9ma45j8n23xvyrj9ki8mg4ibqbn7l4qpl90855";
1292 sha256 = "15nvfx0vnl8akdlv3k6s0n80vqvryj82bm040jdsn7wmyxl1ywpg";
1293 };
1294 meta = {
1295 license = [ pkgs.lib.licenses.bsdOriginal ];
1296 };
1297 };
1298 "pycparser" = super.buildPythonPackage {
1299 name = "pycparser-2.19";
1300 doCheck = false;
1301 src = fetchurl {
1302 url = "https://files.pythonhosted.org/packages/68/9e/49196946aee219aead1290e00d1e7fdeab8567783e83e1b9ab5585e6206a/pycparser-2.19.tar.gz";
1303 sha256 = "1cr5dcj9628lkz1qlwq3fv97c25363qppkmcayqvd05dpy573259";
1250 };
1304 };
1251 meta = {
1305 meta = {
1252 license = [ pkgs.lib.licenses.bsdOriginal ];
1306 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -1274,23 +1328,12 b' self: super: {'
1274 license = [ pkgs.lib.licenses.mit { fullName = "LGPL/MIT"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ];
1328 license = [ pkgs.lib.licenses.mit { fullName = "LGPL/MIT"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ];
1275 };
1329 };
1276 };
1330 };
1277 "pyflakes" = super.buildPythonPackage {
1331 "pygments" = super.buildPythonPackage {
1278 name = "pyflakes-0.8.1";
1332 name = "pygments-2.4.2";
1279 doCheck = false;
1333 doCheck = false;
1280 src = fetchurl {
1334 src = fetchurl {
1281 url = "https://files.pythonhosted.org/packages/75/22/a90ec0252f4f87f3ffb6336504de71fe16a49d69c4538dae2f12b9360a38/pyflakes-0.8.1.tar.gz";
1335 url = "https://files.pythonhosted.org/packages/7e/ae/26808275fc76bf2832deb10d3a3ed3107bc4de01b85dcccbe525f2cd6d1e/Pygments-2.4.2.tar.gz";
1282 sha256 = "0sbpq6pqm1i9wqi41mlfrsc5rk92jv4mskvlyxmnhlbdnc80ma1z";
1336 sha256 = "15v2sqm5g12bqa0c7wikfh9ck2nl97ayizy1hpqhmws5gqalq748";
1283 };
1284 meta = {
1285 license = [ pkgs.lib.licenses.mit ];
1286 };
1287 };
1288 "pygments" = super.buildPythonPackage {
1289 name = "pygments-2.3.1";
1290 doCheck = false;
1291 src = fetchurl {
1292 url = "https://files.pythonhosted.org/packages/64/69/413708eaf3a64a6abb8972644e0f20891a55e621c6759e2c3f3891e05d63/Pygments-2.3.1.tar.gz";
1293 sha256 = "0ji87g09jph8jqcvclgb02qvxasdnr9pzvk90rl66d90yqcxmyjz";
1294 };
1337 };
1295 meta = {
1338 meta = {
1296 license = [ pkgs.lib.licenses.bsdOriginal ];
1339 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -1330,7 +1373,7 b' self: super: {'
1330 };
1373 };
1331 };
1374 };
1332 "pyramid" = super.buildPythonPackage {
1375 "pyramid" = super.buildPythonPackage {
1333 name = "pyramid-1.10.1";
1376 name = "pyramid-1.10.4";
1334 doCheck = false;
1377 doCheck = false;
1335 propagatedBuildInputs = [
1378 propagatedBuildInputs = [
1336 self."hupper"
1379 self."hupper"
@@ -1345,28 +1388,13 b' self: super: {'
1345 self."repoze.lru"
1388 self."repoze.lru"
1346 ];
1389 ];
1347 src = fetchurl {
1390 src = fetchurl {
1348 url = "https://files.pythonhosted.org/packages/0a/3e/22e3ac9be1b70a01139adba8906ee4b8f628bb469fea3c52f6c97b73063c/pyramid-1.10.1.tar.gz";
1391 url = "https://files.pythonhosted.org/packages/c2/43/1ae701c9c6bb3a434358e678a5e72c96e8aa55cf4cb1d2fa2041b5dd38b7/pyramid-1.10.4.tar.gz";
1349 sha256 = "1h5105nfh6rsrfjiyw20aavyibj36la3hajy6vh1fa77xb4y3hrp";
1392 sha256 = "0rkxs1ajycg2zh1c94xlmls56mx5m161sn8112skj0amza6cn36q";
1350 };
1393 };
1351 meta = {
1394 meta = {
1352 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1395 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1353 };
1396 };
1354 };
1397 };
1355 "pyramid-beaker" = super.buildPythonPackage {
1356 name = "pyramid-beaker-0.8";
1357 doCheck = false;
1358 propagatedBuildInputs = [
1359 self."pyramid"
1360 self."beaker"
1361 ];
1362 src = fetchurl {
1363 url = "https://files.pythonhosted.org/packages/d9/6e/b85426e00fd3d57f4545f74e1c3828552d8700f13ededeef9233f7bca8be/pyramid_beaker-0.8.tar.gz";
1364 sha256 = "0hflx3qkcdml1mwpq53sz46s7jickpfn0zy0ns2c7j445j66bp3p";
1365 };
1366 meta = {
1367 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1368 };
1369 };
1370 "pyramid-debugtoolbar" = super.buildPythonPackage {
1398 "pyramid-debugtoolbar" = super.buildPythonPackage {
1371 name = "pyramid-debugtoolbar-4.5";
1399 name = "pyramid-debugtoolbar-4.5";
1372 doCheck = false;
1400 doCheck = false;
@@ -1538,14 +1566,14 b' self: super: {'
1538 };
1566 };
1539 };
1567 };
1540 "python-dateutil" = super.buildPythonPackage {
1568 "python-dateutil" = super.buildPythonPackage {
1541 name = "python-dateutil-2.7.5";
1569 name = "python-dateutil-2.8.0";
1542 doCheck = false;
1570 doCheck = false;
1543 propagatedBuildInputs = [
1571 propagatedBuildInputs = [
1544 self."six"
1572 self."six"
1545 ];
1573 ];
1546 src = fetchurl {
1574 src = fetchurl {
1547 url = "https://files.pythonhosted.org/packages/0e/01/68747933e8d12263d41ce08119620d9a7e5eb72c876a3442257f74490da0/python-dateutil-2.7.5.tar.gz";
1575 url = "https://files.pythonhosted.org/packages/ad/99/5b2e99737edeb28c71bcbec5b5dda19d0d9ef3ca3e92e3e925e7c0bb364c/python-dateutil-2.8.0.tar.gz";
1548 sha256 = "00ngwcdw36w5b37b51mdwn3qxid9zdf3kpffv2q6n9kl05y2iyc8";
1576 sha256 = "17nsfhy4xdz1khrfxa61vd7pmvd5z0wa3zb6v4gb4kfnykv0b668";
1549 };
1577 };
1550 meta = {
1578 meta = {
1551 license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.asl20 { fullName = "Dual License"; } ];
1579 license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.asl20 { fullName = "Dual License"; } ];
@@ -1690,7 +1718,7 b' self: super: {'
1690 };
1718 };
1691 };
1719 };
1692 "rhodecode-enterprise-ce" = super.buildPythonPackage {
1720 "rhodecode-enterprise-ce" = super.buildPythonPackage {
1693 name = "rhodecode-enterprise-ce-4.16.2";
1721 name = "rhodecode-enterprise-ce-4.17.0";
1694 buildInputs = [
1722 buildInputs = [
1695 self."pytest"
1723 self."pytest"
1696 self."py"
1724 self."py"
@@ -1709,36 +1737,29 b' self: super: {'
1709 ];
1737 ];
1710 doCheck = true;
1738 doCheck = true;
1711 propagatedBuildInputs = [
1739 propagatedBuildInputs = [
1712 self."setuptools-scm"
1713 self."amqp"
1740 self."amqp"
1714 self."authomatic"
1741 self."authomatic"
1715 self."atomicwrites"
1716 self."attrs"
1717 self."babel"
1742 self."babel"
1718 self."beaker"
1743 self."beaker"
1719 self."bleach"
1744 self."bleach"
1720 self."celery"
1745 self."celery"
1721 self."chameleon"
1722 self."channelstream"
1746 self."channelstream"
1723 self."click"
1747 self."click"
1724 self."colander"
1748 self."colander"
1725 self."configobj"
1749 self."configobj"
1726 self."cssselect"
1750 self."cssselect"
1751 self."cryptography"
1727 self."decorator"
1752 self."decorator"
1728 self."deform"
1753 self."deform"
1729 self."docutils"
1754 self."docutils"
1730 self."dogpile.cache"
1755 self."dogpile.cache"
1731 self."dogpile.core"
1756 self."dogpile.core"
1732 self."ecdsa"
1733 self."formencode"
1757 self."formencode"
1734 self."future"
1758 self."future"
1735 self."futures"
1759 self."futures"
1736 self."gnureadline"
1737 self."infrae.cache"
1760 self."infrae.cache"
1738 self."iso8601"
1761 self."iso8601"
1739 self."itsdangerous"
1762 self."itsdangerous"
1740 self."jinja2"
1741 self."billiard"
1742 self."kombu"
1763 self."kombu"
1743 self."lxml"
1764 self."lxml"
1744 self."mako"
1765 self."mako"
@@ -1747,21 +1768,18 b' self: super: {'
1747 self."msgpack-python"
1768 self."msgpack-python"
1748 self."pyotp"
1769 self."pyotp"
1749 self."packaging"
1770 self."packaging"
1771 self."pathlib2"
1750 self."paste"
1772 self."paste"
1751 self."pastedeploy"
1773 self."pastedeploy"
1752 self."pastescript"
1774 self."pastescript"
1753 self."pathlib2"
1754 self."peppercorn"
1775 self."peppercorn"
1755 self."psutil"
1776 self."psutil"
1756 self."py-bcrypt"
1777 self."py-bcrypt"
1778 self."pycurl"
1757 self."pycrypto"
1779 self."pycrypto"
1758 self."pycurl"
1759 self."pyflakes"
1760 self."pygments"
1780 self."pygments"
1761 self."pyparsing"
1781 self."pyparsing"
1762 self."pyramid-beaker"
1763 self."pyramid-debugtoolbar"
1782 self."pyramid-debugtoolbar"
1764 self."pyramid-jinja2"
1765 self."pyramid-mako"
1783 self."pyramid-mako"
1766 self."pyramid"
1784 self."pyramid"
1767 self."pyramid-mailer"
1785 self."pyramid-mailer"
@@ -1784,7 +1802,6 b' self: super: {'
1784 self."sshpubkeys"
1802 self."sshpubkeys"
1785 self."subprocess32"
1803 self."subprocess32"
1786 self."supervisor"
1804 self."supervisor"
1787 self."tempita"
1788 self."translationstring"
1805 self."translationstring"
1789 self."urllib3"
1806 self."urllib3"
1790 self."urlobject"
1807 self."urlobject"
@@ -1813,7 +1830,6 b' self: super: {'
1813 self."greenlet"
1830 self."greenlet"
1814 self."gunicorn"
1831 self."gunicorn"
1815 self."waitress"
1832 self."waitress"
1816 self."setproctitle"
1817 self."ipdb"
1833 self."ipdb"
1818 self."ipython"
1834 self."ipython"
1819 self."rhodecode-tools"
1835 self."rhodecode-tools"
@@ -1855,8 +1871,8 b' self: super: {'
1855 self."elasticsearch1-dsl"
1871 self."elasticsearch1-dsl"
1856 ];
1872 ];
1857 src = fetchurl {
1873 src = fetchurl {
1858 url = "https://code.rhodecode.com/rhodecode-tools-ce/archive/v1.2.1.tar.gz?md5=25bc2f7de1da318e547236d3fb463d28";
1874 url = "https://code.rhodecode.com/rhodecode-tools-ce/artifacts/download/0-10ac93f4-bb7d-4b97-baea-68110743dd5a.tar.gz?md5=962dc77c06aceee62282b98d33149661";
1859 sha256 = "1k8l3s4mvshza1zay6dfxprq54fyb5dc85dqdva9wa3f466y0adk";
1875 sha256 = "1vfhgf46inbx7jvlfx4fdzh3vz7lh37r291gzb5hx447pfm3qllg";
1860 };
1876 };
1861 meta = {
1877 meta = {
1862 license = [ { fullName = "Apache 2.0 and Proprietary"; } ];
1878 license = [ { fullName = "Apache 2.0 and Proprietary"; } ];
@@ -1878,11 +1894,11 b' self: super: {'
1878 };
1894 };
1879 };
1895 };
1880 "scandir" = super.buildPythonPackage {
1896 "scandir" = super.buildPythonPackage {
1881 name = "scandir-1.9.0";
1897 name = "scandir-1.10.0";
1882 doCheck = false;
1898 doCheck = false;
1883 src = fetchurl {
1899 src = fetchurl {
1884 url = "https://files.pythonhosted.org/packages/16/2a/557af1181e6b4e30254d5a6163b18f5053791ca66e251e77ab08887e8fe3/scandir-1.9.0.tar.gz";
1900 url = "https://files.pythonhosted.org/packages/df/f5/9c052db7bd54d0cbf1bc0bb6554362bba1012d03e5888950a4f5c5dadc4e/scandir-1.10.0.tar.gz";
1885 sha256 = "0r3hvf1a9jm1rkqgx40gxkmccknkaiqjavs8lccgq9s8khh5x5s4";
1901 sha256 = "1bkqwmf056pkchf05ywbnf659wqlp6lljcdb0y88wr9f0vv32ijd";
1886 };
1902 };
1887 meta = {
1903 meta = {
1888 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "New BSD License"; } ];
1904 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "New BSD License"; } ];
@@ -1900,22 +1916,11 b' self: super: {'
1900 };
1916 };
1901 };
1917 };
1902 "setuptools" = super.buildPythonPackage {
1918 "setuptools" = super.buildPythonPackage {
1903 name = "setuptools-40.8.0";
1919 name = "setuptools-41.0.1";
1904 doCheck = false;
1920 doCheck = false;
1905 src = fetchurl {
1921 src = fetchurl {
1906 url = "https://files.pythonhosted.org/packages/c2/f7/c7b501b783e5a74cf1768bc174ee4fb0a8a6ee5af6afa92274ff964703e0/setuptools-40.8.0.zip";
1922 url = "https://files.pythonhosted.org/packages/1d/64/a18a487b4391a05b9c7f938b94a16d80305bf0369c6b0b9509e86165e1d3/setuptools-41.0.1.zip";
1907 sha256 = "0k9hifpgahnw2a26w3cr346iy733k6d3nwh3f7g9m13y6f8fqkkf";
1923 sha256 = "04sns22y2hhsrwfy1mha2lgslvpjsjsz8xws7h2rh5a7ylkd28m2";
1908 };
1909 meta = {
1910 license = [ pkgs.lib.licenses.mit ];
1911 };
1912 };
1913 "setuptools-scm" = super.buildPythonPackage {
1914 name = "setuptools-scm-2.1.0";
1915 doCheck = false;
1916 src = fetchurl {
1917 url = "https://files.pythonhosted.org/packages/e5/62/f9e1ac314464eb5945c97542acb6bf6f3381dfa5d7a658de7730c36f31a1/setuptools_scm-2.1.0.tar.gz";
1918 sha256 = "0yb364cgk15sfw3x8ln4ssh98z1dj6n8iiz4r2rw1cfsxhgi8rx7";
1919 };
1924 };
1920 meta = {
1925 meta = {
1921 license = [ pkgs.lib.licenses.mit ];
1926 license = [ pkgs.lib.licenses.mit ];
@@ -1966,40 +1971,40 b' self: super: {'
1966 };
1971 };
1967 };
1972 };
1968 "sshpubkeys" = super.buildPythonPackage {
1973 "sshpubkeys" = super.buildPythonPackage {
1969 name = "sshpubkeys-2.2.0";
1974 name = "sshpubkeys-3.1.0";
1970 doCheck = false;
1975 doCheck = false;
1971 propagatedBuildInputs = [
1976 propagatedBuildInputs = [
1972 self."pycrypto"
1977 self."cryptography"
1973 self."ecdsa"
1978 self."ecdsa"
1974 ];
1979 ];
1975 src = fetchurl {
1980 src = fetchurl {
1976 url = "https://files.pythonhosted.org/packages/27/da/337fabeb3dca6b62039a93ceaa636f25065e0ae92b575b1235342076cf0a/sshpubkeys-2.2.0.tar.gz";
1981 url = "https://files.pythonhosted.org/packages/00/23/f7508a12007c96861c3da811992f14283d79c819d71a217b3e12d5196649/sshpubkeys-3.1.0.tar.gz";
1977 sha256 = "0r4kpwzmg96a2x56pllik7dmc3fnqk189v3sfgsi07q2ryrhr6xm";
1982 sha256 = "105g2li04nm1hb15a2y6hm9m9k7fbrkd5l3gy12w3kgcmsf3k25k";
1978 };
1983 };
1979 meta = {
1984 meta = {
1980 license = [ pkgs.lib.licenses.bsdOriginal ];
1985 license = [ pkgs.lib.licenses.bsdOriginal ];
1981 };
1986 };
1982 };
1987 };
1983 "subprocess32" = super.buildPythonPackage {
1988 "subprocess32" = super.buildPythonPackage {
1984 name = "subprocess32-3.5.3";
1989 name = "subprocess32-3.5.4";
1985 doCheck = false;
1990 doCheck = false;
1986 src = fetchurl {
1991 src = fetchurl {
1987 url = "https://files.pythonhosted.org/packages/be/2b/beeba583e9877e64db10b52a96915afc0feabf7144dcbf2a0d0ea68bf73d/subprocess32-3.5.3.tar.gz";
1992 url = "https://files.pythonhosted.org/packages/32/c8/564be4d12629b912ea431f1a50eb8b3b9d00f1a0b1ceff17f266be190007/subprocess32-3.5.4.tar.gz";
1988 sha256 = "1hr5fan8i719hmlmz73hf8rhq74014w07d8ryg7krvvf6692kj3b";
1993 sha256 = "17f7mvwx2271s1wrl0qac3wjqqnrqag866zs3qc8v5wp0k43fagb";
1989 };
1994 };
1990 meta = {
1995 meta = {
1991 license = [ pkgs.lib.licenses.psfl ];
1996 license = [ pkgs.lib.licenses.psfl ];
1992 };
1997 };
1993 };
1998 };
1994 "supervisor" = super.buildPythonPackage {
1999 "supervisor" = super.buildPythonPackage {
1995 name = "supervisor-3.3.5";
2000 name = "supervisor-4.0.3";
1996 doCheck = false;
2001 doCheck = false;
1997 propagatedBuildInputs = [
2002 propagatedBuildInputs = [
1998 self."meld3"
2003 self."meld3"
1999 ];
2004 ];
2000 src = fetchurl {
2005 src = fetchurl {
2001 url = "https://files.pythonhosted.org/packages/ba/65/92575a8757ed576beaee59251f64a3287bde82bdc03964b89df9e1d29e1b/supervisor-3.3.5.tar.gz";
2006 url = "https://files.pythonhosted.org/packages/97/48/f38bf70bd9282d1a18d591616557cc1a77a1c627d57dff66ead65c891dc8/supervisor-4.0.3.tar.gz";
2002 sha256 = "1w3ahridzbc6rxfpbyx8lij6pjlcgf2ymzyg53llkjqxalp6sk8v";
2007 sha256 = "17hla7mx6w5m5jzkkjxgqa8wpswqmfhbhf49f692hw78fg0ans7p";
2003 };
2008 };
2004 meta = {
2009 meta = {
2005 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
2010 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
@@ -2128,22 +2133,22 b' self: super: {'
2128 };
2133 };
2129 };
2134 };
2130 "vine" = super.buildPythonPackage {
2135 "vine" = super.buildPythonPackage {
2131 name = "vine-1.2.0";
2136 name = "vine-1.3.0";
2132 doCheck = false;
2137 doCheck = false;
2133 src = fetchurl {
2138 src = fetchurl {
2134 url = "https://files.pythonhosted.org/packages/46/1a/c94317efa98040c5d50fe3cf9080cafb0372ff5afb0283dc018c751c6746/vine-1.2.0.tar.gz";
2139 url = "https://files.pythonhosted.org/packages/1c/e1/79fb8046e607dd6c2ad05c9b8ebac9d0bd31d086a08f02699e96fc5b3046/vine-1.3.0.tar.gz";
2135 sha256 = "0xjz2sjbr5jrpjk411b7alkghdskhphgsqqrbi7abqfh2pli6j7f";
2140 sha256 = "11ydsbhl1vabndc2r979dv61s6j2b0giq6dgvryifvq1m7bycghk";
2136 };
2141 };
2137 meta = {
2142 meta = {
2138 license = [ pkgs.lib.licenses.bsdOriginal ];
2143 license = [ pkgs.lib.licenses.bsdOriginal ];
2139 };
2144 };
2140 };
2145 };
2141 "waitress" = super.buildPythonPackage {
2146 "waitress" = super.buildPythonPackage {
2142 name = "waitress-1.1.0";
2147 name = "waitress-1.3.0";
2143 doCheck = false;
2148 doCheck = false;
2144 src = fetchurl {
2149 src = fetchurl {
2145 url = "https://files.pythonhosted.org/packages/3c/68/1c10dd5c556872ceebe88483b0436140048d39de83a84a06a8baa8136f4f/waitress-1.1.0.tar.gz";
2150 url = "https://files.pythonhosted.org/packages/43/50/9890471320d5ad22761ae46661cf745f487b1c8c4ec49352b99e1078b970/waitress-1.3.0.tar.gz";
2146 sha256 = "1a85gyji0kajc3p0s1pwwfm06w4wfxjkvvl4rnrz3h164kbd6g6k";
2151 sha256 = "09j5dzbbcxib7vdskhx39s1qsydlr4n2p2png71d7mjnr9pnwajf";
2147 };
2152 };
2148 meta = {
2153 meta = {
2149 license = [ pkgs.lib.licenses.zpl21 ];
2154 license = [ pkgs.lib.licenses.zpl21 ];
@@ -2218,18 +2223,18 b' self: super: {'
2218 };
2223 };
2219 };
2224 };
2220 "webob" = super.buildPythonPackage {
2225 "webob" = super.buildPythonPackage {
2221 name = "webob-1.8.4";
2226 name = "webob-1.8.5";
2222 doCheck = false;
2227 doCheck = false;
2223 src = fetchurl {
2228 src = fetchurl {
2224 url = "https://files.pythonhosted.org/packages/e4/6c/99e322c3d4cc11d9060a67a9bf2f7c9c581f40988c11fffe89bb8c36bc5e/WebOb-1.8.4.tar.gz";
2229 url = "https://files.pythonhosted.org/packages/9d/1a/0c89c070ee2829c934cb6c7082287c822e28236a4fcf90063e6be7c35532/WebOb-1.8.5.tar.gz";
2225 sha256 = "16cfg5y4n6sihz59vsmns2yqbfm0gfsn3l5xgz2g0pdhilaib0x4";
2230 sha256 = "11khpzaxc88q31v25ic330gsf56fwmbdc9b30br8mvp0fmwspah5";
2226 };
2231 };
2227 meta = {
2232 meta = {
2228 license = [ pkgs.lib.licenses.mit ];
2233 license = [ pkgs.lib.licenses.mit ];
2229 };
2234 };
2230 };
2235 };
2231 "webtest" = super.buildPythonPackage {
2236 "webtest" = super.buildPythonPackage {
2232 name = "webtest-2.0.32";
2237 name = "webtest-2.0.33";
2233 doCheck = false;
2238 doCheck = false;
2234 propagatedBuildInputs = [
2239 propagatedBuildInputs = [
2235 self."six"
2240 self."six"
@@ -2238,8 +2243,8 b' self: super: {'
2238 self."beautifulsoup4"
2243 self."beautifulsoup4"
2239 ];
2244 ];
2240 src = fetchurl {
2245 src = fetchurl {
2241 url = "https://files.pythonhosted.org/packages/27/9f/9e74449d272ffbef4fb3012e6dbc53c0b24822d545e7a33a342f80131e59/WebTest-2.0.32.tar.gz";
2246 url = "https://files.pythonhosted.org/packages/a8/b0/ffc9413b637dbe26e291429bb0f6ed731e518d0cd03da28524a8fe2e8a8f/WebTest-2.0.33.tar.gz";
2242 sha256 = "0qp0nnbazzm4ibjiyqfcn6f230svk09i4g58zg2i9x1ga06h48a2";
2247 sha256 = "1l3z0cwqslsf4rcrhi2gr8kdfh74wn2dw76376i4g9i38gz8wd21";
2243 };
2248 };
2244 meta = {
2249 meta = {
2245 license = [ pkgs.lib.licenses.mit ];
2250 license = [ pkgs.lib.licenses.mit ];
@@ -2293,42 +2298,42 b' self: super: {'
2293 };
2298 };
2294 };
2299 };
2295 "zope.deprecation" = super.buildPythonPackage {
2300 "zope.deprecation" = super.buildPythonPackage {
2296 name = "zope.deprecation-4.3.0";
2301 name = "zope.deprecation-4.4.0";
2297 doCheck = false;
2302 doCheck = false;
2298 propagatedBuildInputs = [
2303 propagatedBuildInputs = [
2299 self."setuptools"
2304 self."setuptools"
2300 ];
2305 ];
2301 src = fetchurl {
2306 src = fetchurl {
2302 url = "https://files.pythonhosted.org/packages/a1/18/2dc5e6bfe64fdc3b79411b67464c55bb0b43b127051a20f7f492ab767758/zope.deprecation-4.3.0.tar.gz";
2307 url = "https://files.pythonhosted.org/packages/34/da/46e92d32d545dd067b9436279d84c339e8b16de2ca393d7b892bc1e1e9fd/zope.deprecation-4.4.0.tar.gz";
2303 sha256 = "095jas41wbxgmw95kwdxqhbc3bgihw2hzj9b3qpdg85apcsf2lkx";
2308 sha256 = "1pz2cv7gv9y1r3m0bdv7ks1alagmrn5msm5spwdzkb2by0w36i8d";
2304 };
2309 };
2305 meta = {
2310 meta = {
2306 license = [ pkgs.lib.licenses.zpl21 ];
2311 license = [ pkgs.lib.licenses.zpl21 ];
2307 };
2312 };
2308 };
2313 };
2309 "zope.event" = super.buildPythonPackage {
2314 "zope.event" = super.buildPythonPackage {
2310 name = "zope.event-4.3.0";
2315 name = "zope.event-4.4";
2311 doCheck = false;
2316 doCheck = false;
2312 propagatedBuildInputs = [
2317 propagatedBuildInputs = [
2313 self."setuptools"
2318 self."setuptools"
2314 ];
2319 ];
2315 src = fetchurl {
2320 src = fetchurl {
2316 url = "https://files.pythonhosted.org/packages/9e/d0/54ba59f19a0635f6591b74be259cf6fbf67e73f4edda27b5cd0cf4d26efa/zope.event-4.3.0.tar.gz";
2321 url = "https://files.pythonhosted.org/packages/4c/b2/51c0369adcf5be2334280eed230192ab3b03f81f8efda9ddea6f65cc7b32/zope.event-4.4.tar.gz";
2317 sha256 = "1rrkyx42bcq8dkpj23c2v99kczlrg8d39c06q5qpr0vs4hjfmv70";
2322 sha256 = "1ksbc726av9xacml6jhcfyn828hlhb9xlddpx6fcvnlvmpmpvhk9";
2318 };
2323 };
2319 meta = {
2324 meta = {
2320 license = [ pkgs.lib.licenses.zpl21 ];
2325 license = [ pkgs.lib.licenses.zpl21 ];
2321 };
2326 };
2322 };
2327 };
2323 "zope.interface" = super.buildPythonPackage {
2328 "zope.interface" = super.buildPythonPackage {
2324 name = "zope.interface-4.5.0";
2329 name = "zope.interface-4.6.0";
2325 doCheck = false;
2330 doCheck = false;
2326 propagatedBuildInputs = [
2331 propagatedBuildInputs = [
2327 self."setuptools"
2332 self."setuptools"
2328 ];
2333 ];
2329 src = fetchurl {
2334 src = fetchurl {
2330 url = "https://files.pythonhosted.org/packages/ac/8a/657532df378c2cd2a1fe6b12be3b4097521570769d4852ec02c24bd3594e/zope.interface-4.5.0.tar.gz";
2335 url = "https://files.pythonhosted.org/packages/4e/d0/c9d16bd5b38de44a20c6dc5d5ed80a49626fafcb3db9f9efdc2a19026db6/zope.interface-4.6.0.tar.gz";
2331 sha256 = "0k67m60ij06wkg82n15qgyn96waf4pmrkhv0njpkfzpmv5q89hsp";
2336 sha256 = "1rgh2x3rcl9r0v0499kf78xy86rnmanajf4ywmqb943wpk50sg8v";
2332 };
2337 };
2333 meta = {
2338 meta = {
2334 license = [ pkgs.lib.licenses.zpl21 ];
2339 license = [ pkgs.lib.licenses.zpl21 ];
@@ -1,37 +1,31 b''
1 ## dependencies
1 ## dependencies
2
2
3 setuptools-scm==2.1.0
4 amqp==2.3.1
3 amqp==2.3.1
5 # not released authomatic that has updated some oauth providers
4 # not released authomatic that has updated some oauth providers
6 https://code.rhodecode.com/upstream/authomatic/archive/90a9ce60cc405ae8a2bf5c3713acd5d78579a04e.tar.gz?md5=3c68720a1322b25254009518d1ff6801#egg=authomatic==0.1.0.post1
5 https://code.rhodecode.com/upstream/authomatic/artifacts/download/0-4fe9c041-a567-4f84-be4c-7efa2a606d3c.tar.gz?md5=f6bdc3c769688212db68233e8d2b0383#egg=authomatic==0.1.0.post1
7 atomicwrites==1.2.1
6
8 attrs==18.2.0
9 babel==1.3
7 babel==1.3
10 beaker==1.9.1
8 beaker==1.9.1
11 bleach==3.0.2
9 bleach==3.1.0
12 celery==4.1.1
10 celery==4.1.1
13 chameleon==2.24
14 channelstream==0.5.2
11 channelstream==0.5.2
15 click==7.0
12 click==7.0
16 colander==1.5.1
13 colander==1.7.0
17 # our custom configobj
14 # our custom configobj
18 https://code.rhodecode.com/upstream/configobj/archive/a11ff0a0bd4fbda9e3a91267e720f88329efb4a6.tar.gz?md5=9916c524ea11a6c418217af6b28d4b3c#egg=configobj==5.0.6
15 https://code.rhodecode.com/upstream/configobj/artifacts/download/0-012de99a-b1e1-4f64-a5c0-07a98a41b324.tar.gz?md5=6a513f51fe04b2c18cf84c1395a7c626#egg=configobj==5.0.6
19 cssselect==1.0.3
16 cssselect==1.0.3
17 cryptography==2.6.1
20 decorator==4.1.2
18 decorator==4.1.2
21 deform==2.0.7
19 deform==2.0.7
22 docutils==0.14.0
20 docutils==0.14.0
23 dogpile.cache==0.7.1
21 dogpile.cache==0.7.1
24 dogpile.core==0.4.1
22 dogpile.core==0.4.1
25 ecdsa==0.13
26 formencode==1.2.4
23 formencode==1.2.4
27 future==0.14.3
24 future==0.14.3
28 futures==3.0.2
25 futures==3.0.2
29 gnureadline==6.3.8
30 infrae.cache==1.0.1
26 infrae.cache==1.0.1
31 iso8601==0.1.12
27 iso8601==0.1.12
32 itsdangerous==0.24
28 itsdangerous==0.24
33 jinja2==2.9.6
34 billiard==3.5.0.3
35 kombu==4.2.1
29 kombu==4.2.1
36 lxml==4.2.5
30 lxml==4.2.5
37 mako==1.0.7
31 mako==1.0.7
@@ -40,23 +34,20 b' markupsafe==1.1.0'
40 msgpack-python==0.5.6
34 msgpack-python==0.5.6
41 pyotp==2.2.7
35 pyotp==2.2.7
42 packaging==15.2
36 packaging==15.2
43 paste==3.0.5
37 pathlib2==2.3.4
38 paste==3.0.8
44 pastedeploy==2.0.1
39 pastedeploy==2.0.1
45 pastescript==3.0.0
40 pastescript==3.1.0
46 pathlib2==2.3.3
47 peppercorn==0.6
41 peppercorn==0.6
48 psutil==5.4.8
42 psutil==5.5.1
49 py-bcrypt==0.4
43 py-bcrypt==0.4
50 pycrypto==2.6.1
51 pycurl==7.43.0.2
44 pycurl==7.43.0.2
52 pyflakes==0.8.1
45 pycrypto==2.6.1
53 pygments==2.3.1
46 pygments==2.4.2
54 pyparsing==2.3.0
47 pyparsing==2.3.0
55 pyramid-beaker==0.8
56 pyramid-debugtoolbar==4.5.0
48 pyramid-debugtoolbar==4.5.0
57 pyramid-jinja2==2.7
58 pyramid-mako==1.0.2
49 pyramid-mako==1.0.2
59 pyramid==1.10.1
50 pyramid==1.10.4
60 pyramid_mailer==0.15.1
51 pyramid_mailer==0.15.1
61 python-dateutil
52 python-dateutil
62 python-ldap==3.1.0
53 python-ldap==3.1.0
@@ -74,10 +65,9 b' routes==2.4.1'
74 simplejson==3.16.0
65 simplejson==3.16.0
75 six==1.11.0
66 six==1.11.0
76 sqlalchemy==1.1.18
67 sqlalchemy==1.1.18
77 sshpubkeys==2.2.0
68 sshpubkeys==3.1.0
78 subprocess32==3.5.3
69 subprocess32==3.5.4
79 supervisor==3.3.5
70 supervisor==4.0.3
80 tempita==0.5.2
81 translationstring==1.3
71 translationstring==1.3
82 urllib3==1.24.1
72 urllib3==1.24.1
83 urlobject==2.4.3
73 urlobject==2.4.3
@@ -85,29 +75,29 b' venusian==1.2.0'
85 weberror==0.10.3
75 weberror==0.10.3
86 webhelpers2==2.0
76 webhelpers2==2.0
87 webhelpers==1.3
77 webhelpers==1.3
88 webob==1.8.4
78 webob==1.8.5
89 whoosh==2.7.4
79 whoosh==2.7.4
90 wsgiref==0.1.2
80 wsgiref==0.1.2
91 zope.cachedescriptors==4.3.1
81 zope.cachedescriptors==4.3.1
92 zope.deprecation==4.3.0
82 zope.deprecation==4.4.0
93 zope.event==4.3.0
83 zope.event==4.4.0
94 zope.interface==4.5.0
84 zope.interface==4.6.0
95
85
96 # DB drivers
86 # DB drivers
97 mysql-python==1.2.5
87 mysql-python==1.2.5
98 pymysql==0.8.1
88 pymysql==0.8.1
99 pysqlite==2.8.3
89 pysqlite==2.8.3
100 psycopg2==2.7.5
90 psycopg2==2.8.3
101
91
102 # IPYTHON RENDERING
92 # IPYTHON RENDERING
103 # entrypoints backport, pypi version doesn't support egg installs
93 # entrypoints backport, pypi version doesn't support egg installs
104 https://code.rhodecode.com/upstream/entrypoints/archive/96e6d645684e1af3d7df5b5272f3fe85a546b233.tar.gz?md5=7db37771aea9ac9fefe093e5d6987313#egg=entrypoints==0.2.2.rhodecode-upstream1
94 https://code.rhodecode.com/upstream/entrypoints/artifacts/download/0-8e9ee9e4-c4db-409c-b07e-81568fd1832d.tar.gz?md5=3a027b8ff1d257b91fe257de6c43357d#egg=entrypoints==0.2.2.rhodecode-upstream1
105 nbconvert==5.3.1
95 nbconvert==5.3.1
106 nbformat==4.4.0
96 nbformat==4.4.0
107 jupyter_client==5.0.0
97 jupyter_client==5.0.0
108
98
109 ## cli tools
99 ## cli tools
110 alembic==1.0.5
100 alembic==1.0.10
111 invoke==0.13.0
101 invoke==0.13.0
112 bumpversion==0.5.3
102 bumpversion==0.5.3
113
103
@@ -115,15 +105,14 b' bumpversion==0.5.3'
115 gevent==1.4.0
105 gevent==1.4.0
116 greenlet==0.4.15
106 greenlet==0.4.15
117 gunicorn==19.9.0
107 gunicorn==19.9.0
118 waitress==1.1.0
108 waitress==1.3.0
119 setproctitle==1.1.10
120
109
121 ## debug
110 ## debug
122 ipdb==0.11.0
111 ipdb==0.12.0
123 ipython==5.1.0
112 ipython==5.1.0
124
113
125 ## rhodecode-tools, special case
114 ## rhodecode-tools, special case
126 https://code.rhodecode.com/rhodecode-tools-ce/archive/v1.2.1.tar.gz?md5=25bc2f7de1da318e547236d3fb463d28#egg=rhodecode-tools==1.2.1
115 https://code.rhodecode.com/rhodecode-tools-ce/artifacts/download/0-10ac93f4-bb7d-4b97-baea-68110743dd5a.tar.gz?md5=962dc77c06aceee62282b98d33149661#egg=rhodecode-tools==1.2.1
127
116
128 ## appenlight
117 ## appenlight
129 appenlight-client==0.6.26
118 appenlight-client==0.6.26
@@ -10,7 +10,7 b' gprof2dot==2017.9.19'
10
10
11 mock==1.0.1
11 mock==1.0.1
12 cov-core==1.15.0
12 cov-core==1.15.0
13 coverage==4.5.1
13 coverage==4.5.3
14
14
15 webtest==2.0.32
15 webtest==2.0.33
16 beautifulsoup4==4.6.3
16 beautifulsoup4==4.6.3
@@ -1,1 +1,1 b''
1 4.16.2 No newline at end of file
1 4.17.0 No newline at end of file
@@ -45,7 +45,7 b' PYRAMID_SETTINGS = {}'
45 EXTENSIONS = {}
45 EXTENSIONS = {}
46
46
47 __version__ = ('.'.join((str(each) for each in VERSION[:3])))
47 __version__ = ('.'.join((str(each) for each in VERSION[:3])))
48 __dbversion__ = 95 # defines current db version for migrations
48 __dbversion__ = 98 # defines current db version for migrations
49 __platform__ = platform.system()
49 __platform__ = platform.system()
50 __license__ = 'AGPLv3, and Commercial License'
50 __license__ = 'AGPLv3, and Commercial License'
51 __author__ = 'RhodeCode GmbH'
51 __author__ = 'RhodeCode GmbH'
@@ -37,11 +37,11 b' class TestCommentCommit(object):'
37 assert_error(id_, expected, given=response.body)
37 assert_error(id_, expected, given=response.body)
38
38
39 @pytest.mark.parametrize("commit_id, expected_err", [
39 @pytest.mark.parametrize("commit_id, expected_err", [
40 ('abcabca', {'hg': 'Commit {commit} does not exist for {repo}',
40 ('abcabca', {'hg': 'Commit {commit} does not exist for `{repo}`',
41 'git': 'Commit {commit} does not exist for {repo}',
41 'git': 'Commit {commit} does not exist for `{repo}`',
42 'svn': 'Commit id {commit} not understood.'}),
42 'svn': 'Commit id {commit} not understood.'}),
43 ('idontexist', {'hg': 'Commit {commit} does not exist for {repo}',
43 ('idontexist', {'hg': 'Commit {commit} does not exist for `{repo}`',
44 'git': 'Commit {commit} does not exist for {repo}',
44 'git': 'Commit {commit} does not exist for `{repo}`',
45 'svn': 'Commit id {commit} not understood.'}),
45 'svn': 'Commit id {commit} not understood.'}),
46 ])
46 ])
47 def test_api_comment_commit_wrong_hash(self, backend, commit_id, expected_err):
47 def test_api_comment_commit_wrong_hash(self, backend, commit_id, expected_err):
@@ -53,7 +53,7 b' class TestCommentCommit(object):'
53
53
54 expected_err = expected_err[backend.alias]
54 expected_err = expected_err[backend.alias]
55 expected_err = expected_err.format(
55 expected_err = expected_err.format(
56 repo=backend.repo.scm_instance(), commit=commit_id)
56 repo=backend.repo.scm_instance().name, commit=commit_id)
57 assert_error(id_, expected_err, given=response.body)
57 assert_error(id_, expected_err, given=response.body)
58
58
59 @pytest.mark.parametrize("status_change, message, commit_id", [
59 @pytest.mark.parametrize("status_change, message, commit_id", [
@@ -44,6 +44,7 b' class TestGetRepo(object):'
44 self, apikey_attr, expect_secrets, cache_param, backend,
44 self, apikey_attr, expect_secrets, cache_param, backend,
45 user_util):
45 user_util):
46 repo = backend.create_repo()
46 repo = backend.create_repo()
47 repo_id = repo.repo_id
47 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
48 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
48 group = user_util.create_user_group(members=[usr])
49 group = user_util.create_user_group(members=[usr])
49 user_util.grant_user_group_permission_to_repo(
50 user_util.grant_user_group_permission_to_repo(
@@ -64,6 +65,8 b' class TestGetRepo(object):'
64 permissions = expected_permissions(repo)
65 permissions = expected_permissions(repo)
65
66
66 followers = []
67 followers = []
68
69 repo = RepoModel().get(repo_id)
67 for user in repo.followers:
70 for user in repo.followers:
68 followers.append(user.user.get_api_data(
71 followers.append(user.user.get_api_data(
69 include_secrets=expect_secrets))
72 include_secrets=expect_secrets))
@@ -84,6 +87,7 b' class TestGetRepo(object):'
84 # TODO: Depending on which tests are running before this one, we
87 # TODO: Depending on which tests are running before this one, we
85 # start with a different number of permissions in the database.
88 # start with a different number of permissions in the database.
86 repo = RepoModel().get_by_repo_name(backend.repo_name)
89 repo = RepoModel().get_by_repo_name(backend.repo_name)
90 repo_id = repo.repo_id
87 permission_count = len(repo.repo_to_perm)
91 permission_count = len(repo.repo_to_perm)
88
92
89 RepoModel().grant_user_permission(repo=backend.repo_name,
93 RepoModel().grant_user_permission(repo=backend.repo_name,
@@ -102,6 +106,8 b' class TestGetRepo(object):'
102 permissions = expected_permissions(repo)
106 permissions = expected_permissions(repo)
103
107
104 followers = []
108 followers = []
109
110 repo = RepoModel().get(repo_id)
105 for user in repo.followers:
111 for user in repo.followers:
106 followers.append(user.user.get_api_data())
112 followers.append(user.user.get_api_data())
107
113
@@ -444,7 +444,7 b' def get_repo_nodes(request, apiuser, rep'
444 result: [
444 result: [
445 {
445 {
446 "binary": false,
446 "binary": false,
447 "content": "File line\nLine2\n",
447 "content": "File line",
448 "extension": "md",
448 "extension": "md",
449 "lines": 2,
449 "lines": 2,
450 "md5": "059fa5d29b19c0657e384749480f6422",
450 "md5": "059fa5d29b19c0657e384749480f6422",
@@ -529,6 +529,7 b' def get_repo_file(request, apiuser, repo'
529 :param cache: Use internal caches for fetching files. If disabled fetching
529 :param cache: Use internal caches for fetching files. If disabled fetching
530 files is slower but more memory efficient
530 files is slower but more memory efficient
531 :type cache: Optional(bool)
531 :type cache: Optional(bool)
532
532 Example output:
533 Example output:
533
534
534 .. code-block:: bash
535 .. code-block:: bash
@@ -168,6 +168,28 b' class BaseAppView(object):'
168 from rhodecode.lib.base import attach_context_attributes
168 from rhodecode.lib.base import attach_context_attributes
169 attach_context_attributes(c, self.request, self.request.user.user_id)
169 attach_context_attributes(c, self.request, self.request.user.user_id)
170
170
171 c.is_super_admin = c.auth_user.is_admin
172
173 c.can_create_repo = c.is_super_admin
174 c.can_create_repo_group = c.is_super_admin
175 c.can_create_user_group = c.is_super_admin
176
177 c.is_delegated_admin = False
178
179 if not c.auth_user.is_default and not c.is_super_admin:
180 c.can_create_repo = h.HasPermissionAny('hg.create.repository')(
181 user=self.request.user)
182 repositories = c.auth_user.repositories_admin or c.can_create_repo
183
184 c.can_create_repo_group = h.HasPermissionAny('hg.repogroup.create.true')(
185 user=self.request.user)
186 repository_groups = c.auth_user.repository_groups_admin or c.can_create_repo_group
187
188 c.can_create_user_group = h.HasPermissionAny('hg.usergroup.create.true')(
189 user=self.request.user)
190 user_groups = c.auth_user.user_groups_admin or c.can_create_user_group
191 # delegated admin can create, or manage some objects
192 c.is_delegated_admin = repositories or repository_groups or user_groups
171 return c
193 return c
172
194
173 def _get_template_context(self, tmpl_args, **kwargs):
195 def _get_template_context(self, tmpl_args, **kwargs):
@@ -215,12 +237,17 b' class RepoAppView(BaseAppView):'
215 c.rhodecode_db_repo = self.db_repo
237 c.rhodecode_db_repo = self.db_repo
216 c.repo_name = self.db_repo_name
238 c.repo_name = self.db_repo_name
217 c.repository_pull_requests = self.db_repo_pull_requests
239 c.repository_pull_requests = self.db_repo_pull_requests
240 c.repository_is_user_following = ScmModel().is_following_repo(
241 self.db_repo_name, self._rhodecode_user.user_id)
218 self.path_filter = PathFilter(None)
242 self.path_filter = PathFilter(None)
219
243
220 c.repository_requirements_missing = {}
244 c.repository_requirements_missing = {}
221 try:
245 try:
222 self.rhodecode_vcs_repo = self.db_repo.scm_instance()
246 self.rhodecode_vcs_repo = self.db_repo.scm_instance()
223 if self.rhodecode_vcs_repo:
247 # NOTE(marcink):
248 # comparison to None since if it's an object __bool__ is expensive to
249 # calculate
250 if self.rhodecode_vcs_repo is not None:
224 path_perms = self.rhodecode_vcs_repo.get_path_permissions(
251 path_perms = self.rhodecode_vcs_repo.get_path_permissions(
225 c.auth_user.username)
252 c.auth_user.username)
226 self.path_filter = PathFilter(path_perms)
253 self.path_filter = PathFilter(path_perms)
@@ -85,8 +85,6 b' class NavigationRegistry(object):'
85 'admin_settings_hooks'),
85 'admin_settings_hooks'),
86 NavEntry('search', _('Full Text Search'),
86 NavEntry('search', _('Full Text Search'),
87 'admin_settings_search'),
87 'admin_settings_search'),
88 NavEntry('integrations', _('Integrations'),
89 'global_integrations_home'),
90 NavEntry('system', _('System Info'),
88 NavEntry('system', _('System Info'),
91 'admin_settings_system'),
89 'admin_settings_system'),
92 NavEntry('exceptions', _('Exceptions Tracker'),
90 NavEntry('exceptions', _('Exceptions Tracker'),
@@ -424,6 +424,10 b' def admin_routes(config):'
424 pattern='/repo_groups')
424 pattern='/repo_groups')
425
425
426 config.add_route(
426 config.add_route(
427 name='repo_groups_data',
428 pattern='/repo_groups_data')
429
430 config.add_route(
427 name='repo_group_new',
431 name='repo_group_new',
428 pattern='/repo_group/new')
432 pattern='/repo_group/new')
429
433
@@ -46,10 +46,10 b' def route_path(name, params=None, **kwar'
46
46
47 class TestAdminMainView(TestController):
47 class TestAdminMainView(TestController):
48
48
49 def test_redirect_admin_home(self):
49 def test_access_admin_home(self):
50 self.log_user()
50 self.log_user()
51 response = self.app.get(route_path('admin_home'), status=302)
51 response = self.app.get(route_path('admin_home'), status=200)
52 assert response.location.endswith('/audit_logs')
52 response.mustcontain("Administration area")
53
53
54 def test_redirect_pull_request_view(self, view):
54 def test_redirect_pull_request_view(self, view):
55 self.log_user()
55 self.log_user()
@@ -23,11 +23,11 b' import pytest'
23
23
24 from rhodecode.apps._base import ADMIN_PREFIX
24 from rhodecode.apps._base import ADMIN_PREFIX
25 from rhodecode.lib import helpers as h
25 from rhodecode.lib import helpers as h
26 from rhodecode.model.db import Repository, UserRepoToPerm, User
26 from rhodecode.model.db import Repository, UserRepoToPerm, User, RepoGroup
27 from rhodecode.model.meta import Session
27 from rhodecode.model.meta import Session
28 from rhodecode.model.repo_group import RepoGroupModel
28 from rhodecode.model.repo_group import RepoGroupModel
29 from rhodecode.tests import (
29 from rhodecode.tests import (
30 assert_session_flash, TEST_USER_REGULAR_LOGIN, TESTS_TMP_PATH, TestController)
30 assert_session_flash, TEST_USER_REGULAR_LOGIN, TESTS_TMP_PATH)
31 from rhodecode.tests.fixture import Fixture
31 from rhodecode.tests.fixture import Fixture
32
32
33 fixture = Fixture()
33 fixture = Fixture()
@@ -38,6 +38,7 b' def route_path(name, params=None, **kwar'
38
38
39 base_url = {
39 base_url = {
40 'repo_groups': ADMIN_PREFIX + '/repo_groups',
40 'repo_groups': ADMIN_PREFIX + '/repo_groups',
41 'repo_groups_data': ADMIN_PREFIX + '/repo_groups_data',
41 'repo_group_new': ADMIN_PREFIX + '/repo_group/new',
42 'repo_group_new': ADMIN_PREFIX + '/repo_group/new',
42 'repo_group_create': ADMIN_PREFIX + '/repo_group/create',
43 'repo_group_create': ADMIN_PREFIX + '/repo_group/create',
43
44
@@ -59,13 +60,30 b' def _get_permission_for_user(user, repo)'
59
60
60 @pytest.mark.usefixtures("app")
61 @pytest.mark.usefixtures("app")
61 class TestAdminRepositoryGroups(object):
62 class TestAdminRepositoryGroups(object):
63
62 def test_show_repo_groups(self, autologin_user):
64 def test_show_repo_groups(self, autologin_user):
63 response = self.app.get(route_path('repo_groups'))
65 self.app.get(route_path('repo_groups'))
64 response.mustcontain('data: []')
66
67 def test_show_repo_groups_data(self, autologin_user, xhr_header):
68 response = self.app.get(route_path(
69 'repo_groups_data'), extra_environ=xhr_header)
70
71 all_repo_groups = RepoGroup.query().count()
72 assert response.json['recordsTotal'] == all_repo_groups
65
73
66 def test_show_repo_groups_after_creating_group(self, autologin_user):
74 def test_show_repo_groups_data_filtered(self, autologin_user, xhr_header):
75 response = self.app.get(route_path(
76 'repo_groups_data', params={'search[value]': 'empty_search'}),
77 extra_environ=xhr_header)
78
79 all_repo_groups = RepoGroup.query().count()
80 assert response.json['recordsTotal'] == all_repo_groups
81 assert response.json['recordsFiltered'] == 0
82
83 def test_show_repo_groups_after_creating_group(self, autologin_user, xhr_header):
67 fixture.create_repo_group('test_repo_group')
84 fixture.create_repo_group('test_repo_group')
68 response = self.app.get(route_path('repo_groups'))
85 response = self.app.get(route_path(
86 'repo_groups_data'), extra_environ=xhr_header)
69 response.mustcontain('"name_raw": "test_repo_group"')
87 response.mustcontain('"name_raw": "test_repo_group"')
70 fixture.destroy_repo_group('test_repo_group')
88 fixture.destroy_repo_group('test_repo_group')
71
89
@@ -214,8 +214,7 b' class TestAdminSettingsGlobal(object):'
214 })
214 })
215
215
216 response = response.follow()
216 response = response.follow()
217 response.mustcontain(
217 response.mustcontain(new_title)
218 """<div class="branding">- %s</div>""" % new_title)
219
218
220 def post_and_verify_settings(self, settings):
219 def post_and_verify_settings(self, settings):
221 old_title = 'RhodeCode'
220 old_title = 'RhodeCode'
@@ -173,4 +173,4 b' class TestAdminUsersSshKeysView(TestCont'
173
173
174 response.mustcontain('Private key')
174 response.mustcontain('Private key')
175 response.mustcontain('Public key')
175 response.mustcontain('Public key')
176 response.mustcontain('-----BEGIN RSA PRIVATE KEY-----')
176 response.mustcontain('-----BEGIN PRIVATE KEY-----')
@@ -50,7 +50,7 b' class ExceptionsTrackerView(BaseAppView)'
50 count +=1
50 count +=1
51 return count
51 return count
52
52
53 def get_all_exceptions(self, read_metadata=False, limit=None):
53 def get_all_exceptions(self, read_metadata=False, limit=None, type_filter=None):
54 exc_store_path = exc_tracking.get_exc_store()
54 exc_store_path = exc_tracking.get_exc_store()
55 exception_list = []
55 exception_list = []
56
56
@@ -59,7 +59,7 b' class ExceptionsTrackerView(BaseAppView)'
59 return val.split('_')[-1]
59 return val.split('_')[-1]
60 except Exception:
60 except Exception:
61 return 0
61 return 0
62 count = 0
62
63 for fname in reversed(sorted(os.listdir(exc_store_path), key=key_sorter)):
63 for fname in reversed(sorted(os.listdir(exc_store_path), key=key_sorter)):
64
64
65 parts = fname.split('_', 2)
65 parts = fname.split('_', 2)
@@ -83,13 +83,17 b' class ExceptionsTrackerView(BaseAppView)'
83 except Exception:
83 except Exception:
84 log.exception('Failed to read exc data from:{}'.format(full_path))
84 log.exception('Failed to read exc data from:{}'.format(full_path))
85 pass
85 pass
86
87 # convert our timestamp to a date obj, for nicer representation
86 # convert our timestamp to a date obj, for nicer representation
88 exc['exc_utc_date'] = time_to_utcdatetime(exc['exc_timestamp'])
87 exc['exc_utc_date'] = time_to_utcdatetime(exc['exc_timestamp'])
89 exception_list.append(exc)
90
88
91 count += 1
89 type_present = exc.get('exc_type')
92 if limit and count >= limit:
90 if type_filter:
91 if type_present and type_present == type_filter:
92 exception_list.append(exc)
93 else:
94 exception_list.append(exc)
95
96 if limit and len(exception_list) >= limit:
93 break
97 break
94 return exception_list
98 return exception_list
95
99
@@ -103,8 +107,10 b' class ExceptionsTrackerView(BaseAppView)'
103 c = self.load_default_context()
107 c = self.load_default_context()
104 c.active = 'exceptions_browse'
108 c.active = 'exceptions_browse'
105 c.limit = safe_int(self.request.GET.get('limit')) or 50
109 c.limit = safe_int(self.request.GET.get('limit')) or 50
110 c.type_filter = self.request.GET.get('type_filter')
106 c.next_limit = c.limit + 50
111 c.next_limit = c.limit + 50
107 c.exception_list = self.get_all_exceptions(read_metadata=True, limit=c.limit)
112 c.exception_list = self.get_all_exceptions(
113 read_metadata=True, limit=c.limit, type_filter=c.type_filter)
108 c.exception_list_count = self.count_all_exceptions()
114 c.exception_list_count = self.count_all_exceptions()
109 c.exception_store_dir = exc_tracking.get_exc_store()
115 c.exception_store_dir = exc_tracking.get_exc_store()
110 return self._get_template_context(c)
116 return self._get_template_context(c)
@@ -132,12 +138,20 b' class ExceptionsTrackerView(BaseAppView)'
132 def exception_delete_all(self):
138 def exception_delete_all(self):
133 _ = self.request.translate
139 _ = self.request.translate
134 c = self.load_default_context()
140 c = self.load_default_context()
141 type_filter = self.request.POST.get('type_filter')
135
142
136 c.active = 'exceptions'
143 c.active = 'exceptions'
137 all_exc = self.get_all_exceptions()
144 all_exc = self.get_all_exceptions(read_metadata=bool(type_filter), type_filter=type_filter)
138 exc_count = len(all_exc)
145 exc_count = 0
146
139 for exc in all_exc:
147 for exc in all_exc:
140 exc_tracking.delete_exception(exc['exc_id'], prefix=None)
148 if type_filter:
149 if exc.get('exc_type') == type_filter:
150 exc_tracking.delete_exception(exc['exc_id'], prefix=None)
151 exc_count += 1
152 else:
153 exc_tracking.delete_exception(exc['exc_id'], prefix=None)
154 exc_count += 1
141
155
142 h.flash(_('Removed {} Exceptions').format(exc_count), category='success')
156 h.flash(_('Removed {} Exceptions').format(exc_count), category='success')
143 raise HTTPFound(h.route_path('admin_settings_exception_tracker'))
157 raise HTTPFound(h.route_path('admin_settings_exception_tracker'))
@@ -20,12 +20,12 b''
20
20
21 import logging
21 import logging
22
22
23 from pyramid.httpexceptions import HTTPFound
23 from pyramid.httpexceptions import HTTPFound, HTTPNotFound
24 from pyramid.view import view_config
24 from pyramid.view import view_config
25
25
26 from rhodecode.apps._base import BaseAppView
26 from rhodecode.apps._base import BaseAppView
27 from rhodecode.lib import helpers as h
27 from rhodecode.lib import helpers as h
28 from rhodecode.lib.auth import (LoginRequired, HasPermissionAllDecorator)
28 from rhodecode.lib.auth import (LoginRequired, NotAnonymous)
29 from rhodecode.model.db import PullRequest
29 from rhodecode.model.db import PullRequest
30
30
31
31
@@ -33,14 +33,23 b' log = logging.getLogger(__name__)'
33
33
34
34
35 class AdminMainView(BaseAppView):
35 class AdminMainView(BaseAppView):
36 def load_default_context(self):
37 c = self._get_local_tmpl_context()
38 return c
36
39
37 @LoginRequired()
40 @LoginRequired()
38 @HasPermissionAllDecorator('hg.admin')
41 @NotAnonymous()
39 @view_config(
42 @view_config(
40 route_name='admin_home', request_method='GET')
43 route_name='admin_home', request_method='GET',
44 renderer='rhodecode:templates/admin/main.mako')
41 def admin_main(self):
45 def admin_main(self):
42 # redirect _admin to audit logs...
46 c = self.load_default_context()
43 raise HTTPFound(h.route_path('admin_audit_logs'))
47 c.active = 'admin'
48
49 if not (c.is_super_admin or c.is_delegated_admin):
50 raise HTTPNotFound()
51
52 return self._get_template_context(c)
44
53
45 @LoginRequired()
54 @LoginRequired()
46 @view_config(route_name='pull_requests_global_0', request_method='GET')
55 @view_config(route_name='pull_requests_global_0', request_method='GET')
@@ -49,8 +58,7 b' class AdminMainView(BaseAppView):'
49 def pull_requests(self):
58 def pull_requests(self):
50 """
59 """
51 Global redirect for Pull Requests
60 Global redirect for Pull Requests
52
61 pull_request_id: id of pull requests in the system
53 :param pull_request_id: id of pull requests in the system
54 """
62 """
55
63
56 pull_request = PullRequest.get_or_404(
64 pull_request = PullRequest.get_or_404(
@@ -17,7 +17,7 b''
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20 import datetime
21 import logging
21 import logging
22 import formencode
22 import formencode
23 import formencode.htmlfill
23 import formencode.htmlfill
@@ -30,16 +30,16 b' from pyramid.response import Response'
30 from rhodecode import events
30 from rhodecode import events
31 from rhodecode.apps._base import BaseAppView, DataGridAppView
31 from rhodecode.apps._base import BaseAppView, DataGridAppView
32
32
33 from rhodecode.lib.ext_json import json
34 from rhodecode.lib.auth import (
33 from rhodecode.lib.auth import (
35 LoginRequired, CSRFRequired, NotAnonymous,
34 LoginRequired, CSRFRequired, NotAnonymous,
36 HasPermissionAny, HasRepoGroupPermissionAny)
35 HasPermissionAny, HasRepoGroupPermissionAny)
37 from rhodecode.lib import helpers as h, audit_logger
36 from rhodecode.lib import helpers as h, audit_logger
38 from rhodecode.lib.utils2 import safe_int, safe_unicode
37 from rhodecode.lib.utils2 import safe_int, safe_unicode, datetime_to_time
39 from rhodecode.model.forms import RepoGroupForm
38 from rhodecode.model.forms import RepoGroupForm
40 from rhodecode.model.repo_group import RepoGroupModel
39 from rhodecode.model.repo_group import RepoGroupModel
41 from rhodecode.model.scm import RepoGroupList
40 from rhodecode.model.scm import RepoGroupList
42 from rhodecode.model.db import Session, RepoGroup
41 from rhodecode.model.db import (
42 or_, count, func, in_filter_generator, Session, RepoGroup, User, Repository)
43
43
44 log = logging.getLogger(__name__)
44 log = logging.getLogger(__name__)
45
45
@@ -88,22 +88,168 b' class AdminRepoGroupsView(BaseAppView, D'
88 return False
88 return False
89 return False
89 return False
90
90
91 # permission check in data loading of
92 # `repo_group_list_data` via RepoGroupList
91 @LoginRequired()
93 @LoginRequired()
92 @NotAnonymous()
94 @NotAnonymous()
93 # perms check inside
94 @view_config(
95 @view_config(
95 route_name='repo_groups', request_method='GET',
96 route_name='repo_groups', request_method='GET',
96 renderer='rhodecode:templates/admin/repo_groups/repo_groups.mako')
97 renderer='rhodecode:templates/admin/repo_groups/repo_groups.mako')
97 def repo_group_list(self):
98 def repo_group_list(self):
98 c = self.load_default_context()
99 c = self.load_default_context()
100 return self._get_template_context(c)
99
101
100 repo_group_list = RepoGroup.get_all_repo_groups()
102 # permission check inside
101 repo_group_list_acl = RepoGroupList(
103 @LoginRequired()
102 repo_group_list, perm_set=['group.admin'])
104 @NotAnonymous()
103 repo_group_data = RepoGroupModel().get_repo_groups_as_dict(
105 @view_config(
104 repo_group_list=repo_group_list_acl, admin=True)
106 route_name='repo_groups_data', request_method='GET',
105 c.data = json.dumps(repo_group_data)
107 renderer='json_ext', xhr=True)
106 return self._get_template_context(c)
108 def repo_group_list_data(self):
109 self.load_default_context()
110 column_map = {
111 'name_raw': 'group_name_hash',
112 'desc': 'group_description',
113 'last_change_raw': 'updated_on',
114 'top_level_repos': 'repos_total',
115 'owner': 'user_username',
116 }
117 draw, start, limit = self._extract_chunk(self.request)
118 search_q, order_by, order_dir = self._extract_ordering(
119 self.request, column_map=column_map)
120
121 _render = self.request.get_partial_renderer(
122 'rhodecode:templates/data_table/_dt_elements.mako')
123 c = _render.get_call_context()
124
125 def quick_menu(repo_group_name):
126 return _render('quick_repo_group_menu', repo_group_name)
127
128 def repo_group_lnk(repo_group_name):
129 return _render('repo_group_name', repo_group_name)
130
131 def last_change(last_change):
132 if isinstance(last_change, datetime.datetime) and not last_change.tzinfo:
133 delta = datetime.timedelta(
134 seconds=(datetime.datetime.now() - datetime.datetime.utcnow()).seconds)
135 last_change = last_change + delta
136 return _render("last_change", last_change)
137
138 def desc(desc, personal):
139 return _render(
140 'repo_group_desc', desc, personal, c.visual.stylify_metatags)
141
142 def repo_group_actions(repo_group_id, repo_group_name, gr_count):
143 return _render(
144 'repo_group_actions', repo_group_id, repo_group_name, gr_count)
145
146 def user_profile(username):
147 return _render('user_profile', username)
148
149 auth_repo_group_list = RepoGroupList(
150 RepoGroup.query().all(), perm_set=['group.admin'])
151
152 allowed_ids = [-1]
153 for repo_group in auth_repo_group_list:
154 allowed_ids.append(repo_group.group_id)
155
156 repo_groups_data_total_count = RepoGroup.query()\
157 .filter(or_(
158 # generate multiple IN to fix limitation problems
159 *in_filter_generator(RepoGroup.group_id, allowed_ids)
160 )) \
161 .count()
162
163 repo_groups_data_total_inactive_count = RepoGroup.query()\
164 .filter(RepoGroup.group_id.in_(allowed_ids))\
165 .count()
166
167 repo_count = count(Repository.repo_id)
168 base_q = Session.query(
169 RepoGroup.group_name,
170 RepoGroup.group_name_hash,
171 RepoGroup.group_description,
172 RepoGroup.group_id,
173 RepoGroup.personal,
174 RepoGroup.updated_on,
175 User,
176 repo_count.label('repos_count')
177 ) \
178 .filter(or_(
179 # generate multiple IN to fix limitation problems
180 *in_filter_generator(RepoGroup.group_id, allowed_ids)
181 )) \
182 .outerjoin(Repository) \
183 .join(User, User.user_id == RepoGroup.user_id) \
184 .group_by(RepoGroup, User)
185
186 if search_q:
187 like_expression = u'%{}%'.format(safe_unicode(search_q))
188 base_q = base_q.filter(or_(
189 RepoGroup.group_name.ilike(like_expression),
190 ))
191
192 repo_groups_data_total_filtered_count = base_q.count()
193 # the inactive isn't really used, but we still make it same as other data grids
194 # which use inactive (users,user groups)
195 repo_groups_data_total_filtered_inactive_count = repo_groups_data_total_filtered_count
196
197 sort_defined = False
198 if order_by == 'group_name':
199 sort_col = func.lower(RepoGroup.group_name)
200 sort_defined = True
201 elif order_by == 'repos_total':
202 sort_col = repo_count
203 sort_defined = True
204 elif order_by == 'user_username':
205 sort_col = User.username
206 else:
207 sort_col = getattr(RepoGroup, order_by, None)
208
209 if sort_defined or sort_col:
210 if order_dir == 'asc':
211 sort_col = sort_col.asc()
212 else:
213 sort_col = sort_col.desc()
214
215 base_q = base_q.order_by(sort_col)
216 base_q = base_q.offset(start).limit(limit)
217
218 # authenticated access to user groups
219 auth_repo_group_list = base_q.all()
220
221 repo_groups_data = []
222 for repo_gr in auth_repo_group_list:
223 row = {
224 "menu": quick_menu(repo_gr.group_name),
225 "name": repo_group_lnk(repo_gr.group_name),
226 "name_raw": repo_gr.group_name,
227 "last_change": last_change(repo_gr.updated_on),
228 "last_change_raw": datetime_to_time(repo_gr.updated_on),
229
230 "last_changeset": "",
231 "last_changeset_raw": "",
232
233 "desc": desc(repo_gr.group_description, repo_gr.personal),
234 "owner": user_profile(repo_gr.User.username),
235 "top_level_repos": repo_gr.repos_count,
236 "action": repo_group_actions(
237 repo_gr.group_id, repo_gr.group_name, repo_gr.repos_count),
238
239 }
240
241 repo_groups_data.append(row)
242
243 data = ({
244 'draw': draw,
245 'data': repo_groups_data,
246 'recordsTotal': repo_groups_data_total_count,
247 'recordsTotalInactive': repo_groups_data_total_inactive_count,
248 'recordsFiltered': repo_groups_data_total_filtered_count,
249 'recordsFilteredInactive': repo_groups_data_total_filtered_inactive_count,
250 })
251
252 return data
107
253
108 @LoginRequired()
254 @LoginRequired()
109 @NotAnonymous()
255 @NotAnonymous()
@@ -39,7 +39,7 b' from rhodecode.model.forms import UserGr'
39 from rhodecode.model.permission import PermissionModel
39 from rhodecode.model.permission import PermissionModel
40 from rhodecode.model.scm import UserGroupList
40 from rhodecode.model.scm import UserGroupList
41 from rhodecode.model.db import (
41 from rhodecode.model.db import (
42 or_, count, User, UserGroup, UserGroupMember)
42 or_, count, User, UserGroup, UserGroupMember, in_filter_generator)
43 from rhodecode.model.meta import Session
43 from rhodecode.model.meta import Session
44 from rhodecode.model.user_group import UserGroupModel
44 from rhodecode.model.user_group import UserGroupModel
45 from rhodecode.model.db import true
45 from rhodecode.model.db import true
@@ -107,11 +107,17 b' class AdminUserGroupsView(BaseAppView, D'
107 allowed_ids.append(user_group.users_group_id)
107 allowed_ids.append(user_group.users_group_id)
108
108
109 user_groups_data_total_count = UserGroup.query()\
109 user_groups_data_total_count = UserGroup.query()\
110 .filter(UserGroup.users_group_id.in_(allowed_ids))\
110 .filter(or_(
111 # generate multiple IN to fix limitation problems
112 *in_filter_generator(UserGroup.users_group_id, allowed_ids)
113 ))\
111 .count()
114 .count()
112
115
113 user_groups_data_total_inactive_count = UserGroup.query()\
116 user_groups_data_total_inactive_count = UserGroup.query()\
114 .filter(UserGroup.users_group_id.in_(allowed_ids))\
117 .filter(or_(
118 # generate multiple IN to fix limitation problems
119 *in_filter_generator(UserGroup.users_group_id, allowed_ids)
120 ))\
115 .filter(UserGroup.users_group_active != true()).count()
121 .filter(UserGroup.users_group_active != true()).count()
116
122
117 member_count = count(UserGroupMember.user_id)
123 member_count = count(UserGroupMember.user_id)
@@ -123,11 +129,14 b' class AdminUserGroupsView(BaseAppView, D'
123 UserGroup.group_data,
129 UserGroup.group_data,
124 User,
130 User,
125 member_count.label('member_count')
131 member_count.label('member_count')
126 ) \
132 ) \
127 .filter(UserGroup.users_group_id.in_(allowed_ids)) \
133 .filter(or_(
128 .outerjoin(UserGroupMember) \
134 # generate multiple IN to fix limitation problems
129 .join(User, User.user_id == UserGroup.user_id) \
135 *in_filter_generator(UserGroup.users_group_id, allowed_ids)
130 .group_by(UserGroup, User)
136 )) \
137 .outerjoin(UserGroupMember) \
138 .join(User, User.user_id == UserGroup.user_id) \
139 .group_by(UserGroup, User)
131
140
132 base_q_inactive = base_q.filter(UserGroup.users_group_active != true())
141 base_q_inactive = base_q.filter(UserGroup.users_group_active != true())
133
142
@@ -141,14 +150,16 b' class AdminUserGroupsView(BaseAppView, D'
141 user_groups_data_total_filtered_count = base_q.count()
150 user_groups_data_total_filtered_count = base_q.count()
142 user_groups_data_total_filtered_inactive_count = base_q_inactive.count()
151 user_groups_data_total_filtered_inactive_count = base_q_inactive.count()
143
152
153 sort_defined = False
144 if order_by == 'members_total':
154 if order_by == 'members_total':
145 sort_col = member_count
155 sort_col = member_count
156 sort_defined = True
146 elif order_by == 'user_username':
157 elif order_by == 'user_username':
147 sort_col = User.username
158 sort_col = User.username
148 else:
159 else:
149 sort_col = getattr(UserGroup, order_by, None)
160 sort_col = getattr(UserGroup, order_by, None)
150
161
151 if isinstance(sort_col, count) or sort_col:
162 if sort_defined or sort_col:
152 if order_dir == 'asc':
163 if order_dir == 'asc':
153 sort_col = sort_col.asc()
164 sort_col = sort_col.asc()
154 else:
165 else:
@@ -162,7 +173,7 b' class AdminUserGroupsView(BaseAppView, D'
162
173
163 user_groups_data = []
174 user_groups_data = []
164 for user_gr in auth_user_group_list:
175 for user_gr in auth_user_group_list:
165 user_groups_data.append({
176 row = {
166 "users_group_name": user_group_name(user_gr.users_group_name),
177 "users_group_name": user_group_name(user_gr.users_group_name),
167 "name_raw": h.escape(user_gr.users_group_name),
178 "name_raw": h.escape(user_gr.users_group_name),
168 "description": h.escape(user_gr.user_group_description),
179 "description": h.escape(user_gr.user_group_description),
@@ -175,7 +186,8 b' class AdminUserGroupsView(BaseAppView, D'
175 "owner": user_profile(user_gr.User.username),
186 "owner": user_profile(user_gr.User.username),
176 "action": user_group_actions(
187 "action": user_group_actions(
177 user_gr.users_group_id, user_gr.users_group_name)
188 user_gr.users_group_id, user_gr.users_group_name)
178 })
189 }
190 user_groups_data.append(row)
179
191
180 data = ({
192 data = ({
181 'draw': draw,
193 'draw': draw,
@@ -682,8 +682,7 b' class UsersView(UserAppView):'
682 if personal_repo_group:
682 if personal_repo_group:
683 raise HTTPFound(h.route_path('user_edit_advanced', user_id=user_id))
683 raise HTTPFound(h.route_path('user_edit_advanced', user_id=user_id))
684
684
685 personal_repo_group_name = RepoGroupModel().get_personal_group_name(
685 personal_repo_group_name = RepoGroupModel().get_personal_group_name(c.user)
686 c.user)
687 named_personal_group = RepoGroup.get_by_group_name(
686 named_personal_group = RepoGroup.get_by_group_name(
688 personal_repo_group_name)
687 personal_repo_group_name)
689 try:
688 try:
@@ -38,19 +38,18 b' class LocalFileStorage(object):'
38 """
38 """
39 Resolves a unique name and the correct path. If a filename
39 Resolves a unique name and the correct path. If a filename
40 for that path already exists then a numeric prefix with values > 0 will be
40 for that path already exists then a numeric prefix with values > 0 will be
41 added, for example test.jpg -> test-1.jpg etc. initially file would have 0 prefix.
41 added, for example test.jpg -> 1-test.jpg etc. initially file would have 0 prefix.
42
42
43 :param name: base name of file
43 :param name: base name of file
44 :param directory: absolute directory path
44 :param directory: absolute directory path
45 """
45 """
46
46
47 basename, ext = os.path.splitext(name)
48 counter = 0
47 counter = 0
49 while True:
48 while True:
50 name = '%s-%d%s' % (basename, counter, ext)
49 name = '%d-%s' % (counter, name)
51
50
52 # sub_store prefix to optimize disk usage, e.g some_path/ab/final_file
51 # sub_store prefix to optimize disk usage, e.g some_path/ab/final_file
53 sub_store = cls._sub_store_from_filename(basename)
52 sub_store = cls._sub_store_from_filename(name)
54 sub_store_path = os.path.join(directory, sub_store)
53 sub_store_path = os.path.join(directory, sub_store)
55 if not os.path.exists(sub_store_path):
54 if not os.path.exists(sub_store_path):
56 os.makedirs(sub_store_path)
55 os.makedirs(sub_store_path)
@@ -209,3 +208,16 b' class LocalFileStorage(object):'
209 filename = os.path.join(directory, filename)
208 filename = os.path.join(directory, filename)
210
209
211 return filename, metadata
210 return filename, metadata
211
212 def get_metadata(self, filename):
213 """
214 Reads JSON stored metadata for a file
215
216 :param filename:
217 :return:
218 """
219 filename = self.store_path(filename)
220 filename_meta = filename + '.meta'
221
222 with open(filename_meta, "rb") as source_meta:
223 return json.loads(source_meta.read())
@@ -21,6 +21,7 b' import os'
21 import pytest
21 import pytest
22
22
23 from rhodecode.lib.ext_json import json
23 from rhodecode.lib.ext_json import json
24 from rhodecode.model.db import Session, FileStore
24 from rhodecode.tests import TestController
25 from rhodecode.tests import TestController
25 from rhodecode.apps.file_store import utils, config_keys
26 from rhodecode.apps.file_store import utils, config_keys
26
27
@@ -46,9 +47,12 b' class TestFileStoreViews(TestController)'
46 ('abcde-0.exe', "1234567", True),
47 ('abcde-0.exe', "1234567", True),
47 ('abcde-0.jpg', "xxxxx", False),
48 ('abcde-0.jpg', "xxxxx", False),
48 ])
49 ])
49 def test_get_files_from_store(self, fid, content, exists, tmpdir):
50 def test_get_files_from_store(self, fid, content, exists, tmpdir, user_util):
50 self.log_user()
51 user = self.log_user()
52 user_id = user['user_id']
53 repo_id = user_util.create_repo().repo_id
51 store_path = self.app._pyramid_settings[config_keys.store_path]
54 store_path = self.app._pyramid_settings[config_keys.store_path]
55 store_uid = fid
52
56
53 if exists:
57 if exists:
54 status = 200
58 status = 200
@@ -58,17 +62,28 b' class TestFileStoreViews(TestController)'
58 f.write(content)
62 f.write(content)
59
63
60 with open(filesystem_file, 'rb') as f:
64 with open(filesystem_file, 'rb') as f:
61 fid, metadata = store.save_file(f, fid, extra_metadata={'filename': fid})
65 store_uid, metadata = store.save_file(f, fid, extra_metadata={'filename': fid})
66
67 entry = FileStore.create(
68 file_uid=store_uid, filename=metadata["filename"],
69 file_hash=metadata["sha256"], file_size=metadata["size"],
70 file_display_name='file_display_name',
71 file_description='repo artifact `{}`'.format(metadata["filename"]),
72 check_acl=True, user_id=user_id,
73 scope_repo_id=repo_id
74 )
75 Session().add(entry)
76 Session().commit()
62
77
63 else:
78 else:
64 status = 404
79 status = 404
65
80
66 response = self.app.get(route_path('download_file', fid=fid), status=status)
81 response = self.app.get(route_path('download_file', fid=store_uid), status=status)
67
82
68 if exists:
83 if exists:
69 assert response.text == content
84 assert response.text == content
70 file_store_path = os.path.dirname(store.resolve_name(fid, store_path)[1])
85 file_store_path = os.path.dirname(store.resolve_name(store_uid, store_path)[1])
71 metadata_file = os.path.join(file_store_path, fid + '.meta')
86 metadata_file = os.path.join(file_store_path, store_uid + '.meta')
72 assert os.path.exists(metadata_file)
87 assert os.path.exists(metadata_file)
73 with open(metadata_file, 'rb') as f:
88 with open(metadata_file, 'rb') as f:
74 json_data = json.loads(f.read())
89 json_data = json.loads(f.read())
@@ -19,9 +19,10 b''
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21
21
22 import os
23 import uuid
22 import uuid
24
23
24 import pathlib2
25
25
26
26 def get_file_storage(settings):
27 def get_file_storage(settings):
27 from rhodecode.apps.file_store.local_store import LocalFileStorage
28 from rhodecode.apps.file_store.local_store import LocalFileStorage
@@ -30,6 +31,11 b' def get_file_storage(settings):'
30 return LocalFileStorage(base_path=store_path)
31 return LocalFileStorage(base_path=store_path)
31
32
32
33
34 def splitext(filename):
35 ext = ''.join(pathlib2.Path(filename).suffixes)
36 return filename, ext
37
38
33 def uid_filename(filename, randomized=True):
39 def uid_filename(filename, randomized=True):
34 """
40 """
35 Generates a randomized or stable (uuid) filename,
41 Generates a randomized or stable (uuid) filename,
@@ -38,7 +44,8 b' def uid_filename(filename, randomized=Tr'
38 :param filename: the original filename
44 :param filename: the original filename
39 :param randomized: define if filename should be stable (sha1 based) or randomized
45 :param randomized: define if filename should be stable (sha1 based) or randomized
40 """
46 """
41 _, ext = os.path.splitext(filename)
47
48 _, ext = splitext(filename)
42 if randomized:
49 if randomized:
43 uid = uuid.uuid4()
50 uid = uuid.uuid4()
44 else:
51 else:
@@ -30,7 +30,7 b' from rhodecode.apps.file_store.exception'
30
30
31 from rhodecode.lib import helpers as h
31 from rhodecode.lib import helpers as h
32 from rhodecode.lib import audit_logger
32 from rhodecode.lib import audit_logger
33 from rhodecode.lib.auth import (CSRFRequired, NotAnonymous)
33 from rhodecode.lib.auth import (CSRFRequired, NotAnonymous, HasRepoPermissionAny, HasRepoGroupPermissionAny)
34 from rhodecode.model.db import Session, FileStore
34 from rhodecode.model.db import Session, FileStore
35
35
36 log = logging.getLogger(__name__)
36 log = logging.getLogger(__name__)
@@ -68,7 +68,7 b' class FileStoreView(BaseAppView):'
68 'user_id': self._rhodecode_user.user_id,
68 'user_id': self._rhodecode_user.user_id,
69 'ip': self._rhodecode_user.ip_addr}}
69 'ip': self._rhodecode_user.ip_addr}}
70 try:
70 try:
71 store_fid, metadata = self.storage.save_file(
71 store_uid, metadata = self.storage.save_file(
72 file_obj.file, filename, extra_metadata=metadata)
72 file_obj.file, filename, extra_metadata=metadata)
73 except FileNotAllowedException:
73 except FileNotAllowedException:
74 return {'store_fid': None,
74 return {'store_fid': None,
@@ -82,7 +82,7 b' class FileStoreView(BaseAppView):'
82
82
83 try:
83 try:
84 entry = FileStore.create(
84 entry = FileStore.create(
85 file_uid=store_fid, filename=metadata["filename"],
85 file_uid=store_uid, filename=metadata["filename"],
86 file_hash=metadata["sha256"], file_size=metadata["size"],
86 file_hash=metadata["sha256"], file_size=metadata["size"],
87 file_description='upload attachment',
87 file_description='upload attachment',
88 check_acl=False, user_id=self._rhodecode_user.user_id
88 check_acl=False, user_id=self._rhodecode_user.user_id
@@ -96,8 +96,8 b' class FileStoreView(BaseAppView):'
96 'access_path': None,
96 'access_path': None,
97 'error': 'File {} failed to store in DB.'.format(filename)}
97 'error': 'File {} failed to store in DB.'.format(filename)}
98
98
99 return {'store_fid': store_fid,
99 return {'store_fid': store_uid,
100 'access_path': h.route_path('download_file', fid=store_fid)}
100 'access_path': h.route_path('download_file', fid=store_uid)}
101
101
102 @view_config(route_name='download_file')
102 @view_config(route_name='download_file')
103 def download_file(self):
103 def download_file(self):
@@ -109,6 +109,35 b' class FileStoreView(BaseAppView):'
109 log.debug('File with FID:%s not found in the store', file_uid)
109 log.debug('File with FID:%s not found in the store', file_uid)
110 raise HTTPNotFound()
110 raise HTTPNotFound()
111
111
112 db_obj = FileStore().query().filter(FileStore.file_uid == file_uid).scalar()
113 if not db_obj:
114 raise HTTPNotFound()
115
116 # private upload for user
117 if db_obj.check_acl and db_obj.scope_user_id:
118 user = db_obj.user
119 if self._rhodecode_db_user.user_id != user.user_id:
120 log.warning('Access to file store object forbidden')
121 raise HTTPNotFound()
122
123 # scoped to repository permissions
124 if db_obj.check_acl and db_obj.scope_repo_id:
125 repo = db_obj.repo
126 perm_set = ['repository.read', 'repository.write', 'repository.admin']
127 has_perm = HasRepoPermissionAny(*perm_set)(repo.repo_name, 'FileStore check')
128 if not has_perm:
129 log.warning('Access to file store object forbidden')
130 raise HTTPNotFound()
131
132 # scoped to repository group permissions
133 if db_obj.check_acl and db_obj.scope_repo_group_id:
134 repo_group = db_obj.repo_group
135 perm_set = ['group.read', 'group.write', 'group.admin']
136 has_perm = HasRepoGroupPermissionAny(*perm_set)(repo_group.group_name, 'FileStore check')
137 if not has_perm:
138 log.warning('Access to file store object forbidden')
139 raise HTTPNotFound()
140
112 FileStore.bump_access_counter(file_uid)
141 FileStore.bump_access_counter(file_uid)
113
142
114 file_path = self.storage.store_path(file_uid)
143 file_path = self.storage.store_path(file_uid)
@@ -25,7 +25,7 b' import formencode'
25 import formencode.htmlfill
25 import formencode.htmlfill
26 import peppercorn
26 import peppercorn
27
27
28 from pyramid.httpexceptions import HTTPNotFound, HTTPFound
28 from pyramid.httpexceptions import HTTPNotFound, HTTPFound, HTTPBadRequest
29 from pyramid.view import view_config
29 from pyramid.view import view_config
30 from pyramid.renderers import render
30 from pyramid.renderers import render
31 from pyramid.response import Response
31 from pyramid.response import Response
@@ -67,7 +67,6 b' class GistView(BaseAppView):'
67 (Gist.ACL_LEVEL_PUBLIC, _("Can be accessed by anonymous users"))
67 (Gist.ACL_LEVEL_PUBLIC, _("Can be accessed by anonymous users"))
68 ]
68 ]
69
69
70
71 return c
70 return c
72
71
73 @LoginRequired()
72 @LoginRequired()
@@ -296,6 +295,8 b' class GistView(BaseAppView):'
296 response = Response(content)
295 response = Response(content)
297 response.content_type = 'text/plain'
296 response.content_type = 'text/plain'
298 return response
297 return response
298 elif return_format:
299 raise HTTPBadRequest()
299
300
300 return self._get_template_context(c)
301 return self._get_template_context(c)
301
302
@@ -68,6 +68,10 b' def includeme(config):'
68 pattern='/_markup_preview')
68 pattern='/_markup_preview')
69
69
70 config.add_route(
70 config.add_route(
71 name='file_preview',
72 pattern='/_file_preview')
73
74 config.add_route(
71 name='store_user_session_value',
75 name='store_user_session_value',
72 pattern='/_store_session_attr')
76 pattern='/_store_session_attr')
73
77
@@ -27,13 +27,14 b' from pyramid.view import view_config'
27 from rhodecode.apps._base import BaseAppView
27 from rhodecode.apps._base import BaseAppView
28 from rhodecode.lib import helpers as h
28 from rhodecode.lib import helpers as h
29 from rhodecode.lib.auth import (
29 from rhodecode.lib.auth import (
30 LoginRequired, NotAnonymous, HasRepoGroupPermissionAnyDecorator,
30 LoginRequired, NotAnonymous, HasRepoGroupPermissionAnyDecorator, CSRFRequired)
31 CSRFRequired)
31 from rhodecode.lib.codeblocks import filenode_as_lines_tokens
32 from rhodecode.lib.index import searcher_from_config
32 from rhodecode.lib.index import searcher_from_config
33 from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int
33 from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int
34 from rhodecode.lib.ext_json import json
34 from rhodecode.lib.ext_json import json
35 from rhodecode.lib.vcs.nodes import FileNode
35 from rhodecode.model.db import (
36 from rhodecode.model.db import (
36 func, true, or_, in_filter_generator, Repository, RepoGroup, User, UserGroup)
37 func, true, or_, case, in_filter_generator, Repository, RepoGroup, User, UserGroup)
37 from rhodecode.model.repo import RepoModel
38 from rhodecode.model.repo import RepoModel
38 from rhodecode.model.repo_group import RepoGroupModel
39 from rhodecode.model.repo_group import RepoGroupModel
39 from rhodecode.model.scm import RepoGroupList, RepoList
40 from rhodecode.model.scm import RepoGroupList, RepoList
@@ -105,21 +106,27 b' class HomeView(BaseAppView):'
105
106
106 return {'suggestions': _user_groups}
107 return {'suggestions': _user_groups}
107
108
108 def _get_repo_list(self, name_contains=None, repo_type=None, limit=20):
109 def _get_repo_list(self, name_contains=None, repo_type=None, repo_group_name='', limit=20):
109 org_query = name_contains
110 org_query = name_contains
110 allowed_ids = self._rhodecode_user.repo_acl_ids(
111 allowed_ids = self._rhodecode_user.repo_acl_ids(
111 ['repository.read', 'repository.write', 'repository.admin'],
112 ['repository.read', 'repository.write', 'repository.admin'],
112 cache=False, name_filter=name_contains) or [-1]
113 cache=False, name_filter=name_contains) or [-1]
113
114
114 query = Repository.query()\
115 query = Repository.query()\
115 .order_by(func.length(Repository.repo_name))\
116 .order_by(Repository.repo_name)\
117 .filter(Repository.archived.isnot(true()))\
116 .filter(Repository.archived.isnot(true()))\
118 .filter(or_(
117 .filter(or_(
119 # generate multiple IN to fix limitation problems
118 # generate multiple IN to fix limitation problems
120 *in_filter_generator(Repository.repo_id, allowed_ids)
119 *in_filter_generator(Repository.repo_id, allowed_ids)
121 ))
120 ))
122
121
122 query = query.order_by(case(
123 [
124 (Repository.repo_name.startswith(repo_group_name), repo_group_name+'/'),
125 ],
126 ))
127 query = query.order_by(func.length(Repository.repo_name))
128 query = query.order_by(Repository.repo_name)
129
123 if repo_type:
130 if repo_type:
124 query = query.filter(Repository.repo_type == repo_type)
131 query = query.filter(Repository.repo_type == repo_type)
125
132
@@ -145,20 +152,26 b' class HomeView(BaseAppView):'
145 }
152 }
146 for obj in acl_iter]
153 for obj in acl_iter]
147
154
148 def _get_repo_group_list(self, name_contains=None, limit=20):
155 def _get_repo_group_list(self, name_contains=None, repo_group_name='', limit=20):
149 org_query = name_contains
156 org_query = name_contains
150 allowed_ids = self._rhodecode_user.repo_group_acl_ids(
157 allowed_ids = self._rhodecode_user.repo_group_acl_ids(
151 ['group.read', 'group.write', 'group.admin'],
158 ['group.read', 'group.write', 'group.admin'],
152 cache=False, name_filter=name_contains) or [-1]
159 cache=False, name_filter=name_contains) or [-1]
153
160
154 query = RepoGroup.query()\
161 query = RepoGroup.query()\
155 .order_by(func.length(RepoGroup.group_name))\
156 .order_by(RepoGroup.group_name) \
157 .filter(or_(
162 .filter(or_(
158 # generate multiple IN to fix limitation problems
163 # generate multiple IN to fix limitation problems
159 *in_filter_generator(RepoGroup.group_id, allowed_ids)
164 *in_filter_generator(RepoGroup.group_id, allowed_ids)
160 ))
165 ))
161
166
167 query = query.order_by(case(
168 [
169 (RepoGroup.group_name.startswith(repo_group_name), repo_group_name+'/'),
170 ],
171 ))
172 query = query.order_by(func.length(RepoGroup.group_name))
173 query = query.order_by(RepoGroup.group_name)
174
162 if name_contains:
175 if name_contains:
163 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
176 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
164 query = query.filter(
177 query = query.filter(
@@ -183,11 +196,17 b' class HomeView(BaseAppView):'
183 def _get_user_list(self, name_contains=None, limit=20):
196 def _get_user_list(self, name_contains=None, limit=20):
184 org_query = name_contains
197 org_query = name_contains
185 if not name_contains:
198 if not name_contains:
186 return []
199 return [], False
187
200
188 name_contains = re.compile('(?:user:)(.+)').findall(name_contains)
201 # TODO(marcink): should all logged in users be allowed to search others?
202 allowed_user_search = self._rhodecode_user.username != User.DEFAULT_USER
203 if not allowed_user_search:
204 return [], False
205
206 name_contains = re.compile('(?:user:[ ]?)(.+)').findall(name_contains)
189 if len(name_contains) != 1:
207 if len(name_contains) != 1:
190 return []
208 return [], False
209
191 name_contains = name_contains[0]
210 name_contains = name_contains[0]
192
211
193 query = User.query()\
212 query = User.query()\
@@ -207,22 +226,28 b' class HomeView(BaseAppView):'
207 {
226 {
208 'id': obj.user_id,
227 'id': obj.user_id,
209 'value': org_query,
228 'value': org_query,
210 'value_display': obj.username,
229 'value_display': 'user: `{}`'.format(obj.username),
211 'type': 'user',
230 'type': 'user',
212 'icon_link': h.gravatar_url(obj.email, 30),
231 'icon_link': h.gravatar_url(obj.email, 30),
213 'url': h.route_path(
232 'url': h.route_path(
214 'user_profile', username=obj.username)
233 'user_profile', username=obj.username)
215 }
234 }
216 for obj in acl_iter]
235 for obj in acl_iter], True
217
236
218 def _get_user_groups_list(self, name_contains=None, limit=20):
237 def _get_user_groups_list(self, name_contains=None, limit=20):
219 org_query = name_contains
238 org_query = name_contains
220 if not name_contains:
239 if not name_contains:
221 return []
240 return [], False
222
241
223 name_contains = re.compile('(?:user_group:)(.+)').findall(name_contains)
242 # TODO(marcink): should all logged in users be allowed to search others?
243 allowed_user_search = self._rhodecode_user.username != User.DEFAULT_USER
244 if not allowed_user_search:
245 return [], False
246
247 name_contains = re.compile('(?:user_group:[ ]?)(.+)').findall(name_contains)
224 if len(name_contains) != 1:
248 if len(name_contains) != 1:
225 return []
249 return [], False
250
226 name_contains = name_contains[0]
251 name_contains = name_contains[0]
227
252
228 query = UserGroup.query()\
253 query = UserGroup.query()\
@@ -241,27 +266,34 b' class HomeView(BaseAppView):'
241 {
266 {
242 'id': obj.users_group_id,
267 'id': obj.users_group_id,
243 'value': org_query,
268 'value': org_query,
244 'value_display': obj.users_group_name,
269 'value_display': 'user_group: `{}`'.format(obj.users_group_name),
245 'type': 'user_group',
270 'type': 'user_group',
246 'url': h.route_path(
271 'url': h.route_path(
247 'user_group_profile', user_group_name=obj.users_group_name)
272 'user_group_profile', user_group_name=obj.users_group_name)
248 }
273 }
249 for obj in acl_iter]
274 for obj in acl_iter], True
250
275
251 def _get_hash_commit_list(self, auth_user, searcher, query):
276 def _get_hash_commit_list(self, auth_user, searcher, query, repo=None, repo_group=None):
277 repo_name = repo_group_name = None
278 if repo:
279 repo_name = repo.repo_name
280 if repo_group:
281 repo_group_name = repo_group.group_name
282
252 org_query = query
283 org_query = query
253 if not query or len(query) < 3 or not searcher:
284 if not query or len(query) < 3 or not searcher:
254 return []
285 return [], False
255
286
256 commit_hashes = re.compile('(?:commit:)([0-9a-f]{2,40})').findall(query)
287 commit_hashes = re.compile('(?:commit:[ ]?)([0-9a-f]{2,40})').findall(query)
257
288
258 if len(commit_hashes) != 1:
289 if len(commit_hashes) != 1:
259 return []
290 return [], False
291
260 commit_hash = commit_hashes[0]
292 commit_hash = commit_hashes[0]
261
293
262 result = searcher.search(
294 result = searcher.search(
263 'commit_id:{}*'.format(commit_hash), 'commit', auth_user,
295 'commit_id:{}*'.format(commit_hash), 'commit', auth_user,
264 raise_on_exc=False)
296 repo_name, repo_group_name, raise_on_exc=False)
265
297
266 commits = []
298 commits = []
267 for entry in result['results']:
299 for entry in result['results']:
@@ -286,7 +318,55 b' class HomeView(BaseAppView):'
286 }
318 }
287
319
288 commits.append(commit_entry)
320 commits.append(commit_entry)
289 return commits
321 return commits, True
322
323 def _get_path_list(self, auth_user, searcher, query, repo=None, repo_group=None):
324 repo_name = repo_group_name = None
325 if repo:
326 repo_name = repo.repo_name
327 if repo_group:
328 repo_group_name = repo_group.group_name
329
330 org_query = query
331 if not query or len(query) < 3 or not searcher:
332 return [], False
333
334 paths_re = re.compile('(?:file:[ ]?)(.+)').findall(query)
335 if len(paths_re) != 1:
336 return [], False
337
338 file_path = paths_re[0]
339
340 search_path = searcher.escape_specials(file_path)
341 result = searcher.search(
342 'file.raw:*{}*'.format(search_path), 'path', auth_user,
343 repo_name, repo_group_name, raise_on_exc=False)
344
345 files = []
346 for entry in result['results']:
347 repo_data = {
348 'repository_id': entry.get('repository_id'),
349 'repository_type': entry.get('repo_type'),
350 'repository_name': entry.get('repository'),
351 }
352
353 file_entry = {
354 'id': entry['commit_id'],
355 'value': org_query,
356 'value_display': '`{}` file: {}'.format(
357 entry['repository'], entry['file']),
358 'type': 'file',
359 'repo': entry['repository'],
360 'repo_data': repo_data,
361
362 'url': h.route_path(
363 'repo_files',
364 repo_name=entry['repository'], commit_id=entry['commit_id'],
365 f_path=entry['file'])
366 }
367
368 files.append(file_entry)
369 return files, True
290
370
291 @LoginRequired()
371 @LoginRequired()
292 @view_config(
372 @view_config(
@@ -363,36 +443,42 b' class HomeView(BaseAppView):'
363 def query_modifier():
443 def query_modifier():
364 qry = query
444 qry = query
365 return {'q': qry, 'type': 'content'}
445 return {'q': qry, 'type': 'content'}
366 label = u'File search for `{}` in this repository.'.format(query)
446
367 queries.append(
447 label = u'File search for `{}`'.format(h.escape(query))
368 {
448 file_qry = {
369 'id': -10,
449 'id': -10,
370 'value': query,
450 'value': query,
371 'value_display': label,
451 'value_display': label,
372 'type': 'search',
452 'type': 'search',
373 'url': h.route_path('search_repo',
453 'subtype': 'repo',
374 repo_name=repo_name,
454 'url': h.route_path('search_repo',
375 _query=query_modifier())
455 repo_name=repo_name,
456 _query=query_modifier())
376 }
457 }
377 )
378
458
379 # commits
459 # commits
380 def query_modifier():
460 def query_modifier():
381 qry = query
461 qry = query
382 return {'q': qry, 'type': 'commit'}
462 return {'q': qry, 'type': 'commit'}
383
463
384 label = u'Commit search for `{}` in this repository.'.format(query)
464 label = u'Commit search for `{}`'.format(h.escape(query))
385 queries.append(
465 commit_qry = {
386 {
466 'id': -20,
387 'id': -20,
467 'value': query,
388 'value': query,
468 'value_display': label,
389 'value_display': label,
469 'type': 'search',
390 'type': 'search',
470 'subtype': 'repo',
391 'url': h.route_path('search_repo',
471 'url': h.route_path('search_repo',
392 repo_name=repo_name,
472 repo_name=repo_name,
393 _query=query_modifier())
473 _query=query_modifier())
394 }
474 }
395 )
475
476 if repo_context in ['commit', 'commits']:
477 queries.extend([commit_qry, file_qry])
478 elif repo_context in ['files', 'summary']:
479 queries.extend([file_qry, commit_qry])
480 else:
481 queries.extend([commit_qry, file_qry])
396
482
397 elif is_es_6 and repo_group_name:
483 elif is_es_6 and repo_group_name:
398 # files
484 # files
@@ -400,37 +486,43 b' class HomeView(BaseAppView):'
400 qry = query
486 qry = query
401 return {'q': qry, 'type': 'content'}
487 return {'q': qry, 'type': 'content'}
402
488
403 label = u'File search for `{}` in this repository group'.format(query)
489 label = u'File search for `{}`'.format(query)
404 queries.append(
490 file_qry = {
405 {
491 'id': -30,
406 'id': -30,
492 'value': query,
407 'value': query,
493 'value_display': label,
408 'value_display': label,
494 'type': 'search',
409 'type': 'search',
495 'subtype': 'repo_group',
410 'url': h.route_path('search_repo_group',
496 'url': h.route_path('search_repo_group',
411 repo_group_name=repo_group_name,
497 repo_group_name=repo_group_name,
412 _query=query_modifier())
498 _query=query_modifier())
413 }
499 }
414 )
415
500
416 # commits
501 # commits
417 def query_modifier():
502 def query_modifier():
418 qry = query
503 qry = query
419 return {'q': qry, 'type': 'commit'}
504 return {'q': qry, 'type': 'commit'}
420
505
421 label = u'Commit search for `{}` in this repository group'.format(query)
506 label = u'Commit search for `{}`'.format(query)
422 queries.append(
507 commit_qry = {
423 {
508 'id': -40,
424 'id': -40,
509 'value': query,
425 'value': query,
510 'value_display': label,
426 'value_display': label,
511 'type': 'search',
427 'type': 'search',
512 'subtype': 'repo_group',
428 'url': h.route_path('search_repo_group',
513 'url': h.route_path('search_repo_group',
429 repo_group_name=repo_group_name,
514 repo_group_name=repo_group_name,
430 _query=query_modifier())
515 _query=query_modifier())
431 }
516 }
432 )
433
517
518 if repo_context in ['commit', 'commits']:
519 queries.extend([commit_qry, file_qry])
520 elif repo_context in ['files', 'summary']:
521 queries.extend([file_qry, commit_qry])
522 else:
523 queries.extend([commit_qry, file_qry])
524
525 # Global, not scoped
434 if not queries:
526 if not queries:
435 queries.append(
527 queries.append(
436 {
528 {
@@ -438,6 +530,7 b' class HomeView(BaseAppView):'
438 'value': query,
530 'value': query,
439 'value_display': u'File search for: `{}`'.format(query),
531 'value_display': u'File search for: `{}`'.format(query),
440 'type': 'search',
532 'type': 'search',
533 'subtype': 'global',
441 'url': h.route_path('search',
534 'url': h.route_path('search',
442 _query={'q': query, 'type': 'content'})
535 _query={'q': query, 'type': 'content'})
443 })
536 })
@@ -447,6 +540,7 b' class HomeView(BaseAppView):'
447 'value': query,
540 'value': query,
448 'value_display': u'Commit search for: `{}`'.format(query),
541 'value_display': u'Commit search for: `{}`'.format(query),
449 'type': 'search',
542 'type': 'search',
543 'subtype': 'global',
450 'url': h.route_path('search',
544 'url': h.route_path('search',
451 _query={'q': query, 'type': 'commit'})
545 _query={'q': query, 'type': 'commit'})
452 })
546 })
@@ -469,54 +563,107 b' class HomeView(BaseAppView):'
469 if not query:
563 if not query:
470 return {'suggestions': res}
564 return {'suggestions': res}
471
565
566 def no_match(name):
567 return {
568 'id': -1,
569 'value': "",
570 'value_display': name,
571 'type': 'text',
572 'url': ""
573 }
472 searcher = searcher_from_config(self.request.registry.settings)
574 searcher = searcher_from_config(self.request.registry.settings)
473 for _q in self._get_default_search_queries(self.request.GET, searcher, query):
575 has_specialized_search = False
474 res.append(_q)
475
576
577 # set repo context
578 repo = None
579 repo_id = safe_int(self.request.GET.get('search_context[repo_id]'))
580 if repo_id:
581 repo = Repository.get(repo_id)
582
583 # set group context
584 repo_group = None
476 repo_group_id = safe_int(self.request.GET.get('search_context[repo_group_id]'))
585 repo_group_id = safe_int(self.request.GET.get('search_context[repo_group_id]'))
477 if repo_group_id:
586 if repo_group_id:
478 repo_group = RepoGroup.get(repo_group_id)
587 repo_group = RepoGroup.get(repo_group_id)
479 composed_hint = '{}/{}'.format(repo_group.group_name, query)
588 prefix_match = False
480 show_hint = not query.startswith(repo_group.group_name)
589
481 if repo_group and show_hint:
590 # user: type search
482 hint = u'Repository search inside: `{}`'.format(composed_hint)
591 if not prefix_match:
483 res.append({
592 users, prefix_match = self._get_user_list(query)
484 'id': -1,
593 if users:
485 'value': composed_hint,
594 has_specialized_search = True
486 'value_display': hint,
595 for serialized_user in users:
487 'type': 'hint',
596 res.append(serialized_user)
488 'url': ""
597 elif prefix_match:
489 })
598 has_specialized_search = True
599 res.append(no_match('No matching users found'))
490
600
491 repo_groups = self._get_repo_group_list(query)
601 # user_group: type search
492 for serialized_repo_group in repo_groups:
602 if not prefix_match:
493 res.append(serialized_repo_group)
603 user_groups, prefix_match = self._get_user_groups_list(query)
604 if user_groups:
605 has_specialized_search = True
606 for serialized_user_group in user_groups:
607 res.append(serialized_user_group)
608 elif prefix_match:
609 has_specialized_search = True
610 res.append(no_match('No matching user groups found'))
494
611
495 repos = self._get_repo_list(query)
612 # FTS commit: type search
496 for serialized_repo in repos:
613 if not prefix_match:
497 res.append(serialized_repo)
614 commits, prefix_match = self._get_hash_commit_list(
615 c.auth_user, searcher, query, repo, repo_group)
616 if commits:
617 has_specialized_search = True
618 unique_repos = collections.OrderedDict()
619 for commit in commits:
620 repo_name = commit['repo']
621 unique_repos.setdefault(repo_name, []).append(commit)
498
622
499 # TODO(marcink): should all logged in users be allowed to search others?
623 for _repo, commits in unique_repos.items():
500 allowed_user_search = self._rhodecode_user.username != User.DEFAULT_USER
624 for commit in commits:
501 if allowed_user_search:
625 res.append(commit)
502 users = self._get_user_list(query)
626 elif prefix_match:
503 for serialized_user in users:
627 has_specialized_search = True
504 res.append(serialized_user)
628 res.append(no_match('No matching commits found'))
505
629
506 user_groups = self._get_user_groups_list(query)
630 # FTS file: type search
507 for serialized_user_group in user_groups:
631 if not prefix_match:
508 res.append(serialized_user_group)
632 paths, prefix_match = self._get_path_list(
633 c.auth_user, searcher, query, repo, repo_group)
634 if paths:
635 has_specialized_search = True
636 unique_repos = collections.OrderedDict()
637 for path in paths:
638 repo_name = path['repo']
639 unique_repos.setdefault(repo_name, []).append(path)
509
640
510 commits = self._get_hash_commit_list(c.auth_user, searcher, query)
641 for repo, paths in unique_repos.items():
511 if commits:
642 for path in paths:
512 unique_repos = collections.OrderedDict()
643 res.append(path)
513 for commit in commits:
644 elif prefix_match:
514 repo_name = commit['repo']
645 has_specialized_search = True
515 unique_repos.setdefault(repo_name, []).append(commit)
646 res.append(no_match('No matching files found'))
647
648 # main suggestions
649 if not has_specialized_search:
650 repo_group_name = ''
651 if repo_group:
652 repo_group_name = repo_group.group_name
516
653
517 for repo, commits in unique_repos.items():
654 for _q in self._get_default_search_queries(self.request.GET, searcher, query):
518 for commit in commits:
655 res.append(_q)
519 res.append(commit)
656
657 repo_groups = self._get_repo_group_list(query, repo_group_name=repo_group_name)
658 for serialized_repo_group in repo_groups:
659 res.append(serialized_repo_group)
660
661 repos = self._get_repo_list(query, repo_group_name=repo_group_name)
662 for serialized_repo in repos:
663 res.append(serialized_repo)
664
665 if not repos and not repo_groups:
666 res.append(no_match('No matches found'))
520
667
521 return {'suggestions': res}
668 return {'suggestions': res}
522
669
@@ -564,8 +711,11 b' class HomeView(BaseAppView):'
564 def repo_group_main_page(self):
711 def repo_group_main_page(self):
565 c = self.load_default_context()
712 c = self.load_default_context()
566 c.repo_group = self.request.db_repo_group
713 c.repo_group = self.request.db_repo_group
567 repo_data, repo_group_data = self._get_groups_and_repos(
714 repo_data, repo_group_data = self._get_groups_and_repos(c.repo_group.group_id)
568 c.repo_group.group_id)
715
716 # update every 5 min
717 if self.request.db_repo_group.last_commit_cache_update_diff > 60 * 5:
718 self.request.db_repo_group.update_commit_cache()
569
719
570 # json used to render the grids
720 # json used to render the grids
571 c.repos_data = json.dumps(repo_data)
721 c.repos_data = json.dumps(repo_data)
@@ -594,6 +744,34 b' class HomeView(BaseAppView):'
594 @LoginRequired()
744 @LoginRequired()
595 @CSRFRequired()
745 @CSRFRequired()
596 @view_config(
746 @view_config(
747 route_name='file_preview', request_method='POST',
748 renderer='string', xhr=True)
749 def file_preview(self):
750 # Technically a CSRF token is not needed as no state changes with this
751 # call. However, as this is a POST is better to have it, so automated
752 # tools don't flag it as potential CSRF.
753 # Post is required because the payload could be bigger than the maximum
754 # allowed by GET.
755
756 text = self.request.POST.get('text')
757 file_path = self.request.POST.get('file_path')
758
759 renderer = h.renderer_from_filename(file_path)
760
761 if renderer:
762 return h.render(text, renderer=renderer, mentions=True)
763 else:
764 self.load_default_context()
765 _render = self.request.get_partial_renderer(
766 'rhodecode:templates/files/file_content.mako')
767
768 lines = filenode_as_lines_tokens(FileNode(file_path, text))
769
770 return _render('render_lines', lines)
771
772 @LoginRequired()
773 @CSRFRequired()
774 @view_config(
597 route_name='store_user_session_value', request_method='POST',
775 route_name='store_user_session_value', request_method='POST',
598 renderer='string', xhr=True)
776 renderer='string', xhr=True)
599 def store_user_session_attr(self):
777 def store_user_session_attr(self):
@@ -604,4 +782,4 b' class HomeView(BaseAppView):'
604 if existing_value != val:
782 if existing_value != val:
605 self.request.session[key] = val
783 self.request.session[key] = val
606
784
607 return 'stored:{}'.format(key)
785 return 'stored:{}:{}'.format(key, val)
@@ -31,12 +31,12 b' from pyramid.renderers import render'
31
31
32 from rhodecode.apps._base import BaseAppView
32 from rhodecode.apps._base import BaseAppView
33 from rhodecode.model.db import (
33 from rhodecode.model.db import (
34 or_, joinedload, UserLog, UserFollowing, User, UserApiKeys)
34 or_, joinedload, Repository, UserLog, UserFollowing, User, UserApiKeys)
35 from rhodecode.model.meta import Session
35 from rhodecode.model.meta import Session
36 import rhodecode.lib.helpers as h
36 import rhodecode.lib.helpers as h
37 from rhodecode.lib.helpers import Page
37 from rhodecode.lib.helpers import Page
38 from rhodecode.lib.user_log_filter import user_log_filter
38 from rhodecode.lib.user_log_filter import user_log_filter
39 from rhodecode.lib.auth import LoginRequired, NotAnonymous, CSRFRequired
39 from rhodecode.lib.auth import LoginRequired, NotAnonymous, CSRFRequired, HasRepoPermissionAny
40 from rhodecode.lib.utils2 import safe_int, AttributeDict, md5_safe
40 from rhodecode.lib.utils2 import safe_int, AttributeDict, md5_safe
41 from rhodecode.model.scm import ScmModel
41 from rhodecode.model.scm import ScmModel
42
42
@@ -153,7 +153,7 b' class JournalView(BaseAppView):'
153 desc = action_extra()
153 desc = action_extra()
154 _url = h.route_url('home')
154 _url = h.route_url('home')
155 if entry.repository is not None:
155 if entry.repository is not None:
156 _url = h.route_url('repo_changelog',
156 _url = h.route_url('repo_commits',
157 repo_name=entry.repository.repo_name)
157 repo_name=entry.repository.repo_name)
158
158
159 feed.add_item(
159 feed.add_item(
@@ -199,7 +199,7 b' class JournalView(BaseAppView):'
199 desc = action_extra()
199 desc = action_extra()
200 _url = h.route_url('home')
200 _url = h.route_url('home')
201 if entry.repository is not None:
201 if entry.repository is not None:
202 _url = h.route_url('repo_changelog',
202 _url = h.route_url('repo_commits',
203 repo_name=entry.repository.repo_name)
203 repo_name=entry.repository.repo_name)
204
204
205 feed.add_item(
205 feed.add_item(
@@ -297,18 +297,19 b' class JournalView(BaseAppView):'
297 user_id = self.request.POST.get('follows_user_id')
297 user_id = self.request.POST.get('follows_user_id')
298 if user_id:
298 if user_id:
299 try:
299 try:
300 ScmModel().toggle_following_user(
300 ScmModel().toggle_following_user(user_id, self._rhodecode_user.user_id)
301 user_id, self._rhodecode_user.user_id)
302 Session().commit()
301 Session().commit()
303 return 'ok'
302 return 'ok'
304 except Exception:
303 except Exception:
305 raise HTTPBadRequest()
304 raise HTTPBadRequest()
306
305
307 repo_id = self.request.POST.get('follows_repo_id')
306 repo_id = self.request.POST.get('follows_repo_id')
308 if repo_id:
307 repo = Repository.get_or_404(repo_id)
308 perm_set = ['repository.read', 'repository.write', 'repository.admin']
309 has_perm = HasRepoPermissionAny(*perm_set)(repo.repo_name, 'RepoWatch check')
310 if repo and has_perm:
309 try:
311 try:
310 ScmModel().toggle_following_repo(
312 ScmModel().toggle_following_repo(repo_id, self._rhodecode_user.user_id)
311 repo_id, self._rhodecode_user.user_id)
312 Session().commit()
313 Session().commit()
313 return 'ok'
314 return 'ok'
314 except Exception:
315 except Exception:
@@ -160,4 +160,4 b' class TestMyAccountSshKeysView(TestContr'
160
160
161 response.mustcontain('Private key')
161 response.mustcontain('Private key')
162 response.mustcontain('Public key')
162 response.mustcontain('Public key')
163 response.mustcontain('-----BEGIN RSA PRIVATE KEY-----')
163 response.mustcontain('-----BEGIN PRIVATE KEY-----')
@@ -360,7 +360,7 b' class MyAccountView(BaseAppView, DataGri'
360 'repository.read', 'repository.write', 'repository.admin'])
360 'repository.read', 'repository.write', 'repository.admin'])
361
361
362 repos_data = RepoModel().get_repos_as_dict(
362 repos_data = RepoModel().get_repos_as_dict(
363 repo_list=repo_list, admin=admin)
363 repo_list=repo_list, admin=admin, short_name=False)
364 # json used to render the grid
364 # json used to render the grid
365 return json.dumps(repos_data)
365 return json.dumps(repos_data)
366
366
@@ -423,7 +423,7 b' class MyAccountView(BaseAppView, DataGri'
423 default_redirect_url = ''
423 default_redirect_url = ''
424
424
425 # save repo
425 # save repo
426 if entry.get('bookmark_repo'):
426 if entry.get('bookmark_repo') and safe_int(entry.get('bookmark_repo')):
427 repo = Repository.get(entry['bookmark_repo'])
427 repo = Repository.get(entry['bookmark_repo'])
428 perm_check = HasRepoPermissionAny(
428 perm_check = HasRepoPermissionAny(
429 'repository.read', 'repository.write', 'repository.admin')
429 'repository.read', 'repository.write', 'repository.admin')
@@ -432,7 +432,7 b' class MyAccountView(BaseAppView, DataGri'
432 should_save = True
432 should_save = True
433 default_redirect_url = '${repo_url}'
433 default_redirect_url = '${repo_url}'
434 # save repo group
434 # save repo group
435 elif entry.get('bookmark_repo_group'):
435 elif entry.get('bookmark_repo_group') and safe_int(entry.get('bookmark_repo_group')):
436 repo_group = RepoGroup.get(entry['bookmark_repo_group'])
436 repo_group = RepoGroup.get(entry['bookmark_repo_group'])
437 perm_check = HasRepoGroupPermissionAny(
437 perm_check = HasRepoGroupPermissionAny(
438 'group.read', 'group.write', 'group.admin')
438 'group.read', 'group.write', 'group.admin')
@@ -496,6 +496,7 b' class MyAccountView(BaseAppView, DataGri'
496 if not user_bookmark:
496 if not user_bookmark:
497 raise HTTPFound(redirect_url)
497 raise HTTPFound(redirect_url)
498
498
499 # repository set
499 if user_bookmark.repository:
500 if user_bookmark.repository:
500 repo_name = user_bookmark.repository.repo_name
501 repo_name = user_bookmark.repository.repo_name
501 base_redirect_url = h.route_path(
502 base_redirect_url = h.route_path(
@@ -506,7 +507,7 b' class MyAccountView(BaseAppView, DataGri'
506 .safe_substitute({'repo_url': base_redirect_url})
507 .safe_substitute({'repo_url': base_redirect_url})
507 else:
508 else:
508 redirect_url = base_redirect_url
509 redirect_url = base_redirect_url
509
510 # repository group set
510 elif user_bookmark.repository_group:
511 elif user_bookmark.repository_group:
511 repo_group_name = user_bookmark.repository_group.group_name
512 repo_group_name = user_bookmark.repository_group.group_name
512 base_redirect_url = h.route_path(
513 base_redirect_url = h.route_path(
@@ -517,9 +518,11 b' class MyAccountView(BaseAppView, DataGri'
517 .safe_substitute({'repo_group_url': base_redirect_url})
518 .safe_substitute({'repo_group_url': base_redirect_url})
518 else:
519 else:
519 redirect_url = base_redirect_url
520 redirect_url = base_redirect_url
520
521 # custom URL set
521 elif user_bookmark.redirect_url:
522 elif user_bookmark.redirect_url:
522 redirect_url = user_bookmark.redirect_url
523 server_url = h.route_url('home').rstrip('/')
524 redirect_url = string.Template(user_bookmark.redirect_url) \
525 .safe_substitute({'server_url': server_url})
523
526
524 log.debug('Redirecting bookmark %s to %s', user_bookmark, redirect_url)
527 log.debug('Redirecting bookmark %s to %s', user_bookmark, redirect_url)
525 raise HTTPFound(redirect_url)
528 raise HTTPFound(redirect_url)
@@ -90,7 +90,7 b' def includeme(config):'
90 # Files
90 # Files
91 config.add_route(
91 config.add_route(
92 name='repo_archivefile',
92 name='repo_archivefile',
93 pattern='/{repo_name:.*?[^/]}/archive/{fname}', repo_route=True)
93 pattern='/{repo_name:.*?[^/]}/archive/{fname:.*}', repo_route=True)
94
94
95 config.add_route(
95 config.add_route(
96 name='repo_files_diff',
96 name='repo_files_diff',
@@ -172,6 +172,10 b' def includeme(config):'
172 pattern='/{repo_name:.*?[^/]}/add_file/{commit_id}/{f_path:.*}',
172 pattern='/{repo_name:.*?[^/]}/add_file/{commit_id}/{f_path:.*}',
173 repo_route=True)
173 repo_route=True)
174 config.add_route(
174 config.add_route(
175 name='repo_files_upload_file',
176 pattern='/{repo_name:.*?[^/]}/upload_file/{commit_id}/{f_path:.*}',
177 repo_route=True)
178 config.add_route(
175 name='repo_files_create_file',
179 name='repo_files_create_file',
176 pattern='/{repo_name:.*?[^/]}/create_file/{commit_id}/{f_path:.*}',
180 pattern='/{repo_name:.*?[^/]}/create_file/{commit_id}/{f_path:.*}',
177 repo_route=True)
181 repo_route=True)
@@ -189,19 +193,27 b' def includeme(config):'
189 name='repo_stats',
193 name='repo_stats',
190 pattern='/{repo_name:.*?[^/]}/repo_stats/{commit_id}', repo_route=True)
194 pattern='/{repo_name:.*?[^/]}/repo_stats/{commit_id}', repo_route=True)
191
195
192 # Changelog
196 # Commits
197 config.add_route(
198 name='repo_commits',
199 pattern='/{repo_name:.*?[^/]}/commits', repo_route=True)
200 config.add_route(
201 name='repo_commits_file',
202 pattern='/{repo_name:.*?[^/]}/commits/{commit_id}/{f_path:.*}', repo_route=True)
203 config.add_route(
204 name='repo_commits_elements',
205 pattern='/{repo_name:.*?[^/]}/commits_elements', repo_route=True)
206 config.add_route(
207 name='repo_commits_elements_file',
208 pattern='/{repo_name:.*?[^/]}/commits_elements/{commit_id}/{f_path:.*}', repo_route=True)
209
210 # Changelog (old deprecated name for commits page)
193 config.add_route(
211 config.add_route(
194 name='repo_changelog',
212 name='repo_changelog',
195 pattern='/{repo_name:.*?[^/]}/changelog', repo_route=True)
213 pattern='/{repo_name:.*?[^/]}/changelog', repo_route=True)
196 config.add_route(
214 config.add_route(
197 name='repo_changelog_file',
215 name='repo_changelog_file',
198 pattern='/{repo_name:.*?[^/]}/changelog/{commit_id}/{f_path:.*}', repo_route=True)
216 pattern='/{repo_name:.*?[^/]}/changelog/{commit_id}/{f_path:.*}', repo_route=True)
199 config.add_route(
200 name='repo_changelog_elements',
201 pattern='/{repo_name:.*?[^/]}/changelog_elements', repo_route=True)
202 config.add_route(
203 name='repo_changelog_elements_file',
204 pattern='/{repo_name:.*?[^/]}/changelog_elements/{commit_id}/{f_path:.*}', repo_route=True)
205
217
206 # Compare
218 # Compare
207 config.add_route(
219 config.add_route(
@@ -312,6 +324,11 b' def includeme(config):'
312 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/comment/{comment_id}/delete',
324 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/comment/{comment_id}/delete',
313 repo_route=True, repo_accepted_types=['hg', 'git'])
325 repo_route=True, repo_accepted_types=['hg', 'git'])
314
326
327 # Artifacts, (EE feature)
328 config.add_route(
329 name='repo_artifacts_list',
330 pattern='/{repo_name:.*?[^/]}/artifacts', repo_route=True)
331
315 # Settings
332 # Settings
316 config.add_route(
333 config.add_route(
317 name='edit_repo',
334 name='edit_repo',
@@ -40,11 +40,11 b' def route_path(name, params=None, **kwar'
40 class TestPullRequestList(object):
40 class TestPullRequestList(object):
41
41
42 @pytest.mark.parametrize('params, expected_title', [
42 @pytest.mark.parametrize('params, expected_title', [
43 ({'source': 0, 'closed': 1}, 'Closed Pull Requests'),
43 ({'source': 0, 'closed': 1}, 'Closed'),
44 ({'source': 0, 'my': 1}, 'opened by me'),
44 ({'source': 0, 'my': 1}, 'Opened by me'),
45 ({'source': 0, 'awaiting_review': 1}, 'awaiting review'),
45 ({'source': 0, 'awaiting_review': 1}, 'Awaiting review'),
46 ({'source': 0, 'awaiting_my_review': 1}, 'awaiting my review'),
46 ({'source': 0, 'awaiting_my_review': 1}, 'Awaiting my review'),
47 ({'source': 1}, 'Pull Requests from'),
47 ({'source': 1}, 'From this repo'),
48 ])
48 ])
49 def test_showing_list_page(self, backend, pr_util, params, expected_title):
49 def test_showing_list_page(self, backend, pr_util, params, expected_title):
50 pull_request = pr_util.create_pull_request()
50 pull_request = pr_util.create_pull_request()
@@ -55,9 +55,10 b' class TestPullRequestList(object):'
55 params=params))
55 params=params))
56
56
57 assert_response = response.assert_response()
57 assert_response = response.assert_response()
58 assert_response.element_equals_to('.panel-title', expected_title)
58
59 element = assert_response.get_element('.panel-title')
59 element = assert_response.get_element('.title .active')
60 element_text = assert_response._element_to_string(element)
60 element_text = element.text_content()
61 assert expected_title == element_text
61
62
62 def test_showing_list_page_data(self, backend, pr_util, xhr_header):
63 def test_showing_list_page_data(self, backend, pr_util, xhr_header):
63 pull_request = pr_util.create_pull_request()
64 pull_request = pr_util.create_pull_request()
@@ -32,9 +32,10 b' def route_path(name, params=None, **kwar'
32 import urllib
32 import urllib
33
33
34 base_url = {
34 base_url = {
35 'repo_changelog':'/{repo_name}/changelog',
35 'repo_changelog': '/{repo_name}/changelog',
36 'repo_changelog_file':'/{repo_name}/changelog/{commit_id}/{f_path}',
36 'repo_commits': '/{repo_name}/commits',
37 'repo_changelog_elements':'/{repo_name}/changelog_elements',
37 'repo_commits_file': '/{repo_name}/commits/{commit_id}/{f_path}',
38 'repo_commits_elements': '/{repo_name}/commits_elements',
38 }[name].format(**kwargs)
39 }[name].format(**kwargs)
39
40
40 if params:
41 if params:
@@ -42,8 +43,22 b' def route_path(name, params=None, **kwar'
42 return base_url
43 return base_url
43
44
44
45
46 def assert_commits_on_page(response, indexes):
47 found_indexes = [int(idx) for idx in MATCH_HASH.findall(response.body)]
48 assert found_indexes == indexes
49
50
45 class TestChangelogController(TestController):
51 class TestChangelogController(TestController):
46
52
53 def test_commits_page(self, backend):
54 self.log_user()
55 response = self.app.get(
56 route_path('repo_commits', repo_name=backend.repo_name))
57
58 first_idx = -1
59 last_idx = -DEFAULT_CHANGELOG_SIZE
60 self.assert_commit_range_on_page(response, first_idx, last_idx, backend)
61
47 def test_changelog(self, backend):
62 def test_changelog(self, backend):
48 self.log_user()
63 self.log_user()
49 response = self.app.get(
64 response = self.app.get(
@@ -62,6 +77,14 b' class TestChangelogController(TestContro'
62 params=dict(branch=backend.default_branch_name)),
77 params=dict(branch=backend.default_branch_name)),
63 status=200)
78 status=200)
64
79
80 @pytest.mark.backends("hg", "git")
81 def test_commits_filtered_by_branch(self, backend):
82 self.log_user()
83 self.app.get(
84 route_path('repo_commits', repo_name=backend.repo_name,
85 params=dict(branch=backend.default_branch_name)),
86 status=200)
87
65 @pytest.mark.backends("svn")
88 @pytest.mark.backends("svn")
66 def test_changelog_filtered_by_branch_svn(self, autologin_user, backend):
89 def test_changelog_filtered_by_branch_svn(self, autologin_user, backend):
67 repo = backend['svn-simple-layout']
90 repo = backend['svn-simple-layout']
@@ -70,27 +93,22 b' class TestChangelogController(TestContro'
70 params=dict(branch='trunk')),
93 params=dict(branch='trunk')),
71 status=200)
94 status=200)
72
95
73 self.assert_commits_on_page(
96 assert_commits_on_page(response, indexes=[15, 12, 7, 3, 2, 1])
74 response, indexes=[15, 12, 7, 3, 2, 1])
75
97
76 def test_changelog_filtered_by_wrong_branch(self, backend):
98 def test_commits_filtered_by_wrong_branch(self, backend):
77 self.log_user()
99 self.log_user()
78 branch = 'wrong-branch-name'
100 branch = 'wrong-branch-name'
79 response = self.app.get(
101 response = self.app.get(
80 route_path('repo_changelog', repo_name=backend.repo_name,
102 route_path('repo_commits', repo_name=backend.repo_name,
81 params=dict(branch=branch)),
103 params=dict(branch=branch)),
82 status=302)
104 status=302)
83 expected_url = '/{repo}/changelog/{branch}'.format(
105 expected_url = '/{repo}/commits/{branch}'.format(
84 repo=backend.repo_name, branch=branch)
106 repo=backend.repo_name, branch=branch)
85 assert expected_url in response.location
107 assert expected_url in response.location
86 response = response.follow()
108 response = response.follow()
87 expected_warning = 'Branch {} is not found.'.format(branch)
109 expected_warning = 'Branch {} is not found.'.format(branch)
88 assert expected_warning in response.body
110 assert expected_warning in response.body
89
111
90 def assert_commits_on_page(self, response, indexes):
91 found_indexes = [int(idx) for idx in MATCH_HASH.findall(response.body)]
92 assert found_indexes == indexes
93
94 @pytest.mark.xfail_backends("svn", reason="Depends on branch support")
112 @pytest.mark.xfail_backends("svn", reason="Depends on branch support")
95 def test_changelog_filtered_by_branch_with_merges(
113 def test_changelog_filtered_by_branch_with_merges(
96 self, autologin_user, backend):
114 self, autologin_user, backend):
@@ -112,21 +130,20 b' class TestChangelogController(TestContro'
112 status=200)
130 status=200)
113
131
114 @pytest.mark.backends("hg")
132 @pytest.mark.backends("hg")
115 def test_changelog_closed_branches(self, autologin_user, backend):
133 def test_commits_closed_branches(self, autologin_user, backend):
116 repo = backend['closed_branch']
134 repo = backend['closed_branch']
117 response = self.app.get(
135 response = self.app.get(
118 route_path('repo_changelog', repo_name=repo.repo_name,
136 route_path('repo_commits', repo_name=repo.repo_name,
119 params=dict(branch='experimental')),
137 params=dict(branch='experimental')),
120 status=200)
138 status=200)
121
139
122 self.assert_commits_on_page(
140 assert_commits_on_page(response, indexes=[3, 1])
123 response, indexes=[3, 1])
124
141
125 def test_changelog_pagination(self, backend):
142 def test_changelog_pagination(self, backend):
126 self.log_user()
143 self.log_user()
127 # pagination, walk up to page 6
144 # pagination, walk up to page 6
128 changelog_url = route_path(
145 changelog_url = route_path(
129 'repo_changelog', repo_name=backend.repo_name)
146 'repo_commits', repo_name=backend.repo_name)
130
147
131 for page in range(1, 7):
148 for page in range(1, 7):
132 response = self.app.get(changelog_url, {'page': page})
149 response = self.app.get(changelog_url, {'page': page})
@@ -138,22 +155,30 b' class TestChangelogController(TestContro'
138 def assert_commit_range_on_page(
155 def assert_commit_range_on_page(
139 self, response, first_idx, last_idx, backend):
156 self, response, first_idx, last_idx, backend):
140 input_template = (
157 input_template = (
141 """<input class="commit-range" id="%(raw_id)s" """
158 """<input class="commit-range" """
159 """data-commit-id="%(raw_id)s" data-commit-idx="%(idx)s" """
160 """data-short-id="%(short_id)s" id="%(raw_id)s" """
142 """name="%(raw_id)s" type="checkbox" value="1" />"""
161 """name="%(raw_id)s" type="checkbox" value="1" />"""
143 )
162 )
163
144 commit_span_template = """<span class="commit_hash">r%s:%s</span>"""
164 commit_span_template = """<span class="commit_hash">r%s:%s</span>"""
145 repo = backend.repo
165 repo = backend.repo
146
166
147 first_commit_on_page = repo.get_commit(commit_idx=first_idx)
167 first_commit_on_page = repo.get_commit(commit_idx=first_idx)
148 response.mustcontain(
168 response.mustcontain(
149 input_template % {'raw_id': first_commit_on_page.raw_id})
169 input_template % {'raw_id': first_commit_on_page.raw_id,
170 'idx': first_commit_on_page.idx,
171 'short_id': first_commit_on_page.short_id})
172
150 response.mustcontain(commit_span_template % (
173 response.mustcontain(commit_span_template % (
151 first_commit_on_page.idx, first_commit_on_page.short_id)
174 first_commit_on_page.idx, first_commit_on_page.short_id)
152 )
175 )
153
176
154 last_commit_on_page = repo.get_commit(commit_idx=last_idx)
177 last_commit_on_page = repo.get_commit(commit_idx=last_idx)
155 response.mustcontain(
178 response.mustcontain(
156 input_template % {'raw_id': last_commit_on_page.raw_id})
179 input_template % {'raw_id': last_commit_on_page.raw_id,
180 'idx': last_commit_on_page.idx,
181 'short_id': last_commit_on_page.short_id})
157 response.mustcontain(commit_span_template % (
182 response.mustcontain(commit_span_template % (
158 last_commit_on_page.idx, last_commit_on_page.short_id)
183 last_commit_on_page.idx, last_commit_on_page.short_id)
159 )
184 )
@@ -168,10 +193,10 b' class TestChangelogController(TestContro'
168 '/vcs/exceptions.py',
193 '/vcs/exceptions.py',
169 '//vcs/exceptions.py'
194 '//vcs/exceptions.py'
170 ])
195 ])
171 def test_changelog_with_filenode(self, backend, test_path):
196 def test_commits_with_filenode(self, backend, test_path):
172 self.log_user()
197 self.log_user()
173 response = self.app.get(
198 response = self.app.get(
174 route_path('repo_changelog_file', repo_name=backend.repo_name,
199 route_path('repo_commits_file', repo_name=backend.repo_name,
175 commit_id='tip', f_path=test_path),
200 commit_id='tip', f_path=test_path),
176 )
201 )
177
202
@@ -180,16 +205,16 b' class TestChangelogController(TestContro'
180 response.mustcontain('Added not implemented hg backend test case')
205 response.mustcontain('Added not implemented hg backend test case')
181 response.mustcontain('Added BaseChangeset class')
206 response.mustcontain('Added BaseChangeset class')
182
207
183 def test_changelog_with_filenode_that_is_dirnode(self, backend):
208 def test_commits_with_filenode_that_is_dirnode(self, backend):
184 self.log_user()
209 self.log_user()
185 self.app.get(
210 self.app.get(
186 route_path('repo_changelog_file', repo_name=backend.repo_name,
211 route_path('repo_commits_file', repo_name=backend.repo_name,
187 commit_id='tip', f_path='/tests'),
212 commit_id='tip', f_path='/tests'),
188 status=302)
213 status=302)
189
214
190 def test_changelog_with_filenode_not_existing(self, backend):
215 def test_commits_with_filenode_not_existing(self, backend):
191 self.log_user()
216 self.log_user()
192 self.app.get(
217 self.app.get(
193 route_path('repo_changelog_file', repo_name=backend.repo_name,
218 route_path('repo_commits_file', repo_name=backend.repo_name,
194 commit_id='tip', f_path='wrong_path'),
219 commit_id='tip', f_path='wrong_path'),
195 status=302)
220 status=302)
@@ -94,6 +94,7 b' class TestCompareView(object):'
94 origin_repo = origin.scm_instance(cache=False)
94 origin_repo = origin.scm_instance(cache=False)
95 origin_repo.config.clear_section('hooks')
95 origin_repo.config.clear_section('hooks')
96 origin_repo.pull(fork.repo_full_path, commit_ids=[commit3.raw_id])
96 origin_repo.pull(fork.repo_full_path, commit_ids=[commit3.raw_id])
97 origin_repo = origin.scm_instance(cache=False) # cache rebuild
97
98
98 # Verify test fixture setup
99 # Verify test fixture setup
99 # This does not work for git
100 # This does not work for git
@@ -162,8 +163,7 b' class TestCompareView(object):'
162 compare_page.target_source_are_disabled()
163 compare_page.target_source_are_disabled()
163
164
164 @pytest.mark.xfail_backends("svn", reason="Depends on branch support")
165 @pytest.mark.xfail_backends("svn", reason="Depends on branch support")
165 def test_compare_forks_on_branch_extra_commits_origin_has_incomming(
166 def test_compare_forks_on_branch_extra_commits_origin_has_incomming(self, backend):
166 self, backend):
167 repo1 = backend.create_repo()
167 repo1 = backend.create_repo()
168
168
169 # commit something !
169 # commit something !
@@ -21,6 +21,7 b''
21 import pytest
21 import pytest
22
22
23 from rhodecode.lib.vcs import nodes
23 from rhodecode.lib.vcs import nodes
24 from rhodecode.lib.vcs.backends.base import EmptyCommit
24 from rhodecode.tests.fixture import Fixture
25 from rhodecode.tests.fixture import Fixture
25 from rhodecode.tests.utils import commit_change
26 from rhodecode.tests.utils import commit_change
26
27
@@ -43,70 +44,7 b' def route_path(name, params=None, **kwar'
43 @pytest.mark.usefixtures("autologin_user", "app")
44 @pytest.mark.usefixtures("autologin_user", "app")
44 class TestSideBySideDiff(object):
45 class TestSideBySideDiff(object):
45
46
46 def test_diff_side_by_side(self, app, backend, backend_stub):
47 def test_diff_sidebyside_single_commit(self, app, backend):
47 f_path = 'test_sidebyside_file.py'
48 commit1_content = 'content-25d7e49c18b159446c\n'
49 commit2_content = 'content-603d6c72c46d953420\n'
50 repo = backend.create_repo()
51
52 commit1 = commit_change(
53 repo.repo_name, filename=f_path, content=commit1_content,
54 message='A', vcs_type=backend.alias, parent=None, newfile=True)
55
56 commit2 = commit_change(
57 repo.repo_name, filename=f_path, content=commit2_content,
58 message='B, child of A', vcs_type=backend.alias, parent=commit1)
59
60 response = self.app.get(route_path(
61 'repo_compare',
62 repo_name=repo.repo_name,
63 source_ref_type='rev',
64 source_ref=commit1.raw_id,
65 target_ref_type='rev',
66 target_ref=commit2.raw_id,
67 params=dict(f_path=f_path, target_repo=repo.repo_name, diffmode='sidebyside')
68 ))
69
70 response.mustcontain('Expand 1 commit')
71 response.mustcontain('1 file changed')
72
73 response.mustcontain(
74 'r%s:%s...r%s:%s' % (
75 commit1.idx, commit1.short_id, commit2.idx, commit2.short_id))
76
77 response.mustcontain('<strong>{}</strong>'.format(f_path))
78
79 def test_diff_side_by_side_with_empty_file(self, app, backend, backend_stub):
80 commits = [
81 {'message': 'First commit'},
82 {'message': 'Commit with binary',
83 'added': [nodes.FileNode('file.empty', content='')]},
84 ]
85 f_path = 'file.empty'
86 repo = backend.create_repo(commits=commits)
87 commit1 = repo.get_commit(commit_idx=0)
88 commit2 = repo.get_commit(commit_idx=1)
89
90 response = self.app.get(route_path(
91 'repo_compare',
92 repo_name=repo.repo_name,
93 source_ref_type='rev',
94 source_ref=commit1.raw_id,
95 target_ref_type='rev',
96 target_ref=commit2.raw_id,
97 params=dict(f_path=f_path, target_repo=repo.repo_name, diffmode='sidebyside')
98 ))
99
100 response.mustcontain('Expand 1 commit')
101 response.mustcontain('1 file changed')
102
103 response.mustcontain(
104 'r%s:%s...r%s:%s' % (
105 commit1.idx, commit1.short_id, commit2.idx, commit2.short_id))
106
107 response.mustcontain('<strong>{}</strong>'.format(f_path))
108
109 def test_diff_sidebyside_two_commits(self, app, backend):
110 commit_id_range = {
48 commit_id_range = {
111 'hg': {
49 'hg': {
112 'commits': ['25d7e49c18b159446cadfa506a5cf8ad1cb04067',
50 'commits': ['25d7e49c18b159446cadfa506a5cf8ad1cb04067',
@@ -141,26 +79,164 b' class TestSideBySideDiff(object):'
141 params=dict(target_repo=backend.repo_name, diffmode='sidebyside')
79 params=dict(target_repo=backend.repo_name, diffmode='sidebyside')
142 ))
80 ))
143
81
82 response.mustcontain(file_changes)
144 response.mustcontain('Expand 1 commit')
83 response.mustcontain('Expand 1 commit')
145 response.mustcontain(file_changes)
146
84
147 def test_diff_sidebyside_two_commits_single_file(self, app, backend):
85 def test_diff_sidebyside_two_commits(self, app, backend):
148 commit_id_range = {
86 commit_id_range = {
149 'hg': {
87 'hg': {
150 'commits': ['25d7e49c18b159446cadfa506a5cf8ad1cb04067',
88 'commits': ['4fdd71e9427417b2e904e0464c634fdee85ec5a7',
151 '603d6c72c46d953420c89d36372f08d9f305f5dd'],
89 '603d6c72c46d953420c89d36372f08d9f305f5dd'],
152 'changes': '1 file changed: 1 inserted, 1 deleted'
90 'changes': '32 files changed: 1165 inserted, 308 deleted'
153 },
91 },
154 'git': {
92 'git': {
155 'commits': ['6fc9270775aaf5544c1deb014f4ddd60c952fcbb',
93 'commits': ['f5fbf9cfd5f1f1be146f6d3b38bcd791a7480c13',
156 '03fa803d7e9fb14daa9a3089e0d1494eda75d986'],
94 '03fa803d7e9fb14daa9a3089e0d1494eda75d986'],
157 'changes': '1 file changed: 1 inserted, 1 deleted'
95 'changes': '32 files changed: 1165 inserted, 308 deleted'
158 },
96 },
159
97
160 'svn': {
98 'svn': {
161 'commits': ['336',
99 'commits': ['335',
162 '337'],
100 '337'],
163 'changes': '1 file changed: 1 inserted, 1 deleted'
101 'changes': '32 files changed: 1179 inserted, 310 deleted'
102 },
103 }
104
105 commit_info = commit_id_range[backend.alias]
106 commit2, commit1 = commit_info['commits']
107 file_changes = commit_info['changes']
108
109 response = self.app.get(route_path(
110 'repo_compare',
111 repo_name=backend.repo_name,
112 source_ref_type='rev',
113 source_ref=commit2,
114 target_repo=backend.repo_name,
115 target_ref_type='rev',
116 target_ref=commit1,
117 params=dict(target_repo=backend.repo_name, diffmode='sidebyside')
118 ))
119
120 response.mustcontain(file_changes)
121 response.mustcontain('Expand 2 commits')
122
123 @pytest.mark.xfail(reason='GIT does not handle empty commit compare correct (missing 1 commit)')
124 def test_diff_side_by_side_from_0_commit(self, app, backend, backend_stub):
125 f_path = 'test_sidebyside_file.py'
126 commit1_content = 'content-25d7e49c18b159446c\n'
127 commit2_content = 'content-603d6c72c46d953420\n'
128 repo = backend.create_repo()
129
130 commit1 = commit_change(
131 repo.repo_name, filename=f_path, content=commit1_content,
132 message='A', vcs_type=backend.alias, parent=None, newfile=True)
133
134 commit2 = commit_change(
135 repo.repo_name, filename=f_path, content=commit2_content,
136 message='B, child of A', vcs_type=backend.alias, parent=commit1)
137
138 response = self.app.get(route_path(
139 'repo_compare',
140 repo_name=repo.repo_name,
141 source_ref_type='rev',
142 source_ref=EmptyCommit().raw_id,
143 target_ref_type='rev',
144 target_ref=commit2.raw_id,
145 params=dict(diffmode='sidebyside')
146 ))
147
148 response.mustcontain('Expand 2 commits')
149 response.mustcontain('123 file changed')
150
151 response.mustcontain(
152 'r%s:%s...r%s:%s' % (
153 commit1.idx, commit1.short_id, commit2.idx, commit2.short_id))
154
155 response.mustcontain('<strong>{}</strong>'.format(f_path))
156
157 @pytest.mark.xfail(reason='GIT does not handle empty commit compare correct (missing 1 commit)')
158 def test_diff_side_by_side_from_0_commit_with_file_filter(self, app, backend, backend_stub):
159 f_path = 'test_sidebyside_file.py'
160 commit1_content = 'content-25d7e49c18b159446c\n'
161 commit2_content = 'content-603d6c72c46d953420\n'
162 repo = backend.create_repo()
163
164 commit1 = commit_change(
165 repo.repo_name, filename=f_path, content=commit1_content,
166 message='A', vcs_type=backend.alias, parent=None, newfile=True)
167
168 commit2 = commit_change(
169 repo.repo_name, filename=f_path, content=commit2_content,
170 message='B, child of A', vcs_type=backend.alias, parent=commit1)
171
172 response = self.app.get(route_path(
173 'repo_compare',
174 repo_name=repo.repo_name,
175 source_ref_type='rev',
176 source_ref=EmptyCommit().raw_id,
177 target_ref_type='rev',
178 target_ref=commit2.raw_id,
179 params=dict(f_path=f_path, target_repo=repo.repo_name, diffmode='sidebyside')
180 ))
181
182 response.mustcontain('Expand 2 commits')
183 response.mustcontain('1 file changed')
184
185 response.mustcontain(
186 'r%s:%s...r%s:%s' % (
187 commit1.idx, commit1.short_id, commit2.idx, commit2.short_id))
188
189 response.mustcontain('<strong>{}</strong>'.format(f_path))
190
191 def test_diff_side_by_side_with_empty_file(self, app, backend, backend_stub):
192 commits = [
193 {'message': 'First commit'},
194 {'message': 'Second commit'},
195 {'message': 'Commit with binary',
196 'added': [nodes.FileNode('file.empty', content='')]},
197 ]
198 f_path = 'file.empty'
199 repo = backend.create_repo(commits=commits)
200 commit1 = repo.get_commit(commit_idx=0)
201 commit2 = repo.get_commit(commit_idx=1)
202 commit3 = repo.get_commit(commit_idx=2)
203
204 response = self.app.get(route_path(
205 'repo_compare',
206 repo_name=repo.repo_name,
207 source_ref_type='rev',
208 source_ref=commit1.raw_id,
209 target_ref_type='rev',
210 target_ref=commit3.raw_id,
211 params=dict(f_path=f_path, target_repo=repo.repo_name, diffmode='sidebyside')
212 ))
213
214 response.mustcontain('Expand 2 commits')
215 response.mustcontain('1 file changed')
216
217 response.mustcontain(
218 'r%s:%s...r%s:%s' % (
219 commit2.idx, commit2.short_id, commit3.idx, commit3.short_id))
220
221 response.mustcontain('<strong>{}</strong>'.format(f_path))
222
223 def test_diff_sidebyside_two_commits_with_file_filter(self, app, backend):
224 commit_id_range = {
225 'hg': {
226 'commits': ['4fdd71e9427417b2e904e0464c634fdee85ec5a7',
227 '603d6c72c46d953420c89d36372f08d9f305f5dd'],
228 'changes': '1 file changed: 3 inserted, 3 deleted'
229 },
230 'git': {
231 'commits': ['f5fbf9cfd5f1f1be146f6d3b38bcd791a7480c13',
232 '03fa803d7e9fb14daa9a3089e0d1494eda75d986'],
233 'changes': '1 file changed: 3 inserted, 3 deleted'
234 },
235
236 'svn': {
237 'commits': ['335',
238 '337'],
239 'changes': '1 file changed: 3 inserted, 3 deleted'
164 },
240 },
165 }
241 }
166 f_path = 'docs/conf.py'
242 f_path = 'docs/conf.py'
@@ -179,5 +255,5 b' class TestSideBySideDiff(object):'
179 params=dict(f_path=f_path, target_repo=backend.repo_name, diffmode='sidebyside')
255 params=dict(f_path=f_path, target_repo=backend.repo_name, diffmode='sidebyside')
180 ))
256 ))
181
257
182 response.mustcontain('Expand 1 commit')
258 response.mustcontain('Expand 2 commits')
183 response.mustcontain(file_changes)
259 response.mustcontain(file_changes)
@@ -243,7 +243,7 b' class TestFilesViews(object):'
243 repo_name=backend.repo_name,
243 repo_name=backend.repo_name,
244 commit_id=commit.raw_id, f_path='vcs/nodes.py'))
244 commit_id=commit.raw_id, f_path='vcs/nodes.py'))
245
245
246 msgbox = """<div class="commit right-content">%s</div>"""
246 msgbox = """<div class="commit">%s</div>"""
247 response.mustcontain(msgbox % (commit.message, ))
247 response.mustcontain(msgbox % (commit.message, ))
248
248
249 assert_response = response.assert_response()
249 assert_response = response.assert_response()
@@ -313,6 +313,7 b' class TestFilesViews(object):'
313
313
314 expected_data = json.loads(
314 expected_data = json.loads(
315 fixture.load_resource('svn_node_history_branches.json'))
315 fixture.load_resource('svn_node_history_branches.json'))
316
316 assert expected_data == response.json
317 assert expected_data == response.json
317
318
318 def test_file_source_history_with_annotation(self, backend, xhr_header):
319 def test_file_source_history_with_annotation(self, backend, xhr_header):
@@ -521,10 +522,10 b' class TestRepositoryArchival(object):'
521 def test_archival(self, backend):
522 def test_archival(self, backend):
522 backend.enable_downloads()
523 backend.enable_downloads()
523 commit = backend.repo.get_commit(commit_idx=173)
524 commit = backend.repo.get_commit(commit_idx=173)
524 for archive, info in settings.ARCHIVE_SPECS.items():
525 for a_type, content_type, extension in settings.ARCHIVE_SPECS:
525 mime_type, arch_ext = info
526
526 short = commit.short_id + arch_ext
527 short = commit.short_id + extension
527 fname = commit.raw_id + arch_ext
528 fname = commit.raw_id + extension
528 filename = '%s-%s' % (backend.repo_name, short)
529 filename = '%s-%s' % (backend.repo_name, short)
529 response = self.app.get(
530 response = self.app.get(
530 route_path('repo_archivefile',
531 route_path('repo_archivefile',
@@ -534,7 +535,7 b' class TestRepositoryArchival(object):'
534 assert response.status == '200 OK'
535 assert response.status == '200 OK'
535 headers = [
536 headers = [
536 ('Content-Disposition', 'attachment; filename=%s' % filename),
537 ('Content-Disposition', 'attachment; filename=%s' % filename),
537 ('Content-Type', '%s' % mime_type),
538 ('Content-Type', '%s' % content_type),
538 ]
539 ]
539
540
540 for header in headers:
541 for header in headers:
@@ -761,7 +762,7 b' class TestModifyFilesWithWebInterface(ob'
761
762
762 @pytest.mark.xfail_backends("svn", reason="Depends on online editing")
763 @pytest.mark.xfail_backends("svn", reason="Depends on online editing")
763 def test_add_file_into_repo_missing_content(self, backend, csrf_token):
764 def test_add_file_into_repo_missing_content(self, backend, csrf_token):
764 repo = backend.create_repo()
765 backend.create_repo()
765 filename = 'init.py'
766 filename = 'init.py'
766 response = self.app.post(
767 response = self.app.post(
767 route_path('repo_files_create_file',
768 route_path('repo_files_create_file',
@@ -770,26 +771,25 b' class TestModifyFilesWithWebInterface(ob'
770 params={
771 params={
771 'content': "",
772 'content': "",
772 'filename': filename,
773 'filename': filename,
773 'location': "",
774 'csrf_token': csrf_token,
774 'csrf_token': csrf_token,
775 },
775 },
776 status=302)
776 status=302)
777 assert_session_flash(response,
777 expected_msg = 'Successfully committed new file `{}`'.format(os.path.join(filename))
778 'Successfully committed new file `{}`'.format(
778 assert_session_flash(response, expected_msg)
779 os.path.join(filename)))
780
779
781 def test_add_file_into_repo_missing_filename(self, backend, csrf_token):
780 def test_add_file_into_repo_missing_filename(self, backend, csrf_token):
781 commit_id = backend.repo.get_commit().raw_id
782 response = self.app.post(
782 response = self.app.post(
783 route_path('repo_files_create_file',
783 route_path('repo_files_create_file',
784 repo_name=backend.repo_name,
784 repo_name=backend.repo_name,
785 commit_id='tip', f_path='/'),
785 commit_id=commit_id, f_path='/'),
786 params={
786 params={
787 'content': "foo",
787 'content': "foo",
788 'csrf_token': csrf_token,
788 'csrf_token': csrf_token,
789 },
789 },
790 status=302)
790 status=302)
791
791
792 assert_session_flash(response, 'No filename')
792 assert_session_flash(response, 'No filename specified')
793
793
794 def test_add_file_into_repo_errors_and_no_commits(
794 def test_add_file_into_repo_errors_and_no_commits(
795 self, backend, csrf_token):
795 self, backend, csrf_token):
@@ -806,7 +806,7 b' class TestModifyFilesWithWebInterface(ob'
806 },
806 },
807 status=302)
807 status=302)
808
808
809 assert_session_flash(response, 'No filename')
809 assert_session_flash(response, 'No filename specified')
810
810
811 # Not allowed, redirect to the summary
811 # Not allowed, redirect to the summary
812 redirected = response.follow()
812 redirected = response.follow()
@@ -817,52 +817,51 b' class TestModifyFilesWithWebInterface(ob'
817
817
818 assert redirected.request.path == summary_url
818 assert redirected.request.path == summary_url
819
819
820 @pytest.mark.parametrize("location, filename", [
820 @pytest.mark.parametrize("filename, clean_filename", [
821 ('/abs', 'foo'),
821 ('/abs/foo', 'abs/foo'),
822 ('../rel', 'foo'),
822 ('../rel/foo', 'rel/foo'),
823 ('file/../foo', 'foo'),
823 ('file/../foo/foo', 'file/foo/foo'),
824 ])
824 ])
825 def test_add_file_into_repo_bad_filenames(
825 def test_add_file_into_repo_bad_filenames(self, filename, clean_filename, backend, csrf_token):
826 self, location, filename, backend, csrf_token):
826 repo = backend.create_repo()
827 commit_id = repo.get_commit().raw_id
828
827 response = self.app.post(
829 response = self.app.post(
828 route_path('repo_files_create_file',
830 route_path('repo_files_create_file',
829 repo_name=backend.repo_name,
831 repo_name=repo.repo_name,
830 commit_id='tip', f_path='/'),
832 commit_id=commit_id, f_path='/'),
831 params={
833 params={
832 'content': "foo",
834 'content': "foo",
833 'filename': filename,
835 'filename': filename,
834 'location': location,
835 'csrf_token': csrf_token,
836 'csrf_token': csrf_token,
836 },
837 },
837 status=302)
838 status=302)
838
839
839 assert_session_flash(
840 expected_msg = 'Successfully committed new file `{}`'.format(clean_filename)
840 response,
841 assert_session_flash(response, expected_msg)
841 'The location specified must be a relative path and must not '
842 'contain .. in the path')
843
842
844 @pytest.mark.parametrize("cnt, location, filename", [
843 @pytest.mark.parametrize("cnt, filename, content", [
845 (1, '', 'foo.txt'),
844 (1, 'foo.txt', "Content"),
846 (2, 'dir', 'foo.rst'),
845 (2, 'dir/foo.rst', "Content"),
847 (3, 'rel/dir', 'foo.bar'),
846 (3, 'dir/foo-second.rst', "Content"),
847 (4, 'rel/dir/foo.bar', "Content"),
848 ])
848 ])
849 def test_add_file_into_repo(self, cnt, location, filename, backend,
849 def test_add_file_into_empty_repo(self, cnt, filename, content, backend, csrf_token):
850 csrf_token):
851 repo = backend.create_repo()
850 repo = backend.create_repo()
851 commit_id = repo.get_commit().raw_id
852 response = self.app.post(
852 response = self.app.post(
853 route_path('repo_files_create_file',
853 route_path('repo_files_create_file',
854 repo_name=repo.repo_name,
854 repo_name=repo.repo_name,
855 commit_id='tip', f_path='/'),
855 commit_id=commit_id, f_path='/'),
856 params={
856 params={
857 'content': "foo",
857 'content': content,
858 'filename': filename,
858 'filename': filename,
859 'location': location,
860 'csrf_token': csrf_token,
859 'csrf_token': csrf_token,
861 },
860 },
862 status=302)
861 status=302)
863 assert_session_flash(response,
862
864 'Successfully committed new file `{}`'.format(
863 expected_msg = 'Successfully committed new file `{}`'.format(filename)
865 os.path.join(location, filename)))
864 assert_session_flash(response, expected_msg)
866
865
867 def test_edit_file_view(self, backend):
866 def test_edit_file_view(self, backend):
868 response = self.app.get(
867 response = self.app.get(
@@ -884,8 +883,7 b' class TestModifyFilesWithWebInterface(ob'
884 f_path='vcs/nodes.py'),
883 f_path='vcs/nodes.py'),
885 status=302)
884 status=302)
886 assert_session_flash(
885 assert_session_flash(
887 response,
886 response, 'Cannot modify file. Given commit `tip` is not head of a branch.')
888 'You can only edit files with commit being a valid branch')
889
887
890 def test_edit_file_view_commit_changes(self, backend, csrf_token):
888 def test_edit_file_view_commit_changes(self, backend, csrf_token):
891 repo = backend.create_repo()
889 repo = backend.create_repo()
@@ -953,8 +951,7 b' class TestModifyFilesWithWebInterface(ob'
953 f_path='vcs/nodes.py'),
951 f_path='vcs/nodes.py'),
954 status=302)
952 status=302)
955 assert_session_flash(
953 assert_session_flash(
956 response,
954 response, 'Cannot modify file. Given commit `tip` is not head of a branch.')
957 'You can only delete files with commit being a valid branch')
958
955
959 def test_delete_file_view_commit_changes(self, backend, csrf_token):
956 def test_delete_file_view_commit_changes(self, backend, csrf_token):
960 repo = backend.create_repo()
957 repo = backend.create_repo()
@@ -992,7 +989,7 b' class TestFilesViewOtherCases(object):'
992 repo_file_add_url = route_path(
989 repo_file_add_url = route_path(
993 'repo_files_add_file',
990 'repo_files_add_file',
994 repo_name=repo.repo_name,
991 repo_name=repo.repo_name,
995 commit_id=0, f_path='') + '#edit'
992 commit_id=0, f_path='')
996
993
997 assert_session_flash(
994 assert_session_flash(
998 response,
995 response,
@@ -1009,7 +1006,7 b' class TestFilesViewOtherCases(object):'
1009 repo_file_add_url = route_path(
1006 repo_file_add_url = route_path(
1010 'repo_files_add_file',
1007 'repo_files_add_file',
1011 repo_name=repo.repo_name,
1008 repo_name=repo.repo_name,
1012 commit_id=0, f_path='') + '#edit'
1009 commit_id=0, f_path='')
1013
1010
1014 response = self.app.get(
1011 response = self.app.get(
1015 route_path('repo_files',
1012 route_path('repo_files',
@@ -40,6 +40,8 b' def route_path(name, params=None, **kwar'
40 base_url = {
40 base_url = {
41 'repo_changelog': '/{repo_name}/changelog',
41 'repo_changelog': '/{repo_name}/changelog',
42 'repo_changelog_file': '/{repo_name}/changelog/{commit_id}/{f_path}',
42 'repo_changelog_file': '/{repo_name}/changelog/{commit_id}/{f_path}',
43 'repo_commits': '/{repo_name}/commits',
44 'repo_commits_file': '/{repo_name}/commits/{commit_id}/{f_path}',
43 'pullrequest_show': '/{repo_name}/pull-request/{pull_request_id}',
45 'pullrequest_show': '/{repo_name}/pull-request/{pull_request_id}',
44 'pullrequest_show_all': '/{repo_name}/pull-request',
46 'pullrequest_show_all': '/{repo_name}/pull-request',
45 'pullrequest_show_all_data': '/{repo_name}/pull-request-data',
47 'pullrequest_show_all_data': '/{repo_name}/pull-request-data',
@@ -998,11 +1000,11 b' class TestPullrequestsView(object):'
998 assert len(target_children) == 1
1000 assert len(target_children) == 1
999
1001
1000 expected_origin_link = route_path(
1002 expected_origin_link = route_path(
1001 'repo_changelog',
1003 'repo_commits',
1002 repo_name=pull_request.source_repo.scm_instance().name,
1004 repo_name=pull_request.source_repo.scm_instance().name,
1003 params=dict(branch='origin'))
1005 params=dict(branch='origin'))
1004 expected_target_link = route_path(
1006 expected_target_link = route_path(
1005 'repo_changelog',
1007 'repo_commits',
1006 repo_name=pull_request.target_repo.scm_instance().name,
1008 repo_name=pull_request.target_repo.scm_instance().name,
1007 params=dict(branch='target'))
1009 params=dict(branch='target'))
1008 assert origin_children[0].attrib['href'] == expected_origin_link
1010 assert origin_children[0].attrib['href'] == expected_origin_link
@@ -350,11 +350,11 b' class TestCreateReferenceData(object):'
350 {
350 {
351 'children': [
351 'children': [
352 {
352 {
353 'id': 'a', 'raw_id': 'a_id', 'text': 'a', 'type': 't1',
353 'id': 'a', 'idx': 0, 'raw_id': 'a_id', 'text': 'a', 'type': 't1',
354 'files_url': expected_files_url + 'a/?at=a',
354 'files_url': expected_files_url + 'a/?at=a',
355 },
355 },
356 {
356 {
357 'id': 'b', 'raw_id': 'b_id', 'text': 'b', 'type': 't1',
357 'id': 'b', 'idx': 0, 'raw_id': 'b_id', 'text': 'b', 'type': 't1',
358 'files_url': expected_files_url + 'b/?at=b',
358 'files_url': expected_files_url + 'b/?at=b',
359 }
359 }
360 ],
360 ],
@@ -363,7 +363,7 b' class TestCreateReferenceData(object):'
363 {
363 {
364 'children': [
364 'children': [
365 {
365 {
366 'id': 'c', 'raw_id': 'c_id', 'text': 'c', 'type': 't2',
366 'id': 'c', 'idx': 0, 'raw_id': 'c_id', 'text': 'c', 'type': 't2',
367 'files_url': expected_files_url + 'c/?at=c',
367 'files_url': expected_files_url + 'c/?at=c',
368 }
368 }
369 ],
369 ],
@@ -385,12 +385,12 b' class TestCreateReferenceData(object):'
385 {
385 {
386 'children': [
386 'children': [
387 {
387 {
388 'id': 'a@a_id', 'raw_id': 'a_id',
388 'id': 'a@a_id', 'idx': 0, 'raw_id': 'a_id',
389 'text': 'a', 'type': 't1',
389 'text': 'a', 'type': 't1',
390 'files_url': expected_files_url + 'a_id/a?at=a',
390 'files_url': expected_files_url + 'a_id/a?at=a',
391 },
391 },
392 {
392 {
393 'id': 'b@b_id', 'raw_id': 'b_id',
393 'id': 'b@b_id', 'idx': 0, 'raw_id': 'b_id',
394 'text': 'b', 'type': 't1',
394 'text': 'b', 'type': 't1',
395 'files_url': expected_files_url + 'b_id/b?at=b',
395 'files_url': expected_files_url + 'b_id/b?at=b',
396 }
396 }
@@ -400,7 +400,7 b' class TestCreateReferenceData(object):'
400 {
400 {
401 'children': [
401 'children': [
402 {
402 {
403 'id': 'c@c_id', 'raw_id': 'c_id',
403 'id': 'c@c_id', 'idx': 0, 'raw_id': 'c_id',
404 'text': 'c', 'type': 't2',
404 'text': 'c', 'type': 't2',
405 'files_url': expected_files_url + 'c_id/c?at=c',
405 'files_url': expected_files_url + 'c_id/c?at=c',
406 }
406 }
@@ -516,6 +516,7 b' class TestReferenceItems(object):'
516 'text': ref_name,
516 'text': ref_name,
517 'id': self._format_function(ref_name, ref_id),
517 'id': self._format_function(ref_name, ref_id),
518 'raw_id': ref_id,
518 'raw_id': ref_id,
519 'idx': 0,
519 'type': self.ref_type,
520 'type': self.ref_type,
520 'files_url': self.fake_url
521 'files_url': self.fake_url
521 }
522 }
@@ -113,7 +113,7 b' class RepoChangelogView(RepoAppView):'
113 h.flash('Branch {} is not found.'.format(h.escape(branch_name)),
113 h.flash('Branch {} is not found.'.format(h.escape(branch_name)),
114 category='warning')
114 category='warning')
115 redirect_url = h.route_path(
115 redirect_url = h.route_path(
116 'repo_changelog_file', repo_name=repo_name,
116 'repo_commits_file', repo_name=repo_name,
117 commit_id=branch_name, f_path=f_path or '')
117 commit_id=branch_name, f_path=f_path or '')
118 raise HTTPFound(redirect_url)
118 raise HTTPFound(redirect_url)
119
119
@@ -127,13 +127,13 b' class RepoChangelogView(RepoAppView):'
127 if f_path:
127 if f_path:
128 # changelog for file
128 # changelog for file
129 return h.route_path(
129 return h.route_path(
130 'repo_changelog_file',
130 'repo_commits_file',
131 repo_name=c.rhodecode_db_repo.repo_name,
131 repo_name=c.rhodecode_db_repo.repo_name,
132 commit_id=commit_id, f_path=f_path,
132 commit_id=commit_id, f_path=f_path,
133 _query=query_params)
133 _query=query_params)
134 else:
134 else:
135 return h.route_path(
135 return h.route_path(
136 'repo_changelog',
136 'repo_commits',
137 repo_name=c.rhodecode_db_repo.repo_name, _query=query_params)
137 repo_name=c.rhodecode_db_repo.repo_name, _query=query_params)
138
138
139 c.total_cs = len(collection)
139 c.total_cs = len(collection)
@@ -171,11 +171,18 b' class RepoChangelogView(RepoAppView):'
171 @HasRepoPermissionAnyDecorator(
171 @HasRepoPermissionAnyDecorator(
172 'repository.read', 'repository.write', 'repository.admin')
172 'repository.read', 'repository.write', 'repository.admin')
173 @view_config(
173 @view_config(
174 route_name='repo_commits', request_method='GET',
175 renderer='rhodecode:templates/commits/changelog.mako')
176 @view_config(
177 route_name='repo_commits_file', request_method='GET',
178 renderer='rhodecode:templates/commits/changelog.mako')
179 # old routes for backward compat
180 @view_config(
174 route_name='repo_changelog', request_method='GET',
181 route_name='repo_changelog', request_method='GET',
175 renderer='rhodecode:templates/changelog/changelog.mako')
182 renderer='rhodecode:templates/commits/changelog.mako')
176 @view_config(
183 @view_config(
177 route_name='repo_changelog_file', request_method='GET',
184 route_name='repo_changelog_file', request_method='GET',
178 renderer='rhodecode:templates/changelog/changelog.mako')
185 renderer='rhodecode:templates/commits/changelog.mako')
179 def repo_changelog(self):
186 def repo_changelog(self):
180 c = self.load_default_context()
187 c = self.load_default_context()
181
188
@@ -224,7 +231,7 b' class RepoChangelogView(RepoAppView):'
224 except RepositoryError as e:
231 except RepositoryError as e:
225 h.flash(safe_str(e), category='warning')
232 h.flash(safe_str(e), category='warning')
226 redirect_url = h.route_path(
233 redirect_url = h.route_path(
227 'repo_changelog', repo_name=self.db_repo_name)
234 'repo_commits', repo_name=self.db_repo_name)
228 raise HTTPFound(redirect_url)
235 raise HTTPFound(redirect_url)
229 collection = list(reversed(collection))
236 collection = list(reversed(collection))
230 else:
237 else:
@@ -246,14 +253,14 b' class RepoChangelogView(RepoAppView):'
246 log.exception(safe_str(e))
253 log.exception(safe_str(e))
247 h.flash(safe_str(h.escape(e)), category='error')
254 h.flash(safe_str(h.escape(e)), category='error')
248 raise HTTPFound(
255 raise HTTPFound(
249 h.route_path('repo_changelog', repo_name=self.db_repo_name))
256 h.route_path('repo_commits', repo_name=self.db_repo_name))
250
257
251 if partial_xhr or self.request.environ.get('HTTP_X_PJAX'):
258 if partial_xhr or self.request.environ.get('HTTP_X_PJAX'):
252 # case when loading dynamic file history in file view
259 # case when loading dynamic file history in file view
253 # loading from ajax, we don't want the first result, it's popped
260 # loading from ajax, we don't want the first result, it's popped
254 # in the code above
261 # in the code above
255 html = render(
262 html = render(
256 'rhodecode:templates/changelog/changelog_file_history.mako',
263 'rhodecode:templates/commits/changelog_file_history.mako',
257 self._get_template_context(c), self.request)
264 self._get_template_context(c), self.request)
258 return Response(html)
265 return Response(html)
259
266
@@ -271,14 +278,14 b' class RepoChangelogView(RepoAppView):'
271 @HasRepoPermissionAnyDecorator(
278 @HasRepoPermissionAnyDecorator(
272 'repository.read', 'repository.write', 'repository.admin')
279 'repository.read', 'repository.write', 'repository.admin')
273 @view_config(
280 @view_config(
274 route_name='repo_changelog_elements', request_method=('GET', 'POST'),
281 route_name='repo_commits_elements', request_method=('GET', 'POST'),
275 renderer='rhodecode:templates/changelog/changelog_elements.mako',
282 renderer='rhodecode:templates/commits/changelog_elements.mako',
276 xhr=True)
283 xhr=True)
277 @view_config(
284 @view_config(
278 route_name='repo_changelog_elements_file', request_method=('GET', 'POST'),
285 route_name='repo_commits_elements_file', request_method=('GET', 'POST'),
279 renderer='rhodecode:templates/changelog/changelog_elements.mako',
286 renderer='rhodecode:templates/commits/changelog_elements.mako',
280 xhr=True)
287 xhr=True)
281 def repo_changelog_elements(self):
288 def repo_commits_elements(self):
282 c = self.load_default_context()
289 c = self.load_default_context()
283 commit_id = self.request.matchdict.get('commit_id')
290 commit_id = self.request.matchdict.get('commit_id')
284 f_path = self._get_f_path(self.request.matchdict)
291 f_path = self._get_f_path(self.request.matchdict)
@@ -312,7 +319,7 b' class RepoChangelogView(RepoAppView):'
312 except (RepositoryError, CommitDoesNotExistError, Exception) as e:
319 except (RepositoryError, CommitDoesNotExistError, Exception) as e:
313 log.exception(safe_str(e))
320 log.exception(safe_str(e))
314 raise HTTPFound(
321 raise HTTPFound(
315 h.route_path('repo_changelog', repo_name=self.db_repo_name))
322 h.route_path('repo_commits', repo_name=self.db_repo_name))
316
323
317 collection = base_commit.get_path_history(
324 collection = base_commit.get_path_history(
318 f_path, limit=hist_limit, pre_load=pre_load)
325 f_path, limit=hist_limit, pre_load=pre_load)
@@ -105,10 +105,9 b' class RepoCommitsView(RepoAppView):'
105
105
106 c.commit_ranges = commits
106 c.commit_ranges = commits
107 if not c.commit_ranges:
107 if not c.commit_ranges:
108 raise RepositoryError(
108 raise RepositoryError('The commit range returned an empty result')
109 'The commit range returned an empty result')
109 except CommitDoesNotExistError as e:
110 except CommitDoesNotExistError:
110 msg = _('No such commit exists. Org exception: `{}`').format(e)
111 msg = _('No such commit exists for this repository')
112 h.flash(msg, category='error')
111 h.flash(msg, category='error')
113 raise HTTPNotFound()
112 raise HTTPNotFound()
114 except Exception:
113 except Exception:
@@ -214,29 +214,23 b' class RepoCompareView(RepoAppView):'
214 pre_load = ["author", "branch", "date", "message"]
214 pre_load = ["author", "branch", "date", "message"]
215 c.ancestor = None
215 c.ancestor = None
216
216
217 if c.file_path:
217 try:
218 if source_commit == target_commit:
218 c.commit_ranges = source_scm.compare(
219 c.commit_ranges = []
219 source_commit.raw_id, target_commit.raw_id,
220 else:
220 target_scm, merge, pre_load=pre_load) or []
221 c.commit_ranges = [target_commit]
221 if merge:
222 else:
222 c.ancestor = source_scm.get_common_ancestor(
223 try:
223 source_commit.raw_id, target_commit.raw_id, target_scm)
224 c.commit_ranges = source_scm.compare(
224 except RepositoryRequirementError:
225 source_commit.raw_id, target_commit.raw_id,
225 msg = _('Could not compare repos with different '
226 target_scm, merge, pre_load=pre_load)
226 'large file settings')
227 if merge:
227 log.error(msg)
228 c.ancestor = source_scm.get_common_ancestor(
228 if partial:
229 source_commit.raw_id, target_commit.raw_id, target_scm)
229 return Response(msg)
230 except RepositoryRequirementError:
230 h.flash(msg, category='error')
231 msg = _('Could not compare repos with different '
231 raise HTTPFound(
232 'large file settings')
232 h.route_path('repo_compare_select',
233 log.error(msg)
233 repo_name=self.db_repo_name))
234 if partial:
235 return Response(msg)
236 h.flash(msg, category='error')
237 raise HTTPFound(
238 h.route_path('repo_compare_select',
239 repo_name=self.db_repo_name))
240
234
241 c.statuses = self.db_repo.statuses(
235 c.statuses = self.db_repo.statuses(
242 [x.raw_id for x in c.commit_ranges])
236 [x.raw_id for x in c.commit_ranges])
This diff has been collapsed as it changes many lines, (503 lines changed) Show them Hide them
@@ -25,6 +25,7 b' import shutil'
25 import tempfile
25 import tempfile
26 import collections
26 import collections
27 import urllib
27 import urllib
28 import pathlib2
28
29
29 from pyramid.httpexceptions import HTTPNotFound, HTTPBadRequest, HTTPFound
30 from pyramid.httpexceptions import HTTPNotFound, HTTPBadRequest, HTTPFound
30 from pyramid.view import view_config
31 from pyramid.view import view_config
@@ -42,7 +43,7 b' from rhodecode.lib.exceptions import Non'
42 from rhodecode.lib.codeblocks import (
43 from rhodecode.lib.codeblocks import (
43 filenode_as_lines_tokens, filenode_as_annotated_lines_tokens)
44 filenode_as_lines_tokens, filenode_as_annotated_lines_tokens)
44 from rhodecode.lib.utils2 import (
45 from rhodecode.lib.utils2 import (
45 convert_line_endings, detect_mode, safe_str, str2bool, safe_int)
46 convert_line_endings, detect_mode, safe_str, str2bool, safe_int, sha1, safe_unicode)
46 from rhodecode.lib.auth import (
47 from rhodecode.lib.auth import (
47 LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired)
48 LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired)
48 from rhodecode.lib.vcs import path as vcspath
49 from rhodecode.lib.vcs import path as vcspath
@@ -87,7 +88,7 b' class RepoFilesView(RepoAppView):'
87 c.enable_downloads = self.db_repo.enable_downloads
88 c.enable_downloads = self.db_repo.enable_downloads
88 return c
89 return c
89
90
90 def _ensure_not_locked(self):
91 def _ensure_not_locked(self, commit_id='tip'):
91 _ = self.request.translate
92 _ = self.request.translate
92
93
93 repo = self.db_repo
94 repo = self.db_repo
@@ -98,21 +99,41 b' class RepoFilesView(RepoAppView):'
98 'warning')
99 'warning')
99 files_url = h.route_path(
100 files_url = h.route_path(
100 'repo_files:default_path',
101 'repo_files:default_path',
101 repo_name=self.db_repo_name, commit_id='tip')
102 repo_name=self.db_repo_name, commit_id=commit_id)
102 raise HTTPFound(files_url)
103 raise HTTPFound(files_url)
103
104
104 def check_branch_permission(self, branch_name):
105 def forbid_non_head(self, is_head, f_path, commit_id='tip', json_mode=False):
106 _ = self.request.translate
107
108 if not is_head:
109 message = _('Cannot modify file. '
110 'Given commit `{}` is not head of a branch.').format(commit_id)
111 h.flash(message, category='warning')
112
113 if json_mode:
114 return message
115
116 files_url = h.route_path(
117 'repo_files', repo_name=self.db_repo_name, commit_id=commit_id,
118 f_path=f_path)
119 raise HTTPFound(files_url)
120
121 def check_branch_permission(self, branch_name, commit_id='tip', json_mode=False):
105 _ = self.request.translate
122 _ = self.request.translate
106
123
107 rule, branch_perm = self._rhodecode_user.get_rule_and_branch_permission(
124 rule, branch_perm = self._rhodecode_user.get_rule_and_branch_permission(
108 self.db_repo_name, branch_name)
125 self.db_repo_name, branch_name)
109 if branch_perm and branch_perm not in ['branch.push', 'branch.push_force']:
126 if branch_perm and branch_perm not in ['branch.push', 'branch.push_force']:
110 h.flash(
127 message = _('Branch `{}` changes forbidden by rule {}.').format(
111 _('Branch `{}` changes forbidden by rule {}.').format(branch_name, rule),
128 branch_name, rule)
112 'warning')
129 h.flash(message, 'warning')
130
131 if json_mode:
132 return message
133
113 files_url = h.route_path(
134 files_url = h.route_path(
114 'repo_files:default_path',
135 'repo_files:default_path', repo_name=self.db_repo_name, commit_id=commit_id)
115 repo_name=self.db_repo_name, commit_id='tip')
136
116 raise HTTPFound(files_url)
137 raise HTTPFound(files_url)
117
138
118 def _get_commit_and_path(self):
139 def _get_commit_and_path(self):
@@ -146,8 +167,7 b' class RepoFilesView(RepoAppView):'
146
167
147 _url = h.route_path(
168 _url = h.route_path(
148 'repo_files_add_file',
169 'repo_files_add_file',
149 repo_name=self.db_repo_name, commit_id=0, f_path='',
170 repo_name=self.db_repo_name, commit_id=0, f_path='')
150 _anchor='edit')
151
171
152 if h.HasRepoPermissionAny(
172 if h.HasRepoPermissionAny(
153 'repository.write', 'repository.admin')(self.db_repo_name):
173 'repository.write', 'repository.admin')(self.db_repo_name):
@@ -185,8 +205,7 b' class RepoFilesView(RepoAppView):'
185 h.flash(_('No such commit exists for this repository'), category='error')
205 h.flash(_('No such commit exists for this repository'), category='error')
186 raise HTTPNotFound()
206 raise HTTPNotFound()
187 except RepositoryError as e:
207 except RepositoryError as e:
188 log.warning('Repository error while fetching '
208 log.warning('Repository error while fetching filenode `%s`. Err:%s', path, e)
189 'filenode `%s`. Err:%s', path, e)
190 h.flash(safe_str(h.escape(e)), category='error')
209 h.flash(safe_str(h.escape(e)), category='error')
191 raise HTTPNotFound()
210 raise HTTPNotFound()
192
211
@@ -195,12 +214,7 b' class RepoFilesView(RepoAppView):'
195 def _is_valid_head(self, commit_id, repo):
214 def _is_valid_head(self, commit_id, repo):
196 branch_name = sha_commit_id = ''
215 branch_name = sha_commit_id = ''
197 is_head = False
216 is_head = False
198
217 log.debug('Checking if commit_id `%s` is a head for %s.', commit_id, repo)
199 if h.is_svn(repo) and not repo.is_empty():
200 # Note: Subversion only has one head.
201 if commit_id == repo.get_commit(commit_idx=-1).raw_id:
202 is_head = True
203 return branch_name, sha_commit_id, is_head
204
218
205 for _branch_name, branch_commit_id in repo.branches.items():
219 for _branch_name, branch_commit_id in repo.branches.items():
206 # simple case we pass in branch name, it's a HEAD
220 # simple case we pass in branch name, it's a HEAD
@@ -216,8 +230,14 b' class RepoFilesView(RepoAppView):'
216 sha_commit_id = branch_commit_id
230 sha_commit_id = branch_commit_id
217 break
231 break
218
232
233 if h.is_svn(repo) and not repo.is_empty():
234 # Note: Subversion only has one head.
235 if commit_id == repo.get_commit(commit_idx=-1).raw_id:
236 is_head = True
237 return branch_name, sha_commit_id, is_head
238
219 # checked branches, means we only need to try to get the branch/commit_sha
239 # checked branches, means we only need to try to get the branch/commit_sha
220 if not repo.is_empty:
240 if not repo.is_empty():
221 commit = repo.get_commit(commit_id=commit_id)
241 commit = repo.get_commit(commit_id=commit_id)
222 if commit:
242 if commit:
223 branch_name = commit.branch
243 branch_name = commit.branch
@@ -225,8 +245,7 b' class RepoFilesView(RepoAppView):'
225
245
226 return branch_name, sha_commit_id, is_head
246 return branch_name, sha_commit_id, is_head
227
247
228 def _get_tree_at_commit(
248 def _get_tree_at_commit(self, c, commit_id, f_path, full_load=False):
229 self, c, commit_id, f_path, full_load=False):
230
249
231 repo_id = self.db_repo.repo_id
250 repo_id = self.db_repo.repo_id
232 force_recache = self.get_recache_flag()
251 force_recache = self.get_recache_flag()
@@ -244,16 +263,16 b' class RepoFilesView(RepoAppView):'
244
263
245 @region.conditional_cache_on_arguments(namespace=cache_namespace_uid,
264 @region.conditional_cache_on_arguments(namespace=cache_namespace_uid,
246 condition=cache_on)
265 condition=cache_on)
247 def compute_file_tree(repo_id, commit_id, f_path, full_load):
266 def compute_file_tree(ver, repo_id, commit_id, f_path, full_load):
248 log.debug('Generating cached file tree for repo_id: %s, %s, %s',
267 log.debug('Generating cached file tree at ver:%s for repo_id: %s, %s, %s',
249 repo_id, commit_id, f_path)
268 ver, repo_id, commit_id, f_path)
250
269
251 c.full_load = full_load
270 c.full_load = full_load
252 return render(
271 return render(
253 'rhodecode:templates/files/files_browser_tree.mako',
272 'rhodecode:templates/files/files_browser_tree.mako',
254 self._get_template_context(c), self.request)
273 self._get_template_context(c), self.request)
255
274
256 return compute_file_tree(self.db_repo.repo_id, commit_id, f_path, full_load)
275 return compute_file_tree('v1', self.db_repo.repo_id, commit_id, f_path, full_load)
257
276
258 def _get_archive_spec(self, fname):
277 def _get_archive_spec(self, fname):
259 log.debug('Detecting archive spec for: `%s`', fname)
278 log.debug('Detecting archive spec for: `%s`', fname)
@@ -261,8 +280,7 b' class RepoFilesView(RepoAppView):'
261 fileformat = None
280 fileformat = None
262 ext = None
281 ext = None
263 content_type = None
282 content_type = None
264 for a_type, ext_data in settings.ARCHIVE_SPECS.items():
283 for a_type, content_type, extension in settings.ARCHIVE_SPECS:
265 content_type, extension = ext_data
266
284
267 if fname.endswith(extension):
285 if fname.endswith(extension):
268 fileformat = a_type
286 fileformat = a_type
@@ -278,6 +296,15 b' class RepoFilesView(RepoAppView):'
278
296
279 return commit_id, ext, fileformat, content_type
297 return commit_id, ext, fileformat, content_type
280
298
299 def create_pure_path(self, *parts):
300 # Split paths and sanitize them, removing any ../ etc
301 sanitized_path = [
302 x for x in pathlib2.PurePath(*parts).parts
303 if x not in ['.', '..']]
304
305 pure_path = pathlib2.PurePath(*sanitized_path)
306 return pure_path
307
281 @LoginRequired()
308 @LoginRequired()
282 @HasRepoPermissionAnyDecorator(
309 @HasRepoPermissionAnyDecorator(
283 'repository.read', 'repository.write', 'repository.admin')
310 'repository.read', 'repository.write', 'repository.admin')
@@ -289,9 +316,10 b' class RepoFilesView(RepoAppView):'
289 from rhodecode import CONFIG
316 from rhodecode import CONFIG
290 _ = self.request.translate
317 _ = self.request.translate
291 self.load_default_context()
318 self.load_default_context()
292
319 default_at_path = '/'
293 fname = self.request.matchdict['fname']
320 fname = self.request.matchdict['fname']
294 subrepos = self.request.GET.get('subrepos') == 'true'
321 subrepos = self.request.GET.get('subrepos') == 'true'
322 at_path = self.request.GET.get('at_path') or default_at_path
295
323
296 if not self.db_repo.enable_downloads:
324 if not self.db_repo.enable_downloads:
297 return Response(_('Downloads disabled'))
325 return Response(_('Downloads disabled'))
@@ -311,10 +339,31 b' class RepoFilesView(RepoAppView):'
311 except EmptyRepositoryError:
339 except EmptyRepositoryError:
312 return Response(_('Empty repository'))
340 return Response(_('Empty repository'))
313
341
314 archive_name = '%s-%s%s%s' % (
342 try:
315 safe_str(self.db_repo_name.replace('/', '_')),
343 at_path = commit.get_node(at_path).path or default_at_path
316 '-sub' if subrepos else '',
344 except Exception:
317 safe_str(commit.short_id), ext)
345 return Response(_('No node at path {} for this repository').format(at_path))
346
347 path_sha = sha1(at_path)[:8]
348
349 # original backward compat name of archive
350 clean_name = safe_str(self.db_repo_name.replace('/', '_'))
351 short_sha = safe_str(commit.short_id)
352
353 if at_path == default_at_path:
354 archive_name = '{}-{}{}{}'.format(
355 clean_name,
356 '-sub' if subrepos else '',
357 short_sha,
358 ext)
359 # custom path and new name
360 else:
361 archive_name = '{}-{}{}-{}{}'.format(
362 clean_name,
363 '-sub' if subrepos else '',
364 short_sha,
365 path_sha,
366 ext)
318
367
319 use_cached_archive = False
368 use_cached_archive = False
320 archive_cache_enabled = CONFIG.get(
369 archive_cache_enabled = CONFIG.get(
@@ -339,7 +388,8 b' class RepoFilesView(RepoAppView):'
339 fd, archive = tempfile.mkstemp()
388 fd, archive = tempfile.mkstemp()
340 log.debug('Creating new temp archive in %s', archive)
389 log.debug('Creating new temp archive in %s', archive)
341 try:
390 try:
342 commit.archive_repo(archive, kind=fileformat, subrepos=subrepos)
391 commit.archive_repo(archive, kind=fileformat, subrepos=subrepos,
392 archive_at_path=at_path)
343 except ImproperArchiveTypeError:
393 except ImproperArchiveTypeError:
344 return _('Unknown archive type')
394 return _('Unknown archive type')
345 if archive_cache_enabled:
395 if archive_cache_enabled:
@@ -632,8 +682,7 b' class RepoFilesView(RepoAppView):'
632 c.authors = []
682 c.authors = []
633 # this loads a simple tree without metadata to speed things up
683 # this loads a simple tree without metadata to speed things up
634 # later via ajax we call repo_nodetree_full and fetch whole
684 # later via ajax we call repo_nodetree_full and fetch whole
635 c.file_tree = self._get_tree_at_commit(
685 c.file_tree = self._get_tree_at_commit(c, c.commit.raw_id, f_path)
636 c, c.commit.raw_id, f_path)
637
686
638 except RepositoryError as e:
687 except RepositoryError as e:
639 h.flash(safe_str(h.escape(e)), category='error')
688 h.flash(safe_str(h.escape(e)), category='error')
@@ -875,18 +924,17 b' class RepoFilesView(RepoAppView):'
875 self.db_repo_name, self.db_repo.repo_id, commit.raw_id, f_path)
924 self.db_repo_name, self.db_repo.repo_id, commit.raw_id, f_path)
876 return {'nodes': metadata}
925 return {'nodes': metadata}
877
926
878 def _create_references(
927 def _create_references(self, branches_or_tags, symbolic_reference, f_path, ref_type):
879 self, branches_or_tags, symbolic_reference, f_path):
880 items = []
928 items = []
881 for name, commit_id in branches_or_tags.items():
929 for name, commit_id in branches_or_tags.items():
882 sym_ref = symbolic_reference(commit_id, name, f_path)
930 sym_ref = symbolic_reference(commit_id, name, f_path, ref_type)
883 items.append((sym_ref, name))
931 items.append((sym_ref, name, ref_type))
884 return items
932 return items
885
933
886 def _symbolic_reference(self, commit_id, name, f_path):
934 def _symbolic_reference(self, commit_id, name, f_path, ref_type):
887 return commit_id
935 return commit_id
888
936
889 def _symbolic_reference_svn(self, commit_id, name, f_path):
937 def _symbolic_reference_svn(self, commit_id, name, f_path, ref_type):
890 new_f_path = vcspath.join(name, f_path)
938 new_f_path = vcspath.join(name, f_path)
891 return u'%s@%s' % (new_f_path, commit_id)
939 return u'%s@%s' % (new_f_path, commit_id)
892
940
@@ -916,7 +964,7 b' class RepoFilesView(RepoAppView):'
916 for commit in commits:
964 for commit in commits:
917 branch = ' (%s)' % commit.branch if commit.branch else ''
965 branch = ' (%s)' % commit.branch if commit.branch else ''
918 n_desc = 'r%s:%s%s' % (commit.idx, commit.short_id, branch)
966 n_desc = 'r%s:%s%s' % (commit.idx, commit.short_id, branch)
919 commits_group[0].append((commit.raw_id, n_desc,))
967 commits_group[0].append((commit.raw_id, n_desc, 'sha'))
920 history.append(commits_group)
968 history.append(commits_group)
921
969
922 symbolic_reference = self._symbolic_reference
970 symbolic_reference = self._symbolic_reference
@@ -932,11 +980,11 b' class RepoFilesView(RepoAppView):'
932 symbolic_reference = self._symbolic_reference_svn
980 symbolic_reference = self._symbolic_reference_svn
933
981
934 branches = self._create_references(
982 branches = self._create_references(
935 self.rhodecode_vcs_repo.branches, symbolic_reference, f_path)
983 self.rhodecode_vcs_repo.branches, symbolic_reference, f_path, 'branch')
936 branches_group = (branches, _("Branches"))
984 branches_group = (branches, _("Branches"))
937
985
938 tags = self._create_references(
986 tags = self._create_references(
939 self.rhodecode_vcs_repo.tags, symbolic_reference, f_path)
987 self.rhodecode_vcs_repo.tags, symbolic_reference, f_path, 'tag')
940 tags_group = (tags, _("Tags"))
988 tags_group = (tags, _("Tags"))
941
989
942 history.append(branches_group)
990 history.append(branches_group)
@@ -964,7 +1012,7 b' class RepoFilesView(RepoAppView):'
964 for obj in file_history:
1012 for obj in file_history:
965 res.append({
1013 res.append({
966 'text': obj[1],
1014 'text': obj[1],
967 'children': [{'id': o[0], 'text': o[1]} for o in obj[0]]
1015 'children': [{'id': o[0], 'text': o[1], 'type': o[2]} for o in obj[0]]
968 })
1016 })
969
1017
970 data = {
1018 data = {
@@ -1035,15 +1083,9 b' class RepoFilesView(RepoAppView):'
1035 _branch_name, _sha_commit_id, is_head = \
1083 _branch_name, _sha_commit_id, is_head = \
1036 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1084 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1037
1085
1038 if not is_head:
1086 self.forbid_non_head(is_head, f_path)
1039 h.flash(_('You can only delete files with commit '
1087 self.check_branch_permission(_branch_name)
1040 'being a valid branch head.'), category='warning')
1041 raise HTTPFound(
1042 h.route_path('repo_files',
1043 repo_name=self.db_repo_name, commit_id='tip',
1044 f_path=f_path))
1045
1088
1046 self.check_branch_permission(_branch_name)
1047 c.commit = self._get_commit_or_redirect(commit_id)
1089 c.commit = self._get_commit_or_redirect(commit_id)
1048 c.file = self._get_filenode_or_redirect(c.commit, f_path)
1090 c.file = self._get_filenode_or_redirect(c.commit, f_path)
1049
1091
@@ -1069,13 +1111,7 b' class RepoFilesView(RepoAppView):'
1069 _branch_name, _sha_commit_id, is_head = \
1111 _branch_name, _sha_commit_id, is_head = \
1070 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1112 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1071
1113
1072 if not is_head:
1114 self.forbid_non_head(is_head, f_path)
1073 h.flash(_('You can only delete files with commit '
1074 'being a valid branch head.'), category='warning')
1075 raise HTTPFound(
1076 h.route_path('repo_files',
1077 repo_name=self.db_repo_name, commit_id='tip',
1078 f_path=f_path))
1079 self.check_branch_permission(_branch_name)
1115 self.check_branch_permission(_branch_name)
1080
1116
1081 c.commit = self._get_commit_or_redirect(commit_id)
1117 c.commit = self._get_commit_or_redirect(commit_id)
@@ -1125,14 +1161,8 b' class RepoFilesView(RepoAppView):'
1125 _branch_name, _sha_commit_id, is_head = \
1161 _branch_name, _sha_commit_id, is_head = \
1126 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1162 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1127
1163
1128 if not is_head:
1164 self.forbid_non_head(is_head, f_path, commit_id=commit_id)
1129 h.flash(_('You can only edit files with commit '
1165 self.check_branch_permission(_branch_name, commit_id=commit_id)
1130 'being a valid branch head.'), category='warning')
1131 raise HTTPFound(
1132 h.route_path('repo_files',
1133 repo_name=self.db_repo_name, commit_id='tip',
1134 f_path=f_path))
1135 self.check_branch_permission(_branch_name)
1136
1166
1137 c.commit = self._get_commit_or_redirect(commit_id)
1167 c.commit = self._get_commit_or_redirect(commit_id)
1138 c.file = self._get_filenode_or_redirect(c.commit, f_path)
1168 c.file = self._get_filenode_or_redirect(c.commit, f_path)
@@ -1144,8 +1174,7 b' class RepoFilesView(RepoAppView):'
1144 commit_id=c.commit.raw_id, f_path=f_path)
1174 commit_id=c.commit.raw_id, f_path=f_path)
1145 raise HTTPFound(files_url)
1175 raise HTTPFound(files_url)
1146
1176
1147 c.default_message = _(
1177 c.default_message = _('Edited file {} via RhodeCode Enterprise').format(f_path)
1148 'Edited file {} via RhodeCode Enterprise').format(f_path)
1149 c.f_path = f_path
1178 c.f_path = f_path
1150
1179
1151 return self._get_template_context(c)
1180 return self._get_template_context(c)
@@ -1162,32 +1191,23 b' class RepoFilesView(RepoAppView):'
1162 commit_id, f_path = self._get_commit_and_path()
1191 commit_id, f_path = self._get_commit_and_path()
1163
1192
1164 self._ensure_not_locked()
1193 self._ensure_not_locked()
1165 _branch_name, _sha_commit_id, is_head = \
1166 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1167
1168 if not is_head:
1169 h.flash(_('You can only edit files with commit '
1170 'being a valid branch head.'), category='warning')
1171 raise HTTPFound(
1172 h.route_path('repo_files',
1173 repo_name=self.db_repo_name, commit_id='tip',
1174 f_path=f_path))
1175
1176 self.check_branch_permission(_branch_name)
1177
1194
1178 c.commit = self._get_commit_or_redirect(commit_id)
1195 c.commit = self._get_commit_or_redirect(commit_id)
1179 c.file = self._get_filenode_or_redirect(c.commit, f_path)
1196 c.file = self._get_filenode_or_redirect(c.commit, f_path)
1180
1197
1181 if c.file.is_binary:
1198 if c.file.is_binary:
1182 raise HTTPFound(
1199 raise HTTPFound(h.route_path('repo_files', repo_name=self.db_repo_name,
1183 h.route_path('repo_files',
1200 commit_id=c.commit.raw_id, f_path=f_path))
1184 repo_name=self.db_repo_name,
1201
1185 commit_id=c.commit.raw_id,
1202 _branch_name, _sha_commit_id, is_head = \
1186 f_path=f_path))
1203 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1187
1204
1188 c.default_message = _(
1205 self.forbid_non_head(is_head, f_path, commit_id=commit_id)
1189 'Edited file {} via RhodeCode Enterprise').format(f_path)
1206 self.check_branch_permission(_branch_name, commit_id=commit_id)
1207
1208 c.default_message = _('Edited file {} via RhodeCode Enterprise').format(f_path)
1190 c.f_path = f_path
1209 c.f_path = f_path
1210
1191 old_content = c.file.content
1211 old_content = c.file.content
1192 sl = old_content.splitlines(1)
1212 sl = old_content.splitlines(1)
1193 first_line = sl[0] if sl else ''
1213 first_line = sl[0] if sl else ''
@@ -1198,20 +1218,25 b' class RepoFilesView(RepoAppView):'
1198 content = convert_line_endings(r_post.get('content', ''), line_ending_mode)
1218 content = convert_line_endings(r_post.get('content', ''), line_ending_mode)
1199
1219
1200 message = r_post.get('message') or c.default_message
1220 message = r_post.get('message') or c.default_message
1201 org_f_path = c.file.unicode_path
1221 org_node_path = c.file.unicode_path
1202 filename = r_post['filename']
1222 filename = r_post['filename']
1203 org_filename = c.file.name
1223
1224 root_path = c.file.dir_path
1225 pure_path = self.create_pure_path(root_path, filename)
1226 node_path = safe_unicode(bytes(pure_path))
1204
1227
1205 if content == old_content and filename == org_filename:
1228 default_redirect_url = h.route_path('repo_commit', repo_name=self.db_repo_name,
1206 h.flash(_('No changes'), category='warning')
1229 commit_id=commit_id)
1207 raise HTTPFound(
1230 if content == old_content and node_path == org_node_path:
1208 h.route_path('repo_commit', repo_name=self.db_repo_name,
1231 h.flash(_('No changes detected on {}').format(org_node_path),
1209 commit_id='tip'))
1232 category='warning')
1233 raise HTTPFound(default_redirect_url)
1234
1210 try:
1235 try:
1211 mapping = {
1236 mapping = {
1212 org_f_path: {
1237 org_node_path: {
1213 'org_filename': org_f_path,
1238 'org_filename': org_node_path,
1214 'filename': os.path.join(c.file.dir_path, filename),
1239 'filename': node_path,
1215 'content': content,
1240 'content': content,
1216 'lexer': '',
1241 'lexer': '',
1217 'op': 'mod',
1242 'op': 'mod',
@@ -1219,7 +1244,7 b' class RepoFilesView(RepoAppView):'
1219 }
1244 }
1220 }
1245 }
1221
1246
1222 ScmModel().update_nodes(
1247 commit = ScmModel().update_nodes(
1223 user=self._rhodecode_db_user.user_id,
1248 user=self._rhodecode_db_user.user_id,
1224 repo=self.db_repo,
1249 repo=self.db_repo,
1225 message=message,
1250 message=message,
@@ -1227,21 +1252,25 b' class RepoFilesView(RepoAppView):'
1227 parent_commit=c.commit,
1252 parent_commit=c.commit,
1228 )
1253 )
1229
1254
1230 h.flash(
1255 h.flash(_('Successfully committed changes to file `{}`').format(
1231 _('Successfully committed changes to file `{}`').format(
1232 h.escape(f_path)), category='success')
1256 h.escape(f_path)), category='success')
1257 default_redirect_url = h.route_path(
1258 'repo_commit', repo_name=self.db_repo_name, commit_id=commit.raw_id)
1259
1233 except Exception:
1260 except Exception:
1234 log.exception('Error occurred during commit')
1261 log.exception('Error occurred during commit')
1235 h.flash(_('Error occurred during commit'), category='error')
1262 h.flash(_('Error occurred during commit'), category='error')
1236 raise HTTPFound(
1263
1237 h.route_path('repo_commit', repo_name=self.db_repo_name,
1264 raise HTTPFound(default_redirect_url)
1238 commit_id='tip'))
1239
1265
1240 @LoginRequired()
1266 @LoginRequired()
1241 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
1267 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
1242 @view_config(
1268 @view_config(
1243 route_name='repo_files_add_file', request_method='GET',
1269 route_name='repo_files_add_file', request_method='GET',
1244 renderer='rhodecode:templates/files/files_add.mako')
1270 renderer='rhodecode:templates/files/files_add.mako')
1271 @view_config(
1272 route_name='repo_files_upload_file', request_method='GET',
1273 renderer='rhodecode:templates/files/files_upload.mako')
1245 def repo_files_add_file(self):
1274 def repo_files_add_file(self):
1246 _ = self.request.translate
1275 _ = self.request.translate
1247 c = self.load_default_context()
1276 c = self.load_default_context()
@@ -1252,27 +1281,20 b' class RepoFilesView(RepoAppView):'
1252 c.commit = self._get_commit_or_redirect(commit_id, redirect_after=False)
1281 c.commit = self._get_commit_or_redirect(commit_id, redirect_after=False)
1253 if c.commit is None:
1282 if c.commit is None:
1254 c.commit = EmptyCommit(alias=self.rhodecode_vcs_repo.alias)
1283 c.commit = EmptyCommit(alias=self.rhodecode_vcs_repo.alias)
1255 c.default_message = (_('Added file via RhodeCode Enterprise'))
1256 c.f_path = f_path.lstrip('/') # ensure not relative path
1257
1284
1258 if self.rhodecode_vcs_repo.is_empty:
1285 if self.rhodecode_vcs_repo.is_empty():
1259 # for empty repository we cannot check for current branch, we rely on
1286 # for empty repository we cannot check for current branch, we rely on
1260 # c.commit.branch instead
1287 # c.commit.branch instead
1261 _branch_name = c.commit.branch
1288 _branch_name, _sha_commit_id, is_head = c.commit.branch, '', True
1262 is_head = True
1263 else:
1289 else:
1264 _branch_name, _sha_commit_id, is_head = \
1290 _branch_name, _sha_commit_id, is_head = \
1265 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1291 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1266
1292
1267 if not is_head:
1293 self.forbid_non_head(is_head, f_path, commit_id=commit_id)
1268 h.flash(_('You can only add files with commit '
1294 self.check_branch_permission(_branch_name, commit_id=commit_id)
1269 'being a valid branch head.'), category='warning')
1270 raise HTTPFound(
1271 h.route_path('repo_files',
1272 repo_name=self.db_repo_name, commit_id='tip',
1273 f_path=f_path))
1274
1295
1275 self.check_branch_permission(_branch_name)
1296 c.default_message = (_('Added file via RhodeCode Enterprise'))
1297 c.f_path = f_path.lstrip('/') # ensure not relative path
1276
1298
1277 return self._get_template_context(c)
1299 return self._get_template_context(c)
1278
1300
@@ -1289,86 +1311,62 b' class RepoFilesView(RepoAppView):'
1289
1311
1290 self._ensure_not_locked()
1312 self._ensure_not_locked()
1291
1313
1292 r_post = self.request.POST
1314 c.commit = self._get_commit_or_redirect(commit_id, redirect_after=False)
1293
1294 c.commit = self._get_commit_or_redirect(
1295 commit_id, redirect_after=False)
1296 if c.commit is None:
1315 if c.commit is None:
1297 c.commit = EmptyCommit(alias=self.rhodecode_vcs_repo.alias)
1316 c.commit = EmptyCommit(alias=self.rhodecode_vcs_repo.alias)
1298
1317
1299 if self.rhodecode_vcs_repo.is_empty:
1318 # calculate redirect URL
1300 # for empty repository we cannot check for current branch, we rely on
1319 if self.rhodecode_vcs_repo.is_empty():
1301 # c.commit.branch instead
1302 _branch_name = c.commit.branch
1303 is_head = True
1304 else:
1305 _branch_name, _sha_commit_id, is_head = \
1306 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1307
1308 if not is_head:
1309 h.flash(_('You can only add files with commit '
1310 'being a valid branch head.'), category='warning')
1311 raise HTTPFound(
1312 h.route_path('repo_files',
1313 repo_name=self.db_repo_name, commit_id='tip',
1314 f_path=f_path))
1315
1316 self.check_branch_permission(_branch_name)
1317
1318 c.default_message = (_('Added file via RhodeCode Enterprise'))
1319 c.f_path = f_path
1320 unix_mode = 0
1321 content = convert_line_endings(r_post.get('content', ''), unix_mode)
1322
1323 message = r_post.get('message') or c.default_message
1324 filename = r_post.get('filename')
1325 location = r_post.get('location', '') # dir location
1326 file_obj = r_post.get('upload_file', None)
1327
1328 if file_obj is not None and hasattr(file_obj, 'filename'):
1329 filename = r_post.get('filename_upload')
1330 content = file_obj.file
1331
1332 if hasattr(content, 'file'):
1333 # non posix systems store real file under file attr
1334 content = content.file
1335
1336 if self.rhodecode_vcs_repo.is_empty:
1337 default_redirect_url = h.route_path(
1320 default_redirect_url = h.route_path(
1338 'repo_summary', repo_name=self.db_repo_name)
1321 'repo_summary', repo_name=self.db_repo_name)
1339 else:
1322 else:
1340 default_redirect_url = h.route_path(
1323 default_redirect_url = h.route_path(
1341 'repo_commit', repo_name=self.db_repo_name, commit_id='tip')
1324 'repo_commit', repo_name=self.db_repo_name, commit_id='tip')
1342
1325
1343 # If there's no commit, redirect to repo summary
1326 if self.rhodecode_vcs_repo.is_empty():
1344 if type(c.commit) is EmptyCommit:
1327 # for empty repository we cannot check for current branch, we rely on
1345 redirect_url = h.route_path(
1328 # c.commit.branch instead
1346 'repo_summary', repo_name=self.db_repo_name)
1329 _branch_name, _sha_commit_id, is_head = c.commit.branch, '', True
1347 else:
1330 else:
1348 redirect_url = default_redirect_url
1331 _branch_name, _sha_commit_id, is_head = \
1332 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1333
1334 self.forbid_non_head(is_head, f_path, commit_id=commit_id)
1335 self.check_branch_permission(_branch_name, commit_id=commit_id)
1336
1337 c.default_message = (_('Added file via RhodeCode Enterprise'))
1338 c.f_path = f_path
1339
1340 r_post = self.request.POST
1341 message = r_post.get('message') or c.default_message
1342 filename = r_post.get('filename')
1343 unix_mode = 0
1344 content = convert_line_endings(r_post.get('content', ''), unix_mode)
1349
1345
1350 if not filename:
1346 if not filename:
1351 h.flash(_('No filename'), category='warning')
1347 # If there's no commit, redirect to repo summary
1348 if type(c.commit) is EmptyCommit:
1349 redirect_url = h.route_path(
1350 'repo_summary', repo_name=self.db_repo_name)
1351 else:
1352 redirect_url = default_redirect_url
1353 h.flash(_('No filename specified'), category='warning')
1352 raise HTTPFound(redirect_url)
1354 raise HTTPFound(redirect_url)
1353
1355
1354 # extract the location from filename,
1356 root_path = f_path
1355 # allows using foo/bar.txt syntax to create subdirectories
1357 pure_path = self.create_pure_path(root_path, filename)
1356 subdir_loc = filename.rsplit('/', 1)
1358 node_path = safe_unicode(bytes(pure_path).lstrip('/'))
1357 if len(subdir_loc) == 2:
1358 location = os.path.join(location, subdir_loc[0])
1359
1359
1360 # strip all crap out of file, just leave the basename
1361 filename = os.path.basename(filename)
1362 node_path = os.path.join(location, filename)
1363 author = self._rhodecode_db_user.full_contact
1360 author = self._rhodecode_db_user.full_contact
1361 nodes = {
1362 node_path: {
1363 'content': content
1364 }
1365 }
1364
1366
1365 try:
1367 try:
1366 nodes = {
1368
1367 node_path: {
1369 commit = ScmModel().create_nodes(
1368 'content': content
1369 }
1370 }
1371 ScmModel().create_nodes(
1372 user=self._rhodecode_db_user.user_id,
1370 user=self._rhodecode_db_user.user_id,
1373 repo=self.db_repo,
1371 repo=self.db_repo,
1374 message=message,
1372 message=message,
@@ -1377,14 +1375,16 b' class RepoFilesView(RepoAppView):'
1377 author=author,
1375 author=author,
1378 )
1376 )
1379
1377
1380 h.flash(
1378 h.flash(_('Successfully committed new file `{}`').format(
1381 _('Successfully committed new file `{}`').format(
1382 h.escape(node_path)), category='success')
1379 h.escape(node_path)), category='success')
1380
1381 default_redirect_url = h.route_path(
1382 'repo_commit', repo_name=self.db_repo_name, commit_id=commit.raw_id)
1383
1383 except NonRelativePathError:
1384 except NonRelativePathError:
1384 log.exception('Non Relative path found')
1385 log.exception('Non Relative path found')
1385 h.flash(_(
1386 h.flash(_('The location specified must be a relative path and must not '
1386 'The location specified must be a relative path and must not '
1387 'contain .. in the path'), category='warning')
1387 'contain .. in the path'), category='warning')
1388 raise HTTPFound(default_redirect_url)
1388 raise HTTPFound(default_redirect_url)
1389 except (NodeError, NodeAlreadyExistsError) as e:
1389 except (NodeError, NodeAlreadyExistsError) as e:
1390 h.flash(_(h.escape(e)), category='error')
1390 h.flash(_(h.escape(e)), category='error')
@@ -1393,3 +1393,134 b' class RepoFilesView(RepoAppView):'
1393 h.flash(_('Error occurred during commit'), category='error')
1393 h.flash(_('Error occurred during commit'), category='error')
1394
1394
1395 raise HTTPFound(default_redirect_url)
1395 raise HTTPFound(default_redirect_url)
1396
1397 @LoginRequired()
1398 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
1399 @CSRFRequired()
1400 @view_config(
1401 route_name='repo_files_upload_file', request_method='POST',
1402 renderer='json_ext')
1403 def repo_files_upload_file(self):
1404 _ = self.request.translate
1405 c = self.load_default_context()
1406 commit_id, f_path = self._get_commit_and_path()
1407
1408 self._ensure_not_locked()
1409
1410 c.commit = self._get_commit_or_redirect(commit_id, redirect_after=False)
1411 if c.commit is None:
1412 c.commit = EmptyCommit(alias=self.rhodecode_vcs_repo.alias)
1413
1414 # calculate redirect URL
1415 if self.rhodecode_vcs_repo.is_empty():
1416 default_redirect_url = h.route_path(
1417 'repo_summary', repo_name=self.db_repo_name)
1418 else:
1419 default_redirect_url = h.route_path(
1420 'repo_commit', repo_name=self.db_repo_name, commit_id='tip')
1421
1422 if self.rhodecode_vcs_repo.is_empty():
1423 # for empty repository we cannot check for current branch, we rely on
1424 # c.commit.branch instead
1425 _branch_name, _sha_commit_id, is_head = c.commit.branch, '', True
1426 else:
1427 _branch_name, _sha_commit_id, is_head = \
1428 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1429
1430 error = self.forbid_non_head(is_head, f_path, json_mode=True)
1431 if error:
1432 return {
1433 'error': error,
1434 'redirect_url': default_redirect_url
1435 }
1436 error = self.check_branch_permission(_branch_name, json_mode=True)
1437 if error:
1438 return {
1439 'error': error,
1440 'redirect_url': default_redirect_url
1441 }
1442
1443 c.default_message = (_('Uploaded file via RhodeCode Enterprise'))
1444 c.f_path = f_path
1445
1446 r_post = self.request.POST
1447
1448 message = c.default_message
1449 user_message = r_post.getall('message')
1450 if isinstance(user_message, list) and user_message:
1451 # we take the first from duplicated results if it's not empty
1452 message = user_message[0] if user_message[0] else message
1453
1454 nodes = {}
1455
1456 for file_obj in r_post.getall('files_upload') or []:
1457 content = file_obj.file
1458 filename = file_obj.filename
1459
1460 root_path = f_path
1461 pure_path = self.create_pure_path(root_path, filename)
1462 node_path = safe_unicode(bytes(pure_path).lstrip('/'))
1463
1464 nodes[node_path] = {
1465 'content': content
1466 }
1467
1468 if not nodes:
1469 error = 'missing files'
1470 return {
1471 'error': error,
1472 'redirect_url': default_redirect_url
1473 }
1474
1475 author = self._rhodecode_db_user.full_contact
1476
1477 try:
1478 commit = ScmModel().create_nodes(
1479 user=self._rhodecode_db_user.user_id,
1480 repo=self.db_repo,
1481 message=message,
1482 nodes=nodes,
1483 parent_commit=c.commit,
1484 author=author,
1485 )
1486 if len(nodes) == 1:
1487 flash_message = _('Successfully committed {} new files').format(len(nodes))
1488 else:
1489 flash_message = _('Successfully committed 1 new file')
1490
1491 h.flash(flash_message, category='success')
1492
1493 default_redirect_url = h.route_path(
1494 'repo_commit', repo_name=self.db_repo_name, commit_id=commit.raw_id)
1495
1496 except NonRelativePathError:
1497 log.exception('Non Relative path found')
1498 error = _('The location specified must be a relative path and must not '
1499 'contain .. in the path')
1500 h.flash(error, category='warning')
1501
1502 return {
1503 'error': error,
1504 'redirect_url': default_redirect_url
1505 }
1506 except (NodeError, NodeAlreadyExistsError) as e:
1507 error = h.escape(e)
1508 h.flash(error, category='error')
1509
1510 return {
1511 'error': error,
1512 'redirect_url': default_redirect_url
1513 }
1514 except Exception:
1515 log.exception('Error occurred during commit')
1516 error = _('Error occurred during commit')
1517 h.flash(error, category='error')
1518 return {
1519 'error': error,
1520 'redirect_url': default_redirect_url
1521 }
1522
1523 return {
1524 'error': None,
1525 'redirect_url': default_redirect_url
1526 }
@@ -72,6 +72,7 b' class RepoSummaryView(RepoAppView):'
72 log.debug("Searching for a README file.")
72 log.debug("Searching for a README file.")
73 readme_node = ReadmeFinder(_renderer_type).search(commit)
73 readme_node = ReadmeFinder(_renderer_type).search(commit)
74 if readme_node:
74 if readme_node:
75 log.debug('Found README node: %s', readme_node)
75 relative_urls = {
76 relative_urls = {
76 'raw': h.route_path(
77 'raw': h.route_path(
77 'repo_file_raw', repo_name=_repo_name,
78 'repo_file_raw', repo_name=_repo_name,
@@ -82,7 +83,8 b' class RepoSummaryView(RepoAppView):'
82 }
83 }
83 readme_data = self._render_readme_or_none(
84 readme_data = self._render_readme_or_none(
84 commit, readme_node, relative_urls)
85 commit, readme_node, relative_urls)
85 readme_filename = readme_node.path
86 readme_filename = readme_node.unicode_path
87
86 return readme_data, readme_filename
88 return readme_data, readme_filename
87
89
88 inv_context_manager = rc_cache.InvalidationContext(
90 inv_context_manager = rc_cache.InvalidationContext(
@@ -152,6 +154,26 b' class RepoSummaryView(RepoAppView):'
152 c.comments = self.db_repo.get_comments(page_ids)
154 c.comments = self.db_repo.get_comments(page_ids)
153 c.statuses = self.db_repo.statuses(page_ids)
155 c.statuses = self.db_repo.statuses(page_ids)
154
156
157 def _prepare_and_set_clone_url(self, c):
158 username = ''
159 if self._rhodecode_user.username != User.DEFAULT_USER:
160 username = safe_str(self._rhodecode_user.username)
161
162 _def_clone_uri = _def_clone_uri_id = c.clone_uri_tmpl
163 _def_clone_uri_ssh = c.clone_uri_ssh_tmpl
164
165 if '{repo}' in _def_clone_uri:
166 _def_clone_uri_id = _def_clone_uri.replace('{repo}', '_{repoid}')
167 elif '{repoid}' in _def_clone_uri:
168 _def_clone_uri_id = _def_clone_uri.replace('_{repoid}', '{repo}')
169
170 c.clone_repo_url = self.db_repo.clone_url(
171 user=username, uri_tmpl=_def_clone_uri)
172 c.clone_repo_url_id = self.db_repo.clone_url(
173 user=username, uri_tmpl=_def_clone_uri_id)
174 c.clone_repo_url_ssh = self.db_repo.clone_url(
175 uri_tmpl=_def_clone_uri_ssh, ssh=True)
176
155 @LoginRequired()
177 @LoginRequired()
156 @HasRepoPermissionAnyDecorator(
178 @HasRepoPermissionAnyDecorator(
157 'repository.read', 'repository.write', 'repository.admin')
179 'repository.read', 'repository.write', 'repository.admin')
@@ -160,6 +182,7 b' class RepoSummaryView(RepoAppView):'
160 renderer='rhodecode:templates/summary/summary_commits.mako')
182 renderer='rhodecode:templates/summary/summary_commits.mako')
161 def summary_commits(self):
183 def summary_commits(self):
162 c = self.load_default_context()
184 c = self.load_default_context()
185 self._prepare_and_set_clone_url(c)
163 self._load_commits_context(c)
186 self._load_commits_context(c)
164 return self._get_template_context(c)
187 return self._get_template_context(c)
165
188
@@ -179,26 +202,11 b' class RepoSummaryView(RepoAppView):'
179 c = self.load_default_context()
202 c = self.load_default_context()
180
203
181 # Prepare the clone URL
204 # Prepare the clone URL
182 username = ''
205 self._prepare_and_set_clone_url(c)
183 if self._rhodecode_user.username != User.DEFAULT_USER:
184 username = safe_str(self._rhodecode_user.username)
185
186 _def_clone_uri = _def_clone_uri_id = c.clone_uri_tmpl
187 _def_clone_uri_ssh = c.clone_uri_ssh_tmpl
188
206
189 if '{repo}' in _def_clone_uri:
207 # update every 5 min
190 _def_clone_uri_id = _def_clone_uri.replace(
208 if self.db_repo.last_commit_cache_update_diff > 60 * 5:
191 '{repo}', '_{repoid}')
209 self.db_repo.update_commit_cache()
192 elif '{repoid}' in _def_clone_uri:
193 _def_clone_uri_id = _def_clone_uri.replace(
194 '_{repoid}', '{repo}')
195
196 c.clone_repo_url = self.db_repo.clone_url(
197 user=username, uri_tmpl=_def_clone_uri)
198 c.clone_repo_url_id = self.db_repo.clone_url(
199 user=username, uri_tmpl=_def_clone_uri_id)
200 c.clone_repo_url_ssh = self.db_repo.clone_url(
201 uri_tmpl=_def_clone_uri_ssh, ssh=True)
202
210
203 # If enabled, get statistics data
211 # If enabled, get statistics data
204
212
@@ -231,8 +239,6 b' class RepoSummaryView(RepoAppView):'
231 c.enable_downloads = self.db_repo.enable_downloads
239 c.enable_downloads = self.db_repo.enable_downloads
232 c.repository_followers = scm_model.get_followers(self.db_repo)
240 c.repository_followers = scm_model.get_followers(self.db_repo)
233 c.repository_forks = scm_model.get_forks(self.db_repo)
241 c.repository_forks = scm_model.get_forks(self.db_repo)
234 c.repository_is_user_following = scm_model.is_following_repo(
235 self.db_repo_name, self._rhodecode_user.user_id)
236
242
237 # first interaction with the VCS instance after here...
243 # first interaction with the VCS instance after here...
238 if c.repository_requirements_missing:
244 if c.repository_requirements_missing:
@@ -317,8 +323,7 b' class RepoSummaryView(RepoAppView):'
317 (_("Tag"), repo.tags, 'tag'),
323 (_("Tag"), repo.tags, 'tag'),
318 (_("Bookmark"), repo.bookmarks, 'book'),
324 (_("Bookmark"), repo.bookmarks, 'book'),
319 ]
325 ]
320 res = self._create_reference_data(
326 res = self._create_reference_data(repo, self.db_repo_name, refs_to_create)
321 repo, self.db_repo_name, refs_to_create)
322 data = {
327 data = {
323 'more': False,
328 'more': False,
324 'results': res
329 'results': res
@@ -365,8 +370,7 b' class RepoSummaryView(RepoAppView):'
365 })
370 })
366 return result
371 return result
367
372
368 def _create_reference_items(self, repo, full_repo_name, refs, ref_type,
373 def _create_reference_items(self, repo, full_repo_name, refs, ref_type, format_ref_id):
369 format_ref_id):
370 result = []
374 result = []
371 is_svn = h.is_svn(repo)
375 is_svn = h.is_svn(repo)
372 for ref_name, raw_id in refs.iteritems():
376 for ref_name, raw_id in refs.iteritems():
@@ -378,6 +382,7 b' class RepoSummaryView(RepoAppView):'
378 'raw_id': raw_id,
382 'raw_id': raw_id,
379 'type': ref_type,
383 'type': ref_type,
380 'files_url': files_url,
384 'files_url': files_url,
385 'idx': 0,
381 })
386 })
382 return result
387 return result
383
388
@@ -20,12 +20,13 b''
20
20
21 import os
21 import os
22 import sys
22 import sys
23 import shutil
24 import logging
23 import logging
25 import tempfile
24 import tempfile
26 import textwrap
25 import textwrap
27
26 import collections
28 from .base import VcsServer
27 from .base import VcsServer
28 from rhodecode.model.db import RhodeCodeUi
29 from rhodecode.model.settings import VcsSettingsModel
29
30
30 log = logging.getLogger(__name__)
31 log = logging.getLogger(__name__)
31
32
@@ -37,62 +38,46 b' class MercurialTunnelWrapper(object):'
37 self.server = server
38 self.server = server
38 self.stdin = sys.stdin
39 self.stdin = sys.stdin
39 self.stdout = sys.stdout
40 self.stdout = sys.stdout
40 self.svn_conf_fd, self.svn_conf_path = tempfile.mkstemp()
41 self.hooks_env_fd, self.hooks_env_path = tempfile.mkstemp(prefix='hgrc_rhodecode_')
41 self.hooks_env_fd, self.hooks_env_path = tempfile.mkstemp()
42
42
43 def create_hooks_env(self):
43 def create_hooks_env(self):
44 repo_name = self.server.repo_name
45 hg_flags = self.server.config_to_hgrc(repo_name)
44
46
45 content = textwrap.dedent(
47 content = textwrap.dedent(
46 '''
48 '''
47 # SSH hooks version=1.0.0
49 # RhodeCode SSH hooks version=2.0.0
48 [hooks]
50 {custom}
49 pretxnchangegroup.ssh_auth=python:vcsserver.hooks.pre_push_ssh_auth
51 '''
50 pretxnchangegroup.ssh=python:vcsserver.hooks.pre_push_ssh
52 ).format(custom='\n'.join(hg_flags))
51 changegroup.ssh=python:vcsserver.hooks.post_push_ssh
52
53 preoutgoing.ssh=python:vcsserver.hooks.pre_pull_ssh
54 outgoing.ssh=python:vcsserver.hooks.post_pull_ssh
55
53
56 '''
54 root = self.server.get_root_store()
57 )
55 hgrc_custom = os.path.join(root, repo_name, '.hg', 'hgrc_rhodecode')
56 hgrc_main = os.path.join(root, repo_name, '.hg', 'hgrc')
58
57
58 # cleanup custom hgrc file
59 if os.path.isfile(hgrc_custom):
60 with open(hgrc_custom, 'wb') as f:
61 f.write('')
62 log.debug('Cleanup custom hgrc file under %s', hgrc_custom)
63
64 # write temp
59 with os.fdopen(self.hooks_env_fd, 'w') as hooks_env_file:
65 with os.fdopen(self.hooks_env_fd, 'w') as hooks_env_file:
60 hooks_env_file.write(content)
66 hooks_env_file.write(content)
61 root = self.server.get_root_store()
62
67
63 hgrc_custom = os.path.join(
68 return self.hooks_env_path
64 root, self.server.repo_name, '.hg', 'hgrc_rhodecode')
65 log.debug('Wrote custom hgrc file under %s', hgrc_custom)
66 shutil.move(
67 self.hooks_env_path, hgrc_custom)
68
69 hgrc_main = os.path.join(
70 root, self.server.repo_name, '.hg', 'hgrc')
71 include_marker = '%include hgrc_rhodecode'
72
69
73 if not os.path.isfile(hgrc_main):
70 def remove_configs(self):
74 os.mknod(hgrc_main)
71 os.remove(self.hooks_env_path)
75
76 with open(hgrc_main, 'rb') as f:
77 data = f.read()
78 has_marker = include_marker in data
79
72
80 if not has_marker:
73 def command(self, hgrc_path):
81 log.debug('Adding include marker for hooks')
82 with open(hgrc_main, 'wa') as f:
83 f.write(textwrap.dedent('''
84 # added by RhodeCode
85 {}
86 '''.format(include_marker)))
87
88 def command(self):
89 root = self.server.get_root_store()
74 root = self.server.get_root_store()
90
75
91 command = (
76 command = (
92 "cd {root}; {hg_path} -R {root}{repo_name} "
77 "cd {root}; HGRCPATH={hgrc} {hg_path} -R {root}{repo_name} "
93 "serve --stdio".format(
78 "serve --stdio".format(
94 root=root, hg_path=self.server.hg_path,
79 root=root, hg_path=self.server.hg_path,
95 repo_name=self.server.repo_name))
80 repo_name=self.server.repo_name, hgrc=hgrc_path))
96 log.debug("Final CMD: %s", command)
81 log.debug("Final CMD: %s", command)
97 return command
82 return command
98
83
@@ -102,22 +87,61 b' class MercurialTunnelWrapper(object):'
102 action = '?'
87 action = '?'
103 # permissions are check via `pre_push_ssh_auth` hook
88 # permissions are check via `pre_push_ssh_auth` hook
104 self.server.update_environment(action=action, extras=extras)
89 self.server.update_environment(action=action, extras=extras)
105 self.create_hooks_env()
90 custom_hgrc_file = self.create_hooks_env()
106 return os.system(self.command())
91
92 try:
93 return os.system(self.command(custom_hgrc_file))
94 finally:
95 self.remove_configs()
107
96
108
97
109 class MercurialServer(VcsServer):
98 class MercurialServer(VcsServer):
110 backend = 'hg'
99 backend = 'hg'
100 cli_flags = ['phases', 'largefiles', 'extensions', 'experimental', 'hooks']
111
101
112 def __init__(self, store, ini_path, repo_name,
102 def __init__(self, store, ini_path, repo_name, user, user_permissions, config, env):
113 user, user_permissions, config, env):
103 super(MercurialServer, self).__init__(user, user_permissions, config, env)
114 super(MercurialServer, self).\
115 __init__(user, user_permissions, config, env)
116
104
117 self.store = store
105 self.store = store
118 self.ini_path = ini_path
106 self.ini_path = ini_path
119 self.repo_name = repo_name
107 self.repo_name = repo_name
120 self._path = self.hg_path = config.get(
108 self._path = self.hg_path = config.get('app:main', 'ssh.executable.hg')
121 'app:main', 'ssh.executable.hg')
109 self.tunnel = MercurialTunnelWrapper(server=self)
110
111 def config_to_hgrc(self, repo_name):
112 ui_sections = collections.defaultdict(list)
113 ui = VcsSettingsModel(repo=repo_name).get_ui_settings(section=None, key=None)
114
115 # write default hooks
116 default_hooks = [
117 ('pretxnchangegroup.ssh_auth', 'python:vcsserver.hooks.pre_push_ssh_auth'),
118 ('pretxnchangegroup.ssh', 'python:vcsserver.hooks.pre_push_ssh'),
119 ('changegroup.ssh', 'python:vcsserver.hooks.post_push_ssh'),
120
121 ('preoutgoing.ssh', 'python:vcsserver.hooks.pre_pull_ssh'),
122 ('outgoing.ssh', 'python:vcsserver.hooks.post_pull_ssh'),
123 ]
124
125 for k, v in default_hooks:
126 ui_sections['hooks'].append((k, v))
122
127
123 self.tunnel = MercurialTunnelWrapper(server=self)
128 for entry in ui:
129 if not entry.active:
130 continue
131 sec = entry.section
132 key = entry.key
133
134 if sec in self.cli_flags:
135 # we want only custom hooks, so we skip builtins
136 if sec == 'hooks' and key in RhodeCodeUi.HOOKS_BUILTIN:
137 continue
138
139 ui_sections[sec].append([key, entry.value])
140
141 flags = []
142 for _sec, key_val in ui_sections.items():
143 flags.append(' ')
144 flags.append('[{}]'.format(_sec))
145 for key, val in key_val:
146 flags.append('{}= {}'.format(key, val))
147 return flags
@@ -18,6 +18,7 b''
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import mock
22 import mock
22 import pytest
23 import pytest
23
24
@@ -68,14 +69,16 b' def hg_server(app):'
68
69
69 class TestMercurialServer(object):
70 class TestMercurialServer(object):
70
71
71 def test_command(self, hg_server):
72 def test_command(self, hg_server, tmpdir):
72 server = hg_server.create()
73 server = hg_server.create()
74 custom_hgrc = os.path.join(str(tmpdir), 'hgrc')
73 expected_command = (
75 expected_command = (
74 'cd {root}; {hg_path} -R {root}{repo_name} serve --stdio'.format(
76 'cd {root}; HGRCPATH={custom_hgrc} {hg_path} -R {root}{repo_name} serve --stdio'.format(
75 root=hg_server.root, hg_path=hg_server.hg_path,
77 root=hg_server.root, custom_hgrc=custom_hgrc, hg_path=hg_server.hg_path,
76 repo_name=hg_server.repo_name)
78 repo_name=hg_server.repo_name)
77 )
79 )
78 assert expected_command == server.tunnel.command()
80 server_command = server.tunnel.command(custom_hgrc)
81 assert expected_command == server_command
79
82
80 @pytest.mark.parametrize('permissions, action, code', [
83 @pytest.mark.parametrize('permissions, action, code', [
81 ({}, 'pull', -2),
84 ({}, 'pull', -2),
This diff has been collapsed as it changes many lines, (914 lines changed) Show them Hide them
@@ -28,23 +28,16 b''
28 {
28 {
29 "license": [
29 "license": [
30 {
30 {
31 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
32 "shortName": "bsdOriginal",
33 "spdxId": "BSD-4-Clause",
34 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
35 }
36 ],
37 "name": "python2.7-coverage-3.7.1"
38 },
39 {
40 "license": [
41 {
42 "fullName": "MIT License",
31 "fullName": "MIT License",
43 "shortName": "mit",
32 "shortName": "mit",
44 "spdxId": "MIT",
33 "spdxId": "MIT",
45 "url": "http://spdx.org/licenses/MIT.html"
34 "url": "http://spdx.org/licenses/MIT.html"
46 }
35 }
47 ],
36 ],
37 "name": "python2.7-beautifulsoup4-4.6.3"
38 },
39 {
40 "license": "UNKNOWN",
48 "name": "python2.7-bootstrapped-pip-9.0.1"
41 "name": "python2.7-bootstrapped-pip-9.0.1"
49 },
42 },
50 {
43 {
@@ -56,29 +49,7 b''
56 "url": "http://spdx.org/licenses/MIT.html"
49 "url": "http://spdx.org/licenses/MIT.html"
57 }
50 }
58 ],
51 ],
59 "name": "python2.7-cov-core-1.15.0"
52 "name": "python2.7-webtest-2.0.32"
60 },
61 {
62 "license": [
63 {
64 "fullName": "MIT License",
65 "shortName": "mit",
66 "spdxId": "MIT",
67 "url": "http://spdx.org/licenses/MIT.html"
68 }
69 ],
70 "name": "python2.7-webtest-2.0.29"
71 },
72 {
73 "license": [
74 {
75 "fullName": "MIT License",
76 "shortName": "mit",
77 "spdxId": "MIT",
78 "url": "http://spdx.org/licenses/MIT.html"
79 }
80 ],
81 "name": "python2.7-beautifulsoup4-4.6.3"
82 },
53 },
83 {
54 {
84 "license": [
55 "license": [
@@ -100,7 +71,7 b''
100 "url": "http://spdx.org/licenses/MIT.html"
71 "url": "http://spdx.org/licenses/MIT.html"
101 }
72 }
102 ],
73 ],
103 "name": "python2.7-webob-1.7.4"
74 "name": "python2.7-webob-1.8.4"
104 },
75 },
105 {
76 {
106 "license": [
77 "license": [
@@ -116,6 +87,28 b''
116 {
87 {
117 "license": [
88 "license": [
118 {
89 {
90 "fullName": "Apache License 2.0",
91 "shortName": "asl20",
92 "spdxId": "Apache-2.0",
93 "url": "http://spdx.org/licenses/Apache-2.0.html"
94 }
95 ],
96 "name": "python2.7-coverage-4.5.1"
97 },
98 {
99 "license": [
100 {
101 "fullName": "MIT License",
102 "shortName": "mit",
103 "spdxId": "MIT",
104 "url": "http://spdx.org/licenses/MIT.html"
105 }
106 ],
107 "name": "python2.7-cov-core-1.15.0"
108 },
109 {
110 "license": [
111 {
119 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
112 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
120 "shortName": "bsdOriginal",
113 "shortName": "bsdOriginal",
121 "spdxId": "BSD-4-Clause",
114 "spdxId": "BSD-4-Clause",
@@ -127,6 +120,17 b''
127 {
120 {
128 "license": [
121 "license": [
129 {
122 {
123 "fullName": "GNU Lesser General Public License v3 or later (LGPLv3+)"
124 },
125 {
126 "fullName": "LGPL"
127 }
128 ],
129 "name": "python2.7-gprof2dot-2017.9.19"
130 },
131 {
132 "license": [
133 {
130 "fullName": "MIT License",
134 "fullName": "MIT License",
131 "shortName": "mit",
135 "shortName": "mit",
132 "spdxId": "MIT",
136 "spdxId": "MIT",
@@ -136,7 +140,7 b''
136 "fullName": "DFSG approved"
140 "fullName": "DFSG approved"
137 }
141 }
138 ],
142 ],
139 "name": "python2.7-pytest-timeout-1.2.1"
143 "name": "python2.7-pytest-timeout-1.3.2"
140 },
144 },
141 {
145 {
142 "license": [
146 "license": [
@@ -147,7 +151,32 b''
147 "url": "http://spdx.org/licenses/MIT.html"
151 "url": "http://spdx.org/licenses/MIT.html"
148 }
152 }
149 ],
153 ],
150 "name": "python2.7-pytest-3.6.0"
154 "name": "python2.7-pytest-3.8.2"
155 },
156 {
157 "license": [
158 {
159 "fullName": "MIT License",
160 "shortName": "mit",
161 "spdxId": "MIT",
162 "url": "http://spdx.org/licenses/MIT.html"
163 }
164 ],
165 "name": "python2.7-pathlib2-2.3.3"
166 },
167 {
168 "license": [
169 {
170 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
171 "shortName": "bsdOriginal",
172 "spdxId": "BSD-4-Clause",
173 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
174 },
175 {
176 "fullName": "New BSD License"
177 }
178 ],
179 "name": "python2.7-scandir-1.9.0"
151 },
180 },
152 {
181 {
153 "license": [
182 "license": [
@@ -172,7 +201,7 b''
172 "url": "http://spdx.org/licenses/MIT.html"
201 "url": "http://spdx.org/licenses/MIT.html"
173 }
202 }
174 ],
203 ],
175 "name": "python2.7-pluggy-0.6.0"
204 "name": "python2.7-pluggy-0.9.0"
176 },
205 },
177 {
206 {
178 "license": [
207 "license": [
@@ -183,7 +212,7 b''
183 "url": "http://spdx.org/licenses/MIT.html"
212 "url": "http://spdx.org/licenses/MIT.html"
184 }
213 }
185 ],
214 ],
186 "name": "python2.7-atomicwrites-1.1.5"
215 "name": "python2.7-atomicwrites-1.2.1"
187 },
216 },
188 {
217 {
189 "license": [
218 "license": [
@@ -194,7 +223,7 b''
194 "url": "http://spdx.org/licenses/MIT.html"
223 "url": "http://spdx.org/licenses/MIT.html"
195 }
224 }
196 ],
225 ],
197 "name": "python2.7-more-itertools-4.3.0"
226 "name": "python2.7-more-itertools-5.0.0"
198 },
227 },
199 {
228 {
200 "license": [
229 "license": [
@@ -205,7 +234,7 b''
205 "url": "http://spdx.org/licenses/MIT.html"
234 "url": "http://spdx.org/licenses/MIT.html"
206 }
235 }
207 ],
236 ],
208 "name": "python2.7-attrs-18.1.0"
237 "name": "python2.7-attrs-18.2.0"
209 },
238 },
210 {
239 {
211 "license": [
240 "license": [
@@ -216,18 +245,7 b''
216 "url": "http://spdx.org/licenses/MIT.html"
245 "url": "http://spdx.org/licenses/MIT.html"
217 }
246 }
218 ],
247 ],
219 "name": "python2.7-py-1.5.3"
248 "name": "python2.7-py-1.6.0"
220 },
221 {
222 "license": [
223 {
224 "fullName": "GNU Lesser General Public License v3 or later (LGPLv3+)"
225 },
226 {
227 "fullName": "LGPL"
228 }
229 ],
230 "name": "python2.7-gprof2dot-2017.9.19"
231 },
249 },
232 {
250 {
233 "license": [
251 "license": [
@@ -254,17 +272,6 b''
254 {
272 {
255 "license": [
273 "license": [
256 {
274 {
257 "fullName": "MIT License",
258 "shortName": "mit",
259 "spdxId": "MIT",
260 "url": "http://spdx.org/licenses/MIT.html"
261 }
262 ],
263 "name": "python2.7-setuptools-scm-2.1.0"
264 },
265 {
266 "license": [
267 {
268 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
275 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
269 "shortName": "bsdOriginal",
276 "shortName": "bsdOriginal",
270 "spdxId": "BSD-4-Clause",
277 "spdxId": "BSD-4-Clause",
@@ -299,7 +306,7 b''
299 "url": "http://spdx.org/licenses/MIT.html"
306 "url": "http://spdx.org/licenses/MIT.html"
300 }
307 }
301 ],
308 ],
302 "name": "python2.7-pytest-cov-2.5.1"
309 "name": "python2.7-pytest-cov-2.6.0"
303 },
310 },
304 {
311 {
305 "license": [
312 "license": [
@@ -310,7 +317,7 b''
310 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
317 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
311 }
318 }
312 ],
319 ],
313 "name": "python2.7-appenlight-client-0.6.25"
320 "name": "python2.7-appenlight-client-0.6.26"
314 },
321 },
315 {
322 {
316 "license": [
323 "license": [
@@ -326,10 +333,107 b''
326 {
333 {
327 "license": [
334 "license": [
328 {
335 {
329 "fullName": "AGPLv3 and Proprietary"
336 "fullName": "Apache 2.0 and Proprietary"
337 }
338 ],
339 "name": "python2.7-rhodecode-tools-1.2.1"
340 },
341 {
342 "license": [
343 {
344 "fullName": "Apache License 2.0",
345 "shortName": "asl20",
346 "spdxId": "Apache-2.0",
347 "url": "http://spdx.org/licenses/Apache-2.0.html"
348 }
349 ],
350 "name": "python2.7-elasticsearch1-dsl-0.0.12"
351 },
352 {
353 "license": [
354 {
355 "fullName": "Apache License 2.0",
356 "shortName": "asl20",
357 "spdxId": "Apache-2.0",
358 "url": "http://spdx.org/licenses/Apache-2.0.html"
359 }
360 ],
361 "name": "python2.7-elasticsearch1-1.10.0"
362 },
363 {
364 "license": [
365 {
366 "fullName": "MIT License",
367 "shortName": "mit",
368 "spdxId": "MIT",
369 "url": "http://spdx.org/licenses/MIT.html"
330 }
370 }
331 ],
371 ],
332 "name": "python2.7-rhodecode-tools-0.16.0"
372 "name": "python2.7-urllib3-1.24.1"
373 },
374 {
375 "license": [
376 {
377 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
378 "shortName": "bsdOriginal",
379 "spdxId": "BSD-4-Clause",
380 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
381 },
382 {
383 "fullName": "Apache License 2.0",
384 "shortName": "asl20",
385 "spdxId": "Apache-2.0",
386 "url": "http://spdx.org/licenses/Apache-2.0.html"
387 },
388 {
389 "fullName": "Dual License"
390 }
391 ],
392 "name": "python2.7-python-dateutil-2.8.0"
393 },
394 {
395 "license": [
396 {
397 "fullName": "Apache License 2.0",
398 "shortName": "asl20",
399 "spdxId": "Apache-2.0",
400 "url": "http://spdx.org/licenses/Apache-2.0.html"
401 }
402 ],
403 "name": "python2.7-elasticsearch2-2.5.0"
404 },
405 {
406 "license": [
407 {
408 "fullName": "Apache License 2.0",
409 "shortName": "asl20",
410 "spdxId": "Apache-2.0",
411 "url": "http://spdx.org/licenses/Apache-2.0.html"
412 }
413 ],
414 "name": "python2.7-elasticsearch-dsl-6.3.1"
415 },
416 {
417 "license": [
418 {
419 "fullName": "Python Software Foundation License version 2",
420 "shortName": "psfl",
421 "spdxId": "Python-2.0",
422 "url": "http://spdx.org/licenses/Python-2.0.html"
423 }
424 ],
425 "name": "python2.7-ipaddress-1.0.22"
426 },
427 {
428 "license": [
429 {
430 "fullName": "Apache License 2.0",
431 "shortName": "asl20",
432 "spdxId": "Apache-2.0",
433 "url": "http://spdx.org/licenses/Apache-2.0.html"
434 }
435 ],
436 "name": "python2.7-elasticsearch-6.3.1"
333 },
437 },
334 {
438 {
335 "license": [
439 "license": [
@@ -351,66 +455,13 b''
351 {
455 {
352 "license": [
456 "license": [
353 {
457 {
354 "fullName": "MIT License",
355 "shortName": "mit",
356 "spdxId": "MIT",
357 "url": "http://spdx.org/licenses/MIT.html"
358 }
359 ],
360 "name": "python2.7-urllib3-1.21"
361 },
362 {
363 "license": [
364 {
365 "fullName": "Apache License 2.0",
366 "shortName": "asl20",
367 "spdxId": "Apache-2.0",
368 "url": "http://spdx.org/licenses/Apache-2.0.html"
369 }
370 ],
371 "name": "python2.7-elasticsearch-dsl-2.2.0"
372 },
373 {
374 "license": [
375 {
376 "fullName": "Apache License 2.0",
377 "shortName": "asl20",
378 "spdxId": "Apache-2.0",
379 "url": "http://spdx.org/licenses/Apache-2.0.html"
380 }
381 ],
382 "name": "python2.7-elasticsearch-2.3.0"
383 },
384 {
385 "license": [
386 {
387 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
388 "shortName": "bsdOriginal",
389 "spdxId": "BSD-4-Clause",
390 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
391 },
392 {
393 "fullName": "Apache License 2.0",
394 "shortName": "asl20",
395 "spdxId": "Apache-2.0",
396 "url": "http://spdx.org/licenses/Apache-2.0.html"
397 },
398 {
399 "fullName": "Dual License"
400 }
401 ],
402 "name": "python2.7-python-dateutil-2.7.3"
403 },
404 {
405 "license": [
406 {
407 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
458 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
408 "shortName": "bsdOriginal",
459 "shortName": "bsdOriginal",
409 "spdxId": "BSD-4-Clause",
460 "spdxId": "BSD-4-Clause",
410 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
461 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
411 }
462 }
412 ],
463 ],
413 "name": "python2.7-markupsafe-1.0"
464 "name": "python2.7-markupsafe-1.1.0"
414 },
465 },
415 {
466 {
416 "license": [
467 "license": [
@@ -443,29 +494,7 b''
443 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
494 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
444 }
495 }
445 ],
496 ],
446 "name": "python2.7-click-6.6"
497 "name": "python2.7-click-7.0"
447 },
448 {
449 "license": [
450 {
451 "fullName": "MIT License",
452 "shortName": "mit",
453 "spdxId": "MIT",
454 "url": "http://spdx.org/licenses/MIT.html"
455 }
456 ],
457 "name": "python2.7-bottle-0.12.13"
458 },
459 {
460 "license": [
461 {
462 "fullName": "MIT License",
463 "shortName": "mit",
464 "spdxId": "MIT",
465 "url": "http://spdx.org/licenses/MIT.html"
466 }
467 ],
468 "name": "python2.7-cprofilev-1.0.7"
469 },
498 },
470 {
499 {
471 "license": [
500 "license": [
@@ -519,31 +548,6 b''
519 "url": "http://spdx.org/licenses/MIT.html"
548 "url": "http://spdx.org/licenses/MIT.html"
520 }
549 }
521 ],
550 ],
522 "name": "python2.7-pathlib2-2.3.0"
523 },
524 {
525 "license": [
526 {
527 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
528 "shortName": "bsdOriginal",
529 "spdxId": "BSD-4-Clause",
530 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
531 },
532 {
533 "fullName": "New BSD License"
534 }
535 ],
536 "name": "python2.7-scandir-1.9.0"
537 },
538 {
539 "license": [
540 {
541 "fullName": "MIT License",
542 "shortName": "mit",
543 "spdxId": "MIT",
544 "url": "http://spdx.org/licenses/MIT.html"
545 }
546 ],
547 "name": "python2.7-backports.shutil-get-terminal-size-1.0.0"
551 "name": "python2.7-backports.shutil-get-terminal-size-1.0.0"
548 },
552 },
549 {
553 {
@@ -555,7 +559,7 b''
555 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
559 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
556 }
560 }
557 ],
561 ],
558 "name": "python2.7-pygments-2.2.0"
562 "name": "python2.7-pygments-2.3.1"
559 },
563 },
560 {
564 {
561 "license": [
565 "license": [
@@ -646,7 +650,7 b''
646 "url": "http://spdx.org/licenses/MIT.html"
650 "url": "http://spdx.org/licenses/MIT.html"
647 }
651 }
648 ],
652 ],
649 "name": "python2.7-pickleshare-0.7.4"
653 "name": "python2.7-pickleshare-0.7.5"
650 },
654 },
651 {
655 {
652 "license": [
656 "license": [
@@ -690,7 +694,7 b''
690 "url": "http://spdx.org/licenses/MIT.html"
694 "url": "http://spdx.org/licenses/MIT.html"
691 }
695 }
692 ],
696 ],
693 "name": "python2.7-greenlet-0.4.13"
697 "name": "python2.7-greenlet-0.4.15"
694 },
698 },
695 {
699 {
696 "license": [
700 "license": [
@@ -701,7 +705,7 b''
701 "url": "http://spdx.org/licenses/MIT.html"
705 "url": "http://spdx.org/licenses/MIT.html"
702 }
706 }
703 ],
707 ],
704 "name": "python2.7-gevent-1.3.5"
708 "name": "python2.7-gevent-1.4.0"
705 },
709 },
706 {
710 {
707 "license": [
711 "license": [
@@ -712,7 +716,7 b''
712 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
716 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
713 }
717 }
714 ],
718 ],
715 "name": "python2.7-psutil-5.4.6"
719 "name": "python2.7-psutil-5.5.1"
716 },
720 },
717 {
721 {
718 "license": [
722 "license": [
@@ -745,7 +749,7 b''
745 "url": "http://spdx.org/licenses/MIT.html"
749 "url": "http://spdx.org/licenses/MIT.html"
746 }
750 }
747 ],
751 ],
748 "name": "python2.7-alembic-0.9.9"
752 "name": "python2.7-alembic-1.0.5"
749 },
753 },
750 {
754 {
751 "license": {
755 "license": {
@@ -754,7 +758,7 b''
754 "spdxId": "Apache-2.0",
758 "spdxId": "Apache-2.0",
755 "url": "http://spdx.org/licenses/Apache-2.0.html"
759 "url": "http://spdx.org/licenses/Apache-2.0.html"
756 },
760 },
757 "name": "python2.7-python-editor-1.0.3"
761 "name": "python2.7-python-editor-1.0.4"
758 },
762 },
759 {
763 {
760 "license": [
764 "license": [
@@ -842,39 +846,6 b''
842 {
846 {
843 "license": [
847 "license": [
844 {
848 {
845 "fullName": "Apache License 2.0",
846 "shortName": "asl20",
847 "spdxId": "Apache-2.0",
848 "url": "http://spdx.org/licenses/Apache-2.0.html"
849 }
850 ],
851 "name": "python2.7-bleach-2.1.4"
852 },
853 {
854 "license": [
855 {
856 "fullName": "MIT License",
857 "shortName": "mit",
858 "spdxId": "MIT",
859 "url": "http://spdx.org/licenses/MIT.html"
860 }
861 ],
862 "name": "python2.7-html5lib-1.0.1"
863 },
864 {
865 "license": [
866 {
867 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
868 "shortName": "bsdOriginal",
869 "spdxId": "BSD-4-Clause",
870 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
871 }
872 ],
873 "name": "python2.7-webencodings-0.5.1"
874 },
875 {
876 "license": [
877 {
878 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
849 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
879 "shortName": "bsdOriginal",
850 "shortName": "bsdOriginal",
880 "spdxId": "BSD-4-Clause",
851 "spdxId": "BSD-4-Clause",
@@ -892,7 +863,7 b''
892 "url": "http://spdx.org/licenses/MIT.html"
863 "url": "http://spdx.org/licenses/MIT.html"
893 }
864 }
894 ],
865 ],
895 "name": "python2.7-testpath-0.3.1"
866 "name": "python2.7-testpath-0.4.2"
896 },
867 },
897 {
868 {
898 "license": [
869 "license": [
@@ -908,6 +879,28 b''
908 {
879 {
909 "license": [
880 "license": [
910 {
881 {
882 "fullName": "Apache License 2.0",
883 "shortName": "asl20",
884 "spdxId": "Apache-2.0",
885 "url": "http://spdx.org/licenses/Apache-2.0.html"
886 }
887 ],
888 "name": "python2.7-bleach-3.1.0"
889 },
890 {
891 "license": [
892 {
893 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
894 "shortName": "bsdOriginal",
895 "spdxId": "BSD-4-Clause",
896 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
897 }
898 ],
899 "name": "python2.7-webencodings-0.5.1"
900 },
901 {
902 "license": [
903 {
911 "fullName": "MIT License",
904 "fullName": "MIT License",
912 "shortName": "mit",
905 "shortName": "mit",
913 "spdxId": "MIT",
906 "spdxId": "MIT",
@@ -925,7 +918,7 b''
925 "url": "http://spdx.org/licenses/MIT.html"
918 "url": "http://spdx.org/licenses/MIT.html"
926 }
919 }
927 ],
920 ],
928 "name": "python2.7-configparser-3.5.0"
921 "name": "python2.7-configparser-3.7.3"
929 },
922 },
930 {
923 {
931 "license": [
924 "license": [
@@ -947,7 +940,73 b''
947 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
940 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
948 }
941 }
949 ],
942 ],
950 "name": "python2.7-mistune-0.8.3"
943 "name": "python2.7-mistune-0.8.4"
944 },
945 {
946 "license": {
947 "fullName": "GNU Lesser General Public License v3.0 or later",
948 "shortName": "lgpl3Plus",
949 "spdxId": "LGPL-3.0+",
950 "url": "http://spdx.org/licenses/LGPL-3.0+.html"
951 },
952 "name": "python2.7-psycopg2-2.7.7"
953 },
954 {
955 "license": {
956 "fullName": "PostgreSQL License",
957 "shortName": "postgresql",
958 "spdxId": "PostgreSQL",
959 "url": "http://spdx.org/licenses/PostgreSQL.html"
960 },
961 "name": "postgresql-9.6.10"
962 },
963 {
964 "license": [
965 {
966 "fullName": "zlib License",
967 "shortName": "zlib",
968 "spdxId": "Zlib",
969 "url": "http://spdx.org/licenses/Zlib.html"
970 },
971 {
972 "fullName": "libpng License",
973 "shortName": "libpng",
974 "spdxId": "Libpng",
975 "url": "http://spdx.org/licenses/Libpng.html"
976 }
977 ],
978 "name": "python2.7-pysqlite-2.8.3"
979 },
980 {
981 "license": [
982 {
983 "fullName": "MIT License",
984 "shortName": "mit",
985 "spdxId": "MIT",
986 "url": "http://spdx.org/licenses/MIT.html"
987 }
988 ],
989 "name": "python2.7-pymysql-0.8.1"
990 },
991 {
992 "license": [
993 {
994 "fullName": "GNU General Public License v1.0 only",
995 "shortName": "gpl1",
996 "spdxId": "GPL-1.0",
997 "url": "http://spdx.org/licenses/GPL-1.0.html"
998 }
999 ],
1000 "name": "python2.7-mysql-python-1.2.5"
1001 },
1002 {
1003 "license": {
1004 "fullName": "GNU Library General Public License v2.1 only",
1005 "shortName": "lgpl21",
1006 "spdxId": "LGPL-2.1",
1007 "url": "http://spdx.org/licenses/LGPL-2.1.html"
1008 },
1009 "name": "mariadb-connector-c-2.3.4"
951 },
1010 },
952 {
1011 {
953 "license": [
1012 "license": [
@@ -958,7 +1017,7 b''
958 "url": "http://spdx.org/licenses/ZPL-2.1.html"
1017 "url": "http://spdx.org/licenses/ZPL-2.1.html"
959 }
1018 }
960 ],
1019 ],
961 "name": "python2.7-zope.interface-4.5.0"
1020 "name": "python2.7-zope.interface-4.6.0"
962 },
1021 },
963 {
1022 {
964 "license": [
1023 "license": [
@@ -969,7 +1028,7 b''
969 "url": "http://spdx.org/licenses/ZPL-2.1.html"
1028 "url": "http://spdx.org/licenses/ZPL-2.1.html"
970 }
1029 }
971 ],
1030 ],
972 "name": "python2.7-zope.event-4.3.0"
1031 "name": "python2.7-zope.event-4.4"
973 },
1032 },
974 {
1033 {
975 "license": [
1034 "license": [
@@ -980,7 +1039,7 b''
980 "url": "http://spdx.org/licenses/ZPL-2.1.html"
1039 "url": "http://spdx.org/licenses/ZPL-2.1.html"
981 }
1040 }
982 ],
1041 ],
983 "name": "python2.7-zope.deprecation-4.3.0"
1042 "name": "python2.7-zope.deprecation-4.4.0"
984 },
1043 },
985 {
1044 {
986 "license": [
1045 "license": [
@@ -1043,7 +1102,7 b''
1043 "url": "http://spdx.org/licenses/MIT.html"
1102 "url": "http://spdx.org/licenses/MIT.html"
1044 }
1103 }
1045 ],
1104 ],
1046 "name": "python2.7-paste-2.0.3"
1105 "name": "python2.7-paste-3.0.5"
1047 },
1106 },
1048 {
1107 {
1049 "license": [
1108 "license": [
@@ -1061,7 +1120,7 b''
1061 "fullName": "Repoze License",
1120 "fullName": "Repoze License",
1062 "url": "http://www.repoze.org/LICENSE.txt"
1121 "url": "http://www.repoze.org/LICENSE.txt"
1063 },
1122 },
1064 "name": "python2.7-venusian-1.1.0"
1123 "name": "python2.7-venusian-1.2.0"
1065 },
1124 },
1066 {
1125 {
1067 "license": {
1126 "license": {
@@ -1072,17 +1131,6 b''
1072 "name": "python2.7-urlobject-2.4.3"
1131 "name": "python2.7-urlobject-2.4.3"
1073 },
1132 },
1074 {
1133 {
1075 "license": [
1076 {
1077 "fullName": "Apache License 2.0",
1078 "shortName": "asl20",
1079 "spdxId": "Apache-2.0",
1080 "url": "http://spdx.org/licenses/Apache-2.0.html"
1081 }
1082 ],
1083 "name": "python2.7-trollius-1.0.4"
1084 },
1085 {
1086 "license": {
1134 "license": {
1087 "fullName": "Repoze License",
1135 "fullName": "Repoze License",
1088 "url": "http://www.repoze.org/LICENSE.txt"
1136 "url": "http://www.repoze.org/LICENSE.txt"
@@ -1095,7 +1143,7 b''
1095 "fullName": "BSD-derived (http://www.repoze.org/LICENSE.txt)"
1143 "fullName": "BSD-derived (http://www.repoze.org/LICENSE.txt)"
1096 }
1144 }
1097 ],
1145 ],
1098 "name": "python2.7-supervisor-3.3.4"
1146 "name": "python2.7-supervisor-3.3.5"
1099 },
1147 },
1100 {
1148 {
1101 "license": [
1149 "license": [
@@ -1114,7 +1162,7 b''
1114 "url": "http://spdx.org/licenses/Python-2.0.html"
1162 "url": "http://spdx.org/licenses/Python-2.0.html"
1115 }
1163 }
1116 ],
1164 ],
1117 "name": "python2.7-subprocess32-3.5.1"
1165 "name": "python2.7-subprocess32-3.5.3"
1118 },
1166 },
1119 {
1167 {
1120 "license": [
1168 "license": [
@@ -1125,7 +1173,7 b''
1125 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1173 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1126 }
1174 }
1127 ],
1175 ],
1128 "name": "python2.7-sshpubkeys-2.2.0"
1176 "name": "python2.7-sshpubkeys-3.1.0"
1129 },
1177 },
1130 {
1178 {
1131 "license": [
1179 "license": [
@@ -1141,11 +1189,55 b''
1141 {
1189 {
1142 "license": [
1190 "license": [
1143 {
1191 {
1144 "fullName": "Public Domain",
1192 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
1145 "shortName": "publicDomain"
1193 "shortName": "bsdOriginal",
1194 "spdxId": "BSD-4-Clause",
1195 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1196 },
1197 {
1198 "fullName": "BSD or Apache License, Version 2.0"
1199 },
1200 {
1201 "fullName": "Apache License 2.0",
1202 "shortName": "asl20",
1203 "spdxId": "Apache-2.0",
1204 "url": "http://spdx.org/licenses/Apache-2.0.html"
1146 }
1205 }
1147 ],
1206 ],
1148 "name": "python2.7-pycrypto-2.6.1"
1207 "name": "python2.7-cryptography-2.5"
1208 },
1209 {
1210 "license": [
1211 {
1212 "fullName": "MIT License",
1213 "shortName": "mit",
1214 "spdxId": "MIT",
1215 "url": "http://spdx.org/licenses/MIT.html"
1216 }
1217 ],
1218 "name": "python2.7-cffi-1.12.1"
1219 },
1220 {
1221 "license": [
1222 {
1223 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
1224 "shortName": "bsdOriginal",
1225 "spdxId": "BSD-4-Clause",
1226 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1227 }
1228 ],
1229 "name": "python2.7-pycparser-2.19"
1230 },
1231 {
1232 "license": [
1233 {
1234 "fullName": "MIT License",
1235 "shortName": "mit",
1236 "spdxId": "MIT",
1237 "url": "http://spdx.org/licenses/MIT.html"
1238 }
1239 ],
1240 "name": "python2.7-asn1crypto-0.24.0"
1149 },
1241 },
1150 {
1242 {
1151 "license": [
1243 "license": [
@@ -1159,18 +1251,7 b''
1159 "url": "http://spdx.org/licenses/MIT.html"
1251 "url": "http://spdx.org/licenses/MIT.html"
1160 }
1252 }
1161 ],
1253 ],
1162 "name": "python2.7-simplejson-3.11.1"
1254 "name": "python2.7-simplejson-3.16.0"
1163 },
1164 {
1165 "license": [
1166 {
1167 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
1168 "shortName": "bsdOriginal",
1169 "spdxId": "BSD-4-Clause",
1170 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1171 }
1172 ],
1173 "name": "python2.7-setproctitle-1.1.10"
1174 },
1255 },
1175 {
1256 {
1176 "license": [
1257 "license": [
@@ -1210,7 +1291,7 b''
1210 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1291 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1211 }
1292 }
1212 ],
1293 ],
1213 "name": "python2.7-py-gfm-0.1.3"
1294 "name": "python2.7-py-gfm-0.1.4"
1214 },
1295 },
1215 {
1296 {
1216 "license": [
1297 "license": [
@@ -1248,6 +1329,72 b''
1248 {
1329 {
1249 "license": [
1330 "license": [
1250 {
1331 {
1332 "fullName": "MIT License",
1333 "shortName": "mit",
1334 "spdxId": "MIT",
1335 "url": "http://spdx.org/licenses/MIT.html"
1336 }
1337 ],
1338 "name": "python2.7-python-saml-2.4.2"
1339 },
1340 {
1341 "license": [
1342 {
1343 "fullName": "Python Software Foundation License version 2",
1344 "shortName": "psfl",
1345 "spdxId": "Python-2.0",
1346 "url": "http://spdx.org/licenses/Python-2.0.html"
1347 }
1348 ],
1349 "name": "python2.7-defusedxml-0.5.0"
1350 },
1351 {
1352 "license": [
1353 {
1354 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
1355 "shortName": "bsdOriginal",
1356 "spdxId": "BSD-4-Clause",
1357 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1358 }
1359 ],
1360 "name": "python2.7-isodate-0.6.0"
1361 },
1362 {
1363 "license": [
1364 {
1365 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
1366 "shortName": "bsdOriginal",
1367 "spdxId": "BSD-4-Clause",
1368 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1369 }
1370 ],
1371 "name": "python2.7-dm.xmlsec.binding-1.3.7"
1372 },
1373 {
1374 "license": [
1375 {
1376 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
1377 "shortName": "bsdOriginal",
1378 "spdxId": "BSD-4-Clause",
1379 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1380 }
1381 ],
1382 "name": "python2.7-lxml-4.2.5"
1383 },
1384 {
1385 "license": [
1386 {
1387 "fullName": "MIT License",
1388 "shortName": "mit",
1389 "spdxId": "MIT",
1390 "url": "http://spdx.org/licenses/MIT.html"
1391 }
1392 ],
1393 "name": "python2.7-wheel-0.30.0"
1394 },
1395 {
1396 "license": [
1397 {
1251 "fullName": "License :: OSI Approved :: MIT License"
1398 "fullName": "License :: OSI Approved :: MIT License"
1252 },
1399 },
1253 {
1400 {
@@ -1260,14 +1407,7 b''
1260 "name": "python2.7-python-pam-1.8.4"
1407 "name": "python2.7-python-pam-1.8.4"
1261 },
1408 },
1262 {
1409 {
1263 "license": [
1410 "license": "UNKNOWN",
1264 {
1265 "fullName": "GNU General Public License v1.0 only",
1266 "shortName": "gpl1",
1267 "spdxId": "GPL-1.0",
1268 "url": "http://spdx.org/licenses/GPL-1.0.html"
1269 }
1270 ],
1271 "name": "linux-pam-1.3.0"
1411 "name": "linux-pam-1.3.0"
1272 },
1412 },
1273 {
1413 {
@@ -1302,9 +1442,7 b''
1302 "name": "libkrb5-1.15.2"
1442 "name": "libkrb5-1.15.2"
1303 },
1443 },
1304 {
1444 {
1305 "license":{
1445 "license": "UNKNOWN",
1306 "fullName": "BSD-derived (https://www.openldap.org/software/release/license.html)"
1307 },
1308 "name": "openldap-2.4.45"
1446 "name": "openldap-2.4.45"
1309 },
1447 },
1310 {
1448 {
@@ -1316,7 +1454,18 b''
1316 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1454 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1317 }
1455 }
1318 ],
1456 ],
1319 "name": "python2.7-pyasn1-modules-0.2.2"
1457 "name": "python2.7-pyasn1-modules-0.2.4"
1458 },
1459 {
1460 "license": [
1461 {
1462 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
1463 "shortName": "bsdOriginal",
1464 "spdxId": "BSD-4-Clause",
1465 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1466 }
1467 ],
1468 "name": "python2.7-pyasn1-0.4.5"
1320 },
1469 },
1321 {
1470 {
1322 "license": [
1471 "license": [
@@ -1327,42 +1476,36 b''
1327 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1476 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1328 }
1477 }
1329 ],
1478 ],
1330 "name": "python2.7-pyasn1-0.4.4"
1479 "name": "python2.7-pyramid-mailer-0.15.1"
1331 },
1480 },
1332 {
1481 {
1333 "license": [
1482 "license": [
1334 {
1483 {
1335 "fullName": "zlib License",
1484 "fullName": "Zope Public License 2.1",
1336 "shortName": "zlib",
1485 "shortName": "zpl21",
1337 "spdxId": "Zlib",
1486 "spdxId": "ZPL-2.1",
1338 "url": "http://spdx.org/licenses/Zlib.html"
1487 "url": "http://spdx.org/licenses/ZPL-2.1.html"
1339 },
1340 {
1341 "fullName": "libpng License",
1342 "shortName": "libpng",
1343 "spdxId": "Libpng",
1344 "url": "http://spdx.org/licenses/Libpng.html"
1345 }
1488 }
1346 ],
1489 ],
1347 "name": "python2.7-pysqlite-2.8.3"
1490 "name": "python2.7-transaction-2.4.0"
1491 },
1492 {
1493 "license": [
1494 {
1495 "fullName": "Zope Public License 2.1",
1496 "shortName": "zpl21",
1497 "spdxId": "ZPL-2.1",
1498 "url": "http://spdx.org/licenses/ZPL-2.1.html"
1499 }
1500 ],
1501 "name": "python2.7-repoze.sendmail-4.4.1"
1348 },
1502 },
1349 {
1503 {
1350 "license": {
1504 "license": {
1351 "fullName": "Repoze License",
1505 "fullName": "Repoze License",
1352 "url": "http://www.repoze.org/LICENSE.txt"
1506 "url": "http://www.repoze.org/LICENSE.txt"
1353 },
1507 },
1354 "name": "python2.7-pyramid-1.9.2"
1508 "name": "python2.7-pyramid-1.10.1"
1355 },
1356 {
1357 "license": [
1358 {
1359 "fullName": "MIT License",
1360 "shortName": "mit",
1361 "spdxId": "MIT",
1362 "url": "http://spdx.org/licenses/MIT.html"
1363 }
1364 ],
1365 "name": "python2.7-hupper-1.3"
1366 },
1509 },
1367 {
1510 {
1368 "license": [
1511 "license": [
@@ -1395,7 +1538,18 b''
1395 "url": "http://spdx.org/licenses/MIT.html"
1538 "url": "http://spdx.org/licenses/MIT.html"
1396 }
1539 }
1397 ],
1540 ],
1398 "name": "python2.7-pastedeploy-1.5.2"
1541 "name": "python2.7-pastedeploy-2.0.1"
1542 },
1543 {
1544 "license": [
1545 {
1546 "fullName": "MIT License",
1547 "shortName": "mit",
1548 "spdxId": "MIT",
1549 "url": "http://spdx.org/licenses/MIT.html"
1550 }
1551 ],
1552 "name": "python2.7-hupper-1.5"
1399 },
1553 },
1400 {
1554 {
1401 "license": {
1555 "license": {
@@ -1428,18 +1582,7 b''
1428 "url": "http://www.repoze.org/LICENSE.txt"
1582 "url": "http://www.repoze.org/LICENSE.txt"
1429 }
1583 }
1430 ],
1584 ],
1431 "name": "python2.7-pyramid-debugtoolbar-4.4"
1585 "name": "python2.7-pyramid-debugtoolbar-4.5"
1432 },
1433 {
1434 "license": [
1435 {
1436 "fullName": "Python Software Foundation License version 2",
1437 "shortName": "psfl",
1438 "spdxId": "Python-2.0",
1439 "url": "http://spdx.org/licenses/Python-2.0.html"
1440 }
1441 ],
1442 "name": "python2.7-ipaddress-1.0.22"
1443 },
1586 },
1444 {
1587 {
1445 "license": {
1588 "license": {
@@ -1468,29 +1611,16 b''
1468 "url": "http://spdx.org/licenses/MIT.html"
1611 "url": "http://spdx.org/licenses/MIT.html"
1469 }
1612 }
1470 ],
1613 ],
1471 "name": "python2.7-pyparsing-1.5.7"
1614 "name": "python2.7-pyparsing-2.3.0"
1472 },
1615 },
1473 {
1616 {
1474 "license": [
1617 "license": [
1475 {
1618 {
1476 "fullName": "Apache License 2.0",
1619 "fullName": "Public Domain",
1477 "shortName": "asl20",
1620 "shortName": "publicDomain"
1478 "spdxId": "Apache-2.0",
1479 "url": "http://spdx.org/licenses/Apache-2.0.html"
1480 }
1621 }
1481 ],
1622 ],
1482 "name": "python2.7-pygments-markdown-lexer-0.1.0.dev39"
1623 "name": "python2.7-pycrypto-2.6.1"
1483 },
1484 {
1485 "license": [
1486 {
1487 "fullName": "MIT License",
1488 "shortName": "mit",
1489 "spdxId": "MIT",
1490 "url": "http://spdx.org/licenses/MIT.html"
1491 }
1492 ],
1493 "name": "python2.7-pyflakes-0.8.1"
1494 },
1624 },
1495 {
1625 {
1496 "license": {
1626 "license": {
@@ -1513,30 +1643,12 b''
1513 "name": "python2.7-py-bcrypt-0.4"
1643 "name": "python2.7-py-bcrypt-0.4"
1514 },
1644 },
1515 {
1645 {
1516 "license": {
1517 "fullName": "GNU Lesser General Public License v3.0 or later",
1518 "shortName": "lgpl3Plus",
1519 "spdxId": "LGPL-3.0+",
1520 "url": "http://spdx.org/licenses/LGPL-3.0+.html"
1521 },
1522 "name": "python2.7-psycopg2-2.7.4"
1523 },
1524 {
1525 "license": {
1526 "fullName": "PostgreSQL License",
1527 "shortName": "postgresql",
1528 "spdxId": "PostgreSQL",
1529 "url": "http://spdx.org/licenses/PostgreSQL.html"
1530 },
1531 "name": "postgresql-9.6.10"
1532 },
1533 {
1534 "license": [
1646 "license": [
1535 {
1647 {
1536 "fullName": "BSD-derived (http://www.repoze.org/LICENSE.txt)"
1648 "fullName": "BSD-derived (http://www.repoze.org/LICENSE.txt)"
1537 }
1649 }
1538 ],
1650 ],
1539 "name": "python2.7-peppercorn-0.5"
1651 "name": "python2.7-peppercorn-0.6"
1540 },
1652 },
1541 {
1653 {
1542 "license": [
1654 "license": [
@@ -1547,7 +1659,7 b''
1547 "url": "http://spdx.org/licenses/MIT.html"
1659 "url": "http://spdx.org/licenses/MIT.html"
1548 }
1660 }
1549 ],
1661 ],
1550 "name": "python2.7-pastescript-2.0.2"
1662 "name": "python2.7-pastescript-3.0.0"
1551 },
1663 },
1552 {
1664 {
1553 "license": [
1665 "license": [
@@ -1569,60 +1681,7 b''
1569 "url": "http://spdx.org/licenses/MIT.html"
1681 "url": "http://spdx.org/licenses/MIT.html"
1570 }
1682 }
1571 ],
1683 ],
1572 "name": "python2.7-objgraph-3.1.1"
1684 "name": "python2.7-pyotp-2.2.7"
1573 },
1574 {
1575 "license": [
1576 {
1577 "fullName": "MIT License",
1578 "shortName": "mit",
1579 "spdxId": "MIT",
1580 "url": "http://spdx.org/licenses/MIT.html"
1581 }
1582 ],
1583 "name": "python2.7-graphviz-0.9"
1584 },
1585 {
1586 "license": [
1587 {
1588 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
1589 "shortName": "bsdOriginal",
1590 "spdxId": "BSD-4-Clause",
1591 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1592 }
1593 ],
1594 "name": "python2.7-pyotp-2.2.6"
1595 },
1596 {
1597 "license": [
1598 {
1599 "fullName": "MIT License",
1600 "shortName": "mit",
1601 "spdxId": "MIT",
1602 "url": "http://spdx.org/licenses/MIT.html"
1603 }
1604 ],
1605 "name": "python2.7-pymysql-0.8.1"
1606 },
1607 {
1608 "license": [
1609 {
1610 "fullName": "GNU General Public License v1.0 only",
1611 "shortName": "gpl1",
1612 "spdxId": "GPL-1.0",
1613 "url": "http://spdx.org/licenses/GPL-1.0.html"
1614 }
1615 ],
1616 "name": "python2.7-mysql-python-1.2.5"
1617 },
1618 {
1619 "license": {
1620 "fullName": "GNU Library General Public License v2.1 only",
1621 "shortName": "lgpl21",
1622 "spdxId": "LGPL-2.1",
1623 "url": "http://spdx.org/licenses/LGPL-2.1.html"
1624 },
1625 "name": "mariadb-connector-c-2.3.4"
1626 },
1685 },
1627 {
1686 {
1628 "license": [
1687 "license": [
@@ -1644,29 +1703,7 b''
1644 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1703 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1645 }
1704 }
1646 ],
1705 ],
1647 "name": "python2.7-lxml-3.7.3"
1706 "name": "python2.7-kombu-4.2.1"
1648 },
1649 {
1650 "license": [
1651 {
1652 "fullName": "MIT License",
1653 "shortName": "mit",
1654 "spdxId": "MIT",
1655 "url": "http://spdx.org/licenses/MIT.html"
1656 }
1657 ],
1658 "name": "python2.7-wheel-0.30.0"
1659 },
1660 {
1661 "license": [
1662 {
1663 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
1664 "shortName": "bsdOriginal",
1665 "spdxId": "BSD-4-Clause",
1666 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1667 }
1668 ],
1669 "name": "python2.7-kombu-4.2.0"
1670 },
1707 },
1671 {
1708 {
1672 "license": [
1709 "license": [
@@ -1688,18 +1725,7 b''
1688 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1725 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1689 }
1726 }
1690 ],
1727 ],
1691 "name": "python2.7-vine-1.1.4"
1728 "name": "python2.7-vine-1.2.0"
1692 },
1693 {
1694 "license": [
1695 {
1696 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
1697 "shortName": "bsdOriginal",
1698 "spdxId": "BSD-4-Clause",
1699 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1700 }
1701 ],
1702 "name": "python2.7-billiard-3.5.0.3"
1703 },
1729 },
1704 {
1730 {
1705 "license": [
1731 "license": [
@@ -1721,7 +1747,7 b''
1721 "url": "http://spdx.org/licenses/MIT.html"
1747 "url": "http://spdx.org/licenses/MIT.html"
1722 }
1748 }
1723 ],
1749 ],
1724 "name": "python2.7-iso8601-0.1.11"
1750 "name": "python2.7-iso8601-0.1.12"
1725 },
1751 },
1726 {
1752 {
1727 "license": [
1753 "license": [
@@ -1765,7 +1791,7 b''
1765 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1791 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1766 }
1792 }
1767 ],
1793 ],
1768 "name": "python2.7-dogpile.cache-0.6.6"
1794 "name": "python2.7-dogpile.cache-0.7.1"
1769 },
1795 },
1770 {
1796 {
1771 "license": {
1797 "license": {
@@ -1779,17 +1805,20 b''
1779 {
1805 {
1780 "license": [
1806 "license": [
1781 {
1807 {
1808 "fullName": "Repoze Public License"
1809 },
1810 {
1782 "fullName": "BSD-derived (http://www.repoze.org/LICENSE.txt)"
1811 "fullName": "BSD-derived (http://www.repoze.org/LICENSE.txt)"
1783 }
1812 }
1784 ],
1813 ],
1785 "name": "python2.7-deform-2.0.5"
1814 "name": "python2.7-deform-2.0.7"
1786 },
1815 },
1787 {
1816 {
1788 "license": {
1817 "license": {
1789 "fullName": "Repoze License",
1818 "fullName": "Repoze License",
1790 "url": "http://www.repoze.org/LICENSE.txt"
1819 "url": "http://www.repoze.org/LICENSE.txt"
1791 },
1820 },
1792 "name": "python2.7-colander-1.4"
1821 "name": "python2.7-colander-1.7.0"
1793 },
1822 },
1794 {
1823 {
1795 "license": [
1824 "license": [
@@ -1863,6 +1892,17 b''
1863 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1892 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1864 }
1893 }
1865 ],
1894 ],
1895 "name": "python2.7-billiard-3.5.0.3"
1896 },
1897 {
1898 "license": [
1899 {
1900 "fullName": "BSD 4-clause \"Original\" or \"Old\" License",
1901 "shortName": "bsdOriginal",
1902 "spdxId": "BSD-4-Clause",
1903 "url": "http://spdx.org/licenses/BSD-4-Clause.html"
1904 }
1905 ],
1866 "name": "python2.7-babel-1.3"
1906 "name": "python2.7-babel-1.3"
1867 },
1907 },
1868 {
1908 {
@@ -1877,25 +1917,7 b''
1877 "name": "python2.7-authomatic-0.1.0.post1"
1917 "name": "python2.7-authomatic-0.1.0.post1"
1878 },
1918 },
1879 {
1919 {
1880 "license": [
1920 "license": "UNKNOWN",
1881 {
1882 "fullName": "MIT License",
1883 "shortName": "mit",
1884 "spdxId": "MIT",
1885 "url": "http://spdx.org/licenses/MIT.html"
1886 }
1887 ],
1888 "name": "node-grunt-cli-1.2.0"
1889 },
1890 {
1891 "license": [
1892 {
1893 "fullName": "MIT License",
1894 "shortName": "mit",
1895 "spdxId": "MIT",
1896 "url": "http://spdx.org/licenses/MIT.html"
1897 }
1898 ],
1899 "name": "python2.7-rhodecode-testdata-0.10.0"
1921 "name": "python2.7-rhodecode-testdata-0.10.0"
1900 }
1922 }
1901 ]
1923 ]
@@ -250,7 +250,7 b' def includeme(config):'
250
250
251 # Includes which are required. The application would fail without them.
251 # Includes which are required. The application would fail without them.
252 config.include('pyramid_mako')
252 config.include('pyramid_mako')
253 config.include('pyramid_beaker')
253 config.include('rhodecode.lib.rc_beaker')
254 config.include('rhodecode.lib.rc_cache')
254 config.include('rhodecode.lib.rc_cache')
255
255
256 config.include('rhodecode.apps._base.navigation')
256 config.include('rhodecode.apps._base.navigation')
@@ -28,8 +28,8 b' def _pre_push_hook(*args, **kwargs):'
28 [{u'hg_env|git_env': ...,
28 [{u'hg_env|git_env': ...,
29 u'multiple_heads': [],
29 u'multiple_heads': [],
30 u'name': u'default',
30 u'name': u'default',
31 u'new_rev': u'd0befe0692e722e01d5677f27a104631cf798b69',
31 u'new_rev': u'd0b2ae0692e722e01d5677f27a104631cf798b69',
32 u'old_rev': u'd0befe0692e722e01d5677f27a104631cf798b69',
32 u'old_rev': u'd0b1ae0692e722e01d5677f27a104631cf798b69',
33 u'ref': u'',
33 u'ref': u'',
34 u'total_commits': 2,
34 u'total_commits': 2,
35 u'type': u'branch'}]
35 u'type': u'branch'}]
@@ -47,13 +47,17 b' def _pre_push_hook(*args, **kwargs):'
47 forbid_files = repo_extra_fields.get('forbid_files_glob', {}).get('field_value')
47 forbid_files = repo_extra_fields.get('forbid_files_glob', {}).get('field_value')
48 forbid_files = aslist(forbid_files)
48 forbid_files = aslist(forbid_files)
49
49
50 # forbid_files = ['*'] # example pattern
51
50 # optionally get bytes limit for a single file, e.g 1024 for 1KB
52 # optionally get bytes limit for a single file, e.g 1024 for 1KB
51 forbid_size_over = repo_extra_fields.get('forbid_size_over', {}).get('field_value')
53 forbid_size_over = repo_extra_fields.get('forbid_size_over', {}).get('field_value')
52 forbid_size_over = int(forbid_size_over or 0)
54 forbid_size_over = int(forbid_size_over or 0)
53
55
56 # forbid_size_over = 1024 # example 1024
57
54 def validate_file_name_and_size(file_data, forbidden_files=None, size_limit=None):
58 def validate_file_name_and_size(file_data, forbidden_files=None, size_limit=None):
55 """
59 """
56 This function validates commited files against some sort of rules.
60 This function validates comited files against some sort of rules.
57 It should return a valid boolean, and a reason for failure
61 It should return a valid boolean, and a reason for failure
58
62
59 file_data =[
63 file_data =[
@@ -87,7 +91,10 b' def _pre_push_hook(*args, **kwargs):'
87
91
88 # validate A(dded) files and size
92 # validate A(dded) files and size
89 if size_limit and operation == 'A':
93 if size_limit and operation == 'A':
90 size = len(file_data['raw_diff'])
94 if 'file_size' in file_data:
95 size = file_data['file_size']
96 else:
97 size = len(file_data['raw_diff'])
91
98
92 reason = 'File {} size of {} bytes exceeds limit {}'.format(
99 reason = 'File {} size of {} bytes exceeds limit {}'.format(
93 file_name, format_byte_size_binary(size),
100 file_name, format_byte_size_binary(size),
@@ -34,12 +34,51 b' from rhodecode.lib.vcs.backends.hg.diff '
34 from rhodecode.lib.vcs.backends.git.diff import GitDiff
34 from rhodecode.lib.vcs.backends.git.diff import GitDiff
35
35
36
36
37 def get_hg_files(repo, refs):
37 def get_svn_files(repo, vcs_repo, refs):
38 txn_id = refs[0]
39 files = []
40 stdout, stderr = vcs_repo.run_svn_command(
41 ['svnlook', 'changed', repo.repo_full_path, '--transaction', txn_id])
42
43 svn_op_to_rc_op = {
44 'A': 'A',
45 'U': 'M',
46 'D': 'D',
47 }
48
49 for entry in stdout.splitlines():
50 parsed_entry = {
51 'raw_diff': '',
52 'filename': '',
53 'chunks': [],
54 'ops': {},
55 'file_size': 0
56 }
57
58 op = entry[0]
59 path = entry[1:].strip()
60
61 rc_op = svn_op_to_rc_op.get(op) or '?'
62 parsed_entry['filename'] = path
63 parsed_entry['operation'] = rc_op
64
65 if rc_op in ['A', 'M']:
66 stdout, stderr = vcs_repo.run_svn_command(
67 ['svnlook', 'filesize', repo.repo_full_path, path, '--transaction', txn_id])
68 file_size = int(stdout.strip())
69 parsed_entry['file_size'] = file_size
70
71 files.append(parsed_entry)
72
73 return files
74
75
76 def get_hg_files(repo, vcs_repo, refs):
38 files = []
77 files = []
39 return files
78 return files
40
79
41
80
42 def get_git_files(repo, refs):
81 def get_git_files(repo, vcs_repo, refs):
43 files = []
82 files = []
44
83
45 for data in refs:
84 for data in refs:
@@ -57,7 +96,7 b' def get_git_files(repo, refs):'
57 'diff', old_rev, new_rev
96 'diff', old_rev, new_rev
58 ]
97 ]
59
98
60 stdout, stderr = repo.run_git_command(cmd, extra_env=git_env)
99 stdout, stderr = vcs_repo.run_git_command(cmd, extra_env=git_env)
61 vcs_diff = GitDiff(stdout)
100 vcs_diff = GitDiff(stdout)
62
101
63 diff_processor = diffs.DiffProcessor(vcs_diff, format='newdiff')
102 diff_processor = diffs.DiffProcessor(vcs_diff, format='newdiff')
@@ -86,11 +125,14 b' def run(*args, **kwargs):'
86 if vcs_type == 'git':
125 if vcs_type == 'git':
87 for rev_data in kwargs['commit_ids']:
126 for rev_data in kwargs['commit_ids']:
88 new_environ = dict((k, v) for k, v in rev_data['git_env'])
127 new_environ = dict((k, v) for k, v in rev_data['git_env'])
89 files = get_git_files(vcs_repo, kwargs['commit_ids'])
128 files = get_git_files(repo, vcs_repo, kwargs['commit_ids'])
90
129
91 if vcs_type == 'hg':
130 if vcs_type == 'hg':
92 for rev_data in kwargs['commit_ids']:
131 for rev_data in kwargs['commit_ids']:
93 new_environ = dict((k, v) for k, v in rev_data['hg_env'])
132 new_environ = dict((k, v) for k, v in rev_data['hg_env'])
94 files = get_hg_files(vcs_repo, kwargs['commit_ids'])
133 files = get_hg_files(repo, vcs_repo, kwargs['commit_ids'])
134
135 if vcs_type == 'svn':
136 files = get_svn_files(repo, vcs_repo, kwargs['commit_ids'])
95
137
96 return files
138 return files
@@ -402,7 +402,8 b' class RepoIntegrationsView(IntegrationSe'
402 c.rhodecode_db_repo = self.repo
402 c.rhodecode_db_repo = self.repo
403 c.repo_name = self.db_repo.repo_name
403 c.repo_name = self.db_repo.repo_name
404 c.repository_pull_requests = ScmModel().get_pull_requests(self.repo)
404 c.repository_pull_requests = ScmModel().get_pull_requests(self.repo)
405
405 c.repository_is_user_following = ScmModel().is_following_repo(
406 c.repo_name, self._rhodecode_user.user_id)
406 c.has_origin_repo_read_perm = False
407 c.has_origin_repo_read_perm = False
407 if self.db_repo.fork:
408 if self.db_repo.fork:
408 c.has_origin_repo_read_perm = h.HasRepoPermissionAny(
409 c.has_origin_repo_read_perm = h.HasRepoPermissionAny(
@@ -92,6 +92,9 b' ACTIONS_V1 = {'
92 'repo.commit.comment.delete': {'data': {}},
92 'repo.commit.comment.delete': {'data': {}},
93 'repo.commit.vote': '',
93 'repo.commit.vote': '',
94
94
95 'repo.artifact.add': '',
96 'repo.artifact.delete': '',
97
95 'repo_group.create': {'data': {}},
98 'repo_group.create': {'data': {}},
96 'repo_group.edit': {'old_data': {}},
99 'repo_group.edit': {'old_data': {}},
97 'repo_group.edit.permissions': {},
100 'repo_group.edit.permissions': {},
@@ -2078,8 +2078,7 b' class HasRepoPermissionAny(PermsFunction'
2078 class HasRepoGroupPermissionAny(PermsFunction):
2078 class HasRepoGroupPermissionAny(PermsFunction):
2079 def __call__(self, group_name=None, check_location='', user=None):
2079 def __call__(self, group_name=None, check_location='', user=None):
2080 self.repo_group_name = group_name
2080 self.repo_group_name = group_name
2081 return super(HasRepoGroupPermissionAny, self).__call__(
2081 return super(HasRepoGroupPermissionAny, self).__call__(check_location, user)
2082 check_location, user)
2083
2082
2084 def check_permissions(self, user):
2083 def check_permissions(self, user):
2085 perms = user.permissions
2084 perms = user.permissions
@@ -2095,8 +2094,7 b' class HasRepoGroupPermissionAny(PermsFun'
2095 class HasRepoGroupPermissionAll(PermsFunction):
2094 class HasRepoGroupPermissionAll(PermsFunction):
2096 def __call__(self, group_name=None, check_location='', user=None):
2095 def __call__(self, group_name=None, check_location='', user=None):
2097 self.repo_group_name = group_name
2096 self.repo_group_name = group_name
2098 return super(HasRepoGroupPermissionAll, self).__call__(
2097 return super(HasRepoGroupPermissionAll, self).__call__(check_location, user)
2099 check_location, user)
2100
2098
2101 def check_permissions(self, user):
2099 def check_permissions(self, user):
2102 perms = user.permissions
2100 perms = user.permissions
@@ -2112,8 +2110,7 b' class HasRepoGroupPermissionAll(PermsFun'
2112 class HasUserGroupPermissionAny(PermsFunction):
2110 class HasUserGroupPermissionAny(PermsFunction):
2113 def __call__(self, user_group_name=None, check_location='', user=None):
2111 def __call__(self, user_group_name=None, check_location='', user=None):
2114 self.user_group_name = user_group_name
2112 self.user_group_name = user_group_name
2115 return super(HasUserGroupPermissionAny, self).__call__(
2113 return super(HasUserGroupPermissionAny, self).__call__(check_location, user)
2116 check_location, user)
2117
2114
2118 def check_permissions(self, user):
2115 def check_permissions(self, user):
2119 perms = user.permissions
2116 perms = user.permissions
@@ -2129,8 +2126,7 b' class HasUserGroupPermissionAny(PermsFun'
2129 class HasUserGroupPermissionAll(PermsFunction):
2126 class HasUserGroupPermissionAll(PermsFunction):
2130 def __call__(self, user_group_name=None, check_location='', user=None):
2127 def __call__(self, user_group_name=None, check_location='', user=None):
2131 self.user_group_name = user_group_name
2128 self.user_group_name = user_group_name
2132 return super(HasUserGroupPermissionAll, self).__call__(
2129 return super(HasUserGroupPermissionAll, self).__call__(check_location, user)
2133 check_location, user)
2134
2130
2135 def check_permissions(self, user):
2131 def check_permissions(self, user):
2136 perms = user.permissions
2132 perms = user.permissions
@@ -288,7 +288,6 b' def attach_context_attributes(context, r'
288 """
288 """
289 config = request.registry.settings
289 config = request.registry.settings
290
290
291
292 rc_config = SettingsModel().get_all_settings(cache=True)
291 rc_config = SettingsModel().get_all_settings(cache=True)
293
292
294 context.rhodecode_version = rhodecode.__version__
293 context.rhodecode_version = rhodecode.__version__
@@ -375,20 +374,25 b' def attach_context_attributes(context, r'
375 "sideside": "sideside"
374 "sideside": "sideside"
376 }.get(request.GET.get('diffmode'))
375 }.get(request.GET.get('diffmode'))
377
376
378 if diffmode and diffmode != request.session.get('rc_user_session_attr.diffmode'):
377 is_api = hasattr(request, 'rpc_user')
379 request.session['rc_user_session_attr.diffmode'] = diffmode
380
381 # session settings per user
382 session_attrs = {
378 session_attrs = {
383 # defaults
379 # defaults
384 "clone_url_format": "http",
380 "clone_url_format": "http",
385 "diffmode": "sideside"
381 "diffmode": "sideside"
386 }
382 }
387 for k, v in request.session.items():
383
388 pref = 'rc_user_session_attr.'
384 if not is_api:
389 if k and k.startswith(pref):
385 # don't access pyramid session for API calls
390 k = k[len(pref):]
386 if diffmode and diffmode != request.session.get('rc_user_session_attr.diffmode'):
391 session_attrs[k] = v
387 request.session['rc_user_session_attr.diffmode'] = diffmode
388
389 # session settings per user
390
391 for k, v in request.session.items():
392 pref = 'rc_user_session_attr.'
393 if k and k.startswith(pref):
394 k = k[len(pref):]
395 session_attrs[k] = v
392
396
393 context.user_session_attrs = session_attrs
397 context.user_session_attrs = session_attrs
394
398
@@ -420,8 +424,12 b' def attach_context_attributes(context, r'
420 'extra': {'plugins': {}}
424 'extra': {'plugins': {}}
421 }
425 }
422 # END CONFIG VARS
426 # END CONFIG VARS
427 if is_api:
428 csrf_token = None
429 else:
430 csrf_token = auth.get_csrf_token(session=request.session)
423
431
424 context.csrf_token = auth.get_csrf_token(session=request.session)
432 context.csrf_token = csrf_token
425 context.backends = rhodecode.BACKENDS.keys()
433 context.backends = rhodecode.BACKENDS.keys()
426 context.backends.sort()
434 context.backends.sort()
427 unread_count = 0
435 unread_count = 0
@@ -537,7 +545,7 b' def bootstrap_config(request):'
537
545
538 # allow pyramid lookup in testing
546 # allow pyramid lookup in testing
539 config.include('pyramid_mako')
547 config.include('pyramid_mako')
540 config.include('pyramid_beaker')
548 config.include('rhodecode.lib.rc_beaker')
541 config.include('rhodecode.lib.rc_cache')
549 config.include('rhodecode.lib.rc_cache')
542
550
543 add_events_routes(config)
551 add_events_routes(config)
@@ -375,6 +375,27 b' class DbManage(object):'
375 hgevolve.ui_active = False
375 hgevolve.ui_active = False
376 self.sa.add(hgevolve)
376 self.sa.add(hgevolve)
377
377
378 hgevolve = RhodeCodeUi()
379 hgevolve.ui_section = 'experimental'
380 hgevolve.ui_key = 'evolution'
381 hgevolve.ui_value = ''
382 hgevolve.ui_active = False
383 self.sa.add(hgevolve)
384
385 hgevolve = RhodeCodeUi()
386 hgevolve.ui_section = 'experimental'
387 hgevolve.ui_key = 'evolution.exchange'
388 hgevolve.ui_value = ''
389 hgevolve.ui_active = False
390 self.sa.add(hgevolve)
391
392 hgevolve = RhodeCodeUi()
393 hgevolve.ui_section = 'extensions'
394 hgevolve.ui_key = 'topic'
395 hgevolve.ui_value = ''
396 hgevolve.ui_active = False
397 self.sa.add(hgevolve)
398
378 # enable hggit disabled by default
399 # enable hggit disabled by default
379 hggit = RhodeCodeUi()
400 hggit = RhodeCodeUi()
380 hggit.ui_section = 'extensions'
401 hggit.ui_section = 'extensions'
@@ -464,9 +485,6 b' class DbManage(object):'
464 self.populate_default_permissions()
485 self.populate_default_permissions()
465 return fixed
486 return fixed
466
487
467 def update_repo_info(self):
468 RepoModel.update_repoinfo()
469
470 def config_prompt(self, test_repo_path='', retries=3):
488 def config_prompt(self, test_repo_path='', retries=3):
471 defaults = self.cli_args
489 defaults = self.cli_args
472 _path = defaults.get('repos_location')
490 _path = defaults.get('repos_location')
@@ -614,7 +614,7 b' class Repository(Base, BaseModel):'
614 if (cs_cache != self.changeset_cache or not self.changeset_cache):
614 if (cs_cache != self.changeset_cache or not self.changeset_cache):
615 _default = datetime.datetime.fromtimestamp(0)
615 _default = datetime.datetime.fromtimestamp(0)
616 last_change = cs_cache.get('date') or _default
616 last_change = cs_cache.get('date') or _default
617 log.debug('updated repo %s with new cs cache %s', self.repo_name, cs_cache)
617 log.debug('updated repo %s with new commit cache %s', self.repo_name, cs_cache)
618 self.updated_on = last_change
618 self.updated_on = last_change
619 self.changeset_cache = cs_cache
619 self.changeset_cache = cs_cache
620 Session().add(self)
620 Session().add(self)
@@ -38,8 +38,6 b' from sqlalchemy.orm import relationship,'
38 from sqlalchemy.exc import OperationalError
38 from sqlalchemy.exc import OperationalError
39 from beaker.cache import cache_region, region_invalidate
39 from beaker.cache import cache_region, region_invalidate
40 from webob.exc import HTTPNotFound
40 from webob.exc import HTTPNotFound
41 from Crypto.Cipher import AES
42 from Crypto import Random
43 from zope.cachedescriptors.property import Lazy as LazyProperty
41 from zope.cachedescriptors.property import Lazy as LazyProperty
44
42
45 from rhodecode.translation import _
43 from rhodecode.translation import _
@@ -2164,7 +2164,7 b' class Repository(Base, BaseModel):'
2164 if is_outdated(cs_cache) or not self.changeset_cache:
2164 if is_outdated(cs_cache) or not self.changeset_cache:
2165 _default = datetime.datetime.fromtimestamp(0)
2165 _default = datetime.datetime.fromtimestamp(0)
2166 last_change = cs_cache.get('date') or _default
2166 last_change = cs_cache.get('date') or _default
2167 log.debug('updated repo %s with new cs cache %s',
2167 log.debug('updated repo %s with new commit cache %s',
2168 self.repo_name, cs_cache)
2168 self.repo_name, cs_cache)
2169 self.updated_on = last_change
2169 self.updated_on = last_change
2170 self.changeset_cache = cs_cache
2170 self.changeset_cache = cs_cache
@@ -2230,7 +2230,7 b' class Repository(Base, BaseModel):'
2230 if is_outdated(cs_cache) or not self.changeset_cache:
2230 if is_outdated(cs_cache) or not self.changeset_cache:
2231 _default = datetime.datetime.fromtimestamp(0)
2231 _default = datetime.datetime.fromtimestamp(0)
2232 last_change = cs_cache.get('date') or _default
2232 last_change = cs_cache.get('date') or _default
2233 log.debug('updated repo %s with new cs cache %s',
2233 log.debug('updated repo %s with new commit cache %s',
2234 self.repo_name, cs_cache)
2234 self.repo_name, cs_cache)
2235 self.updated_on = last_change
2235 self.updated_on = last_change
2236 self.changeset_cache = cs_cache
2236 self.changeset_cache = cs_cache
@@ -2278,7 +2278,7 b' class Repository(Base, BaseModel):'
2278 # if yes, we use the current timestamp instead. Imagine you get
2278 # if yes, we use the current timestamp instead. Imagine you get
2279 # old commit pushed 1y ago, we'd set last update 1y to ago.
2279 # old commit pushed 1y ago, we'd set last update 1y to ago.
2280 last_change = _default
2280 last_change = _default
2281 log.debug('updated repo %s with new cs cache %s',
2281 log.debug('updated repo %s with new commit cache %s',
2282 self.repo_name, cs_cache)
2282 self.repo_name, cs_cache)
2283 self.updated_on = last_change
2283 self.updated_on = last_change
2284 self.changeset_cache = cs_cache
2284 self.changeset_cache = cs_cache
@@ -2301,7 +2301,7 b' class Repository(Base, BaseModel):'
2301 # if yes, we use the current timestamp instead. Imagine you get
2301 # if yes, we use the current timestamp instead. Imagine you get
2302 # old commit pushed 1y ago, we'd set last update 1y to ago.
2302 # old commit pushed 1y ago, we'd set last update 1y to ago.
2303 last_change = _default
2303 last_change = _default
2304 log.debug('updated repo %s with new cs cache %s',
2304 log.debug('updated repo %s with new commit cache %s',
2305 self.repo_name, cs_cache)
2305 self.repo_name, cs_cache)
2306 self.updated_on = last_change
2306 self.updated_on = last_change
2307 self.changeset_cache = cs_cache
2307 self.changeset_cache = cs_cache
@@ -2301,7 +2301,7 b' class Repository(Base, BaseModel):'
2301 # if yes, we use the current timestamp instead. Imagine you get
2301 # if yes, we use the current timestamp instead. Imagine you get
2302 # old commit pushed 1y ago, we'd set last update 1y to ago.
2302 # old commit pushed 1y ago, we'd set last update 1y to ago.
2303 last_change = _default
2303 last_change = _default
2304 log.debug('updated repo %s with new cs cache %s',
2304 log.debug('updated repo %s with new commit cache %s',
2305 self.repo_name, cs_cache)
2305 self.repo_name, cs_cache)
2306 self.updated_on = last_change
2306 self.updated_on = last_change
2307 self.changeset_cache = cs_cache
2307 self.changeset_cache = cs_cache
@@ -1865,7 +1865,7 b' class Repository(Base, BaseModel):'
1865 if is_outdated(cs_cache) or not self.changeset_cache:
1865 if is_outdated(cs_cache) or not self.changeset_cache:
1866 _default = datetime.datetime.fromtimestamp(0)
1866 _default = datetime.datetime.fromtimestamp(0)
1867 last_change = cs_cache.get('date') or _default
1867 last_change = cs_cache.get('date') or _default
1868 log.debug('updated repo %s with new cs cache %s',
1868 log.debug('updated repo %s with new commit cache %s',
1869 self.repo_name, cs_cache)
1869 self.repo_name, cs_cache)
1870 self.updated_on = last_change
1870 self.updated_on = last_change
1871 self.changeset_cache = cs_cache
1871 self.changeset_cache = cs_cache
@@ -1868,7 +1868,7 b' class Repository(Base, BaseModel):'
1868 if is_outdated(cs_cache) or not self.changeset_cache:
1868 if is_outdated(cs_cache) or not self.changeset_cache:
1869 _default = datetime.datetime.fromtimestamp(0)
1869 _default = datetime.datetime.fromtimestamp(0)
1870 last_change = cs_cache.get('date') or _default
1870 last_change = cs_cache.get('date') or _default
1871 log.debug('updated repo %s with new cs cache %s',
1871 log.debug('updated repo %s with new commit cache %s',
1872 self.repo_name, cs_cache)
1872 self.repo_name, cs_cache)
1873 self.updated_on = last_change
1873 self.updated_on = last_change
1874 self.changeset_cache = cs_cache
1874 self.changeset_cache = cs_cache
@@ -1867,7 +1867,7 b' class Repository(Base, BaseModel):'
1867 if is_outdated(cs_cache) or not self.changeset_cache:
1867 if is_outdated(cs_cache) or not self.changeset_cache:
1868 _default = datetime.datetime.fromtimestamp(0)
1868 _default = datetime.datetime.fromtimestamp(0)
1869 last_change = cs_cache.get('date') or _default
1869 last_change = cs_cache.get('date') or _default
1870 log.debug('updated repo %s with new cs cache %s',
1870 log.debug('updated repo %s with new commit cache %s',
1871 self.repo_name, cs_cache)
1871 self.repo_name, cs_cache)
1872 self.updated_on = last_change
1872 self.updated_on = last_change
1873 self.changeset_cache = cs_cache
1873 self.changeset_cache = cs_cache
@@ -1869,7 +1869,7 b' class Repository(Base, BaseModel):'
1869 if is_outdated(cs_cache) or not self.changeset_cache:
1869 if is_outdated(cs_cache) or not self.changeset_cache:
1870 _default = datetime.datetime.fromtimestamp(0)
1870 _default = datetime.datetime.fromtimestamp(0)
1871 last_change = cs_cache.get('date') or _default
1871 last_change = cs_cache.get('date') or _default
1872 log.debug('updated repo %s with new cs cache %s',
1872 log.debug('updated repo %s with new commit cache %s',
1873 self.repo_name, cs_cache)
1873 self.repo_name, cs_cache)
1874 self.updated_on = last_change
1874 self.updated_on = last_change
1875 self.changeset_cache = cs_cache
1875 self.changeset_cache = cs_cache
@@ -1869,7 +1869,7 b' class Repository(Base, BaseModel):'
1869 if is_outdated(cs_cache) or not self.changeset_cache:
1869 if is_outdated(cs_cache) or not self.changeset_cache:
1870 _default = datetime.datetime.fromtimestamp(0)
1870 _default = datetime.datetime.fromtimestamp(0)
1871 last_change = cs_cache.get('date') or _default
1871 last_change = cs_cache.get('date') or _default
1872 log.debug('updated repo %s with new cs cache %s',
1872 log.debug('updated repo %s with new commit cache %s',
1873 self.repo_name, cs_cache)
1873 self.repo_name, cs_cache)
1874 self.updated_on = last_change
1874 self.updated_on = last_change
1875 self.changeset_cache = cs_cache
1875 self.changeset_cache = cs_cache
@@ -1912,7 +1912,7 b' class Repository(Base, BaseModel):'
1912 if is_outdated(cs_cache) or not self.changeset_cache:
1912 if is_outdated(cs_cache) or not self.changeset_cache:
1913 _default = datetime.datetime.fromtimestamp(0)
1913 _default = datetime.datetime.fromtimestamp(0)
1914 last_change = cs_cache.get('date') or _default
1914 last_change = cs_cache.get('date') or _default
1915 log.debug('updated repo %s with new cs cache %s',
1915 log.debug('updated repo %s with new commit cache %s',
1916 self.repo_name, cs_cache)
1916 self.repo_name, cs_cache)
1917 self.updated_on = last_change
1917 self.updated_on = last_change
1918 self.changeset_cache = cs_cache
1918 self.changeset_cache = cs_cache
@@ -1913,7 +1913,7 b' class Repository(Base, BaseModel):'
1913 if is_outdated(cs_cache) or not self.changeset_cache:
1913 if is_outdated(cs_cache) or not self.changeset_cache:
1914 _default = datetime.datetime.fromtimestamp(0)
1914 _default = datetime.datetime.fromtimestamp(0)
1915 last_change = cs_cache.get('date') or _default
1915 last_change = cs_cache.get('date') or _default
1916 log.debug('updated repo %s with new cs cache %s',
1916 log.debug('updated repo %s with new commit cache %s',
1917 self.repo_name, cs_cache)
1917 self.repo_name, cs_cache)
1918 self.updated_on = last_change
1918 self.updated_on = last_change
1919 self.changeset_cache = cs_cache
1919 self.changeset_cache = cs_cache
@@ -2100,7 +2100,7 b' class Repository(Base, BaseModel):'
2100 if is_outdated(cs_cache) or not self.changeset_cache:
2100 if is_outdated(cs_cache) or not self.changeset_cache:
2101 _default = datetime.datetime.fromtimestamp(0)
2101 _default = datetime.datetime.fromtimestamp(0)
2102 last_change = cs_cache.get('date') or _default
2102 last_change = cs_cache.get('date') or _default
2103 log.debug('updated repo %s with new cs cache %s',
2103 log.debug('updated repo %s with new commit cache %s',
2104 self.repo_name, cs_cache)
2104 self.repo_name, cs_cache)
2105 self.updated_on = last_change
2105 self.updated_on = last_change
2106 self.changeset_cache = cs_cache
2106 self.changeset_cache = cs_cache
@@ -111,4 +111,28 b' class AESCipher(object):'
111
111
112 @staticmethod
112 @staticmethod
113 def _unpad(s):
113 def _unpad(s):
114 return s[:-ord(s[len(s)-1:])] No newline at end of file
114 return s[:-ord(s[len(s)-1:])]
115
116
117 def validate_and_get_enc_data(enc_data, enc_key, enc_strict_mode):
118 parts = enc_data.split('$', 3)
119 if not len(parts) == 3:
120 # probably not encrypted values
121 return enc_data
122 else:
123 if parts[0] != 'enc':
124 # parts ok but without our header ?
125 return enc_data
126
127 # at that stage we know it's our encryption
128 if parts[1] == 'aes':
129 decrypted_data = AESCipher(enc_key).decrypt(parts[2])
130 elif parts[1] == 'aes_hmac':
131 decrypted_data = AESCipher(
132 enc_key, hmac=True,
133 strict_verification=enc_strict_mode).decrypt(parts[2])
134 else:
135 raise ValueError(
136 'Encryption type part is wrong, must be `aes` '
137 'or `aes_hmac`, got `%s` instead' % (parts[1]))
138 return decrypted_data
@@ -199,6 +199,7 b' class _GetError(object):'
199 if form_errors and field_name in form_errors:
199 if form_errors and field_name in form_errors:
200 return literal(tmpl % form_errors.get(field_name))
200 return literal(tmpl % form_errors.get(field_name))
201
201
202
202 get_error = _GetError()
203 get_error = _GetError()
203
204
204
205
@@ -214,38 +215,45 b' class _ToolTip(object):'
214 tooltip_title = escape(tooltip_title)
215 tooltip_title = escape(tooltip_title)
215 tooltip_title = tooltip_title.replace('<', '&lt;').replace('>', '&gt;')
216 tooltip_title = tooltip_title.replace('<', '&lt;').replace('>', '&gt;')
216 return tooltip_title
217 return tooltip_title
218
219
217 tooltip = _ToolTip()
220 tooltip = _ToolTip()
218
221
222 files_icon = u'<i class="file-breadcrumb-copy tooltip icon-clipboard clipboard-action" data-clipboard-text="{}" title="Copy the full path"></i>'
219
223
220 def files_breadcrumbs(repo_name, commit_id, file_path):
224
225 def files_breadcrumbs(repo_name, commit_id, file_path, at_ref=None, limit_items=False, linkify_last_item=False):
221 if isinstance(file_path, str):
226 if isinstance(file_path, str):
222 file_path = safe_unicode(file_path)
227 file_path = safe_unicode(file_path)
223
228
224 # TODO: johbo: Is this always a url like path, or is this operating
229 route_qry = {'at': at_ref} if at_ref else None
225 # system dependent?
226 path_segments = file_path.split('/')
227
230
228 repo_name_html = escape(repo_name)
231 # first segment is a `..` link to repo files
229 if len(path_segments) == 1 and path_segments[0] == '':
232 root_name = literal(u'<i class="icon-home"></i>')
230 url_segments = [repo_name_html]
233 url_segments = [
231 else:
234 link_to(
232 url_segments = [
235 root_name,
233 link_to(
236 route_path(
234 repo_name_html,
237 'repo_files',
235 route_path(
238 repo_name=repo_name,
236 'repo_files',
239 commit_id=commit_id,
237 repo_name=repo_name,
240 f_path='',
238 commit_id=commit_id,
241 _query=route_qry),
239 f_path=''),
242 )]
240 class_='pjax-link')]
241
243
244 path_segments = file_path.split('/')
242 last_cnt = len(path_segments) - 1
245 last_cnt = len(path_segments) - 1
243 for cnt, segment in enumerate(path_segments):
246 for cnt, segment in enumerate(path_segments):
244 if not segment:
247 if not segment:
245 continue
248 continue
246 segment_html = escape(segment)
249 segment_html = escape(segment)
247
250
248 if cnt != last_cnt:
251 last_item = cnt == last_cnt
252
253 if last_item and linkify_last_item is False:
254 # plain version
255 url_segments.append(segment_html)
256 else:
249 url_segments.append(
257 url_segments.append(
250 link_to(
258 link_to(
251 segment_html,
259 segment_html,
@@ -253,12 +261,32 b' def files_breadcrumbs(repo_name, commit_'
253 'repo_files',
261 'repo_files',
254 repo_name=repo_name,
262 repo_name=repo_name,
255 commit_id=commit_id,
263 commit_id=commit_id,
256 f_path='/'.join(path_segments[:cnt + 1])),
264 f_path='/'.join(path_segments[:cnt + 1]),
257 class_='pjax-link'))
265 _query=route_qry),
258 else:
266 ))
259 url_segments.append(segment_html)
267
268 limited_url_segments = url_segments[:1] + ['...'] + url_segments[-5:]
269 if limit_items and len(limited_url_segments) < len(url_segments):
270 url_segments = limited_url_segments
260
271
261 return literal('/'.join(url_segments))
272 full_path = file_path
273 icon = files_icon.format(escape(full_path))
274 if file_path == '':
275 return root_name
276 else:
277 return literal(' / '.join(url_segments) + icon)
278
279
280 def files_url_data(request):
281 matchdict = request.matchdict
282
283 if 'f_path' not in matchdict:
284 matchdict['f_path'] = ''
285
286 if 'commit_id' not in matchdict:
287 matchdict['commit_id'] = 'tip'
288
289 return json.dumps(matchdict)
262
290
263
291
264 def code_highlight(code, lexer, formatter, use_hl_filter=False):
292 def code_highlight(code, lexer, formatter, use_hl_filter=False):
@@ -1196,7 +1224,7 b' class InitialsGravatar(object):'
1196 </text>
1224 </text>
1197 </svg>""".format(
1225 </svg>""".format(
1198 size=self.size,
1226 size=self.size,
1199 f_size=self.size/1.85, # scale the text inside the box nicely
1227 f_size=self.size/2.05, # scale the text inside the box nicely
1200 background=self.background,
1228 background=self.background,
1201 text_color=self.text_color,
1229 text_color=self.text_color,
1202 text=initials.upper(),
1230 text=initials.upper(),
@@ -1486,10 +1514,12 b' def breadcrumb_repo_link(repo):'
1486 """
1514 """
1487
1515
1488 path = [
1516 path = [
1489 link_to(group.name, route_path('repo_group_home', repo_group_name=group.group_name))
1517 link_to(group.name, route_path('repo_group_home', repo_group_name=group.group_name),
1518 title='last change:{}'.format(format_date(group.last_commit_change)))
1490 for group in repo.groups_with_parents
1519 for group in repo.groups_with_parents
1491 ] + [
1520 ] + [
1492 link_to(repo.just_name, route_path('repo_summary', repo_name=repo.repo_name))
1521 link_to(repo.just_name, route_path('repo_summary', repo_name=repo.repo_name),
1522 title='last change:{}'.format(format_date(repo.last_commit_change)))
1493 ]
1523 ]
1494
1524
1495 return literal(' &raquo; '.join(path))
1525 return literal(' &raquo; '.join(path))
@@ -1507,11 +1537,13 b' def breadcrumb_repo_group_link(repo_grou'
1507
1537
1508 path = [
1538 path = [
1509 link_to(group.name,
1539 link_to(group.name,
1510 route_path('repo_group_home', repo_group_name=group.group_name))
1540 route_path('repo_group_home', repo_group_name=group.group_name),
1541 title='last change:{}'.format(format_date(group.last_commit_change)))
1511 for group in repo_group.parents
1542 for group in repo_group.parents
1512 ] + [
1543 ] + [
1513 link_to(repo_group.name,
1544 link_to(repo_group.name,
1514 route_path('repo_group_home', repo_group_name=repo_group.group_name))
1545 route_path('repo_group_home', repo_group_name=repo_group.group_name),
1546 title='last change:{}'.format(format_date(repo_group.last_commit_change)))
1515 ]
1547 ]
1516
1548
1517 return literal(' &raquo; '.join(path))
1549 return literal(' &raquo; '.join(path))
@@ -1907,23 +1939,26 b' def secure_form(form_url, method="POST",'
1907
1939
1908 def dropdownmenu(name, selected, options, enable_filter=False, **attrs):
1940 def dropdownmenu(name, selected, options, enable_filter=False, **attrs):
1909 select_html = select(name, selected, options, **attrs)
1941 select_html = select(name, selected, options, **attrs)
1942
1910 select2 = """
1943 select2 = """
1911 <script>
1944 <script>
1912 $(document).ready(function() {
1945 $(document).ready(function() {
1913 $('#%s').select2({
1946 $('#%s').select2({
1914 containerCssClass: 'drop-menu',
1947 containerCssClass: 'drop-menu %s',
1915 dropdownCssClass: 'drop-menu-dropdown',
1948 dropdownCssClass: 'drop-menu-dropdown',
1916 dropdownAutoWidth: true%s
1949 dropdownAutoWidth: true%s
1917 });
1950 });
1918 });
1951 });
1919 </script>
1952 </script>
1920 """
1953 """
1954
1921 filter_option = """,
1955 filter_option = """,
1922 minimumResultsForSearch: -1
1956 minimumResultsForSearch: -1
1923 """
1957 """
1924 input_id = attrs.get('id') or name
1958 input_id = attrs.get('id') or name
1959 extra_classes = ' '.join(attrs.pop('extra_classes', []))
1925 filter_enabled = "" if enable_filter else filter_option
1960 filter_enabled = "" if enable_filter else filter_option
1926 select_script = literal(select2 % (input_id, filter_enabled))
1961 select_script = literal(select2 % (input_id, extra_classes, filter_enabled))
1927
1962
1928 return literal(select_html+select_script)
1963 return literal(select_html+select_script)
1929
1964
@@ -1944,7 +1979,7 b' def get_visual_attr(tmpl_context_var, at'
1944
1979
1945 def get_last_path_part(file_node):
1980 def get_last_path_part(file_node):
1946 if not file_node.path:
1981 if not file_node.path:
1947 return u''
1982 return u'/'
1948
1983
1949 path = safe_unicode(file_node.path.split('/')[-1])
1984 path = safe_unicode(file_node.path.split('/')[-1])
1950 return u'../' + path
1985 return u'../' + path
@@ -2033,10 +2068,11 b' def reviewer_as_json(*args, **kwargs):'
2033 def get_repo_view_type(request):
2068 def get_repo_view_type(request):
2034 route_name = request.matched_route.name
2069 route_name = request.matched_route.name
2035 route_to_view_type = {
2070 route_to_view_type = {
2036 'repo_changelog': 'changelog',
2071 'repo_changelog': 'commits',
2072 'repo_commits': 'commits',
2037 'repo_files': 'files',
2073 'repo_files': 'files',
2038 'repo_summary': 'summary',
2074 'repo_summary': 'summary',
2039 'repo_commit': 'commit'
2075 'repo_commit': 'commit'
2076 }
2040
2077
2041 }
2042 return route_to_view_type.get(route_name)
2078 return route_to_view_type.get(route_name)
@@ -80,7 +80,7 b' def trigger_log_create_pull_request_hook'
80 extras = _get_rc_scm_extras(username, repo_name, repo_alias,
80 extras = _get_rc_scm_extras(username, repo_name, repo_alias,
81 'create_pull_request')
81 'create_pull_request')
82 events.trigger(events.PullRequestCreateEvent(pull_request))
82 events.trigger(events.PullRequestCreateEvent(pull_request))
83 extras.update(pull_request.get_api_data())
83 extras.update(pull_request.get_api_data(with_merge_state=False))
84 hooks_base.log_create_pull_request(**extras)
84 hooks_base.log_create_pull_request(**extras)
85
85
86
86
@@ -80,6 +80,13 b' class BaseSearcher(object):'
80 def extract_search_tags(query):
80 def extract_search_tags(query):
81 return []
81 return []
82
82
83 @staticmethod
84 def escape_specials(val):
85 """
86 Handle and escape reserved chars for search
87 """
88 return val
89
83
90
84 def search_config(config, prefix='search.'):
91 def search_config(config, prefix='search.'):
85 _config = {}
92 _config = {}
@@ -20,7 +20,55 b''
20
20
21 import markdown
21 import markdown
22
22
23 from mdx_gfm import GithubFlavoredMarkdownExtension # pragma: no cover
23 from markdown.extensions import Extension
24 from markdown.extensions.fenced_code import FencedCodeExtension
25 from markdown.extensions.smart_strong import SmartEmphasisExtension
26 from markdown.extensions.tables import TableExtension
27 from markdown.extensions.nl2br import Nl2BrExtension
28
29 import gfm
30
31
32 class GithubFlavoredMarkdownExtension(Extension):
33 """
34 An extension that is as compatible as possible with GitHub-flavored
35 Markdown (GFM).
36
37 This extension aims to be compatible with the variant of GFM that GitHub
38 uses for Markdown-formatted gists and files (including READMEs). This
39 variant seems to have all the extensions described in the `GFM
40 documentation`_, except:
41
42 - Newlines in paragraphs are not transformed into ``br`` tags.
43 - Intra-GitHub links to commits, repositories, and issues are not
44 supported.
45
46 If you need support for features specific to GitHub comments and issues,
47 please use :class:`mdx_gfm.GithubFlavoredMarkdownExtension`.
48
49 .. _GFM documentation: https://guides.github.com/features/mastering-markdown/
50 """
51
52 def extendMarkdown(self, md, md_globals):
53 # Built-in extensions
54 FencedCodeExtension().extendMarkdown(md, md_globals)
55 SmartEmphasisExtension().extendMarkdown(md, md_globals)
56 TableExtension().extendMarkdown(md, md_globals)
57
58 # Custom extensions
59 gfm.AutolinkExtension().extendMarkdown(md, md_globals)
60 gfm.AutomailExtension().extendMarkdown(md, md_globals)
61 gfm.HiddenHiliteExtension([
62 ('guess_lang', 'False'),
63 ('css_class', 'highlight')
64 ]).extendMarkdown(md, md_globals)
65 gfm.SemiSaneListExtension().extendMarkdown(md, md_globals)
66 gfm.SpacedLinkExtension().extendMarkdown(md, md_globals)
67 gfm.StrikethroughExtension().extendMarkdown(md, md_globals)
68 gfm.TaskListExtension([
69 ('list_attrs', {'class': 'checkbox'})
70 ]).extendMarkdown(md, md_globals)
71 Nl2BrExtension().extendMarkdown(md, md_globals)
24
72
25
73
26 # Global Vars
74 # Global Vars
@@ -500,38 +500,38 b' class MarkupRenderer(object):'
500 (body, resources) = html_exporter.from_notebook_node(notebook)
500 (body, resources) = html_exporter.from_notebook_node(notebook)
501 header = '<!-- ## IPYTHON NOTEBOOK RENDERING ## -->'
501 header = '<!-- ## IPYTHON NOTEBOOK RENDERING ## -->'
502 js = MakoTemplate(r'''
502 js = MakoTemplate(r'''
503 <!-- Load mathjax -->
503 <!-- MathJax configuration -->
504 <!-- MathJax configuration -->
504 <script type="text/x-mathjax-config">
505 <script type="text/x-mathjax-config">
505 MathJax.Hub.Config({
506 MathJax.Hub.Config({
506 jax: ["input/TeX","output/HTML-CSS", "output/PreviewHTML"],
507 jax: ["input/TeX","output/HTML-CSS", "output/PreviewHTML"],
507 extensions: ["tex2jax.js","MathMenu.js","MathZoom.js", "fast-preview.js", "AssistiveMML.js", "[Contrib]/a11y/accessibility-menu.js"],
508 extensions: ["tex2jax.js","MathMenu.js","MathZoom.js", "fast-preview.js", "AssistiveMML.js", "[Contrib]/a11y/accessibility-menu.js"],
508 TeX: {
509 TeX: {
509 extensions: ["AMSmath.js","AMSsymbols.js","noErrors.js","noUndefined.js"]
510 extensions: ["AMSmath.js","AMSsymbols.js","noErrors.js","noUndefined.js"]
510 },
511 },
511 tex2jax: {
512 tex2jax: {
512 inlineMath: [ ['$','$'], ["\\(","\\)"] ],
513 inlineMath: [ ['$','$'], ["\\(","\\)"] ],
513 displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
514 displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
514 processEscapes: true,
515 processEscapes: true,
515 processEnvironments: true
516 processEnvironments: true
516 },
517 },
517 // Center justify equations in code and markdown cells. Elsewhere
518 // Center justify equations in code and markdown cells. Elsewhere
518 // we use CSS to left justify single line equations in code cells.
519 // we use CSS to left justify single line equations in code cells.
519 displayAlign: 'center',
520 displayAlign: 'center',
520 "HTML-CSS": {
521 "HTML-CSS": {
521 styles: {'.MathJax_Display': {"margin": 0}},
522 styles: {'.MathJax_Display': {"margin": 0}},
522 linebreaks: { automatic: true },
523 linebreaks: { automatic: true },
523 availableFonts: ["STIX", "TeX"]
524 availableFonts: ["STIX", "TeX"]
524 },
525 },
525 showMathMenu: false
526 showMathMenu: false
526 });
527 });
527 </script>
528 </script>
528 <!-- End of MathJax configuration -->
529 <!-- End of mathjax configuration -->
529 <script src="${h.asset('js/src/math_jax/MathJax.js')}"></script>
530 <script src="${h.asset('js/src/math_jax/MathJax.js')}"></script>
531 ''').render(h=helpers)
530 ''').render(h=helpers)
532
531
533 css = '<style>{}</style>'.format(
532 css = MakoTemplate(r'''
534 ''.join(_sanitize_resources(resources['inlining']['css'])))
533 <link rel="stylesheet" type="text/css" href="${h.asset('css/style-ipython.css', ver=ver)}" media="screen"/>
534 ''').render(h=helpers, ver='ver1')
535
535
536 body = '\n'.join([header, css, js, body])
536 body = '\n'.join([header, css, js, body])
537 return body, resources
537 return body, resources
@@ -142,7 +142,7 b' class SimpleGit(simplevcs.SimpleVCS):'
142 return self.scm_app.create_git_wsgi_app(
142 return self.scm_app.create_git_wsgi_app(
143 repo_path, repo_name, config)
143 repo_path, repo_name, config)
144
144
145 def _create_config(self, extras, repo_name):
145 def _create_config(self, extras, repo_name, scheme='http'):
146 extras['git_update_server_info'] = utils2.str2bool(
146 extras['git_update_server_info'] = utils2.str2bool(
147 rhodecode.CONFIG.get('git_update_server_info'))
147 rhodecode.CONFIG.get('git_update_server_info'))
148
148
@@ -152,4 +152,5 b' class SimpleGit(simplevcs.SimpleVCS):'
152 extras['git_lfs_enabled'] = utils2.str2bool(
152 extras['git_lfs_enabled'] = utils2.str2bool(
153 config.get('vcs_git_lfs', 'enabled'))
153 config.get('vcs_git_lfs', 'enabled'))
154 extras['git_lfs_store_path'] = custom_store or default_lfs_store()
154 extras['git_lfs_store_path'] = custom_store or default_lfs_store()
155 extras['git_lfs_http_scheme'] = scheme
155 return extras
156 return extras
@@ -153,7 +153,7 b' class SimpleHg(simplevcs.SimpleVCS):'
153 def _create_wsgi_app(self, repo_path, repo_name, config):
153 def _create_wsgi_app(self, repo_path, repo_name, config):
154 return self.scm_app.create_hg_wsgi_app(repo_path, repo_name, config)
154 return self.scm_app.create_hg_wsgi_app(repo_path, repo_name, config)
155
155
156 def _create_config(self, extras, repo_name):
156 def _create_config(self, extras, repo_name, scheme='http'):
157 config = utils.make_db_config(repo=repo_name)
157 config = utils.make_db_config(repo=repo_name)
158 config.set('rhodecode', 'RC_SCM_DATA', json.dumps(extras))
158 config.set('rhodecode', 'RC_SCM_DATA', json.dumps(extras))
159
159
@@ -87,20 +87,22 b' class SimpleSvnApp(object):'
87 stream = True
87 stream = True
88
88
89 stream = stream
89 stream = stream
90 log.debug(
90 log.debug('Calling SVN PROXY at `%s`, using method:%s. Stream: %s',
91 'Calling SVN PROXY: method:%s via `%s`, Stream: %s',
91 path_info, req_method, stream)
92 req_method, path_info, stream)
92 try:
93 response = requests.request(
93 response = requests.request(
94 req_method, path_info,
94 req_method, path_info,
95 data=data, headers=request_headers, stream=stream)
95 data=data, headers=request_headers, stream=stream)
96 except requests.ConnectionError:
97 log.exception('ConnectionError occurred for endpoint %s', path_info)
98 raise
96
99
97 if response.status_code not in [200, 401]:
100 if response.status_code not in [200, 401]:
101 text = '\n{}'.format(response.text) if response.text else ''
98 if response.status_code >= 500:
102 if response.status_code >= 500:
99 log.error('Got SVN response:%s with text:\n`%s`',
103 log.error('Got SVN response:%s with text:`%s`', response, text)
100 response, response.text)
101 else:
104 else:
102 log.debug('Got SVN response:%s with text:\n`%s`',
105 log.debug('Got SVN response:%s with text:`%s`', response, text)
103 response, response.text)
104 else:
106 else:
105 log.debug('got response code: %s', response.status_code)
107 log.debug('got response code: %s', response.status_code)
106
108
@@ -217,7 +219,7 b' class SimpleSvn(simplevcs.SimpleVCS):'
217 conf = self.repo_vcs_config
219 conf = self.repo_vcs_config
218 return str2bool(conf.get('vcs_svn_proxy', 'http_requests_enabled'))
220 return str2bool(conf.get('vcs_svn_proxy', 'http_requests_enabled'))
219
221
220 def _create_config(self, extras, repo_name):
222 def _create_config(self, extras, repo_name, scheme='http'):
221 conf = self.repo_vcs_config
223 conf = self.repo_vcs_config
222 server_url = conf.get('vcs_svn_proxy', 'http_server_url')
224 server_url = conf.get('vcs_svn_proxy', 'http_server_url')
223 server_url = server_url or self.DEFAULT_HTTP_SERVER
225 server_url = server_url or self.DEFAULT_HTTP_SERVER
@@ -360,6 +360,13 b' class SimpleVCS(object):'
360
360
361 return perm_result
361 return perm_result
362
362
363 def _get_http_scheme(self, environ):
364 try:
365 return environ['wsgi.url_scheme']
366 except Exception:
367 log.exception('Failed to read http scheme')
368 return 'http'
369
363 def _check_ssl(self, environ, start_response):
370 def _check_ssl(self, environ, start_response):
364 """
371 """
365 Checks the SSL check flag and returns False if SSL is not present
372 Checks the SSL check flag and returns False if SSL is not present
@@ -597,7 +604,9 b' class SimpleVCS(object):'
597 extras, environ, action, txn_id=txn_id)
604 extras, environ, action, txn_id=txn_id)
598 log.debug('HOOKS extras is %s', extras)
605 log.debug('HOOKS extras is %s', extras)
599
606
600 config = self._create_config(extras, self.acl_repo_name)
607 http_scheme = self._get_http_scheme(environ)
608
609 config = self._create_config(extras, self.acl_repo_name, scheme=http_scheme)
601 app = self._create_wsgi_app(repo_path, self.url_repo_name, config)
610 app = self._create_wsgi_app(repo_path, self.url_repo_name, config)
602 with callback_daemon:
611 with callback_daemon:
603 app.rc_extras = extras
612 app.rc_extras = extras
@@ -643,7 +652,7 b' class SimpleVCS(object):'
643 """Return the WSGI app that will finally handle the request."""
652 """Return the WSGI app that will finally handle the request."""
644 raise NotImplementedError()
653 raise NotImplementedError()
645
654
646 def _create_config(self, extras, repo_name):
655 def _create_config(self, extras, repo_name, scheme='http'):
647 """Create a safe config representation."""
656 """Create a safe config representation."""
648 raise NotImplementedError()
657 raise NotImplementedError()
649
658
@@ -23,6 +23,7 b' import re'
23 import time
23 import time
24 import datetime
24 import datetime
25 import dateutil
25 import dateutil
26 import pickle
26
27
27 from rhodecode.model.db import DbSession, Session
28 from rhodecode.model.db import DbSession, Session
28
29
@@ -142,7 +143,6 b' class FileAuthSessions(BaseAuthSessions)'
142 return stats['callbacks']
143 return stats['callbacks']
143
144
144
145
145
146 class MemcachedAuthSessions(BaseAuthSessions):
146 class MemcachedAuthSessions(BaseAuthSessions):
147 SESSION_TYPE = 'ext:memcached'
147 SESSION_TYPE = 'ext:memcached'
148 _key_regex = re.compile(r'ITEM (.*_session) \[(.*); (.*)\]')
148 _key_regex = re.compile(r'ITEM (.*_session) \[(.*); (.*)\]')
@@ -195,6 +195,43 b' class MemcachedAuthSessions(BaseAuthSess'
195 raise CleanupCommand('Cleanup for this session type not yet available')
195 raise CleanupCommand('Cleanup for this session type not yet available')
196
196
197
197
198 class RedisAuthSessions(BaseAuthSessions):
199 SESSION_TYPE = 'ext:redis'
200
201 def _get_client(self):
202 import redis
203 args = {
204 'socket_timeout': 60,
205 'url': self.config.get('beaker.session.url')
206 }
207
208 client = redis.StrictRedis.from_url(**args)
209 return client
210
211 def get_count(self):
212 client = self._get_client()
213 return len(client.keys('beaker_cache:*'))
214
215 def get_expired_count(self, older_than_seconds=None):
216 expiry_date = self._seconds_to_date(older_than_seconds)
217 return self.NOT_AVAILABLE
218
219 def clean_sessions(self, older_than_seconds=None):
220 client = self._get_client()
221 expiry_time = time.time() - older_than_seconds
222 deleted_keys = 0
223 for key in client.keys('beaker_cache:*'):
224 data = client.get(key)
225 if data:
226 json_data = pickle.loads(data)
227 accessed_time = json_data['_accessed_time']
228 if accessed_time < expiry_time:
229 client.delete(key)
230 deleted_keys += 1
231
232 return deleted_keys
233
234
198 class MemoryAuthSessions(BaseAuthSessions):
235 class MemoryAuthSessions(BaseAuthSessions):
199 SESSION_TYPE = 'memory'
236 SESSION_TYPE = 'memory'
200
237
@@ -212,6 +249,7 b' def get_session_handler(session_type):'
212 types = {
249 types = {
213 'file': FileAuthSessions,
250 'file': FileAuthSessions,
214 'ext:memcached': MemcachedAuthSessions,
251 'ext:memcached': MemcachedAuthSessions,
252 'ext:redis': RedisAuthSessions,
215 'ext:database': DbAuthSessions,
253 'ext:database': DbAuthSessions,
216 'memory': MemoryAuthSessions
254 'memory': MemoryAuthSessions
217 }
255 }
@@ -371,7 +371,8 b' def config_data_from_db(clear_session=Tr'
371 config.append((
371 config.append((
372 safe_str(setting.section), safe_str(setting.key), False))
372 safe_str(setting.section), safe_str(setting.key), False))
373 log.debug(
373 log.debug(
374 'settings ui from db: %s',
374 'settings ui from db@repo[%s]: %s',
375 repo,
375 ','.join(map(lambda s: '[{}] {}={}'.format(*s), ui_data)))
376 ','.join(map(lambda s: '[{}] {}={}'.format(*s), ui_data)))
376 if clear_session:
377 if clear_session:
377 meta.Session.remove()
378 meta.Session.remove()
@@ -33,6 +33,8 b' import collections'
33 import warnings
33 import warnings
34
34
35 from zope.cachedescriptors.property import Lazy as LazyProperty
35 from zope.cachedescriptors.property import Lazy as LazyProperty
36 from zope.cachedescriptors.property import CachedProperty
37
36 from pyramid import compat
38 from pyramid import compat
37
39
38 from rhodecode.translation import lazy_ugettext
40 from rhodecode.translation import lazy_ugettext
@@ -53,6 +55,7 b' log = logging.getLogger(__name__)'
53
55
54 FILEMODE_DEFAULT = 0o100644
56 FILEMODE_DEFAULT = 0o100644
55 FILEMODE_EXECUTABLE = 0o100755
57 FILEMODE_EXECUTABLE = 0o100755
58 EMPTY_COMMIT_ID = '0' * 40
56
59
57 Reference = collections.namedtuple('Reference', ('type', 'name', 'commit_id'))
60 Reference = collections.namedtuple('Reference', ('type', 'name', 'commit_id'))
58
61
@@ -161,7 +164,7 b' class MergeResponse(object):'
161 u'This pull request cannot be merged because the source contains '
164 u'This pull request cannot be merged because the source contains '
162 u'more branches than the target.'),
165 u'more branches than the target.'),
163 MergeFailureReason.HG_TARGET_HAS_MULTIPLE_HEADS: lazy_ugettext(
166 MergeFailureReason.HG_TARGET_HAS_MULTIPLE_HEADS: lazy_ugettext(
164 u'This pull request cannot be merged because the target '
167 u'This pull request cannot be merged because the target `{target_ref.name}` '
165 u'has multiple heads: `{heads}`.'),
168 u'has multiple heads: `{heads}`.'),
166 MergeFailureReason.TARGET_IS_LOCKED: lazy_ugettext(
169 MergeFailureReason.TARGET_IS_LOCKED: lazy_ugettext(
167 u'This pull request cannot be merged because the target repository is '
170 u'This pull request cannot be merged because the target repository is '
@@ -261,6 +264,7 b' class BaseRepository(object):'
261 EMPTY_COMMIT_ID = '0' * 40
264 EMPTY_COMMIT_ID = '0' * 40
262
265
263 path = None
266 path = None
267 _commit_ids_ver = 0
264
268
265 def __init__(self, repo_path, config=None, create=False, **kwargs):
269 def __init__(self, repo_path, config=None, create=False, **kwargs):
266 """
270 """
@@ -309,6 +313,9 b' class BaseRepository(object):'
309 def _remote(self):
313 def _remote(self):
310 raise NotImplementedError
314 raise NotImplementedError
311
315
316 def _heads(self, branch=None):
317 return []
318
312 @LazyProperty
319 @LazyProperty
313 def EMPTY_COMMIT(self):
320 def EMPTY_COMMIT(self):
314 return EmptyCommit(self.EMPTY_COMMIT_ID)
321 return EmptyCommit(self.EMPTY_COMMIT_ID)
@@ -380,7 +387,7 b' class BaseRepository(object):'
380 return commit.size
387 return commit.size
381
388
382 def is_empty(self):
389 def is_empty(self):
383 return not bool(self.commit_ids)
390 return self._remote.is_empty()
384
391
385 @staticmethod
392 @staticmethod
386 def check_url(url, config):
393 def check_url(url, config):
@@ -401,6 +408,15 b' class BaseRepository(object):'
401 # COMMITS
408 # COMMITS
402 # ==========================================================================
409 # ==========================================================================
403
410
411 @CachedProperty('_commit_ids_ver')
412 def commit_ids(self):
413 raise NotImplementedError
414
415 def append_commit_id(self, commit_id):
416 if commit_id not in self.commit_ids:
417 self._rebuild_cache(self.commit_ids + [commit_id])
418 self._commit_ids_ver = time.time()
419
404 def get_commit(self, commit_id=None, commit_idx=None, pre_load=None, translate_tag=None):
420 def get_commit(self, commit_id=None, commit_idx=None, pre_load=None, translate_tag=None):
405 """
421 """
406 Returns instance of `BaseCommit` class. If `commit_id` and `commit_idx`
422 Returns instance of `BaseCommit` class. If `commit_id` and `commit_idx`
@@ -1091,12 +1107,12 b' class BaseCommit(object):'
1091 """
1107 """
1092 return None
1108 return None
1093
1109
1094 def archive_repo(self, file_path, kind='tgz', subrepos=None,
1110 def archive_repo(self, archive_dest_path, kind='tgz', subrepos=None,
1095 prefix=None, write_metadata=False, mtime=None):
1111 prefix=None, write_metadata=False, mtime=None, archive_at_path='/'):
1096 """
1112 """
1097 Creates an archive containing the contents of the repository.
1113 Creates an archive containing the contents of the repository.
1098
1114
1099 :param file_path: path to the file which to create the archive.
1115 :param archive_dest_path: path to the file which to create the archive.
1100 :param kind: one of following: ``"tbz2"``, ``"tgz"``, ``"zip"``.
1116 :param kind: one of following: ``"tbz2"``, ``"tgz"``, ``"zip"``.
1101 :param prefix: name of root directory in archive.
1117 :param prefix: name of root directory in archive.
1102 Default is repository name and commit's short_id joined with dash:
1118 Default is repository name and commit's short_id joined with dash:
@@ -1104,10 +1120,11 b' class BaseCommit(object):'
1104 :param write_metadata: write a metadata file into archive.
1120 :param write_metadata: write a metadata file into archive.
1105 :param mtime: custom modification time for archive creation, defaults
1121 :param mtime: custom modification time for archive creation, defaults
1106 to time.time() if not given.
1122 to time.time() if not given.
1123 :param archive_at_path: pack files at this path (default '/')
1107
1124
1108 :raise VCSError: If prefix has a problem.
1125 :raise VCSError: If prefix has a problem.
1109 """
1126 """
1110 allowed_kinds = settings.ARCHIVE_SPECS.keys()
1127 allowed_kinds = [x[0] for x in settings.ARCHIVE_SPECS]
1111 if kind not in allowed_kinds:
1128 if kind not in allowed_kinds:
1112 raise ImproperArchiveTypeError(
1129 raise ImproperArchiveTypeError(
1113 'Archive kind (%s) not supported use one of %s' %
1130 'Archive kind (%s) not supported use one of %s' %
@@ -1115,11 +1132,11 b' class BaseCommit(object):'
1115
1132
1116 prefix = self._validate_archive_prefix(prefix)
1133 prefix = self._validate_archive_prefix(prefix)
1117
1134
1118 mtime = mtime or time.mktime(self.date.timetuple())
1135 mtime = mtime is not None or time.mktime(self.date.timetuple())
1119
1136
1120 file_info = []
1137 file_info = []
1121 cur_rev = self.repository.get_commit(commit_id=self.raw_id)
1138 cur_rev = self.repository.get_commit(commit_id=self.raw_id)
1122 for _r, _d, files in cur_rev.walk('/'):
1139 for _r, _d, files in cur_rev.walk(archive_at_path):
1123 for f in files:
1140 for f in files:
1124 f_path = os.path.join(prefix, f.path)
1141 f_path = os.path.join(prefix, f.path)
1125 file_info.append(
1142 file_info.append(
@@ -1128,15 +1145,15 b' class BaseCommit(object):'
1128 if write_metadata:
1145 if write_metadata:
1129 metadata = [
1146 metadata = [
1130 ('repo_name', self.repository.name),
1147 ('repo_name', self.repository.name),
1131 ('rev', self.raw_id),
1148 ('commit_id', self.raw_id),
1132 ('create_time', mtime),
1149 ('mtime', mtime),
1133 ('branch', self.branch),
1150 ('branch', self.branch),
1134 ('tags', ','.join(self.tags)),
1151 ('tags', ','.join(self.tags)),
1135 ]
1152 ]
1136 meta = ["%s:%s" % (f_name, value) for f_name, value in metadata]
1153 meta = ["%s:%s" % (f_name, value) for f_name, value in metadata]
1137 file_info.append(('.archival.txt', 0o644, False, '\n'.join(meta)))
1154 file_info.append(('.archival.txt', 0o644, False, '\n'.join(meta)))
1138
1155
1139 connection.Hg.archive_repo(file_path, mtime, file_info, kind)
1156 connection.Hg.archive_repo(archive_dest_path, mtime, file_info, kind)
1140
1157
1141 def _validate_archive_prefix(self, prefix):
1158 def _validate_archive_prefix(self, prefix):
1142 if prefix is None:
1159 if prefix is None:
@@ -1505,9 +1522,7 b' class BaseInMemoryCommit(object):'
1505 "Cannot remove node at %s from "
1522 "Cannot remove node at %s from "
1506 "following parents: %s" % (not_removed, parents))
1523 "following parents: %s" % (not_removed, parents))
1507
1524
1508 def commit(
1525 def commit(self, message, author, parents=None, branch=None, date=None, **kwargs):
1509 self, message, author, parents=None, branch=None, date=None,
1510 **kwargs):
1511 """
1526 """
1512 Performs in-memory commit (doesn't check workdir in any way) and
1527 Performs in-memory commit (doesn't check workdir in any way) and
1513 returns newly created :class:`BaseCommit`. Updates repository's
1528 returns newly created :class:`BaseCommit`. Updates repository's
@@ -1555,7 +1570,7 b' class EmptyCommit(BaseCommit):'
1555 """
1570 """
1556
1571
1557 def __init__(
1572 def __init__(
1558 self, commit_id='0' * 40, repo=None, alias=None, idx=-1,
1573 self, commit_id=EMPTY_COMMIT_ID, repo=None, alias=None, idx=-1,
1559 message='', author='', date=None):
1574 message='', author='', date=None):
1560 self._empty_commit_id = commit_id
1575 self._empty_commit_id = commit_id
1561 # TODO: johbo: Solve idx parameter, default value does not make
1576 # TODO: johbo: Solve idx parameter, default value does not make
@@ -1615,7 +1630,7 b' class EmptyChangeset(EmptyCommit):'
1615 "Use EmptyCommit instead of EmptyChangeset", DeprecationWarning)
1630 "Use EmptyCommit instead of EmptyChangeset", DeprecationWarning)
1616 return super(EmptyCommit, cls).__new__(cls, *args, **kwargs)
1631 return super(EmptyCommit, cls).__new__(cls, *args, **kwargs)
1617
1632
1618 def __init__(self, cs='0' * 40, repo=None, requested_revision=None,
1633 def __init__(self, cs=EMPTY_COMMIT_ID, repo=None, requested_revision=None,
1619 alias=None, revision=-1, message='', author='', date=None):
1634 alias=None, revision=-1, message='', author='', date=None):
1620 if requested_revision is not None:
1635 if requested_revision is not None:
1621 warnings.warn(
1636 warnings.warn(
@@ -234,8 +234,7 b' class GitCommit(base.BaseCommit):'
234 path = self._fix_path(path)
234 path = self._fix_path(path)
235 if self._get_kind(path) != NodeKind.FILE:
235 if self._get_kind(path) != NodeKind.FILE:
236 raise CommitError(
236 raise CommitError(
237 "File does not exist for commit %s at '%s'" %
237 "File does not exist for commit %s at '%s'" % (self.raw_id, path))
238 (self.raw_id, path))
239 return path
238 return path
240
239
241 def _get_file_nodes(self):
240 def _get_file_nodes(self):
@@ -353,8 +352,7 b' class GitCommit(base.BaseCommit):'
353 def get_nodes(self, path):
352 def get_nodes(self, path):
354 if self._get_kind(path) != NodeKind.DIR:
353 if self._get_kind(path) != NodeKind.DIR:
355 raise CommitError(
354 raise CommitError(
356 "Directory does not exist for commit %s at "
355 "Directory does not exist for commit %s at '%s'" % (self.raw_id, path))
357 " '%s'" % (self.raw_id, path))
358 path = self._fix_path(path)
356 path = self._fix_path(path)
359 id_, _ = self._get_id_for_path(path)
357 id_, _ = self._get_id_for_path(path)
360 tree_id = self._remote[id_]['id']
358 tree_id = self._remote[id_]['id']
@@ -29,8 +29,7 b' from rhodecode.lib.vcs.backends import b'
29
29
30 class GitInMemoryCommit(base.BaseInMemoryCommit):
30 class GitInMemoryCommit(base.BaseInMemoryCommit):
31
31
32 def commit(self, message, author, parents=None, branch=None, date=None,
32 def commit(self, message, author, parents=None, branch=None, date=None, **kwargs):
33 **kwargs):
34 """
33 """
35 Performs in-memory commit (doesn't check workdir in any way) and
34 Performs in-memory commit (doesn't check workdir in any way) and
36 returns newly created `GitCommit`. Updates repository's
35 returns newly created `GitCommit`. Updates repository's
@@ -94,12 +93,12 b' class GitInMemoryCommit(base.BaseInMemor'
94 commit_data, branch, commit_tree, updated, removed)
93 commit_data, branch, commit_tree, updated, removed)
95
94
96 # Update vcs repository object
95 # Update vcs repository object
97 self.repository.commit_ids.append(commit_id)
96 self.repository.append_commit_id(commit_id)
98 self.repository._rebuild_cache(self.repository.commit_ids)
99
97
100 # invalidate parsed refs after commit
98 # invalidate parsed refs after commit
101 self.repository._refs = self.repository._get_refs()
99 self.repository._refs = self.repository._get_refs()
102 self.repository.branches = self.repository._get_branches()
100 self.repository.branches = self.repository._get_branches()
103 tip = self.repository.get_commit()
101 tip = self.repository.get_commit(commit_id)
102
104 self.reset()
103 self.reset()
105 return tip
104 return tip
@@ -25,8 +25,10 b' GIT repository module'
25 import logging
25 import logging
26 import os
26 import os
27 import re
27 import re
28 import time
28
29
29 from zope.cachedescriptors.property import Lazy as LazyProperty
30 from zope.cachedescriptors.property import Lazy as LazyProperty
31 from zope.cachedescriptors.property import CachedProperty
30
32
31 from rhodecode.lib.compat import OrderedDict
33 from rhodecode.lib.compat import OrderedDict
32 from rhodecode.lib.datelib import (
34 from rhodecode.lib.datelib import (
@@ -69,6 +71,9 b' class GitRepository(BaseRepository):'
69 # caches
71 # caches
70 self._commit_ids = {}
72 self._commit_ids = {}
71
73
74 # dependent that trigger re-computation of commit_ids
75 self._commit_ids_ver = 0
76
72 @LazyProperty
77 @LazyProperty
73 def _remote(self):
78 def _remote(self):
74 return connection.Git(self.path, self.config, with_wire=self.with_wire)
79 return connection.Git(self.path, self.config, with_wire=self.with_wire)
@@ -81,7 +86,7 b' class GitRepository(BaseRepository):'
81 def head(self):
86 def head(self):
82 return self._remote.head()
87 return self._remote.head()
83
88
84 @LazyProperty
89 @CachedProperty('_commit_ids_ver')
85 def commit_ids(self):
90 def commit_ids(self):
86 """
91 """
87 Returns list of commit ids, in ascending order. Being lazy
92 Returns list of commit ids, in ascending order. Being lazy
@@ -222,13 +227,10 b' class GitRepository(BaseRepository):'
222 return []
227 return []
223 return output.splitlines()
228 return output.splitlines()
224
229
225 def _get_commit_id(self, commit_id_or_idx):
230 def _lookup_commit(self, commit_id_or_idx, translate_tag=True):
226 def is_null(value):
231 def is_null(value):
227 return len(value) == commit_id_or_idx.count('0')
232 return len(value) == commit_id_or_idx.count('0')
228
233
229 if self.is_empty():
230 raise EmptyRepositoryError("There are no commits yet")
231
232 if commit_id_or_idx in (None, '', 'tip', 'HEAD', 'head', -1):
234 if commit_id_or_idx in (None, '', 'tip', 'HEAD', 'head', -1):
233 return self.commit_ids[-1]
235 return self.commit_ids[-1]
234
236
@@ -238,8 +240,7 b' class GitRepository(BaseRepository):'
238 try:
240 try:
239 commit_id_or_idx = self.commit_ids[int(commit_id_or_idx)]
241 commit_id_or_idx = self.commit_ids[int(commit_id_or_idx)]
240 except Exception:
242 except Exception:
241 msg = "Commit %s does not exist for %s" % (
243 msg = "Commit {} does not exist for `{}`".format(commit_id_or_idx, self.name)
242 commit_id_or_idx, self)
243 raise CommitDoesNotExistError(msg)
244 raise CommitDoesNotExistError(msg)
244
245
245 elif is_bstr:
246 elif is_bstr:
@@ -261,8 +262,7 b' class GitRepository(BaseRepository):'
261
262
262 if (not SHA_PATTERN.match(commit_id_or_idx) or
263 if (not SHA_PATTERN.match(commit_id_or_idx) or
263 commit_id_or_idx not in self.commit_ids):
264 commit_id_or_idx not in self.commit_ids):
264 msg = "Commit %s does not exist for %s" % (
265 msg = "Commit {} does not exist for `{}`".format(commit_id_or_idx, self.name)
265 commit_id_or_idx, self)
266 raise CommitDoesNotExistError(msg)
266 raise CommitDoesNotExistError(msg)
267
267
268 # Ensure we return full id
268 # Ensure we return full id
@@ -431,19 +431,42 b' class GitRepository(BaseRepository):'
431 Returns `GitCommit` object representing commit from git repository
431 Returns `GitCommit` object representing commit from git repository
432 at the given `commit_id` or head (most recent commit) if None given.
432 at the given `commit_id` or head (most recent commit) if None given.
433 """
433 """
434 if self.is_empty():
435 raise EmptyRepositoryError("There are no commits yet")
436
434 if commit_id is not None:
437 if commit_id is not None:
435 self._validate_commit_id(commit_id)
438 self._validate_commit_id(commit_id)
439 try:
440 # we have cached idx, use it without contacting the remote
441 idx = self._commit_ids[commit_id]
442 return GitCommit(self, commit_id, idx, pre_load=pre_load)
443 except KeyError:
444 pass
445
436 elif commit_idx is not None:
446 elif commit_idx is not None:
437 self._validate_commit_idx(commit_idx)
447 self._validate_commit_idx(commit_idx)
438 commit_id = commit_idx
448 try:
439 commit_id = self._get_commit_id(commit_id)
449 _commit_id = self.commit_ids[commit_idx]
450 if commit_idx < 0:
451 commit_idx = self.commit_ids.index(_commit_id)
452 return GitCommit(self, _commit_id, commit_idx, pre_load=pre_load)
453 except IndexError:
454 commit_id = commit_idx
455 else:
456 commit_id = "tip"
457
458 commit_id = self._lookup_commit(commit_id)
459 remote_idx = None
460 if translate_tag:
461 # Need to call remote to translate id for tagging scenario
462 remote_data = self._remote.get_object(commit_id)
463 commit_id = remote_data["commit_id"]
464 remote_idx = remote_data["idx"]
465
440 try:
466 try:
441 if translate_tag:
442 # Need to call remote to translate id for tagging scenario
443 commit_id = self._remote.get_object(commit_id)["commit_id"]
444 idx = self._commit_ids[commit_id]
467 idx = self._commit_ids[commit_id]
445 except KeyError:
468 except KeyError:
446 raise RepositoryError("Cannot get object with id %s" % commit_id)
469 idx = remote_idx or 0
447
470
448 return GitCommit(self, commit_id, idx, pre_load=pre_load)
471 return GitCommit(self, commit_id, idx, pre_load=pre_load)
449
472
@@ -472,6 +495,7 b' class GitRepository(BaseRepository):'
472 """
495 """
473 if self.is_empty():
496 if self.is_empty():
474 raise EmptyRepositoryError("There are no commits yet")
497 raise EmptyRepositoryError("There are no commits yet")
498
475 self._validate_branch_name(branch_name)
499 self._validate_branch_name(branch_name)
476
500
477 if start_id is not None:
501 if start_id is not None:
@@ -479,9 +503,9 b' class GitRepository(BaseRepository):'
479 if end_id is not None:
503 if end_id is not None:
480 self._validate_commit_id(end_id)
504 self._validate_commit_id(end_id)
481
505
482 start_raw_id = self._get_commit_id(start_id)
506 start_raw_id = self._lookup_commit(start_id)
483 start_pos = self._commit_ids[start_raw_id] if start_id else None
507 start_pos = self._commit_ids[start_raw_id] if start_id else None
484 end_raw_id = self._get_commit_id(end_id)
508 end_raw_id = self._lookup_commit(end_id)
485 end_pos = max(0, self._commit_ids[end_raw_id]) if end_id else None
509 end_pos = max(0, self._commit_ids[end_raw_id]) if end_id else None
486
510
487 if None not in [start_id, end_id] and start_pos > end_pos:
511 if None not in [start_id, end_id] and start_pos > end_pos:
@@ -589,8 +613,9 b' class GitRepository(BaseRepository):'
589 commit = commit.parents[0]
613 commit = commit.parents[0]
590 self._remote.set_refs('refs/heads/%s' % branch_name, commit.raw_id)
614 self._remote.set_refs('refs/heads/%s' % branch_name, commit.raw_id)
591
615
592 self.commit_ids = self._get_all_commit_ids()
616 self._commit_ids_ver = time.time()
593 self._rebuild_cache(self.commit_ids)
617 # we updated _commit_ids_ver so accessing self.commit_ids will re-compute it
618 return len(self.commit_ids)
594
619
595 def get_common_ancestor(self, commit_id1, commit_id2, repo2):
620 def get_common_ancestor(self, commit_id1, commit_id2, repo2):
596 if commit_id1 == commit_id2:
621 if commit_id1 == commit_id2:
@@ -193,13 +193,6 b' class MercurialCommit(base.BaseCommit):'
193 children = self._remote.ctx_children(self.idx)
193 children = self._remote.ctx_children(self.idx)
194 return self._make_commits(children)
194 return self._make_commits(children)
195
195
196 def diff(self, ignore_whitespace=True, context=3):
197 result = self._remote.ctx_diff(
198 self.idx,
199 git=True, ignore_whitespace=ignore_whitespace, context=context)
200 diff = ''.join(result)
201 return MercurialDiff(diff)
202
203 def _fix_path(self, path):
196 def _fix_path(self, path):
204 """
197 """
205 Mercurial keeps filenodes as str so we need to encode from unicode
198 Mercurial keeps filenodes as str so we need to encode from unicode
@@ -30,8 +30,7 b' from rhodecode.lib.vcs.exceptions import'
30
30
31 class MercurialInMemoryCommit(BaseInMemoryCommit):
31 class MercurialInMemoryCommit(BaseInMemoryCommit):
32
32
33 def commit(self, message, author, parents=None, branch=None, date=None,
33 def commit(self, message, author, parents=None, branch=None, date=None, **kwargs):
34 **kwargs):
35 """
34 """
36 Performs in-memory commit (doesn't check workdir in any way) and
35 Performs in-memory commit (doesn't check workdir in any way) and
37 returns newly created `MercurialCommit`. Updates repository's
36 returns newly created `MercurialCommit`. Updates repository's
@@ -83,15 +82,14 b' class MercurialInMemoryCommit(BaseInMemo'
83
82
84 date, tz = date_to_timestamp_plus_offset(date)
83 date, tz = date_to_timestamp_plus_offset(date)
85
84
86 new_id = self.repository._remote.commitctx(
85 commit_id = self.repository._remote.commitctx(
87 message=message, parents=parent_ids,
86 message=message, parents=parent_ids,
88 commit_time=date, commit_timezone=tz, user=author,
87 commit_time=date, commit_timezone=tz, user=author,
89 files=self.get_paths(), extra=kwargs, removed=removed,
88 files=self.get_paths(), extra=kwargs, removed=removed,
90 updated=updated)
89 updated=updated)
90 self.repository.append_commit_id(commit_id)
91
91
92 self.repository.commit_ids.append(new_id)
93 self.repository._rebuild_cache(self.repository.commit_ids)
94 self.repository.branches = self.repository._get_branches()
92 self.repository.branches = self.repository._get_branches()
95 tip = self.repository.get_commit()
93 tip = self.repository.get_commit(commit_id)
96 self.reset()
94 self.reset()
97 return tip
95 return tip
@@ -24,9 +24,11 b' HG repository module'
24 import os
24 import os
25 import logging
25 import logging
26 import binascii
26 import binascii
27 import time
27 import urllib
28 import urllib
28
29
29 from zope.cachedescriptors.property import Lazy as LazyProperty
30 from zope.cachedescriptors.property import Lazy as LazyProperty
31 from zope.cachedescriptors.property import CachedProperty
30
32
31 from rhodecode.lib.compat import OrderedDict
33 from rhodecode.lib.compat import OrderedDict
32 from rhodecode.lib.datelib import (
34 from rhodecode.lib.datelib import (
@@ -85,11 +87,14 b' class MercurialRepository(BaseRepository'
85 # caches
87 # caches
86 self._commit_ids = {}
88 self._commit_ids = {}
87
89
90 # dependent that trigger re-computation of commit_ids
91 self._commit_ids_ver = 0
92
88 @LazyProperty
93 @LazyProperty
89 def _remote(self):
94 def _remote(self):
90 return connection.Hg(self.path, self.config, with_wire=self.with_wire)
95 return connection.Hg(self.path, self.config, with_wire=self.with_wire)
91
96
92 @LazyProperty
97 @CachedProperty('_commit_ids_ver')
93 def commit_ids(self):
98 def commit_ids(self):
94 """
99 """
95 Returns list of commit ids, in ascending order. Being lazy
100 Returns list of commit ids, in ascending order. Being lazy
@@ -157,8 +162,7 b' class MercurialRepository(BaseRepository'
157
162
158 return OrderedDict(sorted(_tags, key=get_name, reverse=True))
163 return OrderedDict(sorted(_tags, key=get_name, reverse=True))
159
164
160 def tag(self, name, user, commit_id=None, message=None, date=None,
165 def tag(self, name, user, commit_id=None, message=None, date=None, **kwargs):
161 **kwargs):
162 """
166 """
163 Creates and returns a tag for the given ``commit_id``.
167 Creates and returns a tag for the given ``commit_id``.
164
168
@@ -172,6 +176,7 b' class MercurialRepository(BaseRepository'
172 """
176 """
173 if name in self.tags:
177 if name in self.tags:
174 raise TagAlreadyExistError("Tag %s already exists" % name)
178 raise TagAlreadyExistError("Tag %s already exists" % name)
179
175 commit = self.get_commit(commit_id=commit_id)
180 commit = self.get_commit(commit_id=commit_id)
176 local = kwargs.setdefault('local', False)
181 local = kwargs.setdefault('local', False)
177
182
@@ -180,8 +185,7 b' class MercurialRepository(BaseRepository'
180
185
181 date, tz = date_to_timestamp_plus_offset(date)
186 date, tz = date_to_timestamp_plus_offset(date)
182
187
183 self._remote.tag(
188 self._remote.tag(name, commit.raw_id, message, local, user, date, tz)
184 name, commit.raw_id, message, local, user, date, tz)
185 self._remote.invalidate_vcs_cache()
189 self._remote.invalidate_vcs_cache()
186
190
187 # Reinitialize tags
191 # Reinitialize tags
@@ -203,6 +207,7 b' class MercurialRepository(BaseRepository'
203 """
207 """
204 if name not in self.tags:
208 if name not in self.tags:
205 raise TagDoesNotExistError("Tag %s does not exist" % name)
209 raise TagDoesNotExistError("Tag %s does not exist" % name)
210
206 if message is None:
211 if message is None:
207 message = "Removed tag %s" % name
212 message = "Removed tag %s" % name
208 local = False
213 local = False
@@ -271,8 +276,9 b' class MercurialRepository(BaseRepository'
271 self._remote.strip(commit_id, update=False, backup="none")
276 self._remote.strip(commit_id, update=False, backup="none")
272
277
273 self._remote.invalidate_vcs_cache()
278 self._remote.invalidate_vcs_cache()
274 self.commit_ids = self._get_all_commit_ids()
279 self._commit_ids_ver = time.time()
275 self._rebuild_cache(self.commit_ids)
280 # we updated _commit_ids_ver so accessing self.commit_ids will re-compute it
281 return len(self.commit_ids)
276
282
277 def verify(self):
283 def verify(self):
278 verify = self._remote.verify()
284 verify = self._remote.verify()
@@ -425,18 +431,20 b' class MercurialRepository(BaseRepository'
425 if commit_id is not None:
431 if commit_id is not None:
426 self._validate_commit_id(commit_id)
432 self._validate_commit_id(commit_id)
427 try:
433 try:
434 # we have cached idx, use it without contacting the remote
428 idx = self._commit_ids[commit_id]
435 idx = self._commit_ids[commit_id]
429 return MercurialCommit(self, commit_id, idx, pre_load=pre_load)
436 return MercurialCommit(self, commit_id, idx, pre_load=pre_load)
430 except KeyError:
437 except KeyError:
431 pass
438 pass
439
432 elif commit_idx is not None:
440 elif commit_idx is not None:
433 self._validate_commit_idx(commit_idx)
441 self._validate_commit_idx(commit_idx)
434 try:
442 try:
435 id_ = self.commit_ids[commit_idx]
443 _commit_id = self.commit_ids[commit_idx]
436 if commit_idx < 0:
444 if commit_idx < 0:
437 commit_idx += len(self.commit_ids)
445 commit_idx = self.commit_ids.index(_commit_id)
438 return MercurialCommit(
446
439 self, id_, commit_idx, pre_load=pre_load)
447 return MercurialCommit(self, _commit_id, commit_idx, pre_load=pre_load)
440 except IndexError:
448 except IndexError:
441 commit_id = commit_idx
449 commit_id = commit_idx
442 else:
450 else:
@@ -448,8 +456,8 b' class MercurialRepository(BaseRepository'
448 try:
456 try:
449 raw_id, idx = self._remote.lookup(commit_id, both=True)
457 raw_id, idx = self._remote.lookup(commit_id, both=True)
450 except CommitDoesNotExistError:
458 except CommitDoesNotExistError:
451 msg = "Commit %s does not exist for %s" % (
459 msg = "Commit {} does not exist for `{}`".format(
452 commit_id, self)
460 *map(safe_str, [commit_id, self.name]))
453 raise CommitDoesNotExistError(msg)
461 raise CommitDoesNotExistError(msg)
454
462
455 return MercurialCommit(self, raw_id, idx, pre_load=pre_load)
463 return MercurialCommit(self, raw_id, idx, pre_load=pre_load)
@@ -477,11 +485,11 b' class MercurialRepository(BaseRepository'
477 ``end`` could not be found.
485 ``end`` could not be found.
478 """
486 """
479 # actually we should check now if it's not an empty repo
487 # actually we should check now if it's not an empty repo
480 branch_ancestors = False
481 if self.is_empty():
488 if self.is_empty():
482 raise EmptyRepositoryError("There are no commits yet")
489 raise EmptyRepositoryError("There are no commits yet")
483 self._validate_branch_name(branch_name)
490 self._validate_branch_name(branch_name)
484
491
492 branch_ancestors = False
485 if start_id is not None:
493 if start_id is not None:
486 self._validate_commit_id(start_id)
494 self._validate_commit_id(start_id)
487 c_start = self.get_commit(commit_id=start_id)
495 c_start = self.get_commit(commit_id=start_id)
@@ -715,11 +723,16 b' class MercurialRepository(BaseRepository'
715
723
716 try:
724 try:
717 if target_ref.type == 'branch' and len(self._heads(target_ref.name)) != 1:
725 if target_ref.type == 'branch' and len(self._heads(target_ref.name)) != 1:
718 heads = ','.join(self._heads(target_ref.name))
726 heads = '\n,'.join(self._heads(target_ref.name))
727 metadata = {
728 'target_ref': target_ref,
729 'source_ref': source_ref,
730 'heads': heads
731 }
719 return MergeResponse(
732 return MergeResponse(
720 False, False, None,
733 False, False, None,
721 MergeFailureReason.HG_TARGET_HAS_MULTIPLE_HEADS,
734 MergeFailureReason.HG_TARGET_HAS_MULTIPLE_HEADS,
722 metadata={'heads': heads})
735 metadata=metadata)
723 except CommitDoesNotExistError:
736 except CommitDoesNotExistError:
724 log.exception('Failure when looking up branch heads on hg target')
737 log.exception('Failure when looking up branch heads on hg target')
725 return MergeResponse(
738 return MergeResponse(
@@ -892,11 +905,15 b' class MercurialRepository(BaseRepository'
892
905
893 def read_patterns(suffix):
906 def read_patterns(suffix):
894 svalue = None
907 svalue = None
895 try:
908 for section, option in [
896 svalue = hgacl.get('narrowhgacl', username + suffix)
909 ('narrowacl', username + suffix),
897 except configparser.NoOptionError:
910 ('narrowacl', 'default' + suffix),
911 ('narrowhgacl', username + suffix),
912 ('narrowhgacl', 'default' + suffix)
913 ]:
898 try:
914 try:
899 svalue = hgacl.get('narrowhgacl', 'default' + suffix)
915 svalue = hgacl.get(section, option)
916 break # stop at the first value we find
900 except configparser.NoOptionError:
917 except configparser.NoOptionError:
901 pass
918 pass
902 if not svalue:
919 if not svalue:
@@ -30,8 +30,7 b' from rhodecode.lib.vcs.backends import b'
30
30
31 class SubversionInMemoryCommit(base.BaseInMemoryCommit):
31 class SubversionInMemoryCommit(base.BaseInMemoryCommit):
32
32
33 def commit(self, message, author, parents=None, branch=None, date=None,
33 def commit(self, message, author, parents=None, branch=None, date=None, **kwargs):
34 **kwargs):
35 if branch not in (None, self.repository.DEFAULT_BRANCH_NAME):
34 if branch not in (None, self.repository.DEFAULT_BRANCH_NAME):
36 raise NotImplementedError("Branches are not yet supported")
35 raise NotImplementedError("Branches are not yet supported")
37
36
@@ -74,8 +73,7 b' class SubversionInMemoryCommit(base.Base'
74 # we should not add the commit_id, if it is already evaluated, it
73 # we should not add the commit_id, if it is already evaluated, it
75 # will not be evaluated again.
74 # will not be evaluated again.
76 commit_id = str(svn_rev)
75 commit_id = str(svn_rev)
77 if commit_id not in self.repository.commit_ids:
76 self.repository.append_commit_id(commit_id)
78 self.repository.commit_ids.append(commit_id)
79 tip = self.repository.get_commit()
77 tip = self.repository.get_commit()
80 self.reset()
78 self.reset()
81 return tip
79 return tip
@@ -27,6 +27,7 b' import os'
27 import urllib
27 import urllib
28
28
29 from zope.cachedescriptors.property import Lazy as LazyProperty
29 from zope.cachedescriptors.property import Lazy as LazyProperty
30 from zope.cachedescriptors.property import CachedProperty
30
31
31 from rhodecode.lib.compat import OrderedDict
32 from rhodecode.lib.compat import OrderedDict
32 from rhodecode.lib.datelib import date_astimestamp
33 from rhodecode.lib.datelib import date_astimestamp
@@ -75,6 +76,9 b' class SubversionRepository(base.BaseRepo'
75
76
76 self._init_repo(create, src_url)
77 self._init_repo(create, src_url)
77
78
79 # dependent that trigger re-computation of commit_ids
80 self._commit_ids_ver = 0
81
78 @LazyProperty
82 @LazyProperty
79 def _remote(self):
83 def _remote(self):
80 return connection.Svn(self.path, self.config)
84 return connection.Svn(self.path, self.config)
@@ -93,11 +97,31 b' class SubversionRepository(base.BaseRepo'
93 else:
97 else:
94 self._check_path()
98 self._check_path()
95
99
96 @LazyProperty
100 @CachedProperty('_commit_ids_ver')
97 def commit_ids(self):
101 def commit_ids(self):
98 head = self._remote.lookup(None)
102 head = self._remote.lookup(None)
99 return [str(r) for r in xrange(1, head + 1)]
103 return [str(r) for r in xrange(1, head + 1)]
100
104
105 def _rebuild_cache(self, commit_ids):
106 pass
107
108 def run_svn_command(self, cmd, **opts):
109 """
110 Runs given ``cmd`` as svn command and returns tuple
111 (stdout, stderr).
112
113 :param cmd: full svn command to be executed
114 :param opts: env options to pass into Subprocess command
115 """
116 if not isinstance(cmd, list):
117 raise ValueError('cmd must be a list, got %s instead' % type(cmd))
118
119 skip_stderr_log = opts.pop('skip_stderr_log', False)
120 out, err = self._remote.run_svn_command(cmd, **opts)
121 if err and not skip_stderr_log:
122 log.debug('Stderr output of svn command "%s":\n%s', cmd, err)
123 return out, err
124
101 @LazyProperty
125 @LazyProperty
102 def branches(self):
126 def branches(self):
103 return self._tags_or_branches('vcs_svn_branch')
127 return self._tags_or_branches('vcs_svn_branch')
@@ -260,7 +284,7 b' class SubversionRepository(base.BaseRepo'
260 try:
284 try:
261 commit_id = self.commit_ids[commit_idx]
285 commit_id = self.commit_ids[commit_idx]
262 except IndexError:
286 except IndexError:
263 raise CommitDoesNotExistError
287 raise CommitDoesNotExistError('No commit with idx: {}'.format(commit_idx))
264
288
265 commit_id = self._sanitize_commit_id(commit_id)
289 commit_id = self._sanitize_commit_id(commit_id)
266 commit = SubversionCommit(repository=self, commit_id=commit_id)
290 commit = SubversionCommit(repository=self, commit_id=commit_id)
@@ -42,12 +42,16 b' BACKENDS = {'
42 'svn': 'rhodecode.lib.vcs.backends.svn.SubversionRepository',
42 'svn': 'rhodecode.lib.vcs.backends.svn.SubversionRepository',
43 }
43 }
44
44
45 # TODO: Remove once controllers/files.py is adjusted
45
46 ARCHIVE_SPECS = {
46 ARCHIVE_SPECS = [
47 'tbz2': ('application/x-bzip2', '.tar.bz2'),
47 ('tbz2', 'application/x-bzip2', 'tbz2'),
48 'tgz': ('application/x-gzip', '.tar.gz'),
48 ('tbz2', 'application/x-bzip2', '.tar.bz2'),
49 'zip': ('application/zip', '.zip'),
49
50 }
50 ('tgz', 'application/x-gzip', '.tgz'),
51 ('tgz', 'application/x-gzip', '.tar.gz'),
52
53 ('zip', 'application/zip', '.zip'),
54 ]
51
55
52 HOOKS_PROTOCOL = None
56 HOOKS_PROTOCOL = None
53 HOOKS_DIRECT_CALLS = False
57 HOOKS_DIRECT_CALLS = False
@@ -101,23 +101,35 b' def parse_datetime(text):'
101 :param text: string of desired date/datetime or something more verbose,
101 :param text: string of desired date/datetime or something more verbose,
102 like *yesterday*, *2weeks 3days*, etc.
102 like *yesterday*, *2weeks 3days*, etc.
103 """
103 """
104 if not text:
105 raise ValueError('Wrong date: "%s"' % text)
104
106
105 text = text.strip().lower()
107 if isinstance(text, datetime.datetime):
108 return text
106
109
107 INPUT_FORMATS = (
110 # we limit a format to no include microseconds e.g 2017-10-17t17:48:23.XXXX
111 text = text.strip().lower()[:19]
112
113 input_formats = (
108 '%Y-%m-%d %H:%M:%S',
114 '%Y-%m-%d %H:%M:%S',
115 '%Y-%m-%dt%H:%M:%S',
109 '%Y-%m-%d %H:%M',
116 '%Y-%m-%d %H:%M',
117 '%Y-%m-%dt%H:%M',
110 '%Y-%m-%d',
118 '%Y-%m-%d',
111 '%m/%d/%Y %H:%M:%S',
119 '%m/%d/%Y %H:%M:%S',
120 '%m/%d/%Yt%H:%M:%S',
112 '%m/%d/%Y %H:%M',
121 '%m/%d/%Y %H:%M',
122 '%m/%d/%Yt%H:%M',
113 '%m/%d/%Y',
123 '%m/%d/%Y',
114 '%m/%d/%y %H:%M:%S',
124 '%m/%d/%y %H:%M:%S',
125 '%m/%d/%yt%H:%M:%S',
115 '%m/%d/%y %H:%M',
126 '%m/%d/%y %H:%M',
127 '%m/%d/%yt%H:%M',
116 '%m/%d/%y',
128 '%m/%d/%y',
117 )
129 )
118 for format in INPUT_FORMATS:
130 for format_def in input_formats:
119 try:
131 try:
120 return datetime.datetime(*time.strptime(text, format)[:6])
132 return datetime.datetime(*time.strptime(text, format_def)[:6])
121 except ValueError:
133 except ValueError:
122 pass
134 pass
123
135
@@ -25,6 +25,7 b' Database Models for RhodeCode Enterprise'
25 import re
25 import re
26 import os
26 import os
27 import time
27 import time
28 import string
28 import hashlib
29 import hashlib
29 import logging
30 import logging
30 import datetime
31 import datetime
@@ -39,7 +40,7 b' from sqlalchemy import ('
39 Index, Sequence, UniqueConstraint, ForeignKey, CheckConstraint, Column,
40 Index, Sequence, UniqueConstraint, ForeignKey, CheckConstraint, Column,
40 Boolean, String, Unicode, UnicodeText, DateTime, Integer, LargeBinary,
41 Boolean, String, Unicode, UnicodeText, DateTime, Integer, LargeBinary,
41 Text, Float, PickleType)
42 Text, Float, PickleType)
42 from sqlalchemy.sql.expression import true, false
43 from sqlalchemy.sql.expression import true, false, case
43 from sqlalchemy.sql.functions import coalesce, count # pragma: no cover
44 from sqlalchemy.sql.functions import coalesce, count # pragma: no cover
44 from sqlalchemy.orm import (
45 from sqlalchemy.orm import (
45 relationship, joinedload, class_mapper, validates, aliased)
46 relationship, joinedload, class_mapper, validates, aliased)
@@ -50,6 +51,7 b' from sqlalchemy.dialects.mysql import LO'
50 from zope.cachedescriptors.property import Lazy as LazyProperty
51 from zope.cachedescriptors.property import Lazy as LazyProperty
51 from pyramid import compat
52 from pyramid import compat
52 from pyramid.threadlocal import get_current_request
53 from pyramid.threadlocal import get_current_request
54 from webhelpers.text import collapse, remove_formatting
53
55
54 from rhodecode.translation import _
56 from rhodecode.translation import _
55 from rhodecode.lib.vcs import get_vcs_instance
57 from rhodecode.lib.vcs import get_vcs_instance
@@ -57,13 +59,13 b' from rhodecode.lib.vcs.backends.base imp'
57 from rhodecode.lib.utils2 import (
59 from rhodecode.lib.utils2 import (
58 str2bool, safe_str, get_commit_safe, safe_unicode, sha1_safe,
60 str2bool, safe_str, get_commit_safe, safe_unicode, sha1_safe,
59 time_to_datetime, aslist, Optional, safe_int, get_clone_url, AttributeDict,
61 time_to_datetime, aslist, Optional, safe_int, get_clone_url, AttributeDict,
60 glob2re, StrictAttributeDict, cleaned_uri)
62 glob2re, StrictAttributeDict, cleaned_uri, datetime_to_time, OrderedDefaultDict)
61 from rhodecode.lib.jsonalchemy import MutationObj, MutationList, JsonType, \
63 from rhodecode.lib.jsonalchemy import MutationObj, MutationList, JsonType, \
62 JsonRaw
64 JsonRaw
63 from rhodecode.lib.ext_json import json
65 from rhodecode.lib.ext_json import json
64 from rhodecode.lib.caching_query import FromCache
66 from rhodecode.lib.caching_query import FromCache
65 from rhodecode.lib.encrypt import AESCipher
67 from rhodecode.lib.encrypt import AESCipher, validate_and_get_enc_data
66
68 from rhodecode.lib.encrypt2 import Encryptor
67 from rhodecode.model.meta import Base, Session
69 from rhodecode.model.meta import Base, Session
68
70
69 URL_SEP = '/'
71 URL_SEP = '/'
@@ -159,44 +161,46 b' class EncryptedTextValue(TypeDecorator):'
159 impl = Text
161 impl = Text
160
162
161 def process_bind_param(self, value, dialect):
163 def process_bind_param(self, value, dialect):
162 if not value:
164 """
163 return value
165 Setter for storing value
164 if value.startswith('enc$aes$') or value.startswith('enc$aes_hmac$'):
166 """
165 # protect against double encrypting if someone manually starts
166 # doing
167 raise ValueError('value needs to be in unencrypted format, ie. '
168 'not starting with enc$aes')
169 return 'enc$aes_hmac$%s' % AESCipher(
170 ENCRYPTION_KEY, hmac=True).encrypt(value)
171
172 def process_result_value(self, value, dialect):
173 import rhodecode
167 import rhodecode
174
175 if not value:
168 if not value:
176 return value
169 return value
177
170
178 parts = value.split('$', 3)
171 # protect against double encrypting if values is already encrypted
179 if not len(parts) == 3:
172 if value.startswith('enc$aes$') \
180 # probably not encrypted values
173 or value.startswith('enc$aes_hmac$') \
181 return value
174 or value.startswith('enc2$'):
175 raise ValueError('value needs to be in unencrypted format, '
176 'ie. not starting with enc$ or enc2$')
177
178 algo = rhodecode.CONFIG.get('rhodecode.encrypted_values.algorithm') or 'aes'
179 if algo == 'aes':
180 return 'enc$aes_hmac$%s' % AESCipher(ENCRYPTION_KEY, hmac=True).encrypt(value)
181 elif algo == 'fernet':
182 return Encryptor(ENCRYPTION_KEY).encrypt(value)
182 else:
183 else:
183 if parts[0] != 'enc':
184 ValueError('Bad encryption algorithm, should be fernet or aes, got: {}'.format(algo))
184 # parts ok but without our header ?
185
185 return value
186 def process_result_value(self, value, dialect):
186 enc_strict_mode = str2bool(rhodecode.CONFIG.get(
187 """
187 'rhodecode.encrypted_values.strict') or True)
188 Getter for retrieving value
188 # at that stage we know it's our encryption
189 """
189 if parts[1] == 'aes':
190
190 decrypted_data = AESCipher(ENCRYPTION_KEY).decrypt(parts[2])
191 import rhodecode
191 elif parts[1] == 'aes_hmac':
192 if not value:
192 decrypted_data = AESCipher(
193 return value
193 ENCRYPTION_KEY, hmac=True,
194
194 strict_verification=enc_strict_mode).decrypt(parts[2])
195 algo = rhodecode.CONFIG.get('rhodecode.encrypted_values.algorithm') or 'aes'
195 else:
196 enc_strict_mode = str2bool(rhodecode.CONFIG.get('rhodecode.encrypted_values.strict') or True)
196 raise ValueError(
197 if algo == 'aes':
197 'Encryption type part is wrong, must be `aes` '
198 decrypted_data = validate_and_get_enc_data(value, ENCRYPTION_KEY, enc_strict_mode)
198 'or `aes_hmac`, got `%s` instead' % (parts[1]))
199 elif algo == 'fernet':
199 return decrypted_data
200 return Encryptor(ENCRYPTION_KEY).decrypt(value)
201 else:
202 ValueError('Bad encryption algorithm, should be fernet or aes, got: {}'.format(algo))
203 return decrypted_data
200
204
201
205
202 class BaseModel(object):
206 class BaseModel(object):
@@ -407,6 +411,15 b' class RhodeCodeUi(Base, BaseModel):'
407 HOOK_PUSH = 'changegroup.push_logger'
411 HOOK_PUSH = 'changegroup.push_logger'
408 HOOK_PUSH_KEY = 'pushkey.key_push'
412 HOOK_PUSH_KEY = 'pushkey.key_push'
409
413
414 HOOKS_BUILTIN = [
415 HOOK_PRE_PULL,
416 HOOK_PULL,
417 HOOK_PRE_PUSH,
418 HOOK_PRETX_PUSH,
419 HOOK_PUSH,
420 HOOK_PUSH_KEY,
421 ]
422
410 # TODO: johbo: Unify way how hooks are configured for git and hg,
423 # TODO: johbo: Unify way how hooks are configured for git and hg,
411 # git part is currently hardcoded.
424 # git part is currently hardcoded.
412
425
@@ -1665,11 +1678,12 b' class Repository(Base, BaseModel):'
1665 cascade="all, delete, delete-orphan")
1678 cascade="all, delete, delete-orphan")
1666 ui = relationship('RepoRhodeCodeUi', cascade="all")
1679 ui = relationship('RepoRhodeCodeUi', cascade="all")
1667 settings = relationship('RepoRhodeCodeSetting', cascade="all")
1680 settings = relationship('RepoRhodeCodeSetting', cascade="all")
1668 integrations = relationship('Integration',
1681 integrations = relationship('Integration', cascade="all, delete, delete-orphan")
1669 cascade="all, delete, delete-orphan")
1670
1682
1671 scoped_tokens = relationship('UserApiKeys', cascade="all")
1683 scoped_tokens = relationship('UserApiKeys', cascade="all")
1672
1684
1685 artifacts = relationship('FileStore', cascade="all")
1686
1673 def __unicode__(self):
1687 def __unicode__(self):
1674 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
1688 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
1675 safe_unicode(self.repo_name))
1689 safe_unicode(self.repo_name))
@@ -1717,7 +1731,9 b' class Repository(Base, BaseModel):'
1717 from rhodecode.lib.vcs.backends.base import EmptyCommit
1731 from rhodecode.lib.vcs.backends.base import EmptyCommit
1718 dummy = EmptyCommit().__json__()
1732 dummy = EmptyCommit().__json__()
1719 if not self._changeset_cache:
1733 if not self._changeset_cache:
1720 return dummy
1734 dummy['source_repo_id'] = self.repo_id
1735 return json.loads(json.dumps(dummy))
1736
1721 try:
1737 try:
1722 return json.loads(self._changeset_cache)
1738 return json.loads(self._changeset_cache)
1723 except TypeError:
1739 except TypeError:
@@ -2170,6 +2186,20 b' class Repository(Base, BaseModel):'
2170 return make_lock, currently_locked, lock_info
2186 return make_lock, currently_locked, lock_info
2171
2187
2172 @property
2188 @property
2189 def last_commit_cache_update_diff(self):
2190 return time.time() - (safe_int(self.changeset_cache.get('updated_on')) or 0)
2191
2192 @property
2193 def last_commit_change(self):
2194 from rhodecode.lib.vcs.utils.helpers import parse_datetime
2195 empty_date = datetime.datetime.fromtimestamp(0)
2196 date_latest = self.changeset_cache.get('date', empty_date)
2197 try:
2198 return parse_datetime(date_latest)
2199 except Exception:
2200 return empty_date
2201
2202 @property
2173 def last_db_change(self):
2203 def last_db_change(self):
2174 return self.updated_on
2204 return self.updated_on
2175
2205
@@ -2262,6 +2292,7 b' class Repository(Base, BaseModel):'
2262 """
2292 """
2263 Update cache of last changeset for repository, keys should be::
2293 Update cache of last changeset for repository, keys should be::
2264
2294
2295 source_repo_id
2265 short_id
2296 short_id
2266 raw_id
2297 raw_id
2267 revision
2298 revision
@@ -2269,15 +2300,15 b' class Repository(Base, BaseModel):'
2269 message
2300 message
2270 date
2301 date
2271 author
2302 author
2272
2303 updated_on
2273 :param cs_cache:
2304
2274 """
2305 """
2275 from rhodecode.lib.vcs.backends.base import BaseChangeset
2306 from rhodecode.lib.vcs.backends.base import BaseChangeset
2276 if cs_cache is None:
2307 if cs_cache is None:
2277 # use no-cache version here
2308 # use no-cache version here
2278 scm_repo = self.scm_instance(cache=False, config=config)
2309 scm_repo = self.scm_instance(cache=False, config=config)
2279
2310
2280 empty = not scm_repo or scm_repo.is_empty()
2311 empty = scm_repo is None or scm_repo.is_empty()
2281 if not empty:
2312 if not empty:
2282 cs_cache = scm_repo.get_commit(
2313 cs_cache = scm_repo.get_commit(
2283 pre_load=["author", "date", "message", "parents"])
2314 pre_load=["author", "date", "message", "parents"])
@@ -2297,18 +2328,28 b' class Repository(Base, BaseModel):'
2297 if is_outdated(cs_cache) or not self.changeset_cache:
2328 if is_outdated(cs_cache) or not self.changeset_cache:
2298 _default = datetime.datetime.utcnow()
2329 _default = datetime.datetime.utcnow()
2299 last_change = cs_cache.get('date') or _default
2330 last_change = cs_cache.get('date') or _default
2300 if self.updated_on and self.updated_on > last_change:
2331 # we check if last update is newer than the new value
2301 # we check if last update is newer than the new value
2332 # if yes, we use the current timestamp instead. Imagine you get
2302 # if yes, we use the current timestamp instead. Imagine you get
2333 # old commit pushed 1y ago, we'd set last update 1y to ago.
2303 # old commit pushed 1y ago, we'd set last update 1y to ago.
2334 last_change_timestamp = datetime_to_time(last_change)
2304 last_change = _default
2335 current_timestamp = datetime_to_time(last_change)
2305 log.debug('updated repo %s with new cs cache %s',
2336 if last_change_timestamp > current_timestamp:
2306 self.repo_name, cs_cache)
2337 cs_cache['date'] = _default
2307 self.updated_on = last_change
2338
2339 cs_cache['updated_on'] = time.time()
2308 self.changeset_cache = cs_cache
2340 self.changeset_cache = cs_cache
2309 Session().add(self)
2341 Session().add(self)
2310 Session().commit()
2342 Session().commit()
2343
2344 log.debug('updated repo %s with new commit cache %s',
2345 self.repo_name, cs_cache)
2311 else:
2346 else:
2347 cs_cache = self.changeset_cache
2348 cs_cache['updated_on'] = time.time()
2349 self.changeset_cache = cs_cache
2350 Session().add(self)
2351 Session().commit()
2352
2312 log.debug('Skipping update_commit_cache for repo:`%s` '
2353 log.debug('Skipping update_commit_cache for repo:`%s` '
2313 'commit already with latest changes', self.repo_name)
2354 'commit already with latest changes', self.repo_name)
2314
2355
@@ -2397,6 +2438,7 b' class Repository(Base, BaseModel):'
2397 # control over cache behaviour
2438 # control over cache behaviour
2398 if cache is None and full_cache and not config:
2439 if cache is None and full_cache and not config:
2399 return self._get_instance_cached()
2440 return self._get_instance_cached()
2441 # cache here is sent to the "vcs server"
2400 return self._get_instance(cache=bool(cache), config=config)
2442 return self._get_instance(cache=bool(cache), config=config)
2401
2443
2402 def _get_instance_cached(self):
2444 def _get_instance_cached(self):
@@ -2425,8 +2467,7 b' class Repository(Base, BaseModel):'
2425 else:
2467 else:
2426 instance = get_instance_cached(*args)
2468 instance = get_instance_cached(*args)
2427
2469
2428 log.debug(
2470 log.debug('Repo instance fetched in %.3fs', inv_context_manager.compute_time)
2429 'Repo instance fetched in %.3fs', inv_context_manager.compute_time)
2430 return instance
2471 return instance
2431
2472
2432 def _get_instance(self, cache=True, config=None):
2473 def _get_instance(self, cache=True, config=None):
@@ -2440,7 +2481,8 b' class Repository(Base, BaseModel):'
2440 with_wire=custom_wire,
2481 with_wire=custom_wire,
2441 create=False,
2482 create=False,
2442 _vcs_alias=self.repo_type)
2483 _vcs_alias=self.repo_type)
2443
2484 if repo is not None:
2485 repo.count() # cache rebuild
2444 return repo
2486 return repo
2445
2487
2446 def __json__(self):
2488 def __json__(self):
@@ -2467,7 +2509,8 b' class RepoGroup(Base, BaseModel):'
2467 CHOICES_SEPARATOR = '/' # used to generate select2 choices for nested groups
2509 CHOICES_SEPARATOR = '/' # used to generate select2 choices for nested groups
2468
2510
2469 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
2511 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
2470 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
2512 _group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
2513 group_name_hash = Column("repo_group_name_hash", String(1024), nullable=False, unique=False)
2471 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
2514 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
2472 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
2515 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
2473 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
2516 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
@@ -2475,6 +2518,8 b' class RepoGroup(Base, BaseModel):'
2475 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
2518 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
2476 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
2519 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
2477 personal = Column('personal', Boolean(), nullable=True, unique=None, default=None)
2520 personal = Column('personal', Boolean(), nullable=True, unique=None, default=None)
2521 _changeset_cache = Column(
2522 "changeset_cache", LargeBinary(), nullable=True) # JSON data
2478
2523
2479 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
2524 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
2480 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
2525 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
@@ -2490,6 +2535,38 b' class RepoGroup(Base, BaseModel):'
2490 return u"<%s('id:%s:%s')>" % (
2535 return u"<%s('id:%s:%s')>" % (
2491 self.__class__.__name__, self.group_id, self.group_name)
2536 self.__class__.__name__, self.group_id, self.group_name)
2492
2537
2538 @hybrid_property
2539 def group_name(self):
2540 return self._group_name
2541
2542 @group_name.setter
2543 def group_name(self, value):
2544 self._group_name = value
2545 self.group_name_hash = self.hash_repo_group_name(value)
2546
2547 @hybrid_property
2548 def changeset_cache(self):
2549 from rhodecode.lib.vcs.backends.base import EmptyCommit
2550 dummy = EmptyCommit().__json__()
2551 if not self._changeset_cache:
2552 dummy['source_repo_id'] = ''
2553 return json.loads(json.dumps(dummy))
2554
2555 try:
2556 return json.loads(self._changeset_cache)
2557 except TypeError:
2558 return dummy
2559 except Exception:
2560 log.error(traceback.format_exc())
2561 return dummy
2562
2563 @changeset_cache.setter
2564 def changeset_cache(self, val):
2565 try:
2566 self._changeset_cache = json.dumps(val)
2567 except Exception:
2568 log.error(traceback.format_exc())
2569
2493 @validates('group_parent_id')
2570 @validates('group_parent_id')
2494 def validate_group_parent_id(self, key, val):
2571 def validate_group_parent_id(self, key, val):
2495 """
2572 """
@@ -2506,6 +2583,18 b' class RepoGroup(Base, BaseModel):'
2506 return h.escape(self.group_description)
2583 return h.escape(self.group_description)
2507
2584
2508 @classmethod
2585 @classmethod
2586 def hash_repo_group_name(cls, repo_group_name):
2587 val = remove_formatting(repo_group_name)
2588 val = safe_str(val).lower()
2589 chars = []
2590 for c in val:
2591 if c not in string.ascii_letters:
2592 c = str(ord(c))
2593 chars.append(c)
2594
2595 return ''.join(chars)
2596
2597 @classmethod
2509 def _generate_choice(cls, repo_group):
2598 def _generate_choice(cls, repo_group):
2510 from webhelpers.html import literal as _literal
2599 from webhelpers.html import literal as _literal
2511 _name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
2600 _name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
@@ -2573,8 +2662,7 b' class RepoGroup(Base, BaseModel):'
2573 return q.all()
2662 return q.all()
2574
2663
2575 @property
2664 @property
2576 def parents(self):
2665 def parents(self, parents_recursion_limit = 10):
2577 parents_recursion_limit = 10
2578 groups = []
2666 groups = []
2579 if self.parent_group is None:
2667 if self.parent_group is None:
2580 return groups
2668 return groups
@@ -2597,6 +2685,20 b' class RepoGroup(Base, BaseModel):'
2597 return groups
2685 return groups
2598
2686
2599 @property
2687 @property
2688 def last_commit_cache_update_diff(self):
2689 return time.time() - (safe_int(self.changeset_cache.get('updated_on')) or 0)
2690
2691 @property
2692 def last_commit_change(self):
2693 from rhodecode.lib.vcs.utils.helpers import parse_datetime
2694 empty_date = datetime.datetime.fromtimestamp(0)
2695 date_latest = self.changeset_cache.get('date', empty_date)
2696 try:
2697 return parse_datetime(date_latest)
2698 except Exception:
2699 return empty_date
2700
2701 @property
2600 def last_db_change(self):
2702 def last_db_change(self):
2601 return self.updated_on
2703 return self.updated_on
2602
2704
@@ -2635,7 +2737,7 b' class RepoGroup(Base, BaseModel):'
2635
2737
2636 return cnt + children_count(self)
2738 return cnt + children_count(self)
2637
2739
2638 def _recursive_objects(self, include_repos=True):
2740 def _recursive_objects(self, include_repos=True, include_groups=True):
2639 all_ = []
2741 all_ = []
2640
2742
2641 def _get_members(root_gr):
2743 def _get_members(root_gr):
@@ -2645,11 +2747,16 b' class RepoGroup(Base, BaseModel):'
2645 childs = root_gr.children.all()
2747 childs = root_gr.children.all()
2646 if childs:
2748 if childs:
2647 for gr in childs:
2749 for gr in childs:
2648 all_.append(gr)
2750 if include_groups:
2751 all_.append(gr)
2649 _get_members(gr)
2752 _get_members(gr)
2650
2753
2754 root_group = []
2755 if include_groups:
2756 root_group = [self]
2757
2651 _get_members(self)
2758 _get_members(self)
2652 return [self] + all_
2759 return root_group + all_
2653
2760
2654 def recursive_groups_and_repos(self):
2761 def recursive_groups_and_repos(self):
2655 """
2762 """
@@ -2663,6 +2770,12 b' class RepoGroup(Base, BaseModel):'
2663 """
2770 """
2664 return self._recursive_objects(include_repos=False)
2771 return self._recursive_objects(include_repos=False)
2665
2772
2773 def recursive_repos(self):
2774 """
2775 Returns all children repositories for this group
2776 """
2777 return self._recursive_objects(include_groups=False)
2778
2666 def get_new_name(self, group_name):
2779 def get_new_name(self, group_name):
2667 """
2780 """
2668 returns new full group name based on parent and new name
2781 returns new full group name based on parent and new name
@@ -2673,6 +2786,63 b' class RepoGroup(Base, BaseModel):'
2673 self.parent_group else [])
2786 self.parent_group else [])
2674 return RepoGroup.url_sep().join(path_prefix + [group_name])
2787 return RepoGroup.url_sep().join(path_prefix + [group_name])
2675
2788
2789 def update_commit_cache(self, config=None):
2790 """
2791 Update cache of last changeset for newest repository inside this group, keys should be::
2792
2793 source_repo_id
2794 short_id
2795 raw_id
2796 revision
2797 parents
2798 message
2799 date
2800 author
2801
2802 """
2803 from rhodecode.lib.vcs.utils.helpers import parse_datetime
2804
2805 def repo_groups_and_repos():
2806 all_entries = OrderedDefaultDict(list)
2807
2808 def _get_members(root_gr, pos=0):
2809
2810 for repo in root_gr.repositories:
2811 all_entries[root_gr].append(repo)
2812
2813 # fill in all parent positions
2814 for parent_group in root_gr.parents:
2815 all_entries[parent_group].extend(all_entries[root_gr])
2816
2817 children_groups = root_gr.children.all()
2818 if children_groups:
2819 for cnt, gr in enumerate(children_groups, 1):
2820 _get_members(gr, pos=pos+cnt)
2821
2822 _get_members(root_gr=self)
2823 return all_entries
2824
2825 empty_date = datetime.datetime.fromtimestamp(0)
2826 for repo_group, repos in repo_groups_and_repos().items():
2827
2828 latest_repo_cs_cache = {}
2829 for repo in repos:
2830 repo_cs_cache = repo.changeset_cache
2831 date_latest = latest_repo_cs_cache.get('date', empty_date)
2832 date_current = repo_cs_cache.get('date', empty_date)
2833 current_timestamp = datetime_to_time(parse_datetime(date_latest))
2834 if current_timestamp < datetime_to_time(parse_datetime(date_current)):
2835 latest_repo_cs_cache = repo_cs_cache
2836 latest_repo_cs_cache['source_repo_id'] = repo.repo_id
2837
2838 latest_repo_cs_cache['updated_on'] = time.time()
2839 repo_group.changeset_cache = latest_repo_cs_cache
2840 Session().add(repo_group)
2841 Session().commit()
2842
2843 log.debug('updated repo group %s with new commit cache %s',
2844 repo_group.group_name, latest_repo_cs_cache)
2845
2676 def permissions(self, with_admins=True, with_owner=True,
2846 def permissions(self, with_admins=True, with_owner=True,
2677 expand_from_user_groups=False):
2847 expand_from_user_groups=False):
2678 """
2848 """
@@ -2768,6 +2938,13 b' class RepoGroup(Base, BaseModel):'
2768 }
2938 }
2769 return data
2939 return data
2770
2940
2941 def get_dict(self):
2942 # Since we transformed `group_name` to a hybrid property, we need to
2943 # keep compatibility with the code which uses `group_name` field.
2944 result = super(RepoGroup, self).get_dict()
2945 result['group_name'] = result.pop('_group_name', None)
2946 return result
2947
2771
2948
2772 class Permission(Base, BaseModel):
2949 class Permission(Base, BaseModel):
2773 __tablename__ = 'permissions'
2950 __tablename__ = 'permissions'
@@ -4258,9 +4435,16 b' class Gist(Base, BaseModel):'
4258 # SCM functions
4435 # SCM functions
4259
4436
4260 def scm_instance(self, **kwargs):
4437 def scm_instance(self, **kwargs):
4438 """
4439 Get an instance of VCS Repository
4440
4441 :param kwargs:
4442 """
4443 from rhodecode.model.gist import GistModel
4261 full_repo_path = os.path.join(self.base_path(), self.gist_access_id)
4444 full_repo_path = os.path.join(self.base_path(), self.gist_access_id)
4262 return get_vcs_instance(
4445 return get_vcs_instance(
4263 repo_path=safe_str(full_repo_path), create=False)
4446 repo_path=safe_str(full_repo_path), create=False,
4447 _vcs_alias=GistModel.vcs_backend)
4264
4448
4265
4449
4266 class ExternalIdentity(Base, BaseModel):
4450 class ExternalIdentity(Base, BaseModel):
@@ -4904,8 +5088,8 b' class FileStore(Base, BaseModel):'
4904
5088
4905 @classmethod
5089 @classmethod
4906 def create(cls, file_uid, filename, file_hash, file_size, file_display_name='',
5090 def create(cls, file_uid, filename, file_hash, file_size, file_display_name='',
4907 file_description='', enabled=True, check_acl=True,
5091 file_description='', enabled=True, check_acl=True, user_id=None,
4908 user_id=None, scope_repo_id=None, scope_repo_group_id=None):
5092 scope_user_id=None, scope_repo_id=None, scope_repo_group_id=None):
4909
5093
4910 store_entry = FileStore()
5094 store_entry = FileStore()
4911 store_entry.file_uid = file_uid
5095 store_entry.file_uid = file_uid
@@ -4919,6 +5103,7 b' class FileStore(Base, BaseModel):'
4919 store_entry.enabled = enabled
5103 store_entry.enabled = enabled
4920
5104
4921 store_entry.user_id = user_id
5105 store_entry.user_id = user_id
5106 store_entry.scope_user_id = scope_user_id
4922 store_entry.scope_repo_id = scope_repo_id
5107 store_entry.scope_repo_id = scope_repo_id
4923 store_entry.scope_repo_group_id = scope_repo_group_id
5108 store_entry.scope_repo_group_id = scope_repo_group_id
4924 return store_entry
5109 return store_entry
@@ -618,7 +618,7 b' def PullRequestForm(localizer, repo_id):'
618 revisions = All(#v.NotReviewedRevisions(localizer, repo_id)(),
618 revisions = All(#v.NotReviewedRevisions(localizer, repo_id)(),
619 v.UniqueList(localizer)(not_empty=True))
619 v.UniqueList(localizer)(not_empty=True))
620 review_members = formencode.ForEach(ReviewerForm())
620 review_members = formencode.ForEach(ReviewerForm())
621 pullrequest_title = v.UnicodeString(strip=True, required=True, min=3, max=255)
621 pullrequest_title = v.UnicodeString(strip=True, required=True, min=1, max=255)
622 pullrequest_desc = v.UnicodeString(strip=True, required=False)
622 pullrequest_desc = v.UnicodeString(strip=True, required=False)
623 description_renderer = v.UnicodeString(strip=True, required=False)
623 description_renderer = v.UnicodeString(strip=True, required=False)
624
624
@@ -47,6 +47,7 b" GIST_METADATA_FILE = '.rc_gist_metadata'"
47
47
48 class GistModel(BaseModel):
48 class GistModel(BaseModel):
49 cls = Gist
49 cls = Gist
50 vcs_backend = 'hg'
50
51
51 def _get_gist(self, gist):
52 def _get_gist(self, gist):
52 """
53 """
@@ -145,7 +146,7 b' class GistModel(BaseModel):'
145 gist_repo_path = os.path.join(GIST_STORE_LOC, gist_id)
146 gist_repo_path = os.path.join(GIST_STORE_LOC, gist_id)
146 log.debug('Creating new %s GIST repo in %s', gist_type, gist_repo_path)
147 log.debug('Creating new %s GIST repo in %s', gist_type, gist_repo_path)
147 repo = RepoModel()._create_filesystem_repo(
148 repo = RepoModel()._create_filesystem_repo(
148 repo_name=gist_id, repo_type='hg', repo_group=GIST_STORE_LOC,
149 repo_name=gist_id, repo_type=self.vcs_backend, repo_group=GIST_STORE_LOC,
149 use_global_config=True)
150 use_global_config=True)
150
151
151 # now create single multifile commit
152 # now create single multifile commit
@@ -683,6 +683,7 b' class PullRequestModel(BaseModel):'
683
683
684 # source repo
684 # source repo
685 source_repo = pull_request.source_repo.scm_instance()
685 source_repo = pull_request.source_repo.scm_instance()
686
686 try:
687 try:
687 source_commit = source_repo.get_commit(commit_id=source_ref_name)
688 source_commit = source_repo.get_commit(commit_id=source_ref_name)
688 except CommitDoesNotExistError:
689 except CommitDoesNotExistError:
@@ -696,6 +697,7 b' class PullRequestModel(BaseModel):'
696
697
697 # target repo
698 # target repo
698 target_repo = pull_request.target_repo.scm_instance()
699 target_repo = pull_request.target_repo.scm_instance()
700
699 try:
701 try:
700 target_commit = target_repo.get_commit(commit_id=target_ref_name)
702 target_commit = target_repo.get_commit(commit_id=target_ref_name)
701 except CommitDoesNotExistError:
703 except CommitDoesNotExistError:
@@ -752,8 +754,8 b' class PullRequestModel(BaseModel):'
752 target_commit.raw_id, source_commit.raw_id, source_repo, merge=True,
754 target_commit.raw_id, source_commit.raw_id, source_repo, merge=True,
753 pre_load=pre_load)
755 pre_load=pre_load)
754
756
755 ancestor = target_repo.get_common_ancestor(
757 ancestor = source_repo.get_common_ancestor(
756 target_commit.raw_id, source_commit.raw_id, source_repo)
758 source_commit.raw_id, target_commit.raw_id, target_repo)
757
759
758 pull_request.source_ref = '%s:%s:%s' % (
760 pull_request.source_ref = '%s:%s:%s' % (
759 source_ref_type, source_ref_name, source_commit.raw_id)
761 source_ref_type, source_ref_name, source_commit.raw_id)
@@ -1314,10 +1316,21 b' class PullRequestModel(BaseModel):'
1314 merge_state = self._refresh_merge_state(
1316 merge_state = self._refresh_merge_state(
1315 pull_request, target_vcs, target_ref)
1317 pull_request, target_vcs, target_ref)
1316 else:
1318 else:
1317 possible = pull_request.\
1319 possible = pull_request.last_merge_status == MergeFailureReason.NONE
1318 last_merge_status == MergeFailureReason.NONE
1320 metadata = {
1321 'target_ref': pull_request.target_ref_parts,
1322 'source_ref': pull_request.source_ref_parts,
1323 }
1324 if not possible and target_ref.type == 'branch':
1325 # NOTE(marcink): case for mercurial multiple heads on branch
1326 heads = target_vcs._heads(target_ref.name)
1327 if len(heads) != 1:
1328 heads = '\n,'.join(target_vcs._heads(target_ref.name))
1329 metadata.update({
1330 'heads': heads
1331 })
1319 merge_state = MergeResponse(
1332 merge_state = MergeResponse(
1320 possible, False, None, pull_request.last_merge_status)
1333 possible, False, None, pull_request.last_merge_status, metadata=metadata)
1321
1334
1322 return merge_state
1335 return merge_state
1323
1336
@@ -1326,6 +1339,7 b' class PullRequestModel(BaseModel):'
1326 name_or_id = reference.name
1339 name_or_id = reference.name
1327 else:
1340 else:
1328 name_or_id = reference.commit_id
1341 name_or_id = reference.commit_id
1342
1329 refreshed_commit = vcs_repository.get_commit(name_or_id)
1343 refreshed_commit = vcs_repository.get_commit(name_or_id)
1330 refreshed_reference = Reference(
1344 refreshed_reference = Reference(
1331 reference.type, reference.name, refreshed_commit.raw_id)
1345 reference.type, reference.name, refreshed_commit.raw_id)
@@ -192,14 +192,14 b' class RepoModel(BaseModel):'
192 return repo_log
192 return repo_log
193
193
194 @classmethod
194 @classmethod
195 def update_repoinfo(cls, repositories=None):
195 def update_commit_cache(cls, repositories=None):
196 if not repositories:
196 if not repositories:
197 repositories = Repository.getAll()
197 repositories = Repository.getAll()
198 for repo in repositories:
198 for repo in repositories:
199 repo.update_commit_cache()
199 repo.update_commit_cache()
200
200
201 def get_repos_as_dict(self, repo_list=None, admin=False,
201 def get_repos_as_dict(self, repo_list=None, admin=False,
202 super_user_actions=False):
202 super_user_actions=False, short_name=None):
203 _render = get_current_request().get_partial_renderer(
203 _render = get_current_request().get_partial_renderer(
204 'rhodecode:templates/data_table/_dt_elements.mako')
204 'rhodecode:templates/data_table/_dt_elements.mako')
205 c = _render.get_call_context()
205 c = _render.get_call_context()
@@ -208,8 +208,12 b' class RepoModel(BaseModel):'
208 return _render('quick_menu', repo_name)
208 return _render('quick_menu', repo_name)
209
209
210 def repo_lnk(name, rtype, rstate, private, archived, fork_of):
210 def repo_lnk(name, rtype, rstate, private, archived, fork_of):
211 if short_name is not None:
212 short_name_var = short_name
213 else:
214 short_name_var = not admin
211 return _render('repo_name', name, rtype, rstate, private, archived, fork_of,
215 return _render('repo_name', name, rtype, rstate, private, archived, fork_of,
212 short_name=not admin, admin=False)
216 short_name=short_name_var, admin=False)
213
217
214 def last_change(last_change):
218 def last_change(last_change):
215 if admin and isinstance(last_change, datetime.datetime) and not last_change.tzinfo:
219 if admin and isinstance(last_change, datetime.datetime) and not last_change.tzinfo:
@@ -250,8 +254,8 b' class RepoModel(BaseModel):'
250 repo.private, repo.archived, repo.fork),
254 repo.private, repo.archived, repo.fork),
251 "name_raw": repo.repo_name.lower(),
255 "name_raw": repo.repo_name.lower(),
252
256
253 "last_change": last_change(repo.last_db_change),
257 "last_change": last_change(repo.last_commit_change),
254 "last_change_raw": datetime_to_time(repo.last_db_change),
258 "last_change_raw": datetime_to_time(repo.last_commit_change),
255
259
256 "last_changeset": last_rev(repo.repo_name, cs_cache),
260 "last_changeset": last_rev(repo.repo_name, cs_cache),
257 "last_changeset_raw": cs_cache.get('revision'),
261 "last_changeset_raw": cs_cache.get('revision'),
@@ -97,6 +97,8 b' class RepoGroupModel(BaseModel):'
97 return string.Template(template).safe_substitute(
97 return string.Template(template).safe_substitute(
98 username=user.username,
98 username=user.username,
99 user_id=user.user_id,
99 user_id=user.user_id,
100 first_name=user.first_name,
101 last_name=user.last_name,
100 )
102 )
101
103
102 def create_personal_repo_group(self, user, commit_early=True):
104 def create_personal_repo_group(self, user, commit_early=True):
@@ -307,6 +309,10 b' class RepoGroupModel(BaseModel):'
307 # trigger the post hook
309 # trigger the post hook
308 from rhodecode.lib.hooks_base import log_create_repository_group
310 from rhodecode.lib.hooks_base import log_create_repository_group
309 repo_group = RepoGroup.get_by_group_name(group_name)
311 repo_group = RepoGroup.get_by_group_name(group_name)
312
313 # update repo group commit caches initially
314 repo_group.update_commit_cache()
315
310 log_create_repository_group(
316 log_create_repository_group(
311 created_by=user.username, **repo_group.get_dict())
317 created_by=user.username, **repo_group.get_dict())
312
318
@@ -684,6 +690,13 b' class RepoGroupModel(BaseModel):'
684 'revoked permission from usergroup: {} on repogroup: {}'.format(
690 'revoked permission from usergroup: {} on repogroup: {}'.format(
685 group_name, repo_group), namespace='security.repogroup')
691 group_name, repo_group), namespace='security.repogroup')
686
692
693 @classmethod
694 def update_commit_cache(cls, repo_groups=None):
695 if not repo_groups:
696 repo_groups = RepoGroup.getAll()
697 for repo_group in repo_groups:
698 repo_group.update_commit_cache()
699
687 def get_repo_groups_as_dict(self, repo_group_list=None, admin=False,
700 def get_repo_groups_as_dict(self, repo_group_list=None, admin=False,
688 super_user_actions=False):
701 super_user_actions=False):
689
702
@@ -705,6 +718,11 b' class RepoGroupModel(BaseModel):'
705 (datetime.datetime.now() - datetime.datetime.utcnow()).seconds)
718 (datetime.datetime.now() - datetime.datetime.utcnow()).seconds)
706 return _render("last_change", last_change)
719 return _render("last_change", last_change)
707
720
721 def last_rev(repo_name, cs_cache):
722 return _render('revision', repo_name, cs_cache.get('revision'),
723 cs_cache.get('raw_id'), cs_cache.get('author'),
724 cs_cache.get('message'), cs_cache.get('date'))
725
708 def desc(desc, personal):
726 def desc(desc, personal):
709 return _render(
727 return _render(
710 'repo_group_desc', desc, personal, c.visual.stylify_metatags)
728 'repo_group_desc', desc, personal, c.visual.stylify_metatags)
@@ -721,13 +739,19 b' class RepoGroupModel(BaseModel):'
721
739
722 repo_group_data = []
740 repo_group_data = []
723 for group in repo_group_list:
741 for group in repo_group_list:
742 cs_cache = group.changeset_cache
743 last_repo_name = cs_cache.get('source_repo_name')
724
744
725 row = {
745 row = {
726 "menu": quick_menu(group.group_name),
746 "menu": quick_menu(group.group_name),
727 "name": repo_group_lnk(group.group_name),
747 "name": repo_group_lnk(group.group_name),
728 "name_raw": group.group_name,
748 "name_raw": group.group_name,
729 "last_change": last_change(group.last_db_change),
749 "last_change": last_change(group.last_commit_change),
730 "last_change_raw": datetime_to_time(group.last_db_change),
750 "last_change_raw": datetime_to_time(group.last_commit_change),
751
752 "last_changeset": "",
753 "last_changeset_raw": "",
754
731 "desc": desc(group.description_safe, group.personal),
755 "desc": desc(group.description_safe, group.personal),
732 "top_level_repos": 0,
756 "top_level_repos": 0,
733 "owner": user_profile(group.user.username)
757 "owner": user_profile(group.user.username)
@@ -818,6 +818,8 b' class ScmModel(BaseModel):'
818 repo_name=repo.repo_name, repo_alias=scm_instance.alias,
818 repo_name=repo.repo_name, repo_alias=scm_instance.alias,
819 commit_ids=[tip.raw_id])
819 commit_ids=[tip.raw_id])
820
820
821 return tip
822
821 def delete_nodes(self, user, repo, message, nodes, parent_commit=None,
823 def delete_nodes(self, user, repo, message, nodes, parent_commit=None,
822 author=None, trigger_push_hook=True):
824 author=None, trigger_push_hook=True):
823 """
825 """
@@ -119,6 +119,7 b' class SettingsModel(BaseModel):'
119 new_ui.ui_value = val
119 new_ui.ui_value = val
120 new_ui.ui_active = active
120 new_ui.ui_active = active
121
121
122 repository_id = ''
122 if self.repo:
123 if self.repo:
123 repo = self._get_repo(self.repo)
124 repo = self._get_repo(self.repo)
124 repository_id = repo.repo_id
125 repository_id = repo.repo_id
@@ -440,26 +441,39 b' class VcsSettingsModel(object):'
440 HOOKS_SETTINGS = (
441 HOOKS_SETTINGS = (
441 ('hooks', 'changegroup.repo_size'),
442 ('hooks', 'changegroup.repo_size'),
442 ('hooks', 'changegroup.push_logger'),
443 ('hooks', 'changegroup.push_logger'),
443 ('hooks', 'outgoing.pull_logger'),)
444 ('hooks', 'outgoing.pull_logger'),
445 )
444 HG_SETTINGS = (
446 HG_SETTINGS = (
445 ('extensions', 'largefiles'),
447 ('extensions', 'largefiles'),
446 ('phases', 'publish'),
448 ('phases', 'publish'),
447 ('extensions', 'evolve'),)
449 ('extensions', 'evolve'),
450 ('extensions', 'topic'),
451 ('experimental', 'evolution'),
452 ('experimental', 'evolution.exchange'),
453 )
448 GIT_SETTINGS = (
454 GIT_SETTINGS = (
449 ('vcs_git_lfs', 'enabled'),)
455 ('vcs_git_lfs', 'enabled'),
456 )
450 GLOBAL_HG_SETTINGS = (
457 GLOBAL_HG_SETTINGS = (
451 ('extensions', 'largefiles'),
458 ('extensions', 'largefiles'),
452 ('largefiles', 'usercache'),
459 ('largefiles', 'usercache'),
453 ('phases', 'publish'),
460 ('phases', 'publish'),
454 ('extensions', 'hgsubversion'),
461 ('extensions', 'hgsubversion'),
455 ('extensions', 'evolve'),)
462 ('extensions', 'evolve'),
463 ('extensions', 'topic'),
464 ('experimental', 'evolution'),
465 ('experimental', 'evolution.exchange'),
466 )
467
456 GLOBAL_GIT_SETTINGS = (
468 GLOBAL_GIT_SETTINGS = (
457 ('vcs_git_lfs', 'enabled'),
469 ('vcs_git_lfs', 'enabled'),
458 ('vcs_git_lfs', 'store_location'))
470 ('vcs_git_lfs', 'store_location')
471 )
459
472
460 GLOBAL_SVN_SETTINGS = (
473 GLOBAL_SVN_SETTINGS = (
461 ('vcs_svn_proxy', 'http_requests_enabled'),
474 ('vcs_svn_proxy', 'http_requests_enabled'),
462 ('vcs_svn_proxy', 'http_server_url'))
475 ('vcs_svn_proxy', 'http_server_url')
476 )
463
477
464 SVN_BRANCH_SECTION = 'vcs_svn_branch'
478 SVN_BRANCH_SECTION = 'vcs_svn_branch'
465 SVN_TAG_SECTION = 'vcs_svn_tag'
479 SVN_TAG_SECTION = 'vcs_svn_tag'
@@ -574,12 +588,38 b' class VcsSettingsModel(object):'
574 def create_repo_svn_settings(self, data):
588 def create_repo_svn_settings(self, data):
575 return self._create_svn_settings(self.repo_settings, data)
589 return self._create_svn_settings(self.repo_settings, data)
576
590
591 def _set_evolution(self, settings, is_enabled):
592 if is_enabled:
593 # if evolve is active set evolution=all
594
595 self._create_or_update_ui(
596 settings, *('experimental', 'evolution'), value='all',
597 active=True)
598 self._create_or_update_ui(
599 settings, *('experimental', 'evolution.exchange'), value='yes',
600 active=True)
601 # if evolve is active set topics server support
602 self._create_or_update_ui(
603 settings, *('extensions', 'topic'), value='',
604 active=True)
605
606 else:
607 self._create_or_update_ui(
608 settings, *('experimental', 'evolution'), value='',
609 active=False)
610 self._create_or_update_ui(
611 settings, *('experimental', 'evolution.exchange'), value='no',
612 active=False)
613 self._create_or_update_ui(
614 settings, *('extensions', 'topic'), value='',
615 active=False)
616
577 @assert_repo_settings
617 @assert_repo_settings
578 def create_or_update_repo_hg_settings(self, data):
618 def create_or_update_repo_hg_settings(self, data):
579 largefiles, phases, evolve = \
619 largefiles, phases, evolve = \
580 self.HG_SETTINGS
620 self.HG_SETTINGS[:3]
581 largefiles_key, phases_key, evolve_key = \
621 largefiles_key, phases_key, evolve_key = \
582 self._get_settings_keys(self.HG_SETTINGS, data)
622 self._get_settings_keys(self.HG_SETTINGS[:3], data)
583
623
584 self._create_or_update_ui(
624 self._create_or_update_ui(
585 self.repo_settings, *largefiles, value='',
625 self.repo_settings, *largefiles, value='',
@@ -587,21 +627,22 b' class VcsSettingsModel(object):'
587 self._create_or_update_ui(
627 self._create_or_update_ui(
588 self.repo_settings, *evolve, value='',
628 self.repo_settings, *evolve, value='',
589 active=data[evolve_key])
629 active=data[evolve_key])
630 self._set_evolution(self.repo_settings, is_enabled=data[evolve_key])
631
590 self._create_or_update_ui(
632 self._create_or_update_ui(
591 self.repo_settings, *phases, value=safe_str(data[phases_key]))
633 self.repo_settings, *phases, value=safe_str(data[phases_key]))
592
634
593 def create_or_update_global_hg_settings(self, data):
635 def create_or_update_global_hg_settings(self, data):
594 largefiles, largefiles_store, phases, hgsubversion, evolve \
636 largefiles, largefiles_store, phases, hgsubversion, evolve \
595 = self.GLOBAL_HG_SETTINGS
637 = self.GLOBAL_HG_SETTINGS[:5]
596 largefiles_key, largefiles_store_key, phases_key, subversion_key, evolve_key \
638 largefiles_key, largefiles_store_key, phases_key, subversion_key, evolve_key \
597 = self._get_settings_keys(self.GLOBAL_HG_SETTINGS, data)
639 = self._get_settings_keys(self.GLOBAL_HG_SETTINGS[:5], data)
598
640
599 self._create_or_update_ui(
641 self._create_or_update_ui(
600 self.global_settings, *largefiles, value='',
642 self.global_settings, *largefiles, value='',
601 active=data[largefiles_key])
643 active=data[largefiles_key])
602 self._create_or_update_ui(
644 self._create_or_update_ui(
603 self.global_settings, *largefiles_store,
645 self.global_settings, *largefiles_store, value=data[largefiles_store_key])
604 value=data[largefiles_store_key])
605 self._create_or_update_ui(
646 self._create_or_update_ui(
606 self.global_settings, *phases, value=safe_str(data[phases_key]))
647 self.global_settings, *phases, value=safe_str(data[phases_key]))
607 self._create_or_update_ui(
648 self._create_or_update_ui(
@@ -609,9 +650,10 b' class VcsSettingsModel(object):'
609 self._create_or_update_ui(
650 self._create_or_update_ui(
610 self.global_settings, *evolve, value='',
651 self.global_settings, *evolve, value='',
611 active=data[evolve_key])
652 active=data[evolve_key])
653 self._set_evolution(self.global_settings, is_enabled=data[evolve_key])
612
654
613 def create_or_update_repo_git_settings(self, data):
655 def create_or_update_repo_git_settings(self, data):
614 # NOTE(marcink): # comma make unpack work properly
656 # NOTE(marcink): # comma makes unpack work properly
615 lfs_enabled, \
657 lfs_enabled, \
616 = self.GIT_SETTINGS
658 = self.GIT_SETTINGS
617
659
@@ -675,6 +717,7 b' class VcsSettingsModel(object):'
675 def get_repo_ui_settings(self, section=None, key=None):
717 def get_repo_ui_settings(self, section=None, key=None):
676 global_uis = self.global_settings.get_ui(section, key)
718 global_uis = self.global_settings.get_ui(section, key)
677 repo_uis = self.repo_settings.get_ui(section, key)
719 repo_uis = self.repo_settings.get_ui(section, key)
720
678 filtered_repo_uis = self._filter_ui_settings(repo_uis)
721 filtered_repo_uis = self._filter_ui_settings(repo_uis)
679 filtered_repo_uis_keys = [
722 filtered_repo_uis_keys = [
680 (s.section, s.key) for s in filtered_repo_uis]
723 (s.section, s.key) for s in filtered_repo_uis]
@@ -24,10 +24,15 b' import traceback'
24 import sshpubkeys
24 import sshpubkeys
25 import sshpubkeys.exceptions
25 import sshpubkeys.exceptions
26
26
27 from cryptography.hazmat.primitives.asymmetric import rsa
28 from cryptography.hazmat.primitives import serialization as crypto_serialization
29 from cryptography.hazmat.backends import default_backend as crypto_default_backend
30
27 from rhodecode.model import BaseModel
31 from rhodecode.model import BaseModel
28 from rhodecode.model.db import UserSshKeys
32 from rhodecode.model.db import UserSshKeys
29 from rhodecode.model.meta import Session
33 from rhodecode.model.meta import Session
30
34
35
31 log = logging.getLogger(__name__)
36 log = logging.getLogger(__name__)
32
37
33
38
@@ -62,16 +67,24 b' class SshKeyModel(BaseModel):'
62 raise
67 raise
63
68
64 def generate_keypair(self, comment=None):
69 def generate_keypair(self, comment=None):
65 from Crypto.PublicKey import RSA
66
67 key = RSA.generate(2048)
68 private = key.exportKey('PEM')
69
70
70 pubkey = key.publickey()
71 key = rsa.generate_private_key(
71 public = pubkey.exportKey('OpenSSH')
72 backend=crypto_default_backend(),
73 public_exponent=65537,
74 key_size=2048
75 )
76 private_key = key.private_bytes(
77 crypto_serialization.Encoding.PEM,
78 crypto_serialization.PrivateFormat.PKCS8,
79 crypto_serialization.NoEncryption())
80 public_key = key.public_key().public_bytes(
81 crypto_serialization.Encoding.OpenSSH,
82 crypto_serialization.PublicFormat.OpenSSH
83 )
84
72 if comment:
85 if comment:
73 public = public + " " + comment
86 public_key = public_key + " " + comment
74 return private, public
87 return private_key, public_key
75
88
76 def create(self, user, fingerprint, key_data, description):
89 def create(self, user, fingerprint, key_data, description):
77 """
90 """
@@ -14,11 +14,11 b' input[type="button"] {'
14 font-family: @text-light;
14 font-family: @text-light;
15 text-decoration: none;
15 text-decoration: none;
16 text-shadow: none;
16 text-shadow: none;
17 color: @grey4;
17 color: @grey2;
18 background-color: white;
18 background-color: white;
19 background-image: none;
19 background-image: none;
20 border: none;
20 border: none;
21 .border ( @border-thickness-buttons, @grey4 );
21 .border ( @border-thickness-buttons, @grey5 );
22 .border-radius (@border-radius);
22 .border-radius (@border-radius);
23 cursor: pointer;
23 cursor: pointer;
24 white-space: nowrap;
24 white-space: nowrap;
@@ -26,6 +26,10 b' input[type="button"] {'
26 -moz-transition: background .3s,color .3s;
26 -moz-transition: background .3s,color .3s;
27 -o-transition: background .3s,color .3s;
27 -o-transition: background .3s,color .3s;
28 transition: background .3s,color .3s;
28 transition: background .3s,color .3s;
29 box-shadow: @button-shadow;
30 -webkit-box-shadow: @button-shadow;
31
32
29
33
30 a {
34 a {
31 display: block;
35 display: block;
@@ -44,8 +48,9 b' input[type="button"] {'
44 outline:none;
48 outline:none;
45 }
49 }
46 &:hover {
50 &:hover {
47 color: white;
51 color: @rcdarkblue;
48 background-color: @grey4;
52 background-color: @white;
53 .border ( @border-thickness, @grey4 );
49 }
54 }
50
55
51 .icon-remove-sign {
56 .icon-remove-sign {
@@ -70,26 +75,26 b' input[type="button"] {'
70
75
71
76
72 .btn-default {
77 .btn-default {
73 .border ( @border-thickness-buttons, @rcblue );
78 border: @border-thickness solid @grey5;
74 background-image: none;
79 background-image: none;
75 color: @rcblue;
80 color: @grey2;
76
81
77 a {
82 a {
78 color: @rcblue;
83 color: @grey2;
79 }
84 }
80
85
81 &:hover,
86 &:hover,
82 &.active {
87 &.active {
83 color: white;
88 color: @rcdarkblue;
84 background-color: @rcdarkblue;
89 background-color: @white;
85 .border ( @border-thickness, @rcdarkblue );
90 .border ( @border-thickness, @grey4 );
86
91
87 a {
92 a {
88 color: white;
93 color: @grey2;
89 }
94 }
90 }
95 }
91 &:disabled {
96 &:disabled {
92 .border ( @border-thickness-buttons, @grey4 );
97 .border ( @border-thickness-buttons, @grey5 );
93 background-color: transparent;
98 background-color: transparent;
94 }
99 }
95 }
100 }
@@ -326,6 +331,7 b' input[type="submit"] {'
326 .border ( @border-thickness-buttons, @rcblue );
331 .border ( @border-thickness-buttons, @rcblue );
327 background-color: @rcblue;
332 background-color: @rcblue;
328 color: white;
333 color: white;
334 opacity: 0.5;
329 }
335 }
330 }
336 }
331
337
@@ -416,3 +422,23 b' input[type="reset"] {'
416 }
422 }
417 }
423 }
418
424
425
426 .button-links {
427 float: left;
428 display: inline;
429 margin: 0;
430 padding-left: 0;
431 list-style: none;
432 text-align: right;
433
434 li {
435
436
437 }
438
439 li.active {
440 background-color: @grey6;
441 .border ( @border-thickness, @grey4 );
442 }
443
444 }
@@ -404,12 +404,9 b' div.codeblock {'
404
404
405 // TODO: johbo: Added interim to get rid of the margin around
405 // TODO: johbo: Added interim to get rid of the margin around
406 // Select2 widgets. This needs further cleanup.
406 // Select2 widgets. This needs further cleanup.
407 margin-top: @padding;
408
409 overflow: auto;
407 overflow: auto;
410 padding: 0px;
408 padding: 0px;
411 border: @border-thickness solid @grey5;
409 border: @border-thickness solid @grey6;
412 background: @grey6;
413 .border-radius(@border-radius);
410 .border-radius(@border-radius);
414
411
415 #remove_gist {
412 #remove_gist {
@@ -479,7 +476,7 b' div.codeblock {'
479 }
476 }
480
477
481 .code-body {
478 .code-body {
482 padding: @padding;
479 padding: 0.8em 1em;
483 background-color: #ffffff;
480 background-color: #ffffff;
484 min-width: 100%;
481 min-width: 100%;
485 box-sizing: border-box;
482 box-sizing: border-box;
@@ -492,6 +489,21 b' div.codeblock {'
492 height: auto;
489 height: auto;
493 width: 100%;
490 width: 100%;
494 }
491 }
492
493 .markdown-block {
494 padding: 1em 0;
495 }
496 }
497
498 .codeblock-header {
499 background: @grey7;
500 height: 36px;
501 }
502
503 .path {
504 border-bottom: 1px solid @grey6;
505 padding: .65em 1em;
506 height: 18px;
495 }
507 }
496 }
508 }
497
509
@@ -27,7 +27,7 b''
27
27
28 .CodeMirror-gutters {
28 .CodeMirror-gutters {
29 border-right: 1px solid #ddd;
29 border-right: 1px solid #ddd;
30 background-color: @grey6;
30 background-color: white;
31 white-space: nowrap;
31 white-space: nowrap;
32 }
32 }
33 .CodeMirror-linenumbers {}
33 .CodeMirror-linenumbers {}
@@ -14,7 +14,7 b' tr.inline-comments div {'
14 max-width: 100%;
14 max-width: 100%;
15
15
16 p {
16 p {
17 white-space: normal;
17 white-space: normal;
18 }
18 }
19
19
20 code, pre, .code, dd {
20 code, pre, .code, dd {
@@ -227,7 +227,7 b' tr.inline-comments div {'
227 .delete-comment {
227 .delete-comment {
228 display: inline-block;
228 display: inline-block;
229 color: @rcblue;
229 color: @rcblue;
230
230
231 &:hover {
231 &:hover {
232 cursor: pointer;
232 cursor: pointer;
233 }
233 }
@@ -377,13 +377,13 b' form.comment-form {'
377 position: relative;
377 position: relative;
378 width: 100%;
378 width: 100%;
379 min-height: 42px;
379 min-height: 42px;
380
380
381 .status_box,
381 .status_box,
382 .cancel-button {
382 .cancel-button {
383 float: left;
383 float: left;
384 display: inline-block;
384 display: inline-block;
385 }
385 }
386
386
387 .action-buttons {
387 .action-buttons {
388 float: right;
388 float: right;
389 display: inline-block;
389 display: inline-block;
@@ -426,10 +426,10 b' form.comment-form {'
426
426
427 .comment-form-login {
427 .comment-form-login {
428 .comment-help {
428 .comment-help {
429 padding: 0.9em; //same as the button
429 padding: 0.7em; //same as the button
430 }
430 }
431
431
432 div.clearfix {
432 div.clearfix {
433 clear: both;
433 clear: both;
434 width: 100%;
434 width: 100%;
435 display: block;
435 display: block;
@@ -38,7 +38,7 b''
38
38
39 .form-control {
39 .form-control {
40 width: 100%;
40 width: 100%;
41 padding: 0.9em;
41 padding: 0.7em;
42 border: 1px solid #979797;
42 border: 1px solid #979797;
43 border-radius: 2px;
43 border-radius: 2px;
44 }
44 }
@@ -60,13 +60,13 b' form.rcform {'
60 max-width: 500px;
60 max-width: 500px;
61 margin: 0 0 @padding -@legend-width;
61 margin: 0 0 @padding -@legend-width;
62 padding: 0 0 0 @legend-width;
62 padding: 0 0 0 @legend-width;
63
63
64 .btn {
64 .btn {
65 display: inline-block;
65 display: inline-block;
66 margin: 0 1em @padding 0;
66 margin: 0 1em @padding 0;
67 }
67 }
68 }
68 }
69
69
70 input,
70 input,
71 textarea {
71 textarea {
72 float: left;
72 float: left;
@@ -113,7 +113,7 b' form.rcform {'
113 opacity: 0.5;
113 opacity: 0.5;
114 }
114 }
115 }
115 }
116
116
117 input[type="radio"]:not(#ie),
117 input[type="radio"]:not(#ie),
118 input[type="checkbox"]:not(#ie) {
118 input[type="checkbox"]:not(#ie) {
119 // Hide the input, but have it still be clickable
119 // Hide the input, but have it still be clickable
@@ -187,13 +187,13 b' form.rcform {'
187 filter: progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand', M11=0.7071067811865476, M12=-0.7071067811865475, M21=0.7071067811865475, M22=0.7071067811865476); /* IE6,IE7 */
187 filter: progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand', M11=0.7071067811865476, M12=-0.7071067811865475, M21=0.7071067811865475, M22=0.7071067811865476); /* IE6,IE7 */
188
188
189 -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(SizingMethod='auto expand', M11=0.7071067811865476, M12=-0.7071067811865475, M21=0.7071067811865475, M22=0.7071067811865476)"; /* IE8 */ }
189 -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(SizingMethod='auto expand', M11=0.7071067811865476, M12=-0.7071067811865475, M21=0.7071067811865475, M22=0.7071067811865476)"; /* IE8 */ }
190
190
191 & + .label {
191 & + .label {
192 float: left;
192 float: left;
193 margin-top: 5px
193 margin-top: 5px
194 }
194 }
195 }
195 }
196
196
197 input[type=checkbox]:not(#ie) {
197 input[type=checkbox]:not(#ie) {
198 visibility: hidden;
198 visibility: hidden;
199 &:checked + label:after {
199 &:checked + label:after {
@@ -231,6 +231,11 b' form.rcform {'
231
231
232 .drop-menu {
232 .drop-menu {
233 float: left;
233 float: left;
234
235 & + .last-item {
236 margin: 0;
237 }
238
234 margin: 0 @input-padding 0 0;
239 margin: 0 @input-padding 0 0;
235 }
240 }
236
241
@@ -244,7 +249,7 b' form.rcform {'
244 .error-message {
249 .error-message {
245 margin-top: 5px;
250 margin-top: 5px;
246 }
251 }
247
252
248 input[type=submit] {
253 input[type=submit] {
249 &:extend(.btn-primary);
254 &:extend(.btn-primary);
250
255
@@ -271,14 +276,15 b' form.rcform {'
271 .badged-field {
276 .badged-field {
272 .user-badge {
277 .user-badge {
273 line-height: 25px;
278 line-height: 25px;
274 padding: 10px 5px;
279 padding: .4em;
275 border-radius: @border-radius;
280 border-radius: @border-radius;
276 border-top: 1px solid @rclightblue;
281 border-top: 1px solid @grey4;
277 border-left: 1px solid @rclightblue;
282 border-left: 1px solid @grey4;
278 border-bottom: 1px solid @rclightblue;
283 border-bottom: 1px solid @grey4;
279 font-size: 14px;
284 font-size: 14px;
280 font-style: normal;
285 font-style: normal;
281 color: @text-light;
286 color: @text-light;
287 background: @grey7;
282 display: inline-block;
288 display: inline-block;
283 vertical-align: top;
289 vertical-align: top;
284 cursor: default;
290 cursor: default;
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
1 NO CONTENT: file renamed from rhodecode/public/images/rhodecode-logo-white-216x60.png to rhodecode/public/images/rhodecode-logo-white-60x60.png, binary diff hidden
NO CONTENT: file renamed from rhodecode/public/images/rhodecode-logo-white-216x60.png to rhodecode/public/images/rhodecode-logo-white-60x60.png, binary diff hidden
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/changelog/changelog.mako to rhodecode/templates/commits/changelog.mako
NO CONTENT: file renamed from rhodecode/templates/changelog/changelog.mako to rhodecode/templates/commits/changelog.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/changelog/changelog_elements.mako to rhodecode/templates/commits/changelog_elements.mako
NO CONTENT: file renamed from rhodecode/templates/changelog/changelog_elements.mako to rhodecode/templates/commits/changelog_elements.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/changelog/changelog_file_history.mako to rhodecode/templates/commits/changelog_file_history.mako
NO CONTENT: file renamed from rhodecode/templates/changelog/changelog_file_history.mako to rhodecode/templates/commits/changelog_file_history.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/files/files_detail.mako to rhodecode/templates/files/files_source_header.mako
NO CONTENT: file renamed from rhodecode/templates/files/files_detail.mako to rhodecode/templates/files/files_source_header.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/files/file_tree_detail.mako to rhodecode/templates/files/files_tree_header.mako
NO CONTENT: file renamed from rhodecode/templates/files/file_tree_detail.mako to rhodecode/templates/files/files_tree_header.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now