diff --git a/.bumpversion.cfg b/.bumpversion.cfg --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 4.16.2 +current_version = 4.17.0 message = release: Bump version {current_version} to {new_version} [bumpversion:file:rhodecode/VERSION] diff --git a/.release.cfg b/.release.cfg --- a/.release.cfg +++ b/.release.cfg @@ -5,25 +5,20 @@ done = false done = true [task:rc_tools_pinned] -done = true [task:fixes_on_stable] -done = true [task:pip2nix_generated] -done = true [task:changelog_updated] -done = true [task:generate_api_docs] -done = true + +[task:updated_translation] [release] -state = prepared -version = 4.16.2 - -[task:updated_translation] +state = in_progress +version = 4.17.0 [task:generate_js_routes] diff --git a/Makefile b/Makefile --- a/Makefile +++ b/Makefile @@ -53,3 +53,12 @@ web-build: generate-pkgs: nix-shell pkgs/shell-generate.nix --command "pip2nix generate --licenses" + +generate-js-pkgs: + rm -rf node_modules && \ + 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" && \ + sed -i -e 's/http:\/\//https:\/\//g' pkgs/node-packages.nix + +generate-license-meta: + nix-build pkgs/license-generate.nix -o result-license && \ + cat result-license/licenses.json | python -m json.tool > rhodecode/config/licenses.json \ No newline at end of file diff --git a/configs/development.ini b/configs/development.ini --- a/configs/development.ini +++ b/configs/development.ini @@ -133,6 +133,11 @@ rhodecode.api.url = /_admin/api ## `SignatureVerificationError` in case of wrong key, or damaged encryption data. #rhodecode.encrypted_values.strict = false +## Pick algorithm for encryption. Either fernet (more secure) or aes (default) +## fernet is safer, and we strongly recommend switching to it. +## Due to backward compatibility aes is used as default. +#rhodecode.encrypted_values.algorithm = fernet + ## return gzipped responses from RhodeCode (static files/application) gzip_responses = false @@ -374,6 +379,10 @@ rc_cache.cache_repo_longterm.max_size = beaker.session.type = file beaker.session.data_dir = %(here)s/data/sessions +## redis sessions +#beaker.session.type = ext:redis +#beaker.session.url = redis://127.0.0.1:6379/2 + ## db based session, fast, and allows easy management over logged in users #beaker.session.type = ext:database #beaker.session.table_name = db_session diff --git a/configs/gunicorn_config.py b/configs/gunicorn_config.py --- a/configs/gunicorn_config.py +++ b/configs/gunicorn_config.py @@ -30,10 +30,12 @@ loglevel = 'debug' # SECURITY # The maximum size of HTTP request line in bytes. -limit_request_line = 4094 +# 0 for unlimited +limit_request_line = 0 # Limit the number of HTTP headers fields in a request. -limit_request_fields = 1024 +# By default this value is 100 and can’t be larger than 32768. +limit_request_fields = 10240 # Limit the allowed size of an HTTP request header field. # Value is a positive number or 0. diff --git a/configs/production.ini b/configs/production.ini --- a/configs/production.ini +++ b/configs/production.ini @@ -108,6 +108,11 @@ use = egg:rhodecode-enterprise-ce ## `SignatureVerificationError` in case of wrong key, or damaged encryption data. #rhodecode.encrypted_values.strict = false +## Pick algorithm for encryption. Either fernet (more secure) or aes (default) +## fernet is safer, and we strongly recommend switching to it. +## Due to backward compatibility aes is used as default. +#rhodecode.encrypted_values.algorithm = fernet + ## return gzipped responses from RhodeCode (static files/application) gzip_responses = false @@ -349,6 +354,10 @@ rc_cache.cache_repo_longterm.max_size = beaker.session.type = file beaker.session.data_dir = %(here)s/data/sessions +## redis sessions +#beaker.session.type = ext:redis +#beaker.session.url = redis://127.0.0.1:6379/2 + ## db based session, fast, and allows easy management over logged in users #beaker.session.type = ext:database #beaker.session.table_name = db_session diff --git a/default.nix b/default.nix --- a/default.nix +++ b/default.nix @@ -191,7 +191,7 @@ let # check required files STATIC_CHECK="/robots.txt /502.html /js/scripts.js /js/rhodecode-components.js - /css/style.css /css/style-polymer.css" + /css/style.css /css/style-polymer.css /css/style-ipython.css" for file in $STATIC_CHECK; do diff --git a/docs/admin/repo-admin.rst b/docs/admin/repo-admin.rst new file mode 100644 --- /dev/null +++ b/docs/admin/repo-admin.rst @@ -0,0 +1,28 @@ +.. _repo-admin-set: +.. _permissions-info-add-group-ref: + +Repository Administration +========================= + +Repository permissions in |RCE| can be managed in a number of different ways. +This overview should give you an insight into how you could adopt particular +settings for your needs: + +* Global |repo| permissions: This allows you to set the default permissions + for each new |repo| created within |RCE|, see :ref:`repo-default-ref`. All + |repos| created will inherit these permissions unless explicitly configured. +* Individual |repo| permissions: To set individual |repo| permissions, + see :ref:`set-repo-perms`. +* Repository Group permissions: This allows you to define the permissions for + a group, and all |repos| created within that group will inherit the same + permissions. + +.. toctree:: + + repo_admin/repo-perm-steps + repo_admin/repo-extra-fields + repo_admin/repo-hooks + repo_admin/repo-issue-tracker + repo_admin/repo-vcs + repo_admin/restore-deleted-repositories + repo_admin/repo-admin-tasks \ No newline at end of file diff --git a/docs/admin/repo_admin/repo-admin-tasks.rst b/docs/admin/repo_admin/repo-admin-tasks.rst new file mode 100644 --- /dev/null +++ b/docs/admin/repo_admin/repo-admin-tasks.rst @@ -0,0 +1,24 @@ +.. _repo-admin-tasks: + +Common Admin Tasks for Repositories +----------------------------------- + + +Manually Force Delete Repository +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In case of attached forks or pull-requests repositories should be archived. +Here is how to force delete a repository and remove all dependent objects + + +.. code-block:: bash + + # starts the ishell interactive prompt + $ rccontrol ishell enterprise-1 + +.. code-block:: python + + In [4]: from rhodecode.model.repo import RepoModel + In [3]: repo = Repository.get_by_repo_name('test_repos/repo_with_prs') + In [5]: RepoModel().delete(repo, forks='detach', pull_requests='delete') + In [6]: Session().commit() diff --git a/docs/admin/repo-extra-fields.rst b/docs/admin/repo_admin/repo-extra-fields.rst rename from docs/admin/repo-extra-fields.rst rename to docs/admin/repo_admin/repo-extra-fields.rst --- a/docs/admin/repo-extra-fields.rst +++ b/docs/admin/repo_admin/repo-extra-fields.rst @@ -29,7 +29,7 @@ 1. Go to :menuselection:`Admin --> Repos beside the |repo| to which you wish to add extra fields. 2. On the |repo| settings page, select the :guilabel:`Extra fields` tab. -.. image:: ../images/extra-repo-fields.png +.. image:: ../../images/extra-repo-fields.png The most important is the `New field key` variable which under the value will be stored. It needs to be unique for each repository. The label and description diff --git a/docs/admin/repo-hooks.rst b/docs/admin/repo_admin/repo-hooks.rst rename from docs/admin/repo-hooks.rst rename to docs/admin/repo_admin/repo-hooks.rst diff --git a/docs/admin/repo-issue-tracker.rst b/docs/admin/repo_admin/repo-issue-tracker.rst rename from docs/admin/repo-issue-tracker.rst rename to docs/admin/repo_admin/repo-issue-tracker.rst diff --git a/docs/admin/repo-perm-steps.rst b/docs/admin/repo_admin/repo-perm-steps.rst rename from docs/admin/repo-perm-steps.rst rename to docs/admin/repo_admin/repo-perm-steps.rst diff --git a/docs/admin/repo-vcs.rst b/docs/admin/repo_admin/repo-vcs.rst rename from docs/admin/repo-vcs.rst rename to docs/admin/repo_admin/repo-vcs.rst diff --git a/docs/admin/restore-deleted-repositories.rst b/docs/admin/repo_admin/restore-deleted-repositories.rst rename from docs/admin/restore-deleted-repositories.rst rename to docs/admin/repo_admin/restore-deleted-repositories.rst diff --git a/docs/admin/setting-repo-perms.rst b/docs/admin/setting-repo-perms.rst deleted file mode 100644 --- a/docs/admin/setting-repo-perms.rst +++ /dev/null @@ -1,26 +0,0 @@ -.. _permissions-info-add-group-ref: - -Repository Administration -========================= - -Repository permissions in |RCE| can be managed in a number of different ways. -This overview should give you an insight into how you could adopt particular -settings for your needs: - -* Global |repo| permissions: This allows you to set the default permissions - for each new |repo| created within |RCE|, see :ref:`repo-default-ref`. All - |repos| created will inherit these permissions unless explicitly configured. -* Individual |repo| permissions: To set individual |repo| permissions, - see :ref:`set-repo-perms`. -* Repository Group permissions: This allows you to define the permissions for - a group, and all |repos| created within that group will inherit the same - permissions. - -.. toctree:: - - repo-perm-steps - repo-extra-fields - repo-hooks - repo-issue-tracker - repo-vcs - diff --git a/docs/admin/system-admin.rst b/docs/admin/system-admin.rst --- a/docs/admin/system-admin.rst +++ b/docs/admin/system-admin.rst @@ -16,19 +16,17 @@ The following are the most common system .. toctree:: - config-files-overview - vcs-server - svn-http - svn-path-permissions - gunicorn-ssl-support - apache-config - nginx-config - backup-restore - tuning-rhodecode - indexing - reset-information - enable-debug - admin-tricks - cleanup-cmds - restore-deleted-repositories - + system_admin/config-files-overview + system_admin/vcs-server + system_admin/svn-http + system_admin/svn-path-permissions + system_admin/gunicorn-ssl-support + system_admin/apache-config + system_admin/nginx-config + system_admin/backup-restore + system_admin/tuning-rhodecode + system_admin/indexing + system_admin/reset-information + system_admin/enable-debug + system_admin/admin-tricks + system_admin/cleanup-cmds diff --git a/docs/admin/admin-tricks.rst b/docs/admin/system_admin/admin-tricks.rst rename from docs/admin/admin-tricks.rst rename to docs/admin/system_admin/admin-tricks.rst --- a/docs/admin/admin-tricks.rst +++ b/docs/admin/system_admin/admin-tricks.rst @@ -57,7 +57,7 @@ 2. To add a message that will be display 3. Select :guilabel:`Save`, and you will see the message once your page refreshes. -.. image:: ../images/server-wide-announcement.png +.. image:: ../../images/server-wide-announcement.png :alt: Server Wide Announcement .. _md-rst: @@ -207,7 +207,7 @@ 2. Restart the |RCE| instance and check Instance "enterprise-2" successfully stopped. Instance "enterprise-2" successfully started. -.. image:: ../images/language.png +.. image:: ../../images/language.png .. _set-repo-pub: @@ -239,3 +239,26 @@ following URL: ``{instance-URL}/_admin/p .. _Markdown: http://daringfireball.net/projects/markdown/ .. _reStructured Text: http://docutils.sourceforge.net/docs/index.html + + +Unarchiving a repository +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Archive operation for the repository is similar as delete. Archive keeps the data for future references +but makes the repository read-only. After archiving the repository it shouldn't be modified in any way. +This is why repository settings are disabled for an archived repository. + +If there's a need for unarchiving a repository for some reasons, the interactive +ishell interface should be used. + +.. code-block:: bash + + # Open iShell from the terminal + $ rccontrol ishell enterprise-1/community-1 + +.. code-block:: python + + # Set repository as un-archived + In [1]: repo = Repository.get_by_repo_name('SOME_REPO_NAME') + In [2]: repo.archived = False + In [3]: Session().add(repo);Session().commit() diff --git a/docs/admin/apache-config.rst b/docs/admin/system_admin/apache-config.rst rename from docs/admin/apache-config.rst rename to docs/admin/system_admin/apache-config.rst --- a/docs/admin/apache-config.rst +++ b/docs/admin/system_admin/apache-config.rst @@ -8,7 +8,7 @@ the information in the following section .. toctree:: - apache-conf-example - apache-diffie-hellman - apache-subdirectory - apache-wsgi-coding + apache/apache-conf-example + apache/apache-diffie-hellman + apache/apache-subdirectory + apache/apache-wsgi-coding diff --git a/docs/admin/apache-conf-example.rst b/docs/admin/system_admin/apache/apache-conf-example.rst rename from docs/admin/apache-conf-example.rst rename to docs/admin/system_admin/apache/apache-conf-example.rst --- a/docs/admin/apache-conf-example.rst +++ b/docs/admin/system_admin/apache/apache-conf-example.rst @@ -66,14 +66,18 @@ Below config if for an Apache Reverse Pr # Directive to properly generate url (clone url) for RhodeCode ProxyPreserveHost On + # It allows request bodies to be sent to the backend using chunked transfer encoding. + SetEnv proxy-sendchunked 1 + + # Increase headers size for large Mercurial headers sent with many branches + LimitRequestLine 16380 + # Url to running RhodeCode instance. This is shown as `- URL:` when # running rccontrol status. + ProxyPass / http://127.0.0.1:10002/ timeout=7200 Keepalive=On ProxyPassReverse / http://127.0.0.1:10002/ - # Increase headers for large Mercurial headers - LimitRequestLine 16380 - # strict http prevents from https -> http downgrade Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload" diff --git a/docs/admin/apache-diffie-hellman.rst b/docs/admin/system_admin/apache/apache-diffie-hellman.rst rename from docs/admin/apache-diffie-hellman.rst rename to docs/admin/system_admin/apache/apache-diffie-hellman.rst diff --git a/docs/admin/apache-subdirectory.rst b/docs/admin/system_admin/apache/apache-subdirectory.rst rename from docs/admin/apache-subdirectory.rst rename to docs/admin/system_admin/apache/apache-subdirectory.rst diff --git a/docs/admin/apache-wsgi-coding.rst b/docs/admin/system_admin/apache/apache-wsgi-coding.rst rename from docs/admin/apache-wsgi-coding.rst rename to docs/admin/system_admin/apache/apache-wsgi-coding.rst diff --git a/docs/admin/backup-restore.rst b/docs/admin/system_admin/backup-restore.rst rename from docs/admin/backup-restore.rst rename to docs/admin/system_admin/backup-restore.rst diff --git a/docs/admin/cleanup-cmds.rst b/docs/admin/system_admin/cleanup-cmds.rst rename from docs/admin/cleanup-cmds.rst rename to docs/admin/system_admin/cleanup-cmds.rst diff --git a/docs/admin/config-files-overview.rst b/docs/admin/system_admin/config-files-overview.rst rename from docs/admin/config-files-overview.rst rename to docs/admin/system_admin/config-files-overview.rst diff --git a/docs/admin/enable-debug.rst b/docs/admin/system_admin/enable-debug.rst rename from docs/admin/enable-debug.rst rename to docs/admin/system_admin/enable-debug.rst diff --git a/docs/admin/gunicorn-ssl-support.rst b/docs/admin/system_admin/gunicorn-ssl-support.rst rename from docs/admin/gunicorn-ssl-support.rst rename to docs/admin/system_admin/gunicorn-ssl-support.rst diff --git a/docs/admin/indexing.rst b/docs/admin/system_admin/indexing.rst rename from docs/admin/indexing.rst rename to docs/admin/system_admin/indexing.rst diff --git a/docs/admin/nginx-config.rst b/docs/admin/system_admin/nginx-config.rst rename from docs/admin/nginx-config.rst rename to docs/admin/system_admin/nginx-config.rst --- a/docs/admin/nginx-config.rst +++ b/docs/admin/system_admin/nginx-config.rst @@ -8,7 +8,7 @@ the information in the following section .. toctree:: - nginx-config-example - nginx-diffie-hellman - nginx-proxy-conf - nginx-url-prefix + nginx/nginx-config-example + nginx/nginx-diffie-hellman + nginx/nginx-proxy-conf + nginx/nginx-url-prefix diff --git a/docs/admin/nginx-config-example.rst b/docs/admin/system_admin/nginx/nginx-config-example.rst rename from docs/admin/nginx-config-example.rst rename to docs/admin/system_admin/nginx/nginx-config-example.rst diff --git a/docs/admin/nginx-diffie-hellman.rst b/docs/admin/system_admin/nginx/nginx-diffie-hellman.rst rename from docs/admin/nginx-diffie-hellman.rst rename to docs/admin/system_admin/nginx/nginx-diffie-hellman.rst diff --git a/docs/admin/nginx-proxy-conf.rst b/docs/admin/system_admin/nginx/nginx-proxy-conf.rst rename from docs/admin/nginx-proxy-conf.rst rename to docs/admin/system_admin/nginx/nginx-proxy-conf.rst diff --git a/docs/admin/nginx-url-prefix.rst b/docs/admin/system_admin/nginx/nginx-url-prefix.rst rename from docs/admin/nginx-url-prefix.rst rename to docs/admin/system_admin/nginx/nginx-url-prefix.rst diff --git a/docs/admin/reset-information.rst b/docs/admin/system_admin/reset-information.rst rename from docs/admin/reset-information.rst rename to docs/admin/system_admin/reset-information.rst diff --git a/docs/admin/svn-http.rst b/docs/admin/system_admin/svn-http.rst rename from docs/admin/svn-http.rst rename to docs/admin/system_admin/svn-http.rst diff --git a/docs/admin/svn-path-permissions.rst b/docs/admin/system_admin/svn-path-permissions.rst rename from docs/admin/svn-path-permissions.rst rename to docs/admin/system_admin/svn-path-permissions.rst diff --git a/docs/admin/tuning-rhodecode.rst b/docs/admin/system_admin/tuning-rhodecode.rst rename from docs/admin/tuning-rhodecode.rst rename to docs/admin/system_admin/tuning-rhodecode.rst --- a/docs/admin/tuning-rhodecode.rst +++ b/docs/admin/system_admin/tuning-rhodecode.rst @@ -8,14 +8,14 @@ may find some of the following methods u .. toctree:: - tuning-gunicorn - tuning-vcs-memory-cache - tuning-user-sessions-performance - tuning-increase-db-performance - tuning-scale-horizontally-cluster - tuning-mount-cache-memory - tuning-change-encoding - tuning-change-large-file-dir - tuning-change-lfs-dir - tuning-hg-auth-loop + tuning/tuning-gunicorn + tuning/tuning-vcs-memory-cache + tuning/tuning-user-sessions-performance + tuning/tuning-increase-db-performance + tuning/tuning-scale-horizontally-cluster + tuning/tuning-mount-cache-memory + tuning/tuning-change-encoding + tuning/tuning-change-large-file-dir + tuning/tuning-change-lfs-dir + tuning/tuning-hg-auth-loop diff --git a/docs/admin/tuning-change-encoding.rst b/docs/admin/system_admin/tuning/tuning-change-encoding.rst rename from docs/admin/tuning-change-encoding.rst rename to docs/admin/system_admin/tuning/tuning-change-encoding.rst diff --git a/docs/admin/tuning-change-large-file-dir.rst b/docs/admin/system_admin/tuning/tuning-change-large-file-dir.rst rename from docs/admin/tuning-change-large-file-dir.rst rename to docs/admin/system_admin/tuning/tuning-change-large-file-dir.rst diff --git a/docs/admin/tuning-change-lfs-dir.rst b/docs/admin/system_admin/tuning/tuning-change-lfs-dir.rst rename from docs/admin/tuning-change-lfs-dir.rst rename to docs/admin/system_admin/tuning/tuning-change-lfs-dir.rst diff --git a/docs/admin/tuning-gunicorn.rst b/docs/admin/system_admin/tuning/tuning-gunicorn.rst rename from docs/admin/tuning-gunicorn.rst rename to docs/admin/system_admin/tuning/tuning-gunicorn.rst --- a/docs/admin/tuning-gunicorn.rst +++ b/docs/admin/system_admin/tuning/tuning-gunicorn.rst @@ -42,7 +42,7 @@ 2. In the ``[server:main]`` section, cha ## restarted, could prevent memory leaks max_requests = 1000 max_requests_jitter = 30 - ## amount of time a worker can spend with handling a request before it + ## amount of time a worker can spend with handling a request tuning-change-lfs-dir.before it ## gets killed and restarted. Set to 6hrs timeout = 21600 diff --git a/docs/admin/tuning-hg-auth-loop.rst b/docs/admin/system_admin/tuning/tuning-hg-auth-loop.rst rename from docs/admin/tuning-hg-auth-loop.rst rename to docs/admin/system_admin/tuning/tuning-hg-auth-loop.rst diff --git a/docs/admin/tuning-increase-db-performance.rst b/docs/admin/system_admin/tuning/tuning-increase-db-performance.rst rename from docs/admin/tuning-increase-db-performance.rst rename to docs/admin/system_admin/tuning/tuning-increase-db-performance.rst diff --git a/docs/admin/tuning-mount-cache-memory.rst b/docs/admin/system_admin/tuning/tuning-mount-cache-memory.rst rename from docs/admin/tuning-mount-cache-memory.rst rename to docs/admin/system_admin/tuning/tuning-mount-cache-memory.rst diff --git a/docs/admin/tuning-scale-horizontally-cluster.rst b/docs/admin/system_admin/tuning/tuning-scale-horizontally-cluster.rst rename from docs/admin/tuning-scale-horizontally-cluster.rst rename to docs/admin/system_admin/tuning/tuning-scale-horizontally-cluster.rst diff --git a/docs/admin/tuning-user-sessions-performance.rst b/docs/admin/system_admin/tuning/tuning-user-sessions-performance.rst rename from docs/admin/tuning-user-sessions-performance.rst rename to docs/admin/system_admin/tuning/tuning-user-sessions-performance.rst diff --git a/docs/admin/tuning-vcs-memory-cache.rst b/docs/admin/system_admin/tuning/tuning-vcs-memory-cache.rst rename from docs/admin/tuning-vcs-memory-cache.rst rename to docs/admin/system_admin/tuning/tuning-vcs-memory-cache.rst diff --git a/docs/admin/vcs-server.rst b/docs/admin/system_admin/vcs-server.rst rename from docs/admin/vcs-server.rst rename to docs/admin/system_admin/vcs-server.rst diff --git a/docs/admin/user-admin.rst b/docs/admin/user-admin.rst --- a/docs/admin/user-admin.rst +++ b/docs/admin/user-admin.rst @@ -13,11 +13,12 @@ permissions applied to it; |perm|. .. toctree:: - public-access - default-user-perms - adding-anonymous-user - adding-new-user - setting-default-permissions - setting-usergroup-permissions + user_admin/public-access + user_admin/default-user-perms + user_admin/adding-anonymous-user + user_admin/adding-new-user + user_admin/setting-default-permissions + user_admin/setting-usergroup-permissions + user_admin/user-admin-tasks -.. |perm| replace:: **None**, **Read**, **Write**, or **Admin** \ No newline at end of file +.. |perm| replace:: **None**, **Read**, **Write**, or **Admin** diff --git a/docs/admin/adding-anonymous-user.rst b/docs/admin/user_admin/adding-anonymous-user.rst rename from docs/admin/adding-anonymous-user.rst rename to docs/admin/user_admin/adding-anonymous-user.rst diff --git a/docs/admin/adding-new-user.rst b/docs/admin/user_admin/adding-new-user.rst rename from docs/admin/adding-new-user.rst rename to docs/admin/user_admin/adding-new-user.rst diff --git a/docs/admin/default-user-perms.rst b/docs/admin/user_admin/default-user-perms.rst rename from docs/admin/default-user-perms.rst rename to docs/admin/user_admin/default-user-perms.rst diff --git a/docs/admin/public-access.rst b/docs/admin/user_admin/public-access.rst rename from docs/admin/public-access.rst rename to docs/admin/user_admin/public-access.rst diff --git a/docs/admin/setting-default-permissions.rst b/docs/admin/user_admin/setting-default-permissions.rst rename from docs/admin/setting-default-permissions.rst rename to docs/admin/user_admin/setting-default-permissions.rst diff --git a/docs/admin/setting-usergroup-permissions.rst b/docs/admin/user_admin/setting-usergroup-permissions.rst rename from docs/admin/setting-usergroup-permissions.rst rename to docs/admin/user_admin/setting-usergroup-permissions.rst diff --git a/docs/admin/user_admin/user-admin-tasks.rst b/docs/admin/user_admin/user-admin-tasks.rst new file mode 100644 --- /dev/null +++ b/docs/admin/user_admin/user-admin-tasks.rst @@ -0,0 +1,24 @@ +.. _user-admin-tasks: + +Common Admin Tasks for Users +---------------------------- + + +Manually Set Personal Repository Group +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Here is how to set a repository group as personal for a user using ishell. + + +.. code-block:: bash + + # starts the ishell interactive prompt + $ rccontrol ishell enterprise-1 + +.. code-block:: python + + In [1]: repo_group = RepoGroup.get_by_group_name('some_group_name') + In [2]: user = User.get_by_username('some_user') + In [3]: repo_group.user = user + In [4]: repo_group.personal = True + In [5]: Session().add(repo_group);Session().commit() diff --git a/docs/api/api.rst b/docs/api/api.rst --- a/docs/api/api.rst +++ b/docs/api/api.rst @@ -204,6 +204,7 @@ are not required in args. methods/pull-request-methods methods/repo-methods methods/repo-group-methods + methods/search-methods methods/server-methods methods/user-methods methods/user-group-methods diff --git a/docs/api/methods/repo-methods.rst b/docs/api/methods/repo-methods.rst --- a/docs/api/methods/repo-methods.rst +++ b/docs/api/methods/repo-methods.rst @@ -462,6 +462,7 @@ get_repo_file :param cache: Use internal caches for fetching files. If disabled fetching files is slower but more memory efficient :type cache: Optional(bool) + Example output: .. code-block:: bash @@ -499,53 +500,51 @@ get_repo_nodes .. py:function:: get_repo_nodes(apiuser, repoid, revision, root_path, ret_type=, details=, max_file_bytes=) Returns a list of nodes and children in a flat list for a given - path at given revision. + path at given revision. - It's possible to specify ret_type to show only `files` or `dirs`. + It's possible to specify ret_type to show only `files` or `dirs`. - This command can only be run using an |authtoken| with admin rights, - or users with at least read rights to |repos|. + This command can only be run using an |authtoken| with admin rights, + or users with at least read rights to |repos|. - :param apiuser: This is filled automatically from the |authtoken|. - :type apiuser: AuthUser - :param repoid: The repository name or repository ID. - :type repoid: str or int - :param revision: The revision for which listing should be done. - :type revision: str - :param root_path: The path from which to start displaying. - :type root_path: str - :param ret_type: Set the return type. Valid options are - ``all`` (default), ``files`` and ``dirs``. - :type ret_type: Optional(str) - :param details: Returns extended information about nodes, such as - md5, binary, and or content. - The valid options are ``basic`` and ``full``. - :type details: Optional(str) - :param max_file_bytes: Only return file content under this file size bytes - :type details: Optional(int) - - Example output: + :param apiuser: This is filled automatically from the |authtoken|. + :type apiuser: AuthUser + :param repoid: The repository name or repository ID. + :type repoid: str or int + :param revision: The revision for which listing should be done. + :type revision: str + :param root_path: The path from which to start displaying. + :type root_path: str + :param ret_type: Set the return type. Valid options are + ``all`` (default), ``files`` and ``dirs``. + :type ret_type: Optional(str) + :param details: Returns extended information about nodes, such as + md5, binary, and or content. + The valid options are ``basic`` and ``full``. + :type details: Optional(str) + :param max_file_bytes: Only return file content under this file size bytes + :type details: Optional(int) - .. code-block:: bash + Example output: + + .. code-block:: bash - id : - result: [ - { - "binary": false, - "content": "File line - Line2 - ", - "extension": "md", - "lines": 2, - "md5": "059fa5d29b19c0657e384749480f6422", - "mimetype": "text/x-minidsrc", - "name": "file.md", - "size": 580, - "type": "file" - }, - ... - ] - error: null + id : + result: [ + { + "binary": false, + "content": "File line", + "extension": "md", + "lines": 2, + "md5": "059fa5d29b19c0657e384749480f6422", + "mimetype": "text/x-minidsrc", + "name": "file.md", + "size": 580, + "type": "file" + }, + ... + ] + error: null get_repo_refs diff --git a/docs/api/methods/search-methods.rst b/docs/api/methods/search-methods.rst new file mode 100644 --- /dev/null +++ b/docs/api/methods/search-methods.rst @@ -0,0 +1,35 @@ +.. _search-methods-ref: + +search methods +============== + +search +------ + +.. py:function:: search(apiuser, search_query, search_type, page_limit=, page=, search_sort=, repo_name=, repo_group_name=) + + Fetch Full Text Search results using API. + + :param apiuser: This is filled automatically from the |authtoken|. + :type apiuser: AuthUser + :param search_query: Search query. + :type search_query: str + :param search_type: Search type. The following are valid options: + * commit + * content + * path + :type search_type: str + :param page_limit: Page item limit, from 1 to 500. Default 10 items. + :type page_limit: Optional(int) + :param page: Page number. Default first page. + :type page: Optional(int) + :param search_sort: Search sort order. Default newfirst. The following are valid options: + * newfirst + * oldfirst + :type search_sort: Optional(str) + :param repo_name: Filter by one repo. Default is all. + :type repo_name: Optional(str) + :param repo_group_name: Filter by one repo group. Default is all. + :type repo_group_name: Optional(str) + + diff --git a/docs/auth/auth-saml-bulk-enroll-users.rst b/docs/auth/auth-saml-bulk-enroll-users.rst --- a/docs/auth/auth-saml-bulk-enroll-users.rst +++ b/docs/auth/auth-saml-bulk-enroll-users.rst @@ -32,9 +32,9 @@ The most important this id needs to be u In [1]: saml2user = { ...: # OneLogin, uses externalID available to read from in the UI - ...: 123: {'id: '48253211'}, + ...: 123: {'id': '48253211'}, ...: # for Google/DuoSecurity email is also an option for unique ID - ...: 124: {'id: 'email@domain.com'}, + ...: 124: {'id': 'email@domain.com'}, ...: } @@ -70,7 +70,7 @@ Enter in the ishell prompt ...: new_external_identity.external_id = external_id ...: new_external_identity.external_username = '{}-saml-{}'.format(user.username, user.user_id) ...: new_external_identity.provider_name = provider - ...: new_external_identity.local_user_id = user_id + ...: new_external_identity.local_user_id = user.user_id ...: new_external_identity.access_token = '' ...: new_external_identity.token_secret = '' ...: new_external_identity.alt_token = '' diff --git a/docs/index.rst b/docs/index.rst --- a/docs/index.rst +++ b/docs/index.rst @@ -46,7 +46,7 @@ and commit files and |repos| while manag nix/default-env admin/system-admin admin/user-admin - admin/setting-repo-perms + admin/repo-admin admin/security-tips auth/auth issue-trackers/issue-trackers @@ -64,6 +64,13 @@ and commit files and |repos| while manag .. toctree:: :maxdepth: 1 + :caption: User Documentation + + usage/basic-usage + tutorials/tutorials + +.. toctree:: + :maxdepth: 1 :caption: Developer Documentation api/api @@ -73,13 +80,6 @@ and commit files and |repos| while manag .. toctree:: :maxdepth: 1 - :caption: User Documentation - - usage/basic-usage - tutorials/tutorials - -.. toctree:: - :maxdepth: 1 :caption: About known-issues/known-issues diff --git a/docs/release-notes/release-notes-4.17.0.rst b/docs/release-notes/release-notes-4.17.0.rst new file mode 100644 --- /dev/null +++ b/docs/release-notes/release-notes-4.17.0.rst @@ -0,0 +1,85 @@ +|RCE| 4.17.0 |RNS| +------------------ + +Release Date +^^^^^^^^^^^^ + +- 2019-07-04 + + +New Features +^^^^^^^^^^^^ + +- New artifacts feature. + Ability to store binary artifacts for repository with ACL +- UI/UX refresh for most of the pages. This includes multiple fixes and improvements. +- Diffs: store wide-diff mode in user sessions to store user preference for diff display. +- Mercurial: added support for Mercurial 4.9 +- API: Added search API methods +- Files: adding/editing allows previews for generated content. +- Files: allowed multi file upload using UI. +- Repository Groups: last change is now smartly calculated based on latest change + from all it's children repositories. +- Archives: it's now currently possible to download partial directories from files view. +- SVN: allowed executing pre-commit code with rcextensions, also added example to + validate SVN file size and paths on pre-commit level. + + +General +^^^^^^^ +- Exception store: add filter for display and deletion. +- Files: loading history doesn't display hidden and obsolete commits anymore. +- Repositories: bring back missing watch action in summary view. +- Admin: user groups is now using pure DB filtering to speed up display + for large number of groups. +- Mercurial: enabled full evolve+topic extensions when evolve is enabled. +- Dependencies: bumped evolve to 8.5.1 +- Dependencies: bumped pyramid to 1.10.4 +- Dependencies: bumped psutil to 5.5.1 +- Dependencies: bumped pygments to 2.4.2 +- Dependencies: bumped pyramid to 1.10.4 +- Dependencies: bumped psycopg2 to 2.8.3 +- Dependencies [security]: updated colander to 1.7.0 + + +Security +^^^^^^^^ + +- SSH: replaced pycrypto with cryptography to generate SSH keys as pycrypto isn't + considered safe anymore. + + +Performance +^^^^^^^^^^^ + +- Config: updated header limits on gunicorn to prevent errors on large Mercurial repositories. +- User sessions: added option to cleanup redis based sessions in user session interface. +- Authentication: reduced usage of raw auth calls inside templates to speed up rendering. +- Sessions: don't touch session for API calls. Before each API call created new session + object which wasn't required. + + +Fixes +^^^^^ + +- hHooks: fixed more unicode problems with new pull-request link generator. +- Mercurial: fix ssh-server support for mercurial custom options. +- Pull requests: updated metadata information for failed merges with multiple heads. +- Pull requests: calculate ancestor in the same way as creation mode. + Fixed problem with updates generating wrong diffs in case of merges. +- Pull requests: fixed a bug in removal of multiple reviewers at once. +- Summary: fix timeout issues loading summary page without styling. +- SSH: fix invocation of custom hgrc. +- SSH: call custom hooks via SSH backend +- Markup: fix styling for check-lists. +- Archives: allows downloading refs that have slashes and special refs. e.g f/feat1 branch names. +- Files: ensure we generate archives with consistent hashing (except for .tar.gz which uses temp files names in header) +- Files: fixed rendering of readme files under non-ascii paths. + + +Upgrade notes +^^^^^^^^^^^^^ + +- In this release we introduced new UI across the application. + In case of problems with the display on your systems please send us info to support@rhodecode.com. + diff --git a/docs/release-notes/release-notes.rst b/docs/release-notes/release-notes.rst --- a/docs/release-notes/release-notes.rst +++ b/docs/release-notes/release-notes.rst @@ -9,6 +9,7 @@ Release Notes .. toctree:: :maxdepth: 1 + release-notes-4.17.0.rst release-notes-4.16.2.rst release-notes-4.16.1.rst release-notes-4.16.0.rst diff --git a/grunt_config.json b/grunt_config.json --- a/grunt_config.json +++ b/grunt_config.json @@ -35,6 +35,7 @@ "<%= dirs.js.node_modules %>/moment/min/moment.min.js", "<%= dirs.js.node_modules %>/clipboard/dist/clipboard.min.js", "<%= dirs.js.node_modules %>/favico.js/favico-0.3.10.min.js", + "<%= dirs.js.node_modules %>/dropzone/dist/dropzone.js", "<%= dirs.js.node_modules %>/sticky-sidebar/dist/sticky-sidebar.min.js", "<%= dirs.js.node_modules %>/sticky-sidebar/dist/jquery.sticky-sidebar.min.js", "<%= dirs.js.node_modules %>/waypoints/lib/noframework.waypoints.min.js", @@ -107,7 +108,8 @@ }, "files": { "<%= dirs.css.dest %>/style.css": "<%= dirs.css.src %>/main.less", - "<%= dirs.css.dest %>/style-polymer.css": "<%= dirs.css.src %>/polymer.less" + "<%= dirs.css.dest %>/style-polymer.css": "<%= dirs.css.src %>/polymer.less", + "<%= dirs.css.dest %>/style-ipython.css": "<%= dirs.css.src %>/ipython.less" } }, "production": { @@ -118,7 +120,8 @@ }, "files": { "<%= dirs.css.dest %>/style.css": "<%= dirs.css.src %>/main.less", - "<%= dirs.css.dest %>/style-polymer.css": "<%= dirs.css.src %>/polymer.less" + "<%= dirs.css.dest %>/style-polymer.css": "<%= dirs.css.src %>/polymer.less", + "<%= dirs.css.dest %>/style-ipython.css": "<%= dirs.css.src %>/ipython.less" } }, "components": { diff --git a/package.json b/package.json --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "clipboard": "^2.0.1", "exports-loader": "^0.6.4", "favico.js": "^0.3.10", + "dropzone": "^5.5.0", "grunt": "^0.4.5", "grunt-cli": "^1.3.1", "grunt-contrib-concat": "^0.5.1", diff --git a/pip2nix.ini b/pip2nix.ini --- a/pip2nix.ini +++ b/pip2nix.ini @@ -1,3 +1,3 @@ [pip2nix] -requirements = ., -r ./requirements.txt +requirements = ., -r ./requirements.txt, -r ./requirements_pinned.txt output = ./pkgs/python-packages.nix diff --git a/pkgs/node-packages.nix b/pkgs/node-packages.nix --- a/pkgs/node-packages.nix +++ b/pkgs/node-packages.nix @@ -166,13 +166,13 @@ let sha512 = "dgOe12GyCF1VZBLUQqnzGWlf3xb255FajNCVB1VFj/AtskYtoamnafa7m3a+1vs+C8qbg4Benn5KwgxVDSW4cg=="; }; }; - "@polymer/paper-spinner-3.0.1" = { + "@polymer/paper-spinner-3.0.2" = { name = "_at_polymer_slash_paper-spinner"; packageName = "@polymer/paper-spinner"; - version = "3.0.1"; - src = fetchurl { - url = "https://registry.npmjs.org/@polymer/paper-spinner/-/paper-spinner-3.0.1.tgz"; - sha512 = "MYIU6qWZnhZ5yNFOBzROPgBteGfxKEnDZ6bCgjrvUtJkBuQEz0MQZzSE/zmZc0oaJ9u5QK5xAFuYdudsGv7+sQ=="; + version = "3.0.2"; + src = fetchurl { + url = "https://registry.npmjs.org/@polymer/paper-spinner/-/paper-spinner-3.0.2.tgz"; + sha512 = "XUzu8/4NH+pnNZUTI2MxtOKFAr0EOsW7eGhTg3VBhTh7DDW/q3ewzwYRWnqNJokX9BEnxKMiXXaIeTEBq4k2dw=="; }; }; "@polymer/paper-styles-3.0.1" = { @@ -211,13 +211,13 @@ let sha512 = "yiUk09opTEnE1lK+tb501ENb+yQBi4p++Ep0eGJAHesVYKVMPNgPphVKkIizkDaU+n0SE+zXfTsRbYyOMDYXSg=="; }; }; - "@polymer/polymer-3.1.0" = { + "@polymer/polymer-3.2.0" = { name = "_at_polymer_slash_polymer"; packageName = "@polymer/polymer"; - version = "3.1.0"; - src = fetchurl { - url = "https://registry.npmjs.org/@polymer/polymer/-/polymer-3.1.0.tgz"; - sha512 = "hwN8IMERsFATz/9dSMxYHL+84J9uBkPuuarxJWlTsppZ4CAYTZKnepBfNrKoyNsafBmA3yXBiiKPPf+fJtza7A=="; + version = "3.2.0"; + src = fetchurl { + url = "https://registry.npmjs.org/@polymer/polymer/-/polymer-3.2.0.tgz"; + sha512 = "L6uV1oM6T6xbwbVx6t3biG5T2VSSB03LxnIrUd9M2pr6RkHVPFHJ37pC5MUwBAEhkGFJif7eks7fdMMSGZTeEQ=="; }; }; "@types/clone-0.1.30" = { @@ -229,13 +229,13 @@ let sha1 = "e7365648c1b42136a59c7d5040637b3b5c83b614"; }; }; - "@types/node-6.14.2" = { + "@types/node-6.14.6" = { name = "_at_types_slash_node"; packageName = "@types/node"; - version = "6.14.2"; - src = fetchurl { - url = "https://registry.npmjs.org/@types/node/-/node-6.14.2.tgz"; - sha512 = "JWB3xaVfsfnFY8Ofc9rTB/op0fqqTSqy4vBcVk1LuRJvta7KTX+D//fCkiTMeLGhdr2EbFZzQjC97gvmPilk9Q=="; + version = "6.14.6"; + src = fetchurl { + url = "https://registry.npmjs.org/@types/node/-/node-6.14.6.tgz"; + sha512 = "rFs9zCFtSHuseiNXxYxFlun8ibu+jtZPgRM+2ILCmeLiGeGLiIGxuOzD+cNyHegI1GD+da3R/cIbs9+xCLp13w=="; }; }; "@types/parse5-2.2.34" = { @@ -409,22 +409,22 @@ let sha512 = "mJ3QKWtCchL1vhU/kZlJnLPuQZnlDOdZsyP0bbLWPGdYsQDnSBvyTLhzwBA3QAMlzEL9V4JHygEmK6/OTEyytA=="; }; }; - "@webcomponents/shadycss-1.7.1" = { + "@webcomponents/shadycss-1.9.1" = { name = "_at_webcomponents_slash_shadycss"; packageName = "@webcomponents/shadycss"; - version = "1.7.1"; - src = fetchurl { - url = "https://registry.npmjs.org/@webcomponents/shadycss/-/shadycss-1.7.1.tgz"; - sha512 = "6SZqLajRPWL0rrKDZOGF8PCBq5B9JqgFmE5rX5psk6i8WrqiMkSCuO8+rnirzViTsU5CqnjQPFC3OvG4YJdMrQ=="; - }; - }; - "@webcomponents/webcomponentsjs-2.2.1" = { + version = "1.9.1"; + src = fetchurl { + url = "https://registry.npmjs.org/@webcomponents/shadycss/-/shadycss-1.9.1.tgz"; + sha512 = "IaZOnWOKXHghqk/WfPNDRIgDBi3RsVPY2IFAw6tYiL9UBGvQRy5R6uC+Fk7qTZsReTJ0xh5MTT8yAcb3MUR4mQ=="; + }; + }; + "@webcomponents/webcomponentsjs-2.2.10" = { name = "_at_webcomponents_slash_webcomponentsjs"; packageName = "@webcomponents/webcomponentsjs"; - version = "2.2.1"; - src = fetchurl { - url = "https://registry.npmjs.org/@webcomponents/webcomponentsjs/-/webcomponentsjs-2.2.1.tgz"; - sha512 = "lZZ+Lkke6JhsJcQQqSVk1Pny6/8y4qhJ98LO7a/MwBSRO8WqHqK1X2vscfeL8vOnYGFnmBUyVG95lwYv/AXyLQ=="; + version = "2.2.10"; + src = fetchurl { + url = "https://registry.npmjs.org/@webcomponents/webcomponentsjs/-/webcomponentsjs-2.2.10.tgz"; + sha512 = "5dzhUhP+h0qMiK0IWb7VNb0OGBoXO3AuI6Qi8t9PoKT50s5L1jv0xnwnLq+cFgPuTB8FLTNP8xIDmyoOsKBy9Q=="; }; }; "@xtuc/ieee754-1.2.0" = { @@ -499,22 +499,22 @@ let sha1 = "82ffb02b29e662ae53bdc20af15947706739c536"; }; }; - "ajv-6.6.2" = { + "ajv-6.10.0" = { name = "ajv"; packageName = "ajv"; - version = "6.6.2"; - src = fetchurl { - url = "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz"; - sha512 = "FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g=="; - }; - }; - "ajv-keywords-3.2.0" = { + version = "6.10.0"; + src = fetchurl { + url = "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz"; + sha512 = "nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg=="; + }; + }; + "ajv-keywords-3.4.0" = { name = "ajv-keywords"; packageName = "ajv-keywords"; - version = "3.2.0"; - src = fetchurl { - url = "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz"; - sha1 = "e86b819c602cf8821ad637413698f1dec021847a"; + version = "3.4.0"; + src = fetchurl { + url = "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz"; + sha512 = "aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw=="; }; }; "align-text-0.1.4" = { @@ -716,15 +716,6 @@ let sha1 = "a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"; }; }; - "arrify-1.0.1" = { - name = "arrify"; - packageName = "arrify"; - version = "1.0.1"; - src = fetchurl { - url = "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz"; - sha1 = "898508da2226f380df904728456849c1501a4b0d"; - }; - }; "asap-2.0.6" = { name = "asap"; packageName = "asap"; @@ -752,13 +743,13 @@ let sha512 = "p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw=="; }; }; - "assert-1.4.1" = { + "assert-1.5.0" = { name = "assert"; packageName = "assert"; - version = "1.4.1"; - src = fetchurl { - url = "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz"; - sha1 = "99912d591836b5a6f5b345c0f07eefc08fc65d91"; + version = "1.5.0"; + src = fetchurl { + url = "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz"; + sha512 = "EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA=="; }; }; "assert-plus-0.2.0" = { @@ -815,22 +806,22 @@ let sha1 = "b6bbe0b0674b9d719708ca38de8c237cb526c3d1"; }; }; - "async-2.6.1" = { + "async-2.6.2" = { name = "async"; packageName = "async"; - version = "2.6.1"; - src = fetchurl { - url = "https://registry.npmjs.org/async/-/async-2.6.1.tgz"; - sha512 = "fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ=="; - }; - }; - "async-each-1.0.1" = { + version = "2.6.2"; + src = fetchurl { + url = "https://registry.npmjs.org/async/-/async-2.6.2.tgz"; + sha512 = "H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg=="; + }; + }; + "async-each-1.0.3" = { name = "async-each"; packageName = "async-each"; - version = "1.0.1"; - src = fetchurl { - url = "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz"; - sha1 = "19d386a1d9edc6e7c1c85d388aedbcc56d33602d"; + version = "1.0.3"; + src = fetchurl { + url = "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz"; + sha512 = "z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ=="; }; }; "asynckit-0.4.0" = { @@ -1445,22 +1436,22 @@ let sha512 = "vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ=="; }; }; - "binary-extensions-1.12.0" = { + "binary-extensions-1.13.1" = { name = "binary-extensions"; packageName = "binary-extensions"; - version = "1.12.0"; - src = fetchurl { - url = "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz"; - sha512 = "DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg=="; - }; - }; - "bluebird-3.5.3" = { + version = "1.13.1"; + src = fetchurl { + url = "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz"; + sha512 = "Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw=="; + }; + }; + "bluebird-3.5.4" = { name = "bluebird"; packageName = "bluebird"; - version = "3.5.3"; - src = fetchurl { - url = "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz"; - sha512 = "/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw=="; + version = "3.5.4"; + src = fetchurl { + url = "https://registry.npmjs.org/bluebird/-/bluebird-3.5.4.tgz"; + sha512 = "FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw=="; }; }; "bn.js-4.11.8" = { @@ -1661,13 +1652,13 @@ let sha1 = "9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"; }; }; - "camelcase-5.0.0" = { + "camelcase-5.3.1" = { name = "camelcase"; packageName = "camelcase"; - version = "5.0.0"; - src = fetchurl { - url = "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz"; - sha512 = "faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA=="; + version = "5.3.1"; + src = fetchurl { + url = "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz"; + sha512 = "L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="; }; }; "caniuse-api-1.6.1" = { @@ -1679,22 +1670,22 @@ let sha1 = "b534e7c734c4f81ec5fbe8aca2ad24354b962c6c"; }; }; - "caniuse-db-1.0.30000927" = { + "caniuse-db-1.0.30000967" = { name = "caniuse-db"; packageName = "caniuse-db"; - version = "1.0.30000927"; - src = fetchurl { - url = "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000927.tgz"; - sha512 = "CX/QvLA8oh7kQ9cHCCzFm0UZW4KwSyQSRJ5A1XtH42HaMJQ0yh+9fEVWagMqv9I1vSCtaqA5Mb8k0uKfv7jhDw=="; - }; - }; - "caniuse-lite-1.0.30000927" = { + version = "1.0.30000967"; + src = fetchurl { + url = "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000967.tgz"; + sha512 = "70gk6cLSD5rItxnZ7WUxyCpM9LAjEb1tVzlENQfXQXZS/IiGnfAC6u32G5cZFlDBKjNPBIta/QSx5CZLZepxRA=="; + }; + }; + "caniuse-lite-1.0.30000967" = { name = "caniuse-lite"; packageName = "caniuse-lite"; - version = "1.0.30000927"; - src = fetchurl { - url = "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000927.tgz"; - sha512 = "ogq4NbUWf1uG/j66k0AmiO3GjqJAlQyF8n4w8a954cbCyFKmYGvRtgz6qkq2fWuduTXHibX7GyYL5Pg58Aks2g=="; + version = "1.0.30000967"; + src = fetchurl { + url = "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000967.tgz"; + sha512 = "rUBIbap+VJfxTzrM4akJ00lkvVb5/n5v3EGXfWzSH5zT8aJmGzjA8HWhJ4U6kCpzxozUSnB+yvAYDRPY6mRpgQ=="; }; }; "caseless-0.12.0" = { @@ -1742,13 +1733,13 @@ let sha512 = "Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="; }; }; - "chokidar-2.0.4" = { + "chokidar-2.1.5" = { name = "chokidar"; packageName = "chokidar"; - version = "2.0.4"; - src = fetchurl { - url = "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz"; - sha512 = "z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ=="; + version = "2.1.5"; + src = fetchurl { + url = "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz"; + sha512 = "i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A=="; }; }; "chownr-1.1.1" = { @@ -1976,13 +1967,13 @@ let sha512 = "mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg=="; }; }; - "combined-stream-1.0.7" = { + "combined-stream-1.0.8" = { name = "combined-stream"; packageName = "combined-stream"; - version = "1.0.7"; - src = fetchurl { - url = "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz"; - sha512 = "brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w=="; + version = "1.0.8"; + src = fetchurl { + url = "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz"; + sha512 = "FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="; }; }; "commander-2.14.1" = { @@ -2003,6 +1994,15 @@ let sha512 = "wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg=="; }; }; + "commander-2.19.0" = { + name = "commander"; + packageName = "commander"; + version = "2.19.0"; + src = fetchurl { + url = "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz"; + sha512 = "6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg=="; + }; + }; "commondir-1.0.1" = { name = "commondir"; packageName = "commondir"; @@ -2012,13 +2012,13 @@ let sha1 = "ddd800da0c66127393cca5950ea968a3aaf1253b"; }; }; - "component-emitter-1.2.1" = { + "component-emitter-1.3.0" = { name = "component-emitter"; packageName = "component-emitter"; - version = "1.2.1"; - src = fetchurl { - url = "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz"; - sha1 = "137918d6d78283f7df7a6b7c5a63e140e69425e6"; + version = "1.3.0"; + src = fetchurl { + url = "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz"; + sha512 = "Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="; }; }; "concat-map-0.0.1" = { @@ -2093,13 +2093,13 @@ let sha512 = "Y+SQCF+0NoWQryez2zXn5J5knmr9z/9qSQt7fbL78u83rxmigOy8X5+BFn8CFSuX+nKT8gpYwJX68ekqtQt6ZA=="; }; }; - "core-js-2.6.1" = { + "core-js-2.6.5" = { name = "core-js"; packageName = "core-js"; - version = "2.6.1"; - src = fetchurl { - url = "https://registry.npmjs.org/core-js/-/core-js-2.6.1.tgz"; - sha512 = "L72mmmEayPJBejKIWe2pYtGis5r0tQ5NaJekdhyXgeMQTpJoBsH0NL4ElY2LfSoV15xeQWKQ+XTTOZdyero5Xg=="; + version = "2.6.5"; + src = fetchurl { + url = "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz"; + sha512 = "klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A=="; }; }; "core-util-is-1.0.2" = { @@ -2201,13 +2201,13 @@ let sha512 = "xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA=="; }; }; - "css-what-2.1.2" = { + "css-what-2.1.3" = { name = "css-what"; packageName = "css-what"; - version = "2.1.2"; - src = fetchurl { - url = "https://registry.npmjs.org/css-what/-/css-what-2.1.2.tgz"; - sha512 = "wan8dMWQ0GUeF7DGEPVjhHemVW/vy6xUYmFzRY8RYqgA0JtXC9rJmbScBjqSu6dg9q0lwPQy6ZAmJVr3PPTvqQ=="; + version = "2.1.3"; + src = fetchurl { + url = "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz"; + sha512 = "a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg=="; }; }; "cssesc-0.1.0" = { @@ -2417,13 +2417,13 @@ let sha512 = "kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg=="; }; }; - "dir-glob-2.0.0" = { + "dir-glob-2.2.2" = { name = "dir-glob"; packageName = "dir-glob"; - version = "2.0.0"; - src = fetchurl { - url = "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz"; - sha512 = "37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag=="; + version = "2.2.2"; + src = fetchurl { + url = "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz"; + sha512 = "f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw=="; }; }; "dom-converter-0.2.0" = { @@ -2435,13 +2435,13 @@ let sha512 = "gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA=="; }; }; - "dom-serializer-0.1.0" = { + "dom-serializer-0.1.1" = { name = "dom-serializer"; packageName = "dom-serializer"; - version = "0.1.0"; - src = fetchurl { - url = "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz"; - sha1 = "073c697546ce0780ce23be4a28e293e40bc30c82"; + version = "0.1.1"; + src = fetchurl { + url = "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz"; + sha512 = "l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA=="; }; }; "dom5-2.3.0" = { @@ -2462,15 +2462,6 @@ let sha512 = "jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA=="; }; }; - "domelementtype-1.1.3" = { - name = "domelementtype"; - packageName = "domelementtype"; - version = "1.1.3"; - src = fetchurl { - url = "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz"; - sha1 = "bd28773e2642881aec51544924299c5cd822185b"; - }; - }; "domelementtype-1.3.1" = { name = "domelementtype"; packageName = "domelementtype"; @@ -2480,15 +2471,6 @@ let sha512 = "BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="; }; }; - "domhandler-2.1.0" = { - name = "domhandler"; - packageName = "domhandler"; - version = "2.1.0"; - src = fetchurl { - url = "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz"; - sha1 = "d2646f5e57f6c3bab11cf6cb05d3c0acf7412594"; - }; - }; "domhandler-2.3.0" = { name = "domhandler"; packageName = "domhandler"; @@ -2498,15 +2480,6 @@ let sha1 = "2de59a0822d5027fabff6f032c2b25a2a8abe738"; }; }; - "domutils-1.1.6" = { - name = "domutils"; - packageName = "domutils"; - version = "1.1.6"; - src = fetchurl { - url = "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz"; - sha1 = "bddc3de099b9a2efacc51c623f28f416ecc57485"; - }; - }; "domutils-1.5.1" = { name = "domutils"; packageName = "domutils"; @@ -2516,13 +2489,22 @@ let sha1 = "dcd8488a26f563d61079e48c9f7b7e32373682cf"; }; }; - "duplexify-3.6.1" = { + "dropzone-5.5.1" = { + name = "dropzone"; + packageName = "dropzone"; + version = "5.5.1"; + src = fetchurl { + url = "https://registry.npmjs.org/dropzone/-/dropzone-5.5.1.tgz"; + sha512 = "3VduRWLxx9hbVr42QieQN25mx/I61/mRdUSuxAmDGdDqZIN8qtP7tcKMa3KfpJjuGjOJGYYUzzeq6eGDnkzesA=="; + }; + }; + "duplexify-3.7.1" = { name = "duplexify"; packageName = "duplexify"; - version = "3.6.1"; - src = fetchurl { - url = "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz"; - sha512 = "vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA=="; + version = "3.7.1"; + src = fetchurl { + url = "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz"; + sha512 = "07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g=="; }; }; "ecc-jsbn-0.1.2" = { @@ -2534,13 +2516,13 @@ let sha1 = "3a83a904e54353287874c564b7549386849a98c9"; }; }; - "electron-to-chromium-1.3.98" = { + "electron-to-chromium-1.3.133" = { name = "electron-to-chromium"; packageName = "electron-to-chromium"; - version = "1.3.98"; - src = fetchurl { - url = "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.98.tgz"; - sha512 = "WIZdNuvE3dFr6kkPgv4d/cfswNZD6XbeLBM8baOIQTsnbf4xWrVEaLvp7oNnbnMWWXDqq7Tbv+H5JfciLTJm4Q=="; + version = "1.3.133"; + src = fetchurl { + url = "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.133.tgz"; + sha512 = "lyoC8aoqbbDqsprb6aPdt9n3DpOZZzdz/T4IZKsR0/dkZIxnJVUjjcpOSwA66jPRIOyDAamCTAUqweU05kKNSg=="; }; }; "elliptic-6.4.1" = { @@ -2651,13 +2633,13 @@ let sha1 = "1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"; }; }; - "eslint-scope-4.0.0" = { + "eslint-scope-4.0.3" = { name = "eslint-scope"; packageName = "eslint-scope"; - version = "4.0.0"; - src = fetchurl { - url = "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz"; - sha512 = "1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA=="; + version = "4.0.3"; + src = fetchurl { + url = "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz"; + sha512 = "p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg=="; }; }; "espree-3.5.4" = { @@ -2732,13 +2714,13 @@ let sha1 = "8f61b75cde012b2e9eb284d4545583b5643b61ab"; }; }; - "events-1.1.1" = { + "events-3.0.0" = { name = "events"; packageName = "events"; - version = "1.1.1"; - src = fetchurl { - url = "https://registry.npmjs.org/events/-/events-1.1.1.tgz"; - sha1 = "9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"; + version = "3.0.0"; + src = fetchurl { + url = "https://registry.npmjs.org/events/-/events-3.0.0.tgz"; + sha512 = "Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA=="; }; }; "evp_bytestokey-1.0.3" = { @@ -2948,13 +2930,13 @@ let sha1 = "9326b1488c22d1a6088650a86901b2d9a90a2cbc"; }; }; - "fined-1.1.1" = { + "fined-1.2.0" = { name = "fined"; packageName = "fined"; - version = "1.1.1"; - src = fetchurl { - url = "https://registry.npmjs.org/fined/-/fined-1.1.1.tgz"; - sha512 = "jQp949ZmEbiYHk3gkbdtpJ0G1+kgtLQBNdP5edFP7Fh+WAYceLQz6yO1SBj72Xkg8GVyTB3bBzAYrHJVh5Xd5g=="; + version = "1.2.0"; + src = fetchurl { + url = "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz"; + sha512 = "ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng=="; }; }; "flagged-respawn-1.0.1" = { @@ -2975,13 +2957,13 @@ let sha1 = "dae46a9d78fbe25292258cc1e780a41d95c03782"; }; }; - "flush-write-stream-1.0.3" = { + "flush-write-stream-1.1.1" = { name = "flush-write-stream"; packageName = "flush-write-stream"; - version = "1.0.3"; - src = fetchurl { - url = "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz"; - sha512 = "calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw=="; + version = "1.1.1"; + src = fetchurl { + url = "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz"; + sha512 = "3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w=="; }; }; "for-in-1.0.2" = { @@ -3056,13 +3038,13 @@ let sha1 = "1504ad2523158caa40db4a2787cb01411994ea4f"; }; }; - "fsevents-1.2.4" = { + "fsevents-1.2.9" = { name = "fsevents"; packageName = "fsevents"; - version = "1.2.4"; - src = fetchurl { - url = "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz"; - sha512 = "z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg=="; + version = "1.2.9"; + src = fetchurl { + url = "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz"; + sha512 = "oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw=="; }; }; "function-bind-1.1.1" = { @@ -3146,13 +3128,13 @@ let sha1 = "4a973f635b9190f715d10987d5c00fd2815ebe3d"; }; }; - "glob-7.1.3" = { + "glob-7.1.4" = { name = "glob"; packageName = "glob"; - version = "7.1.3"; - src = fetchurl { - url = "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz"; - sha512 = "vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ=="; + version = "7.1.4"; + src = fetchurl { + url = "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz"; + sha512 = "hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A=="; }; }; "glob-parent-3.1.0" = { @@ -3524,13 +3506,13 @@ let sha1 = "e36c3f2d2cae7d746a857e38d18d5f32a7882db8"; }; }; - "homedir-polyfill-1.0.1" = { + "homedir-polyfill-1.0.3" = { name = "homedir-polyfill"; packageName = "homedir-polyfill"; - version = "1.0.1"; - src = fetchurl { - url = "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz"; - sha1 = "4c2bbc8a758998feebf5ed68580f76d46768b4bc"; + version = "1.0.3"; + src = fetchurl { + url = "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz"; + sha512 = "eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA=="; }; }; "hooker-0.2.3" = { @@ -3587,15 +3569,6 @@ let sha1 = "b01abbd723acaaa7b37b6af4492ebda03d9dd37b"; }; }; - "htmlparser2-3.3.0" = { - name = "htmlparser2"; - packageName = "htmlparser2"; - version = "3.3.0"; - src = fetchurl { - url = "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz"; - sha1 = "cc70d05a59f6542e43f0e685c982e14c924a9efe"; - }; - }; "htmlparser2-3.8.3" = { name = "htmlparser2"; packageName = "htmlparser2"; @@ -3650,13 +3623,13 @@ let sha1 = "83f0a0ec378bf3246178b6c2ad9136f135b1c962"; }; }; - "ieee754-1.1.12" = { + "ieee754-1.1.13" = { name = "ieee754"; packageName = "ieee754"; - version = "1.1.12"; - src = fetchurl { - url = "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz"; - sha512 = "GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA=="; + version = "1.1.13"; + src = fetchurl { + url = "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz"; + sha512 = "4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="; }; }; "iferr-0.1.5" = { @@ -3974,13 +3947,13 @@ let sha1 = "7ba5ae24217804ac70707b96922567486cc3e84a"; }; }; - "is-glob-4.0.0" = { + "is-glob-4.0.1" = { name = "is-glob"; packageName = "is-glob"; - version = "4.0.0"; - src = fetchurl { - url = "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz"; - sha1 = "9521c76845cc2610a85203ddf080a958c2ffabc0"; + version = "4.0.1"; + src = fetchurl { + url = "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz"; + sha512 = "5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg=="; }; }; "is-number-3.0.0" = { @@ -4145,13 +4118,13 @@ let sha1 = "dd8b74278b27102d29df63eae28308a8cfa1b583"; }; }; - "js-base64-2.5.0" = { + "js-base64-2.5.1" = { name = "js-base64"; packageName = "js-base64"; - version = "2.5.0"; - src = fetchurl { - url = "https://registry.npmjs.org/js-base64/-/js-base64-2.5.0.tgz"; - sha512 = "wlEBIZ5LP8usDylWbDNhKPEFVFdI5hCHpnVoT/Ysvoi/PRhJENm/Rlh9TvjYB38HFfKZN7OzEbRjmjvLkFw11g=="; + version = "2.5.1"; + src = fetchurl { + url = "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz"; + sha512 = "M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw=="; }; }; "js-tokens-3.0.2" = { @@ -4208,6 +4181,15 @@ let sha1 = "46c3fec8c1892b12b0833db9bc7622176dbab34b"; }; }; + "jshint-2.10.2" = { + name = "jshint"; + packageName = "jshint"; + version = "2.10.2"; + src = fetchurl { + url = "https://registry.npmjs.org/jshint/-/jshint-2.10.2.tgz"; + sha512 = "e7KZgCSXMJxznE/4WULzybCMNXNAd/bf5TSrvVEq78Q/K8ZwFpmBqQeDtNiHc3l49nV4E/+YeHU/JZjSUIrLAA=="; + }; + }; "jshint-2.9.7" = { name = "jshint"; packageName = "jshint"; @@ -4370,13 +4352,13 @@ let sha1 = "2009291bb31cea861bbf10a7c15a28caf75c31ec"; }; }; - "loader-runner-2.3.1" = { + "loader-runner-2.4.0" = { name = "loader-runner"; packageName = "loader-runner"; - version = "2.3.1"; - src = fetchurl { - url = "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.1.tgz"; - sha512 = "By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw=="; + version = "2.4.0"; + src = fetchurl { + url = "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz"; + sha512 = "Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw=="; }; }; "loader-utils-0.2.17" = { @@ -4460,15 +4442,6 @@ let sha1 = "b28aa6288a2b9fc651035c7711f65ab6190331a6"; }; }; - "lodash.debounce-4.0.8" = { - name = "lodash.debounce"; - packageName = "lodash.debounce"; - version = "4.0.8"; - src = fetchurl { - url = "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz"; - sha1 = "82d79bff30a67c4005ffd5e2515300ad9ca4d7af"; - }; - }; "lodash.isplainobject-4.0.6" = { name = "lodash.isplainobject"; packageName = "lodash.isplainobject"; @@ -4613,13 +4586,13 @@ let sha512 = "xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg=="; }; }; - "mem-4.0.0" = { + "mem-4.3.0" = { name = "mem"; packageName = "mem"; - version = "4.0.0"; - src = fetchurl { - url = "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz"; - sha512 = "WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA=="; + version = "4.3.0"; + src = fetchurl { + url = "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz"; + sha512 = "qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w=="; }; }; "memory-fs-0.4.1" = { @@ -4658,31 +4631,31 @@ let sha512 = "x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="; }; }; - "mime-db-1.37.0" = { + "mime-db-1.40.0" = { name = "mime-db"; packageName = "mime-db"; - version = "1.37.0"; - src = fetchurl { - url = "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz"; - sha512 = "R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg=="; - }; - }; - "mime-types-2.1.21" = { + version = "1.40.0"; + src = fetchurl { + url = "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz"; + sha512 = "jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="; + }; + }; + "mime-types-2.1.24" = { name = "mime-types"; packageName = "mime-types"; - version = "2.1.21"; - src = fetchurl { - url = "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz"; - sha512 = "3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg=="; - }; - }; - "mimic-fn-1.2.0" = { + version = "2.1.24"; + src = fetchurl { + url = "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz"; + sha512 = "WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ=="; + }; + }; + "mimic-fn-2.1.0" = { name = "mimic-fn"; packageName = "mimic-fn"; - version = "1.2.0"; - src = fetchurl { - url = "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz"; - sha512 = "jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="; + version = "2.1.0"; + src = fetchurl { + url = "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz"; + sha512 = "OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="; }; }; "minimalistic-assert-1.0.1" = { @@ -4775,22 +4748,22 @@ let sha1 = "30057438eac6cf7f8c4767f38648d6697d75c903"; }; }; - "moment-2.23.0" = { + "moment-2.24.0" = { name = "moment"; packageName = "moment"; - version = "2.23.0"; - src = fetchurl { - url = "https://registry.npmjs.org/moment/-/moment-2.23.0.tgz"; - sha512 = "3IE39bHVqFbWWaPOMHZF98Q9c3LDKGTmypMiTM2QygGXXElkFWIH7GxfmlwmY2vwa+wmNsoYZmG2iusf1ZjJoA=="; - }; - }; - "mousetrap-1.6.2" = { + version = "2.24.0"; + src = fetchurl { + url = "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz"; + sha512 = "bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="; + }; + }; + "mousetrap-1.6.3" = { name = "mousetrap"; packageName = "mousetrap"; - version = "1.6.2"; - src = fetchurl { - url = "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.2.tgz"; - sha512 = "jDjhi7wlHwdO6q6DS7YRmSHcuI+RVxadBkLt3KHrhd3C2b+w5pKefg3oj5beTcHZyVFA9Aksf+yEE1y5jxUjVA=="; + version = "1.6.3"; + src = fetchurl { + url = "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.3.tgz"; + sha512 = "bd+nzwhhs9ifsUrC2tWaSgm24/oo2c83zaRyZQF06hYA6sANfsXHtnZ19AbbbDXCDzeH5nZBSQ4NvCjgD62tJA=="; }; }; "move-concurrently-1.0.1" = { @@ -4811,13 +4784,13 @@ let sha1 = "5608aeadfc00be6c2901df5f9861788de0d597c8"; }; }; - "nan-2.12.1" = { + "nan-2.13.2" = { name = "nan"; packageName = "nan"; - version = "2.12.1"; - src = fetchurl { - url = "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz"; - sha512 = "JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw=="; + version = "2.13.2"; + src = fetchurl { + url = "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz"; + sha512 = "TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw=="; }; }; "nanomatch-1.2.13" = { @@ -4829,13 +4802,13 @@ let sha512 = "fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA=="; }; }; - "neo-async-2.6.0" = { + "neo-async-2.6.1" = { name = "neo-async"; packageName = "neo-async"; - version = "2.6.0"; - src = fetchurl { - url = "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz"; - sha512 = "MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA=="; + version = "2.6.1"; + src = fetchurl { + url = "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz"; + sha512 = "iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw=="; }; }; "nice-try-1.0.5" = { @@ -4856,13 +4829,13 @@ let sha512 = "rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ=="; }; }; - "node-libs-browser-2.1.0" = { + "node-libs-browser-2.2.0" = { name = "node-libs-browser"; packageName = "node-libs-browser"; - version = "2.1.0"; - src = fetchurl { - url = "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz"; - sha512 = "5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg=="; + version = "2.2.0"; + src = fetchurl { + url = "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.0.tgz"; + sha512 = "5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA=="; }; }; "nopt-1.0.10" = { @@ -4910,6 +4883,15 @@ let sha1 = "1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"; }; }; + "normalize-path-3.0.0" = { + name = "normalize-path"; + packageName = "normalize-path"; + version = "3.0.0"; + src = fetchurl { + url = "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz"; + sha512 = "6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="; + }; + }; "normalize-range-0.1.2" = { name = "normalize-range"; packageName = "normalize-range"; @@ -4991,13 +4973,13 @@ let sha1 = "7e7d858b781bd7c991a41ba975ed3812754e998c"; }; }; - "object-keys-1.0.12" = { + "object-keys-1.1.1" = { name = "object-keys"; packageName = "object-keys"; - version = "1.0.12"; - src = fetchurl { - url = "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz"; - sha512 = "FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag=="; + version = "1.1.1"; + src = fetchurl { + url = "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz"; + sha512 = "NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="; }; }; "object-visit-1.0.1" = { @@ -5117,13 +5099,13 @@ let sha1 = "3fbcfb15b899a44123b34b6dcc18b724336a2cae"; }; }; - "p-is-promise-1.1.0" = { + "p-is-promise-2.1.0" = { name = "p-is-promise"; packageName = "p-is-promise"; - version = "1.1.0"; - src = fetchurl { - url = "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz"; - sha1 = "9c9456989e9f6588017b0434d56097675c3da05e"; + version = "2.1.0"; + src = fetchurl { + url = "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz"; + sha512 = "Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg=="; }; }; "p-limit-1.3.0" = { @@ -5135,13 +5117,13 @@ let sha512 = "vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q=="; }; }; - "p-limit-2.1.0" = { + "p-limit-2.2.0" = { name = "p-limit"; packageName = "p-limit"; - version = "2.1.0"; - src = fetchurl { - url = "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz"; - sha512 = "NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g=="; + version = "2.2.0"; + src = fetchurl { + url = "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz"; + sha512 = "pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ=="; }; }; "p-locate-2.0.0" = { @@ -5171,22 +5153,22 @@ let sha1 = "cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"; }; }; - "p-try-2.0.0" = { + "p-try-2.2.0" = { name = "p-try"; packageName = "p-try"; - version = "2.0.0"; - src = fetchurl { - url = "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz"; - sha512 = "hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ=="; - }; - }; - "pako-1.0.7" = { + version = "2.2.0"; + src = fetchurl { + url = "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz"; + sha512 = "R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="; + }; + }; + "pako-1.0.10" = { name = "pako"; packageName = "pako"; - version = "1.0.7"; - src = fetchurl { - url = "https://registry.npmjs.org/pako/-/pako-1.0.7.tgz"; - sha512 = "3HNK5tW4x8o5mO8RuHZp3Ydw9icZXx0RANAOMzlMzx7LVXhMJ4mo3MOBpzyd7r/+RUu8BmndP47LXT+vzjtWcQ=="; + version = "1.0.10"; + src = fetchurl { + url = "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz"; + sha512 = "0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw=="; }; }; "parallel-transform-1.1.0" = { @@ -5207,13 +5189,13 @@ let sha1 = "df94fd8cf6531ecf75e6bef9a0858fbc72be2247"; }; }; - "parse-asn1-5.1.1" = { + "parse-asn1-5.1.4" = { name = "parse-asn1"; packageName = "parse-asn1"; - version = "5.1.1"; - src = fetchurl { - url = "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz"; - sha512 = "KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw=="; + version = "5.1.4"; + src = fetchurl { + url = "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz"; + sha512 = "Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw=="; }; }; "parse-filepath-1.0.2" = { @@ -5927,13 +5909,13 @@ let sha1 = "9ec61f79049875707d69414596fd907a4d711e73"; }; }; - "randombytes-2.0.6" = { + "randombytes-2.1.0" = { name = "randombytes"; packageName = "randombytes"; - version = "2.0.6"; - src = fetchurl { - url = "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz"; - sha512 = "CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A=="; + version = "2.1.0"; + src = fetchurl { + url = "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz"; + sha512 = "vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ=="; }; }; "randomfill-1.0.4" = { @@ -5954,15 +5936,6 @@ let sha512 = "guh4ZNAf96f+CDwfnPbFeFiO5YcfPllUmZrgcoOmx6iqZPq+DcKbnyjPuBxEAtQ3tqqd++qChsQfQB+VBzFT0Q=="; }; }; - "readable-stream-1.0.34" = { - name = "readable-stream"; - packageName = "readable-stream"; - version = "1.0.34"; - src = fetchurl { - url = "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz"; - sha1 = "125820e34bc842d2f2aaafafe4c2916ee32c157c"; - }; - }; "readable-stream-1.1.14" = { name = "readable-stream"; packageName = "readable-stream"; @@ -6116,13 +6089,13 @@ let sha1 = "c24bce2a283adad5bc3f58e0d48249b92379d8ef"; }; }; - "renderkid-2.0.2" = { + "renderkid-2.0.3" = { name = "renderkid"; packageName = "renderkid"; - version = "2.0.2"; - src = fetchurl { - url = "https://registry.npmjs.org/renderkid/-/renderkid-2.0.2.tgz"; - sha512 = "FsygIxevi1jSiPY9h7vZmBFUbAOcbYm9UwyiLNdVsLRs/5We9Ob5NMPbGYUTWiLq5L+ezlVdE0A8bbME5CWTpg=="; + version = "2.0.3"; + src = fetchurl { + url = "https://registry.npmjs.org/renderkid/-/renderkid-2.0.3.tgz"; + sha512 = "z8CLQp7EZBPCwCnncgf9C4XAi3WR0dv+uWu/PjIyhhAb5d6IJ/QZqlHFprHeKT+59//V6BNUsLbvN8+2LarxGA=="; }; }; "repeat-element-1.1.3" = { @@ -6179,13 +6152,13 @@ let sha1 = "97f717b69d48784f5f526a6c5aa8ffdda055a4d1"; }; }; - "resolve-1.9.0" = { + "resolve-1.10.1" = { name = "resolve"; packageName = "resolve"; - version = "1.9.0"; - src = fetchurl { - url = "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz"; - sha512 = "TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ=="; + version = "1.10.1"; + src = fetchurl { + url = "https://registry.npmjs.org/resolve/-/resolve-1.10.1.tgz"; + sha512 = "KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA=="; }; }; "resolve-cwd-2.0.0" = { @@ -6332,22 +6305,22 @@ let sha1 = "0e7350acdec80b1108528786ec1d4418d11b396d"; }; }; - "semver-5.6.0" = { + "semver-5.7.0" = { name = "semver"; packageName = "semver"; - version = "5.6.0"; - src = fetchurl { - url = "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz"; - sha512 = "RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg=="; - }; - }; - "serialize-javascript-1.6.1" = { + version = "5.7.0"; + src = fetchurl { + url = "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz"; + sha512 = "Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA=="; + }; + }; + "serialize-javascript-1.7.0" = { name = "serialize-javascript"; packageName = "serialize-javascript"; - version = "1.6.1"; - src = fetchurl { - url = "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.6.1.tgz"; - sha512 = "A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw=="; + version = "1.7.0"; + src = fetchurl { + url = "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz"; + sha512 = "ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA=="; }; }; "set-blocking-2.0.0" = { @@ -6593,13 +6566,13 @@ let sha1 = "04e6926f662895354f3dd015203633b857297e2c"; }; }; - "sshpk-1.16.0" = { + "sshpk-1.16.1" = { name = "sshpk"; packageName = "sshpk"; - version = "1.16.0"; - src = fetchurl { - url = "https://registry.npmjs.org/sshpk/-/sshpk-1.16.0.tgz"; - sha512 = "Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ=="; + version = "1.16.1"; + src = fetchurl { + url = "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz"; + sha512 = "HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg=="; }; }; "ssri-5.3.0" = { @@ -6629,13 +6602,13 @@ let sha1 = "142bf6b64c2b416e4b707ebf8f09b8b5a5043877"; }; }; - "stream-browserify-2.0.1" = { + "stream-browserify-2.0.2" = { name = "stream-browserify"; packageName = "stream-browserify"; - version = "2.0.1"; - src = fetchurl { - url = "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz"; - sha1 = "66266ee5f9bdb9940a4e4514cafb43bb71e5c9db"; + version = "2.0.2"; + src = fetchurl { + url = "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz"; + sha512 = "nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg=="; }; }; "stream-each-1.2.3" = { @@ -6836,13 +6809,13 @@ let sha512 = "2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A=="; }; }; - "tapable-1.1.1" = { + "tapable-1.1.3" = { name = "tapable"; packageName = "tapable"; - version = "1.1.1"; - src = fetchurl { - url = "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz"; - sha512 = "9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA=="; + version = "1.1.3"; + src = fetchurl { + url = "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz"; + sha512 = "4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA=="; }; }; "through-2.3.8" = { @@ -6872,13 +6845,13 @@ let sha512 = "YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg=="; }; }; - "tiny-emitter-2.0.2" = { + "tiny-emitter-2.1.0" = { name = "tiny-emitter"; packageName = "tiny-emitter"; - version = "2.0.2"; - src = fetchurl { - url = "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.0.2.tgz"; - sha512 = "2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow=="; + version = "2.1.0"; + src = fetchurl { + url = "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz"; + sha512 = "NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="; }; }; "tiny-lr-fork-0.0.5" = { @@ -7034,13 +7007,13 @@ let sha1 = "29c5733148057bb4e1f75df35b7a9cb72e6a59dd"; }; }; - "uglify-js-3.4.9" = { + "uglify-js-3.4.10" = { name = "uglify-js"; packageName = "uglify-js"; - version = "3.4.9"; - src = fetchurl { - url = "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz"; - sha512 = "8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q=="; + version = "3.4.10"; + src = fetchurl { + url = "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz"; + sha512 = "Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw=="; }; }; "uglify-to-browserify-1.0.2" = { @@ -7160,13 +7133,13 @@ let sha1 = "8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"; }; }; - "upath-1.1.0" = { + "upath-1.1.2" = { name = "upath"; packageName = "upath"; - version = "1.1.0"; - src = fetchurl { - url = "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz"; - sha512 = "bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw=="; + version = "1.1.2"; + src = fetchurl { + url = "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz"; + sha512 = "kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q=="; }; }; "upper-case-1.1.3" = { @@ -7223,13 +7196,13 @@ let sha1 = "7afb1afe50805246489e3db7fe0ed379336ac0f9"; }; }; - "util-0.10.4" = { + "util-0.11.1" = { name = "util"; packageName = "util"; - version = "0.10.4"; - src = fetchurl { - url = "https://registry.npmjs.org/util/-/util-0.10.4.tgz"; - sha512 = "0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A=="; + version = "0.11.1"; + src = fetchurl { + url = "https://registry.npmjs.org/util/-/util-0.11.1.tgz"; + sha512 = "HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ=="; }; }; "util-deprecate-1.0.2" = { @@ -7268,31 +7241,31 @@ let sha512 = "yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="; }; }; - "v8-compile-cache-2.0.2" = { + "v8-compile-cache-2.0.3" = { name = "v8-compile-cache"; packageName = "v8-compile-cache"; - version = "2.0.2"; - src = fetchurl { - url = "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz"; - sha512 = "1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw=="; - }; - }; - "v8flags-3.1.2" = { + version = "2.0.3"; + src = fetchurl { + url = "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz"; + sha512 = "CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w=="; + }; + }; + "v8flags-3.1.3" = { name = "v8flags"; packageName = "v8flags"; - version = "3.1.2"; - src = fetchurl { - url = "https://registry.npmjs.org/v8flags/-/v8flags-3.1.2.tgz"; - sha512 = "MtivA7GF24yMPte9Rp/BWGCYQNaUj86zeYxV/x2RRJMKagImbbv3u8iJC57lNhWLPcGLJmHcHmFWkNsplbbLWw=="; - }; - }; - "vendors-1.0.2" = { + version = "3.1.3"; + src = fetchurl { + url = "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz"; + sha512 = "amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w=="; + }; + }; + "vendors-1.0.3" = { name = "vendors"; packageName = "vendors"; - version = "1.0.2"; - src = fetchurl { - url = "https://registry.npmjs.org/vendors/-/vendors-1.0.2.tgz"; - sha512 = "w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ=="; + version = "1.0.3"; + src = fetchurl { + url = "https://registry.npmjs.org/vendors/-/vendors-1.0.3.tgz"; + sha512 = "fOi47nsJP5Wqefa43kyWSg80qF+Q3XA6MUkgi7Hp1HQaKDQW4cQrK2D0P7mmbFtsV1N89am55Yru/nyEwRubcw=="; }; }; "verror-1.10.0" = { @@ -7430,13 +7403,13 @@ let sha1 = "b79669bb42ecb409f83d583cad52ca17eaa1643f"; }; }; - "worker-farm-1.6.0" = { + "worker-farm-1.7.0" = { name = "worker-farm"; packageName = "worker-farm"; - version = "1.6.0"; - src = fetchurl { - url = "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz"; - sha512 = "6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ=="; + version = "1.7.0"; + src = fetchurl { + url = "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz"; + sha512 = "rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw=="; }; }; "wrap-ansi-2.1.0" = { @@ -7536,14 +7509,14 @@ let sources."@polymer/paper-behaviors-3.0.1" sources."@polymer/paper-button-3.0.1" sources."@polymer/paper-ripple-3.0.1" - sources."@polymer/paper-spinner-3.0.1" + sources."@polymer/paper-spinner-3.0.2" sources."@polymer/paper-styles-3.0.1" sources."@polymer/paper-toast-3.0.1" sources."@polymer/paper-toggle-button-3.0.1" sources."@polymer/paper-tooltip-3.0.1" - sources."@polymer/polymer-3.1.0" + sources."@polymer/polymer-3.2.0" sources."@types/clone-0.1.30" - sources."@types/node-6.14.2" + sources."@types/node-6.14.6" sources."@types/parse5-2.2.34" sources."@webassemblyjs/ast-1.7.10" sources."@webassemblyjs/floating-point-hex-parser-1.7.10" @@ -7563,8 +7536,8 @@ let sources."@webassemblyjs/wasm-parser-1.7.10" sources."@webassemblyjs/wast-parser-1.7.10" sources."@webassemblyjs/wast-printer-1.7.10" - sources."@webcomponents/shadycss-1.7.1" - sources."@webcomponents/webcomponentsjs-2.2.1" + sources."@webcomponents/shadycss-1.9.1" + sources."@webcomponents/webcomponentsjs-2.2.10" sources."@xtuc/ieee754-1.2.0" sources."@xtuc/long-4.2.1" sources."abbrev-1.1.1" @@ -7576,7 +7549,7 @@ let ]; }) sources."ajv-4.11.8" - sources."ajv-keywords-3.2.0" + sources."ajv-keywords-3.4.0" (sources."align-text-0.1.4" // { dependencies = [ sources."kind-of-3.2.2" @@ -7586,7 +7559,11 @@ let sources."amdefine-1.0.1" sources."ansi-regex-0.2.1" sources."ansi-styles-1.1.0" - sources."anymatch-2.0.0" + (sources."anymatch-2.0.0" // { + dependencies = [ + sources."normalize-path-2.1.1" + ]; + }) sources."appenlight-client-git+https://git@github.com/AppEnlight/appenlight-client-js.git#0.5.1" sources."aproba-1.2.0" (sources."argparse-0.1.16" // { @@ -7602,11 +7579,10 @@ let sources."array-union-1.0.2" sources."array-uniq-1.0.3" sources."array-unique-0.3.2" - sources."arrify-1.0.1" sources."asap-2.0.6" sources."asn1-0.2.4" sources."asn1.js-4.10.1" - (sources."assert-1.4.1" // { + (sources."assert-1.5.0" // { dependencies = [ sources."inherits-2.0.1" sources."util-0.10.3" @@ -7616,7 +7592,7 @@ let sources."assign-symbols-1.0.0" sources."ast-types-0.9.6" sources."async-0.1.22" - sources."async-each-1.0.1" + sources."async-each-1.0.3" sources."asynckit-0.4.0" sources."atob-2.1.2" (sources."autoprefixer-6.7.7" // { @@ -7738,8 +7714,8 @@ let sources."base64-js-1.3.0" sources."bcrypt-pbkdf-1.0.2" sources."big.js-5.2.2" - sources."binary-extensions-1.12.0" - sources."bluebird-3.5.3" + sources."binary-extensions-1.13.1" + sources."bluebird-3.5.4" sources."bn.js-4.11.8" sources."boolbase-1.0.0" sources."boom-2.10.1" @@ -7763,7 +7739,7 @@ let sources."builtin-status-codes-3.0.0" (sources."cacache-10.0.4" // { dependencies = [ - sources."glob-7.1.3" + sources."glob-7.1.4" sources."graceful-fs-4.1.15" sources."lru-cache-4.1.5" sources."minimatch-3.0.4" @@ -7772,20 +7748,20 @@ let }) sources."cache-base-1.0.1" sources."camel-case-3.0.0" - sources."camelcase-5.0.0" + sources."camelcase-5.3.1" (sources."caniuse-api-1.6.1" // { dependencies = [ sources."browserslist-1.7.7" ]; }) - sources."caniuse-db-1.0.30000927" - sources."caniuse-lite-1.0.30000927" + sources."caniuse-db-1.0.30000967" + sources."caniuse-lite-1.0.30000967" sources."caseless-0.12.0" sources."center-align-0.1.3" sources."chalk-0.5.1" - (sources."chokidar-2.0.4" // { - dependencies = [ - sources."is-glob-4.0.0" + (sources."chokidar-2.1.5" // { + dependencies = [ + sources."is-glob-4.0.1" ]; }) sources."chownr-1.1.1" @@ -7825,7 +7801,7 @@ let }) (sources."cli-1.0.1" // { dependencies = [ - sources."glob-7.1.3" + sources."glob-7.1.4" sources."minimatch-3.0.4" ]; }) @@ -7848,10 +7824,10 @@ let sources."color-string-0.3.0" sources."colormin-1.1.2" sources."colors-0.6.2" - sources."combined-stream-1.0.7" + sources."combined-stream-1.0.8" sources."commander-2.14.1" sources."commondir-1.0.1" - sources."component-emitter-1.2.1" + sources."component-emitter-1.3.0" sources."concat-map-0.0.1" (sources."concat-stream-1.6.2" // { dependencies = [ @@ -7864,7 +7840,7 @@ let sources."convert-source-map-1.6.0" (sources."copy-concurrently-1.0.5" // { dependencies = [ - sources."glob-7.1.3" + sources."glob-7.1.4" sources."minimatch-3.0.4" sources."rimraf-2.6.3" ]; @@ -7872,11 +7848,11 @@ let sources."copy-descriptor-0.1.1" (sources."copy-webpack-plugin-4.6.0" // { dependencies = [ - sources."is-glob-4.0.0" + sources."is-glob-4.0.1" sources."minimatch-3.0.4" ]; }) - sources."core-js-2.6.1" + sources."core-js-2.6.5" sources."core-util-is-1.0.2" sources."create-ecdh-4.0.3" sources."create-hash-1.2.0" @@ -7896,7 +7872,7 @@ let sources."regexpu-core-1.0.0" ]; }) - sources."css-what-2.1.2" + sources."css-what-2.1.3" sources."cssesc-0.1.0" sources."cssnano-3.10.0" sources."csso-2.3.2" @@ -7921,11 +7897,10 @@ let sources."detect-file-1.0.0" sources."detect-indent-4.0.0" sources."diffie-hellman-5.0.3" - sources."dir-glob-2.0.0" + sources."dir-glob-2.2.2" sources."dom-converter-0.2.0" - (sources."dom-serializer-0.1.0" // { - dependencies = [ - sources."domelementtype-1.1.3" + (sources."dom-serializer-0.1.1" // { + dependencies = [ sources."entities-1.1.2" ]; }) @@ -7939,14 +7914,15 @@ let sources."domelementtype-1.3.1" sources."domhandler-2.3.0" sources."domutils-1.5.1" - (sources."duplexify-3.6.1" // { + sources."dropzone-5.5.1" + (sources."duplexify-3.7.1" // { dependencies = [ sources."readable-stream-2.3.6" sources."string_decoder-1.1.1" ]; }) sources."ecc-jsbn-0.1.2" - sources."electron-to-chromium-1.3.98" + sources."electron-to-chromium-1.3.133" sources."elliptic-6.4.1" sources."emojis-list-2.1.0" sources."end-of-stream-1.4.1" @@ -7961,14 +7937,14 @@ let sources."es-to-primitive-1.2.0" sources."es6-templates-0.2.3" sources."escape-string-regexp-1.0.5" - sources."eslint-scope-4.0.0" + sources."eslint-scope-4.0.3" sources."espree-3.5.4" sources."esprima-1.0.4" sources."esrecurse-4.2.1" sources."estraverse-4.2.0" sources."esutils-2.0.2" sources."eventemitter2-0.4.14" - sources."events-1.1.1" + sources."events-3.0.0" sources."evp_bytestokey-1.0.3" sources."execa-1.0.0" sources."exit-0.1.2" @@ -8025,10 +8001,10 @@ let sources."minimatch-0.3.0" ]; }) - sources."fined-1.1.1" + sources."fined-1.2.0" sources."flagged-respawn-1.0.1" sources."flatten-1.0.2" - (sources."flush-write-stream-1.0.3" // { + (sources."flush-write-stream-1.1.1" // { dependencies = [ sources."readable-stream-2.3.6" sources."string_decoder-1.1.1" @@ -8051,7 +8027,7 @@ let ]; }) sources."fs.realpath-1.0.0" - sources."fsevents-1.2.4" + sources."fsevents-1.2.9" sources."function-bind-1.1.1" sources."gaze-0.5.2" sources."get-caller-file-1.0.3" @@ -8083,7 +8059,7 @@ let sources."globals-9.18.0" (sources."globby-7.1.1" // { dependencies = [ - sources."glob-7.1.3" + sources."glob-7.1.4" sources."minimatch-3.0.4" ]; }) @@ -8115,12 +8091,18 @@ let sources."supports-color-2.0.0" ]; }) - sources."grunt-contrib-jshint-0.12.0" + (sources."grunt-contrib-jshint-0.12.0" // { + dependencies = [ + sources."jshint-2.9.7" + sources."lodash-4.17.11" + sources."minimatch-3.0.4" + ]; + }) (sources."grunt-contrib-less-1.4.1" // { dependencies = [ sources."ansi-regex-2.1.1" sources."ansi-styles-2.2.1" - sources."async-2.6.1" + sources."async-2.6.2" sources."chalk-1.1.3" sources."has-ansi-2.0.0" sources."lodash-4.17.11" @@ -8172,7 +8154,7 @@ let sources."hmac-drbg-1.0.1" sources."hoek-2.16.3" sources."home-or-tmp-2.0.0" - sources."homedir-polyfill-1.0.1" + sources."homedir-polyfill-1.0.3" sources."hooker-0.2.3" sources."html-comment-regex-1.1.2" sources."html-loader-0.4.5" @@ -8203,7 +8185,7 @@ let sources."supports-color-5.5.0" ]; }) - sources."ieee754-1.1.12" + sources."ieee754-1.1.13" sources."iferr-0.1.5" sources."ignore-3.3.10" sources."image-size-0.5.5" @@ -8211,9 +8193,9 @@ let dependencies = [ sources."find-up-3.0.0" sources."locate-path-3.0.0" - sources."p-limit-2.1.0" + sources."p-limit-2.2.0" sources."p-locate-3.0.0" - sources."p-try-2.0.0" + sources."p-try-2.2.0" sources."pkg-dir-3.0.0" ]; }) @@ -8261,12 +8243,12 @@ let sources."isobject-3.0.1" sources."isstream-0.1.2" sources."jquery-1.11.3" - sources."js-base64-2.5.0" + sources."js-base64-2.5.1" sources."js-tokens-3.0.2" sources."js-yaml-2.0.5" sources."jsbn-0.1.1" sources."jsesc-1.3.0" - (sources."jshint-2.9.7" // { + (sources."jshint-2.10.2" // { dependencies = [ sources."lodash-4.17.11" sources."minimatch-3.0.4" @@ -8297,12 +8279,11 @@ let sources."findup-sync-2.0.0" ]; }) - sources."loader-runner-2.3.1" + sources."loader-runner-2.4.0" sources."loader-utils-1.2.3" sources."locate-path-2.0.0" sources."lodash-0.9.2" sources."lodash.camelcase-4.3.0" - sources."lodash.debounce-4.0.8" sources."lodash.isplainobject-4.0.6" sources."lodash.memoize-4.1.2" sources."lodash.uniq-4.5.0" @@ -8318,7 +8299,7 @@ let sources."mark.js-8.11.1" sources."math-expression-evaluator-1.2.17" sources."md5.js-1.3.5" - sources."mem-4.0.0" + sources."mem-4.3.0" (sources."memory-fs-0.4.1" // { dependencies = [ sources."readable-stream-2.3.6" @@ -8328,9 +8309,9 @@ let sources."micromatch-3.1.10" sources."miller-rabin-4.0.1" sources."mime-1.6.0" - sources."mime-db-1.37.0" - sources."mime-types-2.1.21" - sources."mimic-fn-1.2.0" + sources."mime-db-1.40.0" + sources."mime-types-2.1.24" + sources."mimic-fn-2.1.0" sources."minimalistic-assert-1.0.1" sources."minimalistic-crypto-utils-1.0.1" sources."minimatch-0.2.14" @@ -8346,22 +8327,22 @@ let sources."minimist-0.0.8" ]; }) - sources."moment-2.23.0" - sources."mousetrap-1.6.2" + sources."moment-2.24.0" + sources."mousetrap-1.6.3" (sources."move-concurrently-1.0.1" // { dependencies = [ - sources."glob-7.1.3" + sources."glob-7.1.4" sources."minimatch-3.0.4" sources."rimraf-2.6.3" ]; }) sources."ms-2.0.0" - sources."nan-2.12.1" + sources."nan-2.13.2" sources."nanomatch-1.2.13" - sources."neo-async-2.6.0" + sources."neo-async-2.6.1" sources."nice-try-1.0.5" sources."no-case-2.3.2" - (sources."node-libs-browser-2.1.0" // { + (sources."node-libs-browser-2.2.0" // { dependencies = [ (sources."readable-stream-2.3.6" // { dependencies = [ @@ -8377,7 +8358,7 @@ let sources."nopt-2.0.0" ]; }) - sources."normalize-path-2.1.1" + sources."normalize-path-3.0.0" sources."normalize-range-0.1.2" sources."normalize-url-1.9.1" sources."npm-run-path-2.0.2" @@ -8399,7 +8380,7 @@ let sources."kind-of-3.2.2" ]; }) - sources."object-keys-1.0.12" + sources."object-keys-1.1.1" sources."object-visit-1.0.1" sources."object.defaults-1.1.0" sources."object.getownpropertydescriptors-2.0.3" @@ -8413,11 +8394,11 @@ let sources."osenv-0.1.5" sources."p-defer-1.0.0" sources."p-finally-1.0.0" - sources."p-is-promise-1.1.0" + sources."p-is-promise-2.1.0" sources."p-limit-1.3.0" sources."p-locate-2.0.0" sources."p-try-1.0.0" - sources."pako-1.0.7" + sources."pako-1.0.10" (sources."parallel-transform-1.1.0" // { dependencies = [ sources."readable-stream-2.3.6" @@ -8425,7 +8406,7 @@ let ]; }) sources."param-case-2.1.1" - sources."parse-asn1-5.1.1" + sources."parse-asn1-5.1.4" sources."parse-filepath-1.0.2" sources."parse-passwd-1.0.0" sources."parse5-3.0.3" @@ -8564,7 +8545,7 @@ let sources."query-string-4.3.4" sources."querystring-0.2.0" sources."querystring-es3-0.2.1" - sources."randombytes-2.0.6" + sources."randombytes-2.1.0" sources."randomfill-1.0.4" sources."raw-loader-1.0.0-beta.0" (sources."readable-stream-1.1.14" // { @@ -8608,14 +8589,9 @@ let }) sources."relateurl-0.2.7" sources."remove-trailing-separator-1.1.0" - (sources."renderkid-2.0.2" // { + (sources."renderkid-2.0.3" // { dependencies = [ sources."ansi-regex-2.1.1" - sources."domhandler-2.1.0" - sources."domutils-1.1.6" - sources."htmlparser2-3.3.0" - sources."isarray-0.0.1" - sources."readable-stream-1.0.34" sources."strip-ansi-3.0.1" ]; }) @@ -8625,7 +8601,7 @@ let sources."request-2.81.0" sources."require-directory-2.1.1" sources."require-main-filename-1.0.1" - sources."resolve-1.9.0" + sources."resolve-1.10.1" sources."resolve-cwd-2.0.0" sources."resolve-dir-1.0.1" sources."resolve-from-3.0.0" @@ -8641,12 +8617,12 @@ let sources."sax-1.2.4" (sources."schema-utils-0.4.7" // { dependencies = [ - sources."ajv-6.6.2" + sources."ajv-6.10.0" ]; }) sources."select-1.1.2" - sources."semver-5.6.0" - sources."serialize-javascript-1.6.1" + sources."semver-5.7.0" + sources."serialize-javascript-1.7.0" sources."set-blocking-2.0.0" (sources."set-value-2.0.0" // { dependencies = [ @@ -8698,7 +8674,7 @@ let sources."source-map-url-0.4.0" sources."split-string-3.1.0" sources."sprintf-js-1.0.3" - (sources."sshpk-1.16.0" // { + (sources."sshpk-1.16.1" // { dependencies = [ sources."assert-plus-1.0.0" ]; @@ -8722,7 +8698,7 @@ let ]; }) sources."sticky-sidebar-3.3.1" - (sources."stream-browserify-2.0.1" // { + (sources."stream-browserify-2.0.2" // { dependencies = [ sources."readable-stream-2.3.6" sources."string_decoder-1.1.1" @@ -8759,7 +8735,7 @@ let sources."js-yaml-3.7.0" ]; }) - sources."tapable-1.1.1" + sources."tapable-1.1.3" sources."through-2.3.8" (sources."through2-2.0.5" // { dependencies = [ @@ -8768,7 +8744,7 @@ let ]; }) sources."timers-browserify-2.0.10" - sources."tiny-emitter-2.0.2" + sources."tiny-emitter-2.1.0" (sources."tiny-lr-fork-0.0.5" // { dependencies = [ sources."debug-0.7.4" @@ -8808,9 +8784,9 @@ let sources."source-map-0.6.1" ]; }) - (sources."uglify-js-3.4.9" // { - dependencies = [ - sources."commander-2.17.1" + (sources."uglify-js-3.4.10" // { + dependencies = [ + sources."commander-2.19.0" sources."source-map-0.6.1" ]; }) @@ -8843,7 +8819,7 @@ let sources."has-values-0.1.4" ]; }) - sources."upath-1.1.0" + sources."upath-1.1.2" sources."upper-case-1.1.3" (sources."uri-js-4.2.2" // { dependencies = [ @@ -8857,14 +8833,14 @@ let ]; }) sources."use-3.1.1" - sources."util-0.10.4" + sources."util-0.11.1" sources."util-deprecate-1.0.2" sources."util.promisify-1.0.0" sources."utila-0.4.0" sources."uuid-3.3.2" - sources."v8-compile-cache-2.0.2" - sources."v8flags-3.1.2" - sources."vendors-1.0.2" + sources."v8-compile-cache-2.0.3" + sources."v8flags-3.1.3" + sources."vendors-1.0.3" (sources."verror-1.10.0" // { dependencies = [ sources."assert-plus-1.0.0" @@ -8879,7 +8855,7 @@ let sources."waypoints-4.0.1" (sources."webpack-4.23.1" // { dependencies = [ - sources."ajv-6.6.2" + sources."ajv-6.10.0" ]; }) (sources."webpack-cli-3.1.2" // { @@ -8919,7 +8895,7 @@ let sources."which-module-2.0.0" sources."window-size-0.1.0" sources."wordwrap-0.0.2" - sources."worker-farm-1.6.0" + sources."worker-farm-1.7.0" (sources."wrap-ansi-2.1.0" // { dependencies = [ sources."ansi-regex-2.1.1" @@ -8935,9 +8911,9 @@ let dependencies = [ sources."find-up-3.0.0" sources."locate-path-3.0.0" - sources."p-limit-2.1.0" + sources."p-limit-2.2.0" sources."p-locate-3.0.0" - sources."p-try-2.0.0" + sources."p-try-2.2.0" ]; }) sources."yargs-parser-11.1.1" diff --git a/pkgs/python-packages-overrides.nix b/pkgs/python-packages-overrides.nix --- a/pkgs/python-packages-overrides.nix +++ b/pkgs/python-packages-overrides.nix @@ -35,6 +35,18 @@ self: super: { ]; }); + "cffi" = super."cffi".override (attrs: { + buildInputs = [ + pkgs.libffi + ]; + }); + + "cryptography" = super."cryptography".override (attrs: { + buildInputs = [ + pkgs.openssl + ]; + }); + "gevent" = super."gevent".override (attrs: { propagatedBuildInputs = attrs.propagatedBuildInputs ++ [ # NOTE: (marcink) odd requirements from gevent aren't set properly, @@ -152,12 +164,6 @@ self: super: { }; }); - "pytest-runner" = super."pytest-runner".override (attrs: { - propagatedBuildInputs = [ - self."setuptools-scm" - ]; - }); - "python-ldap" = super."python-ldap".override (attrs: { propagatedBuildInputs = attrs.propagatedBuildInputs ++ [ pkgs.openldap diff --git a/pkgs/python-packages.nix b/pkgs/python-packages.nix --- a/pkgs/python-packages.nix +++ b/pkgs/python-packages.nix @@ -5,7 +5,7 @@ self: super: { "alembic" = super.buildPythonPackage { - name = "alembic-1.0.5"; + name = "alembic-1.0.10"; doCheck = false; propagatedBuildInputs = [ self."sqlalchemy" @@ -14,8 +14,8 @@ self: super: { self."python-dateutil" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/1c/65/b8e4f5b2f345bb13b5e0a3fddd892b0b3f0e8ad4880e954fdc6a50d00d84/alembic-1.0.5.tar.gz"; - sha256 = "0rpjqp2iq6p49x1nli18ivak1izz547nnjxi110mzrgc1v7dxzz9"; + url = "https://files.pythonhosted.org/packages/6e/8b/fa3bd058cccd5e9177fea4efa26bfb769228fdd3178436ad5e05830ef6ef/alembic-1.0.10.tar.gz"; + sha256 = "1dwl0264r6ri2jyrjr68am04x538ab26xwy4crqjnnhm4alwm3c2"; }; meta = { license = [ pkgs.lib.licenses.mit ]; @@ -51,6 +51,17 @@ self: super: { license = [ pkgs.lib.licenses.bsdOriginal ]; }; }; + "asn1crypto" = super.buildPythonPackage { + name = "asn1crypto-0.24.0"; + doCheck = false; + src = fetchurl { + url = "https://files.pythonhosted.org/packages/fc/f1/8db7daa71f414ddabfa056c4ef792e1461ff655c2ae2928a2b675bfed6b4/asn1crypto-0.24.0.tar.gz"; + sha256 = "0jaf8rf9dx1lf23xfv2cdd5h52f1qr3w8k63985bc35g3d220p4x"; + }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; + }; "atomicwrites" = super.buildPythonPackage { name = "atomicwrites-1.2.1"; doCheck = false; @@ -77,8 +88,8 @@ self: super: { name = "authomatic-0.1.0.post1"; doCheck = false; src = fetchurl { - url = "https://code.rhodecode.com/upstream/authomatic/archive/90a9ce60cc405ae8a2bf5c3713acd5d78579a04e.tar.gz?md5=3c68720a1322b25254009518d1ff6801"; - sha256 = "1cgk0a86sbsjbri06gf5z5l4npwkjdxw6fdnwl4vvfmxs2sx9yxw"; + url = "https://code.rhodecode.com/upstream/authomatic/artifacts/download/0-4fe9c041-a567-4f84-be4c-7efa2a606d3c.tar.gz?md5=f6bdc3c769688212db68233e8d2b0383"; + sha256 = "0pc716mva0ym6xd8jwzjbjp8dqxy9069wwwv2aqwb8lyhl4757ab"; }; meta = { license = [ pkgs.lib.licenses.mit ]; @@ -146,15 +157,15 @@ self: super: { }; }; "bleach" = super.buildPythonPackage { - name = "bleach-3.0.2"; + name = "bleach-3.1.0"; doCheck = false; propagatedBuildInputs = [ self."six" self."webencodings" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/ae/31/680afc7d44040004296a2d8f0584983c2f2386448cd9d0964197e6c1160e/bleach-3.0.2.tar.gz"; - sha256 = "06474zg7f73hv8h1xw2wcsmvn2ygj73zxgxxqg8zcx8ap1srdls8"; + url = "https://files.pythonhosted.org/packages/78/5a/0df03e8735cd9c75167528299c738702437589b9c71a849489d00ffa82e8/bleach-3.1.0.tar.gz"; + sha256 = "1yhrgrhkln8bd6gn3imj69g1h4xqah9gaz9q26crqr6gmmvpzprz"; }; meta = { license = [ pkgs.lib.licenses.asl20 ]; @@ -187,6 +198,20 @@ self: super: { license = [ pkgs.lib.licenses.bsdOriginal ]; }; }; + "cffi" = super.buildPythonPackage { + name = "cffi-1.12.2"; + doCheck = false; + propagatedBuildInputs = [ + self."pycparser" + ]; + src = fetchurl { + url = "https://files.pythonhosted.org/packages/64/7c/27367b38e6cc3e1f49f193deb761fe75cda9f95da37b67b422e62281fcac/cffi-1.12.2.tar.gz"; + sha256 = "19qfks2djya8vix95bmg3xzipjb8w9b8mbj4j5k2hqkc8j58f4z1"; + }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; + }; "chameleon" = super.buildPythonPackage { name = "chameleon-2.24"; doCheck = false; @@ -230,7 +255,7 @@ self: super: { }; }; "colander" = super.buildPythonPackage { - name = "colander-1.5.1"; + name = "colander-1.7.0"; doCheck = false; propagatedBuildInputs = [ self."translationstring" @@ -238,8 +263,8 @@ self: super: { self."enum34" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/ec/d1/fcca811a0a692c69d27e36b4d11a73acb98b4bab48323442642b6fd4386d/colander-1.5.1.tar.gz"; - sha256 = "18ah4cwwxnpm6qxi6x9ipy51dal4spd343h44s5wd01cnhgrwsyq"; + url = "https://files.pythonhosted.org/packages/db/e4/74ab06f54211917b41865cafc987ce511e35503de48da9bfe9358a1bdc3e/colander-1.7.0.tar.gz"; + sha256 = "1wl1bqab307lbbcjx81i28s3yl6dlm4rf15fxawkjb6j48x1cn6p"; }; meta = { license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ]; @@ -252,19 +277,19 @@ self: super: { self."six" ]; src = fetchurl { - url = "https://code.rhodecode.com/upstream/configobj/archive/a11ff0a0bd4fbda9e3a91267e720f88329efb4a6.tar.gz?md5=9916c524ea11a6c418217af6b28d4b3c"; - sha256 = "1hhcxirwvg58grlfr177b3awhbq8hlx1l3lh69ifl1ki7lfd1s1x"; + url = "https://code.rhodecode.com/upstream/configobj/artifacts/download/0-012de99a-b1e1-4f64-a5c0-07a98a41b324.tar.gz?md5=6a513f51fe04b2c18cf84c1395a7c626"; + sha256 = "0kqfrdfr14mw8yd8qwq14dv2xghpkjmd3yjsy8dfcbvpcc17xnxp"; }; meta = { license = [ pkgs.lib.licenses.bsdOriginal ]; }; }; "configparser" = super.buildPythonPackage { - name = "configparser-3.7.1"; + name = "configparser-3.7.4"; doCheck = false; src = fetchurl { - url = "https://files.pythonhosted.org/packages/b6/a6/eceea7c5a5dbcf56815bed411c38cabd8a879386be10717b160e7362b5a2/configparser-3.7.1.tar.gz"; - sha256 = "0cnz213il9lhgda6x70fw7mfqr8da43s3wm343lwzhqx94mgmmav"; + url = "https://files.pythonhosted.org/packages/e2/1c/83fd53748d8245cb9a3399f705c251d3fc0ce7df04450aac1cfc49dd6a0f/configparser-3.7.4.tar.gz"; + sha256 = "0xac32886ihs2xg7w1gppcq2sgin5qsm8lqwijs5xifq9w0x0q6s"; }; meta = { license = [ pkgs.lib.licenses.mit ]; @@ -285,16 +310,34 @@ self: super: { }; }; "coverage" = super.buildPythonPackage { - name = "coverage-4.5.1"; + name = "coverage-4.5.3"; doCheck = false; src = fetchurl { - url = "https://files.pythonhosted.org/packages/35/fe/e7df7289d717426093c68d156e0fd9117c8f4872b6588e8a8928a0f68424/coverage-4.5.1.tar.gz"; - sha256 = "1wbrzpxka3xd4nmmkc6q0ir343d91kymwsm8pbmwa0d2a7q4ir2n"; + url = "https://files.pythonhosted.org/packages/82/70/2280b5b29a0352519bb95ab0ef1ea942d40466ca71c53a2085bdeff7b0eb/coverage-4.5.3.tar.gz"; + sha256 = "02f6m073qdispn96rc616hg0rnmw1pgqzw3bgxwiwza4zf9hirlx"; }; meta = { license = [ pkgs.lib.licenses.asl20 ]; }; }; + "cryptography" = super.buildPythonPackage { + name = "cryptography-2.6.1"; + doCheck = false; + propagatedBuildInputs = [ + self."asn1crypto" + self."six" + self."cffi" + self."enum34" + self."ipaddress" + ]; + src = fetchurl { + url = "https://files.pythonhosted.org/packages/07/ca/bc827c5e55918ad223d59d299fff92f3563476c3b00d0a9157d9c0217449/cryptography-2.6.1.tar.gz"; + sha256 = "19iwz5avym5zl6jrrrkym1rdaa9h61j20ph4cswsqgv8xg5j3j16"; + }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal { fullName = "BSD or Apache License, Version 2.0"; } pkgs.lib.licenses.asl20 ]; + }; + }; "cssselect" = super.buildPythonPackage { name = "cssselect-1.0.3"; doCheck = false; @@ -337,11 +380,11 @@ self: super: { }; }; "defusedxml" = super.buildPythonPackage { - name = "defusedxml-0.5.0"; + name = "defusedxml-0.6.0"; doCheck = false; src = fetchurl { - url = "https://files.pythonhosted.org/packages/74/ba/4ba4e89e21b5a2e267d80736ea674609a0a33cc4435a6d748ef04f1f9374/defusedxml-0.5.0.tar.gz"; - sha256 = "1x54n0h8hl92vvwyymx883fbqpqjwn2mc8fb383bcg3z9zwz5mr4"; + url = "https://files.pythonhosted.org/packages/a4/5f/f8aa58ca0cf01cbcee728abc9d88bfeb74e95e6cb4334cfd5bed5673ea77/defusedxml-0.6.0.tar.gz"; + sha256 = "1xbp8fivl3wlbyg2jrvs4lalaqv1xp9a9f29p75wdx2s2d6h717n"; }; meta = { license = [ pkgs.lib.licenses.psfl ]; @@ -399,11 +442,11 @@ self: super: { }; }; "ecdsa" = super.buildPythonPackage { - name = "ecdsa-0.13"; + name = "ecdsa-0.13.2"; doCheck = false; src = fetchurl { - url = "https://files.pythonhosted.org/packages/f9/e5/99ebb176e47f150ac115ffeda5fedb6a3dbb3c00c74a59fd84ddf12f5857/ecdsa-0.13.tar.gz"; - sha256 = "1yj31j0asmrx4an9xvsaj2icdmzy6pw0glfpqrrkrphwdpi1xkv4"; + url = "https://files.pythonhosted.org/packages/51/76/139bf6e9b7b6684d5891212cdbd9e0739f2bfc03f380a1a6ffa700f392ac/ecdsa-0.13.2.tar.gz"; + sha256 = "116qaq7bh4lcynzi613960jhsnn19v0kmsqwahiwjfj14gx4y0sw"; }; meta = { license = [ pkgs.lib.licenses.mit ]; @@ -491,8 +534,8 @@ self: super: { self."configparser" ]; src = fetchurl { - url = "https://code.rhodecode.com/upstream/entrypoints/archive/96e6d645684e1af3d7df5b5272f3fe85a546b233.tar.gz?md5=7db37771aea9ac9fefe093e5d6987313"; - sha256 = "0bihrdp8ahsys437kxdhk52gz6kib8rxjv71i93wkw7594fcaxll"; + url = "https://code.rhodecode.com/upstream/entrypoints/artifacts/download/0-8e9ee9e4-c4db-409c-b07e-81568fd1832d.tar.gz?md5=3a027b8ff1d257b91fe257de6c43357d"; + sha256 = "0qih72n2myclanplqipqxpgpj9d2yhff1pz5d02zq1cfqyd173w5"; }; meta = { license = [ pkgs.lib.licenses.mit ]; @@ -623,11 +666,11 @@ self: super: { }; }; "hupper" = super.buildPythonPackage { - name = "hupper-1.4.2"; + name = "hupper-1.6.1"; doCheck = false; src = fetchurl { - url = "https://files.pythonhosted.org/packages/f1/75/1915dc7650b4867fa3049256e24ca8eddb5989998fcec788cf52b9812dfc/hupper-1.4.2.tar.gz"; - sha256 = "16vb9fkiaakdpcp6pn56h3w0dwvm67bxq2k2dv4i382qhqwphdzb"; + url = "https://files.pythonhosted.org/packages/85/d9/e005d357b11249c5d70ddf5b7adab2e4c0da4e8b0531ff146917a04fe6c0/hupper-1.6.1.tar.gz"; + sha256 = "0d3cvkc8ssgwk54wvhbifj56ry97qi10pfzwfk8vwzzcikbfp3zy"; }; meta = { license = [ pkgs.lib.licenses.mit ]; @@ -671,15 +714,15 @@ self: super: { }; }; "ipdb" = super.buildPythonPackage { - name = "ipdb-0.11"; + name = "ipdb-0.12"; doCheck = false; propagatedBuildInputs = [ self."setuptools" self."ipython" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/80/fe/4564de08f174f3846364b3add8426d14cebee228f741c27e702b2877e85b/ipdb-0.11.tar.gz"; - sha256 = "02m0l8wrhhd3z7dg3czn5ys1g5pxib516hpshdzp7rxzsxgcd0bh"; + url = "https://files.pythonhosted.org/packages/6d/43/c3c2e866a8803e196d6209595020a4a6db1a3c5d07c01455669497ae23d0/ipdb-0.12.tar.gz"; + sha256 = "1khr2n7xfy8hg65kj1bsrjq9g7656pp0ybfa8abpbzpdawji3qnw"; }; meta = { license = [ pkgs.lib.licenses.bsdOriginal ]; @@ -802,14 +845,14 @@ self: super: { }; }; "jupyter-core" = super.buildPythonPackage { - name = "jupyter-core-4.4.0"; + name = "jupyter-core-4.5.0"; doCheck = false; propagatedBuildInputs = [ self."traitlets" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/b6/2d/2804f4de3a95583f65e5dcb4d7c8c7183124882323758996e867f47e72af/jupyter_core-4.4.0.tar.gz"; - sha256 = "1dy083rarba8prn9f9srxq3c7n7vyql02ycrqq306c40lr57aw5s"; + url = "https://files.pythonhosted.org/packages/4a/de/ff4ca734656d17ebe0450807b59d728f45277e2e7f4b82bc9aae6cb82961/jupyter_core-4.5.0.tar.gz"; + sha256 = "1xr4pbghwk5hayn5wwnhb7z95380r45p79gf5if5pi1akwg7qvic"; }; meta = { license = [ pkgs.lib.licenses.bsdOriginal ]; @@ -1008,14 +1051,14 @@ self: super: { }; }; "paste" = super.buildPythonPackage { - name = "paste-3.0.5"; + name = "paste-3.0.8"; doCheck = false; propagatedBuildInputs = [ self."six" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/d4/41/91bde422400786b1b06357c1e6e3a5379f54dc3002aeb337cb767233304e/Paste-3.0.5.tar.gz"; - sha256 = "1a6i8fh1fg8r4x800fvy9r82m15clwjim6yf2g9r4dff0y40dchv"; + url = "https://files.pythonhosted.org/packages/66/65/e3acf1663438483c1f6ced0b6c6f3b90da9f0faacb0a6e2aa0f3f9f4b235/Paste-3.0.8.tar.gz"; + sha256 = "05w1sh6ky4d7pmdb8nv82n13w22jcn3qsagg5ih3hjmbws9kkwf4"; }; meta = { license = [ pkgs.lib.licenses.mit ]; @@ -1033,7 +1076,7 @@ self: super: { }; }; "pastescript" = super.buildPythonPackage { - name = "pastescript-3.0.0"; + name = "pastescript-3.1.0"; doCheck = false; propagatedBuildInputs = [ self."paste" @@ -1041,23 +1084,23 @@ self: super: { self."six" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/08/2a/3797377a884ab9a064ad4d564ed612e54d26d7997caa8229c9c9df4eac31/PasteScript-3.0.0.tar.gz"; - sha256 = "1hvmyz1sbn7ws1syw567ph7km9fi0wi75r3vlyzx6sk0z26xkm6r"; + url = "https://files.pythonhosted.org/packages/9e/1d/14db1c283eb21a5d36b6ba1114c13b709629711e64acab653d9994fe346f/PasteScript-3.1.0.tar.gz"; + sha256 = "02qcxjjr32ks7a6d4f533wl34ysc7yhwlrfcyqwqbzr52250v4fs"; }; meta = { license = [ pkgs.lib.licenses.mit ]; }; }; "pathlib2" = super.buildPythonPackage { - name = "pathlib2-2.3.3"; + name = "pathlib2-2.3.4"; doCheck = false; propagatedBuildInputs = [ self."six" self."scandir" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/bf/d7/a2568f4596b75d2c6e2b4094a7e64f620decc7887f69a1f2811931ea15b9/pathlib2-2.3.3.tar.gz"; - sha256 = "0hpp92vqqgcd8h92msm9slv161b1q160igjwnkf2ag6cx0c96695"; + url = "https://files.pythonhosted.org/packages/b5/f4/9c7cc726ece2498b6c8b62d3262aa43f59039b953fe23c9964ac5e18d40b/pathlib2-2.3.4.tar.gz"; + sha256 = "1y0f9rkm1924zrc5dn4bwxlhgdkbml82lkcc28l5rgmr7d918q24"; }; meta = { license = [ pkgs.lib.licenses.mit ]; @@ -1075,14 +1118,14 @@ self: super: { }; }; "pexpect" = super.buildPythonPackage { - name = "pexpect-4.6.0"; + name = "pexpect-4.7.0"; doCheck = false; propagatedBuildInputs = [ self."ptyprocess" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/89/43/07d07654ee3e25235d8cea4164cdee0ec39d1fda8e9203156ebe403ffda4/pexpect-4.6.0.tar.gz"; - sha256 = "1fla85g47iaxxpjhp9vkxdnv4pgc7rplfy6ja491smrrk0jqi3ia"; + url = "https://files.pythonhosted.org/packages/1c/b1/362a0d4235496cb42c33d1d8732b5e2c607b0129ad5fdd76f5a583b9fcb3/pexpect-4.7.0.tar.gz"; + sha256 = "1sv2rri15zwhds85a4kamwh9pj49qcxv7m4miyr4jfpfwv81yb4y"; }; meta = { license = [ pkgs.lib.licenses.isc { fullName = "ISC License (ISCL)"; } ]; @@ -1117,63 +1160,63 @@ self: super: { }; }; "plaster-pastedeploy" = super.buildPythonPackage { - name = "plaster-pastedeploy-0.6"; + name = "plaster-pastedeploy-0.7"; doCheck = false; propagatedBuildInputs = [ self."pastedeploy" self."plaster" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/3f/e7/6a6833158d2038ec40085433308a1e164fd1dac595513f6dd556d5669bb8/plaster_pastedeploy-0.6.tar.gz"; - sha256 = "1bkggk18f4z2bmsmxyxabvf62znvjwbivzh880419r3ap0616cf2"; + url = "https://files.pythonhosted.org/packages/99/69/2d3bc33091249266a1bd3cf24499e40ab31d54dffb4a7d76fe647950b98c/plaster_pastedeploy-0.7.tar.gz"; + sha256 = "1zg7gcsvc1kzay1ry5p699rg2qavfsxqwl17mqxzr0gzw6j9679r"; }; meta = { license = [ pkgs.lib.licenses.mit ]; }; }; "pluggy" = super.buildPythonPackage { - name = "pluggy-0.8.1"; + name = "pluggy-0.11.0"; doCheck = false; src = fetchurl { - url = "https://files.pythonhosted.org/packages/38/e1/83b10c17688af7b2998fa5342fec58ecbd2a5a7499f31e606ae6640b71ac/pluggy-0.8.1.tar.gz"; - sha256 = "05l6g42p9ilmabw0hlbiyxy6gyzjri41m5l11a8dzgvi77q35p4d"; + url = "https://files.pythonhosted.org/packages/0d/a1/862ab336e8128fde20981d2c1aa8506693412daf5083b1911d539412676b/pluggy-0.11.0.tar.gz"; + sha256 = "10511a54dvafw1jrk75mrhml53c7b7w4yaw7241696lc2hfvr895"; }; meta = { license = [ pkgs.lib.licenses.mit ]; }; }; "prompt-toolkit" = super.buildPythonPackage { - name = "prompt-toolkit-1.0.15"; + name = "prompt-toolkit-1.0.16"; doCheck = false; propagatedBuildInputs = [ self."six" self."wcwidth" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/8a/ad/cf6b128866e78ad6d7f1dc5b7f99885fb813393d9860778b2984582e81b5/prompt_toolkit-1.0.15.tar.gz"; - sha256 = "05v9h5nydljwpj5nm8n804ms0glajwfy1zagrzqrg91wk3qqi1c5"; + url = "https://files.pythonhosted.org/packages/f1/03/bb36771dc9fa7553ac4bdc639a9ecdf6fda0ff4176faf940d97e3c16e41d/prompt_toolkit-1.0.16.tar.gz"; + sha256 = "1d65hm6nf0cbq0q0121m60zzy4s1fpg9fn761s1yxf08dridvkn1"; }; meta = { license = [ pkgs.lib.licenses.bsdOriginal ]; }; }; "psutil" = super.buildPythonPackage { - name = "psutil-5.4.8"; + name = "psutil-5.5.1"; doCheck = false; src = fetchurl { - url = "https://files.pythonhosted.org/packages/e3/58/0eae6e4466e5abf779d7e2b71fac7fba5f59e00ea36ddb3ed690419ccb0f/psutil-5.4.8.tar.gz"; - sha256 = "1hyna338sml2cl1mfb2gs89np18z27mvyhmq4ifh22x07n7mq9kf"; + url = "https://files.pythonhosted.org/packages/c7/01/7c30b247cdc5ba29623faa5c8cf1f1bbf7e041783c340414b0ed7e067c64/psutil-5.5.1.tar.gz"; + sha256 = "045qaqvn6k90bj5bcy259yrwcd2afgznaav3sfhphy9b8ambzkkj"; }; meta = { license = [ pkgs.lib.licenses.bsdOriginal ]; }; }; "psycopg2" = super.buildPythonPackage { - name = "psycopg2-2.7.5"; + name = "psycopg2-2.8.3"; doCheck = false; src = fetchurl { - url = "https://files.pythonhosted.org/packages/b2/c1/7bf6c464e903ffc4f3f5907c389e5a4199666bf57f6cd6bf46c17912a1f9/psycopg2-2.7.5.tar.gz"; - sha256 = "17klx964gw8z0znl0raz3by8vdc7cq5gxj4pdcrfcina84nrdkzc"; + url = "https://files.pythonhosted.org/packages/5c/1c/6997288da181277a0c29bc39a5f9143ff20b8c99f2a7d059cfb55163e165/psycopg2-2.8.3.tar.gz"; + sha256 = "0ms4kx0p5n281l89awccix4d05ybmdngnjjpi9jbzd0rhf1nwyl9"; }; meta = { license = [ pkgs.lib.licenses.zpl21 { fullName = "GNU Library or Lesser General Public License (LGPL)"; } { fullName = "LGPL with exceptions or ZPL"; } ]; @@ -1239,14 +1282,25 @@ self: super: { }; }; "pyasn1-modules" = super.buildPythonPackage { - name = "pyasn1-modules-0.2.4"; + name = "pyasn1-modules-0.2.5"; doCheck = false; propagatedBuildInputs = [ self."pyasn1" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/bd/a5/ef7bf693e8a8f015386c9167483199f54f8a8ec01d1c737e05524f16e792/pyasn1-modules-0.2.4.tar.gz"; - sha256 = "0z3w5dqrrvdplg9ma45j8n23xvyrj9ki8mg4ibqbn7l4qpl90855"; + url = "https://files.pythonhosted.org/packages/ec/0b/69620cb04a016e4a1e8e352e8a42717862129b574b3479adb2358a1f12f7/pyasn1-modules-0.2.5.tar.gz"; + sha256 = "15nvfx0vnl8akdlv3k6s0n80vqvryj82bm040jdsn7wmyxl1ywpg"; + }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; + }; + "pycparser" = super.buildPythonPackage { + name = "pycparser-2.19"; + doCheck = false; + src = fetchurl { + url = "https://files.pythonhosted.org/packages/68/9e/49196946aee219aead1290e00d1e7fdeab8567783e83e1b9ab5585e6206a/pycparser-2.19.tar.gz"; + sha256 = "1cr5dcj9628lkz1qlwq3fv97c25363qppkmcayqvd05dpy573259"; }; meta = { license = [ pkgs.lib.licenses.bsdOriginal ]; @@ -1274,23 +1328,12 @@ self: super: { license = [ pkgs.lib.licenses.mit { fullName = "LGPL/MIT"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ]; }; }; - "pyflakes" = super.buildPythonPackage { - name = "pyflakes-0.8.1"; + "pygments" = super.buildPythonPackage { + name = "pygments-2.4.2"; doCheck = false; src = fetchurl { - url = "https://files.pythonhosted.org/packages/75/22/a90ec0252f4f87f3ffb6336504de71fe16a49d69c4538dae2f12b9360a38/pyflakes-0.8.1.tar.gz"; - sha256 = "0sbpq6pqm1i9wqi41mlfrsc5rk92jv4mskvlyxmnhlbdnc80ma1z"; - }; - meta = { - license = [ pkgs.lib.licenses.mit ]; - }; - }; - "pygments" = super.buildPythonPackage { - name = "pygments-2.3.1"; - doCheck = false; - src = fetchurl { - url = "https://files.pythonhosted.org/packages/64/69/413708eaf3a64a6abb8972644e0f20891a55e621c6759e2c3f3891e05d63/Pygments-2.3.1.tar.gz"; - sha256 = "0ji87g09jph8jqcvclgb02qvxasdnr9pzvk90rl66d90yqcxmyjz"; + url = "https://files.pythonhosted.org/packages/7e/ae/26808275fc76bf2832deb10d3a3ed3107bc4de01b85dcccbe525f2cd6d1e/Pygments-2.4.2.tar.gz"; + sha256 = "15v2sqm5g12bqa0c7wikfh9ck2nl97ayizy1hpqhmws5gqalq748"; }; meta = { license = [ pkgs.lib.licenses.bsdOriginal ]; @@ -1330,7 +1373,7 @@ self: super: { }; }; "pyramid" = super.buildPythonPackage { - name = "pyramid-1.10.1"; + name = "pyramid-1.10.4"; doCheck = false; propagatedBuildInputs = [ self."hupper" @@ -1345,28 +1388,13 @@ self: super: { self."repoze.lru" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/0a/3e/22e3ac9be1b70a01139adba8906ee4b8f628bb469fea3c52f6c97b73063c/pyramid-1.10.1.tar.gz"; - sha256 = "1h5105nfh6rsrfjiyw20aavyibj36la3hajy6vh1fa77xb4y3hrp"; + url = "https://files.pythonhosted.org/packages/c2/43/1ae701c9c6bb3a434358e678a5e72c96e8aa55cf4cb1d2fa2041b5dd38b7/pyramid-1.10.4.tar.gz"; + sha256 = "0rkxs1ajycg2zh1c94xlmls56mx5m161sn8112skj0amza6cn36q"; }; meta = { license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ]; }; }; - "pyramid-beaker" = super.buildPythonPackage { - name = "pyramid-beaker-0.8"; - doCheck = false; - propagatedBuildInputs = [ - self."pyramid" - self."beaker" - ]; - src = fetchurl { - url = "https://files.pythonhosted.org/packages/d9/6e/b85426e00fd3d57f4545f74e1c3828552d8700f13ededeef9233f7bca8be/pyramid_beaker-0.8.tar.gz"; - sha256 = "0hflx3qkcdml1mwpq53sz46s7jickpfn0zy0ns2c7j445j66bp3p"; - }; - meta = { - license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ]; - }; - }; "pyramid-debugtoolbar" = super.buildPythonPackage { name = "pyramid-debugtoolbar-4.5"; doCheck = false; @@ -1538,14 +1566,14 @@ self: super: { }; }; "python-dateutil" = super.buildPythonPackage { - name = "python-dateutil-2.7.5"; + name = "python-dateutil-2.8.0"; doCheck = false; propagatedBuildInputs = [ self."six" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/0e/01/68747933e8d12263d41ce08119620d9a7e5eb72c876a3442257f74490da0/python-dateutil-2.7.5.tar.gz"; - sha256 = "00ngwcdw36w5b37b51mdwn3qxid9zdf3kpffv2q6n9kl05y2iyc8"; + url = "https://files.pythonhosted.org/packages/ad/99/5b2e99737edeb28c71bcbec5b5dda19d0d9ef3ca3e92e3e925e7c0bb364c/python-dateutil-2.8.0.tar.gz"; + sha256 = "17nsfhy4xdz1khrfxa61vd7pmvd5z0wa3zb6v4gb4kfnykv0b668"; }; meta = { license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.asl20 { fullName = "Dual License"; } ]; @@ -1690,7 +1718,7 @@ self: super: { }; }; "rhodecode-enterprise-ce" = super.buildPythonPackage { - name = "rhodecode-enterprise-ce-4.16.2"; + name = "rhodecode-enterprise-ce-4.17.0"; buildInputs = [ self."pytest" self."py" @@ -1709,36 +1737,29 @@ self: super: { ]; doCheck = true; propagatedBuildInputs = [ - self."setuptools-scm" self."amqp" self."authomatic" - self."atomicwrites" - self."attrs" self."babel" self."beaker" self."bleach" self."celery" - self."chameleon" self."channelstream" self."click" self."colander" self."configobj" self."cssselect" + self."cryptography" self."decorator" self."deform" self."docutils" self."dogpile.cache" self."dogpile.core" - self."ecdsa" self."formencode" self."future" self."futures" - self."gnureadline" self."infrae.cache" self."iso8601" self."itsdangerous" - self."jinja2" - self."billiard" self."kombu" self."lxml" self."mako" @@ -1747,21 +1768,18 @@ self: super: { self."msgpack-python" self."pyotp" self."packaging" + self."pathlib2" self."paste" self."pastedeploy" self."pastescript" - self."pathlib2" self."peppercorn" self."psutil" self."py-bcrypt" + self."pycurl" self."pycrypto" - self."pycurl" - self."pyflakes" self."pygments" self."pyparsing" - self."pyramid-beaker" self."pyramid-debugtoolbar" - self."pyramid-jinja2" self."pyramid-mako" self."pyramid" self."pyramid-mailer" @@ -1784,7 +1802,6 @@ self: super: { self."sshpubkeys" self."subprocess32" self."supervisor" - self."tempita" self."translationstring" self."urllib3" self."urlobject" @@ -1813,7 +1830,6 @@ self: super: { self."greenlet" self."gunicorn" self."waitress" - self."setproctitle" self."ipdb" self."ipython" self."rhodecode-tools" @@ -1855,8 +1871,8 @@ self: super: { self."elasticsearch1-dsl" ]; src = fetchurl { - url = "https://code.rhodecode.com/rhodecode-tools-ce/archive/v1.2.1.tar.gz?md5=25bc2f7de1da318e547236d3fb463d28"; - sha256 = "1k8l3s4mvshza1zay6dfxprq54fyb5dc85dqdva9wa3f466y0adk"; + url = "https://code.rhodecode.com/rhodecode-tools-ce/artifacts/download/0-10ac93f4-bb7d-4b97-baea-68110743dd5a.tar.gz?md5=962dc77c06aceee62282b98d33149661"; + sha256 = "1vfhgf46inbx7jvlfx4fdzh3vz7lh37r291gzb5hx447pfm3qllg"; }; meta = { license = [ { fullName = "Apache 2.0 and Proprietary"; } ]; @@ -1878,11 +1894,11 @@ self: super: { }; }; "scandir" = super.buildPythonPackage { - name = "scandir-1.9.0"; + name = "scandir-1.10.0"; doCheck = false; src = fetchurl { - url = "https://files.pythonhosted.org/packages/16/2a/557af1181e6b4e30254d5a6163b18f5053791ca66e251e77ab08887e8fe3/scandir-1.9.0.tar.gz"; - sha256 = "0r3hvf1a9jm1rkqgx40gxkmccknkaiqjavs8lccgq9s8khh5x5s4"; + url = "https://files.pythonhosted.org/packages/df/f5/9c052db7bd54d0cbf1bc0bb6554362bba1012d03e5888950a4f5c5dadc4e/scandir-1.10.0.tar.gz"; + sha256 = "1bkqwmf056pkchf05ywbnf659wqlp6lljcdb0y88wr9f0vv32ijd"; }; meta = { license = [ pkgs.lib.licenses.bsdOriginal { fullName = "New BSD License"; } ]; @@ -1900,22 +1916,11 @@ self: super: { }; }; "setuptools" = super.buildPythonPackage { - name = "setuptools-40.8.0"; + name = "setuptools-41.0.1"; doCheck = false; src = fetchurl { - url = "https://files.pythonhosted.org/packages/c2/f7/c7b501b783e5a74cf1768bc174ee4fb0a8a6ee5af6afa92274ff964703e0/setuptools-40.8.0.zip"; - sha256 = "0k9hifpgahnw2a26w3cr346iy733k6d3nwh3f7g9m13y6f8fqkkf"; - }; - meta = { - license = [ pkgs.lib.licenses.mit ]; - }; - }; - "setuptools-scm" = super.buildPythonPackage { - name = "setuptools-scm-2.1.0"; - doCheck = false; - src = fetchurl { - url = "https://files.pythonhosted.org/packages/e5/62/f9e1ac314464eb5945c97542acb6bf6f3381dfa5d7a658de7730c36f31a1/setuptools_scm-2.1.0.tar.gz"; - sha256 = "0yb364cgk15sfw3x8ln4ssh98z1dj6n8iiz4r2rw1cfsxhgi8rx7"; + url = "https://files.pythonhosted.org/packages/1d/64/a18a487b4391a05b9c7f938b94a16d80305bf0369c6b0b9509e86165e1d3/setuptools-41.0.1.zip"; + sha256 = "04sns22y2hhsrwfy1mha2lgslvpjsjsz8xws7h2rh5a7ylkd28m2"; }; meta = { license = [ pkgs.lib.licenses.mit ]; @@ -1966,40 +1971,40 @@ self: super: { }; }; "sshpubkeys" = super.buildPythonPackage { - name = "sshpubkeys-2.2.0"; + name = "sshpubkeys-3.1.0"; doCheck = false; propagatedBuildInputs = [ - self."pycrypto" + self."cryptography" self."ecdsa" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/27/da/337fabeb3dca6b62039a93ceaa636f25065e0ae92b575b1235342076cf0a/sshpubkeys-2.2.0.tar.gz"; - sha256 = "0r4kpwzmg96a2x56pllik7dmc3fnqk189v3sfgsi07q2ryrhr6xm"; + url = "https://files.pythonhosted.org/packages/00/23/f7508a12007c96861c3da811992f14283d79c819d71a217b3e12d5196649/sshpubkeys-3.1.0.tar.gz"; + sha256 = "105g2li04nm1hb15a2y6hm9m9k7fbrkd5l3gy12w3kgcmsf3k25k"; }; meta = { license = [ pkgs.lib.licenses.bsdOriginal ]; }; }; "subprocess32" = super.buildPythonPackage { - name = "subprocess32-3.5.3"; + name = "subprocess32-3.5.4"; doCheck = false; src = fetchurl { - url = "https://files.pythonhosted.org/packages/be/2b/beeba583e9877e64db10b52a96915afc0feabf7144dcbf2a0d0ea68bf73d/subprocess32-3.5.3.tar.gz"; - sha256 = "1hr5fan8i719hmlmz73hf8rhq74014w07d8ryg7krvvf6692kj3b"; + url = "https://files.pythonhosted.org/packages/32/c8/564be4d12629b912ea431f1a50eb8b3b9d00f1a0b1ceff17f266be190007/subprocess32-3.5.4.tar.gz"; + sha256 = "17f7mvwx2271s1wrl0qac3wjqqnrqag866zs3qc8v5wp0k43fagb"; }; meta = { license = [ pkgs.lib.licenses.psfl ]; }; }; "supervisor" = super.buildPythonPackage { - name = "supervisor-3.3.5"; + name = "supervisor-4.0.3"; doCheck = false; propagatedBuildInputs = [ self."meld3" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/ba/65/92575a8757ed576beaee59251f64a3287bde82bdc03964b89df9e1d29e1b/supervisor-3.3.5.tar.gz"; - sha256 = "1w3ahridzbc6rxfpbyx8lij6pjlcgf2ymzyg53llkjqxalp6sk8v"; + url = "https://files.pythonhosted.org/packages/97/48/f38bf70bd9282d1a18d591616557cc1a77a1c627d57dff66ead65c891dc8/supervisor-4.0.3.tar.gz"; + sha256 = "17hla7mx6w5m5jzkkjxgqa8wpswqmfhbhf49f692hw78fg0ans7p"; }; meta = { license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ]; @@ -2128,22 +2133,22 @@ self: super: { }; }; "vine" = super.buildPythonPackage { - name = "vine-1.2.0"; + name = "vine-1.3.0"; doCheck = false; src = fetchurl { - url = "https://files.pythonhosted.org/packages/46/1a/c94317efa98040c5d50fe3cf9080cafb0372ff5afb0283dc018c751c6746/vine-1.2.0.tar.gz"; - sha256 = "0xjz2sjbr5jrpjk411b7alkghdskhphgsqqrbi7abqfh2pli6j7f"; + url = "https://files.pythonhosted.org/packages/1c/e1/79fb8046e607dd6c2ad05c9b8ebac9d0bd31d086a08f02699e96fc5b3046/vine-1.3.0.tar.gz"; + sha256 = "11ydsbhl1vabndc2r979dv61s6j2b0giq6dgvryifvq1m7bycghk"; }; meta = { license = [ pkgs.lib.licenses.bsdOriginal ]; }; }; "waitress" = super.buildPythonPackage { - name = "waitress-1.1.0"; + name = "waitress-1.3.0"; doCheck = false; src = fetchurl { - url = "https://files.pythonhosted.org/packages/3c/68/1c10dd5c556872ceebe88483b0436140048d39de83a84a06a8baa8136f4f/waitress-1.1.0.tar.gz"; - sha256 = "1a85gyji0kajc3p0s1pwwfm06w4wfxjkvvl4rnrz3h164kbd6g6k"; + url = "https://files.pythonhosted.org/packages/43/50/9890471320d5ad22761ae46661cf745f487b1c8c4ec49352b99e1078b970/waitress-1.3.0.tar.gz"; + sha256 = "09j5dzbbcxib7vdskhx39s1qsydlr4n2p2png71d7mjnr9pnwajf"; }; meta = { license = [ pkgs.lib.licenses.zpl21 ]; @@ -2218,18 +2223,18 @@ self: super: { }; }; "webob" = super.buildPythonPackage { - name = "webob-1.8.4"; + name = "webob-1.8.5"; doCheck = false; src = fetchurl { - url = "https://files.pythonhosted.org/packages/e4/6c/99e322c3d4cc11d9060a67a9bf2f7c9c581f40988c11fffe89bb8c36bc5e/WebOb-1.8.4.tar.gz"; - sha256 = "16cfg5y4n6sihz59vsmns2yqbfm0gfsn3l5xgz2g0pdhilaib0x4"; + url = "https://files.pythonhosted.org/packages/9d/1a/0c89c070ee2829c934cb6c7082287c822e28236a4fcf90063e6be7c35532/WebOb-1.8.5.tar.gz"; + sha256 = "11khpzaxc88q31v25ic330gsf56fwmbdc9b30br8mvp0fmwspah5"; }; meta = { license = [ pkgs.lib.licenses.mit ]; }; }; "webtest" = super.buildPythonPackage { - name = "webtest-2.0.32"; + name = "webtest-2.0.33"; doCheck = false; propagatedBuildInputs = [ self."six" @@ -2238,8 +2243,8 @@ self: super: { self."beautifulsoup4" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/27/9f/9e74449d272ffbef4fb3012e6dbc53c0b24822d545e7a33a342f80131e59/WebTest-2.0.32.tar.gz"; - sha256 = "0qp0nnbazzm4ibjiyqfcn6f230svk09i4g58zg2i9x1ga06h48a2"; + url = "https://files.pythonhosted.org/packages/a8/b0/ffc9413b637dbe26e291429bb0f6ed731e518d0cd03da28524a8fe2e8a8f/WebTest-2.0.33.tar.gz"; + sha256 = "1l3z0cwqslsf4rcrhi2gr8kdfh74wn2dw76376i4g9i38gz8wd21"; }; meta = { license = [ pkgs.lib.licenses.mit ]; @@ -2293,42 +2298,42 @@ self: super: { }; }; "zope.deprecation" = super.buildPythonPackage { - name = "zope.deprecation-4.3.0"; + name = "zope.deprecation-4.4.0"; doCheck = false; propagatedBuildInputs = [ self."setuptools" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/a1/18/2dc5e6bfe64fdc3b79411b67464c55bb0b43b127051a20f7f492ab767758/zope.deprecation-4.3.0.tar.gz"; - sha256 = "095jas41wbxgmw95kwdxqhbc3bgihw2hzj9b3qpdg85apcsf2lkx"; + url = "https://files.pythonhosted.org/packages/34/da/46e92d32d545dd067b9436279d84c339e8b16de2ca393d7b892bc1e1e9fd/zope.deprecation-4.4.0.tar.gz"; + sha256 = "1pz2cv7gv9y1r3m0bdv7ks1alagmrn5msm5spwdzkb2by0w36i8d"; }; meta = { license = [ pkgs.lib.licenses.zpl21 ]; }; }; "zope.event" = super.buildPythonPackage { - name = "zope.event-4.3.0"; + name = "zope.event-4.4"; doCheck = false; propagatedBuildInputs = [ self."setuptools" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/9e/d0/54ba59f19a0635f6591b74be259cf6fbf67e73f4edda27b5cd0cf4d26efa/zope.event-4.3.0.tar.gz"; - sha256 = "1rrkyx42bcq8dkpj23c2v99kczlrg8d39c06q5qpr0vs4hjfmv70"; + url = "https://files.pythonhosted.org/packages/4c/b2/51c0369adcf5be2334280eed230192ab3b03f81f8efda9ddea6f65cc7b32/zope.event-4.4.tar.gz"; + sha256 = "1ksbc726av9xacml6jhcfyn828hlhb9xlddpx6fcvnlvmpmpvhk9"; }; meta = { license = [ pkgs.lib.licenses.zpl21 ]; }; }; "zope.interface" = super.buildPythonPackage { - name = "zope.interface-4.5.0"; + name = "zope.interface-4.6.0"; doCheck = false; propagatedBuildInputs = [ self."setuptools" ]; src = fetchurl { - url = "https://files.pythonhosted.org/packages/ac/8a/657532df378c2cd2a1fe6b12be3b4097521570769d4852ec02c24bd3594e/zope.interface-4.5.0.tar.gz"; - sha256 = "0k67m60ij06wkg82n15qgyn96waf4pmrkhv0njpkfzpmv5q89hsp"; + url = "https://files.pythonhosted.org/packages/4e/d0/c9d16bd5b38de44a20c6dc5d5ed80a49626fafcb3db9f9efdc2a19026db6/zope.interface-4.6.0.tar.gz"; + sha256 = "1rgh2x3rcl9r0v0499kf78xy86rnmanajf4ywmqb943wpk50sg8v"; }; meta = { license = [ pkgs.lib.licenses.zpl21 ]; diff --git a/requirements.txt b/requirements.txt --- a/requirements.txt +++ b/requirements.txt @@ -1,37 +1,31 @@ ## dependencies -setuptools-scm==2.1.0 amqp==2.3.1 # not released authomatic that has updated some oauth providers -https://code.rhodecode.com/upstream/authomatic/archive/90a9ce60cc405ae8a2bf5c3713acd5d78579a04e.tar.gz?md5=3c68720a1322b25254009518d1ff6801#egg=authomatic==0.1.0.post1 -atomicwrites==1.2.1 -attrs==18.2.0 +https://code.rhodecode.com/upstream/authomatic/artifacts/download/0-4fe9c041-a567-4f84-be4c-7efa2a606d3c.tar.gz?md5=f6bdc3c769688212db68233e8d2b0383#egg=authomatic==0.1.0.post1 + babel==1.3 beaker==1.9.1 -bleach==3.0.2 +bleach==3.1.0 celery==4.1.1 -chameleon==2.24 channelstream==0.5.2 click==7.0 -colander==1.5.1 +colander==1.7.0 # our custom configobj -https://code.rhodecode.com/upstream/configobj/archive/a11ff0a0bd4fbda9e3a91267e720f88329efb4a6.tar.gz?md5=9916c524ea11a6c418217af6b28d4b3c#egg=configobj==5.0.6 +https://code.rhodecode.com/upstream/configobj/artifacts/download/0-012de99a-b1e1-4f64-a5c0-07a98a41b324.tar.gz?md5=6a513f51fe04b2c18cf84c1395a7c626#egg=configobj==5.0.6 cssselect==1.0.3 +cryptography==2.6.1 decorator==4.1.2 deform==2.0.7 docutils==0.14.0 dogpile.cache==0.7.1 dogpile.core==0.4.1 -ecdsa==0.13 formencode==1.2.4 future==0.14.3 futures==3.0.2 -gnureadline==6.3.8 infrae.cache==1.0.1 iso8601==0.1.12 itsdangerous==0.24 -jinja2==2.9.6 -billiard==3.5.0.3 kombu==4.2.1 lxml==4.2.5 mako==1.0.7 @@ -40,23 +34,20 @@ markupsafe==1.1.0 msgpack-python==0.5.6 pyotp==2.2.7 packaging==15.2 -paste==3.0.5 +pathlib2==2.3.4 +paste==3.0.8 pastedeploy==2.0.1 -pastescript==3.0.0 -pathlib2==2.3.3 +pastescript==3.1.0 peppercorn==0.6 -psutil==5.4.8 +psutil==5.5.1 py-bcrypt==0.4 -pycrypto==2.6.1 pycurl==7.43.0.2 -pyflakes==0.8.1 -pygments==2.3.1 +pycrypto==2.6.1 +pygments==2.4.2 pyparsing==2.3.0 -pyramid-beaker==0.8 pyramid-debugtoolbar==4.5.0 -pyramid-jinja2==2.7 pyramid-mako==1.0.2 -pyramid==1.10.1 +pyramid==1.10.4 pyramid_mailer==0.15.1 python-dateutil python-ldap==3.1.0 @@ -74,10 +65,9 @@ routes==2.4.1 simplejson==3.16.0 six==1.11.0 sqlalchemy==1.1.18 -sshpubkeys==2.2.0 -subprocess32==3.5.3 -supervisor==3.3.5 -tempita==0.5.2 +sshpubkeys==3.1.0 +subprocess32==3.5.4 +supervisor==4.0.3 translationstring==1.3 urllib3==1.24.1 urlobject==2.4.3 @@ -85,29 +75,29 @@ venusian==1.2.0 weberror==0.10.3 webhelpers2==2.0 webhelpers==1.3 -webob==1.8.4 +webob==1.8.5 whoosh==2.7.4 wsgiref==0.1.2 zope.cachedescriptors==4.3.1 -zope.deprecation==4.3.0 -zope.event==4.3.0 -zope.interface==4.5.0 +zope.deprecation==4.4.0 +zope.event==4.4.0 +zope.interface==4.6.0 # DB drivers mysql-python==1.2.5 pymysql==0.8.1 pysqlite==2.8.3 -psycopg2==2.7.5 +psycopg2==2.8.3 # IPYTHON RENDERING # entrypoints backport, pypi version doesn't support egg installs -https://code.rhodecode.com/upstream/entrypoints/archive/96e6d645684e1af3d7df5b5272f3fe85a546b233.tar.gz?md5=7db37771aea9ac9fefe093e5d6987313#egg=entrypoints==0.2.2.rhodecode-upstream1 +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 nbconvert==5.3.1 nbformat==4.4.0 jupyter_client==5.0.0 ## cli tools -alembic==1.0.5 +alembic==1.0.10 invoke==0.13.0 bumpversion==0.5.3 @@ -115,15 +105,14 @@ bumpversion==0.5.3 gevent==1.4.0 greenlet==0.4.15 gunicorn==19.9.0 -waitress==1.1.0 -setproctitle==1.1.10 +waitress==1.3.0 ## debug -ipdb==0.11.0 +ipdb==0.12.0 ipython==5.1.0 ## rhodecode-tools, special case -https://code.rhodecode.com/rhodecode-tools-ce/archive/v1.2.1.tar.gz?md5=25bc2f7de1da318e547236d3fb463d28#egg=rhodecode-tools==1.2.1 +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 ## appenlight appenlight-client==0.6.26 diff --git a/requirements_pinned.txt b/requirements_pinned.txt new file mode 100644 --- /dev/null +++ b/requirements_pinned.txt @@ -0,0 +1,19 @@ +# contains not directly required libraries we want to pin the version. + +atomicwrites==1.2.1 +attrs==18.2.0 +billiard==3.5.0.3 +chameleon==2.24 +cffi==1.12.2 +ecdsa==0.13.2 +hupper==1.6.1 +gnureadline==6.3.8 +jinja2==2.9.6 +jsonschema==2.6.0 +pyramid-jinja2==2.7 +pluggy==0.11.0 +setproctitle==1.1.10 +scandir==1.10.0 +tempita==0.5.2 +vine==1.3.0 +configparser==3.7.4 diff --git a/requirements_test.txt b/requirements_test.txt --- a/requirements_test.txt +++ b/requirements_test.txt @@ -10,7 +10,7 @@ gprof2dot==2017.9.19 mock==1.0.1 cov-core==1.15.0 -coverage==4.5.1 +coverage==4.5.3 -webtest==2.0.32 +webtest==2.0.33 beautifulsoup4==4.6.3 diff --git a/rhodecode/VERSION b/rhodecode/VERSION --- a/rhodecode/VERSION +++ b/rhodecode/VERSION @@ -1,1 +1,1 @@ -4.16.2 \ No newline at end of file +4.17.0 \ No newline at end of file diff --git a/rhodecode/__init__.py b/rhodecode/__init__.py --- a/rhodecode/__init__.py +++ b/rhodecode/__init__.py @@ -45,7 +45,7 @@ PYRAMID_SETTINGS = {} EXTENSIONS = {} __version__ = ('.'.join((str(each) for each in VERSION[:3]))) -__dbversion__ = 95 # defines current db version for migrations +__dbversion__ = 98 # defines current db version for migrations __platform__ = platform.system() __license__ = 'AGPLv3, and Commercial License' __author__ = 'RhodeCode GmbH' diff --git a/rhodecode/api/tests/test_comment_commit.py b/rhodecode/api/tests/test_comment_commit.py --- a/rhodecode/api/tests/test_comment_commit.py +++ b/rhodecode/api/tests/test_comment_commit.py @@ -37,11 +37,11 @@ class TestCommentCommit(object): assert_error(id_, expected, given=response.body) @pytest.mark.parametrize("commit_id, expected_err", [ - ('abcabca', {'hg': 'Commit {commit} does not exist for {repo}', - 'git': 'Commit {commit} does not exist for {repo}', + ('abcabca', {'hg': 'Commit {commit} does not exist for `{repo}`', + 'git': 'Commit {commit} does not exist for `{repo}`', 'svn': 'Commit id {commit} not understood.'}), - ('idontexist', {'hg': 'Commit {commit} does not exist for {repo}', - 'git': 'Commit {commit} does not exist for {repo}', + ('idontexist', {'hg': 'Commit {commit} does not exist for `{repo}`', + 'git': 'Commit {commit} does not exist for `{repo}`', 'svn': 'Commit id {commit} not understood.'}), ]) def test_api_comment_commit_wrong_hash(self, backend, commit_id, expected_err): @@ -53,7 +53,7 @@ class TestCommentCommit(object): expected_err = expected_err[backend.alias] expected_err = expected_err.format( - repo=backend.repo.scm_instance(), commit=commit_id) + repo=backend.repo.scm_instance().name, commit=commit_id) assert_error(id_, expected_err, given=response.body) @pytest.mark.parametrize("status_change, message, commit_id", [ diff --git a/rhodecode/api/tests/test_fts_search.py b/rhodecode/api/tests/test_fts_search.py new file mode 100644 --- /dev/null +++ b/rhodecode/api/tests/test_fts_search.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2010-2019 RhodeCode GmbH +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License, version 3 +# (only), as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# This program is dual-licensed. If you wish to learn more about the +# RhodeCode Enterprise Edition, including its added features, Support services, +# and proprietary license terms, please see https://rhodecode.com/licenses/ + +import pytest +from rhodecode.tests import HG_REPO +from rhodecode.api.tests.utils import ( + build_data, api_call, assert_error, assert_ok) + + +@pytest.mark.usefixtures("testuser_api", "app") +class TestApiSearch(object): + + @pytest.mark.parametrize("query, expected_hits, expected_paths", [ + ('todo', 23, [ + 'vcs/backends/hg/inmemory.py', + 'vcs/tests/test_git.py']), + ('extension:rst installation', 6, [ + 'docs/index.rst', + 'docs/installation.rst']), + ('def repo', 87, [ + 'vcs/tests/test_git.py', + 'vcs/tests/test_changesets.py']), + ('repository:%s def test' % HG_REPO, 18, [ + 'vcs/tests/test_git.py', + 'vcs/tests/test_changesets.py']), + ('"def main"', 9, [ + 'vcs/__init__.py', + 'vcs/tests/__init__.py', + 'vcs/utils/progressbar.py']), + ('owner:test_admin', 358, [ + 'vcs/tests/base.py', + 'MANIFEST.in', + 'vcs/utils/termcolors.py', + 'docs/theme/ADC/static/documentation.png']), + ('owner:test_admin def main', 72, [ + 'vcs/__init__.py', + 'vcs/tests/test_utils_filesize.py', + 'vcs/tests/test_cli.py']), + ('owner:michał test', 0, []), + ]) + def test_search_content_results(self, query, expected_hits, expected_paths): + id_, params = build_data( + self.apikey_regular, 'search', + search_query=query, + search_type='content') + + response = api_call(self.app, params) + json_response = response.json + + assert json_response['result']['item_count'] == expected_hits + paths = [x['f_path'] for x in json_response['result']['results']] + + for expected_path in expected_paths: + assert expected_path in paths + + @pytest.mark.parametrize("query, expected_hits, expected_paths", [ + ('readme.rst', 3, []), + ('test*', 75, []), + ('*model*', 1, []), + ('extension:rst', 48, []), + ('extension:rst api', 24, []), + ]) + def test_search_file_paths(self, query, expected_hits, expected_paths): + id_, params = build_data( + self.apikey_regular, 'search', + search_query=query, + search_type='path') + + response = api_call(self.app, params) + json_response = response.json + + assert json_response['result']['item_count'] == expected_hits + paths = [x['f_path'] for x in json_response['result']['results']] + + for expected_path in expected_paths: + assert expected_path in paths diff --git a/rhodecode/api/tests/test_get_repo.py b/rhodecode/api/tests/test_get_repo.py --- a/rhodecode/api/tests/test_get_repo.py +++ b/rhodecode/api/tests/test_get_repo.py @@ -44,6 +44,7 @@ class TestGetRepo(object): self, apikey_attr, expect_secrets, cache_param, backend, user_util): repo = backend.create_repo() + repo_id = repo.repo_id usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) group = user_util.create_user_group(members=[usr]) user_util.grant_user_group_permission_to_repo( @@ -64,6 +65,8 @@ class TestGetRepo(object): permissions = expected_permissions(repo) followers = [] + + repo = RepoModel().get(repo_id) for user in repo.followers: followers.append(user.user.get_api_data( include_secrets=expect_secrets)) @@ -84,6 +87,7 @@ class TestGetRepo(object): # TODO: Depending on which tests are running before this one, we # start with a different number of permissions in the database. repo = RepoModel().get_by_repo_name(backend.repo_name) + repo_id = repo.repo_id permission_count = len(repo.repo_to_perm) RepoModel().grant_user_permission(repo=backend.repo_name, @@ -102,6 +106,8 @@ class TestGetRepo(object): permissions = expected_permissions(repo) followers = [] + + repo = RepoModel().get(repo_id) for user in repo.followers: followers.append(user.user.get_api_data()) diff --git a/rhodecode/api/views/repo_api.py b/rhodecode/api/views/repo_api.py --- a/rhodecode/api/views/repo_api.py +++ b/rhodecode/api/views/repo_api.py @@ -444,7 +444,7 @@ def get_repo_nodes(request, apiuser, rep result: [ { "binary": false, - "content": "File line\nLine2\n", + "content": "File line", "extension": "md", "lines": 2, "md5": "059fa5d29b19c0657e384749480f6422", @@ -529,6 +529,7 @@ def get_repo_file(request, apiuser, repo :param cache: Use internal caches for fetching files. If disabled fetching files is slower but more memory efficient :type cache: Optional(bool) + Example output: .. code-block:: bash diff --git a/rhodecode/api/views/search_api.py b/rhodecode/api/views/search_api.py new file mode 100644 --- /dev/null +++ b/rhodecode/api/views/search_api.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2011-2019 RhodeCode GmbH +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License, version 3 +# (only), as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# This program is dual-licensed. If you wish to learn more about the +# RhodeCode Enterprise Edition, including its added features, Support services, +# and proprietary license terms, please see https://rhodecode.com/licenses/ + + +import logging + +from rhodecode.api import jsonrpc_method +from rhodecode.api.exc import JSONRPCValidationError +from rhodecode.api.utils import Optional +from rhodecode.lib.index import searcher_from_config +from rhodecode.model import validation_schema +from rhodecode.model.validation_schema.schemas import search_schema + +log = logging.getLogger(__name__) + + +@jsonrpc_method() +def search(request, 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)): + """ + Fetch Full Text Search results using API. + + :param apiuser: This is filled automatically from the |authtoken|. + :type apiuser: AuthUser + :param search_query: Search query. + :type search_query: str + :param search_type: Search type. The following are valid options: + * commit + * content + * path + :type search_type: str + :param page_limit: Page item limit, from 1 to 500. Default 10 items. + :type page_limit: Optional(int) + :param page: Page number. Default first page. + :type page: Optional(int) + :param search_sort: Search sort order. Default newfirst. The following are valid options: + * newfirst + * oldfirst + :type search_sort: Optional(str) + :param repo_name: Filter by one repo. Default is all. + :type repo_name: Optional(str) + :param repo_group_name: Filter by one repo group. Default is all. + :type repo_group_name: Optional(str) + """ + + data = {'execution_time': ''} + repo_name = Optional.extract(repo_name) + repo_group_name = Optional.extract(repo_group_name) + + schema = search_schema.SearchParamsSchema() + + try: + search_params = schema.deserialize( + dict(search_query=search_query, + search_type=search_type, + search_sort=Optional.extract(search_sort), + page_limit=Optional.extract(page_limit), + requested_page=Optional.extract(page)) + ) + except validation_schema.Invalid as err: + raise JSONRPCValidationError(colander_exc=err) + + search_query = search_params.get('search_query') + search_type = search_params.get('search_type') + search_sort = search_params.get('search_sort') + + if search_params.get('search_query'): + page_limit = search_params['page_limit'] + requested_page = search_params['requested_page'] + + searcher = searcher_from_config(request.registry.settings) + + try: + search_result = searcher.search( + search_query, search_type, apiuser, repo_name, repo_group_name, + requested_page=requested_page, page_limit=page_limit, sort=search_sort) + + data.update(dict( + results=list(search_result['results']), page=requested_page, + item_count=search_result['count'], + items_per_page=page_limit)) + finally: + searcher.cleanup() + + if not search_result['error']: + data['execution_time'] = '%s results (%.3f seconds)' % ( + search_result['count'], + search_result['runtime']) + else: + node = schema['search_query'] + raise JSONRPCValidationError( + colander_exc=validation_schema.Invalid(node, search_result['error'])) + + return data diff --git a/rhodecode/apps/_base/__init__.py b/rhodecode/apps/_base/__init__.py --- a/rhodecode/apps/_base/__init__.py +++ b/rhodecode/apps/_base/__init__.py @@ -168,6 +168,28 @@ class BaseAppView(object): from rhodecode.lib.base import attach_context_attributes attach_context_attributes(c, self.request, self.request.user.user_id) + c.is_super_admin = c.auth_user.is_admin + + c.can_create_repo = c.is_super_admin + c.can_create_repo_group = c.is_super_admin + c.can_create_user_group = c.is_super_admin + + c.is_delegated_admin = False + + if not c.auth_user.is_default and not c.is_super_admin: + c.can_create_repo = h.HasPermissionAny('hg.create.repository')( + user=self.request.user) + repositories = c.auth_user.repositories_admin or c.can_create_repo + + c.can_create_repo_group = h.HasPermissionAny('hg.repogroup.create.true')( + user=self.request.user) + repository_groups = c.auth_user.repository_groups_admin or c.can_create_repo_group + + c.can_create_user_group = h.HasPermissionAny('hg.usergroup.create.true')( + user=self.request.user) + user_groups = c.auth_user.user_groups_admin or c.can_create_user_group + # delegated admin can create, or manage some objects + c.is_delegated_admin = repositories or repository_groups or user_groups return c def _get_template_context(self, tmpl_args, **kwargs): @@ -215,12 +237,17 @@ class RepoAppView(BaseAppView): c.rhodecode_db_repo = self.db_repo c.repo_name = self.db_repo_name c.repository_pull_requests = self.db_repo_pull_requests + c.repository_is_user_following = ScmModel().is_following_repo( + self.db_repo_name, self._rhodecode_user.user_id) self.path_filter = PathFilter(None) c.repository_requirements_missing = {} try: self.rhodecode_vcs_repo = self.db_repo.scm_instance() - if self.rhodecode_vcs_repo: + # NOTE(marcink): + # comparison to None since if it's an object __bool__ is expensive to + # calculate + if self.rhodecode_vcs_repo is not None: path_perms = self.rhodecode_vcs_repo.get_path_permissions( c.auth_user.username) self.path_filter = PathFilter(path_perms) diff --git a/rhodecode/apps/_base/navigation.py b/rhodecode/apps/_base/navigation.py --- a/rhodecode/apps/_base/navigation.py +++ b/rhodecode/apps/_base/navigation.py @@ -85,8 +85,6 @@ class NavigationRegistry(object): 'admin_settings_hooks'), NavEntry('search', _('Full Text Search'), 'admin_settings_search'), - NavEntry('integrations', _('Integrations'), - 'global_integrations_home'), NavEntry('system', _('System Info'), 'admin_settings_system'), NavEntry('exceptions', _('Exceptions Tracker'), diff --git a/rhodecode/apps/admin/__init__.py b/rhodecode/apps/admin/__init__.py --- a/rhodecode/apps/admin/__init__.py +++ b/rhodecode/apps/admin/__init__.py @@ -424,6 +424,10 @@ def admin_routes(config): pattern='/repo_groups') config.add_route( + name='repo_groups_data', + pattern='/repo_groups_data') + + config.add_route( name='repo_group_new', pattern='/repo_group/new') diff --git a/rhodecode/apps/admin/tests/test_admin_main_views.py b/rhodecode/apps/admin/tests/test_admin_main_views.py --- a/rhodecode/apps/admin/tests/test_admin_main_views.py +++ b/rhodecode/apps/admin/tests/test_admin_main_views.py @@ -46,10 +46,10 @@ def route_path(name, params=None, **kwar class TestAdminMainView(TestController): - def test_redirect_admin_home(self): + def test_access_admin_home(self): self.log_user() - response = self.app.get(route_path('admin_home'), status=302) - assert response.location.endswith('/audit_logs') + response = self.app.get(route_path('admin_home'), status=200) + response.mustcontain("Administration area") def test_redirect_pull_request_view(self, view): self.log_user() diff --git a/rhodecode/apps/admin/tests/test_admin_repository_groups.py b/rhodecode/apps/admin/tests/test_admin_repository_groups.py --- a/rhodecode/apps/admin/tests/test_admin_repository_groups.py +++ b/rhodecode/apps/admin/tests/test_admin_repository_groups.py @@ -23,11 +23,11 @@ import pytest from rhodecode.apps._base import ADMIN_PREFIX from rhodecode.lib import helpers as h -from rhodecode.model.db import Repository, UserRepoToPerm, User +from rhodecode.model.db import Repository, UserRepoToPerm, User, RepoGroup from rhodecode.model.meta import Session from rhodecode.model.repo_group import RepoGroupModel from rhodecode.tests import ( - assert_session_flash, TEST_USER_REGULAR_LOGIN, TESTS_TMP_PATH, TestController) + assert_session_flash, TEST_USER_REGULAR_LOGIN, TESTS_TMP_PATH) from rhodecode.tests.fixture import Fixture fixture = Fixture() @@ -38,6 +38,7 @@ def route_path(name, params=None, **kwar base_url = { 'repo_groups': ADMIN_PREFIX + '/repo_groups', + 'repo_groups_data': ADMIN_PREFIX + '/repo_groups_data', 'repo_group_new': ADMIN_PREFIX + '/repo_group/new', 'repo_group_create': ADMIN_PREFIX + '/repo_group/create', @@ -59,13 +60,30 @@ def _get_permission_for_user(user, repo) @pytest.mark.usefixtures("app") class TestAdminRepositoryGroups(object): + def test_show_repo_groups(self, autologin_user): - response = self.app.get(route_path('repo_groups')) - response.mustcontain('data: []') + self.app.get(route_path('repo_groups')) + + def test_show_repo_groups_data(self, autologin_user, xhr_header): + response = self.app.get(route_path( + 'repo_groups_data'), extra_environ=xhr_header) + + all_repo_groups = RepoGroup.query().count() + assert response.json['recordsTotal'] == all_repo_groups - def test_show_repo_groups_after_creating_group(self, autologin_user): + def test_show_repo_groups_data_filtered(self, autologin_user, xhr_header): + response = self.app.get(route_path( + 'repo_groups_data', params={'search[value]': 'empty_search'}), + extra_environ=xhr_header) + + all_repo_groups = RepoGroup.query().count() + assert response.json['recordsTotal'] == all_repo_groups + assert response.json['recordsFiltered'] == 0 + + def test_show_repo_groups_after_creating_group(self, autologin_user, xhr_header): fixture.create_repo_group('test_repo_group') - response = self.app.get(route_path('repo_groups')) + response = self.app.get(route_path( + 'repo_groups_data'), extra_environ=xhr_header) response.mustcontain('"name_raw": "test_repo_group"') fixture.destroy_repo_group('test_repo_group') diff --git a/rhodecode/apps/admin/tests/test_admin_settings.py b/rhodecode/apps/admin/tests/test_admin_settings.py --- a/rhodecode/apps/admin/tests/test_admin_settings.py +++ b/rhodecode/apps/admin/tests/test_admin_settings.py @@ -214,8 +214,7 @@ class TestAdminSettingsGlobal(object): }) response = response.follow() - response.mustcontain( - """
- %s
""" % new_title) + response.mustcontain(new_title) def post_and_verify_settings(self, settings): old_title = 'RhodeCode' diff --git a/rhodecode/apps/admin/tests/test_admin_users_ssh_keys.py b/rhodecode/apps/admin/tests/test_admin_users_ssh_keys.py --- a/rhodecode/apps/admin/tests/test_admin_users_ssh_keys.py +++ b/rhodecode/apps/admin/tests/test_admin_users_ssh_keys.py @@ -173,4 +173,4 @@ class TestAdminUsersSshKeysView(TestCont response.mustcontain('Private key') response.mustcontain('Public key') - response.mustcontain('-----BEGIN RSA PRIVATE KEY-----') + response.mustcontain('-----BEGIN PRIVATE KEY-----') diff --git a/rhodecode/apps/admin/views/exception_tracker.py b/rhodecode/apps/admin/views/exception_tracker.py --- a/rhodecode/apps/admin/views/exception_tracker.py +++ b/rhodecode/apps/admin/views/exception_tracker.py @@ -50,7 +50,7 @@ class ExceptionsTrackerView(BaseAppView) count +=1 return count - def get_all_exceptions(self, read_metadata=False, limit=None): + def get_all_exceptions(self, read_metadata=False, limit=None, type_filter=None): exc_store_path = exc_tracking.get_exc_store() exception_list = [] @@ -59,7 +59,7 @@ class ExceptionsTrackerView(BaseAppView) return val.split('_')[-1] except Exception: return 0 - count = 0 + for fname in reversed(sorted(os.listdir(exc_store_path), key=key_sorter)): parts = fname.split('_', 2) @@ -83,13 +83,17 @@ class ExceptionsTrackerView(BaseAppView) except Exception: log.exception('Failed to read exc data from:{}'.format(full_path)) pass - # convert our timestamp to a date obj, for nicer representation exc['exc_utc_date'] = time_to_utcdatetime(exc['exc_timestamp']) - exception_list.append(exc) - count += 1 - if limit and count >= limit: + type_present = exc.get('exc_type') + if type_filter: + if type_present and type_present == type_filter: + exception_list.append(exc) + else: + exception_list.append(exc) + + if limit and len(exception_list) >= limit: break return exception_list @@ -103,8 +107,10 @@ class ExceptionsTrackerView(BaseAppView) c = self.load_default_context() c.active = 'exceptions_browse' c.limit = safe_int(self.request.GET.get('limit')) or 50 + c.type_filter = self.request.GET.get('type_filter') c.next_limit = c.limit + 50 - c.exception_list = self.get_all_exceptions(read_metadata=True, limit=c.limit) + c.exception_list = self.get_all_exceptions( + read_metadata=True, limit=c.limit, type_filter=c.type_filter) c.exception_list_count = self.count_all_exceptions() c.exception_store_dir = exc_tracking.get_exc_store() return self._get_template_context(c) @@ -132,12 +138,20 @@ class ExceptionsTrackerView(BaseAppView) def exception_delete_all(self): _ = self.request.translate c = self.load_default_context() + type_filter = self.request.POST.get('type_filter') c.active = 'exceptions' - all_exc = self.get_all_exceptions() - exc_count = len(all_exc) + all_exc = self.get_all_exceptions(read_metadata=bool(type_filter), type_filter=type_filter) + exc_count = 0 + for exc in all_exc: - exc_tracking.delete_exception(exc['exc_id'], prefix=None) + if type_filter: + if exc.get('exc_type') == type_filter: + exc_tracking.delete_exception(exc['exc_id'], prefix=None) + exc_count += 1 + else: + exc_tracking.delete_exception(exc['exc_id'], prefix=None) + exc_count += 1 h.flash(_('Removed {} Exceptions').format(exc_count), category='success') raise HTTPFound(h.route_path('admin_settings_exception_tracker')) diff --git a/rhodecode/apps/admin/views/main_views.py b/rhodecode/apps/admin/views/main_views.py --- a/rhodecode/apps/admin/views/main_views.py +++ b/rhodecode/apps/admin/views/main_views.py @@ -20,12 +20,12 @@ import logging -from pyramid.httpexceptions import HTTPFound +from pyramid.httpexceptions import HTTPFound, HTTPNotFound from pyramid.view import view_config from rhodecode.apps._base import BaseAppView from rhodecode.lib import helpers as h -from rhodecode.lib.auth import (LoginRequired, HasPermissionAllDecorator) +from rhodecode.lib.auth import (LoginRequired, NotAnonymous) from rhodecode.model.db import PullRequest @@ -33,14 +33,23 @@ log = logging.getLogger(__name__) class AdminMainView(BaseAppView): + def load_default_context(self): + c = self._get_local_tmpl_context() + return c @LoginRequired() - @HasPermissionAllDecorator('hg.admin') + @NotAnonymous() @view_config( - route_name='admin_home', request_method='GET') + route_name='admin_home', request_method='GET', + renderer='rhodecode:templates/admin/main.mako') def admin_main(self): - # redirect _admin to audit logs... - raise HTTPFound(h.route_path('admin_audit_logs')) + c = self.load_default_context() + c.active = 'admin' + + if not (c.is_super_admin or c.is_delegated_admin): + raise HTTPNotFound() + + return self._get_template_context(c) @LoginRequired() @view_config(route_name='pull_requests_global_0', request_method='GET') @@ -49,8 +58,7 @@ class AdminMainView(BaseAppView): def pull_requests(self): """ Global redirect for Pull Requests - - :param pull_request_id: id of pull requests in the system + pull_request_id: id of pull requests in the system """ pull_request = PullRequest.get_or_404( diff --git a/rhodecode/apps/admin/views/repo_groups.py b/rhodecode/apps/admin/views/repo_groups.py --- a/rhodecode/apps/admin/views/repo_groups.py +++ b/rhodecode/apps/admin/views/repo_groups.py @@ -17,7 +17,7 @@ # This program is dual-licensed. If you wish to learn more about the # RhodeCode Enterprise Edition, including its added features, Support services, # and proprietary license terms, please see https://rhodecode.com/licenses/ - +import datetime import logging import formencode import formencode.htmlfill @@ -30,16 +30,16 @@ from pyramid.response import Response from rhodecode import events from rhodecode.apps._base import BaseAppView, DataGridAppView -from rhodecode.lib.ext_json import json from rhodecode.lib.auth import ( LoginRequired, CSRFRequired, NotAnonymous, HasPermissionAny, HasRepoGroupPermissionAny) from rhodecode.lib import helpers as h, audit_logger -from rhodecode.lib.utils2 import safe_int, safe_unicode +from rhodecode.lib.utils2 import safe_int, safe_unicode, datetime_to_time from rhodecode.model.forms import RepoGroupForm from rhodecode.model.repo_group import RepoGroupModel from rhodecode.model.scm import RepoGroupList -from rhodecode.model.db import Session, RepoGroup +from rhodecode.model.db import ( + or_, count, func, in_filter_generator, Session, RepoGroup, User, Repository) log = logging.getLogger(__name__) @@ -88,22 +88,168 @@ class AdminRepoGroupsView(BaseAppView, D return False return False + # permission check in data loading of + # `repo_group_list_data` via RepoGroupList @LoginRequired() @NotAnonymous() - # perms check inside @view_config( route_name='repo_groups', request_method='GET', renderer='rhodecode:templates/admin/repo_groups/repo_groups.mako') def repo_group_list(self): c = self.load_default_context() + return self._get_template_context(c) - repo_group_list = RepoGroup.get_all_repo_groups() - repo_group_list_acl = RepoGroupList( - repo_group_list, perm_set=['group.admin']) - repo_group_data = RepoGroupModel().get_repo_groups_as_dict( - repo_group_list=repo_group_list_acl, admin=True) - c.data = json.dumps(repo_group_data) - return self._get_template_context(c) + # permission check inside + @LoginRequired() + @NotAnonymous() + @view_config( + route_name='repo_groups_data', request_method='GET', + renderer='json_ext', xhr=True) + def repo_group_list_data(self): + self.load_default_context() + column_map = { + 'name_raw': 'group_name_hash', + 'desc': 'group_description', + 'last_change_raw': 'updated_on', + 'top_level_repos': 'repos_total', + 'owner': 'user_username', + } + draw, start, limit = self._extract_chunk(self.request) + search_q, order_by, order_dir = self._extract_ordering( + self.request, column_map=column_map) + + _render = self.request.get_partial_renderer( + 'rhodecode:templates/data_table/_dt_elements.mako') + c = _render.get_call_context() + + def quick_menu(repo_group_name): + return _render('quick_repo_group_menu', repo_group_name) + + def repo_group_lnk(repo_group_name): + return _render('repo_group_name', repo_group_name) + + def last_change(last_change): + if isinstance(last_change, datetime.datetime) and not last_change.tzinfo: + delta = datetime.timedelta( + seconds=(datetime.datetime.now() - datetime.datetime.utcnow()).seconds) + last_change = last_change + delta + return _render("last_change", last_change) + + def desc(desc, personal): + return _render( + 'repo_group_desc', desc, personal, c.visual.stylify_metatags) + + def repo_group_actions(repo_group_id, repo_group_name, gr_count): + return _render( + 'repo_group_actions', repo_group_id, repo_group_name, gr_count) + + def user_profile(username): + return _render('user_profile', username) + + auth_repo_group_list = RepoGroupList( + RepoGroup.query().all(), perm_set=['group.admin']) + + allowed_ids = [-1] + for repo_group in auth_repo_group_list: + allowed_ids.append(repo_group.group_id) + + repo_groups_data_total_count = RepoGroup.query()\ + .filter(or_( + # generate multiple IN to fix limitation problems + *in_filter_generator(RepoGroup.group_id, allowed_ids) + )) \ + .count() + + repo_groups_data_total_inactive_count = RepoGroup.query()\ + .filter(RepoGroup.group_id.in_(allowed_ids))\ + .count() + + repo_count = count(Repository.repo_id) + base_q = Session.query( + RepoGroup.group_name, + RepoGroup.group_name_hash, + RepoGroup.group_description, + RepoGroup.group_id, + RepoGroup.personal, + RepoGroup.updated_on, + User, + repo_count.label('repos_count') + ) \ + .filter(or_( + # generate multiple IN to fix limitation problems + *in_filter_generator(RepoGroup.group_id, allowed_ids) + )) \ + .outerjoin(Repository) \ + .join(User, User.user_id == RepoGroup.user_id) \ + .group_by(RepoGroup, User) + + if search_q: + like_expression = u'%{}%'.format(safe_unicode(search_q)) + base_q = base_q.filter(or_( + RepoGroup.group_name.ilike(like_expression), + )) + + repo_groups_data_total_filtered_count = base_q.count() + # the inactive isn't really used, but we still make it same as other data grids + # which use inactive (users,user groups) + repo_groups_data_total_filtered_inactive_count = repo_groups_data_total_filtered_count + + sort_defined = False + if order_by == 'group_name': + sort_col = func.lower(RepoGroup.group_name) + sort_defined = True + elif order_by == 'repos_total': + sort_col = repo_count + sort_defined = True + elif order_by == 'user_username': + sort_col = User.username + else: + sort_col = getattr(RepoGroup, order_by, None) + + if sort_defined or sort_col: + if order_dir == 'asc': + sort_col = sort_col.asc() + else: + sort_col = sort_col.desc() + + base_q = base_q.order_by(sort_col) + base_q = base_q.offset(start).limit(limit) + + # authenticated access to user groups + auth_repo_group_list = base_q.all() + + repo_groups_data = [] + for repo_gr in auth_repo_group_list: + row = { + "menu": quick_menu(repo_gr.group_name), + "name": repo_group_lnk(repo_gr.group_name), + "name_raw": repo_gr.group_name, + "last_change": last_change(repo_gr.updated_on), + "last_change_raw": datetime_to_time(repo_gr.updated_on), + + "last_changeset": "", + "last_changeset_raw": "", + + "desc": desc(repo_gr.group_description, repo_gr.personal), + "owner": user_profile(repo_gr.User.username), + "top_level_repos": repo_gr.repos_count, + "action": repo_group_actions( + repo_gr.group_id, repo_gr.group_name, repo_gr.repos_count), + + } + + repo_groups_data.append(row) + + data = ({ + 'draw': draw, + 'data': repo_groups_data, + 'recordsTotal': repo_groups_data_total_count, + 'recordsTotalInactive': repo_groups_data_total_inactive_count, + 'recordsFiltered': repo_groups_data_total_filtered_count, + 'recordsFilteredInactive': repo_groups_data_total_filtered_inactive_count, + }) + + return data @LoginRequired() @NotAnonymous() diff --git a/rhodecode/apps/admin/views/user_groups.py b/rhodecode/apps/admin/views/user_groups.py --- a/rhodecode/apps/admin/views/user_groups.py +++ b/rhodecode/apps/admin/views/user_groups.py @@ -39,7 +39,7 @@ from rhodecode.model.forms import UserGr from rhodecode.model.permission import PermissionModel from rhodecode.model.scm import UserGroupList from rhodecode.model.db import ( - or_, count, User, UserGroup, UserGroupMember) + or_, count, User, UserGroup, UserGroupMember, in_filter_generator) from rhodecode.model.meta import Session from rhodecode.model.user_group import UserGroupModel from rhodecode.model.db import true @@ -107,11 +107,17 @@ class AdminUserGroupsView(BaseAppView, D allowed_ids.append(user_group.users_group_id) user_groups_data_total_count = UserGroup.query()\ - .filter(UserGroup.users_group_id.in_(allowed_ids))\ + .filter(or_( + # generate multiple IN to fix limitation problems + *in_filter_generator(UserGroup.users_group_id, allowed_ids) + ))\ .count() user_groups_data_total_inactive_count = UserGroup.query()\ - .filter(UserGroup.users_group_id.in_(allowed_ids))\ + .filter(or_( + # generate multiple IN to fix limitation problems + *in_filter_generator(UserGroup.users_group_id, allowed_ids) + ))\ .filter(UserGroup.users_group_active != true()).count() member_count = count(UserGroupMember.user_id) @@ -123,11 +129,14 @@ class AdminUserGroupsView(BaseAppView, D UserGroup.group_data, User, member_count.label('member_count') - ) \ - .filter(UserGroup.users_group_id.in_(allowed_ids)) \ - .outerjoin(UserGroupMember) \ - .join(User, User.user_id == UserGroup.user_id) \ - .group_by(UserGroup, User) + ) \ + .filter(or_( + # generate multiple IN to fix limitation problems + *in_filter_generator(UserGroup.users_group_id, allowed_ids) + )) \ + .outerjoin(UserGroupMember) \ + .join(User, User.user_id == UserGroup.user_id) \ + .group_by(UserGroup, User) base_q_inactive = base_q.filter(UserGroup.users_group_active != true()) @@ -141,14 +150,16 @@ class AdminUserGroupsView(BaseAppView, D user_groups_data_total_filtered_count = base_q.count() user_groups_data_total_filtered_inactive_count = base_q_inactive.count() + sort_defined = False if order_by == 'members_total': sort_col = member_count + sort_defined = True elif order_by == 'user_username': sort_col = User.username else: sort_col = getattr(UserGroup, order_by, None) - if isinstance(sort_col, count) or sort_col: + if sort_defined or sort_col: if order_dir == 'asc': sort_col = sort_col.asc() else: @@ -162,7 +173,7 @@ class AdminUserGroupsView(BaseAppView, D user_groups_data = [] for user_gr in auth_user_group_list: - user_groups_data.append({ + row = { "users_group_name": user_group_name(user_gr.users_group_name), "name_raw": h.escape(user_gr.users_group_name), "description": h.escape(user_gr.user_group_description), @@ -175,7 +186,8 @@ class AdminUserGroupsView(BaseAppView, D "owner": user_profile(user_gr.User.username), "action": user_group_actions( user_gr.users_group_id, user_gr.users_group_name) - }) + } + user_groups_data.append(row) data = ({ 'draw': draw, diff --git a/rhodecode/apps/admin/views/users.py b/rhodecode/apps/admin/views/users.py --- a/rhodecode/apps/admin/views/users.py +++ b/rhodecode/apps/admin/views/users.py @@ -682,8 +682,7 @@ class UsersView(UserAppView): if personal_repo_group: raise HTTPFound(h.route_path('user_edit_advanced', user_id=user_id)) - personal_repo_group_name = RepoGroupModel().get_personal_group_name( - c.user) + personal_repo_group_name = RepoGroupModel().get_personal_group_name(c.user) named_personal_group = RepoGroup.get_by_group_name( personal_repo_group_name) try: diff --git a/rhodecode/apps/file_store/local_store.py b/rhodecode/apps/file_store/local_store.py --- a/rhodecode/apps/file_store/local_store.py +++ b/rhodecode/apps/file_store/local_store.py @@ -38,19 +38,18 @@ class LocalFileStorage(object): """ Resolves a unique name and the correct path. If a filename for that path already exists then a numeric prefix with values > 0 will be - added, for example test.jpg -> test-1.jpg etc. initially file would have 0 prefix. + added, for example test.jpg -> 1-test.jpg etc. initially file would have 0 prefix. :param name: base name of file :param directory: absolute directory path """ - basename, ext = os.path.splitext(name) counter = 0 while True: - name = '%s-%d%s' % (basename, counter, ext) + name = '%d-%s' % (counter, name) # sub_store prefix to optimize disk usage, e.g some_path/ab/final_file - sub_store = cls._sub_store_from_filename(basename) + sub_store = cls._sub_store_from_filename(name) sub_store_path = os.path.join(directory, sub_store) if not os.path.exists(sub_store_path): os.makedirs(sub_store_path) @@ -209,3 +208,16 @@ class LocalFileStorage(object): filename = os.path.join(directory, filename) return filename, metadata + + def get_metadata(self, filename): + """ + Reads JSON stored metadata for a file + + :param filename: + :return: + """ + filename = self.store_path(filename) + filename_meta = filename + '.meta' + + with open(filename_meta, "rb") as source_meta: + return json.loads(source_meta.read()) diff --git a/rhodecode/apps/file_store/tests/test_upload_file.py b/rhodecode/apps/file_store/tests/test_upload_file.py --- a/rhodecode/apps/file_store/tests/test_upload_file.py +++ b/rhodecode/apps/file_store/tests/test_upload_file.py @@ -21,6 +21,7 @@ import os import pytest from rhodecode.lib.ext_json import json +from rhodecode.model.db import Session, FileStore from rhodecode.tests import TestController from rhodecode.apps.file_store import utils, config_keys @@ -46,9 +47,12 @@ class TestFileStoreViews(TestController) ('abcde-0.exe', "1234567", True), ('abcde-0.jpg', "xxxxx", False), ]) - def test_get_files_from_store(self, fid, content, exists, tmpdir): - self.log_user() + def test_get_files_from_store(self, fid, content, exists, tmpdir, user_util): + user = self.log_user() + user_id = user['user_id'] + repo_id = user_util.create_repo().repo_id store_path = self.app._pyramid_settings[config_keys.store_path] + store_uid = fid if exists: status = 200 @@ -58,17 +62,28 @@ class TestFileStoreViews(TestController) f.write(content) with open(filesystem_file, 'rb') as f: - fid, metadata = store.save_file(f, fid, extra_metadata={'filename': fid}) + store_uid, metadata = store.save_file(f, fid, extra_metadata={'filename': fid}) + + entry = FileStore.create( + file_uid=store_uid, filename=metadata["filename"], + file_hash=metadata["sha256"], file_size=metadata["size"], + file_display_name='file_display_name', + file_description='repo artifact `{}`'.format(metadata["filename"]), + check_acl=True, user_id=user_id, + scope_repo_id=repo_id + ) + Session().add(entry) + Session().commit() else: status = 404 - response = self.app.get(route_path('download_file', fid=fid), status=status) + response = self.app.get(route_path('download_file', fid=store_uid), status=status) if exists: assert response.text == content - file_store_path = os.path.dirname(store.resolve_name(fid, store_path)[1]) - metadata_file = os.path.join(file_store_path, fid + '.meta') + file_store_path = os.path.dirname(store.resolve_name(store_uid, store_path)[1]) + metadata_file = os.path.join(file_store_path, store_uid + '.meta') assert os.path.exists(metadata_file) with open(metadata_file, 'rb') as f: json_data = json.loads(f.read()) diff --git a/rhodecode/apps/file_store/utils.py b/rhodecode/apps/file_store/utils.py --- a/rhodecode/apps/file_store/utils.py +++ b/rhodecode/apps/file_store/utils.py @@ -19,9 +19,10 @@ # and proprietary license terms, please see https://rhodecode.com/licenses/ -import os import uuid +import pathlib2 + def get_file_storage(settings): from rhodecode.apps.file_store.local_store import LocalFileStorage @@ -30,6 +31,11 @@ def get_file_storage(settings): return LocalFileStorage(base_path=store_path) +def splitext(filename): + ext = ''.join(pathlib2.Path(filename).suffixes) + return filename, ext + + def uid_filename(filename, randomized=True): """ Generates a randomized or stable (uuid) filename, @@ -38,7 +44,8 @@ def uid_filename(filename, randomized=Tr :param filename: the original filename :param randomized: define if filename should be stable (sha1 based) or randomized """ - _, ext = os.path.splitext(filename) + + _, ext = splitext(filename) if randomized: uid = uuid.uuid4() else: diff --git a/rhodecode/apps/file_store/views.py b/rhodecode/apps/file_store/views.py --- a/rhodecode/apps/file_store/views.py +++ b/rhodecode/apps/file_store/views.py @@ -30,7 +30,7 @@ from rhodecode.apps.file_store.exception from rhodecode.lib import helpers as h from rhodecode.lib import audit_logger -from rhodecode.lib.auth import (CSRFRequired, NotAnonymous) +from rhodecode.lib.auth import (CSRFRequired, NotAnonymous, HasRepoPermissionAny, HasRepoGroupPermissionAny) from rhodecode.model.db import Session, FileStore log = logging.getLogger(__name__) @@ -68,7 +68,7 @@ class FileStoreView(BaseAppView): 'user_id': self._rhodecode_user.user_id, 'ip': self._rhodecode_user.ip_addr}} try: - store_fid, metadata = self.storage.save_file( + store_uid, metadata = self.storage.save_file( file_obj.file, filename, extra_metadata=metadata) except FileNotAllowedException: return {'store_fid': None, @@ -82,7 +82,7 @@ class FileStoreView(BaseAppView): try: entry = FileStore.create( - file_uid=store_fid, filename=metadata["filename"], + file_uid=store_uid, filename=metadata["filename"], file_hash=metadata["sha256"], file_size=metadata["size"], file_description='upload attachment', check_acl=False, user_id=self._rhodecode_user.user_id @@ -96,8 +96,8 @@ class FileStoreView(BaseAppView): 'access_path': None, 'error': 'File {} failed to store in DB.'.format(filename)} - return {'store_fid': store_fid, - 'access_path': h.route_path('download_file', fid=store_fid)} + return {'store_fid': store_uid, + 'access_path': h.route_path('download_file', fid=store_uid)} @view_config(route_name='download_file') def download_file(self): @@ -109,6 +109,35 @@ class FileStoreView(BaseAppView): log.debug('File with FID:%s not found in the store', file_uid) raise HTTPNotFound() + db_obj = FileStore().query().filter(FileStore.file_uid == file_uid).scalar() + if not db_obj: + raise HTTPNotFound() + + # private upload for user + if db_obj.check_acl and db_obj.scope_user_id: + user = db_obj.user + if self._rhodecode_db_user.user_id != user.user_id: + log.warning('Access to file store object forbidden') + raise HTTPNotFound() + + # scoped to repository permissions + if db_obj.check_acl and db_obj.scope_repo_id: + repo = db_obj.repo + perm_set = ['repository.read', 'repository.write', 'repository.admin'] + has_perm = HasRepoPermissionAny(*perm_set)(repo.repo_name, 'FileStore check') + if not has_perm: + log.warning('Access to file store object forbidden') + raise HTTPNotFound() + + # scoped to repository group permissions + if db_obj.check_acl and db_obj.scope_repo_group_id: + repo_group = db_obj.repo_group + perm_set = ['group.read', 'group.write', 'group.admin'] + has_perm = HasRepoGroupPermissionAny(*perm_set)(repo_group.group_name, 'FileStore check') + if not has_perm: + log.warning('Access to file store object forbidden') + raise HTTPNotFound() + FileStore.bump_access_counter(file_uid) file_path = self.storage.store_path(file_uid) diff --git a/rhodecode/apps/gist/views.py b/rhodecode/apps/gist/views.py --- a/rhodecode/apps/gist/views.py +++ b/rhodecode/apps/gist/views.py @@ -25,7 +25,7 @@ import formencode import formencode.htmlfill import peppercorn -from pyramid.httpexceptions import HTTPNotFound, HTTPFound +from pyramid.httpexceptions import HTTPNotFound, HTTPFound, HTTPBadRequest from pyramid.view import view_config from pyramid.renderers import render from pyramid.response import Response @@ -67,7 +67,6 @@ class GistView(BaseAppView): (Gist.ACL_LEVEL_PUBLIC, _("Can be accessed by anonymous users")) ] - return c @LoginRequired() @@ -296,6 +295,8 @@ class GistView(BaseAppView): response = Response(content) response.content_type = 'text/plain' return response + elif return_format: + raise HTTPBadRequest() return self._get_template_context(c) diff --git a/rhodecode/apps/home/__init__.py b/rhodecode/apps/home/__init__.py --- a/rhodecode/apps/home/__init__.py +++ b/rhodecode/apps/home/__init__.py @@ -68,6 +68,10 @@ def includeme(config): pattern='/_markup_preview') config.add_route( + name='file_preview', + pattern='/_file_preview') + + config.add_route( name='store_user_session_value', pattern='/_store_session_attr') diff --git a/rhodecode/apps/home/views.py b/rhodecode/apps/home/views.py --- a/rhodecode/apps/home/views.py +++ b/rhodecode/apps/home/views.py @@ -27,13 +27,14 @@ from pyramid.view import view_config from rhodecode.apps._base import BaseAppView from rhodecode.lib import helpers as h from rhodecode.lib.auth import ( - LoginRequired, NotAnonymous, HasRepoGroupPermissionAnyDecorator, - CSRFRequired) + LoginRequired, NotAnonymous, HasRepoGroupPermissionAnyDecorator, CSRFRequired) +from rhodecode.lib.codeblocks import filenode_as_lines_tokens from rhodecode.lib.index import searcher_from_config from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int from rhodecode.lib.ext_json import json +from rhodecode.lib.vcs.nodes import FileNode from rhodecode.model.db import ( - func, true, or_, in_filter_generator, Repository, RepoGroup, User, UserGroup) + func, true, or_, case, in_filter_generator, Repository, RepoGroup, User, UserGroup) from rhodecode.model.repo import RepoModel from rhodecode.model.repo_group import RepoGroupModel from rhodecode.model.scm import RepoGroupList, RepoList @@ -105,21 +106,27 @@ class HomeView(BaseAppView): return {'suggestions': _user_groups} - def _get_repo_list(self, name_contains=None, repo_type=None, limit=20): + def _get_repo_list(self, name_contains=None, repo_type=None, repo_group_name='', limit=20): org_query = name_contains allowed_ids = self._rhodecode_user.repo_acl_ids( ['repository.read', 'repository.write', 'repository.admin'], cache=False, name_filter=name_contains) or [-1] query = Repository.query()\ - .order_by(func.length(Repository.repo_name))\ - .order_by(Repository.repo_name)\ .filter(Repository.archived.isnot(true()))\ .filter(or_( # generate multiple IN to fix limitation problems *in_filter_generator(Repository.repo_id, allowed_ids) )) + query = query.order_by(case( + [ + (Repository.repo_name.startswith(repo_group_name), repo_group_name+'/'), + ], + )) + query = query.order_by(func.length(Repository.repo_name)) + query = query.order_by(Repository.repo_name) + if repo_type: query = query.filter(Repository.repo_type == repo_type) @@ -145,20 +152,26 @@ class HomeView(BaseAppView): } for obj in acl_iter] - def _get_repo_group_list(self, name_contains=None, limit=20): + def _get_repo_group_list(self, name_contains=None, repo_group_name='', limit=20): org_query = name_contains allowed_ids = self._rhodecode_user.repo_group_acl_ids( ['group.read', 'group.write', 'group.admin'], cache=False, name_filter=name_contains) or [-1] query = RepoGroup.query()\ - .order_by(func.length(RepoGroup.group_name))\ - .order_by(RepoGroup.group_name) \ .filter(or_( # generate multiple IN to fix limitation problems *in_filter_generator(RepoGroup.group_id, allowed_ids) )) + query = query.order_by(case( + [ + (RepoGroup.group_name.startswith(repo_group_name), repo_group_name+'/'), + ], + )) + query = query.order_by(func.length(RepoGroup.group_name)) + query = query.order_by(RepoGroup.group_name) + if name_contains: ilike_expression = u'%{}%'.format(safe_unicode(name_contains)) query = query.filter( @@ -183,11 +196,17 @@ class HomeView(BaseAppView): def _get_user_list(self, name_contains=None, limit=20): org_query = name_contains if not name_contains: - return [] + return [], False - name_contains = re.compile('(?:user:)(.+)').findall(name_contains) + # TODO(marcink): should all logged in users be allowed to search others? + allowed_user_search = self._rhodecode_user.username != User.DEFAULT_USER + if not allowed_user_search: + return [], False + + name_contains = re.compile('(?:user:[ ]?)(.+)').findall(name_contains) if len(name_contains) != 1: - return [] + return [], False + name_contains = name_contains[0] query = User.query()\ @@ -207,22 +226,28 @@ class HomeView(BaseAppView): { 'id': obj.user_id, 'value': org_query, - 'value_display': obj.username, + 'value_display': 'user: `{}`'.format(obj.username), 'type': 'user', 'icon_link': h.gravatar_url(obj.email, 30), 'url': h.route_path( 'user_profile', username=obj.username) } - for obj in acl_iter] + for obj in acl_iter], True def _get_user_groups_list(self, name_contains=None, limit=20): org_query = name_contains if not name_contains: - return [] + return [], False - name_contains = re.compile('(?:user_group:)(.+)').findall(name_contains) + # TODO(marcink): should all logged in users be allowed to search others? + allowed_user_search = self._rhodecode_user.username != User.DEFAULT_USER + if not allowed_user_search: + return [], False + + name_contains = re.compile('(?:user_group:[ ]?)(.+)').findall(name_contains) if len(name_contains) != 1: - return [] + return [], False + name_contains = name_contains[0] query = UserGroup.query()\ @@ -241,27 +266,34 @@ class HomeView(BaseAppView): { 'id': obj.users_group_id, 'value': org_query, - 'value_display': obj.users_group_name, + 'value_display': 'user_group: `{}`'.format(obj.users_group_name), 'type': 'user_group', 'url': h.route_path( 'user_group_profile', user_group_name=obj.users_group_name) } - for obj in acl_iter] + for obj in acl_iter], True - def _get_hash_commit_list(self, auth_user, searcher, query): + def _get_hash_commit_list(self, auth_user, searcher, query, repo=None, repo_group=None): + repo_name = repo_group_name = None + if repo: + repo_name = repo.repo_name + if repo_group: + repo_group_name = repo_group.group_name + org_query = query if not query or len(query) < 3 or not searcher: - return [] + return [], False - commit_hashes = re.compile('(?:commit:)([0-9a-f]{2,40})').findall(query) + commit_hashes = re.compile('(?:commit:[ ]?)([0-9a-f]{2,40})').findall(query) if len(commit_hashes) != 1: - return [] + return [], False + commit_hash = commit_hashes[0] result = searcher.search( 'commit_id:{}*'.format(commit_hash), 'commit', auth_user, - raise_on_exc=False) + repo_name, repo_group_name, raise_on_exc=False) commits = [] for entry in result['results']: @@ -286,7 +318,55 @@ class HomeView(BaseAppView): } commits.append(commit_entry) - return commits + return commits, True + + def _get_path_list(self, auth_user, searcher, query, repo=None, repo_group=None): + repo_name = repo_group_name = None + if repo: + repo_name = repo.repo_name + if repo_group: + repo_group_name = repo_group.group_name + + org_query = query + if not query or len(query) < 3 or not searcher: + return [], False + + paths_re = re.compile('(?:file:[ ]?)(.+)').findall(query) + if len(paths_re) != 1: + return [], False + + file_path = paths_re[0] + + search_path = searcher.escape_specials(file_path) + result = searcher.search( + 'file.raw:*{}*'.format(search_path), 'path', auth_user, + repo_name, repo_group_name, raise_on_exc=False) + + files = [] + for entry in result['results']: + repo_data = { + 'repository_id': entry.get('repository_id'), + 'repository_type': entry.get('repo_type'), + 'repository_name': entry.get('repository'), + } + + file_entry = { + 'id': entry['commit_id'], + 'value': org_query, + 'value_display': '`{}` file: {}'.format( + entry['repository'], entry['file']), + 'type': 'file', + 'repo': entry['repository'], + 'repo_data': repo_data, + + 'url': h.route_path( + 'repo_files', + repo_name=entry['repository'], commit_id=entry['commit_id'], + f_path=entry['file']) + } + + files.append(file_entry) + return files, True @LoginRequired() @view_config( @@ -363,36 +443,42 @@ class HomeView(BaseAppView): def query_modifier(): qry = query return {'q': qry, 'type': 'content'} - label = u'File search for `{}` in this repository.'.format(query) - queries.append( - { - 'id': -10, - 'value': query, - 'value_display': label, - 'type': 'search', - 'url': h.route_path('search_repo', - repo_name=repo_name, - _query=query_modifier()) + + label = u'File search for `{}`'.format(h.escape(query)) + file_qry = { + 'id': -10, + 'value': query, + 'value_display': label, + 'type': 'search', + 'subtype': 'repo', + 'url': h.route_path('search_repo', + repo_name=repo_name, + _query=query_modifier()) } - ) # commits def query_modifier(): qry = query return {'q': qry, 'type': 'commit'} - label = u'Commit search for `{}` in this repository.'.format(query) - queries.append( - { - 'id': -20, - 'value': query, - 'value_display': label, - 'type': 'search', - 'url': h.route_path('search_repo', - repo_name=repo_name, - _query=query_modifier()) + label = u'Commit search for `{}`'.format(h.escape(query)) + commit_qry = { + 'id': -20, + 'value': query, + 'value_display': label, + 'type': 'search', + 'subtype': 'repo', + 'url': h.route_path('search_repo', + repo_name=repo_name, + _query=query_modifier()) } - ) + + if repo_context in ['commit', 'commits']: + queries.extend([commit_qry, file_qry]) + elif repo_context in ['files', 'summary']: + queries.extend([file_qry, commit_qry]) + else: + queries.extend([commit_qry, file_qry]) elif is_es_6 and repo_group_name: # files @@ -400,37 +486,43 @@ class HomeView(BaseAppView): qry = query return {'q': qry, 'type': 'content'} - label = u'File search for `{}` in this repository group'.format(query) - queries.append( - { - 'id': -30, - 'value': query, - 'value_display': label, - 'type': 'search', - 'url': h.route_path('search_repo_group', - repo_group_name=repo_group_name, - _query=query_modifier()) + label = u'File search for `{}`'.format(query) + file_qry = { + 'id': -30, + 'value': query, + 'value_display': label, + 'type': 'search', + 'subtype': 'repo_group', + 'url': h.route_path('search_repo_group', + repo_group_name=repo_group_name, + _query=query_modifier()) } - ) # commits def query_modifier(): qry = query return {'q': qry, 'type': 'commit'} - label = u'Commit search for `{}` in this repository group'.format(query) - queries.append( - { - 'id': -40, - 'value': query, - 'value_display': label, - 'type': 'search', - 'url': h.route_path('search_repo_group', - repo_group_name=repo_group_name, - _query=query_modifier()) + label = u'Commit search for `{}`'.format(query) + commit_qry = { + 'id': -40, + 'value': query, + 'value_display': label, + 'type': 'search', + 'subtype': 'repo_group', + 'url': h.route_path('search_repo_group', + repo_group_name=repo_group_name, + _query=query_modifier()) } - ) + if repo_context in ['commit', 'commits']: + queries.extend([commit_qry, file_qry]) + elif repo_context in ['files', 'summary']: + queries.extend([file_qry, commit_qry]) + else: + queries.extend([commit_qry, file_qry]) + + # Global, not scoped if not queries: queries.append( { @@ -438,6 +530,7 @@ class HomeView(BaseAppView): 'value': query, 'value_display': u'File search for: `{}`'.format(query), 'type': 'search', + 'subtype': 'global', 'url': h.route_path('search', _query={'q': query, 'type': 'content'}) }) @@ -447,6 +540,7 @@ class HomeView(BaseAppView): 'value': query, 'value_display': u'Commit search for: `{}`'.format(query), 'type': 'search', + 'subtype': 'global', 'url': h.route_path('search', _query={'q': query, 'type': 'commit'}) }) @@ -469,54 +563,107 @@ class HomeView(BaseAppView): if not query: return {'suggestions': res} + def no_match(name): + return { + 'id': -1, + 'value': "", + 'value_display': name, + 'type': 'text', + 'url': "" + } searcher = searcher_from_config(self.request.registry.settings) - for _q in self._get_default_search_queries(self.request.GET, searcher, query): - res.append(_q) + has_specialized_search = False + # set repo context + repo = None + repo_id = safe_int(self.request.GET.get('search_context[repo_id]')) + if repo_id: + repo = Repository.get(repo_id) + + # set group context + repo_group = None repo_group_id = safe_int(self.request.GET.get('search_context[repo_group_id]')) if repo_group_id: repo_group = RepoGroup.get(repo_group_id) - composed_hint = '{}/{}'.format(repo_group.group_name, query) - show_hint = not query.startswith(repo_group.group_name) - if repo_group and show_hint: - hint = u'Repository search inside: `{}`'.format(composed_hint) - res.append({ - 'id': -1, - 'value': composed_hint, - 'value_display': hint, - 'type': 'hint', - 'url': "" - }) + prefix_match = False + + # user: type search + if not prefix_match: + users, prefix_match = self._get_user_list(query) + if users: + has_specialized_search = True + for serialized_user in users: + res.append(serialized_user) + elif prefix_match: + has_specialized_search = True + res.append(no_match('No matching users found')) - repo_groups = self._get_repo_group_list(query) - for serialized_repo_group in repo_groups: - res.append(serialized_repo_group) + # user_group: type search + if not prefix_match: + user_groups, prefix_match = self._get_user_groups_list(query) + if user_groups: + has_specialized_search = True + for serialized_user_group in user_groups: + res.append(serialized_user_group) + elif prefix_match: + has_specialized_search = True + res.append(no_match('No matching user groups found')) - repos = self._get_repo_list(query) - for serialized_repo in repos: - res.append(serialized_repo) + # FTS commit: type search + if not prefix_match: + commits, prefix_match = self._get_hash_commit_list( + c.auth_user, searcher, query, repo, repo_group) + if commits: + has_specialized_search = True + unique_repos = collections.OrderedDict() + for commit in commits: + repo_name = commit['repo'] + unique_repos.setdefault(repo_name, []).append(commit) - # TODO(marcink): should all logged in users be allowed to search others? - allowed_user_search = self._rhodecode_user.username != User.DEFAULT_USER - if allowed_user_search: - users = self._get_user_list(query) - for serialized_user in users: - res.append(serialized_user) + for _repo, commits in unique_repos.items(): + for commit in commits: + res.append(commit) + elif prefix_match: + has_specialized_search = True + res.append(no_match('No matching commits found')) - user_groups = self._get_user_groups_list(query) - for serialized_user_group in user_groups: - res.append(serialized_user_group) + # FTS file: type search + if not prefix_match: + paths, prefix_match = self._get_path_list( + c.auth_user, searcher, query, repo, repo_group) + if paths: + has_specialized_search = True + unique_repos = collections.OrderedDict() + for path in paths: + repo_name = path['repo'] + unique_repos.setdefault(repo_name, []).append(path) - commits = self._get_hash_commit_list(c.auth_user, searcher, query) - if commits: - unique_repos = collections.OrderedDict() - for commit in commits: - repo_name = commit['repo'] - unique_repos.setdefault(repo_name, []).append(commit) + for repo, paths in unique_repos.items(): + for path in paths: + res.append(path) + elif prefix_match: + has_specialized_search = True + res.append(no_match('No matching files found')) + + # main suggestions + if not has_specialized_search: + repo_group_name = '' + if repo_group: + repo_group_name = repo_group.group_name - for repo, commits in unique_repos.items(): - for commit in commits: - res.append(commit) + for _q in self._get_default_search_queries(self.request.GET, searcher, query): + res.append(_q) + + repo_groups = self._get_repo_group_list(query, repo_group_name=repo_group_name) + for serialized_repo_group in repo_groups: + res.append(serialized_repo_group) + + repos = self._get_repo_list(query, repo_group_name=repo_group_name) + for serialized_repo in repos: + res.append(serialized_repo) + + if not repos and not repo_groups: + res.append(no_match('No matches found')) return {'suggestions': res} @@ -564,8 +711,11 @@ class HomeView(BaseAppView): def repo_group_main_page(self): c = self.load_default_context() c.repo_group = self.request.db_repo_group - repo_data, repo_group_data = self._get_groups_and_repos( - c.repo_group.group_id) + repo_data, repo_group_data = self._get_groups_and_repos(c.repo_group.group_id) + + # update every 5 min + if self.request.db_repo_group.last_commit_cache_update_diff > 60 * 5: + self.request.db_repo_group.update_commit_cache() # json used to render the grids c.repos_data = json.dumps(repo_data) @@ -594,6 +744,34 @@ class HomeView(BaseAppView): @LoginRequired() @CSRFRequired() @view_config( + route_name='file_preview', request_method='POST', + renderer='string', xhr=True) + def file_preview(self): + # Technically a CSRF token is not needed as no state changes with this + # call. However, as this is a POST is better to have it, so automated + # tools don't flag it as potential CSRF. + # Post is required because the payload could be bigger than the maximum + # allowed by GET. + + text = self.request.POST.get('text') + file_path = self.request.POST.get('file_path') + + renderer = h.renderer_from_filename(file_path) + + if renderer: + return h.render(text, renderer=renderer, mentions=True) + else: + self.load_default_context() + _render = self.request.get_partial_renderer( + 'rhodecode:templates/files/file_content.mako') + + lines = filenode_as_lines_tokens(FileNode(file_path, text)) + + return _render('render_lines', lines) + + @LoginRequired() + @CSRFRequired() + @view_config( route_name='store_user_session_value', request_method='POST', renderer='string', xhr=True) def store_user_session_attr(self): @@ -604,4 +782,4 @@ class HomeView(BaseAppView): if existing_value != val: self.request.session[key] = val - return 'stored:{}'.format(key) + return 'stored:{}:{}'.format(key, val) diff --git a/rhodecode/apps/journal/views.py b/rhodecode/apps/journal/views.py --- a/rhodecode/apps/journal/views.py +++ b/rhodecode/apps/journal/views.py @@ -31,12 +31,12 @@ from pyramid.renderers import render from rhodecode.apps._base import BaseAppView from rhodecode.model.db import ( - or_, joinedload, UserLog, UserFollowing, User, UserApiKeys) + or_, joinedload, Repository, UserLog, UserFollowing, User, UserApiKeys) from rhodecode.model.meta import Session import rhodecode.lib.helpers as h from rhodecode.lib.helpers import Page from rhodecode.lib.user_log_filter import user_log_filter -from rhodecode.lib.auth import LoginRequired, NotAnonymous, CSRFRequired +from rhodecode.lib.auth import LoginRequired, NotAnonymous, CSRFRequired, HasRepoPermissionAny from rhodecode.lib.utils2 import safe_int, AttributeDict, md5_safe from rhodecode.model.scm import ScmModel @@ -153,7 +153,7 @@ class JournalView(BaseAppView): desc = action_extra() _url = h.route_url('home') if entry.repository is not None: - _url = h.route_url('repo_changelog', + _url = h.route_url('repo_commits', repo_name=entry.repository.repo_name) feed.add_item( @@ -199,7 +199,7 @@ class JournalView(BaseAppView): desc = action_extra() _url = h.route_url('home') if entry.repository is not None: - _url = h.route_url('repo_changelog', + _url = h.route_url('repo_commits', repo_name=entry.repository.repo_name) feed.add_item( @@ -297,18 +297,19 @@ class JournalView(BaseAppView): user_id = self.request.POST.get('follows_user_id') if user_id: try: - ScmModel().toggle_following_user( - user_id, self._rhodecode_user.user_id) + ScmModel().toggle_following_user(user_id, self._rhodecode_user.user_id) Session().commit() return 'ok' except Exception: raise HTTPBadRequest() repo_id = self.request.POST.get('follows_repo_id') - if repo_id: + repo = Repository.get_or_404(repo_id) + perm_set = ['repository.read', 'repository.write', 'repository.admin'] + has_perm = HasRepoPermissionAny(*perm_set)(repo.repo_name, 'RepoWatch check') + if repo and has_perm: try: - ScmModel().toggle_following_repo( - repo_id, self._rhodecode_user.user_id) + ScmModel().toggle_following_repo(repo_id, self._rhodecode_user.user_id) Session().commit() return 'ok' except Exception: diff --git a/rhodecode/apps/my_account/tests/test_my_account_ssh_keys.py b/rhodecode/apps/my_account/tests/test_my_account_ssh_keys.py --- a/rhodecode/apps/my_account/tests/test_my_account_ssh_keys.py +++ b/rhodecode/apps/my_account/tests/test_my_account_ssh_keys.py @@ -160,4 +160,4 @@ class TestMyAccountSshKeysView(TestContr response.mustcontain('Private key') response.mustcontain('Public key') - response.mustcontain('-----BEGIN RSA PRIVATE KEY-----') + response.mustcontain('-----BEGIN PRIVATE KEY-----') diff --git a/rhodecode/apps/my_account/views/my_account.py b/rhodecode/apps/my_account/views/my_account.py --- a/rhodecode/apps/my_account/views/my_account.py +++ b/rhodecode/apps/my_account/views/my_account.py @@ -360,7 +360,7 @@ class MyAccountView(BaseAppView, DataGri 'repository.read', 'repository.write', 'repository.admin']) repos_data = RepoModel().get_repos_as_dict( - repo_list=repo_list, admin=admin) + repo_list=repo_list, admin=admin, short_name=False) # json used to render the grid return json.dumps(repos_data) @@ -423,7 +423,7 @@ class MyAccountView(BaseAppView, DataGri default_redirect_url = '' # save repo - if entry.get('bookmark_repo'): + if entry.get('bookmark_repo') and safe_int(entry.get('bookmark_repo')): repo = Repository.get(entry['bookmark_repo']) perm_check = HasRepoPermissionAny( 'repository.read', 'repository.write', 'repository.admin') @@ -432,7 +432,7 @@ class MyAccountView(BaseAppView, DataGri should_save = True default_redirect_url = '${repo_url}' # save repo group - elif entry.get('bookmark_repo_group'): + elif entry.get('bookmark_repo_group') and safe_int(entry.get('bookmark_repo_group')): repo_group = RepoGroup.get(entry['bookmark_repo_group']) perm_check = HasRepoGroupPermissionAny( 'group.read', 'group.write', 'group.admin') @@ -496,6 +496,7 @@ class MyAccountView(BaseAppView, DataGri if not user_bookmark: raise HTTPFound(redirect_url) + # repository set if user_bookmark.repository: repo_name = user_bookmark.repository.repo_name base_redirect_url = h.route_path( @@ -506,7 +507,7 @@ class MyAccountView(BaseAppView, DataGri .safe_substitute({'repo_url': base_redirect_url}) else: redirect_url = base_redirect_url - + # repository group set elif user_bookmark.repository_group: repo_group_name = user_bookmark.repository_group.group_name base_redirect_url = h.route_path( @@ -517,9 +518,11 @@ class MyAccountView(BaseAppView, DataGri .safe_substitute({'repo_group_url': base_redirect_url}) else: redirect_url = base_redirect_url - + # custom URL set elif user_bookmark.redirect_url: - redirect_url = user_bookmark.redirect_url + server_url = h.route_url('home').rstrip('/') + redirect_url = string.Template(user_bookmark.redirect_url) \ + .safe_substitute({'server_url': server_url}) log.debug('Redirecting bookmark %s to %s', user_bookmark, redirect_url) raise HTTPFound(redirect_url) diff --git a/rhodecode/apps/repository/__init__.py b/rhodecode/apps/repository/__init__.py --- a/rhodecode/apps/repository/__init__.py +++ b/rhodecode/apps/repository/__init__.py @@ -90,7 +90,7 @@ def includeme(config): # Files config.add_route( name='repo_archivefile', - pattern='/{repo_name:.*?[^/]}/archive/{fname}', repo_route=True) + pattern='/{repo_name:.*?[^/]}/archive/{fname:.*}', repo_route=True) config.add_route( name='repo_files_diff', @@ -172,6 +172,10 @@ def includeme(config): pattern='/{repo_name:.*?[^/]}/add_file/{commit_id}/{f_path:.*}', repo_route=True) config.add_route( + name='repo_files_upload_file', + pattern='/{repo_name:.*?[^/]}/upload_file/{commit_id}/{f_path:.*}', + repo_route=True) + config.add_route( name='repo_files_create_file', pattern='/{repo_name:.*?[^/]}/create_file/{commit_id}/{f_path:.*}', repo_route=True) @@ -189,19 +193,27 @@ def includeme(config): name='repo_stats', pattern='/{repo_name:.*?[^/]}/repo_stats/{commit_id}', repo_route=True) - # Changelog + # Commits + config.add_route( + name='repo_commits', + pattern='/{repo_name:.*?[^/]}/commits', repo_route=True) + config.add_route( + name='repo_commits_file', + pattern='/{repo_name:.*?[^/]}/commits/{commit_id}/{f_path:.*}', repo_route=True) + config.add_route( + name='repo_commits_elements', + pattern='/{repo_name:.*?[^/]}/commits_elements', repo_route=True) + config.add_route( + name='repo_commits_elements_file', + pattern='/{repo_name:.*?[^/]}/commits_elements/{commit_id}/{f_path:.*}', repo_route=True) + + # Changelog (old deprecated name for commits page) config.add_route( name='repo_changelog', pattern='/{repo_name:.*?[^/]}/changelog', repo_route=True) config.add_route( name='repo_changelog_file', pattern='/{repo_name:.*?[^/]}/changelog/{commit_id}/{f_path:.*}', repo_route=True) - config.add_route( - name='repo_changelog_elements', - pattern='/{repo_name:.*?[^/]}/changelog_elements', repo_route=True) - config.add_route( - name='repo_changelog_elements_file', - pattern='/{repo_name:.*?[^/]}/changelog_elements/{commit_id}/{f_path:.*}', repo_route=True) # Compare config.add_route( @@ -312,6 +324,11 @@ def includeme(config): pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/comment/{comment_id}/delete', repo_route=True, repo_accepted_types=['hg', 'git']) + # Artifacts, (EE feature) + config.add_route( + name='repo_artifacts_list', + pattern='/{repo_name:.*?[^/]}/artifacts', repo_route=True) + # Settings config.add_route( name='edit_repo', diff --git a/rhodecode/apps/repository/tests/test_pull_requests_list.py b/rhodecode/apps/repository/tests/test_pull_requests_list.py --- a/rhodecode/apps/repository/tests/test_pull_requests_list.py +++ b/rhodecode/apps/repository/tests/test_pull_requests_list.py @@ -40,11 +40,11 @@ def route_path(name, params=None, **kwar class TestPullRequestList(object): @pytest.mark.parametrize('params, expected_title', [ - ({'source': 0, 'closed': 1}, 'Closed Pull Requests'), - ({'source': 0, 'my': 1}, 'opened by me'), - ({'source': 0, 'awaiting_review': 1}, 'awaiting review'), - ({'source': 0, 'awaiting_my_review': 1}, 'awaiting my review'), - ({'source': 1}, 'Pull Requests from'), + ({'source': 0, 'closed': 1}, 'Closed'), + ({'source': 0, 'my': 1}, 'Opened by me'), + ({'source': 0, 'awaiting_review': 1}, 'Awaiting review'), + ({'source': 0, 'awaiting_my_review': 1}, 'Awaiting my review'), + ({'source': 1}, 'From this repo'), ]) def test_showing_list_page(self, backend, pr_util, params, expected_title): pull_request = pr_util.create_pull_request() @@ -55,9 +55,10 @@ class TestPullRequestList(object): params=params)) assert_response = response.assert_response() - assert_response.element_equals_to('.panel-title', expected_title) - element = assert_response.get_element('.panel-title') - element_text = assert_response._element_to_string(element) + + element = assert_response.get_element('.title .active') + element_text = element.text_content() + assert expected_title == element_text def test_showing_list_page_data(self, backend, pr_util, xhr_header): pull_request = pr_util.create_pull_request() diff --git a/rhodecode/apps/repository/tests/test_repo_changelog.py b/rhodecode/apps/repository/tests/test_repo_changelog.py --- a/rhodecode/apps/repository/tests/test_repo_changelog.py +++ b/rhodecode/apps/repository/tests/test_repo_changelog.py @@ -32,9 +32,10 @@ def route_path(name, params=None, **kwar import urllib base_url = { - 'repo_changelog':'/{repo_name}/changelog', - 'repo_changelog_file':'/{repo_name}/changelog/{commit_id}/{f_path}', - 'repo_changelog_elements':'/{repo_name}/changelog_elements', + 'repo_changelog': '/{repo_name}/changelog', + 'repo_commits': '/{repo_name}/commits', + 'repo_commits_file': '/{repo_name}/commits/{commit_id}/{f_path}', + 'repo_commits_elements': '/{repo_name}/commits_elements', }[name].format(**kwargs) if params: @@ -42,8 +43,22 @@ def route_path(name, params=None, **kwar return base_url +def assert_commits_on_page(response, indexes): + found_indexes = [int(idx) for idx in MATCH_HASH.findall(response.body)] + assert found_indexes == indexes + + class TestChangelogController(TestController): + def test_commits_page(self, backend): + self.log_user() + response = self.app.get( + route_path('repo_commits', repo_name=backend.repo_name)) + + first_idx = -1 + last_idx = -DEFAULT_CHANGELOG_SIZE + self.assert_commit_range_on_page(response, first_idx, last_idx, backend) + def test_changelog(self, backend): self.log_user() response = self.app.get( @@ -62,6 +77,14 @@ class TestChangelogController(TestContro params=dict(branch=backend.default_branch_name)), status=200) + @pytest.mark.backends("hg", "git") + def test_commits_filtered_by_branch(self, backend): + self.log_user() + self.app.get( + route_path('repo_commits', repo_name=backend.repo_name, + params=dict(branch=backend.default_branch_name)), + status=200) + @pytest.mark.backends("svn") def test_changelog_filtered_by_branch_svn(self, autologin_user, backend): repo = backend['svn-simple-layout'] @@ -70,27 +93,22 @@ class TestChangelogController(TestContro params=dict(branch='trunk')), status=200) - self.assert_commits_on_page( - response, indexes=[15, 12, 7, 3, 2, 1]) + assert_commits_on_page(response, indexes=[15, 12, 7, 3, 2, 1]) - def test_changelog_filtered_by_wrong_branch(self, backend): + def test_commits_filtered_by_wrong_branch(self, backend): self.log_user() branch = 'wrong-branch-name' response = self.app.get( - route_path('repo_changelog', repo_name=backend.repo_name, + route_path('repo_commits', repo_name=backend.repo_name, params=dict(branch=branch)), status=302) - expected_url = '/{repo}/changelog/{branch}'.format( + expected_url = '/{repo}/commits/{branch}'.format( repo=backend.repo_name, branch=branch) assert expected_url in response.location response = response.follow() expected_warning = 'Branch {} is not found.'.format(branch) assert expected_warning in response.body - def assert_commits_on_page(self, response, indexes): - found_indexes = [int(idx) for idx in MATCH_HASH.findall(response.body)] - assert found_indexes == indexes - @pytest.mark.xfail_backends("svn", reason="Depends on branch support") def test_changelog_filtered_by_branch_with_merges( self, autologin_user, backend): @@ -112,21 +130,20 @@ class TestChangelogController(TestContro status=200) @pytest.mark.backends("hg") - def test_changelog_closed_branches(self, autologin_user, backend): + def test_commits_closed_branches(self, autologin_user, backend): repo = backend['closed_branch'] response = self.app.get( - route_path('repo_changelog', repo_name=repo.repo_name, + route_path('repo_commits', repo_name=repo.repo_name, params=dict(branch='experimental')), status=200) - self.assert_commits_on_page( - response, indexes=[3, 1]) + assert_commits_on_page(response, indexes=[3, 1]) def test_changelog_pagination(self, backend): self.log_user() # pagination, walk up to page 6 changelog_url = route_path( - 'repo_changelog', repo_name=backend.repo_name) + 'repo_commits', repo_name=backend.repo_name) for page in range(1, 7): response = self.app.get(changelog_url, {'page': page}) @@ -138,22 +155,30 @@ class TestChangelogController(TestContro def assert_commit_range_on_page( self, response, first_idx, last_idx, backend): input_template = ( - """""" ) + commit_span_template = """r%s:%s""" repo = backend.repo first_commit_on_page = repo.get_commit(commit_idx=first_idx) response.mustcontain( - input_template % {'raw_id': first_commit_on_page.raw_id}) + input_template % {'raw_id': first_commit_on_page.raw_id, + 'idx': first_commit_on_page.idx, + 'short_id': first_commit_on_page.short_id}) + response.mustcontain(commit_span_template % ( first_commit_on_page.idx, first_commit_on_page.short_id) ) last_commit_on_page = repo.get_commit(commit_idx=last_idx) response.mustcontain( - input_template % {'raw_id': last_commit_on_page.raw_id}) + input_template % {'raw_id': last_commit_on_page.raw_id, + 'idx': last_commit_on_page.idx, + 'short_id': last_commit_on_page.short_id}) response.mustcontain(commit_span_template % ( last_commit_on_page.idx, last_commit_on_page.short_id) ) @@ -168,10 +193,10 @@ class TestChangelogController(TestContro '/vcs/exceptions.py', '//vcs/exceptions.py' ]) - def test_changelog_with_filenode(self, backend, test_path): + def test_commits_with_filenode(self, backend, test_path): self.log_user() response = self.app.get( - route_path('repo_changelog_file', repo_name=backend.repo_name, + route_path('repo_commits_file', repo_name=backend.repo_name, commit_id='tip', f_path=test_path), ) @@ -180,16 +205,16 @@ class TestChangelogController(TestContro response.mustcontain('Added not implemented hg backend test case') response.mustcontain('Added BaseChangeset class') - def test_changelog_with_filenode_that_is_dirnode(self, backend): + def test_commits_with_filenode_that_is_dirnode(self, backend): self.log_user() self.app.get( - route_path('repo_changelog_file', repo_name=backend.repo_name, + route_path('repo_commits_file', repo_name=backend.repo_name, commit_id='tip', f_path='/tests'), status=302) - def test_changelog_with_filenode_not_existing(self, backend): + def test_commits_with_filenode_not_existing(self, backend): self.log_user() self.app.get( - route_path('repo_changelog_file', repo_name=backend.repo_name, + route_path('repo_commits_file', repo_name=backend.repo_name, commit_id='tip', f_path='wrong_path'), status=302) diff --git a/rhodecode/apps/repository/tests/test_repo_compare.py b/rhodecode/apps/repository/tests/test_repo_compare.py --- a/rhodecode/apps/repository/tests/test_repo_compare.py +++ b/rhodecode/apps/repository/tests/test_repo_compare.py @@ -94,6 +94,7 @@ class TestCompareView(object): origin_repo = origin.scm_instance(cache=False) origin_repo.config.clear_section('hooks') origin_repo.pull(fork.repo_full_path, commit_ids=[commit3.raw_id]) + origin_repo = origin.scm_instance(cache=False) # cache rebuild # Verify test fixture setup # This does not work for git @@ -162,8 +163,7 @@ class TestCompareView(object): compare_page.target_source_are_disabled() @pytest.mark.xfail_backends("svn", reason="Depends on branch support") - def test_compare_forks_on_branch_extra_commits_origin_has_incomming( - self, backend): + def test_compare_forks_on_branch_extra_commits_origin_has_incomming(self, backend): repo1 = backend.create_repo() # commit something ! diff --git a/rhodecode/apps/repository/tests/test_repo_compare_on_single_file.py b/rhodecode/apps/repository/tests/test_repo_compare_on_single_file.py --- a/rhodecode/apps/repository/tests/test_repo_compare_on_single_file.py +++ b/rhodecode/apps/repository/tests/test_repo_compare_on_single_file.py @@ -21,6 +21,7 @@ import pytest from rhodecode.lib.vcs import nodes +from rhodecode.lib.vcs.backends.base import EmptyCommit from rhodecode.tests.fixture import Fixture from rhodecode.tests.utils import commit_change @@ -43,70 +44,7 @@ def route_path(name, params=None, **kwar @pytest.mark.usefixtures("autologin_user", "app") class TestSideBySideDiff(object): - def test_diff_side_by_side(self, app, backend, backend_stub): - f_path = 'test_sidebyside_file.py' - commit1_content = 'content-25d7e49c18b159446c\n' - commit2_content = 'content-603d6c72c46d953420\n' - repo = backend.create_repo() - - commit1 = commit_change( - repo.repo_name, filename=f_path, content=commit1_content, - message='A', vcs_type=backend.alias, parent=None, newfile=True) - - commit2 = commit_change( - repo.repo_name, filename=f_path, content=commit2_content, - message='B, child of A', vcs_type=backend.alias, parent=commit1) - - response = self.app.get(route_path( - 'repo_compare', - repo_name=repo.repo_name, - source_ref_type='rev', - source_ref=commit1.raw_id, - target_ref_type='rev', - target_ref=commit2.raw_id, - params=dict(f_path=f_path, target_repo=repo.repo_name, diffmode='sidebyside') - )) - - response.mustcontain('Expand 1 commit') - response.mustcontain('1 file changed') - - response.mustcontain( - 'r%s:%s...r%s:%s' % ( - commit1.idx, commit1.short_id, commit2.idx, commit2.short_id)) - - response.mustcontain('{}'.format(f_path)) - - def test_diff_side_by_side_with_empty_file(self, app, backend, backend_stub): - commits = [ - {'message': 'First commit'}, - {'message': 'Commit with binary', - 'added': [nodes.FileNode('file.empty', content='')]}, - ] - f_path = 'file.empty' - repo = backend.create_repo(commits=commits) - commit1 = repo.get_commit(commit_idx=0) - commit2 = repo.get_commit(commit_idx=1) - - response = self.app.get(route_path( - 'repo_compare', - repo_name=repo.repo_name, - source_ref_type='rev', - source_ref=commit1.raw_id, - target_ref_type='rev', - target_ref=commit2.raw_id, - params=dict(f_path=f_path, target_repo=repo.repo_name, diffmode='sidebyside') - )) - - response.mustcontain('Expand 1 commit') - response.mustcontain('1 file changed') - - response.mustcontain( - 'r%s:%s...r%s:%s' % ( - commit1.idx, commit1.short_id, commit2.idx, commit2.short_id)) - - response.mustcontain('{}'.format(f_path)) - - def test_diff_sidebyside_two_commits(self, app, backend): + def test_diff_sidebyside_single_commit(self, app, backend): commit_id_range = { 'hg': { 'commits': ['25d7e49c18b159446cadfa506a5cf8ad1cb04067', @@ -141,26 +79,164 @@ class TestSideBySideDiff(object): params=dict(target_repo=backend.repo_name, diffmode='sidebyside') )) + response.mustcontain(file_changes) response.mustcontain('Expand 1 commit') - response.mustcontain(file_changes) - def test_diff_sidebyside_two_commits_single_file(self, app, backend): + def test_diff_sidebyside_two_commits(self, app, backend): commit_id_range = { 'hg': { - 'commits': ['25d7e49c18b159446cadfa506a5cf8ad1cb04067', + 'commits': ['4fdd71e9427417b2e904e0464c634fdee85ec5a7', '603d6c72c46d953420c89d36372f08d9f305f5dd'], - 'changes': '1 file changed: 1 inserted, 1 deleted' + 'changes': '32 files changed: 1165 inserted, 308 deleted' }, 'git': { - 'commits': ['6fc9270775aaf5544c1deb014f4ddd60c952fcbb', + 'commits': ['f5fbf9cfd5f1f1be146f6d3b38bcd791a7480c13', '03fa803d7e9fb14daa9a3089e0d1494eda75d986'], - 'changes': '1 file changed: 1 inserted, 1 deleted' + 'changes': '32 files changed: 1165 inserted, 308 deleted' }, 'svn': { - 'commits': ['336', + 'commits': ['335', '337'], - 'changes': '1 file changed: 1 inserted, 1 deleted' + 'changes': '32 files changed: 1179 inserted, 310 deleted' + }, + } + + commit_info = commit_id_range[backend.alias] + commit2, commit1 = commit_info['commits'] + file_changes = commit_info['changes'] + + response = self.app.get(route_path( + 'repo_compare', + repo_name=backend.repo_name, + source_ref_type='rev', + source_ref=commit2, + target_repo=backend.repo_name, + target_ref_type='rev', + target_ref=commit1, + params=dict(target_repo=backend.repo_name, diffmode='sidebyside') + )) + + response.mustcontain(file_changes) + response.mustcontain('Expand 2 commits') + + @pytest.mark.xfail(reason='GIT does not handle empty commit compare correct (missing 1 commit)') + def test_diff_side_by_side_from_0_commit(self, app, backend, backend_stub): + f_path = 'test_sidebyside_file.py' + commit1_content = 'content-25d7e49c18b159446c\n' + commit2_content = 'content-603d6c72c46d953420\n' + repo = backend.create_repo() + + commit1 = commit_change( + repo.repo_name, filename=f_path, content=commit1_content, + message='A', vcs_type=backend.alias, parent=None, newfile=True) + + commit2 = commit_change( + repo.repo_name, filename=f_path, content=commit2_content, + message='B, child of A', vcs_type=backend.alias, parent=commit1) + + response = self.app.get(route_path( + 'repo_compare', + repo_name=repo.repo_name, + source_ref_type='rev', + source_ref=EmptyCommit().raw_id, + target_ref_type='rev', + target_ref=commit2.raw_id, + params=dict(diffmode='sidebyside') + )) + + response.mustcontain('Expand 2 commits') + response.mustcontain('123 file changed') + + response.mustcontain( + 'r%s:%s...r%s:%s' % ( + commit1.idx, commit1.short_id, commit2.idx, commit2.short_id)) + + response.mustcontain('{}'.format(f_path)) + + @pytest.mark.xfail(reason='GIT does not handle empty commit compare correct (missing 1 commit)') + def test_diff_side_by_side_from_0_commit_with_file_filter(self, app, backend, backend_stub): + f_path = 'test_sidebyside_file.py' + commit1_content = 'content-25d7e49c18b159446c\n' + commit2_content = 'content-603d6c72c46d953420\n' + repo = backend.create_repo() + + commit1 = commit_change( + repo.repo_name, filename=f_path, content=commit1_content, + message='A', vcs_type=backend.alias, parent=None, newfile=True) + + commit2 = commit_change( + repo.repo_name, filename=f_path, content=commit2_content, + message='B, child of A', vcs_type=backend.alias, parent=commit1) + + response = self.app.get(route_path( + 'repo_compare', + repo_name=repo.repo_name, + source_ref_type='rev', + source_ref=EmptyCommit().raw_id, + target_ref_type='rev', + target_ref=commit2.raw_id, + params=dict(f_path=f_path, target_repo=repo.repo_name, diffmode='sidebyside') + )) + + response.mustcontain('Expand 2 commits') + response.mustcontain('1 file changed') + + response.mustcontain( + 'r%s:%s...r%s:%s' % ( + commit1.idx, commit1.short_id, commit2.idx, commit2.short_id)) + + response.mustcontain('{}'.format(f_path)) + + def test_diff_side_by_side_with_empty_file(self, app, backend, backend_stub): + commits = [ + {'message': 'First commit'}, + {'message': 'Second commit'}, + {'message': 'Commit with binary', + 'added': [nodes.FileNode('file.empty', content='')]}, + ] + f_path = 'file.empty' + repo = backend.create_repo(commits=commits) + commit1 = repo.get_commit(commit_idx=0) + commit2 = repo.get_commit(commit_idx=1) + commit3 = repo.get_commit(commit_idx=2) + + response = self.app.get(route_path( + 'repo_compare', + repo_name=repo.repo_name, + source_ref_type='rev', + source_ref=commit1.raw_id, + target_ref_type='rev', + target_ref=commit3.raw_id, + params=dict(f_path=f_path, target_repo=repo.repo_name, diffmode='sidebyside') + )) + + response.mustcontain('Expand 2 commits') + response.mustcontain('1 file changed') + + response.mustcontain( + 'r%s:%s...r%s:%s' % ( + commit2.idx, commit2.short_id, commit3.idx, commit3.short_id)) + + response.mustcontain('{}'.format(f_path)) + + def test_diff_sidebyside_two_commits_with_file_filter(self, app, backend): + commit_id_range = { + 'hg': { + 'commits': ['4fdd71e9427417b2e904e0464c634fdee85ec5a7', + '603d6c72c46d953420c89d36372f08d9f305f5dd'], + 'changes': '1 file changed: 3 inserted, 3 deleted' + }, + 'git': { + 'commits': ['f5fbf9cfd5f1f1be146f6d3b38bcd791a7480c13', + '03fa803d7e9fb14daa9a3089e0d1494eda75d986'], + 'changes': '1 file changed: 3 inserted, 3 deleted' + }, + + 'svn': { + 'commits': ['335', + '337'], + 'changes': '1 file changed: 3 inserted, 3 deleted' }, } f_path = 'docs/conf.py' @@ -179,5 +255,5 @@ class TestSideBySideDiff(object): params=dict(f_path=f_path, target_repo=backend.repo_name, diffmode='sidebyside') )) - response.mustcontain('Expand 1 commit') + response.mustcontain('Expand 2 commits') response.mustcontain(file_changes) diff --git a/rhodecode/apps/repository/tests/test_repo_files.py b/rhodecode/apps/repository/tests/test_repo_files.py --- a/rhodecode/apps/repository/tests/test_repo_files.py +++ b/rhodecode/apps/repository/tests/test_repo_files.py @@ -243,7 +243,7 @@ class TestFilesViews(object): repo_name=backend.repo_name, commit_id=commit.raw_id, f_path='vcs/nodes.py')) - msgbox = """
%s
""" + msgbox = """
%s
""" response.mustcontain(msgbox % (commit.message, )) assert_response = response.assert_response() @@ -313,6 +313,7 @@ class TestFilesViews(object): expected_data = json.loads( fixture.load_resource('svn_node_history_branches.json')) + assert expected_data == response.json def test_file_source_history_with_annotation(self, backend, xhr_header): @@ -521,10 +522,10 @@ class TestRepositoryArchival(object): def test_archival(self, backend): backend.enable_downloads() commit = backend.repo.get_commit(commit_idx=173) - for archive, info in settings.ARCHIVE_SPECS.items(): - mime_type, arch_ext = info - short = commit.short_id + arch_ext - fname = commit.raw_id + arch_ext + for a_type, content_type, extension in settings.ARCHIVE_SPECS: + + short = commit.short_id + extension + fname = commit.raw_id + extension filename = '%s-%s' % (backend.repo_name, short) response = self.app.get( route_path('repo_archivefile', @@ -534,7 +535,7 @@ class TestRepositoryArchival(object): assert response.status == '200 OK' headers = [ ('Content-Disposition', 'attachment; filename=%s' % filename), - ('Content-Type', '%s' % mime_type), + ('Content-Type', '%s' % content_type), ] for header in headers: @@ -761,7 +762,7 @@ class TestModifyFilesWithWebInterface(ob @pytest.mark.xfail_backends("svn", reason="Depends on online editing") def test_add_file_into_repo_missing_content(self, backend, csrf_token): - repo = backend.create_repo() + backend.create_repo() filename = 'init.py' response = self.app.post( route_path('repo_files_create_file', @@ -770,26 +771,25 @@ class TestModifyFilesWithWebInterface(ob params={ 'content': "", 'filename': filename, - 'location': "", 'csrf_token': csrf_token, }, status=302) - assert_session_flash(response, - 'Successfully committed new file `{}`'.format( - os.path.join(filename))) + expected_msg = 'Successfully committed new file `{}`'.format(os.path.join(filename)) + assert_session_flash(response, expected_msg) def test_add_file_into_repo_missing_filename(self, backend, csrf_token): + commit_id = backend.repo.get_commit().raw_id response = self.app.post( route_path('repo_files_create_file', repo_name=backend.repo_name, - commit_id='tip', f_path='/'), + commit_id=commit_id, f_path='/'), params={ 'content': "foo", 'csrf_token': csrf_token, }, status=302) - assert_session_flash(response, 'No filename') + assert_session_flash(response, 'No filename specified') def test_add_file_into_repo_errors_and_no_commits( self, backend, csrf_token): @@ -806,7 +806,7 @@ class TestModifyFilesWithWebInterface(ob }, status=302) - assert_session_flash(response, 'No filename') + assert_session_flash(response, 'No filename specified') # Not allowed, redirect to the summary redirected = response.follow() @@ -817,52 +817,51 @@ class TestModifyFilesWithWebInterface(ob assert redirected.request.path == summary_url - @pytest.mark.parametrize("location, filename", [ - ('/abs', 'foo'), - ('../rel', 'foo'), - ('file/../foo', 'foo'), + @pytest.mark.parametrize("filename, clean_filename", [ + ('/abs/foo', 'abs/foo'), + ('../rel/foo', 'rel/foo'), + ('file/../foo/foo', 'file/foo/foo'), ]) - def test_add_file_into_repo_bad_filenames( - self, location, filename, backend, csrf_token): + def test_add_file_into_repo_bad_filenames(self, filename, clean_filename, backend, csrf_token): + repo = backend.create_repo() + commit_id = repo.get_commit().raw_id + response = self.app.post( route_path('repo_files_create_file', - repo_name=backend.repo_name, - commit_id='tip', f_path='/'), + repo_name=repo.repo_name, + commit_id=commit_id, f_path='/'), params={ 'content': "foo", 'filename': filename, - 'location': location, 'csrf_token': csrf_token, }, status=302) - assert_session_flash( - response, - 'The location specified must be a relative path and must not ' - 'contain .. in the path') + expected_msg = 'Successfully committed new file `{}`'.format(clean_filename) + assert_session_flash(response, expected_msg) - @pytest.mark.parametrize("cnt, location, filename", [ - (1, '', 'foo.txt'), - (2, 'dir', 'foo.rst'), - (3, 'rel/dir', 'foo.bar'), + @pytest.mark.parametrize("cnt, filename, content", [ + (1, 'foo.txt', "Content"), + (2, 'dir/foo.rst', "Content"), + (3, 'dir/foo-second.rst', "Content"), + (4, 'rel/dir/foo.bar', "Content"), ]) - def test_add_file_into_repo(self, cnt, location, filename, backend, - csrf_token): + def test_add_file_into_empty_repo(self, cnt, filename, content, backend, csrf_token): repo = backend.create_repo() + commit_id = repo.get_commit().raw_id response = self.app.post( route_path('repo_files_create_file', repo_name=repo.repo_name, - commit_id='tip', f_path='/'), + commit_id=commit_id, f_path='/'), params={ - 'content': "foo", + 'content': content, 'filename': filename, - 'location': location, 'csrf_token': csrf_token, }, status=302) - assert_session_flash(response, - 'Successfully committed new file `{}`'.format( - os.path.join(location, filename))) + + expected_msg = 'Successfully committed new file `{}`'.format(filename) + assert_session_flash(response, expected_msg) def test_edit_file_view(self, backend): response = self.app.get( @@ -884,8 +883,7 @@ class TestModifyFilesWithWebInterface(ob f_path='vcs/nodes.py'), status=302) assert_session_flash( - response, - 'You can only edit files with commit being a valid branch') + response, 'Cannot modify file. Given commit `tip` is not head of a branch.') def test_edit_file_view_commit_changes(self, backend, csrf_token): repo = backend.create_repo() @@ -953,8 +951,7 @@ class TestModifyFilesWithWebInterface(ob f_path='vcs/nodes.py'), status=302) assert_session_flash( - response, - 'You can only delete files with commit being a valid branch') + response, 'Cannot modify file. Given commit `tip` is not head of a branch.') def test_delete_file_view_commit_changes(self, backend, csrf_token): repo = backend.create_repo() @@ -992,7 +989,7 @@ class TestFilesViewOtherCases(object): repo_file_add_url = route_path( 'repo_files_add_file', repo_name=repo.repo_name, - commit_id=0, f_path='') + '#edit' + commit_id=0, f_path='') assert_session_flash( response, @@ -1009,7 +1006,7 @@ class TestFilesViewOtherCases(object): repo_file_add_url = route_path( 'repo_files_add_file', repo_name=repo.repo_name, - commit_id=0, f_path='') + '#edit' + commit_id=0, f_path='') response = self.app.get( route_path('repo_files', diff --git a/rhodecode/apps/repository/tests/test_repo_pullrequests.py b/rhodecode/apps/repository/tests/test_repo_pullrequests.py --- a/rhodecode/apps/repository/tests/test_repo_pullrequests.py +++ b/rhodecode/apps/repository/tests/test_repo_pullrequests.py @@ -40,6 +40,8 @@ def route_path(name, params=None, **kwar base_url = { 'repo_changelog': '/{repo_name}/changelog', 'repo_changelog_file': '/{repo_name}/changelog/{commit_id}/{f_path}', + 'repo_commits': '/{repo_name}/commits', + 'repo_commits_file': '/{repo_name}/commits/{commit_id}/{f_path}', 'pullrequest_show': '/{repo_name}/pull-request/{pull_request_id}', 'pullrequest_show_all': '/{repo_name}/pull-request', 'pullrequest_show_all_data': '/{repo_name}/pull-request-data', @@ -998,11 +1000,11 @@ class TestPullrequestsView(object): assert len(target_children) == 1 expected_origin_link = route_path( - 'repo_changelog', + 'repo_commits', repo_name=pull_request.source_repo.scm_instance().name, params=dict(branch='origin')) expected_target_link = route_path( - 'repo_changelog', + 'repo_commits', repo_name=pull_request.target_repo.scm_instance().name, params=dict(branch='target')) assert origin_children[0].attrib['href'] == expected_origin_link diff --git a/rhodecode/apps/repository/tests/test_repo_summary.py b/rhodecode/apps/repository/tests/test_repo_summary.py --- a/rhodecode/apps/repository/tests/test_repo_summary.py +++ b/rhodecode/apps/repository/tests/test_repo_summary.py @@ -350,11 +350,11 @@ class TestCreateReferenceData(object): { 'children': [ { - 'id': 'a', 'raw_id': 'a_id', 'text': 'a', 'type': 't1', + 'id': 'a', 'idx': 0, 'raw_id': 'a_id', 'text': 'a', 'type': 't1', 'files_url': expected_files_url + 'a/?at=a', }, { - 'id': 'b', 'raw_id': 'b_id', 'text': 'b', 'type': 't1', + 'id': 'b', 'idx': 0, 'raw_id': 'b_id', 'text': 'b', 'type': 't1', 'files_url': expected_files_url + 'b/?at=b', } ], @@ -363,7 +363,7 @@ class TestCreateReferenceData(object): { 'children': [ { - 'id': 'c', 'raw_id': 'c_id', 'text': 'c', 'type': 't2', + 'id': 'c', 'idx': 0, 'raw_id': 'c_id', 'text': 'c', 'type': 't2', 'files_url': expected_files_url + 'c/?at=c', } ], @@ -385,12 +385,12 @@ class TestCreateReferenceData(object): { 'children': [ { - 'id': 'a@a_id', 'raw_id': 'a_id', + 'id': 'a@a_id', 'idx': 0, 'raw_id': 'a_id', 'text': 'a', 'type': 't1', 'files_url': expected_files_url + 'a_id/a?at=a', }, { - 'id': 'b@b_id', 'raw_id': 'b_id', + 'id': 'b@b_id', 'idx': 0, 'raw_id': 'b_id', 'text': 'b', 'type': 't1', 'files_url': expected_files_url + 'b_id/b?at=b', } @@ -400,7 +400,7 @@ class TestCreateReferenceData(object): { 'children': [ { - 'id': 'c@c_id', 'raw_id': 'c_id', + 'id': 'c@c_id', 'idx': 0, 'raw_id': 'c_id', 'text': 'c', 'type': 't2', 'files_url': expected_files_url + 'c_id/c?at=c', } @@ -516,6 +516,7 @@ class TestReferenceItems(object): 'text': ref_name, 'id': self._format_function(ref_name, ref_id), 'raw_id': ref_id, + 'idx': 0, 'type': self.ref_type, 'files_url': self.fake_url } diff --git a/rhodecode/apps/repository/views/repo_artifacts.py b/rhodecode/apps/repository/views/repo_artifacts.py new file mode 100644 --- /dev/null +++ b/rhodecode/apps/repository/views/repo_artifacts.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2011-2019 RhodeCode GmbH +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License, version 3 +# (only), as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# This program is dual-licensed. If you wish to learn more about the +# RhodeCode Enterprise Edition, including its added features, Support services, +# and proprietary license terms, please see https://rhodecode.com/licenses/ + +import logging + +from pyramid.view import view_config + +from rhodecode.apps._base import RepoAppView +from rhodecode.lib.auth import ( + LoginRequired, HasRepoPermissionAnyDecorator) + +log = logging.getLogger(__name__) + + +class RepoArtifactsView(RepoAppView): + + def load_default_context(self): + c = self._get_local_tmpl_context(include_app_defaults=True) + c.rhodecode_repo = self.rhodecode_vcs_repo + return c + + @LoginRequired() + @HasRepoPermissionAnyDecorator( + 'repository.read', 'repository.write', 'repository.admin') + @view_config( + route_name='repo_artifacts_list', request_method='GET', + renderer='rhodecode:templates/artifacts/artifact_list.mako') + def repo_artifacts(self): + c = self.load_default_context() + c.active = 'artifacts' + return self._get_template_context(c) diff --git a/rhodecode/apps/repository/views/repo_changelog.py b/rhodecode/apps/repository/views/repo_changelog.py --- a/rhodecode/apps/repository/views/repo_changelog.py +++ b/rhodecode/apps/repository/views/repo_changelog.py @@ -113,7 +113,7 @@ class RepoChangelogView(RepoAppView): h.flash('Branch {} is not found.'.format(h.escape(branch_name)), category='warning') redirect_url = h.route_path( - 'repo_changelog_file', repo_name=repo_name, + 'repo_commits_file', repo_name=repo_name, commit_id=branch_name, f_path=f_path or '') raise HTTPFound(redirect_url) @@ -127,13 +127,13 @@ class RepoChangelogView(RepoAppView): if f_path: # changelog for file return h.route_path( - 'repo_changelog_file', + 'repo_commits_file', repo_name=c.rhodecode_db_repo.repo_name, commit_id=commit_id, f_path=f_path, _query=query_params) else: return h.route_path( - 'repo_changelog', + 'repo_commits', repo_name=c.rhodecode_db_repo.repo_name, _query=query_params) c.total_cs = len(collection) @@ -171,11 +171,18 @@ class RepoChangelogView(RepoAppView): @HasRepoPermissionAnyDecorator( 'repository.read', 'repository.write', 'repository.admin') @view_config( + route_name='repo_commits', request_method='GET', + renderer='rhodecode:templates/commits/changelog.mako') + @view_config( + route_name='repo_commits_file', request_method='GET', + renderer='rhodecode:templates/commits/changelog.mako') + # old routes for backward compat + @view_config( route_name='repo_changelog', request_method='GET', - renderer='rhodecode:templates/changelog/changelog.mako') + renderer='rhodecode:templates/commits/changelog.mako') @view_config( route_name='repo_changelog_file', request_method='GET', - renderer='rhodecode:templates/changelog/changelog.mako') + renderer='rhodecode:templates/commits/changelog.mako') def repo_changelog(self): c = self.load_default_context() @@ -224,7 +231,7 @@ class RepoChangelogView(RepoAppView): except RepositoryError as e: h.flash(safe_str(e), category='warning') redirect_url = h.route_path( - 'repo_changelog', repo_name=self.db_repo_name) + 'repo_commits', repo_name=self.db_repo_name) raise HTTPFound(redirect_url) collection = list(reversed(collection)) else: @@ -246,14 +253,14 @@ class RepoChangelogView(RepoAppView): log.exception(safe_str(e)) h.flash(safe_str(h.escape(e)), category='error') raise HTTPFound( - h.route_path('repo_changelog', repo_name=self.db_repo_name)) + h.route_path('repo_commits', repo_name=self.db_repo_name)) if partial_xhr or self.request.environ.get('HTTP_X_PJAX'): # case when loading dynamic file history in file view # loading from ajax, we don't want the first result, it's popped # in the code above html = render( - 'rhodecode:templates/changelog/changelog_file_history.mako', + 'rhodecode:templates/commits/changelog_file_history.mako', self._get_template_context(c), self.request) return Response(html) @@ -271,14 +278,14 @@ class RepoChangelogView(RepoAppView): @HasRepoPermissionAnyDecorator( 'repository.read', 'repository.write', 'repository.admin') @view_config( - route_name='repo_changelog_elements', request_method=('GET', 'POST'), - renderer='rhodecode:templates/changelog/changelog_elements.mako', + route_name='repo_commits_elements', request_method=('GET', 'POST'), + renderer='rhodecode:templates/commits/changelog_elements.mako', xhr=True) @view_config( - route_name='repo_changelog_elements_file', request_method=('GET', 'POST'), - renderer='rhodecode:templates/changelog/changelog_elements.mako', + route_name='repo_commits_elements_file', request_method=('GET', 'POST'), + renderer='rhodecode:templates/commits/changelog_elements.mako', xhr=True) - def repo_changelog_elements(self): + def repo_commits_elements(self): c = self.load_default_context() commit_id = self.request.matchdict.get('commit_id') f_path = self._get_f_path(self.request.matchdict) @@ -312,7 +319,7 @@ class RepoChangelogView(RepoAppView): except (RepositoryError, CommitDoesNotExistError, Exception) as e: log.exception(safe_str(e)) raise HTTPFound( - h.route_path('repo_changelog', repo_name=self.db_repo_name)) + h.route_path('repo_commits', repo_name=self.db_repo_name)) collection = base_commit.get_path_history( f_path, limit=hist_limit, pre_load=pre_load) diff --git a/rhodecode/apps/repository/views/repo_commits.py b/rhodecode/apps/repository/views/repo_commits.py --- a/rhodecode/apps/repository/views/repo_commits.py +++ b/rhodecode/apps/repository/views/repo_commits.py @@ -105,10 +105,9 @@ class RepoCommitsView(RepoAppView): c.commit_ranges = commits if not c.commit_ranges: - raise RepositoryError( - 'The commit range returned an empty result') - except CommitDoesNotExistError: - msg = _('No such commit exists for this repository') + raise RepositoryError('The commit range returned an empty result') + except CommitDoesNotExistError as e: + msg = _('No such commit exists. Org exception: `{}`').format(e) h.flash(msg, category='error') raise HTTPNotFound() except Exception: diff --git a/rhodecode/apps/repository/views/repo_compare.py b/rhodecode/apps/repository/views/repo_compare.py --- a/rhodecode/apps/repository/views/repo_compare.py +++ b/rhodecode/apps/repository/views/repo_compare.py @@ -214,29 +214,23 @@ class RepoCompareView(RepoAppView): pre_load = ["author", "branch", "date", "message"] c.ancestor = None - if c.file_path: - if source_commit == target_commit: - c.commit_ranges = [] - else: - c.commit_ranges = [target_commit] - else: - try: - c.commit_ranges = source_scm.compare( - source_commit.raw_id, target_commit.raw_id, - target_scm, merge, pre_load=pre_load) - if merge: - c.ancestor = source_scm.get_common_ancestor( - source_commit.raw_id, target_commit.raw_id, target_scm) - except RepositoryRequirementError: - msg = _('Could not compare repos with different ' - 'large file settings') - log.error(msg) - if partial: - return Response(msg) - h.flash(msg, category='error') - raise HTTPFound( - h.route_path('repo_compare_select', - repo_name=self.db_repo_name)) + try: + c.commit_ranges = source_scm.compare( + source_commit.raw_id, target_commit.raw_id, + target_scm, merge, pre_load=pre_load) or [] + if merge: + c.ancestor = source_scm.get_common_ancestor( + source_commit.raw_id, target_commit.raw_id, target_scm) + except RepositoryRequirementError: + msg = _('Could not compare repos with different ' + 'large file settings') + log.error(msg) + if partial: + return Response(msg) + h.flash(msg, category='error') + raise HTTPFound( + h.route_path('repo_compare_select', + repo_name=self.db_repo_name)) c.statuses = self.db_repo.statuses( [x.raw_id for x in c.commit_ranges]) diff --git a/rhodecode/apps/repository/views/repo_files.py b/rhodecode/apps/repository/views/repo_files.py --- a/rhodecode/apps/repository/views/repo_files.py +++ b/rhodecode/apps/repository/views/repo_files.py @@ -25,6 +25,7 @@ import shutil import tempfile import collections import urllib +import pathlib2 from pyramid.httpexceptions import HTTPNotFound, HTTPBadRequest, HTTPFound from pyramid.view import view_config @@ -42,7 +43,7 @@ from rhodecode.lib.exceptions import Non from rhodecode.lib.codeblocks import ( filenode_as_lines_tokens, filenode_as_annotated_lines_tokens) from rhodecode.lib.utils2 import ( - convert_line_endings, detect_mode, safe_str, str2bool, safe_int) + convert_line_endings, detect_mode, safe_str, str2bool, safe_int, sha1, safe_unicode) from rhodecode.lib.auth import ( LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired) from rhodecode.lib.vcs import path as vcspath @@ -87,7 +88,7 @@ class RepoFilesView(RepoAppView): c.enable_downloads = self.db_repo.enable_downloads return c - def _ensure_not_locked(self): + def _ensure_not_locked(self, commit_id='tip'): _ = self.request.translate repo = self.db_repo @@ -98,21 +99,41 @@ class RepoFilesView(RepoAppView): 'warning') files_url = h.route_path( 'repo_files:default_path', - repo_name=self.db_repo_name, commit_id='tip') + repo_name=self.db_repo_name, commit_id=commit_id) raise HTTPFound(files_url) - def check_branch_permission(self, branch_name): + def forbid_non_head(self, is_head, f_path, commit_id='tip', json_mode=False): + _ = self.request.translate + + if not is_head: + message = _('Cannot modify file. ' + 'Given commit `{}` is not head of a branch.').format(commit_id) + h.flash(message, category='warning') + + if json_mode: + return message + + files_url = h.route_path( + 'repo_files', repo_name=self.db_repo_name, commit_id=commit_id, + f_path=f_path) + raise HTTPFound(files_url) + + def check_branch_permission(self, branch_name, commit_id='tip', json_mode=False): _ = self.request.translate rule, branch_perm = self._rhodecode_user.get_rule_and_branch_permission( self.db_repo_name, branch_name) if branch_perm and branch_perm not in ['branch.push', 'branch.push_force']: - h.flash( - _('Branch `{}` changes forbidden by rule {}.').format(branch_name, rule), - 'warning') + message = _('Branch `{}` changes forbidden by rule {}.').format( + branch_name, rule) + h.flash(message, 'warning') + + if json_mode: + return message + files_url = h.route_path( - 'repo_files:default_path', - repo_name=self.db_repo_name, commit_id='tip') + 'repo_files:default_path', repo_name=self.db_repo_name, commit_id=commit_id) + raise HTTPFound(files_url) def _get_commit_and_path(self): @@ -146,8 +167,7 @@ class RepoFilesView(RepoAppView): _url = h.route_path( 'repo_files_add_file', - repo_name=self.db_repo_name, commit_id=0, f_path='', - _anchor='edit') + repo_name=self.db_repo_name, commit_id=0, f_path='') if h.HasRepoPermissionAny( 'repository.write', 'repository.admin')(self.db_repo_name): @@ -185,8 +205,7 @@ class RepoFilesView(RepoAppView): h.flash(_('No such commit exists for this repository'), category='error') raise HTTPNotFound() except RepositoryError as e: - log.warning('Repository error while fetching ' - 'filenode `%s`. Err:%s', path, e) + log.warning('Repository error while fetching filenode `%s`. Err:%s', path, e) h.flash(safe_str(h.escape(e)), category='error') raise HTTPNotFound() @@ -195,12 +214,7 @@ class RepoFilesView(RepoAppView): def _is_valid_head(self, commit_id, repo): branch_name = sha_commit_id = '' is_head = False - - if h.is_svn(repo) and not repo.is_empty(): - # Note: Subversion only has one head. - if commit_id == repo.get_commit(commit_idx=-1).raw_id: - is_head = True - return branch_name, sha_commit_id, is_head + log.debug('Checking if commit_id `%s` is a head for %s.', commit_id, repo) for _branch_name, branch_commit_id in repo.branches.items(): # simple case we pass in branch name, it's a HEAD @@ -216,8 +230,14 @@ class RepoFilesView(RepoAppView): sha_commit_id = branch_commit_id break + if h.is_svn(repo) and not repo.is_empty(): + # Note: Subversion only has one head. + if commit_id == repo.get_commit(commit_idx=-1).raw_id: + is_head = True + return branch_name, sha_commit_id, is_head + # checked branches, means we only need to try to get the branch/commit_sha - if not repo.is_empty: + if not repo.is_empty(): commit = repo.get_commit(commit_id=commit_id) if commit: branch_name = commit.branch @@ -225,8 +245,7 @@ class RepoFilesView(RepoAppView): return branch_name, sha_commit_id, is_head - def _get_tree_at_commit( - self, c, commit_id, f_path, full_load=False): + def _get_tree_at_commit(self, c, commit_id, f_path, full_load=False): repo_id = self.db_repo.repo_id force_recache = self.get_recache_flag() @@ -244,16 +263,16 @@ class RepoFilesView(RepoAppView): @region.conditional_cache_on_arguments(namespace=cache_namespace_uid, condition=cache_on) - def compute_file_tree(repo_id, commit_id, f_path, full_load): - log.debug('Generating cached file tree for repo_id: %s, %s, %s', - repo_id, commit_id, f_path) + def compute_file_tree(ver, repo_id, commit_id, f_path, full_load): + log.debug('Generating cached file tree at ver:%s for repo_id: %s, %s, %s', + ver, repo_id, commit_id, f_path) c.full_load = full_load return render( 'rhodecode:templates/files/files_browser_tree.mako', self._get_template_context(c), self.request) - return compute_file_tree(self.db_repo.repo_id, commit_id, f_path, full_load) + return compute_file_tree('v1', self.db_repo.repo_id, commit_id, f_path, full_load) def _get_archive_spec(self, fname): log.debug('Detecting archive spec for: `%s`', fname) @@ -261,8 +280,7 @@ class RepoFilesView(RepoAppView): fileformat = None ext = None content_type = None - for a_type, ext_data in settings.ARCHIVE_SPECS.items(): - content_type, extension = ext_data + for a_type, content_type, extension in settings.ARCHIVE_SPECS: if fname.endswith(extension): fileformat = a_type @@ -278,6 +296,15 @@ class RepoFilesView(RepoAppView): return commit_id, ext, fileformat, content_type + def create_pure_path(self, *parts): + # Split paths and sanitize them, removing any ../ etc + sanitized_path = [ + x for x in pathlib2.PurePath(*parts).parts + if x not in ['.', '..']] + + pure_path = pathlib2.PurePath(*sanitized_path) + return pure_path + @LoginRequired() @HasRepoPermissionAnyDecorator( 'repository.read', 'repository.write', 'repository.admin') @@ -289,9 +316,10 @@ class RepoFilesView(RepoAppView): from rhodecode import CONFIG _ = self.request.translate self.load_default_context() - + default_at_path = '/' fname = self.request.matchdict['fname'] subrepos = self.request.GET.get('subrepos') == 'true' + at_path = self.request.GET.get('at_path') or default_at_path if not self.db_repo.enable_downloads: return Response(_('Downloads disabled')) @@ -311,10 +339,31 @@ class RepoFilesView(RepoAppView): except EmptyRepositoryError: return Response(_('Empty repository')) - archive_name = '%s-%s%s%s' % ( - safe_str(self.db_repo_name.replace('/', '_')), - '-sub' if subrepos else '', - safe_str(commit.short_id), ext) + try: + at_path = commit.get_node(at_path).path or default_at_path + except Exception: + return Response(_('No node at path {} for this repository').format(at_path)) + + path_sha = sha1(at_path)[:8] + + # original backward compat name of archive + clean_name = safe_str(self.db_repo_name.replace('/', '_')) + short_sha = safe_str(commit.short_id) + + if at_path == default_at_path: + archive_name = '{}-{}{}{}'.format( + clean_name, + '-sub' if subrepos else '', + short_sha, + ext) + # custom path and new name + else: + archive_name = '{}-{}{}-{}{}'.format( + clean_name, + '-sub' if subrepos else '', + short_sha, + path_sha, + ext) use_cached_archive = False archive_cache_enabled = CONFIG.get( @@ -339,7 +388,8 @@ class RepoFilesView(RepoAppView): fd, archive = tempfile.mkstemp() log.debug('Creating new temp archive in %s', archive) try: - commit.archive_repo(archive, kind=fileformat, subrepos=subrepos) + commit.archive_repo(archive, kind=fileformat, subrepos=subrepos, + archive_at_path=at_path) except ImproperArchiveTypeError: return _('Unknown archive type') if archive_cache_enabled: @@ -632,8 +682,7 @@ class RepoFilesView(RepoAppView): c.authors = [] # this loads a simple tree without metadata to speed things up # later via ajax we call repo_nodetree_full and fetch whole - c.file_tree = self._get_tree_at_commit( - c, c.commit.raw_id, f_path) + c.file_tree = self._get_tree_at_commit(c, c.commit.raw_id, f_path) except RepositoryError as e: h.flash(safe_str(h.escape(e)), category='error') @@ -875,18 +924,17 @@ class RepoFilesView(RepoAppView): self.db_repo_name, self.db_repo.repo_id, commit.raw_id, f_path) return {'nodes': metadata} - def _create_references( - self, branches_or_tags, symbolic_reference, f_path): + def _create_references(self, branches_or_tags, symbolic_reference, f_path, ref_type): items = [] for name, commit_id in branches_or_tags.items(): - sym_ref = symbolic_reference(commit_id, name, f_path) - items.append((sym_ref, name)) + sym_ref = symbolic_reference(commit_id, name, f_path, ref_type) + items.append((sym_ref, name, ref_type)) return items - def _symbolic_reference(self, commit_id, name, f_path): + def _symbolic_reference(self, commit_id, name, f_path, ref_type): return commit_id - def _symbolic_reference_svn(self, commit_id, name, f_path): + def _symbolic_reference_svn(self, commit_id, name, f_path, ref_type): new_f_path = vcspath.join(name, f_path) return u'%s@%s' % (new_f_path, commit_id) @@ -916,7 +964,7 @@ class RepoFilesView(RepoAppView): for commit in commits: branch = ' (%s)' % commit.branch if commit.branch else '' n_desc = 'r%s:%s%s' % (commit.idx, commit.short_id, branch) - commits_group[0].append((commit.raw_id, n_desc,)) + commits_group[0].append((commit.raw_id, n_desc, 'sha')) history.append(commits_group) symbolic_reference = self._symbolic_reference @@ -932,11 +980,11 @@ class RepoFilesView(RepoAppView): symbolic_reference = self._symbolic_reference_svn branches = self._create_references( - self.rhodecode_vcs_repo.branches, symbolic_reference, f_path) + self.rhodecode_vcs_repo.branches, symbolic_reference, f_path, 'branch') branches_group = (branches, _("Branches")) tags = self._create_references( - self.rhodecode_vcs_repo.tags, symbolic_reference, f_path) + self.rhodecode_vcs_repo.tags, symbolic_reference, f_path, 'tag') tags_group = (tags, _("Tags")) history.append(branches_group) @@ -964,7 +1012,7 @@ class RepoFilesView(RepoAppView): for obj in file_history: res.append({ 'text': obj[1], - 'children': [{'id': o[0], 'text': o[1]} for o in obj[0]] + 'children': [{'id': o[0], 'text': o[1], 'type': o[2]} for o in obj[0]] }) data = { @@ -1035,15 +1083,9 @@ class RepoFilesView(RepoAppView): _branch_name, _sha_commit_id, is_head = \ self._is_valid_head(commit_id, self.rhodecode_vcs_repo) - if not is_head: - h.flash(_('You can only delete files with commit ' - 'being a valid branch head.'), category='warning') - raise HTTPFound( - h.route_path('repo_files', - repo_name=self.db_repo_name, commit_id='tip', - f_path=f_path)) + self.forbid_non_head(is_head, f_path) + self.check_branch_permission(_branch_name) - self.check_branch_permission(_branch_name) c.commit = self._get_commit_or_redirect(commit_id) c.file = self._get_filenode_or_redirect(c.commit, f_path) @@ -1069,13 +1111,7 @@ class RepoFilesView(RepoAppView): _branch_name, _sha_commit_id, is_head = \ self._is_valid_head(commit_id, self.rhodecode_vcs_repo) - if not is_head: - h.flash(_('You can only delete files with commit ' - 'being a valid branch head.'), category='warning') - raise HTTPFound( - h.route_path('repo_files', - repo_name=self.db_repo_name, commit_id='tip', - f_path=f_path)) + self.forbid_non_head(is_head, f_path) self.check_branch_permission(_branch_name) c.commit = self._get_commit_or_redirect(commit_id) @@ -1125,14 +1161,8 @@ class RepoFilesView(RepoAppView): _branch_name, _sha_commit_id, is_head = \ self._is_valid_head(commit_id, self.rhodecode_vcs_repo) - if not is_head: - h.flash(_('You can only edit files with commit ' - 'being a valid branch head.'), category='warning') - raise HTTPFound( - h.route_path('repo_files', - repo_name=self.db_repo_name, commit_id='tip', - f_path=f_path)) - self.check_branch_permission(_branch_name) + self.forbid_non_head(is_head, f_path, commit_id=commit_id) + self.check_branch_permission(_branch_name, commit_id=commit_id) c.commit = self._get_commit_or_redirect(commit_id) c.file = self._get_filenode_or_redirect(c.commit, f_path) @@ -1144,8 +1174,7 @@ class RepoFilesView(RepoAppView): commit_id=c.commit.raw_id, f_path=f_path) raise HTTPFound(files_url) - c.default_message = _( - 'Edited file {} via RhodeCode Enterprise').format(f_path) + c.default_message = _('Edited file {} via RhodeCode Enterprise').format(f_path) c.f_path = f_path return self._get_template_context(c) @@ -1162,32 +1191,23 @@ class RepoFilesView(RepoAppView): commit_id, f_path = self._get_commit_and_path() self._ensure_not_locked() - _branch_name, _sha_commit_id, is_head = \ - self._is_valid_head(commit_id, self.rhodecode_vcs_repo) - - if not is_head: - h.flash(_('You can only edit files with commit ' - 'being a valid branch head.'), category='warning') - raise HTTPFound( - h.route_path('repo_files', - repo_name=self.db_repo_name, commit_id='tip', - f_path=f_path)) - - self.check_branch_permission(_branch_name) c.commit = self._get_commit_or_redirect(commit_id) c.file = self._get_filenode_or_redirect(c.commit, f_path) if c.file.is_binary: - raise HTTPFound( - h.route_path('repo_files', - repo_name=self.db_repo_name, - commit_id=c.commit.raw_id, - f_path=f_path)) + raise HTTPFound(h.route_path('repo_files', repo_name=self.db_repo_name, + commit_id=c.commit.raw_id, f_path=f_path)) + + _branch_name, _sha_commit_id, is_head = \ + self._is_valid_head(commit_id, self.rhodecode_vcs_repo) - c.default_message = _( - 'Edited file {} via RhodeCode Enterprise').format(f_path) + self.forbid_non_head(is_head, f_path, commit_id=commit_id) + self.check_branch_permission(_branch_name, commit_id=commit_id) + + c.default_message = _('Edited file {} via RhodeCode Enterprise').format(f_path) c.f_path = f_path + old_content = c.file.content sl = old_content.splitlines(1) first_line = sl[0] if sl else '' @@ -1198,20 +1218,25 @@ class RepoFilesView(RepoAppView): content = convert_line_endings(r_post.get('content', ''), line_ending_mode) message = r_post.get('message') or c.default_message - org_f_path = c.file.unicode_path + org_node_path = c.file.unicode_path filename = r_post['filename'] - org_filename = c.file.name + + root_path = c.file.dir_path + pure_path = self.create_pure_path(root_path, filename) + node_path = safe_unicode(bytes(pure_path)) - if content == old_content and filename == org_filename: - h.flash(_('No changes'), category='warning') - raise HTTPFound( - h.route_path('repo_commit', repo_name=self.db_repo_name, - commit_id='tip')) + default_redirect_url = h.route_path('repo_commit', repo_name=self.db_repo_name, + commit_id=commit_id) + if content == old_content and node_path == org_node_path: + h.flash(_('No changes detected on {}').format(org_node_path), + category='warning') + raise HTTPFound(default_redirect_url) + try: mapping = { - org_f_path: { - 'org_filename': org_f_path, - 'filename': os.path.join(c.file.dir_path, filename), + org_node_path: { + 'org_filename': org_node_path, + 'filename': node_path, 'content': content, 'lexer': '', 'op': 'mod', @@ -1219,7 +1244,7 @@ class RepoFilesView(RepoAppView): } } - ScmModel().update_nodes( + commit = ScmModel().update_nodes( user=self._rhodecode_db_user.user_id, repo=self.db_repo, message=message, @@ -1227,21 +1252,25 @@ class RepoFilesView(RepoAppView): parent_commit=c.commit, ) - h.flash( - _('Successfully committed changes to file `{}`').format( + h.flash(_('Successfully committed changes to file `{}`').format( h.escape(f_path)), category='success') + default_redirect_url = h.route_path( + 'repo_commit', repo_name=self.db_repo_name, commit_id=commit.raw_id) + except Exception: log.exception('Error occurred during commit') h.flash(_('Error occurred during commit'), category='error') - raise HTTPFound( - h.route_path('repo_commit', repo_name=self.db_repo_name, - commit_id='tip')) + + raise HTTPFound(default_redirect_url) @LoginRequired() @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin') @view_config( route_name='repo_files_add_file', request_method='GET', renderer='rhodecode:templates/files/files_add.mako') + @view_config( + route_name='repo_files_upload_file', request_method='GET', + renderer='rhodecode:templates/files/files_upload.mako') def repo_files_add_file(self): _ = self.request.translate c = self.load_default_context() @@ -1252,27 +1281,20 @@ class RepoFilesView(RepoAppView): c.commit = self._get_commit_or_redirect(commit_id, redirect_after=False) if c.commit is None: c.commit = EmptyCommit(alias=self.rhodecode_vcs_repo.alias) - c.default_message = (_('Added file via RhodeCode Enterprise')) - c.f_path = f_path.lstrip('/') # ensure not relative path - if self.rhodecode_vcs_repo.is_empty: + if self.rhodecode_vcs_repo.is_empty(): # for empty repository we cannot check for current branch, we rely on # c.commit.branch instead - _branch_name = c.commit.branch - is_head = True + _branch_name, _sha_commit_id, is_head = c.commit.branch, '', True else: _branch_name, _sha_commit_id, is_head = \ self._is_valid_head(commit_id, self.rhodecode_vcs_repo) - if not is_head: - h.flash(_('You can only add files with commit ' - 'being a valid branch head.'), category='warning') - raise HTTPFound( - h.route_path('repo_files', - repo_name=self.db_repo_name, commit_id='tip', - f_path=f_path)) + self.forbid_non_head(is_head, f_path, commit_id=commit_id) + self.check_branch_permission(_branch_name, commit_id=commit_id) - self.check_branch_permission(_branch_name) + c.default_message = (_('Added file via RhodeCode Enterprise')) + c.f_path = f_path.lstrip('/') # ensure not relative path return self._get_template_context(c) @@ -1289,86 +1311,62 @@ class RepoFilesView(RepoAppView): self._ensure_not_locked() - r_post = self.request.POST - - c.commit = self._get_commit_or_redirect( - commit_id, redirect_after=False) + c.commit = self._get_commit_or_redirect(commit_id, redirect_after=False) if c.commit is None: c.commit = EmptyCommit(alias=self.rhodecode_vcs_repo.alias) - if self.rhodecode_vcs_repo.is_empty: - # for empty repository we cannot check for current branch, we rely on - # c.commit.branch instead - _branch_name = c.commit.branch - is_head = True - else: - _branch_name, _sha_commit_id, is_head = \ - self._is_valid_head(commit_id, self.rhodecode_vcs_repo) - - if not is_head: - h.flash(_('You can only add files with commit ' - 'being a valid branch head.'), category='warning') - raise HTTPFound( - h.route_path('repo_files', - repo_name=self.db_repo_name, commit_id='tip', - f_path=f_path)) - - self.check_branch_permission(_branch_name) - - c.default_message = (_('Added file via RhodeCode Enterprise')) - c.f_path = f_path - unix_mode = 0 - content = convert_line_endings(r_post.get('content', ''), unix_mode) - - message = r_post.get('message') or c.default_message - filename = r_post.get('filename') - location = r_post.get('location', '') # dir location - file_obj = r_post.get('upload_file', None) - - if file_obj is not None and hasattr(file_obj, 'filename'): - filename = r_post.get('filename_upload') - content = file_obj.file - - if hasattr(content, 'file'): - # non posix systems store real file under file attr - content = content.file - - if self.rhodecode_vcs_repo.is_empty: + # calculate redirect URL + if self.rhodecode_vcs_repo.is_empty(): default_redirect_url = h.route_path( 'repo_summary', repo_name=self.db_repo_name) else: default_redirect_url = h.route_path( 'repo_commit', repo_name=self.db_repo_name, commit_id='tip') - # If there's no commit, redirect to repo summary - if type(c.commit) is EmptyCommit: - redirect_url = h.route_path( - 'repo_summary', repo_name=self.db_repo_name) + if self.rhodecode_vcs_repo.is_empty(): + # for empty repository we cannot check for current branch, we rely on + # c.commit.branch instead + _branch_name, _sha_commit_id, is_head = c.commit.branch, '', True else: - redirect_url = default_redirect_url + _branch_name, _sha_commit_id, is_head = \ + self._is_valid_head(commit_id, self.rhodecode_vcs_repo) + + self.forbid_non_head(is_head, f_path, commit_id=commit_id) + self.check_branch_permission(_branch_name, commit_id=commit_id) + + c.default_message = (_('Added file via RhodeCode Enterprise')) + c.f_path = f_path + + r_post = self.request.POST + message = r_post.get('message') or c.default_message + filename = r_post.get('filename') + unix_mode = 0 + content = convert_line_endings(r_post.get('content', ''), unix_mode) if not filename: - h.flash(_('No filename'), category='warning') + # If there's no commit, redirect to repo summary + if type(c.commit) is EmptyCommit: + redirect_url = h.route_path( + 'repo_summary', repo_name=self.db_repo_name) + else: + redirect_url = default_redirect_url + h.flash(_('No filename specified'), category='warning') raise HTTPFound(redirect_url) - # extract the location from filename, - # allows using foo/bar.txt syntax to create subdirectories - subdir_loc = filename.rsplit('/', 1) - if len(subdir_loc) == 2: - location = os.path.join(location, subdir_loc[0]) + root_path = f_path + pure_path = self.create_pure_path(root_path, filename) + node_path = safe_unicode(bytes(pure_path).lstrip('/')) - # strip all crap out of file, just leave the basename - filename = os.path.basename(filename) - node_path = os.path.join(location, filename) author = self._rhodecode_db_user.full_contact + nodes = { + node_path: { + 'content': content + } + } try: - nodes = { - node_path: { - 'content': content - } - } - ScmModel().create_nodes( + + commit = ScmModel().create_nodes( user=self._rhodecode_db_user.user_id, repo=self.db_repo, message=message, @@ -1377,14 +1375,16 @@ class RepoFilesView(RepoAppView): author=author, ) - h.flash( - _('Successfully committed new file `{}`').format( + h.flash(_('Successfully committed new file `{}`').format( h.escape(node_path)), category='success') + + default_redirect_url = h.route_path( + 'repo_commit', repo_name=self.db_repo_name, commit_id=commit.raw_id) + except NonRelativePathError: log.exception('Non Relative path found') - h.flash(_( - 'The location specified must be a relative path and must not ' - 'contain .. in the path'), category='warning') + h.flash(_('The location specified must be a relative path and must not ' + 'contain .. in the path'), category='warning') raise HTTPFound(default_redirect_url) except (NodeError, NodeAlreadyExistsError) as e: h.flash(_(h.escape(e)), category='error') @@ -1393,3 +1393,134 @@ class RepoFilesView(RepoAppView): h.flash(_('Error occurred during commit'), category='error') raise HTTPFound(default_redirect_url) + + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin') + @CSRFRequired() + @view_config( + route_name='repo_files_upload_file', request_method='POST', + renderer='json_ext') + def repo_files_upload_file(self): + _ = self.request.translate + c = self.load_default_context() + commit_id, f_path = self._get_commit_and_path() + + self._ensure_not_locked() + + c.commit = self._get_commit_or_redirect(commit_id, redirect_after=False) + if c.commit is None: + c.commit = EmptyCommit(alias=self.rhodecode_vcs_repo.alias) + + # calculate redirect URL + if self.rhodecode_vcs_repo.is_empty(): + default_redirect_url = h.route_path( + 'repo_summary', repo_name=self.db_repo_name) + else: + default_redirect_url = h.route_path( + 'repo_commit', repo_name=self.db_repo_name, commit_id='tip') + + if self.rhodecode_vcs_repo.is_empty(): + # for empty repository we cannot check for current branch, we rely on + # c.commit.branch instead + _branch_name, _sha_commit_id, is_head = c.commit.branch, '', True + else: + _branch_name, _sha_commit_id, is_head = \ + self._is_valid_head(commit_id, self.rhodecode_vcs_repo) + + error = self.forbid_non_head(is_head, f_path, json_mode=True) + if error: + return { + 'error': error, + 'redirect_url': default_redirect_url + } + error = self.check_branch_permission(_branch_name, json_mode=True) + if error: + return { + 'error': error, + 'redirect_url': default_redirect_url + } + + c.default_message = (_('Uploaded file via RhodeCode Enterprise')) + c.f_path = f_path + + r_post = self.request.POST + + message = c.default_message + user_message = r_post.getall('message') + if isinstance(user_message, list) and user_message: + # we take the first from duplicated results if it's not empty + message = user_message[0] if user_message[0] else message + + nodes = {} + + for file_obj in r_post.getall('files_upload') or []: + content = file_obj.file + filename = file_obj.filename + + root_path = f_path + pure_path = self.create_pure_path(root_path, filename) + node_path = safe_unicode(bytes(pure_path).lstrip('/')) + + nodes[node_path] = { + 'content': content + } + + if not nodes: + error = 'missing files' + return { + 'error': error, + 'redirect_url': default_redirect_url + } + + author = self._rhodecode_db_user.full_contact + + try: + commit = ScmModel().create_nodes( + user=self._rhodecode_db_user.user_id, + repo=self.db_repo, + message=message, + nodes=nodes, + parent_commit=c.commit, + author=author, + ) + if len(nodes) == 1: + flash_message = _('Successfully committed {} new files').format(len(nodes)) + else: + flash_message = _('Successfully committed 1 new file') + + h.flash(flash_message, category='success') + + default_redirect_url = h.route_path( + 'repo_commit', repo_name=self.db_repo_name, commit_id=commit.raw_id) + + except NonRelativePathError: + log.exception('Non Relative path found') + error = _('The location specified must be a relative path and must not ' + 'contain .. in the path') + h.flash(error, category='warning') + + return { + 'error': error, + 'redirect_url': default_redirect_url + } + except (NodeError, NodeAlreadyExistsError) as e: + error = h.escape(e) + h.flash(error, category='error') + + return { + 'error': error, + 'redirect_url': default_redirect_url + } + except Exception: + log.exception('Error occurred during commit') + error = _('Error occurred during commit') + h.flash(error, category='error') + return { + 'error': error, + 'redirect_url': default_redirect_url + } + + return { + 'error': None, + 'redirect_url': default_redirect_url + } diff --git a/rhodecode/apps/repository/views/repo_summary.py b/rhodecode/apps/repository/views/repo_summary.py --- a/rhodecode/apps/repository/views/repo_summary.py +++ b/rhodecode/apps/repository/views/repo_summary.py @@ -72,6 +72,7 @@ class RepoSummaryView(RepoAppView): log.debug("Searching for a README file.") readme_node = ReadmeFinder(_renderer_type).search(commit) if readme_node: + log.debug('Found README node: %s', readme_node) relative_urls = { 'raw': h.route_path( 'repo_file_raw', repo_name=_repo_name, @@ -82,7 +83,8 @@ class RepoSummaryView(RepoAppView): } readme_data = self._render_readme_or_none( commit, readme_node, relative_urls) - readme_filename = readme_node.path + readme_filename = readme_node.unicode_path + return readme_data, readme_filename inv_context_manager = rc_cache.InvalidationContext( @@ -152,6 +154,26 @@ class RepoSummaryView(RepoAppView): c.comments = self.db_repo.get_comments(page_ids) c.statuses = self.db_repo.statuses(page_ids) + def _prepare_and_set_clone_url(self, c): + username = '' + if self._rhodecode_user.username != User.DEFAULT_USER: + username = safe_str(self._rhodecode_user.username) + + _def_clone_uri = _def_clone_uri_id = c.clone_uri_tmpl + _def_clone_uri_ssh = c.clone_uri_ssh_tmpl + + if '{repo}' in _def_clone_uri: + _def_clone_uri_id = _def_clone_uri.replace('{repo}', '_{repoid}') + elif '{repoid}' in _def_clone_uri: + _def_clone_uri_id = _def_clone_uri.replace('_{repoid}', '{repo}') + + c.clone_repo_url = self.db_repo.clone_url( + user=username, uri_tmpl=_def_clone_uri) + c.clone_repo_url_id = self.db_repo.clone_url( + user=username, uri_tmpl=_def_clone_uri_id) + c.clone_repo_url_ssh = self.db_repo.clone_url( + uri_tmpl=_def_clone_uri_ssh, ssh=True) + @LoginRequired() @HasRepoPermissionAnyDecorator( 'repository.read', 'repository.write', 'repository.admin') @@ -160,6 +182,7 @@ class RepoSummaryView(RepoAppView): renderer='rhodecode:templates/summary/summary_commits.mako') def summary_commits(self): c = self.load_default_context() + self._prepare_and_set_clone_url(c) self._load_commits_context(c) return self._get_template_context(c) @@ -179,26 +202,11 @@ class RepoSummaryView(RepoAppView): c = self.load_default_context() # Prepare the clone URL - username = '' - if self._rhodecode_user.username != User.DEFAULT_USER: - username = safe_str(self._rhodecode_user.username) - - _def_clone_uri = _def_clone_uri_id = c.clone_uri_tmpl - _def_clone_uri_ssh = c.clone_uri_ssh_tmpl + self._prepare_and_set_clone_url(c) - if '{repo}' in _def_clone_uri: - _def_clone_uri_id = _def_clone_uri.replace( - '{repo}', '_{repoid}') - elif '{repoid}' in _def_clone_uri: - _def_clone_uri_id = _def_clone_uri.replace( - '_{repoid}', '{repo}') - - c.clone_repo_url = self.db_repo.clone_url( - user=username, uri_tmpl=_def_clone_uri) - c.clone_repo_url_id = self.db_repo.clone_url( - user=username, uri_tmpl=_def_clone_uri_id) - c.clone_repo_url_ssh = self.db_repo.clone_url( - uri_tmpl=_def_clone_uri_ssh, ssh=True) + # update every 5 min + if self.db_repo.last_commit_cache_update_diff > 60 * 5: + self.db_repo.update_commit_cache() # If enabled, get statistics data @@ -231,8 +239,6 @@ class RepoSummaryView(RepoAppView): c.enable_downloads = self.db_repo.enable_downloads c.repository_followers = scm_model.get_followers(self.db_repo) c.repository_forks = scm_model.get_forks(self.db_repo) - c.repository_is_user_following = scm_model.is_following_repo( - self.db_repo_name, self._rhodecode_user.user_id) # first interaction with the VCS instance after here... if c.repository_requirements_missing: @@ -317,8 +323,7 @@ class RepoSummaryView(RepoAppView): (_("Tag"), repo.tags, 'tag'), (_("Bookmark"), repo.bookmarks, 'book'), ] - res = self._create_reference_data( - repo, self.db_repo_name, refs_to_create) + res = self._create_reference_data(repo, self.db_repo_name, refs_to_create) data = { 'more': False, 'results': res @@ -365,8 +370,7 @@ class RepoSummaryView(RepoAppView): }) return result - def _create_reference_items(self, repo, full_repo_name, refs, ref_type, - format_ref_id): + def _create_reference_items(self, repo, full_repo_name, refs, ref_type, format_ref_id): result = [] is_svn = h.is_svn(repo) for ref_name, raw_id in refs.iteritems(): @@ -378,6 +382,7 @@ class RepoSummaryView(RepoAppView): 'raw_id': raw_id, 'type': ref_type, 'files_url': files_url, + 'idx': 0, }) return result diff --git a/rhodecode/apps/ssh_support/lib/backends/hg.py b/rhodecode/apps/ssh_support/lib/backends/hg.py --- a/rhodecode/apps/ssh_support/lib/backends/hg.py +++ b/rhodecode/apps/ssh_support/lib/backends/hg.py @@ -20,12 +20,13 @@ import os import sys -import shutil import logging import tempfile import textwrap - +import collections from .base import VcsServer +from rhodecode.model.db import RhodeCodeUi +from rhodecode.model.settings import VcsSettingsModel log = logging.getLogger(__name__) @@ -37,62 +38,46 @@ class MercurialTunnelWrapper(object): self.server = server self.stdin = sys.stdin self.stdout = sys.stdout - self.svn_conf_fd, self.svn_conf_path = tempfile.mkstemp() - self.hooks_env_fd, self.hooks_env_path = tempfile.mkstemp() + self.hooks_env_fd, self.hooks_env_path = tempfile.mkstemp(prefix='hgrc_rhodecode_') def create_hooks_env(self): + repo_name = self.server.repo_name + hg_flags = self.server.config_to_hgrc(repo_name) content = textwrap.dedent( ''' - # SSH hooks version=1.0.0 - [hooks] - pretxnchangegroup.ssh_auth=python:vcsserver.hooks.pre_push_ssh_auth - pretxnchangegroup.ssh=python:vcsserver.hooks.pre_push_ssh - changegroup.ssh=python:vcsserver.hooks.post_push_ssh - - preoutgoing.ssh=python:vcsserver.hooks.pre_pull_ssh - outgoing.ssh=python:vcsserver.hooks.post_pull_ssh + # RhodeCode SSH hooks version=2.0.0 + {custom} + ''' + ).format(custom='\n'.join(hg_flags)) - ''' - ) + root = self.server.get_root_store() + hgrc_custom = os.path.join(root, repo_name, '.hg', 'hgrc_rhodecode') + hgrc_main = os.path.join(root, repo_name, '.hg', 'hgrc') + # cleanup custom hgrc file + if os.path.isfile(hgrc_custom): + with open(hgrc_custom, 'wb') as f: + f.write('') + log.debug('Cleanup custom hgrc file under %s', hgrc_custom) + + # write temp with os.fdopen(self.hooks_env_fd, 'w') as hooks_env_file: hooks_env_file.write(content) - root = self.server.get_root_store() - hgrc_custom = os.path.join( - root, self.server.repo_name, '.hg', 'hgrc_rhodecode') - log.debug('Wrote custom hgrc file under %s', hgrc_custom) - shutil.move( - self.hooks_env_path, hgrc_custom) - - hgrc_main = os.path.join( - root, self.server.repo_name, '.hg', 'hgrc') - include_marker = '%include hgrc_rhodecode' + return self.hooks_env_path - if not os.path.isfile(hgrc_main): - os.mknod(hgrc_main) - - with open(hgrc_main, 'rb') as f: - data = f.read() - has_marker = include_marker in data + def remove_configs(self): + os.remove(self.hooks_env_path) - if not has_marker: - log.debug('Adding include marker for hooks') - with open(hgrc_main, 'wa') as f: - f.write(textwrap.dedent(''' - # added by RhodeCode - {} - '''.format(include_marker))) - - def command(self): + def command(self, hgrc_path): root = self.server.get_root_store() command = ( - "cd {root}; {hg_path} -R {root}{repo_name} " + "cd {root}; HGRCPATH={hgrc} {hg_path} -R {root}{repo_name} " "serve --stdio".format( root=root, hg_path=self.server.hg_path, - repo_name=self.server.repo_name)) + repo_name=self.server.repo_name, hgrc=hgrc_path)) log.debug("Final CMD: %s", command) return command @@ -102,22 +87,61 @@ class MercurialTunnelWrapper(object): action = '?' # permissions are check via `pre_push_ssh_auth` hook self.server.update_environment(action=action, extras=extras) - self.create_hooks_env() - return os.system(self.command()) + custom_hgrc_file = self.create_hooks_env() + + try: + return os.system(self.command(custom_hgrc_file)) + finally: + self.remove_configs() class MercurialServer(VcsServer): backend = 'hg' + cli_flags = ['phases', 'largefiles', 'extensions', 'experimental', 'hooks'] - def __init__(self, store, ini_path, repo_name, - user, user_permissions, config, env): - super(MercurialServer, self).\ - __init__(user, user_permissions, config, env) + def __init__(self, store, ini_path, repo_name, user, user_permissions, config, env): + super(MercurialServer, self).__init__(user, user_permissions, config, env) self.store = store self.ini_path = ini_path self.repo_name = repo_name - self._path = self.hg_path = config.get( - 'app:main', 'ssh.executable.hg') + self._path = self.hg_path = config.get('app:main', 'ssh.executable.hg') + self.tunnel = MercurialTunnelWrapper(server=self) + + def config_to_hgrc(self, repo_name): + ui_sections = collections.defaultdict(list) + ui = VcsSettingsModel(repo=repo_name).get_ui_settings(section=None, key=None) + + # write default hooks + default_hooks = [ + ('pretxnchangegroup.ssh_auth', 'python:vcsserver.hooks.pre_push_ssh_auth'), + ('pretxnchangegroup.ssh', 'python:vcsserver.hooks.pre_push_ssh'), + ('changegroup.ssh', 'python:vcsserver.hooks.post_push_ssh'), + + ('preoutgoing.ssh', 'python:vcsserver.hooks.pre_pull_ssh'), + ('outgoing.ssh', 'python:vcsserver.hooks.post_pull_ssh'), + ] + + for k, v in default_hooks: + ui_sections['hooks'].append((k, v)) - self.tunnel = MercurialTunnelWrapper(server=self) + for entry in ui: + if not entry.active: + continue + sec = entry.section + key = entry.key + + if sec in self.cli_flags: + # we want only custom hooks, so we skip builtins + if sec == 'hooks' and key in RhodeCodeUi.HOOKS_BUILTIN: + continue + + ui_sections[sec].append([key, entry.value]) + + flags = [] + for _sec, key_val in ui_sections.items(): + flags.append(' ') + flags.append('[{}]'.format(_sec)) + for key, val in key_val: + flags.append('{}= {}'.format(key, val)) + return flags diff --git a/rhodecode/apps/ssh_support/tests/test_server_hg.py b/rhodecode/apps/ssh_support/tests/test_server_hg.py --- a/rhodecode/apps/ssh_support/tests/test_server_hg.py +++ b/rhodecode/apps/ssh_support/tests/test_server_hg.py @@ -18,6 +18,7 @@ # RhodeCode Enterprise Edition, including its added features, Support services, # and proprietary license terms, please see https://rhodecode.com/licenses/ +import os import mock import pytest @@ -68,14 +69,16 @@ def hg_server(app): class TestMercurialServer(object): - def test_command(self, hg_server): + def test_command(self, hg_server, tmpdir): server = hg_server.create() + custom_hgrc = os.path.join(str(tmpdir), 'hgrc') expected_command = ( - 'cd {root}; {hg_path} -R {root}{repo_name} serve --stdio'.format( - root=hg_server.root, hg_path=hg_server.hg_path, + 'cd {root}; HGRCPATH={custom_hgrc} {hg_path} -R {root}{repo_name} serve --stdio'.format( + root=hg_server.root, custom_hgrc=custom_hgrc, hg_path=hg_server.hg_path, repo_name=hg_server.repo_name) ) - assert expected_command == server.tunnel.command() + server_command = server.tunnel.command(custom_hgrc) + assert expected_command == server_command @pytest.mark.parametrize('permissions, action, code', [ ({}, 'pull', -2), diff --git a/rhodecode/config/licenses.json b/rhodecode/config/licenses.json --- a/rhodecode/config/licenses.json +++ b/rhodecode/config/licenses.json @@ -28,23 +28,16 @@ { "license": [ { - "fullName": "BSD 4-clause \"Original\" or \"Old\" License", - "shortName": "bsdOriginal", - "spdxId": "BSD-4-Clause", - "url": "http://spdx.org/licenses/BSD-4-Clause.html" - } - ], - "name": "python2.7-coverage-3.7.1" - }, - { - "license": [ - { "fullName": "MIT License", "shortName": "mit", "spdxId": "MIT", "url": "http://spdx.org/licenses/MIT.html" } ], + "name": "python2.7-beautifulsoup4-4.6.3" + }, + { + "license": "UNKNOWN", "name": "python2.7-bootstrapped-pip-9.0.1" }, { @@ -56,29 +49,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-cov-core-1.15.0" - }, - { - "license": [ - { - "fullName": "MIT License", - "shortName": "mit", - "spdxId": "MIT", - "url": "http://spdx.org/licenses/MIT.html" - } - ], - "name": "python2.7-webtest-2.0.29" - }, - { - "license": [ - { - "fullName": "MIT License", - "shortName": "mit", - "spdxId": "MIT", - "url": "http://spdx.org/licenses/MIT.html" - } - ], - "name": "python2.7-beautifulsoup4-4.6.3" + "name": "python2.7-webtest-2.0.32" }, { "license": [ @@ -100,7 +71,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-webob-1.7.4" + "name": "python2.7-webob-1.8.4" }, { "license": [ @@ -116,6 +87,28 @@ { "license": [ { + "fullName": "Apache License 2.0", + "shortName": "asl20", + "spdxId": "Apache-2.0", + "url": "http://spdx.org/licenses/Apache-2.0.html" + } + ], + "name": "python2.7-coverage-4.5.1" + }, + { + "license": [ + { + "fullName": "MIT License", + "shortName": "mit", + "spdxId": "MIT", + "url": "http://spdx.org/licenses/MIT.html" + } + ], + "name": "python2.7-cov-core-1.15.0" + }, + { + "license": [ + { "fullName": "BSD 4-clause \"Original\" or \"Old\" License", "shortName": "bsdOriginal", "spdxId": "BSD-4-Clause", @@ -127,6 +120,17 @@ { "license": [ { + "fullName": "GNU Lesser General Public License v3 or later (LGPLv3+)" + }, + { + "fullName": "LGPL" + } + ], + "name": "python2.7-gprof2dot-2017.9.19" + }, + { + "license": [ + { "fullName": "MIT License", "shortName": "mit", "spdxId": "MIT", @@ -136,7 +140,7 @@ "fullName": "DFSG approved" } ], - "name": "python2.7-pytest-timeout-1.2.1" + "name": "python2.7-pytest-timeout-1.3.2" }, { "license": [ @@ -147,7 +151,32 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-pytest-3.6.0" + "name": "python2.7-pytest-3.8.2" + }, + { + "license": [ + { + "fullName": "MIT License", + "shortName": "mit", + "spdxId": "MIT", + "url": "http://spdx.org/licenses/MIT.html" + } + ], + "name": "python2.7-pathlib2-2.3.3" + }, + { + "license": [ + { + "fullName": "BSD 4-clause \"Original\" or \"Old\" License", + "shortName": "bsdOriginal", + "spdxId": "BSD-4-Clause", + "url": "http://spdx.org/licenses/BSD-4-Clause.html" + }, + { + "fullName": "New BSD License" + } + ], + "name": "python2.7-scandir-1.9.0" }, { "license": [ @@ -172,7 +201,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-pluggy-0.6.0" + "name": "python2.7-pluggy-0.9.0" }, { "license": [ @@ -183,7 +212,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-atomicwrites-1.1.5" + "name": "python2.7-atomicwrites-1.2.1" }, { "license": [ @@ -194,7 +223,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-more-itertools-4.3.0" + "name": "python2.7-more-itertools-5.0.0" }, { "license": [ @@ -205,7 +234,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-attrs-18.1.0" + "name": "python2.7-attrs-18.2.0" }, { "license": [ @@ -216,18 +245,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-py-1.5.3" - }, - { - "license": [ - { - "fullName": "GNU Lesser General Public License v3 or later (LGPLv3+)" - }, - { - "fullName": "LGPL" - } - ], - "name": "python2.7-gprof2dot-2017.9.19" + "name": "python2.7-py-1.6.0" }, { "license": [ @@ -254,17 +272,6 @@ { "license": [ { - "fullName": "MIT License", - "shortName": "mit", - "spdxId": "MIT", - "url": "http://spdx.org/licenses/MIT.html" - } - ], - "name": "python2.7-setuptools-scm-2.1.0" - }, - { - "license": [ - { "fullName": "BSD 4-clause \"Original\" or \"Old\" License", "shortName": "bsdOriginal", "spdxId": "BSD-4-Clause", @@ -299,7 +306,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-pytest-cov-2.5.1" + "name": "python2.7-pytest-cov-2.6.0" }, { "license": [ @@ -310,7 +317,7 @@ "url": "http://spdx.org/licenses/BSD-4-Clause.html" } ], - "name": "python2.7-appenlight-client-0.6.25" + "name": "python2.7-appenlight-client-0.6.26" }, { "license": [ @@ -326,10 +333,107 @@ { "license": [ { - "fullName": "AGPLv3 and Proprietary" + "fullName": "Apache 2.0 and Proprietary" + } + ], + "name": "python2.7-rhodecode-tools-1.2.1" + }, + { + "license": [ + { + "fullName": "Apache License 2.0", + "shortName": "asl20", + "spdxId": "Apache-2.0", + "url": "http://spdx.org/licenses/Apache-2.0.html" + } + ], + "name": "python2.7-elasticsearch1-dsl-0.0.12" + }, + { + "license": [ + { + "fullName": "Apache License 2.0", + "shortName": "asl20", + "spdxId": "Apache-2.0", + "url": "http://spdx.org/licenses/Apache-2.0.html" + } + ], + "name": "python2.7-elasticsearch1-1.10.0" + }, + { + "license": [ + { + "fullName": "MIT License", + "shortName": "mit", + "spdxId": "MIT", + "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-rhodecode-tools-0.16.0" + "name": "python2.7-urllib3-1.24.1" + }, + { + "license": [ + { + "fullName": "BSD 4-clause \"Original\" or \"Old\" License", + "shortName": "bsdOriginal", + "spdxId": "BSD-4-Clause", + "url": "http://spdx.org/licenses/BSD-4-Clause.html" + }, + { + "fullName": "Apache License 2.0", + "shortName": "asl20", + "spdxId": "Apache-2.0", + "url": "http://spdx.org/licenses/Apache-2.0.html" + }, + { + "fullName": "Dual License" + } + ], + "name": "python2.7-python-dateutil-2.8.0" + }, + { + "license": [ + { + "fullName": "Apache License 2.0", + "shortName": "asl20", + "spdxId": "Apache-2.0", + "url": "http://spdx.org/licenses/Apache-2.0.html" + } + ], + "name": "python2.7-elasticsearch2-2.5.0" + }, + { + "license": [ + { + "fullName": "Apache License 2.0", + "shortName": "asl20", + "spdxId": "Apache-2.0", + "url": "http://spdx.org/licenses/Apache-2.0.html" + } + ], + "name": "python2.7-elasticsearch-dsl-6.3.1" + }, + { + "license": [ + { + "fullName": "Python Software Foundation License version 2", + "shortName": "psfl", + "spdxId": "Python-2.0", + "url": "http://spdx.org/licenses/Python-2.0.html" + } + ], + "name": "python2.7-ipaddress-1.0.22" + }, + { + "license": [ + { + "fullName": "Apache License 2.0", + "shortName": "asl20", + "spdxId": "Apache-2.0", + "url": "http://spdx.org/licenses/Apache-2.0.html" + } + ], + "name": "python2.7-elasticsearch-6.3.1" }, { "license": [ @@ -351,66 +455,13 @@ { "license": [ { - "fullName": "MIT License", - "shortName": "mit", - "spdxId": "MIT", - "url": "http://spdx.org/licenses/MIT.html" - } - ], - "name": "python2.7-urllib3-1.21" - }, - { - "license": [ - { - "fullName": "Apache License 2.0", - "shortName": "asl20", - "spdxId": "Apache-2.0", - "url": "http://spdx.org/licenses/Apache-2.0.html" - } - ], - "name": "python2.7-elasticsearch-dsl-2.2.0" - }, - { - "license": [ - { - "fullName": "Apache License 2.0", - "shortName": "asl20", - "spdxId": "Apache-2.0", - "url": "http://spdx.org/licenses/Apache-2.0.html" - } - ], - "name": "python2.7-elasticsearch-2.3.0" - }, - { - "license": [ - { - "fullName": "BSD 4-clause \"Original\" or \"Old\" License", - "shortName": "bsdOriginal", - "spdxId": "BSD-4-Clause", - "url": "http://spdx.org/licenses/BSD-4-Clause.html" - }, - { - "fullName": "Apache License 2.0", - "shortName": "asl20", - "spdxId": "Apache-2.0", - "url": "http://spdx.org/licenses/Apache-2.0.html" - }, - { - "fullName": "Dual License" - } - ], - "name": "python2.7-python-dateutil-2.7.3" - }, - { - "license": [ - { "fullName": "BSD 4-clause \"Original\" or \"Old\" License", "shortName": "bsdOriginal", "spdxId": "BSD-4-Clause", "url": "http://spdx.org/licenses/BSD-4-Clause.html" } ], - "name": "python2.7-markupsafe-1.0" + "name": "python2.7-markupsafe-1.1.0" }, { "license": [ @@ -443,29 +494,7 @@ "url": "http://spdx.org/licenses/BSD-4-Clause.html" } ], - "name": "python2.7-click-6.6" - }, - { - "license": [ - { - "fullName": "MIT License", - "shortName": "mit", - "spdxId": "MIT", - "url": "http://spdx.org/licenses/MIT.html" - } - ], - "name": "python2.7-bottle-0.12.13" - }, - { - "license": [ - { - "fullName": "MIT License", - "shortName": "mit", - "spdxId": "MIT", - "url": "http://spdx.org/licenses/MIT.html" - } - ], - "name": "python2.7-cprofilev-1.0.7" + "name": "python2.7-click-7.0" }, { "license": [ @@ -519,31 +548,6 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-pathlib2-2.3.0" - }, - { - "license": [ - { - "fullName": "BSD 4-clause \"Original\" or \"Old\" License", - "shortName": "bsdOriginal", - "spdxId": "BSD-4-Clause", - "url": "http://spdx.org/licenses/BSD-4-Clause.html" - }, - { - "fullName": "New BSD License" - } - ], - "name": "python2.7-scandir-1.9.0" - }, - { - "license": [ - { - "fullName": "MIT License", - "shortName": "mit", - "spdxId": "MIT", - "url": "http://spdx.org/licenses/MIT.html" - } - ], "name": "python2.7-backports.shutil-get-terminal-size-1.0.0" }, { @@ -555,7 +559,7 @@ "url": "http://spdx.org/licenses/BSD-4-Clause.html" } ], - "name": "python2.7-pygments-2.2.0" + "name": "python2.7-pygments-2.3.1" }, { "license": [ @@ -646,7 +650,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-pickleshare-0.7.4" + "name": "python2.7-pickleshare-0.7.5" }, { "license": [ @@ -690,7 +694,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-greenlet-0.4.13" + "name": "python2.7-greenlet-0.4.15" }, { "license": [ @@ -701,7 +705,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-gevent-1.3.5" + "name": "python2.7-gevent-1.4.0" }, { "license": [ @@ -712,7 +716,7 @@ "url": "http://spdx.org/licenses/BSD-4-Clause.html" } ], - "name": "python2.7-psutil-5.4.6" + "name": "python2.7-psutil-5.5.1" }, { "license": [ @@ -745,7 +749,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-alembic-0.9.9" + "name": "python2.7-alembic-1.0.5" }, { "license": { @@ -754,7 +758,7 @@ "spdxId": "Apache-2.0", "url": "http://spdx.org/licenses/Apache-2.0.html" }, - "name": "python2.7-python-editor-1.0.3" + "name": "python2.7-python-editor-1.0.4" }, { "license": [ @@ -842,39 +846,6 @@ { "license": [ { - "fullName": "Apache License 2.0", - "shortName": "asl20", - "spdxId": "Apache-2.0", - "url": "http://spdx.org/licenses/Apache-2.0.html" - } - ], - "name": "python2.7-bleach-2.1.4" - }, - { - "license": [ - { - "fullName": "MIT License", - "shortName": "mit", - "spdxId": "MIT", - "url": "http://spdx.org/licenses/MIT.html" - } - ], - "name": "python2.7-html5lib-1.0.1" - }, - { - "license": [ - { - "fullName": "BSD 4-clause \"Original\" or \"Old\" License", - "shortName": "bsdOriginal", - "spdxId": "BSD-4-Clause", - "url": "http://spdx.org/licenses/BSD-4-Clause.html" - } - ], - "name": "python2.7-webencodings-0.5.1" - }, - { - "license": [ - { "fullName": "BSD 4-clause \"Original\" or \"Old\" License", "shortName": "bsdOriginal", "spdxId": "BSD-4-Clause", @@ -892,7 +863,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-testpath-0.3.1" + "name": "python2.7-testpath-0.4.2" }, { "license": [ @@ -908,6 +879,28 @@ { "license": [ { + "fullName": "Apache License 2.0", + "shortName": "asl20", + "spdxId": "Apache-2.0", + "url": "http://spdx.org/licenses/Apache-2.0.html" + } + ], + "name": "python2.7-bleach-3.1.0" + }, + { + "license": [ + { + "fullName": "BSD 4-clause \"Original\" or \"Old\" License", + "shortName": "bsdOriginal", + "spdxId": "BSD-4-Clause", + "url": "http://spdx.org/licenses/BSD-4-Clause.html" + } + ], + "name": "python2.7-webencodings-0.5.1" + }, + { + "license": [ + { "fullName": "MIT License", "shortName": "mit", "spdxId": "MIT", @@ -925,7 +918,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-configparser-3.5.0" + "name": "python2.7-configparser-3.7.3" }, { "license": [ @@ -947,7 +940,73 @@ "url": "http://spdx.org/licenses/BSD-4-Clause.html" } ], - "name": "python2.7-mistune-0.8.3" + "name": "python2.7-mistune-0.8.4" + }, + { + "license": { + "fullName": "GNU Lesser General Public License v3.0 or later", + "shortName": "lgpl3Plus", + "spdxId": "LGPL-3.0+", + "url": "http://spdx.org/licenses/LGPL-3.0+.html" + }, + "name": "python2.7-psycopg2-2.7.7" + }, + { + "license": { + "fullName": "PostgreSQL License", + "shortName": "postgresql", + "spdxId": "PostgreSQL", + "url": "http://spdx.org/licenses/PostgreSQL.html" + }, + "name": "postgresql-9.6.10" + }, + { + "license": [ + { + "fullName": "zlib License", + "shortName": "zlib", + "spdxId": "Zlib", + "url": "http://spdx.org/licenses/Zlib.html" + }, + { + "fullName": "libpng License", + "shortName": "libpng", + "spdxId": "Libpng", + "url": "http://spdx.org/licenses/Libpng.html" + } + ], + "name": "python2.7-pysqlite-2.8.3" + }, + { + "license": [ + { + "fullName": "MIT License", + "shortName": "mit", + "spdxId": "MIT", + "url": "http://spdx.org/licenses/MIT.html" + } + ], + "name": "python2.7-pymysql-0.8.1" + }, + { + "license": [ + { + "fullName": "GNU General Public License v1.0 only", + "shortName": "gpl1", + "spdxId": "GPL-1.0", + "url": "http://spdx.org/licenses/GPL-1.0.html" + } + ], + "name": "python2.7-mysql-python-1.2.5" + }, + { + "license": { + "fullName": "GNU Library General Public License v2.1 only", + "shortName": "lgpl21", + "spdxId": "LGPL-2.1", + "url": "http://spdx.org/licenses/LGPL-2.1.html" + }, + "name": "mariadb-connector-c-2.3.4" }, { "license": [ @@ -958,7 +1017,7 @@ "url": "http://spdx.org/licenses/ZPL-2.1.html" } ], - "name": "python2.7-zope.interface-4.5.0" + "name": "python2.7-zope.interface-4.6.0" }, { "license": [ @@ -969,7 +1028,7 @@ "url": "http://spdx.org/licenses/ZPL-2.1.html" } ], - "name": "python2.7-zope.event-4.3.0" + "name": "python2.7-zope.event-4.4" }, { "license": [ @@ -980,7 +1039,7 @@ "url": "http://spdx.org/licenses/ZPL-2.1.html" } ], - "name": "python2.7-zope.deprecation-4.3.0" + "name": "python2.7-zope.deprecation-4.4.0" }, { "license": [ @@ -1043,7 +1102,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-paste-2.0.3" + "name": "python2.7-paste-3.0.5" }, { "license": [ @@ -1061,7 +1120,7 @@ "fullName": "Repoze License", "url": "http://www.repoze.org/LICENSE.txt" }, - "name": "python2.7-venusian-1.1.0" + "name": "python2.7-venusian-1.2.0" }, { "license": { @@ -1072,17 +1131,6 @@ "name": "python2.7-urlobject-2.4.3" }, { - "license": [ - { - "fullName": "Apache License 2.0", - "shortName": "asl20", - "spdxId": "Apache-2.0", - "url": "http://spdx.org/licenses/Apache-2.0.html" - } - ], - "name": "python2.7-trollius-1.0.4" - }, - { "license": { "fullName": "Repoze License", "url": "http://www.repoze.org/LICENSE.txt" @@ -1095,7 +1143,7 @@ "fullName": "BSD-derived (http://www.repoze.org/LICENSE.txt)" } ], - "name": "python2.7-supervisor-3.3.4" + "name": "python2.7-supervisor-3.3.5" }, { "license": [ @@ -1114,7 +1162,7 @@ "url": "http://spdx.org/licenses/Python-2.0.html" } ], - "name": "python2.7-subprocess32-3.5.1" + "name": "python2.7-subprocess32-3.5.3" }, { "license": [ @@ -1125,7 +1173,7 @@ "url": "http://spdx.org/licenses/BSD-4-Clause.html" } ], - "name": "python2.7-sshpubkeys-2.2.0" + "name": "python2.7-sshpubkeys-3.1.0" }, { "license": [ @@ -1141,11 +1189,55 @@ { "license": [ { - "fullName": "Public Domain", - "shortName": "publicDomain" + "fullName": "BSD 4-clause \"Original\" or \"Old\" License", + "shortName": "bsdOriginal", + "spdxId": "BSD-4-Clause", + "url": "http://spdx.org/licenses/BSD-4-Clause.html" + }, + { + "fullName": "BSD or Apache License, Version 2.0" + }, + { + "fullName": "Apache License 2.0", + "shortName": "asl20", + "spdxId": "Apache-2.0", + "url": "http://spdx.org/licenses/Apache-2.0.html" } ], - "name": "python2.7-pycrypto-2.6.1" + "name": "python2.7-cryptography-2.5" + }, + { + "license": [ + { + "fullName": "MIT License", + "shortName": "mit", + "spdxId": "MIT", + "url": "http://spdx.org/licenses/MIT.html" + } + ], + "name": "python2.7-cffi-1.12.1" + }, + { + "license": [ + { + "fullName": "BSD 4-clause \"Original\" or \"Old\" License", + "shortName": "bsdOriginal", + "spdxId": "BSD-4-Clause", + "url": "http://spdx.org/licenses/BSD-4-Clause.html" + } + ], + "name": "python2.7-pycparser-2.19" + }, + { + "license": [ + { + "fullName": "MIT License", + "shortName": "mit", + "spdxId": "MIT", + "url": "http://spdx.org/licenses/MIT.html" + } + ], + "name": "python2.7-asn1crypto-0.24.0" }, { "license": [ @@ -1159,18 +1251,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-simplejson-3.11.1" - }, - { - "license": [ - { - "fullName": "BSD 4-clause \"Original\" or \"Old\" License", - "shortName": "bsdOriginal", - "spdxId": "BSD-4-Clause", - "url": "http://spdx.org/licenses/BSD-4-Clause.html" - } - ], - "name": "python2.7-setproctitle-1.1.10" + "name": "python2.7-simplejson-3.16.0" }, { "license": [ @@ -1210,7 +1291,7 @@ "url": "http://spdx.org/licenses/BSD-4-Clause.html" } ], - "name": "python2.7-py-gfm-0.1.3" + "name": "python2.7-py-gfm-0.1.4" }, { "license": [ @@ -1248,6 +1329,72 @@ { "license": [ { + "fullName": "MIT License", + "shortName": "mit", + "spdxId": "MIT", + "url": "http://spdx.org/licenses/MIT.html" + } + ], + "name": "python2.7-python-saml-2.4.2" + }, + { + "license": [ + { + "fullName": "Python Software Foundation License version 2", + "shortName": "psfl", + "spdxId": "Python-2.0", + "url": "http://spdx.org/licenses/Python-2.0.html" + } + ], + "name": "python2.7-defusedxml-0.5.0" + }, + { + "license": [ + { + "fullName": "BSD 4-clause \"Original\" or \"Old\" License", + "shortName": "bsdOriginal", + "spdxId": "BSD-4-Clause", + "url": "http://spdx.org/licenses/BSD-4-Clause.html" + } + ], + "name": "python2.7-isodate-0.6.0" + }, + { + "license": [ + { + "fullName": "BSD 4-clause \"Original\" or \"Old\" License", + "shortName": "bsdOriginal", + "spdxId": "BSD-4-Clause", + "url": "http://spdx.org/licenses/BSD-4-Clause.html" + } + ], + "name": "python2.7-dm.xmlsec.binding-1.3.7" + }, + { + "license": [ + { + "fullName": "BSD 4-clause \"Original\" or \"Old\" License", + "shortName": "bsdOriginal", + "spdxId": "BSD-4-Clause", + "url": "http://spdx.org/licenses/BSD-4-Clause.html" + } + ], + "name": "python2.7-lxml-4.2.5" + }, + { + "license": [ + { + "fullName": "MIT License", + "shortName": "mit", + "spdxId": "MIT", + "url": "http://spdx.org/licenses/MIT.html" + } + ], + "name": "python2.7-wheel-0.30.0" + }, + { + "license": [ + { "fullName": "License :: OSI Approved :: MIT License" }, { @@ -1260,14 +1407,7 @@ "name": "python2.7-python-pam-1.8.4" }, { - "license": [ - { - "fullName": "GNU General Public License v1.0 only", - "shortName": "gpl1", - "spdxId": "GPL-1.0", - "url": "http://spdx.org/licenses/GPL-1.0.html" - } - ], + "license": "UNKNOWN", "name": "linux-pam-1.3.0" }, { @@ -1302,9 +1442,7 @@ "name": "libkrb5-1.15.2" }, { - "license":{ - "fullName": "BSD-derived (https://www.openldap.org/software/release/license.html)" - }, + "license": "UNKNOWN", "name": "openldap-2.4.45" }, { @@ -1316,7 +1454,18 @@ "url": "http://spdx.org/licenses/BSD-4-Clause.html" } ], - "name": "python2.7-pyasn1-modules-0.2.2" + "name": "python2.7-pyasn1-modules-0.2.4" + }, + { + "license": [ + { + "fullName": "BSD 4-clause \"Original\" or \"Old\" License", + "shortName": "bsdOriginal", + "spdxId": "BSD-4-Clause", + "url": "http://spdx.org/licenses/BSD-4-Clause.html" + } + ], + "name": "python2.7-pyasn1-0.4.5" }, { "license": [ @@ -1327,42 +1476,36 @@ "url": "http://spdx.org/licenses/BSD-4-Clause.html" } ], - "name": "python2.7-pyasn1-0.4.4" + "name": "python2.7-pyramid-mailer-0.15.1" }, { "license": [ { - "fullName": "zlib License", - "shortName": "zlib", - "spdxId": "Zlib", - "url": "http://spdx.org/licenses/Zlib.html" - }, - { - "fullName": "libpng License", - "shortName": "libpng", - "spdxId": "Libpng", - "url": "http://spdx.org/licenses/Libpng.html" + "fullName": "Zope Public License 2.1", + "shortName": "zpl21", + "spdxId": "ZPL-2.1", + "url": "http://spdx.org/licenses/ZPL-2.1.html" } ], - "name": "python2.7-pysqlite-2.8.3" + "name": "python2.7-transaction-2.4.0" + }, + { + "license": [ + { + "fullName": "Zope Public License 2.1", + "shortName": "zpl21", + "spdxId": "ZPL-2.1", + "url": "http://spdx.org/licenses/ZPL-2.1.html" + } + ], + "name": "python2.7-repoze.sendmail-4.4.1" }, { "license": { "fullName": "Repoze License", "url": "http://www.repoze.org/LICENSE.txt" }, - "name": "python2.7-pyramid-1.9.2" - }, - { - "license": [ - { - "fullName": "MIT License", - "shortName": "mit", - "spdxId": "MIT", - "url": "http://spdx.org/licenses/MIT.html" - } - ], - "name": "python2.7-hupper-1.3" + "name": "python2.7-pyramid-1.10.1" }, { "license": [ @@ -1395,7 +1538,18 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-pastedeploy-1.5.2" + "name": "python2.7-pastedeploy-2.0.1" + }, + { + "license": [ + { + "fullName": "MIT License", + "shortName": "mit", + "spdxId": "MIT", + "url": "http://spdx.org/licenses/MIT.html" + } + ], + "name": "python2.7-hupper-1.5" }, { "license": { @@ -1428,18 +1582,7 @@ "url": "http://www.repoze.org/LICENSE.txt" } ], - "name": "python2.7-pyramid-debugtoolbar-4.4" - }, - { - "license": [ - { - "fullName": "Python Software Foundation License version 2", - "shortName": "psfl", - "spdxId": "Python-2.0", - "url": "http://spdx.org/licenses/Python-2.0.html" - } - ], - "name": "python2.7-ipaddress-1.0.22" + "name": "python2.7-pyramid-debugtoolbar-4.5" }, { "license": { @@ -1468,29 +1611,16 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-pyparsing-1.5.7" + "name": "python2.7-pyparsing-2.3.0" }, { "license": [ { - "fullName": "Apache License 2.0", - "shortName": "asl20", - "spdxId": "Apache-2.0", - "url": "http://spdx.org/licenses/Apache-2.0.html" + "fullName": "Public Domain", + "shortName": "publicDomain" } ], - "name": "python2.7-pygments-markdown-lexer-0.1.0.dev39" - }, - { - "license": [ - { - "fullName": "MIT License", - "shortName": "mit", - "spdxId": "MIT", - "url": "http://spdx.org/licenses/MIT.html" - } - ], - "name": "python2.7-pyflakes-0.8.1" + "name": "python2.7-pycrypto-2.6.1" }, { "license": { @@ -1513,30 +1643,12 @@ "name": "python2.7-py-bcrypt-0.4" }, { - "license": { - "fullName": "GNU Lesser General Public License v3.0 or later", - "shortName": "lgpl3Plus", - "spdxId": "LGPL-3.0+", - "url": "http://spdx.org/licenses/LGPL-3.0+.html" - }, - "name": "python2.7-psycopg2-2.7.4" - }, - { - "license": { - "fullName": "PostgreSQL License", - "shortName": "postgresql", - "spdxId": "PostgreSQL", - "url": "http://spdx.org/licenses/PostgreSQL.html" - }, - "name": "postgresql-9.6.10" - }, - { "license": [ { "fullName": "BSD-derived (http://www.repoze.org/LICENSE.txt)" } ], - "name": "python2.7-peppercorn-0.5" + "name": "python2.7-peppercorn-0.6" }, { "license": [ @@ -1547,7 +1659,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-pastescript-2.0.2" + "name": "python2.7-pastescript-3.0.0" }, { "license": [ @@ -1569,60 +1681,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-objgraph-3.1.1" - }, - { - "license": [ - { - "fullName": "MIT License", - "shortName": "mit", - "spdxId": "MIT", - "url": "http://spdx.org/licenses/MIT.html" - } - ], - "name": "python2.7-graphviz-0.9" - }, - { - "license": [ - { - "fullName": "BSD 4-clause \"Original\" or \"Old\" License", - "shortName": "bsdOriginal", - "spdxId": "BSD-4-Clause", - "url": "http://spdx.org/licenses/BSD-4-Clause.html" - } - ], - "name": "python2.7-pyotp-2.2.6" - }, - { - "license": [ - { - "fullName": "MIT License", - "shortName": "mit", - "spdxId": "MIT", - "url": "http://spdx.org/licenses/MIT.html" - } - ], - "name": "python2.7-pymysql-0.8.1" - }, - { - "license": [ - { - "fullName": "GNU General Public License v1.0 only", - "shortName": "gpl1", - "spdxId": "GPL-1.0", - "url": "http://spdx.org/licenses/GPL-1.0.html" - } - ], - "name": "python2.7-mysql-python-1.2.5" - }, - { - "license": { - "fullName": "GNU Library General Public License v2.1 only", - "shortName": "lgpl21", - "spdxId": "LGPL-2.1", - "url": "http://spdx.org/licenses/LGPL-2.1.html" - }, - "name": "mariadb-connector-c-2.3.4" + "name": "python2.7-pyotp-2.2.7" }, { "license": [ @@ -1644,29 +1703,7 @@ "url": "http://spdx.org/licenses/BSD-4-Clause.html" } ], - "name": "python2.7-lxml-3.7.3" - }, - { - "license": [ - { - "fullName": "MIT License", - "shortName": "mit", - "spdxId": "MIT", - "url": "http://spdx.org/licenses/MIT.html" - } - ], - "name": "python2.7-wheel-0.30.0" - }, - { - "license": [ - { - "fullName": "BSD 4-clause \"Original\" or \"Old\" License", - "shortName": "bsdOriginal", - "spdxId": "BSD-4-Clause", - "url": "http://spdx.org/licenses/BSD-4-Clause.html" - } - ], - "name": "python2.7-kombu-4.2.0" + "name": "python2.7-kombu-4.2.1" }, { "license": [ @@ -1688,18 +1725,7 @@ "url": "http://spdx.org/licenses/BSD-4-Clause.html" } ], - "name": "python2.7-vine-1.1.4" - }, - { - "license": [ - { - "fullName": "BSD 4-clause \"Original\" or \"Old\" License", - "shortName": "bsdOriginal", - "spdxId": "BSD-4-Clause", - "url": "http://spdx.org/licenses/BSD-4-Clause.html" - } - ], - "name": "python2.7-billiard-3.5.0.3" + "name": "python2.7-vine-1.2.0" }, { "license": [ @@ -1721,7 +1747,7 @@ "url": "http://spdx.org/licenses/MIT.html" } ], - "name": "python2.7-iso8601-0.1.11" + "name": "python2.7-iso8601-0.1.12" }, { "license": [ @@ -1765,7 +1791,7 @@ "url": "http://spdx.org/licenses/BSD-4-Clause.html" } ], - "name": "python2.7-dogpile.cache-0.6.6" + "name": "python2.7-dogpile.cache-0.7.1" }, { "license": { @@ -1779,17 +1805,20 @@ { "license": [ { + "fullName": "Repoze Public License" + }, + { "fullName": "BSD-derived (http://www.repoze.org/LICENSE.txt)" } ], - "name": "python2.7-deform-2.0.5" + "name": "python2.7-deform-2.0.7" }, { "license": { "fullName": "Repoze License", "url": "http://www.repoze.org/LICENSE.txt" }, - "name": "python2.7-colander-1.4" + "name": "python2.7-colander-1.7.0" }, { "license": [ @@ -1863,6 +1892,17 @@ "url": "http://spdx.org/licenses/BSD-4-Clause.html" } ], + "name": "python2.7-billiard-3.5.0.3" + }, + { + "license": [ + { + "fullName": "BSD 4-clause \"Original\" or \"Old\" License", + "shortName": "bsdOriginal", + "spdxId": "BSD-4-Clause", + "url": "http://spdx.org/licenses/BSD-4-Clause.html" + } + ], "name": "python2.7-babel-1.3" }, { @@ -1877,25 +1917,7 @@ "name": "python2.7-authomatic-0.1.0.post1" }, { - "license": [ - { - "fullName": "MIT License", - "shortName": "mit", - "spdxId": "MIT", - "url": "http://spdx.org/licenses/MIT.html" - } - ], - "name": "node-grunt-cli-1.2.0" - }, - { - "license": [ - { - "fullName": "MIT License", - "shortName": "mit", - "spdxId": "MIT", - "url": "http://spdx.org/licenses/MIT.html" - } - ], + "license": "UNKNOWN", "name": "python2.7-rhodecode-testdata-0.10.0" } ] diff --git a/rhodecode/config/middleware.py b/rhodecode/config/middleware.py --- a/rhodecode/config/middleware.py +++ b/rhodecode/config/middleware.py @@ -250,7 +250,7 @@ def includeme(config): # Includes which are required. The application would fail without them. config.include('pyramid_mako') - config.include('pyramid_beaker') + config.include('rhodecode.lib.rc_beaker') config.include('rhodecode.lib.rc_cache') config.include('rhodecode.apps._base.navigation') diff --git a/rhodecode/config/rcextensions/examples/validate_pushed_files_name_and_size.py b/rhodecode/config/rcextensions/examples/validate_pushed_files_name_and_size.py --- a/rhodecode/config/rcextensions/examples/validate_pushed_files_name_and_size.py +++ b/rhodecode/config/rcextensions/examples/validate_pushed_files_name_and_size.py @@ -28,8 +28,8 @@ def _pre_push_hook(*args, **kwargs): [{u'hg_env|git_env': ..., u'multiple_heads': [], u'name': u'default', - u'new_rev': u'd0befe0692e722e01d5677f27a104631cf798b69', - u'old_rev': u'd0befe0692e722e01d5677f27a104631cf798b69', + u'new_rev': u'd0b2ae0692e722e01d5677f27a104631cf798b69', + u'old_rev': u'd0b1ae0692e722e01d5677f27a104631cf798b69', u'ref': u'', u'total_commits': 2, u'type': u'branch'}] @@ -47,13 +47,17 @@ def _pre_push_hook(*args, **kwargs): forbid_files = repo_extra_fields.get('forbid_files_glob', {}).get('field_value') forbid_files = aslist(forbid_files) + # forbid_files = ['*'] # example pattern + # optionally get bytes limit for a single file, e.g 1024 for 1KB forbid_size_over = repo_extra_fields.get('forbid_size_over', {}).get('field_value') forbid_size_over = int(forbid_size_over or 0) + # forbid_size_over = 1024 # example 1024 + def validate_file_name_and_size(file_data, forbidden_files=None, size_limit=None): """ - This function validates commited files against some sort of rules. + This function validates comited files against some sort of rules. It should return a valid boolean, and a reason for failure file_data =[ @@ -87,7 +91,10 @@ def _pre_push_hook(*args, **kwargs): # validate A(dded) files and size if size_limit and operation == 'A': - size = len(file_data['raw_diff']) + if 'file_size' in file_data: + size = file_data['file_size'] + else: + size = len(file_data['raw_diff']) reason = 'File {} size of {} bytes exceeds limit {}'.format( file_name, format_byte_size_binary(size), diff --git a/rhodecode/config/rcextensions/helpers/extract_pre_files.py b/rhodecode/config/rcextensions/helpers/extract_pre_files.py --- a/rhodecode/config/rcextensions/helpers/extract_pre_files.py +++ b/rhodecode/config/rcextensions/helpers/extract_pre_files.py @@ -34,12 +34,51 @@ from rhodecode.lib.vcs.backends.hg.diff from rhodecode.lib.vcs.backends.git.diff import GitDiff -def get_hg_files(repo, refs): +def get_svn_files(repo, vcs_repo, refs): + txn_id = refs[0] + files = [] + stdout, stderr = vcs_repo.run_svn_command( + ['svnlook', 'changed', repo.repo_full_path, '--transaction', txn_id]) + + svn_op_to_rc_op = { + 'A': 'A', + 'U': 'M', + 'D': 'D', + } + + for entry in stdout.splitlines(): + parsed_entry = { + 'raw_diff': '', + 'filename': '', + 'chunks': [], + 'ops': {}, + 'file_size': 0 + } + + op = entry[0] + path = entry[1:].strip() + + rc_op = svn_op_to_rc_op.get(op) or '?' + parsed_entry['filename'] = path + parsed_entry['operation'] = rc_op + + if rc_op in ['A', 'M']: + stdout, stderr = vcs_repo.run_svn_command( + ['svnlook', 'filesize', repo.repo_full_path, path, '--transaction', txn_id]) + file_size = int(stdout.strip()) + parsed_entry['file_size'] = file_size + + files.append(parsed_entry) + + return files + + +def get_hg_files(repo, vcs_repo, refs): files = [] return files -def get_git_files(repo, refs): +def get_git_files(repo, vcs_repo, refs): files = [] for data in refs: @@ -57,7 +96,7 @@ def get_git_files(repo, refs): 'diff', old_rev, new_rev ] - stdout, stderr = repo.run_git_command(cmd, extra_env=git_env) + stdout, stderr = vcs_repo.run_git_command(cmd, extra_env=git_env) vcs_diff = GitDiff(stdout) diff_processor = diffs.DiffProcessor(vcs_diff, format='newdiff') @@ -86,11 +125,14 @@ def run(*args, **kwargs): if vcs_type == 'git': for rev_data in kwargs['commit_ids']: new_environ = dict((k, v) for k, v in rev_data['git_env']) - files = get_git_files(vcs_repo, kwargs['commit_ids']) + files = get_git_files(repo, vcs_repo, kwargs['commit_ids']) if vcs_type == 'hg': for rev_data in kwargs['commit_ids']: new_environ = dict((k, v) for k, v in rev_data['hg_env']) - files = get_hg_files(vcs_repo, kwargs['commit_ids']) + files = get_hg_files(repo, vcs_repo, kwargs['commit_ids']) + + if vcs_type == 'svn': + files = get_svn_files(repo, vcs_repo, kwargs['commit_ids']) return files diff --git a/rhodecode/integrations/views.py b/rhodecode/integrations/views.py --- a/rhodecode/integrations/views.py +++ b/rhodecode/integrations/views.py @@ -402,7 +402,8 @@ class RepoIntegrationsView(IntegrationSe c.rhodecode_db_repo = self.repo c.repo_name = self.db_repo.repo_name c.repository_pull_requests = ScmModel().get_pull_requests(self.repo) - + c.repository_is_user_following = ScmModel().is_following_repo( + c.repo_name, self._rhodecode_user.user_id) c.has_origin_repo_read_perm = False if self.db_repo.fork: c.has_origin_repo_read_perm = h.HasRepoPermissionAny( diff --git a/rhodecode/lib/audit_logger.py b/rhodecode/lib/audit_logger.py --- a/rhodecode/lib/audit_logger.py +++ b/rhodecode/lib/audit_logger.py @@ -92,6 +92,9 @@ ACTIONS_V1 = { 'repo.commit.comment.delete': {'data': {}}, 'repo.commit.vote': '', + 'repo.artifact.add': '', + 'repo.artifact.delete': '', + 'repo_group.create': {'data': {}}, 'repo_group.edit': {'old_data': {}}, 'repo_group.edit.permissions': {}, diff --git a/rhodecode/lib/auth.py b/rhodecode/lib/auth.py --- a/rhodecode/lib/auth.py +++ b/rhodecode/lib/auth.py @@ -2078,8 +2078,7 @@ class HasRepoPermissionAny(PermsFunction class HasRepoGroupPermissionAny(PermsFunction): def __call__(self, group_name=None, check_location='', user=None): self.repo_group_name = group_name - return super(HasRepoGroupPermissionAny, self).__call__( - check_location, user) + return super(HasRepoGroupPermissionAny, self).__call__(check_location, user) def check_permissions(self, user): perms = user.permissions @@ -2095,8 +2094,7 @@ class HasRepoGroupPermissionAny(PermsFun class HasRepoGroupPermissionAll(PermsFunction): def __call__(self, group_name=None, check_location='', user=None): self.repo_group_name = group_name - return super(HasRepoGroupPermissionAll, self).__call__( - check_location, user) + return super(HasRepoGroupPermissionAll, self).__call__(check_location, user) def check_permissions(self, user): perms = user.permissions @@ -2112,8 +2110,7 @@ class HasRepoGroupPermissionAll(PermsFun class HasUserGroupPermissionAny(PermsFunction): def __call__(self, user_group_name=None, check_location='', user=None): self.user_group_name = user_group_name - return super(HasUserGroupPermissionAny, self).__call__( - check_location, user) + return super(HasUserGroupPermissionAny, self).__call__(check_location, user) def check_permissions(self, user): perms = user.permissions @@ -2129,8 +2126,7 @@ class HasUserGroupPermissionAny(PermsFun class HasUserGroupPermissionAll(PermsFunction): def __call__(self, user_group_name=None, check_location='', user=None): self.user_group_name = user_group_name - return super(HasUserGroupPermissionAll, self).__call__( - check_location, user) + return super(HasUserGroupPermissionAll, self).__call__(check_location, user) def check_permissions(self, user): perms = user.permissions diff --git a/rhodecode/lib/base.py b/rhodecode/lib/base.py --- a/rhodecode/lib/base.py +++ b/rhodecode/lib/base.py @@ -288,7 +288,6 @@ def attach_context_attributes(context, r """ config = request.registry.settings - rc_config = SettingsModel().get_all_settings(cache=True) context.rhodecode_version = rhodecode.__version__ @@ -375,20 +374,25 @@ def attach_context_attributes(context, r "sideside": "sideside" }.get(request.GET.get('diffmode')) - if diffmode and diffmode != request.session.get('rc_user_session_attr.diffmode'): - request.session['rc_user_session_attr.diffmode'] = diffmode - - # session settings per user + is_api = hasattr(request, 'rpc_user') session_attrs = { # defaults "clone_url_format": "http", "diffmode": "sideside" } - for k, v in request.session.items(): - pref = 'rc_user_session_attr.' - if k and k.startswith(pref): - k = k[len(pref):] - session_attrs[k] = v + + if not is_api: + # don't access pyramid session for API calls + if diffmode and diffmode != request.session.get('rc_user_session_attr.diffmode'): + request.session['rc_user_session_attr.diffmode'] = diffmode + + # session settings per user + + for k, v in request.session.items(): + pref = 'rc_user_session_attr.' + if k and k.startswith(pref): + k = k[len(pref):] + session_attrs[k] = v context.user_session_attrs = session_attrs @@ -420,8 +424,12 @@ def attach_context_attributes(context, r 'extra': {'plugins': {}} } # END CONFIG VARS + if is_api: + csrf_token = None + else: + csrf_token = auth.get_csrf_token(session=request.session) - context.csrf_token = auth.get_csrf_token(session=request.session) + context.csrf_token = csrf_token context.backends = rhodecode.BACKENDS.keys() context.backends.sort() unread_count = 0 @@ -537,7 +545,7 @@ def bootstrap_config(request): # allow pyramid lookup in testing config.include('pyramid_mako') - config.include('pyramid_beaker') + config.include('rhodecode.lib.rc_beaker') config.include('rhodecode.lib.rc_cache') add_events_routes(config) diff --git a/rhodecode/lib/db_manage.py b/rhodecode/lib/db_manage.py --- a/rhodecode/lib/db_manage.py +++ b/rhodecode/lib/db_manage.py @@ -375,6 +375,27 @@ class DbManage(object): hgevolve.ui_active = False self.sa.add(hgevolve) + hgevolve = RhodeCodeUi() + hgevolve.ui_section = 'experimental' + hgevolve.ui_key = 'evolution' + hgevolve.ui_value = '' + hgevolve.ui_active = False + self.sa.add(hgevolve) + + hgevolve = RhodeCodeUi() + hgevolve.ui_section = 'experimental' + hgevolve.ui_key = 'evolution.exchange' + hgevolve.ui_value = '' + hgevolve.ui_active = False + self.sa.add(hgevolve) + + hgevolve = RhodeCodeUi() + hgevolve.ui_section = 'extensions' + hgevolve.ui_key = 'topic' + hgevolve.ui_value = '' + hgevolve.ui_active = False + self.sa.add(hgevolve) + # enable hggit disabled by default hggit = RhodeCodeUi() hggit.ui_section = 'extensions' @@ -464,9 +485,6 @@ class DbManage(object): self.populate_default_permissions() return fixed - def update_repo_info(self): - RepoModel.update_repoinfo() - def config_prompt(self, test_repo_path='', retries=3): defaults = self.cli_args _path = defaults.get('repos_location') diff --git a/rhodecode/lib/dbmigrate/schema/db_1_6_0.py b/rhodecode/lib/dbmigrate/schema/db_1_6_0.py --- a/rhodecode/lib/dbmigrate/schema/db_1_6_0.py +++ b/rhodecode/lib/dbmigrate/schema/db_1_6_0.py @@ -614,7 +614,7 @@ class Repository(Base, BaseModel): if (cs_cache != self.changeset_cache or not self.changeset_cache): _default = datetime.datetime.fromtimestamp(0) last_change = cs_cache.get('date') or _default - log.debug('updated repo %s with new cs cache %s', self.repo_name, cs_cache) + log.debug('updated repo %s with new commit cache %s', self.repo_name, cs_cache) self.updated_on = last_change self.changeset_cache = cs_cache Session().add(self) diff --git a/rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py b/rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py --- a/rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py +++ b/rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py @@ -38,8 +38,6 @@ from sqlalchemy.orm import relationship, from sqlalchemy.exc import OperationalError from beaker.cache import cache_region, region_invalidate from webob.exc import HTTPNotFound -from Crypto.Cipher import AES -from Crypto import Random from zope.cachedescriptors.property import Lazy as LazyProperty from rhodecode.translation import _ diff --git a/rhodecode/lib/dbmigrate/schema/db_4_11_0_0.py b/rhodecode/lib/dbmigrate/schema/db_4_11_0_0.py --- a/rhodecode/lib/dbmigrate/schema/db_4_11_0_0.py +++ b/rhodecode/lib/dbmigrate/schema/db_4_11_0_0.py @@ -2164,7 +2164,7 @@ class Repository(Base, BaseModel): if is_outdated(cs_cache) or not self.changeset_cache: _default = datetime.datetime.fromtimestamp(0) last_change = cs_cache.get('date') or _default - log.debug('updated repo %s with new cs cache %s', + log.debug('updated repo %s with new commit cache %s', self.repo_name, cs_cache) self.updated_on = last_change self.changeset_cache = cs_cache diff --git a/rhodecode/lib/dbmigrate/schema/db_4_13_0_0.py b/rhodecode/lib/dbmigrate/schema/db_4_13_0_0.py --- a/rhodecode/lib/dbmigrate/schema/db_4_13_0_0.py +++ b/rhodecode/lib/dbmigrate/schema/db_4_13_0_0.py @@ -2230,7 +2230,7 @@ class Repository(Base, BaseModel): if is_outdated(cs_cache) or not self.changeset_cache: _default = datetime.datetime.fromtimestamp(0) last_change = cs_cache.get('date') or _default - log.debug('updated repo %s with new cs cache %s', + log.debug('updated repo %s with new commit cache %s', self.repo_name, cs_cache) self.updated_on = last_change self.changeset_cache = cs_cache diff --git a/rhodecode/lib/dbmigrate/schema/db_4_16_0_0.py b/rhodecode/lib/dbmigrate/schema/db_4_16_0_0.py --- a/rhodecode/lib/dbmigrate/schema/db_4_16_0_0.py +++ b/rhodecode/lib/dbmigrate/schema/db_4_16_0_0.py @@ -2278,7 +2278,7 @@ class Repository(Base, BaseModel): # if yes, we use the current timestamp instead. Imagine you get # old commit pushed 1y ago, we'd set last update 1y to ago. last_change = _default - log.debug('updated repo %s with new cs cache %s', + log.debug('updated repo %s with new commit cache %s', self.repo_name, cs_cache) self.updated_on = last_change self.changeset_cache = cs_cache diff --git a/rhodecode/lib/dbmigrate/schema/db_4_16_0_1.py b/rhodecode/lib/dbmigrate/schema/db_4_16_0_1.py --- a/rhodecode/lib/dbmigrate/schema/db_4_16_0_1.py +++ b/rhodecode/lib/dbmigrate/schema/db_4_16_0_1.py @@ -2301,7 +2301,7 @@ class Repository(Base, BaseModel): # if yes, we use the current timestamp instead. Imagine you get # old commit pushed 1y ago, we'd set last update 1y to ago. last_change = _default - log.debug('updated repo %s with new cs cache %s', + log.debug('updated repo %s with new commit cache %s', self.repo_name, cs_cache) self.updated_on = last_change self.changeset_cache = cs_cache diff --git a/rhodecode/lib/dbmigrate/schema/db_4_16_0_2.py b/rhodecode/lib/dbmigrate/schema/db_4_16_0_2.py --- a/rhodecode/lib/dbmigrate/schema/db_4_16_0_2.py +++ b/rhodecode/lib/dbmigrate/schema/db_4_16_0_2.py @@ -2301,7 +2301,7 @@ class Repository(Base, BaseModel): # if yes, we use the current timestamp instead. Imagine you get # old commit pushed 1y ago, we'd set last update 1y to ago. last_change = _default - log.debug('updated repo %s with new cs cache %s', + log.debug('updated repo %s with new commit cache %s', self.repo_name, cs_cache) self.updated_on = last_change self.changeset_cache = cs_cache diff --git a/rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py b/rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py --- a/rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py +++ b/rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py @@ -1865,7 +1865,7 @@ class Repository(Base, BaseModel): if is_outdated(cs_cache) or not self.changeset_cache: _default = datetime.datetime.fromtimestamp(0) last_change = cs_cache.get('date') or _default - log.debug('updated repo %s with new cs cache %s', + log.debug('updated repo %s with new commit cache %s', self.repo_name, cs_cache) self.updated_on = last_change self.changeset_cache = cs_cache diff --git a/rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py b/rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py --- a/rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py +++ b/rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py @@ -1868,7 +1868,7 @@ class Repository(Base, BaseModel): if is_outdated(cs_cache) or not self.changeset_cache: _default = datetime.datetime.fromtimestamp(0) last_change = cs_cache.get('date') or _default - log.debug('updated repo %s with new cs cache %s', + log.debug('updated repo %s with new commit cache %s', self.repo_name, cs_cache) self.updated_on = last_change self.changeset_cache = cs_cache diff --git a/rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py b/rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py --- a/rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py +++ b/rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py @@ -1867,7 +1867,7 @@ class Repository(Base, BaseModel): if is_outdated(cs_cache) or not self.changeset_cache: _default = datetime.datetime.fromtimestamp(0) last_change = cs_cache.get('date') or _default - log.debug('updated repo %s with new cs cache %s', + log.debug('updated repo %s with new commit cache %s', self.repo_name, cs_cache) self.updated_on = last_change self.changeset_cache = cs_cache diff --git a/rhodecode/lib/dbmigrate/schema/db_4_4_0_2.py b/rhodecode/lib/dbmigrate/schema/db_4_4_0_2.py --- a/rhodecode/lib/dbmigrate/schema/db_4_4_0_2.py +++ b/rhodecode/lib/dbmigrate/schema/db_4_4_0_2.py @@ -1869,7 +1869,7 @@ class Repository(Base, BaseModel): if is_outdated(cs_cache) or not self.changeset_cache: _default = datetime.datetime.fromtimestamp(0) last_change = cs_cache.get('date') or _default - log.debug('updated repo %s with new cs cache %s', + log.debug('updated repo %s with new commit cache %s', self.repo_name, cs_cache) self.updated_on = last_change self.changeset_cache = cs_cache diff --git a/rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py b/rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py --- a/rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py +++ b/rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py @@ -1869,7 +1869,7 @@ class Repository(Base, BaseModel): if is_outdated(cs_cache) or not self.changeset_cache: _default = datetime.datetime.fromtimestamp(0) last_change = cs_cache.get('date') or _default - log.debug('updated repo %s with new cs cache %s', + log.debug('updated repo %s with new commit cache %s', self.repo_name, cs_cache) self.updated_on = last_change self.changeset_cache = cs_cache diff --git a/rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py b/rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py --- a/rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py +++ b/rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py @@ -1912,7 +1912,7 @@ class Repository(Base, BaseModel): if is_outdated(cs_cache) or not self.changeset_cache: _default = datetime.datetime.fromtimestamp(0) last_change = cs_cache.get('date') or _default - log.debug('updated repo %s with new cs cache %s', + log.debug('updated repo %s with new commit cache %s', self.repo_name, cs_cache) self.updated_on = last_change self.changeset_cache = cs_cache diff --git a/rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py b/rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py --- a/rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py +++ b/rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py @@ -1913,7 +1913,7 @@ class Repository(Base, BaseModel): if is_outdated(cs_cache) or not self.changeset_cache: _default = datetime.datetime.fromtimestamp(0) last_change = cs_cache.get('date') or _default - log.debug('updated repo %s with new cs cache %s', + log.debug('updated repo %s with new commit cache %s', self.repo_name, cs_cache) self.updated_on = last_change self.changeset_cache = cs_cache diff --git a/rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py b/rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py --- a/rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py +++ b/rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py @@ -2100,7 +2100,7 @@ class Repository(Base, BaseModel): if is_outdated(cs_cache) or not self.changeset_cache: _default = datetime.datetime.fromtimestamp(0) last_change = cs_cache.get('date') or _default - log.debug('updated repo %s with new cs cache %s', + log.debug('updated repo %s with new commit cache %s', self.repo_name, cs_cache) self.updated_on = last_change self.changeset_cache = cs_cache diff --git a/rhodecode/lib/dbmigrate/versions/096_version_4_17_0.py b/rhodecode/lib/dbmigrate/versions/096_version_4_17_0.py new file mode 100644 --- /dev/null +++ b/rhodecode/lib/dbmigrate/versions/096_version_4_17_0.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- + +import logging + +from alembic.migration import MigrationContext +from alembic.operations import Operations +from sqlalchemy import String, Column +from sqlalchemy.sql import text + +from rhodecode.lib.dbmigrate.versions import _reset_base +from rhodecode.lib.utils2 import safe_str +from rhodecode.model import meta, init_model_encryption +from rhodecode.model.db import RepoGroup + + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from rhodecode.lib.dbmigrate.schema import db_4_16_0_2 + + init_model_encryption(db_4_16_0_2) + + context = MigrationContext.configure(migrate_engine.connect()) + op = Operations(context) + + repo_group = db_4_16_0_2.RepoGroup.__table__ + + with op.batch_alter_table(repo_group.name) as batch_op: + batch_op.add_column( + Column("repo_group_name_hash", String(1024), nullable=True, unique=False)) + + _generate_repo_group_name_hashes(db_4_16_0_2, op, meta.Session) + + +def downgrade(migrate_engine): + pass + + +def _generate_repo_group_name_hashes(models, op, session): + repo_groups = models.RepoGroup.get_all() + for repo_group in repo_groups: + print(safe_str(repo_group.group_name)) + hash_ = RepoGroup.hash_repo_group_name(repo_group.group_name) + params = {'hash': hash_, 'id': repo_group.group_id} + query = text( + 'UPDATE groups SET repo_group_name_hash = :hash' + ' WHERE group_id = :id').bindparams(**params) + op.execute(query) + session().commit() diff --git a/rhodecode/lib/dbmigrate/versions/097_version_4_17_0.py b/rhodecode/lib/dbmigrate/versions/097_version_4_17_0.py new file mode 100644 --- /dev/null +++ b/rhodecode/lib/dbmigrate/versions/097_version_4_17_0.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- + +import logging + +from alembic.migration import MigrationContext +from alembic.operations import Operations + +from rhodecode.lib.dbmigrate.versions import _reset_base +from rhodecode.model import init_model_encryption + + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from rhodecode.lib.dbmigrate.schema import db_4_16_0_2 + + init_model_encryption(db_4_16_0_2) + + context = MigrationContext.configure(migrate_engine.connect()) + op = Operations(context) + + repo_group = db_4_16_0_2.RepoGroup.__table__ + + with op.batch_alter_table(repo_group.name) as batch_op: + batch_op.alter_column("repo_group_name_hash", nullable=False) + + +def downgrade(migrate_engine): + pass diff --git a/rhodecode/lib/dbmigrate/versions/098_version_4_17_0.py b/rhodecode/lib/dbmigrate/versions/098_version_4_17_0.py new file mode 100644 --- /dev/null +++ b/rhodecode/lib/dbmigrate/versions/098_version_4_17_0.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- + +import logging + +from alembic.migration import MigrationContext +from alembic.operations import Operations +from sqlalchemy import Column, LargeBinary + +from rhodecode.lib.dbmigrate.versions import _reset_base +from rhodecode.model import init_model_encryption + + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from rhodecode.lib.dbmigrate.schema import db_4_16_0_2 + + init_model_encryption(db_4_16_0_2) + + context = MigrationContext.configure(migrate_engine.connect()) + op = Operations(context) + + repo_group = db_4_16_0_2.RepoGroup.__table__ + + with op.batch_alter_table(repo_group.name) as batch_op: + batch_op.add_column( + Column("changeset_cache", LargeBinary(1024), nullable=True)) + + +def downgrade(migrate_engine): + pass diff --git a/rhodecode/lib/encrypt.py b/rhodecode/lib/encrypt.py --- a/rhodecode/lib/encrypt.py +++ b/rhodecode/lib/encrypt.py @@ -111,4 +111,28 @@ class AESCipher(object): @staticmethod def _unpad(s): - return s[:-ord(s[len(s)-1:])] \ No newline at end of file + return s[:-ord(s[len(s)-1:])] + + +def validate_and_get_enc_data(enc_data, enc_key, enc_strict_mode): + parts = enc_data.split('$', 3) + if not len(parts) == 3: + # probably not encrypted values + return enc_data + else: + if parts[0] != 'enc': + # parts ok but without our header ? + return enc_data + + # at that stage we know it's our encryption + if parts[1] == 'aes': + decrypted_data = AESCipher(enc_key).decrypt(parts[2]) + elif parts[1] == 'aes_hmac': + decrypted_data = AESCipher( + enc_key, hmac=True, + strict_verification=enc_strict_mode).decrypt(parts[2]) + else: + raise ValueError( + 'Encryption type part is wrong, must be `aes` ' + 'or `aes_hmac`, got `%s` instead' % (parts[1])) + return decrypted_data diff --git a/rhodecode/lib/encrypt2.py b/rhodecode/lib/encrypt2.py new file mode 100644 --- /dev/null +++ b/rhodecode/lib/encrypt2.py @@ -0,0 +1,69 @@ +import os +import base64 +from cryptography.fernet import Fernet, InvalidToken +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC + + +class Encryptor(object): + key_format = 'enc2$salt:{}$data:{}' + pref_len = 5 # salt:, data: + + def __init__(self, enc_key): + self.enc_key = enc_key + + def b64_encode(self, data): + return base64.urlsafe_b64encode(data) + + def b64_decode(self, data): + return base64.urlsafe_b64decode(data) + + def get_encryptor(self, salt): + """ + Uses Fernet as encryptor with HMAC signature + :param salt: random salt used for encrypting the data + """ + kdf = PBKDF2HMAC( + algorithm=hashes.SHA512(), + length=32, + salt=salt, + iterations=100000, + backend=default_backend() + ) + key = self.b64_encode(kdf.derive(self.enc_key)) + return Fernet(key) + + def _get_parts(self, enc_data): + parts = enc_data.split('$', 3) + if len(parts) != 3: + raise ValueError('Encrypted Data has invalid format, expected {}'.format(self.key_format)) + prefix, salt, enc_data = parts + + try: + salt = self.b64_decode(salt[self.pref_len:]) + except TypeError: + # bad base64 + raise ValueError('Encrypted Data salt invalid format, expected base64 format') + + enc_data = enc_data[self.pref_len:] + return prefix, salt, enc_data + + def encrypt(self, data): + salt = os.urandom(64) + encryptor = self.get_encryptor(salt) + enc_data = encryptor.encrypt(data) + return self.key_format.format(self.b64_encode(salt), enc_data) + + def decrypt(self, data, safe=True): + parts = self._get_parts(data) + salt = parts[1] + enc_data = parts[2] + encryptor = self.get_encryptor(salt) + try: + return encryptor.decrypt(enc_data) + except (InvalidToken,): + if safe: + return '' + else: + raise diff --git a/rhodecode/lib/helpers.py b/rhodecode/lib/helpers.py --- a/rhodecode/lib/helpers.py +++ b/rhodecode/lib/helpers.py @@ -199,6 +199,7 @@ class _GetError(object): if form_errors and field_name in form_errors: return literal(tmpl % form_errors.get(field_name)) + get_error = _GetError() @@ -214,38 +215,45 @@ class _ToolTip(object): tooltip_title = escape(tooltip_title) tooltip_title = tooltip_title.replace('<', '<').replace('>', '>') return tooltip_title + + tooltip = _ToolTip() +files_icon = u'' -def files_breadcrumbs(repo_name, commit_id, file_path): + +def files_breadcrumbs(repo_name, commit_id, file_path, at_ref=None, limit_items=False, linkify_last_item=False): if isinstance(file_path, str): file_path = safe_unicode(file_path) - # TODO: johbo: Is this always a url like path, or is this operating - # system dependent? - path_segments = file_path.split('/') + route_qry = {'at': at_ref} if at_ref else None - repo_name_html = escape(repo_name) - if len(path_segments) == 1 and path_segments[0] == '': - url_segments = [repo_name_html] - else: - url_segments = [ - link_to( - repo_name_html, - route_path( - 'repo_files', - repo_name=repo_name, - commit_id=commit_id, - f_path=''), - class_='pjax-link')] + # first segment is a `..` link to repo files + root_name = literal(u'') + url_segments = [ + link_to( + root_name, + route_path( + 'repo_files', + repo_name=repo_name, + commit_id=commit_id, + f_path='', + _query=route_qry), + )] + path_segments = file_path.split('/') last_cnt = len(path_segments) - 1 for cnt, segment in enumerate(path_segments): if not segment: continue segment_html = escape(segment) - if cnt != last_cnt: + last_item = cnt == last_cnt + + if last_item and linkify_last_item is False: + # plain version + url_segments.append(segment_html) + else: url_segments.append( link_to( segment_html, @@ -253,12 +261,32 @@ def files_breadcrumbs(repo_name, commit_ 'repo_files', repo_name=repo_name, commit_id=commit_id, - f_path='/'.join(path_segments[:cnt + 1])), - class_='pjax-link')) - else: - url_segments.append(segment_html) + f_path='/'.join(path_segments[:cnt + 1]), + _query=route_qry), + )) + + limited_url_segments = url_segments[:1] + ['...'] + url_segments[-5:] + if limit_items and len(limited_url_segments) < len(url_segments): + url_segments = limited_url_segments - return literal('/'.join(url_segments)) + full_path = file_path + icon = files_icon.format(escape(full_path)) + if file_path == '': + return root_name + else: + return literal(' / '.join(url_segments) + icon) + + +def files_url_data(request): + matchdict = request.matchdict + + if 'f_path' not in matchdict: + matchdict['f_path'] = '' + + if 'commit_id' not in matchdict: + matchdict['commit_id'] = 'tip' + + return json.dumps(matchdict) def code_highlight(code, lexer, formatter, use_hl_filter=False): @@ -1196,7 +1224,7 @@ class InitialsGravatar(object): """.format( size=self.size, - f_size=self.size/1.85, # scale the text inside the box nicely + f_size=self.size/2.05, # scale the text inside the box nicely background=self.background, text_color=self.text_color, text=initials.upper(), @@ -1486,10 +1514,12 @@ def breadcrumb_repo_link(repo): """ path = [ - link_to(group.name, route_path('repo_group_home', repo_group_name=group.group_name)) + link_to(group.name, route_path('repo_group_home', repo_group_name=group.group_name), + title='last change:{}'.format(format_date(group.last_commit_change))) for group in repo.groups_with_parents ] + [ - link_to(repo.just_name, route_path('repo_summary', repo_name=repo.repo_name)) + link_to(repo.just_name, route_path('repo_summary', repo_name=repo.repo_name), + title='last change:{}'.format(format_date(repo.last_commit_change))) ] return literal(' » '.join(path)) @@ -1507,11 +1537,13 @@ def breadcrumb_repo_group_link(repo_grou path = [ link_to(group.name, - route_path('repo_group_home', repo_group_name=group.group_name)) + route_path('repo_group_home', repo_group_name=group.group_name), + title='last change:{}'.format(format_date(group.last_commit_change))) for group in repo_group.parents ] + [ link_to(repo_group.name, - route_path('repo_group_home', repo_group_name=repo_group.group_name)) + route_path('repo_group_home', repo_group_name=repo_group.group_name), + title='last change:{}'.format(format_date(repo_group.last_commit_change))) ] return literal(' » '.join(path)) @@ -1907,23 +1939,26 @@ def secure_form(form_url, method="POST", def dropdownmenu(name, selected, options, enable_filter=False, **attrs): select_html = select(name, selected, options, **attrs) + select2 = """ """ + filter_option = """, minimumResultsForSearch: -1 """ input_id = attrs.get('id') or name + extra_classes = ' '.join(attrs.pop('extra_classes', [])) filter_enabled = "" if enable_filter else filter_option - select_script = literal(select2 % (input_id, filter_enabled)) + select_script = literal(select2 % (input_id, extra_classes, filter_enabled)) return literal(select_html+select_script) @@ -1944,7 +1979,7 @@ def get_visual_attr(tmpl_context_var, at def get_last_path_part(file_node): if not file_node.path: - return u'' + return u'/' path = safe_unicode(file_node.path.split('/')[-1]) return u'../' + path @@ -2033,10 +2068,11 @@ def reviewer_as_json(*args, **kwargs): def get_repo_view_type(request): route_name = request.matched_route.name route_to_view_type = { - 'repo_changelog': 'changelog', + 'repo_changelog': 'commits', + 'repo_commits': 'commits', 'repo_files': 'files', 'repo_summary': 'summary', 'repo_commit': 'commit' + } - } return route_to_view_type.get(route_name) diff --git a/rhodecode/lib/hooks_utils.py b/rhodecode/lib/hooks_utils.py --- a/rhodecode/lib/hooks_utils.py +++ b/rhodecode/lib/hooks_utils.py @@ -80,7 +80,7 @@ def trigger_log_create_pull_request_hook extras = _get_rc_scm_extras(username, repo_name, repo_alias, 'create_pull_request') events.trigger(events.PullRequestCreateEvent(pull_request)) - extras.update(pull_request.get_api_data()) + extras.update(pull_request.get_api_data(with_merge_state=False)) hooks_base.log_create_pull_request(**extras) diff --git a/rhodecode/lib/index/__init__.py b/rhodecode/lib/index/__init__.py --- a/rhodecode/lib/index/__init__.py +++ b/rhodecode/lib/index/__init__.py @@ -80,6 +80,13 @@ class BaseSearcher(object): def extract_search_tags(query): return [] + @staticmethod + def escape_specials(val): + """ + Handle and escape reserved chars for search + """ + return val + def search_config(config, prefix='search.'): _config = {} diff --git a/rhodecode/lib/markdown_ext.py b/rhodecode/lib/markdown_ext.py --- a/rhodecode/lib/markdown_ext.py +++ b/rhodecode/lib/markdown_ext.py @@ -20,7 +20,55 @@ import markdown -from mdx_gfm import GithubFlavoredMarkdownExtension # pragma: no cover +from markdown.extensions import Extension +from markdown.extensions.fenced_code import FencedCodeExtension +from markdown.extensions.smart_strong import SmartEmphasisExtension +from markdown.extensions.tables import TableExtension +from markdown.extensions.nl2br import Nl2BrExtension + +import gfm + + +class GithubFlavoredMarkdownExtension(Extension): + """ + An extension that is as compatible as possible with GitHub-flavored + Markdown (GFM). + + This extension aims to be compatible with the variant of GFM that GitHub + uses for Markdown-formatted gists and files (including READMEs). This + variant seems to have all the extensions described in the `GFM + documentation`_, except: + + - Newlines in paragraphs are not transformed into ``br`` tags. + - Intra-GitHub links to commits, repositories, and issues are not + supported. + + If you need support for features specific to GitHub comments and issues, + please use :class:`mdx_gfm.GithubFlavoredMarkdownExtension`. + + .. _GFM documentation: https://guides.github.com/features/mastering-markdown/ + """ + + def extendMarkdown(self, md, md_globals): + # Built-in extensions + FencedCodeExtension().extendMarkdown(md, md_globals) + SmartEmphasisExtension().extendMarkdown(md, md_globals) + TableExtension().extendMarkdown(md, md_globals) + + # Custom extensions + gfm.AutolinkExtension().extendMarkdown(md, md_globals) + gfm.AutomailExtension().extendMarkdown(md, md_globals) + gfm.HiddenHiliteExtension([ + ('guess_lang', 'False'), + ('css_class', 'highlight') + ]).extendMarkdown(md, md_globals) + gfm.SemiSaneListExtension().extendMarkdown(md, md_globals) + gfm.SpacedLinkExtension().extendMarkdown(md, md_globals) + gfm.StrikethroughExtension().extendMarkdown(md, md_globals) + gfm.TaskListExtension([ + ('list_attrs', {'class': 'checkbox'}) + ]).extendMarkdown(md, md_globals) + Nl2BrExtension().extendMarkdown(md, md_globals) # Global Vars diff --git a/rhodecode/lib/markup_renderer.py b/rhodecode/lib/markup_renderer.py --- a/rhodecode/lib/markup_renderer.py +++ b/rhodecode/lib/markup_renderer.py @@ -500,38 +500,38 @@ class MarkupRenderer(object): (body, resources) = html_exporter.from_notebook_node(notebook) header = '' js = MakoTemplate(r''' - - - - - + + + + ''').render(h=helpers) - css = ''.format( - ''.join(_sanitize_resources(resources['inlining']['css']))) + css = MakoTemplate(r''' + + ''').render(h=helpers, ver='ver1') body = '\n'.join([header, css, js, body]) return body, resources diff --git a/rhodecode/lib/middleware/simplegit.py b/rhodecode/lib/middleware/simplegit.py --- a/rhodecode/lib/middleware/simplegit.py +++ b/rhodecode/lib/middleware/simplegit.py @@ -142,7 +142,7 @@ class SimpleGit(simplevcs.SimpleVCS): return self.scm_app.create_git_wsgi_app( repo_path, repo_name, config) - def _create_config(self, extras, repo_name): + def _create_config(self, extras, repo_name, scheme='http'): extras['git_update_server_info'] = utils2.str2bool( rhodecode.CONFIG.get('git_update_server_info')) @@ -152,4 +152,5 @@ class SimpleGit(simplevcs.SimpleVCS): extras['git_lfs_enabled'] = utils2.str2bool( config.get('vcs_git_lfs', 'enabled')) extras['git_lfs_store_path'] = custom_store or default_lfs_store() + extras['git_lfs_http_scheme'] = scheme return extras diff --git a/rhodecode/lib/middleware/simplehg.py b/rhodecode/lib/middleware/simplehg.py --- a/rhodecode/lib/middleware/simplehg.py +++ b/rhodecode/lib/middleware/simplehg.py @@ -153,7 +153,7 @@ class SimpleHg(simplevcs.SimpleVCS): def _create_wsgi_app(self, repo_path, repo_name, config): return self.scm_app.create_hg_wsgi_app(repo_path, repo_name, config) - def _create_config(self, extras, repo_name): + def _create_config(self, extras, repo_name, scheme='http'): config = utils.make_db_config(repo=repo_name) config.set('rhodecode', 'RC_SCM_DATA', json.dumps(extras)) diff --git a/rhodecode/lib/middleware/simplesvn.py b/rhodecode/lib/middleware/simplesvn.py --- a/rhodecode/lib/middleware/simplesvn.py +++ b/rhodecode/lib/middleware/simplesvn.py @@ -87,20 +87,22 @@ class SimpleSvnApp(object): stream = True stream = stream - log.debug( - 'Calling SVN PROXY: method:%s via `%s`, Stream: %s', - req_method, path_info, stream) - response = requests.request( - req_method, path_info, - data=data, headers=request_headers, stream=stream) + log.debug('Calling SVN PROXY at `%s`, using method:%s. Stream: %s', + path_info, req_method, stream) + try: + response = requests.request( + req_method, path_info, + data=data, headers=request_headers, stream=stream) + except requests.ConnectionError: + log.exception('ConnectionError occurred for endpoint %s', path_info) + raise if response.status_code not in [200, 401]: + text = '\n{}'.format(response.text) if response.text else '' if response.status_code >= 500: - log.error('Got SVN response:%s with text:\n`%s`', - response, response.text) + log.error('Got SVN response:%s with text:`%s`', response, text) else: - log.debug('Got SVN response:%s with text:\n`%s`', - response, response.text) + log.debug('Got SVN response:%s with text:`%s`', response, text) else: log.debug('got response code: %s', response.status_code) @@ -217,7 +219,7 @@ class SimpleSvn(simplevcs.SimpleVCS): conf = self.repo_vcs_config return str2bool(conf.get('vcs_svn_proxy', 'http_requests_enabled')) - def _create_config(self, extras, repo_name): + def _create_config(self, extras, repo_name, scheme='http'): conf = self.repo_vcs_config server_url = conf.get('vcs_svn_proxy', 'http_server_url') server_url = server_url or self.DEFAULT_HTTP_SERVER diff --git a/rhodecode/lib/middleware/simplevcs.py b/rhodecode/lib/middleware/simplevcs.py --- a/rhodecode/lib/middleware/simplevcs.py +++ b/rhodecode/lib/middleware/simplevcs.py @@ -360,6 +360,13 @@ class SimpleVCS(object): return perm_result + def _get_http_scheme(self, environ): + try: + return environ['wsgi.url_scheme'] + except Exception: + log.exception('Failed to read http scheme') + return 'http' + def _check_ssl(self, environ, start_response): """ Checks the SSL check flag and returns False if SSL is not present @@ -597,7 +604,9 @@ class SimpleVCS(object): extras, environ, action, txn_id=txn_id) log.debug('HOOKS extras is %s', extras) - config = self._create_config(extras, self.acl_repo_name) + http_scheme = self._get_http_scheme(environ) + + config = self._create_config(extras, self.acl_repo_name, scheme=http_scheme) app = self._create_wsgi_app(repo_path, self.url_repo_name, config) with callback_daemon: app.rc_extras = extras @@ -643,7 +652,7 @@ class SimpleVCS(object): """Return the WSGI app that will finally handle the request.""" raise NotImplementedError() - def _create_config(self, extras, repo_name): + def _create_config(self, extras, repo_name, scheme='http'): """Create a safe config representation.""" raise NotImplementedError() diff --git a/rhodecode/lib/rc_beaker.py b/rhodecode/lib/rc_beaker.py new file mode 100644 --- /dev/null +++ b/rhodecode/lib/rc_beaker.py @@ -0,0 +1,200 @@ +# Copyright (c) 2010 Agendaless Consulting and Contributors. +# (http://www.agendaless.com), All Rights Reserved +# License: BSD-derived (http://www.repoze.org/LICENSE.txt) +# With Patches from RhodeCode GmBH + + +import os + +from beaker import cache +from beaker.session import SessionObject +from beaker.util import coerce_cache_params +from beaker.util import coerce_session_params + +from pyramid.interfaces import ISession +from pyramid.settings import asbool +from zope.interface import implementer + +from binascii import hexlify + + +def BeakerSessionFactoryConfig(**options): + """ Return a Pyramid session factory using Beaker session settings + supplied directly as ``**options``""" + + class PyramidBeakerSessionObject(SessionObject): + _options = options + _cookie_on_exception = _options.pop('cookie_on_exception', True) + _constant_csrf_token = _options.pop('constant_csrf_token', False) + + def __init__(self, request): + SessionObject.__init__(self, request.environ, **self._options) + + def session_callback(request, response): + exception = getattr(request, 'exception', None) + if (exception is None or self._cookie_on_exception) and self.accessed(): + self.persist() + headers = self.__dict__['_headers'] + if headers['set_cookie'] and headers['cookie_out']: + response.headerlist.append(('Set-Cookie', headers['cookie_out'])) + request.add_response_callback(session_callback) + + # ISession API + + @property + def id(self): + # this is as inspected in SessionObject.__init__ + if self.__dict__['_params'].get('type') != 'cookie': + return self._session().id + return None + + @property + def new(self): + return self.last_accessed is None + + changed = SessionObject.save + + # modifying dictionary methods + + @call_save + def clear(self): + return self._session().clear() + + @call_save + def update(self, d, **kw): + return self._session().update(d, **kw) + + @call_save + def setdefault(self, k, d=None): + return self._session().setdefault(k, d) + + @call_save + def pop(self, k, d=None): + return self._session().pop(k, d) + + @call_save + def popitem(self): + return self._session().popitem() + + __setitem__ = call_save(SessionObject.__setitem__) + __delitem__ = call_save(SessionObject.__delitem__) + + # Flash API methods + def flash(self, msg, queue='', allow_duplicate=True): + storage = self.setdefault('_f_' + queue, []) + if allow_duplicate or (msg not in storage): + storage.append(msg) + + def pop_flash(self, queue=''): + storage = self.pop('_f_' + queue, []) + return storage + + def peek_flash(self, queue=''): + storage = self.get('_f_' + queue, []) + return storage + + # CSRF API methods + def new_csrf_token(self): + token = (self._constant_csrf_token + or hexlify(os.urandom(20)).decode('ascii')) + self['_csrft_'] = token + return token + + def get_csrf_token(self): + token = self.get('_csrft_', None) + if token is None: + token = self.new_csrf_token() + return token + + return implementer(ISession)(PyramidBeakerSessionObject) + + +def call_save(wrapped): + """ By default, in non-auto-mode beaker badly wants people to + call save even though it should know something has changed when + a mutating method is called. This hack should be removed if + Beaker ever starts to do this by default. """ + def save(session, *arg, **kw): + value = wrapped(session, *arg, **kw) + session.save() + return value + save.__doc__ = wrapped.__doc__ + return save + + +def session_factory_from_settings(settings): + """ Return a Pyramid session factory using Beaker session settings + supplied from a Paste configuration file""" + prefixes = ('session.', 'beaker.session.') + options = {} + + # Pull out any config args meant for beaker session. if there are any + for k, v in settings.items(): + for prefix in prefixes: + if k.startswith(prefix): + option_name = k[len(prefix):] + if option_name == 'cookie_on_exception': + v = asbool(v) + options[option_name] = v + + options = coerce_session_params(options) + return BeakerSessionFactoryConfig(**options) + + +def set_cache_regions_from_settings(settings): + """ Add cache support to the Pylons application. + + The ``settings`` passed to the configurator are used to setup + the cache options. Cache options in the settings should start + with either 'beaker.cache.' or 'cache.'. + + """ + cache_settings = {'regions': []} + for key in settings.keys(): + for prefix in ['beaker.cache.', 'cache.']: + if key.startswith(prefix): + name = key.split(prefix)[1].strip() + cache_settings[name] = settings[key].strip() + + if ('expire' in cache_settings + and isinstance(cache_settings['expire'], basestring) + and cache_settings['expire'].lower() in ['none', 'no']): + cache_settings['expire'] = None + + coerce_cache_params(cache_settings) + + if 'enabled' not in cache_settings: + cache_settings['enabled'] = True + + regions = cache_settings['regions'] + if regions: + for region in regions: + if not region: + continue + + region_settings = { + 'data_dir': cache_settings.get('data_dir'), + 'lock_dir': cache_settings.get('lock_dir'), + 'expire': cache_settings.get('expire', 60), + 'enabled': cache_settings['enabled'], + 'key_length': cache_settings.get('key_length', 250), + 'type': cache_settings.get('type'), + 'url': cache_settings.get('url'), + } + region_prefix = '%s.' % region + region_len = len(region_prefix) + for key in list(cache_settings.keys()): + if key.startswith(region_prefix): + region_settings[key[region_len:]] = cache_settings.pop(key) + + if (isinstance(region_settings['expire'], basestring) + and region_settings['expire'].lower() in ['none', 'no']): + region_settings['expire'] = None + coerce_cache_params(region_settings) + cache.cache_regions[region] = region_settings + + +def includeme(config): + session_factory = session_factory_from_settings(config.registry.settings) + config.set_session_factory(session_factory) + set_cache_regions_from_settings(config.registry.settings) diff --git a/rhodecode/lib/user_sessions.py b/rhodecode/lib/user_sessions.py --- a/rhodecode/lib/user_sessions.py +++ b/rhodecode/lib/user_sessions.py @@ -23,6 +23,7 @@ import re import time import datetime import dateutil +import pickle from rhodecode.model.db import DbSession, Session @@ -142,7 +143,6 @@ class FileAuthSessions(BaseAuthSessions) return stats['callbacks'] - class MemcachedAuthSessions(BaseAuthSessions): SESSION_TYPE = 'ext:memcached' _key_regex = re.compile(r'ITEM (.*_session) \[(.*); (.*)\]') @@ -195,6 +195,43 @@ class MemcachedAuthSessions(BaseAuthSess raise CleanupCommand('Cleanup for this session type not yet available') +class RedisAuthSessions(BaseAuthSessions): + SESSION_TYPE = 'ext:redis' + + def _get_client(self): + import redis + args = { + 'socket_timeout': 60, + 'url': self.config.get('beaker.session.url') + } + + client = redis.StrictRedis.from_url(**args) + return client + + def get_count(self): + client = self._get_client() + return len(client.keys('beaker_cache:*')) + + def get_expired_count(self, older_than_seconds=None): + expiry_date = self._seconds_to_date(older_than_seconds) + return self.NOT_AVAILABLE + + def clean_sessions(self, older_than_seconds=None): + client = self._get_client() + expiry_time = time.time() - older_than_seconds + deleted_keys = 0 + for key in client.keys('beaker_cache:*'): + data = client.get(key) + if data: + json_data = pickle.loads(data) + accessed_time = json_data['_accessed_time'] + if accessed_time < expiry_time: + client.delete(key) + deleted_keys += 1 + + return deleted_keys + + class MemoryAuthSessions(BaseAuthSessions): SESSION_TYPE = 'memory' @@ -212,6 +249,7 @@ def get_session_handler(session_type): types = { 'file': FileAuthSessions, 'ext:memcached': MemcachedAuthSessions, + 'ext:redis': RedisAuthSessions, 'ext:database': DbAuthSessions, 'memory': MemoryAuthSessions } diff --git a/rhodecode/lib/utils.py b/rhodecode/lib/utils.py --- a/rhodecode/lib/utils.py +++ b/rhodecode/lib/utils.py @@ -371,7 +371,8 @@ def config_data_from_db(clear_session=Tr config.append(( safe_str(setting.section), safe_str(setting.key), False)) log.debug( - 'settings ui from db: %s', + 'settings ui from db@repo[%s]: %s', + repo, ','.join(map(lambda s: '[{}] {}={}'.format(*s), ui_data))) if clear_session: meta.Session.remove() diff --git a/rhodecode/lib/vcs/backends/base.py b/rhodecode/lib/vcs/backends/base.py --- a/rhodecode/lib/vcs/backends/base.py +++ b/rhodecode/lib/vcs/backends/base.py @@ -33,6 +33,8 @@ import collections import warnings from zope.cachedescriptors.property import Lazy as LazyProperty +from zope.cachedescriptors.property import CachedProperty + from pyramid import compat from rhodecode.translation import lazy_ugettext @@ -53,6 +55,7 @@ log = logging.getLogger(__name__) FILEMODE_DEFAULT = 0o100644 FILEMODE_EXECUTABLE = 0o100755 +EMPTY_COMMIT_ID = '0' * 40 Reference = collections.namedtuple('Reference', ('type', 'name', 'commit_id')) @@ -161,7 +164,7 @@ class MergeResponse(object): u'This pull request cannot be merged because the source contains ' u'more branches than the target.'), MergeFailureReason.HG_TARGET_HAS_MULTIPLE_HEADS: lazy_ugettext( - u'This pull request cannot be merged because the target ' + u'This pull request cannot be merged because the target `{target_ref.name}` ' u'has multiple heads: `{heads}`.'), MergeFailureReason.TARGET_IS_LOCKED: lazy_ugettext( u'This pull request cannot be merged because the target repository is ' @@ -261,6 +264,7 @@ class BaseRepository(object): EMPTY_COMMIT_ID = '0' * 40 path = None + _commit_ids_ver = 0 def __init__(self, repo_path, config=None, create=False, **kwargs): """ @@ -309,6 +313,9 @@ class BaseRepository(object): def _remote(self): raise NotImplementedError + def _heads(self, branch=None): + return [] + @LazyProperty def EMPTY_COMMIT(self): return EmptyCommit(self.EMPTY_COMMIT_ID) @@ -380,7 +387,7 @@ class BaseRepository(object): return commit.size def is_empty(self): - return not bool(self.commit_ids) + return self._remote.is_empty() @staticmethod def check_url(url, config): @@ -401,6 +408,15 @@ class BaseRepository(object): # COMMITS # ========================================================================== + @CachedProperty('_commit_ids_ver') + def commit_ids(self): + raise NotImplementedError + + def append_commit_id(self, commit_id): + if commit_id not in self.commit_ids: + self._rebuild_cache(self.commit_ids + [commit_id]) + self._commit_ids_ver = time.time() + def get_commit(self, commit_id=None, commit_idx=None, pre_load=None, translate_tag=None): """ Returns instance of `BaseCommit` class. If `commit_id` and `commit_idx` @@ -1091,12 +1107,12 @@ class BaseCommit(object): """ return None - def archive_repo(self, file_path, kind='tgz', subrepos=None, - prefix=None, write_metadata=False, mtime=None): + def archive_repo(self, archive_dest_path, kind='tgz', subrepos=None, + prefix=None, write_metadata=False, mtime=None, archive_at_path='/'): """ Creates an archive containing the contents of the repository. - :param file_path: path to the file which to create the archive. + :param archive_dest_path: path to the file which to create the archive. :param kind: one of following: ``"tbz2"``, ``"tgz"``, ``"zip"``. :param prefix: name of root directory in archive. Default is repository name and commit's short_id joined with dash: @@ -1104,10 +1120,11 @@ class BaseCommit(object): :param write_metadata: write a metadata file into archive. :param mtime: custom modification time for archive creation, defaults to time.time() if not given. + :param archive_at_path: pack files at this path (default '/') :raise VCSError: If prefix has a problem. """ - allowed_kinds = settings.ARCHIVE_SPECS.keys() + allowed_kinds = [x[0] for x in settings.ARCHIVE_SPECS] if kind not in allowed_kinds: raise ImproperArchiveTypeError( 'Archive kind (%s) not supported use one of %s' % @@ -1115,11 +1132,11 @@ class BaseCommit(object): prefix = self._validate_archive_prefix(prefix) - mtime = mtime or time.mktime(self.date.timetuple()) + mtime = mtime is not None or time.mktime(self.date.timetuple()) file_info = [] cur_rev = self.repository.get_commit(commit_id=self.raw_id) - for _r, _d, files in cur_rev.walk('/'): + for _r, _d, files in cur_rev.walk(archive_at_path): for f in files: f_path = os.path.join(prefix, f.path) file_info.append( @@ -1128,15 +1145,15 @@ class BaseCommit(object): if write_metadata: metadata = [ ('repo_name', self.repository.name), - ('rev', self.raw_id), - ('create_time', mtime), + ('commit_id', self.raw_id), + ('mtime', mtime), ('branch', self.branch), ('tags', ','.join(self.tags)), ] meta = ["%s:%s" % (f_name, value) for f_name, value in metadata] file_info.append(('.archival.txt', 0o644, False, '\n'.join(meta))) - connection.Hg.archive_repo(file_path, mtime, file_info, kind) + connection.Hg.archive_repo(archive_dest_path, mtime, file_info, kind) def _validate_archive_prefix(self, prefix): if prefix is None: @@ -1505,9 +1522,7 @@ class BaseInMemoryCommit(object): "Cannot remove node at %s from " "following parents: %s" % (not_removed, parents)) - def commit( - self, message, author, parents=None, branch=None, date=None, - **kwargs): + def commit(self, message, author, parents=None, branch=None, date=None, **kwargs): """ Performs in-memory commit (doesn't check workdir in any way) and returns newly created :class:`BaseCommit`. Updates repository's @@ -1555,7 +1570,7 @@ class EmptyCommit(BaseCommit): """ def __init__( - self, commit_id='0' * 40, repo=None, alias=None, idx=-1, + self, commit_id=EMPTY_COMMIT_ID, repo=None, alias=None, idx=-1, message='', author='', date=None): self._empty_commit_id = commit_id # TODO: johbo: Solve idx parameter, default value does not make @@ -1615,7 +1630,7 @@ class EmptyChangeset(EmptyCommit): "Use EmptyCommit instead of EmptyChangeset", DeprecationWarning) return super(EmptyCommit, cls).__new__(cls, *args, **kwargs) - def __init__(self, cs='0' * 40, repo=None, requested_revision=None, + def __init__(self, cs=EMPTY_COMMIT_ID, repo=None, requested_revision=None, alias=None, revision=-1, message='', author='', date=None): if requested_revision is not None: warnings.warn( diff --git a/rhodecode/lib/vcs/backends/git/commit.py b/rhodecode/lib/vcs/backends/git/commit.py --- a/rhodecode/lib/vcs/backends/git/commit.py +++ b/rhodecode/lib/vcs/backends/git/commit.py @@ -234,8 +234,7 @@ class GitCommit(base.BaseCommit): path = self._fix_path(path) if self._get_kind(path) != NodeKind.FILE: raise CommitError( - "File does not exist for commit %s at '%s'" % - (self.raw_id, path)) + "File does not exist for commit %s at '%s'" % (self.raw_id, path)) return path def _get_file_nodes(self): @@ -353,8 +352,7 @@ class GitCommit(base.BaseCommit): def get_nodes(self, path): if self._get_kind(path) != NodeKind.DIR: raise CommitError( - "Directory does not exist for commit %s at " - " '%s'" % (self.raw_id, path)) + "Directory does not exist for commit %s at '%s'" % (self.raw_id, path)) path = self._fix_path(path) id_, _ = self._get_id_for_path(path) tree_id = self._remote[id_]['id'] diff --git a/rhodecode/lib/vcs/backends/git/inmemory.py b/rhodecode/lib/vcs/backends/git/inmemory.py --- a/rhodecode/lib/vcs/backends/git/inmemory.py +++ b/rhodecode/lib/vcs/backends/git/inmemory.py @@ -29,8 +29,7 @@ from rhodecode.lib.vcs.backends import b class GitInMemoryCommit(base.BaseInMemoryCommit): - def commit(self, message, author, parents=None, branch=None, date=None, - **kwargs): + def commit(self, message, author, parents=None, branch=None, date=None, **kwargs): """ Performs in-memory commit (doesn't check workdir in any way) and returns newly created `GitCommit`. Updates repository's @@ -94,12 +93,12 @@ class GitInMemoryCommit(base.BaseInMemor commit_data, branch, commit_tree, updated, removed) # Update vcs repository object - self.repository.commit_ids.append(commit_id) - self.repository._rebuild_cache(self.repository.commit_ids) + self.repository.append_commit_id(commit_id) # invalidate parsed refs after commit self.repository._refs = self.repository._get_refs() self.repository.branches = self.repository._get_branches() - tip = self.repository.get_commit() + tip = self.repository.get_commit(commit_id) + self.reset() return tip diff --git a/rhodecode/lib/vcs/backends/git/repository.py b/rhodecode/lib/vcs/backends/git/repository.py --- a/rhodecode/lib/vcs/backends/git/repository.py +++ b/rhodecode/lib/vcs/backends/git/repository.py @@ -25,8 +25,10 @@ GIT repository module import logging import os import re +import time from zope.cachedescriptors.property import Lazy as LazyProperty +from zope.cachedescriptors.property import CachedProperty from rhodecode.lib.compat import OrderedDict from rhodecode.lib.datelib import ( @@ -69,6 +71,9 @@ class GitRepository(BaseRepository): # caches self._commit_ids = {} + # dependent that trigger re-computation of commit_ids + self._commit_ids_ver = 0 + @LazyProperty def _remote(self): return connection.Git(self.path, self.config, with_wire=self.with_wire) @@ -81,7 +86,7 @@ class GitRepository(BaseRepository): def head(self): return self._remote.head() - @LazyProperty + @CachedProperty('_commit_ids_ver') def commit_ids(self): """ Returns list of commit ids, in ascending order. Being lazy @@ -222,13 +227,10 @@ class GitRepository(BaseRepository): return [] return output.splitlines() - def _get_commit_id(self, commit_id_or_idx): + def _lookup_commit(self, commit_id_or_idx, translate_tag=True): def is_null(value): return len(value) == commit_id_or_idx.count('0') - if self.is_empty(): - raise EmptyRepositoryError("There are no commits yet") - if commit_id_or_idx in (None, '', 'tip', 'HEAD', 'head', -1): return self.commit_ids[-1] @@ -238,8 +240,7 @@ class GitRepository(BaseRepository): try: commit_id_or_idx = self.commit_ids[int(commit_id_or_idx)] except Exception: - msg = "Commit %s does not exist for %s" % ( - commit_id_or_idx, self) + msg = "Commit {} does not exist for `{}`".format(commit_id_or_idx, self.name) raise CommitDoesNotExistError(msg) elif is_bstr: @@ -261,8 +262,7 @@ class GitRepository(BaseRepository): if (not SHA_PATTERN.match(commit_id_or_idx) or commit_id_or_idx not in self.commit_ids): - msg = "Commit %s does not exist for %s" % ( - commit_id_or_idx, self) + msg = "Commit {} does not exist for `{}`".format(commit_id_or_idx, self.name) raise CommitDoesNotExistError(msg) # Ensure we return full id @@ -431,19 +431,42 @@ class GitRepository(BaseRepository): Returns `GitCommit` object representing commit from git repository at the given `commit_id` or head (most recent commit) if None given. """ + if self.is_empty(): + raise EmptyRepositoryError("There are no commits yet") + if commit_id is not None: self._validate_commit_id(commit_id) + try: + # we have cached idx, use it without contacting the remote + idx = self._commit_ids[commit_id] + return GitCommit(self, commit_id, idx, pre_load=pre_load) + except KeyError: + pass + elif commit_idx is not None: self._validate_commit_idx(commit_idx) - commit_id = commit_idx - commit_id = self._get_commit_id(commit_id) + try: + _commit_id = self.commit_ids[commit_idx] + if commit_idx < 0: + commit_idx = self.commit_ids.index(_commit_id) + return GitCommit(self, _commit_id, commit_idx, pre_load=pre_load) + except IndexError: + commit_id = commit_idx + else: + commit_id = "tip" + + commit_id = self._lookup_commit(commit_id) + remote_idx = None + if translate_tag: + # Need to call remote to translate id for tagging scenario + remote_data = self._remote.get_object(commit_id) + commit_id = remote_data["commit_id"] + remote_idx = remote_data["idx"] + try: - if translate_tag: - # Need to call remote to translate id for tagging scenario - commit_id = self._remote.get_object(commit_id)["commit_id"] idx = self._commit_ids[commit_id] except KeyError: - raise RepositoryError("Cannot get object with id %s" % commit_id) + idx = remote_idx or 0 return GitCommit(self, commit_id, idx, pre_load=pre_load) @@ -472,6 +495,7 @@ class GitRepository(BaseRepository): """ if self.is_empty(): raise EmptyRepositoryError("There are no commits yet") + self._validate_branch_name(branch_name) if start_id is not None: @@ -479,9 +503,9 @@ class GitRepository(BaseRepository): if end_id is not None: self._validate_commit_id(end_id) - start_raw_id = self._get_commit_id(start_id) + start_raw_id = self._lookup_commit(start_id) start_pos = self._commit_ids[start_raw_id] if start_id else None - end_raw_id = self._get_commit_id(end_id) + end_raw_id = self._lookup_commit(end_id) end_pos = max(0, self._commit_ids[end_raw_id]) if end_id else None if None not in [start_id, end_id] and start_pos > end_pos: @@ -589,8 +613,9 @@ class GitRepository(BaseRepository): commit = commit.parents[0] self._remote.set_refs('refs/heads/%s' % branch_name, commit.raw_id) - self.commit_ids = self._get_all_commit_ids() - self._rebuild_cache(self.commit_ids) + self._commit_ids_ver = time.time() + # we updated _commit_ids_ver so accessing self.commit_ids will re-compute it + return len(self.commit_ids) def get_common_ancestor(self, commit_id1, commit_id2, repo2): if commit_id1 == commit_id2: diff --git a/rhodecode/lib/vcs/backends/hg/commit.py b/rhodecode/lib/vcs/backends/hg/commit.py --- a/rhodecode/lib/vcs/backends/hg/commit.py +++ b/rhodecode/lib/vcs/backends/hg/commit.py @@ -193,13 +193,6 @@ class MercurialCommit(base.BaseCommit): children = self._remote.ctx_children(self.idx) return self._make_commits(children) - def diff(self, ignore_whitespace=True, context=3): - result = self._remote.ctx_diff( - self.idx, - git=True, ignore_whitespace=ignore_whitespace, context=context) - diff = ''.join(result) - return MercurialDiff(diff) - def _fix_path(self, path): """ Mercurial keeps filenodes as str so we need to encode from unicode diff --git a/rhodecode/lib/vcs/backends/hg/inmemory.py b/rhodecode/lib/vcs/backends/hg/inmemory.py --- a/rhodecode/lib/vcs/backends/hg/inmemory.py +++ b/rhodecode/lib/vcs/backends/hg/inmemory.py @@ -30,8 +30,7 @@ from rhodecode.lib.vcs.exceptions import class MercurialInMemoryCommit(BaseInMemoryCommit): - def commit(self, message, author, parents=None, branch=None, date=None, - **kwargs): + def commit(self, message, author, parents=None, branch=None, date=None, **kwargs): """ Performs in-memory commit (doesn't check workdir in any way) and returns newly created `MercurialCommit`. Updates repository's @@ -83,15 +82,14 @@ class MercurialInMemoryCommit(BaseInMemo date, tz = date_to_timestamp_plus_offset(date) - new_id = self.repository._remote.commitctx( + commit_id = self.repository._remote.commitctx( message=message, parents=parent_ids, commit_time=date, commit_timezone=tz, user=author, files=self.get_paths(), extra=kwargs, removed=removed, updated=updated) + self.repository.append_commit_id(commit_id) - self.repository.commit_ids.append(new_id) - self.repository._rebuild_cache(self.repository.commit_ids) self.repository.branches = self.repository._get_branches() - tip = self.repository.get_commit() + tip = self.repository.get_commit(commit_id) self.reset() return tip diff --git a/rhodecode/lib/vcs/backends/hg/repository.py b/rhodecode/lib/vcs/backends/hg/repository.py --- a/rhodecode/lib/vcs/backends/hg/repository.py +++ b/rhodecode/lib/vcs/backends/hg/repository.py @@ -24,9 +24,11 @@ HG repository module import os import logging import binascii +import time import urllib from zope.cachedescriptors.property import Lazy as LazyProperty +from zope.cachedescriptors.property import CachedProperty from rhodecode.lib.compat import OrderedDict from rhodecode.lib.datelib import ( @@ -85,11 +87,14 @@ class MercurialRepository(BaseRepository # caches self._commit_ids = {} + # dependent that trigger re-computation of commit_ids + self._commit_ids_ver = 0 + @LazyProperty def _remote(self): return connection.Hg(self.path, self.config, with_wire=self.with_wire) - @LazyProperty + @CachedProperty('_commit_ids_ver') def commit_ids(self): """ Returns list of commit ids, in ascending order. Being lazy @@ -157,8 +162,7 @@ class MercurialRepository(BaseRepository return OrderedDict(sorted(_tags, key=get_name, reverse=True)) - def tag(self, name, user, commit_id=None, message=None, date=None, - **kwargs): + def tag(self, name, user, commit_id=None, message=None, date=None, **kwargs): """ Creates and returns a tag for the given ``commit_id``. @@ -172,6 +176,7 @@ class MercurialRepository(BaseRepository """ if name in self.tags: raise TagAlreadyExistError("Tag %s already exists" % name) + commit = self.get_commit(commit_id=commit_id) local = kwargs.setdefault('local', False) @@ -180,8 +185,7 @@ class MercurialRepository(BaseRepository date, tz = date_to_timestamp_plus_offset(date) - self._remote.tag( - name, commit.raw_id, message, local, user, date, tz) + self._remote.tag(name, commit.raw_id, message, local, user, date, tz) self._remote.invalidate_vcs_cache() # Reinitialize tags @@ -203,6 +207,7 @@ class MercurialRepository(BaseRepository """ if name not in self.tags: raise TagDoesNotExistError("Tag %s does not exist" % name) + if message is None: message = "Removed tag %s" % name local = False @@ -271,8 +276,9 @@ class MercurialRepository(BaseRepository self._remote.strip(commit_id, update=False, backup="none") self._remote.invalidate_vcs_cache() - self.commit_ids = self._get_all_commit_ids() - self._rebuild_cache(self.commit_ids) + self._commit_ids_ver = time.time() + # we updated _commit_ids_ver so accessing self.commit_ids will re-compute it + return len(self.commit_ids) def verify(self): verify = self._remote.verify() @@ -425,18 +431,20 @@ class MercurialRepository(BaseRepository if commit_id is not None: self._validate_commit_id(commit_id) try: + # we have cached idx, use it without contacting the remote idx = self._commit_ids[commit_id] return MercurialCommit(self, commit_id, idx, pre_load=pre_load) except KeyError: pass + elif commit_idx is not None: self._validate_commit_idx(commit_idx) try: - id_ = self.commit_ids[commit_idx] + _commit_id = self.commit_ids[commit_idx] if commit_idx < 0: - commit_idx += len(self.commit_ids) - return MercurialCommit( - self, id_, commit_idx, pre_load=pre_load) + commit_idx = self.commit_ids.index(_commit_id) + + return MercurialCommit(self, _commit_id, commit_idx, pre_load=pre_load) except IndexError: commit_id = commit_idx else: @@ -448,8 +456,8 @@ class MercurialRepository(BaseRepository try: raw_id, idx = self._remote.lookup(commit_id, both=True) except CommitDoesNotExistError: - msg = "Commit %s does not exist for %s" % ( - commit_id, self) + msg = "Commit {} does not exist for `{}`".format( + *map(safe_str, [commit_id, self.name])) raise CommitDoesNotExistError(msg) return MercurialCommit(self, raw_id, idx, pre_load=pre_load) @@ -477,11 +485,11 @@ class MercurialRepository(BaseRepository ``end`` could not be found. """ # actually we should check now if it's not an empty repo - branch_ancestors = False if self.is_empty(): raise EmptyRepositoryError("There are no commits yet") self._validate_branch_name(branch_name) + branch_ancestors = False if start_id is not None: self._validate_commit_id(start_id) c_start = self.get_commit(commit_id=start_id) @@ -715,11 +723,16 @@ class MercurialRepository(BaseRepository try: if target_ref.type == 'branch' and len(self._heads(target_ref.name)) != 1: - heads = ','.join(self._heads(target_ref.name)) + heads = '\n,'.join(self._heads(target_ref.name)) + metadata = { + 'target_ref': target_ref, + 'source_ref': source_ref, + 'heads': heads + } return MergeResponse( False, False, None, MergeFailureReason.HG_TARGET_HAS_MULTIPLE_HEADS, - metadata={'heads': heads}) + metadata=metadata) except CommitDoesNotExistError: log.exception('Failure when looking up branch heads on hg target') return MergeResponse( @@ -892,11 +905,15 @@ class MercurialRepository(BaseRepository def read_patterns(suffix): svalue = None - try: - svalue = hgacl.get('narrowhgacl', username + suffix) - except configparser.NoOptionError: + for section, option in [ + ('narrowacl', username + suffix), + ('narrowacl', 'default' + suffix), + ('narrowhgacl', username + suffix), + ('narrowhgacl', 'default' + suffix) + ]: try: - svalue = hgacl.get('narrowhgacl', 'default' + suffix) + svalue = hgacl.get(section, option) + break # stop at the first value we find except configparser.NoOptionError: pass if not svalue: diff --git a/rhodecode/lib/vcs/backends/svn/inmemory.py b/rhodecode/lib/vcs/backends/svn/inmemory.py --- a/rhodecode/lib/vcs/backends/svn/inmemory.py +++ b/rhodecode/lib/vcs/backends/svn/inmemory.py @@ -30,8 +30,7 @@ from rhodecode.lib.vcs.backends import b class SubversionInMemoryCommit(base.BaseInMemoryCommit): - def commit(self, message, author, parents=None, branch=None, date=None, - **kwargs): + def commit(self, message, author, parents=None, branch=None, date=None, **kwargs): if branch not in (None, self.repository.DEFAULT_BRANCH_NAME): raise NotImplementedError("Branches are not yet supported") @@ -74,8 +73,7 @@ class SubversionInMemoryCommit(base.Base # we should not add the commit_id, if it is already evaluated, it # will not be evaluated again. commit_id = str(svn_rev) - if commit_id not in self.repository.commit_ids: - self.repository.commit_ids.append(commit_id) + self.repository.append_commit_id(commit_id) tip = self.repository.get_commit() self.reset() return tip diff --git a/rhodecode/lib/vcs/backends/svn/repository.py b/rhodecode/lib/vcs/backends/svn/repository.py --- a/rhodecode/lib/vcs/backends/svn/repository.py +++ b/rhodecode/lib/vcs/backends/svn/repository.py @@ -27,6 +27,7 @@ import os import urllib from zope.cachedescriptors.property import Lazy as LazyProperty +from zope.cachedescriptors.property import CachedProperty from rhodecode.lib.compat import OrderedDict from rhodecode.lib.datelib import date_astimestamp @@ -75,6 +76,9 @@ class SubversionRepository(base.BaseRepo self._init_repo(create, src_url) + # dependent that trigger re-computation of commit_ids + self._commit_ids_ver = 0 + @LazyProperty def _remote(self): return connection.Svn(self.path, self.config) @@ -93,11 +97,31 @@ class SubversionRepository(base.BaseRepo else: self._check_path() - @LazyProperty + @CachedProperty('_commit_ids_ver') def commit_ids(self): head = self._remote.lookup(None) return [str(r) for r in xrange(1, head + 1)] + def _rebuild_cache(self, commit_ids): + pass + + def run_svn_command(self, cmd, **opts): + """ + Runs given ``cmd`` as svn command and returns tuple + (stdout, stderr). + + :param cmd: full svn command to be executed + :param opts: env options to pass into Subprocess command + """ + if not isinstance(cmd, list): + raise ValueError('cmd must be a list, got %s instead' % type(cmd)) + + skip_stderr_log = opts.pop('skip_stderr_log', False) + out, err = self._remote.run_svn_command(cmd, **opts) + if err and not skip_stderr_log: + log.debug('Stderr output of svn command "%s":\n%s', cmd, err) + return out, err + @LazyProperty def branches(self): return self._tags_or_branches('vcs_svn_branch') @@ -260,7 +284,7 @@ class SubversionRepository(base.BaseRepo try: commit_id = self.commit_ids[commit_idx] except IndexError: - raise CommitDoesNotExistError + raise CommitDoesNotExistError('No commit with idx: {}'.format(commit_idx)) commit_id = self._sanitize_commit_id(commit_id) commit = SubversionCommit(repository=self, commit_id=commit_id) diff --git a/rhodecode/lib/vcs/conf/settings.py b/rhodecode/lib/vcs/conf/settings.py --- a/rhodecode/lib/vcs/conf/settings.py +++ b/rhodecode/lib/vcs/conf/settings.py @@ -42,12 +42,16 @@ BACKENDS = { 'svn': 'rhodecode.lib.vcs.backends.svn.SubversionRepository', } -# TODO: Remove once controllers/files.py is adjusted -ARCHIVE_SPECS = { - 'tbz2': ('application/x-bzip2', '.tar.bz2'), - 'tgz': ('application/x-gzip', '.tar.gz'), - 'zip': ('application/zip', '.zip'), -} + +ARCHIVE_SPECS = [ + ('tbz2', 'application/x-bzip2', 'tbz2'), + ('tbz2', 'application/x-bzip2', '.tar.bz2'), + + ('tgz', 'application/x-gzip', '.tgz'), + ('tgz', 'application/x-gzip', '.tar.gz'), + + ('zip', 'application/zip', '.zip'), +] HOOKS_PROTOCOL = None HOOKS_DIRECT_CALLS = False diff --git a/rhodecode/lib/vcs/utils/helpers.py b/rhodecode/lib/vcs/utils/helpers.py --- a/rhodecode/lib/vcs/utils/helpers.py +++ b/rhodecode/lib/vcs/utils/helpers.py @@ -101,23 +101,35 @@ def parse_datetime(text): :param text: string of desired date/datetime or something more verbose, like *yesterday*, *2weeks 3days*, etc. """ + if not text: + raise ValueError('Wrong date: "%s"' % text) - text = text.strip().lower() + if isinstance(text, datetime.datetime): + return text - INPUT_FORMATS = ( + # we limit a format to no include microseconds e.g 2017-10-17t17:48:23.XXXX + text = text.strip().lower()[:19] + + input_formats = ( '%Y-%m-%d %H:%M:%S', + '%Y-%m-%dt%H:%M:%S', '%Y-%m-%d %H:%M', + '%Y-%m-%dt%H:%M', '%Y-%m-%d', '%m/%d/%Y %H:%M:%S', + '%m/%d/%Yt%H:%M:%S', '%m/%d/%Y %H:%M', + '%m/%d/%Yt%H:%M', '%m/%d/%Y', '%m/%d/%y %H:%M:%S', + '%m/%d/%yt%H:%M:%S', '%m/%d/%y %H:%M', + '%m/%d/%yt%H:%M', '%m/%d/%y', ) - for format in INPUT_FORMATS: + for format_def in input_formats: try: - return datetime.datetime(*time.strptime(text, format)[:6]) + return datetime.datetime(*time.strptime(text, format_def)[:6]) except ValueError: pass diff --git a/rhodecode/model/db.py b/rhodecode/model/db.py --- a/rhodecode/model/db.py +++ b/rhodecode/model/db.py @@ -25,6 +25,7 @@ Database Models for RhodeCode Enterprise import re import os import time +import string import hashlib import logging import datetime @@ -39,7 +40,7 @@ from sqlalchemy import ( Index, Sequence, UniqueConstraint, ForeignKey, CheckConstraint, Column, Boolean, String, Unicode, UnicodeText, DateTime, Integer, LargeBinary, Text, Float, PickleType) -from sqlalchemy.sql.expression import true, false +from sqlalchemy.sql.expression import true, false, case from sqlalchemy.sql.functions import coalesce, count # pragma: no cover from sqlalchemy.orm import ( relationship, joinedload, class_mapper, validates, aliased) @@ -50,6 +51,7 @@ from sqlalchemy.dialects.mysql import LO from zope.cachedescriptors.property import Lazy as LazyProperty from pyramid import compat from pyramid.threadlocal import get_current_request +from webhelpers.text import collapse, remove_formatting from rhodecode.translation import _ from rhodecode.lib.vcs import get_vcs_instance @@ -57,13 +59,13 @@ from rhodecode.lib.vcs.backends.base imp from rhodecode.lib.utils2 import ( str2bool, safe_str, get_commit_safe, safe_unicode, sha1_safe, time_to_datetime, aslist, Optional, safe_int, get_clone_url, AttributeDict, - glob2re, StrictAttributeDict, cleaned_uri) + glob2re, StrictAttributeDict, cleaned_uri, datetime_to_time, OrderedDefaultDict) from rhodecode.lib.jsonalchemy import MutationObj, MutationList, JsonType, \ JsonRaw from rhodecode.lib.ext_json import json from rhodecode.lib.caching_query import FromCache -from rhodecode.lib.encrypt import AESCipher - +from rhodecode.lib.encrypt import AESCipher, validate_and_get_enc_data +from rhodecode.lib.encrypt2 import Encryptor from rhodecode.model.meta import Base, Session URL_SEP = '/' @@ -159,44 +161,46 @@ class EncryptedTextValue(TypeDecorator): impl = Text def process_bind_param(self, value, dialect): - if not value: - return value - if value.startswith('enc$aes$') or value.startswith('enc$aes_hmac$'): - # protect against double encrypting if someone manually starts - # doing - raise ValueError('value needs to be in unencrypted format, ie. ' - 'not starting with enc$aes') - return 'enc$aes_hmac$%s' % AESCipher( - ENCRYPTION_KEY, hmac=True).encrypt(value) - - def process_result_value(self, value, dialect): + """ + Setter for storing value + """ import rhodecode - if not value: return value - parts = value.split('$', 3) - if not len(parts) == 3: - # probably not encrypted values - return value + # protect against double encrypting if values is already encrypted + if value.startswith('enc$aes$') \ + or value.startswith('enc$aes_hmac$') \ + or value.startswith('enc2$'): + raise ValueError('value needs to be in unencrypted format, ' + 'ie. not starting with enc$ or enc2$') + + algo = rhodecode.CONFIG.get('rhodecode.encrypted_values.algorithm') or 'aes' + if algo == 'aes': + return 'enc$aes_hmac$%s' % AESCipher(ENCRYPTION_KEY, hmac=True).encrypt(value) + elif algo == 'fernet': + return Encryptor(ENCRYPTION_KEY).encrypt(value) else: - if parts[0] != 'enc': - # parts ok but without our header ? - return value - enc_strict_mode = str2bool(rhodecode.CONFIG.get( - 'rhodecode.encrypted_values.strict') or True) - # at that stage we know it's our encryption - if parts[1] == 'aes': - decrypted_data = AESCipher(ENCRYPTION_KEY).decrypt(parts[2]) - elif parts[1] == 'aes_hmac': - decrypted_data = AESCipher( - ENCRYPTION_KEY, hmac=True, - strict_verification=enc_strict_mode).decrypt(parts[2]) - else: - raise ValueError( - 'Encryption type part is wrong, must be `aes` ' - 'or `aes_hmac`, got `%s` instead' % (parts[1])) - return decrypted_data + ValueError('Bad encryption algorithm, should be fernet or aes, got: {}'.format(algo)) + + def process_result_value(self, value, dialect): + """ + Getter for retrieving value + """ + + import rhodecode + if not value: + return value + + algo = rhodecode.CONFIG.get('rhodecode.encrypted_values.algorithm') or 'aes' + enc_strict_mode = str2bool(rhodecode.CONFIG.get('rhodecode.encrypted_values.strict') or True) + if algo == 'aes': + decrypted_data = validate_and_get_enc_data(value, ENCRYPTION_KEY, enc_strict_mode) + elif algo == 'fernet': + return Encryptor(ENCRYPTION_KEY).decrypt(value) + else: + ValueError('Bad encryption algorithm, should be fernet or aes, got: {}'.format(algo)) + return decrypted_data class BaseModel(object): @@ -407,6 +411,15 @@ class RhodeCodeUi(Base, BaseModel): HOOK_PUSH = 'changegroup.push_logger' HOOK_PUSH_KEY = 'pushkey.key_push' + HOOKS_BUILTIN = [ + HOOK_PRE_PULL, + HOOK_PULL, + HOOK_PRE_PUSH, + HOOK_PRETX_PUSH, + HOOK_PUSH, + HOOK_PUSH_KEY, + ] + # TODO: johbo: Unify way how hooks are configured for git and hg, # git part is currently hardcoded. @@ -1665,11 +1678,12 @@ class Repository(Base, BaseModel): cascade="all, delete, delete-orphan") ui = relationship('RepoRhodeCodeUi', cascade="all") settings = relationship('RepoRhodeCodeSetting', cascade="all") - integrations = relationship('Integration', - cascade="all, delete, delete-orphan") + integrations = relationship('Integration', cascade="all, delete, delete-orphan") scoped_tokens = relationship('UserApiKeys', cascade="all") + artifacts = relationship('FileStore', cascade="all") + def __unicode__(self): return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id, safe_unicode(self.repo_name)) @@ -1717,7 +1731,9 @@ class Repository(Base, BaseModel): from rhodecode.lib.vcs.backends.base import EmptyCommit dummy = EmptyCommit().__json__() if not self._changeset_cache: - return dummy + dummy['source_repo_id'] = self.repo_id + return json.loads(json.dumps(dummy)) + try: return json.loads(self._changeset_cache) except TypeError: @@ -2170,6 +2186,20 @@ class Repository(Base, BaseModel): return make_lock, currently_locked, lock_info @property + def last_commit_cache_update_diff(self): + return time.time() - (safe_int(self.changeset_cache.get('updated_on')) or 0) + + @property + def last_commit_change(self): + from rhodecode.lib.vcs.utils.helpers import parse_datetime + empty_date = datetime.datetime.fromtimestamp(0) + date_latest = self.changeset_cache.get('date', empty_date) + try: + return parse_datetime(date_latest) + except Exception: + return empty_date + + @property def last_db_change(self): return self.updated_on @@ -2262,6 +2292,7 @@ class Repository(Base, BaseModel): """ Update cache of last changeset for repository, keys should be:: + source_repo_id short_id raw_id revision @@ -2269,15 +2300,15 @@ class Repository(Base, BaseModel): message date author - - :param cs_cache: + updated_on + """ from rhodecode.lib.vcs.backends.base import BaseChangeset if cs_cache is None: # use no-cache version here scm_repo = self.scm_instance(cache=False, config=config) - empty = not scm_repo or scm_repo.is_empty() + empty = scm_repo is None or scm_repo.is_empty() if not empty: cs_cache = scm_repo.get_commit( pre_load=["author", "date", "message", "parents"]) @@ -2297,18 +2328,28 @@ class Repository(Base, BaseModel): if is_outdated(cs_cache) or not self.changeset_cache: _default = datetime.datetime.utcnow() last_change = cs_cache.get('date') or _default - if self.updated_on and self.updated_on > last_change: - # we check if last update is newer than the new value - # if yes, we use the current timestamp instead. Imagine you get - # old commit pushed 1y ago, we'd set last update 1y to ago. - last_change = _default - log.debug('updated repo %s with new cs cache %s', - self.repo_name, cs_cache) - self.updated_on = last_change + # we check if last update is newer than the new value + # if yes, we use the current timestamp instead. Imagine you get + # old commit pushed 1y ago, we'd set last update 1y to ago. + last_change_timestamp = datetime_to_time(last_change) + current_timestamp = datetime_to_time(last_change) + if last_change_timestamp > current_timestamp: + cs_cache['date'] = _default + + cs_cache['updated_on'] = time.time() self.changeset_cache = cs_cache Session().add(self) Session().commit() + + log.debug('updated repo %s with new commit cache %s', + self.repo_name, cs_cache) else: + cs_cache = self.changeset_cache + cs_cache['updated_on'] = time.time() + self.changeset_cache = cs_cache + Session().add(self) + Session().commit() + log.debug('Skipping update_commit_cache for repo:`%s` ' 'commit already with latest changes', self.repo_name) @@ -2397,6 +2438,7 @@ class Repository(Base, BaseModel): # control over cache behaviour if cache is None and full_cache and not config: return self._get_instance_cached() + # cache here is sent to the "vcs server" return self._get_instance(cache=bool(cache), config=config) def _get_instance_cached(self): @@ -2425,8 +2467,7 @@ class Repository(Base, BaseModel): else: instance = get_instance_cached(*args) - log.debug( - 'Repo instance fetched in %.3fs', inv_context_manager.compute_time) + log.debug('Repo instance fetched in %.3fs', inv_context_manager.compute_time) return instance def _get_instance(self, cache=True, config=None): @@ -2440,7 +2481,8 @@ class Repository(Base, BaseModel): with_wire=custom_wire, create=False, _vcs_alias=self.repo_type) - + if repo is not None: + repo.count() # cache rebuild return repo def __json__(self): @@ -2467,7 +2509,8 @@ class RepoGroup(Base, BaseModel): CHOICES_SEPARATOR = '/' # used to generate select2 choices for nested groups group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) - group_name = Column("group_name", String(255), nullable=False, unique=True, default=None) + _group_name = Column("group_name", String(255), nullable=False, unique=True, default=None) + group_name_hash = Column("repo_group_name_hash", String(1024), nullable=False, unique=False) group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None) group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None) enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False) @@ -2475,6 +2518,8 @@ class RepoGroup(Base, BaseModel): created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) personal = Column('personal', Boolean(), nullable=True, unique=None, default=None) + _changeset_cache = Column( + "changeset_cache", LargeBinary(), nullable=True) # JSON data repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id') users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all') @@ -2490,6 +2535,38 @@ class RepoGroup(Base, BaseModel): return u"<%s('id:%s:%s')>" % ( self.__class__.__name__, self.group_id, self.group_name) + @hybrid_property + def group_name(self): + return self._group_name + + @group_name.setter + def group_name(self, value): + self._group_name = value + self.group_name_hash = self.hash_repo_group_name(value) + + @hybrid_property + def changeset_cache(self): + from rhodecode.lib.vcs.backends.base import EmptyCommit + dummy = EmptyCommit().__json__() + if not self._changeset_cache: + dummy['source_repo_id'] = '' + return json.loads(json.dumps(dummy)) + + try: + return json.loads(self._changeset_cache) + except TypeError: + return dummy + except Exception: + log.error(traceback.format_exc()) + return dummy + + @changeset_cache.setter + def changeset_cache(self, val): + try: + self._changeset_cache = json.dumps(val) + except Exception: + log.error(traceback.format_exc()) + @validates('group_parent_id') def validate_group_parent_id(self, key, val): """ @@ -2506,6 +2583,18 @@ class RepoGroup(Base, BaseModel): return h.escape(self.group_description) @classmethod + def hash_repo_group_name(cls, repo_group_name): + val = remove_formatting(repo_group_name) + val = safe_str(val).lower() + chars = [] + for c in val: + if c not in string.ascii_letters: + c = str(ord(c)) + chars.append(c) + + return ''.join(chars) + + @classmethod def _generate_choice(cls, repo_group): from webhelpers.html import literal as _literal _name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k)) @@ -2573,8 +2662,7 @@ class RepoGroup(Base, BaseModel): return q.all() @property - def parents(self): - parents_recursion_limit = 10 + def parents(self, parents_recursion_limit = 10): groups = [] if self.parent_group is None: return groups @@ -2597,6 +2685,20 @@ class RepoGroup(Base, BaseModel): return groups @property + def last_commit_cache_update_diff(self): + return time.time() - (safe_int(self.changeset_cache.get('updated_on')) or 0) + + @property + def last_commit_change(self): + from rhodecode.lib.vcs.utils.helpers import parse_datetime + empty_date = datetime.datetime.fromtimestamp(0) + date_latest = self.changeset_cache.get('date', empty_date) + try: + return parse_datetime(date_latest) + except Exception: + return empty_date + + @property def last_db_change(self): return self.updated_on @@ -2635,7 +2737,7 @@ class RepoGroup(Base, BaseModel): return cnt + children_count(self) - def _recursive_objects(self, include_repos=True): + def _recursive_objects(self, include_repos=True, include_groups=True): all_ = [] def _get_members(root_gr): @@ -2645,11 +2747,16 @@ class RepoGroup(Base, BaseModel): childs = root_gr.children.all() if childs: for gr in childs: - all_.append(gr) + if include_groups: + all_.append(gr) _get_members(gr) + root_group = [] + if include_groups: + root_group = [self] + _get_members(self) - return [self] + all_ + return root_group + all_ def recursive_groups_and_repos(self): """ @@ -2663,6 +2770,12 @@ class RepoGroup(Base, BaseModel): """ return self._recursive_objects(include_repos=False) + def recursive_repos(self): + """ + Returns all children repositories for this group + """ + return self._recursive_objects(include_groups=False) + def get_new_name(self, group_name): """ returns new full group name based on parent and new name @@ -2673,6 +2786,63 @@ class RepoGroup(Base, BaseModel): self.parent_group else []) return RepoGroup.url_sep().join(path_prefix + [group_name]) + def update_commit_cache(self, config=None): + """ + Update cache of last changeset for newest repository inside this group, keys should be:: + + source_repo_id + short_id + raw_id + revision + parents + message + date + author + + """ + from rhodecode.lib.vcs.utils.helpers import parse_datetime + + def repo_groups_and_repos(): + all_entries = OrderedDefaultDict(list) + + def _get_members(root_gr, pos=0): + + for repo in root_gr.repositories: + all_entries[root_gr].append(repo) + + # fill in all parent positions + for parent_group in root_gr.parents: + all_entries[parent_group].extend(all_entries[root_gr]) + + children_groups = root_gr.children.all() + if children_groups: + for cnt, gr in enumerate(children_groups, 1): + _get_members(gr, pos=pos+cnt) + + _get_members(root_gr=self) + return all_entries + + empty_date = datetime.datetime.fromtimestamp(0) + for repo_group, repos in repo_groups_and_repos().items(): + + latest_repo_cs_cache = {} + for repo in repos: + repo_cs_cache = repo.changeset_cache + date_latest = latest_repo_cs_cache.get('date', empty_date) + date_current = repo_cs_cache.get('date', empty_date) + current_timestamp = datetime_to_time(parse_datetime(date_latest)) + if current_timestamp < datetime_to_time(parse_datetime(date_current)): + latest_repo_cs_cache = repo_cs_cache + latest_repo_cs_cache['source_repo_id'] = repo.repo_id + + latest_repo_cs_cache['updated_on'] = time.time() + repo_group.changeset_cache = latest_repo_cs_cache + Session().add(repo_group) + Session().commit() + + log.debug('updated repo group %s with new commit cache %s', + repo_group.group_name, latest_repo_cs_cache) + def permissions(self, with_admins=True, with_owner=True, expand_from_user_groups=False): """ @@ -2768,6 +2938,13 @@ class RepoGroup(Base, BaseModel): } return data + def get_dict(self): + # Since we transformed `group_name` to a hybrid property, we need to + # keep compatibility with the code which uses `group_name` field. + result = super(RepoGroup, self).get_dict() + result['group_name'] = result.pop('_group_name', None) + return result + class Permission(Base, BaseModel): __tablename__ = 'permissions' @@ -4258,9 +4435,16 @@ class Gist(Base, BaseModel): # SCM functions def scm_instance(self, **kwargs): + """ + Get an instance of VCS Repository + + :param kwargs: + """ + from rhodecode.model.gist import GistModel full_repo_path = os.path.join(self.base_path(), self.gist_access_id) return get_vcs_instance( - repo_path=safe_str(full_repo_path), create=False) + repo_path=safe_str(full_repo_path), create=False, + _vcs_alias=GistModel.vcs_backend) class ExternalIdentity(Base, BaseModel): @@ -4904,8 +5088,8 @@ class FileStore(Base, BaseModel): @classmethod def create(cls, file_uid, filename, file_hash, file_size, file_display_name='', - file_description='', enabled=True, check_acl=True, - user_id=None, scope_repo_id=None, scope_repo_group_id=None): + file_description='', enabled=True, check_acl=True, user_id=None, + scope_user_id=None, scope_repo_id=None, scope_repo_group_id=None): store_entry = FileStore() store_entry.file_uid = file_uid @@ -4919,6 +5103,7 @@ class FileStore(Base, BaseModel): store_entry.enabled = enabled store_entry.user_id = user_id + store_entry.scope_user_id = scope_user_id store_entry.scope_repo_id = scope_repo_id store_entry.scope_repo_group_id = scope_repo_group_id return store_entry diff --git a/rhodecode/model/forms.py b/rhodecode/model/forms.py --- a/rhodecode/model/forms.py +++ b/rhodecode/model/forms.py @@ -618,7 +618,7 @@ def PullRequestForm(localizer, repo_id): revisions = All(#v.NotReviewedRevisions(localizer, repo_id)(), v.UniqueList(localizer)(not_empty=True)) review_members = formencode.ForEach(ReviewerForm()) - pullrequest_title = v.UnicodeString(strip=True, required=True, min=3, max=255) + pullrequest_title = v.UnicodeString(strip=True, required=True, min=1, max=255) pullrequest_desc = v.UnicodeString(strip=True, required=False) description_renderer = v.UnicodeString(strip=True, required=False) diff --git a/rhodecode/model/gist.py b/rhodecode/model/gist.py --- a/rhodecode/model/gist.py +++ b/rhodecode/model/gist.py @@ -47,6 +47,7 @@ GIST_METADATA_FILE = '.rc_gist_metadata' class GistModel(BaseModel): cls = Gist + vcs_backend = 'hg' def _get_gist(self, gist): """ @@ -145,7 +146,7 @@ class GistModel(BaseModel): gist_repo_path = os.path.join(GIST_STORE_LOC, gist_id) log.debug('Creating new %s GIST repo in %s', gist_type, gist_repo_path) repo = RepoModel()._create_filesystem_repo( - repo_name=gist_id, repo_type='hg', repo_group=GIST_STORE_LOC, + repo_name=gist_id, repo_type=self.vcs_backend, repo_group=GIST_STORE_LOC, use_global_config=True) # now create single multifile commit diff --git a/rhodecode/model/pull_request.py b/rhodecode/model/pull_request.py --- a/rhodecode/model/pull_request.py +++ b/rhodecode/model/pull_request.py @@ -683,6 +683,7 @@ class PullRequestModel(BaseModel): # source repo source_repo = pull_request.source_repo.scm_instance() + try: source_commit = source_repo.get_commit(commit_id=source_ref_name) except CommitDoesNotExistError: @@ -696,6 +697,7 @@ class PullRequestModel(BaseModel): # target repo target_repo = pull_request.target_repo.scm_instance() + try: target_commit = target_repo.get_commit(commit_id=target_ref_name) except CommitDoesNotExistError: @@ -752,8 +754,8 @@ class PullRequestModel(BaseModel): target_commit.raw_id, source_commit.raw_id, source_repo, merge=True, pre_load=pre_load) - ancestor = target_repo.get_common_ancestor( - target_commit.raw_id, source_commit.raw_id, source_repo) + ancestor = source_repo.get_common_ancestor( + source_commit.raw_id, target_commit.raw_id, target_repo) pull_request.source_ref = '%s:%s:%s' % ( source_ref_type, source_ref_name, source_commit.raw_id) @@ -1314,10 +1316,21 @@ class PullRequestModel(BaseModel): merge_state = self._refresh_merge_state( pull_request, target_vcs, target_ref) else: - possible = pull_request.\ - last_merge_status == MergeFailureReason.NONE + possible = pull_request.last_merge_status == MergeFailureReason.NONE + metadata = { + 'target_ref': pull_request.target_ref_parts, + 'source_ref': pull_request.source_ref_parts, + } + if not possible and target_ref.type == 'branch': + # NOTE(marcink): case for mercurial multiple heads on branch + heads = target_vcs._heads(target_ref.name) + if len(heads) != 1: + heads = '\n,'.join(target_vcs._heads(target_ref.name)) + metadata.update({ + 'heads': heads + }) merge_state = MergeResponse( - possible, False, None, pull_request.last_merge_status) + possible, False, None, pull_request.last_merge_status, metadata=metadata) return merge_state @@ -1326,6 +1339,7 @@ class PullRequestModel(BaseModel): name_or_id = reference.name else: name_or_id = reference.commit_id + refreshed_commit = vcs_repository.get_commit(name_or_id) refreshed_reference = Reference( reference.type, reference.name, refreshed_commit.raw_id) diff --git a/rhodecode/model/repo.py b/rhodecode/model/repo.py --- a/rhodecode/model/repo.py +++ b/rhodecode/model/repo.py @@ -192,14 +192,14 @@ class RepoModel(BaseModel): return repo_log @classmethod - def update_repoinfo(cls, repositories=None): + def update_commit_cache(cls, repositories=None): if not repositories: repositories = Repository.getAll() for repo in repositories: repo.update_commit_cache() def get_repos_as_dict(self, repo_list=None, admin=False, - super_user_actions=False): + super_user_actions=False, short_name=None): _render = get_current_request().get_partial_renderer( 'rhodecode:templates/data_table/_dt_elements.mako') c = _render.get_call_context() @@ -208,8 +208,12 @@ class RepoModel(BaseModel): return _render('quick_menu', repo_name) def repo_lnk(name, rtype, rstate, private, archived, fork_of): + if short_name is not None: + short_name_var = short_name + else: + short_name_var = not admin return _render('repo_name', name, rtype, rstate, private, archived, fork_of, - short_name=not admin, admin=False) + short_name=short_name_var, admin=False) def last_change(last_change): if admin and isinstance(last_change, datetime.datetime) and not last_change.tzinfo: @@ -250,8 +254,8 @@ class RepoModel(BaseModel): repo.private, repo.archived, repo.fork), "name_raw": repo.repo_name.lower(), - "last_change": last_change(repo.last_db_change), - "last_change_raw": datetime_to_time(repo.last_db_change), + "last_change": last_change(repo.last_commit_change), + "last_change_raw": datetime_to_time(repo.last_commit_change), "last_changeset": last_rev(repo.repo_name, cs_cache), "last_changeset_raw": cs_cache.get('revision'), diff --git a/rhodecode/model/repo_group.py b/rhodecode/model/repo_group.py --- a/rhodecode/model/repo_group.py +++ b/rhodecode/model/repo_group.py @@ -97,6 +97,8 @@ class RepoGroupModel(BaseModel): return string.Template(template).safe_substitute( username=user.username, user_id=user.user_id, + first_name=user.first_name, + last_name=user.last_name, ) def create_personal_repo_group(self, user, commit_early=True): @@ -307,6 +309,10 @@ class RepoGroupModel(BaseModel): # trigger the post hook from rhodecode.lib.hooks_base import log_create_repository_group repo_group = RepoGroup.get_by_group_name(group_name) + + # update repo group commit caches initially + repo_group.update_commit_cache() + log_create_repository_group( created_by=user.username, **repo_group.get_dict()) @@ -684,6 +690,13 @@ class RepoGroupModel(BaseModel): 'revoked permission from usergroup: {} on repogroup: {}'.format( group_name, repo_group), namespace='security.repogroup') + @classmethod + def update_commit_cache(cls, repo_groups=None): + if not repo_groups: + repo_groups = RepoGroup.getAll() + for repo_group in repo_groups: + repo_group.update_commit_cache() + def get_repo_groups_as_dict(self, repo_group_list=None, admin=False, super_user_actions=False): @@ -705,6 +718,11 @@ class RepoGroupModel(BaseModel): (datetime.datetime.now() - datetime.datetime.utcnow()).seconds) return _render("last_change", last_change) + def last_rev(repo_name, cs_cache): + return _render('revision', repo_name, cs_cache.get('revision'), + cs_cache.get('raw_id'), cs_cache.get('author'), + cs_cache.get('message'), cs_cache.get('date')) + def desc(desc, personal): return _render( 'repo_group_desc', desc, personal, c.visual.stylify_metatags) @@ -721,13 +739,19 @@ class RepoGroupModel(BaseModel): repo_group_data = [] for group in repo_group_list: + cs_cache = group.changeset_cache + last_repo_name = cs_cache.get('source_repo_name') row = { "menu": quick_menu(group.group_name), "name": repo_group_lnk(group.group_name), "name_raw": group.group_name, - "last_change": last_change(group.last_db_change), - "last_change_raw": datetime_to_time(group.last_db_change), + "last_change": last_change(group.last_commit_change), + "last_change_raw": datetime_to_time(group.last_commit_change), + + "last_changeset": "", + "last_changeset_raw": "", + "desc": desc(group.description_safe, group.personal), "top_level_repos": 0, "owner": user_profile(group.user.username) diff --git a/rhodecode/model/scm.py b/rhodecode/model/scm.py --- a/rhodecode/model/scm.py +++ b/rhodecode/model/scm.py @@ -818,6 +818,8 @@ class ScmModel(BaseModel): repo_name=repo.repo_name, repo_alias=scm_instance.alias, commit_ids=[tip.raw_id]) + return tip + def delete_nodes(self, user, repo, message, nodes, parent_commit=None, author=None, trigger_push_hook=True): """ diff --git a/rhodecode/model/settings.py b/rhodecode/model/settings.py --- a/rhodecode/model/settings.py +++ b/rhodecode/model/settings.py @@ -119,6 +119,7 @@ class SettingsModel(BaseModel): new_ui.ui_value = val new_ui.ui_active = active + repository_id = '' if self.repo: repo = self._get_repo(self.repo) repository_id = repo.repo_id @@ -440,26 +441,39 @@ class VcsSettingsModel(object): HOOKS_SETTINGS = ( ('hooks', 'changegroup.repo_size'), ('hooks', 'changegroup.push_logger'), - ('hooks', 'outgoing.pull_logger'),) + ('hooks', 'outgoing.pull_logger'), + ) HG_SETTINGS = ( ('extensions', 'largefiles'), ('phases', 'publish'), - ('extensions', 'evolve'),) + ('extensions', 'evolve'), + ('extensions', 'topic'), + ('experimental', 'evolution'), + ('experimental', 'evolution.exchange'), + ) GIT_SETTINGS = ( - ('vcs_git_lfs', 'enabled'),) + ('vcs_git_lfs', 'enabled'), + ) GLOBAL_HG_SETTINGS = ( ('extensions', 'largefiles'), ('largefiles', 'usercache'), ('phases', 'publish'), ('extensions', 'hgsubversion'), - ('extensions', 'evolve'),) + ('extensions', 'evolve'), + ('extensions', 'topic'), + ('experimental', 'evolution'), + ('experimental', 'evolution.exchange'), + ) + GLOBAL_GIT_SETTINGS = ( ('vcs_git_lfs', 'enabled'), - ('vcs_git_lfs', 'store_location')) + ('vcs_git_lfs', 'store_location') + ) GLOBAL_SVN_SETTINGS = ( ('vcs_svn_proxy', 'http_requests_enabled'), - ('vcs_svn_proxy', 'http_server_url')) + ('vcs_svn_proxy', 'http_server_url') + ) SVN_BRANCH_SECTION = 'vcs_svn_branch' SVN_TAG_SECTION = 'vcs_svn_tag' @@ -574,12 +588,38 @@ class VcsSettingsModel(object): def create_repo_svn_settings(self, data): return self._create_svn_settings(self.repo_settings, data) + def _set_evolution(self, settings, is_enabled): + if is_enabled: + # if evolve is active set evolution=all + + self._create_or_update_ui( + settings, *('experimental', 'evolution'), value='all', + active=True) + self._create_or_update_ui( + settings, *('experimental', 'evolution.exchange'), value='yes', + active=True) + # if evolve is active set topics server support + self._create_or_update_ui( + settings, *('extensions', 'topic'), value='', + active=True) + + else: + self._create_or_update_ui( + settings, *('experimental', 'evolution'), value='', + active=False) + self._create_or_update_ui( + settings, *('experimental', 'evolution.exchange'), value='no', + active=False) + self._create_or_update_ui( + settings, *('extensions', 'topic'), value='', + active=False) + @assert_repo_settings def create_or_update_repo_hg_settings(self, data): largefiles, phases, evolve = \ - self.HG_SETTINGS + self.HG_SETTINGS[:3] largefiles_key, phases_key, evolve_key = \ - self._get_settings_keys(self.HG_SETTINGS, data) + self._get_settings_keys(self.HG_SETTINGS[:3], data) self._create_or_update_ui( self.repo_settings, *largefiles, value='', @@ -587,21 +627,22 @@ class VcsSettingsModel(object): self._create_or_update_ui( self.repo_settings, *evolve, value='', active=data[evolve_key]) + self._set_evolution(self.repo_settings, is_enabled=data[evolve_key]) + self._create_or_update_ui( self.repo_settings, *phases, value=safe_str(data[phases_key])) def create_or_update_global_hg_settings(self, data): largefiles, largefiles_store, phases, hgsubversion, evolve \ - = self.GLOBAL_HG_SETTINGS + = self.GLOBAL_HG_SETTINGS[:5] largefiles_key, largefiles_store_key, phases_key, subversion_key, evolve_key \ - = self._get_settings_keys(self.GLOBAL_HG_SETTINGS, data) + = self._get_settings_keys(self.GLOBAL_HG_SETTINGS[:5], data) self._create_or_update_ui( self.global_settings, *largefiles, value='', active=data[largefiles_key]) self._create_or_update_ui( - self.global_settings, *largefiles_store, - value=data[largefiles_store_key]) + self.global_settings, *largefiles_store, value=data[largefiles_store_key]) self._create_or_update_ui( self.global_settings, *phases, value=safe_str(data[phases_key])) self._create_or_update_ui( @@ -609,9 +650,10 @@ class VcsSettingsModel(object): self._create_or_update_ui( self.global_settings, *evolve, value='', active=data[evolve_key]) + self._set_evolution(self.global_settings, is_enabled=data[evolve_key]) def create_or_update_repo_git_settings(self, data): - # NOTE(marcink): # comma make unpack work properly + # NOTE(marcink): # comma makes unpack work properly lfs_enabled, \ = self.GIT_SETTINGS @@ -675,6 +717,7 @@ class VcsSettingsModel(object): def get_repo_ui_settings(self, section=None, key=None): global_uis = self.global_settings.get_ui(section, key) repo_uis = self.repo_settings.get_ui(section, key) + filtered_repo_uis = self._filter_ui_settings(repo_uis) filtered_repo_uis_keys = [ (s.section, s.key) for s in filtered_repo_uis] diff --git a/rhodecode/model/ssh_key.py b/rhodecode/model/ssh_key.py --- a/rhodecode/model/ssh_key.py +++ b/rhodecode/model/ssh_key.py @@ -24,10 +24,15 @@ import traceback import sshpubkeys import sshpubkeys.exceptions +from cryptography.hazmat.primitives.asymmetric import rsa +from cryptography.hazmat.primitives import serialization as crypto_serialization +from cryptography.hazmat.backends import default_backend as crypto_default_backend + from rhodecode.model import BaseModel from rhodecode.model.db import UserSshKeys from rhodecode.model.meta import Session + log = logging.getLogger(__name__) @@ -62,16 +67,24 @@ class SshKeyModel(BaseModel): raise def generate_keypair(self, comment=None): - from Crypto.PublicKey import RSA - - key = RSA.generate(2048) - private = key.exportKey('PEM') - pubkey = key.publickey() - public = pubkey.exportKey('OpenSSH') + key = rsa.generate_private_key( + backend=crypto_default_backend(), + public_exponent=65537, + key_size=2048 + ) + private_key = key.private_bytes( + crypto_serialization.Encoding.PEM, + crypto_serialization.PrivateFormat.PKCS8, + crypto_serialization.NoEncryption()) + public_key = key.public_key().public_bytes( + crypto_serialization.Encoding.OpenSSH, + crypto_serialization.PublicFormat.OpenSSH + ) + if comment: - public = public + " " + comment - return private, public + public_key = public_key + " " + comment + return private_key, public_key def create(self, user, fingerprint, key_data, description): """ diff --git a/rhodecode/public/css/buttons.less b/rhodecode/public/css/buttons.less --- a/rhodecode/public/css/buttons.less +++ b/rhodecode/public/css/buttons.less @@ -14,11 +14,11 @@ input[type="button"] { font-family: @text-light; text-decoration: none; text-shadow: none; - color: @grey4; + color: @grey2; background-color: white; background-image: none; border: none; - .border ( @border-thickness-buttons, @grey4 ); + .border ( @border-thickness-buttons, @grey5 ); .border-radius (@border-radius); cursor: pointer; white-space: nowrap; @@ -26,6 +26,10 @@ input[type="button"] { -moz-transition: background .3s,color .3s; -o-transition: background .3s,color .3s; transition: background .3s,color .3s; + box-shadow: @button-shadow; + -webkit-box-shadow: @button-shadow; + + a { display: block; @@ -44,8 +48,9 @@ input[type="button"] { outline:none; } &:hover { - color: white; - background-color: @grey4; + color: @rcdarkblue; + background-color: @white; + .border ( @border-thickness, @grey4 ); } .icon-remove-sign { @@ -70,26 +75,26 @@ input[type="button"] { .btn-default { - .border ( @border-thickness-buttons, @rcblue ); + border: @border-thickness solid @grey5; background-image: none; - color: @rcblue; + color: @grey2; a { - color: @rcblue; + color: @grey2; } &:hover, &.active { - color: white; - background-color: @rcdarkblue; - .border ( @border-thickness, @rcdarkblue ); + color: @rcdarkblue; + background-color: @white; + .border ( @border-thickness, @grey4 ); a { - color: white; + color: @grey2; } } &:disabled { - .border ( @border-thickness-buttons, @grey4 ); + .border ( @border-thickness-buttons, @grey5 ); background-color: transparent; } } @@ -326,6 +331,7 @@ input[type="submit"] { .border ( @border-thickness-buttons, @rcblue ); background-color: @rcblue; color: white; + opacity: 0.5; } } @@ -416,3 +422,23 @@ input[type="reset"] { } } + +.button-links { + float: left; + display: inline; + margin: 0; + padding-left: 0; + list-style: none; + text-align: right; + + li { + + + } + + li.active { + background-color: @grey6; + .border ( @border-thickness, @grey4 ); + } + +} diff --git a/rhodecode/public/css/code-block.less b/rhodecode/public/css/code-block.less --- a/rhodecode/public/css/code-block.less +++ b/rhodecode/public/css/code-block.less @@ -404,12 +404,9 @@ div.codeblock { // TODO: johbo: Added interim to get rid of the margin around // Select2 widgets. This needs further cleanup. - margin-top: @padding; - overflow: auto; padding: 0px; - border: @border-thickness solid @grey5; - background: @grey6; + border: @border-thickness solid @grey6; .border-radius(@border-radius); #remove_gist { @@ -479,7 +476,7 @@ div.codeblock { } .code-body { - padding: @padding; + padding: 0.8em 1em; background-color: #ffffff; min-width: 100%; box-sizing: border-box; @@ -492,6 +489,21 @@ div.codeblock { height: auto; width: 100%; } + + .markdown-block { + padding: 1em 0; + } + } + + .codeblock-header { + background: @grey7; + height: 36px; + } + + .path { + border-bottom: 1px solid @grey6; + padding: .65em 1em; + height: 18px; } } diff --git a/rhodecode/public/css/codemirror.less b/rhodecode/public/css/codemirror.less --- a/rhodecode/public/css/codemirror.less +++ b/rhodecode/public/css/codemirror.less @@ -27,7 +27,7 @@ .CodeMirror-gutters { border-right: 1px solid #ddd; - background-color: @grey6; + background-color: white; white-space: nowrap; } .CodeMirror-linenumbers {} diff --git a/rhodecode/public/css/comments.less b/rhodecode/public/css/comments.less --- a/rhodecode/public/css/comments.less +++ b/rhodecode/public/css/comments.less @@ -14,7 +14,7 @@ tr.inline-comments div { max-width: 100%; p { - white-space: normal; + white-space: normal; } code, pre, .code, dd { @@ -227,7 +227,7 @@ tr.inline-comments div { .delete-comment { display: inline-block; color: @rcblue; - + &:hover { cursor: pointer; } @@ -377,13 +377,13 @@ form.comment-form { position: relative; width: 100%; min-height: 42px; - + .status_box, .cancel-button { float: left; display: inline-block; } - + .action-buttons { float: right; display: inline-block; @@ -426,10 +426,10 @@ form.comment-form { .comment-form-login { .comment-help { - padding: 0.9em; //same as the button + padding: 0.7em; //same as the button } - div.clearfix { + div.clearfix { clear: both; width: 100%; display: block; diff --git a/rhodecode/public/css/deform.less b/rhodecode/public/css/deform.less --- a/rhodecode/public/css/deform.less +++ b/rhodecode/public/css/deform.less @@ -38,7 +38,7 @@ .form-control { width: 100%; - padding: 0.9em; + padding: 0.7em; border: 1px solid #979797; border-radius: 2px; } diff --git a/rhodecode/public/css/forms.less b/rhodecode/public/css/forms.less --- a/rhodecode/public/css/forms.less +++ b/rhodecode/public/css/forms.less @@ -60,13 +60,13 @@ form.rcform { max-width: 500px; margin: 0 0 @padding -@legend-width; padding: 0 0 0 @legend-width; - + .btn { display: inline-block; margin: 0 1em @padding 0; } } - + input, textarea { float: left; @@ -113,7 +113,7 @@ form.rcform { opacity: 0.5; } } - + input[type="radio"]:not(#ie), input[type="checkbox"]:not(#ie) { // Hide the input, but have it still be clickable @@ -187,13 +187,13 @@ form.rcform { filter: progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand', M11=0.7071067811865476, M12=-0.7071067811865475, M21=0.7071067811865475, M22=0.7071067811865476); /* IE6,IE7 */ -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(SizingMethod='auto expand', M11=0.7071067811865476, M12=-0.7071067811865475, M21=0.7071067811865475, M22=0.7071067811865476)"; /* IE8 */ } - + & + .label { float: left; margin-top: 5px } } - + input[type=checkbox]:not(#ie) { visibility: hidden; &:checked + label:after { @@ -231,6 +231,11 @@ form.rcform { .drop-menu { float: left; + + & + .last-item { + margin: 0; + } + margin: 0 @input-padding 0 0; } @@ -244,7 +249,7 @@ form.rcform { .error-message { margin-top: 5px; } - + input[type=submit] { &:extend(.btn-primary); @@ -271,14 +276,15 @@ form.rcform { .badged-field { .user-badge { line-height: 25px; - padding: 10px 5px; + padding: .4em; border-radius: @border-radius; - border-top: 1px solid @rclightblue; - border-left: 1px solid @rclightblue; - border-bottom: 1px solid @rclightblue; + border-top: 1px solid @grey4; + border-left: 1px solid @grey4; + border-bottom: 1px solid @grey4; font-size: 14px; font-style: normal; color: @text-light; + background: @grey7; display: inline-block; vertical-align: top; cursor: default; diff --git a/rhodecode/public/css/ipython.less b/rhodecode/public/css/ipython.less new file mode 100644 --- /dev/null +++ b/rhodecode/public/css/ipython.less @@ -0,0 +1,11669 @@ +div.ipynb { +/*! +* +* Twitter Bootstrap +* +*/ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + box-sizing: content-box; + height: 0; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-appearance: textfield; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + background: transparent !important; + color: #000 !important; + box-shadow: none !important; + text-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + src: url('../components/bootstrap/fonts/glyphicons-halflings-regular.eot'); + src: url('../components/bootstrap/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../components/bootstrap/fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../components/bootstrap/fonts/glyphicons-halflings-regular.woff') format('woff'), url('../components/bootstrap/fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../components/bootstrap/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\002a"; +} +.glyphicon-plus:before { + content: "\002b"; +} +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.glyphicon-cd:before { + content: "\e201"; +} +.glyphicon-save-file:before { + content: "\e202"; +} +.glyphicon-open-file:before { + content: "\e203"; +} +.glyphicon-level-up:before { + content: "\e204"; +} +.glyphicon-copy:before { + content: "\e205"; +} +.glyphicon-paste:before { + content: "\e206"; +} +.glyphicon-alert:before { + content: "\e209"; +} +.glyphicon-equalizer:before { + content: "\e210"; +} +.glyphicon-king:before { + content: "\e211"; +} +.glyphicon-queen:before { + content: "\e212"; +} +.glyphicon-pawn:before { + content: "\e213"; +} +.glyphicon-bishop:before { + content: "\e214"; +} +.glyphicon-knight:before { + content: "\e215"; +} +.glyphicon-baby-formula:before { + content: "\e216"; +} +.glyphicon-tent:before { + content: "\26fa"; +} +.glyphicon-blackboard:before { + content: "\e218"; +} +.glyphicon-bed:before { + content: "\e219"; +} +.glyphicon-apple:before { + content: "\f8ff"; +} +.glyphicon-erase:before { + content: "\e221"; +} +.glyphicon-hourglass:before { + content: "\231b"; +} +.glyphicon-lamp:before { + content: "\e223"; +} +.glyphicon-duplicate:before { + content: "\e224"; +} +.glyphicon-piggy-bank:before { + content: "\e225"; +} +.glyphicon-scissors:before { + content: "\e226"; +} +.glyphicon-bitcoin:before { + content: "\e227"; +} +.glyphicon-btc:before { + content: "\e227"; +} +.glyphicon-xbt:before { + content: "\e227"; +} +.glyphicon-yen:before { + content: "\00a5"; +} +.glyphicon-jpy:before { + content: "\00a5"; +} +.glyphicon-ruble:before { + content: "\20bd"; +} +.glyphicon-rub:before { + content: "\20bd"; +} +.glyphicon-scale:before { + content: "\e230"; +} +.glyphicon-ice-lolly:before { + content: "\e231"; +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} +.glyphicon-education:before { + content: "\e233"; +} +.glyphicon-option-horizontal:before { + content: "\e234"; +} +.glyphicon-option-vertical:before { + content: "\e235"; +} +.glyphicon-menu-hamburger:before { + content: "\e236"; +} +.glyphicon-modal-window:before { + content: "\e237"; +} +.glyphicon-oil:before { + content: "\e238"; +} +.glyphicon-grain:before { + content: "\e239"; +} +.glyphicon-sunglasses:before { + content: "\e240"; +} +.glyphicon-text-size:before { + content: "\e241"; +} +.glyphicon-text-color:before { + content: "\e242"; +} +.glyphicon-text-background:before { + content: "\e243"; +} +.glyphicon-object-align-top:before { + content: "\e244"; +} +.glyphicon-object-align-bottom:before { + content: "\e245"; +} +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} +.glyphicon-object-align-left:before { + content: "\e247"; +} +.glyphicon-object-align-vertical:before { + content: "\e248"; +} +.glyphicon-object-align-right:before { + content: "\e249"; +} +.glyphicon-triangle-right:before { + content: "\e250"; +} +.glyphicon-triangle-left:before { + content: "\e251"; +} +.glyphicon-triangle-bottom:before { + content: "\e252"; +} +.glyphicon-triangle-top:before { + content: "\e253"; +} +.glyphicon-console:before { + content: "\e254"; +} +.glyphicon-superscript:before { + content: "\e255"; +} +.glyphicon-subscript:before { + content: "\e256"; +} +.glyphicon-menu-left:before { + content: "\e257"; +} +.glyphicon-menu-right:before { + content: "\e258"; +} +.glyphicon-menu-down:before { + content: "\e259"; +} +.glyphicon-menu-up:before { + content: "\e260"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + line-height: 1.42857143; + color: #000; + background-color: #fff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #337ab7; + text-decoration: none; +} +a:hover, +a:focus { + color: #23527c; + text-decoration: underline; +} +a:focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 3px; +} +.img-thumbnail { + padding: 4px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 2px; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + max-width: 100%; + height: auto; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 18px; + margin-bottom: 18px; + border: 0; + border-top: 1px solid #eeeeee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +[role="button"] { + cursor: pointer; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777777; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 18px; + margin-bottom: 9px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 9px; + margin-bottom: 9px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 33px; +} +h2, +.h2 { + font-size: 27px; +} +h3, +.h3 { + font-size: 23px; +} +h4, +.h4 { + font-size: 17px; +} +h5, +.h5 { + font-size: 13px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 9px; +} +.lead { + margin-bottom: 18px; + font-size: 14px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 19.5px; + } +} +small, +.small { + font-size: 92%; +} +mark, +.mark { + background-color: #fcf8e3; + padding: .2em; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #777777; +} +.text-primary { + color: #337ab7; +} +a.text-primary:hover, +a.text-primary:focus { + color: #286090; +} +.text-success { + color: #3c763d; +} +a.text-success:hover, +a.text-success:focus { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover, +a.text-info:focus { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover, +a.text-warning:focus { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover, +a.text-danger:focus { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #337ab7; +} +a.bg-primary:hover, +a.bg-primary:focus { + background-color: #286090; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover, +a.bg-success:focus { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover, +a.bg-info:focus { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover, +a.bg-warning:focus { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover, +a.bg-danger:focus { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 8px; + margin: 36px 0 18px; + border-bottom: 1px solid #eeeeee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 9px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + list-style: none; + margin-left: -5px; +} +.list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; +} +dl { + margin-top: 0; + margin-bottom: 18px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 541px) { + .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777777; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 9px 18px; + margin: 0 0 18px; + font-size: inherit; + border-left: 5px solid #eeeeee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777777; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; + text-align: right; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +address { + margin-bottom: 18px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 2px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #888; + background-color: transparent; + border-radius: 1px; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + box-shadow: none; +} +pre { + display: block; + padding: 8.5px; + margin: 0 0 9px; + font-size: 12px; + line-height: 1.42857143; + word-break: break-all; + word-wrap: break-word; + color: #333333; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 2px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + margin-right: auto; + margin-left: auto; + padding-left: 0px; + padding-right: 0px; +} +@media (min-width: 768px) { + .container { + width: 768px; + } +} +@media (min-width: 992px) { + .container { + width: 940px; + } +} +@media (min-width: 1200px) { + .container { + width: 1140px; + } +} +.container-fluid { + margin-right: auto; + margin-left: auto; + padding-left: 0px; + padding-right: 0px; +} +.row { + margin-left: 0px; + margin-right: 0px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 0px; + padding-right: 0px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0%; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0%; + } +} +table { + background-color: transparent; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777777; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 18px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #ddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #ddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #ddd; +} +.table .table { + background-color: #fff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + float: none; + display: table-column; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + float: none; + display: table-cell; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +.table-responsive { + overflow-x: auto; + min-height: 0.01%; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 13.5px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + padding: 0; + margin: 0; + border: 0; + min-width: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 18px; + font-size: 19.5px; + line-height: inherit; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 13px; + line-height: 1.42857143; + color: #555555; +} +.form-control { + display: block; + width: 100%; + height: 32px; + padding: 6px 12px; + font-size: 13px; + line-height: 1.42857143; + color: #555555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 2px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); +} +.form-control::-moz-placeholder { + color: #999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999; +} +.form-control::-webkit-input-placeholder { + color: #999; +} +.form-control::-ms-expand { + border: 0; + background-color: transparent; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + background-color: #eeeeee; + opacity: 1; +} +.form-control[disabled], +fieldset[disabled] .form-control { + cursor: not-allowed; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"].form-control, + input[type="time"].form-control, + input[type="datetime-local"].form-control, + input[type="month"].form-control { + line-height: 32px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 30px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 45px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 18px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-left: -20px; + margin-top: 4px \9; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; + min-height: 31px; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-left: 0; + padding-right: 0; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 1px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 1px; +} +.form-group-sm select.form-control { + height: 30px; + line-height: 30px; +} +.form-group-sm textarea.form-control, +.form-group-sm select[multiple].form-control { + height: auto; +} +.form-group-sm .form-control-static { + height: 30px; + min-height: 30px; + padding: 6px 10px; + font-size: 12px; + line-height: 1.5; +} +.input-lg { + height: 45px; + padding: 10px 16px; + font-size: 17px; + line-height: 1.3333333; + border-radius: 3px; +} +select.input-lg { + height: 45px; + line-height: 45px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.form-group-lg .form-control { + height: 45px; + padding: 10px 16px; + font-size: 17px; + line-height: 1.3333333; + border-radius: 3px; +} +.form-group-lg select.form-control { + height: 45px; + line-height: 45px; +} +.form-group-lg textarea.form-control, +.form-group-lg select[multiple].form-control { + height: auto; +} +.form-group-lg .form-control-static { + height: 45px; + min-height: 35px; + padding: 11px 16px; + font-size: 17px; + line-height: 1.3333333; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 40px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 32px; + height: 32px; + line-height: 32px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback, +.input-group-lg + .form-control-feedback, +.form-group-lg .form-control + .form-control-feedback { + width: 45px; + height: 45px; + line-height: 45px; +} +.input-sm + .form-control-feedback, +.input-group-sm + .form-control-feedback, +.form-group-sm .form-control + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + border-color: #3c763d; + background-color: #dff0d8; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + border-color: #8a6d3b; + background-color: #fcf8e3; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + border-color: #a94442; + background-color: #f2dede; +} +.has-error .form-control-feedback { + color: #a94442; +} +.has-feedback label ~ .form-control-feedback { + top: 23px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #404040; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 7px; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 25px; +} +.form-horizontal .form-group { + margin-left: 0px; + margin-right: 0px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + text-align: right; + margin-bottom: 0; + padding-top: 7px; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 0px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 11px; + font-size: 17px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + font-size: 12px; + } +} +.btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + touch-action: manipulation; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + white-space: nowrap; + padding: 6px 12px; + font-size: 13px; + line-height: 1.42857143; + border-radius: 2px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #333; + text-decoration: none; +} +.btn:active, +.btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} +a.btn.disabled, +fieldset[disabled] a.btn { + pointer-events: none; +} +.btn-default { + color: #333; + background-color: #fff; + border-color: #ccc; +} +.btn-default:focus, +.btn-default.focus { + color: #333; + background-color: #e6e6e6; + border-color: #8c8c8c; +} +.btn-default:hover { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active:hover, +.btn-default.active:hover, +.open > .dropdown-toggle.btn-default:hover, +.btn-default:active:focus, +.btn-default.active:focus, +.open > .dropdown-toggle.btn-default:focus, +.btn-default:active.focus, +.btn-default.active.focus, +.open > .dropdown-toggle.btn-default.focus { + color: #333; + background-color: #d4d4d4; + border-color: #8c8c8c; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus { + background-color: #fff; + border-color: #ccc; +} +.btn-default .badge { + color: #fff; + background-color: #333; +} +.btn-primary { + color: #fff; + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary:focus, +.btn-primary.focus { + color: #fff; + background-color: #286090; + border-color: #122b40; +} +.btn-primary:hover { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active:hover, +.btn-primary.active:hover, +.open > .dropdown-toggle.btn-primary:hover, +.btn-primary:active:focus, +.btn-primary.active:focus, +.open > .dropdown-toggle.btn-primary:focus, +.btn-primary:active.focus, +.btn-primary.active.focus, +.open > .dropdown-toggle.btn-primary.focus { + color: #fff; + background-color: #204d74; + border-color: #122b40; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus { + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary .badge { + color: #337ab7; + background-color: #fff; +} +.btn-success { + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:focus, +.btn-success.focus { + color: #fff; + background-color: #449d44; + border-color: #255625; +} +.btn-success:hover { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active:hover, +.btn-success.active:hover, +.open > .dropdown-toggle.btn-success:hover, +.btn-success:active:focus, +.btn-success.active:focus, +.open > .dropdown-toggle.btn-success:focus, +.btn-success:active.focus, +.btn-success.active.focus, +.open > .dropdown-toggle.btn-success.focus { + color: #fff; + background-color: #398439; + border-color: #255625; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #fff; +} +.btn-info { + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:focus, +.btn-info.focus { + color: #fff; + background-color: #31b0d5; + border-color: #1b6d85; +} +.btn-info:hover { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active:hover, +.btn-info.active:hover, +.open > .dropdown-toggle.btn-info:hover, +.btn-info:active:focus, +.btn-info.active:focus, +.open > .dropdown-toggle.btn-info:focus, +.btn-info:active.focus, +.btn-info.active.focus, +.open > .dropdown-toggle.btn-info.focus { + color: #fff; + background-color: #269abc; + border-color: #1b6d85; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #fff; +} +.btn-warning { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:focus, +.btn-warning.focus { + color: #fff; + background-color: #ec971f; + border-color: #985f0d; +} +.btn-warning:hover { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active:hover, +.btn-warning.active:hover, +.open > .dropdown-toggle.btn-warning:hover, +.btn-warning:active:focus, +.btn-warning.active:focus, +.open > .dropdown-toggle.btn-warning:focus, +.btn-warning:active.focus, +.btn-warning.active.focus, +.open > .dropdown-toggle.btn-warning.focus { + color: #fff; + background-color: #d58512; + border-color: #985f0d; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #fff; +} +.btn-danger { + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:focus, +.btn-danger.focus { + color: #fff; + background-color: #c9302c; + border-color: #761c19; +} +.btn-danger:hover { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active:hover, +.btn-danger.active:hover, +.open > .dropdown-toggle.btn-danger:hover, +.btn-danger:active:focus, +.btn-danger.active:focus, +.open > .dropdown-toggle.btn-danger:focus, +.btn-danger:active.focus, +.btn-danger.active.focus, +.open > .dropdown-toggle.btn-danger.focus { + color: #fff; + background-color: #ac2925; + border-color: #761c19; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #fff; +} +.btn-link { + color: #337ab7; + font-weight: normal; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #23527c; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 17px; + line-height: 1.3333333; + border-radius: 3px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 1px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 1px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-property: height, visibility; + transition-property: height, visibility; + -webkit-transition-duration: 0.35s; + transition-duration: 0.35s; + -webkit-transition-timing-function: ease; + transition-timing-function: ease; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px dashed; + border-top: 4px solid \9; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 13px; + text-align: left; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 2px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 8px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + text-decoration: none; + color: #262626; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #fff; + text-decoration: none; + outline: 0; + background-color: #337ab7; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + left: auto; + right: 0; +} +.dropdown-menu-left { + left: 0; + right: auto; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px dashed; + border-bottom: 4px solid \9; + content: ""; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 541px) { + .navbar-right .dropdown-menu { + left: auto; + right: 0; + } + .navbar-right .dropdown-menu-left { + left: 0; + right: auto; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn, +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 2px; + border-top-left-radius: 2px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-top-right-radius: 0; + border-top-left-radius: 0; + border-bottom-right-radius: 2px; + border-bottom-left-radius: 2px; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + float: none; + display: table-cell; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-left: 0; + padding-right: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group .form-control:focus { + z-index: 3; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 45px; + padding: 10px 16px; + font-size: 17px; + line-height: 1.3333333; + border-radius: 3px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 45px; + line-height: 45px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 1px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 13px; + font-weight: normal; + line-height: 1; + color: #555555; + text-align: center; + background-color: #eeeeee; + border: 1px solid #ccc; + border-radius: 2px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 1px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 17px; + border-radius: 3px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + z-index: 2; + margin-left: -1px; +} +.nav { + margin-bottom: 0; + padding-left: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +.nav > li.disabled > a { + color: #777777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777777; + text-decoration: none; + background-color: transparent; + cursor: not-allowed; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eeeeee; + border-color: #337ab7; +} +.nav .nav-divider { + height: 1px; + margin: 8px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #ddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 2px 2px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eeeeee #eeeeee #ddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555555; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; + cursor: default; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 2px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 2px 2px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 2px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #fff; + background-color: #337ab7; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 2px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 2px 2px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar { + position: relative; + min-height: 30px; + margin-bottom: 18px; + border: 1px solid transparent; +} +@media (min-width: 541px) { + .navbar { + border-radius: 2px; + } +} +@media (min-width: 541px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + overflow-x: visible; + padding-right: 0px; + padding-left: 0px; + border-top: 1px solid transparent; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 541px) { + .navbar-collapse { + width: auto; + border-top: 0; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-left: 0; + padding-right: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 540px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: 0px; + margin-left: 0px; +} +@media (min-width: 541px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 541px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 541px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + padding: 6px 0px; + font-size: 17px; + line-height: 18px; + height: 30px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 541px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: 0px; + } +} +.navbar-toggle { + position: relative; + float: right; + margin-right: 0px; + padding: 9px 10px; + margin-top: -2px; + margin-bottom: -2px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 2px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 541px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 3px 0px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 18px; +} +@media (max-width: 540px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 18px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 541px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 6px; + padding-bottom: 6px; + } +} +.navbar-form { + margin-left: 0px; + margin-right: 0px; + padding: 10px 0px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + margin-top: -1px; + margin-bottom: -1px; +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 540px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 541px) { + .navbar-form { + width: auto; + border: 0; + margin-left: 0; + margin-right: 0; + padding-top: 0; + padding-bottom: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-right-radius: 2px; + border-top-left-radius: 2px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: -1px; + margin-bottom: -1px; +} +.navbar-btn.btn-sm { + margin-top: 0px; + margin-bottom: 0px; +} +.navbar-btn.btn-xs { + margin-top: 4px; + margin-bottom: 4px; +} +.navbar-text { + margin-top: 6px; + margin-bottom: 6px; +} +@media (min-width: 541px) { + .navbar-text { + float: left; + margin-left: 0px; + margin-right: 0px; + } +} +@media (min-width: 541px) { + .navbar-left { + float: left !important; + float: left; + } + .navbar-right { + float: right !important; + float: right; + margin-right: 0px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +.navbar-default .navbar-brand { + color: #777; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #777; +} +.navbar-default .navbar-nav > li > a { + color: #777; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555; + background-color: #e7e7e7; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #ccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #ddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #ddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + background-color: #e7e7e7; + color: #555; +} +@media (max-width: 540px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #ccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #777; +} +.navbar-default .navbar-link:hover { + color: #333; +} +.navbar-default .btn-link { + color: #777; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #333; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #ccc; +} +.navbar-inverse { + background-color: #222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #9d9d9d; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #fff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #fff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + background-color: #080808; + color: #fff; +} +@media (max-width: 540px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #9d9d9d; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #fff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #9d9d9d; +} +.navbar-inverse .navbar-link:hover { + color: #fff; +} +.navbar-inverse .btn-link { + color: #9d9d9d; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #fff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 18px; + list-style: none; + background-color: #f5f5f5; + border-radius: 2px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + content: "/\00a0"; + padding: 0 5px; + color: #5e5e5e; +} +.breadcrumb > .active { + color: #777777; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 18px 0; + border-radius: 2px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + line-height: 1.42857143; + text-decoration: none; + color: #337ab7; + background-color: #fff; + border: 1px solid #ddd; + margin-left: -1px; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-bottom-left-radius: 2px; + border-top-left-radius: 2px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-bottom-right-radius: 2px; + border-top-right-radius: 2px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + z-index: 2; + color: #23527c; + background-color: #eeeeee; + border-color: #ddd; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 3; + color: #fff; + background-color: #337ab7; + border-color: #337ab7; + cursor: default; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777777; + background-color: #fff; + border-color: #ddd; + cursor: not-allowed; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 17px; + line-height: 1.3333333; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-bottom-left-radius: 1px; + border-top-left-radius: 1px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-bottom-right-radius: 1px; + border-top-right-radius: 1px; +} +.pager { + padding-left: 0; + margin: 18px 0; + list-style: none; + text-align: center; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #777777; + background-color: #fff; + cursor: not-allowed; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #777777; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #5e5e5e; +} +.label-primary { + background-color: #337ab7; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #286090; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + color: #fff; + line-height: 1; + vertical-align: middle; + white-space: nowrap; + text-align: center; + background-color: #777777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge, +.btn-group-xs > .btn .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #337ab7; + background-color: #fff; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding-top: 30px; + padding-bottom: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #eeeeee; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 20px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #d5d5d5; +} +.container .jumbotron, +.container-fluid .jumbotron { + border-radius: 3px; + padding-left: 0px; + padding-right: 0px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-left: 60px; + padding-right: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 59px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 18px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 2px; + -webkit-transition: border 0.2s ease-in-out; + -o-transition: border 0.2s ease-in-out; + transition: border 0.2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-left: auto; + margin-right: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #337ab7; +} +.thumbnail .caption { + padding: 9px; + color: #000; +} +.alert { + padding: 15px; + margin-bottom: 18px; + border: 1px solid transparent; + border-radius: 2px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + background-color: #dff0d8; + border-color: #d6e9c6; + color: #3c763d; +} +.alert-success hr { + border-top-color: #c9e2b3; +} +.alert-success .alert-link { + color: #2b542c; +} +.alert-info { + background-color: #d9edf7; + border-color: #bce8f1; + color: #31708f; +} +.alert-info hr { + border-top-color: #a6e1ec; +} +.alert-info .alert-link { + color: #245269; +} +.alert-warning { + background-color: #fcf8e3; + border-color: #faebcc; + color: #8a6d3b; +} +.alert-warning hr { + border-top-color: #f7e1b5; +} +.alert-warning .alert-link { + color: #66512c; +} +.alert-danger { + background-color: #f2dede; + border-color: #ebccd1; + color: #a94442; +} +.alert-danger hr { + border-top-color: #e4b9c0; +} +.alert-danger .alert-link { + color: #843534; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + overflow: hidden; + height: 18px; + margin-bottom: 18px; + background-color: #f5f5f5; + border-radius: 2px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} +.progress-bar { + float: left; + width: 0%; + height: 100%; + font-size: 12px; + line-height: 18px; + color: #fff; + text-align: center; + background-color: #337ab7; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media, +.media-body { + zoom: 1; + overflow: hidden; +} +.media-body { + width: 10000px; +} +.media-object { + display: block; +} +.media-object.img-thumbnail { + max-width: none; +} +.media-right, +.media > .pull-right { + padding-left: 10px; +} +.media-left, +.media > .pull-left { + padding-right: 10px; +} +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + margin-bottom: 20px; + padding-left: 0; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd; +} +.list-group-item:first-child { + border-top-right-radius: 2px; + border-top-left-radius: 2px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 2px; + border-bottom-left-radius: 2px; +} +a.list-group-item, +button.list-group-item { + color: #555; +} +a.list-group-item .list-group-item-heading, +button.list-group-item .list-group-item-heading { + color: #333; +} +a.list-group-item:hover, +button.list-group-item:hover, +a.list-group-item:focus, +button.list-group-item:focus { + text-decoration: none; + color: #555; + background-color: #f5f5f5; +} +button.list-group-item { + width: 100%; + text-align: left; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + background-color: #eeeeee; + color: #777777; + cursor: not-allowed; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #777777; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #c7ddef; +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} +a.list-group-item-success, +button.list-group-item-success { + color: #3c763d; +} +a.list-group-item-success .list-group-item-heading, +button.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +button.list-group-item-success:hover, +a.list-group-item-success:focus, +button.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +button.list-group-item-success.active, +a.list-group-item-success.active:hover, +button.list-group-item-success.active:hover, +a.list-group-item-success.active:focus, +button.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} +a.list-group-item-info, +button.list-group-item-info { + color: #31708f; +} +a.list-group-item-info .list-group-item-heading, +button.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +button.list-group-item-info:hover, +a.list-group-item-info:focus, +button.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +button.list-group-item-info.active, +a.list-group-item-info.active:hover, +button.list-group-item-info.active:hover, +a.list-group-item-info.active:focus, +button.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} +a.list-group-item-warning, +button.list-group-item-warning { + color: #8a6d3b; +} +a.list-group-item-warning .list-group-item-heading, +button.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +button.list-group-item-warning:hover, +a.list-group-item-warning:focus, +button.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +button.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +button.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus, +button.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} +a.list-group-item-danger, +button.list-group-item-danger { + color: #a94442; +} +a.list-group-item-danger .list-group-item-heading, +button.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +button.list-group-item-danger:hover, +a.list-group-item-danger:focus, +button.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +button.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +button.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus, +button.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 18px; + background-color: #fff; + border: 1px solid transparent; + border-radius: 2px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 1px; + border-top-left-radius: 1px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 15px; + color: inherit; +} +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + border-bottom-right-radius: 1px; + border-bottom-left-radius: 1px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-right-radius: 1px; + border-top-left-radius: 1px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 1px; + border-bottom-left-radius: 1px; +} +.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-left: 15px; + padding-right: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-right-radius: 1px; + border-top-left-radius: 1px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 1px; + border-top-right-radius: 1px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 1px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 1px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 1px; + border-bottom-left-radius: 1px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-left-radius: 1px; + border-bottom-right-radius: 1px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 1px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 1px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #ddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + border: 0; + margin-bottom: 0; +} +.panel-group { + margin-bottom: 18px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 2px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid #ddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #ddd; +} +.panel-default { + border-color: #ddd; +} +.panel-default > .panel-heading { + color: #333333; + background-color: #f5f5f5; + border-color: #ddd; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ddd; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ddd; +} +.panel-primary { + border-color: #337ab7; +} +.panel-primary > .panel-heading { + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #337ab7; +} +.panel-primary > .panel-heading .badge { + color: #337ab7; + background-color: #fff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #337ab7; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + left: 0; + bottom: 0; + height: 100%; + width: 100%; + border: 0; +} +.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 2px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} +.well-lg { + padding: 24px; + border-radius: 3px; +} +.well-sm { + padding: 9px; + border-radius: 1px; +} +.close { + float: right; + font-size: 19.5px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + opacity: 0.2; + filter: alpha(opacity=20); +} +.close:hover, +.close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + opacity: 0.5; + filter: alpha(opacity=50); +} +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} +.modal-open { + overflow: hidden; +} +.modal { + display: none; + overflow: hidden; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); + -webkit-transition: -webkit-transform 0.3s ease-out; + -moz-transition: -moz-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: transform 0.3s ease-out; +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #fff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 3px; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + background-clip: padding-box; + outline: 0; +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} +.modal-backdrop.fade { + opacity: 0; + filter: alpha(opacity=0); +} +.modal-backdrop.in { + opacity: 0.5; + filter: alpha(opacity=50); +} +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 15px; +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-left: 5px; + margin-bottom: 0; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-style: normal; + font-weight: normal; + letter-spacing: normal; + line-break: auto; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + white-space: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + font-size: 12px; + opacity: 0; + filter: alpha(opacity=0); +} +.tooltip.in { + opacity: 0.9; + filter: alpha(opacity=90); +} +.tooltip.top { + margin-top: -3px; + padding: 5px 0; +} +.tooltip.right { + margin-left: 3px; + padding: 0 5px; +} +.tooltip.bottom { + margin-top: 3px; + padding: 5px 0; +} +.tooltip.left { + margin-left: -3px; + padding: 0 5px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + background-color: #000; + border-radius: 2px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-left .tooltip-arrow { + bottom: 0; + right: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-style: normal; + font-weight: normal; + letter-spacing: normal; + line-break: auto; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + white-space: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + font-size: 13px; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 3px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + margin: 0; + padding: 8px 14px; + font-size: 13px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 2px 2px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + border-width: 10px; + content: ""; +} +.popover.top > .arrow { + left: 50%; + margin-left: -11px; + border-bottom-width: 0; + border-top-color: #999999; + border-top-color: rgba(0, 0, 0, 0.25); + bottom: -11px; +} +.popover.top > .arrow:after { + content: " "; + bottom: 1px; + margin-left: -10px; + border-bottom-width: 0; + border-top-color: #fff; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-left-width: 0; + border-right-color: #999999; + border-right-color: rgba(0, 0, 0, 0.25); +} +.popover.right > .arrow:after { + content: " "; + left: 1px; + bottom: -10px; + border-left-width: 0; + border-right-color: #fff; +} +.popover.bottom > .arrow { + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999999; + border-bottom-color: rgba(0, 0, 0, 0.25); + top: -11px; +} +.popover.bottom > .arrow:after { + content: " "; + top: 1px; + margin-left: -10px; + border-top-width: 0; + border-bottom-color: #fff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999999; + border-left-color: rgba(0, 0, 0, 0.25); +} +.popover.left > .arrow:after { + content: " "; + right: 1px; + border-right-width: 0; + border-left-color: #fff; + bottom: -10px; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + overflow: hidden; + width: 100%; +} +.carousel-inner > .item { + display: none; + position: relative; + -webkit-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform 0.6s ease-in-out; + -moz-transition: -moz-transform 0.6s ease-in-out; + -o-transition: -o-transform 0.6s ease-in-out; + transition: transform 0.6s ease-in-out; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + -moz-perspective: 1000px; + perspective: 1000px; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + left: 0; + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + left: 0; + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + left: 0; + } +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 15%; + opacity: 0.5; + filter: alpha(opacity=50); + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); + background-color: rgba(0, 0, 0, 0); +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); +} +.carousel-control.right { + left: auto; + right: 0; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); +} +.carousel-control:hover, +.carousel-control:focus { + outline: 0; + color: #fff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + margin-top: -10px; + z-index: 5; + display: inline-block; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + line-height: 1; + font-family: serif; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + margin-left: -30%; + padding-left: 0; + list-style: none; + text-align: center; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + border: 1px solid #fff; + border-radius: 10px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); +} +.carousel-indicators .active { + margin: 0; + width: 12px; + height: 12px; + background-color: #fff; +} +.carousel-caption { + position: absolute; + left: 15%; + right: 15%; + bottom: 20px; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -10px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -10px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -10px; + } + .carousel-caption { + left: 20%; + right: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-header:before, +.modal-header:after, +.modal-footer:before, +.modal-footer:after, +.item_buttons:before, +.item_buttons:after { + content: " "; + display: table; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-header:after, +.modal-footer:after, +.item_buttons:after { + clear: both; +} +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table !important; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table !important; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table !important; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table !important; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table !important; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} +/*! +* +* Font Awesome +* +*/ +/*! + * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ +/* FONT PATH + * -------------------------- */ +@font-face { + font-family: 'FontAwesome'; + src: url('../components/font-awesome/fonts/fontawesome-webfont.eot?v=4.2.0'); + src: url('../components/font-awesome/fonts/fontawesome-webfont.eot?#iefix&v=4.2.0') format('embedded-opentype'), url('../components/font-awesome/fonts/fontawesome-webfont.woff?v=4.2.0') format('woff'), url('../components/font-awesome/fonts/fontawesome-webfont.ttf?v=4.2.0') format('truetype'), url('../components/font-awesome/fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular') format('svg'); + font-weight: normal; + font-style: normal; +} +.fa { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +/* makes the font 33% larger relative to the icon container */ +.fa-lg { + font-size: 1.33333333em; + line-height: 0.75em; + vertical-align: -15%; +} +.fa-2x { + font-size: 2em; +} +.fa-3x { + font-size: 3em; +} +.fa-4x { + font-size: 4em; +} +.fa-5x { + font-size: 5em; +} +.fa-fw { + width: 1.28571429em; + text-align: center; +} +.fa-ul { + padding-left: 0; + margin-left: 2.14285714em; + list-style-type: none; +} +.fa-ul > li { + position: relative; +} +.fa-li { + position: absolute; + left: -2.14285714em; + width: 2.14285714em; + top: 0.14285714em; + text-align: center; +} +.fa-li.fa-lg { + left: -1.85714286em; +} +.fa-border { + padding: .2em .25em .15em; + border: solid 0.08em #eee; + border-radius: .1em; +} +.pull-right { + float: right; +} +.pull-left { + float: left; +} +.fa.pull-left { + margin-right: .3em; +} +.fa.pull-right { + margin-left: .3em; +} +.fa-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; +} +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +.fa-rotate-90 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); +} +.fa-rotate-180 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} +.fa-rotate-270 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); + -webkit-transform: rotate(270deg); + -ms-transform: rotate(270deg); + transform: rotate(270deg); +} +.fa-flip-horizontal { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1); + -webkit-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + transform: scale(-1, 1); +} +.fa-flip-vertical { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1); + -webkit-transform: scale(1, -1); + -ms-transform: scale(1, -1); + transform: scale(1, -1); +} +:root .fa-rotate-90, +:root .fa-rotate-180, +:root .fa-rotate-270, +:root .fa-flip-horizontal, +:root .fa-flip-vertical { + filter: none; +} +.fa-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} +.fa-stack-1x, +.fa-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.fa-stack-1x { + line-height: inherit; +} +.fa-stack-2x { + font-size: 2em; +} +.fa-inverse { + color: #fff; +} +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ +.fa-glass:before { + content: "\f000"; +} +.fa-music:before { + content: "\f001"; +} +.fa-search:before { + content: "\f002"; +} +.fa-envelope-o:before { + content: "\f003"; +} +.fa-heart:before { + content: "\f004"; +} +.fa-star:before { + content: "\f005"; +} +.fa-star-o:before { + content: "\f006"; +} +.fa-user:before { + content: "\f007"; +} +.fa-film:before { + content: "\f008"; +} +.fa-th-large:before { + content: "\f009"; +} +.fa-th:before { + content: "\f00a"; +} +.fa-th-list:before { + content: "\f00b"; +} +.fa-check:before { + content: "\f00c"; +} +.fa-remove:before, +.fa-close:before, +.fa-times:before { + content: "\f00d"; +} +.fa-search-plus:before { + content: "\f00e"; +} +.fa-search-minus:before { + content: "\f010"; +} +.fa-power-off:before { + content: "\f011"; +} +.fa-signal:before { + content: "\f012"; +} +.fa-gear:before, +.fa-cog:before { + content: "\f013"; +} +.fa-trash-o:before { + content: "\f014"; +} +.fa-home:before { + content: "\f015"; +} +.fa-file-o:before { + content: "\f016"; +} +.fa-clock-o:before { + content: "\f017"; +} +.fa-road:before { + content: "\f018"; +} +.fa-download:before { + content: "\f019"; +} +.fa-arrow-circle-o-down:before { + content: "\f01a"; +} +.fa-arrow-circle-o-up:before { + content: "\f01b"; +} +.fa-inbox:before { + content: "\f01c"; +} +.fa-play-circle-o:before { + content: "\f01d"; +} +.fa-rotate-right:before, +.fa-repeat:before { + content: "\f01e"; +} +.fa-refresh:before { + content: "\f021"; +} +.fa-list-alt:before { + content: "\f022"; +} +.fa-lock:before { + content: "\f023"; +} +.fa-flag:before { + content: "\f024"; +} +.fa-headphones:before { + content: "\f025"; +} +.fa-volume-off:before { + content: "\f026"; +} +.fa-volume-down:before { + content: "\f027"; +} +.fa-volume-up:before { + content: "\f028"; +} +.fa-qrcode:before { + content: "\f029"; +} +.fa-barcode:before { + content: "\f02a"; +} +.fa-tag:before { + content: "\f02b"; +} +.fa-tags:before { + content: "\f02c"; +} +.fa-book:before { + content: "\f02d"; +} +.fa-bookmark:before { + content: "\f02e"; +} +.fa-print:before { + content: "\f02f"; +} +.fa-camera:before { + content: "\f030"; +} +.fa-font:before { + content: "\f031"; +} +.fa-bold:before { + content: "\f032"; +} +.fa-italic:before { + content: "\f033"; +} +.fa-text-height:before { + content: "\f034"; +} +.fa-text-width:before { + content: "\f035"; +} +.fa-align-left:before { + content: "\f036"; +} +.fa-align-center:before { + content: "\f037"; +} +.fa-align-right:before { + content: "\f038"; +} +.fa-align-justify:before { + content: "\f039"; +} +.fa-list:before { + content: "\f03a"; +} +.fa-dedent:before, +.fa-outdent:before { + content: "\f03b"; +} +.fa-indent:before { + content: "\f03c"; +} +.fa-video-camera:before { + content: "\f03d"; +} +.fa-photo:before, +.fa-image:before, +.fa-picture-o:before { + content: "\f03e"; +} +.fa-pencil:before { + content: "\f040"; +} +.fa-map-marker:before { + content: "\f041"; +} +.fa-adjust:before { + content: "\f042"; +} +.fa-tint:before { + content: "\f043"; +} +.fa-edit:before, +.fa-pencil-square-o:before { + content: "\f044"; +} +.fa-share-square-o:before { + content: "\f045"; +} +.fa-check-square-o:before { + content: "\f046"; +} +.fa-arrows:before { + content: "\f047"; +} +.fa-step-backward:before { + content: "\f048"; +} +.fa-fast-backward:before { + content: "\f049"; +} +.fa-backward:before { + content: "\f04a"; +} +.fa-play:before { + content: "\f04b"; +} +.fa-pause:before { + content: "\f04c"; +} +.fa-stop:before { + content: "\f04d"; +} +.fa-forward:before { + content: "\f04e"; +} +.fa-fast-forward:before { + content: "\f050"; +} +.fa-step-forward:before { + content: "\f051"; +} +.fa-eject:before { + content: "\f052"; +} +.fa-chevron-left:before { + content: "\f053"; +} +.fa-chevron-right:before { + content: "\f054"; +} +.fa-plus-circle:before { + content: "\f055"; +} +.fa-minus-circle:before { + content: "\f056"; +} +.fa-times-circle:before { + content: "\f057"; +} +.fa-check-circle:before { + content: "\f058"; +} +.fa-question-circle:before { + content: "\f059"; +} +.fa-info-circle:before { + content: "\f05a"; +} +.fa-crosshairs:before { + content: "\f05b"; +} +.fa-times-circle-o:before { + content: "\f05c"; +} +.fa-check-circle-o:before { + content: "\f05d"; +} +.fa-ban:before { + content: "\f05e"; +} +.fa-arrow-left:before { + content: "\f060"; +} +.fa-arrow-right:before { + content: "\f061"; +} +.fa-arrow-up:before { + content: "\f062"; +} +.fa-arrow-down:before { + content: "\f063"; +} +.fa-mail-forward:before, +.fa-share:before { + content: "\f064"; +} +.fa-expand:before { + content: "\f065"; +} +.fa-compress:before { + content: "\f066"; +} +.fa-plus:before { + content: "\f067"; +} +.fa-minus:before { + content: "\f068"; +} +.fa-asterisk:before { + content: "\f069"; +} +.fa-exclamation-circle:before { + content: "\f06a"; +} +.fa-gift:before { + content: "\f06b"; +} +.fa-leaf:before { + content: "\f06c"; +} +.fa-fire:before { + content: "\f06d"; +} +.fa-eye:before { + content: "\f06e"; +} +.fa-eye-slash:before { + content: "\f070"; +} +.fa-warning:before, +.fa-exclamation-triangle:before { + content: "\f071"; +} +.fa-plane:before { + content: "\f072"; +} +.fa-calendar:before { + content: "\f073"; +} +.fa-random:before { + content: "\f074"; +} +.fa-comment:before { + content: "\f075"; +} +.fa-magnet:before { + content: "\f076"; +} +.fa-chevron-up:before { + content: "\f077"; +} +.fa-chevron-down:before { + content: "\f078"; +} +.fa-retweet:before { + content: "\f079"; +} +.fa-shopping-cart:before { + content: "\f07a"; +} +.fa-folder:before { + content: "\f07b"; +} +.fa-folder-open:before { + content: "\f07c"; +} +.fa-arrows-v:before { + content: "\f07d"; +} +.fa-arrows-h:before { + content: "\f07e"; +} +.fa-bar-chart-o:before, +.fa-bar-chart:before { + content: "\f080"; +} +.fa-twitter-square:before { + content: "\f081"; +} +.fa-facebook-square:before { + content: "\f082"; +} +.fa-camera-retro:before { + content: "\f083"; +} +.fa-key:before { + content: "\f084"; +} +.fa-gears:before, +.fa-cogs:before { + content: "\f085"; +} +.fa-comments:before { + content: "\f086"; +} +.fa-thumbs-o-up:before { + content: "\f087"; +} +.fa-thumbs-o-down:before { + content: "\f088"; +} +.fa-star-half:before { + content: "\f089"; +} +.fa-heart-o:before { + content: "\f08a"; +} +.fa-sign-out:before { + content: "\f08b"; +} +.fa-linkedin-square:before { + content: "\f08c"; +} +.fa-thumb-tack:before { + content: "\f08d"; +} +.fa-external-link:before { + content: "\f08e"; +} +.fa-sign-in:before { + content: "\f090"; +} +.fa-trophy:before { + content: "\f091"; +} +.fa-github-square:before { + content: "\f092"; +} +.fa-upload:before { + content: "\f093"; +} +.fa-lemon-o:before { + content: "\f094"; +} +.fa-phone:before { + content: "\f095"; +} +.fa-square-o:before { + content: "\f096"; +} +.fa-bookmark-o:before { + content: "\f097"; +} +.fa-phone-square:before { + content: "\f098"; +} +.fa-twitter:before { + content: "\f099"; +} +.fa-facebook:before { + content: "\f09a"; +} +.fa-github:before { + content: "\f09b"; +} +.fa-unlock:before { + content: "\f09c"; +} +.fa-credit-card:before { + content: "\f09d"; +} +.fa-rss:before { + content: "\f09e"; +} +.fa-hdd-o:before { + content: "\f0a0"; +} +.fa-bullhorn:before { + content: "\f0a1"; +} +.fa-bell:before { + content: "\f0f3"; +} +.fa-certificate:before { + content: "\f0a3"; +} +.fa-hand-o-right:before { + content: "\f0a4"; +} +.fa-hand-o-left:before { + content: "\f0a5"; +} +.fa-hand-o-up:before { + content: "\f0a6"; +} +.fa-hand-o-down:before { + content: "\f0a7"; +} +.fa-arrow-circle-left:before { + content: "\f0a8"; +} +.fa-arrow-circle-right:before { + content: "\f0a9"; +} +.fa-arrow-circle-up:before { + content: "\f0aa"; +} +.fa-arrow-circle-down:before { + content: "\f0ab"; +} +.fa-globe:before { + content: "\f0ac"; +} +.fa-wrench:before { + content: "\f0ad"; +} +.fa-tasks:before { + content: "\f0ae"; +} +.fa-filter:before { + content: "\f0b0"; +} +.fa-briefcase:before { + content: "\f0b1"; +} +.fa-arrows-alt:before { + content: "\f0b2"; +} +.fa-group:before, +.fa-users:before { + content: "\f0c0"; +} +.fa-chain:before, +.fa-link:before { + content: "\f0c1"; +} +.fa-cloud:before { + content: "\f0c2"; +} +.fa-flask:before { + content: "\f0c3"; +} +.fa-cut:before, +.fa-scissors:before { + content: "\f0c4"; +} +.fa-copy:before, +.fa-files-o:before { + content: "\f0c5"; +} +.fa-paperclip:before { + content: "\f0c6"; +} +.fa-save:before, +.fa-floppy-o:before { + content: "\f0c7"; +} +.fa-square:before { + content: "\f0c8"; +} +.fa-navicon:before, +.fa-reorder:before, +.fa-bars:before { + content: "\f0c9"; +} +.fa-list-ul:before { + content: "\f0ca"; +} +.fa-list-ol:before { + content: "\f0cb"; +} +.fa-strikethrough:before { + content: "\f0cc"; +} +.fa-underline:before { + content: "\f0cd"; +} +.fa-table:before { + content: "\f0ce"; +} +.fa-magic:before { + content: "\f0d0"; +} +.fa-truck:before { + content: "\f0d1"; +} +.fa-pinterest:before { + content: "\f0d2"; +} +.fa-pinterest-square:before { + content: "\f0d3"; +} +.fa-google-plus-square:before { + content: "\f0d4"; +} +.fa-google-plus:before { + content: "\f0d5"; +} +.fa-money:before { + content: "\f0d6"; +} +.fa-caret-down:before { + content: "\f0d7"; +} +.fa-caret-up:before { + content: "\f0d8"; +} +.fa-caret-left:before { + content: "\f0d9"; +} +.fa-caret-right:before { + content: "\f0da"; +} +.fa-columns:before { + content: "\f0db"; +} +.fa-unsorted:before, +.fa-sort:before { + content: "\f0dc"; +} +.fa-sort-down:before, +.fa-sort-desc:before { + content: "\f0dd"; +} +.fa-sort-up:before, +.fa-sort-asc:before { + content: "\f0de"; +} +.fa-envelope:before { + content: "\f0e0"; +} +.fa-linkedin:before { + content: "\f0e1"; +} +.fa-rotate-left:before, +.fa-undo:before { + content: "\f0e2"; +} +.fa-legal:before, +.fa-gavel:before { + content: "\f0e3"; +} +.fa-dashboard:before, +.fa-tachometer:before { + content: "\f0e4"; +} +.fa-comment-o:before { + content: "\f0e5"; +} +.fa-comments-o:before { + content: "\f0e6"; +} +.fa-flash:before, +.fa-bolt:before { + content: "\f0e7"; +} +.fa-sitemap:before { + content: "\f0e8"; +} +.fa-umbrella:before { + content: "\f0e9"; +} +.fa-paste:before, +.fa-clipboard:before { + content: "\f0ea"; +} +.fa-lightbulb-o:before { + content: "\f0eb"; +} +.fa-exchange:before { + content: "\f0ec"; +} +.fa-cloud-download:before { + content: "\f0ed"; +} +.fa-cloud-upload:before { + content: "\f0ee"; +} +.fa-user-md:before { + content: "\f0f0"; +} +.fa-stethoscope:before { + content: "\f0f1"; +} +.fa-suitcase:before { + content: "\f0f2"; +} +.fa-bell-o:before { + content: "\f0a2"; +} +.fa-coffee:before { + content: "\f0f4"; +} +.fa-cutlery:before { + content: "\f0f5"; +} +.fa-file-text-o:before { + content: "\f0f6"; +} +.fa-building-o:before { + content: "\f0f7"; +} +.fa-hospital-o:before { + content: "\f0f8"; +} +.fa-ambulance:before { + content: "\f0f9"; +} +.fa-medkit:before { + content: "\f0fa"; +} +.fa-fighter-jet:before { + content: "\f0fb"; +} +.fa-beer:before { + content: "\f0fc"; +} +.fa-h-square:before { + content: "\f0fd"; +} +.fa-plus-square:before { + content: "\f0fe"; +} +.fa-angle-double-left:before { + content: "\f100"; +} +.fa-angle-double-right:before { + content: "\f101"; +} +.fa-angle-double-up:before { + content: "\f102"; +} +.fa-angle-double-down:before { + content: "\f103"; +} +.fa-angle-left:before { + content: "\f104"; +} +.fa-angle-right:before { + content: "\f105"; +} +.fa-angle-up:before { + content: "\f106"; +} +.fa-angle-down:before { + content: "\f107"; +} +.fa-desktop:before { + content: "\f108"; +} +.fa-laptop:before { + content: "\f109"; +} +.fa-tablet:before { + content: "\f10a"; +} +.fa-mobile-phone:before, +.fa-mobile:before { + content: "\f10b"; +} +.fa-circle-o:before { + content: "\f10c"; +} +.fa-quote-left:before { + content: "\f10d"; +} +.fa-quote-right:before { + content: "\f10e"; +} +.fa-spinner:before { + content: "\f110"; +} +.fa-circle:before { + content: "\f111"; +} +.fa-mail-reply:before, +.fa-reply:before { + content: "\f112"; +} +.fa-github-alt:before { + content: "\f113"; +} +.fa-folder-o:before { + content: "\f114"; +} +.fa-folder-open-o:before { + content: "\f115"; +} +.fa-smile-o:before { + content: "\f118"; +} +.fa-frown-o:before { + content: "\f119"; +} +.fa-meh-o:before { + content: "\f11a"; +} +.fa-gamepad:before { + content: "\f11b"; +} +.fa-keyboard-o:before { + content: "\f11c"; +} +.fa-flag-o:before { + content: "\f11d"; +} +.fa-flag-checkered:before { + content: "\f11e"; +} +.fa-terminal:before { + content: "\f120"; +} +.fa-code:before { + content: "\f121"; +} +.fa-mail-reply-all:before, +.fa-reply-all:before { + content: "\f122"; +} +.fa-star-half-empty:before, +.fa-star-half-full:before, +.fa-star-half-o:before { + content: "\f123"; +} +.fa-location-arrow:before { + content: "\f124"; +} +.fa-crop:before { + content: "\f125"; +} +.fa-code-fork:before { + content: "\f126"; +} +.fa-unlink:before, +.fa-chain-broken:before { + content: "\f127"; +} +.fa-question:before { + content: "\f128"; +} +.fa-info:before { + content: "\f129"; +} +.fa-exclamation:before { + content: "\f12a"; +} +.fa-superscript:before { + content: "\f12b"; +} +.fa-subscript:before { + content: "\f12c"; +} +.fa-eraser:before { + content: "\f12d"; +} +.fa-puzzle-piece:before { + content: "\f12e"; +} +.fa-microphone:before { + content: "\f130"; +} +.fa-microphone-slash:before { + content: "\f131"; +} +.fa-shield:before { + content: "\f132"; +} +.fa-calendar-o:before { + content: "\f133"; +} +.fa-fire-extinguisher:before { + content: "\f134"; +} +.fa-rocket:before { + content: "\f135"; +} +.fa-maxcdn:before { + content: "\f136"; +} +.fa-chevron-circle-left:before { + content: "\f137"; +} +.fa-chevron-circle-right:before { + content: "\f138"; +} +.fa-chevron-circle-up:before { + content: "\f139"; +} +.fa-chevron-circle-down:before { + content: "\f13a"; +} +.fa-html5:before { + content: "\f13b"; +} +.fa-css3:before { + content: "\f13c"; +} +.fa-anchor:before { + content: "\f13d"; +} +.fa-unlock-alt:before { + content: "\f13e"; +} +.fa-bullseye:before { + content: "\f140"; +} +.fa-ellipsis-h:before { + content: "\f141"; +} +.fa-ellipsis-v:before { + content: "\f142"; +} +.fa-rss-square:before { + content: "\f143"; +} +.fa-play-circle:before { + content: "\f144"; +} +.fa-ticket:before { + content: "\f145"; +} +.fa-minus-square:before { + content: "\f146"; +} +.fa-minus-square-o:before { + content: "\f147"; +} +.fa-level-up:before { + content: "\f148"; +} +.fa-level-down:before { + content: "\f149"; +} +.fa-check-square:before { + content: "\f14a"; +} +.fa-pencil-square:before { + content: "\f14b"; +} +.fa-external-link-square:before { + content: "\f14c"; +} +.fa-share-square:before { + content: "\f14d"; +} +.fa-compass:before { + content: "\f14e"; +} +.fa-toggle-down:before, +.fa-caret-square-o-down:before { + content: "\f150"; +} +.fa-toggle-up:before, +.fa-caret-square-o-up:before { + content: "\f151"; +} +.fa-toggle-right:before, +.fa-caret-square-o-right:before { + content: "\f152"; +} +.fa-euro:before, +.fa-eur:before { + content: "\f153"; +} +.fa-gbp:before { + content: "\f154"; +} +.fa-dollar:before, +.fa-usd:before { + content: "\f155"; +} +.fa-rupee:before, +.fa-inr:before { + content: "\f156"; +} +.fa-cny:before, +.fa-rmb:before, +.fa-yen:before, +.fa-jpy:before { + content: "\f157"; +} +.fa-ruble:before, +.fa-rouble:before, +.fa-rub:before { + content: "\f158"; +} +.fa-won:before, +.fa-krw:before { + content: "\f159"; +} +.fa-bitcoin:before, +.fa-btc:before { + content: "\f15a"; +} +.fa-file:before { + content: "\f15b"; +} +.fa-file-text:before { + content: "\f15c"; +} +.fa-sort-alpha-asc:before { + content: "\f15d"; +} +.fa-sort-alpha-desc:before { + content: "\f15e"; +} +.fa-sort-amount-asc:before { + content: "\f160"; +} +.fa-sort-amount-desc:before { + content: "\f161"; +} +.fa-sort-numeric-asc:before { + content: "\f162"; +} +.fa-sort-numeric-desc:before { + content: "\f163"; +} +.fa-thumbs-up:before { + content: "\f164"; +} +.fa-thumbs-down:before { + content: "\f165"; +} +.fa-youtube-square:before { + content: "\f166"; +} +.fa-youtube:before { + content: "\f167"; +} +.fa-xing:before { + content: "\f168"; +} +.fa-xing-square:before { + content: "\f169"; +} +.fa-youtube-play:before { + content: "\f16a"; +} +.fa-dropbox:before { + content: "\f16b"; +} +.fa-stack-overflow:before { + content: "\f16c"; +} +.fa-instagram:before { + content: "\f16d"; +} +.fa-flickr:before { + content: "\f16e"; +} +.fa-adn:before { + content: "\f170"; +} +.fa-bitbucket:before { + content: "\f171"; +} +.fa-bitbucket-square:before { + content: "\f172"; +} +.fa-tumblr:before { + content: "\f173"; +} +.fa-tumblr-square:before { + content: "\f174"; +} +.fa-long-arrow-down:before { + content: "\f175"; +} +.fa-long-arrow-up:before { + content: "\f176"; +} +.fa-long-arrow-left:before { + content: "\f177"; +} +.fa-long-arrow-right:before { + content: "\f178"; +} +.fa-apple:before { + content: "\f179"; +} +.fa-windows:before { + content: "\f17a"; +} +.fa-android:before { + content: "\f17b"; +} +.fa-linux:before { + content: "\f17c"; +} +.fa-dribbble:before { + content: "\f17d"; +} +.fa-skype:before { + content: "\f17e"; +} +.fa-foursquare:before { + content: "\f180"; +} +.fa-trello:before { + content: "\f181"; +} +.fa-female:before { + content: "\f182"; +} +.fa-male:before { + content: "\f183"; +} +.fa-gittip:before { + content: "\f184"; +} +.fa-sun-o:before { + content: "\f185"; +} +.fa-moon-o:before { + content: "\f186"; +} +.fa-archive:before { + content: "\f187"; +} +.fa-bug:before { + content: "\f188"; +} +.fa-vk:before { + content: "\f189"; +} +.fa-weibo:before { + content: "\f18a"; +} +.fa-renren:before { + content: "\f18b"; +} +.fa-pagelines:before { + content: "\f18c"; +} +.fa-stack-exchange:before { + content: "\f18d"; +} +.fa-arrow-circle-o-right:before { + content: "\f18e"; +} +.fa-arrow-circle-o-left:before { + content: "\f190"; +} +.fa-toggle-left:before, +.fa-caret-square-o-left:before { + content: "\f191"; +} +.fa-dot-circle-o:before { + content: "\f192"; +} +.fa-wheelchair:before { + content: "\f193"; +} +.fa-vimeo-square:before { + content: "\f194"; +} +.fa-turkish-lira:before, +.fa-try:before { + content: "\f195"; +} +.fa-plus-square-o:before { + content: "\f196"; +} +.fa-space-shuttle:before { + content: "\f197"; +} +.fa-slack:before { + content: "\f198"; +} +.fa-envelope-square:before { + content: "\f199"; +} +.fa-wordpress:before { + content: "\f19a"; +} +.fa-openid:before { + content: "\f19b"; +} +.fa-institution:before, +.fa-bank:before, +.fa-university:before { + content: "\f19c"; +} +.fa-mortar-board:before, +.fa-graduation-cap:before { + content: "\f19d"; +} +.fa-yahoo:before { + content: "\f19e"; +} +.fa-google:before { + content: "\f1a0"; +} +.fa-reddit:before { + content: "\f1a1"; +} +.fa-reddit-square:before { + content: "\f1a2"; +} +.fa-stumbleupon-circle:before { + content: "\f1a3"; +} +.fa-stumbleupon:before { + content: "\f1a4"; +} +.fa-delicious:before { + content: "\f1a5"; +} +.fa-digg:before { + content: "\f1a6"; +} +.fa-pied-piper:before { + content: "\f1a7"; +} +.fa-pied-piper-alt:before { + content: "\f1a8"; +} +.fa-drupal:before { + content: "\f1a9"; +} +.fa-joomla:before { + content: "\f1aa"; +} +.fa-language:before { + content: "\f1ab"; +} +.fa-fax:before { + content: "\f1ac"; +} +.fa-building:before { + content: "\f1ad"; +} +.fa-child:before { + content: "\f1ae"; +} +.fa-paw:before { + content: "\f1b0"; +} +.fa-spoon:before { + content: "\f1b1"; +} +.fa-cube:before { + content: "\f1b2"; +} +.fa-cubes:before { + content: "\f1b3"; +} +.fa-behance:before { + content: "\f1b4"; +} +.fa-behance-square:before { + content: "\f1b5"; +} +.fa-steam:before { + content: "\f1b6"; +} +.fa-steam-square:before { + content: "\f1b7"; +} +.fa-recycle:before { + content: "\f1b8"; +} +.fa-automobile:before, +.fa-car:before { + content: "\f1b9"; +} +.fa-cab:before, +.fa-taxi:before { + content: "\f1ba"; +} +.fa-tree:before { + content: "\f1bb"; +} +.fa-spotify:before { + content: "\f1bc"; +} +.fa-deviantart:before { + content: "\f1bd"; +} +.fa-soundcloud:before { + content: "\f1be"; +} +.fa-database:before { + content: "\f1c0"; +} +.fa-file-pdf-o:before { + content: "\f1c1"; +} +.fa-file-word-o:before { + content: "\f1c2"; +} +.fa-file-excel-o:before { + content: "\f1c3"; +} +.fa-file-powerpoint-o:before { + content: "\f1c4"; +} +.fa-file-photo-o:before, +.fa-file-picture-o:before, +.fa-file-image-o:before { + content: "\f1c5"; +} +.fa-file-zip-o:before, +.fa-file-archive-o:before { + content: "\f1c6"; +} +.fa-file-sound-o:before, +.fa-file-audio-o:before { + content: "\f1c7"; +} +.fa-file-movie-o:before, +.fa-file-video-o:before { + content: "\f1c8"; +} +.fa-file-code-o:before { + content: "\f1c9"; +} +.fa-vine:before { + content: "\f1ca"; +} +.fa-codepen:before { + content: "\f1cb"; +} +.fa-jsfiddle:before { + content: "\f1cc"; +} +.fa-life-bouy:before, +.fa-life-buoy:before, +.fa-life-saver:before, +.fa-support:before, +.fa-life-ring:before { + content: "\f1cd"; +} +.fa-circle-o-notch:before { + content: "\f1ce"; +} +.fa-ra:before, +.fa-rebel:before { + content: "\f1d0"; +} +.fa-ge:before, +.fa-empire:before { + content: "\f1d1"; +} +.fa-git-square:before { + content: "\f1d2"; +} +.fa-git:before { + content: "\f1d3"; +} +.fa-hacker-news:before { + content: "\f1d4"; +} +.fa-tencent-weibo:before { + content: "\f1d5"; +} +.fa-qq:before { + content: "\f1d6"; +} +.fa-wechat:before, +.fa-weixin:before { + content: "\f1d7"; +} +.fa-send:before, +.fa-paper-plane:before { + content: "\f1d8"; +} +.fa-send-o:before, +.fa-paper-plane-o:before { + content: "\f1d9"; +} +.fa-history:before { + content: "\f1da"; +} +.fa-circle-thin:before { + content: "\f1db"; +} +.fa-header:before { + content: "\f1dc"; +} +.fa-paragraph:before { + content: "\f1dd"; +} +.fa-sliders:before { + content: "\f1de"; +} +.fa-share-alt:before { + content: "\f1e0"; +} +.fa-share-alt-square:before { + content: "\f1e1"; +} +.fa-bomb:before { + content: "\f1e2"; +} +.fa-soccer-ball-o:before, +.fa-futbol-o:before { + content: "\f1e3"; +} +.fa-tty:before { + content: "\f1e4"; +} +.fa-binoculars:before { + content: "\f1e5"; +} +.fa-plug:before { + content: "\f1e6"; +} +.fa-slideshare:before { + content: "\f1e7"; +} +.fa-twitch:before { + content: "\f1e8"; +} +.fa-yelp:before { + content: "\f1e9"; +} +.fa-newspaper-o:before { + content: "\f1ea"; +} +.fa-wifi:before { + content: "\f1eb"; +} +.fa-calculator:before { + content: "\f1ec"; +} +.fa-paypal:before { + content: "\f1ed"; +} +.fa-google-wallet:before { + content: "\f1ee"; +} +.fa-cc-visa:before { + content: "\f1f0"; +} +.fa-cc-mastercard:before { + content: "\f1f1"; +} +.fa-cc-discover:before { + content: "\f1f2"; +} +.fa-cc-amex:before { + content: "\f1f3"; +} +.fa-cc-paypal:before { + content: "\f1f4"; +} +.fa-cc-stripe:before { + content: "\f1f5"; +} +.fa-bell-slash:before { + content: "\f1f6"; +} +.fa-bell-slash-o:before { + content: "\f1f7"; +} +.fa-trash:before { + content: "\f1f8"; +} +.fa-copyright:before { + content: "\f1f9"; +} +.fa-at:before { + content: "\f1fa"; +} +.fa-eyedropper:before { + content: "\f1fb"; +} +.fa-paint-brush:before { + content: "\f1fc"; +} +.fa-birthday-cake:before { + content: "\f1fd"; +} +.fa-area-chart:before { + content: "\f1fe"; +} +.fa-pie-chart:before { + content: "\f200"; +} +.fa-line-chart:before { + content: "\f201"; +} +.fa-lastfm:before { + content: "\f202"; +} +.fa-lastfm-square:before { + content: "\f203"; +} +.fa-toggle-off:before { + content: "\f204"; +} +.fa-toggle-on:before { + content: "\f205"; +} +.fa-bicycle:before { + content: "\f206"; +} +.fa-bus:before { + content: "\f207"; +} +.fa-ioxhost:before { + content: "\f208"; +} +.fa-angellist:before { + content: "\f209"; +} +.fa-cc:before { + content: "\f20a"; +} +.fa-shekel:before, +.fa-sheqel:before, +.fa-ils:before { + content: "\f20b"; +} +.fa-meanpath:before { + content: "\f20c"; +} +/*! +* +* IPython base +* +*/ +.modal.fade .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +code { + color: #000; +} +pre { + font-size: inherit; + line-height: inherit; +} +label { + font-weight: normal; +} +/* Make the page background atleast 100% the height of the view port */ +/* Make the page itself atleast 70% the height of the view port */ +.border-box-sizing { + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; +} +.corner-all { + border-radius: 2px; +} +.no-padding { + padding: 0px; +} +/* Flexible box model classes */ +/* Taken from Alex Russell http://infrequently.org/2009/08/css-3-progress/ */ +/* This file is a compatability layer. It allows the usage of flexible box +model layouts accross multiple browsers, including older browsers. The newest, +universal implementation of the flexible box model is used when available (see +`Modern browsers` comments below). Browsers that are known to implement this +new spec completely include: + + Firefox 28.0+ + Chrome 29.0+ + Internet Explorer 11+ + Opera 17.0+ + +Browsers not listed, including Safari, are supported via the styling under the +`Old browsers` comments below. +*/ +.hbox { + /* Old browsers */ + display: -webkit-box; + -webkit-box-orient: horizontal; + -webkit-box-align: stretch; + display: -moz-box; + -moz-box-orient: horizontal; + -moz-box-align: stretch; + display: box; + box-orient: horizontal; + box-align: stretch; + /* Modern browsers */ + display: flex; + flex-direction: row; + align-items: stretch; +} +.hbox > * { + /* Old browsers */ + -webkit-box-flex: 0; + -moz-box-flex: 0; + box-flex: 0; + /* Modern browsers */ + flex: none; +} +.vbox { + /* Old browsers */ + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-box-align: stretch; + display: -moz-box; + -moz-box-orient: vertical; + -moz-box-align: stretch; + display: box; + box-orient: vertical; + box-align: stretch; + /* Modern browsers */ + display: flex; + flex-direction: column; + align-items: stretch; +} +.vbox > * { + /* Old browsers */ + -webkit-box-flex: 0; + -moz-box-flex: 0; + box-flex: 0; + /* Modern browsers */ + flex: none; +} +.hbox.reverse, +.vbox.reverse, +.reverse { + /* Old browsers */ + -webkit-box-direction: reverse; + -moz-box-direction: reverse; + box-direction: reverse; + /* Modern browsers */ + flex-direction: row-reverse; +} +.hbox.box-flex0, +.vbox.box-flex0, +.box-flex0 { + /* Old browsers */ + -webkit-box-flex: 0; + -moz-box-flex: 0; + box-flex: 0; + /* Modern browsers */ + flex: none; + width: auto; +} +.hbox.box-flex1, +.vbox.box-flex1, +.box-flex1 { + /* Old browsers */ + -webkit-box-flex: 1; + -moz-box-flex: 1; + box-flex: 1; + /* Modern browsers */ + flex: 1; +} +.hbox.box-flex, +.vbox.box-flex, +.box-flex { + /* Old browsers */ + /* Old browsers */ + -webkit-box-flex: 1; + -moz-box-flex: 1; + box-flex: 1; + /* Modern browsers */ + flex: 1; +} +.hbox.box-flex2, +.vbox.box-flex2, +.box-flex2 { + /* Old browsers */ + -webkit-box-flex: 2; + -moz-box-flex: 2; + box-flex: 2; + /* Modern browsers */ + flex: 2; +} +.box-group1 { + /* Deprecated */ + -webkit-box-flex-group: 1; + -moz-box-flex-group: 1; + box-flex-group: 1; +} +.box-group2 { + /* Deprecated */ + -webkit-box-flex-group: 2; + -moz-box-flex-group: 2; + box-flex-group: 2; +} +.hbox.start, +.vbox.start, +.start { + /* Old browsers */ + -webkit-box-pack: start; + -moz-box-pack: start; + box-pack: start; + /* Modern browsers */ + justify-content: flex-start; +} +.hbox.end, +.vbox.end, +.end { + /* Old browsers */ + -webkit-box-pack: end; + -moz-box-pack: end; + box-pack: end; + /* Modern browsers */ + justify-content: flex-end; +} +.hbox.center, +.vbox.center, +.center { + /* Old browsers */ + -webkit-box-pack: center; + -moz-box-pack: center; + box-pack: center; + /* Modern browsers */ + justify-content: center; +} +.hbox.baseline, +.vbox.baseline, +.baseline { + /* Old browsers */ + -webkit-box-pack: baseline; + -moz-box-pack: baseline; + box-pack: baseline; + /* Modern browsers */ + justify-content: baseline; +} +.hbox.stretch, +.vbox.stretch, +.stretch { + /* Old browsers */ + -webkit-box-pack: stretch; + -moz-box-pack: stretch; + box-pack: stretch; + /* Modern browsers */ + justify-content: stretch; +} +.hbox.align-start, +.vbox.align-start, +.align-start { + /* Old browsers */ + -webkit-box-align: start; + -moz-box-align: start; + box-align: start; + /* Modern browsers */ + align-items: flex-start; +} +.hbox.align-end, +.vbox.align-end, +.align-end { + /* Old browsers */ + -webkit-box-align: end; + -moz-box-align: end; + box-align: end; + /* Modern browsers */ + align-items: flex-end; +} +.hbox.align-center, +.vbox.align-center, +.align-center { + /* Old browsers */ + -webkit-box-align: center; + -moz-box-align: center; + box-align: center; + /* Modern browsers */ + align-items: center; +} +.hbox.align-baseline, +.vbox.align-baseline, +.align-baseline { + /* Old browsers */ + -webkit-box-align: baseline; + -moz-box-align: baseline; + box-align: baseline; + /* Modern browsers */ + align-items: baseline; +} +.hbox.align-stretch, +.vbox.align-stretch, +.align-stretch { + /* Old browsers */ + -webkit-box-align: stretch; + -moz-box-align: stretch; + box-align: stretch; + /* Modern browsers */ + align-items: stretch; +} +div.error { + margin: 2em; + text-align: center; +} +div.error > h1 { + font-size: 500%; + line-height: normal; +} +div.error > p { + font-size: 200%; + line-height: normal; +} +div.traceback-wrapper { + text-align: left; + max-width: 800px; + margin: auto; +} +/** + * Primary styles + * + * Author: Jupyter Development Team + */ +body { + background-color: #fff; + /* This makes sure that the body covers the entire window and needs to + be in a different element than the display: box in wrapper below */ + position: absolute; + left: 0px; + right: 0px; + top: 0px; + bottom: 0px; + overflow: visible; +} +body > #header { + /* Initially hidden to prevent FLOUC */ + display: none; + background-color: #fff; + /* Display over codemirror */ + position: relative; + z-index: 100; +} +body > #header #header-container { + padding-bottom: 5px; + padding-top: 5px; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; +} +body > #header .header-bar { + width: 100%; + height: 1px; + background: #e7e7e7; + margin-bottom: -1px; +} +@media print { + body > #header { + display: none !important; + } +} +#header-spacer { + width: 100%; + visibility: hidden; +} +@media print { + #header-spacer { + display: none; + } +} +#ipython_notebook { + padding-left: 0px; + padding-top: 1px; + padding-bottom: 1px; +} +@media (max-width: 991px) { + #ipython_notebook { + margin-left: 10px; + } +} +[dir="rtl"] #ipython_notebook { + float: right !important; +} +#noscript { + width: auto; + padding-top: 16px; + padding-bottom: 16px; + text-align: center; + font-size: 22px; + color: red; + font-weight: bold; +} +#ipython_notebook img { + height: 28px; +} +#site { + width: 100%; + display: none; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + overflow: auto; +} +@media print { + #site { + height: auto !important; + } +} +/* Smaller buttons */ +.ui-button .ui-button-text { + padding: 0.2em 0.8em; + font-size: 77%; +} +input.ui-button { + padding: 0.3em 0.9em; +} +span#login_widget { + float: right; +} +span#login_widget > .button, +#logout { + color: #333; + background-color: #fff; + border-color: #ccc; +} +span#login_widget > .button:focus, +#logout:focus, +span#login_widget > .button.focus, +#logout.focus { + color: #333; + background-color: #e6e6e6; + border-color: #8c8c8c; +} +span#login_widget > .button:hover, +#logout:hover { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +span#login_widget > .button:active, +#logout:active, +span#login_widget > .button.active, +#logout.active, +.open > .dropdown-togglespan#login_widget > .button, +.open > .dropdown-toggle#logout { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +span#login_widget > .button:active:hover, +#logout:active:hover, +span#login_widget > .button.active:hover, +#logout.active:hover, +.open > .dropdown-togglespan#login_widget > .button:hover, +.open > .dropdown-toggle#logout:hover, +span#login_widget > .button:active:focus, +#logout:active:focus, +span#login_widget > .button.active:focus, +#logout.active:focus, +.open > .dropdown-togglespan#login_widget > .button:focus, +.open > .dropdown-toggle#logout:focus, +span#login_widget > .button:active.focus, +#logout:active.focus, +span#login_widget > .button.active.focus, +#logout.active.focus, +.open > .dropdown-togglespan#login_widget > .button.focus, +.open > .dropdown-toggle#logout.focus { + color: #333; + background-color: #d4d4d4; + border-color: #8c8c8c; +} +span#login_widget > .button:active, +#logout:active, +span#login_widget > .button.active, +#logout.active, +.open > .dropdown-togglespan#login_widget > .button, +.open > .dropdown-toggle#logout { + background-image: none; +} +span#login_widget > .button.disabled:hover, +#logout.disabled:hover, +span#login_widget > .button[disabled]:hover, +#logout[disabled]:hover, +fieldset[disabled] span#login_widget > .button:hover, +fieldset[disabled] #logout:hover, +span#login_widget > .button.disabled:focus, +#logout.disabled:focus, +span#login_widget > .button[disabled]:focus, +#logout[disabled]:focus, +fieldset[disabled] span#login_widget > .button:focus, +fieldset[disabled] #logout:focus, +span#login_widget > .button.disabled.focus, +#logout.disabled.focus, +span#login_widget > .button[disabled].focus, +#logout[disabled].focus, +fieldset[disabled] span#login_widget > .button.focus, +fieldset[disabled] #logout.focus { + background-color: #fff; + border-color: #ccc; +} +span#login_widget > .button .badge, +#logout .badge { + color: #fff; + background-color: #333; +} +.nav-header { + text-transform: none; +} +#header > span { + margin-top: 10px; +} +.modal_stretch .modal-dialog { + /* Old browsers */ + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-box-align: stretch; + display: -moz-box; + -moz-box-orient: vertical; + -moz-box-align: stretch; + display: box; + box-orient: vertical; + box-align: stretch; + /* Modern browsers */ + display: flex; + flex-direction: column; + align-items: stretch; + min-height: 80vh; +} +.modal_stretch .modal-dialog .modal-body { + max-height: calc(100vh - 200px); + overflow: auto; + flex: 1; +} +@media (min-width: 768px) { + .modal .modal-dialog { + width: 700px; + } +} +@media (min-width: 768px) { + select.form-control { + margin-left: 12px; + margin-right: 12px; + } +} +/*! +* +* IPython auth +* +*/ +.center-nav { + display: inline-block; + margin-bottom: -4px; +} +/*! +* +* IPython tree view +* +*/ +/* We need an invisible input field on top of the sentense*/ +/* "Drag file onto the list ..." */ +.alternate_upload { + background-color: none; + display: inline; +} +.alternate_upload.form { + padding: 0; + margin: 0; +} +.alternate_upload input.fileinput { + text-align: center; + vertical-align: middle; + display: inline; + opacity: 0; + z-index: 2; + width: 12ex; + margin-right: -12ex; +} +.alternate_upload .btn-upload { + height: 22px; +} +/** + * Primary styles + * + * Author: Jupyter Development Team + */ +[dir="rtl"] #tabs li { + float: right; +} +ul#tabs { + margin-bottom: 4px; +} +[dir="rtl"] ul#tabs { + margin-right: 0px; +} +ul#tabs a { + padding-top: 6px; + padding-bottom: 4px; +} +ul.breadcrumb a:focus, +ul.breadcrumb a:hover { + text-decoration: none; +} +ul.breadcrumb i.icon-home { + font-size: 16px; + margin-right: 4px; +} +ul.breadcrumb span { + color: #5e5e5e; +} +.list_toolbar { + padding: 4px 0 4px 0; + vertical-align: middle; +} +.list_toolbar .tree-buttons { + padding-top: 1px; +} +[dir="rtl"] .list_toolbar .tree-buttons { + float: left !important; +} +[dir="rtl"] .list_toolbar .pull-right { + padding-top: 1px; + float: left !important; +} +[dir="rtl"] .list_toolbar .pull-left { + float: right !important; +} +.dynamic-buttons { + padding-top: 3px; + display: inline-block; +} +.list_toolbar [class*="span"] { + min-height: 24px; +} +.list_header { + font-weight: bold; + background-color: #EEE; +} +.list_placeholder { + font-weight: bold; + padding-top: 4px; + padding-bottom: 4px; + padding-left: 7px; + padding-right: 7px; +} +.list_container { + margin-top: 4px; + margin-bottom: 20px; + border: 1px solid #ddd; + border-radius: 2px; +} +.list_container > div { + border-bottom: 1px solid #ddd; +} +.list_container > div:hover .list-item { + background-color: red; +} +.list_container > div:last-child { + border: none; +} +.list_item:hover .list_item { + background-color: #ddd; +} +.list_item a { + text-decoration: none; +} +.list_item:hover { + background-color: #fafafa; +} +.list_header > div, +.list_item > div { + padding-top: 4px; + padding-bottom: 4px; + padding-left: 7px; + padding-right: 7px; + line-height: 22px; +} +.list_header > div input, +.list_item > div input { + margin-right: 7px; + margin-left: 14px; + vertical-align: baseline; + line-height: 22px; + position: relative; + top: -1px; +} +.list_header > div .item_link, +.list_item > div .item_link { + margin-left: -1px; + vertical-align: baseline; + line-height: 22px; +} +.new-file input[type=checkbox] { + visibility: hidden; +} +.item_name { + line-height: 22px; + height: 24px; +} +.item_icon { + font-size: 14px; + color: #5e5e5e; + margin-right: 7px; + margin-left: 7px; + line-height: 22px; + vertical-align: baseline; +} +.item_buttons { + line-height: 1em; + margin-left: -5px; +} +.item_buttons .btn, +.item_buttons .btn-group, +.item_buttons .input-group { + float: left; +} +.item_buttons > .btn, +.item_buttons > .btn-group, +.item_buttons > .input-group { + margin-left: 5px; +} +.item_buttons .btn { + min-width: 13ex; +} +.item_buttons .running-indicator { + padding-top: 4px; + color: #5cb85c; +} +.item_buttons .kernel-name { + padding-top: 4px; + color: #5bc0de; + margin-right: 7px; + float: left; +} +.toolbar_info { + height: 24px; + line-height: 24px; +} +.list_item input:not([type=checkbox]) { + padding-top: 3px; + padding-bottom: 3px; + height: 22px; + line-height: 14px; + margin: 0px; +} +.highlight_text { + color: blue; +} +#project_name { + display: inline-block; + padding-left: 7px; + margin-left: -2px; +} +#project_name > .breadcrumb { + padding: 0px; + margin-bottom: 0px; + background-color: transparent; + font-weight: bold; +} +#tree-selector { + padding-right: 0px; +} +[dir="rtl"] #tree-selector a { + float: right; +} +#button-select-all { + min-width: 50px; +} +#select-all { + margin-left: 7px; + margin-right: 2px; +} +.menu_icon { + margin-right: 2px; +} +.tab-content .row { + margin-left: 0px; + margin-right: 0px; +} +.folder_icon:before { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: "\f114"; +} +.folder_icon:before.pull-left { + margin-right: .3em; +} +.folder_icon:before.pull-right { + margin-left: .3em; +} +.notebook_icon:before { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: "\f02d"; + position: relative; + top: -1px; +} +.notebook_icon:before.pull-left { + margin-right: .3em; +} +.notebook_icon:before.pull-right { + margin-left: .3em; +} +.running_notebook_icon:before { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: "\f02d"; + position: relative; + top: -1px; + color: #5cb85c; +} +.running_notebook_icon:before.pull-left { + margin-right: .3em; +} +.running_notebook_icon:before.pull-right { + margin-left: .3em; +} +.file_icon:before { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: "\f016"; + position: relative; + top: -2px; +} +.file_icon:before.pull-left { + margin-right: .3em; +} +.file_icon:before.pull-right { + margin-left: .3em; +} +#notebook_toolbar .pull-right { + padding-top: 0px; + margin-right: -1px; +} +ul#new-menu { + left: auto; + right: 0; +} +[dir="rtl"] #new-menu { + text-align: right; +} +.kernel-menu-icon { + padding-right: 12px; + width: 24px; + content: "\f096"; +} +.kernel-menu-icon:before { + content: "\f096"; +} +.kernel-menu-icon-current:before { + content: "\f00c"; +} +#tab_content { + padding-top: 20px; +} +#running .panel-group .panel { + margin-top: 3px; + margin-bottom: 1em; +} +#running .panel-group .panel .panel-heading { + background-color: #EEE; + padding-top: 4px; + padding-bottom: 4px; + padding-left: 7px; + padding-right: 7px; + line-height: 22px; +} +#running .panel-group .panel .panel-heading a:focus, +#running .panel-group .panel .panel-heading a:hover { + text-decoration: none; +} +#running .panel-group .panel .panel-body { + padding: 0px; +} +#running .panel-group .panel .panel-body .list_container { + margin-top: 0px; + margin-bottom: 0px; + border: 0px; + border-radius: 0px; +} +#running .panel-group .panel .panel-body .list_container .list_item { + border-bottom: 1px solid #ddd; +} +#running .panel-group .panel .panel-body .list_container .list_item:last-child { + border-bottom: 0px; +} +[dir="rtl"] #running .col-sm-8 { + float: right !important; +} +.delete-button { + display: none; +} +.duplicate-button { + display: none; +} +.rename-button { + display: none; +} +.shutdown-button { + display: none; +} +.dynamic-instructions { + display: inline-block; + padding-top: 4px; +} +/*! +* +* IPython text editor webapp +* +*/ +.selected-keymap i.fa { + padding: 0px 5px; +} +.selected-keymap i.fa:before { + content: "\f00c"; +} +#mode-menu { + overflow: auto; + max-height: 20em; +} +.edit_app #header { + -webkit-box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2); + box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2); +} +.edit_app #menubar .navbar { + /* Use a negative 1 bottom margin, so the border overlaps the border of the + header */ + margin-bottom: -1px; +} +.dirty-indicator { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + width: 20px; +} +.dirty-indicator.pull-left { + margin-right: .3em; +} +.dirty-indicator.pull-right { + margin-left: .3em; +} +.dirty-indicator-dirty { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + width: 20px; +} +.dirty-indicator-dirty.pull-left { + margin-right: .3em; +} +.dirty-indicator-dirty.pull-right { + margin-left: .3em; +} +.dirty-indicator-clean { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + width: 20px; +} +.dirty-indicator-clean.pull-left { + margin-right: .3em; +} +.dirty-indicator-clean.pull-right { + margin-left: .3em; +} +.dirty-indicator-clean:before { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: "\f00c"; +} +.dirty-indicator-clean:before.pull-left { + margin-right: .3em; +} +.dirty-indicator-clean:before.pull-right { + margin-left: .3em; +} +#filename { + font-size: 16pt; + display: table; + padding: 0px 5px; +} +#current-mode { + padding-left: 5px; + padding-right: 5px; +} +#texteditor-backdrop { + padding-top: 20px; + padding-bottom: 20px; +} +@media not print { + #texteditor-backdrop { + background-color: #EEE; + } +} +@media print { + #texteditor-backdrop #texteditor-container .CodeMirror-gutter, + #texteditor-backdrop #texteditor-container .CodeMirror-gutters { + background-color: #fff; + } +} +@media not print { + #texteditor-backdrop #texteditor-container .CodeMirror-gutter, + #texteditor-backdrop #texteditor-container .CodeMirror-gutters { + background-color: #fff; + } +} +@media not print { + #texteditor-backdrop #texteditor-container { + padding: 0px; + background-color: #fff; + -webkit-box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2); + box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2); + } +} +/*! +* +* IPython notebook +* +*/ +/* CSS font colors for translated ANSI colors. */ +.ansibold { + font-weight: bold; +} +/* use dark versions for foreground, to improve visibility */ +.ansiblack { + color: black; +} +.ansired { + color: darkred; +} +.ansigreen { + color: darkgreen; +} +.ansiyellow { + color: #c4a000; +} +.ansiblue { + color: darkblue; +} +.ansipurple { + color: darkviolet; +} +.ansicyan { + color: steelblue; +} +.ansigray { + color: gray; +} +/* and light for background, for the same reason */ +.ansibgblack { + background-color: black; +} +.ansibgred { + background-color: red; +} +.ansibggreen { + background-color: green; +} +.ansibgyellow { + background-color: yellow; +} +.ansibgblue { + background-color: blue; +} +.ansibgpurple { + background-color: magenta; +} +.ansibgcyan { + background-color: cyan; +} +.ansibggray { + background-color: gray; +} +div.cell { + /* Old browsers */ + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-box-align: stretch; + display: -moz-box; + -moz-box-orient: vertical; + -moz-box-align: stretch; + display: box; + box-orient: vertical; + box-align: stretch; + /* Modern browsers */ + display: flex; + flex-direction: column; + align-items: stretch; + border-radius: 2px; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + border-width: 1px; + border-style: solid; + border-color: transparent; + width: 100%; + padding: 5px; + /* This acts as a spacer between cells, that is outside the border */ + margin: 0px; + outline: none; + border-left-width: 1px; + padding-left: 5px; + background: linear-gradient(to right, transparent -40px, transparent 1px, transparent 1px, transparent 100%); +} +div.cell.jupyter-soft-selected { + border-left-color: #90CAF9; + border-left-color: #E3F2FD; + border-left-width: 1px; + padding-left: 5px; + border-right-color: #E3F2FD; + border-right-width: 1px; + background: #E3F2FD; +} +@media print { + div.cell.jupyter-soft-selected { + border-color: transparent; + } +} +div.cell.selected { + border-color: #ababab; + border-left-width: 0px; + padding-left: 6px; + background: linear-gradient(to right, #42A5F5 -40px, #42A5F5 5px, transparent 5px, transparent 100%); +} +@media print { + div.cell.selected { + border-color: transparent; + } +} +div.cell.selected.jupyter-soft-selected { + border-left-width: 0; + padding-left: 6px; + background: linear-gradient(to right, #42A5F5 -40px, #42A5F5 7px, #E3F2FD 7px, #E3F2FD 100%); +} +.edit_mode div.cell.selected { + border-color: #66BB6A; + border-left-width: 0px; + padding-left: 6px; + background: linear-gradient(to right, #66BB6A -40px, #66BB6A 5px, transparent 5px, transparent 100%); +} +@media print { + .edit_mode div.cell.selected { + border-color: transparent; + } +} +.prompt { + /* This needs to be wide enough for 3 digit prompt numbers: In[100]: */ + min-width: 14ex; + /* This padding is tuned to match the padding on the CodeMirror editor. */ + padding: 0.4em; + margin: 0px; + font-family: monospace; + text-align: right; + /* This has to match that of the the CodeMirror class line-height below */ + line-height: 1.21429em; + /* Don't highlight prompt number selection */ + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + /* Use default cursor */ + cursor: default; +} +@media (max-width: 540px) { + .prompt { + text-align: left; + } +} +div.inner_cell { + min-width: 0; + /* Old browsers */ + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-box-align: stretch; + display: -moz-box; + -moz-box-orient: vertical; + -moz-box-align: stretch; + display: box; + box-orient: vertical; + box-align: stretch; + /* Modern browsers */ + display: flex; + flex-direction: column; + align-items: stretch; + /* Old browsers */ + -webkit-box-flex: 1; + -moz-box-flex: 1; + box-flex: 1; + /* Modern browsers */ + flex: 1; +} +/* input_area and input_prompt must match in top border and margin for alignment */ +div.input_area { + border: 1px solid #cfcfcf; + border-radius: 2px; + background: #f7f7f7; + line-height: 1.21429em; +} +/* This is needed so that empty prompt areas can collapse to zero height when there + is no content in the output_subarea and the prompt. The main purpose of this is + to make sure that empty JavaScript output_subareas have no height. */ +div.prompt:empty { + padding-top: 0; + padding-bottom: 0; +} +div.unrecognized_cell { + padding: 5px 5px 5px 0px; + /* Old browsers */ + display: -webkit-box; + -webkit-box-orient: horizontal; + -webkit-box-align: stretch; + display: -moz-box; + -moz-box-orient: horizontal; + -moz-box-align: stretch; + display: box; + box-orient: horizontal; + box-align: stretch; + /* Modern browsers */ + display: flex; + flex-direction: row; + align-items: stretch; +} +div.unrecognized_cell .inner_cell { + border-radius: 2px; + padding: 5px; + font-weight: bold; + color: red; + border: 1px solid #cfcfcf; + background: #eaeaea; +} +div.unrecognized_cell .inner_cell a { + color: inherit; + text-decoration: none; +} +div.unrecognized_cell .inner_cell a:hover { + color: inherit; + text-decoration: none; +} +@media (max-width: 540px) { + div.unrecognized_cell > div.prompt { + display: none; + } +} +div.code_cell { + /* avoid page breaking on code cells when printing */ +} +@media print { + div.code_cell { + page-break-inside: avoid; + } +} +/* any special styling for code cells that are currently running goes here */ +div.input { + page-break-inside: avoid; + /* Old browsers */ + display: -webkit-box; + -webkit-box-orient: horizontal; + -webkit-box-align: stretch; + display: -moz-box; + -moz-box-orient: horizontal; + -moz-box-align: stretch; + display: box; + box-orient: horizontal; + box-align: stretch; + /* Modern browsers */ + display: flex; + flex-direction: row; + align-items: stretch; +} +@media (max-width: 540px) { + div.input { + /* Old browsers */ + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-box-align: stretch; + display: -moz-box; + -moz-box-orient: vertical; + -moz-box-align: stretch; + display: box; + box-orient: vertical; + box-align: stretch; + /* Modern browsers */ + display: flex; + flex-direction: column; + align-items: stretch; + } +} +/* input_area and input_prompt must match in top border and margin for alignment */ +div.input_prompt { + color: #303F9F; + border-top: 1px solid transparent; +} +div.input_area > div.highlight { + margin: 0.4em; + border: none; + padding: 0px; + background-color: transparent; +} +div.input_area > div.highlight > pre { + margin: 0px; + border: none; + padding: 0px; + background-color: transparent; +} +/* The following gets added to the if it is detected that the user has a + * monospace font with inconsistent normal/bold/italic height. See + * notebookmain.js. Such fonts will have keywords vertically offset with + * respect to the rest of the text. The user should select a better font. + * See: https://github.com/ipython/ipython/issues/1503 + * + * .CodeMirror span { + * vertical-align: bottom; + * } + */ +.CodeMirror { + line-height: 1.21429em; + /* Changed from 1em to our global default */ + font-size: 14px; + height: auto; + /* Changed to auto to autogrow */ + background: none; + /* Changed from white to allow our bg to show through */ +} +.CodeMirror-scroll { + /* The CodeMirror docs are a bit fuzzy on if overflow-y should be hidden or visible.*/ + /* We have found that if it is visible, vertical scrollbars appear with font size changes.*/ + overflow-y: hidden; + overflow-x: auto; +} +.CodeMirror-lines { + /* In CM2, this used to be 0.4em, but in CM3 it went to 4px. We need the em value because */ + /* we have set a different line-height and want this to scale with that. */ + padding: 0.4em; +} +.CodeMirror-linenumber { + padding: 0 8px 0 4px; +} +.CodeMirror-gutters { + border-bottom-left-radius: 2px; + border-top-left-radius: 2px; +} +.CodeMirror pre { + /* In CM3 this went to 4px from 0 in CM2. We need the 0 value because of how we size */ + /* .CodeMirror-lines */ + padding: 0; + border: 0; + border-radius: 0; +} +/* + +Original style from softwaremaniacs.org (c) Ivan Sagalaev +Adapted from GitHub theme + +*/ +.highlight-base { + color: #000; +} +.highlight-variable { + color: #000; +} +.highlight-variable-2 { + color: #1a1a1a; +} +.highlight-variable-3 { + color: #333333; +} +.highlight-string { + color: #BA2121; +} +.highlight-comment { + color: #408080; + font-style: italic; +} +.highlight-number { + color: #080; +} +.highlight-atom { + color: #88F; +} +.highlight-keyword { + color: #008000; + font-weight: bold; +} +.highlight-builtin { + color: #008000; +} +.highlight-error { + color: #f00; +} +.highlight-operator { + color: #AA22FF; + font-weight: bold; +} +.highlight-meta { + color: #AA22FF; +} +/* previously not defined, copying from default codemirror */ +.highlight-def { + color: #00f; +} +.highlight-string-2 { + color: #f50; +} +.highlight-qualifier { + color: #555; +} +.highlight-bracket { + color: #997; +} +.highlight-tag { + color: #170; +} +.highlight-attribute { + color: #00c; +} +.highlight-header { + color: blue; +} +.highlight-quote { + color: #090; +} +.highlight-link { + color: #00c; +} +/* apply the same style to codemirror */ +.cm-s-ipython span.cm-keyword { + color: #008000; + font-weight: bold; +} +.cm-s-ipython span.cm-atom { + color: #88F; +} +.cm-s-ipython span.cm-number { + color: #080; +} +.cm-s-ipython span.cm-def { + color: #00f; +} +.cm-s-ipython span.cm-variable { + color: #000; +} +.cm-s-ipython span.cm-operator { + color: #AA22FF; + font-weight: bold; +} +.cm-s-ipython span.cm-variable-2 { + color: #1a1a1a; +} +.cm-s-ipython span.cm-variable-3 { + color: #333333; +} +.cm-s-ipython span.cm-comment { + color: #408080; + font-style: italic; +} +.cm-s-ipython span.cm-string { + color: #BA2121; +} +.cm-s-ipython span.cm-string-2 { + color: #f50; +} +.cm-s-ipython span.cm-meta { + color: #AA22FF; +} +.cm-s-ipython span.cm-qualifier { + color: #555; +} +.cm-s-ipython span.cm-builtin { + color: #008000; +} +.cm-s-ipython span.cm-bracket { + color: #997; +} +.cm-s-ipython span.cm-tag { + color: #170; +} +.cm-s-ipython span.cm-attribute { + color: #00c; +} +.cm-s-ipython span.cm-header { + color: blue; +} +.cm-s-ipython span.cm-quote { + color: #090; +} +.cm-s-ipython span.cm-link { + color: #00c; +} +.cm-s-ipython span.cm-error { + color: #f00; +} +.cm-s-ipython span.cm-tab { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=); + background-position: right; + background-repeat: no-repeat; +} +div.output_wrapper { + /* this position must be relative to enable descendents to be absolute within it */ + position: relative; + /* Old browsers */ + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-box-align: stretch; + display: -moz-box; + -moz-box-orient: vertical; + -moz-box-align: stretch; + display: box; + box-orient: vertical; + box-align: stretch; + /* Modern browsers */ + display: flex; + flex-direction: column; + align-items: stretch; + z-index: 1; +} +/* class for the output area when it should be height-limited */ +div.output_scroll { + /* ideally, this would be max-height, but FF barfs all over that */ + height: 24em; + /* FF needs this *and the wrapper* to specify full width, or it will shrinkwrap */ + width: 100%; + overflow: auto; + border-radius: 2px; + -webkit-box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.8); + box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.8); + display: block; +} +/* output div while it is collapsed */ +div.output_collapsed { + margin: 0px; + padding: 0px; + /* Old browsers */ + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-box-align: stretch; + display: -moz-box; + -moz-box-orient: vertical; + -moz-box-align: stretch; + display: box; + box-orient: vertical; + box-align: stretch; + /* Modern browsers */ + display: flex; + flex-direction: column; + align-items: stretch; +} +div.out_prompt_overlay { + height: 100%; + padding: 0px 0.4em; + position: absolute; + border-radius: 2px; +} +div.out_prompt_overlay:hover { + /* use inner shadow to get border that is computed the same on WebKit/FF */ + -webkit-box-shadow: inset 0 0 1px #000; + box-shadow: inset 0 0 1px #000; + background: rgba(240, 240, 240, 0.5); +} +div.output_prompt { + color: #D84315; +} +/* This class is the outer container of all output sections. */ +div.output_area { + padding: 0px; + page-break-inside: avoid; + /* Old browsers */ + display: -webkit-box; + -webkit-box-orient: horizontal; + -webkit-box-align: stretch; + display: -moz-box; + -moz-box-orient: horizontal; + -moz-box-align: stretch; + display: box; + box-orient: horizontal; + box-align: stretch; + /* Modern browsers */ + display: flex; + flex-direction: row; + align-items: stretch; +} +div.output_area .MathJax_Display { + text-align: left !important; +} +div.output_area .rendered_html table { + margin-left: 0; + margin-right: 0; +} +div.output_area .rendered_html img { + margin-left: 0; + margin-right: 0; +} +div.output_area img, +div.output_area svg { + max-width: 100%; + height: auto; +} +div.output_area img.unconfined, +div.output_area svg.unconfined { + max-width: none; +} +/* This is needed to protect the pre formating from global settings such + as that of bootstrap */ +.output { + /* Old browsers */ + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-box-align: stretch; + display: -moz-box; + -moz-box-orient: vertical; + -moz-box-align: stretch; + display: box; + box-orient: vertical; + box-align: stretch; + /* Modern browsers */ + display: flex; + flex-direction: column; + align-items: stretch; +} +@media (max-width: 540px) { + div.output_area { + /* Old browsers */ + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-box-align: stretch; + display: -moz-box; + -moz-box-orient: vertical; + -moz-box-align: stretch; + display: box; + box-orient: vertical; + box-align: stretch; + /* Modern browsers */ + display: flex; + flex-direction: column; + align-items: stretch; + } +} +div.output_area pre { + margin: 0; + padding: 0; + border: 0; + vertical-align: baseline; + color: black; + background-color: transparent; + border-radius: 0; +} +/* This class is for the output subarea inside the output_area and after + the prompt div. */ +div.output_subarea { + overflow-x: auto; + padding: 0.4em; + /* Old browsers */ + -webkit-box-flex: 1; + -moz-box-flex: 1; + box-flex: 1; + /* Modern browsers */ + flex: 1; + max-width: calc(100% - 14ex); +} +div.output_scroll div.output_subarea { + overflow-x: visible; +} +/* The rest of the output_* classes are for special styling of the different + output types */ +/* all text output has this class: */ +div.output_text { + text-align: left; + color: #000; + /* This has to match that of the the CodeMirror class line-height below */ + line-height: 1.21429em; +} +/* stdout/stderr are 'text' as well as 'stream', but execute_result/error are *not* streams */ +div.output_stderr { + background: #fdd; + /* very light red background for stderr */ +} +div.output_latex { + text-align: left; +} +/* Empty output_javascript divs should have no height */ +div.output_javascript:empty { + padding: 0; +} +.js-error { + color: darkred; +} +/* raw_input styles */ +div.raw_input_container { + line-height: 1.21429em; + padding-top: 5px; +} +pre.raw_input_prompt { + /* nothing needed here. */ +} +input.raw_input { + font-family: monospace; + font-size: inherit; + color: inherit; + width: auto; + /* make sure input baseline aligns with prompt */ + vertical-align: baseline; + /* padding + margin = 0.5em between prompt and cursor */ + padding: 0em 0.25em; + margin: 0em 0.25em; +} +input.raw_input:focus { + box-shadow: none; +} +p.p-space { + margin-bottom: 10px; +} +div.output_unrecognized { + padding: 5px; + font-weight: bold; + color: red; +} +div.output_unrecognized a { + color: inherit; + text-decoration: none; +} +div.output_unrecognized a:hover { + color: inherit; + text-decoration: none; +} +.rendered_html { + color: #000; + /* any extras will just be numbers: */ +} +.rendered_html em { + font-style: italic; +} +.rendered_html strong { + font-weight: bold; +} +.rendered_html u { + text-decoration: underline; +} +.rendered_html :link { + text-decoration: underline; +} +.rendered_html :visited { + text-decoration: underline; +} +.rendered_html h1 { + font-size: 185.7%; + margin: 1.08em 0 0 0; + font-weight: bold; + line-height: 1.0; +} +.rendered_html h2 { + font-size: 157.1%; + margin: 1.27em 0 0 0; + font-weight: bold; + line-height: 1.0; +} +.rendered_html h3 { + font-size: 128.6%; + margin: 1.55em 0 0 0; + font-weight: bold; + line-height: 1.0; +} +.rendered_html h4 { + font-size: 100%; + margin: 2em 0 0 0; + font-weight: bold; + line-height: 1.0; +} +.rendered_html h5 { + font-size: 100%; + margin: 2em 0 0 0; + font-weight: bold; + line-height: 1.0; + font-style: italic; +} +.rendered_html h6 { + font-size: 100%; + margin: 2em 0 0 0; + font-weight: bold; + line-height: 1.0; + font-style: italic; +} +.rendered_html h1:first-child { + margin-top: 0.538em; +} +.rendered_html h2:first-child { + margin-top: 0.636em; +} +.rendered_html h3:first-child { + margin-top: 0.777em; +} +.rendered_html h4:first-child { + margin-top: 1em; +} +.rendered_html h5:first-child { + margin-top: 1em; +} +.rendered_html h6:first-child { + margin-top: 1em; +} +.rendered_html ul { + list-style: disc; + margin: 0em 2em; + padding-left: 0px; +} +.rendered_html ul ul { + list-style: square; + margin: 0em 2em; +} +.rendered_html ul ul ul { + list-style: circle; + margin: 0em 2em; +} +.rendered_html ol { + list-style: decimal; + margin: 0em 2em; + padding-left: 0px; +} +.rendered_html ol ol { + list-style: upper-alpha; + margin: 0em 2em; +} +.rendered_html ol ol ol { + list-style: lower-alpha; + margin: 0em 2em; +} +.rendered_html ol ol ol ol { + list-style: lower-roman; + margin: 0em 2em; +} +.rendered_html ol ol ol ol ol { + list-style: decimal; + margin: 0em 2em; +} +.rendered_html * + ul { + margin-top: 1em; +} +.rendered_html * + ol { + margin-top: 1em; +} +.rendered_html hr { + color: black; + background-color: black; +} +.rendered_html pre { + margin: 1em 2em; +} +.rendered_html pre, +.rendered_html code { + border: 0; + background-color: #fff; + color: #000; + font-size: 100%; + padding: 0px; +} +.rendered_html blockquote { + margin: 1em 2em; +} +.rendered_html table { + margin-left: auto; + margin-right: auto; + border: 1px solid black; + border-collapse: collapse; +} +.rendered_html tr, +.rendered_html th, +.rendered_html td { + border: 1px solid black; + border-collapse: collapse; + margin: 1em 2em; +} +.rendered_html td, +.rendered_html th { + text-align: left; + vertical-align: middle; + padding: 4px; +} +.rendered_html th { + font-weight: bold; +} +.rendered_html * + table { + margin-top: 1em; +} +.rendered_html p { + text-align: left; +} +.rendered_html * + p { + margin-top: 1em; +} +.rendered_html img { + display: block; + margin-left: auto; + margin-right: auto; +} +.rendered_html * + img { + margin-top: 1em; +} +.rendered_html img, +.rendered_html svg { + max-width: 100%; + height: auto; +} +.rendered_html img.unconfined, +.rendered_html svg.unconfined { + max-width: none; +} +div.text_cell { + /* Old browsers */ + display: -webkit-box; + -webkit-box-orient: horizontal; + -webkit-box-align: stretch; + display: -moz-box; + -moz-box-orient: horizontal; + -moz-box-align: stretch; + display: box; + box-orient: horizontal; + box-align: stretch; + /* Modern browsers */ + display: flex; + flex-direction: row; + align-items: stretch; +} +@media (max-width: 540px) { + div.text_cell > div.prompt { + display: none; + } +} +div.text_cell_render { + /*font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;*/ + outline: none; + resize: none; + width: inherit; + border-style: none; + padding: 0.5em 0.5em 0.5em 0.4em; + color: #000; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; +} +a.anchor-link:link { + text-decoration: none; + padding: 0px 20px; + visibility: hidden; +} +h1:hover .anchor-link, +h2:hover .anchor-link, +h3:hover .anchor-link, +h4:hover .anchor-link, +h5:hover .anchor-link, +h6:hover .anchor-link { + visibility: visible; +} +.text_cell.rendered .input_area { + display: none; +} +.text_cell.rendered .rendered_html { + overflow-x: auto; + overflow-y: hidden; +} +.text_cell.unrendered .text_cell_render { + display: none; +} +.cm-header-1, +.cm-header-2, +.cm-header-3, +.cm-header-4, +.cm-header-5, +.cm-header-6 { + font-weight: bold; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} +.cm-header-1 { + font-size: 185.7%; +} +.cm-header-2 { + font-size: 157.1%; +} +.cm-header-3 { + font-size: 128.6%; +} +.cm-header-4 { + font-size: 110%; +} +.cm-header-5 { + font-size: 100%; + font-style: italic; +} +.cm-header-6 { + font-size: 100%; + font-style: italic; +} +/*! +* +* IPython notebook webapp +* +*/ +@media (max-width: 767px) { + .notebook_app { + padding-left: 0px; + padding-right: 0px; + } +} +#ipython-main-app { + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + height: 100%; +} +div#notebook_panel { + margin: 0px; + padding: 0px; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + height: 100%; +} +div#notebook { + font-size: 14px; + line-height: 20px; + overflow-y: hidden; + overflow-x: auto; + width: 100%; + /* This spaces the page away from the edge of the notebook area */ + padding-top: 20px; + margin: 0px; + outline: none; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + min-height: 100%; +} +@media not print { + #notebook-container { + padding: 15px; + background-color: #fff; + min-height: 0; + -webkit-box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2); + box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2); + } +} +@media print { + #notebook-container { + width: 100%; + } +} +div.ui-widget-content { + border: 1px solid #ababab; + outline: none; +} +pre.dialog { + background-color: #f7f7f7; + border: 1px solid #ddd; + border-radius: 2px; + padding: 0.4em; + padding-left: 2em; +} +p.dialog { + padding: 0.2em; +} +/* Word-wrap output correctly. This is the CSS3 spelling, though Firefox seems + to not honor it correctly. Webkit browsers (Chrome, rekonq, Safari) do. + */ +pre, +code, +kbd, +samp { + white-space: pre-wrap; +} +#fonttest { + font-family: monospace; +} +p { + margin-bottom: 0; +} +.end_space { + min-height: 100px; + transition: height .2s ease; +} +.notebook_app > #header { + -webkit-box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2); + box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2); +} +@media not print { + .notebook_app { + background-color: #EEE; + } +} +kbd { + border-style: solid; + border-width: 1px; + box-shadow: none; + margin: 2px; + padding-left: 2px; + padding-right: 2px; + padding-top: 1px; + padding-bottom: 1px; +} +/* CSS for the cell toolbar */ +.celltoolbar { + border: thin solid #CFCFCF; + border-bottom: none; + background: #EEE; + border-radius: 2px 2px 0px 0px; + width: 100%; + height: 29px; + padding-right: 4px; + /* Old browsers */ + display: -webkit-box; + -webkit-box-orient: horizontal; + -webkit-box-align: stretch; + display: -moz-box; + -moz-box-orient: horizontal; + -moz-box-align: stretch; + display: box; + box-orient: horizontal; + box-align: stretch; + /* Modern browsers */ + display: flex; + flex-direction: row; + align-items: stretch; + /* Old browsers */ + -webkit-box-pack: end; + -moz-box-pack: end; + box-pack: end; + /* Modern browsers */ + justify-content: flex-end; + display: -webkit-flex; +} +@media print { + .celltoolbar { + display: none; + } +} +.ctb_hideshow { + display: none; + vertical-align: bottom; +} +/* ctb_show is added to the ctb_hideshow div to show the cell toolbar. + Cell toolbars are only shown when the ctb_global_show class is also set. +*/ +.ctb_global_show .ctb_show.ctb_hideshow { + display: block; +} +.ctb_global_show .ctb_show + .input_area, +.ctb_global_show .ctb_show + div.text_cell_input, +.ctb_global_show .ctb_show ~ div.text_cell_render { + border-top-right-radius: 0px; + border-top-left-radius: 0px; +} +.ctb_global_show .ctb_show ~ div.text_cell_render { + border: 1px solid #cfcfcf; +} +.celltoolbar { + font-size: 87%; + padding-top: 3px; +} +.celltoolbar select { + display: block; + width: 100%; + height: 32px; + padding: 6px 12px; + font-size: 13px; + line-height: 1.42857143; + color: #555555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 2px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 1px; + width: inherit; + font-size: inherit; + height: 22px; + padding: 0px; + display: inline-block; +} +.celltoolbar select:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); +} +.celltoolbar select::-moz-placeholder { + color: #999; + opacity: 1; +} +.celltoolbar select:-ms-input-placeholder { + color: #999; +} +.celltoolbar select::-webkit-input-placeholder { + color: #999; +} +.celltoolbar select::-ms-expand { + border: 0; + background-color: transparent; +} +.celltoolbar select[disabled], +.celltoolbar select[readonly], +fieldset[disabled] .celltoolbar select { + background-color: #eeeeee; + opacity: 1; +} +.celltoolbar select[disabled], +fieldset[disabled] .celltoolbar select { + cursor: not-allowed; +} +textarea.celltoolbar select { + height: auto; +} +select.celltoolbar select { + height: 30px; + line-height: 30px; +} +textarea.celltoolbar select, +select[multiple].celltoolbar select { + height: auto; +} +.celltoolbar label { + margin-left: 5px; + margin-right: 5px; +} +.completions { + position: absolute; + z-index: 110; + overflow: hidden; + border: 1px solid #ababab; + border-radius: 2px; + -webkit-box-shadow: 0px 6px 10px -1px #adadad; + box-shadow: 0px 6px 10px -1px #adadad; + line-height: 1; +} +.completions select { + background: white; + outline: none; + border: none; + padding: 0px; + margin: 0px; + overflow: auto; + font-family: monospace; + font-size: 110%; + color: #000; + width: auto; +} +.completions select option.context { + color: #286090; +} +#kernel_logo_widget { + float: right !important; + float: right; +} +#kernel_logo_widget .current_kernel_logo { + display: none; + margin-top: -1px; + margin-bottom: -1px; + width: 32px; + height: 32px; +} +#menubar { + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + margin-top: 1px; +} +#menubar .navbar { + border-top: 1px; + border-radius: 0px 0px 2px 2px; + margin-bottom: 0px; +} +#menubar .navbar-toggle { + float: left; + padding-top: 7px; + padding-bottom: 7px; + border: none; +} +#menubar .navbar-collapse { + clear: left; +} +.nav-wrapper { + border-bottom: 1px solid #e7e7e7; +} +i.menu-icon { + padding-top: 4px; +} +ul#help_menu li a { + overflow: hidden; + padding-right: 2.2em; +} +ul#help_menu li a i { + margin-right: -1.2em; +} +.dropdown-submenu { + position: relative; +} +.dropdown-submenu > .dropdown-menu { + top: 0; + left: 100%; + margin-top: -6px; + margin-left: -1px; +} +.dropdown-submenu:hover > .dropdown-menu { + display: block; +} +.dropdown-submenu > a:after { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + display: block; + content: "\f0da"; + float: right; + color: #333333; + margin-top: 2px; + margin-right: -10px; +} +.dropdown-submenu > a:after.pull-left { + margin-right: .3em; +} +.dropdown-submenu > a:after.pull-right { + margin-left: .3em; +} +.dropdown-submenu:hover > a:after { + color: #262626; +} +.dropdown-submenu.pull-left { + float: none; +} +.dropdown-submenu.pull-left > .dropdown-menu { + left: -100%; + margin-left: 10px; +} +#notification_area { + float: right !important; + float: right; + z-index: 10; +} +.indicator_area { + float: right !important; + float: right; + color: #777; + margin-left: 5px; + margin-right: 5px; + width: 11px; + z-index: 10; + text-align: center; + width: auto; +} +#kernel_indicator { + float: right !important; + float: right; + color: #777; + margin-left: 5px; + margin-right: 5px; + width: 11px; + z-index: 10; + text-align: center; + width: auto; + border-left: 1px solid; +} +#kernel_indicator .kernel_indicator_name { + padding-left: 5px; + padding-right: 5px; +} +#modal_indicator { + float: right !important; + float: right; + color: #777; + margin-left: 5px; + margin-right: 5px; + width: 11px; + z-index: 10; + text-align: center; + width: auto; +} +#readonly-indicator { + float: right !important; + float: right; + color: #777; + margin-left: 5px; + margin-right: 5px; + width: 11px; + z-index: 10; + text-align: center; + width: auto; + margin-top: 2px; + margin-bottom: 0px; + margin-left: 0px; + margin-right: 0px; + display: none; +} +.modal_indicator:before { + width: 1.28571429em; + text-align: center; +} +.edit_mode .modal_indicator:before { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: "\f040"; +} +.edit_mode .modal_indicator:before.pull-left { + margin-right: .3em; +} +.edit_mode .modal_indicator:before.pull-right { + margin-left: .3em; +} +.command_mode .modal_indicator:before { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: ' '; +} +.command_mode .modal_indicator:before.pull-left { + margin-right: .3em; +} +.command_mode .modal_indicator:before.pull-right { + margin-left: .3em; +} +.kernel_idle_icon:before { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: "\f10c"; +} +.kernel_idle_icon:before.pull-left { + margin-right: .3em; +} +.kernel_idle_icon:before.pull-right { + margin-left: .3em; +} +.kernel_busy_icon:before { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: "\f111"; +} +.kernel_busy_icon:before.pull-left { + margin-right: .3em; +} +.kernel_busy_icon:before.pull-right { + margin-left: .3em; +} +.kernel_dead_icon:before { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: "\f1e2"; +} +.kernel_dead_icon:before.pull-left { + margin-right: .3em; +} +.kernel_dead_icon:before.pull-right { + margin-left: .3em; +} +.kernel_disconnected_icon:before { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: "\f127"; +} +.kernel_disconnected_icon:before.pull-left { + margin-right: .3em; +} +.kernel_disconnected_icon:before.pull-right { + margin-left: .3em; +} +.notification_widget { + color: #777; + z-index: 10; + background: rgba(240, 240, 240, 0.5); + margin-right: 4px; + color: #333; + background-color: #fff; + border-color: #ccc; +} +.notification_widget:focus, +.notification_widget.focus { + color: #333; + background-color: #e6e6e6; + border-color: #8c8c8c; +} +.notification_widget:hover { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.notification_widget:active, +.notification_widget.active, +.open > .dropdown-toggle.notification_widget { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.notification_widget:active:hover, +.notification_widget.active:hover, +.open > .dropdown-toggle.notification_widget:hover, +.notification_widget:active:focus, +.notification_widget.active:focus, +.open > .dropdown-toggle.notification_widget:focus, +.notification_widget:active.focus, +.notification_widget.active.focus, +.open > .dropdown-toggle.notification_widget.focus { + color: #333; + background-color: #d4d4d4; + border-color: #8c8c8c; +} +.notification_widget:active, +.notification_widget.active, +.open > .dropdown-toggle.notification_widget { + background-image: none; +} +.notification_widget.disabled:hover, +.notification_widget[disabled]:hover, +fieldset[disabled] .notification_widget:hover, +.notification_widget.disabled:focus, +.notification_widget[disabled]:focus, +fieldset[disabled] .notification_widget:focus, +.notification_widget.disabled.focus, +.notification_widget[disabled].focus, +fieldset[disabled] .notification_widget.focus { + background-color: #fff; + border-color: #ccc; +} +.notification_widget .badge { + color: #fff; + background-color: #333; +} +.notification_widget.warning { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; +} +.notification_widget.warning:focus, +.notification_widget.warning.focus { + color: #fff; + background-color: #ec971f; + border-color: #985f0d; +} +.notification_widget.warning:hover { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.notification_widget.warning:active, +.notification_widget.warning.active, +.open > .dropdown-toggle.notification_widget.warning { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.notification_widget.warning:active:hover, +.notification_widget.warning.active:hover, +.open > .dropdown-toggle.notification_widget.warning:hover, +.notification_widget.warning:active:focus, +.notification_widget.warning.active:focus, +.open > .dropdown-toggle.notification_widget.warning:focus, +.notification_widget.warning:active.focus, +.notification_widget.warning.active.focus, +.open > .dropdown-toggle.notification_widget.warning.focus { + color: #fff; + background-color: #d58512; + border-color: #985f0d; +} +.notification_widget.warning:active, +.notification_widget.warning.active, +.open > .dropdown-toggle.notification_widget.warning { + background-image: none; +} +.notification_widget.warning.disabled:hover, +.notification_widget.warning[disabled]:hover, +fieldset[disabled] .notification_widget.warning:hover, +.notification_widget.warning.disabled:focus, +.notification_widget.warning[disabled]:focus, +fieldset[disabled] .notification_widget.warning:focus, +.notification_widget.warning.disabled.focus, +.notification_widget.warning[disabled].focus, +fieldset[disabled] .notification_widget.warning.focus { + background-color: #f0ad4e; + border-color: #eea236; +} +.notification_widget.warning .badge { + color: #f0ad4e; + background-color: #fff; +} +.notification_widget.success { + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.notification_widget.success:focus, +.notification_widget.success.focus { + color: #fff; + background-color: #449d44; + border-color: #255625; +} +.notification_widget.success:hover { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.notification_widget.success:active, +.notification_widget.success.active, +.open > .dropdown-toggle.notification_widget.success { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.notification_widget.success:active:hover, +.notification_widget.success.active:hover, +.open > .dropdown-toggle.notification_widget.success:hover, +.notification_widget.success:active:focus, +.notification_widget.success.active:focus, +.open > .dropdown-toggle.notification_widget.success:focus, +.notification_widget.success:active.focus, +.notification_widget.success.active.focus, +.open > .dropdown-toggle.notification_widget.success.focus { + color: #fff; + background-color: #398439; + border-color: #255625; +} +.notification_widget.success:active, +.notification_widget.success.active, +.open > .dropdown-toggle.notification_widget.success { + background-image: none; +} +.notification_widget.success.disabled:hover, +.notification_widget.success[disabled]:hover, +fieldset[disabled] .notification_widget.success:hover, +.notification_widget.success.disabled:focus, +.notification_widget.success[disabled]:focus, +fieldset[disabled] .notification_widget.success:focus, +.notification_widget.success.disabled.focus, +.notification_widget.success[disabled].focus, +fieldset[disabled] .notification_widget.success.focus { + background-color: #5cb85c; + border-color: #4cae4c; +} +.notification_widget.success .badge { + color: #5cb85c; + background-color: #fff; +} +.notification_widget.info { + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; +} +.notification_widget.info:focus, +.notification_widget.info.focus { + color: #fff; + background-color: #31b0d5; + border-color: #1b6d85; +} +.notification_widget.info:hover { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.notification_widget.info:active, +.notification_widget.info.active, +.open > .dropdown-toggle.notification_widget.info { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.notification_widget.info:active:hover, +.notification_widget.info.active:hover, +.open > .dropdown-toggle.notification_widget.info:hover, +.notification_widget.info:active:focus, +.notification_widget.info.active:focus, +.open > .dropdown-toggle.notification_widget.info:focus, +.notification_widget.info:active.focus, +.notification_widget.info.active.focus, +.open > .dropdown-toggle.notification_widget.info.focus { + color: #fff; + background-color: #269abc; + border-color: #1b6d85; +} +.notification_widget.info:active, +.notification_widget.info.active, +.open > .dropdown-toggle.notification_widget.info { + background-image: none; +} +.notification_widget.info.disabled:hover, +.notification_widget.info[disabled]:hover, +fieldset[disabled] .notification_widget.info:hover, +.notification_widget.info.disabled:focus, +.notification_widget.info[disabled]:focus, +fieldset[disabled] .notification_widget.info:focus, +.notification_widget.info.disabled.focus, +.notification_widget.info[disabled].focus, +fieldset[disabled] .notification_widget.info.focus { + background-color: #5bc0de; + border-color: #46b8da; +} +.notification_widget.info .badge { + color: #5bc0de; + background-color: #fff; +} +.notification_widget.danger { + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; +} +.notification_widget.danger:focus, +.notification_widget.danger.focus { + color: #fff; + background-color: #c9302c; + border-color: #761c19; +} +.notification_widget.danger:hover { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.notification_widget.danger:active, +.notification_widget.danger.active, +.open > .dropdown-toggle.notification_widget.danger { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.notification_widget.danger:active:hover, +.notification_widget.danger.active:hover, +.open > .dropdown-toggle.notification_widget.danger:hover, +.notification_widget.danger:active:focus, +.notification_widget.danger.active:focus, +.open > .dropdown-toggle.notification_widget.danger:focus, +.notification_widget.danger:active.focus, +.notification_widget.danger.active.focus, +.open > .dropdown-toggle.notification_widget.danger.focus { + color: #fff; + background-color: #ac2925; + border-color: #761c19; +} +.notification_widget.danger:active, +.notification_widget.danger.active, +.open > .dropdown-toggle.notification_widget.danger { + background-image: none; +} +.notification_widget.danger.disabled:hover, +.notification_widget.danger[disabled]:hover, +fieldset[disabled] .notification_widget.danger:hover, +.notification_widget.danger.disabled:focus, +.notification_widget.danger[disabled]:focus, +fieldset[disabled] .notification_widget.danger:focus, +.notification_widget.danger.disabled.focus, +.notification_widget.danger[disabled].focus, +fieldset[disabled] .notification_widget.danger.focus { + background-color: #d9534f; + border-color: #d43f3a; +} +.notification_widget.danger .badge { + color: #d9534f; + background-color: #fff; +} +div#pager { + background-color: #fff; + font-size: 14px; + line-height: 20px; + overflow: hidden; + display: none; + position: fixed; + bottom: 0px; + width: 100%; + max-height: 50%; + padding-top: 8px; + -webkit-box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2); + box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2); + /* Display over codemirror */ + z-index: 100; + /* Hack which prevents jquery ui resizable from changing top. */ + top: auto !important; +} +div#pager pre { + line-height: 1.21429em; + color: #000; + background-color: #f7f7f7; + padding: 0.4em; +} +div#pager #pager-button-area { + position: absolute; + top: 8px; + right: 20px; +} +div#pager #pager-contents { + position: relative; + overflow: auto; + width: 100%; + height: 100%; +} +div#pager #pager-contents #pager-container { + position: relative; + padding: 15px 0px; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; +} +div#pager .ui-resizable-handle { + top: 0px; + height: 8px; + background: #f7f7f7; + border-top: 1px solid #cfcfcf; + border-bottom: 1px solid #cfcfcf; + /* This injects handle bars (a short, wide = symbol) for + the resize handle. */ +} +div#pager .ui-resizable-handle::after { + content: ''; + top: 2px; + left: 50%; + height: 3px; + width: 30px; + margin-left: -15px; + position: absolute; + border-top: 1px solid #cfcfcf; +} +.quickhelp { + /* Old browsers */ + display: -webkit-box; + -webkit-box-orient: horizontal; + -webkit-box-align: stretch; + display: -moz-box; + -moz-box-orient: horizontal; + -moz-box-align: stretch; + display: box; + box-orient: horizontal; + box-align: stretch; + /* Modern browsers */ + display: flex; + flex-direction: row; + align-items: stretch; + line-height: 1.8em; +} +.shortcut_key { + display: inline-block; + width: 21ex; + text-align: right; + font-family: monospace; +} +.shortcut_descr { + display: inline-block; + /* Old browsers */ + -webkit-box-flex: 1; + -moz-box-flex: 1; + box-flex: 1; + /* Modern browsers */ + flex: 1; +} +span.save_widget { + margin-top: 6px; +} +span.save_widget span.filename { + height: 1em; + line-height: 1em; + padding: 3px; + margin-left: 16px; + border: none; + font-size: 146.5%; + border-radius: 2px; +} +span.save_widget span.filename:hover { + background-color: #e6e6e6; +} +span.checkpoint_status, +span.autosave_status { + font-size: small; +} +@media (max-width: 767px) { + span.save_widget { + font-size: small; + } + span.checkpoint_status, + span.autosave_status { + display: none; + } +} +@media (min-width: 768px) and (max-width: 991px) { + span.checkpoint_status { + display: none; + } + span.autosave_status { + font-size: x-small; + } +} +.toolbar { + padding: 0px; + margin-left: -5px; + margin-top: 2px; + margin-bottom: 5px; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; +} +.toolbar select, +.toolbar label { + width: auto; + vertical-align: middle; + margin-right: 2px; + margin-bottom: 0px; + display: inline; + font-size: 92%; + margin-left: 0.3em; + margin-right: 0.3em; + padding: 0px; + padding-top: 3px; +} +.toolbar .btn { + padding: 2px 8px; +} +.toolbar .btn-group { + margin-top: 0px; + margin-left: 5px; +} +#maintoolbar { + margin-bottom: -3px; + margin-top: -8px; + border: 0px; + min-height: 27px; + margin-left: 0px; + padding-top: 11px; + padding-bottom: 3px; +} +#maintoolbar .navbar-text { + float: none; + vertical-align: middle; + text-align: right; + margin-left: 5px; + margin-right: 0px; + margin-top: 0px; +} +.select-xs { + height: 24px; +} +.pulse, +.dropdown-menu > li > a.pulse, +li.pulse > a.dropdown-toggle, +li.pulse.open > a.dropdown-toggle { + background-color: #F37626; + color: white; +} +/** + * Primary styles + * + * Author: Jupyter Development Team + */ +/** WARNING IF YOU ARE EDITTING THIS FILE, if this is a .css file, It has a lot + * of chance of beeing generated from the ../less/[samename].less file, you can + * try to get back the less file by reverting somme commit in history + **/ +/* + * We'll try to get something pretty, so we + * have some strange css to have the scroll bar on + * the left with fix button on the top right of the tooltip + */ +@-moz-keyframes fadeOut { + from { + opacity: 1; + } + to { + opacity: 0; + } +} +@-webkit-keyframes fadeOut { + from { + opacity: 1; + } + to { + opacity: 0; + } +} +@-moz-keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} +@-webkit-keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} +/*properties of tooltip after "expand"*/ +.bigtooltip { + overflow: auto; + height: 200px; + -webkit-transition-property: height; + -webkit-transition-duration: 500ms; + -moz-transition-property: height; + -moz-transition-duration: 500ms; + transition-property: height; + transition-duration: 500ms; +} +/*properties of tooltip before "expand"*/ +.smalltooltip { + -webkit-transition-property: height; + -webkit-transition-duration: 500ms; + -moz-transition-property: height; + -moz-transition-duration: 500ms; + transition-property: height; + transition-duration: 500ms; + text-overflow: ellipsis; + overflow: hidden; + height: 80px; +} +.tooltipbuttons { + position: absolute; + padding-right: 15px; + top: 0px; + right: 0px; +} +.tooltiptext { + /*avoid the button to overlap on some docstring*/ + padding-right: 30px; +} +.ipython_tooltip { + max-width: 700px; + /*fade-in animation when inserted*/ + -webkit-animation: fadeOut 400ms; + -moz-animation: fadeOut 400ms; + animation: fadeOut 400ms; + -webkit-animation: fadeIn 400ms; + -moz-animation: fadeIn 400ms; + animation: fadeIn 400ms; + vertical-align: middle; + background-color: #f7f7f7; + overflow: visible; + border: #ababab 1px solid; + outline: none; + padding: 3px; + margin: 0px; + padding-left: 7px; + font-family: monospace; + min-height: 50px; + -moz-box-shadow: 0px 6px 10px -1px #adadad; + -webkit-box-shadow: 0px 6px 10px -1px #adadad; + box-shadow: 0px 6px 10px -1px #adadad; + border-radius: 2px; + position: absolute; + z-index: 1000; +} +.ipython_tooltip a { + float: right; +} +.ipython_tooltip .tooltiptext pre { + border: 0; + border-radius: 0; + font-size: 100%; + background-color: #f7f7f7; +} +.pretooltiparrow { + left: 0px; + margin: 0px; + top: -16px; + width: 40px; + height: 16px; + overflow: hidden; + position: absolute; +} +.pretooltiparrow:before { + background-color: #f7f7f7; + border: 1px #ababab solid; + z-index: 11; + content: ""; + position: absolute; + left: 15px; + top: 10px; + width: 25px; + height: 25px; + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -ms-transform: rotate(45deg); + -o-transform: rotate(45deg); +} +ul.typeahead-list i { + margin-left: -10px; + width: 18px; +} +ul.typeahead-list { + max-height: 80vh; + overflow: auto; +} +ul.typeahead-list > li > a { + /** Firefox bug **/ + /* see https://github.com/jupyter/notebook/issues/559 */ + white-space: normal; +} +.cmd-palette .modal-body { + padding: 7px; +} +.cmd-palette form { + background: white; +} +.cmd-palette input { + outline: none; +} +.no-shortcut { + display: none; +} +.command-shortcut:before { + content: "(command)"; + padding-right: 3px; + color: #777777; +} +.edit-shortcut:before { + content: "(edit)"; + padding-right: 3px; + color: #777777; +} +#find-and-replace #replace-preview .match, +#find-and-replace #replace-preview .insert { + background-color: #BBDEFB; + border-color: #90CAF9; + border-style: solid; + border-width: 1px; + border-radius: 0px; +} +#find-and-replace #replace-preview .replace .match { + background-color: #FFCDD2; + border-color: #EF9A9A; + border-radius: 0px; +} +#find-and-replace #replace-preview .replace .insert { + background-color: #C8E6C9; + border-color: #A5D6A7; + border-radius: 0px; +} +#find-and-replace #replace-preview { + max-height: 60vh; + overflow: auto; +} +#find-and-replace #replace-preview pre { + padding: 5px 10px; +} +.terminal-app { + background: #EEE; +} +.terminal-app #header { + background: #fff; + -webkit-box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2); + box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2); +} +.terminal-app .terminal { + width: 100%; + float: left; + font-family: monospace; + color: white; + background: black; + padding: 0.4em; + border-radius: 2px; + -webkit-box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.4); + box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.4); +} +.terminal-app .terminal, +.terminal-app .terminal dummy-screen { + line-height: 1em; + font-size: 14px; +} +.terminal-app .terminal .xterm-rows { + padding: 10px; +} +.terminal-app .terminal-cursor { + color: black; + background: white; +} +.terminal-app #terminado-container { + margin-top: 20px; +} +/*# sourceMappingURL=style.min.css.map */ + .c-ElasticMatch { background-color: #faffa6; padding: 0.2em;} + .hll { background-color: #ffffcc } + .c { color: #408080; font-style: italic } /* Comment */ + .err, .codehilite .err { border: none } /* Error */ + .k { color: #008000; font-weight: bold } /* Keyword */ + .o { color: #666666 } /* Operator */ + .ch { color: #408080; font-style: italic } /* Comment.Hashbang */ + .cm { color: #408080; font-style: italic } /* Comment.Multiline */ + .cp { color: #BC7A00 } /* Comment.Preproc */ + .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */ + .c1 { color: #408080; font-style: italic } /* Comment.Single */ + .cs { color: #408080; font-style: italic } /* Comment.Special */ + .gd { color: #A00000 } /* Generic.Deleted */ + .ge { font-style: italic } /* Generic.Emph */ + .gr { color: #FF0000 } /* Generic.Error */ + .gh { color: #000080; font-weight: bold } /* Generic.Heading */ + .gi { color: #00A000 } /* Generic.Inserted */ + .go { color: #888888 } /* Generic.Output */ + .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ + .gs { font-weight: bold } /* Generic.Strong */ + .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ + .gt { color: #0044DD } /* Generic.Traceback */ + .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ + .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ + .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ + .kp { color: #008000 } /* Keyword.Pseudo */ + .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ + .kt { color: #B00040 } /* Keyword.Type */ + .m { color: #666666 } /* Literal.Number */ + .s { color: #BA2121 } /* Literal.String */ + .na { color: #7D9029 } /* Name.Attribute */ + .nb { color: #008000 } /* Name.Builtin */ + .nc { color: #0000FF; font-weight: bold } /* Name.Class */ + .no { color: #880000 } /* Name.Constant */ + .nd { color: #AA22FF } /* Name.Decorator */ + .ni { color: #999999; font-weight: bold } /* Name.Entity */ + .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ + .nf { color: #0000FF } /* Name.Function */ + .nl { color: #A0A000 } /* Name.Label */ + .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ + .nt { color: #008000; font-weight: bold } /* Name.Tag */ + .nv { color: #19177C } /* Name.Variable */ + .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ + .w { color: #bbbbbb } /* Text.Whitespace */ + .mb { color: #666666 } /* Literal.Number.Bin */ + .mf { color: #666666 } /* Literal.Number.Float */ + .mh { color: #666666 } /* Literal.Number.Hex */ + .mi { color: #666666 } /* Literal.Number.Integer */ + .mo { color: #666666 } /* Literal.Number.Oct */ + .sa { color: #BA2121 } /* Literal.String.Affix */ + .sb { color: #BA2121 } /* Literal.String.Backtick */ + .sc { color: #BA2121 } /* Literal.String.Char */ + .dl { color: #BA2121 } /* Literal.String.Delimiter */ + .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ + .s2 { color: #BA2121 } /* Literal.String.Double */ + .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ + .sh { color: #BA2121 } /* Literal.String.Heredoc */ + .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ + .sx { color: #008000 } /* Literal.String.Other */ + .sr { color: #BB6688 } /* Literal.String.Regex */ + .s1 { color: #BA2121 } /* Literal.String.Single */ + .ss { color: #19177C } /* Literal.String.Symbol */ + .bp { color: #008000 } /* Name.Builtin.Pseudo */ + .fm { color: #0000FF } /* Name.Function.Magic */ + .vc { color: #19177C } /* Name.Variable.Class */ + .vg { color: #19177C } /* Name.Variable.Global */ + .vi { color: #19177C } /* Name.Variable.Instance */ + .vm { color: #19177C } /* Name.Variable.Magic */ + .il { color: #666666 } /* Literal.Number.Integer.Long */ +} \ No newline at end of file diff --git a/rhodecode/public/css/legacy_code_styles.less b/rhodecode/public/css/legacy_code_styles.less --- a/rhodecode/public/css/legacy_code_styles.less +++ b/rhodecode/public/css/legacy_code_styles.less @@ -212,6 +212,13 @@ div.markdown-block strong { margin: 0; } +div.markdown-block ul.checkbox, +div.markdown-block ol.checkbox { + padding-left: 20px !important; + margin-top: 0px !important; + margin-bottom: 18px !important; +} + div.markdown-block ul, div.markdown-block ol { padding-left: 30px !important; @@ -219,6 +226,13 @@ div.markdown-block ol { margin-bottom: 18px !important; } +div.markdown-block ul.checkbox li, +div.markdown-block ol.checkbox li { + list-style: none !important; + margin: 6px !important; + padding: 0 !important; +} + div.markdown-block ul li, div.markdown-block ol li { list-style: disc !important; diff --git a/rhodecode/public/css/login.less b/rhodecode/public/css/login.less --- a/rhodecode/public/css/login.less +++ b/rhodecode/public/css/login.less @@ -95,7 +95,7 @@ margin: 0 1em @padding 0; } } - + .checkbox { display: inline; width: auto; @@ -198,15 +198,16 @@ } .user-menu.submenu { - right: 0; - left: auto; + right: 0!important; + left: auto!important; min-width: 290px; } - .user-menu { .bookmark-items { - padding: 4px 2px; + border-top: @border-thickness solid @grey6; + margin-top: 1em; + padding: 1em .5em; color: @grey3; border-bottom: @grey3; @@ -227,8 +228,10 @@ padding: @menupadding; z-index: 999; overflow: hidden; - background-color: @grey6; + background-color: @white; + border: 1px solid @grey5; color: @grey2; + box-shadow: @dropdown-shadow; h4 { margin-bottom: 12px; @@ -261,7 +264,7 @@ .buttons .register { a { color: @rcblue; - + &:hover { color: @rcdarkblue; } @@ -289,15 +292,16 @@ .big_gravatar { float: left; display: block; - margin-top: .5em; + padding: .5em; } - .full_name, - .email { - margin: 0 0 0 65px; + .full_name { + margin: 0 0 0 70px; + padding-top: 1em; } .email { + margin: 0 0 0 70px; font-family: @text-light; } @@ -307,8 +311,6 @@ padding: @padding 0 0 0; li { - border-top: @border-thickness solid @grey5; - input { margin: @padding 0 0 0; } diff --git a/rhodecode/public/css/main.less b/rhodecode/public/css/main.less --- a/rhodecode/public/css/main.less +++ b/rhodecode/public/css/main.less @@ -107,6 +107,12 @@ input + .action-link, .action-link.first .clipboard-action { cursor: pointer; + color: @grey4; + margin-left: 5px; + + &:hover { + color: @grey2; + } } ul.simple-list{ @@ -237,7 +243,7 @@ input.inline[type="file"] { position: relative; vertical-align: bottom; padding: 0 @header-padding; - background-color: @grey2; + background-color: @grey1; color: @grey5; .title { @@ -271,7 +277,9 @@ input.inline[type="file"] { // Gists #files_data { clear: both; //for firefox + padding-top: 10px; } + #gistid { margin-right: @padding; } @@ -516,7 +524,7 @@ ul.auth_plugins { text-align: center; vertical-align: middle; color: @grey2; - background-color: @grey6; + font-size: 11px; p { margin: 0; @@ -605,10 +613,20 @@ button.close { } -input { +input, textarea { &.disabled { opacity: .5; } + + &:hover { + border-color: @grey3; + box-shadow: @button-shadow; + } + + &:focus { + border-color: @rcblue; + box-shadow: @button-shadow; + } } // remove extra padding in firefox @@ -643,16 +661,20 @@ select { padding: 0 18px 0 8px; line-height:1em; font-size: @basefontsize; - border: @border-thickness solid @rcblue; + border: @border-thickness solid @grey5; + border-radius: @border-radius; background:white url("../images/dt-arrow-dn.png") no-repeat 100% 50%; - color: @rcblue; + color: @grey4; + box-shadow: @button-shadow; &:after { content: "\00A0\25BE"; } - &:focus { + &:focus, &:hover { outline: none; + border-color: @grey4; + color: @rcdarkblue; } } @@ -712,8 +734,8 @@ label { margin: -5px 0; padding: 0; line-height: 1em; - border: 1px solid @grey4; box-sizing: content-box; + border-radius: 50%; &.gravatar-large { margin: -0.5em .25em -0.5em 0; @@ -938,9 +960,6 @@ label { } -#graph_nodes { - padding-top: 43px; -} #graph_content{ @@ -973,13 +992,12 @@ label { } .graph-col-wrapper { - padding-left: 110px; #graph_nodes { width: 100px; - margin-left: -110px; - float: left; - clear: left; + position: absolute; + left: 70px; + z-index: -1; } } @@ -996,6 +1014,16 @@ label { } } +.obsolete-toggle { + line-height: 30px; + margin-left: -15px; +} + +#rev_range_container, #rev_range_clear, #rev_range_more { + margin-top: -5px; + margin-bottom: -5px; +} + #filter_changelog { float: left; } @@ -1024,11 +1052,15 @@ label { float:left; } -.branding{ +.branding { float: left; padding: 9px 2px; line-height: 1em; font-size: @navigation-fontsize; + + a { + color: @grey5 + } } img { @@ -1047,7 +1079,7 @@ label { } .flag_status { - margin: 2px 8px 6px 2px; + margin: 2px; &.under_review { .circle(5px, @alert3); } @@ -1218,24 +1250,37 @@ table.integrations { .autocomplete-suggestions { width: auto !important; // overrides autocomplete.js + min-width: 278px; margin: 0; - border: @border-thickness solid @rcblue; + border: @border-thickness solid @grey5; border-radius: @border-radius; - color: @rcblue; + color: @grey2; background-color: white; } + +.autocomplete-qfilter-suggestions { + width: auto !important; // overrides autocomplete.js + max-height: 100% !important; + min-width: 376px; + margin: 0; + border: @border-thickness solid @grey5; + color: @grey2; + background-color: white; +} + .autocomplete-selected { background: #F0F0F0; } + .ac-container-wrap { margin: 0; padding: 8px; - border-bottom: @border-thickness solid @rclightblue; + border-bottom: @border-thickness solid @grey5; list-style-type: none; cursor: pointer; &:hover { - background-color: @rclightblue; + background-color: @grey7; } img { @@ -1290,9 +1335,9 @@ table.integrations { } } - #editor_container{ - position: relative; - margin: @padding; + #editor_container { + position: relative; + margin: @padding 10px; } } @@ -1796,7 +1841,6 @@ BIN_FILENODE = 7 } #changeset_compare_view_content { - margin-bottom: @space; clear: both; width: 100%; box-sizing: border-box; @@ -2027,15 +2071,15 @@ BIN_FILENODE = 7 // Files .edit-file-title { - border-bottom: @border-thickness solid @border-default-color; - - .breadcrumbs { - margin-bottom: 0; + font-size: 16px; + + .title-heading { + padding: 2px; } } .edit-file-fieldset { - margin-top: @sidebarpadding; + margin: @sidebarpadding 0; .fieldset { .left-label { @@ -2080,8 +2124,29 @@ BIN_FILENODE = 7 .new-file, #filter_activate, #filter_deactivate { - float: left; - margin: 0 0 0 15px; + float: right; + margin: 0 0 0 10px; +} + +.file-upload-transaction-wrapper { + margin-top: 57px; + clear: both; +} + +.file-upload-transaction-wrapper .error { + color: @color5; +} + +.file-upload-transaction { + min-height: 200px; + padding: 54px; + border: 1px solid @grey5; + text-align: center; + clear: both; +} + +.file-upload-transaction i { + font-size: 48px } h3.files_location{ @@ -2089,11 +2154,12 @@ h3.files_location{ } .browser-nav { + width: 100%; display: table; - margin-bottom: @space; - + margin-bottom: 20px; .info_box { + float: left; display: inline-table; height: 2.5em; @@ -2102,36 +2168,58 @@ h3.files_location{ vertical-align: middle; } + .drop-menu { + margin: 0 10px; + } + .info_box_elem { - border-top: @border-thickness solid @rcblue; - border-bottom: @border-thickness solid @rcblue; + border-top: @border-thickness solid @grey5; + border-bottom: @border-thickness solid @grey5; + box-shadow: @button-shadow; #at_rev, a { - padding: 0.6em 0.9em; + padding: 0.6em 0.4em; margin: 0; .box-shadow(none); border: 0; height: 12px; + color: @grey2; } input#at_rev { max-width: 50px; - text-align: right; + text-align: center; } &.previous { - border: @border-thickness solid @rcblue; + border: @border-thickness solid @grey5; + border-top-left-radius: @border-radius; + border-bottom-left-radius: @border-radius; + + &:hover { + border-color: @grey4; + } + .disabled { - color: @grey4; + color: @grey5; cursor: not-allowed; + opacity: 0.5; } } &.next { - border: @border-thickness solid @rcblue; + border: @border-thickness solid @grey5; + border-top-right-radius: @border-radius; + border-bottom-right-radius: @border-radius; + + &:hover { + border-color: @grey4; + } + .disabled { - color: @grey4; + color: @grey5; cursor: not-allowed; + opacity: 0.5; } } } @@ -2148,8 +2236,14 @@ h3.files_location{ margin-right: @padding; } } + } + .select-index-number { + margin: 0 0 0 20px; + color: @grey3; + } + .search_activate { display: table-cell; vertical-align: middle; @@ -2178,26 +2272,54 @@ h3.files_location{ margin: -25px 0px 5px 0px; } -.node-filter { - font-size: @repo-title-fontsize; - padding: 4px 0px 0px 0px; - - .node-filter-path { - float: left; - color: @grey4; +.files-quick-filter { + float: right; + width: 180px; + position: relative; +} + +.files-filter-box { + display: flex; + padding: 0px; + border-radius: 3px; + margin-bottom: 0; + + a { + border: none !important; + } + + li { + list-style-type: none + } +} + +.files-filter-box-path { + line-height: 33px; + padding: 0; + width: 20px; + position: absolute; + z-index: 11; + left: 5px; +} + +.files-filter-box-input { + margin-right: 0; + + input { + border: 1px solid @white; + padding-left: 25px; + width: 145px; + + &:hover { + border-color: @grey6; } - .node-filter-input { - float: left; - margin: -2px 0px 0px 2px; - input { - padding: 2px; - border: none; - font-size: @repo-title-fontsize; - } + + &:focus { + border-color: @grey5; } + } } - .browser-result{ td a{ margin-left: 0.5em; @@ -2215,6 +2337,142 @@ h3.files_location{ } +.edit-file-fieldset #location, +.edit-file-fieldset #filename { + display: flex; + width: -moz-available; /* WebKit-based browsers will ignore this. */ + width: -webkit-fill-available; /* Mozilla-based browsers will ignore this. */ + width: fill-available; + border: 0; +} + +.path-items { + display: flex; + padding: 0; + border: 1px solid #eeeeee; + width: 100%; + float: left; + + .breadcrumb-path { + line-height: 30px; + padding: 0 4px; + white-space: nowrap; + } + + .location-path { + width: -moz-available; /* WebKit-based browsers will ignore this. */ + width: -webkit-fill-available; /* Mozilla-based browsers will ignore this. */ + width: fill-available; + + .file-name-input { + padding: 0.5em 0; + } + + } + + ul { + display: flex; + margin: 0; + padding: 0; + width: 100%; + } + + li { + list-style-type: none; + } + +} + +.editor-items { + height: 40px; + margin: 10px 0 -17px 10px; + + .editor-action { + cursor: pointer; + } + + .editor-action.active { + border-bottom: 2px solid #5C5C5C; + } + + li { + list-style-type: none; + } +} + +.edit-file-fieldset .message textarea { + border: 1px solid #eeeeee; +} + +#files_data .codeblock { + background-color: #F5F5F5; +} + +#editor_preview { + background: white; +} + +.show-editor { + padding: 10px; + background-color: white; + +} + +.show-preview { + padding: 10px; + background-color: white; + border-left: 1px solid #eeeeee; +} +// quick filter +.grid-quick-filter { + float: right; + position: relative; +} + +.grid-filter-box { + display: flex; + padding: 0px; + border-radius: 3px; + margin-bottom: 0; + + a { + border: none !important; + } + + li { + list-style-type: none + } +} + +.grid-filter-box-icon { + line-height: 33px; + padding: 0; + width: 20px; + position: absolute; + z-index: 11; + left: 5px; +} + +.grid-filter-box-input { + margin-right: 0; + + input { + border: 1px solid @white; + padding-left: 25px; + width: 145px; + + &:hover { + border-color: @grey6; + } + + &:focus { + border-color: @grey5; + } + } +} + + + // Search .search-form{ @@ -2277,7 +2535,7 @@ div.search-code-body { } .code-body { - border: @border-thickness solid @border-default-color; + border: @border-thickness solid @grey6; .border-radius(@border-radius); } @@ -2297,6 +2555,11 @@ div.search-code-body { .break { background-color: #DDE7EF; width: 100%; color: #747474; display: block; } } + .path { + border-bottom: none !important; + border-left: 1px solid @grey6 !important; + border-right: 1px solid @grey6 !important; + } } table.rctable td.td-search-results div { @@ -2472,3 +2735,56 @@ form.markup-form { padding: 20px; background-color: white; } + + +.dropzone-wrapper { + border: 1px solid @grey5; + padding: 20px; +} + +.dropzone, +.dropzone-pure { + border: 2px dashed @grey5; + border-radius: 5px; + background: white; + min-height: 200px; + padding: 54px; + + .dz-message { + font-weight: 700; + text-align: center; + margin: 2em 0; + } + +} + +.dz-preview { + margin: 10px 0 !important; + position: relative; + vertical-align: top; + padding: 10px; + border-bottom: 1px solid @grey5; +} + +.dz-filename { + font-weight: 700; + float:left; +} + +.dz-sending { + float: right; +} + +.dz-response { + clear:both +} + +.dz-filename-size { + float:right +} + +.dz-error-message { + color: @alert2; + padding-top: 10px; + clear: both; +} diff --git a/rhodecode/public/css/navigation.less b/rhodecode/public/css/navigation.less --- a/rhodecode/public/css/navigation.less +++ b/rhodecode/public/css/navigation.less @@ -2,10 +2,21 @@ // For use in RhodeCode applications; // see style guide documentation for guidelines. +// TOP MAIN DARK NAVIGATION + +.header .main_nav.horizontal-list { + float: right; + color: @grey4; + > li { + a { + color: @grey4; + } + } +} + // HEADER NAVIGATION .horizontal-list { - float: right; display: block; margin: 0; padding: 0; @@ -18,6 +29,7 @@ li { line-height: 1em; list-style-type: none; + margin: 0 20px 0 0; a { padding: 0 .5em; @@ -55,12 +67,6 @@ .user { padding-bottom: 10px; } - - &.open { - .user { - border-bottom: 5px solid @rcblue; - } - } } &:before { content: none; } @@ -80,10 +86,6 @@ } } - &.active { - border-bottom: 5px solid @rcblue; - } - &.open { a { @@ -118,14 +120,12 @@ > a, &.has_select2 a { display: block; - padding: 10px 0 2px; + padding: 10px 0; } .menulabel { - padding: 0 .5em; line-height: 1em; // for this specifically we do not use a variable - border-right: 1px solid @grey4; } .pr_notifications { @@ -141,7 +141,7 @@ &.open, &.active { a { - color: @grey1; + color: @rcblue; } } } @@ -156,6 +156,14 @@ position: relative; } + .menulink { + &.disabled { + color: @grey3; + cursor: default; + opacity: 0.5; + } + } + #quick_login { li a { @@ -281,16 +289,19 @@ } .navigation li:last-child .submenu { - right: -20px; - left: auto; + right: auto; + left: 0; + border: 1px solid @grey5; + background: @white; + box-shadow: @dropdown-shadow; } .submenu { position: absolute; top: 100%; left: 0; - min-width: 150px; - margin: 6px 0 0; + min-width: 180px; + margin: 2px 0 0; padding: 0; text-align: left; font-family: @text-light; @@ -303,7 +314,7 @@ padding: 0 .5em; line-height: 1em; color: @grey3; - background-color: @grey6; + background-color: @white; list-style-type: none; a { @@ -324,7 +335,7 @@ z-index: 30; } &:hover { - background-color: @grey5; + background-color: @grey7; -webkit-transition: background .3s; -moz-transition: background .3s; -o-transition: background .3s; @@ -501,10 +512,10 @@ #context-bar { display: block; - margin: 0 auto; + margin: 0 auto 20px 0; padding: 0 @header-padding; - background-color: @grey6; - border-bottom: @border-thickness solid @grey5; + background-color: @grey7; + border-bottom: 1px solid @grey5; .clear { clear: both; @@ -513,19 +524,22 @@ ul#context-pages { li { - line-height: 1em; list-style-type: none; a { - color: @grey3; + color: @grey2; + + &:hover { + color: @grey1; + } } &.active { // special case, non-variable color - border-bottom: 4px solid @nav-grey; + border-bottom: 2px solid @rcblue; a { - color: @grey1; + color: @rcblue; } } } @@ -534,8 +548,9 @@ ul#context-pages { // PAGINATION .pagination { - border: @border-thickness solid @rcblue; - color: @rcblue; + border: @border-thickness solid @grey5; + color: @grey2; + box-shadow: @button-shadow; .current { color: @grey4; @@ -552,33 +567,44 @@ ul#context-pages { .dataTables_paginate, .pagination-wh { text-align: left; display: inline-block; - border-left: 1px solid @rcblue; + border-left: 1px solid @grey5; float: none; overflow: hidden; + box-shadow: @button-shadow; .paginate_button, .pager_curpage, .pager_link, .pg-previous, .pg-next, .pager_dotdot { display: inline-block; padding: @menupadding/4 @menupadding; - border: 1px solid @rcblue; + border: 1px solid @grey5; border-left: 0; - color: @rcblue; + color: @grey2; cursor: pointer; float: left; + + &:hover { + color: @rcdarkblue; + } } - .pager_curpage, .pager_dotdot, - .paginate_button.current, .paginate_button.disabled, + .paginate_button.disabled, .disabled { color: @grey3; cursor: default; + opacity: 0.5; + } + + .paginate_button.current, .pager_curpage { + background: @rcblue; + border-color: @rcblue; + color: @white; } .ellipsis { display: inline-block; text-align: left; padding: @menupadding/4 @menupadding; - border: 1px solid @rcblue; + border: 1px solid @grey5; border-left: 0; float: left; } @@ -595,14 +621,6 @@ ul#context-pages { font-family: @text-regular; color: @grey1; - &#graph_nodes { - clear:both; - width: auto; - margin-left: -100px; - padding: 0; - border: none; - } - .nav-pills { margin: 0; } @@ -631,19 +649,56 @@ ul#context-pages { .main_filter_help_box { padding: 7px 7px; - border-top: 1px solid @grey4; - border-right: 1px solid @grey4; - border-bottom: 1px solid @grey4; display: inline-block; vertical-align: top; background: inherit; position: absolute; - right: 8px; + right: 0; top: 9px; } .main_filter_input_box { display: inline-block; + + .searchItems { + display:flex; + background: @black; + padding: 0px; + border-radius: 3px; + border: 1px solid @black; + + a { + border: none !important; + } + } + + .searchTag { + line-height: 28px; + padding: 0 5px; + + .tag { + color: @grey5; + border-color: @grey2; + background: @grey1; + } + } + + .searchTagFilter { + background-color: @black !important; + margin-right: 0; + } + + .searchTagHelp { + background-color: @grey1 !important; + margin: 0; + } + .searchTagHelp:hover { + background-color: @grey1 !important; + } + .searchTagInput { + background-color: @grey1 !important; + margin-right: 0; + } } .main_filter_box { @@ -651,31 +706,33 @@ ul#context-pages { } #main_filter_help { - background: @grey3; + background: @grey1; border: 1px solid black; position: absolute; white-space: pre; z-index: 9999; color: @nav-grey; - margin: 1px 7px; padding: 0 10px; } -.main_filter_input { - padding: 5px; - min-width: 260px; - color: @nav-grey; - background: @grey3; - min-height: 18px; - +input { - &:active { - color: @grey2 !important; - background: white !important; - } - &:focus { - color: @grey2 !important; - background: white !important; + &.main_filter_input { + padding: 5px 10px; + min-width: 340px; + color: @grey7; + background: @black; + min-height: 18px; + border: 0; + + &:active { + color: @grey2 !important; + background: white !important; + } + &:focus { + color: @grey2 !important; + background: white !important; + } } } diff --git a/rhodecode/public/css/panels.less b/rhodecode/public/css/panels.less --- a/rhodecode/public/css/panels.less +++ b/rhodecode/public/css/panels.less @@ -47,7 +47,7 @@ min-height: 150px } } - + .panel-footer { background-color: white; padding: .65em @panel-padding .5em; @@ -63,10 +63,6 @@ &.user-profile { float: left; - .panel-heading { - margin-bottom: @padding; - } - .panel-body { &:extend(.clearfix); } diff --git a/rhodecode/public/css/rcicons.less b/rhodecode/public/css/rcicons.less --- a/rhodecode/public/css/rcicons.less +++ b/rhodecode/public/css/rcicons.less @@ -1,11 +1,13 @@ @font-face { font-family: 'rcicons'; - src: url('../fonts/RCIcons/rcicons.eot?74666722'); - src: url('../fonts/RCIcons/rcicons.eot?74666722#iefix') format('embedded-opentype'), - url('../fonts/RCIcons/rcicons.woff2?74666722') format('woff2'), - url('../fonts/RCIcons/rcicons.woff?74666722') format('woff'), - url('../fonts/RCIcons/rcicons.ttf?74666722') format('truetype'), - url('../fonts/RCIcons/rcicons.svg?74666722#rcicons') format('svg'); + + src: url('../fonts/RCIcons/rcicons.eot?92789106'); + src: url('../fonts/RCIcons/rcicons.eot?92789106#iefix') format('embedded-opentype'), + url('../fonts/RCIcons/rcicons.woff2?92789106') format('woff2'), + url('../fonts/RCIcons/rcicons.woff?92789106') format('woff'), + url('../fonts/RCIcons/rcicons.ttf?92789106') format('truetype'), + url('../fonts/RCIcons/rcicons.svg?92789106#rcicons') format('svg'); + font-weight: normal; font-style: normal; } @@ -55,78 +57,164 @@ /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ } +.animate-spin { + -moz-animation: spin 2s infinite linear; + -o-animation: spin 2s infinite linear; + -webkit-animation: spin 2s infinite linear; + animation: spin 2s infinite linear; + display: inline-block; +} +@-moz-keyframes spin { + 0% { + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + 100% { + -moz-transform: rotate(359deg); + -o-transform: rotate(359deg); + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@-webkit-keyframes spin { + 0% { + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + 100% { + -moz-transform: rotate(359deg); + -o-transform: rotate(359deg); + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@-o-keyframes spin { + 0% { + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + 100% { + -moz-transform: rotate(359deg); + -o-transform: rotate(359deg); + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@-ms-keyframes spin { + 0% { + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + 100% { + -moz-transform: rotate(359deg); + -o-transform: rotate(359deg); + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@keyframes spin { + 0% { + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + 100% { + -moz-transform: rotate(359deg); + -o-transform: rotate(359deg); + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + + + .icon-no-margin::before { margin: 0; } // -- ICON CLASSES -- // +// sorter = lambda s: '\n'.join(sorted(s.splitlines())) +.icon-delete:before { content: '\e800'; } /* '' */ +.icon-ok:before { content: '\e801'; } /* '' */ +.icon-comment:before { content: '\e802'; } /* '' */ .icon-bookmark:before { content: '\e803'; } /* '' */ .icon-branch:before { content: '\e804'; } /* '' */ +.icon-tag:before { content: '\e805'; } /* '' */ .icon-lock:before { content: '\e806'; } /* '' */ .icon-unlock:before { content: '\e807'; } /* '' */ -.icon-delete:before { content: '\e808'; } /* '' */ -.icon-false:before { content: '\e808'; } /* '' */ - -.icon-ok:before { content: '\e809'; } /* '' */ -.icon-true:before { content: '\e809'; } /* '' */ - -.icon-comment:before { content: '\e80a'; } /* '' */ -.icon-comment-add:before { content: '\e816'; } /* '' */ -.icon-comment_toggle:before { content: '\e818'; } /* '' */ - -.icon-feed:before { content: '\e80b'; } /* '' */ - -.icon-right:before { content: '\e80c'; } /* '' */ -.icon-left:before { content: '\e80d'; } /* '' */ - -.icon-arrow_down:before { content: '\e80e'; } /* '' */ -.icon-arrow_up:before { content: '\e80e'; } /* '' */ - -.icon-group:before { content: '\e812'; } /* '' */ - -.icon-fork:before { content: '\e814'; } /* '' */ -.icon-merge:before { content: '\e814'; } /* '' */ - -.icon-more:before { content: '\e815'; } /* '' */ - -.icon-more-linked { cursor: pointer; color: @grey3 } -.icon-more-linked:before { content: '\e815'; } /* '' */ - -.icon-expand-linked { cursor: pointer; color: @grey3; font-size: 8px } -.icon-expand-linked:before { content: '\e80e'; } /* '' */ - -.icon-git-inv:before { content: '\e80f'; } /* '' */ -.icon-hg-inv:before { content: '\e810'; } /* '' */ -.icon-svn-inv:before { content: '\e811'; } /* '' */ - -.icon-git:before { content: '\e81a'; } /* '' */ -.icon-hg:before { content: '\e81b'; } /* '' */ -.icon-svn:before { content: '\e820'; } /* '' */ - -.icon-minus:before { content: '\e81c'; } /* '' */ +.icon-feed:before { content: '\e808'; } /* '' */ +.icon-left:before { content: '\e809'; } /* '' */ +.icon-right:before { content: '\e80a'; } /* '' */ +.icon-down:before { content: '\e80b'; } /* '' */ +.icon-folder:before { content: '\e80c'; } /* '' */ +.icon-folder-open:before { content: '\e80d'; } /* '' */ +.icon-folder-empty:before { content: '\f114'; } /* '' */ +.icon-folder-open-empty:before { content: '\f115'; } /* '' */ +.icon-trash-empty:before { content: '\e80e'; } /* '' */ +.icon-group:before { content: '\e80f'; } /* '' */ +.icon-remove:before { content: '\e810'; } /* '' */ +.icon-fork:before { content: '\e811'; } /* '' */ +.icon-more:before { content: '\e812'; } /* '' */ +.icon-search:before { content: '\e813'; } /* '' */ +.icon-scissors:before { content: '\e814'; } /* '' */ +.icon-download:before { content: '\e815'; } /* '' */ +.icon-doc:before { content: '\e816'; } /* '' */ +.icon-cog:before { content: '\e817'; } /* '' */ +.icon-cog-alt:before { content: '\e818'; } /* '' */ +.icon-eye:before { content: '\e819'; } /* '' */ +.icon-eye-off:before { content: '\e81a'; } /* '' */ +.icon-cancel-circled2:before { content: '\e81b'; } /* '' */ +.icon-cancel-circled:before { content: '\e81c'; } /* '' */ .icon-plus:before { content: '\e81d'; } /* '' */ -.icon-remove:before { content: '\e81e'; } /* '' */ -.icon-remove-sign:before { content: '\e81e'; } /* '' */ - -.icon-rhodecode:before { content: '\e81f'; } /* '' */ - -.icon-tag:before { content: '\e821'; } /* '' */ -.icon-copy:before { content: '\f0c5'; } /* '' */ -.icon-clipboard:before { content: '\f0c5'; } /* '' */ +.icon-plus-circled:before { content: '\e81e'; } /* '' */ +.icon-minus-circled:before { content: '\e81f'; } /* '' */ +.icon-minus:before { content: '\e820'; } /* '' */ +.icon-info-circled:before { content: '\e821'; } /* '' */ +.icon-upload:before { content: '\e822'; } /* '' */ +.icon-home:before { content: '\e823'; } /* '' */ +.icon-git:before { content: '\e82a'; } /* '' */ +.icon-hg:before { content: '\e82d'; } /* '' */ +.icon-svn:before { content: '\e82e'; } /* '' */ +.icon-comment-add:before { content: '\e82f'; } /* '' */ +.icon-comment-toggle:before { content: '\e830'; } /* '' */ +.icon-rhodecode:before { content: '\e831'; } /* '' */ +.icon-up:before { content: '\e832'; } /* '' */ +.icon-merge:before { content: '\e833'; } /* '' */ +.icon-docs:before { content: '\f0c5'; } /* '' */ +.icon-menu:before { content: '\f0c9'; } /* '' */ +.icon-paste:before { content: '\f0ea'; } /* '' */ +.icon-doc-text:before { content: '\f0f6'; } /* '' */ +.icon-plus-squared:before { content: '\f0fe'; } /* '' */ +.icon-minus-squared:before { content: '\f146'; } /* '' */ +.icon-minus-squared-alt:before { content: '\f147'; } /* '' */ +.icon-doc-inv:before { content: '\f15b'; } /* '' */ +.icon-doc-text-inv:before { content: '\f15c'; } /* '' */ +.icon-plus-squared-alt:before { content: '\f196'; } /* '' */ +.icon-file-code:before { content: '\f1c9'; } /* '' */ +.icon-history:before { content: '\f1da'; } /* '' */ +.icon-sliders:before { content: '\f1de'; } /* '' */ +.icon-trash:before { content: '\f1f8'; } /* '' */ +.icon-spin-alt:before { content: '\e834'; } /* '' */ +.icon-spin:before { content: '\e838'; } /* '' */ -.icon-folder:before { content: '\e813'; } /* '' */ -.icon-folder-close:before { content: '\e813'; } /* '' */ - -.icon-directory:before { content: '\e800'; } /* '' */ -.icon-directory-empty:before { content: '\f114'; } /* '' */ -.icon-file-text:before { content: '\f0f6'; } /* '' */ -.icon-file-text-inv:before { content: '\f15c'; } /* '' */ -.icon-file-code:before { content: '\f1c9'; } /* '' */ - -// MERGED ICONS - +// MERGED ICONS BASED ON CURRENT ONES +.icon-repo-group:before { &:extend(.icon-folder-open:before); } .icon-repo-private:before { &:extend(.icon-lock:before); } .icon-repo-lock:before { &:extend(.icon-lock:before); } .icon-unlock-alt:before { &:extend(.icon-unlock:before); } @@ -134,9 +222,20 @@ .icon-repo-public:before { &:extend(.icon-unlock:before); } .icon-rss-sign:before { &:extend(.icon-feed:before); } .icon-code-fork:before { &:extend(.icon-fork:before); } +.icon-arrow_up:before { &:extend(.icon-up:before); } +.icon-file:before { &:extend(.icon-file-code:before); } +.icon-file-text:before { &:extend(.icon-file-code:before); } +.icon-directory:before { &:extend(.icon-folder:before); } +.icon-more-linked:before { &:extend(.icon-more:before); } +.icon-clipboard:before { &:extend(.icon-docs:before); } +.icon-copy:before { &:extend(.icon-docs:before); } +.icon-true:before { &:extend(.icon-ok:before); } +.icon-false:before { &:extend(.icon-delete:before); } +.icon-expand-linked:before { &:extend(.icon-down:before); } +.icon-pr-merge-fail:before { &:extend(.icon-delete:before); } // TRANSFORM -.icon-arrow_up:before {transform: rotate(180deg);} + .icon-merge:before {transform: rotate(180deg);} // -- END ICON CLASSES -- // @@ -152,6 +251,9 @@ .icon-svn-inv { color: @color1 !important; } .icon-repo-lock { color: #FF0000; } .icon-repo-unlock { color: #FF0000; } +.icon-false { color: @grey5 } +.icon-expand-linked { cursor: pointer; color: @grey3; font-size: 14px } +.icon-more-linked { cursor: pointer; color: @grey3 } .repo-switcher-dropdown .select2-result-label { .icon-git:before { diff --git a/rhodecode/public/css/readme-box.less b/rhodecode/public/css/readme-box.less --- a/rhodecode/public/css/readme-box.less +++ b/rhodecode/public/css/readme-box.less @@ -88,7 +88,6 @@ div.readme_box pre { font-size: 13px !important; overflow: visible !important; line-height: 140% !important; - background-color: @grey7; } div.readme_box img { @@ -156,10 +155,10 @@ div.readme_box code { } div.readme_box pre { - border: @border-thickness solid @grey5; + border: @border-thickness solid #CBDBEB; overflow: auto; padding: .5em; - background-color: @grey7; + background-color: #FCFEFF; } div.readme_box pre > code { diff --git a/rhodecode/public/css/select2.less b/rhodecode/public/css/select2.less --- a/rhodecode/public/css/select2.less +++ b/rhodecode/public/css/select2.less @@ -17,7 +17,7 @@ .select2-search, .select2-search input {.box-sizing(border-box);} .select2-container .select2-choice{display:block; line-height:1em; -webkit-touch-callout:none;-moz-user-select:none;-ms-user-select:none;user-select:none; } -.main .select2-container .select2-choice { background-color: white; } +.main .select2-container .select2-choice { background-color: white; box-shadow: @button-shadow;} .select2-container .select2-choice abbr { display: none; width: 12px; height: 12px; position: absolute; right: 24px; top: 8px; font-size: 1px; text-decoration: none; border: 0; background: url('../images/select2.png') right top no-repeat; cursor: pointer; outline: 0; } .select2-container.select2-allowclear .select2-choice abbr {display: inline-block;} .select2-container .select2-choice abbr:hover { background-position: right -11px; cursor: pointer; } @@ -92,10 +92,18 @@ select.select2{height:28px;visibility:hi min-width: 160px; margin: 0 @padding 0 0; padding: 0; - border: @border-thickness solid @rcblue; + border: @border-thickness solid @grey5; border-radius: @border-radius; - color: @rcblue; + color: @grey2; background-color: white; + + a { + color: @grey2; + + &:hover { + color: @rcdarkblue; + } + } } .drop-menu-dropdown { @@ -120,7 +128,7 @@ select.select2{height:28px;visibility:hi a { display:block; - padding: .9em; + padding: .7em; padding-right: 2em; position: relative; @@ -129,7 +137,7 @@ select.select2{height:28px;visibility:hi content: "\00A0\25BE"; right: .1em; line-height: 1em; - top: 0.4em; + top: 0.2em; width: 1em; font-size: 20px; } @@ -157,6 +165,12 @@ select.select2{height:28px;visibility:hi width: 100%; margin: .5em 0; padding: .5em; + border-color: @grey4; + + &:focus, &:hover { + border-color: @rcblue; + box-shadow: @button-shadow; + } } .select2-no-results { @@ -176,7 +190,13 @@ select.select2{height:28px;visibility:hi &:hover, &.select2-highlighted { - background-color: @rclightblue; + background-color: @grey7; + + .select2-result-label { + &:hover { + color: @grey1!important; + } + } } &.select2-result-with-children { @@ -189,8 +209,7 @@ select.select2{height:28px;visibility:hi display:block; padding: 8px; font-family: @text-regular; - border-bottom: @border-thickness solid @rclightblue; - color: @rcblue; + color: @grey2; cursor: pointer; } &.select2-result-with-children { @@ -205,7 +224,7 @@ select.select2{height:28px;visibility:hi ul.select2-result-sub li .select2-result-label { padding-left: 16px; font-family: @text-regular; - color: @rcblue; + color: @grey2; cursor: pointer; } } diff --git a/rhodecode/public/css/summary.less b/rhodecode/public/css/summary.less --- a/rhodecode/public/css/summary.less +++ b/rhodecode/public/css/summary.less @@ -3,30 +3,33 @@ // Used for headers and file detail summary screens. .summary { - float: left; + clear: both; + float: none; position: relative; width: 100%; margin: 0; padding: 0; + background: #FCFCFC; + border: 1px solid #EAEAEA; + border-radius: @border-radius; + margin-bottom: 20px; .summary-detail-header { - float: left; display: block; width: 100%; - margin-bottom: @textmargin; + margin-bottom: 10px; padding: 0 0 .5em 0; border-bottom: @border-thickness solid @border-default-color; .breadcrumbs { - float: left; display: inline; margin: 0; padding: 0; } + h4 { - float: left; margin: 0 1em 0 0; - padding: 0; + padding: 10px 0 5px 20px; line-height: 1.2em; font-size: @basefontsize; } @@ -42,11 +45,11 @@ } .summary-detail { - float: left; + float: none; position: relative; - width: 73%; - margin: 0 3% @space 0; - padding: 0; + width: 100%; + margin: 0; + padding: 0 0 20px 0; .file_diff_buttons { margin-top: @space; @@ -62,18 +65,37 @@ height: 30px; margin: 0; padding: 0; + width: 130px; font-weight: @text-semibold-weight; font-family: @text-semibold; } + .left-clone select { + width: 130px; + margin-right: 0; + background-color: @grey7; + border-color: @grey4; + color: #5C5C5C; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } .right-clone { - float: right; - width: 83%; + float: left; + width: ~"calc(100% - 170px)"; + + .clipboard-action { + margin-left: -30px; + } } .clone_url_input { - width: ~"calc(100% - 35px)"; - padding: 5px; + width: ~"calc(100% - 90px)"; + padding: 6px 30px 6px 10px; + height: 14px; + box-shadow: 0 1px 1px 0 rgba(0,0,0,0.07); + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin-left: -1px; } &.directory { @@ -123,18 +145,32 @@ border: @border-thickness solid @border-default-color; .border-radius(@border-radius); } + + .btn-collapse { + clear: both; + float: none; + background: #F7F7F7; + text-align: center; + color: #949494; + font-size: 11px; + + &:hover { + background: #f1f1f1; + color: #2B2B2D; + } + } } // this is used outside of just the summary .fieldset, // similar to form fieldset .summary .sidebar-right-content { // these have to match clear: both; - float: left; + float: none; position: relative; display:block; width: 100%; - min-height: 1em; - margin-bottom: @textmargin; + min-height: 20px; + margin-bottom: 10px; padding: 0; line-height: 1.2em; @@ -147,19 +183,28 @@ } .summary .sidebar-right-content { - margin-bottom: @space; + margin-bottom: 0; .rc-user { min-width: 0; } + + li { + list-style: none; + line-height: normal; + } +} + +.summary { + .fieldset { + margin-bottom: 0; + } } .fieldset { .left-label { // similar to form legend - float: left; display: block; - width: 25%; margin: 0; padding: 0; font-weight: @text-semibold-weight; @@ -167,16 +212,78 @@ } .left-label-summary { - .left-label; - width: 150px; + padding-left: 20px; + margin-bottom: 5px; + + p { + margin-bottom: 5px; + color: @grey1; + float: left; + width: 130px; + + &.spacing { + margin-top: 10px; + } + } + + .right-label-summary { + float: left; + margin-top: 7px; + width: ~"calc(100% - 160px)"; + } } - + + .left-label-summary-files { + padding-left: 45px; + margin-top: 5px; + + p { + margin-bottom: 5px; + color: @grey1; + float: left; + width: 130px; + + &.spacing { + margin-top: 10px; + } + } + + .right-label-summary { + float: left; + margin-top: 7px; + } + } + + .left-content { + width: ~"calc(60% - 20px)"; + float: left; + margin: 15px 0 15px 20px; + + .rc-user { + min-width: auto; + max-width: none; + min-height: auto; + padding-right: 5px; + } + + .left-content-avatar { + width: 45px; + float: left; + margin-top: 8px; + } + + .left-content-message { + float: left; + width: ~"calc(100% - 45px)"; + } + } + .right-content { // similar to form fields float: left; display: block; - width: 75%; - margin: 0 0 0 -15%; - padding: 0 0 0 15%; + width: ~"calc(40% - 20px)"; + text-align: right; + margin: 15px 20px 15px 0; .truncate-wrap, .truncate { @@ -187,11 +294,49 @@ .commit-long { overflow-x: auto; } + + .commit-info { + margin-top: 7px; + } + + .summary-tag, + .summary-tagtag, + .summary-branchtag, + .summary-booktag, + .summary-metatag, + .summary-perm_tag { + background:transparent; + border: none; + box-shadow: none; + margin-left: 10px; + font-size: 13px; + } + + .summary-tag span, + .summary-tag i, + .summary-tag a { + color: @grey1; + } + + } + .commit { + color: @grey1; + margin-bottom: 5px; + white-space: pre; } .commit.truncate-wrap { overflow:hidden; text-overflow: ellipsis; } + .commit-author { + color: @grey1; + } + .commit-date { + color: @grey4; + } + .fieldset-text-line { + line-height: 36px; + } } // expand commit message @@ -214,19 +359,46 @@ .comments-show { display: inline; } .comments-hide { display: none; } - + &.comments-visible { .comments-show { display: none; } .comments-hide { display: inline; } } } - + // Quick Start section + +.empty-repo { + border: 1px solid #EAEAEA; + border-bottom: 0; + border-radius: @border-radius; + padding: 0 20px; +} + +.empty-repo h3, .quick_start p { + margin-bottom: 10px; +} + +.quick_start pre { + background: #FCFEFF; + border: 1px solid #CBDBEB; + box-shadow: @button-shadow; + padding: 10px 15px; + border-radius: 4px; + color: @grey2; +} + +.clear-fix { + clear: both; +} + .quick_start { - float: left; display: block; position: relative; - width: 100%; + border: 1px solid #EAEAEA; + border-top: 0; + border-radius: @border-radius; + padding: 0 20px; // adds some space to make copy and paste easier .left-label, @@ -235,6 +407,7 @@ } } + .submodule { .summary-detail { width: 100%; @@ -250,23 +423,32 @@ display: block; width: 100%; margin: 0; - padding: @space 0 10px 0; - border-top: @border-thickness solid @border-default-color; + + .file-filename { + float:left; + padding: 10px; + } - .stats { - float: left; + .file-stats { + padding: 10px; + float:right; } - .stats-filename { - font-size: 120%; - } + + .stats-first-item { padding: 0px 0px 0px 3px; } + .stats-info { + font-size: 11px; + color: @grey4; + } + .buttons { float: right; text-align: right; color: @grey4; + padding: 10px; } .file-container { @@ -286,6 +468,25 @@ .repo-size { margin-bottom: .5em; } - + } +.rctable.repo_summary { + border: 1px solid #eaeaea; + border-radius: 2px; + border-collapse: inherit; + border-bottom: 0; + + th { + background: @grey7; + border-bottom: 0; + } + + td { + border-color: #eaeaea; + } + + td.td-status { + padding: 0 0 0 10px; + } +} diff --git a/rhodecode/public/css/tables.less b/rhodecode/public/css/tables.less --- a/rhodecode/public/css/tables.less +++ b/rhodecode/public/css/tables.less @@ -33,7 +33,7 @@ table.dataTable { td { height: auto; max-width: 20%; - padding: .65em 1em .65em 0; + padding: .65em 0 .65em 1em; vertical-align: middle; border-bottom: @border-thickness solid @grey5; white-space: normal; @@ -103,6 +103,11 @@ table.dataTable { } } + &.td-icon { + min-width: 20px; + width: 20px; + } + &.td-hash { min-width: 80px; width: 200px; @@ -113,6 +118,12 @@ table.dataTable { } } + &.td-graphbox { + width: 100px; + max-width: 100px; + min-width: 100px; + } + &.td-time { width: 160px; white-space: nowrap; @@ -141,6 +152,11 @@ table.dataTable { } } + &.td-grid-name { + white-space: nowrap; + min-width: 300px; + } + &.td-componentname { white-space: nowrap; } @@ -403,29 +419,11 @@ table.trending_language_tbl { .trending_language { position: relative; - width: 100%; - height: 19px; overflow: hidden; - background-color: @grey6; + color: @text-color; + width: 400px; - span, b{ - position: absolute; - display: block; - height: 12px; - margin-bottom: 0px; - white-space: pre; - padding: floor(@basefontsize/4); - top: 0; - left: 0; - } - - span{ - color: @text-color; - z-index: 0; - min-width: 20px; - } - - b { + .lang-bar { z-index: 1; overflow: hidden; background-color: @rcblue; @@ -437,6 +435,9 @@ table.trending_language_tbl { // Changesets #changesets.rctable { + th { + padding: 0 1em 0.65em 0; + } // td must be fixed height for graph td { diff --git a/rhodecode/public/css/tags.less b/rhodecode/public/css/tags.less --- a/rhodecode/public/css/tags.less +++ b/rhodecode/public/css/tags.less @@ -13,15 +13,19 @@ font-size: (-1 + @basefontsize); //fit in tables line-height: .9em; border: none; + box-shadow: @button-shadow; .border-radius(@border-radius); font-family: @text-regular; background-image: none; color: @grey4; - .border ( @border-thickness-tags, @grey4 ); + .border ( @border-thickness-tags, @grey5 ); white-space: nowrap; a { color: inherit; - text-decoration: underline; + + &:hover { + color: @grey2; + } i, [class^="icon-"]:before, @@ -29,6 +33,10 @@ text-decoration: none; } } + + &:hover { + border-color: @grey4; + } } .tag0 { .border ( @border-thickness-tags, @grey4 ); color:@grey4; } diff --git a/rhodecode/public/css/type.less b/rhodecode/public/css/type.less --- a/rhodecode/public/css/type.less +++ b/rhodecode/public/css/type.less @@ -46,6 +46,13 @@ h6, .h6 { font-size: 1em; font-weight .breadcrumbs { font-size: @repo-title-fontsize; margin: 0; + width: ~"calc(100% - 180px)"; + float: left; + + h4 { + font-size: @basefontsize; + margin-bottom: 15px; + } } .breadcrumbs_light { @@ -156,6 +163,19 @@ pre { // Emphasis & misc // ------------------------- +.discreet { + color: @grey4; + font-size: 85%; + font-weight: normal; + + a { + color: @grey4; + + &:hover { + color: @rcdarkblue; + } + } +} small, .small { @@ -231,7 +251,8 @@ mark, clear: both; float: left; width: 100%; - margin: @pagepadding/2 0 @pagepadding; + margin: @pagepadding/2 0 @pagepadding/4; + min-height: 25px; .breadcrumbs { float: left; @@ -285,6 +306,11 @@ mark, } .title-content { + + &.repo-title { + float: none + } + float: left; margin: 0; padding: 0; diff --git a/rhodecode/public/css/variables.less b/rhodecode/public/css/variables.less --- a/rhodecode/public/css/variables.less +++ b/rhodecode/public/css/variables.less @@ -8,13 +8,15 @@ @rchighlightblue: lighten(@rcblue, 35%); // Secondary Colors (greyscale) -@grey1: #202020; //midnight -@grey2: #323232; //charcoal -@grey3: #666666; //tungsten -@grey4: #979797; //light grey +@black: #000; +@white: #fff; +@grey1: #2B2B2D; //midnight +@grey2: #5C5C5C; //charcoal +@grey3: #7E7F7F; //tungsten +@grey4: #949494; //light grey @grey5: #dbd9da; //greyish @grey6: #eeeeee; //silver -@grey7: #f9f9f9; //light silver +@grey7: #F5F5F5; //light silver // special for navigation @nav-grey: #CDCCCD; @@ -102,7 +104,7 @@ // FORMS (new) @border-thickness-inputs: 1px; -@input-padding: @button-padding; //needs to match button padding +@input-padding: .6em; //needs to match button padding // TODO: johbo: Needed for working computation of paddings around labels etc. // Expected to be replaced once we are done with the form refactoring. @input-padding-px: 12px; @@ -128,10 +130,14 @@ @fields-input-l: 720px; // BUTTONS -@button-padding: .9em; +@button-padding: .7em; +@button-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.07); + +// DROPDOWNS +@dropdown-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.07); // DEFAULT WIDTHS -@wrapper-maxwidth: 1200px; +@wrapper-maxwidth: 1600px; @sidebar-width: 145px; @sidebar-all-width: @sidebar-width + 2 * @sidebarpadding; @sidebar-small-width: 100px; diff --git a/rhodecode/public/fonts/RCIcons/config.json b/rhodecode/public/fonts/RCIcons/config.json new file mode 100755 --- /dev/null +++ b/rhodecode/public/fonts/RCIcons/config.json @@ -0,0 +1,623 @@ +{ + "name": "rcicons", + "css_prefix_text": "icon-", + "css_use_suffix": false, + "hinting": true, + "units_per_em": 1000, + "ascent": 850, + "copyright": "RhodeCode GmbH", + "glyphs": [ + { + "uid": "a5f9b6d4d795603e6e29a5b8007cc139", + "css": "bookmark", + "code": 59395, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M780 990L520 700C510 690 495 690 485 700L225 995C205 1015 180 1000 180 965V35C175 15 190 0 205 0H795C810 0 825 15 825 35V960C825 995 795 1010 780 990Z", + "width": 1000 + }, + "search": [ + "bookmark" + ] + }, + { + "uid": "fbc028d3a6a0df72f8f508ff5dfbab72", + "css": "tag", + "code": 59397, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M459.8 62.5L93.8 53.6C75.9 53.6 62.5 67 62.5 84.8L75.9 450.9C75.9 459.8 80.4 464.3 84.8 473.2L549.1 937.5C562.5 950.9 580.4 950.9 593.8 937.5L946.4 584.8C959.8 571.4 959.8 553.6 946.4 540.2L477.7 71.4C473.2 67 464.3 62.5 459.8 62.5ZM357.1 285.7C357.1 321.4 325.9 352.7 290.2 352.7 254.5 352.7 223.2 321.4 223.2 285.7 223.2 250 254.5 218.8 290.2 218.8S357.1 245.5 357.1 285.7Z", + "width": 1000 + }, + "search": [ + "tag" + ] + }, + { + "uid": "1c67c02366438b324c184ff9e356dca1", + "css": "branch", + "code": 59396, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M875 250C875 174.1 817 116.1 741.1 116.1S607.1 174.1 607.1 250C607.1 299.1 633.9 339.3 669.6 361.6 651.8 504.5 531.3 544.6 459.8 558V245.5C504.5 223.2 531.3 183 531.3 133.9 531.3 58 473.2 0 397.3 0S263.4 58 263.4 133.9C263.4 183 290.2 227.7 330.4 250V750C290.2 772.3 263.4 817 263.4 866.1 263.4 942 321.4 1000 397.3 1000S531.3 942 531.3 866.1C531.3 817 504.5 772.3 464.3 750V692C526.8 683 629.5 660.7 709.8 580.4 767.9 522.3 799.1 450.9 808 366.1 848.2 343.8 875 299.1 875 250ZM397.3 89.3C424.1 89.3 442 107.1 442 133.9S424.1 178.6 397.3 178.6 352.7 160.7 352.7 133.9 370.5 89.3 397.3 89.3ZM397.3 910.7C370.5 910.7 352.7 892.9 352.7 866.1S370.5 821.4 397.3 821.4 442 839.3 442 866.1 419.6 910.7 397.3 910.7ZM741.1 205.4C767.9 205.4 785.7 223.2 785.7 250S767.9 294.6 741.1 294.6 696.4 276.8 696.4 250 718.8 205.4 741.1 205.4Z", + "width": 1000 + }, + "search": [ + "branch" + ] + }, + { + "uid": "b75f7b47706aebd803ef370082e8e334", + "css": "group", + "code": 59407, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M961.5 630.8V646.2C961.5 650 957.7 657.7 950 657.7H788.5 784.6C769.2 638.5 746.2 619.2 707.7 615.4 673.1 607.7 653.8 600 638.5 592.3 646.2 584.6 657.7 580.8 669.2 576.9 715.4 569.2 726.9 553.8 734.6 542.3 742.3 530.8 742.3 519.2 734.6 503.8 726.9 488.5 703.8 461.5 703.8 423.1 703.8 384.6 703.8 319.2 776.9 319.2H784.6 792.3C865.4 323.1 869.2 384.6 865.4 423.1 865.4 461.5 842.3 492.3 834.6 503.8 826.9 519.2 826.9 530.8 834.6 542.3 842.3 553.8 857.7 569.2 900 576.9 953.8 580.8 961.5 623.1 961.5 630.8 961.5 630.8 961.5 630.8 961.5 630.8ZM253.8 646.2C269.2 630.8 292.3 615.4 323.1 611.5 361.5 603.8 384.6 596.2 396.2 584.6 388.5 576.9 376.9 569.2 361.5 565.4 315.4 557.7 303.8 542.3 296.2 530.8 288.5 519.2 288.5 507.7 296.2 492.3 303.8 476.9 326.9 450 326.9 411.5 326.9 373.1 326.9 307.7 253.8 307.7H246.2 234.6C161.5 311.5 157.7 373.1 161.5 411.5 161.5 450 184.6 480.8 192.3 492.3 200 507.7 200 519.2 192.3 530.8 184.6 542.3 169.2 557.7 126.9 565.4 80.8 573.1 73.1 615.4 73.1 619.2 73.1 619.2 73.1 619.2 73.1 619.2V634.6C73.1 638.5 76.9 646.2 84.6 646.2H246.2 253.8ZM707.7 634.6C634.6 623.1 611.5 600 600 580.8 588.5 561.5 588.5 542.3 600 519.2 611.5 496.2 650 450 653.8 388.5 657.7 326.9 653.8 223.1 534.6 219.2H519.2 503.8C384.6 223.1 380.8 323.1 384.6 384.6 388.5 446.2 423.1 492.3 438.5 515.4 450 538.5 450 557.7 438.5 576.9 426.9 596.2 403.8 619.2 330.8 630.8 257.7 642.3 246.2 711.5 246.2 719.2 246.2 719.2 246.2 719.2 246.2 719.2V742.3C246.2 750 253.8 757.7 261.5 757.7H519.2 776.9C784.6 757.7 792.3 750 792.3 742.3V719.2C792.3 719.2 792.3 719.2 792.3 719.2 788.5 715.4 780.8 646.2 707.7 634.6Z", + "width": 1000 + }, + "search": [ + "group" + ] + }, + { + "uid": "7ae0ef039bb0217d9581e44b09448905", + "css": "fork", + "code": 59409, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M792.3 196.2C792.3 138.5 746.2 96.2 692.3 96.2 634.6 96.2 592.3 142.3 592.3 196.2 592.3 230.8 611.5 261.5 638.5 280.8 626.9 365.4 569.2 403.8 511.5 423.1 453.8 407.7 396.2 369.2 384.6 280.8 411.5 261.5 430.8 230.8 430.8 196.2 430.8 138.5 384.6 96.2 330.8 96.2S223.1 138.5 223.1 196.2C223.1 234.6 246.2 269.2 276.9 284.6 288.5 392.3 353.8 473.1 457.7 511.5V673.1C426.9 692.3 407.7 723.1 407.7 761.5 407.7 819.2 453.8 861.5 507.7 861.5S607.7 815.4 607.7 761.5C607.7 723.1 588.5 692.3 557.7 673.1V511.5C661.5 473.1 726.9 392.3 738.5 284.6 769.2 265.4 792.3 234.6 792.3 196.2ZM326.9 161.5C346.2 161.5 361.5 176.9 361.5 196.2S346.2 226.9 326.9 226.9 292.3 215.4 292.3 196.2 307.7 161.5 326.9 161.5ZM507.7 796.2C488.5 796.2 473.1 780.8 473.1 761.5S488.5 726.9 507.7 726.9C526.9 726.9 542.3 742.3 542.3 761.5S526.9 796.2 507.7 796.2ZM692.3 161.5C711.5 161.5 726.9 176.9 726.9 196.2S711.5 226.9 692.3 226.9 657.7 211.5 657.7 192.3 673.1 161.5 692.3 161.5Z", + "width": 1000 + }, + "search": [ + "fork" + ] + }, + { + "uid": "65e66c3e7d74e2c345fb78fadd400d3f", + "css": "rhodecode", + "code": 59441, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M174.6 216.8C173.4 220.9 172.2 225 171 229.1 168.1 239.1 165.2 249.1 162.3 259.1 158.7 271.6 155 284.2 151.4 296.7 148 308.4 144.6 320.1 141.2 331.8 139 339.3 136.8 346.8 134.7 354.3 134.4 355.4 134.1 356.5 133.7 357.6 133.7 357.7 133.9 358.2 134 358.3 134.3 359 134.5 359.7 134.8 360.5 137.2 367.3 139.7 374.1 142.1 381 146 392 149.9 403 153.9 414.1 158.3 426.5 162.8 439 167.2 451.4 171.1 462.5 175.1 473.6 179 484.7 181.5 491.7 184 498.6 186.4 505.6 186.8 506.7 187.2 507.7 187.5 508.8 187.8 509.6 188.6 510.4 189 511.1 192.8 516.9 196.5 522.6 200.3 528.4 206.5 537.9 212.7 547.4 219 556.9 226.2 567.9 233.4 578.9 240.6 590 247.3 600.3 254.1 610.6 260.8 620.9 265.6 628.2 270.4 635.6 275.2 642.9 276.4 644.8 277.6 646.6 278.9 648.5 279.2 649 279.5 649.5 279.8 649.8 282.7 652.6 285.5 655.4 288.4 658.2 294.6 664.3 300.9 670.5 307.1 676.6 315.5 684.9 323.9 693.2 332.4 701.4 341.8 710.6 351.2 719.9 360.6 729.1 369.8 738.1 378.9 747.1 388.1 756.1 395.8 763.7 403.6 771.3 411.3 778.9 416.4 783.9 421.5 788.9 426.6 793.9 428.2 795.5 429.8 797.3 431.6 798.6 438.9 803.9 446.1 809.2 453.4 814.5 463.7 822 473.9 829.5 484.2 837 487.6 839.5 491.1 842 494.5 844.5 495.3 845.1 496.1 845.7 496.9 846.3 497.2 846.5 497.2 846.6 497.6 846.4 504.7 842.7 511.8 839.1 518.9 835.4 530.3 829.5 541.7 823.6 553.1 817.7 559.2 814.5 565.4 811.4 571.5 808.2 571.9 808 572.3 807.1 572.6 806.8 573.7 805.4 574.8 804 576 802.5 580.2 797.2 584.3 791.9 588.5 786.7 594.7 778.9 600.8 771.1 607 763.3 614.5 753.8 622 744.3 629.5 734.8 637.7 724.5 645.8 714.1 654 703.8 662.1 693.5 670.3 683.2 678.4 672.9 685.9 663.5 693.3 654 700.8 644.6 706.9 636.9 713 629.2 719.1 621.5 723.2 616.4 727.2 611.2 731.3 606.1 732.7 604.4 734 602.6 735.4 600.9 735.2 600.8 734.8 600.8 734.6 600.7 733.8 600.5 733 600.4 732.2 600.2 729.1 599.6 726 598.9 722.9 598.2 718 597.1 713 596 708.1 594.8 701.5 593.2 694.9 591.5 688.3 589.7 680.2 587.5 672.2 585.2 664.1 582.9 654.7 580.1 645.4 577.2 636.1 574.1 625.6 570.6 615.2 567 604.8 563.3 593.4 559.1 582 554.8 570.8 550.2 558.6 545.3 546.6 540.1 534.6 534.8 521.9 529.1 509.3 523.1 496.8 516.8 483.7 510.2 470.7 503.4 457.9 496.2 444.6 488.7 431.4 480.9 418.5 472.8 405.1 464.4 392 455.6 379.1 446.4 365.9 437 352.9 427.1 340.3 416.9 327.4 406.4 314.8 395.5 302.7 384.2 290.3 372.6 278.3 360.6 266.8 348.1 255.1 335.3 243.8 322.1 233.2 308.4 222.3 294.4 212 279.9 202.4 265 192.5 249.7 183.4 233.9 175 217.8 175 217.4 174.8 217.1 174.6 216.8ZM172.1 214.2C170.7 218.7 169.3 223.3 167.8 227.8 164.5 238.5 161.1 249.2 157.8 259.9 153.9 272.4 150 285 146.1 297.5 143 307.5 139.9 317.4 136.7 327.4 135.9 330.1 135 332.7 134.2 335.4 134 336.1 133.6 336.7 133.8 337.4 135.4 342.2 137 347.1 138.6 351.9 141.9 361.9 145.2 371.8 148.6 381.8 152.7 394.1 156.8 406.5 160.9 418.8 164.9 430.8 168.9 442.8 172.9 454.8 175.9 463.7 178.8 472.6 181.8 481.4 182.6 483.8 183.4 486.2 184.2 488.7 184.4 489.4 184.6 490.1 184.9 490.8 187.2 495 189.5 499.2 191.8 503.4 196.8 512.6 201.9 521.8 206.9 531 213.2 542.4 219.4 553.9 225.7 565.3 231.7 576.2 237.6 587.1 243.6 598 247.8 605.6 251.9 613.2 256.1 620.8 257.3 623 258.2 625.4 259.9 627.2 264.1 631.7 268.3 636.2 272.5 640.7 280.2 648.9 287.9 657.2 295.5 665.4 304.5 675 313.5 684.7 322.4 694.3 330.5 703 338.6 711.7 346.7 720.4 351.8 725.8 356.8 731.3 361.9 736.7 363.5 738.4 365 740 366.6 741.6 372.3 747.3 378 753 383.7 758.7 392.5 767.5 401.2 776.2 410 785 419.1 794.1 428.3 803.3 437.4 812.4 444.2 819.2 451.1 826.1 457.9 832.9 459.6 834.6 461.3 836.3 463 838 463.3 838.3 463.6 838.6 463.8 838.8 463.9 838.9 465.1 838.7 465.3 838.6 475.9 837.2 486.5 835.8 497 834.5 505.6 833.4 514.1 832.3 522.7 831.2 523 831.2 523.7 830.1 523.9 829.9 525.1 828.6 526.3 827.2 527.6 825.9 532.1 820.9 536.7 815.9 541.2 810.9 547.9 803.5 554.6 796.1 561.4 788.7 569.6 779.7 577.7 770.7 585.9 761.8 594.8 752 603.6 742.3 612.5 732.5 621.3 722.8 630.1 713.1 639 703.4 647 694.5 655.1 685.7 663.1 676.8 669.6 669.6 676.2 662.4 682.7 655.2 687 650.5 691.3 645.8 695.6 641 696.6 639.9 697.7 638.7 698.7 637.6 698.9 637.4 699.6 636.9 699.6 636.6 699.6 636.5 696.6 635.7 696.5 635.7 693.5 634.8 690.4 633.9 687.4 633 682.6 631.5 677.8 630 673 628.4 666.6 626.3 660.1 624.1 653.8 621.8 645.9 619 638.1 616.1 630.3 613.1 621.2 609.6 612.1 606 603.1 602.2 592.9 598 582.8 593.6 572.8 589 561.8 584 550.8 578.8 540 573.4 528.3 567.6 516.7 561.6 505.2 555.3 493 548.7 480.9 541.8 469 534.6 456.5 527.1 444.1 519.3 431.9 511.2 419.2 502.8 406.7 494 394.5 484.9 381.8 475.5 369.5 465.8 357.4 455.7 345 445.3 332.8 434.6 321.1 423.4 309.1 412 297.4 400.2 286.2 388 274.7 375.5 263.7 362.6 253.2 349.3 242.5 335.7 232.3 321.7 222.8 307.2 213 292.4 203.9 277.2 195.5 261.7 186.8 246.5 179 230.5 172.1 214.2ZM169.5 204C168.8 207.8 168.1 211.6 167.3 215.4 165.5 224.9 163.7 234.5 161.9 244 159.5 256.5 157.1 269 154.7 281.5 152.3 294.2 149.8 307 147.4 319.7 145.5 329.9 143.5 340.1 141.6 350.3 140.7 355.2 139.7 360.1 138.8 365 138.7 365.7 139.1 366.4 139.3 367 140.2 369.6 141.1 372.2 142 374.8 145.4 384.5 148.7 394.3 152.1 404 156.4 416.4 160.7 428.7 165 441.1 168.8 452.1 172.6 463 176.4 474 178.3 479.5 180.2 485 182.1 490.5 182.3 491.2 182.7 491.8 183 492.4 184.2 494.8 185.4 497.1 186.5 499.5 190.9 508.4 195.4 517.2 199.8 526.1 205.6 537.7 211.4 549.3 217.2 560.9 222.7 571.9 228.2 583 233.8 594 237.4 601.2 241 608.3 244.6 615.5 245.2 616.6 245.7 617.7 246.3 618.8 246.7 619.6 247.6 620.4 248.2 621.1 252.8 626.6 257.4 632.1 262 637.7 269.5 646.7 276.9 655.6 284.4 664.6 292.8 674.7 301.3 684.9 309.7 695 317.2 704 324.8 713.1 332.3 722.1 337 727.8 341.8 733.5 346.5 739.1 347.2 740 347.9 740.8 348.7 741.7 348.9 741.9 349.2 742 349.4 742.2 350.2 742.7 350.9 743.2 351.7 743.7 358.7 748.5 365.8 753.3 372.8 758.1 383.3 765.3 393.9 772.5 404.4 779.7 414.6 786.6 424.7 793.6 434.9 800.5 440.8 804.5 446.7 808.6 452.7 812.6 456.3 815.1 459.5 818.1 462.9 820.8 472.5 828.7 482.1 836.7 491.7 844.6 498.5 850.2 505.4 855.9 512.2 861.5 512.8 862 512.7 861.9 513.3 861.3 514.2 860.3 515.2 859.2 516.1 858.2 520 853.9 524 849.6 527.9 845.3 534 838.6 540.2 831.9 546.3 825.2 554 816.8 561.7 808.3 569.4 799.9 578.1 790.4 586.7 781 595.4 771.5 604.4 761.7 613.3 751.9 622.3 742.1 630.9 732.6 639.6 723.2 648.2 713.7 655.9 705.3 663.6 696.9 671.3 688.5 677.4 681.8 683.5 675.1 689.6 668.4 693.5 664.1 697.4 659.9 701.3 655.6 702.4 654.4 703.5 653.2 704.6 652 704.6 652 704.6 652 704.6 652 704.6 652 704.6 652 704.6 652 704.6 652.1 701.6 651.3 701.5 651.3 698.5 650.5 695.5 649.5 692.6 648.6 687.9 647.1 683.1 645.5 678.4 643.8 672.1 641.6 665.8 639.2 659.5 636.9 651.8 634 644.1 630.9 636.4 627.8 627.5 624.1 618.6 620.3 609.7 616.4 599.7 612 589.8 607.4 580 602.7 569.2 597.5 558.4 592.1 547.7 586.6 536.2 580.6 524.8 574.4 513.4 568 501.4 561.2 489.5 554.2 477.7 546.9 465.3 539.3 453.1 531.4 441.1 523.3 428.6 514.8 416.3 506.1 404.2 497 391.7 487.7 379.5 478 367.5 468 355.2 457.8 343.2 447.2 331.5 436.3 319.6 425.2 308 413.6 296.8 401.7 285.4 389.6 274.5 377.1 264 364.3 253.3 351.2 243.2 337.8 233.6 323.9 223.8 309.8 214.6 295.4 206.1 280.5 197.4 265.4 189.4 249.9 182.1 234 177.7 224.2 173.5 214.2 169.5 204ZM866 183.5C863.9 179.4 861.1 176.2 857.1 174 851.9 171.1 846.2 168.9 840.7 166.5 829.5 161.7 818.2 157.4 806.7 153.4 783.6 145.4 760 138.9 736.3 132.9 711.7 126.7 687.1 120.9 662.3 115.7 637.1 110.4 611.7 105.6 586.3 101.4 561.2 97.2 536 93.1 510.5 91.1 497.8 90.1 485 89.9 472.4 91.3 465.9 92 459.4 93.2 453 94.2 446.6 95.2 440.1 96.2 433.7 97.3 408.2 101.5 382.8 106 357.4 111 332.2 115.9 307.1 121.2 282.1 126.9 257.2 132.5 232.6 139.2 208.4 147.3 196.3 151.4 184.2 155.8 172.3 160.5 166.4 162.8 160.5 165.2 154.6 167.7 151.7 168.9 148.8 170.2 145.8 171.4 143.2 172.5 140.6 173.5 138.1 174.7 134 176.7 130.6 179.7 128.3 183.6 127 185.8 126.2 188.2 125.3 190.6 124.2 193.6 123.1 196.6 122.1 199.6 118.1 211.5 114.9 223.7 112.5 236 107.7 260.4 106 285.4 106.8 310.2 107.2 322.7 108.2 335.3 109.7 347.7 111.2 360.2 112.7 372.8 115.1 385.2 119.8 410.4 126.7 435.1 134.8 459.3 138.9 471.4 143.3 483.5 147.9 495.4 152.2 506.5 157.5 517.3 162.7 528 173 549.2 184.4 569.8 196.6 589.9 208.8 609.9 221.9 629.3 235.7 648.1 249.5 666.8 264.1 685 279.3 702.6 295.3 721.1 311.7 739.2 328.6 756.9 345.6 774.8 363 792.2 381 809 398.9 825.9 417.4 842.2 436.4 857.8 445.6 865.4 454.9 872.8 464.2 880.2 473.6 887.7 483.1 895.1 492 903.2 494.3 905.2 496.5 907.3 498.7 909.5 498.9 909.7 499.7 910.8 500 910.8 500.2 910.8 500.5 910.8 500.7 910.8 501.2 910.8 502 911 502.5 910.8 507.3 907.1 512 903.3 516.8 899.6 526.2 892.1 535.6 884.6 544.9 876.9 563.3 861.7 581.4 846.2 599.2 830.3 616.9 814.5 634.1 798.2 651 781.5 667.9 764.7 684.4 747.5 700.3 729.7 716.3 711.8 731.8 693.4 746.5 674.4 761 655.7 774.8 636.5 787.8 616.8 800.7 597.2 812.8 577 823.8 556.2 835 535.1 845.2 513.5 854.3 491.4 863.4 469.1 871.2 446.3 877.3 423 883.4 399.9 887.8 376.4 890.3 352.7 892.9 328.6 893.4 304.3 892 280 891.8 276.9 891 273.8 890.3 270.7 889.7 267.7 889 264.6 888.4 261.6 887.2 255.7 886 249.9 884.7 244 882.3 233 879.7 222 876.5 211.1 873.4 201.8 870.1 192.5 866 183.5 863.5 178.4 878.8 211.7 866 183.5ZM814.8 393.5C808.1 418.2 799.5 442.5 789.4 466 780 487.9 770 509.6 758.5 530.5 747.4 550.7 735.1 570.3 722 589.3 708.8 608.4 694.7 626.8 680 644.8 664.8 663.4 649 681.5 632.7 699.1 615.9 717.3 598.5 734.9 580.5 752 562.5 769.1 544.1 785.7 525.1 801.6 515.7 809.5 506.1 817.3 496.5 824.9 496.1 825.2 495.2 826.3 494.7 826.3 494 826.3 493.3 826.3 492.6 826.3 492 826.3 491.4 825.5 491 825.1 490.5 824.6 490 824.1 489.5 823.6 488.4 822.6 487.2 821.5 486.1 820.5 481.6 816.6 476.9 813.1 472.2 809.4 469.9 807.6 467.6 805.7 465.3 803.8 463.1 801.9 461 799.8 458.8 797.8 454.2 793.7 449.7 789.6 445.2 785.5 435.9 777 426.6 768.5 417.5 759.8 408.4 751.1 399.5 742.3 390.9 733.2 386.7 728.8 382.7 724.3 378.4 720 374.2 715.8 370 711.5 365.8 707.2 349.1 690 332.9 672.5 317.4 654.3 301.8 636 286.9 617 273.1 597.3 259.2 577.5 246.4 556.9 234.5 535.8 222.8 515 212.1 493.7 202.6 471.8 193.1 449.9 184.8 427.4 177.9 404.6 176.1 398.6 174.4 392.6 173.1 386.5 171.7 380.1 170.6 373.6 169.6 367.1 167.6 354.2 166.3 341.2 165.5 328.2 164.7 315.3 164.3 302.3 164.5 289.3 164.7 276.7 165.9 264.2 167.5 251.7 167.9 248.5 168.3 245.4 168.7 242.2 168.9 240.6 169.1 239.1 169.3 237.5 169.5 235.9 169.6 234.3 169.8 232.7 170.1 230.3 171.1 228.1 171.7 225.7 172 224.5 172.2 223.2 172.2 221.9 172.2 220.8 172.8 220.1 173.6 219.5 174.6 218.8 175.6 218.3 176.5 217.5 177.1 217 177.6 216.6 178.4 216.3 179.2 216 180.1 215.7 180.9 215.3 183.9 214.2 186.8 213 189.8 211.9 195.7 209.7 201.6 207.5 207.6 205.3 231.3 196.7 255.3 189 279.7 182.4 292 179.1 304.3 176.1 316.7 173.5 322.9 172.2 329.1 170.6 335.4 169.3 341.7 167.9 348 166.6 354.3 165.4 379.8 160.4 405.4 156.3 431.1 152.5 444 150.6 457 148.8 470 147 473.2 146.6 476.5 146.1 479.7 145.7 481.3 145.5 482.8 145.3 484.4 145.1 485.7 144.9 487.1 145 488.4 145.1 493.9 145.1 499.5 145.3 504.9 146.3 506.2 146.5 507.4 146.8 508.6 147.1 510.1 147.5 511.5 147.8 513 148 516.1 148.4 519.2 148.9 522.3 149.3 528.6 150.2 534.8 151.1 541.1 152 553.7 153.8 566.4 155.7 579 157.7 604.4 161.7 629.7 166 654.8 171.4 680 176.8 705 183.2 729.7 190.3 742.1 193.9 754.4 197.7 766.6 201.7 772.7 203.7 778.7 205.8 784.7 207.9 787.7 209 790.7 210 793.7 211.1 795.1 211.6 796.6 212.1 798 212.7 798.7 213 799.4 213.2 800.1 213.5 800.8 213.8 801.9 214 802.4 214.5 803.6 215.7 805.3 216.5 806.3 217.9 806.8 218.7 807.1 219.5 807.2 220.5 807.3 221.2 807.2 221.8 807.4 222.5 807.7 223.4 807.9 224.3 808.1 225.2 809.8 231.5 811.2 237.9 812.3 244.4 813.4 250.8 814.1 257.2 814.5 263.6 814.7 266.8 814.8 270 814.9 273.2 814.9 274 814.9 274.7 814.9 275.5 814.9 276.3 815.2 277.1 815.3 277.8 815.7 279.5 816 281.1 816.4 282.8 821.3 306.5 822.7 330.7 820.7 354.8 819.6 367.7 817.6 380.7 814.8 393.5 807.1 421.7 822.5 357.6 814.8 393.5ZM617.6 393.5C616.1 389 614.6 384.5 613.1 379.9 612.9 379.3 612.7 378.7 612.5 378.1 612.4 377.7 612.5 377.1 612.4 376.7 612.3 376.1 612.2 375.5 612.1 374.9 611.8 373.8 611.4 372.8 610.8 371.9 609.7 370.1 608.1 368.5 606.5 367 604.7 365.2 602.4 362.7 599.6 362.7 601.6 360.7 604.3 360 606.5 358.3 607.6 357.4 608.5 356.5 609.7 355.7 610.5 355.2 611.6 354.7 612.1 353.8 612.3 353.4 612.4 352.9 612.4 352.5 612.9 352 613.3 351.5 613.7 350.9 614.4 349.8 614.7 348.6 614.9 347.3 615.1 345.1 615 342.9 615 340.7 615 338.4 615 336.1 615 333.8 615 331.4 615 329 614.4 326.6 613.1 321.5 610 316.8 606.4 313.1 604.7 311.4 603 309.9 601 308.6 598.3 306.9 595.5 305.5 592.7 304.1 589.9 302.7 586.9 301.8 583.8 301.4 581.4 301.1 579 301.1 576.6 301.1 573.9 301.1 571.2 301.1 568.5 301.1 556.2 301.1 543.8 301.1 531.5 301.1 526.9 301.1 522.3 301.1 517.7 301.1 516.9 301.1 516.1 301.1 515.2 301.1 515.1 301.1 515.2 305.3 515.2 305.6 515.2 308.8 515.2 311.9 515.2 315.1 515.2 316.2 515.2 317.3 515.2 318.4 515.2 318.9 515 319.1 515.5 319.1 516.7 319.1 528 319 528 319.2 528 327.2 528 335.2 528 343.2 528 355.8 528 368.3 528 380.9 528 384.6 528 388.3 528 392 528 392.2 528.1 393.4 527.9 393.4 525.4 393.4 522.8 393.4 520.3 393.4 518.9 393.4 517.6 393.4 516.2 393.4 515.9 393.4 515.2 393.2 515.2 393.6 515.2 395.7 515.2 397.8 515.2 400 515.2 401 515.2 414 515.2 414 524.7 414 534.3 414 543.8 414 549.3 414 554.8 414 560.2 414 561.4 414 562.5 414 563.7 414 564 414 563.8 411.1 563.8 410.7 563.8 405.1 563.8 399.6 563.8 394 563.8 393.4 563.9 393.5 563.3 393.5 562 393.5 560.7 393.5 559.3 393.5 557.8 393.5 556.3 393.5 554.8 393.5 554.6 393.5 553.5 393.7 553.5 393.4 553.5 388.4 553.5 383.4 553.5 378.4 553.5 375.6 553.5 372.9 553.5 370.1 553.5 369.4 553.5 368.8 553.5 368.1 553.5 367.7 554.2 367.9 554.5 367.9 557.4 367.9 560.2 367.9 563.1 367.9 565 367.9 566.9 367.9 568.8 367.9 570.1 367.9 571.6 367.7 572.8 368.1 573.9 368.4 574.8 369 575.7 369.7 576.8 370.6 578.3 371.8 578.9 373.1 579.2 373.8 579.2 374.5 579.2 375.3 579.2 376.6 579.6 377.7 580.2 378.9 580.7 380 581.3 381 581.6 382.2 581.7 382.6 581.7 383 581.8 383.4 581.9 384 582 384.6 582.1 385.1 583.1 390.9 584.2 396.6 585.2 402.4 585.6 404.9 586.1 407.3 586.5 409.8 586.6 410.3 586.7 410.8 586.8 411.3 586.8 411.4 587.2 411.4 587.4 411.4 597.8 411.4 608.3 411.4 618.7 411.4 619.2 411.4 619.6 411.4 620.1 411.4 620.2 411.4 620.2 410.7 620.2 410.6 620.2 408.2 620.2 405.7 620.2 403.3 620.2 398.3 620.2 393.3 620.2 388.4 620.2 388.4 620.2 388.4 620.2 388.4 619.3 390.1 618.5 391.8 617.6 393.5ZM592 339.7C592 342 589.2 342.8 587.7 344.1 587.4 344.3 587.1 344.6 586.9 344.8 586.7 344.8 586.4 344.8 586.2 344.9 585.8 345 585.4 345.2 585.1 345.4 584.4 345.9 583.9 346.6 583.2 347 582.1 347.5 580.7 347.3 579.6 347.3 577.9 347.3 576.3 347.3 574.6 347.3 573.9 347.3 573.2 347.3 572.5 347.3 569.5 347.3 566.4 347.3 563.4 347.3 563 347.3 558.8 347.4 558.8 347.2 558.8 337.9 558.8 328.5 558.8 319.2 558.8 319.1 571.7 319.2 573 319.2 577 319.2 581 319.1 584.9 320.1 586.4 320.5 587.8 321 589.2 321.6 590.1 322.1 591 323.2 591.6 324 593.1 325.7 594.1 327.8 594.5 330 594.6 330.7 594.6 331.3 594.6 332 594.3 332.6 594 333.2 593.7 333.9 593.3 334.7 592.9 335.5 592.6 336.3 592.1 337.4 592 338.5 592 339.7ZM722.6 393.5C722.6 384.2 722.6 374.9 722.6 365.6 722.6 357.1 720.9 348 714.6 341.9 707.5 335.1 696.4 333.9 687 334.7 685.1 334.9 683.2 335.3 681.4 336.1 680.4 336.5 679.5 336.9 678.6 337.6 678 338.1 677.3 338.5 676.7 338.8 673.6 340.4 670.5 341.6 668.8 344.9 668.8 335.9 668.8 326.8 668.8 317.8 668.8 311.9 668.8 306 668.8 300.1 668.8 298.4 668.8 296.6 668.8 294.9 668.8 294.4 669.1 293.7 668.5 293.7 657.9 293.7 647.3 293.7 636.7 293.7 635.5 293.7 634.2 293.7 633 293.7 633 293.7 633 297.8 633 298.1 633 303.4 633 308.7 633 314 633 314.3 633.8 314.2 634 314.2 635.4 314.2 636.7 314.2 638.1 314.2 640.6 314.2 643.2 314.2 645.7 314.2 645.9 314.2 645.8 319.4 645.8 319.8 645.8 331.2 645.8 342.6 645.8 353.9 645.8 364.9 645.8 375.8 645.8 386.8 645.8 388 645.8 389.2 645.8 390.3 645.8 391.2 645.7 391 644.6 391 641.6 391 638.7 391 635.7 391 634.8 391 633.9 391 633 391 632.9 391 632.9 391.9 632.9 392 632.9 397.7 632.9 403.4 632.9 409 632.9 409.8 632.9 410.5 632.9 411.3 632.9 411.5 633 411.5 633.2 411.5 634.5 411.5 635.9 411.5 637.2 411.5 649.1 411.5 661 411.5 672.9 411.5 673.4 411.5 681.5 411.5 681.5 411.5 681.5 406.5 681.5 401.5 681.5 396.5 681.5 394.7 681.5 392.9 681.5 391.1 681.5 391.1 675.6 391.1 675.2 391.1 674.8 391.1 668.7 391.1 668.7 391.1 668.7 389.8 668.7 388.5 668.7 387.3 668.7 381.2 668.7 375 668.7 368.9 668.7 366.5 668.7 364.2 668.7 361.8 668.7 361.3 668.7 360.9 668.7 360.4 668.7 360 670.3 358.8 670.6 358.5 671.7 357.5 672.8 356.5 674.2 355.8 674.7 355.5 675.3 355.3 675.8 355.3 676.5 355.2 676.8 354.8 677.4 354.3 678.5 353.5 679.7 353 681 352.8 683.6 352.4 685.8 352.7 687.9 354.2 689.1 355.1 690.1 356.1 691.2 357.2 692 358 692.7 358.8 693.3 359.8 694.2 361.6 694.3 363.7 694.3 365.7 694.4 369.3 694.3 372.9 694.3 376.6 694.3 387.8 694.3 399 694.3 410.3 694.3 410.9 694 411.6 694.7 411.6 696.4 411.6 698.1 411.6 699.8 411.6 706 411.6 712.3 411.6 718.5 411.6 722.4 411.6 726.3 411.6 730.2 411.6 730.2 411.6 730.2 398.5 730.2 397.5 730.2 395.4 730.2 393.3 730.2 391.2 727.8 391.8 725.2 392.6 722.6 393.5ZM730.3 270.6C727.9 270.6 725.4 270.6 723 270.6 722 270.6 721.1 270.6 720.1 270.6 720 270.6 719.6 271.3 719.6 271.4 716.5 276 713.4 280.6 710.4 285.3 708.9 287.5 707.4 289.7 706 292 705.6 292.5 705.3 293.1 704.9 293.6 704.6 294.1 704.8 294.9 704.8 295.4 704.8 295.6 704.8 298.8 704.8 298.8 705.4 298.8 706 298.8 706.5 298.8 709.5 298.8 712.4 298.8 715.4 298.8 717.8 298.8 720.1 298.8 722.5 298.8 723 298.8 722.7 299.6 722.7 299.9 722.7 301.4 722.7 302.9 722.7 304.4 722.7 305.8 722.7 307.1 722.7 308.5 722.7 309.3 723 309.1 723.8 309.1 725.3 309.1 726.9 309.1 728.4 309.1 728.7 309.1 730.3 309.3 730.3 308.9 730.3 306.2 730.3 303.4 730.3 300.7 730.3 300.4 730.1 298.8 730.5 298.8 731.9 298.8 733.3 298.8 734.6 298.8 734.7 298.8 735.4 298.8 735.4 298.8 735.4 298.2 735.4 297.7 735.4 297.1 735.4 296.9 735.4 293.7 735.4 293.7 734.1 293.7 732.9 293.7 731.6 293.7 731.1 293.7 730.3 294 730.3 293.4 730.3 285.7 730.3 278.1 730.3 270.6ZM722.6 285.9C722.6 287.2 722.6 288.5 722.6 289.7 722.6 290.6 722.6 291.4 722.6 292.3 722.6 292.5 722.7 293.4 722.6 293.6 722.5 293.7 721.6 293.6 721.5 293.6 720.6 293.6 719.7 293.6 718.8 293.6 717.5 293.6 716.2 293.6 715 293.6 716.3 291.6 717.7 289.6 719 287.6 719.6 286.7 720.2 285.9 720.8 285.1 722.4 283.1 722.6 280.7 722.6 278.2 722.6 280.8 722.6 283.4 722.6 285.9ZM763.6 288.5C760.9 285.8 756.2 285.9 752.6 285.9 752 285.9 751.4 285.9 750.8 285.9 750.8 285.9 750.8 284.8 750.8 284.7 750.8 283.4 750.8 282.1 750.8 280.8 750.8 280.7 763.9 280.8 765.2 280.8 765.7 280.8 766.2 281 766.2 280.5 766.2 279.1 766.2 277.7 766.2 276.4 766.2 275.3 766.2 274.2 766.2 273.2 766.2 273.2 764.9 273.2 764.9 273.2 759.2 273.2 753.5 273.2 747.8 273.2 747.2 273.2 746.5 273.2 745.9 273.2 745.7 273.2 745.7 273.6 745.7 273.8 745.4 276 745.1 278.2 744.9 280.4 744.3 284.8 743.8 289.3 743.2 293.7 747 293.7 751.5 293.1 755.1 294.8 757.9 296.2 759 299.4 758.5 302.4 758 305.8 754.4 306.5 751.5 306.5 749.6 306.5 743.2 307 743.2 303.9 742.3 306.5 741.5 309 740.6 311.6 742.3 311.6 744 312.6 745.6 313.2 748 314.1 750.5 314.3 753 314.1 756.9 313.8 761 312.5 763.6 309.4 766.3 306.1 766.2 301.9 766.2 297.8 766.2 295.6 766.2 293.3 765.7 291.1 765.5 290.1 765 288.6 763.7 288.5 763.7 288.5 763.6 288.5 763.6 288.5 761 285.9 766.2 288.5 763.6 288.5Z", + "width": 1000 + }, + "search": [ + "rhodecode" + ] + }, + { + "uid": "e5ad8728e6d6290aff4b6ffcfcaa9167", + "css": "up", + "code": 59442, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M686.5 595.8L513.6 379.1C506.3 369.9 492.4 369.9 485.1 379.1L312.2 595.8C302.7 607.8 311.2 625.4 326.5 625.4H672.2C687.5 625.4 696 607.8 686.5 595.8Z", + "width": 1000 + }, + "search": [ + "up" + ] + }, + { + "uid": "6e459e39444c93a2c017f258186765d6", + "css": "unlock", + "code": 59399, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M780.8 434.6H396.2V342.3C396.2 284.6 438.5 238.5 492.3 226.9 492.3 226.9 492.3 226.9 496.2 226.9 503.8 226.9 507.7 226.9 515.4 226.9 515.4 226.9 519.2 226.9 519.2 226.9 519.2 226.9 519.2 226.9 523.1 226.9 530.8 226.9 538.5 226.9 546.2 230.8 546.2 230.8 546.2 230.8 546.2 230.8 553.8 230.8 557.7 234.6 565.4 238.5 565.4 238.5 569.2 238.5 569.2 242.3 573.1 246.2 580.8 246.2 584.6 250 584.6 250 584.6 250 584.6 250 588.5 253.8 596.2 257.7 600 261.5 600 261.5 603.8 265.4 603.8 265.4 607.7 269.2 611.5 273.1 615.4 276.9 615.4 276.9 615.4 276.9 619.2 280.8 623.1 284.6 626.9 292.3 630.8 300 630.8 300 630.8 303.8 630.8 303.8 634.6 307.7 634.6 315.4 634.6 319.2 634.6 319.2 634.6 323.1 634.6 323.1 634.6 323.1 634.6 323.1 634.6 326.9 638.5 338.5 646.2 346.2 657.7 346.2H715.4C730.8 346.2 742.3 334.6 738.5 319.2 738.5 319.2 738.5 319.2 738.5 319.2 738.5 319.2 738.5 315.4 738.5 315.4 738.5 307.7 734.6 303.8 734.6 296.2 734.6 292.3 734.6 292.3 730.8 288.5 730.8 273.1 730.8 269.2 726.9 261.5 726.9 261.5 726.9 257.7 723.1 257.7 719.2 250 715.4 242.3 711.5 234.6 711.5 234.6 707.7 230.8 707.7 230.8 703.8 223.1 700 219.2 696.2 215.4 696.2 211.5 692.3 211.5 692.3 207.7 688.5 203.8 684.6 196.2 680.8 192.3 680.8 192.3 676.9 188.5 676.9 188.5 669.2 180.8 665.4 176.9 657.7 169.2 657.7 169.2 653.8 169.2 653.8 165.4 650 161.5 642.3 157.7 634.6 153.8 630.8 153.8 630.8 150 626.9 150 623.1 146.2 615.4 142.3 611.5 142.3 607.7 142.3 607.7 138.5 603.8 138.5 596.2 134.6 588.5 130.8 580.8 130.8 580.8 130.8 580.8 130.8 580.8 130.8 573.1 126.9 565.4 126.9 553.8 123.1 550 123.1 550 123.1 546.2 123.1 538.5 123.1 534.6 123.1 526.9 119.2 523.1 119.2 519.2 119.2 519.2 119.2 511.5 119.2 503.8 119.2 496.2 119.2 496.2 119.2 492.3 119.2 492.3 119.2 484.6 119.2 476.9 123.1 465.4 123.1 461.5 123.1 453.8 126.9 450 126.9 450 126.9 446.2 126.9 446.2 126.9 353.8 153.8 288.5 242.3 288.5 342.3V434.6H246.2C230.8 434.6 223.1 446.2 223.1 457.7V857.7C223.1 873.1 234.6 880.8 246.2 880.8H780.8C796.2 880.8 803.8 869.2 803.8 857.7V457.7C807.7 446.2 796.2 434.6 780.8 434.6Z", + "width": 1000 + }, + "search": [ + "unlock" + ] + }, + { + "uid": "b077586592b9b69166b981325446c836", + "css": "delete", + "code": 59392, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M515.4 92.3C303.8 92.3 130.8 265.4 130.8 476.9 130.8 688.5 303.8 861.5 515.4 861.5S900 688.5 900 476.9C900 265.4 726.9 92.3 515.4 92.3ZM742.3 507.7C742.3 523.1 730.8 534.6 711.5 534.6H315.4C300 534.6 284.6 523.1 284.6 507.7V446.2C284.6 430.8 296.2 419.2 315.4 419.2H711.5C726.9 419.2 742.3 430.8 742.3 446.2V507.7Z", + "width": 1000 + }, + "search": [ + "delete" + ] + }, + { + "uid": "dca63ad885c0d6f1780a8d1d55bc2380", + "css": "ok", + "code": 59393, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M515.4 115.4C303.8 115.4 130.8 288.5 130.8 500 130.8 711.5 303.8 884.6 515.4 884.6S900 711.5 900 500C900 288.5 726.9 115.4 515.4 115.4ZM753.8 411.5L450 715.4C438.5 726.9 423.1 726.9 411.5 715.4L273.1 576.9C261.5 565.4 261.5 550 273.1 538.5L315.4 496.2C326.9 484.6 342.3 484.6 353.8 496.2L411.5 553.8C423.1 565.4 438.5 565.4 450 553.8L669.2 334.6C680.8 323.1 696.2 323.1 707.7 334.6L750 376.9C765.4 384.6 765.4 400 753.8 411.5Z", + "width": 1000 + }, + "search": [ + "ok" + ] + }, + { + "uid": "c158b3a004c055c6ad1471cd98932268", + "css": "down", + "code": 59403, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M703.8 396.2L530.8 615.4C523.1 623.1 507.7 623.1 503.8 615.4L330.8 396.2C323.1 384.6 330.8 365.4 346.2 365.4H692.3C703.8 365.4 711.5 384.6 703.8 396.2Z", + "width": 1000 + }, + "search": [ + "arrow_down" + ] + }, + { + "uid": "02f59f392ad28056845cfc04cb121f13", + "css": "comment", + "code": 59394, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M130.8 784.6V280.8C130.8 207.7 188.5 150 261.5 150H769.2C842.3 150 900 207.7 900 280.8V569.2C900 642.3 842.3 700 769.2 700H273.1C269.2 700 261.5 703.8 257.7 707.7L165.4 800C153.8 815.4 130.8 803.8 130.8 784.6ZM261.5 211.5C223.1 211.5 188.5 242.3 188.5 284.6V696.2L234.6 650C238.5 646.2 242.3 642.3 250 642.3H769.2C807.7 642.3 842.3 611.5 842.3 569.2V280.8C842.3 242.3 811.5 207.7 769.2 207.7H261.5Z", + "width": 1000 + }, + "search": [ + "comment" + ] + }, + { + "uid": "9a44b838872ca62b8aba7bbbbf67cc59", + "css": "feed", + "code": 59400, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M842.3 111.5H188.5C153.8 111.5 130.8 138.5 130.8 169.2V826.9C130.8 857.7 157.7 884.6 188.5 884.6H846.2C876.9 884.6 903.8 857.7 903.8 826.9V169.2C900 138.5 873.1 111.5 842.3 111.5ZM307.7 776.9C269.2 776.9 234.6 746.2 234.6 703.8S265.4 630.8 307.7 630.8C346.2 630.8 380.8 661.5 380.8 703.8S346.2 776.9 307.7 776.9ZM553.8 788.5C519.2 788.5 496.2 761.5 496.2 730.8 496.2 619.2 407.7 530.8 296.2 530.8 265.4 530.8 230.8 503.8 230.8 473.1 230.8 438.5 253.8 411.5 284.6 411.5L296.2 411.5C473.1 411.5 615.4 553.8 615.4 730.8 611.5 761.5 584.6 788.5 553.8 788.5ZM750 788.5C715.4 788.5 692.3 761.5 692.3 730.8 692.3 511.5 511.5 330.8 292.3 330.8 261.5 330.8 226.9 303.8 226.9 269.2 226.9 234.6 250 207.7 280.8 207.7L292.3 207.7C576.9 207.7 811.5 438.5 811.5 726.9 811.5 761.5 784.6 788.5 750 788.5Z", + "width": 1000 + }, + "search": [ + "feed" + ] + }, + { + "uid": "e0118d6f20b76d77317977ae8dc849d7", + "css": "left", + "code": 59401, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M692.3 76.9L761.5 146.2C773.1 157.7 773.1 173.1 761.5 184.6L473.1 473.1C461.5 484.6 461.5 500 473.1 511.5L769.2 807.7C780.8 819.2 780.8 834.6 769.2 846.2L700 915.4C688.5 926.9 673.1 926.9 661.5 915.4L257.7 511.5C246.2 500 246.2 484.6 257.7 473.1L653.8 76.9C665.4 65.4 680.8 65.4 692.3 76.9Z", + "width": 1000 + }, + "search": [ + "left" + ] + }, + { + "uid": "3cea97f90c8f2b0a90833855434f58de", + "css": "right", + "code": 59402, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M338.5 915.4L265.4 846.2C253.8 834.6 253.8 819.2 265.4 807.7L553.8 519.2C565.4 507.7 565.4 492.3 553.8 480.8L257.7 184.6C246.2 173.1 246.2 157.7 257.7 146.2L326.9 76.9C338.5 65.4 353.8 65.4 365.4 76.9L769.2 480.8C780.8 492.3 780.8 507.7 769.2 519.2L376.9 915.4C365.4 926.9 346.2 926.9 338.5 915.4Z", + "width": 1000 + }, + "search": [ + "right" + ] + }, + { + "uid": "820a44cb2e7fc1d0e28b1d2a8cd44cb9", + "css": "git", + "code": 59434, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M928.8 6.3H71.3C35 6.3 6.3 36.3 6.3 71.3V927.5C6.3 963.8 36.3 992.5 71.3 992.5H927.5C963.8 992.5 992.5 962.5 992.5 927.5V71.3C993.8 36.3 963.7 6.3 928.8 6.3ZM200 555C203.8 566.3 208.8 575 213.8 582.5 220 590 227.5 596.3 236.3 600 245 603.8 255 606.3 265 606.3 273.8 606.3 281.3 605 288.8 603.8 296.3 602.5 302.5 600 308.8 597.5L315 546.3H287.5C283.8 546.3 280 545 277.5 542.5 276.3 541.3 275 537.5 275 535L280 496.2H385L368.7 627.5C361.2 633.8 352.5 638.7 343.7 642.5 335 646.3 326.3 650 316.2 652.5 306.2 655 297.5 657.5 286.3 658.8 276.3 660 265 661.3 252.5 661.3 232.5 661.3 215 657.5 198.7 650 182.5 642.5 168.7 632.5 157.5 620 146.2 607.5 137.5 592.5 131.2 575 125 557.5 121.2 538.8 121.2 518.8 121.2 501.3 123.7 485 127.5 468.8 131.2 452.5 137.5 438.8 145 425 152.5 411.3 161.2 400 171.2 388.8 181.2 377.5 192.5 368.8 205 361.3 217.5 353.8 231.3 347.5 246.3 343.8 261.3 340 276.3 337.5 292.5 337.5 306.3 337.5 317.5 338.8 328.7 341.3 340 343.8 350 347.5 357.5 351.3 366.2 355 373.8 360 380 365 386.3 370 392.5 376.3 397.5 381.3L377.5 412.5C373.8 417.5 368.8 420 363.8 421.3 358.8 422.5 353.7 421.3 347.5 417.5 342.5 413.8 337.5 411.3 333.7 408.8 328.7 406.3 325 403.8 320 402.5 315 401.3 310 400 305 398.8 300 397.5 293.7 397.5 287.5 397.5 273.7 397.5 261.2 400 250 406.3 238.7 412.5 228.7 420 221.2 431.3 212.5 441.2 206.2 455 202.5 468.8 197.5 483.8 196.2 500 196.2 517.5 195 531.3 197.5 543.8 200 555ZM536.3 657.5H465L503.7 342.5H575L536.3 657.5ZM878.8 398.8H798.8L766.3 657.5H696.3L727.5 398.7H647.5L655 342.5H886.3L878.8 398.8Z", + "width": 1000 + }, + "search": [ + "git" + ] + }, + { + "uid": "ea152b092f5ad7d610de2c388553e188", + "css": "hg", + "code": 59437, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M926.6 9.2H73.9C37.9 9.2 8.7 38.5 8.7 74.4V927.1C8.7 963.1 38 992.3 73.9 992.3H926.6C962.6 992.3 991.8 963 991.8 927.1V74.4C991.8 38.4 962.6 9.2 926.6 9.2ZM444 657.4H373.5L389.8 524.1H276.7L260.4 657.4H189.9L228.6 344.2H299.1L282.8 476.4H395.9L412.2 344.2H482.7L444 657.4ZM621 555.8C624.3 566.8 629.1 576 635.3 583.5 641.5 591 648.8 596.8 657.5 600.8 666.1 604.8 675.6 606.8 686.1 606.8 694.7 606.8 702.4 606 709.3 604.5 716.2 603 722.8 600.8 729.1 598.1L735.1 546.9H708.4C704.1 546.9 700.8 545.8 698.6 543.6 696.4 541.4 695.5 538.5 695.9 534.9L700.6 496.2H805.1L788.8 627.1C780.8 633 772.5 638.1 763.9 642.3 755.3 646.6 746.3 650 736.9 652.7 727.5 655.5 717.6 657.5 707.2 658.7 696.8 660 685.7 660.6 674 660.6 654.6 660.6 637 657 621 650 605 642.9 591.3 633.1 579.9 620.7 568.5 608.2 559.7 593.5 553.5 576.4 547.2 559.3 544.1 540.9 544.1 520.9 544.1 503.6 546.1 487.1 550 471.3 554 455.6 559.6 441.1 566.9 427.8 574.2 414.5 583 402.4 593.2 391.7 603.4 381 614.9 371.8 627.4 364.2 639.9 356.6 653.5 350.7 667.9 346.6 682.4 342.6 697.6 340.5 713.5 340.5 726.8 340.5 738.9 341.7 749.7 344.2 760.5 346.6 770.2 349.9 778.8 353.9 787.4 358 795.1 362.8 801.8 368.1 808.6 373.5 814.5 379 819.7 384.8L797 413.2C793.3 418.2 788.8 421.3 783.7 422.3 778.6 423.4 773.2 422.2 767.8 418.8 762.8 415.4 758.1 412.4 753.6 409.9 749.2 407.4 744.7 405.3 740.1 403.7 735.5 402 730.7 400.8 725.6 400 720.5 399.2 714.8 398.8 708.5 398.8 694.9 398.8 682.4 401.7 671.1 407.5 659.8 413.3 650 421.5 641.9 432 633.7 442.5 627.4 455.2 622.9 469.9 618.4 484.7 616.1 501 616.1 518.7 615.9 532.5 617.6 544.8 621 555.8Z", + "width": 1000 + }, + "search": [ + "hg" + ] + }, + { + "uid": "4a842c0afb4c35dacd21da71f9fed3f1", + "css": "comment-add", + "code": 59439, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M952.4 591.9V274.9C952.4 268.4 952.3 261.9 951.8 255.4 950.7 242.9 948.2 230.6 944.1 218.8 936.5 196.6 923.8 176.2 907.3 159.6 890.8 143.1 870.6 130.4 848.5 122.7 836.6 118.6 824.2 115.9 811.6 114.8 805.3 114.2 798.9 114.2 792.6 114.2H216.9C204 114.2 191.3 114.1 178.5 116 166.3 117.9 154.4 121.2 143 125.9 121.4 134.8 101.9 148.7 86.4 166.2 70.8 183.8 59.3 205 53.1 227.7 49.7 240.1 47.9 252.8 47.6 265.6 47.3 278.7 47.6 291.8 47.6 304.9V861.8C47.6 870.7 52.5 878.6 60.5 882.5 67.3 885.9 75.6 886.2 82.4 882.7 84.8 881.5 86.9 879.7 88.8 877.8 91.1 875.5 93.4 873.2 95.6 871 100.3 866.3 105 861.6 109.7 856.9L137.9 828.6C147.3 819.2 156.6 809.9 166 800.5 175.2 791.3 184.6 782.1 193.7 772.7 197.7 768.5 201.9 764.4 207.6 762.7 210.4 761.9 213.2 761.8 216 761.8H782.7C795.5 761.8 808.3 762 821 760.1 844.8 756.5 867.7 747.3 887.3 733.3 906.2 719.9 922.1 702.1 933.2 681.8 945.1 660.2 951.5 636 952.2 611.4 952.5 604.9 952.4 598.4 952.4 591.9ZM883.4 285.1V602.5C883.4 608.8 883.4 615.1 882.5 621.4 881.7 627.5 880.2 633.6 878.1 639.4 874.4 649.4 868.8 658.7 861.7 666.7 846.6 683.6 825.1 693.8 802.5 695.1 796.3 695.4 790 695.2 783.8 695.2H207.8C201.2 695.2 194.7 695.2 188.1 695.2 185 695.2 181.8 695.2 178.8 696.1 176.2 696.9 173.9 698.2 171.8 699.9 169.6 701.7 167.6 703.7 165.6 705.7 163.3 708 161 710.3 158.7 712.6 154 717.3 149.4 721.9 144.7 726.6 135.3 736 126 745.3 116.6 754.7V270C116.6 257.8 118.8 245.7 123.7 234.6 128 224.9 134 215.9 141.5 208.4 157.5 192.4 179.6 183.3 202.2 183.3H791.5C797.6 183.3 803.7 183.3 809.7 184.2 832 187.4 852.4 199.4 866 217.4 872.8 226.4 877.7 236.7 880.5 247.6 882 253.5 882.9 259.6 883.1 265.8 883.6 272.2 883.4 278.7 883.4 285.1ZM668.8 402H538.2C534.4 402 526.7 394.3 526.7 390.5V263.7C526.7 256 519 248.3 515.2 248.3H465.3C457.6 248.3 449.9 256 449.9 259.8V390.4C449.9 394.2 442.2 401.9 438.4 401.9H311.7C304 401.9 296.3 409.6 296.3 413.4V463.3C296.3 471 304 478.7 307.8 478.7H434.5C442.2 478.7 449.9 486.4 449.9 490.2V617C449.9 624.7 457.6 632.4 461.4 632.4H511.3C519 632.4 526.7 624.7 526.7 620.9V494.1C526.7 486.4 534.4 478.7 538.2 478.7H665C672.7 478.7 680.4 471 680.4 467.2V417.3C680.3 409.6 672.6 402 668.8 402Z", + "width": 1000 + }, + "search": [ + "comment-add" + ] + }, + { + "uid": "2427f6b8d4379b9a0b41cf31780807cf", + "css": "comment-toggle", + "code": 59440, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M797.6 114.2H202.4C116.6 114.2 47.6 183.3 47.6 269V861.9C47.6 881.4 69.5 891.1 84.1 881.8 86.4 880.7 88.6 879.1 90.6 877.1L199.8 768C202.1 765.7 204.7 764 207.7 762.8 209.7 762.2 211.9 761.9 214.3 761.9H797.6C883.4 761.9 952.4 692.8 952.4 607.1V269C952.4 183.2 883.3 114.2 797.6 114.2ZM118.3 752.6V269.5C118.3 222.5 156.4 184.3 203.5 184.3H680.1C593.7 267.9 175.5 695.4 171.4 699.5L118.3 752.6Z", + "width": 1000 + }, + "search": [ + "comment-toggle" + ] + }, + { + "uid": "6533bdc16ab201eb3f3b27ce989cab33", + "css": "folder-open-empty", + "code": 61717, + "src": "fontawesome" + }, + { + "uid": "d64b34fac1d9923b7d29d1550b628ecd", + "css": "lock", + "code": 59398, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M812.5 424.1H758.9V317C758.9 308 758.9 303.6 758.9 299.1 758.9 294.6 758.9 290.2 758.9 285.7 758.9 281.3 758.9 281.3 758.9 276.8 758.9 267.9 758.9 263.4 754.5 254.5 754.5 250 754.5 250 750 245.5 750 236.6 745.5 232.1 741.1 223.2 741.1 223.2 741.1 218.8 736.6 218.8 732.1 209.8 727.7 200.9 723.2 192 723.2 192 718.8 187.5 718.8 187.5 723.2 178.6 718.8 169.6 714.3 165.2 714.3 160.7 709.8 160.7 709.8 156.3 705.4 151.8 700.9 142.9 696.4 138.4 696.4 138.4 692 133.9 692 133.9 683 125 678.6 120.5 669.6 111.6 669.6 111.6 665.2 111.6 665.2 107.1 660.7 102.7 651.8 98.2 642.9 93.8 638.4 93.8 638.4 89.3 633.9 89.3 629.5 84.8 620.5 80.4 616.1 80.4 611.6 80.4 611.6 75.9 607.1 75.9 598.2 71.4 589.3 67 580.4 67 580.4 67 580.4 67 580.4 67 571.4 62.5 562.5 62.5 549.1 58 544.6 58 544.6 58 540.2 58 535.7 58 535.7 58 531.3 58 531.3 58 526.8 58 526.8 58 526.8 58 522.3 58 522.3 58 522.3 58 522.3 58 522.3 58 522.3 58 522.3 58 522.3 58 517.9 58 513.4 58 513.4 58 513.4 58 508.9 58 508.9 58 504.5 58 504.5 58 500 58 500 58 500 58 500 58 495.5 58 491.1 58 491.1 58 491.1 58 491.1 58 491.1 58 491.1 58 491.1 58 491.1 58 491.1 58 486.6 58 486.6 58 486.6 58 482.1 58 482.1 58 477.7 58 477.7 58 473.2 58 468.8 58 468.8 58 464.3 58 455.4 58 442 62.5 433 67 433 67 433 67 433 67 410.7 67 397.3 71.4 388.4 75.9 383.9 75.9 383.9 80.4 379.5 80.4 375 84.8 370.5 84.8 361.6 89.3 361.6 93.8 357.1 93.8 357.1 93.8 348.2 98.2 339.3 102.7 334.8 111.6 334.8 111.6 330.4 111.6 330.4 116.1 321.4 120.5 317 125 308 133.9 308 133.9 303.6 138.4 303.6 138.4 299.1 142.9 294.6 151.8 290.2 156.3 290.2 160.7 285.7 160.7 285.7 165.2 276.8 169.6 272.3 178.6 272.3 183 267.9 183 267.9 187.5 267.9 187.5 263.4 196.4 258.9 205.4 254.5 214.3 254.5 214.3 254.5 218.8 250 218.8 250 232.1 245.5 236.6 245.5 245.5 245.5 250 245.5 250 241.1 254.5 241.1 263.4 236.6 267.9 236.6 276.8 236.6 281.3 236.6 281.3 236.6 285.7 236.6 290.2 236.6 294.6 236.6 299.1 236.6 303.6 236.6 312.5 236.6 317V424.1H187.5C169.6 424.1 160.7 437.5 160.7 450.9V915.2C160.7 933 174.1 942 187.5 942H808C825.9 942 834.8 928.6 834.8 915.2V450.9C839.3 433 825.9 424.1 812.5 424.1ZM361.6 317C361.6 250 410.7 196.4 473.2 183 473.2 183 473.2 183 477.7 183 486.6 183 491.1 183 500 183 500 183 504.5 183 504.5 183 504.5 183 504.5 183 504.5 183 513.4 183 517.9 183 526.8 183 526.8 183 526.8 183 531.3 183 593.8 196.4 642.9 250 642.9 317V424.1H361.6V317Z", + "width": 1000 + }, + "search": [ + "lock" + ] + }, + { + "uid": "d95fde5e3bfeb3302efc47c90538a1c5", + "css": "more", + "code": 59410, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M546.2 415.4H446.2C430.8 415.4 419.2 426.9 419.2 442.3V542.3C419.2 557.7 430.8 569.2 446.2 569.2H546.2C561.5 569.2 573.1 557.7 573.1 542.3V442.3C573.1 426.9 561.5 415.4 546.2 415.4ZM546.2 107.7H446.2C430.8 107.7 419.2 119.2 419.2 134.6V234.6C419.2 250 430.8 261.5 446.2 261.5H546.2C561.5 261.5 573.1 250 573.1 234.6V134.6C573.1 119.2 561.5 107.7 546.2 107.7ZM546.2 723.1H446.2C430.8 723.1 419.2 734.6 419.2 750V850C419.2 865.4 430.8 876.9 446.2 876.9H546.2C561.5 876.9 573.1 865.4 573.1 850V750C573.1 734.6 561.5 723.1 546.2 723.1Z", + "width": 1000 + }, + "search": [ + "more" + ] + }, + { + "uid": "34e7772638ae3ca1bfb0a4eca2c39221", + "css": "merge", + "code": 59443, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M199.8 740.5C199.8 812.2 258.1 870.5 329.8 870.5S459.8 812.2 459.8 740.5C459.8 694.6 435.8 654.5 399.8 631.3 418.4 491.7 533.4 451.9 602.4 440.6V742.4C563.7 765 537.4 806.4 537.4 854.4 537.4 926.1 595.7 984.4 667.4 984.4S797.4 926.1 797.4 854.4C797.4 806.5 771.1 765 732.4 742.4V254.9C771.1 232.3 797.4 190.9 797.4 142.9 797.4 71.2 739.1 12.9 667.4 12.9S537.4 71.2 537.4 142.9C537.4 190.8 563.7 232.3 602.4 254.9V309.9C542.2 317.8 440.4 342.3 364.2 417.8 309.5 472.1 277.9 542.1 269.6 625.9 228.4 647.7 199.8 690.6 199.8 740.5ZM667.6 897.8C643.7 897.8 624.3 878.3 624.3 854.5S643.8 811.2 667.6 811.2C691.5 811.2 710.9 830.7 710.9 854.5S691.5 897.8 667.6 897.8ZM667.6 99.6C691.5 99.6 710.9 119 710.9 142.9S691.4 186.2 667.6 186.2C643.7 186.2 624.3 166.8 624.3 142.9S643.7 99.6 667.6 99.6ZM329.9 783.9C306 783.9 286.6 764.4 286.6 740.6S306.1 697.3 329.9 697.3C353.8 697.3 373.2 716.7 373.2 740.6S353.8 783.9 329.9 783.9Z", + "width": 1000 + }, + "search": [ + "merge" + ] + }, + { + "uid": "c95735c17a10af81448c7fed98a04546", + "css": "folder-open", + "code": 59405, + "src": "fontawesome" + }, + { + "uid": "865ac833a8efcfc24a6f573705ce56b1", + "css": "svn", + "code": 59438, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M933.4 9.2H80.7C44.7 9.2 15.5 38.5 15.5 74.4V927.1C15.5 963.1 44.8 992.3 80.7 992.3H933.4C969.4 992.3 998.6 963 998.6 927.1V74.4C998.7 38.4 969.4 9.2 933.4 9.2ZM167.9 447.1C171.1 451 175.4 454.4 180.8 457.3 186.2 460.2 192.2 463 199 465.4 205.7 467.8 212.7 470.5 219.8 473.3 226.9 476.2 233.9 479.5 240.7 483.2 247.5 486.9 253.6 491.6 259 497.2 264.4 502.8 268.7 509.6 271.9 517.4 275.1 525.3 276.8 534.8 276.8 545.8 276.8 561.6 274.1 576.4 268.6 590.3 263.1 604.3 255.3 616.4 245.1 626.8 234.9 637.2 222.5 645.4 208 651.5 193.4 657.6 177 660.7 158.8 660.7 149.7 660.7 140.7 659.7 131.5 657.7S113.6 652.8 105.2 649.2C96.8 645.5 89 641.2 81.8 636.2 74.6 631.2 68.5 625.6 63.5 619.5L88.5 586.7C90.5 584.3 93 582.3 95.9 580.7 98.8 579.1 101.8 578.3 104.8 578.3 108.8 578.3 112.7 579.7 116.5 582.5 120.3 585.3 124.5 588.4 129.1 591.8 133.7 595.2 139 598.2 145.1 601.1 151.2 603.9 158.7 605.3 167.6 605.3 180.7 605.3 190.7 601.7 197.8 594.7 204.9 587.6 208.4 577.1 208.4 563.2 208.4 556.8 206.8 551.4 203.5 547.3 200.3 543.1 196 539.7 190.8 536.8 185.6 533.9 179.6 531.4 172.8 529.1 166 526.9 159.2 524.5 152.1 521.9 145.1 519.3 138.2 516.2 131.4 512.8 124.6 509.3 118.6 504.7 113.4 499 108.2 493.3 103.9 486.4 100.7 478.2 97.5 469.9 95.9 459.8 95.9 447.7 95.9 433.8 98.5 420.4 103.7 407.6 108.9 394.8 116.4 383.4 126.2 373.5 136 363.6 147.8 355.7 161.7 349.8 175.6 343.9 191.3 341 208.6 341 217.5 341 226.1 341.9 234.5 343.8S250.8 348.2 258.1 351.6C265.4 354.9 272.1 358.8 278.1 363.3 284.1 367.8 289.2 372.8 293.4 378.1L272.3 407C269.7 410.3 267.2 412.8 264.8 414.4 262.4 416 259.4 416.8 256 416.8 252.7 416.8 249.4 415.8 246.1 413.6 242.8 411.4 239.1 409.1 235 406.5 230.9 403.9 226.2 401.6 220.9 399.4 215.6 397.2 209.3 396.2 202.2 396.2 195.6 396.2 189.8 397.1 184.9 399 179.9 400.9 175.8 403.4 172.5 406.8 169.2 410.1 166.7 414 165.1 418.4 163.5 422.9 162.6 427.8 162.6 433 163.1 438.4 164.7 443.2 167.9 447.1ZM480 657.4H416.3L339.2 343.7H395.6C401.6 343.7 406.4 345.1 410 348 413.6 350.8 415.8 354.5 416.7 359L449.4 531.8C451.3 538.7 453 546.3 454.6 554.8 456.2 563.2 457.5 571.9 458.7 581 461.7 572 464.9 563.2 468.4 554.8 471.8 546.4 475.4 538.8 479.2 531.8L552.3 359C553.2 357.1 554.4 355.2 556.1 353.4 557.7 351.5 559.6 349.8 561.8 348.4 564 347 566.4 345.8 569 345 571.6 344.2 574.4 343.7 577.3 343.7H634.1L480 657.4ZM902.6 657.4H866C860.5 657.4 856.1 656.5 852.8 654.7 849.4 652.9 846.2 649.9 843.2 645.8L733.6 452.2C733.3 456.2 733 460.1 732.7 463.8 732.3 467.6 732 471.1 731.7 474.4L710.2 657.4H648.2L686.9 343.7H723.9C726.9 343.7 729.5 343.8 731.6 344 733.7 344.2 735.5 344.7 737.1 345.5 738.7 346.3 740.1 347.4 741.4 348.8S744.1 352.1 745.5 354.4L855.5 548.1C855.8 543.1 856.2 538.3 856.7 533.7 857.2 529.2 857.8 524.8 858.3 520.8L879.4 343.6H941.4L902.6 657.4Z", + "width": 1000 + }, + "search": [ + "svn" + ] + }, + { + "uid": "bbfb51903f40597f0b70fd75bc7b5cac", + "css": "trash", + "code": 61944, + "src": "fontawesome" + }, + { + "uid": "f48ae54adfb27d8ada53d0fd9e34ee10", + "css": "trash-empty", + "code": 59406, + "src": "fontawesome" + }, + { + "uid": "f8aa663c489bcbd6e68ec8147dca841e", + "css": "folder", + "code": 59404, + "src": "fontawesome" + }, + { + "uid": "c8585e1e5b0467f28b70bce765d5840c", + "css": "docs", + "code": 61637, + "src": "fontawesome" + }, + { + "uid": "1b5a5d7b7e3c71437f5a26befdd045ed", + "css": "doc", + "code": 59414, + "src": "fontawesome" + }, + { + "uid": "5408be43f7c42bccee419c6be53fdef5", + "css": "doc-text", + "code": 61686, + "src": "fontawesome" + }, + { + "uid": "b091a8bd0fdade174951f17d936f51e4", + "css": "folder-empty", + "code": 61716, + "src": "fontawesome" + }, + { + "uid": "c08a1cde48d96cba21d8c05fa7d7feb1", + "css": "doc-text-inv", + "code": 61788, + "src": "fontawesome" + }, + { + "uid": "178053298e3e5b03551d754d4b9acd8b", + "css": "doc-inv", + "code": 61787, + "src": "fontawesome" + }, + { + "uid": "e99461abfef3923546da8d745372c995", + "css": "cog", + "code": 59415, + "src": "fontawesome" + }, + { + "uid": "98687378abd1faf8f6af97c254eb6cd6", + "css": "cog-alt", + "code": 59416, + "src": "fontawesome" + }, + { + "uid": "21b42d3c3e6be44c3cc3d73042faa216", + "css": "sliders", + "code": 61918, + "src": "fontawesome" + }, + { + "uid": "559647a6f430b3aeadbecd67194451dd", + "css": "menu", + "code": 61641, + "src": "fontawesome" + }, + { + "uid": "c5fd349cbd3d23e4ade333789c29c729", + "css": "eye", + "code": 59417, + "src": "fontawesome" + }, + { + "uid": "7fd683b2c518ceb9e5fa6757f2276faa", + "css": "eye-off", + "code": 59418, + "src": "fontawesome" + }, + { + "uid": "2e2dba0307a502a8507c1729084c7ab5", + "css": "cancel-circled2", + "code": 59419, + "src": "fontawesome" + }, + { + "uid": "0f4cae16f34ae243a6144c18a003f2d8", + "css": "cancel-circled", + "code": 59420, + "src": "fontawesome" + }, + { + "uid": "26613a2e6bc41593c54bead46f8c8ee3", + "css": "file-code", + "code": 61897, + "src": "fontawesome" + }, + { + "uid": "5211af474d3a9848f67f945e2ccaf143", + "css": "remove", + "code": 59408, + "src": "fontawesome" + }, + { + "uid": "44e04715aecbca7f266a17d5a7863c68", + "css": "plus", + "code": 59421, + "src": "fontawesome" + }, + { + "uid": "4ba33d2607902cf690dd45df09774cb0", + "css": "plus-circled", + "code": 59422, + "src": "fontawesome" + }, + { + "uid": "1a5cfa186647e8c929c2b17b9fc4dac1", + "css": "plus-squared", + "code": 61694, + "src": "fontawesome" + }, + { + "uid": "2d3be3e856fc1e4ac067590d2ded1b07", + "css": "plus-squared-alt", + "code": 61846, + "src": "fontawesome" + }, + { + "uid": "eeadb020bb75d089b25d8424aabe19e0", + "css": "minus-circled", + "code": 59423, + "src": "fontawesome" + }, + { + "uid": "f755a58fb985eeb70bd47d9b31892a34", + "css": "minus-squared", + "code": 61766, + "src": "fontawesome" + }, + { + "uid": "18ef25350258541e8e54148ed79845c0", + "css": "minus-squared-alt", + "code": 61767, + "src": "fontawesome" + }, + { + "uid": "861ab06e455e2de3232ebef67d60d708", + "css": "minus", + "code": 59424, + "src": "fontawesome" + }, + { + "uid": "e82cedfa1d5f15b00c5a81c9bd731ea2", + "css": "info-circled", + "code": 59425, + "src": "fontawesome" + }, + { + "uid": "9dd9e835aebe1060ba7190ad2b2ed951", + "css": "search", + "code": 59411, + "src": "fontawesome" + }, + { + "uid": "b429436ec5a518c78479d44ef18dbd60", + "css": "paste", + "code": 61674, + "src": "fontawesome" + }, + { + "uid": "8772331a9fec983cdb5d72902a6f9e0e", + "css": "scissors", + "code": 59412, + "src": "fontawesome" + }, + { + "uid": "9a76bc135eac17d2c8b8ad4a5774fc87", + "css": "download", + "code": 59413, + "src": "fontawesome" + }, + { + "uid": "eeec3208c90b7b48e804919d0d2d4a41", + "css": "upload", + "code": 59426, + "src": "fontawesome" + }, + { + "uid": "5d2d07f112b8de19f2c0dbfec3e42c05", + "css": "spin", + "code": 59448, + "src": "fontelico" + }, + { + "uid": "9bd60140934a1eb9236fd7a8ab1ff6ba", + "css": "spin-alt", + "code": 59444, + "src": "fontelico" + }, + { + "uid": "513ac180ff85bd275f2b736720cbbf5e", + "css": "home", + "code": 59427, + "src": "entypo" + }, + { + "uid": "d4816c0845aa43767213d45574b3b145", + "css": "history", + "code": 61914, + "src": "fontawesome" + }, + { + "uid": "c43db6645e7515889fc2193294f50767", + "css": "plus", + "code": 59411, + "src": "custom_icons", + "selected": false, + "svg": { + "path": "M873.1 446.2H619.2C603.8 446.2 592.3 434.6 592.3 419.2V165.4C592.3 150 580.8 138.5 565.4 138.5H465.4C450 138.5 438.5 150 438.5 165.4V419.2C438.5 434.6 426.9 446.2 411.5 446.2H157.7C142.3 446.2 130.8 457.7 130.8 473.1V573.1C130.8 588.5 142.3 600 157.7 600H411.5C426.9 600 438.5 611.5 438.5 626.9V880.8C438.5 896.2 450 907.7 465.4 907.7H565.4C580.8 907.7 592.3 896.2 592.3 880.8V626.9C592.3 611.5 603.8 600 619.2 600H873.1C888.5 600 900 588.5 900 573.1V473.1C900 457.7 888.5 446.2 873.1 446.2Z", + "width": 1000 + }, + "search": [ + "plus" + ] + }, + { + "uid": "7d7f338d90203f20c0d8d5c26091cc69", + "css": "minus", + "code": 59412, + "src": "custom_icons", + "selected": false, + "svg": { + "path": "M980 560H20C10 560 0 550 0 540V380C0 370 10 360 20 360H985C995 360 1005 370 1005 380V545C1000 550 990 560 980 560Z", + "width": 1000 + }, + "search": [ + "minus" + ] + }, + { + "uid": "4ccc61480001600f2e7e3c7dd0546c6e", + "css": "remove", + "code": 59413, + "src": "custom_icons", + "selected": false, + "svg": { + "path": "M975 140L860 25C845 10 825 10 810 25L525 310C510 325 490 325 475 310L190 25C175 10 155 10 140 25L25 140C10 155 10 175 25 190L310 475C325 490 325 510 310 525L25 810C10 825 10 845 25 860L140 975C155 990 175 990 190 975L475 690C490 675 510 675 525 690L810 975C825 990 845 990 860 975L975 860C990 845 990 825 975 810L690 525C675 510 675 490 690 475L975 190C990 180 990 155 975 140Z", + "width": 1000 + }, + "search": [ + "remove" + ] + }, + { + "uid": "b1afcccc053ecb95fbcacf06e5c0d554", + "css": "history", + "code": 59418, + "src": "custom_icons", + "selected": false, + "svg": { + "path": "", + "width": 1143 + }, + "search": [ + "history" + ] + } + ] +} \ No newline at end of file diff --git a/rhodecode/public/fonts/RCIcons/rcicons.eot b/rhodecode/public/fonts/RCIcons/rcicons.eot index ce6f326628a5965923e7d2be0c2efb33a5de778b..041a625cef455f924ff6020314e110f7355ddc65 GIT binary patch literal 18076 zc%0pQdw3kxedu}2duC^6c4uZETCG<5)XRG8YIpsRWgFX)5wbJLc#G;ks0>kXF#_X}-r+N6Y#hU7N1%}pUsn$TvU_a-9EJq(6#XX%e;y!v_}Id&|F(DO4QLMlou8RI zF!7(Rd-5@;-vRNvk4@Zq9A8VIJdQ#iXCJ@o|LKL;vJ&kI$W0_{O>)>_%uK z(2YFBaHr!-M-bxrmd-7mi z2~o+PDvvJf$XAf&PaQ%Ed=Xk|%2$A_!-#Ae*}4nqGZPE5D2}+M{N^y8nLacD?fWsv z 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 Fe*wN;eU|_L diff --git a/rhodecode/public/fonts/RCIcons/rcicons.svg b/rhodecode/public/fonts/RCIcons/rcicons.svg --- a/rhodecode/public/fonts/RCIcons/rcicons.svg +++ b/rhodecode/public/fonts/RCIcons/rcicons.svg @@ -1,78 +1,134 @@ -Copyright (C) 2017 by original authors @ fontello.com +Copyright (C) 2019 by original authors @ fontello.com - + - + + + - + + + - + + + - + - + + + - + + + - + + + - + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - + - + + + - + + + - + + + - + - + + + - + + + - + + + - + - + + + - + + + - + + + - + + + - + + + - + + + - + - + + + + + + + \ No newline at end of file diff --git a/rhodecode/public/fonts/RCIcons/rcicons.ttf b/rhodecode/public/fonts/RCIcons/rcicons.ttf index ce04da872ddf44d907a0b38a0d8c7316ecada14e..567538e5a7fbcac3d5306bd158d27bf86f0a0721 GIT binary patch literal 17912 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 A3IG5A diff --git a/rhodecode/public/fonts/RCIcons/rcicons.woff b/rhodecode/public/fonts/RCIcons/rcicons.woff index beb0f4362bf5241b14955e441c04e312149215a9..ce1edfade12afa523e7c7211219ef9697849ab77 GIT binary patch literal 10764 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 diff --git a/rhodecode/public/fonts/RCIcons/rcicons.woff2 b/rhodecode/public/fonts/RCIcons/rcicons.woff2 index f33e01713cf9a983e07481a6021b9cbd7144f33b..57e99161f3477a5f5ec4bc8f8ef04091d5e743ec GIT binary patch literal 9124 zc$@*GBU{{ePew8T0RR9103)OT3jhEB07du!03%WW0RR9100000000000000000000 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 Pathfinder in Illustrator +to build a compound image. It may happen that your image is rasterized, in which +case it will need to be converted to vector; check the results carefully. + + .. note:: + When adding to the existing icon collection, please maintain our + existing icon style. + + +Creating The Font +----------------- + +*Fontello* + +We use fontello.com to generate the font files. On the main page, there is a +section for clicking and dragging icons to add to a font. If you would like to +use the existing font icons, here you will need to drag the .json file from the +current fontello folder. Once it has preloaded all of the existing fonts, drag +any new .svg icons into this same section to add them. + +Any icons which appear blank or incorrect will need to be rebuilt in Illustrator. +This likely means that the paths have not been generated correctly; check the +settings in the Pathfinder tool. + +After all of the icons are loaded into fontello, resist the temptation to click +the big red button; there's another task to do. Each icon has a pencil button; +click *every* icon - including the pre-existing ones - and check the settings. +Each current icon should have the same hex code as that which is listed in +rcicons.less. The "default css name" should be its simplified name; this is what +will be prepended with "icon-" for the CSS classes. Also remove any unnecessary +information from the keywords. + +Once you have checked the icons, click the button in fontello which downloads a +zip file of the new font. + + +Preparing The LESS Files +------------------------ + + .. note:: + It's a good idea to have `grunt watch` running in the background for this. + +First, obviously the font files located in the unzipped folder under "font" +should replace the existing files in rhodecode/public/fonts/RCIcons/. While +doing this, check the permissions of the files that they have not changed; they +should be set to `chmod 644` but fontello's files may be different. + +Next, you'll need to open the rcicons.css file which comes in the fontello .zip +and match the @font-face declaration to the one at the top of +rhodecode/public/css/rcicons.less, making sure to adjust the paths to +/fonts/RCIcons/. + +In the same file, you will see the CSS for each icon. Take a quick look to make +sure that the existing icons haven't changed; if they have, you'll need to +adjust the content. Add any new icons to rcicons.less (note that similar ones +have been grouped together). + +If you haven't yet, you'll need to run grunt to compile the LESS files; see the +developer documentation for instructions. + diff --git a/rhodecode/public/images/rhodecode-logo-white-266x74.png b/rhodecode/public/images/rhodecode-logo-white-266x74.png deleted file mode 100644 index 8428dcb71885ffd052f8ba7c634434560b81ee74..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@r7KpvP7VN& z=+Y|8UMVF0X4-0i%3;opD}~oZ$IK7_2o?kYB4Yu7vnx~NIskx_1OPT20RV6Y0Kfvz zYB5#3a@>IHSo;G2RE)ow1n@eG^$N_|)7%PSWoQ6)@$r^$a`ka`lL+*N1AdcYAoxo3 zc0)Mv26{h+`GW%?z<))6ujJom5Rms@AqXf0Xk}=^tM23H#w#ZwDz{hbKm`RM;M!TkSe>#9M}Zx2XHLK5^J z?BDRetzct6Pq(Ygzwwo%6hZ%E`*$s%|0?G1PC@^)szj*>`p>c{Q5tj!Spxv{wYnOr z<{sC6yrxP?okI4Fv>$S>VkAlVbm&onri`!M)C$I;RSk66nX1*Mz0&2z%q^gXkL{*p z+3V^BTd;b6Nj21b@RHK=Ad_NGqbt`+DbUbB7inm+s%9LYBi->cOT_tB<&Kc%fK^&l zaTx?UyzT#U)_u3`c-B3)?;`83x4pf+&nqh{LE0t~#d_KyA(G9N!|4?aU27sf;>^Gt z&bw{Ugbck1;L8kqGqdpxj@NJA#4MmGCcj1V3iGp+Qm2=Zg@G859~#JDVdtGx+RIgB z>doHX-kARWr|`;-@_s_Ep2Y)8OXBU@ChGe7RP&^k78a{sUS85)C-IEsxitq2^fVoB zsMrt)M0r0fGI?h3h<0w`NfI+bt(RadN+~+!WJ>;?5GX+#M&3yY|(jSF91C!ZG9a&|uCNcEB}RI?bhwhED}zRTkz%;mYo_mEk@^>VJn z_}TZpv1?-LofceKYohj}r{3|Kw@^2=Kcifu#CRS$WCwq>k*Q$Xd0F^4`-glV9f}M; z=xwOL)*rZXx^fNWXOWT)_DSqp#=mAXAzuDmD?o1??39abe9<-M==Wf`=bQeH>#=j3 z@@U%An~n*A;Dlb91c=*UN|=_d#v#UE>$yHYM97?EOK@U#dHsax=wfrZneVhQ#TeDH zk>A00yw5c?EIvdX`O3?PkycYZ@d@+V?b?p^!i5Dn`50tsppccBYfayGTZiw} z<>cfbWgcPI8KoU4y!>Fsh7_JYW(qev8^%674u>cm;Cq4$<_$G{ulfl7oNnO^fvCsn?S2 zO$07X$H&KC7<5y>^J1KnYr1&1$t~SDR7m-1j%rTsJfqr*@Da;AYNvQjxDF=8P!{jF zYOd%SjA=(H5eS4KS6=k{40vb%dSGi3rMI4V%F}vjWju$M7(!@^XqK&FC zy~Rdzx7t5O0Hm!n>x>lb(D5FKXW*APK5D~6@@f1Ha>j0alaO9k89H|@&FEC~i z`1G|%W&dgqgnmD_v^0bQ*N#LdDP`^Viv8Uz`!%Yg72js-fL6T@|DgH8*zZ2ToF7_TDSpkSz=v;j0Pe zK8<%_kcAB?lwrS>o~ zpx=+}4H?_+9Y_{}qIn)TOSVjgGAddA(L7sZ)_dmT?F~`K)i>5bPKJl4sZbt3zBCcT zT<1SdU+%9ea{lR%igCr-1ROLLN*!VE}@!{s& z19!=o?PzzLZR-PLp-zwqOez+JX2Ylyo|=2l+nwd(F7TK|I(8iE9{6kSU3TZV7kWfj zr0Qlk8>xe=;`B4(xG1?b41cwQo0J7MB<}YeiopKjsxl^G z1PuXKFby@eqLUk))C9>8M|O95mSFoTqLDmzzDXHQ*8r{He(5Mdu}qyD>}{Y9G8r2O z!{co{^oQWlwY9W>%XO5lIYGB5E$Z!DO*K|r41bv)QVn%)5g{9;Sc#=qp`GUrPIx2Z zZgk=YAm)~!nO@tbn!J`}0S23x*p(K`;$dO!b9Qr9Yqq`z&W&yOMRR>8Vo`%|=J#e! z6Nd(SQ(RT#uUK|JE_Qt@O7V*r{3oGxGs{%?0B&ObK%|PTFq9sXIQ~wBJc?^reX~E;g{8g`yM}=M>_E{e@ z-+8&iN$K5E?it&`;WCbg(x>>!u|qxa*V|AW~27(I+#w=^-p^0m&9M& z4hx0K7QsN8uz?j$REBlBa5#-W`9ylZ?14yhsV?3cII*?*zTH5r_m&2zOQuk70&Qj1?A2nEJj3Z z(NCZcnny|2dka(q&{4U$cfB7bo~`Kz#g*~T{E)0nl#4W57@^hfhc+cBXB(H`4k=kk z4jVY)*I0dDyaO%0O=x-gjc0t9c}s>Jy8)l&lIIocf_5+TXPJB+GpJCS^y#Z3O1DOI z1gmyUWpeEr)XzDi>Z#ql^y}^ZD)p%i=BswZIrmP>(^SxvipkWOmXsXmkyRb0`u^fb zhcA~2dvr+=bTiIqpdk*t;q+%8$0!v=hYoKnpO|->V=?S9HCWxzY@KPpsa5IZZR5d5 za+_(iCSNEn#c6YD3oK@B#CCfJ2L}VLPBN~ENxLRfj4+b_#hUuN>;Y#jZPW7iWOZLF zrWAxbBr=pMKBrs9M!uqxyi-H9onJ$N0(B=FFa%@;C2WKa;<5$D1Ii03$tl=Y!rN42 znsaL(`Gb0)K+EVix^oGb&yjWgbp!VY4qiAP1SZoWJ9&w(SUI%b+8RhRx$i5{j78hV zS~oqRu1$^daT;ww?G(=U`=~EiBN)vD>W8~_kW{Cvr*$h!#_1%5LcMY$c(|!vRg*nE z?+GKjMVV=q5V=(Lm~8fjq3RV zJv58W+@lUFx;zses!3z}#dCB1G6U1t^%pdr z&Z9!C6?t_H+jtUz$p?0OE$$I9b-zAui@o!E)r<;HjJ$(U--;S}8CFn17d~{9Y?Q`c z?l@{xap{dsB5#EWN;+9~cr!?rV~!W1M8aY>&ba&NMb5Yo;S zDJyW#kc>#XiZvIM--YPNjZ=DrC4Dvby9-ml5?KUz{8k|%o`siGTsqk@D}F|Gw?Pnm zCc_s^_R8-FJvuP}NNd|#hFcDc zJb|nUDxLN`$H(B6lz>6ia+_vaO5E#xk>$ym?UZ@kE2}bfmrlK`QOfC=_G)&^+Up1!WnT0WQN}v0hB|726^ruN`X7B%D^yWgY-B|odwK<7FFyG9hk5tuY_h$r z^+4;>+U-c}@wBj(9bdb-V=1$G2iO(=j3&271*8e@$jFyJU(n9{;axw;j`JAgKpT-0 z6b)$iS}$|k=Xdc-BR3kKbMjaZoqrSGO<-U>pJDB_TQL!8!-4VT5$?;VuB84XY>SZ! zN4bR6(}RNLWf{xQTQ)(u-?$g&b}u*Y=^n50N_pJ0@e~Wps(KIeV>wCe*HChL*4oo7 zme}XWy4jsE<2!DfX{@8eD!|)P+4V4h^+jz!P(@H`pI$iIo{wK?PQfeu2fKFs>b*Z^ zvdULE%bR4RKTfQ)bEZr;QAsxz)&#mYE-$(lu0*)v8u!Jq3KQ>)8@c$)6rA(7nafX* ztc#w3BG};lk)=3cp9`kze+6<^RXuHWl*e7}pzV*_7jzp#l8Q`p9VJY~XkIl2rp2ex)5mw_J-S5Ub}2j0ld`yOTnqp`-ND%NSA$_&HsmyKr&?dQq( zg?ux65=rtU__8#mET?TUOv?@H4Tj)Xr}yYtg2F%k*@=1GQDHLcA__xU9YcL{QI1j7 zZFAX#J4|1(8z^Vq>?;o1SJ~jF8@aDKp&l@O*GrlU-0Jg_)&UB-QO#4v&0TV|huE(ebyh4h@5W z-KJK^|Ey395 zZ&vC_?wYNoyvpo-PEt4|iP@qpAmqCHDgOK#D*{u;#UD|W56DfvV;^>$1bk(ve^RKd z!Dh$4h^3CWLv_z->W1aKmKOEN^~y{C&0I-aron7~fk#BY=;=iN2E*HU$o+Zp(nRMb z=F6vNMe)f{cg@WiPn#ZUWvDFi9q$_P)~9HTyok#m(Y`zqBl#CZRki(r6%K1khfBNn a=gN&=CcbP58N2-c2-4Lw(x_B(jQ&5;;}&87 diff --git a/rhodecode/public/js/rhodecode/base/keyboard-bindings.js b/rhodecode/public/js/rhodecode/base/keyboard-bindings.js --- a/rhodecode/public/js/rhodecode/base/keyboard-bindings.js +++ b/rhodecode/public/js/rhodecode/base/keyboard-bindings.js @@ -98,7 +98,7 @@ function setRCMouseBindings(repoName, re }); Mousetrap.bind(['g c'], function(e) { window.location = pyroutes.url( - 'repo_changelog', {'repo_name': repoName}); + 'repo_commits', {'repo_name': repoName}); }); Mousetrap.bind(['g F'], function(e) { window.location = pyroutes.url( diff --git a/rhodecode/public/js/rhodecode/routes.js b/rhodecode/public/js/rhodecode/routes.js --- a/rhodecode/public/js/rhodecode/routes.js +++ b/rhodecode/public/js/rhodecode/routes.js @@ -131,6 +131,7 @@ function registerRCRoutes() { pyroutes.register('repo_new', '/_admin/repos/new', []); pyroutes.register('repo_create', '/_admin/repos/create', []); pyroutes.register('repo_groups', '/_admin/repo_groups', []); + pyroutes.register('repo_groups_data', '/_admin/repo_groups_data', []); pyroutes.register('repo_group_new', '/_admin/repo_group/new', []); pyroutes.register('repo_group_create', '/_admin/repo_group/create', []); pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []); @@ -148,6 +149,7 @@ function registerRCRoutes() { pyroutes.register('repo_group_list_data', '/_repo_groups', []); pyroutes.register('goto_switcher_data', '/_goto_data', []); pyroutes.register('markup_preview', '/_markup_preview', []); + pyroutes.register('file_preview', '/_file_preview', []); pyroutes.register('store_user_session_value', '/_store_session_attr', []); pyroutes.register('journal', '/_admin/journal', []); pyroutes.register('journal_rss', '/_admin/journal/rss', []); @@ -195,14 +197,17 @@ function registerRCRoutes() { pyroutes.register('repo_files_edit_file', '/%(repo_name)s/edit_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); pyroutes.register('repo_files_update_file', '/%(repo_name)s/update_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); pyroutes.register('repo_files_add_file', '/%(repo_name)s/add_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); + pyroutes.register('repo_files_upload_file', '/%(repo_name)s/upload_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); pyroutes.register('repo_files_create_file', '/%(repo_name)s/create_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']); pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']); pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']); + pyroutes.register('repo_commits', '/%(repo_name)s/commits', ['repo_name']); + pyroutes.register('repo_commits_file', '/%(repo_name)s/commits/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); + pyroutes.register('repo_commits_elements', '/%(repo_name)s/commits_elements', ['repo_name']); + pyroutes.register('repo_commits_elements_file', '/%(repo_name)s/commits_elements/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); pyroutes.register('repo_changelog', '/%(repo_name)s/changelog', ['repo_name']); pyroutes.register('repo_changelog_file', '/%(repo_name)s/changelog/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); - pyroutes.register('repo_changelog_elements', '/%(repo_name)s/changelog_elements', ['repo_name']); - pyroutes.register('repo_changelog_elements_file', '/%(repo_name)s/changelog_elements/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); pyroutes.register('repo_compare_select', '/%(repo_name)s/compare', ['repo_name']); pyroutes.register('repo_compare', '/%(repo_name)s/compare/%(source_ref_type)s@%(source_ref)s...%(target_ref_type)s@%(target_ref)s', ['repo_name', 'source_ref_type', 'source_ref', 'target_ref_type', 'target_ref']); pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']); @@ -356,6 +361,12 @@ function registerRCRoutes() { pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []); pyroutes.register('my_account_external_identity', '/_admin/my_account/external-identity', []); pyroutes.register('my_account_external_identity_delete', '/_admin/my_account/external-identity/delete', []); + pyroutes.register('repo_artifacts_list', '/%(repo_name)s/artifacts', ['repo_name']); + pyroutes.register('repo_artifacts_data', '/%(repo_name)s/artifacts_data', ['repo_name']); + pyroutes.register('repo_artifacts_new', '/%(repo_name)s/artifacts/new', ['repo_name']); + pyroutes.register('repo_artifacts_get', '/%(repo_name)s/artifacts/download/%(uid)s', ['repo_name', 'uid']); + pyroutes.register('repo_artifacts_store', '/%(repo_name)s/artifacts/store', ['repo_name']); + pyroutes.register('repo_artifacts_delete', '/%(repo_name)s/artifacts/delete/%(uid)s', ['repo_name', 'uid']); pyroutes.register('repo_automation', '/%(repo_name)s/settings/automation', ['repo_name']); pyroutes.register('repo_automation_update', '/%(repo_name)s/settings/automation/%(entry_id)s/update', ['repo_name', 'entry_id']); pyroutes.register('edit_repo_remote_push', '/%(repo_name)s/settings/remote/push', ['repo_name']); diff --git a/rhodecode/public/js/src/plugins/jquery.autocomplete.js b/rhodecode/public/js/src/plugins/jquery.autocomplete.js --- a/rhodecode/public/js/src/plugins/jquery.autocomplete.js +++ b/rhodecode/public/js/src/plugins/jquery.autocomplete.js @@ -528,7 +528,19 @@ if ($.isFunction(serviceUrl)) { serviceUrl = serviceUrl.call(that.element, query); } - cacheKey = serviceUrl + '?' + $.param(params || {}); + + var callParams = {}; + //make an evaluated copy of params + $.each(params, function(index, value) { + if($.isFunction(value)){ + callParams[index] = value(); + } + else { + callParams[index] = value; + } + }); + + cacheKey = serviceUrl + '?' + $.param(callParams); response = that.cachedResponse[cacheKey]; } @@ -536,7 +548,7 @@ that.suggestions = response.suggestions; that.suggest(); } else if (!that.isBadQuery(query)) { - if (options.onSearchStart.call(that.element, options.params) === false) { + if (options.onSearchStart.call(that.element, params) === false) { return; } if (that.currentRequest) { diff --git a/rhodecode/public/js/src/rhodecode.js b/rhodecode/public/js/src/rhodecode.js --- a/rhodecode/public/js/src/rhodecode.js +++ b/rhodecode/public/js/src/rhodecode.js @@ -102,7 +102,7 @@ var showRepoStats = function(target, dat var total = 0; var no_data = true; var tbl = document.createElement('table'); - tbl.setAttribute('class', 'trending_language_tbl'); + tbl.setAttribute('class', 'trending_language_tbl rctable'); $.each(data, function(key, val){ total += val.count; @@ -120,54 +120,47 @@ var showRepoStats = function(target, dat cnt += 1; no_data = false; - var hide = cnt > 2; var tr = document.createElement('tr'); - if (hide) { - tr.setAttribute('style', 'display:none'); - tr.setAttribute('class', 'stats_hidden'); - } var key = val[0]; var obj = {"desc": val[1].desc, "count": val[1].count}; - var percentage = Math.round((obj.count / total * 100), 2); - + // meta language names var td1 = document.createElement('td'); - td1.width = 300; var trending_language_label = document.createElement('div'); - trending_language_label.innerHTML = obj.desc + " (.{0})".format(key); + trending_language_label.innerHTML = obj.desc; td1.appendChild(trending_language_label); + // extensions var td2 = document.createElement('td'); - var trending_language = document.createElement('div'); - var nr_files = obj.count +" "+ _ngettext('file', 'files', obj.count); - - trending_language.title = key + " " + nr_files; + var extension = document.createElement('div'); + extension.innerHTML = ".{0}".format(key) + td2.appendChild(extension); - trending_language.innerHTML = "" + percentage + "% " + nr_files - + "" + percentage + "% " + nr_files + ""; + // number of files + var td3 = document.createElement('td'); + var file_count = document.createElement('div'); + var percentage_num = Math.round((obj.count / total * 100), 2); + var label = _ngettext('file', 'files', obj.count); + file_count.innerHTML = "{0} {1} ({2}%)".format(obj.count, label, percentage_num) ; + td3.appendChild(file_count); - trending_language.setAttribute("class", 'trending_language'); - $('b', trending_language)[0].style.width = percentage + "%"; - td2.appendChild(trending_language); + // percentage + var td4 = document.createElement('td'); + td4.setAttribute("class", 'trending_language'); + + var percentage = document.createElement('div'); + percentage.setAttribute('class', 'lang-bar'); + percentage.innerHTML = " "; + percentage.style.width = percentage_num + '%'; + td4.appendChild(percentage); tr.appendChild(td1); tr.appendChild(td2); + tr.appendChild(td3); + tr.appendChild(td4); tbl.appendChild(tr); - if (cnt == 3) { - var show_more = document.createElement('tr'); - var td = document.createElement('td'); - lnk = document.createElement('a'); - lnk.href = '#'; - lnk.innerHTML = _gettext('Show more'); - lnk.id = 'code_stats_show_more'; - td.appendChild(lnk); - - show_more.appendChild(td); - show_more.appendChild(document.createElement('td')); - tbl.appendChild(show_more); - } }); $(container).html(tbl); diff --git a/rhodecode/public/js/src/rhodecode/changelog.js b/rhodecode/public/js/src/rhodecode/changelog.js --- a/rhodecode/public/js/src/rhodecode/changelog.js +++ b/rhodecode/public/js/src/rhodecode/changelog.js @@ -46,6 +46,8 @@ var CommitsController = function () { self.$graphCanvas.html(''); var edgeData = $("[data-graph]").data('graph') || this.$graphCanvas.data('graph') || []; + var prev_link = $('.load-more-commits').find('.prev-commits').get(0); + var next_link = $('.load-more-commits').find('.next-commits').get(0); // Determine max number of edges per row in graph var edgeCount = 1; @@ -57,10 +59,20 @@ var CommitsController = function () { }); }); + if (prev_link && next_link) { + var graph_padding = -64; + } + else if (next_link) { + var graph_padding = -32; + } else { + var graph_padding = 0; + } + var x_step = Math.min(10, Math.floor(86 / edgeCount)); + var height = $('#changesets').find('.commits-range').height() + graph_padding; var graph_options = { width: 100, - height: $('#changesets').find('.commits-range').height(), + height: height, x_step: x_step, y_step: 42, dotRadius: 3.5, @@ -85,13 +97,20 @@ var CommitsController = function () { this.$graphCanvas.commits(graph_options); this.setLabelText(edgeData); - if ($('.load-more-commits').find('.prev-commits').get(0)) { - var padding = 75; - } else { - var padding = 43; + var padding = 90; + if (prev_link) { + padding += 34; + } $('#graph_nodes').css({'padding-top': padding}); + + $.each($('.message.truncate'), function(idx, value) { + if(!(value.offsetWidth < value.scrollWidth)){ + $(this).closest('td').siblings('.expand_commit').find('i').hide(); + } + }); + }; this.getChunkUrl = function (page, chunk, branch, commit_id, f_path) { @@ -112,10 +131,10 @@ var CommitsController = function () { } if (urlData['commit_id'] && urlData['f_path']) { - return pyroutes.url('repo_changelog_elements_file', urlData); + return pyroutes.url('repo_commits_elements_file', urlData); } else { - return pyroutes.url('repo_changelog_elements', urlData); + return pyroutes.url('repo_commits_elements', urlData); } }; diff --git a/rhodecode/public/js/src/rhodecode/codemirror.js b/rhodecode/public/js/src/rhodecode/codemirror.js --- a/rhodecode/public/js/src/rhodecode/codemirror.js +++ b/rhodecode/public/js/src/rhodecode/codemirror.js @@ -204,7 +204,12 @@ var CodeMirrorCompleteAfter = function(c }; var initCodeMirror = function(textAreadId, resetUrl, focus, options) { - var ta = $('#' + textAreadId).get(0); + if (textAreadId.substr(0,1) === "#"){ + var ta = $(textAreadId).get(0); + }else { + var ta = $('#' + textAreadId).get(0); + } + if (focus === undefined) { focus = true; } @@ -644,18 +649,6 @@ var fillCodeMirrorOptions = function(tar } }; -var CodeMirrorPreviewEnable = function(edit_mode) { - // in case it a preview enabled mode enable the button - if (['markdown', 'rst', 'gfm'].indexOf(edit_mode) !== -1) { - $('#render_preview').removeClass('hidden'); - } - else { - if (!$('#render_preview').hasClass('hidden')) { - $('#render_preview').addClass('hidden'); - } - } -}; - /* markup form */ (function(mod) { diff --git a/rhodecode/public/js/src/rhodecode/comments.js b/rhodecode/public/js/src/rhodecode/comments.js --- a/rhodecode/public/js/src/rhodecode/comments.js +++ b/rhodecode/public/js/src/rhodecode/comments.js @@ -587,12 +587,14 @@ var CommentsController = function() { $('#content').removeClass("wrapper"); $('#content').addClass("wide-mode-wrapper"); $(node).addClass('btn-success'); + return true } else { $('#content').removeClass("wide-mode-wrapper"); $('#content').addClass("wrapper"); $(node).removeClass('btn-success'); + return false } - return false; + }; this.toggleComments = function(node, show) { diff --git a/rhodecode/public/js/src/rhodecode/files.js b/rhodecode/public/js/src/rhodecode/files.js --- a/rhodecode/public/js/src/rhodecode/files.js +++ b/rhodecode/public/js/src/rhodecode/files.js @@ -19,234 +19,254 @@ /** * Search file list */ -// global reference to file-node filter -var _NODEFILTER = {}; + +var NodeFilter = {}; -var fileBrowserListeners = function(node_list_url, url_base){ - var n_filter = $('#node_filter').get(0); - - _NODEFILTER.filterTimeout = null; - var nodes = null; +var fileBrowserListeners = function (node_list_url, url_base) { + var $filterInput = $('#node_filter'); + var n_filter = $filterInput.get(0); - _NODEFILTER.fetchNodes = function(callback) { - $.ajax({url: node_list_url, headers: {'X-PARTIAL-XHR': true}}) - .done(function(data){ - nodes = data.nodes; - if (callback) { - callback(); - } - }) - .fail(function(data){ - console.log('failed to load'); - }); - }; + NodeFilter.filterTimeout = null; + var nodes = null; - _NODEFILTER.fetchNodesCallback = function() { - $('#node_filter_box_loading').hide(); - $('#node_filter_box').removeClass('hidden').show(); - n_filter.focus(); - if ($('#node_filter').hasClass('init')){ - n_filter.value = ''; - $('#node_filter').removeClass('init'); - } - }; + NodeFilter.focus = function () { + $filterInput.focus() + }; - _NODEFILTER.initFilter = function(){ - $('#node_filter_box_loading').removeClass('hidden').show(); - $('#search_activate_id').hide(); - $('#search_deactivate_id').removeClass('hidden').show(); - $('#add_node_id').hide(); - _NODEFILTER.fetchNodes(_NODEFILTER.fetchNodesCallback); - }; + NodeFilter.fetchNodes = function (callback) { + $.ajax( + {url: node_list_url, headers: {'X-PARTIAL-XHR': true}}) + .done(function (data) { + nodes = data.nodes; + if (callback) { + callback(); + } + }) + .fail(function (data) { + console.log('failed to load'); + }); + }; - _NODEFILTER.resetFilter = function(){ - $('#node_filter_box_loading').hide(); - $('#node_filter_box').hide(); - $('#search_activate_id').show(); - $('#search_deactivate_id').hide(); - $('#add_node_id').show(); - $('#tbody').show(); - $('#tbody_filtered').hide(); - $('#node_filter').val(''); - }; - - _NODEFILTER.fuzzy_match = function(filepath, query) { - var highlight = []; - var order = 0; - for (var i = 0; i < query.length; i++) { - var match_position = filepath.indexOf(query[i]); - if (match_position !== -1) { - var prev_match_position = highlight[highlight.length-1]; - if (prev_match_position === undefined) { - highlight.push(match_position); - } else { - var current_match_position = prev_match_position + match_position + 1; - highlight.push(current_match_position); - order = order + current_match_position - prev_match_position; + NodeFilter.initFilter = function (e) { + if ($filterInput.hasClass('loading')) { + return } - filepath = filepath.substring(match_position+1); - } else { - return false; - } - } - return {'order': order, - 'highlight': highlight}; - }; - _NODEFILTER.sortPredicate = function(a, b) { - if (a.order < b.order) return -1; - if (a.order > b.order) return 1; - if (a.filepath < b.filepath) return -1; - if (a.filepath > b.filepath) return 1; - return 0; - }; - - _NODEFILTER.updateFilter = function(elem, e) { - return function(){ - // Reset timeout - _NODEFILTER.filterTimeout = null; - var query = elem.value.toLowerCase(); - var match = []; - var matches_max = 20; - if (query !== ""){ - var results = []; - for(var k=0;k 0){ - var n = results[i].filepath; - var t = results[i].type; - var n_hl = n.split(""); - var pos = results[i].highlight; - for (var j = 0; j < pos.length; j++) { - n_hl[pos[j]] = "" + n_hl[pos[j]] + ""; - } - n_hl = n_hl.join(""); - var new_url = url_base.replace('__FPATH__',n); + var iconLoading = 'icon-spin animate-spin'; + var iconSearch = 'icon-search'; + $('.files-filter-box-path i').removeClass(iconSearch).addClass(iconLoading); + $filterInput.addClass('loading'); - var typeObj = { - dir: 'icon-directory browser-dir', - file: 'icon-file-text browser-file' - }; + var callback = function (org) { + return function () { + if ($filterInput.hasClass('init')) { + $filterInput.removeClass('init'); + $filterInput.removeClass('loading'); + } + $('.files-filter-box-path i').removeClass(iconLoading).addClass(iconSearch); - var typeIcon = ''.format(typeObj[t]); - match.push('{1}{2}'.format(new_url,typeIcon, n_hl)); - } - } - if(results.length > limit){ - var truncated_count = results.length - matches_max; - if (truncated_count === 1) { - match.push('{0} {1}'.format(truncated_count, _gettext('truncated result'))); - } else { - match.push('{0} {1}'.format(truncated_count, _gettext('truncated results'))); - } - } - } - if (query !== ""){ - $('#tbody').hide(); - $('#tbody_filtered').show(); + // auto re-filter if we filled in the input + if (n_filter.value !== "") { + NodeFilter.updateFilter(n_filter, e)() + } - if (match.length === 0){ - match.push('{0}'.format(_gettext('No matching files'))); - } - $('#tbody_filtered').html(match.join("")); - } - else{ + } + }; + // load node data + NodeFilter.fetchNodes(callback()); + + }; + + NodeFilter.resetFilter = function () { $('#tbody').show(); $('#tbody_filtered').hide(); - } + $filterInput.val(''); + }; + + NodeFilter.handleKey = function (e) { + var scrollDown = function (element) { + var elementBottom = element.offset().top + $(element).outerHeight(); + var windowBottom = window.innerHeight + $(window).scrollTop(); + if (elementBottom > windowBottom) { + var offset = elementBottom - window.innerHeight; + $('html,body').scrollTop(offset); + return false; + } + return true; + }; + + var scrollUp = function (element) { + if (element.offset().top < $(window).scrollTop()) { + $('html,body').scrollTop(element.offset().top); + return false; + } + return true; + }; + var $hlElem = $('.browser-highlight'); + + if (e.keyCode === 40) { // Down + if ($hlElem.length === 0) { + $('.browser-result').first().addClass('browser-highlight'); + } else { + var next = $hlElem.next(); + if (next.length !== 0) { + $hlElem.removeClass('browser-highlight'); + next.addClass('browser-highlight'); + } + } + + if ($hlElem.get(0) !== undefined){ + scrollDown($hlElem); + } + } + if (e.keyCode === 38) { // Up + e.preventDefault(); + if ($hlElem.length !== 0) { + var next = $hlElem.prev(); + if (next.length !== 0) { + $('.browser-highlight').removeClass('browser-highlight'); + next.addClass('browser-highlight'); + } + } + + if ($hlElem.get(0) !== undefined){ + scrollUp($hlElem); + } + + } + if (e.keyCode === 13) { // Enter + if ($('.browser-highlight').length !== 0) { + var url = $('.browser-highlight').find('.match-link').attr('href'); + window.location = url; + } + } + if (e.keyCode === 27) { // Esc + NodeFilter.resetFilter(); + $('html,body').scrollTop(0); + } + + var capture_keys = [ + 40, // ArrowDown + 38, // ArrowUp + 39, // ArrowRight + 37, // ArrowLeft + 13, // Enter + 27 // Esc + ]; + + if ($.inArray(e.keyCode, capture_keys) === -1) { + clearTimeout(NodeFilter.filterTimeout); + NodeFilter.filterTimeout = setTimeout(NodeFilter.updateFilter(n_filter, e), 200); + } }; - }; - - var scrollDown = function(element){ - var elementBottom = element.offset().top + $(element).outerHeight(); - var windowBottom = window.innerHeight + $(window).scrollTop(); - if (elementBottom > windowBottom) { - var offset = elementBottom - window.innerHeight; - $('html,body').scrollTop(offset); - return false; - } - return true; - }; - var scrollUp = function(element){ - if (element.offset().top < $(window).scrollTop()) { - $('html,body').scrollTop(element.offset().top); - return false; - } - return true; - }; + NodeFilter.fuzzy_match = function (filepath, query) { + var highlight = []; + var order = 0; + for (var i = 0; i < query.length; i++) { + var match_position = filepath.indexOf(query[i]); + if (match_position !== -1) { + var prev_match_position = highlight[highlight.length - 1]; + if (prev_match_position === undefined) { + highlight.push(match_position); + } else { + var current_match_position = prev_match_position + match_position + 1; + highlight.push(current_match_position); + order = order + current_match_position - prev_match_position; + } + filepath = filepath.substring(match_position + 1); + } else { + return false; + } + } + return { + 'order': order, + 'highlight': highlight + }; + }; - $('#filter_activate').click(function() { - _NODEFILTER.initFilter(); - }); - - $('#filter_deactivate').click(function() { - _NODEFILTER.resetFilter(); - }); - - $(n_filter).click(function() { - if ($('#node_filter').hasClass('init')){ - n_filter.value = ''; - $('#node_filter').removeClass('init'); - } - }); + NodeFilter.sortPredicate = function (a, b) { + if (a.order < b.order) return -1; + if (a.order > b.order) return 1; + if (a.filepath < b.filepath) return -1; + if (a.filepath > b.filepath) return 1; + return 0; + }; - $(n_filter).keydown(function(e) { - if (e.keyCode === 40){ // Down - if ($('.browser-highlight').length === 0){ - $('.browser-result').first().addClass('browser-highlight'); - } else { - var next = $('.browser-highlight').next(); - if (next.length !== 0) { - $('.browser-highlight').removeClass('browser-highlight'); - next.addClass('browser-highlight'); - } - } - scrollDown($('.browser-highlight')); - } - if (e.keyCode === 38){ // Up - e.preventDefault(); - if ($('.browser-highlight').length !== 0){ - var next = $('.browser-highlight').prev(); - if (next.length !== 0) { - $('.browser-highlight').removeClass('browser-highlight'); - next.addClass('browser-highlight'); - } - } - scrollUp($('.browser-highlight')); - } - if (e.keyCode === 13){ // Enter - if ($('.browser-highlight').length !== 0){ - var url = $('.browser-highlight').find('.pjax-link').attr('href'); - $.pjax({url: url, container: '#pjax-container', timeout: pjaxTimeout}); - } - } - if (e.keyCode === 27){ // Esc - _NODEFILTER.resetFilter(); - $('html,body').scrollTop(0); - } - }); - var capture_keys = [40, 38, 39, 37, 13, 27]; - $(n_filter).keyup(function(e) { - if ($.inArray(e.keyCode, capture_keys) === -1){ - clearTimeout(_NODEFILTER.filterTimeout); - _NODEFILTER.filterTimeout = setTimeout(_NODEFILTER.updateFilter(n_filter, e),200); - } - }); + NodeFilter.updateFilter = function (elem, e) { + return function () { + // Reset timeout + NodeFilter.filterTimeout = null; + var query = elem.value.toLowerCase(); + var match = []; + var matches_max = 20; + if (query !== "") { + var results = []; + for (var k = 0; k < nodes.length; k++) { + var result = NodeFilter.fuzzy_match( + nodes[k].name.toLowerCase(), query); + if (result) { + result.type = nodes[k].type; + result.filepath = nodes[k].name; + results.push(result); + } + } + results = results.sort(NodeFilter.sortPredicate); + var limit = matches_max; + if (results.length < matches_max) { + limit = results.length; + } + for (var i = 0; i < limit; i++) { + if (query && results.length > 0) { + var n = results[i].filepath; + var t = results[i].type; + var n_hl = n.split(""); + var pos = results[i].highlight; + for (var j = 0; j < pos.length; j++) { + n_hl[pos[j]] = "" + n_hl[pos[j]] + ""; + } + n_hl = n_hl.join(""); + var new_url = url_base.replace('__FPATH__', n); + + var typeObj = { + dir: 'icon-directory browser-dir', + file: 'icon-file-text browser-file' + }; + + var typeIcon = ''.format(typeObj[t]); + match.push('{1}{2}'.format(new_url, typeIcon, n_hl)); + } + } + if (results.length > limit) { + var truncated_count = results.length - matches_max; + if (truncated_count === 1) { + match.push('{0} {1}'.format(truncated_count, _gettext('truncated result'))); + } else { + match.push('{0} {1}'.format(truncated_count, _gettext('truncated results'))); + } + } + } + if (query !== "") { + $('#tbody').hide(); + $('#tbody_filtered').show(); + + if (match.length === 0) { + match.push('{0}'.format(_gettext('No matching files'))); + } + $('#tbody_filtered').html(match.join("")); + } else { + $('#tbody').show(); + $('#tbody_filtered').hide(); + } + + }; + }; + }; var getIdentNode = function(n){ @@ -308,3 +328,190 @@ var getSelectionLink = function(e) { } } }; + +var getFileState = function() { + // relies on a global set filesUrlData + var f_path = filesUrlData['f_path']; + var commit_id = filesUrlData['commit_id']; + + var url_params = { + repo_name: templateContext.repo_name, + commit_id: commit_id, + f_path:'__FPATH__' + }; + if (atRef !== '') { + url_params['at'] = atRef + } + + var _url_base = pyroutes.url('repo_files', url_params); + var _node_list_url = pyroutes.url('repo_files_nodelist', + {repo_name: templateContext.repo_name, + commit_id: commit_id, f_path: f_path}); + + return { + f_path: f_path, + commit_id: commit_id, + node_list_url: _node_list_url, + url_base: _url_base + }; +}; + +var getFilesMetadata = function() { + // relies on metadataRequest global state + if (metadataRequest && metadataRequest.readyState != 4) { + metadataRequest.abort(); + } + + if ($('#file-tree-wrapper').hasClass('full-load')) { + // in case our HTML wrapper has full-load class we don't + // trigger the async load of metadata + return false; + } + + var state = getFileState(); + var url_data = { + 'repo_name': templateContext.repo_name, + 'commit_id': state.commit_id, + 'f_path': state.f_path + }; + + var url = pyroutes.url('repo_nodetree_full', url_data); + + metadataRequest = $.ajax({url: url}); + + metadataRequest.done(function(data) { + $('#file-tree').html(data); + timeagoActivate(); + }); + metadataRequest.fail(function (data, textStatus, errorThrown) { + if (data.status != 0) { + alert("Error while fetching metadata.\nError code {0} ({1}).Please consider reloading the page".format(data.status,data.statusText)); + } + }); +}; + +// show more authors +var showAuthors = function(elem, annotate) { + var state = getFileState('callbacks'); + + var url = pyroutes.url('repo_file_authors', + {'repo_name': templateContext.repo_name, + 'commit_id': state.commit_id, 'f_path': state.f_path}); + + $.pjax({ + url: url, + data: 'annotate={0}'.format(annotate), + container: '#file_authors', + push: false, + timeout: 5000 + }).complete(function(){ + $(elem).hide(); + $('#file_authors_title').html(_gettext('All Authors')) + }) +}; + + +(function (mod) { + + if (typeof exports == "object" && typeof module == "object") { + // CommonJS + module.exports = mod(); + } else { + // Plain browser env + (this || window).FileEditor = mod(); + } + +})(function () { + "use strict"; + + function FileEditor(textAreaElement, options) { + if (!(this instanceof FileEditor)) { + return new FileEditor(textAreaElement, options); + } + // bind the element instance to our Form + var te = $(textAreaElement).get(0); + if (te !== undefined) { + te.FileEditor = this; + } + + this.modes_select = '#set_mode'; + this.filename_selector = '#filename'; + this.commit_btn_selector = '#commit_btn'; + this.line_wrap_selector = '#line_wrap'; + this.editor_preview_selector = '#editor_preview'; + + if (te !== undefined) { + this.cm = initCodeMirror(textAreaElement, null, false); + } + + // FUNCTIONS and helpers + var self = this; + + this.submitHandler = function() { + $(self.commit_btn_selector).on('click', function(e) { + + var filename = $(self.filename_selector).val(); + if (filename === "") { + alert("Missing filename"); + e.preventDefault(); + } + + var button = $(this); + if (button.hasClass('clicked')) { + button.attr('disabled', true); + } else { + button.addClass('clicked'); + } + }); + }; + this.submitHandler(); + + // on select line wraps change the editor + this.lineWrapHandler = function () { + $(self.line_wrap_selector).on('change', function (e) { + var selected = e.currentTarget; + var line_wraps = {'on': true, 'off': false}[selected.value]; + setCodeMirrorLineWrap(self.cm, line_wraps) + }); + }; + this.lineWrapHandler(); + + + this.showPreview = function () { + + var _text = self.cm.getValue(); + var _file_path = $(self.filename_selector).val(); + if (_text && _file_path) { + $('.show-preview').addClass('active'); + $('.show-editor').removeClass('active'); + + $(self.editor_preview_selector).show(); + $(self.cm.getWrapperElement()).hide(); + + + var post_data = {'text': _text, 'file_path': _file_path, 'csrf_token': CSRF_TOKEN}; + $(self.editor_preview_selector).html(_gettext('Loading ...')); + + var url = pyroutes.url('file_preview'); + + ajaxPOST(url, post_data, function (o) { + $(self.editor_preview_selector).html(o); + }) + } + + }; + + this.showEditor = function () { + $(self.editor_preview_selector).hide(); + $('.show-editor').addClass('active'); + $('.show-preview').removeClass('active'); + + $(self.cm.getWrapperElement()).show(); + }; + + + } + + return FileEditor; +}); + diff --git a/rhodecode/public/js/src/rhodecode/followers.js b/rhodecode/public/js/src/rhodecode/followers.js --- a/rhodecode/public/js/src/rhodecode/followers.js +++ b/rhodecode/public/js/src/rhodecode/followers.js @@ -16,58 +16,44 @@ // # RhodeCode Enterprise Edition, including its added features, Support services, // # and proprietary license terms, please see https://rhodecode.com/licenses/ -var onSuccessFollow = function(target){ - var f = $(target); - var f_cnt = $('#current_followers_count'); +var onSuccessFollow = function (target) { + var targetEl = $(target); - if(f.hasClass('follow')){ - f.removeClass('follow'); - f.addClass('following'); - f.attr('title', _gettext('Stop following this repository')); - $(f).html(_gettext('Unfollow')); - if(f_cnt.length){ - var cnt = Number(f_cnt.html())+1; - f_cnt.html(cnt); + var callback = function () { + targetEl.animate({'opacity': 1.00}, 200); + if (targetEl.hasClass('watching')) { + targetEl.removeClass('watching'); + targetEl.attr('title', _gettext('Stopped watching this repository')); + $(targetEl).html(''+_gettext('Watch')); + } else { + targetEl.addClass('watching'); + targetEl.attr('title', _gettext('Started watching this repository')); + $(targetEl).html(''+_gettext('Unwatch')); } - } - else{ - f.removeClass('following'); - f.addClass('follow'); - f.attr('title', _gettext('Start following this repository')); - $(f).html(_gettext('Follow')); - if(f_cnt.length){ - var cnt = Number(f_cnt.html())-1; - f_cnt.html(cnt); - } - } + }; + targetEl.animate({'opacity': 0.15}, 200, callback); }; -// TODO:: check if the function is needed. 0 usage found -var toggleFollowingUser = function(target,follows_user_id,token,user_id){ + +var toggleFollowingUser = function (target, follows_user_id) { var args = { 'follows_user_id': follows_user_id, - 'auth_token': token, 'csrf_token': CSRF_TOKEN }; - if(user_id != undefined){ - args.user_id = user_id - } - ajaxPOST(pyroutes.url('toggle_following'), args, function(){ + + ajaxPOST(pyroutes.url('toggle_following'), args, function () { onSuccessFollow(target); }); return false; }; -var toggleFollowingRepo = function(target,follows_repo_id,token,user_id){ +var toggleFollowingRepo = function (target, follows_repo_id) { var args = { 'follows_repo_id': follows_repo_id, - 'auth_token': token, 'csrf_token': CSRF_TOKEN }; - if(user_id != undefined){ - args.user_id = user_id - } - ajaxPOST(pyroutes.url('toggle_following'), args, function(){ + + ajaxPOST(pyroutes.url('toggle_following'), args, function () { onSuccessFollow(target); }); return false; diff --git a/rhodecode/public/js/src/rhodecode/select2_widgets.js b/rhodecode/public/js/src/rhodecode/select2_widgets.js --- a/rhodecode/public/js/src/rhodecode/select2_widgets.js +++ b/rhodecode/public/js/src/rhodecode/select2_widgets.js @@ -73,10 +73,3 @@ var select2RefSwitcher = function(target {'repo_name': templateContext.repo_name}); select2RefBaseSwitcher(targetElement, loadUrl, initialData); }; - -var select2FileHistorySwitcher = function(targetElement, initialData, state) { - var loadUrl = pyroutes.url('repo_file_history', - {'repo_name': templateContext.repo_name, 'commit_id': state.rev, - 'f_path': state.f_path}); - select2RefBaseSwitcher(targetElement, loadUrl, initialData); -}; diff --git a/rhodecode/templates/admin/admin_audit_log_entry.mako b/rhodecode/templates/admin/admin_audit_log_entry.mako --- a/rhodecode/templates/admin/admin_audit_log_entry.mako +++ b/rhodecode/templates/admin/admin_audit_log_entry.mako @@ -9,20 +9,23 @@ %endif -<%def name="breadcrumbs_links()"> - ${_('Audit long entry')} ${c.audit_log_entry.entry_id} - +<%def name="breadcrumbs_links()"> <%def name="menu_bar_nav()"> ${self.menu_items(active='admin')} + +<%def name="menu_bar_subnav()"> + ${self.admin_menu(active='audit_logs')} + + <%def name="main()">
- +
- ${self.breadcrumbs()} + ${_('Audit long entry')} ${c.audit_log_entry.entry_id}
- +
diff --git a/rhodecode/templates/admin/admin_audit_logs.mako b/rhodecode/templates/admin/admin_audit_logs.mako --- a/rhodecode/templates/admin/admin_audit_logs.mako +++ b/rhodecode/templates/admin/admin_audit_logs.mako @@ -8,27 +8,28 @@ %endif -<%def name="breadcrumbs_links()"> - ${h.form(None, id_="filter_form", method="get")} - - - ${_('Audit logs')} - ${_ungettext('%s entry', '%s entries', c.audit_logs.item_count) % (c.audit_logs.item_count)} - ${h.end_form()} -

${_('Example Queries')}

- - +<%def name="breadcrumbs_links()"> <%def name="menu_bar_nav()"> ${self.menu_items(active='admin')} +<%def name="menu_bar_subnav()"> + ${self.admin_menu(active='audit_logs')} + + <%def name="main()">
-
- ${self.breadcrumbs()} + ${h.form(None, id_="filter_form", method="get")} + + + ${_('Audit logs')} - ${_ungettext('%s entry', '%s entries', c.audit_logs.item_count) % (c.audit_logs.item_count)} + ${h.end_form()} +

${_('Example Queries')}

+
- +
<%include file="/admin/admin_log_base.mako" /> diff --git a/rhodecode/templates/admin/auth/auth_settings.mako b/rhodecode/templates/admin/auth/auth_settings.mako --- a/rhodecode/templates/admin/auth/auth_settings.mako +++ b/rhodecode/templates/admin/auth/auth_settings.mako @@ -8,29 +8,26 @@ %endif -<%def name="breadcrumbs_links()"> - ${h.link_to(_('Admin'),h.route_path('admin_home'))} - » - ${_('Authentication Plugins')} - +<%def name="breadcrumbs_links()"> <%def name="menu_bar_nav()"> ${self.menu_items(active='admin')} +<%def name="menu_bar_subnav()"> + ${self.admin_menu(active='authentication')} + + <%def name="main()">
-
- ${self.breadcrumbs()} -
%for plugin in available_plugins: - + diff --git a/rhodecode/templates/admin/auth/plugin_settings.mako b/rhodecode/templates/admin/auth/plugin_settings.mako --- a/rhodecode/templates/admin/auth/plugin_settings.mako +++ b/rhodecode/templates/admin/auth/plugin_settings.mako @@ -2,10 +2,10 @@ <%inherit file="/base/base.mako"/> <%def name="title()"> - ${_('Authentication Settings')} - %if c.rhodecode_name: + ${_('Authentication Settings')} + %if c.rhodecode_name: · ${h.branding(c.rhodecode_name)}} - %endif + %endif <%def name="breadcrumbs_links()"> @@ -17,22 +17,23 @@ <%def name="menu_bar_nav()"> - ${self.menu_items(active='admin')} + ${self.menu_items(active='admin')} + + +<%def name="menu_bar_subnav()"> + ${self.admin_menu(active='authentication')} <%def name="main()"> +
-
- ${self.breadcrumbs()} -
+
${_('Plugin ID')} ${_('Enabled')}
- - ${_('activated') if plugin.get_id() in enabled_plugins else _('not active')} + + ${(_('activated') if plugin.get_id() in enabled_plugins else _('not active'))} ${plugin.get_display_name()}
-
+ - - // refilter table if page load via back button - $("#q_filter").trigger('keyup'); -}); - diff --git a/rhodecode/templates/admin/repos/repo_add.mako b/rhodecode/templates/admin/repos/repo_add.mako --- a/rhodecode/templates/admin/repos/repo_add.mako +++ b/rhodecode/templates/admin/repos/repo_add.mako @@ -26,12 +26,12 @@ ${self.menu_items(active='admin')} +<%def name="menu_bar_subnav()"> + ${self.admin_menu(active='repositories')} + + <%def name="main()">
- -
- ${self.breadcrumbs()} -
<%include file="repo_add_base.mako"/>
diff --git a/rhodecode/templates/admin/repos/repo_edit.mako b/rhodecode/templates/admin/repos/repo_edit.mako --- a/rhodecode/templates/admin/repos/repo_edit.mako +++ b/rhodecode/templates/admin/repos/repo_edit.mako @@ -20,7 +20,7 @@ <%def name="menu_bar_subnav()"> - ${self.repo_menu(active='options')} + ${self.repo_menu(active='settings')} <%def name="main_content()"> @@ -34,10 +34,6 @@ <%def name="main()">
-
- ${self.repo_page_title(c.rhodecode_db_repo)} - -