diff --git a/.bumpversion.cfg b/.bumpversion.cfg --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 4.1.2 +current_version = 4.2.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 @@ -1,32 +1,26 @@ [DEFAULT] done = false +[task:fixes_on_stable] + +[task:changelog_updated] + [task:bump_version] done = true -[task:rc_tools_pinned] -done = true +[task:generate_api_docs] + +[task:updated_translation] -[task:fixes_on_stable] -done = true +[release] +state = in_progress +version = 4.2.0 + +[task:rc_tools_pinned] [task:pip2nix_generated] -done = true - -[task:changelog_updated] -done = true - -[task:generate_api_docs] -done = true [task:generate_js_routes] -done = true - -[release] -state = prepared -version = 4.1.2 - -[task:updated_translation] [task:updated_trial_license] diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -41,6 +41,19 @@ The latest sources can be obtained from https://code.rhodecode.com +Contributions +------------- + +RhodeCode is open-source; contributions are welcome! + +Please see the contribution documentation inside of the docs folder, which is +also available at +https://docs.rhodecode.com/RhodeCode-Enterprise/contributing/contributing.html + +For additional information about collaboration tools, our issue tracker, +licensing, and contribution credit, visit https://rhodecode.com/open-source + + RhodeCode Features ------------------ diff --git a/acceptance_tests/README.rst b/acceptance_tests/README.rst --- a/acceptance_tests/README.rst +++ b/acceptance_tests/README.rst @@ -1,7 +1,7 @@ README - Quickstart =================== -This folder contains functional tests and the automation of specification +This folder contains the functional tests and automation of specification examples. Details about testing can be found in `/docs-internal/testing/index.rst`. @@ -21,7 +21,7 @@ Use the following example call for the d --api-key=9999999999999999999999999999999999999999 \ your-enterprise-config.ini -This way the username, password and auth token of the admin user will match the +This way the username, password, and auth token of the admin user will match the defaults from the test run. @@ -34,7 +34,7 @@ 1. Make sure your Rhodecode Enterprise i 2. Enter `nix-shell` from the acceptance_tests folder:: cd acceptance_tests - nix-shell -I ~/dev + nix-shell Make sure that `rcpkgs` and `rcnixpkgs` are available on the nix path. diff --git a/configs/development.ini b/configs/development.ini --- a/configs/development.ini +++ b/configs/development.ini @@ -8,7 +8,6 @@ [DEFAULT] debug = true -pdebug = false ################################################################################ ## Uncomment and replace with the email address which should receive ## ## any error reports after an application crash ## @@ -115,11 +114,23 @@ rhodecode.api.url = /_admin/api ## END RHODECODE PLUGINS ## +## encryption key used to encrypt social plugin tokens, +## remote_urls with credentials etc, if not set it defaults to +## `beaker.session.secret` +#rhodecode.encrypted_values.secret = + +## decryption strict mode (enabled by default). It controls if decryption raises +## `SignatureVerificationError` in case of wrong key, or damaged encryption data. +#rhodecode.encrypted_values.strict = false + full_stack = true ## Serve static files via RhodeCode, disable to serve them via HTTP server static_files = true +# autogenerate javascript routes file on startup +generate_js_files = false + ## Optional Languages ## en(default), be, de, es, fr, it, ja, pl, pt, ru, zh lang = en @@ -380,7 +391,6 @@ beaker.session.auto = false search.module = rhodecode.lib.index.whoosh search.location = %(here)s/data/index - ################################### ## APPENLIGHT CONFIG ## ################################### @@ -514,7 +524,7 @@ vcs.connection_timeout = 3600 ### LOGGING CONFIGURATION #### ################################ [loggers] -keys = root, routes, rhodecode, sqlalchemy, beaker, pyro4, templates, whoosh_indexer +keys = root, routes, rhodecode, sqlalchemy, beaker, pyro4, templates [handlers] keys = console, console_sql @@ -566,12 +576,6 @@ handlers = console_sql qualname = sqlalchemy.engine propagate = 0 -[logger_whoosh_indexer] -level = DEBUG -handlers = -qualname = whoosh_indexer -propagate = 1 - ############## ## HANDLERS ## ############## diff --git a/configs/production.ini b/configs/production.ini --- a/configs/production.ini +++ b/configs/production.ini @@ -8,7 +8,6 @@ [DEFAULT] debug = true -pdebug = false ################################################################################ ## Uncomment and replace with the email address which should receive ## ## any error reports after an application crash ## @@ -89,11 +88,23 @@ use = egg:rhodecode-enterprise-ce ## enable proxy prefix middleware, defined below #filter-with = proxy-prefix +## encryption key used to encrypt social plugin tokens, +## remote_urls with credentials etc, if not set it defaults to +## `beaker.session.secret` +#rhodecode.encrypted_values.secret = + +## decryption strict mode (enabled by default). It controls if decryption raises +## `SignatureVerificationError` in case of wrong key, or damaged encryption data. +#rhodecode.encrypted_values.strict = false + full_stack = true ## Serve static files via RhodeCode, disable to serve them via HTTP server static_files = true +# autogenerate javascript routes file on startup +generate_js_files = false + ## Optional Languages ## en(default), be, de, es, fr, it, ja, pl, pt, ru, zh lang = en @@ -354,7 +365,6 @@ beaker.session.auto = false search.module = rhodecode.lib.index.whoosh search.location = %(here)s/data/index - ################################### ## APPENLIGHT CONFIG ## ################################### @@ -483,7 +493,7 @@ vcs.connection_timeout = 3600 ### LOGGING CONFIGURATION #### ################################ [loggers] -keys = root, routes, rhodecode, sqlalchemy, beaker, pyro4, templates, whoosh_indexer +keys = root, routes, rhodecode, sqlalchemy, beaker, pyro4, templates [handlers] keys = console, console_sql @@ -535,12 +545,6 @@ handlers = console_sql qualname = sqlalchemy.engine propagate = 0 -[logger_whoosh_indexer] -level = DEBUG -handlers = -qualname = whoosh_indexer -propagate = 1 - ############## ## HANDLERS ## ############## diff --git a/default.nix b/default.nix --- a/default.nix +++ b/default.nix @@ -46,6 +46,7 @@ let !elem ext ["egg-info" "pyc"] && !startsWith "result" path; + sources = pkgs.config.rc.sources or {}; rhodecode-enterprise-ce-src = builtins.filterSource src-filter ./.; # Load the generated node packages @@ -98,9 +99,11 @@ let ''; in super.rhodecode-enterprise-ce.override (attrs: { - inherit doCheck; + inherit + doCheck + version; name = "rhodecode-enterprise-ce-${version}"; - version = version; + releaseName = "RhodeCodeEnterpriseCE-${version}"; src = rhodecode-enterprise-ce-src; buildInputs = @@ -109,7 +112,7 @@ let pkgs.nodePackages.grunt-cli pkgs.subversion pytest-catchlog - rc_testdata + rhodecode-testdata ]); propagatedBuildInputs = attrs.propagatedBuildInputs ++ (with self; [ @@ -197,17 +200,22 @@ let }); - rc_testdata = self.buildPythonPackage rec { - name = "rc_testdata-0.7.0"; - src = pkgs.fetchhg { - url = "https://code.rhodecode.com/upstream/rc_testdata"; - rev = "v0.7.0"; - sha256 = "0w3z0zn8lagr707v67lgys23sl6pbi4xg7pfvdbw58h3q384h6rx"; - }; + rhodecode-testdata = import "${rhodecode-testdata-src}/default.nix" { + inherit + doCheck + pkgs + pythonPackages; }; }; + rhodecode-testdata-src = sources.rhodecode-testdata or ( + pkgs.fetchhg { + url = "https://code.rhodecode.com/upstream/rc_testdata"; + rev = "v0.8.0"; + sha256 = "0hy1ba134rq2f9si85yx7j4qhc9ky0hjzdk553s3q026i7km809m"; + }); + # Apply all overrides and fix the final package set myPythonPackagesUnfix = (extends pythonExternalOverrides diff --git a/docs/admin/enable-debug.rst b/docs/admin/enable-debug.rst --- a/docs/admin/enable-debug.rst +++ b/docs/admin/enable-debug.rst @@ -47,7 +47,7 @@ the ``debug`` level. ### LOGGING CONFIGURATION #### ################################ [loggers] - keys = root, routes, rhodecode, sqlalchemy, beaker, pyro4, templates, whoosh_indexer + keys = root, routes, rhodecode, sqlalchemy, beaker, pyro4, templates [handlers] keys = console, console_sql, file, file_rotating @@ -99,12 +99,6 @@ the ``debug`` level. qualname = sqlalchemy.engine propagate = 0 - [logger_whoosh_indexer] - level = DEBUG - handlers = - qualname = whoosh_indexer - propagate = 1 - ############## ## HANDLERS ## ############## diff --git a/docs/contributing/checklist-tickets.rst b/docs/contributing/checklist-tickets.rst new file mode 100644 --- /dev/null +++ b/docs/contributing/checklist-tickets.rst @@ -0,0 +1,137 @@ +.. _checklist-tickets: + +================= +Ticket Checklists +================= + + +Ticket Description +================== + +In general these things really matter in the description: + +- Reasoning / Rationale. Explain "WHY" it makes sense and is important. + +- How to reproduce. Easy to follow steps, that’s important. + + - Observation: The problem (short) + + - Expectation: How it should be (short) + +- Specs: It is fine to draft them as good as it works. + + If anything is unclear, please ask for a review or help on this via the + Community Portal or Slack channel. + + +Checklists for Tickets +====================== + +BUG +--- + +Definition: An existing function that does not work as expected for the user. + +- Problem description +- Steps needed to recreate (gherkin) +- Link to the screen in question and/or description of how to find it via + navigation +- Explanation of what the expected outcome is +- Any hints into the source of the problem +- Information about platform/browser/db/etc. where applicable +- Examples of other similar cases which have different behaviour + +DESIGN +------ + +Definition: Styling and user interface issues, including cosmetic improvements +or appearance and behaviour of frontend functionality. + +- Screenshot/animation of existing page/behaviour +- Sketches or wireframes if available +- Link to the screen in question and/or description of how to find it via + navigation +- Problem description +- Explanation of what the expected outcome is +- Since this may be examined by a designer; it should be written in a way that a + non-developer can understand + +EPIC +---- + +Definition: A collection of tickets which together complete a larger overall +project. + +- Benefit explanation +- Clear objective - when is this complete? +- Explanations of exceptions/corner cases +- Documentation subtask +- Comprehensive wireframes and/or design subtasks +- Links to subtasks + +FEATURE +------- + +Definition: A new function in the software which previously did not exist. + +- Benefit explanation +- Clear objective +- Explanations of exceptions/corner cases +- Documentation subtask +- Comprehensive wireframes and/or design subtasks + +SUPPORT +------- + +Definition: An issue related to a customer report. + +- Link to support ticket, if available +- Problem description +- Steps needed to recreate (gherkin) +- Link to the screen in question and/or description of how to find it via + navigation +- Explanation of what the expected outcome is +- Any hints into the source of the problem +- Information about platform/browser/db/etc. where applicable +- Examples of other similar cases which have different behaviour + +TASK +---- + +Definition: An improvement or step towards implementing a feature or fixing +a bug. Includes refactoring and other tech debt. + +- Clear objective +- Benefit explanation +- Links to parent/related tickets + + +All details below. + + +External links: + +- Avoid linking to external images; they disappear over time. Please attach any + relevant images to the ticket itself. + +- External links in general: They also disappear over time, consider copying the + relevant bit of information into a comment or write a paragraph to sum up the + general idea. + + +Hints +===== + +Change Description +------------------ + +It can be tricky to figure out how to change the description of a ticket. There +is a very small pencil which has to be clicked once you see the edit form of a +ticket. + + +.. figure:: images/redmine-description.png + :alt: Example of pencil to change the ticket description + + Shows an example of the pencil which lets you change the description. + diff --git a/docs/contributing/contributing.rst b/docs/contributing/contributing.rst --- a/docs/contributing/contributing.rst +++ b/docs/contributing/contributing.rst @@ -5,13 +5,14 @@ Contributing to RhodeCode -Welcome to contribution guides and development docs of RhodeCode. +Welcome to the contribution guides and development docs of RhodeCode. .. toctree:: :maxdepth: 1 + overview testing/index dev-setup db-schema diff --git a/docs/contributing/db-schema.rst b/docs/contributing/db-schema.rst --- a/docs/contributing/db-schema.rst +++ b/docs/contributing/db-schema.rst @@ -2,7 +2,7 @@ DB Schema and Migration ======================= -To create or alter tables in the database it's necessary to change a couple of +To create or alter tables in the database, it's necessary to change a couple of files, apart from configuring the settings pointing to the latest database schema. @@ -11,11 +11,11 @@ Database Model and ORM ---------------------- On ``rhodecode.model.db`` you will find the database definition of all tables and -fields. Any fresh install database will be correctly created by the definitions -here. So, any change to this files will affect the tests without having to change +fields. Any freshly installed database will be correctly created by the definitions +here. So, any change to this file will affect the tests without having to change any other file. -A second layer are the businness classes that are inside ``rhodecode.model``. +A second layer are the business classes inside ``rhodecode.model``. Database Migration @@ -30,7 +30,7 @@ Three files play a role when creating da Schema is a snapshot of the database version BEFORE the migration. So, it's the initial state before any changes were added. The name convention is -the latest release version where the snapshot were created, and not the +the latest release version where the snapshot was created, and not the target version of this code. Version is the method that will define how to UPGRADE/DOWNGRADE the database. @@ -45,8 +45,8 @@ For examples on how to create those file Migration Command ^^^^^^^^^^^^^^^^^ -After you changed the database ORM and migration files, you can run:: +After you've changed the database ORM and migration files, you can run:: paster upgrade-db -And the database will be upgraded up to the version defined in the ``__init__`` file. \ No newline at end of file +The database will be upgraded up to the version defined in the ``__init__`` file. \ No newline at end of file diff --git a/docs/contributing/dev-settings.rst b/docs/contributing/dev-settings.rst --- a/docs/contributing/dev-settings.rst +++ b/docs/contributing/dev-settings.rst @@ -13,7 +13,7 @@ purposes. This section contains an overv ============= Enables the section "Style" in the application. This section provides an -overview of all components which are found in the frontend style of the +overview of all components which are found in the frontend of the application. @@ -29,9 +29,9 @@ to ease development. `[logging]` =========== -Use this to configure loggig to your current needs. The documentation of -Python's `logging` module explains all details. The following snippets are -useful for day to day development work. +Use this to configure logging to your current needs. The documentation of +Python's `logging` module explains all of the details. The following snippets +are useful for day to day development work. Mute SQL output diff --git a/docs/contributing/dev-setup.rst b/docs/contributing/dev-setup.rst --- a/docs/contributing/dev-setup.rst +++ b/docs/contributing/dev-setup.rst @@ -1,3 +1,4 @@ +.. _dev-setup: =================== Development setup @@ -7,21 +8,21 @@ RhodeCode Enterprise runs inside a Nix managed environment. This ensures build environment dependencies are correctly declared and installed during setup. It also enables atomic upgrades, rollbacks, and multiple instances of RhodeCode -Enterprise for efficient cluster management. +Enterprise running with isolation. -To set up RhodeCode Enterprise inside the Nix environment use the following steps: +To set up RhodeCode Enterprise inside the Nix environment, use the following steps: Setup Nix Package Manager ------------------------- -To install the Nix Package Manager please run:: +To install the Nix Package Manager, please run:: $ curl https://nixos.org/nix/install | sh -or go to https://nixos.org/nix/ and follow their installation instructions. -Once this is correctly set up on your system you should be able to use the +or go to https://nixos.org/nix/ and follow the installation instructions. +Once this is correctly set up on your system, you should be able to use the following commands: * `nix-env` @@ -34,8 +35,8 @@ following commands: Update your channels frequently by running ``nix-channel --upgrade``. -Switch nix to latest STABLE channel ------------------------------------ +Switch nix to the latest STABLE channel +--------------------------------------- run:: @@ -49,7 +50,7 @@ Followed by:: Clone the required repositories ------------------------------- -After Nix is set up, clone the RhodeCode Enterprise Community Edition, and +After Nix is set up, clone the RhodeCode Enterprise Community Edition and RhodeCode VCSServer repositories into the same directory. To do this, use the following example:: @@ -59,23 +60,25 @@ To do this, use the following example:: .. note:: - If you cannot clone the repository, please request read permissions. + If you cannot clone the repository, please request read permissions + via support@rhodecode.com Enter the Development Shell --------------------------- -The final step is to start into the development shell. To do this run the +The final step is to start the development shell. To do this, run the following command from inside the cloned repository:: cd ~/rhodecode-enterprise-ce - nix-shell --arg dev true + nix-shell .. note:: On the first run, this will take a while to download and optionally compile - a few things. The next runs of it will be faster. + a few things. The following runs will be faster. The development shell works + fine on MacOS and Linux platforms. @@ -90,13 +93,13 @@ 2. Adjust the configuration settings to .. note:: - It is recommended to call it `dev.ini`. + It is recommended to use the name `dev.ini`. Setup the Development Database ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -To create a development database use the following example. This is a one +To create a development database, use the following example. This is a one time operation:: paster setup-rhodecode dev.ini \ @@ -109,7 +112,7 @@ Start the Development Server ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ When starting the development server, you should start the vcsserver as a -separate process. To do this use one of the following examples: +separate process. To do this, use one of the following examples: 1. Set the `start.vcs_server` flag in the ``dev.ini`` file to true. For example: @@ -136,6 +139,6 @@ 3. Start the development server in a dif Run the Environment Tests ^^^^^^^^^^^^^^^^^^^^^^^^^ -Please make sure that the test are passing to verify that your environment is -set up correctly. More details about the tests are described in: -:file:`/docs/dev/testing`. +Please make sure that the tests are passing to verify that your environment is +set up correctly. RhodeCode uses py.test to run tests. +Please simply run ``make test`` to run the basic test suite. diff --git a/docs/contributing/frontend.rst b/docs/contributing/frontend.rst new file mode 100644 --- /dev/null +++ b/docs/contributing/frontend.rst @@ -0,0 +1,153 @@ + +================================================== + Code style and structure guide for frontend work +================================================== + +About: Outline of frontend development practices. + + + + +Templates +========= + +- Indent with 4 spaces in general. +- Embedded Python code follows the same conventions as in the backend. + + A common problem is missed spaces around operators. + + + + +Grunt +===== + +We use Grunt to compile our JavaScript and LESS files. This is done automatically +when you start an instance. If you are changing these files, however, it is +recommended to amend `--reload` to the `runserver` command, or use `grunt watch` +- the Gruntfile is located in the base directory. For more info on Grunt, see +http://gruntjs.com/ + + + + +LESS CSS +======== + + +Style +----- + +- Use 4 spaces instead of tabs. +- Avoid ``!important``; it is very often an indicator for a problem. + + + + +Structure +--------- + +It is important that we maintain consistency in the LESS files so that things +scale properly. CSS is organized using LESS and then compiled into a CSS file +to be used in production. Find the class you need to change and change it +there. Do not add overriding styles at the end of the file. The LESS file will +be minified; use plenty of spacing and comments for readability. + +These will be kept in auxillary LESS files to be imported (in this order) at the top: + +- `fonts.less` (font-face declarations) +- `mixins` (place all LESS mixins here) +- `helpers` (basic classes for hiding mobile elements, centering, etc) +- `variables` (theme-specific colors, spacing, and fonts which might change later) + + +Sections of the primary LESS file are as follows. Add comments describing +layout and modules. + +.. code-block:: css + + //--- BASE ------------------// + Very basic, sitewide styles. + + //--- LAYOUT ------------------// + Essential layout, ex. containers and wrappers. + Do not put type styles in here. + + //--- MODULES ------------------// + Reusable sections, such as sidebars and menus. + + //--- THEME ------------------// + Theme styles, typography, etc. + + + +Formatting rules +~~~~~~~~~~~~~~~~ + +- Each rule should be indented on a separate line (this is helpful for diff + checking). + +- Use a space after each colon and a semicolon after each last rule. + +- Put a blank line between each class. + +- Nested classes should be listed after the parent class' rules, separated with a + blank line, and indented. + +- Using the below as a guide, place each rule in order of its effect on content, + layout, sizing, and last listing minor style changes such as font color and + backgrounds. Not every possible rule is listed here; when adding new ones, + judge where it should go in the list based on that hierarchy. + + .. code-block:: scss + + .class { + content + list-style-type + position + float + top + right + bottom + left + height + max-height + min-height + width + max-width + min-width + margin + padding + indent + vertical-align + text-align + border + border-radius + font-size + line-height + font + font-style + font-variant + font-weight + color + text-shadow + background + background-color + box-shadow + background-url + background-position + background-repeat + background-cover + transitions + cursor + pointer-events + + .nested-class { + position + background-color + + &:hover { + color + } + } + } diff --git a/docs/contributing/overview.rst b/docs/contributing/overview.rst new file mode 100644 --- /dev/null +++ b/docs/contributing/overview.rst @@ -0,0 +1,111 @@ + +======================= + Contributing Overview +======================= + + +RhodeCode Community Edition is an open source code management platform. We +encourage contributions to our project from the community. This is a basic +overview of the procedures for adding your contribution to RhodeCode. + + + +Check the Issue Tracker +======================= + +Make an account at https://issues.rhodecode.com/account/register and browse the +current tickets for bugs to fix and tasks to do. Have a bug or feature that you +can't find in the tracker? Create a new issue for it. When you select a ticket, +make sure to assign it to yourself and mark it "in progress" to avoid duplicated +work. + + + +Sign Up at code.rhodecode.com +============================= + +Make an account at https://code.rhodecode.com/ using an email or your existing +GitHub, Bitbucket, Google, or Twitter account. Fork the repo you'd like to +contribute to; we suggest adding your username to the fork name. Clone your fork +to your computer. We use Mercurial for source control management; see +https://www.mercurial-scm.org/guide to get started quickly. + + + +Set Up A Local Instance +======================= + +You will need to set up an instance of RhodeCode CE using VCSServer so that you +can see your work locally as you make changes. We recommend using Linux for this +but it can also be built on OSX. + +See :doc:`dev-setup` for instructions. + + + +Code! +===== + +You can now make, see, and test your changes locally. We are always improving to +keep our code clean and the cost of maintaining it low. This applies in the same +way for contributions. We run automated checks on our pull requests, and expect +understandable code. We also aim to provide test coverage for as much of our +codebase as possible; any new features should be augmented with tests. + +Keep in mind that when we accept your contribution, we also take responsibility +for it; we must understand it to take on that responsibility. + +See :doc:`standards` for more detailed information. + + + +Commit And Push Your Changes +============================ + +We highly recommend making a new bookmark for each feature, bug, or set of +commits you make so that you can point to it when creating your pull request. +Please also reference the ticket number in your commit messages. Don't forget to +push the bookmark! + + + +Submit a Pull Request +===================== + +Go to your fork, and choose "Create Pull Request" from the Options menu. Use +your bookmark as the source, and choose someone to review it. Don't worry about +chosing the right person; we'll assign the best contributor for the job. You'll +get feedback and an assigned status. + +Be prepared to make updates to your pull request after some feedback. +Collaboration is part of the process and improvements can often be made. + + + +Sign the Contributor License Agreement +====================================== + +If your contribution is approved, you will need to virtually sign the license +agreement in order for it to be merged into the project's codebase. You can read +it on our website here: https://rhodecode.com/static/pdf/RhodeCode-CLA.pdf + +To sign, go to code.rhodecode.com +and clone the CLA repository. Add your name and make a pull request to add it to +the contributor agreement; this serves as your virtual signature. Once your +signature is merged, add a link to the relevant commit to your contribution +pull request. + + + +That's it! We'll take it from there. Thanks for your contribution! +------------------------------------------------------------------ + +.. note:: If you have any questions or comments, feel free to contact us through + either the community portal(community.rhodecode.com), IRC + (irc.freenode.net), or Slack (rhodecode.com/join). + + + + + + diff --git a/docs/contributing/standards.rst b/docs/contributing/standards.rst new file mode 100644 --- /dev/null +++ b/docs/contributing/standards.rst @@ -0,0 +1,177 @@ + +====================== +Contribution Standards +====================== + +Standards help to improve the quality of our product and its development. Herein +we define our standards for processes and development to maintain consistency +and function well as a community. It is a work in progress; modifications to this +document should be discussed and agreed upon by the community. + + +-------------------------------------------------------------------------------- + +Code +==== + +This provides an outline for standards we use in our codebase to keep our code +easy to read and easy to maintain. Much of our code guidelines are based on the +book `Clean Code `_ +by Robert Martin. + +We maintain a Tech Glossary to provide consistency in terms and symbolic names +used for items and concepts within the application. This is found in the CE +project in /docs-internal/glossary.rst + + +Refactoring +----------- +Make it better than you found it! + +Our codebase can always use improvement and often benefits from refactoring. +New code should be refactored as it is being written, and old code should be +treated with the same care as if it was new. Before doing any refactoring, +ensure that there is test coverage on the affected code; this will help +minimize issues. + + +Python +------ +For Python, we use `PEP8 `_. +We adjust lines of code to under 80 characters and use 4 spaces for indentation. + + +JavaScript +---------- +This currently remains undefined. Suggestions welcome! + + +HTML +---- +Unfortunately, we currently have no strict HTML standards, but there are a few +guidelines we do follow. Templates must work in all modern browsers. HTML should +be clean and easy to read, and additionally should be free of inline CSS or +JavaScript. It is recommended to use data attributes for JS actions where +possible in order to separate it from styling and prevent unintentional changes. + + +LESS/CSS +-------- +We use LESS for our CSS; see :doc:`frontend` for structure and formatting +guidelines. + + +Linters +------- +Currently, we have a linter for pull requests which checks code against PEP8. +We intend to add more in the future as we clarify standards. + + +-------------------------------------------------------------------------------- + +Naming Conventions +================== + +These still need to be defined for naming everything from Python variables to +HTML classes to files and folders. + + +-------------------------------------------------------------------------------- + +Testing +======= + +Testing is a very important aspect of our process, especially as we are our own +quality control team. While it is of course unrealistic to hit every potential +combination, our goal is to cover every line of Python code with a test. + +The following is a brief introduction to our test suite. Our tests are primarily +written using `py.test `_ + + +Acceptance Tests +---------------- +Also known as "ac tests", these test from the user and business perspective to +check if the requirements of a feature are met. Scenarios are created at a +feature's inception and help to define its value. + +py.test is used for ac tests; they are located in a repo separate from the +other tests which follow. Each feature has a .feature file which contains a +brief description and the scenarios to be tested. + + +Functional Tests +---------------- +These test specific functionality in the application which checks through the +entire stack. Typically these are user actions or permissions which go through +the web browser. They are located in rhodecode/tests. + + +Unit Tests +---------- +These test isolated, individual modules to ensure that they function correctly. +They are located in rhodecode/tests. + + +Integration Tests +----------------- +These are used for testing performance of larger systems than the unit tests. +They are located in rhodecode/tests. + + +JavaScript Testing +------------------ +Currently, we have not defined how to test our JavaScript code. + + +-------------------------------------------------------------------------------- + +Pull Requests +============= + +Pull requests should generally contain only one thing: a single feature, one bug +fix, etc.. The commit history should be concise and clean, and the pull request +should contain the ticket number (also a good idea for the commits themselves) +to provide context for the reviewer. + +See also: :doc:`checklist-pull-request` + + +Reviewers +--------- +Each pull request must be approved by at least one member of the RhodeCode +team. Assignments may be based on expertise or familiarity with a particular +area of code, or simply availability. Switching up or adding extra community +members for different pull requests helps to share knowledge as well as provide +other perspectives. + + +Responsibility +-------------- +The community is responsible for maintaining features and this must be taken +into consideration. External contributions must be held to the same standards +as internal contributions. + + +Feature Switch +-------------- +Experimental and work-in-progress features can be hidden behind one of two +switches: + +* A setting can be added to the Labs page in the Admin section which may allow + customers to access and toggle additional features. +* For work-in-progress or other features where customer access is not desired, + use a custom setting in the .ini file as a trigger. + + +-------------------------------------------------------------------------------- + +Tickets +======= + +Redmine tickets are a crucial part of our development process. Any code added or +changed in our codebase should have a corresponding ticket to document it. With +this in mind, it is important that tickets be as clear and concise as possible, +including what the expected outcome is. + +See also: :doc:`checklist-tickets` diff --git a/docs/contributing/testing/index.rst b/docs/contributing/testing/index.rst --- a/docs/contributing/testing/index.rst +++ b/docs/contributing/testing/index.rst @@ -17,12 +17,12 @@ Overview ======== -We have a quite big test suite inside of :file:`rhodecode/tests` which is a mix +We have a quite large test suite inside of :file:`rhodecode/tests` which is a mix of unit tests and functional or integration tests. More details are in :ref:`test-unit-and-functional`. -Apart from that we start to apply "Specification by Example" and maintain a -collection of such specifications together with an implementation so that it can -be validated in an automatic way. The files can be found in +Apart from that, we are starting to apply "Specification by Example" and maintain +a collection of such specifications together with an implementation so that it +can be validated in an automatic way. The files can be found in :file:`acceptance_tests`. More details are in :ref:`test-spec-by-example`. diff --git a/docs/contributing/testing/spec-by-example.rst b/docs/contributing/testing/spec-by-example.rst --- a/docs/contributing/testing/spec-by-example.rst +++ b/docs/contributing/testing/spec-by-example.rst @@ -66,10 +66,10 @@ Locators -------- The specific information how to locate an element inside of the DOM tree of a -page is kept in a separate class. This class serves mainly as a data container, +page is kept in a separate class. This class serves mainly as a data container; it shall not contain any logic. The reason for keeping the locators separate is that we expect a frequent need -for change whenever we work on our templates. In such a case it is more -efficient to have all locators together and update them there instead of having -to find all locators inside of the logic of a page object. +for change whenever we work on our templates. In such a case, it is more +efficient to have all of thelocators together and update them there instead of +having to find every locator inside of the logic of a page object. diff --git a/docs/contributing/testing/unit-and-functional.rst b/docs/contributing/testing/unit-and-functional.rst --- a/docs/contributing/testing/unit-and-functional.rst +++ b/docs/contributing/testing/unit-and-functional.rst @@ -27,7 +27,7 @@ py.test integration The integration with the test runner is based on the following three parts: - `pytest_pylons` is a py.test plugin which does the integration with the - Pylons web framework. It sets up the Pylons environment based on a given ini + Pylons web framework. It sets up the Pylons environment based on the given ini file. Tests which depend on the Pylons environment to be set up must request the diff --git a/docs/release-notes/release-notes-4.2.0.rst b/docs/release-notes/release-notes-4.2.0.rst new file mode 100644 --- /dev/null +++ b/docs/release-notes/release-notes-4.2.0.rst @@ -0,0 +1,70 @@ +|RCE| 4.2.0 |RNS| +----------------- + +Release Date +^^^^^^^^^^^^ + +- 2016-06-30 + + +General +^^^^^^^ + +- Autocomplete: add GET flag support to show/hide active users on autocomplete, + also display this information in autocomplete data. ref #3374 +- Gravatar: add flag to show current gravatar + user as disabled user (non-active) +- Repos, repo groups, user groups: allow to use disabled users in owner field. + This fixes #3374. +- Repos, repo groups, user groups: visually show what user is an owner of a + resource, and if potentially he is disabled in the system. +- Pull requests: reorder navigation on repo pull requests, fixes #2995 +- Dependencies: bump dulwich to 0.13.0 + +New Features +^^^^^^^^^^^^ + +- My account: made pull requests aggregate view for users look like not + created in 1995. Now uses a consistent look with repo one. +- emails: expose profile link on registation email that super-admins receive. + Implements #3999. +- Social auth: move the buttons to the top of nav so they are easier to reach. + + +Security +^^^^^^^^ + +- Encryption: allow to pass in alternative key for encryption values. Now + users can use `rhodecode.encrypted_values.secret` that is alternative key, + de-coupled from `beaker.session` key. +- Encryption: Implement a slightly improved AesCipher encryption. + This addresses issues from #4036. +- Encryption: encrypted values now by default uses HMAC signatures to detect + if data or secret key is incorrect. The strict checks can be disabled using + `rhodecode.encrypted_values.strict = false` .ini setting + + +Performance +^^^^^^^^^^^ + +- Sql: use smarter JOINs when fetching repository information +- Helpers: optimize slight calls for link_to_user to save some intense queries. +- App settings: use computed caches for repository settings, this in some cases + brings almost 4x performance increase for large repos with a lot of issue + tracker patterns. + + +Fixes +^^^^^ + +- Fixed events on user pre/post create actions +- Authentication: fixed problem with saving forms with errors on auth plugins +- Svn: Avoid chunked transfer for Subversion that caused checkout issues in some cases. +- Users: fix generate new user password helper. +- Celery: fixed problem with workers running action in sync mode in some cases. +- Setup-db: fix redundant question on writable dir. The question needs to be + asked only when the dir is actually not writable. +- Elasticsearch: fixed issues when searching single repo using elastic search +- Social auth: fix issues with non-active users using social authentication + causing a 500 error. +- Fixed problem with largefiles extensions on per-repo settings using local + .hgrc files present inside the repo directory. 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.2.0.rst release-notes-4.1.2.rst release-notes-4.1.1.rst release-notes-4.1.0.rst diff --git a/license.nix b/license.nix --- a/license.nix +++ b/license.nix @@ -34,9 +34,6 @@ let # figure it out without calling into nix-store. enterprise = import ./default.nix { doCheck = false; - with_vcsserver = false; - with_pyramid = false; - cythonize = false; }; # For a given derivation, return the list of all dependencies 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 @@ -8,10 +8,28 @@ let sed = "sed -i"; + localLicenses = { + repoze = { + fullName = "Repoze License"; + url = http://www.repoze.org/LICENSE.txt; + }; + }; in self: super: { + appenlight-client = super.appenlight-client.override (attrs: { + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; + }); + + future = super.future.override (attrs: { + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; + }); + gnureadline = super.gnureadline.override (attrs: { buildInputs = attrs.buildInputs ++ [ pkgs.ncurses @@ -72,6 +90,9 @@ self: super: { propagatedBuildInputs = attrs.propagatedBuildInputs ++ [ pkgs.postgresql ]; + meta = { + license = pkgs.lib.licenses.lgpl3Plus; + }; }); pycurl = super.pycurl.override (attrs: { @@ -83,6 +104,10 @@ self: super: { substituteInPlace setup.py --replace '--static-libs' '--libs' export PYCURL_SSL_LIBRARY=openssl ''; + meta = { + # TODO: It is LGPL and MIT + license = pkgs.lib.licenses.mit; + }; }); Pylons = super.Pylons.override (attrs: { @@ -101,6 +126,15 @@ self: super: { # confuses pserve. ${sed} '/import sys; sys.argv/d' $out/bin/.pserve-wrapped ''; + meta = { + license = localLicenses.repoze; + }; + }); + + pyramid-debugtoolbar = super.pyramid-debugtoolbar.override (attrs: { + meta = { + license = [ pkgs.lib.licenses.bsdOriginal localLicenses.repoze ]; + }; }); Pyro4 = super.Pyro4.override (attrs: { @@ -117,6 +151,9 @@ self: super: { propagatedBuildInputs = [ pkgs.sqlite ]; + meta = { + license = [ pkgs.lib.licenses.zlib pkgs.lib.licenses.libpng ]; + }; }); pytest-runner = super.pytest-runner.override (attrs: { @@ -158,6 +195,77 @@ self: super: { ]; }); + URLObject = super.URLObject.override (attrs: { + meta = { + license = { + spdxId = "Unlicense"; + fullName = "The Unlicense"; + url = http://unlicense.org/; + }; + }; + }); + + amqplib = super.amqplib.override (attrs: { + meta = { + license = pkgs.lib.licenses.lgpl3; + }; + }); + + docutils = super.docutils.override (attrs: { + meta = { + license = pkgs.lib.licenses.bsd2; + }; + }); + + colander = super.colander.override (attrs: { + meta = { + license = localLicenses.repoze; + }; + }); + + pyramid-beaker = super.pyramid-beaker.override (attrs: { + meta = { + license = localLicenses.repoze; + }; + }); + + pyramid-mako = super.pyramid-mako.override (attrs: { + meta = { + license = localLicenses.repoze; + }; + }); + + repoze.lru = super.repoze.lru.override (attrs: { + meta = { + license = localLicenses.repoze; + }; + }); + + recaptcha-client = super.recaptcha-client.override (attrs: { + meta = { + # TODO: It is MIT/X11 + license = pkgs.lib.licenses.mit; + }; + }); + + python-editor = super.python-editor.override (attrs: { + meta = { + license = pkgs.lib.licenses.asl20; + }; + }); + + translationstring = super.translationstring.override (attrs: { + meta = { + license = localLicenses.repoze; + }; + }); + + venusian = super.venusian.override (attrs: { + meta = { + license = localLicenses.repoze; + }; + }); + # Avoid that setuptools is replaced, this leads to trouble # with buildPythonPackage. setuptools = basePythonPackages.setuptools; diff --git a/pkgs/python-packages.nix b/pkgs/python-packages.nix --- a/pkgs/python-packages.nix +++ b/pkgs/python-packages.nix @@ -8,6 +8,9 @@ url = "https://pypi.python.org/packages/33/27/e3978243a03a76398c384c83f7ca879bc6e8f1511233a621fcada135606e/Babel-1.3.tar.gz"; md5 = "5264ceb02717843cbc9ffce8e6e06bdb"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; Beaker = super.buildPythonPackage { name = "Beaker-1.7.0"; @@ -18,6 +21,9 @@ url = "https://pypi.python.org/packages/97/8e/409d2e7c009b8aa803dc9e6f239f1db7c3cdf578249087a404e7c27a505d/Beaker-1.7.0.tar.gz"; md5 = "386be3f7fe427358881eee4622b428b3"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; CProfileV = super.buildPythonPackage { name = "CProfileV-1.0.6"; @@ -28,6 +34,9 @@ url = "https://pypi.python.org/packages/eb/df/983a0b6cfd3ac94abf023f5011cb04f33613ace196e33f53c86cf91850d5/CProfileV-1.0.6.tar.gz"; md5 = "08c7c242b6e64237bc53c5d13537e03d"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; Fabric = super.buildPythonPackage { name = "Fabric-1.10.0"; @@ -38,6 +47,9 @@ url = "https://pypi.python.org/packages/e3/5f/b6ebdb5241d5ec9eab582a5c8a01255c1107da396f849e538801d2fe64a5/Fabric-1.10.0.tar.gz"; md5 = "2cb96473387f0e7aa035210892352f4a"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; FormEncode = super.buildPythonPackage { name = "FormEncode-1.2.4"; @@ -48,6 +60,9 @@ url = "https://pypi.python.org/packages/8e/59/0174271a6f004512e0201188593e6d319db139d14cb7490e488bbb078015/FormEncode-1.2.4.tar.gz"; md5 = "6bc17fb9aed8aea198975e888e2077f4"; }; + meta = { + license = [ pkgs.lib.licenses.psfl ]; + }; }; Jinja2 = super.buildPythonPackage { name = "Jinja2-2.7.3"; @@ -58,6 +73,9 @@ url = "https://pypi.python.org/packages/b0/73/eab0bca302d6d6a0b5c402f47ad1760dc9cb2dd14bbc1873ad48db258e4d/Jinja2-2.7.3.tar.gz"; md5 = "b9dffd2f3b43d673802fe857c8445b1a"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; Mako = super.buildPythonPackage { name = "Mako-1.0.1"; @@ -68,6 +86,9 @@ url = "https://pypi.python.org/packages/8e/a4/aa56533ecaa5f22ca92428f74e074d0c9337282933c722391902c8f9e0f8/Mako-1.0.1.tar.gz"; md5 = "9f0aafd177b039ef67b90ea350497a54"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; Markdown = super.buildPythonPackage { name = "Markdown-2.6.2"; @@ -78,6 +99,9 @@ url = "https://pypi.python.org/packages/62/8b/83658b5f6c220d5fcde9f9852d46ea54765d734cfbc5a9f4c05bfc36db4d/Markdown-2.6.2.tar.gz"; md5 = "256d19afcc564dc4ce4c229bb762f7ae"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; MarkupSafe = super.buildPythonPackage { name = "MarkupSafe-0.23"; @@ -88,6 +112,9 @@ url = "https://pypi.python.org/packages/c0/41/bae1254e0396c0cc8cf1751cb7d9afc90a602353695af5952530482c963f/MarkupSafe-0.23.tar.gz"; md5 = "f5ab3deee4c37cd6a922fb81e730da6e"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; MySQL-python = super.buildPythonPackage { name = "MySQL-python-1.2.5"; @@ -98,6 +125,9 @@ url = "https://pypi.python.org/packages/a5/e9/51b544da85a36a68debe7a7091f068d802fc515a3a202652828c73453cad/MySQL-python-1.2.5.zip"; md5 = "654f75b302db6ed8dc5a898c625e030c"; }; + meta = { + license = [ pkgs.lib.licenses.gpl1 ]; + }; }; Paste = super.buildPythonPackage { name = "Paste-2.0.2"; @@ -108,6 +138,9 @@ url = "https://pypi.python.org/packages/d5/8d/0f8ac40687b97ff3e07ebd1369be20bdb3f93864d2dc3c2ff542edb4ce50/Paste-2.0.2.tar.gz"; md5 = "4bfc8a7eaf858f6309d2ac0f40fc951c"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; PasteDeploy = super.buildPythonPackage { name = "PasteDeploy-1.5.2"; @@ -118,6 +151,9 @@ url = "https://pypi.python.org/packages/0f/90/8e20cdae206c543ea10793cbf4136eb9a8b3f417e04e40a29d72d9922cbd/PasteDeploy-1.5.2.tar.gz"; md5 = "352b7205c78c8de4987578d19431af3b"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; PasteScript = super.buildPythonPackage { name = "PasteScript-1.7.5"; @@ -128,6 +164,9 @@ url = "https://pypi.python.org/packages/a5/05/fc60efa7c2f17a1dbaeccb2a903a1e90902d92b9d00eebabe3095829d806/PasteScript-1.7.5.tar.gz"; md5 = "4c72d78dcb6bb993f30536842c16af4d"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; Pygments = super.buildPythonPackage { name = "Pygments-2.0.2"; @@ -138,6 +177,9 @@ url = "https://pypi.python.org/packages/f4/c6/bdbc5a8a112256b2b6136af304dbae93d8b1ef8738ff2d12a51018800e46/Pygments-2.0.2.tar.gz"; md5 = "238587a1370d62405edabd0794b3ec4a"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; Pylons = super.buildPythonPackage { name = "Pylons-1.0.1"; @@ -148,6 +190,9 @@ url = "https://pypi.python.org/packages/a2/69/b835a6bad00acbfeed3f33c6e44fa3f936efc998c795bfb15c61a79ecf62/Pylons-1.0.1.tar.gz"; md5 = "6cb880d75fa81213192142b07a6e4915"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; Pyro4 = super.buildPythonPackage { name = "Pyro4-4.41"; @@ -158,6 +203,9 @@ url = "https://pypi.python.org/packages/56/2b/89b566b4bf3e7f8ba790db2d1223852f8cb454c52cab7693dd41f608ca2a/Pyro4-4.41.tar.gz"; md5 = "ed69e9bfafa9c06c049a87cb0c4c2b6c"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; Routes = super.buildPythonPackage { name = "Routes-1.13"; @@ -168,6 +216,9 @@ url = "https://pypi.python.org/packages/88/d3/259c3b3cde8837eb9441ab5f574a660e8a4acea8f54a078441d4d2acac1c/Routes-1.13.tar.gz"; md5 = "d527b0ab7dd9172b1275a41f97448783"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; SQLAlchemy = super.buildPythonPackage { name = "SQLAlchemy-0.9.9"; @@ -178,6 +229,9 @@ url = "https://pypi.python.org/packages/28/f7/1bbfd0d8597e8c358d5e15a166a486ad82fc5579b4e67b6ef7c05b1d182b/SQLAlchemy-0.9.9.tar.gz"; md5 = "8a10a9bd13ed3336ef7333ac2cc679ff"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; Sphinx = super.buildPythonPackage { name = "Sphinx-1.2.2"; @@ -188,6 +242,9 @@ url = "https://pypi.python.org/packages/0a/50/34017e6efcd372893a416aba14b84a1a149fc7074537b0e9cb6ca7b7abe9/Sphinx-1.2.2.tar.gz"; md5 = "3dc73ccaa8d0bfb2d62fb671b1f7e8a4"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; Tempita = super.buildPythonPackage { name = "Tempita-0.5.2"; @@ -198,6 +255,9 @@ url = "https://pypi.python.org/packages/56/c8/8ed6eee83dbddf7b0fc64dd5d4454bc05e6ccaafff47991f73f2894d9ff4/Tempita-0.5.2.tar.gz"; md5 = "4c2f17bb9d481821c41b6fbee904cea1"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; URLObject = super.buildPythonPackage { name = "URLObject-2.4.0"; @@ -208,6 +268,9 @@ url = "https://pypi.python.org/packages/cb/b6/e25e58500f9caef85d664bec71ec67c116897bfebf8622c32cb75d1ca199/URLObject-2.4.0.tar.gz"; md5 = "2ed819738a9f0a3051f31dc9924e3065"; }; + meta = { + license = [ ]; + }; }; WebError = super.buildPythonPackage { name = "WebError-0.10.3"; @@ -218,6 +281,9 @@ url = "https://pypi.python.org/packages/35/76/e7e5c2ce7e9c7f31b54c1ff295a495886d1279a002557d74dd8957346a79/WebError-0.10.3.tar.gz"; md5 = "84b9990b0baae6fd440b1e60cdd06f9a"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; WebHelpers = super.buildPythonPackage { name = "WebHelpers-1.3"; @@ -228,6 +294,9 @@ url = "https://pypi.python.org/packages/ee/68/4d07672821d514184357f1552f2dad923324f597e722de3b016ca4f7844f/WebHelpers-1.3.tar.gz"; md5 = "32749ffadfc40fea51075a7def32588b"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; WebHelpers2 = super.buildPythonPackage { name = "WebHelpers2-2.0"; @@ -238,6 +307,9 @@ url = "https://pypi.python.org/packages/ff/30/56342c6ea522439e3662427c8d7b5e5b390dff4ff2dc92d8afcb8ab68b75/WebHelpers2-2.0.tar.gz"; md5 = "0f6b68d70c12ee0aed48c00b24da13d3"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; WebOb = super.buildPythonPackage { name = "WebOb-1.3.1"; @@ -248,6 +320,9 @@ url = "https://pypi.python.org/packages/16/78/adfc0380b8a0d75b2d543fa7085ba98a573b1ae486d9def88d172b81b9fa/WebOb-1.3.1.tar.gz"; md5 = "20918251c5726956ba8fef22d1556177"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; WebTest = super.buildPythonPackage { name = "WebTest-1.4.3"; @@ -258,6 +333,9 @@ url = "https://pypi.python.org/packages/51/3d/84fd0f628df10b30c7db87895f56d0158e5411206b721ca903cb51bfd948/WebTest-1.4.3.zip"; md5 = "631ce728bed92c681a4020a36adbc353"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; Whoosh = super.buildPythonPackage { name = "Whoosh-2.7.0"; @@ -268,6 +346,9 @@ url = "https://pypi.python.org/packages/1c/dc/2f0231ff3875ded36df8c1ab851451e51a237dc0e5a86d3d96036158da94/Whoosh-2.7.0.zip"; md5 = "7abfd970f16fadc7311960f3fa0bc7a9"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.bsd2 ]; + }; }; alembic = super.buildPythonPackage { name = "alembic-0.8.4"; @@ -278,6 +359,9 @@ url = "https://pypi.python.org/packages/ca/7e/299b4499b5c75e5a38c5845145ad24755bebfb8eec07a2e1c366b7181eeb/alembic-0.8.4.tar.gz"; md5 = "5f95d8ee62b443f9b37eb5bee76c582d"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; amqplib = super.buildPythonPackage { name = "amqplib-1.0.2"; @@ -288,6 +372,9 @@ url = "https://pypi.python.org/packages/75/b7/8c2429bf8d92354a0118614f9a4d15e53bc69ebedce534284111de5a0102/amqplib-1.0.2.tgz"; md5 = "5c92f17fbedd99b2b4a836d4352d1e2f"; }; + meta = { + license = [ { fullName = "LGPL"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ]; + }; }; anyjson = super.buildPythonPackage { name = "anyjson-0.3.3"; @@ -298,6 +385,9 @@ url = "https://pypi.python.org/packages/c3/4d/d4089e1a3dd25b46bebdb55a992b0797cff657b4477bc32ce28038fdecbc/anyjson-0.3.3.tar.gz"; md5 = "2ea28d6ec311aeeebaf993cb3008b27c"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; appenlight-client = super.buildPythonPackage { name = "appenlight-client-0.6.14"; @@ -308,6 +398,9 @@ url = "https://pypi.python.org/packages/4d/e0/23fee3ebada8143f707e65c06bcb82992040ee64ea8355e044ed55ebf0c1/appenlight_client-0.6.14.tar.gz"; md5 = "578c69b09f4356d898fff1199b98a95c"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal { fullName = "DFSG approved"; } ]; + }; }; authomatic = super.buildPythonPackage { name = "authomatic-0.1.0.post1"; @@ -318,6 +411,9 @@ url = "https://pypi.python.org/packages/08/1a/8a930461e604c2d5a7a871e1ac59fa82ccf994c32e807230c8d2fb07815a/Authomatic-0.1.0.post1.tar.gz"; md5 = "be3f3ce08747d776aae6d6cc8dcb49a9"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; backport-ipaddress = super.buildPythonPackage { name = "backport-ipaddress-0.1"; @@ -328,6 +424,9 @@ url = "https://pypi.python.org/packages/d3/30/54c6dab05a4dec44db25ff309f1fbb6b7a8bde3f2bade38bb9da67bbab8f/backport_ipaddress-0.1.tar.gz"; md5 = "9c1f45f4361f71b124d7293a60006c05"; }; + meta = { + license = [ pkgs.lib.licenses.psfl ]; + }; }; bottle = super.buildPythonPackage { name = "bottle-0.12.8"; @@ -338,6 +437,9 @@ url = "https://pypi.python.org/packages/52/df/e4a408f3a7af396d186d4ecd3b389dd764f0f943b4fa8d257bfe7b49d343/bottle-0.12.8.tar.gz"; md5 = "13132c0a8f607bf860810a6ee9064c5b"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; bumpversion = super.buildPythonPackage { name = "bumpversion-0.5.3"; @@ -348,6 +450,9 @@ url = "https://pypi.python.org/packages/14/41/8c9da3549f8e00c84f0432c3a8cf8ed6898374714676aab91501d48760db/bumpversion-0.5.3.tar.gz"; md5 = "c66a3492eafcf5ad4b024be9fca29820"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; celery = super.buildPythonPackage { name = "celery-2.2.10"; @@ -358,6 +463,9 @@ url = "https://pypi.python.org/packages/b1/64/860fd50e45844c83442e7953effcddeff66b2851d90b2d784f7201c111b8/celery-2.2.10.tar.gz"; md5 = "898bc87e54f278055b561316ba73e222"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; click = super.buildPythonPackage { name = "click-5.1"; @@ -368,6 +476,9 @@ url = "https://pypi.python.org/packages/b7/34/a496632c4fb6c1ee76efedf77bb8d28b29363d839953d95095b12defe791/click-5.1.tar.gz"; md5 = "9c5323008cccfe232a8b161fc8196d41"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; colander = super.buildPythonPackage { name = "colander-1.2"; @@ -378,6 +489,9 @@ url = "https://pypi.python.org/packages/14/23/c9ceba07a6a1dc0eefbb215fc0dc64aabc2b22ee756bc0f0c13278fa0887/colander-1.2.tar.gz"; md5 = "83db21b07936a0726e588dae1914b9ed"; }; + meta = { + license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ]; + }; }; configobj = super.buildPythonPackage { name = "configobj-5.0.6"; @@ -388,6 +502,9 @@ url = "https://pypi.python.org/packages/64/61/079eb60459c44929e684fa7d9e2fdca403f67d64dd9dbac27296be2e0fab/configobj-5.0.6.tar.gz"; md5 = "e472a3a1c2a67bb0ec9b5d54c13a47d6"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; cov-core = super.buildPythonPackage { name = "cov-core-1.15.0"; @@ -398,6 +515,9 @@ url = "https://pypi.python.org/packages/4b/87/13e75a47b4ba1be06f29f6d807ca99638bedc6b57fa491cd3de891ca2923/cov-core-1.15.0.tar.gz"; md5 = "f519d4cb4c4e52856afb14af52919fe6"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; coverage = super.buildPythonPackage { name = "coverage-3.7.1"; @@ -408,6 +528,9 @@ url = "https://pypi.python.org/packages/09/4f/89b06c7fdc09687bca507dc411c342556ef9c5a3b26756137a4878ff19bf/coverage-3.7.1.tar.gz"; md5 = "c47b36ceb17eaff3ecfab3bcd347d0df"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; cssselect = super.buildPythonPackage { name = "cssselect-0.9.1"; @@ -418,6 +541,9 @@ url = "https://pypi.python.org/packages/aa/e5/9ee1460d485b94a6d55732eb7ad5b6c084caf73dd6f9cb0bb7d2a78fafe8/cssselect-0.9.1.tar.gz"; md5 = "c74f45966277dc7a0f768b9b0f3522ac"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; decorator = super.buildPythonPackage { name = "decorator-3.4.2"; @@ -428,6 +554,9 @@ url = "https://pypi.python.org/packages/35/3a/42566eb7a2cbac774399871af04e11d7ae3fc2579e7dae85213b8d1d1c57/decorator-3.4.2.tar.gz"; md5 = "9e0536870d2b83ae27d58dbf22582f4d"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; docutils = super.buildPythonPackage { name = "docutils-0.12"; @@ -438,6 +567,9 @@ url = "https://pypi.python.org/packages/37/38/ceda70135b9144d84884ae2fc5886c6baac4edea39550f28bcd144c1234d/docutils-0.12.tar.gz"; md5 = "4622263b62c5c771c03502afa3157768"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.publicDomain pkgs.lib.licenses.gpl1 { fullName = "public domain, Python, 2-Clause BSD, GPL 3 (see COPYING.txt)"; } pkgs.lib.licenses.psfl ]; + }; }; dogpile.cache = super.buildPythonPackage { name = "dogpile.cache-0.5.7"; @@ -448,6 +580,9 @@ url = "https://pypi.python.org/packages/07/74/2a83bedf758156d9c95d112691bbad870d3b77ccbcfb781b4ef836ea7d96/dogpile.cache-0.5.7.tar.gz"; md5 = "3e58ce41af574aab41d78e9c4190f194"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; dogpile.core = super.buildPythonPackage { name = "dogpile.core-0.4.1"; @@ -458,6 +593,9 @@ url = "https://pypi.python.org/packages/0e/77/e72abc04c22aedf874301861e5c1e761231c288b5de369c18be8f4b5c9bb/dogpile.core-0.4.1.tar.gz"; md5 = "01cb19f52bba3e95c9b560f39341f045"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; dulwich = super.buildPythonPackage { name = "dulwich-0.12.0"; @@ -468,6 +606,9 @@ url = "https://pypi.python.org/packages/6f/04/fbe561b6d45c0ec758330d5b7f5ba4b6cb4f1ca1ab49859d2fc16320da75/dulwich-0.12.0.tar.gz"; md5 = "f3a8a12bd9f9dd8c233e18f3d49436fa"; }; + meta = { + license = [ pkgs.lib.licenses.gpl2Plus ]; + }; }; ecdsa = super.buildPythonPackage { name = "ecdsa-0.11"; @@ -478,6 +619,9 @@ url = "https://pypi.python.org/packages/6c/3f/92fe5dcdcaa7bd117be21e5520c9a54375112b66ec000d209e9e9519fad1/ecdsa-0.11.tar.gz"; md5 = "8ef586fe4dbb156697d756900cb41d7c"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; elasticsearch = super.buildPythonPackage { name = "elasticsearch-2.3.0"; @@ -488,6 +632,9 @@ url = "https://pypi.python.org/packages/10/35/5fd52c5f0b0ee405ed4b5195e8bce44c5e041787680dc7b94b8071cac600/elasticsearch-2.3.0.tar.gz"; md5 = "2550f3b51629cf1ef9636608af92c340"; }; + meta = { + license = [ pkgs.lib.licenses.asl20 ]; + }; }; elasticsearch-dsl = super.buildPythonPackage { name = "elasticsearch-dsl-2.0.0"; @@ -498,6 +645,9 @@ url = "https://pypi.python.org/packages/4e/5d/e788ae8dbe2ff4d13426db0a027533386a5c276c77a2654dc0e2007ce04a/elasticsearch-dsl-2.0.0.tar.gz"; md5 = "4cdfec81bb35383dd3b7d02d7dc5ee68"; }; + meta = { + license = [ pkgs.lib.licenses.asl20 ]; + }; }; flake8 = super.buildPythonPackage { name = "flake8-2.4.1"; @@ -508,6 +658,9 @@ url = "https://pypi.python.org/packages/8f/b5/9a73c66c7dba273bac8758398f060c008a25f3e84531063b42503b5d0a95/flake8-2.4.1.tar.gz"; md5 = "ed45d3db81a3b7c88bd63c6e37ca1d65"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; future = super.buildPythonPackage { name = "future-0.14.3"; @@ -518,6 +671,9 @@ url = "https://pypi.python.org/packages/83/80/8ef3a11a15f8eaafafa0937b20c1b3f73527e69ab6b3fa1cf94a5a96aabb/future-0.14.3.tar.gz"; md5 = "e94079b0bd1fc054929e8769fc0f6083"; }; + meta = { + license = [ { fullName = "OSI Approved"; } pkgs.lib.licenses.mit ]; + }; }; futures = super.buildPythonPackage { name = "futures-3.0.2"; @@ -528,6 +684,9 @@ url = "https://pypi.python.org/packages/f8/e7/fc0fcbeb9193ba2d4de00b065e7fd5aecd0679e93ce95a07322b2b1434f4/futures-3.0.2.tar.gz"; md5 = "42aaf1e4de48d6e871d77dc1f9d96d5a"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; gnureadline = super.buildPythonPackage { name = "gnureadline-6.3.3"; @@ -538,9 +697,12 @@ url = "https://pypi.python.org/packages/3a/ee/2c3f568b0a74974791ac590ec742ef6133e2fbd287a074ba72a53fa5e97c/gnureadline-6.3.3.tar.gz"; md5 = "c4af83c9a3fbeac8f2da9b5a7c60e51c"; }; + meta = { + license = [ pkgs.lib.licenses.gpl1 ]; + }; }; gprof2dot = super.buildPythonPackage { - name = "gprof2dot-2015.12.01"; + name = "gprof2dot-2015.12.1"; buildInputs = with self; []; doCheck = false; propagatedBuildInputs = with self; []; @@ -548,6 +710,9 @@ url = "https://pypi.python.org/packages/b9/34/7bf93c1952d40fa5c95ad963f4d8344b61ef58558632402eca18e6c14127/gprof2dot-2015.12.1.tar.gz"; md5 = "e23bf4e2f94db032750c193384b4165b"; }; + meta = { + license = [ { fullName = "LGPL"; } ]; + }; }; greenlet = super.buildPythonPackage { name = "greenlet-0.4.9"; @@ -558,6 +723,9 @@ url = "https://pypi.python.org/packages/4e/3d/9d421539b74e33608b245092870156b2e171fb49f2b51390aa4641eecb4a/greenlet-0.4.9.zip"; md5 = "c6659cdb2a5e591723e629d2eef22e82"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; gunicorn = super.buildPythonPackage { name = "gunicorn-19.6.0"; @@ -568,6 +736,9 @@ url = "https://pypi.python.org/packages/84/ce/7ea5396efad1cef682bbc4068e72a0276341d9d9d0f501da609fab9fcb80/gunicorn-19.6.0.tar.gz"; md5 = "338e5e8a83ea0f0625f768dba4597530"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; infrae.cache = super.buildPythonPackage { name = "infrae.cache-1.0.1"; @@ -578,15 +749,21 @@ url = "https://pypi.python.org/packages/bb/f0/e7d5e984cf6592fd2807dc7bc44a93f9d18e04e6a61f87fdfb2622422d74/infrae.cache-1.0.1.tar.gz"; md5 = "b09076a766747e6ed2a755cc62088e32"; }; + meta = { + license = [ pkgs.lib.licenses.zpt21 ]; + }; }; invoke = super.buildPythonPackage { - name = "invoke-0.11.1"; + name = "invoke-0.13.0"; buildInputs = with self; []; doCheck = false; propagatedBuildInputs = with self; []; src = fetchurl { - url = "https://pypi.python.org/packages/d3/bb/36a5558ea19882073def7b0edeef4a0e6282056fed96506dd10b1d532bd4/invoke-0.11.1.tar.gz"; - md5 = "3d4ecbe26779ceef1046ecf702c9c4a8"; + url = "https://pypi.python.org/packages/47/bf/d07ef52fa1ac645468858bbac7cb95b246a972a045e821493d17d89c81be/invoke-0.13.0.tar.gz"; + md5 = "c0d1ed4bfb34eaab551662d8cfee6540"; + }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; }; }; ipdb = super.buildPythonPackage { @@ -598,6 +775,9 @@ url = "https://pypi.python.org/packages/f0/25/d7dd430ced6cd8dc242a933c8682b5dbf32eb4011d82f87e34209e5ec845/ipdb-0.8.zip"; md5 = "96dca0712efa01aa5eaf6b22071dd3ed"; }; + meta = { + license = [ pkgs.lib.licenses.gpl1 ]; + }; }; ipython = super.buildPythonPackage { name = "ipython-3.1.0"; @@ -608,6 +788,9 @@ url = "https://pypi.python.org/packages/06/91/120c0835254c120af89f066afaabf81289bc2726c1fc3ca0555df6882f58/ipython-3.1.0.tar.gz"; md5 = "a749d90c16068687b0ec45a27e72ef8f"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; iso8601 = super.buildPythonPackage { name = "iso8601-0.1.11"; @@ -618,6 +801,9 @@ url = "https://pypi.python.org/packages/c0/75/c9209ee4d1b5975eb8c2cba4428bde6b61bd55664a98290dd015cdb18e98/iso8601-0.1.11.tar.gz"; md5 = "b06d11cd14a64096f907086044f0fe38"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; itsdangerous = super.buildPythonPackage { name = "itsdangerous-0.24"; @@ -628,6 +814,9 @@ url = "https://pypi.python.org/packages/dc/b4/a60bcdba945c00f6d608d8975131ab3f25b22f2bcfe1dab221165194b2d4/itsdangerous-0.24.tar.gz"; md5 = "a3d55aa79369aef5345c036a8a26307f"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; kombu = super.buildPythonPackage { name = "kombu-1.5.1"; @@ -638,6 +827,9 @@ url = "https://pypi.python.org/packages/19/53/74bf2a624644b45f0850a638752514fc10a8e1cbd738f10804951a6df3f5/kombu-1.5.1.tar.gz"; md5 = "50662f3c7e9395b3d0721fb75d100b63"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; lxml = super.buildPythonPackage { name = "lxml-3.4.4"; @@ -648,6 +840,9 @@ url = "https://pypi.python.org/packages/63/c7/4f2a2a4ad6c6fa99b14be6b3c1cece9142e2d915aa7c43c908677afc8fa4/lxml-3.4.4.tar.gz"; md5 = "a9a65972afc173ec7a39c585f4eea69c"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; mccabe = super.buildPythonPackage { name = "mccabe-0.3"; @@ -658,6 +853,9 @@ url = "https://pypi.python.org/packages/c9/2e/75231479e11a906b64ac43bad9d0bb534d00080b18bdca8db9da46e1faf7/mccabe-0.3.tar.gz"; md5 = "81640948ff226f8c12b3277059489157"; }; + meta = { + license = [ { fullName = "Expat license"; } pkgs.lib.licenses.mit ]; + }; }; meld3 = super.buildPythonPackage { name = "meld3-1.0.2"; @@ -668,6 +866,9 @@ url = "https://pypi.python.org/packages/45/a0/317c6422b26c12fe0161e936fc35f36552069ba8e6f7ecbd99bbffe32a5f/meld3-1.0.2.tar.gz"; md5 = "3ccc78cd79cffd63a751ad7684c02c91"; }; + meta = { + license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ]; + }; }; mock = super.buildPythonPackage { name = "mock-1.0.1"; @@ -678,6 +879,9 @@ url = "https://pypi.python.org/packages/15/45/30273ee91feb60dabb8fbb2da7868520525f02cf910279b3047182feed80/mock-1.0.1.zip"; md5 = "869f08d003c289a97c1a6610faf5e913"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; msgpack-python = super.buildPythonPackage { name = "msgpack-python-0.4.6"; @@ -688,6 +892,9 @@ url = "https://pypi.python.org/packages/15/ce/ff2840885789ef8035f66cd506ea05bdb228340307d5e71a7b1e3f82224c/msgpack-python-0.4.6.tar.gz"; md5 = "8b317669314cf1bc881716cccdaccb30"; }; + meta = { + license = [ pkgs.lib.licenses.asl20 ]; + }; }; nose = super.buildPythonPackage { name = "nose-1.3.6"; @@ -698,6 +905,9 @@ url = "https://pypi.python.org/packages/70/c7/469e68148d17a0d3db5ed49150242fd70a74a8147b8f3f8b87776e028d99/nose-1.3.6.tar.gz"; md5 = "0ca546d81ca8309080fc80cb389e7a16"; }; + meta = { + license = [ { fullName = "GNU Library or Lesser General Public License (LGPL)"; } { fullName = "GNU LGPL"; } ]; + }; }; objgraph = super.buildPythonPackage { name = "objgraph-2.0.0"; @@ -708,6 +918,9 @@ url = "https://pypi.python.org/packages/d7/33/ace750b59247496ed769b170586c5def7202683f3d98e737b75b767ff29e/objgraph-2.0.0.tar.gz"; md5 = "25b0d5e5adc74aa63ead15699614159c"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; packaging = super.buildPythonPackage { name = "packaging-15.2"; @@ -718,6 +931,9 @@ url = "https://pypi.python.org/packages/24/c4/185da1304f07047dc9e0c46c31db75c0351bd73458ac3efad7da3dbcfbe1/packaging-15.2.tar.gz"; md5 = "c16093476f6ced42128bf610e5db3784"; }; + meta = { + license = [ pkgs.lib.licenses.asl20 ]; + }; }; paramiko = super.buildPythonPackage { name = "paramiko-1.15.1"; @@ -728,6 +944,9 @@ url = "https://pypi.python.org/packages/04/2b/a22d2a560c1951abbbf95a0628e245945565f70dc082d9e784666887222c/paramiko-1.15.1.tar.gz"; md5 = "48c274c3f9b1282932567b21f6acf3b5"; }; + meta = { + license = [ { fullName = "LGPL"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ]; + }; }; pep8 = super.buildPythonPackage { name = "pep8-1.5.7"; @@ -738,6 +957,9 @@ url = "https://pypi.python.org/packages/8b/de/259f5e735897ada1683489dd514b2a1c91aaa74e5e6b68f80acf128a6368/pep8-1.5.7.tar.gz"; md5 = "f6adbdd69365ecca20513c709f9b7c93"; }; + meta = { + license = [ { fullName = "Expat license"; } pkgs.lib.licenses.mit ]; + }; }; psutil = super.buildPythonPackage { name = "psutil-2.2.1"; @@ -748,6 +970,9 @@ url = "https://pypi.python.org/packages/df/47/ee54ef14dd40f8ce831a7581001a5096494dc99fe71586260ca6b531fe86/psutil-2.2.1.tar.gz"; md5 = "1a2b58cd9e3a53528bb6148f0c4d5244"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; psycopg2 = super.buildPythonPackage { name = "psycopg2-2.6"; @@ -758,6 +983,9 @@ url = "https://pypi.python.org/packages/dd/c7/9016ff8ff69da269b1848276eebfb264af5badf6b38caad805426771f04d/psycopg2-2.6.tar.gz"; md5 = "fbbb039a8765d561a1c04969bbae7c74"; }; + meta = { + license = [ pkgs.lib.licenses.zpt21 { fullName = "GNU Library or Lesser General Public License (LGPL)"; } { fullName = "LGPL with exceptions or ZPL"; } ]; + }; }; py = super.buildPythonPackage { name = "py-1.4.29"; @@ -768,6 +996,9 @@ url = "https://pypi.python.org/packages/2a/bc/a1a4a332ac10069b8e5e25136a35e08a03f01fd6ab03d819889d79a1fd65/py-1.4.29.tar.gz"; md5 = "c28e0accba523a29b35a48bb703fb96c"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; py-bcrypt = super.buildPythonPackage { name = "py-bcrypt-0.4"; @@ -778,6 +1009,9 @@ url = "https://pypi.python.org/packages/68/b1/1c3068c5c4d2e35c48b38dcc865301ebfdf45f54507086ac65ced1fd3b3d/py-bcrypt-0.4.tar.gz"; md5 = "dd8b367d6b716a2ea2e72392525f4e36"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; pycrypto = super.buildPythonPackage { name = "pycrypto-2.6.1"; @@ -788,6 +1022,9 @@ url = "https://pypi.python.org/packages/60/db/645aa9af249f059cc3a368b118de33889219e0362141e75d4eaf6f80f163/pycrypto-2.6.1.tar.gz"; md5 = "55a61a054aa66812daf5161a0d5d7eda"; }; + meta = { + license = [ pkgs.lib.licenses.publicDomain ]; + }; }; pycurl = super.buildPythonPackage { name = "pycurl-7.19.5"; @@ -798,6 +1035,9 @@ url = "https://pypi.python.org/packages/6c/48/13bad289ef6f4869b1d8fc11ae54de8cfb3cc4a2eb9f7419c506f763be46/pycurl-7.19.5.tar.gz"; md5 = "47b4eac84118e2606658122104e62072"; }; + meta = { + 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"; @@ -808,6 +1048,9 @@ url = "https://pypi.python.org/packages/75/22/a90ec0252f4f87f3ffb6336504de71fe16a49d69c4538dae2f12b9360a38/pyflakes-0.8.1.tar.gz"; md5 = "905fe91ad14b912807e8fdc2ac2e2c23"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; pyparsing = super.buildPythonPackage { name = "pyparsing-1.5.7"; @@ -818,6 +1061,9 @@ url = "https://pypi.python.org/packages/2e/26/e8fb5b4256a5f5036be7ce115ef8db8d06bc537becfbdc46c6af008314ee/pyparsing-1.5.7.zip"; md5 = "b86854857a368d6ccb4d5b6e76d0637f"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; pyramid = super.buildPythonPackage { name = "pyramid-1.6.1"; @@ -828,6 +1074,9 @@ url = "https://pypi.python.org/packages/30/b3/fcc4a2a4800cbf21989e00454b5828cf1f7fe35c63e0810b350e56d4c475/pyramid-1.6.1.tar.gz"; md5 = "b18688ff3cc33efdbb098a35b45dd122"; }; + meta = { + license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ]; + }; }; pyramid-beaker = super.buildPythonPackage { name = "pyramid-beaker-0.8"; @@ -838,6 +1087,9 @@ url = "https://pypi.python.org/packages/d9/6e/b85426e00fd3d57f4545f74e1c3828552d8700f13ededeef9233f7bca8be/pyramid_beaker-0.8.tar.gz"; md5 = "22f14be31b06549f80890e2c63a93834"; }; + meta = { + license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ]; + }; }; pyramid-debugtoolbar = super.buildPythonPackage { name = "pyramid-debugtoolbar-2.4.2"; @@ -848,6 +1100,9 @@ url = "https://pypi.python.org/packages/89/00/ed5426ee41ed747ba3ffd30e8230841a6878286ea67d480b1444d24f06a2/pyramid_debugtoolbar-2.4.2.tar.gz"; md5 = "073ea67086cc4bd5decc3a000853642d"; }; + meta = { + license = [ { fullName = "Repoze Public License"; } pkgs.lib.licenses.bsdOriginal ]; + }; }; pyramid-jinja2 = super.buildPythonPackage { name = "pyramid-jinja2-2.5"; @@ -858,6 +1113,9 @@ url = "https://pypi.python.org/packages/a1/80/595e26ffab7deba7208676b6936b7e5a721875710f982e59899013cae1ed/pyramid_jinja2-2.5.tar.gz"; md5 = "07cb6547204ac5e6f0b22a954ccee928"; }; + meta = { + license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ]; + }; }; pyramid-mako = super.buildPythonPackage { name = "pyramid-mako-1.0.2"; @@ -868,6 +1126,9 @@ url = "https://pypi.python.org/packages/f1/92/7e69bcf09676d286a71cb3bbb887b16595b96f9ba7adbdc239ffdd4b1eb9/pyramid_mako-1.0.2.tar.gz"; md5 = "ee25343a97eb76bd90abdc2a774eb48a"; }; + meta = { + license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ]; + }; }; pysqlite = super.buildPythonPackage { name = "pysqlite-2.6.3"; @@ -878,6 +1139,9 @@ url = "https://pypi.python.org/packages/5c/a6/1c429cd4c8069cf4bfbd0eb4d592b3f4042155a8202df83d7e9b93aa3dc2/pysqlite-2.6.3.tar.gz"; md5 = "7ff1cedee74646b50117acff87aa1cfa"; }; + meta = { + license = [ { fullName = "zlib/libpng License"; } { fullName = "zlib/libpng license"; } ]; + }; }; pytest = super.buildPythonPackage { name = "pytest-2.8.5"; @@ -888,6 +1152,9 @@ url = "https://pypi.python.org/packages/b1/3d/d7ea9b0c51e0cacded856e49859f0a13452747491e842c236bbab3714afe/pytest-2.8.5.zip"; md5 = "8493b06f700862f1294298d6c1b715a9"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; pytest-catchlog = super.buildPythonPackage { name = "pytest-catchlog-1.2.2"; @@ -898,6 +1165,9 @@ url = "https://pypi.python.org/packages/f2/2b/2faccdb1a978fab9dd0bf31cca9f6847fbe9184a0bdcc3011ac41dd44191/pytest-catchlog-1.2.2.zip"; md5 = "09d890c54c7456c818102b7ff8c182c8"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; pytest-cov = super.buildPythonPackage { name = "pytest-cov-1.8.1"; @@ -908,6 +1178,9 @@ url = "https://pypi.python.org/packages/11/4b/b04646e97f1721878eb21e9f779102d84dd044d324382263b1770a3e4838/pytest-cov-1.8.1.tar.gz"; md5 = "76c778afa2494088270348be42d759fc"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; pytest-profiling = super.buildPythonPackage { name = "pytest-profiling-1.0.1"; @@ -918,6 +1191,9 @@ url = "https://pypi.python.org/packages/d8/67/8ffab73406e22870e07fa4dc8dce1d7689b26dba8efd00161c9b6fc01ec0/pytest-profiling-1.0.1.tar.gz"; md5 = "354404eb5b3fd4dc5eb7fffbb3d9b68b"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; pytest-runner = super.buildPythonPackage { name = "pytest-runner-2.7.1"; @@ -928,6 +1204,9 @@ url = "https://pypi.python.org/packages/99/6b/c4ff4418d3424d4475b7af60724fd4a5cdd91ed8e489dc9443281f0052bc/pytest-runner-2.7.1.tar.gz"; md5 = "e56f0bc8d79a6bd91772b44ef4215c7e"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; pytest-timeout = super.buildPythonPackage { name = "pytest-timeout-0.4"; @@ -938,6 +1217,9 @@ url = "https://pypi.python.org/packages/24/48/5f6bd4b8026a26e1dd427243d560a29a0f1b24a5c7cffca4bf049a7bb65b/pytest-timeout-0.4.tar.gz"; md5 = "03b28aff69cbbfb959ed35ade5fde262"; }; + meta = { + license = [ pkgs.lib.licenses.mit { fullName = "DFSG approved"; } ]; + }; }; python-dateutil = super.buildPythonPackage { name = "python-dateutil-1.5"; @@ -948,6 +1230,9 @@ url = "https://pypi.python.org/packages/b4/7c/df59c89a753eb33c7c44e1dd42de0e9bc2ccdd5a4d576e0bfad97cc280cb/python-dateutil-1.5.tar.gz"; md5 = "0dcb1de5e5cad69490a3b6ab63f0cfa5"; }; + meta = { + license = [ pkgs.lib.licenses.psfl ]; + }; }; python-editor = super.buildPythonPackage { name = "python-editor-1.0.1"; @@ -958,6 +1243,9 @@ url = "https://pypi.python.org/packages/2b/c0/df7b87d5cf016f82eab3b05cd35f53287c1178ad8c42bfb6fa61b89b22f6/python-editor-1.0.1.tar.gz"; md5 = "e1fa63535b40e022fa4fd646fd8b511a"; }; + meta = { + license = [ pkgs.lib.licenses.asl20 ]; + }; }; python-ldap = super.buildPythonPackage { name = "python-ldap-2.4.19"; @@ -968,6 +1256,9 @@ url = "https://pypi.python.org/packages/42/81/1b64838c82e64f14d4e246ff00b52e650a35c012551b891ada2b85d40737/python-ldap-2.4.19.tar.gz"; md5 = "b941bf31d09739492aa19ef679e94ae3"; }; + meta = { + license = [ pkgs.lib.licenses.psfl ]; + }; }; python-memcached = super.buildPythonPackage { name = "python-memcached-1.57"; @@ -978,6 +1269,9 @@ url = "https://pypi.python.org/packages/52/9d/eebc0dcbc5c7c66840ad207dfc1baa376dadb74912484bff73819cce01e6/python-memcached-1.57.tar.gz"; md5 = "de21f64b42b2d961f3d4ad7beb5468a1"; }; + meta = { + license = [ pkgs.lib.licenses.psfl ]; + }; }; python-pam = super.buildPythonPackage { name = "python-pam-1.8.2"; @@ -988,6 +1282,9 @@ url = "https://pypi.python.org/packages/de/8c/f8f5d38b4f26893af267ea0b39023d4951705ab0413a39e0cf7cf4900505/python-pam-1.8.2.tar.gz"; md5 = "db71b6b999246fb05d78ecfbe166629d"; }; + meta = { + license = [ { fullName = "License :: OSI Approved :: MIT License"; } pkgs.lib.licenses.mit ]; + }; }; pytz = super.buildPythonPackage { name = "pytz-2015.4"; @@ -998,6 +1295,9 @@ url = "https://pypi.python.org/packages/7e/1a/f43b5c92df7b156822030fed151327ea096bcf417e45acc23bd1df43472f/pytz-2015.4.zip"; md5 = "233f2a2b370d03f9b5911700cc9ebf3c"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; pyzmq = super.buildPythonPackage { name = "pyzmq-14.6.0"; @@ -1008,6 +1308,9 @@ url = "https://pypi.python.org/packages/8a/3b/5463d5a9d712cd8bbdac335daece0d69f6a6792da4e3dd89956c0db4e4e6/pyzmq-14.6.0.tar.gz"; md5 = "395b5de95a931afa5b14c9349a5b8024"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal { fullName = "LGPL+BSD"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ]; + }; }; recaptcha-client = super.buildPythonPackage { name = "recaptcha-client-1.0.6"; @@ -1018,6 +1321,9 @@ url = "https://pypi.python.org/packages/0a/ea/5f2fbbfd894bdac1c68ef8d92019066cfcf9fbff5fe3d728d2b5c25c8db4/recaptcha-client-1.0.6.tar.gz"; md5 = "74228180f7e1fb76c4d7089160b0d919"; }; + meta = { + license = [ { fullName = "MIT/X11"; } ]; + }; }; repoze.lru = super.buildPythonPackage { name = "repoze.lru-0.6"; @@ -1028,6 +1334,9 @@ url = "https://pypi.python.org/packages/6e/1e/aa15cc90217e086dc8769872c8778b409812ff036bf021b15795638939e4/repoze.lru-0.6.tar.gz"; md5 = "2c3b64b17a8e18b405f55d46173e14dd"; }; + meta = { + license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ]; + }; }; requests = super.buildPythonPackage { name = "requests-2.9.1"; @@ -1038,13 +1347,19 @@ url = "https://pypi.python.org/packages/f9/6d/07c44fb1ebe04d069459a189e7dab9e4abfe9432adcd4477367c25332748/requests-2.9.1.tar.gz"; md5 = "0b7f480d19012ec52bab78292efd976d"; }; + meta = { + license = [ pkgs.lib.licenses.asl20 ]; + }; }; rhodecode-enterprise-ce = super.buildPythonPackage { - name = "rhodecode-enterprise-ce-4.1.2"; + name = "rhodecode-enterprise-ce-4.2.0"; buildInputs = with self; [WebTest configobj cssselect flake8 lxml mock pytest pytest-cov pytest-runner]; doCheck = true; propagatedBuildInputs = with self; [Babel Beaker FormEncode Mako Markdown MarkupSafe MySQL-python Paste PasteDeploy PasteScript Pygments Pylons Pyro4 Routes SQLAlchemy Tempita URLObject WebError WebHelpers WebHelpers2 WebOb WebTest Whoosh alembic amqplib anyjson appenlight-client authomatic backport-ipaddress celery colander decorator docutils gunicorn infrae.cache ipython iso8601 kombu msgpack-python packaging psycopg2 pycrypto pycurl pyparsing pyramid pyramid-debugtoolbar pyramid-mako pyramid-beaker pysqlite python-dateutil python-ldap python-memcached python-pam recaptcha-client repoze.lru requests simplejson waitress zope.cachedescriptors psutil py-bcrypt]; src = ./.; + meta = { + license = [ { fullName = "AGPLv3, and Commercial License"; } ]; + }; }; rhodecode-tools = super.buildPythonPackage { name = "rhodecode-tools-0.8.3"; @@ -1055,6 +1370,9 @@ url = "https://code.rhodecode.com/rhodecode-tools-ce/archive/v0.8.3.zip"; md5 = "9acdfd71b8ddf4056057065f37ab9ccb"; }; + meta = { + license = [ { fullName = "AGPLv3 and Proprietary"; } ]; + }; }; serpent = super.buildPythonPackage { name = "serpent-1.12"; @@ -1065,6 +1383,9 @@ url = "https://pypi.python.org/packages/3b/19/1e0e83b47c09edaef8398655088036e7e67386b5c48770218ebb339fbbd5/serpent-1.12.tar.gz"; md5 = "05869ac7b062828b34f8f927f0457b65"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; setproctitle = super.buildPythonPackage { name = "setproctitle-1.1.8"; @@ -1075,6 +1396,9 @@ url = "https://pypi.python.org/packages/33/c3/ad367a4f4f1ca90468863ae727ac62f6edb558fc09a003d344a02cfc6ea6/setproctitle-1.1.8.tar.gz"; md5 = "728f4c8c6031bbe56083a48594027edd"; }; + meta = { + license = [ pkgs.lib.licenses.bsdOriginal ]; + }; }; setuptools = super.buildPythonPackage { name = "setuptools-20.8.1"; @@ -1085,6 +1409,9 @@ url = "https://pypi.python.org/packages/c4/19/c1bdc88b53da654df43770f941079dbab4e4788c2dcb5658fb86259894c7/setuptools-20.8.1.zip"; md5 = "fe58a5cac0df20bb83942b252a4b0543"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; setuptools-scm = super.buildPythonPackage { name = "setuptools-scm-1.11.0"; @@ -1095,6 +1422,9 @@ url = "https://pypi.python.org/packages/cd/5f/e3a038292358058d83d764a47d09114aa5a8003ed4529518f9e580f1a94f/setuptools_scm-1.11.0.tar.gz"; md5 = "4c5c896ba52e134bbc3507bac6400087"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; simplejson = super.buildPythonPackage { name = "simplejson-3.7.2"; @@ -1105,6 +1435,9 @@ url = "https://pypi.python.org/packages/6d/89/7f13f099344eea9d6722779a1f165087cb559598107844b1ac5dbd831fb1/simplejson-3.7.2.tar.gz"; md5 = "a5fc7d05d4cb38492285553def5d4b46"; }; + meta = { + license = [ pkgs.lib.licenses.mit pkgs.lib.licenses.afl21 ]; + }; }; six = super.buildPythonPackage { name = "six-1.9.0"; @@ -1115,6 +1448,9 @@ url = "https://pypi.python.org/packages/16/64/1dc5e5976b17466fd7d712e59cbe9fb1e18bec153109e5ba3ed6c9102f1a/six-1.9.0.tar.gz"; md5 = "476881ef4012262dfc8adc645ee786c4"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; subprocess32 = super.buildPythonPackage { name = "subprocess32-3.2.6"; @@ -1125,6 +1461,9 @@ url = "https://pypi.python.org/packages/28/8d/33ccbff51053f59ae6c357310cac0e79246bbed1d345ecc6188b176d72c3/subprocess32-3.2.6.tar.gz"; md5 = "754c5ab9f533e764f931136974b618f1"; }; + meta = { + license = [ pkgs.lib.licenses.psfl ]; + }; }; supervisor = super.buildPythonPackage { name = "supervisor-3.1.3"; @@ -1135,6 +1474,9 @@ url = "https://pypi.python.org/packages/a6/41/65ad5bd66230b173eb4d0b8810230f3a9c59ef52ae066e540b6b99895db7/supervisor-3.1.3.tar.gz"; md5 = "aad263c4fbc070de63dd354864d5e552"; }; + meta = { + license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ]; + }; }; transifex-client = super.buildPythonPackage { name = "transifex-client-0.10"; @@ -1145,6 +1487,9 @@ url = "https://pypi.python.org/packages/f3/4e/7b925192aee656fb3e04fa6381c8b3dc40198047c3b4a356f6cfd642c809/transifex-client-0.10.tar.gz"; md5 = "5549538d84b8eede6b254cd81ae024fa"; }; + meta = { + license = [ pkgs.lib.licenses.gpl2 ]; + }; }; translationstring = super.buildPythonPackage { name = "translationstring-1.3"; @@ -1155,6 +1500,9 @@ url = "https://pypi.python.org/packages/5e/eb/bee578cc150b44c653b63f5ebe258b5d0d812ddac12497e5f80fcad5d0b4/translationstring-1.3.tar.gz"; md5 = "a4b62e0f3c189c783a1685b3027f7c90"; }; + meta = { + license = [ { fullName = "BSD-like (http://repoze.org/license.html)"; } ]; + }; }; trollius = super.buildPythonPackage { name = "trollius-1.0.4"; @@ -1165,6 +1513,9 @@ url = "https://pypi.python.org/packages/aa/e6/4141db437f55e6ee7a3fb69663239e3fde7841a811b4bef293145ad6c836/trollius-1.0.4.tar.gz"; md5 = "3631a464d49d0cbfd30ab2918ef2b783"; }; + meta = { + license = [ pkgs.lib.licenses.asl20 ]; + }; }; uWSGI = super.buildPythonPackage { name = "uWSGI-2.0.11.2"; @@ -1175,6 +1526,9 @@ url = "https://pypi.python.org/packages/9b/78/918db0cfab0546afa580c1e565209c49aaf1476bbfe491314eadbe47c556/uwsgi-2.0.11.2.tar.gz"; md5 = "1f02dcbee7f6f61de4b1fd68350cf16f"; }; + meta = { + license = [ pkgs.lib.licenses.gpl2 ]; + }; }; urllib3 = super.buildPythonPackage { name = "urllib3-1.16"; @@ -1185,6 +1539,9 @@ url = "https://pypi.python.org/packages/3b/f0/e763169124e3f5db0926bc3dbfcd580a105f9ca44cf5d8e6c7a803c9f6b5/urllib3-1.16.tar.gz"; md5 = "fcaab1c5385c57deeb7053d3d7d81d59"; }; + meta = { + license = [ pkgs.lib.licenses.mit ]; + }; }; venusian = super.buildPythonPackage { name = "venusian-1.0"; @@ -1195,6 +1552,9 @@ url = "https://pypi.python.org/packages/86/20/1948e0dfc4930ddde3da8c33612f6a5717c0b4bc28f591a5c5cf014dd390/venusian-1.0.tar.gz"; md5 = "dccf2eafb7113759d60c86faf5538756"; }; + meta = { + license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ]; + }; }; waitress = super.buildPythonPackage { name = "waitress-0.8.9"; @@ -1205,6 +1565,9 @@ url = "https://pypi.python.org/packages/ee/65/fc9dee74a909a1187ca51e4f15ad9c4d35476e4ab5813f73421505c48053/waitress-0.8.9.tar.gz"; md5 = "da3f2e62b3676be5dd630703a68e2a04"; }; + meta = { + license = [ pkgs.lib.licenses.zpt21 ]; + }; }; wsgiref = super.buildPythonPackage { name = "wsgiref-0.1.2"; @@ -1215,6 +1578,9 @@ url = "https://pypi.python.org/packages/41/9e/309259ce8dff8c596e8c26df86dbc4e848b9249fd36797fd60be456f03fc/wsgiref-0.1.2.zip"; md5 = "29b146e6ebd0f9fb119fe321f7bcf6cb"; }; + meta = { + license = [ { fullName = "PSF or ZPL"; } ]; + }; }; zope.cachedescriptors = super.buildPythonPackage { name = "zope.cachedescriptors-4.0.0"; @@ -1225,6 +1591,9 @@ url = "https://pypi.python.org/packages/40/33/694b6644c37f28553f4b9f20b3c3a20fb709a22574dff20b5bdffb09ecd5/zope.cachedescriptors-4.0.0.tar.gz"; md5 = "8d308de8c936792c8e758058fcb7d0f0"; }; + meta = { + license = [ pkgs.lib.licenses.zpt21 ]; + }; }; zope.deprecation = super.buildPythonPackage { name = "zope.deprecation-4.1.2"; @@ -1235,6 +1604,9 @@ url = "https://pypi.python.org/packages/c1/d3/3919492d5e57d8dd01b36f30b34fc8404a30577392b1eb817c303499ad20/zope.deprecation-4.1.2.tar.gz"; md5 = "e9a663ded58f4f9f7881beb56cae2782"; }; + meta = { + license = [ pkgs.lib.licenses.zpt21 ]; + }; }; zope.event = super.buildPythonPackage { name = "zope.event-4.0.3"; @@ -1245,6 +1617,9 @@ url = "https://pypi.python.org/packages/c1/29/91ba884d7d6d96691df592e9e9c2bfa57a47040ec1ff47eff18c85137152/zope.event-4.0.3.tar.gz"; md5 = "9a3780916332b18b8b85f522bcc3e249"; }; + meta = { + license = [ pkgs.lib.licenses.zpt21 ]; + }; }; zope.interface = super.buildPythonPackage { name = "zope.interface-4.1.3"; @@ -1255,6 +1630,9 @@ url = "https://pypi.python.org/packages/9d/81/2509ca3c6f59080123c1a8a97125eb48414022618cec0e64eb1313727bfe/zope.interface-4.1.3.tar.gz"; md5 = "9ae3d24c0c7415deb249dd1a132f0f79"; }; + meta = { + license = [ pkgs.lib.licenses.zpt21 ]; + }; }; ### Test requirements diff --git a/release.nix b/release.nix --- a/release.nix +++ b/release.nix @@ -25,6 +25,7 @@ # vcsserver resides. { pkgs ? import {} +, doCheck ? true }: let diff --git a/requirements.txt b/requirements.txt --- a/requirements.txt +++ b/requirements.txt @@ -69,7 +69,6 @@ flake8==2.4.1 future==0.14.3 futures==3.0.2 gprof2dot==2015.12.1 -greenlet==0.4.9 gunicorn==19.6.0 # TODO: Needs subvertpy and blows up without Subversion headers, @@ -78,7 +77,7 @@ gunicorn==19.6.0 gnureadline==6.3.3 infrae.cache==1.0.1 -invoke==0.11.1 +invoke==0.13.0 ipdb==0.8 ipython==3.1.0 iso8601==0.1.11 diff --git a/rhodecode/VERSION b/rhodecode/VERSION --- a/rhodecode/VERSION +++ b/rhodecode/VERSION @@ -1,1 +1,1 @@ -4.1.2 \ No newline at end of file +4.2.0 \ No newline at end of file diff --git a/rhodecode/admin/__init__.py b/rhodecode/admin/__init__.py new file mode 100644 --- /dev/null +++ b/rhodecode/admin/__init__.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2016-2016 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/ + + +from rhodecode.admin.navigation import NavigationRegistry +from rhodecode.config.routing import ADMIN_PREFIX +from rhodecode.lib.utils2 import str2bool + + +def includeme(config): + settings = config.get_settings() + + # Create admin navigation registry and add it to the pyramid registry. + labs_active = str2bool(settings.get('labs_settings_active', False)) + navigation_registry = NavigationRegistry(labs_active=labs_active) + config.registry.registerUtility(navigation_registry) + + config.add_route( + name='admin_settings_open_source', + pattern=ADMIN_PREFIX + '/settings/open_source') + + # Scan module for configuration decorators. + config.scan() diff --git a/rhodecode/admin/interfaces.py b/rhodecode/admin/interfaces.py new file mode 100644 --- /dev/null +++ b/rhodecode/admin/interfaces.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2016-2016 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/ + +from zope.interface import Interface + + +class IAdminNavigationRegistry(Interface): + """ + Interface for the admin navigation registry. Currently this is only + used to register and retrieve it via pyramids registry. + """ + pass diff --git a/rhodecode/admin/navigation.py b/rhodecode/admin/navigation.py new file mode 100644 --- /dev/null +++ b/rhodecode/admin/navigation.py @@ -0,0 +1,124 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2016-2016 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 +import collections + +from pylons import url +from zope.interface import implementer + +from rhodecode.admin.interfaces import IAdminNavigationRegistry +from rhodecode.lib.utils import get_registry +from rhodecode.translation import _ + + +log = logging.getLogger(__name__) + +NavListEntry = collections.namedtuple('NavListEntry', ['key', 'name', 'url']) + + +class NavEntry(object): + """ + Represents an entry in the admin navigation. + + :param key: Unique identifier used to store reference in an OrderedDict. + :param name: Display name, usually a translation string. + :param view_name: Name of the view, used generate the URL. + :param pyramid: Indicator to use pyramid for URL generation. This should + be removed as soon as we are fully migrated to pyramid. + """ + + def __init__(self, key, name, view_name, pyramid=False): + self.key = key + self.name = name + self.view_name = view_name + self.pyramid = pyramid + + def generate_url(self, request): + if self.pyramid: + if hasattr(request, 'route_path'): + return request.route_path(self.view_name) + else: + # TODO: johbo: Remove this after migrating to pyramid. + # We need the pyramid request here to generate URLs to pyramid + # views from within pylons views. + from pyramid.threadlocal import get_current_request + pyramid_request = get_current_request() + return pyramid_request.route_path(self.view_name) + else: + return url(self.view_name) + + +@implementer(IAdminNavigationRegistry) +class NavigationRegistry(object): + + _base_entries = [ + NavEntry('global', _('Global'), 'admin_settings_global'), + NavEntry('vcs', _('VCS'), 'admin_settings_vcs'), + NavEntry('visual', _('Visual'), 'admin_settings_visual'), + NavEntry('mapping', _('Remap and Rescan'), 'admin_settings_mapping'), + NavEntry('issuetracker', _('Issue Tracker'), + 'admin_settings_issuetracker'), + NavEntry('email', _('Email'), 'admin_settings_email'), + NavEntry('hooks', _('Hooks'), 'admin_settings_hooks'), + NavEntry('search', _('Full Text Search'), 'admin_settings_search'), + NavEntry('system', _('System Info'), 'admin_settings_system'), + NavEntry('open_source', _('Open Source Licenses'), + 'admin_settings_open_source', pyramid=True), + # TODO: marcink: we disable supervisor now until the supervisor stats + # page is fixed in the nix configuration + # NavEntry('supervisor', _('Supervisor'), 'admin_settings_supervisor'), + ] + + _labs_entry = NavEntry('labs', _('Labs'), + 'admin_settings_labs') + + def __init__(self, labs_active=False): + self._registered_entries = collections.OrderedDict([ + (item.key, item) for item in self.__class__._base_entries + ]) + + if labs_active: + self.add_entry(self._labs_entry) + + def add_entry(self, entry): + self._registered_entries[entry.key] = entry + + def get_navlist(self, request): + navlist = [NavListEntry(i.key, i.name, i.generate_url(request)) + for i in self._registered_entries.values()] + return navlist + + +def navigation_registry(request): + """ + Helper that returns the admin navigation registry. + """ + pyramid_registry = get_registry(request) + nav_registry = pyramid_registry.queryUtility(IAdminNavigationRegistry) + return nav_registry + + +def navigation_list(request): + """ + Helper that returns the admin navigation as list of NavListEntry objects. + """ + return navigation_registry(request).get_navlist(request) diff --git a/rhodecode/admin/views.py b/rhodecode/admin/views.py new file mode 100644 --- /dev/null +++ b/rhodecode/admin/views.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2016-2016 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 collections +import logging + +from pylons import tmpl_context as c +from pyramid.view import view_config + +from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator +from rhodecode.lib.utils import read_opensource_licenses + +from .navigation import navigation_list + + +log = logging.getLogger(__name__) + + +class AdminSettingsView(object): + + def __init__(self, context, request): + self.request = request + self.context = context + self.session = request.session + self._rhodecode_user = request.user + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @view_config( + route_name='admin_settings_open_source', request_method='GET', + renderer='rhodecode:templates/admin/settings/settings.html') + def open_source_licenses(self): + c.active = 'open_source' + c.navlist = navigation_list(self.request) + c.opensource_licenses = collections.OrderedDict( + sorted(read_opensource_licenses().items(), key=lambda t: t[0])) + + return {} diff --git a/rhodecode/authentication/base.py b/rhodecode/authentication/base.py --- a/rhodecode/authentication/base.py +++ b/rhodecode/authentication/base.py @@ -22,6 +22,7 @@ Authentication modules """ +import colander import logging import time import traceback @@ -97,16 +98,18 @@ class RhodeCodeAuthPluginBase(object): # Mapping of python to DB settings model types. Plugins may override or # extend this mapping. _settings_type_map = { - str: 'str', - int: 'int', - unicode: 'unicode', - bool: 'bool', - list: 'list', + colander.String: 'unicode', + colander.Integer: 'int', + colander.Boolean: 'bool', + colander.List: 'list', } def __init__(self, plugin_id): self._plugin_id = plugin_id + def __str__(self): + return self.get_id() + def _get_setting_full_name(self, name): """ Return the full setting name used for storing values in the database. @@ -116,16 +119,19 @@ class RhodeCodeAuthPluginBase(object): # PluginSetting or to use the plugin id here. return 'auth_{}_{}'.format(self.name, name) - def _get_setting_type(self, name, value): + def _get_setting_type(self, name): + """ + Return the type of a setting. This type is defined by the SettingsModel + and determines how the setting is stored in DB. Optionally the suffix + `.encrypted` is appended to instruct SettingsModel to store it + encrypted. """ - Get the type as used by the SettingsModel accordingly to type of passed - value. Optionally the suffix `.encrypted` is appended to instruct - SettingsModel to store it encrypted. - """ - type_ = self._settings_type_map.get(type(value), 'unicode') + schema_node = self.get_settings_schema().get(name) + db_type = self._settings_type_map.get( + type(schema_node.typ), 'unicode') if name in self._settings_encrypted: - type_ = '{}.encrypted'.format(type_) - return type_ + db_type = '{}.encrypted'.format(db_type) + return db_type def is_enabled(self): """ @@ -161,20 +167,20 @@ class RhodeCodeAuthPluginBase(object): """ return AuthnPluginSettingsSchemaBase() - def get_setting_by_name(self, name): + def get_setting_by_name(self, name, default=None): """ Returns a plugin setting by name. """ full_name = self._get_setting_full_name(name) db_setting = SettingsModel().get_setting_by_name(full_name) - return db_setting.app_settings_value if db_setting else None + return db_setting.app_settings_value if db_setting else default def create_or_update_setting(self, name, value): """ Create or update a setting for this plugin in the persistent storage. """ full_name = self._get_setting_full_name(name) - type_ = self._get_setting_type(name, value) + type_ = self._get_setting_type(name) db_setting = SettingsModel().create_or_update_setting( full_name, value, type_) return db_setting.app_settings_value diff --git a/rhodecode/authentication/tests/__init__.py b/rhodecode/authentication/tests/__init__.py new file mode 100644 diff --git a/rhodecode/authentication/tests/conftest.py b/rhodecode/authentication/tests/conftest.py new file mode 100644 --- /dev/null +++ b/rhodecode/authentication/tests/conftest.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2016-2016 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 + + +class EnabledAuthPlugin(): + """ + Context manager that updates the 'auth_plugins' setting in DB to enable + a plugin. Previous setting is restored on exit. The rhodecode auth plugin + is also enabled because it is needed to login the test users. + """ + + def __init__(self, plugin): + self.new_value = set([ + 'egg:rhodecode-enterprise-ce#rhodecode', + plugin.get_id() + ]) + + def __enter__(self): + from rhodecode.model.settings import SettingsModel + self._old_value = SettingsModel().get_auth_plugins() + SettingsModel().create_or_update_setting( + 'auth_plugins', ','.join(self.new_value)) + + def __exit__(self, type, value, traceback): + from rhodecode.model.settings import SettingsModel + SettingsModel().create_or_update_setting( + 'auth_plugins', ','.join(self._old_value)) + + +class DisabledAuthPlugin(): + """ + Context manager that updates the 'auth_plugins' setting in DB to disable + a plugin. Previous setting is restored on exit. + """ + + def __init__(self, plugin): + self.plugin_id = plugin.get_id() + + def __enter__(self): + from rhodecode.model.settings import SettingsModel + self._old_value = SettingsModel().get_auth_plugins() + new_value = [id_ for id_ in self._old_value if id_ != self.plugin_id] + SettingsModel().create_or_update_setting( + 'auth_plugins', ','.join(new_value)) + + def __exit__(self, type, value, traceback): + from rhodecode.model.settings import SettingsModel + SettingsModel().create_or_update_setting( + 'auth_plugins', ','.join(self._old_value)) + + +@pytest.fixture(params=[ + ('rhodecode.authentication.plugins.auth_crowd', 'egg:rhodecode-enterprise-ce#crowd'), + ('rhodecode.authentication.plugins.auth_headers', 'egg:rhodecode-enterprise-ce#headers'), + ('rhodecode.authentication.plugins.auth_jasig_cas', 'egg:rhodecode-enterprise-ce#jasig_cas'), + ('rhodecode.authentication.plugins.auth_ldap', 'egg:rhodecode-enterprise-ce#ldap'), + ('rhodecode.authentication.plugins.auth_pam', 'egg:rhodecode-enterprise-ce#pam'), + ('rhodecode.authentication.plugins.auth_rhodecode', 'egg:rhodecode-enterprise-ce#rhodecode'), + ('rhodecode.authentication.plugins.auth_token', 'egg:rhodecode-enterprise-ce#token'), +]) +def auth_plugin(request): + """ + Fixture that provides instance for each authentication plugin. These + instances are NOT the instances which are registered to the authentication + registry. + """ + from importlib import import_module + + # Create plugin instance. + module, plugin_id = request.param + plugin_module = import_module(module) + return plugin_module.plugin_factory(plugin_id) diff --git a/rhodecode/authentication/tests/functional/__init__.py b/rhodecode/authentication/tests/functional/__init__.py new file mode 100644 diff --git a/rhodecode/authentication/tests/functional/test_settings.py b/rhodecode/authentication/tests/functional/test_settings.py new file mode 100644 --- /dev/null +++ b/rhodecode/authentication/tests/functional/test_settings.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2016-2016 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.authentication.tests.conftest import ( + EnabledAuthPlugin, DisabledAuthPlugin) +from rhodecode.config.routing import ADMIN_PREFIX + + +@pytest.mark.usefixtures('autologin_user', 'app') +class TestAuthenticationSettings: + + def test_auth_settings_global_view_get(self, app): + url = '{prefix}/auth/'.format(prefix=ADMIN_PREFIX) + response = app.get(url) + assert response.status_code == 200 + + def test_plugin_settings_view_get(self, app, auth_plugin): + url = '{prefix}/auth/{name}'.format( + prefix=ADMIN_PREFIX, + name=auth_plugin.name) + with EnabledAuthPlugin(auth_plugin): + response = app.get(url) + assert response.status_code == 200 + + def test_plugin_settings_view_post(self, app, auth_plugin, csrf_token): + url = '{prefix}/auth/{name}'.format( + prefix=ADMIN_PREFIX, + name=auth_plugin.name) + params = { + 'enabled': True, + 'cache_ttl': 0, + 'csrf_token': csrf_token, + } + with EnabledAuthPlugin(auth_plugin): + response = app.post(url, params=params) + assert response.status_code in [200, 302] + + def test_plugin_settings_view_get_404(self, app, auth_plugin): + url = '{prefix}/auth/{name}'.format( + prefix=ADMIN_PREFIX, + name=auth_plugin.name) + with DisabledAuthPlugin(auth_plugin): + response = app.get(url, status=404) + assert response.status_code == 404 + + def test_plugin_settings_view_post_404(self, app, auth_plugin, csrf_token): + url = '{prefix}/auth/{name}'.format( + prefix=ADMIN_PREFIX, + name=auth_plugin.name) + params = { + 'enabled': True, + 'cache_ttl': 0, + 'csrf_token': csrf_token, + } + with DisabledAuthPlugin(auth_plugin): + response = app.post(url, params=params, status=404) + assert response.status_code == 404 diff --git a/rhodecode/authentication/tests/test_auth_plugin_base.py b/rhodecode/authentication/tests/test_auth_plugin_base.py new file mode 100644 --- /dev/null +++ b/rhodecode/authentication/tests/test_auth_plugin_base.py @@ -0,0 +1,28 @@ +# Copyright (C) 2016 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/ + +""" +Checks around the API of the class RhodeCodeAuthPluginBase. +""" + +from rhodecode.authentication.base import RhodeCodeAuthPluginBase + + +def test_str_returns_plugin_id(): + plugin = RhodeCodeAuthPluginBase(plugin_id='stub_plugin_id') + assert str(plugin) == 'stub_plugin_id' diff --git a/rhodecode/authentication/views.py b/rhodecode/authentication/views.py --- a/rhodecode/authentication/views.py +++ b/rhodecode/authentication/views.py @@ -56,10 +56,12 @@ class AuthnPluginViewBase(object): errors = errors or {} schema = self.plugin.get_settings_schema() - # Get default values for the form. + # Compute default values for the form. Priority is: + # 1. Passed to this method 2. DB value 3. Schema default for node in schema: - db_value = self.plugin.get_setting_by_name(node.name) - defaults.setdefault(node.name, db_value) + if node.name not in defaults: + defaults[node.name] = self.plugin.get_setting_by_name( + node.name, node.default) template_context = { 'defaults': defaults, @@ -78,15 +80,17 @@ class AuthnPluginViewBase(object): View that validates and stores the plugin settings. """ schema = self.plugin.get_settings_schema() + data = self.request.params + try: - valid_data = schema.deserialize(self.request.params) + valid_data = schema.deserialize(data) except colander.Invalid, e: # Display error message and display form again. self.request.session.flash( _('Errors exist when saving plugin settings. ' 'Please check the form inputs.'), queue='error') - defaults = schema.flatten(self.request.params) + defaults = {key: data[key] for key in data if key in schema} return self.settings_get(errors=e.asdict(), defaults=defaults) # Store validated data. diff --git a/rhodecode/config/environment.py b/rhodecode/config/environment.py --- a/rhodecode/config/environment.py +++ b/rhodecode/config/environment.py @@ -82,7 +82,7 @@ def load_environment(global_conf, app_co config['routes.map'] = make_map(config) - if asbool(config['debug']): + if asbool(config.get('generate_js_files', 'false')): jsroutes = config['routes.map'].jsroutes() jsroutes_file_content = generate_jsroutes_content(jsroutes) jsroutes_file_path = os.path.join( diff --git a/rhodecode/config/jsroutes.py b/rhodecode/config/jsroutes.py --- a/rhodecode/config/jsroutes.py +++ b/rhodecode/config/jsroutes.py @@ -29,7 +29,8 @@ def generate_jsroutes_content(jsroutes): * DO NOT CHANGE THIS FILE MANUALLY * * * * * - * This file is automatically generated when the app starts up. * + * This file is automatically generated when the app starts up with * + * generate_js_files = true * * * * To add a route here pass jsroute=True to the route definition in the app * * * diff --git a/rhodecode/config/licenses.json b/rhodecode/config/licenses.json --- a/rhodecode/config/licenses.json +++ b/rhodecode/config/licenses.json @@ -1,217 +1,256 @@ { - "cyrus-sasl-2.1.26": { - "cyrus": "http://cyrusimap.web.cmu.edu/mediawiki/index.php/Downloads#Licensing" + "nodejs-4.3.1": { + "MIT License": "http://spdx.org/licenses/MIT" }, - "openldap-2.4.41": { - "OLDAP-2.8": "http://spdx.org/licenses/OLDAP-2.8" + "postgresql-9.5.1": { + "PostgreSQL License": "http://spdx.org/licenses/PostgreSQL" }, - "openssl-1.0.1p": { - "OpenSSL": "http://spdx.org/licenses/OpenSSL" - }, - "python-2.7.10": { - "Python-2.0": "http://spdx.org/licenses/Python-2.0" + "python-2.7.11": { + "Python Software Foundation License version 2": "http://spdx.org/licenses/Python-2.0" }, "python2.7-Babel-1.3": { - "BSD-3-Clause": "http://spdx.org/licenses/BSD-3-Clause" + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" }, "python2.7-Beaker-1.7.0": { - "BSD-3-Clause": "http://spdx.org/licenses/BSD-3-Clause" + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" }, "python2.7-FormEncode-1.2.4": { - "Python-2.0": "http://spdx.org/licenses/Python-2.0" + "Python Software Foundation License version 2": "http://spdx.org/licenses/Python-2.0" }, "python2.7-Mako-1.0.1": { - "MIT": "http://spdx.org/licenses/MIT" + "MIT License": "http://spdx.org/licenses/MIT" }, "python2.7-Markdown-2.6.2": { - "BSD-3-Clause": "http://spdx.org/licenses/BSD-3-Clause" + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" }, "python2.7-MarkupSafe-0.23": { - "BSD-3-Clause": "http://spdx.org/licenses/BSD-3-Clause" + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" }, "python2.7-Paste-2.0.2": { - "MIT": "http://spdx.org/licenses/MIT" + "MIT License": "http://spdx.org/licenses/MIT" }, "python2.7-PasteDeploy-1.5.2": { - "MIT": "http://spdx.org/licenses/MIT" + "MIT License": "http://spdx.org/licenses/MIT" }, "python2.7-PasteScript-1.7.5": { - "MIT": "http://spdx.org/licenses/MIT" + "MIT License": "http://spdx.org/licenses/MIT" }, "python2.7-Pygments-2.0.2": { - "BSD-2-Clause": "http://spdx.org/licenses/BSD-2-Clause" + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" }, - "python2.7-Pylons-1.0.2-patch1": { - "BSD-3-Clause": "http://spdx.org/licenses/BSD-3-Clause" + "python2.7-Pylons-1.0.1-patch1": { + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" }, "python2.7-Pyro4-4.35": { - "MIT": "http://spdx.org/licenses/MIT" + "MIT License": "http://spdx.org/licenses/MIT" }, "python2.7-Routes-1.13": { - "MIT": "http://spdx.org/licenses/MIT" + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" }, "python2.7-SQLAlchemy-0.9.9": { - "MIT": "http://spdx.org/licenses/MIT" + "MIT License": "http://spdx.org/licenses/MIT" }, "python2.7-Tempita-0.5.2": { - "MIT": "http://spdx.org/licenses/MIT" + "MIT License": "http://spdx.org/licenses/MIT" }, "python2.7-URLObject-2.4.0": { - "Unlicense": "http://spdx.org/licenses/Unlicense" + "The Unlicense": "http://unlicense.org/" }, "python2.7-WebError-0.10.3": { - "MIT": "http://spdx.org/licenses/MIT" + "MIT License": "http://spdx.org/licenses/MIT" }, - "python2.7-WebHelpers-1.3-cust1": { - "BSD-3-Clause": "http://spdx.org/licenses/BSD-3-Clause" + "python2.7-WebHelpers-1.3": { + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" }, "python2.7-WebHelpers2-2.0": { - "BSD-3-Clause": "http://spdx.org/licenses/BSD-3-Clause" + "MIT License": "http://spdx.org/licenses/MIT" }, "python2.7-WebOb-1.3.1": { - "MIT": "http://spdx.org/licenses/MIT" + "MIT License": "http://spdx.org/licenses/MIT" }, - "python2.7-Whoosh-2.7.0-patch1": { - "BSD-2-Clause": "http://spdx.org/licenses/BSD-2-Clause" + "python2.7-Whoosh-2.7.0": { + "BSD 2-clause \"Simplified\" License": "http://spdx.org/licenses/BSD-2-Clause", + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" }, "python2.7-alembic-0.8.4": { - "MIT": "http://spdx.org/licenses/MIT" + "MIT License": "http://spdx.org/licenses/MIT" }, "python2.7-amqplib-1.0.2": { - "LGPL-3.0": "http://spdx.org/licenses/LGPL-3.0" + "GNU Lesser General Public License v3.0 only": "http://spdx.org/licenses/LGPL-3.0" }, "python2.7-anyjson-0.3.3": { - "BSD-2-Clause": "http://spdx.org/licenses/BSD-2-Clause" + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" + }, + "python2.7-appenlight-client-0.6.14": { + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" }, - "python2.7-appenlight_client-0.6.14": { - "BSD-2-Clause": "http://spdx.org/licenses/BSD-2-Clause" + "python2.7-authomatic-0.1.0.post1": { + "MIT License": "http://spdx.org/licenses/MIT" }, - "python2.7-backport_ipaddress-0.1": { - "Python-2.0": "http://spdx.org/licenses/Python-2.0" + "python2.7-backport-ipaddress-0.1": { + "Python Software Foundation License version 2": "http://spdx.org/licenses/Python-2.0" }, "python2.7-celery-2.2.10": { - "BSD-2-Clause": "http://spdx.org/licenses/BSD-2-Clause" + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" }, - "python2.7-click-4.0": { - "BSD-3-Clause": "http://spdx.org/licenses/BSD-3-Clause" + "python2.7-click-5.1": { + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" + }, + "python2.7-colander-1.2": { + "Repoze License": "http://www.repoze.org/LICENSE.txt" }, "python2.7-configobj-5.0.6": { - "BSD-3-Clause": "http://spdx.org/licenses/BSD-3-Clause" + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" }, "python2.7-cssselect-0.9.1": { - "BSD-2-Clause": "http://spdx.org/licenses/BSD-2-Clause" + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" }, "python2.7-decorator-3.4.2": { - "BSD-3-Clause": "http://spdx.org/licenses/BSD-3-Clause" + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" }, "python2.7-docutils-0.12": { - "BSD-2-Clause": "http://spdx.org/licenses/BSD-2-Clause" + "BSD 2-clause \"Simplified\" License": "http://spdx.org/licenses/BSD-2-Clause" + }, + "python2.7-elasticsearch-2.3.0": { + "Apache License 2.0": "http://spdx.org/licenses/Apache-2.0" + }, + "python2.7-elasticsearch-dsl-2.0.0": { + "Apache License 2.0": "http://spdx.org/licenses/Apache-2.0" }, "python2.7-future-0.14.3": { - "MIT": "http://spdx.org/licenses/MIT" + "MIT License": "http://spdx.org/licenses/MIT" }, "python2.7-futures-3.0.2": { - "BSD-3-Clause": "http://spdx.org/licenses/BSD-3-Clause" + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" + }, + "python2.7-gnureadline-6.3.3": { + "GNU General Public License v1.0 only": "http://spdx.org/licenses/GPL-1.0" }, - "python2.7-greenlet-0.4.7": { - "MIT": "http://spdx.org/licenses/MIT" + "python2.7-gunicorn-19.6.0": { + "MIT License": "http://spdx.org/licenses/MIT" }, - "python2.7-gunicorn-19.3.0": { - "MIT": "http://spdx.org/licenses/MIT" + "python2.7-infrae.cache-1.0.1": { + "Zope Public License 2.1": "http://spdx.org/licenses/ZPL-2.1" }, "python2.7-ipython-3.1.0": { - "BSD-3-Clause": "http://spdx.org/licenses/BSD-3-Clause" - }, - "python2.7-kombu-1.5.1-patch1": { - "BSD-3-Clause": "http://spdx.org/licenses/BSD-3-Clause" + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" }, - "python2.7-mccabe-0.3": { - "expat": "http://directory.fsf.org/wiki/License:Expat" + "python2.7-iso8601-0.1.11": { + "MIT License": "http://spdx.org/licenses/MIT" }, - "python2.7-meld3-1.0.2": { - "repoze": "http://repoze.org/license.html" + "python2.7-kombu-1.5.1": { + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" }, "python2.7-msgpack-python-0.4.6": { - "Apache-2.0": "http://spdx.org/licenses/Apache-2.0" - }, - "python2.7-objgraph-2.0.0": { - "MIT": "http://spdx.org/licenses/MIT" + "Apache License 2.0": "http://spdx.org/licenses/Apache-2.0" }, "python2.7-packaging-15.2": { - "Apache-2.0": "http://spdx.org/licenses/Apache-2.0" + "Apache License 2.0": "http://spdx.org/licenses/Apache-2.0" }, "python2.7-psutil-2.2.1": { - "BSD-2-Clause": "http://spdx.org/licenses/BSD-2-Clause" + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" }, "python2.7-psycopg2-2.6": { - "LGPL-3.0+": "http://spdx.org/licenses/LGPL-3.0+" + "GNU Lesser General Public License v3.0 or later": "http://spdx.org/licenses/LGPL-3.0+" }, "python2.7-py-1.4.29": { - "MIT": "http://spdx.org/licenses/MIT" + "MIT License": "http://spdx.org/licenses/MIT" }, "python2.7-py-bcrypt-0.4": { - "BSD-4-Clause": "http://spdx.org/licenses/BSD-4-Clause" + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause" }, "python2.7-pycrypto-2.6.1": { - "publicDomain": null + "Public Domain": null + }, + "python2.7-pycurl-7.19.5": { + "MIT License": "http://spdx.org/licenses/MIT" }, "python2.7-pyparsing-1.5.7": { - "MIT": "http://spdx.org/licenses/MIT" + "MIT License": "http://spdx.org/licenses/MIT" + }, + "python2.7-pyramid-1.6.1": { + "Repoze License": "http://www.repoze.org/LICENSE.txt" + }, + "python2.7-pyramid-beaker-0.8": { + "Repoze License": "http://www.repoze.org/LICENSE.txt" + }, + "python2.7-pyramid-debugtoolbar-2.4.2": { + "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause", + "Repoze License": "http://www.repoze.org/LICENSE.txt" + }, + "python2.7-pyramid-mako-1.0.2": { + "Repoze License": "http://www.repoze.org/LICENSE.txt" }, "python2.7-pysqlite-2.6.3": { - "Libpng": "http://spdx.org/licenses/Libpng", - "Zlib": "http://spdx.org/licenses/Zlib" + "libpng License": "http://spdx.org/licenses/Libpng", + "zlib License": "http://spdx.org/licenses/Zlib" }, "python2.7-pytest-2.8.5": { - "MIT": "http://spdx.org/licenses/MIT" + "MIT License": "http://spdx.org/licenses/MIT" + }, + "python2.7-pytest-runner-2.7.1": { + "MIT License": "http://spdx.org/licenses/MIT" }, "python2.7-python-dateutil-1.5": { - "BSD-2-Clause": "http://spdx.org/licenses/BSD-2-Clause" + "Python Software Foundation License version 2": "http://spdx.org/licenses/Python-2.0" + }, + "python2.7-python-editor-1.0.1": { + "Apache License 2.0": "http://spdx.org/licenses/Apache-2.0" }, "python2.7-python-ldap-2.4.19": { - "Python-2.0": "http://spdx.org/licenses/Python-2.0" + "Python Software Foundation License version 2": "http://spdx.org/licenses/Python-2.0" + }, + "python2.7-python-memcached-1.57": { + "Python Software Foundation License version 2": "http://spdx.org/licenses/Python-2.0" }, "python2.7-pytz-2015.4": { - "MIT": "http://spdx.org/licenses/MIT" + "MIT License": "http://spdx.org/licenses/MIT" }, "python2.7-recaptcha-client-1.0.6": { - "MIT": "http://spdx.org/licenses/MIT" + "MIT License": "http://spdx.org/licenses/MIT" }, "python2.7-repoze.lru-0.6": { - "repoze": "http://repoze.org/license.html" + "Repoze License": "http://www.repoze.org/LICENSE.txt" }, - "python2.7-requests-2.5.1": { - "APSL-2.0": "http://spdx.org/licenses/APSL-2.0" + "python2.7-requests-2.9.1": { + "Apache License 2.0": "http://spdx.org/licenses/Apache-2.0" }, - "python2.7-serpent-1.11": { - "MIT": "http://spdx.org/licenses/MIT" + "python2.7-serpent-1.12": { + "MIT License": "http://spdx.org/licenses/MIT" }, - "python2.7-setproctitle-1.1.8": { - "BSD-2-Clause": "http://spdx.org/licenses/BSD-2-Clause" + "python2.7-setuptools-19.4": { + "Python Software Foundation License version 2": "http://spdx.org/licenses/Python-2.0", + "Zope Public License 2.0": "http://spdx.org/licenses/ZPL-2.0" }, - "python2.7-setuptools-18.0.1": { - "PSF": null, - "ZPL": null + "python2.7-setuptools-scm-1.11.0": { + "MIT License": "http://spdx.org/licenses/MIT" }, "python2.7-simplejson-3.7.2": { - "MIT": "http://spdx.org/licenses/MIT" + "Academic Free License": "http://spdx.org/licenses/AFL-2.1", + "MIT License": "http://spdx.org/licenses/MIT" }, "python2.7-six-1.9.0": { - "MIT": "http://spdx.org/licenses/MIT" + "MIT License": "http://spdx.org/licenses/MIT" }, - "python2.7-subprocess32-3.2.6": { - "Python-2.0": "http://spdx.org/licenses/Python-2.0" + "python2.7-translationstring-1.3": { + "Repoze License": "http://www.repoze.org/LICENSE.txt" }, - "python2.7-supervisor-3.1.3": { - "repoze": "http://repoze.org/license.html" + "python2.7-urllib3-1.16": { + "MIT License": "http://spdx.org/licenses/MIT" }, - "python2.7-trollius-1.0.4": { - "APSL-2.0": "http://spdx.org/licenses/APSL-2.0" + "python2.7-venusian-1.0": { + "Repoze License": "http://www.repoze.org/LICENSE.txt" }, "python2.7-waitress-0.8.9": { - "ZPL-2.1": "http://spdx.org/licenses/ZPL-2.1" + "Zope Public License 2.1": "http://spdx.org/licenses/ZPL-2.1" }, "python2.7-zope.cachedescriptors-4.0.0": { - "ZPL-2.1": "http://spdx.org/licenses/ZPL-2.1" + "Zope Public License 2.1": "http://spdx.org/licenses/ZPL-2.1" + }, + "python2.7-zope.deprecation-4.1.2": { + "Zope Public License 2.1": "http://spdx.org/licenses/ZPL-2.1" + }, + "python2.7-zope.interface-4.1.3": { + "Zope Public License 2.1": "http://spdx.org/licenses/ZPL-2.1" } -} +} \ No newline at end of file diff --git a/rhodecode/config/middleware.py b/rhodecode/config/middleware.py --- a/rhodecode/config/middleware.py +++ b/rhodecode/config/middleware.py @@ -25,13 +25,15 @@ import logging from paste.registry import RegistryManager from paste.gzipper import make_gzip_middleware -from pylons.middleware import ErrorHandler, StatusCodeRedirect from pylons.wsgiapp import PylonsApp from pyramid.authorization import ACLAuthorizationPolicy from pyramid.config import Configurator from pyramid.static import static_view from pyramid.settings import asbool, aslist from pyramid.wsgi import wsgiapp +from pyramid.httpexceptions import HTTPError, HTTPInternalServerError +import pyramid.httpexceptions as httpexceptions +from pyramid.renderers import render_to_response, render from routes.middleware import RoutesMiddleware import routes.util @@ -87,38 +89,15 @@ def make_app(global_conf, full_stack=Tru app = csrf.OriginChecker(app, expected_origin, skip_urls=[routes.util.url_for('api')]) - # Add RoutesMiddleware. Currently we have two instances in the stack. This - # is the lower one to make the StatusCodeRedirect middleware happy. - # TODO: johbo: This is not optimal, search for a better solution. - app = RoutesMiddleware(app, config['routes.map']) - - # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) - if asbool(config['pdebug']): - from rhodecode.lib.profiler import ProfilingMiddleware - app = ProfilingMiddleware(app) - - # Protect from VCS Server error related pages when server is not available - vcs_server_enabled = asbool(config.get('vcs.server.enable', 'true')) - if not vcs_server_enabled: - app = DisableVCSPagesWrapper(app) if asbool(full_stack): # Appenlight monitoring and error handler app, appenlight_client = wrap_in_appenlight_if_enabled(app, config) - # Handle Python exceptions - app = ErrorHandler(app, global_conf, **config['pylons.errorware']) - # we want our low level middleware to get to the request ASAP. We don't # need any pylons stack middleware in them app = VCSMiddleware(app, config, appenlight_client) - # Display error documents for 401, 403, 404 status codes (and - # 500 when debug is disabled) - if asbool(config['debug']): - app = StatusCodeRedirect(app) - else: - app = StatusCodeRedirect(app, [400, 401, 403, 404, 500]) # Establish the Registry for this application app = RegistryManager(app) @@ -176,16 +155,69 @@ def add_pylons_compat_data(registry, glo registry._pylons_compat_settings = settings +def webob_to_pyramid_http_response(webob_response): + ResponseClass = httpexceptions.status_map[webob_response.status_int] + pyramid_response = ResponseClass(webob_response.status) + pyramid_response.status = webob_response.status + pyramid_response.headers.update(webob_response.headers) + if pyramid_response.headers['content-type'] == 'text/html': + pyramid_response.headers['content-type'] = 'text/html; charset=UTF-8' + return pyramid_response + + +def error_handler(exception, request): + # TODO: dan: replace the old pylons error controller with this + from rhodecode.model.settings import SettingsModel + from rhodecode.lib.utils2 import AttributeDict + + try: + rc_config = SettingsModel().get_all_settings() + except Exception: + log.exception('failed to fetch settings') + rc_config = {} + + base_response = HTTPInternalServerError() + # prefer original exception for the response since it may have headers set + if isinstance(exception, HTTPError): + base_response = exception + + c = AttributeDict() + c.error_message = base_response.status + c.error_explanation = base_response.explanation or str(base_response) + c.visual = AttributeDict() + + c.visual.rhodecode_support_url = ( + request.registry.settings.get('rhodecode_support_url') or + request.route_url('rhodecode_support') + ) + c.redirect_time = 0 + c.rhodecode_name = rc_config.get('rhodecode_title', '') + if not c.rhodecode_name: + c.rhodecode_name = 'Rhodecode' + + response = render_to_response( + '/errors/error_document.html', {'c': c}, request=request, + response=base_response) + + return response + + def includeme(config): settings = config.registry.settings + if asbool(settings.get('appenlight', 'false')): + config.include('appenlight_client.ext.pyramid_tween') + # Includes which are required. The application would fail without them. config.include('pyramid_mako') config.include('pyramid_beaker') + config.include('rhodecode.admin') config.include('rhodecode.authentication') config.include('rhodecode.login') config.include('rhodecode.tweens') config.include('rhodecode.api') + config.add_route( + 'rhodecode_support', 'https://rhodecode.com/help/', static=True) # Set the authorization policy. authz_policy = ACLAuthorizationPolicy() @@ -204,16 +236,52 @@ def includeme(config): for inc in includes: config.include(inc) + pylons_app = make_app( + config.registry._pylons_compat_global_config, + **config.registry._pylons_compat_settings) + config.registry._pylons_compat_config = pylons_app.config + + pylons_app_as_view = wsgiapp(pylons_app) + + # Protect from VCS Server error related pages when server is not available + vcs_server_enabled = asbool(settings.get('vcs.server.enable', 'true')) + if not vcs_server_enabled: + pylons_app_as_view = DisableVCSPagesWrapper(pylons_app_as_view) + + + def pylons_app_with_error_handler(context, request): + """ + Handle exceptions from rc pylons app: + + - old webob type exceptions get converted to pyramid exceptions + - pyramid exceptions are passed to the error handler view + """ + try: + response = pylons_app_as_view(context, request) + if 400 <= response.status_int <= 599: # webob type error responses + return error_handler( + webob_to_pyramid_http_response(response), request) + except HTTPError as e: # pyramid type exceptions + return error_handler(e, request) + except Exception: + if settings.get('debugtoolbar.enabled', False): + raise + return error_handler(HTTPInternalServerError(), request) + return response + # This is the glue which allows us to migrate in chunks. By registering the # pylons based application as the "Not Found" view in Pyramid, we will # fallback to the old application each time the new one does not yet know # how to handle a request. - pylons_app = make_app( - config.registry._pylons_compat_global_config, - **config.registry._pylons_compat_settings) - config.registry._pylons_compat_config = pylons_app.config - pylons_app_as_view = wsgiapp(pylons_app) - config.add_notfound_view(pylons_app_as_view) + config.add_notfound_view(pylons_app_with_error_handler) + + if settings.get('debugtoolbar.enabled', False): + # if toolbar, then only http type exceptions get caught and rendered + ExcClass = HTTPError + else: + # if no toolbar, then any exception gets caught and rendered + ExcClass = Exception + config.add_view(error_handler, context=ExcClass) def includeme_last(config): @@ -253,13 +321,16 @@ def wrap_app_in_wsgi_middlewares(pyramid # enable https redirects based on HTTP_X_URL_SCHEME set by proxy pyramid_app = HttpsFixup(pyramid_app, settings) - # Add RoutesMiddleware. Currently we have two instances in the stack. This - # is the upper one to support the pylons compatibility tween during + # Add RoutesMiddleware to support the pylons compatibility tween during # migration to pyramid. pyramid_app = RoutesMiddleware( pyramid_app, config.registry._pylons_compat_config['routes.map']) + if asbool(settings.get('appenlight', 'false')): + pyramid_app, _ = wrap_in_appenlight_if_enabled( + pyramid_app, config.registry._pylons_compat_config) + # TODO: johbo: Don't really see why we enable the gzip middleware when # serving static files, might be something that should have its own setting # as well? diff --git a/rhodecode/config/routing.py b/rhodecode/config/routing.py --- a/rhodecode/config/routing.py +++ b/rhodecode/config/routing.py @@ -166,10 +166,6 @@ def make_map(config): def check_int(environ, match_dict): return match_dict.get('id').isdigit() - # The ErrorController route (handles 404/500 error pages); it should - # likely stay at the top, ensuring it can always be resolved - rmap.connect('/error/{action}', controller='error') - rmap.connect('/error/{action}/{id}', controller='error') #========================================================================== # CUSTOM ROUTES HERE @@ -509,10 +505,6 @@ def make_map(config): m.connect('admin_settings_labs', '/settings/labs', action='settings_labs', conditions={'method': ['GET']}) - m.connect('admin_settings_open_source', '/settings/open_source', - action='settings_open_source', - conditions={'method': ['GET']}) - # ADMIN MY ACCOUNT with rmap.submapper(path_prefix=ADMIN_PREFIX, controller='admin/my_account') as m: diff --git a/rhodecode/config/utils.py b/rhodecode/config/utils.py --- a/rhodecode/config/utils.py +++ b/rhodecode/config/utils.py @@ -68,21 +68,25 @@ def configure_vcs(config): def initialize_database(config): - from rhodecode.lib.utils2 import engine_from_config + from rhodecode.lib.utils2 import engine_from_config, get_encryption_key engine = engine_from_config(config, 'sqlalchemy.db1.') - init_model(engine, encryption_key=config['beaker.session.secret']) + init_model(engine, encryption_key=get_encryption_key(config)) def initialize_test_environment(settings, test_env=None): if test_env is None: test_env = not int(os.environ.get('RC_NO_TMP_PATH', 0)) - from rhodecode.lib.utils import create_test_env, create_test_index + from rhodecode.lib.utils import ( + create_test_directory, create_test_database, create_test_repositories, + create_test_index) from rhodecode.tests import TESTS_TMP_PATH # test repos if test_env: - create_test_env(TESTS_TMP_PATH, settings) - create_test_index(TESTS_TMP_PATH, settings, True) + create_test_directory(TESTS_TMP_PATH) + create_test_database(TESTS_TMP_PATH, settings) + create_test_repositories(TESTS_TMP_PATH, settings) + create_test_index(TESTS_TMP_PATH, settings) def get_vcs_server_protocol(config): diff --git a/rhodecode/controllers/admin/repo_groups.py b/rhodecode/controllers/admin/repo_groups.py --- a/rhodecode/controllers/admin/repo_groups.py +++ b/rhodecode/controllers/admin/repo_groups.py @@ -99,7 +99,7 @@ class RepoGroupsController(BaseControlle if repo_group.user: data.update({'user': repo_group.user.username}) else: - replacement_user = User.get_first_admin().username + replacement_user = User.get_first_super_admin().username data.update({'user': replacement_user}) # fill repository group users @@ -246,11 +246,10 @@ class RepoGroupsController(BaseControlle repo_group=c.repo_group) repo_group_form = RepoGroupForm( - edit=True, - old_data=c.repo_group.get_dict(), + edit=True, old_data=c.repo_group.get_dict(), available_groups=c.repo_groups_choices, - can_create_in_root=can_create_in_root, - )() + can_create_in_root=can_create_in_root, allow_disabled=True)() + try: form_result = repo_group_form.to_python(dict(request.POST)) gr_name = form_result['group_name'] diff --git a/rhodecode/controllers/admin/repos.py b/rhodecode/controllers/admin/repos.py --- a/rhodecode/controllers/admin/repos.py +++ b/rhodecode/controllers/admin/repos.py @@ -248,9 +248,9 @@ class ReposController(BaseRepoController task_id = request.GET.get('task_id') if task_id and task_id not in ['None']: - from rhodecode import CELERY_ENABLED + import rhodecode from celery.result import AsyncResult - if CELERY_ENABLED: + if rhodecode.CELERY_ENABLED: task = AsyncResult(task_id) if task.failed(): msg = self._log_creation_exception(task.result, c.repo) @@ -307,9 +307,9 @@ class ReposController(BaseRepoController 'repo_group': repo.group.get_dict() if repo.group else {}, 'repo_type': repo.repo_type, } - _form = RepoForm(edit=True, old_data=old_data, - repo_groups=c.repo_groups_choices, - landing_revs=c.landing_revs_choices)() + _form = RepoForm( + edit=True, old_data=old_data, repo_groups=c.repo_groups_choices, + landing_revs=c.landing_revs_choices, allow_disabled=True)() try: form_result = _form.to_python(dict(request.POST)) diff --git a/rhodecode/controllers/admin/settings.py b/rhodecode/controllers/admin/settings.py --- a/rhodecode/controllers/admin/settings.py +++ b/rhodecode/controllers/admin/settings.py @@ -37,6 +37,7 @@ from pylons.i18n.translation import _, l from webob.exc import HTTPBadRequest import rhodecode +from rhodecode.admin.navigation import navigation_list from rhodecode.lib import auth from rhodecode.lib import helpers as h from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator @@ -47,7 +48,7 @@ from rhodecode.lib.utils2 import ( str2bool, safe_unicode, AttributeDict, safe_int) from rhodecode.lib.compat import OrderedDict from rhodecode.lib.ext_json import json -from rhodecode.lib.utils import jsonify, read_opensource_licenses +from rhodecode.lib.utils import jsonify from rhodecode.model.db import RhodeCodeUi, Repository from rhodecode.model.forms import ApplicationSettingsForm, \ @@ -60,8 +61,9 @@ from rhodecode.model.meta import Session from rhodecode.model.settings import ( IssueTrackerSettingsModel, VcsSettingsModel, SettingNotFound, SettingsModel) + from rhodecode.model.supervisor import SupervisorModel, SUPERVISOR_MASTER -from rhodecode.model.user import UserModel + log = logging.getLogger(__name__) @@ -78,7 +80,7 @@ class SettingsController(BaseController) super(SettingsController, self).__before__() c.labs_active = str2bool( rhodecode.CONFIG.get('labs_settings_active', 'false')) - c.navlist = navigation.get_navlist(request) + c.navlist = navigation_list(request) def _get_hg_ui_settings(self): ret = RhodeCodeUi.query().all() @@ -257,8 +259,8 @@ class SettingsController(BaseController) Session().add(sett) Session().commit() + SettingsModel().invalidate_settings_cache() h.flash(_('Updated application settings'), category='success') - except Exception: log.exception("Exception while updating application settings") h.flash( @@ -321,7 +323,7 @@ class SettingsController(BaseController) Session().add(sett) Session().commit() - + SettingsModel().invalidate_settings_cache() h.flash(_('Updated visualisation settings'), category='success') except Exception: log.exception("Exception updating visualization settings") @@ -403,6 +405,7 @@ class SettingsController(BaseController) Session().commit() + SettingsModel().invalidate_settings_cache() h.flash(_('Updated issue tracker entries'), category='success') return redirect(url('admin_settings_issuetracker')) @@ -523,6 +526,7 @@ class SettingsController(BaseController) def settings_system(self): """GET /admin/settings/system: All items in the collection""" # url('admin_settings_system') + snapshot = str2bool(request.GET.get('snapshot')) c.active = 'system' defaults = self._form_defaults() @@ -557,6 +561,35 @@ class SettingsController(BaseController) except TypeError: c.system_memory = 'NOT AVAILABLE' + rhodecode_ini_safe = rhodecode.CONFIG.copy() + blacklist = [ + 'rhodecode_license_key', + 'routes.map', + 'pylons.h', + 'pylons.app_globals', + 'pylons.environ_config', + 'sqlalchemy.db1.url', + ('app_conf', 'sqlalchemy.db1.url') + ] + for k in blacklist: + if isinstance(k, tuple): + section, key = k + if section in rhodecode_ini_safe: + rhodecode_ini_safe[section].pop(key, None) + else: + rhodecode_ini_safe.pop(k, None) + + c.rhodecode_ini_safe = rhodecode_ini_safe + + # TODO: marcink, figure out how to allow only selected users to do this + c.allowed_to_snapshot = False + + if snapshot: + if c.allowed_to_snapshot: + return render('admin/settings/settings_system_snapshot.html') + else: + h.flash('You are not allowed to do this', category='warning') + return htmlfill.render( render('admin/settings/settings.html'), defaults=defaults, @@ -708,6 +741,7 @@ class SettingsController(BaseController) category='error') else: Session().commit() + SettingsModel().invalidate_settings_cache() h.flash(_('Updated Labs settings'), category='success') return redirect(url('admin_settings_labs')) @@ -733,20 +767,6 @@ class SettingsController(BaseController) encoding='UTF-8', force_defaults=False) - @HasPermissionAllDecorator('hg.admin') - def settings_open_source(self): - # url('admin_settings_open_source') - - c.active = 'open_source' - c.opensource_licenses = collections.OrderedDict( - sorted(read_opensource_licenses().items(), key=lambda t: t[0])) - - return htmlfill.render( - render('admin/settings/settings.html'), - defaults=self._form_defaults(), - encoding='UTF-8', - force_defaults=False) - def _form_defaults(self): defaults = SettingsModel().get_all_settings() defaults.update(self._get_hg_ui_settings()) @@ -791,76 +811,3 @@ LabSetting = collections.namedtuple( help=lazy_ugettext('e.g. http://localhost:8080/') ), ] - - -NavListEntry = collections.namedtuple('NavListEntry', ['key', 'name', 'url']) - - -class NavEntry(object): - - def __init__(self, key, name, view_name, pyramid=False): - self.key = key - self.name = name - self.view_name = view_name - self.pyramid = pyramid - - def generate_url(self, request): - if self.pyramid: - if hasattr(request, 'route_path'): - return request.route_path(self.view_name) - else: - # TODO: johbo: Remove this after migrating to pyramid. - # We need the pyramid request here to generate URLs to pyramid - # views from within pylons views. - from pyramid.threadlocal import get_current_request - pyramid_request = get_current_request() - return pyramid_request.route_path(self.view_name) - else: - return url(self.view_name) - - -class NavigationRegistry(object): - - _base_entries = [ - NavEntry('global', lazy_ugettext('Global'), 'admin_settings_global'), - NavEntry('vcs', lazy_ugettext('VCS'), 'admin_settings_vcs'), - NavEntry('visual', lazy_ugettext('Visual'), 'admin_settings_visual'), - NavEntry('mapping', lazy_ugettext('Remap and Rescan'), - 'admin_settings_mapping'), - NavEntry('issuetracker', lazy_ugettext('Issue Tracker'), - 'admin_settings_issuetracker'), - NavEntry('email', lazy_ugettext('Email'), 'admin_settings_email'), - NavEntry('hooks', lazy_ugettext('Hooks'), 'admin_settings_hooks'), - NavEntry('search', lazy_ugettext('Full Text Search'), - 'admin_settings_search'), - NavEntry('system', lazy_ugettext('System Info'), - 'admin_settings_system'), - NavEntry('open_source', lazy_ugettext('Open Source Licenses'), - 'admin_settings_open_source'), - # TODO: marcink: we disable supervisor now until the supervisor stats - # page is fixed in the nix configuration - # NavEntry('supervisor', lazy_ugettext('Supervisor'), - # 'admin_settings_supervisor'), - ] - - def __init__(self): - self._registered_entries = collections.OrderedDict([ - (item.key, item) for item in self.__class__._base_entries - ]) - - # Add the labs entry when it's activated. - labs_active = str2bool( - rhodecode.CONFIG.get('labs_settings_active', 'false')) - if labs_active: - self.add_entry( - NavEntry('labs', lazy_ugettext('Labs'), 'admin_settings_labs')) - - def add_entry(self, entry): - self._registered_entries[entry.key] = entry - - def get_navlist(self, request): - navlist = [NavListEntry(i.key, i.name, i.generate_url(request)) - for i in self._registered_entries.values()] - return navlist - -navigation = NavigationRegistry() diff --git a/rhodecode/controllers/admin/user_groups.py b/rhodecode/controllers/admin/user_groups.py --- a/rhodecode/controllers/admin/user_groups.py +++ b/rhodecode/controllers/admin/user_groups.py @@ -88,7 +88,7 @@ class UserGroupsController(BaseControlle if user_group.user: data.update({'user': user_group.user.username}) else: - replacement_user = User.get_first_admin().username + replacement_user = User.get_first_super_admin().username data.update({'user': replacement_user}) return data @@ -209,9 +209,9 @@ class UserGroupsController(BaseControlle available_members = [safe_unicode(x[0]) for x in c.available_members] - users_group_form = UserGroupForm(edit=True, - old_data=c.user_group.get_dict(), - available_members=available_members)() + users_group_form = UserGroupForm( + edit=True, old_data=c.user_group.get_dict(), + available_members=available_members, allow_disabled=True)() try: form_result = users_group_form.to_python(request.POST) diff --git a/rhodecode/controllers/admin/users.py b/rhodecode/controllers/admin/users.py --- a/rhodecode/controllers/admin/users.py +++ b/rhodecode/controllers/admin/users.py @@ -216,6 +216,8 @@ class UsersController(BaseController): prefix_error=False, encoding="UTF-8", force_defaults=False) + except UserCreationError as e: + h.flash(e, 'error') except Exception: log.exception("Exception updating user") h.flash(_('Error occurred during update of user %s') @@ -401,7 +403,7 @@ class UsersController(BaseController): c.active = 'advanced' c.perm_user = AuthUser(user_id=user_id, ip_addr=self.ip_addr) c.personal_repo_group = RepoGroup.get_by_group_name(user.username) - c.first_admin = User.get_first_admin() + c.first_admin = User.get_first_super_admin() defaults = user.get_dict() # Interim workaround if the user participated on any pull requests as a diff --git a/rhodecode/controllers/error.py b/rhodecode/controllers/error.py deleted file mode 100644 --- a/rhodecode/controllers/error.py +++ /dev/null @@ -1,138 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (C) 2010-2016 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/ - -""" -RhodeCode error controller -""" - -import cgi -import logging -import os -import paste.fileapp - -from pylons import tmpl_context as c, request, config, url -from pylons.i18n.translation import _ -from pylons.middleware import media_path -from webob.exc import HTTPNotFound - -from rhodecode.lib.base import BaseController, render -from rhodecode.lib.utils2 import AttributeDict -from rhodecode.model.settings import SettingsModel - -log = logging.getLogger(__name__) - - -class ErrorController(BaseController): - """Generates error documents as and when they are required. - - The ErrorDocuments middleware forwards to ErrorController when error - related status codes are returned from the application. - - This behavior can be altered by changing the parameters to the - ErrorDocuments middleware in your config/middleware.py file. - """ - - def __before__(self): - - try: - rc_config = SettingsModel().get_all_settings() - except Exception: - log.exception('failed to fetch settings') - rc_config = {} - - c.visual = AttributeDict({}) - c.visual.rhodecode_support_url = ( - rc_config.get('rhodecode_support_url') or url('rhodecode_support')) - return - - def document(self): - resp = request.environ.get('pylons.original_response', None) - if not resp: - raise HTTPNotFound() - - c.rhodecode_name = config.get('rhodecode_title') - - log.debug('### %s ###' % resp.status) - - e = request.environ - c.serv_p = r'%(protocol)s://%(host)s/' % { - 'protocol': e.get('wsgi.url_scheme'), - 'host': e.get('HTTP_HOST'), - } - - c.error_message = cgi.escape(request.GET.get('code', str(resp.status))) - c.error_explanation = self.get_error_explanation(resp.status_int) - - # redirect to when error with given seconds - c.redirect_time = 0 - c.redirect_module = _('Home page') - c.url_redirect = "/" - - return render('/errors/error_document.html') - - def img(self, id): - """Serve Pylons' stock images""" - return self._serve_file(os.path.join(media_path, 'img', id)) - - def style(self, id): - """Serve Pylons' stock stylesheets""" - return self._serve_file(os.path.join(media_path, 'style', id)) - - def _serve_file(self, path): - """Call Paste's FileApp (a WSGI application) to serve the file - at the specified path - """ - fapp = paste.fileapp.FileApp(path) - return fapp(request.environ, self.start_response) - - def get_error_explanation(self, code): - """ get the error explanations of int codes - [400, 401, 403, 404, 500]""" - try: - code = int(code) - except Exception: - code = 500 - - if code == 400: - return _('The request could not be understood by the server' - ' due to malformed syntax.') - if code == 401: - return _('Unauthorized access to resource') - if code == 403: - return _("You don't have permission to view this page") - if code == 404: - return _('The resource could not be found') - if code == 500: - return _('The server encountered an unexpected condition' - ' which prevented it from fulfilling the request.') - - def vcs_unavailable(self): - c.rhodecode_name = config.get('rhodecode_title') - c.error_message = _('VCS Server Required') - c.error_explanation = _( - 'A VCS Server is required for this action. ' - 'There is currently no VCS Server configured.') - c.error_docs_link = 'https://docs.rhodecode.com/RhodeCode-Control/'\ - 'tasks/upgrade-from-cli.html#manually-changing-vcs-server-settings' - # redirect to when error with given seconds - c.redirect_time = 0 - c.redirect_module = _('Home page') - c.url_redirect = "/" - return render('/errors/error_document.html') diff --git a/rhodecode/controllers/home.py b/rhodecode/controllers/home.py --- a/rhodecode/controllers/home.py +++ b/rhodecode/controllers/home.py @@ -37,7 +37,7 @@ from rhodecode.lib.base import BaseContr from rhodecode.lib.index import searcher_from_config from rhodecode.lib.ext_json import json from rhodecode.lib.utils import jsonify -from rhodecode.lib.utils2 import safe_unicode +from rhodecode.lib.utils2 import safe_unicode, str2bool from rhodecode.model.db import Repository, RepoGroup from rhodecode.model.repo import RepoModel from rhodecode.model.repo_group import RepoGroupModel @@ -259,13 +259,16 @@ class HomeController(BaseController): @jsonify def user_autocomplete_data(self): query = request.GET.get('query') + active = str2bool(request.GET.get('active') or True) repo_model = RepoModel() - _users = repo_model.get_users(name_contains=query) + _users = repo_model.get_users( + name_contains=query, only_active=active) if request.GET.get('user_groups'): # extend with user groups - _user_groups = repo_model.get_user_groups(name_contains=query) + _user_groups = repo_model.get_user_groups( + name_contains=query, only_active=active) _users = _users + _user_groups return {'suggestions': _users} @@ -274,4 +277,13 @@ class HomeController(BaseController): @XHRRequired() @jsonify def user_group_autocomplete_data(self): - return {'suggestions': []} + query = request.GET.get('query') + active = str2bool(request.GET.get('active') or True) + + repo_model = RepoModel() + _user_groups = repo_model.get_user_groups( + name_contains=query, only_active=active) + _user_groups = _user_groups + + return {'suggestions': _user_groups} + diff --git a/rhodecode/events.py b/rhodecode/events.py --- a/rhodecode/events.py +++ b/rhodecode/events.py @@ -17,7 +17,8 @@ # and proprietary license terms, please see https://rhodecode.com/licenses/ from zope.interface import implementer -from rhodecode.interfaces import IUserRegistered +from rhodecode.interfaces import ( + IUserRegistered, IUserPreCreate, IUserPreUpdate) @implementer(IUserRegistered) @@ -29,3 +30,24 @@ class UserRegistered(object): def __init__(self, user, session): self.user = user self.session = session + + +@implementer(IUserPreCreate) +class UserPreCreate(object): + """ + An instance of this class is emitted as an :term:`event` before a new user + object is created. + """ + def __init__(self, user_data): + self.user_data = user_data + + +@implementer(IUserPreUpdate) +class UserPreUpdate(object): + """ + An instance of this class is emitted as an :term:`event` before a user + object is updated. + """ + def __init__(self, user, user_data): + self.user = user + self.user_data = user_data diff --git a/rhodecode/i18n/rhodecode.pot b/rhodecode/i18n/rhodecode.pot --- a/rhodecode/i18n/rhodecode.pot +++ b/rhodecode/i18n/rhodecode.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: rhodecode-enterprise-ce 4.0.0\n" +"Project-Id-Version: rhodecode-enterprise-ce 4.2.0\n" "Report-Msgid-Bugs-To: marcin@rhodecode.com\n" -"POT-Creation-Date: 2016-05-22 18:01+0000\n" +"POT-Creation-Date: 2016-06-28 10:55+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,44 +17,271 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" -#: rhodecode/authentication/routes.py:61 -#: rhodecode/controllers/admin/settings.py:825 +#: rhodecode/authentication/routes.py:60 +#: rhodecode/controllers/admin/settings.py:844 #: rhodecode/templates/admin/permissions/permissions.html:36 msgid "Global" msgstr "" +#: rhodecode/authentication/schema.py:35 +msgid "Enable or disable this authentication plugin." +msgstr "" + #: rhodecode/authentication/schema.py:37 -msgid "Enable or disable this authentication plugin." -msgstr "" - -#: rhodecode/authentication/schema.py:39 msgid "Enabled" msgstr "" -#: rhodecode/authentication/schema.py:45 +#: rhodecode/authentication/schema.py:43 msgid "Amount of seconds to cache the authentication call for this plugin. Useful for long calls like LDAP to improve the responsiveness of the authentication system (0 means disabled)." msgstr "" -#: rhodecode/authentication/schema.py:50 +#: rhodecode/authentication/schema.py:48 msgid "Auth Cache TTL" msgstr "" -#: rhodecode/authentication/views.py:108 +#: rhodecode/authentication/views.py:88 msgid "Errors exist when saving plugin settings. Please check the form inputs." msgstr "" -#: rhodecode/authentication/views.py:131 rhodecode/authentication/views.py:200 +#: rhodecode/authentication/views.py:101 rhodecode/authentication/views.py:170 msgid "Auth settings updated successfully." msgstr "" -#: rhodecode/authentication/views.py:205 +#: rhodecode/authentication/views.py:175 msgid "Errors exist when saving plugin setting. Please check the form inputs." msgstr "" -#: rhodecode/authentication/views.py:215 +#: rhodecode/authentication/views.py:185 msgid "Error occurred during update of auth settings." msgstr "" +#: rhodecode/authentication/plugins/auth_crowd.py:61 +msgid "The FQDN or IP of the Atlassian CROWD Server" +msgstr "" + +#: rhodecode/authentication/plugins/auth_crowd.py:63 +msgid "Host" +msgstr "" + +#: rhodecode/authentication/plugins/auth_crowd.py:68 +msgid "The Port in use by the Atlassian CROWD Server" +msgstr "" + +#: rhodecode/authentication/plugins/auth_crowd.py:70 +#: rhodecode/authentication/plugins/auth_ldap.py:84 +msgid "Port" +msgstr "" + +#: rhodecode/authentication/plugins/auth_crowd.py:76 +msgid "The Application Name to authenticate to CROWD" +msgstr "" + +#: rhodecode/authentication/plugins/auth_crowd.py:78 +msgid "Application Name" +msgstr "" + +#: rhodecode/authentication/plugins/auth_crowd.py:83 +msgid "The password to authenticate to CROWD" +msgstr "" + +#: rhodecode/authentication/plugins/auth_crowd.py:85 +msgid "Application Password" +msgstr "" + +#: rhodecode/authentication/plugins/auth_crowd.py:90 +msgid "A comma separated list of group names that identify users as RhodeCode Administrators" +msgstr "" + +#: rhodecode/authentication/plugins/auth_crowd.py:94 +msgid "Admin Groups" +msgstr "" + +#: rhodecode/authentication/plugins/auth_crowd.py:216 +msgid "CROWD" +msgstr "" + +#: rhodecode/authentication/plugins/auth_headers.py:55 +msgid "Header to extract the user from" +msgstr "" + +#: rhodecode/authentication/plugins/auth_headers.py:57 +msgid "Header" +msgstr "" + +#: rhodecode/authentication/plugins/auth_headers.py:62 +msgid "Header to extract the user from when main one fails" +msgstr "" + +#: rhodecode/authentication/plugins/auth_headers.py:64 +msgid "Fallback header" +msgstr "" + +#: rhodecode/authentication/plugins/auth_headers.py:69 +msgid "Perform cleaning of user, if passed user has @ in username then first part before @ is taken. If there's \\ in the username only the part after \\ is taken" +msgstr "" + +#: rhodecode/authentication/plugins/auth_headers.py:74 +msgid "Clean username" +msgstr "" + +#: rhodecode/authentication/plugins/auth_headers.py:99 +msgid "Headers" +msgstr "" + +#: rhodecode/authentication/plugins/auth_jasig_cas.py:63 +msgid "The url of the Jasig CAS REST service" +msgstr "" + +#: rhodecode/authentication/plugins/auth_jasig_cas.py:65 +#: rhodecode/templates/admin/gists/show.html:21 +msgid "URL" +msgstr "" + +#: rhodecode/authentication/plugins/auth_jasig_cas.py:93 +msgid "Jasig-CAS" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:75 +msgid "Host of the LDAP Server" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:77 +msgid "LDAP Host" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:82 +msgid "Port that the LDAP server is listening on" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:90 +msgid "User to connect to LDAP" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:93 +msgid "Account" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:98 +msgid "Password to connect to LDAP" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:101 +#: rhodecode/templates/login.html:50 rhodecode/templates/register.html:48 +#: rhodecode/templates/admin/my_account/my_account.html:30 +#: rhodecode/templates/admin/users/user_add.html:44 +#: rhodecode/templates/base/base.html:314 +#: rhodecode/templates/debug_style/login.html:45 +msgid "Password" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:106 +msgid "TLS Type" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:107 +msgid "Connection Security" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:113 +msgid "Require Cert over TLS?" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:114 +msgid "Certificate Checks" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:120 +msgid "Base DN to search (e.g., dc=mydomain,dc=com)" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:123 +msgid "Base DN" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:128 +msgid "Filter to narrow results (e.g., ou=Users, etc)" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:131 +msgid "LDAP Search Filter" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:136 +msgid "How deep to search LDAP" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:137 +msgid "LDAP Search Scope" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:143 +msgid "LDAP Attribute to map to user name" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:144 +msgid "The LDAP Login attribute of the CN must be specified" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:146 +msgid "Login Attribute" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:151 +msgid "LDAP Attribute to map to first name" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:154 +msgid "First Name Attribute" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:159 +msgid "LDAP Attribute to map to last name" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:162 +msgid "Last Name Attribute" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:167 +msgid "LDAP Attribute to map to email address" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:170 +msgid "Email Attribute" +msgstr "" + +#: rhodecode/authentication/plugins/auth_ldap.py:348 +msgid "LDAP" +msgstr "" + +#: rhodecode/authentication/plugins/auth_pam.py:60 +msgid "PAM service name to use for authentication." +msgstr "" + +#: rhodecode/authentication/plugins/auth_pam.py:62 +msgid "PAM service name" +msgstr "" + +#: rhodecode/authentication/plugins/auth_pam.py:67 +msgid "Regular expression for extracting user name/email etc. from Unix userinfo." +msgstr "" + +#: rhodecode/authentication/plugins/auth_pam.py:70 +msgid "Gecos Regex" +msgstr "" + +#: rhodecode/authentication/plugins/auth_pam.py:98 +msgid "PAM" +msgstr "" + +#: rhodecode/authentication/plugins/auth_rhodecode.py:68 +msgid "Rhodecode" +msgstr "" + +#: rhodecode/authentication/plugins/auth_token.py:71 +msgid "Rhodecode Token Auth" +msgstr "" + #: rhodecode/controllers/changelog.py:90 rhodecode/controllers/compare.py:63 #: rhodecode/controllers/pullrequests.py:279 msgid "There are no commits yet" @@ -92,8 +319,8 @@ msgid "No such commit exists for this re msgstr "" #: rhodecode/controllers/changeset.py:335 -#: rhodecode/controllers/pullrequests.py:744 -#: rhodecode/model/pull_request.py:828 +#: rhodecode/controllers/pullrequests.py:746 +#: rhodecode/model/pull_request.py:836 #, python-format msgid "Status change %(transition_icon)s %(status)s" msgstr "" @@ -106,61 +333,29 @@ msgstr "" msgid "Select commit" msgstr "" -#: rhodecode/controllers/compare.py:142 +#: rhodecode/controllers/compare.py:139 #, python-format msgid "Could not find the original repo: %(repo)s" msgstr "" -#: rhodecode/controllers/compare.py:150 +#: rhodecode/controllers/compare.py:147 #, python-format msgid "Could not find the other repo: %(repo)s" msgstr "" -#: rhodecode/controllers/compare.py:159 +#: rhodecode/controllers/compare.py:156 msgid "The comparison of two different kinds of remote repos is not available" msgstr "" -#: rhodecode/controllers/compare.py:186 +#: rhodecode/controllers/compare.py:190 msgid "Could not compare repos with different large file settings" msgstr "" -#: rhodecode/controllers/compare.py:223 +#: rhodecode/controllers/compare.py:226 #, python-format msgid "Repositories unrelated. Cannot compare commit %(commit1)s from repository %(repo1)s with commit %(commit2)s from repository %(repo2)s." msgstr "" -#: rhodecode/controllers/error.py:85 rhodecode/controllers/error.py:136 -msgid "Home page" -msgstr "" - -#: rhodecode/controllers/error.py:114 -msgid "The request could not be understood by the server due to malformed syntax." -msgstr "" - -#: rhodecode/controllers/error.py:117 -msgid "Unauthorized access to resource" -msgstr "" - -#: rhodecode/controllers/error.py:119 -msgid "You don't have permission to view this page" -msgstr "" - -#: rhodecode/controllers/error.py:121 -msgid "The resource could not be found" -msgstr "" - -#: rhodecode/controllers/error.py:123 -msgid "The server encountered an unexpected condition which prevented it from fulfilling the request." -msgstr "" - -#: rhodecode/controllers/error.py:128 -msgid "VCS Server Required" -msgstr "" - -#: rhodecode/controllers/error.py:129 -msgid "A VCS Server is required for this action. There is currently no VCS Server configured." -msgstr "" - #: rhodecode/controllers/feed.py:70 #, python-format msgid "Changes on %s repository" @@ -268,7 +463,7 @@ msgid "Changesets" msgstr "" #: rhodecode/controllers/files.py:1035 rhodecode/controllers/summary.py:256 -#: rhodecode/model/pull_request.py:1037 rhodecode/model/scm.py:783 +#: rhodecode/model/pull_request.py:1051 rhodecode/model/scm.py:783 #: rhodecode/templates/base/vcs_settings.html:138 msgid "Branches" msgstr "" @@ -283,21 +478,26 @@ msgstr "" msgid "An error occurred during repository forking %s" msgstr "" -#: rhodecode/controllers/home.py:174 +#: rhodecode/controllers/home.py:205 msgid "Groups" msgstr "" -#: rhodecode/controllers/home.py:181 rhodecode/controllers/home.py:203 +#: rhodecode/controllers/home.py:212 rhodecode/controllers/home.py:247 #: rhodecode/controllers/pullrequests.py:382 #: rhodecode/templates/admin/repo_groups/repo_group_edit_perms.html:128 #: rhodecode/templates/admin/repos/repo_add.html:15 #: rhodecode/templates/admin/repos/repo_add.html:19 #: rhodecode/templates/admin/users/user_edit_advanced.html:11 -#: rhodecode/templates/base/base.html:79 rhodecode/templates/base/base.html:147 -#: rhodecode/templates/base/base.html:621 +#: rhodecode/templates/base/base.html:79 rhodecode/templates/base/base.html:149 +#: rhodecode/templates/base/base.html:626 msgid "Repositories" msgstr "" +#: rhodecode/controllers/home.py:225 +#, python-format +msgid "Commits in %(repo)s" +msgstr "" + #: rhodecode/controllers/journal.py:107 rhodecode/controllers/journal.py:150 msgid "public journal" msgstr "" @@ -306,30 +506,6 @@ msgstr "" msgid "journal" msgstr "" -#: rhodecode/controllers/login.py:227 rhodecode/controllers/login.py:281 -msgid "bad captcha" -msgstr "" - -#: rhodecode/controllers/login.py:241 -msgid "You have successfully registered with RhodeCode" -msgstr "" - -#: rhodecode/controllers/login.py:286 -msgid "Your password reset link was sent" -msgstr "" - -#: rhodecode/controllers/login.py:307 -msgid "Your password reset was successful, a new password has been sent to your email" -msgstr "" - -#: rhodecode/controllers/login.py:340 -msgid "There was an error during OAuth processing." -msgstr "" - -#: rhodecode/controllers/login.py:406 -msgid "You need to finish registration process to bind your external identity to your account or sign in to existing account" -msgstr "" - #: rhodecode/controllers/pullrequests.py:293 msgid "Commit does not exist" msgstr "" @@ -378,24 +554,28 @@ msgstr "" msgid "Pull request reviewer approval is pending." msgstr "" -#: rhodecode/controllers/pullrequests.py:629 +#: rhodecode/controllers/pullrequests.py:593 +msgid "Pull request was successfully merged and closed." +msgstr "" + +#: rhodecode/controllers/pullrequests.py:631 msgid "Successfully deleted pull request" msgstr "" -#: rhodecode/controllers/pullrequests.py:662 +#: rhodecode/controllers/pullrequests.py:664 msgid "Reviewer approval is pending." msgstr "" -#: rhodecode/controllers/pullrequests.py:704 +#: rhodecode/controllers/pullrequests.py:706 msgid "Close Pull Request" msgstr "" -#: rhodecode/controllers/pullrequests.py:748 -#: rhodecode/model/pull_request.py:832 +#: rhodecode/controllers/pullrequests.py:750 +#: rhodecode/model/pull_request.py:840 msgid "Closing with" msgstr "" -#: rhodecode/controllers/pullrequests.py:793 +#: rhodecode/controllers/pullrequests.py:795 #, python-format msgid "Closing pull request on other statuses than rejected or approved is forbidden. Calculated status from all reviewers is currently: %s" msgstr "" @@ -425,38 +605,38 @@ msgid "Error occurred during update of d msgstr "" #: rhodecode/controllers/admin/gists.py:59 -#: rhodecode/controllers/admin/my_account.py:308 -#: rhodecode/controllers/admin/users.py:434 +#: rhodecode/controllers/admin/my_account.py:307 +#: rhodecode/controllers/admin/users.py:436 msgid "forever" msgstr "" #: rhodecode/controllers/admin/gists.py:60 -#: rhodecode/controllers/admin/my_account.py:309 -#: rhodecode/controllers/admin/users.py:435 +#: rhodecode/controllers/admin/my_account.py:308 +#: rhodecode/controllers/admin/users.py:437 msgid "5 minutes" msgstr "" #: rhodecode/controllers/admin/gists.py:61 -#: rhodecode/controllers/admin/my_account.py:310 -#: rhodecode/controllers/admin/users.py:436 +#: rhodecode/controllers/admin/my_account.py:309 +#: rhodecode/controllers/admin/users.py:438 msgid "1 hour" msgstr "" #: rhodecode/controllers/admin/gists.py:62 -#: rhodecode/controllers/admin/my_account.py:311 -#: rhodecode/controllers/admin/users.py:437 +#: rhodecode/controllers/admin/my_account.py:310 +#: rhodecode/controllers/admin/users.py:439 msgid "1 day" msgstr "" #: rhodecode/controllers/admin/gists.py:63 -#: rhodecode/controllers/admin/my_account.py:312 -#: rhodecode/controllers/admin/users.py:438 +#: rhodecode/controllers/admin/my_account.py:311 +#: rhodecode/controllers/admin/users.py:440 msgid "1 month" msgstr "" #: rhodecode/controllers/admin/gists.py:67 -#: rhodecode/controllers/admin/my_account.py:314 -#: rhodecode/controllers/admin/users.py:440 +#: rhodecode/controllers/admin/my_account.py:313 +#: rhodecode/controllers/admin/users.py:442 msgid "Lifetime" msgstr "" @@ -505,68 +685,64 @@ msgstr "" msgid "%(expiry)s - current value" msgstr "" -#: rhodecode/controllers/admin/my_account.py:71 +#: rhodecode/controllers/admin/my_account.py:70 msgid "You can't edit this user since it's crucial for entire application" msgstr "" -#: rhodecode/controllers/admin/my_account.py:129 +#: rhodecode/controllers/admin/my_account.py:128 msgid "Your account was updated successfully" msgstr "" -#: rhodecode/controllers/admin/my_account.py:144 -#: rhodecode/controllers/admin/users.py:221 +#: rhodecode/controllers/admin/my_account.py:143 +#: rhodecode/controllers/admin/users.py:223 #, python-format msgid "Error occurred during update of user %s" msgstr "" -#: rhodecode/controllers/admin/my_account.py:203 +#: rhodecode/controllers/admin/my_account.py:202 msgid "Successfully updated password" msgstr "" -#: rhodecode/controllers/admin/my_account.py:214 +#: rhodecode/controllers/admin/my_account.py:213 msgid "Error occurred during update of user password" msgstr "" -#: rhodecode/controllers/admin/my_account.py:262 -#: rhodecode/controllers/admin/users.py:614 +#: rhodecode/controllers/admin/my_account.py:261 +#: rhodecode/controllers/admin/users.py:616 #, python-format msgid "Added new email address `%s` for user account" msgstr "" -#: rhodecode/controllers/admin/my_account.py:269 -#: rhodecode/controllers/admin/users.py:621 +#: rhodecode/controllers/admin/my_account.py:268 +#: rhodecode/controllers/admin/users.py:623 msgid "An error occurred during email saving" msgstr "" -#: rhodecode/controllers/admin/my_account.py:279 -#: rhodecode/controllers/admin/users.py:636 +#: rhodecode/controllers/admin/my_account.py:278 +#: rhodecode/controllers/admin/users.py:638 msgid "Removed email address from user account" msgstr "" -#: rhodecode/controllers/admin/my_account.py:317 -#: rhodecode/controllers/admin/users.py:443 +#: rhodecode/controllers/admin/my_account.py:316 +#: rhodecode/controllers/admin/users.py:445 msgid "Role" msgstr "" -#: rhodecode/controllers/admin/my_account.py:330 -#: rhodecode/controllers/admin/users.py:467 +#: rhodecode/controllers/admin/my_account.py:329 +#: rhodecode/controllers/admin/users.py:469 msgid "Auth token successfully created" msgstr "" -#: rhodecode/controllers/admin/my_account.py:343 -#: rhodecode/controllers/admin/users.py:486 +#: rhodecode/controllers/admin/my_account.py:342 +#: rhodecode/controllers/admin/users.py:488 msgid "Auth token successfully reset" msgstr "" -#: rhodecode/controllers/admin/my_account.py:347 -#: rhodecode/controllers/admin/users.py:490 +#: rhodecode/controllers/admin/my_account.py:346 +#: rhodecode/controllers/admin/users.py:492 msgid "Auth token successfully deleted" msgstr "" -#: rhodecode/controllers/admin/my_account.py:371 -msgid "OAuth token successfully deleted" -msgstr "" - #: rhodecode/controllers/admin/permissions.py:111 msgid "Application permissions updated successfully" msgstr "" @@ -595,46 +771,46 @@ msgstr "" msgid "Error occurred during creation of repository group %s" msgstr "" -#: rhodecode/controllers/admin/repo_groups.py:259 +#: rhodecode/controllers/admin/repo_groups.py:258 #, python-format msgid "Updated repository group %s" msgstr "" -#: rhodecode/controllers/admin/repo_groups.py:275 +#: rhodecode/controllers/admin/repo_groups.py:274 #, python-format msgid "Error occurred during update of repository group %s" msgstr "" -#: rhodecode/controllers/admin/repo_groups.py:297 +#: rhodecode/controllers/admin/repo_groups.py:296 #, python-format msgid "This group contains %(num)d repository and cannot be deleted" msgid_plural "This group contains %(num)d repositories and cannot be deleted" msgstr[0] "" msgstr[1] "" -#: rhodecode/controllers/admin/repo_groups.py:306 +#: rhodecode/controllers/admin/repo_groups.py:305 #, python-format msgid "This group contains %(num)d subgroup and cannot be deleted" msgid_plural "This group contains %(num)d subgroups and cannot be deleted" msgstr[0] "" msgstr[1] "" -#: rhodecode/controllers/admin/repo_groups.py:313 +#: rhodecode/controllers/admin/repo_groups.py:312 #, python-format msgid "Removed repository group %s" msgstr "" -#: rhodecode/controllers/admin/repo_groups.py:318 +#: rhodecode/controllers/admin/repo_groups.py:317 #, python-format msgid "Error occurred during deletion of repository group %s" msgstr "" -#: rhodecode/controllers/admin/repo_groups.py:389 -#: rhodecode/controllers/admin/user_groups.py:323 +#: rhodecode/controllers/admin/repo_groups.py:388 +#: rhodecode/controllers/admin/user_groups.py:325 msgid "Cannot change permission for yourself as admin" msgstr "" -#: rhodecode/controllers/admin/repo_groups.py:406 +#: rhodecode/controllers/admin/repo_groups.py:405 msgid "Repository Group permissions updated" msgstr "" @@ -782,18 +958,18 @@ msgid "Error occurred during deleting is msgstr "" #: rhodecode/controllers/admin/repos.py:720 -#: rhodecode/controllers/admin/settings.py:361 +#: rhodecode/controllers/admin/settings.py:362 msgid "Removed issue tracker entry" msgstr "" #: rhodecode/controllers/admin/repos.py:750 -#: rhodecode/controllers/admin/settings.py:406 +#: rhodecode/controllers/admin/settings.py:408 msgid "Updated issue tracker entries" msgstr "" #: rhodecode/controllers/admin/repos.py:809 -#: rhodecode/controllers/admin/settings.py:140 -#: rhodecode/controllers/admin/settings.py:686 +#: rhodecode/controllers/admin/settings.py:141 +#: rhodecode/controllers/admin/settings.py:718 msgid "Some form inputs contain invalid data." msgstr "" @@ -802,114 +978,114 @@ msgid "Error occurred during updating re msgstr "" #: rhodecode/controllers/admin/repos.py:831 -#: rhodecode/controllers/admin/settings.py:166 +#: rhodecode/controllers/admin/settings.py:167 msgid "Updated VCS settings" msgstr "" -#: rhodecode/controllers/admin/settings.py:162 -#: rhodecode/controllers/admin/settings.py:265 +#: rhodecode/controllers/admin/settings.py:163 +#: rhodecode/controllers/admin/settings.py:266 msgid "Error occurred during updating application settings" msgstr "" -#: rhodecode/controllers/admin/settings.py:209 +#: rhodecode/controllers/admin/settings.py:210 #, python-format msgid "Repositories successfully rescanned added: %s ; removed: %s" msgstr "" -#: rhodecode/controllers/admin/settings.py:260 +#: rhodecode/controllers/admin/settings.py:262 msgid "Updated application settings" msgstr "" -#: rhodecode/controllers/admin/settings.py:325 +#: rhodecode/controllers/admin/settings.py:326 msgid "Updated visualisation settings" msgstr "" -#: rhodecode/controllers/admin/settings.py:328 +#: rhodecode/controllers/admin/settings.py:329 msgid "Error occurred during updating visualisation settings" msgstr "" -#: rhodecode/controllers/admin/settings.py:419 +#: rhodecode/controllers/admin/settings.py:421 msgid "Please enter email address" msgstr "" -#: rhodecode/controllers/admin/settings.py:437 +#: rhodecode/controllers/admin/settings.py:439 msgid "Send email task created" msgstr "" -#: rhodecode/controllers/admin/settings.py:470 +#: rhodecode/controllers/admin/settings.py:472 msgid "Added new hook" msgstr "" -#: rhodecode/controllers/admin/settings.py:485 +#: rhodecode/controllers/admin/settings.py:487 msgid "Updated hooks" msgstr "" -#: rhodecode/controllers/admin/settings.py:489 +#: rhodecode/controllers/admin/settings.py:491 msgid "Error occurred during hook creation" msgstr "" -#: rhodecode/controllers/admin/settings.py:536 +#: rhodecode/controllers/admin/settings.py:539 #, python-format msgid "Critical: your disk space is very low %s%% usedpercent" msgstr "" -#: rhodecode/controllers/admin/settings.py:540 +#: rhodecode/controllers/admin/settings.py:543 #, python-format msgid "Warning: your disk space is running low %s%% usedpercent" msgstr "" -#: rhodecode/controllers/admin/settings.py:707 +#: rhodecode/controllers/admin/settings.py:739 msgid "Error occurred during updating labs settings" msgstr "" -#: rhodecode/controllers/admin/settings.py:711 +#: rhodecode/controllers/admin/settings.py:744 msgid "Updated Labs settings" msgstr "" -#: rhodecode/controllers/admin/settings.py:775 +#: rhodecode/controllers/admin/settings.py:794 msgid "Mercurial server-side merge" msgstr "" -#: rhodecode/controllers/admin/settings.py:776 +#: rhodecode/controllers/admin/settings.py:795 msgid "Use rebase instead of creating a merge commit when merging via web interface" msgstr "" -#: rhodecode/controllers/admin/settings.py:782 +#: rhodecode/controllers/admin/settings.py:801 msgid "Subversion HTTP Support" msgstr "" -#: rhodecode/controllers/admin/settings.py:783 +#: rhodecode/controllers/admin/settings.py:802 msgid "Proxy subversion HTTP requests" msgstr "" -#: rhodecode/controllers/admin/settings.py:789 +#: rhodecode/controllers/admin/settings.py:808 msgid "Subversion HTTP Server URL" msgstr "" -#: rhodecode/controllers/admin/settings.py:791 +#: rhodecode/controllers/admin/settings.py:810 msgid "e.g. http://localhost:8080/" msgstr "" -#: rhodecode/controllers/admin/settings.py:826 +#: rhodecode/controllers/admin/settings.py:845 #: rhodecode/templates/admin/repos/repo_edit.html:48 msgid "VCS" msgstr "" -#: rhodecode/controllers/admin/settings.py:827 +#: rhodecode/controllers/admin/settings.py:846 msgid "Visual" msgstr "" -#: rhodecode/controllers/admin/settings.py:828 +#: rhodecode/controllers/admin/settings.py:847 msgid "Remap and Rescan" msgstr "" -#: rhodecode/controllers/admin/settings.py:830 +#: rhodecode/controllers/admin/settings.py:849 #: rhodecode/templates/admin/repos/repo_edit.html:54 msgid "Issue Tracker" msgstr "" -#: rhodecode/controllers/admin/settings.py:832 -#: rhodecode/templates/register.html:51 +#: rhodecode/controllers/admin/settings.py:851 +#: rhodecode/templates/register.html:76 #: rhodecode/templates/admin/my_account/my_account_profile.html:48 #: rhodecode/templates/admin/my_account/my_account_profile_edit.html:94 #: rhodecode/templates/admin/users/user_add.html:86 @@ -919,69 +1095,69 @@ msgstr "" msgid "Email" msgstr "" -#: rhodecode/controllers/admin/settings.py:833 +#: rhodecode/controllers/admin/settings.py:852 msgid "Hooks" msgstr "" -#: rhodecode/controllers/admin/settings.py:834 +#: rhodecode/controllers/admin/settings.py:853 msgid "Full Text Search" msgstr "" -#: rhodecode/controllers/admin/settings.py:836 +#: rhodecode/controllers/admin/settings.py:855 #: rhodecode/templates/admin/settings/settings_system.html:47 msgid "System Info" msgstr "" -#: rhodecode/controllers/admin/settings.py:838 +#: rhodecode/controllers/admin/settings.py:857 msgid "Open Source Licenses" msgstr "" -#: rhodecode/controllers/admin/settings.py:856 +#: rhodecode/controllers/admin/settings.py:875 msgid "Labs" msgstr "" -#: rhodecode/controllers/admin/user_groups.py:167 +#: rhodecode/controllers/admin/user_groups.py:168 #, python-format msgid "Created user group %(user_group_link)s" msgstr "" -#: rhodecode/controllers/admin/user_groups.py:181 +#: rhodecode/controllers/admin/user_groups.py:182 #, python-format msgid "Error occurred during creation of user group %s" msgstr "" -#: rhodecode/controllers/admin/user_groups.py:221 +#: rhodecode/controllers/admin/user_groups.py:223 #, python-format msgid "Updated user group %s" msgstr "" -#: rhodecode/controllers/admin/user_groups.py:236 +#: rhodecode/controllers/admin/user_groups.py:238 #, python-format msgid "Error occurred during update of user group %s" msgstr "" -#: rhodecode/controllers/admin/user_groups.py:258 +#: rhodecode/controllers/admin/user_groups.py:260 msgid "Successfully deleted user group" msgstr "" -#: rhodecode/controllers/admin/user_groups.py:263 +#: rhodecode/controllers/admin/user_groups.py:265 msgid "An error occurred during deletion of user group" msgstr "" -#: rhodecode/controllers/admin/user_groups.py:331 +#: rhodecode/controllers/admin/user_groups.py:333 msgid "Target group cannot be the same" msgstr "" -#: rhodecode/controllers/admin/user_groups.py:337 +#: rhodecode/controllers/admin/user_groups.py:339 msgid "User Group permissions updated" msgstr "" -#: rhodecode/controllers/admin/user_groups.py:422 +#: rhodecode/controllers/admin/user_groups.py:424 msgid "User Group global permissions updated successfully" msgstr "" -#: rhodecode/controllers/admin/user_groups.py:438 -#: rhodecode/controllers/admin/users.py:564 +#: rhodecode/controllers/admin/user_groups.py:440 +#: rhodecode/controllers/admin/users.py:566 msgid "An error occurred during permissions saving" msgstr "" @@ -999,100 +1175,100 @@ msgstr "" msgid "User updated successfully" msgstr "" -#: rhodecode/controllers/admin/users.py:255 +#: rhodecode/controllers/admin/users.py:257 #, python-format msgid "Detached %s repositories" msgstr "" -#: rhodecode/controllers/admin/users.py:260 +#: rhodecode/controllers/admin/users.py:262 #, python-format msgid "Deleted %s repositories" msgstr "" -#: rhodecode/controllers/admin/users.py:268 +#: rhodecode/controllers/admin/users.py:270 #, python-format msgid "Detached %s repository groups" msgstr "" -#: rhodecode/controllers/admin/users.py:273 +#: rhodecode/controllers/admin/users.py:275 #, python-format msgid "Deleted %s repository groups" msgstr "" -#: rhodecode/controllers/admin/users.py:281 +#: rhodecode/controllers/admin/users.py:283 #, python-format msgid "Detached %s user groups" msgstr "" -#: rhodecode/controllers/admin/users.py:286 +#: rhodecode/controllers/admin/users.py:288 #, python-format msgid "Deleted %s user groups" msgstr "" -#: rhodecode/controllers/admin/users.py:297 +#: rhodecode/controllers/admin/users.py:299 msgid "Successfully deleted user" msgstr "" -#: rhodecode/controllers/admin/users.py:303 +#: rhodecode/controllers/admin/users.py:305 msgid "An error occurred during deletion of user" msgstr "" -#: rhodecode/controllers/admin/users.py:322 -msgid "Force password change disabled for user" -msgstr "" - #: rhodecode/controllers/admin/users.py:324 +msgid "Force password change disabled for user" +msgstr "" + +#: rhodecode/controllers/admin/users.py:326 msgid "Force password change enabled for user" msgstr "" -#: rhodecode/controllers/admin/users.py:328 +#: rhodecode/controllers/admin/users.py:330 msgid "An error occurred during password reset for user" msgstr "" -#: rhodecode/controllers/admin/users.py:354 +#: rhodecode/controllers/admin/users.py:356 #, python-format msgid "Created repository group `%s`" msgstr "" -#: rhodecode/controllers/admin/users.py:358 +#: rhodecode/controllers/admin/users.py:360 msgid "An error occurred during repository group creation for user" msgstr "" -#: rhodecode/controllers/admin/users.py:377 -#: rhodecode/controllers/admin/users.py:398 -#: rhodecode/controllers/admin/users.py:428 -#: rhodecode/controllers/admin/users.py:459 -#: rhodecode/controllers/admin/users.py:476 -#: rhodecode/controllers/admin/users.py:499 -#: rhodecode/controllers/admin/users.py:573 -#: rhodecode/controllers/admin/users.py:586 -#: rhodecode/controllers/admin/users.py:644 +#: rhodecode/controllers/admin/users.py:379 +#: rhodecode/controllers/admin/users.py:400 +#: rhodecode/controllers/admin/users.py:430 +#: rhodecode/controllers/admin/users.py:461 +#: rhodecode/controllers/admin/users.py:478 +#: rhodecode/controllers/admin/users.py:501 +#: rhodecode/controllers/admin/users.py:575 +#: rhodecode/controllers/admin/users.py:588 +#: rhodecode/controllers/admin/users.py:646 msgid "You can't edit this user" msgstr "" -#: rhodecode/controllers/admin/users.py:412 +#: rhodecode/controllers/admin/users.py:414 msgid "The user participates as reviewer in pull requests and cannot be deleted. You can set the user to \"inactive\" instead of deleting it." msgstr "" -#: rhodecode/controllers/admin/users.py:548 +#: rhodecode/controllers/admin/users.py:550 msgid "User global permissions updated successfully" msgstr "" -#: rhodecode/controllers/admin/users.py:676 +#: rhodecode/controllers/admin/users.py:678 #, python-format msgid "An error occurred during ip saving:%s" msgstr "" -#: rhodecode/controllers/admin/users.py:691 +#: rhodecode/controllers/admin/users.py:693 msgid "An error occurred during ip saving" msgstr "" -#: rhodecode/controllers/admin/users.py:695 +#: rhodecode/controllers/admin/users.py:697 #, python-format msgid "Added ips %s to user whitelist" msgstr "" -#: rhodecode/controllers/admin/users.py:713 +#: rhodecode/controllers/admin/users.py:715 msgid "Removed ip address from user whitelist" msgstr "" @@ -1219,25 +1395,25 @@ msgstr "" msgid "Commit not found" msgstr "" -#: rhodecode/lib/auth.py:1106 +#: rhodecode/lib/auth.py:1180 #, python-format msgid "IP %s not allowed" msgstr "" -#: rhodecode/lib/auth.py:1180 +#: rhodecode/lib/auth.py:1254 msgid "You need to be a registered user to perform this action" msgstr "" -#: rhodecode/lib/auth.py:1227 +#: rhodecode/lib/auth.py:1302 #, python-format msgid "Action not supported for %s." msgstr "" -#: rhodecode/lib/auth.py:1264 +#: rhodecode/lib/auth.py:1339 msgid "You need to be signed in to view this page" msgstr "" -#: rhodecode/lib/base.py:513 +#: rhodecode/lib/base.py:511 #, python-format msgid "The repository at %(repo_name)s cannot be located." msgstr "" @@ -1254,36 +1430,36 @@ msgstr "" msgid "No changes detected" msgstr "" -#: rhodecode/lib/helpers.py:1246 +#: rhodecode/lib/helpers.py:1434 #, python-format msgid " and %s more" msgstr "" -#: rhodecode/lib/helpers.py:1250 +#: rhodecode/lib/helpers.py:1438 msgid "No Files" msgstr "" -#: rhodecode/lib/helpers.py:1323 +#: rhodecode/lib/helpers.py:1511 msgid "new file" msgstr "" -#: rhodecode/lib/helpers.py:1326 +#: rhodecode/lib/helpers.py:1514 msgid "mod" msgstr "" -#: rhodecode/lib/helpers.py:1329 +#: rhodecode/lib/helpers.py:1517 msgid "del" msgstr "" -#: rhodecode/lib/helpers.py:1332 +#: rhodecode/lib/helpers.py:1520 msgid "rename" msgstr "" -#: rhodecode/lib/helpers.py:1337 +#: rhodecode/lib/helpers.py:1525 msgid "chmod" msgstr "" -#: rhodecode/lib/helpers.py:1579 +#: rhodecode/lib/helpers.py:1767 msgid "" "Example filter terms:\n" " repository:vcs\n" @@ -1302,299 +1478,92 @@ msgid "" " \"username:test AND repository:test*\"\n" msgstr "" -#: rhodecode/lib/helpers.py:1599 +#: rhodecode/lib/helpers.py:1787 #, python-format msgid "%s repository is not mapped to db perhaps it was created or renamed from the filesystem please run the application again in order to rescan repositories" msgstr "" -#: rhodecode/lib/utils2.py:446 +#: rhodecode/lib/utils2.py:453 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "" msgstr[1] "" -#: rhodecode/lib/utils2.py:447 +#: rhodecode/lib/utils2.py:454 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "" msgstr[1] "" -#: rhodecode/lib/utils2.py:448 +#: rhodecode/lib/utils2.py:455 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" msgstr[1] "" -#: rhodecode/lib/utils2.py:449 +#: rhodecode/lib/utils2.py:456 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" -#: rhodecode/lib/utils2.py:450 +#: rhodecode/lib/utils2.py:457 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" -#: rhodecode/lib/utils2.py:451 +#: rhodecode/lib/utils2.py:458 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "" msgstr[1] "" -#: rhodecode/lib/utils2.py:469 +#: rhodecode/lib/utils2.py:476 #, python-format msgid "in %s" msgstr "" -#: rhodecode/lib/utils2.py:475 +#: rhodecode/lib/utils2.py:482 #, python-format msgid "%s ago" msgstr "" -#: rhodecode/lib/utils2.py:485 +#: rhodecode/lib/utils2.py:492 #, python-format msgid "%s, %s ago" msgstr "" -#: rhodecode/lib/utils2.py:487 +#: rhodecode/lib/utils2.py:494 #, python-format msgid "in %s, %s" msgstr "" -#: rhodecode/lib/utils2.py:489 +#: rhodecode/lib/utils2.py:496 #, python-format msgid "%s and %s" msgstr "" -#: rhodecode/lib/utils2.py:491 +#: rhodecode/lib/utils2.py:498 #, python-format msgid "%s and %s ago" msgstr "" -#: rhodecode/lib/utils2.py:493 +#: rhodecode/lib/utils2.py:500 #, python-format msgid "in %s and %s" msgstr "" -#: rhodecode/lib/utils2.py:497 +#: rhodecode/lib/utils2.py:504 msgid "just now" msgstr "" -#: rhodecode/lib/auth_modules/__init__.py:690 -msgid "This provider is currently disabled" -msgstr "" - -#: rhodecode/lib/auth_modules/__init__.py:708 -msgid "Your external identity is now connected with your account" -msgstr "" - -#: rhodecode/lib/auth_modules/__init__.py:712 -msgid "No external user id found? Perhaps permissionsfor authentication are set incorrectly" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_crowd.py:60 -msgid "The FQDN or IP of the Atlassian CROWD Server" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_crowd.py:61 -msgid "Host" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_crowd.py:66 -msgid "The Port in use by the Atlassian CROWD Server" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_crowd.py:67 -#: rhodecode/lib/auth_modules/auth_ldap.py:81 -msgid "Port" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_crowd.py:73 -msgid "The Application Name to authenticate to CROWD" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_crowd.py:74 -msgid "Application Name" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_crowd.py:79 -msgid "The password to authenticate to CROWD" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_crowd.py:80 -msgid "Application Password" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_crowd.py:85 -msgid "A comma separated list of group names that identify users as RhodeCode Administrators" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_crowd.py:88 -msgid "Admin Groups" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_crowd.py:208 -msgid "CROWD" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_jasig_cas.py:63 -msgid "The url of the Jasig CAS REST service" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_jasig_cas.py:64 -#: rhodecode/templates/admin/gists/show.html:21 -msgid "URL" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_jasig_cas.py:90 -msgid "Jasig-CAS" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:74 -msgid "Host of the LDAP Server" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:75 -msgid "LDAP Host" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:80 -msgid "Port that the LDAP server is listening on" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:87 -msgid "User to connect to LDAP" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:89 -msgid "Account" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:94 -msgid "Password to connect to LDAP" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:96 rhodecode/templates/login.html:45 -#: rhodecode/templates/register.html:43 -#: rhodecode/templates/admin/my_account/my_account.html:30 -#: rhodecode/templates/admin/users/user_add.html:44 -#: rhodecode/templates/base/base.html:312 -#: rhodecode/templates/debug_style/login.html:45 -msgid "Password" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:101 -msgid "TLS Type" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:102 -msgid "Connection Security" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:108 -msgid "Require Cert over TLS?" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:109 -msgid "Certificate Checks" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:115 -msgid "Base DN to search (e.g., dc=mydomain,dc=com)" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:117 -msgid "Base DN" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:122 -msgid "Filter to narrow results (e.g., ou=Users, etc)" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:124 -msgid "LDAP Search Filter" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:129 -msgid "How deep to search LDAP" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:130 -msgid "LDAP Search Scope" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:136 -msgid "LDAP Attribute to map to user name" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:137 -msgid "Login Attribute" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:138 -msgid "The LDAP Login attribute of the CN must be specified" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:143 -msgid "LDAP Attribute to map to first name" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:145 -msgid "First Name Attribute" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:150 -msgid "LDAP Attribute to map to last name" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:152 -msgid "Last Name Attribute" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:157 -msgid "LDAP Attribute to map to email address" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:159 -msgid "Email Attribute" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_ldap.py:335 -msgid "LDAP" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_pam.py:60 -msgid "PAM service name to use for authentication." -msgstr "" - -#: rhodecode/lib/auth_modules/auth_pam.py:61 -msgid "PAM service name" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_pam.py:66 -msgid "Regular expression for extracting user name/email etc. from Unix userinfo." -msgstr "" - -#: rhodecode/lib/auth_modules/auth_pam.py:68 -msgid "Gecos Regex" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_pam.py:94 -msgid "PAM" -msgstr "" - -#: rhodecode/lib/auth_modules/auth_rhodecode.py:66 -msgid "Rhodecode" -msgstr "" - #: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:570 #: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:582 #: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:599 @@ -1605,19 +1574,19 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:683 #: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:700 #: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:717 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:735 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:738 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:740 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:740 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:767 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:777 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:820 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:819 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:820 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:820 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:826 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:948 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:973 rhodecode/model/db.py:2243 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:733 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:736 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:738 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:738 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:765 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:775 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:818 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:817 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:818 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:818 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:824 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:946 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:971 rhodecode/model/db.py:2291 msgid "Repository no access" msgstr "" @@ -1631,19 +1600,19 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:684 #: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:701 #: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:718 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:736 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:739 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:741 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:741 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:768 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:778 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:821 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:820 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:821 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:821 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:827 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:949 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:974 rhodecode/model/db.py:2244 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:734 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:737 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:739 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:739 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:766 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:776 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:819 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:818 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:819 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:819 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:825 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:947 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:972 rhodecode/model/db.py:2292 msgid "Repository read access" msgstr "" @@ -1657,19 +1626,19 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:685 #: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:702 #: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:719 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:737 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:740 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:742 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:742 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:769 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:779 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:822 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:821 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:822 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:822 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:828 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:950 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:975 rhodecode/model/db.py:2245 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:735 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:738 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:740 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:740 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:767 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:777 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:820 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:819 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:820 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:820 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:826 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:948 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:973 rhodecode/model/db.py:2293 msgid "Repository write access" msgstr "" @@ -1683,19 +1652,19 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:686 #: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:703 #: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:720 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:738 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:741 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:743 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:743 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:770 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:780 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:823 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:822 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:823 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:823 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:829 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:951 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:976 rhodecode/model/db.py:2246 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:736 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:739 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:741 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:741 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:768 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:778 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:821 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:820 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:821 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:821 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:827 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:949 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:974 rhodecode/model/db.py:2294 msgid "Repository admin access" msgstr "" @@ -1733,9 +1702,9 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:681 #: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:698 #: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:715 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:733 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:736 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:738 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:731 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:734 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:736 msgid "RhodeCode Administrator" msgstr "" @@ -1749,19 +1718,19 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:704 #: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:721 #: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:738 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:756 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:759 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:761 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:761 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:788 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:798 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:841 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:840 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:841 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:841 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:847 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:969 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:994 rhodecode/model/db.py:2264 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:754 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:757 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:759 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:759 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:786 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:796 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:839 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:838 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:839 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:839 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:845 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:967 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:992 rhodecode/model/db.py:2312 msgid "Repository creation disabled" msgstr "" @@ -1775,19 +1744,19 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:705 #: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:722 #: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:739 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:757 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:760 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:762 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:762 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:789 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:799 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:842 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:841 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:842 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:842 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:848 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:970 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:995 rhodecode/model/db.py:2265 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:755 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:758 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:760 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:760 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:787 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:797 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:840 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:839 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:840 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:840 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:846 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:968 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:993 rhodecode/model/db.py:2313 msgid "Repository creation enabled" msgstr "" @@ -1801,19 +1770,19 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:707 #: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:724 #: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:741 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:761 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:764 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:766 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:766 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:793 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:803 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:846 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:845 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:846 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:846 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:852 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:974 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:999 rhodecode/model/db.py:2269 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:759 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:762 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:764 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:764 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:791 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:801 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:844 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:843 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:844 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:844 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:850 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:972 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:997 rhodecode/model/db.py:2317 msgid "Repository forking disabled" msgstr "" @@ -1827,19 +1796,19 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:708 #: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:725 #: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:742 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:762 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:765 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:767 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:767 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:794 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:804 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:847 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:846 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:847 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:847 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:853 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:975 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1000 rhodecode/model/db.py:2270 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:760 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:763 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:765 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:765 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:792 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:802 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:845 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:844 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:845 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:845 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:851 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:973 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:998 rhodecode/model/db.py:2318 msgid "Repository forking enabled" msgstr "" @@ -1874,19 +1843,19 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:1021 #: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:1038 #: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:1055 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:1076 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:1079 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:1090 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:1093 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:1123 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:1137 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:1180 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:1179 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:1188 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:1188 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:1198 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:1320 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1345 rhodecode/model/db.py:2900 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:1074 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:1077 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:1088 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:1091 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:1121 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:1135 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:1178 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:1177 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:1186 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:1186 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:1196 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:1318 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1343 rhodecode/model/db.py:2950 msgid "Not Reviewed" msgstr "" @@ -1900,19 +1869,19 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:1022 #: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:1039 #: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:1056 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:1077 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:1080 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:1091 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:1094 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:1124 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:1138 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:1181 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:1180 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:1189 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:1189 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:1199 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:1321 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1346 rhodecode/model/db.py:2901 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:1075 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:1078 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:1089 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:1092 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:1122 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:1136 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:1179 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:1178 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:1187 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:1187 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:1197 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:1319 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1344 rhodecode/model/db.py:2951 msgid "Approved" msgstr "" @@ -1926,19 +1895,19 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:1023 #: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:1040 #: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:1057 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:1078 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:1081 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:1092 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:1095 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:1125 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:1139 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:1182 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:1181 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:1190 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:1190 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:1200 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:1322 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1347 rhodecode/model/db.py:2902 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:1076 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:1079 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:1090 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:1093 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:1123 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:1137 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:1180 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:1179 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:1188 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:1188 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:1198 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:1320 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1345 rhodecode/model/db.py:2952 msgid "Rejected" msgstr "" @@ -1952,19 +1921,19 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:1024 #: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:1041 #: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:1058 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:1079 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:1082 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:1093 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:1096 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:1126 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:1140 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:1183 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:1182 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:1191 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:1191 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:1201 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:1323 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1348 rhodecode/model/db.py:2903 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:1077 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:1080 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:1091 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:1094 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:1124 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:1138 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:1181 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:1180 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:1189 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:1189 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:1199 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:1321 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1346 rhodecode/model/db.py:2953 msgid "Under Review" msgstr "" @@ -1975,6 +1944,52 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:688 #: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:705 #: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:722 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:738 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:741 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:743 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:743 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:770 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:780 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:823 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:822 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:823 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:823 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:829 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:951 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:976 rhodecode/model/db.py:2296 +msgid "Repository group no access" +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:690 +#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:663 +#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:665 +#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:688 +#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:689 +#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:706 +#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:723 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:739 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:742 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:744 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:744 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:771 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:781 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:824 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:823 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:824 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:824 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:830 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:952 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:977 rhodecode/model/db.py:2297 +msgid "Repository group read access" +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:691 +#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:664 +#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:666 +#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:689 +#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:690 +#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:707 +#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:724 #: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:740 #: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:743 #: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:745 @@ -1987,17 +2002,17 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:825 #: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:831 #: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:953 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:978 rhodecode/model/db.py:2248 -msgid "Repository group no access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:690 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:663 -#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:665 -#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:688 -#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:689 -#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:706 -#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:723 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:978 rhodecode/model/db.py:2298 +msgid "Repository group write access" +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:692 +#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:665 +#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:667 +#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:690 +#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:691 +#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:708 +#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:725 #: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:741 #: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:744 #: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:746 @@ -2010,40 +2025,16 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:826 #: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:832 #: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:954 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:979 rhodecode/model/db.py:2249 -msgid "Repository group read access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:691 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:664 -#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:666 -#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:689 -#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:690 -#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:707 -#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:724 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:742 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:745 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:747 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:747 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:774 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:784 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:827 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:826 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:827 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:827 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:833 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:955 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:980 rhodecode/model/db.py:2250 -msgid "Repository group write access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:692 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:665 -#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:667 -#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:690 -#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:691 -#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:708 -#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:725 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:979 rhodecode/model/db.py:2299 +msgid "Repository group admin access" +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:667 +#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:669 +#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:692 +#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:693 +#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:710 +#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:727 #: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:743 #: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:746 #: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:748 @@ -2056,16 +2047,38 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:828 #: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:834 #: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:956 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:981 rhodecode/model/db.py:2251 -msgid "Repository group admin access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:667 -#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:669 -#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:692 -#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:693 -#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:710 -#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:727 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:981 rhodecode/model/db.py:2301 +msgid "User group no access" +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:668 +#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:670 +#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:693 +#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:694 +#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:711 +#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:728 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:744 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:747 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:749 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:749 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:776 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:786 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:829 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:828 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:829 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:829 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:835 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:957 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:982 rhodecode/model/db.py:2302 +msgid "User group read access" +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:669 +#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:671 +#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:694 +#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:695 +#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:712 +#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:729 #: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:745 #: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:748 #: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:750 @@ -2078,16 +2091,16 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:830 #: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:836 #: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:958 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:983 rhodecode/model/db.py:2253 -msgid "User group no access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:668 -#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:670 -#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:693 -#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:694 -#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:711 -#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:728 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:983 rhodecode/model/db.py:2303 +msgid "User group write access" +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:670 +#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:672 +#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:695 +#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:696 +#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:713 +#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:730 #: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:746 #: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:749 #: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:751 @@ -2100,38 +2113,16 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:831 #: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:837 #: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:959 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:984 rhodecode/model/db.py:2254 -msgid "User group read access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:669 -#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:671 -#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:694 -#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:695 -#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:712 -#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:729 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:747 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:750 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:752 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:752 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:779 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:789 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:832 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:831 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:832 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:832 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:838 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:960 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:985 rhodecode/model/db.py:2255 -msgid "User group write access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:670 -#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:672 -#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:695 -#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:696 -#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:713 -#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:730 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:984 rhodecode/model/db.py:2304 +msgid "User group admin access" +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:672 +#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:674 +#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:697 +#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:698 +#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:715 +#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:732 #: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:748 #: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:751 #: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:753 @@ -2144,29 +2135,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:833 #: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:839 #: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:961 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:986 rhodecode/model/db.py:2256 -msgid "User group admin access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:672 -#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:674 -#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:697 -#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:698 -#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:715 -#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:732 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:750 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:753 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:755 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:755 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:782 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:792 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:835 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:834 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:835 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:835 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:841 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:963 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:988 rhodecode/model/db.py:2258 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:986 rhodecode/model/db.py:2306 msgid "Repository Group creation disabled" msgstr "" @@ -2176,6 +2145,28 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:699 #: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:716 #: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:733 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:749 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:752 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:754 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:754 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:781 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:791 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:834 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:833 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:834 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:834 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:840 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:962 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:987 rhodecode/model/db.py:2307 +msgid "Repository Group creation enabled" +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:675 +#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:677 +#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:700 +#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:701 +#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:718 +#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:735 #: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:751 #: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:754 #: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:756 @@ -2188,29 +2179,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:836 #: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:842 #: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:964 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:989 rhodecode/model/db.py:2259 -msgid "Repository Group creation enabled" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:675 -#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:677 -#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:700 -#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:701 -#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:718 -#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:735 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:753 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:756 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:758 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:758 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:785 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:795 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:838 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:837 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:838 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:838 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:844 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:966 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:991 rhodecode/model/db.py:2261 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:989 rhodecode/model/db.py:2309 msgid "User Group creation disabled" msgstr "" @@ -2220,19 +2189,19 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:702 #: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:719 #: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:736 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:754 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:757 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:759 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:759 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:786 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:796 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:839 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:838 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:839 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:839 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:845 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:967 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:992 rhodecode/model/db.py:2262 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:752 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:755 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:757 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:757 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:784 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:794 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:837 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:836 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:837 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:837 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:843 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:965 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:990 rhodecode/model/db.py:2310 msgid "User Group creation enabled" msgstr "" @@ -2242,6 +2211,50 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:710 #: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:727 #: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:744 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:762 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:765 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:767 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:767 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:794 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:804 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:847 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:846 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:847 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:847 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:853 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:975 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1000 rhodecode/model/db.py:2320 +msgid "Registration disabled" +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:685 +#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:687 +#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:710 +#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:711 +#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:728 +#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:745 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:763 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:766 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:768 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:768 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:795 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:805 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:848 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:847 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:848 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:848 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:854 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:976 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1001 rhodecode/model/db.py:2321 +msgid "User Registration with manual account activation" +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:686 +#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:688 +#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:711 +#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:712 +#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:729 +#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:746 #: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:764 #: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:767 #: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:769 @@ -2254,38 +2267,16 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:849 #: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:855 #: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:977 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1002 rhodecode/model/db.py:2272 -msgid "Registration disabled" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:685 -#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:687 -#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:710 -#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:711 -#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:728 -#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:745 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:765 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:768 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:770 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:770 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:797 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:807 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:850 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:849 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:850 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:850 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:856 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:978 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1003 rhodecode/model/db.py:2273 -msgid "User Registration with manual account activation" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:686 -#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:688 -#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:711 -#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:712 -#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:729 -#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:746 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1002 rhodecode/model/db.py:2322 +msgid "User Registration with automatic account activation" +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:688 +#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:690 +#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:713 +#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:714 +#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:731 +#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:748 #: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:766 #: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:769 #: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:771 @@ -2298,29 +2289,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:851 #: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:857 #: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:979 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1004 rhodecode/model/db.py:2274 -msgid "User Registration with automatic account activation" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:688 -#: rhodecode/lib/dbmigrate/schema/db_1_8_0.py:690 -#: rhodecode/lib/dbmigrate/schema/db_2_0_0.py:713 -#: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:714 -#: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:731 -#: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:748 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:768 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:771 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:773 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:773 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:800 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:810 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:853 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:852 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:853 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:853 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:859 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:981 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1006 rhodecode/model/db.py:2276 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1004 rhodecode/model/db.py:2324 msgid "Manual activation of external account" msgstr "" @@ -2330,11 +2299,67 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_2_0_1.py:715 #: rhodecode/lib/dbmigrate/schema/db_2_0_2.py:732 #: rhodecode/lib/dbmigrate/schema/db_2_1_0.py:749 -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:769 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:772 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:774 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:774 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:801 +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:767 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:770 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:772 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:772 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:799 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:809 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:852 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:851 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:852 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:852 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:858 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:980 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1005 rhodecode/model/db.py:2325 +msgid "Automatic activation of external account" +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:756 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:759 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:761 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:761 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:788 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:798 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:841 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:840 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:841 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:841 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:847 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:969 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:994 rhodecode/model/db.py:2314 +msgid "Repository creation enabled with write permission to a repository group" +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:757 +#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:760 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:762 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:762 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:789 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:799 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:842 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:841 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:842 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:842 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:848 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:970 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:995 rhodecode/model/db.py:2315 +msgid "Repository creation disabled with write permission to a repository group" +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:736 +#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:763 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:773 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:816 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:815 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:816 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:816 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:822 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:944 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:969 rhodecode/model/db.py:2289 +msgid "RhodeCode Super Administrator" +msgstr "" + #: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:811 #: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:854 #: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:853 @@ -2342,130 +2367,90 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:854 #: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:860 #: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:982 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1007 rhodecode/model/db.py:2277 -msgid "Automatic activation of external account" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:758 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:761 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:763 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:763 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:790 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:800 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:843 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:842 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:843 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:843 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:849 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:971 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:996 rhodecode/model/db.py:2266 -msgid "Repository creation enabled with write permission to a repository group" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_2_2_0.py:759 -#: rhodecode/lib/dbmigrate/schema/db_2_2_3.py:762 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_0.py:764 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:764 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:791 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:801 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:844 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:843 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:844 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:844 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:850 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:972 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:997 rhodecode/model/db.py:2267 -msgid "Repository creation disabled with write permission to a repository group" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_1.py:738 -#: rhodecode/lib/dbmigrate/schema/db_2_3_0_2.py:765 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:775 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:818 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:817 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:818 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:818 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:824 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:946 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:971 rhodecode/model/db.py:2241 -msgid "RhodeCode Super Administrator" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:813 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:856 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:855 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:856 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:856 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:862 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:984 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1009 rhodecode/model/db.py:2279 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1007 rhodecode/model/db.py:2327 msgid "Inherit object permissions from default user disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:814 -#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:857 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:856 -#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:857 -#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:857 -#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:863 -#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:985 -#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1010 rhodecode/model/db.py:2280 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_0.py:812 +#: rhodecode/lib/dbmigrate/schema/db_3_0_0_1.py:855 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_0.py:854 +#: rhodecode/lib/dbmigrate/schema/db_3_1_0_1.py:855 +#: rhodecode/lib/dbmigrate/schema/db_3_2_0_0.py:855 +#: rhodecode/lib/dbmigrate/schema/db_3_3_0_0.py:861 +#: rhodecode/lib/dbmigrate/schema/db_3_5_0_0.py:983 +#: rhodecode/lib/dbmigrate/schema/db_3_7_0_0.py:1008 rhodecode/model/db.py:2328 msgid "Inherit object permissions from default user enabled" msgstr "" -#: rhodecode/lib/index/whoosh.py:129 +#: rhodecode/lib/index/whoosh.py:148 msgid "Invalid search query. Try quoting it." msgstr "" -#: rhodecode/lib/index/whoosh.py:131 -msgid "There is no index to search in. Please run whoosh indexer" -msgstr "" - -#: rhodecode/lib/index/whoosh.py:136 -msgid "An error occurred during this search operation" -msgstr "" - -#: rhodecode/lib/index/whoosh.py:144 -msgid "Index Type" -msgstr "" - -#: rhodecode/lib/index/whoosh.py:145 -msgid "File Index" -msgstr "" - -#: rhodecode/lib/index/whoosh.py:146 rhodecode/lib/index/whoosh.py:151 -msgid "Indexed documents" -msgstr "" - -#: rhodecode/lib/index/whoosh.py:148 rhodecode/lib/index/whoosh.py:153 -msgid "Last update" -msgstr "" - #: rhodecode/lib/index/whoosh.py:150 +msgid "There is no index to search in. Please run whoosh indexer" +msgstr "" + +#: rhodecode/lib/index/whoosh.py:155 +msgid "An error occurred during this search operation" +msgstr "" + +#: rhodecode/lib/index/whoosh.py:163 +msgid "Index Type" +msgstr "" + +#: rhodecode/lib/index/whoosh.py:164 +msgid "File Index" +msgstr "" + +#: rhodecode/lib/index/whoosh.py:165 rhodecode/lib/index/whoosh.py:170 +msgid "Indexed documents" +msgstr "" + +#: rhodecode/lib/index/whoosh.py:167 rhodecode/lib/index/whoosh.py:172 +msgid "Last update" +msgstr "" + +#: rhodecode/lib/index/whoosh.py:169 msgid "Commit index" msgstr "" -#: rhodecode/model/db.py:871 +#: rhodecode/login/views.py:237 rhodecode/login/views.py:296 +msgid "bad captcha" +msgstr "" + +#: rhodecode/login/views.py:246 +msgid "You have successfully registered with RhodeCode" +msgstr "" + +#: rhodecode/login/views.py:312 +msgid "Your password reset link was sent" +msgstr "" + +#: rhodecode/login/views.py:333 +msgid "Your password reset was successful, a new password has been sent to your email" +msgstr "" + +#: rhodecode/model/db.py:909 msgid "all" msgstr "" -#: rhodecode/model/db.py:872 +#: rhodecode/model/db.py:910 msgid "http/web interface" msgstr "" -#: rhodecode/model/db.py:873 +#: rhodecode/model/db.py:911 msgid "vcs (git/hg protocol)" msgstr "" -#: rhodecode/model/db.py:874 +#: rhodecode/model/db.py:912 msgid "api calls" msgstr "" -#: rhodecode/model/db.py:875 +#: rhodecode/model/db.py:913 msgid "feed access" msgstr "" -#: rhodecode/model/db.py:2020 +#: rhodecode/model/db.py:2067 msgid "No parent" msgstr "" @@ -2583,7 +2568,7 @@ msgstr "" msgid "This pull request cannot be merged because the target or the source reference is missing." msgstr "" -#: rhodecode/model/pull_request.py:411 +#: rhodecode/model/pull_request.py:416 #, python-format msgid "" "Merge pull request #%(pr_id)s from %(source_repo)s %(source_ref_name)s\n" @@ -2591,39 +2576,39 @@ msgid "" " %(pr_title)s" msgstr "" -#: rhodecode/model/pull_request.py:443 +#: rhodecode/model/pull_request.py:448 msgid "Pull request merged and closed" msgstr "" -#: rhodecode/model/pull_request.py:859 +#: rhodecode/model/pull_request.py:867 msgid "Server-side pull request merging is disabled." msgstr "" -#: rhodecode/model/pull_request.py:861 +#: rhodecode/model/pull_request.py:869 msgid "This pull request is closed." msgstr "" -#: rhodecode/model/pull_request.py:872 +#: rhodecode/model/pull_request.py:880 msgid "Pull request merging is not supported." msgstr "" -#: rhodecode/model/pull_request.py:890 +#: rhodecode/model/pull_request.py:898 msgid "Target repository large files support is disabled." msgstr "" -#: rhodecode/model/pull_request.py:893 +#: rhodecode/model/pull_request.py:901 msgid "Source repository large files support is disabled." msgstr "" -#: rhodecode/model/pull_request.py:1036 rhodecode/model/scm.py:791 +#: rhodecode/model/pull_request.py:1050 rhodecode/model/scm.py:791 msgid "Bookmarks" msgstr "" -#: rhodecode/model/pull_request.py:1041 +#: rhodecode/model/pull_request.py:1055 msgid "Commit IDs" msgstr "" -#: rhodecode/model/pull_request.py:1044 +#: rhodecode/model/pull_request.py:1058 msgid "Closed Branches" msgstr "" @@ -2635,220 +2620,236 @@ msgstr "" msgid "You can't Edit this user since it's crucial for entire application" msgstr "" -#: rhodecode/model/user.py:283 +#: rhodecode/model/user.py:285 #, python-format msgid "You can't edit this user (`%(username)s`) since it's crucial for entire application" msgstr "" -#: rhodecode/model/user.py:456 +#: rhodecode/model/user.py:458 msgid "You can't remove this user since it's crucial for entire application" msgstr "" -#: rhodecode/model/user.py:464 +#: rhodecode/model/user.py:466 #, python-format msgid "user \"%s\" still owns %s repositories and cannot be removed. Switch owners or remove those repositories:%s" msgstr "" -#: rhodecode/model/user.py:473 +#: rhodecode/model/user.py:475 #, python-format msgid "user \"%s\" still owns %s repository groups and cannot be removed. Switch owners or remove those repository groups:%s" msgstr "" -#: rhodecode/model/user.py:482 +#: rhodecode/model/user.py:484 #, python-format msgid "user \"%s\" still owns %s user groups and cannot be removed. Switch owners or remove those user groups:%s" msgstr "" -#: rhodecode/model/validators.py:96 rhodecode/model/validators.py:97 +#: rhodecode/model/validators.py:98 rhodecode/model/validators.py:99 msgid "Value cannot be an empty list" msgstr "" -#: rhodecode/model/validators.py:140 +#: rhodecode/model/validators.py:142 msgid "Pattern already exists" msgstr "" -#: rhodecode/model/validators.py:158 -#, python-format -msgid "Username \"%(username)s\" already exists" -msgstr "" - #: rhodecode/model/validators.py:160 #, python-format -msgid "Username \"%(username)s\" is forbidden" +msgid "Username \"%(username)s\" already exists" msgstr "" #: rhodecode/model/validators.py:162 +#, python-format +msgid "Username \"%(username)s\" is forbidden" +msgstr "" + +#: rhodecode/model/validators.py:164 msgid "Username may only contain alphanumeric characters underscores, periods or dashes and must begin with alphanumeric character or underscore" msgstr "" -#: rhodecode/model/validators.py:190 +#: rhodecode/model/validators.py:192 msgid "The input is not valid" msgstr "" -#: rhodecode/model/validators.py:197 +#: rhodecode/model/validators.py:199 #, python-format msgid "Username %(username)s is not valid" msgstr "" -#: rhodecode/model/validators.py:216 +#: rhodecode/model/validators.py:200 +#, python-format +msgid "Username %(username)s is disabled" +msgstr "" + +#: rhodecode/model/validators.py:223 msgid "Invalid user group name" msgstr "" -#: rhodecode/model/validators.py:217 +#: rhodecode/model/validators.py:224 #, python-format msgid "User group \"%(usergroup)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:219 +#: rhodecode/model/validators.py:226 msgid "user group name may only contain alphanumeric characters underscores, periods or dashes and must begin with alphanumeric character" msgstr "" -#: rhodecode/model/validators.py:257 +#: rhodecode/model/validators.py:264 msgid "Cannot assign this group as parent" msgstr "" -#: rhodecode/model/validators.py:258 +#: rhodecode/model/validators.py:265 #, python-format msgid "Group \"%(group_name)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:259 +#: rhodecode/model/validators.py:266 #, python-format msgid "Repository with name \"%(group_name)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:261 +#: rhodecode/model/validators.py:268 msgid "no permission to store repository groupin this location" msgstr "" -#: rhodecode/model/validators.py:263 +#: rhodecode/model/validators.py:270 msgid "no permission to store repository group in root location" msgstr "" -#: rhodecode/model/validators.py:379 +#: rhodecode/model/validators.py:386 msgid "Invalid characters (non-ascii) in password" msgstr "" -#: rhodecode/model/validators.py:394 +#: rhodecode/model/validators.py:401 msgid "Invalid old password" msgstr "" -#: rhodecode/model/validators.py:412 +#: rhodecode/model/validators.py:418 msgid "Passwords do not match" msgstr "" -#: rhodecode/model/validators.py:430 +#: rhodecode/model/validators.py:436 msgid "invalid password" msgstr "" -#: rhodecode/model/validators.py:431 +#: rhodecode/model/validators.py:437 msgid "invalid user name" msgstr "" -#: rhodecode/model/validators.py:432 +#: rhodecode/model/validators.py:438 msgid "Your account is disabled" msgstr "" -#: rhodecode/model/validators.py:465 +#: rhodecode/model/validators.py:470 msgid "Token mismatch" msgstr "" -#: rhodecode/model/validators.py:479 +#: rhodecode/model/validators.py:484 #, python-format msgid "Repository name %(repo)s is disallowed" msgstr "" -#: rhodecode/model/validators.py:481 -#, python-format -msgid "Repository with name %(repo)s already exists" -msgstr "" - -#: rhodecode/model/validators.py:483 -#, python-format -msgid "Repository group with name \"%(repo)s\" already exists" -msgstr "" - #: rhodecode/model/validators.py:486 #, python-format -msgid "Repository with name %(repo)s exists in group \"%(group)s\"" +msgid "Repository with name %(repo)s already exists" msgstr "" #: rhodecode/model/validators.py:488 #, python-format +msgid "Repository group with name \"%(repo)s\" already exists" +msgstr "" + +#: rhodecode/model/validators.py:491 +#, python-format +msgid "Repository with name %(repo)s exists in group \"%(group)s\"" +msgstr "" + +#: rhodecode/model/validators.py:493 +#, python-format msgid "Repository group with name \"%(repo)s\" exists in group \"%(group)s\"" msgstr "" -#: rhodecode/model/validators.py:615 +#: rhodecode/model/validators.py:620 #, python-format msgid "invalid clone url for %(rtype)s repository" msgstr "" -#: rhodecode/model/validators.py:616 +#: rhodecode/model/validators.py:621 #, python-format msgid "Invalid clone url, provide a valid clone url starting with one of %(allowed_prefixes)s" msgstr "" -#: rhodecode/model/validators.py:645 +#: rhodecode/model/validators.py:650 msgid "Fork have to be the same type as parent" msgstr "" -#: rhodecode/model/validators.py:660 +#: rhodecode/model/validators.py:665 msgid "You do not have the permission to create repositories in this group." msgstr "" -#: rhodecode/model/validators.py:663 +#: rhodecode/model/validators.py:668 msgid "You do not have the permission to store repositories in the root location." msgstr "" -#: rhodecode/model/validators.py:723 +#: rhodecode/model/validators.py:728 msgid "This username or user group name is not valid" msgstr "" -#: rhodecode/model/validators.py:841 +#: rhodecode/model/validators.py:846 msgid "This is not a valid path" msgstr "" -#: rhodecode/model/validators.py:856 +#: rhodecode/model/validators.py:861 msgid "This e-mail address is already taken" msgstr "" -#: rhodecode/model/validators.py:876 +#: rhodecode/model/validators.py:881 #, python-format msgid "e-mail \"%(email)s\" does not exist." msgstr "" -#: rhodecode/model/validators.py:912 -msgid "The LDAP Login attribute of the CN must be specified - this is the name of the attribute that is equivalent to \"username\"" -msgstr "" - -#: rhodecode/model/validators.py:926 +#: rhodecode/model/validators.py:902 #, python-format msgid "Revisions %(revs)s are already part of pull request or have set status" msgstr "" -#: rhodecode/model/validators.py:957 +#: rhodecode/model/validators.py:933 msgid "Please enter a valid IPv4 or IpV6 address" msgstr "" -#: rhodecode/model/validators.py:958 +#: rhodecode/model/validators.py:934 #, python-format msgid "The network size (bits) must be within the range of 0-32 (not %(bits)r)" msgstr "" -#: rhodecode/model/validators.py:985 +#: rhodecode/model/validators.py:961 msgid "Key name can only consist of letters, underscore, dash or numbers" msgstr "" +#: rhodecode/model/validators.py:976 +msgid "Filename cannot be inside a directory" +msgstr "" + +#: rhodecode/model/validators.py:992 +#, python-format +msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name" +msgstr "" + +#: rhodecode/model/validators.py:995 +#, python-format +msgid "The plugin \"%(plugin_id)s\" is missing an includeme function." +msgstr "" + +#: rhodecode/model/validators.py:998 +#, python-format +msgid "Can not load plugin \"%(plugin_id)s\"" +msgstr "" + #: rhodecode/model/validators.py:1000 -msgid "Filename cannot be inside a directory" -msgstr "" - -#: rhodecode/model/validators.py:1016 -#, python-format -msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name" -msgstr "" - -#: rhodecode/model/validators.py:1048 +#, python-format +msgid "No plugin available with ID \"%(plugin_id)s\"" +msgstr "" + +#: rhodecode/model/validators.py:1067 msgid "This gistid is already in use" msgstr "" @@ -2904,10 +2905,10 @@ msgstr "" #: rhodecode/templates/admin/my_account/my_account_watched.html:31 #: rhodecode/templates/admin/repo_groups/repo_groups.html:53 #: rhodecode/templates/admin/repos/repo_add_base.html:9 -#: rhodecode/templates/admin/repos/repo_edit_settings.html:12 +#: rhodecode/templates/admin/repos/repo_edit_settings.html:15 #: rhodecode/templates/admin/repos/repos.html:54 #: rhodecode/templates/admin/user_groups/user_groups.html:55 -#: rhodecode/templates/base/perms_summary.html:103 +#: rhodecode/templates/base/perms_summary.html:102 #: rhodecode/templates/bookmarks/bookmarks.html:59 #: rhodecode/templates/branches/branches.html:58 #: rhodecode/templates/files/files_browser.html:49 @@ -2921,25 +2922,25 @@ msgstr "" #: rhodecode/templates/admin/gists/index.html:114 #: rhodecode/templates/admin/my_account/my_account_auth_tokens.html:77 #: rhodecode/templates/admin/repo_groups/repo_group_add.html:45 -#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:30 +#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:42 #: rhodecode/templates/admin/repo_groups/repo_groups.html:56 #: rhodecode/templates/admin/repos/repo_add_base.html:32 #: rhodecode/templates/admin/repos/repo_edit_issuetracker.html:29 -#: rhodecode/templates/admin/repos/repo_edit_settings.html:83 +#: rhodecode/templates/admin/repos/repo_edit_settings.html:96 #: rhodecode/templates/admin/repos/repos.html:57 #: rhodecode/templates/admin/user_groups/user_group_add.html:43 -#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:29 +#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:42 #: rhodecode/templates/admin/user_groups/user_groups.html:57 #: rhodecode/templates/admin/users/user_edit_auth_tokens.html:74 #: rhodecode/templates/base/issue_tracker_settings.html:10 #: rhodecode/templates/changeset/changeset.html:53 -#: rhodecode/templates/compare/compare_cs.html:24 +#: rhodecode/templates/compare/compare_commits.html:24 #: rhodecode/templates/email_templates/pull_request_review.mako:30 #: rhodecode/templates/email_templates/pull_request_review.mako:67 #: rhodecode/templates/files/file_tree_detail.html:5 #: rhodecode/templates/files/file_tree_detail.html:12 #: rhodecode/templates/forks/fork.html:48 -#: rhodecode/templates/forks/forks_data.html:8 +#: rhodecode/templates/forks/forks_data.html:9 #: rhodecode/templates/pullrequests/pullrequest.html:47 #: rhodecode/templates/pullrequests/pullrequest_show.html:122 #: rhodecode/templates/summary/components.html:73 @@ -2949,14 +2950,15 @@ msgstr "" #: rhodecode/templates/index_base.html:102 #: rhodecode/templates/index_base.html:133 #: rhodecode/templates/admin/repo_groups/repo_group_edit_advanced.html:5 -#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:21 +#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:24 #: rhodecode/templates/admin/repo_groups/repo_groups.html:60 #: rhodecode/templates/admin/repos/repo_edit_advanced.html:5 -#: rhodecode/templates/admin/repos/repo_edit_settings.html:74 +#: rhodecode/templates/admin/repos/repo_edit_settings.html:78 #: rhodecode/templates/admin/repos/repos.html:65 #: rhodecode/templates/admin/user_groups/user_group_edit_advanced.html:5 -#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:20 +#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:24 #: rhodecode/templates/admin/user_groups/user_groups.html:64 +#: rhodecode/templates/forks/forks_data.html:7 #: rhodecode/templates/summary/components.html:195 msgid "Owner" msgstr "" @@ -2975,7 +2977,7 @@ msgstr "" #: rhodecode/templates/changelog/changelog.html:106 #: rhodecode/templates/changelog/changelog_summary_data.html:6 #: rhodecode/templates/changeset/changeset.html:36 -#: rhodecode/templates/compare/compare_cs.html:22 +#: rhodecode/templates/compare/compare_commits.html:22 #: rhodecode/templates/email_templates/commit_comment.mako:16 #: rhodecode/templates/email_templates/commit_comment.mako:45 #: rhodecode/templates/search/search_commit.html:6 @@ -2992,13 +2994,13 @@ msgstr "" msgid "Home" msgstr "" -#: rhodecode/templates/login.html:6 rhodecode/templates/login.html:36 -#: rhodecode/templates/login.html:52 rhodecode/templates/base/base.html:326 +#: rhodecode/templates/login.html:5 rhodecode/templates/login.html:35 +#: rhodecode/templates/login.html:64 rhodecode/templates/base/base.html:328 #: rhodecode/templates/debug_style/login.html:60 msgid "Sign In" msgstr "" -#: rhodecode/templates/login.html:38 +#: rhodecode/templates/login.html:37 msgid "Go to the registration page to create a new account." msgstr "" @@ -3010,26 +3012,22 @@ msgstr "" #: rhodecode/templates/admin/users/user_add.html:35 #: rhodecode/templates/admin/users/user_edit_profile.html:39 #: rhodecode/templates/admin/users/users.html:89 -#: rhodecode/templates/base/base.html:303 +#: rhodecode/templates/base/base.html:305 #: rhodecode/templates/debug_style/login.html:36 #: rhodecode/templates/users/user_profile.html:27 msgid "Username" msgstr "" -#: rhodecode/templates/login.html:48 +#: rhodecode/templates/login.html:58 msgid "Remember me" msgstr "" -#: rhodecode/templates/login.html:50 +#: rhodecode/templates/login.html:61 msgid "Forgot your password?" msgstr "" -#: rhodecode/templates/login.html:62 -msgid "Sign In using one of external services" -msgstr "" - #: rhodecode/templates/password_reset.html:5 -#: rhodecode/templates/register.html:6 +#: rhodecode/templates/register.html:5 msgid "Create an Account" msgstr "" @@ -3045,32 +3043,32 @@ msgstr "" msgid "Email Address" msgstr "" -#: rhodecode/templates/password_reset.html:45 -#: rhodecode/templates/register.html:56 +#: rhodecode/templates/password_reset.html:49 +#: rhodecode/templates/register.html:85 msgid "Captcha" msgstr "" -#: rhodecode/templates/password_reset.html:51 +#: rhodecode/templates/password_reset.html:59 msgid "Send password reset email" msgstr "" -#: rhodecode/templates/password_reset.html:52 +#: rhodecode/templates/password_reset.html:60 msgid "Password reset link will be send to matching email address" msgstr "" +#: rhodecode/templates/register.html:35 +msgid "Create an account" +msgstr "" + #: rhodecode/templates/register.html:36 -msgid "Create an account" -msgstr "" - -#: rhodecode/templates/register.html:37 msgid "Go to the login page to sign in with an existing account." msgstr "" -#: rhodecode/templates/register.html:45 +#: rhodecode/templates/register.html:55 msgid "Re-enter password" msgstr "" -#: rhodecode/templates/register.html:47 +#: rhodecode/templates/register.html:62 #: rhodecode/templates/admin/my_account/my_account_profile.html:32 #: rhodecode/templates/admin/my_account/my_account_profile_edit.html:30 #: rhodecode/templates/admin/my_account/my_account_profile_edit.html:76 @@ -3080,7 +3078,7 @@ msgstr "" msgid "First Name" msgstr "" -#: rhodecode/templates/register.html:49 +#: rhodecode/templates/register.html:69 #: rhodecode/templates/admin/my_account/my_account_profile.html:40 #: rhodecode/templates/admin/my_account/my_account_profile_edit.html:39 #: rhodecode/templates/admin/my_account/my_account_profile_edit.html:85 @@ -3090,18 +3088,14 @@ msgstr "" msgid "Last Name" msgstr "" -#: rhodecode/templates/register.html:64 +#: rhodecode/templates/register.html:97 msgid "Account activation requires admin approval." msgstr "" -#: rhodecode/templates/register.html:71 +#: rhodecode/templates/register.html:104 msgid "Create Account" msgstr "" -#: rhodecode/templates/register.html:77 -msgid "Register using one of external services" -msgstr "" - #: rhodecode/templates/admin/admin.html:5 #: rhodecode/templates/admin/admin.html:15 #: rhodecode/templates/base/base.html:78 @@ -3188,8 +3182,8 @@ msgstr "" #: rhodecode/templates/admin/users/user_edit.html:12 #: rhodecode/templates/admin/users/users.html:13 #: rhodecode/templates/admin/users/users.html:102 -#: rhodecode/templates/base/base.html:403 -#: rhodecode/templates/base/base.html:410 +#: rhodecode/templates/base/base.html:405 +#: rhodecode/templates/base/base.html:412 msgid "Admin" msgstr "" @@ -3223,7 +3217,7 @@ msgid "disabled" msgstr "" #: rhodecode/templates/admin/auth/auth_settings.html:81 -#: rhodecode/templates/admin/auth/plugin_settings.html:90 +#: rhodecode/templates/admin/auth/plugin_settings.html:87 #: rhodecode/templates/admin/defaults/defaults_repositories.html:63 #: rhodecode/templates/admin/my_account/my_account_password.html:36 #: rhodecode/templates/admin/my_account/my_account_profile_edit.html:103 @@ -3231,16 +3225,16 @@ msgstr "" #: rhodecode/templates/admin/permissions/permissions_objects.html:56 #: rhodecode/templates/admin/repo_groups/repo_group_add.html:72 #: rhodecode/templates/admin/repo_groups/repo_group_edit_perms.html:135 -#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:55 +#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:67 #: rhodecode/templates/admin/repos/repo_add_base.html:88 #: rhodecode/templates/admin/repos/repo_edit_issuetracker.html:79 #: rhodecode/templates/admin/repos/repo_edit_permissions.html:110 -#: rhodecode/templates/admin/repos/repo_edit_settings.html:145 +#: rhodecode/templates/admin/repos/repo_edit_settings.html:158 #: rhodecode/templates/admin/settings/settings_hooks.html:63 #: rhodecode/templates/admin/settings/settings_issuetracker.html:15 #: rhodecode/templates/admin/user_groups/user_group_add.html:60 #: rhodecode/templates/admin/user_groups/user_group_edit_perms.html:120 -#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:72 +#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:89 #: rhodecode/templates/admin/users/user_add.html:125 #: rhodecode/templates/admin/users/user_edit_profile.html:134 #: rhodecode/templates/base/default_perms_box.html:88 @@ -3274,7 +3268,7 @@ msgstr "" #: rhodecode/templates/admin/defaults/defaults_repositories.html:27 #: rhodecode/templates/admin/repos/repo_add_base.html:84 -#: rhodecode/templates/admin/repos/repo_edit_settings.html:97 +#: rhodecode/templates/admin/repos/repo_edit_settings.html:110 #: rhodecode/templates/forks/fork.html:85 msgid "Private repositories are only visible to people explicitly added as collaborators." msgstr "" @@ -3399,16 +3393,18 @@ msgid "My public" msgstr "" #: rhodecode/templates/admin/gists/index.html:108 +#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:24 +#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:87 #: rhodecode/templates/bookmarks/bookmarks.html:63 #: rhodecode/templates/branches/branches.html:62 #: rhodecode/templates/changelog/changelog.html:102 #: rhodecode/templates/changelog/changelog_summary_data.html:10 #: rhodecode/templates/changeset/changeset.html:164 -#: rhodecode/templates/compare/compare_cs.html:21 +#: rhodecode/templates/compare/compare_commits.html:21 #: rhodecode/templates/files/files_browser.html:53 #: rhodecode/templates/pullrequests/pullrequest_show.html:169 #: rhodecode/templates/pullrequests/pullrequests.html:102 -#: rhodecode/templates/search/search_commit.html:10 +#: rhodecode/templates/search/search_commit.html:16 #: rhodecode/templates/tags/tags.html:63 msgid "Author" msgstr "" @@ -3461,11 +3457,11 @@ msgstr "" #: rhodecode/templates/admin/permissions/permissions_ips.html:61 #: rhodecode/templates/admin/permissions/permissions_objects.html:57 #: rhodecode/templates/admin/repo_groups/repo_group_edit_perms.html:136 -#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:56 +#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:68 #: rhodecode/templates/admin/repos/repo_edit_fields.html:66 #: rhodecode/templates/admin/repos/repo_edit_issuetracker.html:80 #: rhodecode/templates/admin/repos/repo_edit_permissions.html:111 -#: rhodecode/templates/admin/repos/repo_edit_settings.html:146 +#: rhodecode/templates/admin/repos/repo_edit_settings.html:159 #: rhodecode/templates/admin/repos/repo_edit_vcs.html:46 #: rhodecode/templates/admin/settings/settings_global.html:110 #: rhodecode/templates/admin/settings/settings_issuetracker.html:16 @@ -3490,8 +3486,7 @@ msgstr "" #: rhodecode/templates/admin/gists/show.html:49 #: rhodecode/templates/admin/my_account/my_account_auth_tokens.html:56 #: rhodecode/templates/admin/my_account/my_account_emails.html:32 -#: rhodecode/templates/admin/my_account/my_account_oauth.html:50 -#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:34 +#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:61 #: rhodecode/templates/admin/permissions/permissions_ips.html:26 #: rhodecode/templates/admin/repos/repo_edit_fields.html:25 #: rhodecode/templates/admin/settings/settings_hooks.html:46 @@ -3557,7 +3552,7 @@ msgid "Show as raw" msgstr "" #: rhodecode/templates/admin/my_account/my_account.html:5 -#: rhodecode/templates/base/base.html:340 +#: rhodecode/templates/base/base.html:342 msgid "My account" msgstr "" @@ -3575,29 +3570,29 @@ msgstr "" msgid "Auth Tokens" msgstr "" -#: rhodecode/templates/admin/my_account/my_account.html:32 +#: rhodecode/templates/admin/my_account/my_account.html:34 msgid "OAuth Identities" msgstr "" -#: rhodecode/templates/admin/my_account/my_account.html:33 -msgid "My Emails" -msgstr "" - -#: rhodecode/templates/admin/my_account/my_account.html:34 -msgid "My Repositories" -msgstr "" - -#: rhodecode/templates/admin/my_account/my_account.html:35 -msgid "Watched" -msgstr "" - -#: rhodecode/templates/admin/my_account/my_account.html:36 -#: rhodecode/templates/admin/notifications/notifications.html:33 -#: rhodecode/templates/base/base.html:240 -msgid "Pull Requests" -msgstr "" - #: rhodecode/templates/admin/my_account/my_account.html:37 +msgid "My Emails" +msgstr "" + +#: rhodecode/templates/admin/my_account/my_account.html:38 +msgid "My Repositories" +msgstr "" + +#: rhodecode/templates/admin/my_account/my_account.html:39 +msgid "Watched" +msgstr "" + +#: rhodecode/templates/admin/my_account/my_account.html:40 +#: rhodecode/templates/admin/notifications/notifications.html:33 +#: rhodecode/templates/base/base.html:242 +msgid "Pull Requests" +msgstr "" + +#: rhodecode/templates/admin/my_account/my_account.html:41 msgid "My Permissions" msgstr "" @@ -3687,26 +3682,6 @@ msgstr "" msgid "New email address" msgstr "" -#: rhodecode/templates/admin/my_account/my_account_oauth.html:5 -msgid "Oauth Identities" -msgstr "" - -#: rhodecode/templates/admin/my_account/my_account_oauth.html:9 -msgid "External services currently connected with your Rhodecode user" -msgstr "" - -#: rhodecode/templates/admin/my_account/my_account_oauth.html:15 -msgid "No social authentication plugins are enabled by administrator" -msgstr "" - -#: rhodecode/templates/admin/my_account/my_account_oauth.html:49 -msgid "Confirm to remove this provider from your account" -msgstr "" - -#: rhodecode/templates/admin/my_account/my_account_oauth.html:59 -msgid "You have no accounts linked yet" -msgstr "" - #: rhodecode/templates/admin/my_account/my_account_password.html:3 msgid "Change Your Account Password" msgstr "" @@ -3756,42 +3731,60 @@ msgstr "" msgid "Show Closed Pull Requests" msgstr "" -#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:16 +#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:15 msgid "Pull Requests You Opened" msgstr "" +#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:23 +#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:86 +msgid "Target Repo" +msgstr "" + +#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:26 +#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:89 +#: rhodecode/templates/admin/settings/settings_global.html:9 +#: rhodecode/templates/email_templates/pull_request_review.mako:28 +#: rhodecode/templates/email_templates/pull_request_review.mako:65 +#: rhodecode/templates/pullrequests/pullrequest.html:38 +#: rhodecode/templates/pullrequests/pullrequests.html:104 +msgid "Title" +msgstr "" + #: rhodecode/templates/admin/my_account/my_account_pullrequests.html:27 -#, python-format -msgid "Pull request #%s opened on %s" -msgstr "" - -#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:29 -#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:64 +#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:90 +msgid "Opened On" +msgstr "" + +#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:41 +#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:103 +#: rhodecode/templates/changelog/changelog.html:141 +#: rhodecode/templates/compare/compare_commits.html:49 +#: rhodecode/templates/search/search_commit.html:36 +msgid "Expand commit message" +msgstr "" + +#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:50 +#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:112 #: rhodecode/templates/changeset/changeset_file_comment.html:284 #: rhodecode/templates/pullrequests/pullrequest_show.html:14 #: rhodecode/templates/pullrequests/pullrequest_show.html:112 -#: rhodecode/templates/pullrequests/pullrequests.html:51 +#: rhodecode/templates/pullrequests/pullrequests.html:52 msgid "Closed" msgstr "" -#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:35 +#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:62 msgid "Confirm to delete this pull request" msgstr "" -#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:42 +#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:69 msgid "You currently have no open pull requests." msgstr "" -#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:50 +#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:77 msgid "Pull Requests You Participate In" msgstr "" -#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:61 -#, python-format -msgid "Pull request #%s opened by %s on %s" -msgstr "" - -#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:70 +#: rhodecode/templates/admin/my_account/my_account_pullrequests.html:125 msgid "There are currently no open pull requests requiring your participation." msgstr "" @@ -3972,12 +3965,12 @@ msgstr "" #: rhodecode/templates/admin/repo_groups/repo_group_add.html:14 #: rhodecode/templates/admin/users/user_edit_advanced.html:12 -#: rhodecode/templates/base/base.html:80 rhodecode/templates/base/base.html:150 +#: rhodecode/templates/base/base.html:80 rhodecode/templates/base/base.html:152 msgid "Repository groups" msgstr "" #: rhodecode/templates/admin/repo_groups/repo_group_add.html:36 -#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:13 +#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:15 msgid "Group Name" msgstr "" @@ -4008,7 +4001,7 @@ msgstr "" #: rhodecode/templates/admin/repos/repo_edit.html:39 #: rhodecode/templates/admin/settings/settings.html:14 #: rhodecode/templates/admin/user_groups/user_group_edit.html:33 -#: rhodecode/templates/base/base.html:86 rhodecode/templates/base/base.html:248 +#: rhodecode/templates/base/base.html:86 rhodecode/templates/base/base.html:250 msgid "Settings" msgstr "" @@ -4101,7 +4094,7 @@ msgstr "" #: rhodecode/templates/admin/repo_groups/repo_group_edit_perms.html:34 #: rhodecode/templates/admin/repos/repo_edit_permissions.html:34 #: rhodecode/templates/admin/user_groups/user_group_edit_perms.html:34 -#: rhodecode/templates/pullrequests/pullrequest_show.html:200 +#: rhodecode/templates/pullrequests/pullrequest_show.html:199 msgid "owner" msgstr "" @@ -4144,24 +4137,24 @@ msgstr "" msgid "Set or revoke permissions to selected types of children of this group, including non-private repositories and other groups if chosen." msgstr "" -#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:4 +#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:6 #, python-format msgid "Settings for Repository Group: %s" msgstr "" -#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:25 -msgid "Change Repository Group Owner." -msgstr "" - -#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:39 -msgid "Group parent" -msgstr "" - -#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:47 -msgid "Enable Repository Locking" +#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:36 +msgid "Change owner of this repository group." msgstr "" #: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:51 +msgid "Group parent" +msgstr "" + +#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:59 +msgid "Enable Repository Locking" +msgstr "" + +#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html:63 msgid "Repository locking will be enabled on all subgroups and repositories inside this repository group. Pulling from a repository locks it, and it is unlocked by pushing back by the same user." msgstr "" @@ -4186,7 +4179,7 @@ msgid "Import Existing Repository ?" msgstr "" #: rhodecode/templates/admin/repos/repo_add_base.html:23 -#: rhodecode/templates/base/base.html:195 +#: rhodecode/templates/base/base.html:197 msgid "Clone from" msgstr "" @@ -4195,7 +4188,7 @@ msgid "Optional http[s] URL from which t msgstr "" #: rhodecode/templates/admin/repos/repo_add_base.html:36 -#: rhodecode/templates/admin/repos/repo_edit_settings.html:87 +#: rhodecode/templates/admin/repos/repo_edit_settings.html:100 #: rhodecode/templates/forks/fork.html:52 msgid "Keep it short and to the point. Use a README file for longer descriptions." msgstr "" @@ -4205,7 +4198,7 @@ msgid "Repository Group" msgstr "" #: rhodecode/templates/admin/repos/repo_add_base.html:46 -#: rhodecode/templates/admin/repos/repo_edit_settings.html:58 +#: rhodecode/templates/admin/repos/repo_edit_settings.html:61 #: rhodecode/templates/forks/fork.html:63 #, python-format msgid "Select my personal group (%(repo_group_name)s)" @@ -4225,7 +4218,7 @@ msgid "Set the type of repository to cre msgstr "" #: rhodecode/templates/admin/repos/repo_add_base.html:71 -#: rhodecode/templates/admin/repos/repo_edit_settings.html:65 +#: rhodecode/templates/admin/repos/repo_edit_settings.html:68 #: rhodecode/templates/forks/fork.html:71 msgid "Landing commit" msgstr "" @@ -4424,7 +4417,7 @@ msgstr "" #: rhodecode/templates/admin/repos/repo_edit_caches.html:37 #: rhodecode/templates/admin/user_groups/user_group_add.html:52 -#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:38 +#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:51 #: rhodecode/templates/admin/user_groups/user_groups.html:62 #: rhodecode/templates/admin/users/user_add.html:97 #: rhodecode/templates/admin/users/user_edit_profile.html:90 @@ -4535,99 +4528,99 @@ msgstr "" msgid "This repository does not have any remote mirror url set." msgstr "" -#: rhodecode/templates/admin/repos/repo_edit_settings.html:3 +#: rhodecode/templates/admin/repos/repo_edit_settings.html:6 #, python-format msgid "Settings for Repository: %s" msgstr "" -#: rhodecode/templates/admin/repos/repo_edit_settings.html:16 -msgid "Non-changeable id" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_settings.html:16 -msgid "what is that ?" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_settings.html:18 -msgid "URL by id" -msgstr "" - #: rhodecode/templates/admin/repos/repo_edit_settings.html:19 +msgid "Non-changeable id" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit_settings.html:19 +msgid "what is that ?" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit_settings.html:21 +msgid "URL by id" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit_settings.html:22 msgid "" "In case this repository is renamed or moved into another group the repository url changes.\n" " Using above url guarantees that this repository will always be accessible under such url.\n" " Useful for CI systems, or any other cases that you need to hardcode the url into 3rd party service." msgstr "" -#: rhodecode/templates/admin/repos/repo_edit_settings.html:27 +#: rhodecode/templates/admin/repos/repo_edit_settings.html:30 msgid "Remote uri" msgstr "" -#: rhodecode/templates/admin/repos/repo_edit_settings.html:33 -#: rhodecode/templates/base/perms_summary.html:80 -#: rhodecode/templates/base/perms_summary.html:142 -#: rhodecode/templates/base/perms_summary.html:144 -#: rhodecode/templates/debug_style/form-elements.html:45 -msgid "edit" -msgstr "" - #: rhodecode/templates/admin/repos/repo_edit_settings.html:36 +#: rhodecode/templates/base/perms_summary.html:79 +#: rhodecode/templates/base/perms_summary.html:149 +#: rhodecode/templates/base/perms_summary.html:151 +#: rhodecode/templates/debug_style/form-elements.html:45 +msgid "edit" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit_settings.html:39 msgid "new value, leave empty to remove" msgstr "" -#: rhodecode/templates/admin/repos/repo_edit_settings.html:38 +#: rhodecode/templates/admin/repos/repo_edit_settings.html:41 msgid "cancel" msgstr "" -#: rhodecode/templates/admin/repos/repo_edit_settings.html:45 +#: rhodecode/templates/admin/repos/repo_edit_settings.html:48 msgid "http[s] url where from repository was imported, also used for doing remote pulls." msgstr "" -#: rhodecode/templates/admin/repos/repo_edit_settings.html:53 +#: rhodecode/templates/admin/repos/repo_edit_settings.html:56 #: rhodecode/templates/data_table/_dt_elements.html:158 #: rhodecode/templates/forks/fork.html:58 msgid "Repository group" msgstr "" -#: rhodecode/templates/admin/repos/repo_edit_settings.html:60 +#: rhodecode/templates/admin/repos/repo_edit_settings.html:63 msgid "Optional select a group to put this repository into." msgstr "" -#: rhodecode/templates/admin/repos/repo_edit_settings.html:69 +#: rhodecode/templates/admin/repos/repo_edit_settings.html:72 #: rhodecode/templates/forks/fork.html:75 msgid "Default commit for files page, downloads, whoosh and readme" msgstr "" -#: rhodecode/templates/admin/repos/repo_edit_settings.html:78 +#: rhodecode/templates/admin/repos/repo_edit_settings.html:90 msgid "Change owner of this repository." msgstr "" -#: rhodecode/templates/admin/repos/repo_edit_settings.html:93 -#: rhodecode/templates/data_table/_dt_elements.html:58 -msgid "Private repository" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_settings.html:102 -msgid "Enable statistics" -msgstr "" - #: rhodecode/templates/admin/repos/repo_edit_settings.html:106 -msgid "Enable statistics window on summary page." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_settings.html:111 -msgid "Enable downloads" +#: rhodecode/templates/data_table/_dt_elements.html:58 +msgid "Private repository" msgstr "" #: rhodecode/templates/admin/repos/repo_edit_settings.html:115 -msgid "Enable download menu on summary page." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_settings.html:120 -msgid "Enable automatic locking" +msgid "Enable statistics" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit_settings.html:119 +msgid "Enable statistics window on summary page." msgstr "" #: rhodecode/templates/admin/repos/repo_edit_settings.html:124 +msgid "Enable downloads" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit_settings.html:128 +msgid "Enable download menu on summary page." +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit_settings.html:133 +msgid "Enable automatic locking" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit_settings.html:137 msgid "Enable automatic locking on repository. Pulling from this repository creates a lock that can be released by pushing back by the same user" msgstr "" @@ -4747,14 +4740,6 @@ msgstr "" msgid "Branding" msgstr "" -#: rhodecode/templates/admin/settings/settings_global.html:9 -#: rhodecode/templates/email_templates/pull_request_review.mako:28 -#: rhodecode/templates/email_templates/pull_request_review.mako:65 -#: rhodecode/templates/pullrequests/pullrequest.html:38 -#: rhodecode/templates/pullrequests/pullrequests.html:104 -msgid "Title" -msgstr "" - #: rhodecode/templates/admin/settings/settings_global.html:16 msgid "Set a custom title for your RhodeCode instance (limited to 40 characters)." msgstr "" @@ -4910,6 +4895,7 @@ msgid "Last %(size)s bytes of process lo msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:4 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:4 msgid "RhodeCode Enterprise version" msgstr "" @@ -4918,6 +4904,7 @@ msgid "check for updates" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:5 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:5 msgid "Upgrade info endpoint" msgstr "" @@ -4926,50 +4913,62 @@ msgid "Note: please make sure this serve msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:6 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:6 msgid "Configuration INI file" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:8 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:8 msgid "RhodeCode Enterprise Server IP" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:9 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:9 msgid "RhodeCode Enterprise Server ID" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:10 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:10 msgid "Platform" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:11 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:11 msgid "Uptime" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:12 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:12 msgid "Storage location" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:13 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:13 msgid "Storage disk space" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:15 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:15 msgid "Search index storage" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:16 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:16 msgid "Search index size" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:18 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:18 msgid "Gist storage" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:19 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:19 msgid "Gist storage size" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:21 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:21 msgid "Archive cache" msgstr "" @@ -4978,46 +4977,57 @@ msgid "Enable this by setting archive_ca msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:22 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:22 msgid "Archive cache size" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:24 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:24 msgid "System memory" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:25 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:25 msgid "CPU" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:26 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:26 msgid "Load" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:29 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:29 msgid "Python version" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:30 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:30 msgid "Python path" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:31 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:31 msgid "GIT version" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:32 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:32 msgid "HG version" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:33 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:33 msgid "SVN version" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:34 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:34 msgid "Database" msgstr "" #: rhodecode/templates/admin/settings/settings_system.html:35 +#: rhodecode/templates/admin/settings/settings_system_snapshot.html:35 msgid "Database version" msgstr "" @@ -5025,7 +5035,11 @@ msgstr "" msgid "Checking for updates..." msgstr "" -#: rhodecode/templates/admin/settings/settings_system.html:61 +#: rhodecode/templates/admin/settings/settings_system.html:49 +msgid "create snapshot" +msgstr "" + +#: rhodecode/templates/admin/settings/settings_system.html:64 msgid "Python Packages" msgstr "" @@ -5197,7 +5211,7 @@ msgstr "" #: rhodecode/templates/admin/user_groups/user_group_add.html:13 #: rhodecode/templates/admin/users/user_edit_advanced.html:13 -#: rhodecode/templates/base/base.html:82 rhodecode/templates/base/base.html:153 +#: rhodecode/templates/base/base.html:82 rhodecode/templates/base/base.html:155 msgid "User groups" msgstr "" @@ -5207,12 +5221,12 @@ msgid "Add User Group" msgstr "" #: rhodecode/templates/admin/user_groups/user_group_add.html:35 -#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:12 +#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:15 msgid "Group name" msgstr "" #: rhodecode/templates/admin/user_groups/user_group_add.html:47 -#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:33 +#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:46 msgid "Short, optional description for this user group." msgstr "" @@ -5233,7 +5247,6 @@ msgstr "" #: rhodecode/templates/admin/user_groups/user_group_edit.html:38 #: rhodecode/templates/admin/user_groups/user_group_edit_advanced.html:8 -#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:46 #: rhodecode/templates/admin/user_groups/user_groups.html:60 #: rhodecode/templates/debug_style/form-elements.html:509 msgid "Members" @@ -5248,7 +5261,7 @@ msgid "Assigned to repo groups" msgstr "" #: rhodecode/templates/admin/user_groups/user_group_edit_advanced.html:17 -#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:3 +#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:6 #, python-format msgid "User Group: %s" msgstr "" @@ -5284,32 +5297,36 @@ msgstr "" msgid "revoke" msgstr "" -#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:24 +#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:36 msgid "Change owner of this user group." msgstr "" -#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:50 +#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:59 +#: rhodecode/templates/base/base.html:257 +#: rhodecode/templates/base/base.html:399 +#: rhodecode/templates/search/search.html:64 +msgid "Search" +msgstr "" + +#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:66 #: rhodecode/templates/debug_style/form-elements.html:513 #: rhodecode/templates/debug_style/form-elements.html:571 #: rhodecode/templates/debug_style/forms.html:236 msgid "Chosen group members" msgstr "" -#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:53 +#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:69 #: rhodecode/templates/debug_style/form-elements.html:525 #: rhodecode/templates/debug_style/form-elements.html:575 #: rhodecode/templates/debug_style/forms.html:240 msgid "Remove all elements" msgstr "" -#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:63 -#: rhodecode/templates/debug_style/form-elements.html:535 -#: rhodecode/templates/debug_style/form-elements.html:585 -#: rhodecode/templates/debug_style/forms.html:250 -msgid "Available members" -msgstr "" - -#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:66 +#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:79 +msgid "Available users" +msgstr "" + +#: rhodecode/templates/admin/user_groups/user_group_edit_settings.html:83 #: rhodecode/templates/debug_style/form-elements.html:543 #: rhodecode/templates/debug_style/form-elements.html:593 #: rhodecode/templates/debug_style/forms.html:258 @@ -5361,7 +5378,7 @@ msgid "" "User will be automatically set as this group owner." msgstr "" -#: rhodecode/templates/admin/users/user_add.html:137 +#: rhodecode/templates/admin/users/user_add.html:136 msgid "generated password:" msgstr "" @@ -5598,40 +5615,40 @@ msgstr "" msgid "Show More" msgstr "" -#: rhodecode/templates/base/base.html:187 +#: rhodecode/templates/base/base.html:189 msgid "Fork of" msgstr "" -#: rhodecode/templates/base/base.html:204 +#: rhodecode/templates/base/base.html:206 #, python-format msgid "Repository locked by %(user)s" msgstr "" -#: rhodecode/templates/base/base.html:209 +#: rhodecode/templates/base/base.html:211 msgid "Repository not locked. Pull repository to lock it." msgstr "" -#: rhodecode/templates/base/base.html:227 +#: rhodecode/templates/base/base.html:229 #: rhodecode/templates/data_table/_dt_elements.html:12 #: rhodecode/templates/data_table/_dt_elements.html:13 #: rhodecode/templates/data_table/_dt_elements.html:147 msgid "Summary" msgstr "" -#: rhodecode/templates/base/base.html:228 +#: rhodecode/templates/base/base.html:230 #: rhodecode/templates/data_table/_dt_elements.html:17 #: rhodecode/templates/data_table/_dt_elements.html:18 msgid "Changelog" msgstr "" -#: rhodecode/templates/base/base.html:229 +#: rhodecode/templates/base/base.html:231 #: rhodecode/templates/data_table/_dt_elements.html:22 #: rhodecode/templates/data_table/_dt_elements.html:23 #: rhodecode/templates/files/files.html:15 msgid "Files" msgstr "" -#: rhodecode/templates/base/base.html:231 +#: rhodecode/templates/base/base.html:233 #: rhodecode/templates/bookmarks/bookmarks.html:68 #: rhodecode/templates/branches/branches.html:67 #: rhodecode/templates/files/file_diff.html:11 @@ -5640,111 +5657,105 @@ msgstr "" msgid "Compare" msgstr "" -#: rhodecode/templates/base/base.html:236 +#: rhodecode/templates/base/base.html:238 #, python-format msgid "Show Pull Requests for %s" msgstr "" -#: rhodecode/templates/base/base.html:245 +#: rhodecode/templates/base/base.html:247 msgid "Options" msgstr "" -#: rhodecode/templates/base/base.html:252 -#: rhodecode/templates/forks/forks_data.html:28 +#: rhodecode/templates/base/base.html:254 +#: rhodecode/templates/forks/forks_data.html:30 msgid "Compare fork" msgstr "" -#: rhodecode/templates/base/base.html:255 -#: rhodecode/templates/base/base.html:397 -#: rhodecode/templates/search/search.html:64 -msgid "Search" -msgstr "" - -#: rhodecode/templates/base/base.html:259 -msgid "Unlock" -msgstr "" - #: rhodecode/templates/base/base.html:261 +msgid "Unlock" +msgstr "" + +#: rhodecode/templates/base/base.html:263 msgid "Lock" msgstr "" -#: rhodecode/templates/base/base.html:266 +#: rhodecode/templates/base/base.html:268 #: rhodecode/templates/data_table/_dt_elements.html:27 #: rhodecode/templates/data_table/_dt_elements.html:28 -#: rhodecode/templates/forks/forks_data.html:7 +#: rhodecode/templates/forks/forks_data.html:8 #: rhodecode/templates/summary/components.html:103 msgid "Fork" msgid_plural "Forks" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/base/base.html:267 +#: rhodecode/templates/base/base.html:269 msgid "Create Pull Request" msgstr "" -#: rhodecode/templates/base/base.html:289 +#: rhodecode/templates/base/base.html:291 msgid "Sign in" msgstr "" -#: rhodecode/templates/base/base.html:297 +#: rhodecode/templates/base/base.html:299 #: rhodecode/templates/debug_style/login.html:28 msgid "Sign in to your account" msgstr "" -#: rhodecode/templates/base/base.html:313 +#: rhodecode/templates/base/base.html:315 #: rhodecode/templates/debug_style/login.html:46 msgid "(Forgot password?)" msgstr "" -#: rhodecode/templates/base/base.html:322 +#: rhodecode/templates/base/base.html:324 #: rhodecode/templates/debug_style/login.html:56 msgid "Don't have an account ?" msgstr "" -#: rhodecode/templates/base/base.html:343 +#: rhodecode/templates/base/base.html:345 msgid "Sign Out" msgstr "" -#: rhodecode/templates/base/base.html:379 +#: rhodecode/templates/base/base.html:381 msgid "Show activity journal" msgstr "" -#: rhodecode/templates/base/base.html:380 +#: rhodecode/templates/base/base.html:382 #: rhodecode/templates/journal/journal.html:4 #: rhodecode/templates/journal/journal.html:14 msgid "Journal" msgstr "" -#: rhodecode/templates/base/base.html:385 +#: rhodecode/templates/base/base.html:387 msgid "Show Public activity journal" msgstr "" -#: rhodecode/templates/base/base.html:386 +#: rhodecode/templates/base/base.html:388 msgid "Public journal" msgstr "" -#: rhodecode/templates/base/base.html:391 +#: rhodecode/templates/base/base.html:393 msgid "Show Gists" msgstr "" -#: rhodecode/templates/base/base.html:392 +#: rhodecode/templates/base/base.html:394 msgid "Gists" msgstr "" -#: rhodecode/templates/base/base.html:396 +#: rhodecode/templates/base/base.html:398 msgid "Search in repositories you have access to" msgstr "" -#: rhodecode/templates/base/base.html:402 +#: rhodecode/templates/base/base.html:404 msgid "Admin settings" msgstr "" -#: rhodecode/templates/base/base.html:409 +#: rhodecode/templates/base/base.html:411 msgid "Delegated Admin settings" msgstr "" -#: rhodecode/templates/base/base.html:419 -#: rhodecode/templates/base/base.html:420 +#: rhodecode/templates/base/base.html:421 +#: rhodecode/templates/base/base.html:422 #: rhodecode/templates/debug_style/buttons.html:5 #: rhodecode/templates/debug_style/code-block.html:6 #: rhodecode/templates/debug_style/collapsable-content.html:5 @@ -5765,15 +5776,15 @@ msgstr "" msgid "Style" msgstr "" -#: rhodecode/templates/base/base.html:474 +#: rhodecode/templates/base/base.html:479 msgid "Go to" msgstr "" -#: rhodecode/templates/base/base.html:585 +#: rhodecode/templates/base/base.html:590 msgid "Keyboard shortcuts" msgstr "" -#: rhodecode/templates/base/base.html:593 +#: rhodecode/templates/base/base.html:598 msgid "Site-wide shortcuts" msgstr "" @@ -5878,88 +5889,80 @@ msgstr "" msgid "Test Pattern Preview" msgstr "" +#: rhodecode/templates/base/perms_summary.html:18 +msgid "show" +msgstr "" + #: rhodecode/templates/base/perms_summary.html:19 -msgid "show" +msgid "none" msgstr "" #: rhodecode/templates/base/perms_summary.html:20 -msgid "none" +msgid "read" msgstr "" #: rhodecode/templates/base/perms_summary.html:21 -msgid "read" +msgid "write" msgstr "" #: rhodecode/templates/base/perms_summary.html:22 -msgid "write" -msgstr "" - -#: rhodecode/templates/base/perms_summary.html:23 msgid "admin" msgstr "" -#: rhodecode/templates/base/perms_summary.html:30 +#: rhodecode/templates/base/perms_summary.html:29 msgid "No permissions defined" msgstr "" -#: rhodecode/templates/base/perms_summary.html:38 -#: rhodecode/templates/base/perms_summary.html:104 +#: rhodecode/templates/base/perms_summary.html:37 +#: rhodecode/templates/base/perms_summary.html:103 msgid "Permission" msgstr "" -#: rhodecode/templates/base/perms_summary.html:40 -#: rhodecode/templates/base/perms_summary.html:106 +#: rhodecode/templates/base/perms_summary.html:39 +#: rhodecode/templates/base/perms_summary.html:105 msgid "Edit Permission" msgstr "" -#: rhodecode/templates/base/perms_summary.html:86 +#: rhodecode/templates/base/perms_summary.html:85 msgid "Super admin" msgstr "" +#: rhodecode/templates/base/perms_summary.html:87 +msgid "Repository default permission" +msgstr "" + #: rhodecode/templates/base/perms_summary.html:88 -msgid "Repository default permission" +msgid "Repository group default permission" msgstr "" #: rhodecode/templates/base/perms_summary.html:89 -msgid "Repository group default permission" -msgstr "" - -#: rhodecode/templates/base/perms_summary.html:90 msgid "User group default permission" msgstr "" +#: rhodecode/templates/base/perms_summary.html:91 +msgid "Create repositories" +msgstr "" + #: rhodecode/templates/base/perms_summary.html:92 -msgid "Create repositories" +msgid "Fork repositories" msgstr "" #: rhodecode/templates/base/perms_summary.html:93 -msgid "Fork repositories" +msgid "Create repository groups" msgstr "" #: rhodecode/templates/base/perms_summary.html:94 -msgid "Create repository groups" -msgstr "" - -#: rhodecode/templates/base/perms_summary.html:95 msgid "Create user groups" msgstr "" -#: rhodecode/templates/base/perms_summary.html:155 +#: rhodecode/templates/base/perms_summary.html:162 msgid "No permission defined" msgstr "" -#: rhodecode/templates/base/root.html:150 +#: rhodecode/templates/base/root.html:151 msgid "Please enable JavaScript to use RhodeCode Enterprise" msgstr "" -#: rhodecode/templates/base/social_buttons.html:6 -msgid "Sign in with" -msgstr "" - -#: rhodecode/templates/base/social_buttons.html:8 -msgid "Connect with" -msgstr "" - #: rhodecode/templates/base/vcs_settings.html:16 msgid "Require SSL for vcs operations" msgstr "" @@ -6133,7 +6136,7 @@ msgstr[0] "" msgstr[1] "" #: rhodecode/templates/changelog/changelog.html:41 -#: rhodecode/templates/forks/forks_data.html:26 +#: rhodecode/templates/forks/forks_data.html:28 #, python-format msgid "Compare fork with %s" msgstr "" @@ -6158,7 +6161,6 @@ msgstr "" #: rhodecode/templates/changelog/changelog.html:103 #: rhodecode/templates/changelog/changelog_summary_data.html:9 -#: rhodecode/templates/search/search_commit.html:9 msgid "Age" msgstr "" @@ -6187,12 +6189,6 @@ msgstr "" msgid "Commit status: %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:141 -#: rhodecode/templates/compare/compare_cs.html:47 -#: rhodecode/templates/search/search_commit.html:30 -msgid "Expand commit message" -msgstr "" - #: rhodecode/templates/changelog/changelog.html:162 #: rhodecode/templates/changelog/changelog_summary_data.html:33 msgid "Commit has comments" @@ -6599,15 +6595,15 @@ msgid_plural "%(num)s files changed: %(l msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/compare/compare_cs.html:5 +#: rhodecode/templates/compare/compare_commits.html:5 msgid "No Commits" msgstr "" -#: rhodecode/templates/compare/compare_cs.html:9 +#: rhodecode/templates/compare/compare_commits.html:9 msgid "Common Ancestor Commit" msgstr "" -#: rhodecode/templates/compare/compare_cs.html:20 +#: rhodecode/templates/compare/compare_commits.html:20 msgid "Time" msgstr "" @@ -6727,6 +6723,12 @@ msgstr "" msgid "Default" msgstr "" +#: rhodecode/templates/debug_style/form-elements.html:535 +#: rhodecode/templates/debug_style/form-elements.html:585 +#: rhodecode/templates/debug_style/forms.html:250 +msgid "Available members" +msgstr "" + #: rhodecode/templates/debug_style/forms.html:119 msgid "Some text..." msgstr "" @@ -7208,7 +7210,7 @@ msgid "Location" msgstr "" #: rhodecode/templates/files/files_source.html:6 -#: rhodecode/templates/search/search_content.html:20 +#: rhodecode/templates/search/search_content.html:57 msgid "line" msgid_plural "lines" msgstr[0] "" @@ -7219,22 +7221,22 @@ msgid "History" msgstr "" #: rhodecode/templates/files/files_source.html:15 -#: rhodecode/templates/search/search_content.html:31 +#: rhodecode/templates/search/search_content.html:68 msgid "Show Full History" msgstr "" #: rhodecode/templates/files/files_source.html:20 -#: rhodecode/templates/search/search_content.html:33 +#: rhodecode/templates/search/search_content.html:70 msgid "Annotation" msgstr "" #: rhodecode/templates/files/files_source.html:22 -#: rhodecode/templates/search/search_content.html:34 +#: rhodecode/templates/search/search_content.html:71 msgid "Raw" msgstr "" #: rhodecode/templates/files/files_source.html:24 -#: rhodecode/templates/search/search_content.html:36 +#: rhodecode/templates/search/search_content.html:73 msgid "Download" msgstr "" @@ -7311,11 +7313,11 @@ msgstr "" msgid "Create new fork" msgstr "" -#: rhodecode/templates/forks/forks_data.html:9 +#: rhodecode/templates/forks/forks_data.html:10 msgid "Forked" msgstr "" -#: rhodecode/templates/forks/forks_data.html:46 +#: rhodecode/templates/forks/forks_data.html:48 msgid "There are no forks yet" msgstr "" @@ -7383,35 +7385,35 @@ msgstr "" msgid "Add reviewer" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:278 -#: rhodecode/templates/pullrequests/pullrequest.html:520 +#: rhodecode/templates/pullrequests/pullrequest.html:279 +#: rhodecode/templates/pullrequests/pullrequest.html:521 msgid "Please select origin and destination" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:284 +#: rhodecode/templates/pullrequests/pullrequest.html:285 msgid "Loading compare ..." msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:331 -#: rhodecode/templates/pullrequests/pullrequest.html:333 +#: rhodecode/templates/pullrequests/pullrequest.html:332 +#: rhodecode/templates/pullrequests/pullrequest.html:334 msgid "This pull request will consist of __COMMITS__ commit." msgid_plural "This pull request will consist of __COMMITS__ commits." msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/pullrequests/pullrequest.html:336 +#: rhodecode/templates/pullrequests/pullrequest.html:337 msgid "Show detailed compare." msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:343 +#: rhodecode/templates/pullrequests/pullrequest.html:344 msgid "There are no commits to merge." msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:450 +#: rhodecode/templates/pullrequests/pullrequest.html:451 msgid "Destination repository" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:461 +#: rhodecode/templates/pullrequests/pullrequest.html:462 msgid "Select commit reference" msgstr "" @@ -7468,7 +7470,7 @@ msgstr "" msgid "Save Changes" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:200 +#: rhodecode/templates/pullrequests/pullrequest_show.html:199 msgid "reviewer" msgstr "" @@ -7531,13 +7533,13 @@ msgid "Opened by me" msgstr "" #: rhodecode/templates/pullrequests/pullrequests.html:50 +msgid "Awaiting review" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequests.html:51 msgid "Awaiting my review" msgstr "" -#: rhodecode/templates/pullrequests/pullrequests.html:52 -msgid "Awaiting review" -msgstr "" - #: rhodecode/templates/pullrequests/pullrequests.html:53 msgid "From this repo" msgstr "" @@ -7599,6 +7601,18 @@ msgstr "" msgid "File names" msgstr "" +#: rhodecode/templates/search/search_commit.html:11 +msgid "Age (new first)" +msgstr "" + +#: rhodecode/templates/search/search_commit.html:13 +msgid "Age (old first)" +msgstr "" + +#: rhodecode/templates/search/search_content.html:33 +msgid "more matches in this file" +msgstr "" + #: rhodecode/templates/search/search_path.html:4 msgid "File" msgstr "" diff --git a/rhodecode/interfaces.py b/rhodecode/interfaces.py --- a/rhodecode/interfaces.py +++ b/rhodecode/interfaces.py @@ -26,3 +26,18 @@ class IUserRegistered(Interface): """ user = Attribute('The user object.') session = Attribute('The session while processing the register form post.') + + +class IUserPreCreate(Interface): + """ + An event type that is emitted before a new user object is created. + """ + user_data = Attribute('Data used to create the new user') + + +class IUserPreUpdate(Interface): + """ + An event type that is emitted before a user object is updated. + """ + user = Attribute('The not yet updated user object') + user_data = Attribute('Data used to update the user') diff --git a/rhodecode/lib/base.py b/rhodecode/lib/base.py --- a/rhodecode/lib/base.py +++ b/rhodecode/lib/base.py @@ -255,7 +255,7 @@ class BasicAuth(AuthBasicAuthenticator): def attach_context_attributes(context): - rc_config = SettingsModel().get_all_settings() + rc_config = SettingsModel().get_all_settings(cache=True) context.rhodecode_version = rhodecode.__version__ context.rhodecode_edition = config.get('rhodecode.edition') @@ -425,7 +425,7 @@ class BaseController(WSGIController): _route_name = '.'.join([environ['pylons.routes_dict']['controller'], environ['pylons.routes_dict']['action']]) - self.rc_config = SettingsModel().get_all_settings() + self.rc_config = SettingsModel().get_all_settings(cache=True) self.ip_addr = get_ip_addr(environ) # The rhodecode auth user is looked up and passed through the diff --git a/rhodecode/lib/caches.py b/rhodecode/lib/caches.py --- a/rhodecode/lib/caches.py +++ b/rhodecode/lib/caches.py @@ -87,6 +87,12 @@ def get_cache_manager(region_name, cache def clear_cache_manager(cache_manager): + """ + namespace = 'foobar' + cache_manager = get_cache_manager('repo_cache_long', namespace) + clear_cache_manager(cache_manager) + """ + log.debug('Clearing all values for cache manager %s', cache_manager) cache_manager.clear() @@ -161,7 +167,7 @@ class FreshRegionCache(ActiveRegionCache class InvalidationContext(object): def __repr__(self): return ''.format( - self.repo_name, self.cache_type) + safe_str(self.repo_name), safe_str(self.cache_type)) def __init__(self, compute_func, repo_name, cache_type, raise_exception=False): diff --git a/rhodecode/lib/celerylib/__init__.py b/rhodecode/lib/celerylib/__init__.py --- a/rhodecode/lib/celerylib/__init__.py +++ b/rhodecode/lib/celerylib/__init__.py @@ -34,7 +34,6 @@ from decorator import decorator from zope.cachedescriptors.property import Lazy as LazyProperty -from rhodecode import CELERY_ENABLED, CELERY_EAGER from rhodecode.config import utils from rhodecode.lib.utils2 import safe_str, md5_safe, aslist from rhodecode.lib.pidlock import DaemonLock, LockHeld @@ -54,8 +53,7 @@ class ResultWrapper(object): def run_task(task, *args, **kwargs): - global CELERY_ENABLED - if CELERY_ENABLED: + if rhodecode.CELERY_ENABLED: try: t = task.apply_async(args=args, kwargs=kwargs) log.info('running task %s:%s', t.task_id, task) @@ -63,18 +61,18 @@ def run_task(task, *args, **kwargs): except socket.error as e: if isinstance(e, IOError) and e.errno == 111: - log.debug('Unable to connect to celeryd. Sync execution') - CELERY_ENABLED = False + log.error('Unable to connect to celeryd. Sync execution') + rhodecode.CELERY_ENABLED = False else: log.exception("Exception while connecting to celeryd.") except KeyError as e: - log.debug('Unable to connect to celeryd. Sync execution') + log.error('Unable to connect to celeryd. Sync execution') except Exception as e: log.exception( "Exception while trying to run task asynchronous. " "Fallback to sync execution.") - - log.debug('executing task %s in sync mode', task) + else: + log.debug('executing task %s in sync mode', task) return ResultWrapper(task(*args, **kwargs)) @@ -106,7 +104,7 @@ def locked_task(func): def get_session(): - if CELERY_ENABLED: + if rhodecode.CELERY_ENABLED: utils.initialize_database(config) sa = meta.Session() return sa @@ -118,7 +116,7 @@ def dbsession(func): ret = func(*fargs, **fkwargs) return ret finally: - if CELERY_ENABLED and not CELERY_EAGER: + if rhodecode.CELERY_ENABLED and not rhodecode.CELERY_EAGER: meta.Session.remove() return decorator(__wrapper, func) @@ -126,7 +124,7 @@ def dbsession(func): def vcsconnection(func): def __wrapper(func, *fargs, **fkwargs): - if CELERY_ENABLED and not CELERY_EAGER: + if rhodecode.CELERY_ENABLED and not rhodecode.CELERY_EAGER: backends = config['vcs.backends'] = aslist( config.get('vcs.backends', 'hg,git'), sep=',') for alias in rhodecode.BACKENDS.keys(): diff --git a/rhodecode/lib/celerylib/tasks.py b/rhodecode/lib/celerylib/tasks.py --- a/rhodecode/lib/celerylib/tasks.py +++ b/rhodecode/lib/celerylib/tasks.py @@ -30,7 +30,7 @@ import logging from celery.task import task from pylons import config -from rhodecode import CELERY_ENABLED +import rhodecode from rhodecode.lib.celerylib import ( run_task, dbsession, __get_lockkey, LockHeld, DaemonLock, get_session, vcsconnection) @@ -45,7 +45,7 @@ add_cache(config) # pragma: no cover def get_logger(cls): - if CELERY_ENABLED: + if rhodecode.CELERY_ENABLED: try: log = cls.get_logger() except Exception: 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 @@ -478,9 +478,9 @@ class DbManage(object): elif not os.access(path, os.W_OK) and path_ok: log.warning('No write permission to given path %s' % (path,)) - q = ('Given path %s is not writeable, do you want to ' - 'continue with read only mode ? [y/n]' % (path,)) - if not self.ask_ok(q): + q = ('Given path %s is not writeable, do you want to ' + 'continue with read only mode ? [y/n]' % (path,)) + if not self.ask_ok(q): log.error('Canceled by user') sys.exit(-1) diff --git a/rhodecode/lib/encrypt.py b/rhodecode/lib/encrypt.py --- a/rhodecode/lib/encrypt.py +++ b/rhodecode/lib/encrypt.py @@ -23,31 +23,84 @@ Generic encryption library for RhodeCode """ -import hashlib import base64 from Crypto.Cipher import AES from Crypto import Random +from Crypto.Hash import HMAC, SHA256 from rhodecode.lib.utils2 import safe_str +class SignatureVerificationError(Exception): + pass + + +class InvalidDecryptedValue(str): + + def __new__(cls, content): + """ + This will generate something like this:: + + And represent a safe indicator that encryption key is broken + """ + content = '<{}({}...)>'.format(cls.__name__, content[:16]) + return str.__new__(cls, content) + + class AESCipher(object): - def __init__(self, key): - # create padding, trim to long enc key + def __init__(self, key, hmac=False, strict_verification=True): if not key: raise ValueError('passed key variable is empty') + self.strict_verification = strict_verification self.block_size = 32 - self.key = hashlib.sha256(safe_str(key)).digest() + self.hmac_size = 32 + self.hmac = hmac + + self.key = SHA256.new(safe_str(key)).digest() + self.hmac_key = SHA256.new(self.key).digest() + + def verify_hmac_signature(self, raw_data): + org_hmac_signature = raw_data[-self.hmac_size:] + data_without_sig = raw_data[:-self.hmac_size] + recomputed_hmac = HMAC.new( + self.hmac_key, data_without_sig, digestmod=SHA256).digest() + return org_hmac_signature == recomputed_hmac def encrypt(self, raw): raw = self._pad(raw) iv = Random.new().read(AES.block_size) cipher = AES.new(self.key, AES.MODE_CBC, iv) - return base64.b64encode(iv + cipher.encrypt(raw)) + enc_value = cipher.encrypt(raw) + + hmac_signature = '' + if self.hmac: + # compute hmac+sha256 on iv + enc text, we use + # encrypt then mac method to create the signature + hmac_signature = HMAC.new( + self.hmac_key, iv + enc_value, digestmod=SHA256).digest() + + return base64.b64encode(iv + enc_value + hmac_signature) def decrypt(self, enc): + enc_org = enc enc = base64.b64decode(enc) + + if self.hmac and len(enc) > self.hmac_size: + if self.verify_hmac_signature(enc): + # cut off the HMAC verification digest + enc = enc[:-self.hmac_size] + else: + if self.strict_verification: + raise SignatureVerificationError( + "Encryption signature verification failed. " + "Please check your secret key, and/or encrypted value. " + "Secret key is stored as " + "`rhodecode.encrypted_values.secret` or " + "`beaker.session.secret` inside .ini file") + + return InvalidDecryptedValue(enc_org) + iv = enc[:AES.block_size] cipher = AES.new(self.key, AES.MODE_CBC, iv) return self._unpad(cipher.decrypt(enc[AES.block_size:])) diff --git a/rhodecode/lib/helpers.py b/rhodecode/lib/helpers.py --- a/rhodecode/lib/helpers.py +++ b/rhodecode/lib/helpers.py @@ -438,15 +438,17 @@ def get_matching_line_offsets(lines, ter :param max_lines: cut off for lines of interest eg. - >>> get_matching_line_offsets(''' -words words words -words words words -some text some -words words words -words words words -text here what -''', 'text', context=1) + text = ''' + words words words + words words words + some text some + words words words + words words words + text here what + ''' + get_matching_line_offsets(text, 'text', context=1) {3: [(5, 9)], 6: [(0, 4)]] + """ matching_lines = {} phrases = [normalize_text_for_matching(phrase) @@ -460,6 +462,7 @@ text here what return matching_lines + def get_lexer_safe(mimetype=None, filepath=None): """ Tries to return a relevant pygments lexer using mimetype/filepath name, @@ -470,7 +473,7 @@ def get_lexer_safe(mimetype=None, filepa if mimetype: lexer = get_lexer_for_mimetype(mimetype) if not lexer: - lexer = get_lexer_for_filename(path) + lexer = get_lexer_for_filename(filepath) except pygments.util.ClassNotFound: pass @@ -675,11 +678,6 @@ def _shorten_commit_id(commit_id): return commit_id[:def_len] -def get_repo_id_from_name(repo_name): - repo = get_by_repo_name(repo_name) - return repo.repo_id - - def show_id(commit): """ Configurable function that shows ID @@ -744,6 +742,32 @@ def is_svn_without_proxy(repository): return False +def discover_user(author): + """ + Tries to discover RhodeCode User based on the autho string. Author string + is typically `FirstName LastName ` + """ + + # if author is already an instance use it for extraction + if isinstance(author, User): + return author + + # Valid email in the attribute passed, see if they're in the system + _email = author_email(author) + if _email != '': + user = User.get_by_email(_email, case_insensitive=True, cache=True) + if user is not None: + return user + + # Maybe it's a username, we try to extract it and fetch by username ? + _author = author_name(author) + user = User.get_by_username(_author, case_insensitive=True, cache=True) + if user is not None: + return user + + return None + + def email_or_none(author): # extract email from the commit string _email = author_email(author) @@ -765,30 +789,13 @@ def email_or_none(author): return None -def discover_user(author): - # if author is already an instance use it for extraction - if isinstance(author, User): - return author - - # Valid email in the attribute passed, see if they're in the system - _email = email(author) - if _email != '': - user = User.get_by_email(_email, case_insensitive=True, cache=True) - if user is not None: - return user - - # Maybe it's a username? - _author = author_name(author) - user = User.get_by_username(_author, case_insensitive=True, - cache=True) - if user is not None: - return user - - return None - - def link_to_user(author, length=0, **kwargs): user = discover_user(author) + # user can be None, but if we have it already it means we can re-use it + # in the person() function, so we save 1 intensive-query + if user: + author = user + display_person = person(author, 'username_or_name_or_email') if length: display_person = shorter(display_person, length) @@ -803,11 +810,9 @@ def link_to_user(author, length=0, **kwa def person(author, show_attr="username_and_name"): - # attr to return from fetched user - person_getter = lambda usr: getattr(usr, show_attr) user = discover_user(author) if user: - return person_getter(user) + return getattr(user, show_attr) else: _author = author_name(author) _email = email(author) @@ -827,10 +832,10 @@ def person_by_id(id_, show_attr="usernam return id_ -def gravatar_with_user(author): +def gravatar_with_user(author, show_disabled=False): from rhodecode.lib.utils import PartialRenderer _render = PartialRenderer('base/base.html') - return _render('gravatar_with_user', author) + return _render('gravatar_with_user', author, show_disabled=show_disabled) def desc_stylize(value): @@ -851,7 +856,7 @@ def desc_stylize(value): value = re.sub(r'\[(lang|language)\ \=\>\ *([a-zA-Z\-\/\#\+]*)\]', '
\\2
', value) value = re.sub(r'\[([a-z]+)\]', - '
\\1
', value) + '
\\1
', value) return value @@ -876,7 +881,7 @@ def escaped_stylize(value): value = re.sub(r'\[(lang|language)\ \=\>\ *([a-zA-Z\-\/\#\+]*)\]', '
\\2
', value) value = re.sub(r'\[([a-z]+)\]', - '
\\1
', value) + '
\\1
', value) return value @@ -1647,10 +1652,10 @@ def process_patterns(text_string, repo_n if repo_name: # Retrieving repo_name to avoid invalid repo_name to explode on # IssueTrackerSettingsModel but still passing invalid name further down - repo = Repository.get_by_repo_name(repo_name) + repo = Repository.get_by_repo_name(repo_name, cache=True) settings_model = IssueTrackerSettingsModel(repo=repo) - active_entries = settings_model.get_settings() + active_entries = settings_model.get_settings(cache=True) newtext = text_string for uid, entry in active_entries.items(): diff --git a/rhodecode/lib/middleware/disable_vcs.py b/rhodecode/lib/middleware/disable_vcs.py --- a/rhodecode/lib/middleware/disable_vcs.py +++ b/rhodecode/lib/middleware/disable_vcs.py @@ -24,15 +24,21 @@ Disable VCS pages when VCS Server is not import logging import re - +from pyramid.httpexceptions import HTTPBadGateway log = logging.getLogger(__name__) +class VCSServerUnavailable(HTTPBadGateway): + """ HTTP Exception class for when VCS Server is unavailable """ + code = 502 + title = 'VCS Server Required' + explanation = 'A VCS Server is required for this action. There is currently no VCS Server configured.' + class DisableVCSPagesWrapper(object): """ - Wrapper to disable all pages that require VCS Server to be running, - avoiding that errors explode to the user. + Pyramid view wrapper to disable all pages that require VCS Server to be + running, avoiding that errors explode to the user. This Wrapper should be enabled only in case VCS Server is not available for the instance. @@ -60,11 +66,11 @@ class DisableVCSPagesWrapper(object): log.debug('accessing: `%s` with VCS Server disabled', path_info) return False - def __init__(self, app): - self.application = app + def __init__(self, handler): + self.handler = handler - def __call__(self, environ, start_response): - if not self._check_vcs_requirement(environ['PATH_INFO']): - environ['PATH_INFO'] = '/error/vcs_unavailable' + def __call__(self, context, request): + if not self._check_vcs_requirement(request.path): + raise VCSServerUnavailable('VCS Server is not available') - return self.application(environ, start_response) + return self.handler(context, request) diff --git a/rhodecode/lib/profiler.py b/rhodecode/lib/profiler.py deleted file mode 100644 --- a/rhodecode/lib/profiler.py +++ /dev/null @@ -1,79 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (C) 2010-2016 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 gc -import objgraph -import cProfile -import pstats -import cgi -import pprint -import threading - -from StringIO import StringIO - - -class ProfilingMiddleware(object): - def __init__(self, app): - self.lock = threading.Lock() - self.app = app - - def __call__(self, environ, start_response): - with self.lock: - profiler = cProfile.Profile() - - def run_app(*a, **kw): - self.response = self.app(environ, start_response) - - profiler.runcall(run_app, environ, start_response) - - profiler.snapshot_stats() - - stats = pstats.Stats(profiler) - stats.sort_stats('calls') #cummulative - - # Redirect output - out = StringIO() - stats.stream = out - - stats.print_stats() - - resp = ''.join(self.response) - - # Lets at least only put this on html-like responses. - if resp.strip().startswith('<'): - ## The profiling info is just appended to the response. - ## Browsers don't mind this. - resp += ('
')
-                resp += cgi.escape(out.getvalue(), True)
-
-                ct = objgraph.show_most_common_types()
-                print ct
-
-                resp += ct if ct else '---'
-
-                output = StringIO()
-                pprint.pprint(environ, output, depth=3)
-
-                resp += cgi.escape(output.getvalue(), True)
-                resp += '
' - - return resp diff --git a/rhodecode/lib/utils.py b/rhodecode/lib/utils.py --- a/rhodecode/lib/utils.py +++ b/rhodecode/lib/utils.py @@ -33,14 +33,14 @@ import tempfile import traceback import tarfile import warnings -from os.path import abspath -from os.path import dirname as dn, join as jn +from os.path import join as jn import paste import pkg_resources from paste.script.command import Command, BadCommand from webhelpers.text import collapse, remove_formatting, strip_tags from mako import exceptions +from pyramid.threadlocal import get_current_registry from rhodecode.lib.fakemod import create_module from rhodecode.lib.vcs.backends.base import Config @@ -52,8 +52,7 @@ from rhodecode.model import meta from rhodecode.model.db import ( Repository, User, RhodeCodeUi, UserLog, RepoGroup, UserGroup) from rhodecode.model.meta import Session -from rhodecode.model.repo_group import RepoGroupModel -from rhodecode.model.settings import VcsSettingsModel, SettingsModel + log = logging.getLogger(__name__) @@ -384,6 +383,8 @@ def config_data_from_db(clear_session=Tr Read the configuration data from the database and return configuration tuples. """ + from rhodecode.model.settings import VcsSettingsModel + config = [] sa = meta.Session() @@ -467,6 +468,7 @@ def set_rhodecode_config(config): :param config: """ + from rhodecode.model.settings import SettingsModel app_settings = SettingsModel().get_all_settings() for k, v in app_settings.items(): @@ -481,6 +483,7 @@ def map_groups(path): :param paths: full path to repository """ + from rhodecode.model.repo_group import RepoGroupModel sa = meta.Session() groups = path.split(Repository.NAME_SEP) parent = None @@ -489,7 +492,7 @@ def map_groups(path): # last element is repo in nested groups structure groups = groups[:-1] rgm = RepoGroupModel(sa) - owner = User.get_first_admin() + owner = User.get_first_super_admin() for lvl, group_name in enumerate(groups): group_name = '/'.join(groups[:lvl] + [group_name]) group = RepoGroup.get_by_group_name(group_name) @@ -525,9 +528,12 @@ def repo2db_mapper(initial_repo_list, re """ from rhodecode.model.repo import RepoModel from rhodecode.model.scm import ScmModel + from rhodecode.model.repo_group import RepoGroupModel + from rhodecode.model.settings import SettingsModel + sa = meta.Session() repo_model = RepoModel() - user = User.get_first_admin() + user = User.get_first_super_admin() added = [] # creation defaults @@ -701,58 +707,56 @@ def get_custom_lexer(extension): #============================================================================== # TEST FUNCTIONS AND CREATORS #============================================================================== -def create_test_index(repo_location, config, full_index): +def create_test_index(repo_location, config): """ - Makes default test index - - :param config: test config - :param full_index: - # start test server: - rcserver --with-vcsserver test.ini + Makes default test index. + """ + import rc_testdata - # build index and store it in /tmp/rc/index: - rhodecode-index --force --api-host=http://vps1.dev:5000 --api-key=xxx --engine-location=/tmp/rc/index - - # package and move new packages - tar -zcvf vcs_search_index.tar.gz -C /tmp/rc index - mv vcs_search_index.tar.gz rhodecode/tests/fixtures/ - - """ - cur_dir = dn(dn(abspath(__file__))) - with tarfile.open(jn(cur_dir, 'tests', 'fixtures', - 'vcs_search_index.tar.gz')) as tar: - tar.extractall(os.path.dirname(config['search.location'])) + rc_testdata.extract_search_index( + 'vcs_search_index', os.path.dirname(config['search.location'])) -def create_test_env(repos_test_path, config): +def create_test_directory(test_path): + """ + Create test directory if it doesn't exist. """ - Makes a fresh database and - installs test repository into tmp dir + if not os.path.isdir(test_path): + log.debug('Creating testdir %s', test_path) + os.makedirs(test_path) + + +def create_test_database(test_path, config): + """ + Makes a fresh database. """ from rhodecode.lib.db_manage import DbManage - from rhodecode.tests import HG_REPO, GIT_REPO, SVN_REPO, TESTS_TMP_PATH # PART ONE create db dbconf = config['sqlalchemy.db1.url'] log.debug('making test db %s', dbconf) - # create test dir if it doesn't exist - if not os.path.isdir(repos_test_path): - log.debug('Creating testdir %s', repos_test_path) - os.makedirs(repos_test_path) - dbmanage = DbManage(log_sql=False, dbconf=dbconf, root=config['here'], tests=True, cli_args={'force_ask': True}) dbmanage.create_tables(override=True) dbmanage.set_db_version() # for tests dynamically set new root paths based on generated content - dbmanage.create_settings(dbmanage.config_prompt(repos_test_path)) + dbmanage.create_settings(dbmanage.config_prompt(test_path)) dbmanage.create_default_user() dbmanage.create_test_admin_and_users() dbmanage.create_permissions() dbmanage.populate_default_permissions() Session().commit() - # PART TWO make test repo + + +def create_test_repositories(test_path, config): + """ + Creates test repositories in the temporary directory. Repositories are + extracted from archives within the rc_testdata package. + """ + import rc_testdata + from rhodecode.tests import HG_REPO, GIT_REPO, SVN_REPO + log.debug('making test vcs repositories') idx_path = config['search.location'] @@ -767,24 +771,15 @@ def create_test_env(repos_test_path, con log.debug('remove %s', data_path) shutil.rmtree(data_path) - # CREATE DEFAULT TEST REPOS - cur_dir = dn(dn(abspath(__file__))) - with tarfile.open(jn(cur_dir, 'tests', 'fixtures', - 'vcs_test_hg.tar.gz')) as tar: - tar.extractall(jn(TESTS_TMP_PATH, HG_REPO)) - - cur_dir = dn(dn(abspath(__file__))) - with tarfile.open(jn(cur_dir, 'tests', 'fixtures', - 'vcs_test_git.tar.gz')) as tar: - tar.extractall(jn(TESTS_TMP_PATH, GIT_REPO)) + rc_testdata.extract_hg_dump('vcs_test_hg', jn(test_path, HG_REPO)) + rc_testdata.extract_git_dump('vcs_test_git', jn(test_path, GIT_REPO)) # Note: Subversion is in the process of being integrated with the system, # until we have a properly packed version of the test svn repository, this # tries to copy over the repo from a package "rc_testdata" - import rc_testdata svn_repo_path = rc_testdata.get_svn_repo_archive() with tarfile.open(svn_repo_path) as tar: - tar.extractall(jn(TESTS_TMP_PATH, SVN_REPO)) + tar.extractall(jn(test_path, SVN_REPO)) #============================================================================== @@ -976,7 +971,20 @@ def read_opensource_licenses(): if not _license_cache: licenses = pkg_resources.resource_string( - 'rhodecode.config', 'licenses.json') + 'rhodecode', 'config/licenses.json') _license_cache = json.loads(licenses) return _license_cache + + +def get_registry(request): + """ + Utility to get the pyramid registry from a request. During migration to + pyramid we sometimes want to use the pyramid registry from pylons context. + Therefore this utility returns `request.registry` for pyramid requests and + uses `get_current_registry()` for pylons requests. + """ + try: + return request.registry + except AttributeError: + return get_current_registry() diff --git a/rhodecode/lib/utils2.py b/rhodecode/lib/utils2.py --- a/rhodecode/lib/utils2.py +++ b/rhodecode/lib/utils2.py @@ -321,7 +321,8 @@ def engine_from_config(configuration, pr setattr(conn, 'query_start_time', time.time()) log.info(color_sql(">>>>> STARTING QUERY >>>>>")) calling_context = find_calling_context(ignore_modules=[ - 'rhodecode.lib.caching_query' + 'rhodecode.lib.caching_query', + 'rhodecode.model.settings', ]) if calling_context: log.info(color_sql('call context %s:%s' % ( @@ -341,6 +342,12 @@ def engine_from_config(configuration, pr return engine +def get_encryption_key(config): + secret = config.get('rhodecode.encrypted_values.secret') + default = config['beaker.session.secret'] + return secret or default + + def age(prevdate, now=None, show_short_version=False, show_suffix=True, short_format=False): """ diff --git a/rhodecode/lib/vcs/__init__.py b/rhodecode/lib/vcs/__init__.py --- a/rhodecode/lib/vcs/__init__.py +++ b/rhodecode/lib/vcs/__init__.py @@ -93,11 +93,14 @@ def connect_http(server_and_port): from rhodecode.lib.vcs import connection, client_http from rhodecode.lib.middleware.utils import scm_app - session = _create_http_rpc_session() + session_factory = client_http.ThreadlocalSessionFactory() - connection.Git = client_http.RepoMaker(server_and_port, '/git', session) - connection.Hg = client_http.RepoMaker(server_and_port, '/hg', session) - connection.Svn = client_http.RepoMaker(server_and_port, '/svn', session) + connection.Git = client_http.RepoMaker( + server_and_port, '/git', session_factory) + connection.Hg = client_http.RepoMaker( + server_and_port, '/hg', session_factory) + connection.Svn = client_http.RepoMaker( + server_and_port, '/svn', session_factory) scm_app.HG_REMOTE_WSGI = client_http.VcsHttpProxy( server_and_port, '/proxy/hg') diff --git a/rhodecode/lib/vcs/client_http.py b/rhodecode/lib/vcs/client_http.py --- a/rhodecode/lib/vcs/client_http.py +++ b/rhodecode/lib/vcs/client_http.py @@ -31,6 +31,7 @@ implementation. import copy import logging +import threading import urllib2 import urlparse import uuid @@ -38,7 +39,7 @@ import uuid import msgpack import requests -from . import exceptions +from . import exceptions, CurlSession log = logging.getLogger(__name__) @@ -54,15 +55,16 @@ EXCEPTIONS_MAP = { class RepoMaker(object): - def __init__(self, server_and_port, backend_endpoint, session): + def __init__(self, server_and_port, backend_endpoint, session_factory): self.url = urlparse.urljoin( 'http://%s' % server_and_port, backend_endpoint) - self._session = session + self._session_factory = session_factory def __call__(self, path, config, with_wire=None): log.debug('RepoMaker call on %s', path) return RemoteRepo( - path, config, self.url, self._session, with_wire=with_wire) + path, config, self.url, self._session_factory(), + with_wire=with_wire) def __getattr__(self, name): def f(*args, **kwargs): @@ -76,7 +78,8 @@ class RepoMaker(object): 'method': name, 'params': {'args': args, 'kwargs': kwargs} } - return _remote_call(self.url, payload, EXCEPTIONS_MAP, self._session) + return _remote_call( + self.url, payload, EXCEPTIONS_MAP, self._session_factory()) class RemoteRepo(object): @@ -216,3 +219,17 @@ class VcsHttpProxy(object): headers = iterator.next() return iterator, status, headers + + +class ThreadlocalSessionFactory(object): + """ + Creates one CurlSession per thread on demand. + """ + + def __init__(self): + self._thread_local = threading.local() + + def __call__(self): + if not hasattr(self._thread_local, 'curl_session'): + self._thread_local.curl_session = CurlSession() + return self._thread_local.curl_session diff --git a/rhodecode/model/__init__.py b/rhodecode/model/__init__.py --- a/rhodecode/model/__init__.py +++ b/rhodecode/model/__init__.py @@ -43,9 +43,10 @@ The application's model objects import logging from pylons import config +from pyramid.threadlocal import get_current_registry from rhodecode.model import meta, db -from rhodecode.lib.utils2 import obfuscate_url_pw +from rhodecode.lib.utils2 import obfuscate_url_pw, get_encryption_key log = logging.getLogger(__name__) @@ -65,8 +66,8 @@ def init_model(engine, encryption_key=No def init_model_encryption(migration_models): - migration_models.ENCRYPTION_KEY = config['beaker.session.secret'] - db.ENCRYPTION_KEY = config['beaker.session.secret'] + migration_models.ENCRYPTION_KEY = get_encryption_key(config) + db.ENCRYPTION_KEY = get_encryption_key(config) class BaseModel(object): @@ -144,6 +145,17 @@ class BaseModel(object): return self._get_instance( db.Permission, permission, callback=db.Permission.get_by_key) + def send_event(self, event): + """ + Helper method to send an event. This wraps the pyramid logic to send an + event. + """ + # For the first step we are using pyramids thread locals here. If the + # event mechanism works out as a good solution we should think about + # passing the registry into the constructor to get rid of it. + registry = get_current_registry() + registry.notify(event) + @classmethod def get_all(cls): """ diff --git a/rhodecode/model/db.py b/rhodecode/model/db.py --- a/rhodecode/model/db.py +++ b/rhodecode/model/db.py @@ -70,7 +70,8 @@ log = logging.getLogger(__name__) # BASE CLASSES # ============================================================================= -# this is propagated from .ini file beaker.session.secret +# this is propagated from .ini file rhodecode.encrypted_values.secret or +# beaker.session.secret if first is not set. # and initialized at environment.py ENCRYPTION_KEY = None @@ -115,14 +116,17 @@ class EncryptedTextValue(TypeDecorator): def process_bind_param(self, value, dialect): if not value: return value - if value.startswith('enc$aes$'): + 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$%s' % AESCipher(ENCRYPTION_KEY).encrypt(value) + 'not starting with enc$aes') + return 'enc$aes_hmac$%s' % AESCipher( + ENCRYPTION_KEY, hmac=True).encrypt(value) def process_result_value(self, value, dialect): + import rhodecode + if not value: return value @@ -134,9 +138,19 @@ class EncryptedTextValue(TypeDecorator): 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 - decrypted_data = AESCipher(ENCRYPTION_KEY).decrypt(parts[2]) + 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 @@ -220,6 +234,20 @@ class BaseModel(object): obj = cls.query().get(id_) Session().delete(obj) + @classmethod + def identity_cache(cls, session, attr_name, value): + exist_in_session = [] + for (item_cls, pkey), instance in session.identity_map.items(): + if cls == item_cls and getattr(instance, attr_name) == value: + exist_in_session.append(instance) + if exist_in_session: + if len(exist_in_session) == 1: + return exist_in_session[0] + log.exception( + 'multiple objects with attr %s and ' + 'value %s found with same name: %r', + attr_name, value, exist_in_session) + def __repr__(self): if hasattr(self, '__unicode__'): # python repr needs to return str @@ -639,16 +667,26 @@ class User(Base, BaseModel): log.error(traceback.format_exc()) @classmethod - def get_by_username(cls, username, case_insensitive=False, cache=False): + def get_by_username(cls, username, case_insensitive=False, + cache=False, identity_cache=False): + session = Session() + if case_insensitive: - q = cls.query().filter(func.lower(cls.username) == func.lower(username)) + q = cls.query().filter( + func.lower(cls.username) == func.lower(username)) else: q = cls.query().filter(cls.username == username) if cache: - q = q.options(FromCache( - "sql_cache_short", - "get_user_%s" % _hash_key(username))) + if identity_cache: + val = cls.identity_cache(session, 'username', username) + if val: + return val + else: + q = q.options( + FromCache("sql_cache_short", + "get_user_by_name_%s" % _hash_key(username))) + return q.scalar() @classmethod @@ -752,10 +790,10 @@ class User(Base, BaseModel): Session().add(self) @classmethod - def get_first_admin(cls): - user = User.query().filter(User.admin == True).first() + def get_first_super_admin(cls): + user = User.query().filter(User.admin == true()).first() if user is None: - raise Exception('Missing administrative account!') + raise Exception('FATAL: Missing administrative account!') return user @classmethod @@ -770,7 +808,7 @@ class User(Base, BaseModel): def get_default_user(cls, cache=False): user = User.get_by_username(User.DEFAULT_USER, cache=cache) if user is None: - raise Exception('Missing default account!') + raise Exception('FATAL: Missing default account!') return user def _get_default_perms(self, user, suffix=''): @@ -1264,9 +1302,9 @@ class Repository(Base, BaseModel): "group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None) - user = relationship('User') - fork = relationship('Repository', remote_side=repo_id) - group = relationship('RepoGroup') + user = relationship('User', lazy='joined') + fork = relationship('Repository', remote_side=repo_id, lazy='joined') + group = relationship('RepoGroup', lazy='joined') repo_to_perm = relationship( 'UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id') @@ -1364,7 +1402,7 @@ class Repository(Base, BaseModel): def normalize_repo_name(cls, repo_name): """ Normalizes os specific repo_name to the format internally stored inside - dabatabase using URL_SEP + database using URL_SEP :param cls: :param repo_name: @@ -1372,11 +1410,20 @@ class Repository(Base, BaseModel): return cls.NAME_SEP.join(repo_name.split(os.sep)) @classmethod - def get_by_repo_name(cls, repo_name): - q = Session().query(cls).filter(cls.repo_name == repo_name) - q = q.options(joinedload(Repository.fork))\ - .options(joinedload(Repository.user))\ - .options(joinedload(Repository.group)) + def get_by_repo_name(cls, repo_name, cache=False, identity_cache=False): + session = Session() + q = session.query(cls).filter(cls.repo_name == repo_name) + + if cache: + if identity_cache: + val = cls.identity_cache(session, 'repo_name', repo_name) + if val: + return val + else: + q = q.options( + FromCache("sql_cache_short", + "get_repo_by_name_%s" % _hash_key(repo_name))) + return q.scalar() @classmethod @@ -1721,7 +1768,7 @@ class Repository(Base, BaseModel): clone_uri = self.clone_uri if clone_uri: import urlobject - url_obj = urlobject.URLObject(self.clone_uri) + url_obj = urlobject.URLObject(clone_uri) if url_obj.password: clone_uri = url_obj.with_password('*****') return clone_uri diff --git a/rhodecode/model/forms.py b/rhodecode/model/forms.py --- a/rhodecode/model/forms.py +++ b/rhodecode/model/forms.py @@ -138,7 +138,11 @@ def UserForm(edit=False, available_langu return _UserForm -def UserGroupForm(edit=False, old_data={}, available_members=[]): +def UserGroupForm(edit=False, old_data=None, available_members=None, + allow_disabled=False): + old_data = old_data or {} + available_members = available_members or [] + class _UserGroupForm(formencode.Schema): allow_extra_fields = True filter_extra_fields = True @@ -157,14 +161,18 @@ def UserGroupForm(edit=False, old_data={ available_members, hideList=False, testValueList=True, if_missing=None, not_empty=False ) - #this is user group owner - user = All(v.UnicodeString(not_empty=True), v.ValidRepoUser()) - + # this is user group owner + user = All( + v.UnicodeString(not_empty=True), + v.ValidRepoUser(allow_disabled)) return _UserGroupForm -def RepoGroupForm(edit=False, old_data={}, available_groups=[], - can_create_in_root=False): +def RepoGroupForm(edit=False, old_data=None, available_groups=None, + can_create_in_root=False, allow_disabled=False): + old_data = old_data or {} + available_groups = available_groups or [] + class _RepoGroupForm(formencode.Schema): allow_extra_fields = True filter_extra_fields = False @@ -178,11 +186,14 @@ def RepoGroupForm(edit=False, old_data={ group_parent_id = v.OneOf(available_groups, hideList=False, testValueList=True, not_empty=True) enable_locking = v.StringBoolean(if_missing=False) - chained_validators = [v.ValidRepoGroup(edit, old_data, can_create_in_root)] + chained_validators = [ + v.ValidRepoGroup(edit, old_data, can_create_in_root)] if edit: - #this is repo group owner - user = All(v.UnicodeString(not_empty=True), v.ValidRepoUser()) + # this is repo group owner + user = All( + v.UnicodeString(not_empty=True), + v.ValidRepoUser(allow_disabled)) return _RepoGroupForm @@ -221,7 +232,8 @@ def PasswordResetForm(): return _PasswordResetForm -def RepoForm(edit=False, old_data=None, repo_groups=None, landing_revs=None): +def RepoForm(edit=False, old_data=None, repo_groups=None, landing_revs=None, + allow_disabled=False): old_data = old_data or {} repo_groups = repo_groups or [] landing_revs = landing_revs or [] @@ -248,7 +260,9 @@ def RepoForm(edit=False, old_data=None, if edit: # this is repo owner - user = All(v.UnicodeString(not_empty=True), v.ValidRepoUser()) + user = All( + v.UnicodeString(not_empty=True), + v.ValidRepoUser(allow_disabled)) clone_uri_change = v.UnicodeString( not_empty=False, if_missing=v.Missing) diff --git a/rhodecode/model/repo.py b/rhodecode/model/repo.py --- a/rhodecode/model/repo.py +++ b/rhodecode/model/repo.py @@ -140,10 +140,12 @@ class RepoModel(BaseModel): return None - def get_users(self, name_contains=None, limit=20): + def get_users(self, name_contains=None, limit=20, only_active=True): # TODO: mikhail: move this method to the UserModel. query = self.sa.query(User) - query = query.filter(User.active == true()) + if only_active: + query = query.filter(User.active == true()) + if name_contains: ilike_expression = u'%{}%'.format(safe_unicode(name_contains)) query = query.filter( @@ -165,16 +167,19 @@ class RepoModel(BaseModel): 'icon_link': h.gravatar_url(user.email, 14), 'value_display': h.person(user.email), 'value': user.username, - 'value_type': 'user' + 'value_type': 'user', + 'active': user.active, } for user in users ] return _users - def get_user_groups(self, name_contains=None, limit=20): + def get_user_groups(self, name_contains=None, limit=20, only_active=True): # TODO: mikhail: move this method to the UserGroupModel. query = self.sa.query(UserGroup) - query = query.filter(UserGroup.users_group_active == true()) + if only_active: + query = query.filter(UserGroup.users_group_active == true()) + if name_contains: ilike_expression = u'%{}%'.format(safe_unicode(name_contains)) query = query.filter( @@ -196,7 +201,8 @@ class RepoModel(BaseModel): 'value_display': 'Group: %s (%d members)' % ( group.users_group_name, len(group.members),), 'value': group.users_group_name, - 'value_type': 'user_group' + 'value_type': 'user_group', + 'active': group.users_group_active, } for group in user_groups ] @@ -333,7 +339,7 @@ class RepoModel(BaseModel): if repo_info.user: defaults.update({'user': repo_info.user.username}) else: - replacement_user = User.get_first_admin().username + replacement_user = User.get_first_super_admin().username defaults.update({'user': replacement_user}) # fill repository users diff --git a/rhodecode/model/settings.py b/rhodecode/model/settings.py --- a/rhodecode/model/settings.py +++ b/rhodecode/model/settings.py @@ -23,6 +23,7 @@ import logging from collections import namedtuple from functools import wraps +from rhodecode.lib import caches from rhodecode.lib.caching_query import FromCache from rhodecode.lib.utils2 import ( Optional, AttributeDict, safe_str, remove_prefix, str2bool) @@ -200,23 +201,37 @@ class SettingsModel(BaseModel): Session.add(res) return res + def invalidate_settings_cache(self): + namespace = 'rhodecode_settings' + cache_manager = caches.get_cache_manager('sql_cache_short', namespace) + caches.clear_cache_manager(cache_manager) + def get_all_settings(self, cache=False): - q = self._get_settings_query() - if cache: - repo = self._get_repo(self.repo) if self.repo else None - cache_key = ( - "get_repo_{}_settings".format(repo.repo_id) - if repo else "get_hg_settings") - q = q.options(FromCache("sql_cache_short", cache_key)) + def _compute(): + q = self._get_settings_query() + if not q: + raise Exception('Could not get application settings !') - if not q: - raise Exception('Could not get application settings !') + settings = { + 'rhodecode_' + result.app_settings_name: result.app_settings_value + for result in q + } + return settings - settings = { - 'rhodecode_' + result.app_settings_name: result.app_settings_value - for result in q - } - return settings + if cache: + log.debug('Fetching app settings using cache') + repo = self._get_repo(self.repo) if self.repo else None + namespace = 'rhodecode_settings' + cache_manager = caches.get_cache_manager( + 'sql_cache_short', namespace) + _cache_key = ( + "get_repo_{}_settings".format(repo.repo_id) + if repo else "get_app_settings") + + return cache_manager.get(_cache_key, createfunc=_compute) + + else: + return _compute() def get_auth_settings(self): q = self._get_settings_query() diff --git a/rhodecode/model/user.py b/rhodecode/model/user.py --- a/rhodecode/model/user.py +++ b/rhodecode/model/user.py @@ -26,13 +26,13 @@ import logging import traceback import datetime -from pylons import url from pylons.i18n.translation import _ import ipaddress from sqlalchemy.exc import DatabaseError from sqlalchemy.sql.expression import true, false +from rhodecode.events import UserPreCreate, UserPreUpdate from rhodecode.lib.utils2 import ( safe_unicode, get_current_rhodecode_user, action_logger_generic, AttributeDict) @@ -270,10 +270,12 @@ class UserModel(BaseModel): # raises UserCreationError if it's not allowed for any reason to # create new active user, this also executes pre-create hooks check_allowed_create_user(user_data, cur_user, strict_check=True) + self.send_event(UserPreCreate(user_data)) new_user = User() edit = False else: log.debug('updating user %s', username) + self.send_event(UserPreUpdate(user, user_data)) new_user = user edit = True @@ -375,7 +377,7 @@ class UserModel(BaseModel): raise def _handle_user_repos(self, username, repositories, handle_mode=None): - _superadmin = self.cls.get_first_admin() + _superadmin = self.cls.get_first_super_admin() left_overs = True from rhodecode.model.repo import RepoModel @@ -398,7 +400,7 @@ class UserModel(BaseModel): def _handle_user_repo_groups(self, username, repository_groups, handle_mode=None): - _superadmin = self.cls.get_first_admin() + _superadmin = self.cls.get_first_super_admin() left_overs = True from rhodecode.model.repo_group import RepoGroupModel @@ -420,7 +422,7 @@ class UserModel(BaseModel): return left_overs def _handle_user_user_groups(self, username, user_groups, handle_mode=None): - _superadmin = self.cls.get_first_admin() + _superadmin = self.cls.get_first_super_admin() left_overs = True from rhodecode.model.user_group import UserGroupModel diff --git a/rhodecode/model/user_group.py b/rhodecode/model/user_group.py --- a/rhodecode/model/user_group.py +++ b/rhodecode/model/user_group.py @@ -498,7 +498,7 @@ class UserGroupModel(BaseModel): self.remove_user_from_group(gr, user) # now we calculate in which groups user should be == groups params - owner = User.get_first_admin().username + owner = User.get_first_super_admin().username for gr in set(groups): existing_group = UserGroup.get_by_group_name(gr) if not existing_group: diff --git a/rhodecode/model/validators.py b/rhodecode/model/validators.py --- a/rhodecode/model/validators.py +++ b/rhodecode/model/validators.py @@ -193,21 +193,26 @@ def ValidRegex(msg=None): return _validator -def ValidRepoUser(): +def ValidRepoUser(allow_disabled=False): class _validator(formencode.validators.FancyValidator): messages = { - 'invalid_username': _(u'Username %(username)s is not valid') + 'invalid_username': _(u'Username %(username)s is not valid'), + 'disabled_username': _(u'Username %(username)s is disabled') } def validate_python(self, value, state): try: - User.query().filter(User.active == true())\ - .filter(User.username == value).one() + user = User.query().filter(User.username == value).one() except Exception: msg = M(self, 'invalid_username', state, username=value) raise formencode.Invalid( msg, value, state, error_dict={'username': msg} ) + if user and (not allow_disabled and not user.active): + msg = M(self, 'disabled_username', state, username=value) + raise formencode.Invalid( + msg, value, state, error_dict={'username': msg} + ) return _validator 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 @@ -269,6 +269,33 @@ form.rcform { } +.badged-field { + .user-badge { + line-height: 25px; + padding: 10px 5px; + border-radius: @border-radius; + border-top: 1px solid @rclightblue; + border-left: 1px solid @rclightblue; + border-bottom: 1px solid @rclightblue; + font-size: 14px; + font-style: normal; + color: @text-light; + display: inline-block; + vertical-align: top; + cursor: default; + margin-right: -2px; + } + .badge-input-container { + display: flex; + position: relative; + } + .user-disabled { + text-decoration: line-through; + } + .badge-input-wrap { + display: inline-block; + } +} // for situations where we wish to display the form value but not the form input input.input-valuedisplay { 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 @@ -296,30 +296,30 @@ ul.auth_plugins { } } -// Pull Requests + +// My Account PR list + +#show_closed { + margin: 0 1em 0 0; +} .pullrequestlist { - max-width: @pullrequest-width; - margin-bottom: @space; - - // Tweaks for "My Account" / "Pull requests" - .prwrapper { - clear: left; + .closed { + background-color: @grey6; + } + .td-status { + padding-left: .5em; + } + .truncate { + height: 2.75em; + white-space: pre-line; + } + table.rctable .user { + padding-left: 0; + } +} - .pr { - margin: 0; - padding: 0; - border-bottom: none; - } - - // TODO: johbo: Replace with something that makes up an inline form or - // similar. - .repolist_actions { - display: inline-block; - } - } - -} +// Pull Requests .pullrequests_section_head { display: block; @@ -1086,6 +1086,7 @@ table.issuetracker { } } + //Permissions Settings #add_perm { margin: 0 0 @padding; 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 @@ -28,7 +28,7 @@ margin: 0 7px 0 .7em; font-size: @basefontsize; color: white; - + &.empty { background-color: @grey4; } @@ -94,7 +94,7 @@ &:focus { outline: none; } - + ul li { display: block; @@ -145,7 +145,7 @@ &:hover, &.open, &.active { - a { + a { color: @grey1; } } @@ -288,6 +288,11 @@ } } +.navigation li:last-child .submenu { + right: -20px; + left: auto; +} + .submenu { position: absolute; top: 100%; @@ -333,7 +338,7 @@ -moz-transition: background .3s; -o-transition: background .3s; transition: background .3s; - + ul { display: block; } @@ -480,7 +485,7 @@ &.select2-result-unselectable > .select2-result-label { margin: 0 8px; } - + } } @@ -594,7 +599,7 @@ ul#context-pages { padding: 0; border: none; } - + .nav-pills { margin: 0; } 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 @@ -6,7 +6,6 @@ width: 100%; margin: 0 0 25px 0; - border-color: @grey5; .border-radius(@border-radius); .box-shadow(none); @@ -23,7 +22,6 @@ position: relative; min-height: 1em; padding: @padding @panel-padding; - background-color: @grey6; border-bottom: none; .panel-title, diff --git a/rhodecode/public/js/src/rhodecode/utils/autocomplete.js b/rhodecode/public/js/src/rhodecode/utils/autocomplete.js --- a/rhodecode/public/js/src/rhodecode/utils/autocomplete.js +++ b/rhodecode/public/js/src/rhodecode/utils/autocomplete.js @@ -19,19 +19,25 @@ /** * autocomplete formatter that uses gravatar * */ -var autocompleteFormatResult = function(data, value, org_formatter) { - var value_display = data.value_display; +var autocompleteFormatResult = function (data, value, org_formatter) { + var activeUser = data.active || true; + var valueDisplay = data.value_display; + + if (!activeUser) { + valueDisplay = '(disabled) ' + valueDisplay; + } + var escapeRegExChars = function (value) { return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); }; var pattern = '(' + escapeRegExChars(value) + ')'; - value_display = value_display.replace(new RegExp(pattern, 'gi'), '$1<\/strong>'); + valueDisplay = valueDisplay.replace(new RegExp(pattern, 'gi'), '$1<\/strong>'); var tmpl = '
{1}
'; if (data.icon_link === "") { tmpl = '
{0}
'; - return tmpl.format(value_display); + return tmpl.format(valueDisplay); } - return tmpl.format(data.icon_link, value_display); + return tmpl.format(data.icon_link, valueDisplay); }; /** diff --git a/rhodecode/templates/admin/my_account/my_account_pullrequests.html b/rhodecode/templates/admin/my_account/my_account_pullrequests.html --- a/rhodecode/templates/admin/my_account/my_account_pullrequests.html +++ b/rhodecode/templates/admin/my_account/my_account_pullrequests.html @@ -1,13 +1,12 @@ +<%namespace name="base" file="/base/base.html"/>
-
%if c.show_closed: ${h.checkbox('show_closed',checked="checked", label=_('Show Closed Pull Requests'))} %else: ${h.checkbox('show_closed',label=_('Show Closed Pull Requests'))} %endif -
@@ -15,29 +14,57 @@

${_('Pull Requests You Opened')}

-
%if c.my_pull_requests: + + + + + + + + + + %for pull_request in c.my_pull_requests: -
-
+
+ + + + + + + + + %endfor +
${_('Target Repo')}${_('Author')}${_('Title')}${_('Opened On')}
- - ${_('Pull request #%s opened on %s') % (pull_request.pull_request_id, h.format_date(pull_request.created_on))} - %if pull_request.is_closed(): - (${_('Closed')}) - %endif - -
- ${h.secure_form(url('pullrequest_delete', repo_name=pull_request.target_repo.repo_name, pull_request_id=pull_request.pull_request_id),method='delete')} - ${h.submit('remove_%s' % pull_request.pull_request_id, _('Delete'), - class_="btn btn-link btn-danger",onclick="return confirm('"+_('Confirm to delete this pull request')+"');")} - ${h.end_form()} +
+ ${h.link_to(pull_request.target_repo.repo_name,h.url('summary_home',repo_name=pull_request.target_repo.repo_name))} + + ${base.gravatar_with_user(pull_request.author.email, 16)} + +
+  
- - +
+
+
#${pull_request.pull_request_id}: ${pull_request.title}\ + %if pull_request.is_closed(): +  (${_('Closed')})\ + %endif +
${pull_request.description}
+
+
+ ${h.age_component(pull_request.created_on)} + + ${h.secure_form(url('pullrequest_delete', repo_name=pull_request.target_repo.repo_name, pull_request_id=pull_request.pull_request_id),method='delete')} + ${h.submit('remove_%s' % pull_request.pull_request_id, _('Delete'), + class_="btn btn-link btn-danger",onclick="return confirm('"+_('Confirm to delete this pull request')+"');")} + ${h.end_form()} +
%else:

${_('You currently have no open pull requests.')}

%endif @@ -53,21 +80,49 @@
%if c.participate_in_pull_requests: + + + + + + + + + %for pull_request in c.participate_in_pull_requests: - + + + + + + + + + %endfor +
${_('Target Repo')}${_('Author')}${_('Title')}${_('Opened On')}
+
+
+ ${h.link_to(pull_request.target_repo.repo_name,h.url('summary_home',repo_name=pull_request.target_repo.repo_name))} + + ${base.gravatar_with_user(pull_request.author.email, 16)} + +
+   +
+
+
+
#${pull_request.pull_request_id}: ${pull_request.title}\ + %if pull_request.is_closed(): +  (${_('Closed')})\ + %endif +
${pull_request.description}
+
+
+ ${h.age_component(pull_request.created_on)} +
%else: -
  • ${_('There are currently no open pull requests requiring your participation.')}
  • +

    ${_('There are currently no open pull requests requiring your participation.')}

    %endif
    @@ -81,5 +136,18 @@ else{ window.location = "${h.url('my_account_pullrequests')}"; } - }) + }); + $('.expand_commit').on('click',function(e){ + var target_expand = $(this); + var cid = target_expand.data('prId'); + + if (target_expand.hasClass('open')){ + $('#c-'+cid).css({'height': '2.75em', 'text-overflow': 'ellipsis', 'overflow':'hidden'}); + target_expand.removeClass('open'); + } + else { + $('#c-'+cid).css({'height': 'auto', 'text-overflow': 'initial', 'overflow':'visible'}); + target_expand.addClass('open'); + } + }); diff --git a/rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html b/rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html --- a/rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html +++ b/rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html @@ -1,4 +1,6 @@ ## -*- coding: utf-8 -*- +<%namespace name="base" file="/base/base.html"/> +

    ${_('Settings for Repository Group: %s') % c.repo_group.name}

    @@ -16,15 +18,25 @@ ${h.text('group_name',class_='medium')}
    -
    + +
    - ${h.text('user', class_="medium", autocomplete="off")} - ${_('Change Repository Group Owner.')} +
    +
    + ${base.gravatar_with_user(c.repo_group.user.email, show_disabled=not c.repo_group.user.active)} +
    +
    + ${h.text('user', class_="medium", autocomplete="off")} +
    +
    + +

    ${_('Change owner of this repository group.')}

    +
    diff --git a/rhodecode/templates/admin/repos/repo_edit_settings.html b/rhodecode/templates/admin/repos/repo_edit_settings.html --- a/rhodecode/templates/admin/repos/repo_edit_settings.html +++ b/rhodecode/templates/admin/repos/repo_edit_settings.html @@ -1,3 +1,6 @@ +## -*- coding: utf-8 -*- +<%namespace name="base" file="/base/base.html"/> +

    ${_('Settings for Repository: %s') % c.repo_info.repo_name}

    @@ -69,15 +72,25 @@

    ${_('Default commit for files page, downloads, whoosh and readme')}

    -
    + +
    - ${h.text('user', class_="medium", autocomplete="off")} -

    ${_('Change owner of this repository.')}

    +
    +
    + ${base.gravatar_with_user(c.repo_info.user.email, show_disabled=not c.repo_info.user.active)} +
    +
    + ${h.text('user', class_="medium", autocomplete="off")} +
    +
    + +

    ${_('Change owner of this repository.')}

    -
    +
    +
    diff --git a/rhodecode/templates/admin/settings/settings_open_source.html b/rhodecode/templates/admin/settings/settings_open_source.html --- a/rhodecode/templates/admin/settings/settings_open_source.html +++ b/rhodecode/templates/admin/settings/settings_open_source.html @@ -20,6 +20,7 @@ ${h.literal(', '.join([ '%(name)s' % {'link':link, 'name':name} + if link else name for name,link in licenses.items()]))} diff --git a/rhodecode/templates/admin/settings/settings_system.html b/rhodecode/templates/admin/settings/settings_system.html --- a/rhodecode/templates/admin/settings/settings_system.html +++ b/rhodecode/templates/admin/settings/settings_system.html @@ -45,12 +45,15 @@

    ${_('System Info')}

    + % if c.allowed_to_snapshot: + ${_('create snapshot')} + % endif
    %for dt, dd, tt in elems: -
    ${dt}:
    -
    ${dd}
    +
    ${dt}:
    +
    ${dd}
    %endfor
    @@ -69,7 +72,7 @@ %for key, value in c.py_modules: - ${key} + ${key} ${value} %endfor diff --git a/rhodecode/templates/admin/settings/settings_system_snapshot.html b/rhodecode/templates/admin/settings/settings_system_snapshot.html new file mode 100644 --- /dev/null +++ b/rhodecode/templates/admin/settings/settings_system_snapshot.html @@ -0,0 +1,75 @@ +<% + elems = [ + ## general + (_('RhodeCode Enterprise version'), c.rhodecode_version, ''), + (_('Upgrade info endpoint'), c.rhodecode_update_url, ''), + (_('Configuration INI file'), c.rhodecode_config_ini, ''), + ## systems stats + (_('RhodeCode Enterprise Server IP'), c.server_ip, ''), + (_('RhodeCode Enterprise Server ID'), c.server_id, ''), + (_('Platform'), c.platform, ''), + (_('Uptime'), c.uptime_age, ''), + (_('Storage location'), c.storage, ''), + (_('Storage disk space'), "%s/%s, %s%% used%s" % (h.format_byte_size_binary(c.disk['used']), h.format_byte_size_binary(c.disk['total']),(c.disk['percent']), ' %s' % c.disk['error'] if 'error' in c.disk else ''), ''), + + (_('Search index storage'), c.index_storage, ''), + (_('Search index size'), "%s %s" % (h.format_byte_size_binary(c.disk_index['used']), ' %s' % c.disk_index['error'] if 'error' in c.disk_index else ''), ''), + + (_('Gist storage'), c.gist_storage, ''), + (_('Gist storage size'), "%s (%s items)%s" % (h.format_byte_size_binary(c.disk_gist['used']),c.disk_gist['items'], ' %s' % c.disk_gist['error'] if 'error' in c.disk_gist else ''), ''), + + (_('Archive cache'), c.archive_storage, ''), + (_('Archive cache size'), "%s%s" % (h.format_byte_size_binary(c.disk_archive['used']), ' %s' % c.disk_archive['error'] if 'error' in c.disk_archive else ''), ''), + + (_('System memory'), c.system_memory, ''), + (_('CPU'), '%s %%' %(c.cpu), ''), + (_('Load'), '1min: %s, 5min: %s, 15min: %s' %(c.load['1_min'],c.load['5_min'],c.load['15_min']), ''), + + ## rhodecode stuff + (_('Python version'), c.py_version, ''), + (_('Python path'), c.py_path, ''), + (_('GIT version'), c.git_version, ''), + (_('HG version'), c.hg_version, ''), + (_('SVN version'), c.svn_version, ''), + (_('Database'), "%s @ version: %s" % (c.db_type, c.db_migrate_version), ''), + (_('Database version'), c.db_version, ''), + + ] +%> + +
    +SYSTEM INFO
    +-----------
    +
    +% for dt, dd, tt in elems:
    +${dt}: ${dd}
    +% endfor
    +
    +PYTHON PACKAGES
    +---------------
    +
    +% for key, value in c.py_modules:
    +${key}: ${value}
    +% endfor
    +
    +SYSTEM SETTINGS
    +---------------
    +
    +% for key, value in sorted(c.rhodecode_ini_safe.items()):
    +  % if isinstance(value, dict):
    +
    +    % for key2, value2 in value.items():
    +[${key}]${key2}: ${value2}
    +    % endfor
    +
    +  % else:
    +${key}: ${value}
    +  % endif
    +% endfor
    +
    +
    + + + + + diff --git a/rhodecode/templates/admin/user_groups/user_group_edit_settings.html b/rhodecode/templates/admin/user_groups/user_group_edit_settings.html --- a/rhodecode/templates/admin/user_groups/user_group_edit_settings.html +++ b/rhodecode/templates/admin/user_groups/user_group_edit_settings.html @@ -1,3 +1,6 @@ +## -*- coding: utf-8 -*- +<%namespace name="base" file="/base/base.html"/> +

    ${_('User Group: %s') % c.user_group.users_group_name}

    @@ -15,15 +18,25 @@ ${h.text('users_group_name',class_='medium')}
    -
    + +
    - ${h.text('user', class_="medium", autocomplete="off")} - ${_('Change owner of this user group.')} +
    +
    + ${base.gravatar_with_user(c.user_group.user.email, show_disabled=not c.user_group.user.active)} +
    +
    + ${h.text('user', class_="medium", autocomplete="off")} +
    +
    + +

    ${_('Change owner of this user group.')}

    -
    +
    +
    diff --git a/rhodecode/templates/admin/users/user_add.html b/rhodecode/templates/admin/users/user_add.html --- a/rhodecode/templates/admin/users/user_add.html +++ b/rhodecode/templates/admin/users/user_add.html @@ -128,7 +128,6 @@
    ${h.end_form()}
    - + diff --git a/rhodecode/templates/base/base.html b/rhodecode/templates/base/base.html --- a/rhodecode/templates/base/base.html +++ b/rhodecode/templates/base/base.html @@ -134,10 +134,10 @@ -<%def name="gravatar_with_user(contact, size=16)"> +<%def name="gravatar_with_user(contact, size=16, show_disabled=False)">
    ${self.gravatar(h.email_or_none(contact), size)} - ${h.link_to_user(contact)} + ${h.link_to_user(contact)}
    @@ -195,7 +195,7 @@ %if repo_instance.clone_uri:

    ${_('Clone from')} - ${h.hide_credentials(repo_instance.clone_uri)} + ${h.hide_credentials(repo_instance.clone_uri)}

    %endif diff --git a/rhodecode/templates/email_templates/user_registration.mako b/rhodecode/templates/email_templates/user_registration.mako --- a/rhodecode/templates/email_templates/user_registration.mako +++ b/rhodecode/templates/email_templates/user_registration.mako @@ -13,9 +13,10 @@ A new user `${user.username}` has regist - Username: ${user.username} - Full Name: ${user.firstname} ${user.lastname} - Email: ${user.email} +- Profile link: ${h.url('user_profile', username=user.username, qualified=True)} ## BODY GOES BELOW
    ${body_plaintext()} -
    \ No newline at end of file +
    diff --git a/rhodecode/templates/login.html b/rhodecode/templates/login.html --- a/rhodecode/templates/login.html +++ b/rhodecode/templates/login.html @@ -27,7 +27,7 @@
    - + <%block name="above_login_button" />
    <%include file="/base/flash_msg.html"/> diff --git a/rhodecode/templates/pullrequests/pullrequests.html b/rhodecode/templates/pullrequests/pullrequests.html --- a/rhodecode/templates/pullrequests/pullrequests.html +++ b/rhodecode/templates/pullrequests/pullrequests.html @@ -47,9 +47,9 @@
    diff --git a/rhodecode/templates/register.html b/rhodecode/templates/register.html --- a/rhodecode/templates/register.html +++ b/rhodecode/templates/register.html @@ -27,7 +27,7 @@
    - + <%block name="above_register_button" />
    <%include file="/base/flash_msg.html"/> diff --git a/rhodecode/tests/controllers/test_error.py b/rhodecode/tests/controllers/test_error.py deleted file mode 100644 --- a/rhodecode/tests/controllers/test_error.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (C) 2010-2016 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 url - - -@pytest.mark.usefixtures('app') -class TestErrorController(object): - def test_direct_document_call(self): - self.app.get(url(controller='error', action='document'), status=404) diff --git a/rhodecode/tests/fixtures/vcs_search_index.tar.gz b/rhodecode/tests/fixtures/vcs_search_index.tar.gz deleted file mode 100644 index 8608697cfaee888c2a9275f9365e31e8956dab31..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@""" in response def test_rss_with_auth_token(self, backend): - auth_token = User.get_first_admin().feed_token + auth_token = User.get_first_super_admin().feed_token assert auth_token != '' response = self.app.get(url(controller='feed', action='rss', repo_name=backend.repo_name, auth_token=auth_token)) diff --git a/rhodecode/tests/functional/test_home.py b/rhodecode/tests/functional/test_home.py --- a/rhodecode/tests/functional/test_home.py +++ b/rhodecode/tests/functional/test_home.py @@ -110,10 +110,12 @@ class TestHomeController(TestController) def test_index_show_version(self, autologin_user, name, state): version_string = 'RhodeCode Enterprise %s' % rhodecode.__version__ - show = SettingsModel().get_setting_by_name('show_version') - show.app_settings_value = state - Session().add(show) + sett = SettingsModel().create_or_update_setting( + 'show_version', state, 'bool') + Session().add(sett) Session().commit() + SettingsModel().invalidate_settings_cache() + response = self.app.get(url(controller='home', action='index')) if state is True: response.mustcontain(version_string) @@ -133,6 +135,18 @@ class TestUserAutocompleteData(TestContr values = [suggestion['value'] for suggestion in result['suggestions']] assert user_name in values + def test_returns_inactive_users_when_active_flag_sent(self, user_util): + self.log_user() + user = user_util.create_user(is_active=False) + user_name = user.username + response = self.app.get( + url(controller='home', action='user_autocomplete_data', + user_groups='true', active='0'), + headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200) + result = json.loads(response.body) + values = [suggestion['value'] for suggestion in result['suggestions']] + assert user_name in values + def test_returns_groups_when_user_groups_sent(self, user_util): self.log_user() group = user_util.create_user_group(user_groups_active=True) @@ -173,8 +187,10 @@ class TestUserAutocompleteData(TestContr headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200) result = json.loads(response.body) - users_mock.assert_called_once_with(name_contains=query) - groups_mock.assert_called_once_with(name_contains=query) + users_mock.assert_called_once_with( + name_contains=query, only_active=True) + groups_mock.assert_called_once_with( + name_contains=query, only_active=True) assert len(result['suggestions']) == 20 diff --git a/rhodecode/tests/functional/test_login.py b/rhodecode/tests/functional/test_login.py --- a/rhodecode/tests/functional/test_login.py +++ b/rhodecode/tests/functional/test_login.py @@ -448,7 +448,7 @@ class TestLoginController: assert [] == whitelist['api_access_controllers_whitelist'] if test_name == 'proper_auth_token': # use builtin if api_key is None - auth_token = User.get_first_admin().api_key + auth_token = User.get_first_super_admin().api_key with fixture.anon_access(False): self.app.get(url(controller='changeset', @@ -471,7 +471,7 @@ class TestLoginController: assert ['ChangesetController:changeset_raw'] == \ whitelist['api_access_controllers_whitelist'] if test_name == 'proper_auth_token': - auth_token = User.get_first_admin().api_key + auth_token = User.get_first_super_admin().api_key with fixture.anon_access(False): self.app.get(url(controller='changeset', diff --git a/rhodecode/tests/lib/middleware/test_disable_vcs.py b/rhodecode/tests/lib/middleware/test_disable_vcs.py --- a/rhodecode/tests/lib/middleware/test_disable_vcs.py +++ b/rhodecode/tests/lib/middleware/test_disable_vcs.py @@ -19,36 +19,35 @@ # and proprietary license terms, please see https://rhodecode.com/licenses/ import pytest -from rhodecode.lib.middleware.disable_vcs import DisableVCSPagesWrapper +from pyramid.response import Response +from pyramid.testing import DummyRequest +from rhodecode.lib.middleware.disable_vcs import ( + DisableVCSPagesWrapper, VCSServerUnavailable) -@pytest.mark.parametrize('url, expected_url', [ - ('/', '/'), - ('/_admin/settings', '/_admin/settings'), - ('/_admin/i_am_fine', '/_admin/i_am_fine'), - ('/_admin/settings/mappings', '/error/vcs_unavailable'), - ('/_admin/my_account/repos', '/error/vcs_unavailable'), - ('/_admin/create_repository', '/error/vcs_unavailable'), - ('/_admin/gists/1', '/error/vcs_unavailable'), - ('/_admin/notifications/1', '/error/vcs_unavailable'), +@pytest.mark.parametrize('url, should_raise', [ + ('/', False), + ('/_admin/settings', False), + ('/_admin/i_am_fine', False), + ('/_admin/settings/mappings', True), + ('/_admin/my_account/repos', True), + ('/_admin/create_repository', True), + ('/_admin/gists/1', True), + ('/_admin/notifications/1', True), ]) -def test_vcs_disabled(url, expected_url): - app = DisableVCSPagesWrapper(app=SimpleApp()) - assert expected_url == app(get_environ(url), None) - +def test_vcs_disabled(url, should_raise): + wrapped_view = DisableVCSPagesWrapper(pyramid_view) + request = DummyRequest(path=url) -def get_environ(url): - """Construct a minimum WSGI environ based on the URL.""" - environ = { - 'PATH_INFO': url, - } - return environ - + if should_raise: + with pytest.raises(VCSServerUnavailable): + response = wrapped_view(None, request) + else: + response = wrapped_view(None, request) + assert response.status_int == 200 -class SimpleApp(object): +def pyramid_view(context, request): """ - A mock app to be used in the wrapper that returns the modified URL - from the middleware + A mock pyramid view to be used in the wrapper """ - def __call__(self, environ, start_response): - return environ['PATH_INFO'] + return Response('success') diff --git a/rhodecode/tests/lib/test_encrypt.py b/rhodecode/tests/lib/test_encrypt.py --- a/rhodecode/tests/lib/test_encrypt.py +++ b/rhodecode/tests/lib/test_encrypt.py @@ -20,7 +20,8 @@ import pytest -from rhodecode.lib.encrypt import AESCipher +from rhodecode.lib.encrypt import ( + AESCipher, SignatureVerificationError, InvalidDecryptedValue) class TestEncryptModule(object): @@ -38,3 +39,38 @@ class TestEncryptModule(object): def test_encryption(self, key, text): enc = AESCipher(key).encrypt(text) assert AESCipher(key).decrypt(enc) == text + + def test_encryption_with_hmac(self): + key = 'secret' + text = 'ihatemysql' + enc = AESCipher(key, hmac=True).encrypt(text) + assert AESCipher(key, hmac=True).decrypt(enc) == text + + def test_encryption_with_hmac_with_bad_key(self): + key = 'secretstring' + text = 'ihatemysql' + enc = AESCipher(key, hmac=True).encrypt(text) + + with pytest.raises(SignatureVerificationError) as e: + assert AESCipher('differentsecret', hmac=True).decrypt(enc) == '' + + assert 'Encryption signature verification failed' in str(e) + + def test_encryption_with_hmac_with_bad_data(self): + key = 'secret' + text = 'ihatemysql' + enc = AESCipher(key, hmac=True).encrypt(text) + enc = 'xyz' + enc[3:] + with pytest.raises(SignatureVerificationError) as e: + assert AESCipher(key, hmac=True).decrypt(enc) == text + + assert 'Encryption signature verification failed' in str(e) + + def test_encryption_with_hmac_with_bad_key_not_strict(self): + key = 'secretstring' + text = 'ihatemysql' + enc = AESCipher(key, hmac=True).encrypt(text) + + assert isinstance(AESCipher( + 'differentsecret', hmac=True, strict_verification=False + ).decrypt(enc), InvalidDecryptedValue) diff --git a/rhodecode/tests/lib/test_helpers.py b/rhodecode/tests/lib/test_helpers.py --- a/rhodecode/tests/lib/test_helpers.py +++ b/rhodecode/tests/lib/test_helpers.py @@ -84,8 +84,12 @@ def test_process_patterns_repo(backend, 'pref': '#', } } + + def get_settings_mock(self, cache=True): + return config + with mock.patch.object(IssueTrackerSettingsModel, - 'get_settings', lambda s: config): + 'get_settings', get_settings_mock): processed_text = helpers.process_patterns( text_string, repo.repo_name, config) @@ -106,8 +110,12 @@ def test_process_patterns_no_repo(text_s 'pref': '#', } } + + def get_settings_mock(self, cache=True): + return config + with mock.patch.object(IssueTrackerSettingsModel, - 'get_global_settings', lambda s, cache: config): + 'get_global_settings', get_settings_mock): processed_text = helpers.process_patterns( text_string, '', config) @@ -126,8 +134,12 @@ def test_process_patterns_non_existent_r 'pref': '#', } } + + def get_settings_mock(self, cache=True): + return config + with mock.patch.object(IssueTrackerSettingsModel, - 'get_global_settings', lambda s, cache: config): + 'get_global_settings', get_settings_mock): processed_text = helpers.process_patterns( text_string, 'do-not-exist', config) @@ -182,10 +194,12 @@ def test_get_matching_offsets(test_text, assert helpers.get_matching_offsets( test_text, text_phrases) == expected_output + def test_normalize_text_for_matching(): assert helpers.normalize_text_for_matching( 'OJjfe)*#$*@)$JF*)3r2f80h') == 'ojjfe jf 3r2f80h' + def test_get_matching_line_offsets(): assert helpers.get_matching_line_offsets([ 'words words words', @@ -193,4 +207,4 @@ def test_get_matching_line_offsets(): 'some text some', 'words words words', 'words words words', - 'text here what'], 'text') == {3: [(5, 9)], 6: [(0, 4)]} \ No newline at end of file + 'text here what'], 'text') == {3: [(5, 9)], 6: [(0, 4)]} diff --git a/rhodecode/tests/lib/test_utils.py b/rhodecode/tests/lib/test_utils.py --- a/rhodecode/tests/lib/test_utils.py +++ b/rhodecode/tests/lib/test_utils.py @@ -29,6 +29,7 @@ import pytest from rhodecode.lib import caching_query from rhodecode.lib import utils from rhodecode.lib.utils2 import md5 +from rhodecode.model import settings from rhodecode.model import db from rhodecode.model import meta from rhodecode.model.repo import RepoModel @@ -402,7 +403,7 @@ class TestConfigDataFromDb(object): ] repo_name = 'test_repo' - model_patch = mock.patch.object(utils, 'VcsSettingsModel') + model_patch = mock.patch.object(settings, 'VcsSettingsModel') hooks_patch = mock.patch.object( utils, 'get_enabled_hook_classes', return_value=['pull', 'push', 'repo_size']) diff --git a/rhodecode/tests/other/test_libs.py b/rhodecode/tests/other/test_libs.py --- a/rhodecode/tests/other/test_libs.py +++ b/rhodecode/tests/other/test_libs.py @@ -432,7 +432,13 @@ def test_get_repo_by_id(test, expected): assert _test == expected -def test_invalidation_context(pylonsapp): +@pytest.mark.parametrize("test_repo_name, repo_type", [ + ("test_repo_1", None), + ("repo_group/foobar", None), + ("test_non_asci_ąćę", None), + (u"test_non_asci_unicode_ąćę", None), +]) +def test_invalidation_context(pylonsapp, test_repo_name, repo_type): from beaker.cache import cache_region from rhodecode.lib import caches from rhodecode.model.db import CacheKey @@ -442,7 +448,7 @@ def test_invalidation_context(pylonsapp) return 'result' invalidator_context = CacheKey.repo_context_cache( - _dummy_func, 'test_repo_1', 'repo') + _dummy_func, test_repo_name, 'repo') with invalidator_context as context: invalidated = context.invalidate() @@ -452,6 +458,8 @@ def test_invalidation_context(pylonsapp) assert 'result' == result assert isinstance(context, caches.FreshRegionCache) + assert 'InvalidationContext' in repr(invalidator_context) + with invalidator_context as context: context.invalidate() result = context.compute() diff --git a/rhodecode/tests/vcs/test_client_http.py b/rhodecode/tests/vcs/test_client_http.py --- a/rhodecode/tests/vcs/test_client_http.py +++ b/rhodecode/tests/vcs/test_client_http.py @@ -58,30 +58,43 @@ def stub_session(): return session -def test_repo_maker_uses_session_for_classmethods(stub_session): +@pytest.fixture +def stub_session_factory(stub_session): + """ + Stub of `rhodecode.lib.vcs.client_http.ThreadlocalSessionFactory`. + """ + session_factory = mock.Mock() + session_factory.return_value = stub_session + return session_factory + + +def test_repo_maker_uses_session_for_classmethods(stub_session_factory): repo_maker = client_http.RepoMaker( - 'server_and_port', 'endpoint', stub_session) + 'server_and_port', 'endpoint', stub_session_factory) repo_maker.example_call() - stub_session.post.assert_called_with( + stub_session_factory().post.assert_called_with( 'http://server_and_port/endpoint', data=mock.ANY) def test_repo_maker_uses_session_for_instance_methods( - stub_session, config): + stub_session_factory, config): repo_maker = client_http.RepoMaker( - 'server_and_port', 'endpoint', stub_session) + 'server_and_port', 'endpoint', stub_session_factory) repo = repo_maker('stub_path', config) repo.example_call() - stub_session.post.assert_called_with( + stub_session_factory().post.assert_called_with( 'http://server_and_port/endpoint', data=mock.ANY) +@mock.patch('rhodecode.lib.vcs.client_http.ThreadlocalSessionFactory') @mock.patch('rhodecode.lib.vcs.connection') -def test_connect_passes_in_the_same_session(connection, stub_session): - session_factory_patcher = mock.patch.object( - vcs, '_create_http_rpc_session', return_value=stub_session) - with session_factory_patcher: - vcs.connect_http('server_and_port') - assert connection.Hg._session == stub_session - assert connection.Svn._session == stub_session - assert connection.Git._session == stub_session +def test_connect_passes_in_the_same_session( + connection, session_factory_class, stub_session): + session_factory = session_factory_class.return_value + session_factory.return_value = stub_session + + vcs.connect_http('server_and_port') + + assert connection.Hg._session_factory() == stub_session + assert connection.Svn._session_factory() == stub_session + assert connection.Git._session_factory() == stub_session diff --git a/rhodecode/tweens.py b/rhodecode/tweens.py --- a/rhodecode/tweens.py +++ b/rhodecode/tweens.py @@ -69,7 +69,6 @@ def pylons_compatibility_tween_factory(h context.rhodecode_user = auth_user attach_context_attributes(context) pylons.tmpl_context._push_object(context) - return handler(request) finally: # Dispose current database session and rollback uncommitted diff --git a/test.ini b/test.ini --- a/test.ini +++ b/test.ini @@ -518,7 +518,7 @@ vcs.connection_timeout = 3600 ### LOGGING CONFIGURATION #### ################################ [loggers] -keys = root, routes, rhodecode, sqlalchemy, beaker, pyro4, templates, whoosh_indexer +keys = root, routes, rhodecode, sqlalchemy, beaker, pyro4, templates [handlers] keys = console, console_sql @@ -570,12 +570,6 @@ handlers = console_sql qualname = sqlalchemy.engine propagate = 0 -[logger_whoosh_indexer] -level = DEBUG -handlers = -qualname = whoosh_indexer -propagate = 1 - ############## ## HANDLERS ## ##############