# HG changeset patch # User Marcin Kuzminski # Date 2016-12-01 10:12:00 # Node ID 729990d56b98a5df3c604c6ec0c6f9114f2d979d # Parent f2f014dc8f4447e81ff3b99a1a9965fdc9980de0 # Parent 66ac4b2d6d39bd0409892a50da0e248ad11a67be release: Merge default into stable for release preparation diff --git a/.bumpversion.cfg b/.bumpversion.cfg --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 4.4.2 +current_version = 4.5.0 message = release: Bump version {current_version} to {new_version} [bumpversion:file:rhodecode/VERSION] diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -43,6 +43,7 @@ syntax: regexp ^rhodecode/public/css/style-polymer.css$ ^rhodecode/public/js/rhodecode-components.html$ ^rhodecode/public/js/scripts.js$ +^rhodecode/public/js/rhodecode-components.js$ ^rhodecode/public/js/src/components/root-styles.gen.html$ ^rhodecode/public/js/vendors/webcomponentsjs/ ^rhodecode\.db$ diff --git a/.release.cfg b/.release.cfg --- a/.release.cfg +++ b/.release.cfg @@ -4,26 +4,21 @@ done = false [task:bump_version] done = true -[task:rc_tools_pinned] -done = true - [task:fixes_on_stable] -done = true [task:pip2nix_generated] -done = true [task:changelog_updated] -done = true [task:generate_api_docs] -done = true + +[task:updated_translation] [release] -state = prepared -version = 4.4.2 +state = in_progress +version = 4.5.0 -[task:updated_translation] +[task:rc_tools_pinned] [task:generate_js_routes] diff --git a/Gruntfile.js b/Gruntfile.js --- a/Gruntfile.js +++ b/Gruntfile.js @@ -11,5 +11,5 @@ module.exports = function(grunt) { grunt.loadNpmTasks('grunt-crisper'); grunt.loadNpmTasks('grunt-contrib-copy'); - grunt.registerTask('default', ['less:production', 'less:components', 'concat:polymercss', 'copy','vulcanize', 'crisper', 'concat:dist']); + grunt.registerTask('default', ['less:production', 'less:components', 'concat:polymercss', 'copy', 'concat:dist', 'vulcanize', 'crisper']); }; diff --git a/LICENSE.txt b/LICENSE.txt --- a/LICENSE.txt +++ b/LICENSE.txt @@ -12,6 +12,10 @@ permission notice: file:licenses/msgpack_license.txt Copyright (c) 2009 - tornado file:licenses/tornado_license.txt + Copyright (c) 2015 - pygments-markdown-lexer + file:licenses/pygments_markdown_lexer_license.txt + Copyright 2006 - diff_match_patch + file:licenses/diff_match_patch_license.txt All licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/Makefile b/Makefile --- a/Makefile +++ b/Makefile @@ -2,7 +2,6 @@ WEBPACK=./node_modules/webpack/bin/webpack.js GRUNT=grunt NODE_PATH=./node_modules -FLAKE8=flake8 setup.py pytest_pylons/ rhodecode/ --select=E124 --ignore=E711,E712,E510,E121,E122,E126,E127,E128,E501,F401 --max-line-length=100 --exclude=*rhodecode/lib/dbmigrate/*,*rhodecode/tests/*,*rhodecode/lib/vcs/utils/* CI_PREFIX=enterprise .PHONY: docs docs-clean ci-docs clean test test-clean test-lint test-only @@ -25,13 +24,6 @@ test: test-clean test-only test-clean: rm -rf coverage.xml htmlcov junit.xml pylint.log result -test-lint: - if [ "$$IN_NIX_SHELL" = "1" ]; then \ - $(FLAKE8); \ - else \ - $(FLAKE8) --format=pylint --exit-zero > pylint.log; \ - fi - test-only: PYTHONHASHSEED=random py.test -vv -r xw --cov=rhodecode --cov-report=term-missing --cov-report=html rhodecode/tests/ diff --git a/bower.json b/bower.json --- a/bower.json +++ b/bower.json @@ -10,6 +10,8 @@ "paper-tooltip": "PolymerElements/paper-tooltip#^1.1.2", "paper-toast": "PolymerElements/paper-toast#^1.3.0", "paper-toggle-button": "PolymerElements/paper-toggle-button#^1.2.0", - "iron-ajax": "PolymerElements/iron-ajax#^1.4.3" + "iron-ajax": "PolymerElements/iron-ajax#^1.4.3", + "iron-autogrow-textarea": "PolymerElements/iron-autogrow-textarea#^1.0.13", + "iron-a11y-keys": "PolymerElements/iron-a11y-keys#^1.0.6" } } diff --git a/configs/development.ini b/configs/development.ini --- a/configs/development.ini +++ b/configs/development.ini @@ -1,7 +1,7 @@ ################################################################################ -## RHODECODE ENTERPRISE CONFIGURATION ## +## RHODECODE COMMUNITY EDITION CONFIGURATION ## # The %(here)s variable will be replaced with the parent directory of this file# ################################################################################ @@ -64,7 +64,7 @@ asyncore_use_poll = true ########################## ## GUNICORN WSGI SERVER ## ########################## -## run with gunicorn --log-config --paste +## run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini #use = egg:gunicorn#main ## Sets the number of process workers. You must set `instance_id = *` @@ -91,11 +91,13 @@ asyncore_use_poll = true #timeout = 21600 -## prefix middleware for RhodeCode, disables force_https flag. +## prefix middleware for RhodeCode. ## recommended when using proxy setup. ## allows to set RhodeCode under a prefix in server. -## eg https://server.com/. Enable `filter-with =` option below as well. -## optionally set prefix like: `prefix = /` +## eg https://server.com/custom_prefix. Enable `filter-with =` option below as well. +## And set your prefix like: `prefix = /custom_prefix` +## be sure to also set beaker.session.cookie_path = /custom_prefix if you need +## to make your cookies only work on prefix url [filter:proxy-prefix] use = egg:PasteDeploy#prefix prefix = / @@ -194,17 +196,17 @@ rss_items_per_page = 10 rss_include_diff = false ## gist URL alias, used to create nicer urls for gist. This should be an -## url that does rewrites to _admin/gists/. +## url that does rewrites to _admin/gists/{gistid}. ## example: http://gist.rhodecode.org/{gistid}. Empty means use the internal -## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/ +## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/{gistid} gist_alias_url = ## List of controllers (using glob pattern syntax) that AUTH TOKENS could be ## used for access. -## Adding ?auth_token = to the url authenticates this request as if it +## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it ## came from the the logged in user who own this authentication token. ## -## Syntax is :. +## Syntax is ControllerClass:function_pattern. ## To enable access to raw_files put `FilesController:raw`. ## To enable access to patches add `ChangesetController:changeset_patch`. ## The list should be "," separated and on a single line. @@ -377,15 +379,15 @@ beaker.session.lock_dir = %(here)s/data/ ## Secure encrypted cookie. Requires AES and AES python libraries ## you must disable beaker.session.secret to use this -#beaker.session.encrypt_key = -#beaker.session.validate_key = +#beaker.session.encrypt_key = key_for_encryption +#beaker.session.validate_key = validation_key ## sets session as invalid(also logging out user) if it haven not been ## accessed for given amount of time in seconds beaker.session.timeout = 2592000 beaker.session.httponly = true -## Path to use for the cookie. -#beaker.session.cookie_path = / +## Path to use for the cookie. Set to prefix if you use prefix middleware +#beaker.session.cookie_path = /custom_prefix ## uncomment for https secure cookie beaker.session.secure = false @@ -403,8 +405,8 @@ beaker.session.auto = false ## Full text search indexer is available in rhodecode-tools under ## `rhodecode-tools index` command -# WHOOSH Backend, doesn't require additional services to run -# it works good with few dozen repos +## WHOOSH Backend, doesn't require additional services to run +## it works good with few dozen repos search.module = rhodecode.lib.index.whoosh search.location = %(here)s/data/index @@ -511,7 +513,7 @@ sqlalchemy.db1.url = sqlite:///%(here)s/ ## print the sql statements to output sqlalchemy.db1.echo = false -## recycle the connections after this ammount of seconds +## recycle the connections after this amount of seconds sqlalchemy.db1.pool_recycle = 3600 sqlalchemy.db1.convert_unicode = true @@ -533,19 +535,19 @@ vcs.server = localhost:9900 ## Web server connectivity protocol, responsible for web based VCS operatations ## Available protocols are: -## `pyro4` - using pyro4 server -## `http` - using http-rpc backend +## `pyro4` - use pyro4 server +## `http` - use http-rpc backend (default) vcs.server.protocol = http ## Push/Pull operations protocol, available options are: -## `pyro4` - using pyro4 server -## `rhodecode.lib.middleware.utils.scm_app_http` - Http based, recommended -## `vcsserver.scm_app` - internal app (EE only) -vcs.scm_app_implementation = rhodecode.lib.middleware.utils.scm_app_http +## `pyro4` - use pyro4 server +## `http` - use http-rpc backend (default) +## +vcs.scm_app_implementation = http ## Push/Pull operations hooks protocol, available options are: -## `pyro4` - using pyro4 server -## `http` - using http-rpc backend +## `pyro4` - use pyro4 server +## `http` - use http-rpc backend (default) vcs.hooks.protocol = http vcs.server.log_level = debug @@ -574,12 +576,15 @@ svn.proxy.generate_config = false svn.proxy.list_parent_path = true ## Set location and file name of generated config file. svn.proxy.config_file_path = %(here)s/mod_dav_svn.conf -## File system path to the directory containing the repositories served by -## RhodeCode. -svn.proxy.parent_path_root = /path/to/repo_store -## Used as a prefix to the block in the generated config file. In -## most cases it should be set to `/`. +## Used as a prefix to the `Location` block in the generated config file. +## In most cases it should be set to `/`. svn.proxy.location_root = / +## Command to reload the mod dav svn configuration on change. +## Example: `/etc/init.d/apache2 reload` +#svn.proxy.reload_cmd = /etc/init.d/apache2 reload +## If the timeout expires before the reload command finishes, the command will +## be killed. Setting it to zero means no timeout. Defaults to 10 seconds. +#svn.proxy.reload_timeout = 10 ################################ diff --git a/configs/production.ini b/configs/production.ini --- a/configs/production.ini +++ b/configs/production.ini @@ -1,7 +1,7 @@ ################################################################################ -## RHODECODE ENTERPRISE CONFIGURATION ## +## RHODECODE COMMUNITY EDITION CONFIGURATION ## # The %(here)s variable will be replaced with the parent directory of this file# ################################################################################ @@ -64,7 +64,7 @@ port = 5000 ########################## ## GUNICORN WSGI SERVER ## ########################## -## run with gunicorn --log-config --paste +## run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini use = egg:gunicorn#main ## Sets the number of process workers. You must set `instance_id = *` @@ -91,11 +91,13 @@ max_requests_jitter = 30 timeout = 21600 -## prefix middleware for RhodeCode, disables force_https flag. +## prefix middleware for RhodeCode. ## recommended when using proxy setup. ## allows to set RhodeCode under a prefix in server. -## eg https://server.com/. Enable `filter-with =` option below as well. -## optionally set prefix like: `prefix = /` +## eg https://server.com/custom_prefix. Enable `filter-with =` option below as well. +## And set your prefix like: `prefix = /custom_prefix` +## be sure to also set beaker.session.cookie_path = /custom_prefix if you need +## to make your cookies only work on prefix url [filter:proxy-prefix] use = egg:PasteDeploy#prefix prefix = / @@ -168,17 +170,17 @@ rss_items_per_page = 10 rss_include_diff = false ## gist URL alias, used to create nicer urls for gist. This should be an -## url that does rewrites to _admin/gists/. +## url that does rewrites to _admin/gists/{gistid}. ## example: http://gist.rhodecode.org/{gistid}. Empty means use the internal -## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/ +## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/{gistid} gist_alias_url = ## List of controllers (using glob pattern syntax) that AUTH TOKENS could be ## used for access. -## Adding ?auth_token = to the url authenticates this request as if it +## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it ## came from the the logged in user who own this authentication token. ## -## Syntax is :. +## Syntax is ControllerClass:function_pattern. ## To enable access to raw_files put `FilesController:raw`. ## To enable access to patches add `ChangesetController:changeset_patch`. ## The list should be "," separated and on a single line. @@ -351,15 +353,15 @@ beaker.session.lock_dir = %(here)s/data/ ## Secure encrypted cookie. Requires AES and AES python libraries ## you must disable beaker.session.secret to use this -#beaker.session.encrypt_key = -#beaker.session.validate_key = +#beaker.session.encrypt_key = key_for_encryption +#beaker.session.validate_key = validation_key ## sets session as invalid(also logging out user) if it haven not been ## accessed for given amount of time in seconds beaker.session.timeout = 2592000 beaker.session.httponly = true -## Path to use for the cookie. -#beaker.session.cookie_path = / +## Path to use for the cookie. Set to prefix if you use prefix middleware +#beaker.session.cookie_path = /custom_prefix ## uncomment for https secure cookie beaker.session.secure = false @@ -377,8 +379,8 @@ beaker.session.auto = false ## Full text search indexer is available in rhodecode-tools under ## `rhodecode-tools index` command -# WHOOSH Backend, doesn't require additional services to run -# it works good with few dozen repos +## WHOOSH Backend, doesn't require additional services to run +## it works good with few dozen repos search.module = rhodecode.lib.index.whoosh search.location = %(here)s/data/index @@ -480,7 +482,7 @@ sqlalchemy.db1.url = postgresql://postgr ## print the sql statements to output sqlalchemy.db1.echo = false -## recycle the connections after this ammount of seconds +## recycle the connections after this amount of seconds sqlalchemy.db1.pool_recycle = 3600 sqlalchemy.db1.convert_unicode = true @@ -502,20 +504,20 @@ vcs.server = localhost:9900 ## Web server connectivity protocol, responsible for web based VCS operatations ## Available protocols are: -## `pyro4` - using pyro4 server -## `http` - using http-rpc backend -#vcs.server.protocol = http +## `pyro4` - use pyro4 server +## `http` - use http-rpc backend (default) +vcs.server.protocol = http ## Push/Pull operations protocol, available options are: -## `pyro4` - using pyro4 server -## `rhodecode.lib.middleware.utils.scm_app_http` - Http based, recommended -## `vcsserver.scm_app` - internal app (EE only) -#vcs.scm_app_implementation = rhodecode.lib.middleware.utils.scm_app_http +## `pyro4` - use pyro4 server +## `http` - use http-rpc backend (default) +## +vcs.scm_app_implementation = http ## Push/Pull operations hooks protocol, available options are: -## `pyro4` - using pyro4 server -## `http` - using http-rpc backend -#vcs.hooks.protocol = http +## `pyro4` - use pyro4 server +## `http` - use http-rpc backend (default) +vcs.hooks.protocol = http vcs.server.log_level = info ## Start VCSServer with this instance as a subprocess, usefull for development @@ -543,12 +545,15 @@ svn.proxy.generate_config = false svn.proxy.list_parent_path = true ## Set location and file name of generated config file. svn.proxy.config_file_path = %(here)s/mod_dav_svn.conf -## File system path to the directory containing the repositories served by -## RhodeCode. -svn.proxy.parent_path_root = /path/to/repo_store -## Used as a prefix to the block in the generated config file. In -## most cases it should be set to `/`. +## Used as a prefix to the `Location` block in the generated config file. +## In most cases it should be set to `/`. svn.proxy.location_root = / +## Command to reload the mod dav svn configuration on change. +## Example: `/etc/init.d/apache2 reload` +#svn.proxy.reload_cmd = /etc/init.d/apache2 reload +## If the timeout expires before the reload command finishes, the command will +## be killed. Setting it to zero means no timeout. Defaults to 10 seconds. +#svn.proxy.reload_timeout = 10 ################################ diff --git a/default.nix b/default.nix --- a/default.nix +++ b/default.nix @@ -4,27 +4,55 @@ # derivation. For advanced tweaks to pimp up the development environment we use # "shell.nix" so that it does not have to clutter this file. -{ pkgs ? (import {}) -, pythonPackages ? "python27Packages" +args@ +{ pythonPackages ? "python27Packages" , pythonExternalOverrides ? self: super: {} , doCheck ? true +, ... }: -let pkgs_ = pkgs; in - let - pkgs = pkgs_.overridePackages (self: super: { - # Override subversion derivation to - # - activate python bindings - # - set version to 1.8 - subversion = super.subversion18.override { - httpSupport = true; - pythonBindings = true; - python = self.python27Packages.python; - }; + + # Use nixpkgs from args or import them. We use this indirect approach + # through args to be able to use the name `pkgs` for our customized packages. + # Otherwise we will end up with an infinite recursion. + nixpkgs = args.pkgs or (import { }); + + # johbo: Interim bridge which allows us to build with the upcoming + # nixos.16.09 branch (unstable at the moment of writing this note) and the + # current stable nixos-16.03. + backwardsCompatibleFetchgit = { ... }@args: + let + origSources = nixpkgs.fetchgit args; + in + nixpkgs.lib.overrideDerivation origSources (oldAttrs: { + NIX_PREFETCH_GIT_CHECKOUT_HOOK = '' + find $out -name '.git*' -print0 | xargs -0 rm -rf + ''; + }); + + # Create a customized version of nixpkgs which should be used throughout the + # rest of this file. + pkgs = nixpkgs.overridePackages (self: super: { + fetchgit = backwardsCompatibleFetchgit; }); - inherit (pkgs.lib) fix extends; + # Evaluates to the last segment of a file system path. + basename = path: with pkgs.lib; last (splitString "/" path); + + # source code filter used as arugment to builtins.filterSource. + src-filter = path: type: with pkgs.lib; + let + ext = last (splitString "." path); + in + !builtins.elem (basename path) [ + ".git" ".hg" "__pycache__" ".eggs" + "bower_components" "node_modules" + "build" "data" "result" "tmp"] && + !builtins.elem ext ["egg-info" "pyc"] && + # TODO: johbo: This check is wrong, since "path" contains an absolute path, + # it would still be good to restore it since we want to ignore "result-*". + !hasPrefix "result" path; basePythonPackages = with builtins; if isAttrs pythonPackages then pythonPackages @@ -34,25 +62,6 @@ let pkgs.buildBowerComponents or (import ./pkgs/backport-16.03-build-bower-components.nix { inherit pkgs; }); - elem = builtins.elem; - basename = path: with pkgs.lib; last (splitString "/" path); - startsWith = prefix: full: let - actualPrefix = builtins.substring 0 (builtins.stringLength prefix) full; - in actualPrefix == prefix; - - src-filter = path: type: with pkgs.lib; - let - ext = last (splitString "." path); - in - !elem (basename path) [ - ".git" ".hg" "__pycache__" ".eggs" - "bower_components" "node_modules" - "build" "data" "result" "tmp"] && - !elem ext ["egg-info" "pyc"] && - # TODO: johbo: This check is wrong, since "path" contains an absolute path, - # it would still be good to restore it since we want to ignore "result-*". - !startsWith "result" path; - sources = pkgs.config.rc.sources or {}; version = builtins.readFile ./rhodecode/VERSION; rhodecode-enterprise-ce-src = builtins.filterSource src-filter ./.; @@ -147,18 +156,6 @@ let then "${pkgs.glibcLocales}/lib/locale/locale-archive" else ""; - # Somewhat snappier setup of the development environment - # TODO: move into shell.nix - # TODO: think of supporting a stable path again, so that multiple shells - # can share it. - shellHook = '' - tmp_path=$(mktemp -d) - export PATH="$tmp_path/bin:$PATH" - export PYTHONPATH="$tmp_path/${self.python.sitePackages}:$PYTHONPATH" - mkdir -p $tmp_path/${self.python.sitePackages} - python setup.py develop --prefix $tmp_path --allow-hosts "" - '' + linkNodeAndBowerPackages; - preCheck = '' export PATH="$out/bin:$PATH" ''; @@ -226,16 +223,16 @@ let rhodecode-testdata-src = sources.rhodecode-testdata or ( pkgs.fetchhg { url = "https://code.rhodecode.com/upstream/rc_testdata"; - rev = "v0.8.0"; - sha256 = "0hy1ba134rq2f9si85yx7j4qhc9ky0hjzdk553s3q026i7km809m"; + rev = "v0.9.0"; + sha256 = "0k0ccb7cncd6mmzwckfbr6l7fsymcympwcm948qc3i0f0m6bbg1y"; }); # Apply all overrides and fix the final package set - myPythonPackagesUnfix = + myPythonPackagesUnfix = with pkgs.lib; (extends pythonExternalOverrides (extends pythonLocalOverrides (extends pythonOverrides pythonGeneratedPackages))); - myPythonPackages = (fix myPythonPackagesUnfix); + myPythonPackages = (pkgs.lib.fix myPythonPackagesUnfix); in myPythonPackages.rhodecode-enterprise-ce diff --git a/docs/admin/admin-tricks.rst b/docs/admin/admin-tricks.rst --- a/docs/admin/admin-tricks.rst +++ b/docs/admin/admin-tricks.rst @@ -62,6 +62,24 @@ 3. Select :guilabel:`Save`, and you will .. _md-rst: + +Suppress license warnings or errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In case you're running on maximum allowed users, RhodeCode will display a +warning message on pages that you're close to the license limits. +It's often not desired to show that all the time. Here's how you can suppress +the license messages. + +1. From the |RCE| interface, select + :menuselection:`Admin --> Settings --> Global` +2. Select :guilabel:`Flash message filtering` from the drop-down menu. +3. Select :guilabel:`Save`, and you will no longer see the license message + once your page refreshes. + +.. _admin-tricks-suppress-license-messages: + + Markdown or RST Rendering ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/admin/apache-subdirectory.rst b/docs/admin/apache-subdirectory.rst --- a/docs/admin/apache-subdirectory.rst +++ b/docs/admin/apache-subdirectory.rst @@ -7,10 +7,11 @@ Use the following example to configure A .. code-block:: apache - > # Change into your chosen prefix - ProxyPass http://127.0.0.1:5000/ - ProxyPassReverse http://127.0.0.1:5000/ - SetEnvIf X-Url-Scheme https HTTPS=1 + / # Change into your chosen prefix + ProxyPreserveHost On + ProxyPass "http://127.0.0.1:5000/" + ProxyPassReverse "http://127.0.0.1:5000/" + Header set X-Url-Scheme https env=HTTPS In addition to the regular Apache setup you will need to add the following diff --git a/docs/admin/backup-restore.rst b/docs/admin/backup-restore.rst --- a/docs/admin/backup-restore.rst +++ b/docs/admin/backup-restore.rst @@ -9,9 +9,14 @@ Backup and Restore To snapshot an instance of |RCE|, and save its settings, you need to backup the following parts of the system at the same time. -* The |repos| managed by the instance. +* The |repos| managed by the instance together with the stored Gists. * The |RCE| database. -* Any configuration files or extensions that you've configured. +* Any configuration files or extensions that you've configured. In most + cases it's only the :file:`rhodecode.ini` file. +* Installer files such as those in `/opt/rhodecode` can be backed-up, however + it's not required since in case of a recovery installer simply + re-creates those. + .. important:: @@ -29,11 +34,17 @@ Repository Backup ^^^^^^^^^^^^^^^^^ To back up your |repos|, use the API to get a list of all |repos| managed, -and then clone them to your backup location. +and then clone them to your backup location. This is the most safe backup option. +Backing up the storage directory could potentially result in a backup of +partially committed files or commits. (Backup taking place during a big push) +As an alternative you could use a rsync or simple `cp` commands if you can +ensure your instance is only in read-only mode or stopped at the moment. + Use the ``get_repos`` method to list all your managed |repos|, and use the ``clone_uri`` information that is returned. See the :ref:`api` -for more information. +for more information. Be sure to keep the structure or repositories with their +repository groups. .. important:: @@ -54,13 +65,19 @@ backup location: .. code-block:: bash # For MySQL DBs - $ mysqldump -u -p db_name > mysql-db-backup + $ mysqldump -u -p rhodecode_db_name > mysql-db-backup + # MySQL restore command + $ mysql -u -p rhodecode_db_name < mysql-db-backup # For PostgreSQL DBs - $ pg_dump dbname > postgresql-db-backup + $ PGPASSWORD= pg_dump rhodecode_db_name > postgresql-db-backup + # PosgreSQL restore + $ PGPASSWORD= psql -U -h localhost -d rhodecode_db_name -1 -f postgresql-db-backup - # For SQLlite + # For SQLite $ sqlite3 rhodecode.db ‘.dump’ > sqlite-db-backup + # SQLite restore + $ copy sqlite-db-backup rhodecode.db The default |RCE| SQLite database location is @@ -75,13 +92,18 @@ Configuration File Backup Depending on your setup, you could have a number of configuration files that should be backed up. You may have some, or all of the configuration files listed in the :ref:`config-rce-files` section. Ideally you should back these -up at the same time as the database and |repos|. +up at the same time as the database and |repos|. It really depends on if you need +the configuration file like logs, custom modules. We always recommend backing +those up. Gist Backup ^^^^^^^^^^^ -To backup the gists on your |RCE| instance you can use the ``get_users`` and -``get_gists`` API methods to fetch the gists for each user on the instance. +To backup the gists on your |RCE| instance you usually have to backup the +gist storage path. If this haven't been changed it's located inside +:file:`.rc_gist_store` and the metadata in :file:`.rc_gist_metadata`. +You can use the ``get_users`` and ``get_gists`` API methods to fetch the +gists for each user on the instance. Extension Backups ^^^^^^^^^^^^^^^^^ @@ -100,15 +122,17 @@ the :ref:`indexing-ref` section. Restoration Steps ----------------- -To restore an instance of |RCE| from its backed up components, use the -following steps. +To restore an instance of |RCE| from its backed up components, to a fresh +system use the following steps. -1. Install a new instance of |RCE|. -2. Once installed, configure the instance to use the backed up - :file:`rhodecode.ini` file. Ensure this file points to the backed up +1. Install a new instance of |RCE| using sqlite option as database. +2. Restore your database. +3. Once installed, replace you backed up the :file:`rhodecode.ini` with your + backup version. Ensure this file points to the restored database, see the :ref:`config-database` section. -3. Restart |RCE| and remap and rescan your |repos|, see the - :ref:`remap-rescan` section. +4. Restart |RCE| and remap and rescan your |repos| to verify filesystem access, + see the :ref:`remap-rescan` section. + Post Restoration Steps ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/admin/reset-information.rst b/docs/admin/reset-information.rst --- a/docs/admin/reset-information.rst +++ b/docs/admin/reset-information.rst @@ -22,8 +22,8 @@ account permissions. .. code-block:: bash # Open iShell from the terminal - $ .rccontrol/enterprise-5/profile/bin/paster \ - ishell .rccontrol/enterprise-5/rhodecode.ini + $ .rccontrol/enterprise-1/profile/bin/paster \ + ishell .rccontrol/enterprise-1/rhodecode.ini .. code-block:: mysql @@ -52,11 +52,12 @@ following example to make changes to thi .. code-block:: mysql # Use this example to enable global .hgrc access - In [4]: new_option = RhodeCodeUi() - In [5]: new_option.ui_section='web' - In [6]: new_option.ui_key='allow_push' - In [7]: new_option.ui_value='*' - In [8]: Session().add(new_option);Session().commit() + In [1]: new_option = RhodeCodeUi() + In [2]: new_option.ui_section='web' + In [3]: new_option.ui_key='allow_push' + In [4]: new_option.ui_value='*' + In [5]: Session().add(new_option);Session().commit() + In [6]: exit() Manually Reset Password ^^^^^^^^^^^^^^^^^^^^^^^ @@ -72,24 +73,47 @@ Use the following code example to carry .. code-block:: bash # starts the ishell interactive prompt - $ .rccontrol/enterprise-5/profile/bin/paster \ - ishell .rccontrol/enterprise-5/rhodecode.ini + $ .rccontrol/enterprise-1/profile/bin/paster \ + ishell .rccontrol/enterprise-1/rhodecode.ini .. code-block:: mysql - from rhodecode.lib.auth import generate_auth_token - from rhodecode.lib.auth import get_crypt_password - + In [1]: from rhodecode.lib.auth import generate_auth_token + In [2]: from rhodecode.lib.auth import get_crypt_password # Enter the user name whose password you wish to change - my_user = 'USERNAME' - u = User.get_by_username(my_user) - + In [3]: my_user = 'USERNAME' + In [4]: u = User.get_by_username(my_user) # If this fails then the user does not exist - u.auth_token = generate_auth_token(my_user) - + In [5]: u.auth_token = generate_auth_token(my_user) # Set the new password - u.password = get_crypt_password('PASSWORD') + In [6]: u.password = get_crypt_password('PASSWORD') + In [7]: Session().add(u);Session().commit() + In [8]: exit() + + + +Change user details +^^^^^^^^^^^^^^^^^^^ + +If you need to manually change some of users details, use the following steps. + +1. Navigate to your |RCE| install location. +2. Run the interactive ``ishell`` prompt. +3. Set a new arguments for users. - Session().add(u) - Session().commit() - exit +Use the following code example to carry out these steps. + +.. code-block:: bash + + # starts the ishell interactive prompt + $ .rccontrol/enterprise-1/profile/bin/paster \ + ishell .rccontrol/enterprise-1/rhodecode.ini + +.. code-block:: mysql + + # Use this example to change email and username of LDAP user + In [1]: my_user = User.get_by_username('some_username') + In [2]: my_user.email = 'new_email@foobar.com' + In [3]: my_user.username = 'SomeUser' + In [4]: Session().add(my_user);Session().commit() + In [5]: exit() diff --git a/docs/admin/sec-your-server.rst b/docs/admin/sec-your-server.rst --- a/docs/admin/sec-your-server.rst +++ b/docs/admin/sec-your-server.rst @@ -36,7 +36,7 @@ 1. On your local machine create the publ Your public key has been saved in /home/user/.ssh/id_rsa.pub. The key fingerprint is: 02:82:38:95:e5:30:d2:ad:17:60:15:7f:94:17:9f:30 user@ubuntu - The key's randomart image is: + The key\'s randomart image is: +--[ RSA 2048]----+ 2. SFTP to your server, and copy the public key to the ``~/.ssh`` folder. diff --git a/docs/admin/svn-http.rst b/docs/admin/svn-http.rst new file mode 100644 --- /dev/null +++ b/docs/admin/svn-http.rst @@ -0,0 +1,137 @@ +.. _svn-http: + +|svn| With Write Over HTTP +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To use |svn| with read/write support over the |svn| HTTP protocol, you have to +configure the HTTP |svn| backend. + +Prerequisites +============= + +- Enable HTTP support inside the admin VCS settings on your |RCE| instance +- You need to install the following tools on the machine that is running an + instance of |RCE|: + ``Apache HTTP Server`` and ``mod_dav_svn``. + + +Using Ubuntu 14.04 Distribution as an example execute the following: + +.. code-block:: bash + + $ sudo apt-get install apache2 libapache2-mod-svn + +Once installed you need to enable ``dav_svn``: + +.. code-block:: bash + + $ sudo a2enmod dav_svn + $ sudo a2enmod headers + + +Configuring Apache Setup +======================== + +.. tip:: + + It is recommended to run Apache on a port other than 80, due to possible + conflicts with other HTTP servers like nginx. To do this, set the + ``Listen`` parameter in the ``/etc/apache2/ports.conf`` file, for example + ``Listen 8090``. + + +.. warning:: + + Make sure your Apache instance which runs the mod_dav_svn module is + only accessible by |RCE|. Otherwise everyone is able to browse + the repositories or run subversion operations (checkout/commit/etc.). + +It is also recommended to run apache as the same user as |RCE|, otherwise +permission issues could occur. To do this edit the ``/etc/apache2/envvars`` + + .. code-block:: apache + + export APACHE_RUN_USER=rhodecode + export APACHE_RUN_GROUP=rhodecode + +1. To configure Apache, create and edit a virtual hosts file, for example + :file:`/etc/apache2/sites-available/default.conf`. Below is an example + how to use one with auto-generated config ```mod_dav_svn.conf``` + from configured |RCE| instance. + +.. code-block:: apache + + + ServerAdmin rhodecode-admin@localhost + DocumentRoot /var/www/html + ErrorLog ${'${APACHE_LOG_DIR}'}/error.log + CustomLog ${'${APACHE_LOG_DIR}'}/access.log combined + Include /home/user/.rccontrol/enterprise-1/mod_dav_svn.conf + + + +2. Go to the :menuselection:`Admin --> Settings --> VCS` page, and + enable :guilabel:`Proxy Subversion HTTP requests`, and specify the + :guilabel:`Subversion HTTP Server URL`. + +3. Open the |RCE| configuration file, + :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini` + +4. Add the following configuration option in the ``[app:main]`` + section if you don't have it yet. + + This enables mapping of the created |RCE| repo groups into special + |svn| paths. Each time a new repository group is created, the system will + update the template file and create new mapping. Apache web server needs to + be reloaded to pick up the changes on this file. + To do this, simply configure `svn.proxy.reload_cmd` inside the .ini file. + Example configuration: + + +.. code-block:: ini + + ############################################################ + ### Subversion proxy support (mod_dav_svn) ### + ### Maps RhodeCode repo groups into SVN paths for Apache ### + ############################################################ + ## Enable or disable the config file generation. + svn.proxy.generate_config = true + ## Generate config file with `SVNListParentPath` set to `On`. + svn.proxy.list_parent_path = true + ## Set location and file name of generated config file. + svn.proxy.config_file_path = %(here)s/mod_dav_svn.conf + ## Used as a prefix to the block in the generated config file. + ## In most cases it should be set to `/`. + svn.proxy.location_root = / + ## Command to reload the mod dav svn configuration on change. + ## Example: `/etc/init.d/apache2 reload` + svn.proxy.reload_cmd = /etc/init.d/apache2 reload + ## If the timeout expires before the reload command finishes, the command will + ## be killed. Setting it to zero means no timeout. Defaults to 10 seconds. + #svn.proxy.reload_timeout = 10 + + +This would create a special template file called ```mod_dav_svn.conf```. We +used that file path in the apache config above inside the Include statement. +It's also possible to generate the config from the +:menuselection:`Admin --> Settings --> VCS` page. + + +Using |svn| +=========== + +Once |svn| has been enabled on your instance, you can use it with the +following examples. For more |svn| information, see the `Subversion Red Book`_ + +.. code-block:: bash + + # To clone a repository + svn checkout http://my-svn-server.example.com/my-svn-repo + + # svn commit + svn commit + + +.. _Subversion Red Book: http://svnbook.red-bean.com/en/1.7/svn-book.html#svn.ref.svn + +.. _Ask Ubuntu: http://askubuntu.com/questions/162391/how-do-i-fix-my-locale-issue \ No newline at end of file diff --git a/docs/admin/system-admin.rst b/docs/admin/system-admin.rst --- a/docs/admin/system-admin.rst +++ b/docs/admin/system-admin.rst @@ -18,6 +18,7 @@ The following are the most common system config-files-overview vcs-server + svn-http apache-config nginx-config backup-restore diff --git a/docs/admin/tuning-change-large-file-dir.rst b/docs/admin/tuning-change-large-file-dir.rst --- a/docs/admin/tuning-change-large-file-dir.rst +++ b/docs/admin/tuning-change-large-file-dir.rst @@ -18,7 +18,7 @@ 1. Open ishell from the terminal and use 2. Run the following commands, and ensure that |RCE| has write access to the new directory: -.. code-block:: mysql +.. code-block:: bash # Once logged into the database, use SQL to redirect # the large files location diff --git a/docs/admin/vcs-server.rst b/docs/admin/vcs-server.rst --- a/docs/admin/vcs-server.rst +++ b/docs/admin/vcs-server.rst @@ -298,133 +298,7 @@ For a more detailed explanation of the l format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s datefmt = %Y-%m-%d %H:%M:%S -.. _svn-http: - -|svn| With Write Over HTTP -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -To use |svn| with read/write support over the |svn| HTTP protocol, you have to -configure the HTTP |svn| backend. - -Prerequisites -============= - -- Enable HTTP support inside the admin VCS settings on your |RCE| instance -- You need to install the following tools on the machine that is running an - instance of |RCE|: - ``Apache HTTP Server`` and - ``mod_dav_svn``. - - -Using Ubuntu Distribution as an example you can run: - -.. code-block:: bash - - $ sudo apt-get install apache2 libapache2-mod-svn - -Once installed you need to enable ``dav_svn``: - -.. code-block:: bash - - $ sudo a2enmod dav_svn - -Configuring Apache Setup -======================== - -.. tip:: - - It is recommended to run Apache on a port other than 80, due to possible - conflicts with other HTTP servers like nginx. To do this, set the - ``Listen`` parameter in the ``/etc/apache2/ports.conf`` file, for example - ``Listen 8090``. - - -.. warning:: - - Make sure your Apache instance which runs the mod_dav_svn module is - only accessible by RhodeCode. Otherwise everyone is able to browse - the repositories or run subversion operations (checkout/commit/etc.). - -It is also recommended to run apache as the same user as |RCE|, otherwise -permission issues could occur. To do this edit the ``/etc/apache2/envvars`` - - .. code-block:: apache - - export APACHE_RUN_USER=rhodecode - export APACHE_RUN_GROUP=rhodecode - -1. To configure Apache, create and edit a virtual hosts file, for example - :file:`/etc/apache2/sites-available/default.conf`. Below is an example - how to use one with auto-generated config ```mod_dav_svn.conf``` - from configured |RCE| instance. - -.. code-block:: apache - - - ServerAdmin rhodecode-admin@localhost - DocumentRoot /var/www/html - ErrorLog ${'${APACHE_LOG_DIR}'}/error.log - CustomLog ${'${APACHE_LOG_DIR}'}/access.log combined - Include /home/user/.rccontrol/enterprise-1/mod_dav_svn.conf - - - -2. Go to the :menuselection:`Admin --> Settings --> VCS` page, and - enable :guilabel:`Proxy Subversion HTTP requests`, and specify the - :guilabel:`Subversion HTTP Server URL`. - -3. Open the |RCE| configuration file, - :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini` - -4. Add the following configuration option in the ``[app:main]`` - section if you don't have it yet. - - This enables mapping of the created |RCE| repo groups into special |svn| paths. - Each time a new repository group is created, the system will update - the template file and create new mapping. Apache web server needs to be - reloaded to pick up the changes on this file. - It's recommended to add reload into a crontab so the changes can be picked - automatically once someone creates a repository group inside RhodeCode. - - -.. code-block:: ini - - ############################################## - ### Subversion proxy support (mod_dav_svn) ### - ############################################## - ## Enable or disable the config file generation. - svn.proxy.generate_config = true - ## Generate config file with `SVNListParentPath` set to `On`. - svn.proxy.list_parent_path = true - ## Set location and file name of generated config file. - svn.proxy.config_file_path = %(here)s/mod_dav_svn.conf - ## File system path to the directory containing the repositories served by - ## RhodeCode. - svn.proxy.parent_path_root = /path/to/repo_store - ## Used as a prefix to the block in the generated config file. In - ## most cases it should be set to `/`. - svn.proxy.location_root = / - - -This would create a special template file called ```mod_dav_svn.conf```. We -used that file path in the apache config above inside the Include statement. - - -Using |svn| -=========== - -Once |svn| has been enabled on your instance, you can use it with the -following examples. For more |svn| information, see the `Subversion Red Book`_ - -.. code-block:: bash - - # To clone a repository - svn checkout http://my-svn-server.example.com/my-svn-repo - - # svn commit - svn commit .. _Subversion Red Book: http://svnbook.red-bean.com/en/1.7/svn-book.html#svn.ref.svn - -.. _Ask Ubuntu: http://askubuntu.com/questions/162391/how-do-i-fix-my-locale-issue \ No newline at end of file +.. _Ask Ubuntu: http://askubuntu.com/questions/162391/how-do-i-fix-my-locale-issue diff --git a/docs/api/methods/deprecated-methods.rst b/docs/api/methods/deprecated-methods.rst --- a/docs/api/methods/deprecated-methods.rst +++ b/docs/api/methods/deprecated-methods.rst @@ -1,7 +1,7 @@ .. _deprecated-methods-ref: deprecated methods -================= +================== changeset_comment ----------------- diff --git a/docs/api/methods/gist-methods.rst b/docs/api/methods/gist-methods.rst --- a/docs/api/methods/gist-methods.rst +++ b/docs/api/methods/gist-methods.rst @@ -1,7 +1,7 @@ .. _gist-methods-ref: gist methods -================= +============ create_gist ----------- diff --git a/docs/api/methods/license-methods.rst b/docs/api/methods/license-methods.rst --- a/docs/api/methods/license-methods.rst +++ b/docs/api/methods/license-methods.rst @@ -1,10 +1,10 @@ .. _license-methods-ref: license methods -================= +=============== get_license_info (EE only) ----------------- +-------------------------- .. py:function:: get_license_info(apiuser) @@ -32,7 +32,7 @@ get_license_info (EE only) set_license_key (EE only) ---------------- +------------------------- .. py:function:: set_license_key(apiuser, key) diff --git a/docs/api/methods/pull-request-methods.rst b/docs/api/methods/pull-request-methods.rst --- a/docs/api/methods/pull-request-methods.rst +++ b/docs/api/methods/pull-request-methods.rst @@ -1,7 +1,7 @@ .. _pull-request-methods-ref: pull_request methods -================= +==================== close_pull_request ------------------ @@ -103,6 +103,10 @@ create_pull_request :type description: Optional(str) :param reviewers: Set the new pull request reviewers list. :type reviewers: Optional(list) + Accepts username strings or objects of the format: + { + 'username': 'nick', 'reasons': ['original author'] + } get_pull_request @@ -165,6 +169,15 @@ get_pull_request "commit_id": "", } }, + "merge": { + "clone_url": "", + "reference": + { + "name": "", + "type": "", + "commit_id": "", + } + }, "author": , "reviewers": [ ... @@ -241,6 +254,15 @@ get_pull_requests "commit_id": "", } }, + "merge": { + "clone_url": "", + "reference": + { + "name": "", + "type": "", + "commit_id": "", + } + }, "author": , "reviewers": [ ... @@ -284,7 +306,12 @@ merge_pull_request "executed": "", "failure_reason": "", "merge_commit_id": "", - "possible": "" + "possible": "", + "merge_ref": { + "commit_id": "", + "type": "", + "name": "" + } }, "error": null diff --git a/docs/api/methods/repo-group-methods.rst b/docs/api/methods/repo-group-methods.rst --- a/docs/api/methods/repo-group-methods.rst +++ b/docs/api/methods/repo-group-methods.rst @@ -1,24 +1,25 @@ .. _repo-group-methods-ref: repo_group methods -================= +================== create_repo_group ----------------- -.. py:function:: create_repo_group(apiuser, group_name, description=, owner=>, copy_permissions=) +.. py:function:: create_repo_group(apiuser, group_name, owner=>, description=, copy_permissions=) Creates a repository group. - * If the repository group name contains "/", all the required repository - groups will be created. + * If the repository group name contains "/", repository group will be + created inside a repository group or nested repository groups - For example "foo/bar/baz" will create |repo| groups "foo" and "bar" - (with "foo" as parent). It will also create the "baz" repository - with "bar" as |repo| group. + For example "foo/bar/group1" will create repository group called "group1" + inside group "foo/bar". You have to have permissions to access and + write to the last repository group ("bar" in this example) - This command can only be run using an |authtoken| with admin - permissions. + This command can only be run using an |authtoken| with at least + permissions to create repository groups, or admin permissions to + parent repository groups. :param apiuser: This is filled automatically from the |authtoken|. :type apiuser: AuthUser @@ -73,7 +74,7 @@ delete_repo_group id : result : { - 'msg': 'deleted repo group ID: + 'msg': 'deleted repo group ID: ' 'repo_group': null } error : null @@ -325,13 +326,22 @@ revoke_user_permission_from_repo_group update_repo_group ----------------- -.. py:function:: update_repo_group(apiuser, repogroupid, group_name=, description=, owner=>, parent=, enable_locking=) +.. py:function:: update_repo_group(apiuser, repogroupid, group_name=, description=, owner=>, enable_locking=) Updates repository group with the details given. This command can only be run using an |authtoken| with admin permissions. + * If the group_name name contains "/", repository group will be updated + accordingly with a repository group or nested repository groups + + For example repogroupid=group-test group_name="foo/bar/group-test" + will update repository group called "group-test" and place it + inside group "foo/bar". + You have to have permissions to access and write to the last repository + group ("bar" in this example) + :param apiuser: This is filled automatically from the |authtoken|. :type apiuser: AuthUser :param repogroupid: Set the ID of repository group. @@ -342,8 +352,6 @@ update_repo_group :type description: str :param owner: Set the |repo| group owner. :type owner: str - :param parent: Set the |repo| group parent. - :type parent: str or int :param enable_locking: Enable |repo| locking. The default is false. :type enable_locking: bool diff --git a/docs/api/methods/repo-methods.rst b/docs/api/methods/repo-methods.rst --- a/docs/api/methods/repo-methods.rst +++ b/docs/api/methods/repo-methods.rst @@ -1,7 +1,7 @@ .. _repo-methods-ref: repo methods -================= +============ add_field_to_repo ----------------- @@ -68,15 +68,16 @@ create_repo Creates a repository. - * If the repository name contains "/", all the required repository - groups will be created. + * If the repository name contains "/", repository will be created inside + a repository group or nested repository groups - For example "foo/bar/baz" will create |repo| groups "foo" and "bar" - (with "foo" as parent). It will also create the "baz" repository - with "bar" as |repo| group. + For example "foo/bar/repo1" will create |repo| called "repo1" inside + group "foo/bar". You have to have permissions to access and write to + the last repository group ("bar" in this example) This command can only be run using an |authtoken| with at least - write permissions to the |repo|. + permissions to create repositories, or write permissions to + parent repository groups. :param apiuser: This is filled automatically from the |authtoken|. :type apiuser: AuthUser @@ -88,9 +89,9 @@ create_repo :type owner: Optional(str) :param description: Set the repository description. :type description: Optional(str) - :param private: + :param private: set repository as private :type private: bool - :param clone_uri: + :param clone_uri: set clone_uri :type clone_uri: str :param landing_rev: : :type landing_rev: str @@ -125,7 +126,7 @@ create_repo id : result : null error : { - 'failed to create repository `` + 'failed to create repository ``' } @@ -164,25 +165,29 @@ delete_repo fork_repo --------- -.. py:function:: fork_repo(apiuser, repoid, fork_name, owner=>, description=, copy_permissions=, private=, landing_rev=) +.. py:function:: fork_repo(apiuser, repoid, fork_name, owner=>, description=, private=, clone_uri=, landing_rev=, copy_permissions=) Creates a fork of the specified |repo|. - * If using |RCE| with Celery this will immediately return a success - message, even though the fork will be created asynchronously. + * If the fork_name contains "/", fork will be created inside + a repository group or nested repository groups - This command can only be run using an |authtoken| with fork - permissions on the |repo|. + For example "foo/bar/fork-repo" will create fork called "fork-repo" + inside group "foo/bar". You have to have permissions to access and + write to the last repository group ("bar" in this example) + + This command can only be run using an |authtoken| with minimum + read permissions of the forked repo, create fork permissions for an user. :param apiuser: This is filled automatically from the |authtoken|. :type apiuser: AuthUser :param repoid: Set repository name or repository ID. :type repoid: str or int - :param fork_name: Set the fork name. + :param fork_name: Set the fork name, including it's repository group membership. :type fork_name: str :param owner: Set the fork owner. :type owner: str - :param description: Set the fork descripton. + :param description: Set the fork description. :type description: str :param copy_permissions: Copy permissions from parent |repo|. The default is False. @@ -729,7 +734,7 @@ lock id : result : null error : { - 'Error occurred locking repository `` + 'Error occurred locking repository ``' } @@ -923,24 +928,31 @@ strip update_repo ----------- -.. py:function:: update_repo(apiuser, repoid, name=, owner=>, group=, fork_of=, description=, private=, clone_uri=, landing_rev=, enable_statistics=, enable_locking=, enable_downloads=, fields=) +.. py:function:: update_repo(apiuser, repoid, repo_name=, owner=>, description=, private=, clone_uri=, landing_rev=, fork_of=, enable_statistics=, enable_locking=, enable_downloads=, fields=) Updates a repository with the given information. This command can only be run using an |authtoken| with at least - write permissions to the |repo|. + admin permissions to the |repo|. + + * If the repository name contains "/", repository will be updated + accordingly with a repository group or nested repository groups + + For example repoid=repo-test name="foo/bar/repo-test" will update |repo| + called "repo-test" and place it inside group "foo/bar". + You have to have permissions to access and write to the last repository + group ("bar" in this example) :param apiuser: This is filled automatically from the |authtoken|. :type apiuser: AuthUser :param repoid: repository name or repository ID. :type repoid: str or int - :param name: Update the |repo| name. - :type name: str + :param repo_name: Update the |repo| name, including the + repository group it's in. + :type repo_name: str :param owner: Set the |repo| owner. :type owner: str - :param group: Set the |repo| group the |repo| belongs to. - :type group: str - :param fork_of: Set the master |repo| name. + :param fork_of: Set the |repo| as fork of another |repo|. :type fork_of: str :param description: Update the |repo| description. :type description: str @@ -948,16 +960,13 @@ update_repo :type private: bool :param clone_uri: Update the |repo| clone URI. :type clone_uri: str - :param landing_rev: Set the |repo| landing revision. Default is - ``tip``. + :param landing_rev: Set the |repo| landing revision. Default is ``rev:tip``. :type landing_rev: str - :param enable_statistics: Enable statistics on the |repo|, - (True | False). + :param enable_statistics: Enable statistics on the |repo|, (True | False). :type enable_statistics: bool :param enable_locking: Enable |repo| locking. :type enable_locking: bool - :param enable_downloads: Enable downloads from the |repo|, - (True | False). + :param enable_downloads: Enable downloads from the |repo|, (True | False). :type enable_downloads: bool :param fields: Add extra fields to the |repo|. Use the following example format: ``field_key=field_val,field_key2=fieldval2``. diff --git a/docs/api/methods/server-methods.rst b/docs/api/methods/server-methods.rst --- a/docs/api/methods/server-methods.rst +++ b/docs/api/methods/server-methods.rst @@ -1,7 +1,7 @@ .. _server-methods-ref: server methods -================= +============== get_ip ------ diff --git a/docs/api/methods/user-group-methods.rst b/docs/api/methods/user-group-methods.rst --- a/docs/api/methods/user-group-methods.rst +++ b/docs/api/methods/user-group-methods.rst @@ -1,7 +1,7 @@ .. _user-group-methods-ref: user_group methods -================= +================== add_user_to_user_group ---------------------- diff --git a/docs/api/methods/user-methods.rst b/docs/api/methods/user-methods.rst --- a/docs/api/methods/user-methods.rst +++ b/docs/api/methods/user-methods.rst @@ -1,12 +1,12 @@ .. _user-methods-ref: user methods -================= +============ create_user ----------- -.. py:function:: create_user(apiuser, username, email, password=, firstname=, lastname=, active=, admin=, extern_name=, extern_type=, force_password_change=) +.. py:function:: create_user(apiuser, username, email, password=, firstname=, lastname=, active=, admin=, extern_name=, extern_type=, force_password_change=, create_personal_repo_group=) Creates a new user and returns the new user object. @@ -39,7 +39,8 @@ create_user :param force_password_change: Force the new user to change password on next login. :type force_password_change: Optional(``True`` | ``False``) - + :param create_personal_repo_group: Create personal repo group for this user + :type create_personal_repo_group: Optional(``True`` | ``False``) Example output: .. code-block:: bash @@ -163,6 +164,7 @@ get_user "usergroup.read", "hg.repogroup.create.false", "hg.create.none", + "hg.password_reset.enabled", "hg.extern_activate.manual", "hg.create.write_on_repogroup.false", "hg.usergroup.create.false", diff --git a/docs/contributing/api.rst b/docs/contributing/api.rst --- a/docs/contributing/api.rst +++ b/docs/contributing/api.rst @@ -1,7 +1,7 @@ -===== - API -===== +=================== +CONTRIBUTING TO API +=================== diff --git a/docs/contributing/checklist-pull-request.rst b/docs/contributing/checklist-pull-request.rst new file mode 100644 --- /dev/null +++ b/docs/contributing/checklist-pull-request.rst @@ -0,0 +1,17 @@ +.. _checklist-pull-request: + +======================= +Pull Request Checklists +======================= + + + +Checklists for Pull Request +=========================== + + +- Informative description +- Linear commit history +- Rebased on top of latest changes +- Add ticket references. eg fixes #123, references #123 etc. + diff --git a/docs/contributing/checklist-tickets.rst b/docs/contributing/checklist-tickets.rst --- a/docs/contributing/checklist-tickets.rst +++ b/docs/contributing/checklist-tickets.rst @@ -130,7 +130,7 @@ is a very small pencil which has to be c ticket. -.. figure:: images/redmine-description.png +.. 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/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 @@ -9,9 +9,6 @@ .. Avoid duplicating the quickstart instructions by importing the README file. -.. include:: ../../../acceptance_tests/README.rst - - Choices of technology and tools =============================== diff --git a/docs/default.nix b/docs/default.nix --- a/docs/default.nix +++ b/docs/default.nix @@ -88,10 +88,10 @@ let }; Sphinx = buildPythonPackage (rec { - name = "Sphinx-1.4.4"; + name = "Sphinx-1.4.8"; src = fetchurl { - url = "https://pypi.python.org/packages/20/a2/72f44c84f6c4115e3fef58d36d657ec311d80196eab9fd5ec7bcde76143b/${name}.tar.gz"; - md5 = "64ce2ec08d37ed56313a98232cbe2aee"; + url = "https://pypi.python.org/packages/1f/f6/e54a7aad73e35232356103771ae76306dadd8546b024c646fbe75135571c/${name}.tar.gz"; + md5 = "5ec718a4855917e149498bba91b74e67"; }; propagatedBuildInputs = [ docutils diff --git a/docs/images/redmine-description.png b/docs/images/redmine-description.png new file mode 100644 index 0000000000000000000000000000000000000000..cd473f66abd02ec5ff47ae2811bf81c345977fa8 GIT binary patch literal 17629 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 k_jZGb046VNVDHdf7#)iSHoOjh-#--