merged default branch into stable

This commit is contained in:
RhodeCode Admin 2024-02-22 09:56:13 +01:00
commit 32c32c445c
1001 changed files with 21498 additions and 31876 deletions

View file

@ -1,10 +1,17 @@
{
"presets": [
["env", {
"targets": {
"browsers": ["last 2 versions"]
[
"env",
{
"targets": {
"browsers": [
"last 2 versions"
]
}
}
}]
]
],
"plugins": ["transform-object-rest-spread"]
"plugins": [
"transform-object-rest-spread"
]
}

View file

@ -1,6 +1,5 @@
[bumpversion]
current_version = 4.27.1
current_version = 5.0.0
message = release: Bump version {current_version} to {new_version}
[bumpversion:file:rhodecode/VERSION]

View file

@ -1,4 +1,5 @@
syntax: glob
*.egg
*.egg-info
*.idea
@ -18,6 +19,7 @@ syntax: regexp
^\.pydevproject$
^\.coverage$
^\.cache.*$
^\.ruff_cache.*$
^\.rhodecode$
^rcextensions
@ -36,6 +38,7 @@ syntax: regexp
^junit\.xml$
^node_modules/
^node_binaries/
^package-lock.json
^pylint.log$
^rcextensions/
^result$
@ -53,6 +56,7 @@ syntax: regexp
^rhodecode_dev\.log$
^test\.db$
# ac-tests
^acceptance_tests/\.cache.*$
^acceptance_tests/externals

View file

@ -1,12 +1,12 @@
# top level files
include MANIFEST.in
include README.rst
include CHANGES.rst
include LICENSE.txt
include *.rst
include *.txt
include rhodecode/VERSION
# all python files inside packages
graft rhodecode
# docs
recursive-include docs *
@ -48,5 +48,10 @@ recursive-include rhodecode/public/js *
recursive-include rhodecode/templates *
# skip any tests files
recursive-exclude rhodecode/api/tests *
recursive-exclude rhodecode/tests *
recursive-exclude docs/_build *
recursive-exclude * __pycache__
recursive-exclude * *.py[co]
recursive-exclude * .*.sw[a-z]

182
Makefile
View file

@ -1,98 +1,192 @@
.DEFAULT_GOAL := help
# required for pushd to work..
SHELL = /bin/bash
# set by: PATH_TO_OUTDATED_PACKAGES=/some/path/outdated_packages.py
OUTDATED_PACKAGES = ${PATH_TO_OUTDATED_PACKAGES}
NODE_PATH=./node_modules
WEBPACK=./node_binaries/webpack
GRUNT=./node_binaries/grunt
.PHONY: clean
clean: ## full clean
## Cleanup compiled and cache py files
clean:
make test-clean
find . -type f \( -iname '*.c' -o -iname '*.pyc' -o -iname '*.so' -o -iname '*.orig' \) -exec rm '{}' ';'
find . -type d -name "build" -prune -exec rm -rf '{}' ';'
.PHONY: test
test: ## run test-clean and tests
## run test-clean and tests
test:
make test-clean
make test-only
.PHONY:test-clean
test-clean: ## run test-clean and tests
.PHONY: test-clean
## run test-clean and tests
test-clean:
rm -rf coverage.xml htmlcov junit.xml pylint.log result
find . -type d -name "__pycache__" -prune -exec rm -rf '{}' ';'
find . -type f \( -iname '.coverage.*' \) -exec rm '{}' ';'
.PHONY: test-only
test-only: ## run tests
## Run tests only without cleanup
test-only:
PYTHONHASHSEED=random \
py.test -x -vv -r xw -p no:sugar \
--cov=rhodecode --cov-report=term-missing --cov-report=html \
rhodecode
--cov-report=term-missing --cov-report=html \
--cov=rhodecode rhodecode
.PHONY: test-only-mysql
test-only-mysql: ## run tests against mysql
## run tests against mysql
test-only-mysql:
PYTHONHASHSEED=random \
py.test -x -vv -r xw -p no:sugar \
--cov=rhodecode --cov-report=term-missing --cov-report=html \
--cov-report=term-missing --cov-report=html \
--ini-config-override='{"app:main": {"sqlalchemy.db1.url": "mysql://root:qweqwe@localhost/rhodecode_test?charset=utf8"}}' \
rhodecode
--cov=rhodecode rhodecode
.PHONY: test-only-postgres
test-only-postgres: ## run tests against postgres
## run tests against postgres
test-only-postgres:
PYTHONHASHSEED=random \
py.test -x -vv -r xw -p no:sugar \
--cov=rhodecode --cov-report=term-missing --cov-report=html \
--cov-report=term-missing --cov-report=html \
--ini-config-override='{"app:main": {"sqlalchemy.db1.url": "postgresql://postgres:qweqwe@localhost/rhodecode_test"}}' \
rhodecode
--cov=rhodecode rhodecode
.PHONY: ruff-check
## run a ruff analysis
ruff-check:
ruff check --ignore F401 --ignore I001 --ignore E402 --ignore E501 --ignore F841 --exclude rhodecode/lib/dbmigrate --exclude .eggs --exclude .dev .
.PHONY: docs
docs: ## build docs
(cd docs; nix-build default.nix -o result; make clean html)
## build docs
docs:
(cd docs; docker run --rm -v $(PWD):/project --workdir=/project/docs sphinx-doc-build-rc make clean html)
.PHONY: docs-clean
docs-clean: ## Cleanup docs
(cd docs; make clean)
## Cleanup docs
docs-clean:
(cd docs; docker run --rm -v $(PWD):/project --workdir=/project/docs sphinx-doc-build-rc make clean)
.PHONY: docs-cleanup
docs-cleanup: ## Cleanup docs
(cd docs; make cleanup)
## Cleanup docs
docs-cleanup:
(cd docs; docker run --rm -v $(PWD):/project --workdir=/project/docs sphinx-doc-build-rc make cleanup)
.PHONY: web-build
web-build: ## Build static/js
NODE_PATH=$(NODE_PATH) $(GRUNT)
.PHONY: generate-pkgs
generate-pkgs: ## generate new python packages
nix-shell pkgs/shell-generate.nix --command "pip2nix generate --licenses"
## Build JS packages static/js
web-build:
docker run -it --rm -v $(PWD):/project --workdir=/project rhodecode/static-files-build:16 -c "npm install && /project/node_modules/.bin/grunt"
# run static file check
./rhodecode/tests/scripts/static-file-check.sh rhodecode/public/
rm -rf node_modules
.PHONY: pip-packages
pip-packages: ## show outdated packages
## Show outdated packages
pip-packages:
python ${OUTDATED_PACKAGES}
.PHONY: generate-js-pkgs
generate-js-pkgs: ## generate js packages
rm -rf node_modules && \
nix-shell pkgs/shell-generate.nix --command "node2nix --input package.json -o pkgs/node-packages.nix -e pkgs/node-env.nix -c pkgs/node-default.nix -d --flatten --nodejs-8" && \
sed -i -e 's/http:\/\//https:\/\//g' pkgs/node-packages.nix
.PHONY: build
## Build sdist/egg
build:
python -m build
.PHONY: generate-license-meta
generate-license-meta: ## Generate license metadata
nix-build pkgs/license-generate.nix -o result-license && \
cat result-license/licenses.json | python -m json.tool > rhodecode/config/licenses.json
.PHONY: dev-sh
## make dev-sh
dev-sh:
sudo echo "deb [trusted=yes] https://apt.fury.io/rsteube/ /" | sudo tee -a "/etc/apt/sources.list.d/fury.list"
sudo apt-get update
sudo apt-get install -y zsh carapace-bin
rm -rf /home/rhodecode/.oh-my-zsh
curl https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh | sh
echo "source <(carapace _carapace)" > /home/rhodecode/.zsrc
PROMPT='%(?.%F{green}√.%F{red}?%?)%f %B%F{240}%1~%f%b %# ' zsh
.PHONY: help
help:
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-24s\033[0m %s\n", $$1, $$2}'
.PHONY: dev-cleanup
## Cleanup: pip freeze | grep -v "^-e" | grep -v "@" | xargs pip uninstall -y
dev-cleanup:
pip freeze | grep -v "^-e" | grep -v "@" | xargs pip uninstall -y
rm -rf /tmp/*
.PHONY: dev-env
## make dev-env based on the requirements files and install develop of packages
dev-env:
pip install build virtualenv
pushd ../rhodecode-vcsserver/ && make dev-env && popd
pip wheel --wheel-dir=/home/rhodecode/.cache/pip/wheels -r requirements.txt -r requirements_rc_tools.txt -r requirements_test.txt -r requirements_debug.txt
pip install --no-index --find-links=/home/rhodecode/.cache/pip/wheels -r requirements.txt -r requirements_rc_tools.txt -r requirements_test.txt -r requirements_debug.txt
pip install -e .
.PHONY: sh
## shortcut for make dev-sh dev-env
sh:
make dev-env
make dev-sh
.PHONY: dev-srv
## run develop server instance, docker exec -it $(docker ps -q --filter 'name=dev-enterprise-ce') /bin/bash
dev-srv:
pserve --reload .dev/dev.ini
.PHONY: dev-srv-g
## run gunicorn multi process workers
dev-srv-g:
gunicorn --paste .dev/dev.ini --bind=0.0.0.0:10020 --config=.dev/gunicorn_config.py --timeout=120 --reload
# Default command on calling make
.DEFAULT_GOAL := show-help
.PHONY: show-help
show-help:
@echo "$$(tput bold)Available rules:$$(tput sgr0)"
@echo
@sed -n -e "/^## / { \
h; \
s/.*//; \
:doc" \
-e "H; \
n; \
s/^## //; \
t doc" \
-e "s/:.*//; \
G; \
s/\\n## /---/; \
s/\\n/ /g; \
p; \
}" ${MAKEFILE_LIST} \
| LC_ALL='C' sort --ignore-case \
| awk -F '---' \
-v ncol=$$(tput cols) \
-v indent=19 \
-v col_on="$$(tput setaf 6)" \
-v col_off="$$(tput sgr0)" \
'{ \
printf "%s%*s%s ", col_on, -indent, $$1, col_off; \
n = split($$2, words, " "); \
line_length = ncol - indent; \
for (i = 1; i <= n; i++) { \
line_length -= length(words[i]) + 1; \
if (line_length <= 0) { \
line_length = ncol - indent - length(words[i]) - 1; \
printf "\n%*s ", -indent, " "; \
} \
printf "%s ", words[i]; \
} \
printf "\n"; \
}'

View file

@ -1,4 +1,3 @@
## -*- coding: utf-8 -*-
; #########################################
; RHODECODE COMMUNITY EDITION CONFIGURATION
@ -27,9 +26,10 @@ debug = true
#smtp_use_ssl = true
[server:main]
; COMMON HOST/IP CONFIG
; COMMON HOST/IP CONFIG, This applies mostly to develop setup,
; Host port for gunicorn are controlled by gunicorn_conf.py
host = 127.0.0.1
port = 5000
port = 10020
; ##################################################
; WAITRESS WSGI SERVER - Recommended for Development
@ -53,82 +53,11 @@ asyncore_use_poll = true
; GUNICORN APPLICATION SERVER
; ###########################
; run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
; run with gunicorn --paste rhodecode.ini --config gunicorn_conf.py
; Module to use, this setting shouldn't be changed
#use = egg:gunicorn#main
; Sets the number of process workers. More workers means more concurrent connections
; RhodeCode can handle at the same time. Each additional worker also it increases
; memory usage as each has it's own set of caches.
; Recommended value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers, but no more
; than 8-10 unless for really big deployments .e.g 700-1000 users.
; `instance_id = *` must be set in the [app:main] section below (which is the default)
; when using more than 1 worker.
#workers = 2
; Gunicorn access log level
#loglevel = info
; Process name visible in process list
#proc_name = rhodecode
; Type of worker class, one of `sync`, `gevent`
; Recommended type is `gevent`
#worker_class = gevent
; The maximum number of simultaneous clients. Valid only for gevent
#worker_connections = 10
; Max number of requests that worker will handle before being gracefully restarted.
; Prevents memory leaks, jitter adds variability so not all workers are restarted at once.
#max_requests = 1000
#max_requests_jitter = 30
; Amount of time a worker can spend with handling a request before it
; gets killed and restarted. By default set to 21600 (6hrs)
; Examples: 1800 (30min), 3600 (1hr), 7200 (2hr), 43200 (12h)
#timeout = 21600
; The maximum size of HTTP request line in bytes.
; 0 for unlimited
#limit_request_line = 0
; Limit the number of HTTP headers fields in a request.
; By default this value is 100 and can't be larger than 32768.
#limit_request_fields = 32768
; Limit the allowed size of an HTTP request header field.
; Value is a positive number or 0.
; Setting it to 0 will allow unlimited header field sizes.
#limit_request_field_size = 0
; Timeout for graceful workers restart.
; After receiving a restart signal, workers have this much time to finish
; serving requests. Workers still alive after the timeout (starting from the
; receipt of the restart signal) are force killed.
; Examples: 1800 (30min), 3600 (1hr), 7200 (2hr), 43200 (12h)
#graceful_timeout = 3600
# The number of seconds to wait for requests on a Keep-Alive connection.
# Generally set in the 1-5 seconds range.
#keepalive = 2
; Maximum memory usage that each worker can use before it will receive a
; graceful restart signal 0 = memory monitoring is disabled
; Examples: 268435456 (256MB), 536870912 (512MB)
; 1073741824 (1GB), 2147483648 (2GB), 4294967296 (4GB)
#memory_max_usage = 0
; How often in seconds to check for memory usage for each gunicorn worker
#memory_usage_check_interval = 60
; Threshold value for which we don't recycle worker if GarbageCollection
; frees up enough resources. Before each restart we try to run GC on worker
; in case we get enough free memory after that, restart will not happen.
#memory_usage_recovery_threshold = 0.8
; Prefix middleware for RhodeCode.
; recommended when using proxy setup.
; allows to set RhodeCode under a prefix in server.
@ -143,8 +72,16 @@ prefix = /
[app:main]
; The %(here)s variable will be replaced with the absolute path of parent directory
; of this file
; In addition ENVIRONMENT variables usage is possible, e.g
; sqlalchemy.db1.url = {ENV_RC_DB_URL}
; Each option in the app:main can be override by an environmental variable
;
;To override an option:
;
;RC_<KeyName>
;Everything should be uppercase, . and - should be replaced by _.
;For example, if you have these configuration settings:
;rc_cache.repo_object.backend = foo
;can be overridden by
;export RC_CACHE_REPO_OBJECT_BACKEND=foo
use = egg:rhodecode-enterprise-ce
@ -211,12 +148,6 @@ lang = en
; Settings this to true could lead to very long startup time.
startup.import_repos = false
; Uncomment and set this path to use archive download cache.
; Once enabled, generated archives will be cached at this location
; and served from the cache during subsequent requests for the same archive of
; the repository.
#archive_cache_dir = /tmp/tarballcache
; URL at which the application is running. This is used for Bootstrapping
; requests in context when no web request is available. Used in ishell, or
; SSH calls. Set this for events to receive proper url for SSH calls.
@ -370,23 +301,43 @@ file_store.backend = local
; path to store the uploaded binaries
file_store.storage_path = %(here)s/data/file_store
; Uncomment and set this path to control settings for archive download cache.
; Generated repo archives will be cached at this location
; and served from the cache during subsequent requests for the same archive of
; the repository. This path is important to be shared across filesystems and with
; RhodeCode and vcsserver
; Default is $cache_dir/archive_cache if not set
archive_cache.store_dir = %(here)s/data/archive_cache
; The limit in GB sets how much data we cache before recycling last used, defaults to 10 gb
archive_cache.cache_size_gb = 10
; By default cache uses sharding technique, this specifies how many shards are there
archive_cache.cache_shards = 10
; #############
; CELERY CONFIG
; #############
; manually run celery: /path/to/celery worker -E --beat --app rhodecode.lib.celerylib.loader --scheduler rhodecode.lib.celerylib.scheduler.RcScheduler --loglevel DEBUG --ini /path/to/rhodecode.ini
; manually run celery: /path/to/celery worker --task-events --beat --app rhodecode.lib.celerylib.loader --scheduler rhodecode.lib.celerylib.scheduler.RcScheduler --loglevel DEBUG --ini /path/to/rhodecode.ini
use_celery = false
; path to store schedule database
#celerybeat-schedule.path =
; connection url to the message broker (default redis)
celery.broker_url = redis://localhost:6379/8
celery.broker_url = redis://redis:6379/8
; results backend to get results for (default redis)
celery.result_backend = redis://redis:6379/8
; rabbitmq example
#celery.broker_url = amqp://rabbitmq:qweqwe@localhost:5672/rabbitmqhost
; maximum tasks to execute before worker restart
celery.max_tasks_per_child = 100
celery.max_tasks_per_child = 20
; tasks will never be sent to the queue, but executed locally instead.
celery.task_always_eager = false
@ -418,13 +369,42 @@ rc_cache.cache_repo_longterm.expiration_time = 2592000
rc_cache.cache_repo_longterm.max_size = 10000
; *********************************************
; `cache_general` cache for general purpose use
; for simplicity use rc.file_namespace backend,
; for performance and scale use rc.redis
; *********************************************
rc_cache.cache_general.backend = dogpile.cache.rc.file_namespace
rc_cache.cache_general.expiration_time = 43200
; file cache store path. Defaults to `cache_dir =` value or tempdir if both values are not set
#rc_cache.cache_general.arguments.filename = /tmp/cache_general_db
; alternative `cache_general` redis backend with distributed lock
#rc_cache.cache_general.backend = dogpile.cache.rc.redis
#rc_cache.cache_general.expiration_time = 300
; redis_expiration_time needs to be greater then expiration_time
#rc_cache.cache_general.arguments.redis_expiration_time = 7200
#rc_cache.cache_general.arguments.host = localhost
#rc_cache.cache_general.arguments.port = 6379
#rc_cache.cache_general.arguments.db = 0
#rc_cache.cache_general.arguments.socket_timeout = 30
; more Redis options: https://dogpilecache.sqlalchemy.org/en/latest/api.html#redis-backends
#rc_cache.cache_general.arguments.distributed_lock = true
; auto-renew lock to prevent stale locks, slower but safer. Use only if problems happen
#rc_cache.cache_general.arguments.lock_auto_renewal = true
; *************************************************
; `cache_perms` cache for permission tree, auth TTL
; for simplicity use rc.file_namespace backend,
; for performance and scale use rc.redis
; *************************************************
rc_cache.cache_perms.backend = dogpile.cache.rc.file_namespace
rc_cache.cache_perms.expiration_time = 300
rc_cache.cache_perms.expiration_time = 3600
; file cache store path. Defaults to `cache_dir =` value or tempdir if both values are not set
#rc_cache.cache_perms.arguments.filename = /tmp/cache_perms.db
#rc_cache.cache_perms.arguments.filename = /tmp/cache_perms_db
; alternative `cache_perms` redis backend with distributed lock
#rc_cache.cache_perms.backend = dogpile.cache.rc.redis
@ -440,14 +420,18 @@ rc_cache.cache_perms.expiration_time = 300
; more Redis options: https://dogpilecache.sqlalchemy.org/en/latest/api.html#redis-backends
#rc_cache.cache_perms.arguments.distributed_lock = true
; auto-renew lock to prevent stale locks, slower but safer. Use only if problems happen
#rc_cache.cache_perms.arguments.lock_auto_renewal = true
; ***************************************************
; `cache_repo` cache for file tree, Readme, RSS FEEDS
; for simplicity use rc.file_namespace backend,
; for performance and scale use rc.redis
; ***************************************************
rc_cache.cache_repo.backend = dogpile.cache.rc.file_namespace
rc_cache.cache_repo.expiration_time = 2592000
; file cache store path. Defaults to `cache_dir =` value or tempdir if both values are not set
#rc_cache.cache_repo.arguments.filename = /tmp/cache_repo.db
#rc_cache.cache_repo.arguments.filename = /tmp/cache_repo_db
; alternative `cache_repo` redis backend with distributed lock
#rc_cache.cache_repo.backend = dogpile.cache.rc.redis
@ -463,14 +447,16 @@ rc_cache.cache_repo.expiration_time = 2592000
; more Redis options: https://dogpilecache.sqlalchemy.org/en/latest/api.html#redis-backends
#rc_cache.cache_repo.arguments.distributed_lock = true
; auto-renew lock to prevent stale locks, slower but safer. Use only if problems happen
#rc_cache.cache_repo.arguments.lock_auto_renewal = true
; ##############
; BEAKER SESSION
; ##############
; beaker.session.type is type of storage options for the logged users sessions. Current allowed
; types are file, ext:redis, ext:database, ext:memcached, and memory (default if not specified).
; Fastest ones are Redis and ext:database
; types are file, ext:redis, ext:database, ext:memcached
; Fastest ones are ext:redis and ext:database, DO NOT use memory type for session
beaker.session.type = file
beaker.session.data_dir = %(here)s/data/sessions
@ -565,10 +551,12 @@ sqlalchemy.db1.echo = false
; recycle the connections after this amount of seconds
sqlalchemy.db1.pool_recycle = 3600
sqlalchemy.db1.convert_unicode = true
; the number of connections to keep open inside the connection pool.
; 0 indicates no limit
; the general calculus with gevent is:
; if your system allows 500 concurrent greenlets (max_connections) that all do database access,
; then increase pool size + max overflow so that they add up to 500.
#sqlalchemy.db1.pool_size = 5
; The number of connections to allow in connection pool "overflow", that is
@ -599,9 +587,10 @@ vcs.scm_app_implementation = http
; `http` - use http-rpc backend (default)
vcs.hooks.protocol = http
; Host on which this instance is listening for hooks. If vcsserver is in other location
; this should be adjusted.
vcs.hooks.host = 127.0.0.1
; Host on which this instance is listening for hooks. vcsserver will call this host to pull/push hooks so it should be
; accessible via network.
; Use vcs.hooks.host = "*" to bind to current hostname (for Docker)
vcs.hooks.host = *
; Start VCSServer with this instance as a subprocess, useful for development
vcs.start_server = false
@ -620,6 +609,9 @@ vcs.connection_timeout = 3600
; Legacy available options are: pre-1.4-compatible, pre-1.5-compatible, pre-1.6-compatible, pre-1.8-compatible, pre-1.9-compatible
#vcs.svn.compatible_version = 1.8
; Cache flag to cache vcsserver remote calls locally
; It uses cache_region `cache_repo`
vcs.methods.cache = true
; ####################################################
; Subversion proxy support (mod_dav_svn)
@ -702,55 +694,74 @@ ssh.enable_ui_key_generator = true
; http://appenlight.rhodecode.com for details how to obtain an account
; Appenlight integration enabled
appenlight = false
#appenlight = false
appenlight.server_url = https://api.appenlight.com
appenlight.api_key = YOUR_API_KEY
#appenlight.server_url = https://api.appenlight.com
#appenlight.api_key = YOUR_API_KEY
#appenlight.transport_config = https://api.appenlight.com?threaded=1&timeout=5
; used for JS client
appenlight.api_public_key = YOUR_API_PUBLIC_KEY
#appenlight.api_public_key = YOUR_API_PUBLIC_KEY
; TWEAK AMOUNT OF INFO SENT HERE
; enables 404 error logging (default False)
appenlight.report_404 = false
#appenlight.report_404 = false
; time in seconds after request is considered being slow (default 1)
appenlight.slow_request_time = 1
#appenlight.slow_request_time = 1
; record slow requests in application
; (needs to be enabled for slow datastore recording and time tracking)
appenlight.slow_requests = true
#appenlight.slow_requests = true
; enable hooking to application loggers
appenlight.logging = true
#appenlight.logging = true
; minimum log level for log capture
appenlight.logging.level = WARNING
#ppenlight.logging.level = WARNING
; send logs only from erroneous/slow requests
; (saves API quota for intensive logging)
appenlight.logging_on_error = false
#appenlight.logging_on_error = false
; list of additional keywords that should be grabbed from environ object
; can be string with comma separated list of words in lowercase
; (by default client will always send following info:
; 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
; start with HTTP* this list be extended with additional keywords here
appenlight.environ_keys_whitelist =
#appenlight.environ_keys_whitelist =
; list of keywords that should be blanked from request object
; can be string with comma separated list of words in lowercase
; (by default client will always blank keys that contain following words
; 'password', 'passwd', 'pwd', 'auth_tkt', 'secret', 'csrf'
; this list be extended with additional keywords set here
appenlight.request_keys_blacklist =
#appenlight.request_keys_blacklist =
; list of namespaces that should be ignores when gathering log entries
; can be string with comma separated list of namespaces
; (by default the client ignores own entries: appenlight_client.client)
appenlight.log_namespace_blacklist =
#appenlight.log_namespace_blacklist =
; Statsd client config, this is used to send metrics to statsd
; We recommend setting statsd_exported and scrape them using Prometheus
#statsd.enabled = false
#statsd.statsd_host = 0.0.0.0
#statsd.statsd_port = 8125
#statsd.statsd_prefix =
#statsd.statsd_ipv6 = false
; configure logging automatically at server startup set to false
; to use the below custom logging config.
; RC_LOGGING_FORMATTER
; RC_LOGGING_LEVEL
; env variables can control the settings for logging in case of autoconfigure
#logging.autoconfigure = true
; specify your own custom logging config file to configure logging
#logging.logging_conf_file = /path/to/custom_logging.ini
; Dummy marker to add new entries after.
; Add any custom entries below. Please don't remove this marker.
@ -760,6 +771,7 @@ custom.conf = 1
; #####################
; LOGGING CONFIGURATION
; #####################
[loggers]
keys = root, sqlalchemy, beaker, celery, rhodecode, ssh_wrapper
@ -767,7 +779,7 @@ keys = root, sqlalchemy, beaker, celery, rhodecode, ssh_wrapper
keys = console, console_sql
[formatters]
keys = generic, color_formatter, color_formatter_sql
keys = generic, json, color_formatter, color_formatter_sql
; #######
; LOGGERS
@ -814,6 +826,8 @@ qualname = celery
class = StreamHandler
args = (sys.stderr, )
level = DEBUG
; To enable JSON formatted logs replace 'generic/color_formatter' with 'json'
; This allows sending properly formatted logs to grafana loki or elasticsearch
formatter = color_formatter
[handler_console_sql]
@ -823,6 +837,8 @@ formatter = color_formatter
class = StreamHandler
args = (sys.stderr, )
level = WARN
; To enable JSON formatted logs replace 'generic/color_formatter_sql' with 'json'
; This allows sending properly formatted logs to grafana loki or elasticsearch
formatter = color_formatter_sql
; ##########
@ -843,3 +859,7 @@ datefmt = %Y-%m-%d %H:%M:%S
class = rhodecode.lib.logging_formatter.ColorFormatterSql
format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %Y-%m-%d %H:%M:%S
[formatter_json]
format = %(timestamp)s %(levelname)s %(name)s %(message)s %(req_id)s
class = rhodecode.lib._vendor.jsonlogger.JsonFormatter

View file

@ -11,6 +11,8 @@ import time
import threading
import traceback
import random
import socket
import dataclasses
from gunicorn.glogging import Logger
@ -18,8 +20,14 @@ def get_workers():
import multiprocessing
return multiprocessing.cpu_count() * 2 + 1
# GLOBAL
bind = "127.0.0.1:10020"
# Error logging output for gunicorn (-) is stdout
errorlog = '-'
# Access logging output for gunicorn (-) is stdout
accesslog = '-'
@ -29,13 +37,113 @@ accesslog = '-'
worker_tmp_dir = None
tmp_upload_dir = None
# Custom log format
access_log_format = (
'%(t)s %(p)s INFO [GNCRN] %(h)-15s rqt:%(L)s %(s)s %(b)-6s "%(m)s:%(U)s %(q)s" usr:%(u)s "%(f)s" "%(a)s"')
# use re-use port logic
#reuse_port = True
# self adjust workers based on CPU count
# Custom log format
#access_log_format = (
# '%(t)s %(p)s INFO [GNCRN] %(h)-15s rqt:%(L)s %(s)s %(b)-6s "%(m)s:%(U)s %(q)s" usr:%(u)s "%(f)s" "%(a)s"')
# loki format for easier parsing in grafana
access_log_format = (
'time="%(t)s" pid=%(p)s level="INFO" type="[GNCRN]" ip="%(h)-15s" rqt="%(L)s" response_code="%(s)s" response_bytes="%(b)-6s" uri="%(m)s:%(U)s %(q)s" user=":%(u)s" user_agent="%(a)s"')
# self adjust workers based on CPU count, to use maximum of CPU and not overquota the resources
# workers = get_workers()
# Gunicorn access log level
loglevel = 'info'
# Process name visible in a process list
proc_name = 'rhodecode_enterprise'
# Type of worker class, one of `sync`, `gevent` or `gthread`
# currently `sync` is the only option allowed for vcsserver and for rhodecode all of 3 are allowed
# gevent:
# In this case, the maximum number of concurrent requests is (N workers * X worker_connections)
# e.g. workers =3 worker_connections=10 = 3*10, 30 concurrent requests can be handled
# gthread:
# In this case, the maximum number of concurrent requests is (N workers * X threads)
# e.g. workers = 3 threads=3 = 3*3, 9 concurrent requests can be handled
worker_class = 'gthread'
# Sets the number of process workers. More workers means more concurrent connections
# RhodeCode can handle at the same time. Each additional worker also it increases
# memory usage as each has its own set of caches.
# The Recommended value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers, but no more
# than 8-10 unless for huge deployments .e.g 700-1000 users.
# `instance_id = *` must be set in the [app:main] section below (which is the default)
# when using more than 1 worker.
workers = 2
# Threads numbers for worker class gthread
threads = 1
# The maximum number of simultaneous clients. Valid only for gevent
# In this case, the maximum number of concurrent requests is (N workers * X worker_connections)
# e.g workers =3 worker_connections=10 = 3*10, 30 concurrent requests can be handled
worker_connections = 10
# Max number of requests that worker will handle before being gracefully restarted.
# Prevents memory leaks, jitter adds variability so not all workers are restarted at once.
max_requests = 2000
max_requests_jitter = int(max_requests * 0.2) # 20% of max_requests
# The maximum number of pending connections.
# Exceeding this number results in the client getting an error when attempting to connect.
backlog = 64
# The Amount of time a worker can spend with handling a request before it
# gets killed and restarted. By default, set to 21600 (6hrs)
# Examples: 1800 (30min), 3600 (1hr), 7200 (2hr), 43200 (12h)
timeout = 21600
# The maximum size of HTTP request line in bytes.
# 0 for unlimited
limit_request_line = 0
# Limit the number of HTTP headers fields in a request.
# By default this value is 100 and can't be larger than 32768.
limit_request_fields = 32768
# Limit the allowed size of an HTTP request header field.
# Value is a positive number or 0.
# Setting it to 0 will allow unlimited header field sizes.
limit_request_field_size = 0
# Timeout for graceful workers restart.
# After receiving a restart signal, workers have this much time to finish
# serving requests. Workers still alive after the timeout (starting from the
# receipt of the restart signal) are force killed.
# Examples: 1800 (30min), 3600 (1hr), 7200 (2hr), 43200 (12h)
graceful_timeout = 21600
# The number of seconds to wait for requests on a Keep-Alive connection.
# Generally set in the 1-5 seconds range.
keepalive = 2
# Maximum memory usage that each worker can use before it will receive a
# graceful restart signal 0 = memory monitoring is disabled
# Examples: 268435456 (256MB), 536870912 (512MB)
# 1073741824 (1GB), 2147483648 (2GB), 4294967296 (4GB)
# Dynamic formula 1024 * 1024 * 256 == 256MBs
memory_max_usage = 0
# How often in seconds to check for memory usage for each gunicorn worker
memory_usage_check_interval = 60
# Threshold value for which we don't recycle worker if GarbageCollection
# frees up enough resources. Before each restart, we try to run GC on worker
# in case we get enough free memory after that; restart will not happen.
memory_usage_recovery_threshold = 0.8
@dataclasses.dataclass
class MemoryCheckConfig:
max_usage: int
check_interval: int
recovery_threshold: float
def _get_process_rss(pid=None):
try:
@ -50,11 +158,8 @@ def _get_process_rss(pid=None):
def _get_config(ini_path):
import configparser
try:
import configparser
except ImportError:
import ConfigParser as configparser
try:
config = configparser.RawConfigParser()
config.read(ini_path)
@ -63,8 +168,40 @@ def _get_config(ini_path):
return None
def _time_with_offset(memory_usage_check_interval):
return time.time() - random.randint(0, memory_usage_check_interval/2.0)
def get_memory_usage_params(config=None):
# memory spec defaults
_memory_max_usage = memory_max_usage
_memory_usage_check_interval = memory_usage_check_interval
_memory_usage_recovery_threshold = memory_usage_recovery_threshold
if config:
ini_path = os.path.abspath(config)
conf = _get_config(ini_path)
section = 'server:main'
if conf and conf.has_section(section):
if conf.has_option(section, 'memory_max_usage'):
_memory_max_usage = conf.getint(section, 'memory_max_usage')
if conf.has_option(section, 'memory_usage_check_interval'):
_memory_usage_check_interval = conf.getint(section, 'memory_usage_check_interval')
if conf.has_option(section, 'memory_usage_recovery_threshold'):
_memory_usage_recovery_threshold = conf.getfloat(section, 'memory_usage_recovery_threshold')
_memory_max_usage = int(os.environ.get('RC_GUNICORN_MEMORY_MAX_USAGE', '')
or _memory_max_usage)
_memory_usage_check_interval = int(os.environ.get('RC_GUNICORN_MEMORY_USAGE_CHECK_INTERVAL', '')
or _memory_usage_check_interval)
_memory_usage_recovery_threshold = float(os.environ.get('RC_GUNICORN_MEMORY_USAGE_RECOVERY_THRESHOLD', '')
or _memory_usage_recovery_threshold)
return MemoryCheckConfig(_memory_max_usage, _memory_usage_check_interval, _memory_usage_recovery_threshold)
def _time_with_offset(check_interval):
return time.time() - random.randint(0, check_interval/2.0)
def pre_fork(server, worker):
@ -73,39 +210,27 @@ def pre_fork(server, worker):
def post_fork(server, worker):
# memory spec defaults
_memory_max_usage = 0
_memory_usage_check_interval = 60
_memory_usage_recovery_threshold = 0.8
memory_conf = get_memory_usage_params()
_memory_max_usage = memory_conf.max_usage
_memory_usage_check_interval = memory_conf.check_interval
_memory_usage_recovery_threshold = memory_conf.recovery_threshold
ini_path = os.path.abspath(server.cfg.paste)
conf = _get_config(ini_path)
section = 'server:main'
if conf and conf.has_section(section):
if conf.has_option(section, 'memory_max_usage'):
_memory_max_usage = conf.getint(section, 'memory_max_usage')
if conf.has_option(section, 'memory_usage_check_interval'):
_memory_usage_check_interval = conf.getint(section, 'memory_usage_check_interval')
if conf.has_option(section, 'memory_usage_recovery_threshold'):
_memory_usage_recovery_threshold = conf.getfloat(section, 'memory_usage_recovery_threshold')
worker._memory_max_usage = _memory_max_usage
worker._memory_usage_check_interval = _memory_usage_check_interval
worker._memory_usage_recovery_threshold = _memory_usage_recovery_threshold
worker._memory_max_usage = int(os.environ.get('RC_GUNICORN_MEMORY_MAX_USAGE', '')
or _memory_max_usage)
worker._memory_usage_check_interval = int(os.environ.get('RC_GUNICORN_MEMORY_USAGE_CHECK_INTERVAL', '')
or _memory_usage_check_interval)
worker._memory_usage_recovery_threshold = float(os.environ.get('RC_GUNICORN_MEMORY_USAGE_RECOVERY_THRESHOLD', '')
or _memory_usage_recovery_threshold)
# register memory last check time, with some random offset so we don't recycle all
# at once
worker._last_memory_check_time = _time_with_offset(_memory_usage_check_interval)
if _memory_max_usage:
server.log.info("[%-10s] WORKER spawned with max memory set at %s", worker.pid,
server.log.info("pid=[%-10s] WORKER spawned with max memory set at %s", worker.pid,
_format_data_size(_memory_max_usage))
else:
server.log.info("[%-10s] WORKER spawned", worker.pid)
server.log.info("pid=[%-10s] WORKER spawned", worker.pid)
def pre_exec(server):
@ -115,6 +240,9 @@ def pre_exec(server):
def on_starting(server):
server_lbl = '{} {}'.format(server.proc_name, server.address)
server.log.info("Server %s is starting.", server_lbl)
server.log.info('Config:')
server.log.info(f"\n{server.cfg}")
server.log.info(get_memory_usage_params())
def when_ready(server):
@ -174,42 +302,45 @@ def _format_data_size(size, unit="B", precision=1, binary=True):
def _check_memory_usage(worker):
memory_max_usage = worker._memory_max_usage
if not memory_max_usage:
_memory_max_usage = worker._memory_max_usage
if not _memory_max_usage:
return
memory_usage_check_interval = worker._memory_usage_check_interval
memory_usage_recovery_threshold = memory_max_usage * worker._memory_usage_recovery_threshold
_memory_usage_check_interval = worker._memory_usage_check_interval
_memory_usage_recovery_threshold = memory_max_usage * worker._memory_usage_recovery_threshold
elapsed = time.time() - worker._last_memory_check_time
if elapsed > memory_usage_check_interval:
if elapsed > _memory_usage_check_interval:
mem_usage = _get_process_rss()
if mem_usage and mem_usage > memory_max_usage:
if mem_usage and mem_usage > _memory_max_usage:
worker.log.info(
"memory usage %s > %s, forcing gc",
_format_data_size(mem_usage), _format_data_size(memory_max_usage))
_format_data_size(mem_usage), _format_data_size(_memory_max_usage))
# Try to clean it up by forcing a full collection.
gc.collect()
mem_usage = _get_process_rss()
if mem_usage > memory_usage_recovery_threshold:
if mem_usage > _memory_usage_recovery_threshold:
# Didn't clean up enough, we'll have to terminate.
worker.log.warning(
"memory usage %s > %s after gc, quitting",
_format_data_size(mem_usage), _format_data_size(memory_max_usage))
_format_data_size(mem_usage), _format_data_size(_memory_max_usage))
# This will cause worker to auto-restart itself
worker.alive = False
worker._last_memory_check_time = time.time()
def worker_int(worker):
worker.log.info("[%-10s] worker received INT or QUIT signal", worker.pid)
worker.log.info("pid=[%-10s] worker received INT or QUIT signal", worker.pid)
# get traceback info, when a worker crashes
def get_thread_id(t_id):
id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
return id2name.get(t_id, "unknown_thread_id")
# get traceback info, on worker crash
id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
code = []
for thread_id, stack in sys._current_frames().items():
for thread_id, stack in sys._current_frames().items(): # noqa
code.append(
"\n# Thread: %s(%d)" % (id2name.get(thread_id, ""), thread_id))
"\n# Thread: %s(%d)" % (get_thread_id(thread_id), thread_id))
for fname, lineno, name, line in traceback.extract_stack(stack):
code.append('File: "%s", line %d, in %s' % (fname, lineno, name))
if line:
@ -218,15 +349,15 @@ def worker_int(worker):
def worker_abort(worker):
worker.log.info("[%-10s] worker received SIGABRT signal", worker.pid)
worker.log.info("pid=[%-10s] worker received SIGABRT signal", worker.pid)
def worker_exit(server, worker):
worker.log.info("[%-10s] worker exit", worker.pid)
worker.log.info("pid=[%-10s] worker exit", worker.pid)
def child_exit(server, worker):
worker.log.info("[%-10s] worker child exit", worker.pid)
worker.log.info("pid=[%-10s] worker child exit", worker.pid)
def pre_request(worker, req):
@ -245,6 +376,76 @@ def post_request(worker, req, environ, resp):
_check_memory_usage(worker)
def _filter_proxy(ip):
"""
Passed in IP addresses in HEADERS can be in a special format of multiple
ips. Those comma separated IPs are passed from various proxies in the
chain of request processing. The left-most being the original client.
We only care about the first IP which came from the org. client.
:param ip: ip string from headers
"""
if ',' in ip:
_ips = ip.split(',')
_first_ip = _ips[0].strip()
return _first_ip
return ip
def _filter_port(ip):
"""
Removes a port from ip, there are 4 main cases to handle here.
- ipv4 eg. 127.0.0.1
- ipv6 eg. ::1
- ipv4+port eg. 127.0.0.1:8080
- ipv6+port eg. [::1]:8080
:param ip:
"""
def is_ipv6(ip_addr):
if hasattr(socket, 'inet_pton'):
try:
socket.inet_pton(socket.AF_INET6, ip_addr)
except socket.error:
return False
else:
return False
return True
if ':' not in ip: # must be ipv4 pure ip
return ip
if '[' in ip and ']' in ip: # ipv6 with port
return ip.split(']')[0][1:].lower()
# must be ipv6 or ipv4 with port
if is_ipv6(ip):
return ip
else:
ip, _port = ip.split(':')[:2] # means ipv4+port
return ip
def get_ip_addr(environ):
proxy_key = 'HTTP_X_REAL_IP'
proxy_key2 = 'HTTP_X_FORWARDED_FOR'
def_key = 'REMOTE_ADDR'
def _filters(x):
return _filter_port(_filter_proxy(x))
ip = environ.get(proxy_key)
if ip:
return _filters(ip)
ip = environ.get(proxy_key2)
if ip:
return _filters(ip)
ip = environ.get(def_key, '0.0.0.0')
return _filters(ip)
class RhodeCodeLogger(Logger):
"""
Custom Logger that allows some customization that gunicorn doesn't allow
@ -258,8 +459,62 @@ class RhodeCodeLogger(Logger):
def now(self):
""" return date in RhodeCode Log format """
now = time.time()
msecs = int((now - long(now)) * 1000)
msecs = int((now - int(now)) * 1000)
return time.strftime(self.datefmt, time.localtime(now)) + '.{0:03d}'.format(msecs)
def atoms(self, resp, req, environ, request_time):
""" Gets atoms for log formatting.
"""
status = resp.status
if isinstance(status, str):
status = status.split(None, 1)[0]
atoms = {
'h': get_ip_addr(environ),
'l': '-',
'u': self._get_user(environ) or '-',
't': self.now(),
'r': "%s %s %s" % (environ['REQUEST_METHOD'],
environ['RAW_URI'],
environ["SERVER_PROTOCOL"]),
's': status,
'm': environ.get('REQUEST_METHOD'),
'U': environ.get('PATH_INFO'),
'q': environ.get('QUERY_STRING'),
'H': environ.get('SERVER_PROTOCOL'),
'b': getattr(resp, 'sent', None) is not None and str(resp.sent) or '-',
'B': getattr(resp, 'sent', None),
'f': environ.get('HTTP_REFERER', '-'),
'a': environ.get('HTTP_USER_AGENT', '-'),
'T': request_time.seconds,
'D': (request_time.seconds * 1000000) + request_time.microseconds,
'M': (request_time.seconds * 1000) + int(request_time.microseconds/1000),
'L': "%d.%06d" % (request_time.seconds, request_time.microseconds),
'p': "<%s>" % os.getpid()
}
# add request headers
if hasattr(req, 'headers'):
req_headers = req.headers
else:
req_headers = req
if hasattr(req_headers, "items"):
req_headers = req_headers.items()
atoms.update({"{%s}i" % k.lower(): v for k, v in req_headers})
resp_headers = resp.headers
if hasattr(resp_headers, "items"):
resp_headers = resp_headers.items()
# add response headers
atoms.update({"{%s}o" % k.lower(): v for k, v in resp_headers})
# add environ variables
environ_variables = environ.items()
atoms.update({"{%s}e" % k.lower(): v for k, v in environ_variables})
return atoms
logger_class = RhodeCodeLogger

95
configs/logging.ini Normal file
View file

@ -0,0 +1,95 @@
; #####################
; LOGGING CONFIGURATION
; #####################
[loggers]
keys = root, sqlalchemy, beaker, celery, rhodecode, ssh_wrapper
[handlers]
keys = console, console_sql
[formatters]
keys = generic, json, color_formatter, color_formatter_sql
; #######
; LOGGERS
; #######
[logger_root]
level = NOTSET
handlers = console
[logger_sqlalchemy]
level = $RC_LOGGING_LEVEL
handlers = console_sql
qualname = sqlalchemy.engine
propagate = 0
[logger_beaker]
level = $RC_LOGGING_LEVEL
handlers =
qualname = beaker.container
propagate = 1
[logger_rhodecode]
level = $RC_LOGGING_LEVEL
handlers =
qualname = rhodecode
propagate = 1
[logger_ssh_wrapper]
level = $RC_LOGGING_LEVEL
handlers =
qualname = ssh_wrapper
propagate = 1
[logger_celery]
level = $RC_LOGGING_LEVEL
handlers =
qualname = celery
; ########
; HANDLERS
; ########
[handler_console]
class = StreamHandler
args = (sys.stderr, )
level = $RC_LOGGING_LEVEL
; To enable JSON formatted logs replace 'generic' with 'json'
; This allows sending properly formatted logs to grafana loki or elasticsearch
formatter = $RC_LOGGING_FORMATTER
[handler_console_sql]
; "level = DEBUG" logs SQL queries and results.
; "level = INFO" logs SQL queries.
; "level = WARN" logs neither. (Recommended for production systems.)
class = StreamHandler
args = (sys.stderr, )
level = WARN
; To enable JSON formatted logs replace 'generic/color_formatter_sql' with 'json'
; This allows sending properly formatted logs to grafana loki or elasticsearch
formatter = $RC_LOGGING_FORMATTER
; ##########
; FORMATTERS
; ##########
[formatter_generic]
class = rhodecode.lib.logging_formatter.ExceptionAwareFormatter
format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %Y-%m-%d %H:%M:%S
[formatter_color_formatter]
class = rhodecode.lib.logging_formatter.ColorFormatter
format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %Y-%m-%d %H:%M:%S
[formatter_color_formatter_sql]
class = rhodecode.lib.logging_formatter.ColorFormatterSql
format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %Y-%m-%d %H:%M:%S
[formatter_json]
format = %(timestamp)s %(levelname)s %(name)s %(message)s %(req_id)s
class = rhodecode.lib._vendor.jsonlogger.JsonFormatter

View file

@ -1,4 +1,3 @@
## -*- coding: utf-8 -*-
; #########################################
; RHODECODE COMMUNITY EDITION CONFIGURATION
@ -27,91 +26,21 @@ debug = false
#smtp_use_ssl = true
[server:main]
; COMMON HOST/IP CONFIG
; COMMON HOST/IP CONFIG, This applies mostly to develop setup,
; Host port for gunicorn are controlled by gunicorn_conf.py
host = 127.0.0.1
port = 5000
port = 10020
; ###########################
; GUNICORN APPLICATION SERVER
; ###########################
; run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
; run with gunicorn --paste rhodecode.ini --config gunicorn_conf.py
; Module to use, this setting shouldn't be changed
use = egg:gunicorn#main
; Sets the number of process workers. More workers means more concurrent connections
; RhodeCode can handle at the same time. Each additional worker also it increases
; memory usage as each has it's own set of caches.
; Recommended value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers, but no more
; than 8-10 unless for really big deployments .e.g 700-1000 users.
; `instance_id = *` must be set in the [app:main] section below (which is the default)
; when using more than 1 worker.
workers = 2
; Gunicorn access log level
loglevel = info
; Process name visible in process list
proc_name = rhodecode
; Type of worker class, one of `sync`, `gevent`
; Recommended type is `gevent`
worker_class = gevent
; The maximum number of simultaneous clients per worker. Valid only for gevent
worker_connections = 10
; Max number of requests that worker will handle before being gracefully restarted.
; Prevents memory leaks, jitter adds variability so not all workers are restarted at once.
max_requests = 1000
max_requests_jitter = 30
; Amount of time a worker can spend with handling a request before it
; gets killed and restarted. By default set to 21600 (6hrs)
; Examples: 1800 (30min), 3600 (1hr), 7200 (2hr), 43200 (12h)
timeout = 21600
; The maximum size of HTTP request line in bytes.
; 0 for unlimited
limit_request_line = 0
; Limit the number of HTTP headers fields in a request.
; By default this value is 100 and can't be larger than 32768.
limit_request_fields = 32768
; Limit the allowed size of an HTTP request header field.
; Value is a positive number or 0.
; Setting it to 0 will allow unlimited header field sizes.
limit_request_field_size = 0
; Timeout for graceful workers restart.
; After receiving a restart signal, workers have this much time to finish
; serving requests. Workers still alive after the timeout (starting from the
; receipt of the restart signal) are force killed.
; Examples: 1800 (30min), 3600 (1hr), 7200 (2hr), 43200 (12h)
graceful_timeout = 3600
# The number of seconds to wait for requests on a Keep-Alive connection.
# Generally set in the 1-5 seconds range.
keepalive = 2
; Maximum memory usage that each worker can use before it will receive a
; graceful restart signal 0 = memory monitoring is disabled
; Examples: 268435456 (256MB), 536870912 (512MB)
; 1073741824 (1GB), 2147483648 (2GB), 4294967296 (4GB)
memory_max_usage = 0
; How often in seconds to check for memory usage for each gunicorn worker
memory_usage_check_interval = 60
; Threshold value for which we don't recycle worker if GarbageCollection
; frees up enough resources. Before each restart we try to run GC on worker
; in case we get enough free memory after that, restart will not happen.
memory_usage_recovery_threshold = 0.8
; Prefix middleware for RhodeCode.
; recommended when using proxy setup.
; allows to set RhodeCode under a prefix in server.
@ -126,8 +55,16 @@ prefix = /
[app:main]
; The %(here)s variable will be replaced with the absolute path of parent directory
; of this file
; In addition ENVIRONMENT variables usage is possible, e.g
; sqlalchemy.db1.url = {ENV_RC_DB_URL}
; Each option in the app:main can be override by an environmental variable
;
;To override an option:
;
;RC_<KeyName>
;Everything should be uppercase, . and - should be replaced by _.
;For example, if you have these configuration settings:
;rc_cache.repo_object.backend = foo
;can be overridden by
;export RC_CACHE_REPO_OBJECT_BACKEND=foo
use = egg:rhodecode-enterprise-ce
@ -162,12 +99,6 @@ lang = en
; Settings this to true could lead to very long startup time.
startup.import_repos = false
; Uncomment and set this path to use archive download cache.
; Once enabled, generated archives will be cached at this location
; and served from the cache during subsequent requests for the same archive of
; the repository.
#archive_cache_dir = /tmp/tarballcache
; URL at which the application is running. This is used for Bootstrapping
; requests in context when no web request is available. Used in ishell, or
; SSH calls. Set this for events to receive proper url for SSH calls.
@ -321,23 +252,43 @@ file_store.backend = local
; path to store the uploaded binaries
file_store.storage_path = %(here)s/data/file_store
; Uncomment and set this path to control settings for archive download cache.
; Generated repo archives will be cached at this location
; and served from the cache during subsequent requests for the same archive of
; the repository. This path is important to be shared across filesystems and with
; RhodeCode and vcsserver
; Default is $cache_dir/archive_cache if not set
archive_cache.store_dir = %(here)s/data/archive_cache
; The limit in GB sets how much data we cache before recycling last used, defaults to 10 gb
archive_cache.cache_size_gb = 40
; By default cache uses sharding technique, this specifies how many shards are there
archive_cache.cache_shards = 4
; #############
; CELERY CONFIG
; #############
; manually run celery: /path/to/celery worker -E --beat --app rhodecode.lib.celerylib.loader --scheduler rhodecode.lib.celerylib.scheduler.RcScheduler --loglevel DEBUG --ini /path/to/rhodecode.ini
; manually run celery: /path/to/celery worker --task-events --beat --app rhodecode.lib.celerylib.loader --scheduler rhodecode.lib.celerylib.scheduler.RcScheduler --loglevel DEBUG --ini /path/to/rhodecode.ini
use_celery = false
; path to store schedule database
#celerybeat-schedule.path =
; connection url to the message broker (default redis)
celery.broker_url = redis://localhost:6379/8
celery.broker_url = redis://redis:6379/8
; results backend to get results for (default redis)
celery.result_backend = redis://redis:6379/8
; rabbitmq example
#celery.broker_url = amqp://rabbitmq:qweqwe@localhost:5672/rabbitmqhost
; maximum tasks to execute before worker restart
celery.max_tasks_per_child = 100
celery.max_tasks_per_child = 20
; tasks will never be sent to the queue, but executed locally instead.
celery.task_always_eager = false
@ -369,13 +320,42 @@ rc_cache.cache_repo_longterm.expiration_time = 2592000
rc_cache.cache_repo_longterm.max_size = 10000
; *********************************************
; `cache_general` cache for general purpose use
; for simplicity use rc.file_namespace backend,
; for performance and scale use rc.redis
; *********************************************
rc_cache.cache_general.backend = dogpile.cache.rc.file_namespace
rc_cache.cache_general.expiration_time = 43200
; file cache store path. Defaults to `cache_dir =` value or tempdir if both values are not set
#rc_cache.cache_general.arguments.filename = /tmp/cache_general_db
; alternative `cache_general` redis backend with distributed lock
#rc_cache.cache_general.backend = dogpile.cache.rc.redis
#rc_cache.cache_general.expiration_time = 300
; redis_expiration_time needs to be greater then expiration_time
#rc_cache.cache_general.arguments.redis_expiration_time = 7200
#rc_cache.cache_general.arguments.host = localhost
#rc_cache.cache_general.arguments.port = 6379
#rc_cache.cache_general.arguments.db = 0
#rc_cache.cache_general.arguments.socket_timeout = 30
; more Redis options: https://dogpilecache.sqlalchemy.org/en/latest/api.html#redis-backends
#rc_cache.cache_general.arguments.distributed_lock = true
; auto-renew lock to prevent stale locks, slower but safer. Use only if problems happen
#rc_cache.cache_general.arguments.lock_auto_renewal = true
; *************************************************
; `cache_perms` cache for permission tree, auth TTL
; for simplicity use rc.file_namespace backend,
; for performance and scale use rc.redis
; *************************************************
rc_cache.cache_perms.backend = dogpile.cache.rc.file_namespace
rc_cache.cache_perms.expiration_time = 300
rc_cache.cache_perms.expiration_time = 3600
; file cache store path. Defaults to `cache_dir =` value or tempdir if both values are not set
#rc_cache.cache_perms.arguments.filename = /tmp/cache_perms.db
#rc_cache.cache_perms.arguments.filename = /tmp/cache_perms_db
; alternative `cache_perms` redis backend with distributed lock
#rc_cache.cache_perms.backend = dogpile.cache.rc.redis
@ -396,11 +376,13 @@ rc_cache.cache_perms.expiration_time = 300
; ***************************************************
; `cache_repo` cache for file tree, Readme, RSS FEEDS
; for simplicity use rc.file_namespace backend,
; for performance and scale use rc.redis
; ***************************************************
rc_cache.cache_repo.backend = dogpile.cache.rc.file_namespace
rc_cache.cache_repo.expiration_time = 2592000
; file cache store path. Defaults to `cache_dir =` value or tempdir if both values are not set
#rc_cache.cache_repo.arguments.filename = /tmp/cache_repo.db
#rc_cache.cache_repo.arguments.filename = /tmp/cache_repo_db
; alternative `cache_repo` redis backend with distributed lock
#rc_cache.cache_repo.backend = dogpile.cache.rc.redis
@ -424,8 +406,8 @@ rc_cache.cache_repo.expiration_time = 2592000
; ##############
; beaker.session.type is type of storage options for the logged users sessions. Current allowed
; types are file, ext:redis, ext:database, ext:memcached, and memory (default if not specified).
; Fastest ones are Redis and ext:database
; types are file, ext:redis, ext:database, ext:memcached
; Fastest ones are ext:redis and ext:database, DO NOT use memory type for session
beaker.session.type = file
beaker.session.data_dir = %(here)s/data/sessions
@ -520,10 +502,12 @@ sqlalchemy.db1.echo = false
; recycle the connections after this amount of seconds
sqlalchemy.db1.pool_recycle = 3600
sqlalchemy.db1.convert_unicode = true
; the number of connections to keep open inside the connection pool.
; 0 indicates no limit
; the general calculus with gevent is:
; if your system allows 500 concurrent greenlets (max_connections) that all do database access,
; then increase pool size + max overflow so that they add up to 500.
#sqlalchemy.db1.pool_size = 5
; The number of connections to allow in connection pool "overflow", that is
@ -554,9 +538,10 @@ vcs.scm_app_implementation = http
; `http` - use http-rpc backend (default)
vcs.hooks.protocol = http
; Host on which this instance is listening for hooks. If vcsserver is in other location
; this should be adjusted.
vcs.hooks.host = 127.0.0.1
; Host on which this instance is listening for hooks. vcsserver will call this host to pull/push hooks so it should be
; accessible via network.
; Use vcs.hooks.host = "*" to bind to current hostname (for Docker)
vcs.hooks.host = *
; Start VCSServer with this instance as a subprocess, useful for development
vcs.start_server = false
@ -575,6 +560,9 @@ vcs.connection_timeout = 3600
; Legacy available options are: pre-1.4-compatible, pre-1.5-compatible, pre-1.6-compatible, pre-1.8-compatible, pre-1.9-compatible
#vcs.svn.compatible_version = 1.8
; Cache flag to cache vcsserver remote calls locally
; It uses cache_region `cache_repo`
vcs.methods.cache = true
; ####################################################
; Subversion proxy support (mod_dav_svn)
@ -657,55 +645,74 @@ ssh.enable_ui_key_generator = true
; http://appenlight.rhodecode.com for details how to obtain an account
; Appenlight integration enabled
appenlight = false
#appenlight = false
appenlight.server_url = https://api.appenlight.com
appenlight.api_key = YOUR_API_KEY
#appenlight.server_url = https://api.appenlight.com
#appenlight.api_key = YOUR_API_KEY
#appenlight.transport_config = https://api.appenlight.com?threaded=1&timeout=5
; used for JS client
appenlight.api_public_key = YOUR_API_PUBLIC_KEY
#appenlight.api_public_key = YOUR_API_PUBLIC_KEY
; TWEAK AMOUNT OF INFO SENT HERE
; enables 404 error logging (default False)
appenlight.report_404 = false
#appenlight.report_404 = false
; time in seconds after request is considered being slow (default 1)
appenlight.slow_request_time = 1
#appenlight.slow_request_time = 1
; record slow requests in application
; (needs to be enabled for slow datastore recording and time tracking)
appenlight.slow_requests = true
#appenlight.slow_requests = true
; enable hooking to application loggers
appenlight.logging = true
#appenlight.logging = true
; minimum log level for log capture
appenlight.logging.level = WARNING
#ppenlight.logging.level = WARNING
; send logs only from erroneous/slow requests
; (saves API quota for intensive logging)
appenlight.logging_on_error = false
#appenlight.logging_on_error = false
; list of additional keywords that should be grabbed from environ object
; can be string with comma separated list of words in lowercase
; (by default client will always send following info:
; 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
; start with HTTP* this list be extended with additional keywords here
appenlight.environ_keys_whitelist =
#appenlight.environ_keys_whitelist =
; list of keywords that should be blanked from request object
; can be string with comma separated list of words in lowercase
; (by default client will always blank keys that contain following words
; 'password', 'passwd', 'pwd', 'auth_tkt', 'secret', 'csrf'
; this list be extended with additional keywords set here
appenlight.request_keys_blacklist =
#appenlight.request_keys_blacklist =
; list of namespaces that should be ignores when gathering log entries
; can be string with comma separated list of namespaces
; (by default the client ignores own entries: appenlight_client.client)
appenlight.log_namespace_blacklist =
#appenlight.log_namespace_blacklist =
; Statsd client config, this is used to send metrics to statsd
; We recommend setting statsd_exported and scrape them using Prometheus
#statsd.enabled = false
#statsd.statsd_host = 0.0.0.0
#statsd.statsd_port = 8125
#statsd.statsd_prefix =
#statsd.statsd_ipv6 = false
; configure logging automatically at server startup set to false
; to use the below custom logging config.
; RC_LOGGING_FORMATTER
; RC_LOGGING_LEVEL
; env variables can control the settings for logging in case of autoconfigure
#logging.autoconfigure = true
; specify your own custom logging config file to configure logging
#logging.logging_conf_file = /path/to/custom_logging.ini
; Dummy marker to add new entries after.
; Add any custom entries below. Please don't remove this marker.
@ -715,6 +722,7 @@ custom.conf = 1
; #####################
; LOGGING CONFIGURATION
; #####################
[loggers]
keys = root, sqlalchemy, beaker, celery, rhodecode, ssh_wrapper
@ -722,7 +730,7 @@ keys = root, sqlalchemy, beaker, celery, rhodecode, ssh_wrapper
keys = console, console_sql
[formatters]
keys = generic, color_formatter, color_formatter_sql
keys = generic, json, color_formatter, color_formatter_sql
; #######
; LOGGERS
@ -769,6 +777,8 @@ qualname = celery
class = StreamHandler
args = (sys.stderr, )
level = INFO
; To enable JSON formatted logs replace 'generic/color_formatter' with 'json'
; This allows sending properly formatted logs to grafana loki or elasticsearch
formatter = generic
[handler_console_sql]
@ -778,6 +788,8 @@ formatter = generic
class = StreamHandler
args = (sys.stderr, )
level = WARN
; To enable JSON formatted logs replace 'generic/color_formatter_sql' with 'json'
; This allows sending properly formatted logs to grafana loki or elasticsearch
formatter = generic
; ##########
@ -798,3 +810,7 @@ datefmt = %Y-%m-%d %H:%M:%S
class = rhodecode.lib.logging_formatter.ColorFormatterSql
format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %Y-%m-%d %H:%M:%S
[formatter_json]
format = %(timestamp)s %(levelname)s %(name)s %(message)s %(req_id)s
class = rhodecode.lib._vendor.jsonlogger.JsonFormatter

57
conftest.py Normal file
View file

@ -0,0 +1,57 @@
# Copyright (C) 2010-2023 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 <http://www.gnu.org/licenses/>.
#
# 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 # noqa
# keep the imports to have a toplevel conftest.py but still importable from EE edition
from rhodecode.tests.conftest_common import ( # noqa
pytest_generate_tests,
pytest_runtest_makereport,
pytest_addoption
)
pytest_plugins = [
"rhodecode.tests.fixture_mods.fixture_pyramid",
"rhodecode.tests.fixture_mods.fixture_utils",
]
def pytest_configure(config):
from rhodecode.config import patches # noqa
def pytest_collection_modifyitems(session, config, items):
# nottest marked, compare nose, used for transition from nose to pytest
remaining = [
i for i in items if getattr(i.obj, '__test__', True)]
items[:] = remaining
# NOTE(marcink): custom test ordering, db tests and vcstests are slowest and should
# be executed at the end for faster test feedback
def sorter(item):
pos = 0
key = item._nodeid
if key.startswith('rhodecode/tests/database'):
pos = 1
elif key.startswith('rhodecode/tests/vcs_operations'):
pos = 2
return pos
items.sort(key=sorter)

View file

@ -1,296 +0,0 @@
# Nix environment for the community edition
#
# This shall be as lean as possible, just producing the enterprise-ce
# derivation. For advanced tweaks to pimp up the development environment we use
# "shell.nix" so that it does not have to clutter this file.
#
# Configuration, set values in "~/.nixpkgs/config.nix".
# example
# {
# # Thoughts on how to configure the dev environment
# rc = {
# codeInternalUrl = "https://usr:token@code.rhodecode.com/internal";
# sources = {
# rhodecode-vcsserver = "/home/user/work/rhodecode-vcsserver";
# rhodecode-enterprise-ce = "/home/user/work/rhodecode-enterprise-ce";
# rhodecode-enterprise-ee = "/home/user/work/rhodecode-enterprise-ee";
# };
# };
# }
args@
{ system ? builtins.currentSystem
, pythonPackages ? "python27Packages"
, pythonExternalOverrides ? self: super: {}
, doCheck ? false
, ...
}:
let
pkgs_ = args.pkgs or (import <nixpkgs> { inherit system; });
in
let
pkgs = import <nixpkgs> {
overlays = [
(import ./pkgs/overlays.nix)
];
inherit
(pkgs_)
system;
};
# Works with the new python-packages, still can fallback to the old
# variant.
basePythonPackagesUnfix = basePythonPackages.__unfix__ or (
self: basePythonPackages.override (a: { inherit self; }));
# 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" ".idea" ".dev"
"node_modules" "node_binaries"
"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;
sources =
let
inherit
(pkgs.lib)
all
isString
attrValues;
sourcesConfig = pkgs.config.rc.sources or {};
in
# Ensure that sources are configured as strings. Using a path
# would result in a copy into the nix store.
assert all isString (attrValues sourcesConfig);
sourcesConfig;
version = builtins.readFile "${rhodecode-enterprise-ce-src}/rhodecode/VERSION";
rhodecode-enterprise-ce-src = builtins.filterSource src-filter ./.;
nodeEnv = import ./pkgs/node-default.nix {
inherit
pkgs
system;
};
nodeDependencies = nodeEnv.shell.nodeDependencies;
rhodecode-testdata-src = sources.rhodecode-testdata or (
pkgs.fetchhg {
url = "https://code.rhodecode.com/upstream/rc_testdata";
rev = "v0.10.0";
sha256 = "0zn9swwvx4vgw4qn8q3ri26vvzgrxn15x6xnjrysi1bwmz01qjl0";
});
rhodecode-testdata = import "${rhodecode-testdata-src}/default.nix" {
inherit
doCheck
pkgs
pythonPackages;
};
pythonLocalOverrides = self: super: {
rhodecode-enterprise-ce =
let
linkNodePackages = ''
export RHODECODE_CE_PATH=${rhodecode-enterprise-ce-src}
echo "[BEGIN]: Link node packages and binaries"
# johbo: Linking individual packages allows us to run "npm install"
# inside of a shell to try things out. Re-entering the shell will
# restore a clean environment.
rm -fr node_modules
mkdir node_modules
ln -s ${nodeDependencies}/lib/node_modules/* node_modules/
export NODE_PATH=./node_modules
rm -fr node_binaries
mkdir node_binaries
ln -s ${nodeDependencies}/bin/* node_binaries/
echo "[DONE ]: Link node packages and binaries"
'';
releaseName = "RhodeCodeEnterpriseCE-${version}";
in super.rhodecode-enterprise-ce.override (attrs: {
inherit
doCheck
version;
name = "rhodecode-enterprise-ce-${version}";
releaseName = releaseName;
src = rhodecode-enterprise-ce-src;
dontStrip = true; # prevent strip, we don't need it.
# expose following attributed outside
passthru = {
inherit
rhodecode-testdata
linkNodePackages
myPythonPackagesUnfix
pythonLocalOverrides
pythonCommunityOverrides;
pythonPackages = self;
};
buildInputs =
attrs.buildInputs or [] ++ [
rhodecode-testdata
];
#NOTE: option to inject additional propagatedBuildInputs
propagatedBuildInputs =
attrs.propagatedBuildInputs or [] ++ [
];
LC_ALL = "en_US.UTF-8";
LOCALE_ARCHIVE =
if pkgs.stdenv.isLinux
then "${pkgs.glibcLocales}/lib/locale/locale-archive"
else "";
# Add bin directory to path so that tests can find 'rhodecode'.
preCheck = ''
export PATH="$out/bin:$PATH"
'';
# custom check phase for testing
checkPhase = ''
runHook preCheck
PYTHONHASHSEED=random py.test -vv -p no:sugar -r xw --cov-config=.coveragerc --cov=rhodecode --cov-report=term-missing rhodecode
runHook postCheck
'';
postCheck = ''
echo "Cleanup of rhodecode/tests"
rm -rf $out/lib/${self.python.libPrefix}/site-packages/rhodecode/tests
'';
preBuild = ''
echo "[BEGIN]: Building frontend assets"
${linkNodePackages}
make web-build
rm -fr node_modules
rm -fr node_binaries
echo "[DONE ]: Building frontend assets"
'';
postInstall = ''
# check required files
STATIC_CHECK="/robots.txt /502.html
/js/scripts.min.js /js/rhodecode-components.js
/css/style.css /css/style-polymer.css /css/style-ipython.css"
for file in $STATIC_CHECK;
do
if [ ! -f rhodecode/public/$file ]; then
echo "Missing $file"
exit 1
fi
done
echo "Writing enterprise-ce meta information for rccontrol to nix-support/rccontrol"
mkdir -p $out/nix-support/rccontrol
cp -v rhodecode/VERSION $out/nix-support/rccontrol/version
echo "[DONE ]: enterprise-ce meta information for rccontrol written"
mkdir -p $out/etc
cp configs/production.ini $out/etc
echo "[DONE ]: saved enterprise-ce production.ini into $out/etc"
cp -Rf rhodecode/config/rcextensions $out/etc/rcextensions.tmpl
echo "[DONE ]: saved enterprise-ce rcextensions into $out/etc/rcextensions.tmpl"
# python based programs need to be wrapped
mkdir -p $out/bin
# required binaries from dependencies
ln -s ${self.supervisor}/bin/supervisorctl $out/bin/
ln -s ${self.supervisor}/bin/supervisord $out/bin/
ln -s ${self.pastescript}/bin/paster $out/bin/
ln -s ${self.channelstream}/bin/channelstream $out/bin/
ln -s ${self.celery}/bin/celery $out/bin/
ln -s ${self.gunicorn}/bin/gunicorn $out/bin/
ln -s ${self.pyramid}/bin/prequest $out/bin/
ln -s ${self.pyramid}/bin/pserve $out/bin/
echo "[DONE ]: created symlinks into $out/bin"
DEPS="$out/bin/supervisorctl \
$out/bin/supervisord \
$out/bin/paster \
$out/bin/channelstream \
$out/bin/celery \
$out/bin/gunicorn \
$out/bin/prequest \
$out/bin/pserve"
# wrap only dependency scripts, they require to have full PYTHONPATH set
# to be able to import all packages
for file in $DEPS;
do
wrapProgram $file \
--prefix PATH : $PATH \
--prefix PYTHONPATH : $PYTHONPATH \
--set PYTHONHASHSEED random
done
echo "[DONE ]: enterprise-ce binary wrapping"
# rhodecode-tools don't need wrapping
ln -s ${self.rhodecode-tools}/bin/rhodecode-* $out/bin/
# expose sources of CE
ln -s $out $out/etc/rhodecode_enterprise_ce_source
# expose static files folder
cp -Rf $out/lib/${self.python.libPrefix}/site-packages/rhodecode/public/ $out/etc/static
chmod 755 -R $out/etc/static
'';
});
};
basePythonPackages = with builtins;
if isAttrs pythonPackages then
pythonPackages
else
getAttr pythonPackages pkgs;
pythonGeneratedPackages = import ./pkgs/python-packages.nix {
inherit
pkgs;
inherit
(pkgs)
fetchurl
fetchgit
fetchhg;
};
pythonCommunityOverrides = import ./pkgs/python-packages-overrides.nix {
inherit pkgs basePythonPackages;
};
# Apply all overrides and fix the final package set
myPythonPackagesUnfix = with pkgs.lib;
(extends pythonExternalOverrides
(extends pythonLocalOverrides
(extends pythonCommunityOverrides
(extends pythonGeneratedPackages
basePythonPackagesUnfix))));
myPythonPackages = (pkgs.lib.fix myPythonPackagesUnfix);
in myPythonPackages.rhodecode-enterprise-ce

View file

@ -1,9 +1,6 @@
# generating packages
nix-shell pkgs/shell-generate.nix
cd docs
pip2nix generate
## BUILD
# cd docs
# docker build --tag sphinx-doc-build-rc .
# building the docs
cd docs
nix-build default.nix -o result
make clean html
# Build Docs
# docker run --rm -v $(PWD):/project --workdir=/project/docs sphinx-doc-build-rc make clean html

24
docs/Dockerfile Normal file
View file

@ -0,0 +1,24 @@
FROM python:3.12.0-bullseye
WORKDIR /project
RUN apt-get update \
&& apt-get install --no-install-recommends --yes \
curl \
zip \
graphviz \
imagemagick \
make \
&& apt-get autoremove \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN \
python3 -m pip install --no-cache-dir --upgrade pip && \
python3 -m pip install --no-cache-dir Sphinx Pillow
ADD requirements_docs.txt /project
RUN \
python3 -m pip install -r requirements_docs.txt
CMD ["sphinx-build", "-M", "html", ".", "_build"]

View file

@ -2,9 +2,9 @@
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = ./result/bin/sphinx-build
PAPER =
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = _build
# User-friendly check for sphinx-build

117
docs/_templates/base.html vendored Normal file
View file

@ -0,0 +1,117 @@
<!doctype html>
<html class="no-js"{% if language is not none %} lang="{{ language }}"{% endif %} data-content_root="{{ content_root }}">
<head>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-M2TSG36B');</script>
<!-- End Google Tag Manager -->
{%- block site_meta -%}
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<meta name="color-scheme" content="light dark">
{%- if metatags %}{{ metatags }}{% endif -%}
{%- block linktags %}
{%- if hasdoc('about') -%}
<link rel="author" title="{{ _('About these documents') }}" href="{{ pathto('about') }}" />
{%- endif -%}
{%- if hasdoc('genindex') -%}
<link rel="index" title="{{ _('Index') }}" href="{{ pathto('genindex') }}" />
{%- endif -%}
{%- if hasdoc('search') -%}
<link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}" />
{%- endif -%}
{%- if hasdoc('copyright') -%}
<link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}" />
{%- endif -%}
{%- if next -%}
<link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}" />
{%- endif -%}
{%- if prev -%}
<link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}" />
{%- endif -%}
{#- rel="canonical" (set by html_baseurl) -#}
{%- if pageurl %}
<link rel="canonical" href="{{ pageurl|e }}" />
{%- endif %}
{%- endblock linktags %}
{# Favicon #}
{%- if favicon_url -%}
<link rel="shortcut icon" href="{{ favicon_url }}"/>
{%- endif -%}
<!-- Generated with Sphinx {{ sphinx_version }} and Furo {{ furo_version }} -->
{%- endblock site_meta -%}
{#- Site title -#}
{%- block htmltitle -%}
{% if not docstitle %}
<title>{{ title|striptags|e }}</title>
{% elif pagename == master_doc %}
<title>{{ docstitle|striptags|e }}</title>
{% else %}
<title>{{ title|striptags|e }} - {{ docstitle|striptags|e }}</title>
{% endif %}
{%- endblock -%}
{%- block styles -%}
{# Custom stylesheets #}
{%- block regular_styles -%}
{%- for css in css_files -%}
{% if css|attr("filename") -%}
{{ css_tag(css) }}
{%- else -%}
<link rel="stylesheet" href="{{ pathto(css, 1)|e }}" type="text/css" />
{%- endif %}
{% endfor -%}
{%- endblock regular_styles -%}
{#- Theme-related stylesheets -#}
{%- block theme_styles %}
{% include "partials/_head_css_variables.html" with context %}
{%- endblock -%}
{%- block extra_styles %}
{%- endblock -%}
{%- endblock styles -%}
{#- Custom front matter #}
{%- block extrahead -%}{%- endblock -%}
</head>
<body>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-M2TSG36B"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
{% block body %}
<script>
document.body.dataset.theme = localStorage.getItem("theme") || "auto";
</script>
{% endblock %}
{%- block scripts -%}
{# Custom JS #}
{%- block regular_scripts -%}
{% for path in script_files -%}
{{ js_tag(path) }}
{% endfor -%}
{%- endblock regular_scripts -%}
{# Theme-related JavaScript code #}
{%- block theme_scripts -%}
{%- endblock -%}
{%- endblock scripts -%}
</body>
</html>

View file

@ -1,6 +0,0 @@
{% extends "!footer.html" %}
{% block extrafooter %}
<br/>
Documentation defects and suggestions can be submitted <a href="https://issues.rhodecode.com/projects/documentation">here</a>
{% endblock %}

View file

@ -1,18 +0,0 @@
{% extends "!layout.html" %}
{% set css_files = css_files + ['_static/add.css'] %}
{% block footer %}
{{ super() }}
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-55639800-3', 'auto');
ga('send', 'pageview');
</script>
{% endblock %}

204
docs/_templates/page.html vendored Normal file
View file

@ -0,0 +1,204 @@
{% extends "base.html" %}
{% block body -%}
{{ super() }}
{% include "partials/icons.html" %}
<input type="checkbox" class="sidebar-toggle" name="__navigation" id="__navigation">
<input type="checkbox" class="sidebar-toggle" name="__toc" id="__toc">
<label class="overlay sidebar-overlay" for="__navigation">
<div class="visually-hidden">Hide navigation sidebar</div>
</label>
<label class="overlay toc-overlay" for="__toc">
<div class="visually-hidden">Hide table of contents sidebar</div>
</label>
{% if theme_announcement -%}
<div class="announcement">
<aside class="announcement-content">
{% block announcement %} {{ theme_announcement }} {% endblock announcement %}
</aside>
</div>
{%- endif %}
<div class="page">
<header class="mobile-header">
<div class="header-left">
<label class="nav-overlay-icon" for="__navigation">
<div class="visually-hidden">Toggle site navigation sidebar</div>
<i class="icon"><svg><use href="#svg-menu"></use></svg></i>
</label>
</div>
<div class="header-center">
<a href="{{ pathto(master_doc) }}"><div class="brand">{{ docstitle if docstitle else project }}</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
<button class="theme-toggle">
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
</button>
</div>
<label class="toc-overlay-icon toc-header-icon{% if furo_hide_toc %} no-toc{% endif %}" for="__toc">
<div class="visually-hidden">Toggle table of contents sidebar</div>
<i class="icon"><svg><use href="#svg-toc"></use></svg></i>
</label>
</div>
</header>
<aside class="sidebar-drawer">
<div class="sidebar-container">
{% block left_sidebar %}
<div class="sidebar-sticky">
{%- for sidebar_section in sidebars %}
{%- include sidebar_section %}
{%- endfor %}
</div>
{% endblock left_sidebar %}
</div>
</aside>
<div class="main">
<div class="content">
<div class="article-container">
<a href="#" class="back-to-top muted-link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12z"></path>
</svg>
<span>{% trans %}Back to top{% endtrans %}</span>
</a>
<div class="content-icon-container">
{% if theme_top_of_page_button == "edit" -%}
{%- include "components/edit-this-page.html" with context -%}
{%- elif theme_top_of_page_button != None -%}
{{ warning("Got an unsupported value for 'top_of_page_button'") }}
{%- endif -%}
{#- Theme toggle -#}
<div class="theme-toggle-container theme-toggle-content">
<button class="theme-toggle">
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
</button>
</div>
<label class="toc-overlay-icon toc-content-icon{% if furo_hide_toc %} no-toc{% endif %}" for="__toc">
<div class="visually-hidden">Toggle table of contents sidebar</div>
<i class="icon"><svg><use href="#svg-toc"></use></svg></i>
</label>
</div>
<article role="main">
{% block content %}{{ body }}{% endblock %}
</article>
</div>
<footer>
{% block footer %}
<div class="related-pages">
{% if next -%}
<a class="next-page" href="{{ next.link }}">
<div class="page-info">
<div class="context">
<span>{{ _("Next") }}</span>
</div>
<div class="title">{{ next.title }}</div>
</div>
<svg class="furo-related-icon"><use href="#svg-arrow-right"></use></svg>
</a>
{%- endif %}
{% if prev -%}
<a class="prev-page" href="{{ prev.link }}">
<svg class="furo-related-icon"><use href="#svg-arrow-right"></use></svg>
<div class="page-info">
<div class="context">
<span>{{ _("Previous") }}</span>
</div>
{% if prev.link == pathto(master_doc) %}
<div class="title">{{ _("Home") }}</div>
{% else %}
<div class="title">{{ prev.title }}</div>
{% endif %}
</div>
</a>
{%- endif %}
</div>
<div class="bottom-of-page">
<div class="left-details">
{%- if show_copyright %}
<div class="copyright">
{%- if hasdoc('copyright') %}
{% trans path=pathto('copyright'), copyright=copyright|e -%}
<a href="{{ path }}">Copyright</a> &#169; {{ copyright }}
{%- endtrans %}
{%- else %}
{% trans copyright=copyright|e -%}
Copyright &#169; {{ copyright }}
{%- endtrans %}
{%- endif %}
</div>
{%- endif %}
{%- if show_sphinx -%}
{% trans %}<a href="https://www.sphinx-doc.org/">Sphinx</a> and {% endtrans -%}
<a class="muted-link" href="https://pradyunsg.me">@pradyunsg</a>'s
{% endif -%}
{%- if last_updated -%}
<div class="last-updated">
{% trans last_updated=last_updated|e -%}
Last updated on {{ last_updated }}
{%- endtrans -%}
</div>
<div style="border-top: 0">
Got documentation defects and suggestions? <a href="https://community.rhodecode.com">Submit docs issues</a>
</div>
{%- endif %}
</div>
<div class="right-details">
{% if theme_footer_icons or READTHEDOCS -%}
<div class="icons">
{% if theme_footer_icons -%}
{% for icon_dict in theme_footer_icons -%}
<a class="muted-link {{ icon_dict.class }}" href="{{ icon_dict.url }}" aria-label="{{ icon_dict.name }}">
{{- icon_dict.html -}}
</a>
{% endfor %}
{%- else -%}
{#- Show Read the Docs project -#}
{%- if READTHEDOCS and slug -%}
<a class="muted-link" href="https://readthedocs.org/projects/{{ slug }}" aria-label="On Read the Docs">
<svg x="0px" y="0px" viewBox="-125 217 360 360" xml:space="preserve">
<path fill="currentColor" d="M39.2,391.3c-4.2,0.6-7.1,4.4-6.5,8.5c0.4,3,2.6,5.5,5.5,6.3 c0,0,18.5,6.1,50,8.7c25.3,2.1,54-1.8,54-1.8c4.2-0.1,7.5-3.6,7.4-7.8c-0.1-4.2-3.6-7.5-7.8-7.4c-0.5,0-1,0.1-1.5,0.2 c0,0-28.1,3.5-50.9,1.6c-30.1-2.4-46.5-7.9-46.5-7.9C41.7,391.3,40.4,391.1,39.2,391.3z M39.2,353.6c-4.2,0.6-7.1,4.4-6.5,8.5 c0.4,3,2.6,5.5,5.5,6.3c0,0,18.5,6.1,50,8.7c25.3,2.1,54-1.8,54-1.8c4.2-0.1,7.5-3.6,7.4-7.8c-0.1-4.2-3.6-7.5-7.8-7.4 c-0.5,0-1,0.1-1.5,0.2c0,0-28.1,3.5-50.9,1.6c-30.1-2.4-46.5-7.9-46.5-7.9C41.7,353.6,40.4,353.4,39.2,353.6z M39.2,315.9 c-4.2,0.6-7.1,4.4-6.5,8.5c0.4,3,2.6,5.5,5.5,6.3c0,0,18.5,6.1,50,8.7c25.3,2.1,54-1.8,54-1.8c4.2-0.1,7.5-3.6,7.4-7.8 c-0.1-4.2-3.6-7.5-7.8-7.4c-0.5,0-1,0.1-1.5,0.2c0,0-28.1,3.5-50.9,1.6c-30.1-2.4-46.5-7.9-46.5-7.9 C41.7,315.9,40.4,315.8,39.2,315.9z M39.2,278.3c-4.2,0.6-7.1,4.4-6.5,8.5c0.4,3,2.6,5.5,5.5,6.3c0,0,18.5,6.1,50,8.7 c25.3,2.1,54-1.8,54-1.8c4.2-0.1,7.5-3.6,7.4-7.8c-0.1-4.2-3.6-7.5-7.8-7.4c-0.5,0-1,0.1-1.5,0.2c0,0-28.1,3.5-50.9,1.6 c-30.1-2.4-46.5-7.9-46.5-7.9C41.7,278.2,40.4,278.1,39.2,278.3z M-13.6,238.5c-39.6,0.3-54.3,12.5-54.3,12.5v295.7 c0,0,14.4-12.4,60.8-10.5s55.9,18.2,112.9,19.3s71.3-8.8,71.3-8.8l0.8-301.4c0,0-25.6,7.3-75.6,7.7c-49.9,0.4-61.9-12.7-107.7-14.2 C-8.2,238.6-10.9,238.5-13.6,238.5z M19.5,257.8c0,0,24,7.9,68.3,10.1c37.5,1.9,75-3.7,75-3.7v267.9c0,0-19,10-66.5,6.6 C59.5,536.1,19,522.1,19,522.1L19.5,257.8z M-3.6,264.8c4.2,0,7.7,3.4,7.7,7.7c0,4.2-3.4,7.7-7.7,7.7c0,0-12.4,0.1-20,0.8 c-12.7,1.3-21.4,5.9-21.4,5.9c-3.7,2-8.4,0.5-10.3-3.2c-2-3.7-0.5-8.4,3.2-10.3c0,0,0,0,0,0c0,0,11.3-6,27-7.5 C-16,264.9-3.6,264.8-3.6,264.8z M-11,302.6c4.2-0.1,7.4,0,7.4,0c4.2,0.5,7.2,4.3,6.7,8.5c-0.4,3.5-3.2,6.3-6.7,6.7 c0,0-12.4,0.1-20,0.8c-12.7,1.3-21.4,5.9-21.4,5.9c-3.7,2-8.4,0.5-10.3-3.2c-2-3.7-0.5-8.4,3.2-10.3c0,0,11.3-6,27-7.5 C-20.5,302.9-15.2,302.7-11,302.6z M-3.6,340.2c4.2,0,7.7,3.4,7.7,7.7s-3.4,7.7-7.7,7.7c0,0-12.4-0.1-20,0.7 c-12.7,1.3-21.4,5.9-21.4,5.9c-3.7,2-8.4,0.5-10.3-3.2c-2-3.7-0.5-8.4,3.2-10.3c0,0,11.3-6,27-7.5C-16,340.1-3.6,340.2-3.6,340.2z" />
</svg>
</a>
{%- endif -%}
{%- endif %}
</div>
{%- endif %}
</div>
</div>
{% endblock footer %}
</footer>
</div>
<aside class="toc-drawer{% if furo_hide_toc %} no-toc{% endif %}">
{% block right_sidebar %}
{% if not furo_hide_toc %}
<div class="toc-sticky toc-scroll">
<div class="toc-title-container">
<span class="toc-title">
{{ _("On this page") }}
</span>
</div>
<div class="toc-tree-container">
<div class="toc-tree">
{{ toc }}
</div>
</div>
</div>
{% endif %}
{% endblock right_sidebar %}
</aside>
</div>
</div>
{%- endblock %}

View file

@ -80,8 +80,9 @@ the permissions onto *all* repositories and/or repository groups.
2a) Add user called 'admin' into all repositories with write permission.
Permissions can be also `repository.read`, `repository.admin`, `repository.none`
.. code-block:: python
:dedent: 1
:dedent:
In [1]: from rhodecode.model.repo import RepoModel
In [2]: user = User.get_by_username('admin')
@ -94,7 +95,7 @@ the permissions onto *all* repositories and/or repository groups.
Permissions can be also can be `group.read`, `group.admin`, `group.none`
.. code-block:: python
:dedent: 1
:dedent:
In [1]: from rhodecode.model.repo import RepoModel
In [2]: user = User.get_by_username('admin')
@ -108,7 +109,7 @@ Delete a problematic pull request
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: python
:dedent: 1
:dedent:
In [1]: from rhodecode.model.pull_request import PullRequestModel
In [2]: pullrequest_id = 123

View file

@ -25,7 +25,7 @@ account permissions.
# Open iShell from the terminal
$ rccontrol ishell enterprise-1
.. code-block:: mysql
.. code-block:: python
# Use this example to change user permissions
In [1]: adminuser = User.get_by_username('username')
@ -49,7 +49,7 @@ following example to make changes to this table.
# Open iShell from the terminal
$ rccontrol ishell enterprise-1
.. code-block:: mysql
.. code-block:: python
# Use this example to enable global .hgrc access
In [1]: new_option = RhodeCodeUi()
@ -76,7 +76,7 @@ Use the following code example to carry out these steps.
# starts the ishell interactive prompt
$ rccontrol ishell enterprise-1
.. code-block:: mysql
.. code-block:: python
In [1]: from rhodecode.lib.auth import generate_auth_token
In [2]: from rhodecode.lib.auth import get_crypt_password
@ -107,7 +107,7 @@ Use the following code example to carry out these steps.
# starts the ishell interactive prompt
$ rccontrol ishell enterprise-1
.. code-block:: mysql
.. code-block:: python
# Use this example to change email and username of LDAP user
In [1]: my_user = User.get_by_username('some_username')
@ -139,7 +139,7 @@ Use the text which is shown after '#' sign, eg.
# starts the ishell interactive prompt
$ rccontrol ishell enterprise-1
.. code-block:: mysql
.. code-block:: python
# Use this example to change users from authentication
# using rhodecode internal to ldap

View file

@ -202,7 +202,6 @@ are not required in args.
methods/deprecated-methods
methods/gist-methods
methods/pull-request-methods
methods/repo-methods
methods/repo-group-methods
methods/search-methods
methods/server-methods

View file

@ -1,32 +0,0 @@
# Try and keep this list alphabetical
# ui is for user interface elements and messages
# button - that's obvious
rst_epilog = '''
.. |AE| replace:: Appenlight
.. |authtoken| replace:: Authentication Token
.. |authtokens| replace:: **Auth Tokens**
.. |RCCEshort| replace:: Community
.. |RCEEshort| replace:: Enterprise
.. |git| replace:: Git
.. |hg| replace:: Mercurial
.. |svn| replace:: Subversion
.. |LDAP| replace:: LDAP / Active Directory
.. |os| replace:: operating system
.. |OS| replace:: Operating System
.. |PY| replace:: Python
.. |pr| replace:: pull request
.. |prs| replace:: pull requests
.. |psf| replace:: Python Software Foundation
.. |repo| replace:: repository
.. |repos| replace:: repositories
.. |RCC| replace:: RhodeCode Control
.. |RCE| replace:: RhodeCode Enterprise
.. |RCCE| replace:: RhodeCode Community
.. |RCEE| replace:: RhodeCode Enterprise
.. |RCX| replace:: RhodeCode Extensions
.. |RCT| replace:: RhodeCode Tools
.. |RCEBOLD| replace:: **RhodeCode Enterprise**
.. |RCEITALICS| replace:: `RhodeCode Enterprise`
.. |RNS| replace:: Release Notes
'''

View file

@ -1,132 +1,160 @@
# -*- coding: utf-8 -*-
# Configuration file for the Sphinx documentation builder.
#
# RhodeCode Enterprise documentation build configuration file, created by
# sphinx-quickstart on Tue Nov 4 11:48:37 2014.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
import sys
import os
import sys
import datetime
import sphinx_rtd_theme
# sphinx injects tags magically during build, we re-define it here to make linters happy
tags = tags # noqa
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('.'))
import common
sys.path.insert(0, os.path.abspath("."))
def _get_version():
with open("../rhodecode/VERSION") as f:
return f.read().strip()
now = datetime.datetime.today()
# The full project version, used as the replacement for |release| and e.g. in the HTML templates.
# For example, for the Python documentation, this may be something like 2.6.0rc1.
# If you dont need the separation provided between version and release, just set them both to the same value.
release = _get_version()
# The major project version, used as the replacement for |version|.
# For example, for the Python documentation, this may be something like 2.6.
version = ".".join(release.split(".", 2)[:2]) # First two parts of release
# General information about the project.
project = "RhodeCode Enterprise"
copyright = f"2010-{now.year}, RhodeCode GmbH"
author = "RhodeCode GmbH"
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.todo',
'sphinx.ext.imgmath'
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
"sphinx.ext.todo",
"sphinx.ext.imgmath",
]
intersphinx_mapping = {
'enterprise': ('https://docs.rhodecode.com/RhodeCode-Enterprise/', None),
'control': ('https://docs.rhodecode.com/RhodeCode-Control/', None),
"enterprise": ("https://docs.rhodecode.com/RhodeCode-Enterprise/", None),
"rcstack": ("https://docs.rhodecode.com/rcstack/", None),
"control": ("https://docs.rhodecode.com/RhodeCode-Control/", None),
}
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]
# The suffix of source filenames.
source_suffix = '.rst'
source_suffix = ".rst"
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
master_doc = "index"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
def _get_version():
with open('../rhodecode/VERSION') as f:
return f.read().strip()
# The full version, including alpha/beta/rc tags.
release = _get_version()
# The short X.Y version.
version = '.'.join(release.split('.', 2)[:2]) # First two parts of release
# General information about the project.
project = u'RhodeCode Enterprise %s ' % _get_version()
copyright = u'2010-{now.year}, RhodeCode GmbH'.format(
now=datetime.datetime.today())
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# language = None
rst_epilog = common.rst_epilog + """
rst_epilog = """
.. |async| replace:: asynchronous
.. |AE| replace:: Appenlight
.. |authtoken| replace:: Authentication Token
.. |authtokens| replace:: **Auth Tokens**
.. |RCCEshort| replace:: Community
.. |RCEEshort| replace:: Enterprise
.. |git| replace:: Git
.. |hg| replace:: Mercurial
.. |svn| replace:: Subversion
.. |LDAP| replace:: LDAP / Active Directory
.. |os| replace:: operating system
.. |OS| replace:: Operating System
.. |PY| replace:: Python
.. |pr| replace:: pull request
.. |prs| replace:: pull requests
.. |psf| replace:: Python Software Foundation
.. |repo| replace:: repository
.. |repos| replace:: repositories
.. |RCC| replace:: RhodeCode Control
.. |RCE| replace:: RhodeCode Enterprise
.. |RCCE| replace:: RhodeCode Community
.. |RCEE| replace:: RhodeCode Enterprise
.. |RCX| replace:: RhodeCode Extensions
.. |RCT| replace:: RhodeCode Tools
.. |RCEBOLD| replace:: **RhodeCode Enterprise**
.. |RCEITALICS| replace:: `RhodeCode Enterprise`
.. |RNS| replace:: Release Notes
"""
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = [
# Special directories
'_build',
'result',
"_build",
"result",
# Other RST files
'admin/rhodecode-backup.rst',
'issue-trackers/redmine.rst',
'known-issues/error-msg-guide.rst',
'tutorials/docs-build.rst',
'integrations/example-ext.py',
'collaboration/supported-workflows.rst',
"admin/rhodecode-backup.rst",
"issue-trackers/redmine.rst",
"known-issues/error-msg-guide.rst",
"tutorials/docs-build.rst",
"integrations/example-ext.py",
"collaboration/supported-workflows.rst",
]
# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
pygments_style = "sphinx"
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
keep_warnings = tags.has("dev")
@ -136,135 +164,138 @@ keep_warnings = tags.has("dev")
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#html_theme = 'rctheme'
html_theme = 'sphinx_rtd_theme'
html_theme = "furo"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
html_sidebars = {
'**': ['globaltoc.html'],
}
# html_logo = None
#html_sidebars = {
# "**": ["globaltoc.html"],
#}
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
html_favicon = 'images/favicon.ico'
html_favicon = "images/favicon.ico"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['static/css/add.css']
html_static_path = ["static/css/add.css"]
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
html_last_updated_fmt = " %H:%m %b %d, %Y"
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
html_show_sphinx = False
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'rhodecode-enterprise'
htmlhelp_basename = "rhodecode-enterprise"
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
'classoptions': ',oneside',
'babel': '\\usepackage[english]{babel}',
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
"classoptions": ",oneside",
"babel": "\\usepackage[english]{babel}",
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
('index', 'RhodeCodeEnterprise.tex', u'RhodeCode Enterprise',
u'RhodeCode GmbH', 'manual'),
(
"index",
"RhodeCodeEnterprise.tex",
"RhodeCode Enterprise",
"RhodeCode GmbH",
"manual",
),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# latex_use_parts = False
# If true, show page references after internal links.
latex_show_pagerefs = True
# If true, show URL addresses after external links.
latex_show_urls = 'footnote'
latex_show_urls = "footnote"
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# latex_domain_indices = True
# Mode for literal blocks wider than the frame. Can be
# overflow, shrink or truncate
@ -276,12 +307,11 @@ pdf_fit_mode = "truncate"
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'rhodecodeenterprise', u'RhodeCode Enterprise',
[u'RhodeCode GmbH'], 1)
("index", "rhodecodeenterprise", "RhodeCode Enterprise", ["RhodeCode GmbH"], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
@ -290,22 +320,28 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'RhodeCodeEnterprise', u'RhodeCode Enterprise',
u'RhodeCode Docs Team', 'RhodeCodeEnterprise', 'RhodeCode Docs Project',
'Miscellaneous'),
(
"index",
"RhodeCodeEnterprise",
"RhodeCode Enterprise",
"RhodeCode Docs Team",
"RhodeCodeEnterprise",
"RhodeCode Docs Project",
"Miscellaneous",
),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
# texinfo_no_detailmenu = False
# We want to see todo notes in case of a pre-release build of the documentation
todo_include_todos = tags.has("dev")

View file

@ -1,227 +0,0 @@
{ system ? builtins.currentSystem
}:
let
pkgs = import <nixpkgs> { inherit system; };
inherit (pkgs) fetchurl;
buildPythonPackage = pkgs.python27Packages.buildPythonPackage;
python = pkgs.python27Packages.python;
alabaster = buildPythonPackage {
name = "alabaster-0.7.11";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/3f/46/9346ea429931d80244ab7f11c4fce83671df0b7ae5a60247a2b588592c46/alabaster-0.7.11.tar.gz";
sha256 = "1mvm69xsn5xf1jc45kdq1mn0yq0pfn54mv2jcww4s1vwqx6iyfxn";
};
};
babel = buildPythonPackage {
name = "babel-2.6.0";
doCheck = false;
propagatedBuildInputs = [
pytz
];
src = fetchurl {
url = "https://files.pythonhosted.org/packages/be/cc/9c981b249a455fa0c76338966325fc70b7265521bad641bf2932f77712f4/Babel-2.6.0.tar.gz";
sha256 = "08rxmbx2s4irp0w0gmn498vns5xy0fagm0fg33xa772jiks51flc";
};
};
certifi = buildPythonPackage {
name = "certifi-2018.8.24";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/e1/0f/f8d5e939184547b3bdc6128551b831a62832713aa98c2ccdf8c47ecc7f17/certifi-2018.8.24.tar.gz";
sha256 = "0f0nhrj9mlrf79iway4578wrsgmjh0fmacl9zv8zjckdy7b90rip";
};
};
chardet = buildPythonPackage {
name = "chardet-3.0.4";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/fc/bb/a5768c230f9ddb03acc9ef3f0d4a3cf93462473795d18e9535498c8f929d/chardet-3.0.4.tar.gz";
sha256 = "1bpalpia6r5x1kknbk11p1fzph56fmmnp405ds8icksd3knr5aw4";
};
};
docutils = buildPythonPackage {
name = "docutils-0.14";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/84/f4/5771e41fdf52aabebbadecc9381d11dea0fa34e4759b4071244fa094804c/docutils-0.14.tar.gz";
sha256 = "0x22fs3pdmr42kvz6c654756wja305qv6cx1zbhwlagvxgr4xrji";
};
};
idna = buildPythonPackage {
name = "idna-2.7";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/65/c4/80f97e9c9628f3cac9b98bfca0402ede54e0563b56482e3e6e45c43c4935/idna-2.7.tar.gz";
sha256 = "05jam7d31767dr12x0rbvvs8lxnpb1mhdb2zdlfxgh83z6k3hjk8";
};
};
imagesize = buildPythonPackage {
name = "imagesize-1.1.0";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/41/f5/3cf63735d54aa9974e544aa25858d8f9670ac5b4da51020bbfc6aaade741/imagesize-1.1.0.tar.gz";
sha256 = "1dg3wn7qpwmhgqc0r9na2ding1wif9q5spz3j9zn2riwphc2k0zk";
};
};
jinja2 = buildPythonPackage {
name = "jinja2-2.9.6";
doCheck = false;
propagatedBuildInputs = [
markupsafe
];
src = fetchurl {
url = "https://files.pythonhosted.org/packages/90/61/f820ff0076a2599dd39406dcb858ecb239438c02ce706c8e91131ab9c7f1/Jinja2-2.9.6.tar.gz";
sha256 = "1zzrkywhziqffrzks14kzixz7nd4yh2vc0fb04a68vfd2ai03anx";
};
};
markupsafe = buildPythonPackage {
name = "markupsafe-1.0";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/4d/de/32d741db316d8fdb7680822dd37001ef7a448255de9699ab4bfcbdf4172b/MarkupSafe-1.0.tar.gz";
sha256 = "0rdn1s8x9ni7ss8rfiacj7x1085lx8mh2zdwqslnw8xc3l4nkgm6";
};
};
packaging = buildPythonPackage {
name = "packaging-17.1";
doCheck = false;
propagatedBuildInputs = [
pyparsing
six
];
src = fetchurl {
url = "https://files.pythonhosted.org/packages/77/32/439f47be99809c12ef2da8b60a2c47987786d2c6c9205549dd6ef95df8bd/packaging-17.1.tar.gz";
sha256 = "0nrpayk8kij1zm9sjnk38ldz3a6705ggvw8ljylqbrb4vmqbf6gh";
};
};
pygments = buildPythonPackage {
name = "pygments-2.2.0";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/71/2a/2e4e77803a8bd6408a2903340ac498cb0a2181811af7c9ec92cb70b0308a/Pygments-2.2.0.tar.gz";
sha256 = "1k78qdvir1yb1c634nkv6rbga8wv4289xarghmsbbvzhvr311bnv";
};
};
pyparsing = buildPythonPackage {
name = "pyparsing-2.2.0";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/3c/ec/a94f8cf7274ea60b5413df054f82a8980523efd712ec55a59e7c3357cf7c/pyparsing-2.2.0.tar.gz";
sha256 = "016b9gh606aa44sq92jslm89bg874ia0yyiyb643fa6dgbsbqch8";
};
};
pytz = buildPythonPackage {
name = "pytz-2018.4";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/10/76/52efda4ef98e7544321fd8d5d512e11739c1df18b0649551aeccfb1c8376/pytz-2018.4.tar.gz";
sha256 = "0jgpqx3kk2rhv81j1izjxvmx8d0x7hzs1857pgqnixic5wq2ar60";
};
};
requests = buildPythonPackage {
name = "requests-2.19.1";
doCheck = false;
propagatedBuildInputs = [
chardet
idna
urllib3
certifi
];
src = fetchurl {
url = "https://files.pythonhosted.org/packages/54/1f/782a5734931ddf2e1494e4cd615a51ff98e1879cbe9eecbdfeaf09aa75e9/requests-2.19.1.tar.gz";
sha256 = "0snf8xxdzsgh1x2zv3vilvbrv9jbpmnfagzzb1rjmmvflckdh8pc";
};
};
six = buildPythonPackage {
name = "six-1.11.0";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/16/d8/bc6316cf98419719bd59c91742194c111b6f2e85abac88e496adefaf7afe/six-1.11.0.tar.gz";
sha256 = "1scqzwc51c875z23phj48gircqjgnn3af8zy2izjwmnlxrxsgs3h";
};
};
snowballstemmer = buildPythonPackage {
name = "snowballstemmer-1.2.1";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/20/6b/d2a7cb176d4d664d94a6debf52cd8dbae1f7203c8e42426daa077051d59c/snowballstemmer-1.2.1.tar.gz";
sha256 = "0a0idq4y5frv7qsg2x62jd7rd272749xk4x99misf5rcifk2d7wi";
};
};
sphinx = buildPythonPackage {
name = "sphinx-1.7.8";
doCheck = false;
propagatedBuildInputs = [
six
jinja2
pygments
docutils
snowballstemmer
babel
alabaster
imagesize
requests
setuptools
packaging
sphinxcontrib-websupport
typing
];
src = fetchurl {
url = "https://files.pythonhosted.org/packages/ac/54/4ef326d0c654da1ed91341a7a1f43efc18a8c770ddd2b8e45df97cb79d82/Sphinx-1.7.8.tar.gz";
sha256 = "1ryz0w4c31930f1br2sjwrxwx9cmsy7cqdb0d81g98n9bj250w50";
};
};
sphinx-rtd-theme = buildPythonPackage {
name = "sphinx-rtd-theme-0.4.1";
doCheck = false;
propagatedBuildInputs = [
sphinx
];
src = fetchurl {
url = "https://files.pythonhosted.org/packages/f2/b0/a1933d792b806118ddbca6699f2e2c844d9b1b16e84a89d7effd5cd2a800/sphinx_rtd_theme-0.4.1.tar.gz";
sha256 = "1xkyqam8dzbjaymdyvkiif85m4y3jf8crdiwlgcfp8gqcj57aj9v";
};
};
sphinxcontrib-websupport = buildPythonPackage {
name = "sphinxcontrib-websupport-1.1.0";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/07/7a/e74b06dce85555ffee33e1d6b7381314169ebf7e31b62c18fcb2815626b7/sphinxcontrib-websupport-1.1.0.tar.gz";
sha256 = "1ff3ix76xi1y6m99qxhaq5161ix9swwzydilvdya07mgbcvpzr4x";
};
};
typing = buildPythonPackage {
name = "typing-3.6.6";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/bf/9b/2bf84e841575b633d8d91ad923e198a415e3901f228715524689495b4317/typing-3.6.6.tar.gz";
sha256 = "0ba9acs4awx15bf9v3nrs781msbd2nx826906nj6fqks2bvca9s0";
};
};
urllib3 = buildPythonPackage {
name = "urllib3-1.23";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/3c/d2/dc5471622bd200db1cd9319e02e71bc655e9ea27b8e0ce65fc69de0dac15/urllib3-1.23.tar.gz";
sha256 = "1bvbd35q3zdcd7gsv38fwpizy7p06dr0154g5gfybrvnbvhwb2m6";
};
};
# Avoid that setuptools is replaced, this leads to trouble
# with buildPythonPackage.
setuptools = pkgs.python27Packages.setuptools;
in python.buildEnv.override {
inherit python;
extraLibs = [
sphinx
sphinx-rtd-theme
];
}

View file

@ -68,7 +68,7 @@ In order to install and configure Celery, follow these steps:
celery.broker_url = redis://localhost:6379/8
# maximum tasks to execute before worker restart
celery.max_tasks_per_child = 100
celery.max_tasks_per_child = 20
## tasks will never be sent to the queue, but executed locally instead.
celery.task_always_eager = false

View file

@ -1,14 +0,0 @@
.. _integrations-hipchat:
Hipchat integration
===================
In order to set a Hipchat integration up, it is necessary to obtain the Hipchat
service url by:
1. Log into Hipchat (https://your-hipchat.hipchat.com/)
2. Go to *Integrations* -> *Build your own*
3. Select a room to post notifications to and save it
Hipchat will create a URL for you to use in your integration as outlined in
:ref:`creating-integrations`.

View file

@ -16,7 +16,6 @@ Type/Name RhodeCode Edition Description
================================ ================== ========================================
:ref:`integrations-webhook` |RCCEshort| Trigger events as `json` to a custom url
:ref:`integrations-slack` |RCCEshort| Integrate with https://slack.com/
:ref:`integrations-hipchat` |RCCEshort| Integrate with https://www.hipchat.com/
:ref:`integrations-email` |RCCEshort| Send repo push commits by email
:ref:`integrations-ci` |RCCEshort| Trigger Builds for Common CI Systems
:ref:`integrations-rcextensions` |RCCEshort| Advanced low-level integration framework
@ -50,7 +49,6 @@ See pages specific to each type of integration for more instructions:
.. toctree::
slack
hipchat
redmine
jira
webhook

View file

@ -1,3 +0,0 @@
[pip2nix]
requirements = -r ./requirements_docs.txt
output = ./python-packages-generated.nix

View file

@ -1,221 +0,0 @@
# Generated by pip2nix 0.8.0.dev1
# See https://github.com/johbo/pip2nix
{ pkgs, fetchurl, fetchgit, fetchhg }:
self: super: {
"alabaster" = super.buildPythonPackage {
name = "alabaster-0.7.12";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/cc/b4/ed8dcb0d67d5cfb7f83c4d5463a7614cb1d078ad7ae890c9143edebbf072/alabaster-0.7.12.tar.gz";
sha256 = "00nwwjj2d2ym4s2kk217x7jkx1hnczc3fvm8yxbqmsp6b0nxfqd6";
};
};
"babel" = super.buildPythonPackage {
name = "babel-2.6.0";
doCheck = false;
propagatedBuildInputs = [
self."pytz"
];
src = fetchurl {
url = "https://files.pythonhosted.org/packages/be/cc/9c981b249a455fa0c76338966325fc70b7265521bad641bf2932f77712f4/Babel-2.6.0.tar.gz";
sha256 = "08rxmbx2s4irp0w0gmn498vns5xy0fagm0fg33xa772jiks51flc";
};
};
"certifi" = super.buildPythonPackage {
name = "certifi-2018.11.29";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/55/54/3ce77783acba5979ce16674fc98b1920d00b01d337cfaaf5db22543505ed/certifi-2018.11.29.tar.gz";
sha256 = "1dvccavd2fzq4j37w0sznylp92ps14zi6gvlxzm23in0yhzciya7";
};
};
"chardet" = super.buildPythonPackage {
name = "chardet-3.0.4";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/fc/bb/a5768c230f9ddb03acc9ef3f0d4a3cf93462473795d18e9535498c8f929d/chardet-3.0.4.tar.gz";
sha256 = "1bpalpia6r5x1kknbk11p1fzph56fmmnp405ds8icksd3knr5aw4";
};
};
"docutils" = super.buildPythonPackage {
name = "docutils-0.14";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/84/f4/5771e41fdf52aabebbadecc9381d11dea0fa34e4759b4071244fa094804c/docutils-0.14.tar.gz";
sha256 = "0x22fs3pdmr42kvz6c654756wja305qv6cx1zbhwlagvxgr4xrji";
};
};
"idna" = super.buildPythonPackage {
name = "idna-2.7";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/65/c4/80f97e9c9628f3cac9b98bfca0402ede54e0563b56482e3e6e45c43c4935/idna-2.7.tar.gz";
sha256 = "05jam7d31767dr12x0rbvvs8lxnpb1mhdb2zdlfxgh83z6k3hjk8";
};
};
"imagesize" = super.buildPythonPackage {
name = "imagesize-1.1.0";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/41/f5/3cf63735d54aa9974e544aa25858d8f9670ac5b4da51020bbfc6aaade741/imagesize-1.1.0.tar.gz";
sha256 = "1dg3wn7qpwmhgqc0r9na2ding1wif9q5spz3j9zn2riwphc2k0zk";
};
};
"jinja2" = super.buildPythonPackage {
name = "jinja2-2.9.6";
doCheck = false;
propagatedBuildInputs = [
self."markupsafe"
];
src = fetchurl {
url = "https://files.pythonhosted.org/packages/90/61/f820ff0076a2599dd39406dcb858ecb239438c02ce706c8e91131ab9c7f1/Jinja2-2.9.6.tar.gz";
sha256 = "1zzrkywhziqffrzks14kzixz7nd4yh2vc0fb04a68vfd2ai03anx";
};
};
"markupsafe" = super.buildPythonPackage {
name = "markupsafe-1.0";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/4d/de/32d741db316d8fdb7680822dd37001ef7a448255de9699ab4bfcbdf4172b/MarkupSafe-1.0.tar.gz";
sha256 = "0rdn1s8x9ni7ss8rfiacj7x1085lx8mh2zdwqslnw8xc3l4nkgm6";
};
};
"packaging" = super.buildPythonPackage {
name = "packaging-18.0";
doCheck = false;
propagatedBuildInputs = [
self."pyparsing"
self."six"
];
src = fetchurl {
url = "https://files.pythonhosted.org/packages/cf/50/1f10d2626df0aa97ce6b62cf6ebe14f605f4e101234f7748b8da4138a8ed/packaging-18.0.tar.gz";
sha256 = "01wq9c53ix5rz6qg2c98gy8n4ff768rmanifm8m5jpjiaizj51h8";
};
};
"pygments" = super.buildPythonPackage {
name = "pygments-2.3.0";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/63/a2/91c31c4831853dedca2a08a0f94d788fc26a48f7281c99a303769ad2721b/Pygments-2.3.0.tar.gz";
sha256 = "1z34ms51dh4jq4h3cizp7vd1dmsxcbvffkjsd2xxfav22nn6lrl2";
};
};
"pyparsing" = super.buildPythonPackage {
name = "pyparsing-2.3.0";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/d0/09/3e6a5eeb6e04467b737d55f8bba15247ac0876f98fae659e58cd744430c6/pyparsing-2.3.0.tar.gz";
sha256 = "14k5v7n3xqw8kzf42x06bzp184spnlkya2dpjyflax6l3yrallzk";
};
};
"pytz" = super.buildPythonPackage {
name = "pytz-2018.4";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/10/76/52efda4ef98e7544321fd8d5d512e11739c1df18b0649551aeccfb1c8376/pytz-2018.4.tar.gz";
sha256 = "0jgpqx3kk2rhv81j1izjxvmx8d0x7hzs1857pgqnixic5wq2ar60";
};
};
"requests" = super.buildPythonPackage {
name = "requests-2.20.1";
doCheck = false;
propagatedBuildInputs = [
self."chardet"
self."idna"
self."urllib3"
self."certifi"
];
src = fetchurl {
url = "https://files.pythonhosted.org/packages/40/35/298c36d839547b50822985a2cf0611b3b978a5ab7a5af5562b8ebe3e1369/requests-2.20.1.tar.gz";
sha256 = "0qzj6cgv3k9wyj7wlxgz7xq0cfg4jbbkfm24pp8dnhczwl31527a";
};
};
"setuptools" = super.buildPythonPackage {
name = "setuptools-40.6.2";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/b0/d1/8acb42f391cba52e35b131e442e80deffbb8d0676b93261d761b1f0ef8fb/setuptools-40.6.2.zip";
sha256 = "0r2c5hapirlzm34h7pl1lgkm6gk7bcrlrdj28qgsvaqg3f74vfw6";
};
};
"six" = super.buildPythonPackage {
name = "six-1.11.0";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/16/d8/bc6316cf98419719bd59c91742194c111b6f2e85abac88e496adefaf7afe/six-1.11.0.tar.gz";
sha256 = "1scqzwc51c875z23phj48gircqjgnn3af8zy2izjwmnlxrxsgs3h";
};
};
"snowballstemmer" = super.buildPythonPackage {
name = "snowballstemmer-1.2.1";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/20/6b/d2a7cb176d4d664d94a6debf52cd8dbae1f7203c8e42426daa077051d59c/snowballstemmer-1.2.1.tar.gz";
sha256 = "0a0idq4y5frv7qsg2x62jd7rd272749xk4x99misf5rcifk2d7wi";
};
};
"sphinx" = super.buildPythonPackage {
name = "sphinx-1.8.2";
doCheck = false;
propagatedBuildInputs = [
self."six"
self."jinja2"
self."pygments"
self."docutils"
self."snowballstemmer"
self."babel"
self."alabaster"
self."imagesize"
self."requests"
self."setuptools"
self."packaging"
self."sphinxcontrib-websupport"
self."typing"
];
src = fetchurl {
url = "https://files.pythonhosted.org/packages/4c/ea/7388faba7cf02999e1bc42f6a8eb1ea0120aec3dd93474cee21cea2d693f/Sphinx-1.8.2.tar.gz";
sha256 = "1sia2h5rfzy76rbsd69ghr8bbidhsjzzinf3f523dcmivp5k41qj";
};
};
"sphinx-rtd-theme" = super.buildPythonPackage {
name = "sphinx-rtd-theme-0.4.1";
doCheck = false;
propagatedBuildInputs = [
self."sphinx"
];
src = fetchurl {
url = "https://files.pythonhosted.org/packages/f2/b0/a1933d792b806118ddbca6699f2e2c844d9b1b16e84a89d7effd5cd2a800/sphinx_rtd_theme-0.4.1.tar.gz";
sha256 = "1xkyqam8dzbjaymdyvkiif85m4y3jf8crdiwlgcfp8gqcj57aj9v";
};
};
"sphinxcontrib-websupport" = super.buildPythonPackage {
name = "sphinxcontrib-websupport-1.1.0";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/07/7a/e74b06dce85555ffee33e1d6b7381314169ebf7e31b62c18fcb2815626b7/sphinxcontrib-websupport-1.1.0.tar.gz";
sha256 = "1ff3ix76xi1y6m99qxhaq5161ix9swwzydilvdya07mgbcvpzr4x";
};
};
"typing" = super.buildPythonPackage {
name = "typing-3.6.6";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/bf/9b/2bf84e841575b633d8d91ad923e198a415e3901f228715524689495b4317/typing-3.6.6.tar.gz";
sha256 = "0ba9acs4awx15bf9v3nrs781msbd2nx826906nj6fqks2bvca9s0";
};
};
"urllib3" = super.buildPythonPackage {
name = "urllib3-1.24.1";
doCheck = false;
src = fetchurl {
url = "https://files.pythonhosted.org/packages/b1/53/37d82ab391393565f2f831b8eedbffd57db5a718216f82f1a8b4d381a1c1/urllib3-1.24.1.tar.gz";
sha256 = "08lwd9f3hqznyf32vnzwvp87pchx062nkbgyrf67rwlkgj0jk5fy";
};
};
### Test requirements
}

View file

@ -1,8 +1,11 @@
sphinx==1.8.2
six==1.11.0
sphinx_rtd_theme==0.4.1
docutils==0.16.0
pygments==2.3.0
markupsafe==1.0.0
jinja2==2.9.6
pytz==2018.4
sphinx==7.2.6
furo==2023.9.10
sphinx-press-theme==0.8.0
sphinx-rtd-theme==1.3.0
pygments==2.16.1
docutils<0.19
markupsafe==2.1.3
jinja2==3.1.2

View file

@ -41,7 +41,6 @@
"<%= dirs.js.node_modules %>/sticky-sidebar/dist/jquery.sticky-sidebar.min.js",
"<%= dirs.js.node_modules %>/waypoints/lib/noframework.waypoints.min.js",
"<%= dirs.js.node_modules %>/waypoints/lib/jquery.waypoints.min.js",
"<%= dirs.js.node_modules %>/appenlight-client/appenlight-client.min.js",
"<%= dirs.js.src %>/logging.js",
"<%= dirs.js.src %>/bootstrap.js",
"<%= dirs.js.src %>/i18n_utils.js",

View file

@ -1,62 +1,61 @@
{
"name": "rhodecode-enterprise",
"version": "2.0.0",
"version": "5.0.0",
"private": true,
"description" : "RhodeCode JS packaged",
"description": "RhodeCode JS packaged",
"license": "SEE LICENSE IN LICENSE.txt",
"repository" : {
"type" : "hg",
"url" : "https://code.rhodecode.com/rhodecode-enterprise-ce"
"repository": {
"type": "hg",
"url": "https://code.rhodecode.com/rhodecode-enterprise-ce"
},
"devDependencies": {
"appenlight-client": "git+https://git@github.com/AppEnlight/appenlight-client-js.git#0.5.1",
"clipboard": "^2.0.1",
"exports-loader": "^0.6.4",
"favico.js": "^0.3.10",
"dropzone": "^5.5.0",
"grunt": "^0.4.5",
"grunt-cli": "^1.3.1",
"grunt-contrib-concat": "^0.5.1",
"grunt-contrib-copy": "^1.0.0",
"grunt-contrib-jshint": "^0.12.0",
"grunt-contrib-less": "^1.1.0",
"grunt-contrib-watch": "^0.6.1",
"grunt-webpack": "^3.1.3",
"grunt-contrib-uglify": "^4.0.1",
"sweetalert2": "^9.10.12",
"jquery": "1.11.3",
"mark.js": "8.11.1",
"jshint": "^2.9.1-rc3",
"moment": "^2.18.1",
"mousetrap": "^1.6.1",
"qrious": "^4.0.2",
"sticky-sidebar": "3.3.1",
"waypoints": "4.0.1",
"webpack": "4.23.1",
"webpack-cli": "3.1.2",
"@polymer/iron-a11y-keys": "^3.0.0",
"@polymer/iron-ajax": "^3.0.0",
"@polymer/iron-autogrow-textarea": "^3.0.0",
"@polymer/paper-button": "^3.0.0",
"@polymer/paper-spinner": "^3.0.0",
"@polymer/paper-toast": "^3.0.0",
"@polymer/paper-toggle-button": "^3.0.0",
"@polymer/paper-tooltip": "^3.0.0",
"@polymer/polymer": "^3.0.0",
"@webcomponents/webcomponentsjs": "^2.0.0",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.2",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-preset-env": "^1.6.0",
"clipboard": "^2.0.1",
"copy-webpack-plugin": "^4.4.2",
"css-loader": "^0.28.11",
"dropzone": "^5.5.0",
"exports-loader": "^0.6.4",
"favico.js": "^0.3.10",
"grunt": "^0.4.5",
"grunt-cli": "^1.4.3",
"grunt-contrib-concat": "^0.5.1",
"grunt-contrib-copy": "^1.0.0",
"grunt-contrib-jshint": "^0.12.0",
"grunt-contrib-less": "^1.1.0",
"grunt-contrib-uglify": "^4.0.1",
"grunt-contrib-watch": "^0.6.1",
"grunt-webpack": "^3.1.3",
"html-loader": "^0.4.4",
"html-webpack-plugin": "^3.2.0",
"imports-loader": "^0.7.1",
"jquery": "1.11.3",
"jshint": "^2.9.1-rc3",
"mark.js": "8.11.1",
"moment": "^2.18.1",
"mousetrap": "^1.6.1",
"polymer-webpack-loader": "^2.0.1",
"style-loader": "^0.21.0",
"webpack-uglify-js-plugin": "^1.1.9",
"qrious": "^4.0.2",
"raw-loader": "1.0.0-beta.0",
"sticky-sidebar": "3.3.1",
"style-loader": "^0.21.0",
"sweetalert2": "^9.10.12",
"ts-loader": "^1.3.3",
"@webcomponents/webcomponentsjs": "^2.0.0",
"@polymer/polymer": "^3.0.0",
"@polymer/paper-button": "^3.0.0",
"@polymer/paper-spinner": "^3.0.0",
"@polymer/paper-tooltip": "^3.0.0",
"@polymer/paper-toast": "^3.0.0",
"@polymer/paper-toggle-button": "^3.0.0",
"@polymer/iron-ajax": "^3.0.0",
"@polymer/iron-autogrow-textarea": "^3.0.0",
"@polymer/iron-a11y-keys": "^3.0.0"
"waypoints": "4.0.1",
"webpack": "4.23.1",
"webpack-cli": "3.1.2",
"webpack-uglify-js-plugin": "^1.1.9"
}
}

View file

@ -1,3 +0,0 @@
[pip2nix]
requirements = ., -r ./requirements.txt, -r ./requirements_pinned.txt
output = ./pkgs/python-packages.nix

View file

@ -1,57 +0,0 @@
==============================
Generate the Nix expressions
==============================
Details can be found in the repository of `RhodeCode Enterprise CE`_ inside of
the file `docs/contributing/dependencies.rst`.
Start the environment as follows:
.. code:: shell
nix-shell pkgs/shell-generate.nix
Python dependencies
===================
.. code:: shell
pip2nix generate --licenses
# or
nix-shell pkgs/shell-generate.nix --command "pip2nix generate --licenses"
NodeJS dependencies
===================
Generate node-packages.nix file with all dependencies from NPM and package.json file
This should be run before entering nix-shell.
The sed at the end fixes a bug with http rewrite of re-generated packages
.. code:: shell
rm -rf node_modules &&
nix-shell pkgs/shell-generate.nix --command "
node2nix --input package.json \
-o pkgs/node-packages.nix \
-e pkgs/node-env.nix \
-c pkgs/node-default.nix \
-d --flatten --nodejs-8 " &&
sed -i -e 's/http:\/\//https:\/\//g' pkgs/node-packages.nix
Generate license data
=====================
.. code:: shell
nix-build pkgs/license-generate.nix -o result-license && cat result-license/licenses.json | python -m json.tool > rhodecode/config/licenses.json
.. Links
.. _RhodeCode Enterprise CE: https://code.rhodecode.com/rhodecode-enterprise-ce

View file

@ -1,159 +0,0 @@
# Utility to generate the license information
#
# Usage:
#
# nix-build license.nix -o result-license
#
# Afterwards ./result-license will contain the license information as JSON files.
#
#
# Overview
#
# Uses two steps to get the relevant license information:
#
# 1. Walk down the derivations based on "buildInputs" and
# "propagatedBuildInputs". This results in all dependencies based on the nix
# declartions.
#
# 2. Build Enterprise and query nix-store to get a list of runtime
# dependencies. The results from step 1 are then limited to the ones which
# are in this list.
#
# The result is then available in ./result-license/license.json.
#
let
nixpkgs = import <nixpkgs> {};
stdenv = nixpkgs.stdenv;
# Enterprise as simple as possible, goal here is just to identify the runtime
# dependencies. Ideally we could avoid building Enterprise at all and somehow
# figure it out without calling into nix-store.
enterprise = import ../default.nix {
doCheck = false;
};
# For a given derivation, return the list of all dependencies
drvToDependencies = drv: nixpkgs.lib.flatten [
drv.buildInputs or []
drv.propagatedBuildInputs or []
];
# Transform the given derivation into the meta information which we need in
# the resulting JSON files.
drvToMeta = drv: {
name = drv.name or drv;
license = if drv ? meta.license then drv.meta.license else "UNKNOWN";
};
# Walk the tree of buildInputs and propagatedBuildInputs and return it as a
# flat list. Duplicates are avoided.
listDrvDependencies = drv: let
addElement = element: seen:
if (builtins.elem element seen)
then seen
else let
newSeen = seen ++ [ element ];
newDeps = drvToDependencies element;
in nixpkgs.lib.fold addElement newSeen newDeps;
initialElements = drvToDependencies drv;
in nixpkgs.lib.fold addElement [] initialElements;
# Reads in a file with store paths and returns a list of derivation names.
#
# Reads the file, splits the lines, then removes the prefix, so that we
# end up with a list of derivation names in the end.
storePathsToDrvNames = srcPath: let
rawStorePaths = nixpkgs.lib.removeSuffix "\n" (
builtins.readFile srcPath);
storePaths = nixpkgs.lib.splitString "\n" rawStorePaths;
storePathPrefix = (
builtins.stringLength "/nix/store/afafafafafafafafafafafafafafafaf-");
storePathToName = path:
builtins.substring storePathPrefix (builtins.stringLength path) path;
in (map storePathToName storePaths);
in rec {
# Build Enterprise and call nix-store to retrieve the runtime
# dependencies. The result is available in the nix store.
runtimeDependencies = stdenv.mkDerivation {
name = "runtime-dependencies";
buildInputs = [
# Needed to query the store
nixpkgs.nix
];
unpackPhase = ''
echo "Nothing to unpack"
'';
buildPhase = ''
# Get a list of runtime dependencies
nix-store -q --references ${enterprise} > nix-store-references
'';
installPhase = ''
mkdir -p $out
cp -v nix-store-references $out/
'';
};
# Produce the license overview files.
result = let
# Dependencies according to the nix-store
runtimeDependencyNames = (
storePathsToDrvNames "${runtimeDependencies}/nix-store-references");
# Dependencies based on buildInputs and propagatedBuildInputs
enterpriseAllDependencies = listDrvDependencies enterprise;
enterpriseRuntimeDependencies = let
elemName = element: element.name or "UNNAMED";
isRuntime = element: builtins.elem (elemName element) runtimeDependencyNames;
in builtins.filter isRuntime enterpriseAllDependencies;
# Extract relevant meta information
enterpriseAllLicenses = map drvToMeta enterpriseAllDependencies;
enterpriseRuntimeLicenses = map drvToMeta enterpriseRuntimeDependencies;
in stdenv.mkDerivation {
name = "licenses";
buildInputs = [];
unpackPhase = ''
echo "Nothing to unpack"
'';
buildPhase = ''
mkdir build
# Copy list of runtime dependencies for the Python processor
cp "${runtimeDependencies}/nix-store-references" ./build/nix-store-references
# All licenses which we found by walking buildInputs and
# propagatedBuildInputs
cat > build/all-licenses.json <<EOF
${builtins.toJSON enterpriseAllLicenses}
EOF
# License information for our runtime dependencies only. Basically all
# licenses limited to the items which where also reported by nix-store as
# a dependency.
cat > build/licenses.json <<EOF
${builtins.toJSON enterpriseRuntimeLicenses}
EOF
'';
installPhase = ''
mkdir -p $out
# Store it all, that helps when things go wrong
cp -rv ./build/* $out
'';
};
}

View file

@ -1,17 +0,0 @@
{ pkgs
, pythonPackages
}:
rec {
pip2nix-src = pkgs.fetchzip {
url = https://github.com/johbo/pip2nix/archive/51e6fdae34d0e8ded9efeef7a8601730249687a6.tar.gz;
sha256 = "02a4jjgi7lsvf8mhrxsd56s9a3yg20081rl9bgc2m84w60v2gbz2";
};
pip2nix = import pip2nix-src {
inherit
pkgs
pythonPackages;
};
}

View file

@ -1,17 +0,0 @@
# This file has been generated by node2nix 1.6.0. Do not edit!
{pkgs ? import <nixpkgs> {
inherit system;
}, system ? builtins.currentSystem, nodejs ? pkgs."nodejs-8_x"}:
let
nodeEnv = import ./node-env.nix {
inherit (pkgs) stdenv python2 utillinux runCommand writeTextFile;
inherit nodejs;
libtool = if pkgs.stdenv.isDarwin then pkgs.darwin.cctools else null;
};
in
import ./node-packages.nix {
inherit (pkgs) fetchurl fetchgit;
inherit nodeEnv;
}

View file

@ -1,542 +0,0 @@
# This file originates from node2nix
{stdenv, nodejs, python2, utillinux, libtool, runCommand, writeTextFile}:
let
python = if nodejs ? python then nodejs.python else python2;
# Create a tar wrapper that filters all the 'Ignoring unknown extended header keyword' noise
tarWrapper = runCommand "tarWrapper" {} ''
mkdir -p $out/bin
cat > $out/bin/tar <<EOF
#! ${stdenv.shell} -e
$(type -p tar) "\$@" --warning=no-unknown-keyword
EOF
chmod +x $out/bin/tar
'';
# Function that generates a TGZ file from a NPM project
buildNodeSourceDist =
{ name, version, src, ... }:
stdenv.mkDerivation {
name = "node-tarball-${name}-${version}";
inherit src;
buildInputs = [ nodejs ];
buildPhase = ''
export HOME=$TMPDIR
tgzFile=$(npm pack | tail -n 1) # Hooks to the pack command will add output (https://docs.npmjs.com/misc/scripts)
'';
installPhase = ''
mkdir -p $out/tarballs
mv $tgzFile $out/tarballs
mkdir -p $out/nix-support
echo "file source-dist $out/tarballs/$tgzFile" >> $out/nix-support/hydra-build-products
'';
};
includeDependencies = {dependencies}:
stdenv.lib.optionalString (dependencies != [])
(stdenv.lib.concatMapStrings (dependency:
''
# Bundle the dependencies of the package
mkdir -p node_modules
cd node_modules
# Only include dependencies if they don't exist. They may also be bundled in the package.
if [ ! -e "${dependency.name}" ]
then
${composePackage dependency}
fi
cd ..
''
) dependencies);
# Recursively composes the dependencies of a package
composePackage = { name, packageName, src, dependencies ? [], ... }@args:
''
DIR=$(pwd)
cd $TMPDIR
unpackFile ${src}
# Make the base dir in which the target dependency resides first
mkdir -p "$(dirname "$DIR/${packageName}")"
if [ -f "${src}" ]
then
# Figure out what directory has been unpacked
packageDir="$(find . -maxdepth 1 -type d | tail -1)"
# Restore write permissions to make building work
find "$packageDir" -type d -print0 | xargs -0 chmod u+x
chmod -R u+w "$packageDir"
# Move the extracted tarball into the output folder
mv "$packageDir" "$DIR/${packageName}"
elif [ -d "${src}" ]
then
# Get a stripped name (without hash) of the source directory.
# On old nixpkgs it's already set internally.
if [ -z "$strippedName" ]
then
strippedName="$(stripHash ${src})"
fi
# Restore write permissions to make building work
chmod -R u+w "$strippedName"
# Move the extracted directory into the output folder
mv "$strippedName" "$DIR/${packageName}"
fi
# Unset the stripped name to not confuse the next unpack step
unset strippedName
# Include the dependencies of the package
cd "$DIR/${packageName}"
${includeDependencies { inherit dependencies; }}
cd ..
${stdenv.lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."}
'';
pinpointDependencies = {dependencies, production}:
let
pinpointDependenciesFromPackageJSON = writeTextFile {
name = "pinpointDependencies.js";
text = ''
var fs = require('fs');
var path = require('path');
function resolveDependencyVersion(location, name) {
if(location == process.env['NIX_STORE']) {
return null;
} else {
var dependencyPackageJSON = path.join(location, "node_modules", name, "package.json");
if(fs.existsSync(dependencyPackageJSON)) {
var dependencyPackageObj = JSON.parse(fs.readFileSync(dependencyPackageJSON));
if(dependencyPackageObj.name == name) {
return dependencyPackageObj.version;
}
} else {
return resolveDependencyVersion(path.resolve(location, ".."), name);
}
}
}
function replaceDependencies(dependencies) {
if(typeof dependencies == "object" && dependencies !== null) {
for(var dependency in dependencies) {
var resolvedVersion = resolveDependencyVersion(process.cwd(), dependency);
if(resolvedVersion === null) {
process.stderr.write("WARNING: cannot pinpoint dependency: "+dependency+", context: "+process.cwd()+"\n");
} else {
dependencies[dependency] = resolvedVersion;
}
}
}
}
/* Read the package.json configuration */
var packageObj = JSON.parse(fs.readFileSync('./package.json'));
/* Pinpoint all dependencies */
replaceDependencies(packageObj.dependencies);
if(process.argv[2] == "development") {
replaceDependencies(packageObj.devDependencies);
}
replaceDependencies(packageObj.optionalDependencies);
/* Write the fixed package.json file */
fs.writeFileSync("package.json", JSON.stringify(packageObj, null, 2));
'';
};
in
''
node ${pinpointDependenciesFromPackageJSON} ${if production then "production" else "development"}
${stdenv.lib.optionalString (dependencies != [])
''
if [ -d node_modules ]
then
cd node_modules
${stdenv.lib.concatMapStrings (dependency: pinpointDependenciesOfPackage dependency) dependencies}
cd ..
fi
''}
'';
# Recursively traverses all dependencies of a package and pinpoints all
# dependencies in the package.json file to the versions that are actually
# being used.
pinpointDependenciesOfPackage = { packageName, dependencies ? [], production ? true, ... }@args:
''
if [ -d "${packageName}" ]
then
cd "${packageName}"
${pinpointDependencies { inherit dependencies production; }}
cd ..
${stdenv.lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."}
fi
'';
# Extract the Node.js source code which is used to compile packages with
# native bindings
nodeSources = runCommand "node-sources" {} ''
tar --no-same-owner --no-same-permissions -xf ${nodejs.src}
mv node-* $out
'';
# Script that adds _integrity fields to all package.json files to prevent NPM from consulting the cache (that is empty)
addIntegrityFieldsScript = writeTextFile {
name = "addintegrityfields.js";
text = ''
var fs = require('fs');
var path = require('path');
function augmentDependencies(baseDir, dependencies) {
for(var dependencyName in dependencies) {
var dependency = dependencies[dependencyName];
// Open package.json and augment metadata fields
var packageJSONDir = path.join(baseDir, "node_modules", dependencyName);
var packageJSONPath = path.join(packageJSONDir, "package.json");
if(fs.existsSync(packageJSONPath)) { // Only augment packages that exist. Sometimes we may have production installs in which development dependencies can be ignored
console.log("Adding metadata fields to: "+packageJSONPath);
var packageObj = JSON.parse(fs.readFileSync(packageJSONPath));
if(dependency.integrity) {
packageObj["_integrity"] = dependency.integrity;
} else {
packageObj["_integrity"] = "sha1-000000000000000000000000000="; // When no _integrity string has been provided (e.g. by Git dependencies), add a dummy one. It does not seem to harm and it bypasses downloads.
}
packageObj["_resolved"] = dependency.version; // Set the resolved version to the version identifier. This prevents NPM from cloning Git repositories.
fs.writeFileSync(packageJSONPath, JSON.stringify(packageObj, null, 2));
}
// Augment transitive dependencies
if(dependency.dependencies !== undefined) {
augmentDependencies(packageJSONDir, dependency.dependencies);
}
}
}
if(fs.existsSync("./package-lock.json")) {
var packageLock = JSON.parse(fs.readFileSync("./package-lock.json"));
if(packageLock.lockfileVersion !== 1) {
process.stderr.write("Sorry, I only understand lock file version 1!\n");
process.exit(1);
}
if(packageLock.dependencies !== undefined) {
augmentDependencies(".", packageLock.dependencies);
}
}
'';
};
# Reconstructs a package-lock file from the node_modules/ folder structure and package.json files with dummy sha1 hashes
reconstructPackageLock = writeTextFile {
name = "addintegrityfields.js";
text = ''
var fs = require('fs');
var path = require('path');
var packageObj = JSON.parse(fs.readFileSync("package.json"));
var lockObj = {
name: packageObj.name,
version: packageObj.version,
lockfileVersion: 1,
requires: true,
dependencies: {}
};
function augmentPackageJSON(filePath, dependencies) {
var packageJSON = path.join(filePath, "package.json");
if(fs.existsSync(packageJSON)) {
var packageObj = JSON.parse(fs.readFileSync(packageJSON));
dependencies[packageObj.name] = {
version: packageObj.version,
integrity: "sha1-000000000000000000000000000=",
dependencies: {}
};
processDependencies(path.join(filePath, "node_modules"), dependencies[packageObj.name].dependencies);
}
}
function processDependencies(dir, dependencies) {
if(fs.existsSync(dir)) {
var files = fs.readdirSync(dir);
files.forEach(function(entry) {
var filePath = path.join(dir, entry);
var stats = fs.statSync(filePath);
if(stats.isDirectory()) {
if(entry.substr(0, 1) == "@") {
// When we encounter a namespace folder, augment all packages belonging to the scope
var pkgFiles = fs.readdirSync(filePath);
pkgFiles.forEach(function(entry) {
if(stats.isDirectory()) {
var pkgFilePath = path.join(filePath, entry);
augmentPackageJSON(pkgFilePath, dependencies);
}
});
} else {
augmentPackageJSON(filePath, dependencies);
}
}
});
}
}
processDependencies("node_modules", lockObj.dependencies);
fs.writeFileSync("package-lock.json", JSON.stringify(lockObj, null, 2));
'';
};
# Builds and composes an NPM package including all its dependencies
buildNodePackage =
{ name
, packageName
, version
, dependencies ? []
, buildInputs ? []
, production ? true
, npmFlags ? ""
, dontNpmInstall ? false
, bypassCache ? false
, preRebuild ? ""
, dontStrip ? true
, unpackPhase ? "true"
, buildPhase ? "true"
, ... }@args:
let
forceOfflineFlag = if bypassCache then "--offline" else "--registry http://www.example.com";
extraArgs = removeAttrs args [ "name" "dependencies" "buildInputs" "dontStrip" "dontNpmInstall" "preRebuild" "unpackPhase" "buildPhase" ];
in
stdenv.mkDerivation ({
name = "node-${name}-${version}";
buildInputs = [ tarWrapper python nodejs ]
++ stdenv.lib.optional (stdenv.isLinux) utillinux
++ stdenv.lib.optional (stdenv.isDarwin) libtool
++ buildInputs;
inherit dontStrip; # Stripping may fail a build for some package deployments
inherit dontNpmInstall preRebuild unpackPhase buildPhase;
compositionScript = composePackage args;
pinpointDependenciesScript = pinpointDependenciesOfPackage args;
passAsFile = [ "compositionScript" "pinpointDependenciesScript" ];
installPhase = ''
# Create and enter a root node_modules/ folder
mkdir -p $out/lib/node_modules
cd $out/lib/node_modules
# Compose the package and all its dependencies
source $compositionScriptPath
# Pinpoint the versions of all dependencies to the ones that are actually being used
echo "pinpointing versions of dependencies..."
source $pinpointDependenciesScriptPath
# Patch the shebangs of the bundled modules to prevent them from
# calling executables outside the Nix store as much as possible
patchShebangs .
# Deploy the Node.js package by running npm install. Since the
# dependencies have been provided already by ourselves, it should not
# attempt to install them again, which is good, because we want to make
# it Nix's responsibility. If it needs to install any dependencies
# anyway (e.g. because the dependency parameters are
# incomplete/incorrect), it fails.
#
# The other responsibilities of NPM are kept -- version checks, build
# steps, postprocessing etc.
export HOME=$TMPDIR
cd "${packageName}"
runHook preRebuild
${stdenv.lib.optionalString bypassCache ''
if [ ! -f package-lock.json ]
then
echo "No package-lock.json file found, reconstructing..."
node ${reconstructPackageLock}
fi
node ${addIntegrityFieldsScript}
''}
npm ${forceOfflineFlag} --nodedir=${nodeSources} ${npmFlags} ${stdenv.lib.optionalString production "--production"} rebuild
if [ "$dontNpmInstall" != "1" ]
then
# NPM tries to download packages even when they already exist if npm-shrinkwrap is used.
rm -f npm-shrinkwrap.json
npm ${forceOfflineFlag} --nodedir=${nodeSources} ${npmFlags} ${stdenv.lib.optionalString production "--production"} install
fi
# Create symlink to the deployed executable folder, if applicable
if [ -d "$out/lib/node_modules/.bin" ]
then
ln -s $out/lib/node_modules/.bin $out/bin
fi
# Create symlinks to the deployed manual page folders, if applicable
if [ -d "$out/lib/node_modules/${packageName}/man" ]
then
mkdir -p $out/share
for dir in "$out/lib/node_modules/${packageName}/man/"*
do
mkdir -p $out/share/man/$(basename "$dir")
for page in "$dir"/*
do
ln -s $page $out/share/man/$(basename "$dir")
done
done
fi
# Run post install hook, if provided
runHook postInstall
'';
} // extraArgs);
# Builds a development shell
buildNodeShell =
{ name
, packageName
, version
, src
, dependencies ? []
, buildInputs ? []
, production ? true
, npmFlags ? ""
, dontNpmInstall ? false
, bypassCache ? false
, dontStrip ? true
, unpackPhase ? "true"
, buildPhase ? "true"
, ... }@args:
let
forceOfflineFlag = if bypassCache then "--offline" else "--registry http://www.example.com";
extraArgs = removeAttrs args [ "name" "dependencies" "buildInputs" ];
nodeDependencies = stdenv.mkDerivation ({
name = "node-dependencies-${name}-${version}";
buildInputs = [ tarWrapper python nodejs ]
++ stdenv.lib.optional (stdenv.isLinux) utillinux
++ stdenv.lib.optional (stdenv.isDarwin) libtool
++ buildInputs;
inherit dontStrip; # Stripping may fail a build for some package deployments
inherit dontNpmInstall unpackPhase buildPhase;
includeScript = includeDependencies { inherit dependencies; };
pinpointDependenciesScript = pinpointDependenciesOfPackage args;
passAsFile = [ "includeScript" "pinpointDependenciesScript" ];
installPhase = ''
mkdir -p $out/${packageName}
cd $out/${packageName}
source $includeScriptPath
# Create fake package.json to make the npm commands work properly
cp ${src}/package.json .
chmod 644 package.json
${stdenv.lib.optionalString bypassCache ''
if [ -f ${src}/package-lock.json ]
then
cp ${src}/package-lock.json .
fi
''}
# Pinpoint the versions of all dependencies to the ones that are actually being used
echo "pinpointing versions of dependencies..."
cd ..
${stdenv.lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."}
source $pinpointDependenciesScriptPath
cd ${packageName}
# Patch the shebangs of the bundled modules to prevent them from
# calling executables outside the Nix store as much as possible
patchShebangs .
export HOME=$PWD
${stdenv.lib.optionalString bypassCache ''
if [ ! -f package-lock.json ]
then
echo "No package-lock.json file found, reconstructing..."
node ${reconstructPackageLock}
fi
node ${addIntegrityFieldsScript}
''}
npm ${forceOfflineFlag} --nodedir=${nodeSources} ${npmFlags} ${stdenv.lib.optionalString production "--production"} rebuild
${stdenv.lib.optionalString (!dontNpmInstall) ''
# NPM tries to download packages even when they already exist if npm-shrinkwrap is used.
rm -f npm-shrinkwrap.json
npm ${forceOfflineFlag} --nodedir=${nodeSources} ${npmFlags} ${stdenv.lib.optionalString production "--production"} install
''}
cd ..
${stdenv.lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."}
mv ${packageName} lib
ln -s $out/lib/node_modules/.bin $out/bin
'';
} // extraArgs);
in
stdenv.mkDerivation {
name = "node-shell-${name}-${version}";
buildInputs = [ python nodejs ] ++ stdenv.lib.optional (stdenv.isLinux) utillinux ++ buildInputs;
buildCommand = ''
mkdir -p $out/bin
cat > $out/bin/shell <<EOF
#! ${stdenv.shell} -e
$shellHook
exec ${stdenv.shell}
EOF
chmod +x $out/bin/shell
'';
# Provide the dependencies in a development shell through the NODE_PATH environment variable
inherit nodeDependencies;
shellHook = stdenv.lib.optionalString (dependencies != []) ''
export NODE_PATH=$nodeDependencies/lib/node_modules
'';
};
in
{
buildNodeSourceDist = stdenv.lib.makeOverridable buildNodeSourceDist;
buildNodePackage = stdenv.lib.makeOverridable buildNodePackage;
buildNodeShell = stdenv.lib.makeOverridable buildNodeShell;
}

File diff suppressed because it is too large Load diff

View file

@ -1,3 +0,0 @@
self: super: {
}

View file

@ -1,18 +0,0 @@
diff -rup Beaker-1.9.1-orig/beaker/session.py Beaker-1.9.1/beaker/session.py
--- Beaker-1.9.1-orig/beaker/session.py 2020-04-10 10:23:04.000000000 +0200
+++ Beaker-1.9.1/beaker/session.py 2020-04-10 10:23:34.000000000 +0200
@@ -156,6 +156,14 @@ def __init__(self, request, id=None, invalidate_corrupt=False,
if timeout and not save_accessed_time:
raise BeakerException("timeout requires save_accessed_time")
self.timeout = timeout
+ # We want to pass timeout param to redis backend to support expiration of keys
+ # In future, I believe, we can use this param for memcached and mongo as well
+ if self.timeout is not None and self.type == 'ext:redis':
+ # The backend expiration should always be a bit longer (I decied to use 2 minutes) than the
+ # session expiration itself to prevent the case where the backend data expires while
+ # the session is being read (PR#153)
+ self.namespace_args['timeout'] = self.timeout + 60 * 2
+
self.save_atime = save_accessed_time
self.use_cookies = use_cookies
self.cookie_expires = cookie_expires

View file

@ -1,26 +0,0 @@
diff -rup Beaker-1.9.1-orig/beaker/ext/redisnm.py Beaker-1.9.1/beaker/ext/redisnm.py
--- Beaker-1.9.1-orig/beaker/ext/redisnm.py 2018-04-10 10:23:04.000000000 +0200
+++ Beaker-1.9.1/beaker/ext/redisnm.py 2018-04-10 10:23:34.000000000 +0200
@@ -30,9 +30,10 @@ class RedisNamespaceManager(NamespaceManager):
clients = SyncDict()
- def __init__(self, namespace, url, **kw):
+ def __init__(self, namespace, url, timeout=None, **kw):
super(RedisNamespaceManager, self).__init__(namespace)
self.lock_dir = None # Redis uses redis itself for locking.
+ self.timeout = timeout
if redis is None:
raise RuntimeError('redis is not available')
@@ -68,6 +69,8 @@ def has_key(self, key):
def set_value(self, key, value, expiretime=None):
value = pickle.dumps(value)
+ if expiretime is None and self.timeout is not None:
+ expiretime = self.timeout
if expiretime is not None:
self.client.setex(self._format_key(key), int(expiretime), value)
else:

View file

@ -1,20 +0,0 @@
diff -rup Beaker-1.9.1-orig/beaker/container.py Beaker-1.9.1/beaker/container.py
--- Beaker-1.9.1-orig/beaker/container.py 2018-04-10 10:23:04.000000000 +0200
+++ Beaker-1.9.1/beaker/container.py 2018-04-10 10:23:34.000000000 +0200
@@ -353,13 +353,13 @@ class Value(object):
debug("get_value returning old value while new one is created")
return value
else:
- debug("lock_creatfunc (didnt wait)")
+ debug("lock_creatfunc `%s` (didnt wait)", self.createfunc.__name__)
has_createlock = True
if not has_createlock:
- debug("lock_createfunc (waiting)")
+ debug("lock_createfunc `%s` (waiting)", self.createfunc.__name__)
creation_lock.acquire()
- debug("lock_createfunc (waited)")
+ debug("lock_createfunc `%s` (waited)", self.createfunc.__name__)
try:
# see if someone created the value already

View file

@ -1,13 +0,0 @@
diff -rup Beaker-1.9.1-orig/beaker/ext/database.py Beaker-1.9.1/beaker/ext/database.py
--- Beaker-1.9.1-orig/beaker/ext/database.py 2018-05-22 18:22:34.802619619 +0200
+++ Beaker-1.9.1/beaker/ext/database.py 2018-05-22 17:07:14.048335196 +0200
@@ -91,7 +91,8 @@ class DatabaseNamespaceManager(OpenResou
sa.Column('created', types.DateTime, nullable=False),
sa.Column('data', types.PickleType, nullable=False),
sa.UniqueConstraint('namespace'),
- schema=schema_name if schema_name else meta.schema
+ schema=schema_name if schema_name else meta.schema,
+ extend_existing=True
)
cache.create(checkfirst=True)
return cache

View file

@ -1,13 +0,0 @@
diff -rup channelstream-0.6.14-orig/setup.py channelstream-0.6.14/setup.py
--- channelstream-0.6.14/setup-orig.py 2021-03-11 12:34:45.000000000 +0100
+++ channelstream-0.6.14/setup.py 2021-03-11 12:34:56.000000000 +0100
@@ -52,7 +52,7 @@ setup(
include_package_data=True,
install_requires=requires,
python_requires=">=2.7",
- setup_requires=["pytest-runner"],
+ setup_requires=["pytest-runner==5.1.0"],
extras_require={
"dev": ["coverage", "pytest", "pyramid", "tox", "mock", "webtest"],
"lint": ["black"],

View file

@ -1,10 +0,0 @@
diff -rup configparser-4.0.2-orig/pyproject.toml configparser-4.0.2/pyproject.toml
--- configparser-4.0.2-orig/pyproject.toml 2021-03-22 21:28:11.000000000 +0100
+++ configparser-4.0.2/pyproject.toml 2021-03-22 21:28:11.000000000 +0100
@@ -1,5 +1,5 @@
[build-system]
-requires = ["setuptools>=40.7", "wheel", "setuptools_scm>=1.15"]
+requires = ["setuptools<=42.0", "wheel", "setuptools_scm<6.0.0"]
build-backend = "setuptools.build_meta"
[tool.black]

View file

@ -1,7 +0,0 @@
diff -rup importlib-metadata-1.6.0-orig/yproject.toml importlib-metadata-1.6.0/pyproject.toml
--- importlib-metadata-1.6.0-orig/yproject.toml 2021-03-22 22:10:33.000000000 +0100
+++ importlib-metadata-1.6.0/pyproject.toml 2021-03-22 22:11:09.000000000 +0100
@@ -1,3 +1,3 @@
[build-system]
-requires = ["setuptools>=30.3", "wheel", "setuptools_scm"]
+requires = ["setuptools<42.0", "wheel", "setuptools_scm<6.0.0"]

View file

@ -1,12 +0,0 @@
diff -rup pyramid-apispec-0.3.2-orig/setup.py pyramid-apispec-0.3.2/setup.py
--- pyramid-apispec-0.3.2-orig/setup.py 2021-03-11 11:19:26.000000000 +0100
+++ pyramid-apispec-0.3.2/setup.py 2021-03-11 11:19:51.000000000 +0100
@@ -44,7 +44,7 @@ setup(
packages=find_packages(exclude=["contrib", "docs", "tests"]),
package_data={"pyramid_apispec": ["static/*.*"], "": ["LICENSE"]},
install_requires=["apispec[yaml]==1.0.0"],
- setup_requires=["pytest-runner"],
+ setup_requires=["pytest-runner==5.1"],
extras_require={
"dev": ["coverage", "pytest", "pyramid", "tox", "webtest"],
"demo": ["marshmallow==2.15.3", "pyramid", "apispec", "webtest"],

View file

@ -1,12 +0,0 @@
diff -rup pytest-4.6.5-orig/setup.py pytest-4.6.5/setup.py
--- pytest-4.6.5-orig/setup.py 2018-04-10 10:23:04.000000000 +0200
+++ pytest-4.6.5/setup.py 2018-04-10 10:23:34.000000000 +0200
@@ -24,7 +24,7 @@ INSTALL_REQUIRES = [
def main():
setup(
use_scm_version={"write_to": "src/_pytest/_version.py"},
- setup_requires=["setuptools-scm", "setuptools>=40.0"],
+ setup_requires=["setuptools-scm<6.0.0", "setuptools<=42.0"],
package_dir={"": "src"},
# fmt: off
extras_require={

View file

@ -1,13 +0,0 @@
diff -rup rhodecode-tools-1.4.1-orig/setup.py rhodecode-tools-1.4.1/setup.py
--- rhodecode-tools-1.4.1/setup-orig.py 2021-03-11 12:34:45.000000000 +0100
+++ rhodecode-tools-1.4.1/setup.py 2021-03-11 12:34:56.000000000 +0100
@@ -69,7 +69,7 @@ def _get_requirements(req_filename, excl
# requirements extract
-setup_requirements = ['pytest-runner']
+setup_requirements = ['pytest-runner==5.1.0']
install_requirements = _get_requirements(
'requirements.txt', exclude=['setuptools'])
-test_requirements = _get_requirements('requirements_test.txt')
-test_requirements = []

View file

@ -1,16 +0,0 @@
diff -rup supervisor-3.3.4-orig/supervisor/options.py supervisor-3.3.4/supervisor/options.py
--- supervisor-3.3.4-orig/supervisor/options.py 1970-01-01 01:00:01.000000000 +0100
+++ supervisor-3.3.4/supervisor-new/options.py 2018-10-24 10:53:19.368503735 +0200
@@ -1395,7 +1395,11 @@ class ServerOptions(Options):
name = limit['name']
name = name # name is used below by locals()
- soft, hard = resource.getrlimit(res)
+ try:
+ soft, hard = resource.getrlimit(res)
+ except Exception:
+ # handle old kernel problems, this is not critical to execute
+ soft, hard = -1, -1
if (soft < min) and (soft != -1): # -1 means unlimited
if (hard < min) and (hard != -1):

View file

@ -1,10 +0,0 @@
diff -rup zip-1.2.0-orig/pyproject.toml zip-1.2.0/pyproject.toml
--- zip-1.2.0-orig/pyproject.toml 2021-03-23 10:55:37.000000000 +0100
+++ zip-1.2.0/pyproject.toml 2021-03-23 10:56:05.000000000 +0100
@@ -1,5 +1,5 @@
[build-system]
-requires = ["setuptools>=34.4", "wheel", "setuptools_scm>=1.15"]
+requires = ["setuptools<42.0", "wheel", "setuptools_scm<6.0.0"]
build-backend = "setuptools.build_meta"
[tool.black]

View file

@ -1,353 +0,0 @@
# Overrides for the generated python-packages.nix
#
# This function is intended to be used as an extension to the generated file
# python-packages.nix. The main objective is to add needed dependencies of C
# libraries and tweak the build instructions where needed.
{ pkgs
, basePythonPackages
}:
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 ];
};
});
"beaker" = super."beaker".override (attrs: {
patches = [
./patches/beaker/patch-beaker-lock-func-debug.diff
./patches/beaker/patch-beaker-metadata-reuse.diff
./patches/beaker/patch-beaker-improved-redis.diff
./patches/beaker/patch-beaker-improved-redis-2.diff
];
});
"cffi" = super."cffi".override (attrs: {
buildInputs = [
pkgs.libffi
];
});
"cryptography" = super."cryptography".override (attrs: {
buildInputs = [
pkgs.openssl
];
});
"gevent" = super."gevent".override (attrs: {
propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
# NOTE: (marcink) odd requirements from gevent aren't set properly,
# thus we need to inject psutil manually
self."psutil"
];
});
"future" = super."future".override (attrs: {
meta = {
license = [ pkgs.lib.licenses.mit ];
};
});
"testpath" = super."testpath".override (attrs: {
meta = {
license = [ pkgs.lib.licenses.mit ];
};
});
"gnureadline" = super."gnureadline".override (attrs: {
buildInputs = [
pkgs.ncurses
];
patchPhase = ''
substituteInPlace setup.py --replace "/bin/bash" "${pkgs.bash}/bin/bash"
'';
});
"gunicorn" = super."gunicorn".override (attrs: {
propagatedBuildInputs = [
# johbo: futures is needed as long as we are on Python 2, otherwise
# gunicorn explodes if used with multiple threads per worker.
self."futures"
];
});
"nbconvert" = super."nbconvert".override (attrs: {
propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
# marcink: plug in jupyter-client for notebook rendering
self."jupyter-client"
];
});
"ipython" = super."ipython".override (attrs: {
propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
self."gnureadline"
];
});
"lxml" = super."lxml".override (attrs: {
buildInputs = [
pkgs.libxml2
pkgs.libxslt
];
propagatedBuildInputs = [
# Needed, so that "setup.py bdist_wheel" does work
self."wheel"
];
});
"mysql-python" = super."mysql-python".override (attrs: {
buildInputs = [
pkgs.openssl
];
propagatedBuildInputs = [
pkgs.libmysql
pkgs.zlib
];
});
"psycopg2" = super."psycopg2".override (attrs: {
propagatedBuildInputs = [
pkgs.postgresql
];
meta = {
license = pkgs.lib.licenses.lgpl3Plus;
};
});
"pycurl" = super."pycurl".override (attrs: {
propagatedBuildInputs = [
pkgs.curl
pkgs.openssl
];
preConfigure = ''
substituteInPlace setup.py --replace '--static-libs' '--libs'
export PYCURL_SSL_LIBRARY=openssl
'';
meta = {
license = pkgs.lib.licenses.mit;
};
});
"pyramid" = super."pyramid".override (attrs: {
meta = {
license = localLicenses.repoze;
};
});
"pyramid-debugtoolbar" = super."pyramid-debugtoolbar".override (attrs: {
meta = {
license = [ pkgs.lib.licenses.bsdOriginal localLicenses.repoze ];
};
});
"pysqlite" = super."pysqlite".override (attrs: {
propagatedBuildInputs = [
pkgs.sqlite
];
meta = {
license = [ pkgs.lib.licenses.zlib pkgs.lib.licenses.libpng ];
};
});
"python-ldap" = super."python-ldap".override (attrs: {
propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
pkgs.openldap
pkgs.cyrus_sasl
pkgs.openssl
];
});
"python-pam" = super."python-pam".override (attrs: {
propagatedBuildInputs = [
pkgs.pam
];
# TODO: johbo: Check if this can be avoided, or transform into
# a real patch
patchPhase = ''
substituteInPlace pam.py \
--replace 'find_library("pam")' '"${pkgs.pam}/lib/libpam.so.0"'
'';
});
"python-saml" = super."python-saml".override (attrs: {
buildInputs = [
pkgs.libxml2
pkgs.libxslt
];
});
"dm.xmlsec.binding" = super."dm.xmlsec.binding".override (attrs: {
buildInputs = [
pkgs.libxml2
pkgs.libxslt
pkgs.xmlsec
pkgs.libtool
];
});
"pyzmq" = super."pyzmq".override (attrs: {
buildInputs = [
pkgs.czmq
];
});
"urlobject" = super."urlobject".override (attrs: {
meta = {
license = {
spdxId = "Unlicense";
fullName = "The Unlicense";
url = http://unlicense.org/;
};
};
});
"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;
};
});
"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;
};
});
"supervisor" = super."supervisor".override (attrs: {
patches = [
./patches/supervisor/patch-rlimits-old-kernel.diff
];
});
"pytest" = super."pytest".override (attrs: {
patches = [
./patches/pytest/setuptools.patch
];
});
"pytest-runner" = super."pytest-runner".override (attrs: {
propagatedBuildInputs = [
self."setuptools-scm"
];
});
"py" = super."py".override (attrs: {
propagatedBuildInputs = [
self."setuptools-scm"
];
});
"python-dateutil" = super."python-dateutil".override (attrs: {
propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
self."setuptools-scm"
];
});
"configparser" = super."configparser".override (attrs: {
patches = [
./patches/configparser/pyproject.patch
];
propagatedBuildInputs = [
self."setuptools-scm"
];
});
"importlib-metadata" = super."importlib-metadata".override (attrs: {
patches = [
./patches/importlib_metadata/pyproject.patch
];
propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
self."setuptools-scm"
];
});
"zipp" = super."zipp".override (attrs: {
patches = [
./patches/zipp/pyproject.patch
];
propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
self."setuptools-scm"
];
});
"pyramid-apispec" = super."pyramid-apispec".override (attrs: {
patches = [
./patches/pyramid_apispec/setuptools.patch
];
});
"channelstream" = super."channelstream".override (attrs: {
patches = [
./patches/channelstream/setuptools.patch
];
});
"rhodecode-tools" = super."rhodecode-tools".override (attrs: {
patches = [
./patches/rhodecode_tools/setuptools.patch
];
});
# Avoid that base packages screw up the build process
inherit (basePythonPackages)
setuptools;
}

File diff suppressed because it is too large Load diff

View file

@ -1,55 +0,0 @@
{ pkgs ? (import <nixpkgs> {})
, pythonPackages ? "python27Packages"
}:
with pkgs.lib;
let _pythonPackages = pythonPackages; in
let
pythonPackages = getAttr _pythonPackages pkgs;
pip2nix = import ./nix-common/pip2nix.nix {
inherit
pkgs
pythonPackages;
};
in
pkgs.stdenv.mkDerivation {
name = "pip2nix-generated";
buildInputs = [
# Allows to generate python packages
pip2nix.pip2nix
pythonPackages.pip-tools
# Allows to generate node dependencies
pkgs.nodePackages.node2nix
# We need mysql_config to be around
pkgs.mysql
# We need postgresql to be around
pkgs.postgresql
# we need the below for saml
pkgs.libxml2
pkgs.libxslt
pkgs.xmlsec
# Curl is needed for pycurl
pkgs.curl
];
shellHook = ''
runHook preShellHook
runHook postShellHook
'';
preShellHook = ''
echo "Starting Generate Shell"
# Custom prompt to distinguish from other dev envs.
export PS1="\n\[\033[1;32m\][Generate-shell:\w]$\[\033[0m\] "
export PYCURL_SSL_LIBRARY=openssl
'';
}

View file

@ -11,7 +11,9 @@ addopts =
--pdbcls=IPython.terminal.debugger:TerminalPdb
--strict-markers
--capture=no
--show-capture=no
--show-capture=all
# --test-loglevel=INFO, show log-level during execution
markers =
vcs_operations: Mark tests depending on a running RhodeCode instance.

View file

@ -1,22 +0,0 @@
# This file defines how to "build" for packaging.
{ pkgs ? import <nixpkgs> {}
, system ? builtins.currentSystem
, doCheck ? false
}:
let
enterprise_ce = import ./default.nix {
inherit
doCheck
system;
# disable checkPhase for build
checkPhase = ''
'';
};
in {
build = enterprise_ce;
}

View file

@ -1,122 +1,295 @@
## dependencies
# deps, generated via pipdeptree --exclude setuptools,wheel,pipdeptree,pip -f | tr '[:upper:]' '[:lower:]'
amqp==2.5.2
babel==1.3
beaker==1.9.1
bleach==3.1.3
celery==4.3.0
channelstream==0.6.14
click==7.0
colander==1.7.0
# our custom configobj
https://code.rhodecode.com/upstream/configobj/artifacts/download/0-012de99a-b1e1-4f64-a5c0-07a98a41b324.tar.gz?md5=6a513f51fe04b2c18cf84c1395a7c626#egg=configobj==5.0.6
cssselect==1.0.3
cryptography==2.6.1
decorator==4.1.2
deform==2.0.8
docutils==0.16.0
dogpile.cache==0.9.0
dogpile.core==0.4.1
formencode==1.2.4
future==0.14.3
futures==3.0.2
infrae.cache==1.0.1
iso8601==0.1.12
itsdangerous==1.1.0
kombu==4.6.6
lxml==4.2.5
mako==1.1.0
markdown==2.6.11
markupsafe==1.1.1
msgpack-python==0.5.6
pyotp==2.3.0
packaging==20.3
pathlib2==2.3.5
paste==3.4.0
pastedeploy==2.1.0
pastescript==3.2.0
peppercorn==0.6
premailer==3.6.1
psutil==5.7.0
alembic==1.12.1
mako==1.2.4
markupsafe==2.1.2
sqlalchemy==1.4.51
greenlet==3.0.3
typing_extensions==4.9.0
async-timeout==4.0.3
babel==2.12.1
beaker==1.12.1
celery==5.3.6
billiard==4.2.0
click==8.1.3
click-didyoumean==0.3.0
click==8.1.3
click-plugins==1.1.1
click==8.1.3
click-repl==0.2.0
click==8.1.3
prompt-toolkit==3.0.38
wcwidth==0.2.6
six==1.16.0
kombu==5.3.5
amqp==5.2.0
vine==5.1.0
vine==5.1.0
python-dateutil==2.8.2
six==1.16.0
tzdata==2023.4
vine==5.1.0
channelstream==0.7.1
gevent==24.2.1
greenlet==3.0.3
zope.event==5.0.0
zope.interface==6.1.0
itsdangerous==1.1.0
marshmallow==2.18.0
pyramid==2.0.2
hupper==1.12
plaster==1.1.2
plaster-pastedeploy==1.0.1
pastedeploy==3.1.0
plaster==1.1.2
translationstring==1.4
venusian==3.0.0
webob==1.8.7
zope.deprecation==5.0.0
zope.interface==6.1.0
pyramid-apispec==0.3.3
apispec==1.3.3
pyramid-jinja2==2.10
jinja2==3.1.2
markupsafe==2.1.2
markupsafe==2.1.2
pyramid==2.0.2
hupper==1.12
plaster==1.1.2
plaster-pastedeploy==1.0.1
pastedeploy==3.1.0
plaster==1.1.2
translationstring==1.4
venusian==3.0.0
webob==1.8.7
zope.deprecation==5.0.0
zope.interface==6.1.0
zope.deprecation==5.0.0
python-dateutil==2.8.2
six==1.16.0
requests==2.28.2
certifi==2022.12.7
charset-normalizer==3.1.0
idna==3.4
urllib3==1.26.14
ws4py==0.5.1
deform==2.0.15
chameleon==3.10.2
colander==2.0
iso8601==1.1.0
translationstring==1.4
iso8601==1.1.0
peppercorn==0.6
translationstring==1.4
zope.deprecation==5.0.0
diskcache==5.6.3
docutils==0.19
dogpile.cache==1.3.0
decorator==5.1.1
stevedore==5.1.0
pbr==5.11.1
formencode==2.1.0
six==1.16.0
gunicorn==21.2.0
packaging==23.1
gevent==24.2.1
greenlet==3.0.3
zope.event==5.0.0
zope.interface==6.1.0
ipython==8.14.0
backcall==0.2.0
decorator==5.1.1
jedi==0.19.0
parso==0.8.3
matplotlib-inline==0.1.6
traitlets==5.9.0
pexpect==4.8.0
ptyprocess==0.7.0
pickleshare==0.7.5
prompt-toolkit==3.0.38
wcwidth==0.2.6
pygments==2.15.1
stack-data==0.6.2
asttokens==2.2.1
six==1.16.0
executing==1.2.0
pure-eval==0.2.2
traitlets==5.9.0
markdown==3.4.3
msgpack==1.0.7
mysqlclient==2.1.1
nbconvert==7.7.3
beautifulsoup4==4.11.2
soupsieve==2.4
bleach==6.1.0
six==1.16.0
webencodings==0.5.1
defusedxml==0.7.1
jinja2==3.1.2
markupsafe==2.1.2
jupyter_core==5.3.1
platformdirs==3.10.0
traitlets==5.9.0
jupyterlab-pygments==0.2.2
markupsafe==2.1.2
mistune==2.0.5
nbclient==0.8.0
jupyter_client==8.3.0
jupyter_core==5.3.1
platformdirs==3.10.0
traitlets==5.9.0
python-dateutil==2.8.2
six==1.16.0
pyzmq==25.0.0
tornado==6.2
traitlets==5.9.0
jupyter_core==5.3.1
platformdirs==3.10.0
traitlets==5.9.0
nbformat==5.9.2
fastjsonschema==2.18.0
jsonschema==4.18.6
attrs==22.2.0
pyrsistent==0.19.3
jupyter_core==5.3.1
platformdirs==3.10.0
traitlets==5.9.0
traitlets==5.9.0
traitlets==5.9.0
nbformat==5.9.2
fastjsonschema==2.18.0
jsonschema==4.18.6
attrs==22.2.0
pyrsistent==0.19.3
jupyter_core==5.3.1
platformdirs==3.10.0
traitlets==5.9.0
traitlets==5.9.0
packaging==23.1
pandocfilters==1.5.0
pygments==2.15.1
tinycss2==1.2.1
webencodings==0.5.1
traitlets==5.9.0
orjson==3.9.13
pastescript==3.4.0
paste==3.7.1
six==1.16.0
pastedeploy==3.1.0
six==1.16.0
premailer==3.10.0
cachetools==5.3.2
cssselect==1.2.0
cssutils==2.6.0
lxml==4.9.3
requests==2.28.2
certifi==2022.12.7
charset-normalizer==3.1.0
idna==3.4
urllib3==1.26.14
psutil==5.9.8
psycopg2==2.9.9
py-bcrypt==0.4
pycurl==7.43.0.3
pycrypto==2.6.1
pygments==2.4.2
pyparsing==2.4.7
pyramid-debugtoolbar==4.6.1
pyramid-mako==1.1.0
pyramid==1.10.4
pyramid_mailer==0.15.1
python-dateutil==2.8.1
python-ldap==3.2.0
pycmarkgfm==1.2.0
cffi==1.16.0
pycparser==2.21
pycryptodome==3.17
pycurl==7.45.2
pymysql==1.0.3
pyotp==2.8.0
pyparsing==3.1.1
pyramid-debugtoolbar==4.11
pygments==2.15.1
pyramid==2.0.2
hupper==1.12
plaster==1.1.2
plaster-pastedeploy==1.0.1
pastedeploy==3.1.0
plaster==1.1.2
translationstring==1.4
venusian==3.0.0
webob==1.8.7
zope.deprecation==5.0.0
zope.interface==6.1.0
pyramid-mako==1.1.0
mako==1.2.4
markupsafe==2.1.2
pyramid==2.0.2
hupper==1.12
plaster==1.1.2
plaster-pastedeploy==1.0.1
pastedeploy==3.1.0
plaster==1.1.2
translationstring==1.4
venusian==3.0.0
webob==1.8.7
zope.deprecation==5.0.0
zope.interface==6.1.0
pyramid-mailer==0.15.1
pyramid==2.0.2
hupper==1.12
plaster==1.1.2
plaster-pastedeploy==1.0.1
pastedeploy==3.1.0
plaster==1.1.2
translationstring==1.4
venusian==3.0.0
webob==1.8.7
zope.deprecation==5.0.0
zope.interface==6.1.0
repoze.sendmail==4.4.1
transaction==3.1.0
zope.interface==6.1.0
zope.interface==6.1.0
transaction==3.1.0
zope.interface==6.1.0
python-ldap==3.4.3
pyasn1==0.4.8
pyasn1-modules==0.2.8
pyasn1==0.4.8
python-memcached==1.59
python-pam==1.8.4
python-saml==2.4.2
pytz==2019.3
tzlocal==1.5.1
pyzmq==14.6.0
py-gfm==0.1.4
regex==2020.9.27
redis==3.5.3
repoze.lru==0.7
requests==2.22.0
routes==2.4.1
simplejson==3.16.0
six==1.11.0
sqlalchemy==1.3.15
sshpubkeys==3.1.0
subprocess32==3.5.4
supervisor==4.1.0
translationstring==1.3
urllib3==1.25.2
six==1.16.0
python-pam==2.0.2
python3-saml==1.15.0
isodate==0.6.1
six==1.16.0
lxml==4.9.3
xmlsec==1.3.13
lxml==4.9.3
pyyaml==6.0.1
redis==5.0.1
regex==2022.10.31
routes==2.5.1
repoze.lru==0.7
six==1.16.0
simplejson==3.19.1
sshpubkeys==3.3.1
cryptography==40.0.2
cffi==1.16.0
pycparser==2.21
ecdsa==0.18.0
six==1.16.0
sqlalchemy==1.4.51
greenlet==3.0.3
typing_extensions==4.9.0
supervisor==4.2.5
tzlocal==4.3
pytz-deprecation-shim==0.1.0.post0
tzdata==2023.4
unidecode==1.3.6
urlobject==2.4.3
venusian==1.2.0
waitress==3.0.0
weberror==0.13.1
paste==3.7.1
six==1.16.0
pygments==2.15.1
tempita==0.5.2
webob==1.8.7
webhelpers2==2.0
webob==1.8.5
markupsafe==2.1.2
six==1.16.0
whoosh==2.7.4
wsgiref==0.1.2
zope.cachedescriptors==4.3.1
zope.deprecation==4.4.0
zope.event==4.4.0
zope.interface==4.6.0
# DB drivers
mysql-python==1.2.5
pymysql==0.8.1
pysqlite==2.8.3
psycopg2==2.8.4
# IPYTHON RENDERING
# entrypoints backport, pypi version doesn't support egg installs
https://code.rhodecode.com/upstream/entrypoints/artifacts/download/0-8e9ee9e4-c4db-409c-b07e-81568fd1832d.tar.gz?md5=3a027b8ff1d257b91fe257de6c43357d#egg=entrypoints==0.2.2.rhodecode-upstream1
nbconvert==5.3.1
nbformat==4.4.0
jupyter-client==5.0.0
jupyter-core==4.5.0
## cli tools
alembic==1.4.2
invoke==0.13.0
bumpversion==0.5.3
## http servers
gevent==1.5.0
greenlet==0.4.15
gunicorn==19.9.0
waitress==1.3.1
## debug
ipdb==0.13.2
ipython==5.1.0
## rhodecode-tools, special case, use file://PATH.tar.gz#egg=rhodecode-tools==X.Y.Z, to test local version
https://code.rhodecode.com/rhodecode-tools-ce/artifacts/download/0-d9ea7914-e475-44af-a80a-7e32edc17e2f.tar.gz?sha256=6e5aaac455b4a0b2dee013a1241b367e2991e345fda6ed0f4a8c66c941a19184#egg=rhodecode-tools==1.4.1
## appenlight
appenlight-client==0.6.26
zope.cachedescriptors==5.0.0
## uncomment to add the debug libraries
#-r requirements_debug.txt

View file

@ -1,3 +1,28 @@
## special libraries we could extend the requirements.txt file with to add some
## custom libraries usefull for debug and memory tracing
objgraph==3.1.1
objgraph
memory-profiler
pympler
## debug
ipdb
ipython
rich
# format
flake8
ruff
pipdeptree==2.7.1
invoke==2.0.0
bumpversion==0.6.0
bump2version==1.0.1
docutils-stubs
types-redis
types-requests==2.31.0.6
types-sqlalchemy
types-psutil
types-pycurl
types-ujson

View file

@ -1,28 +0,0 @@
# contains not directly required libraries we want to pin the version.
atomicwrites==1.3.0
attrs==19.3.0
asn1crypto==0.24.0
billiard==3.6.1.0
cffi==1.12.3
chameleon==2.24
configparser==4.0.2
contextlib2==0.6.0.post1
ecdsa==0.13.2
gnureadline==6.3.8
hupper==1.10.2
ipaddress==1.0.23
importlib-metadata==1.6.0
jinja2==2.9.6
jsonschema==2.6.0
pluggy==0.13.1
pyasn1-modules==0.2.6
pyramid-jinja2==2.7
pyramid-apispec==0.3.2
scandir==1.10.0
setproctitle==1.1.10
tempita==0.5.2
testpath==0.4.4
transaction==2.4.0
vine==1.3.0
wcwidth==0.1.9

View file

@ -0,0 +1,3 @@
## rhodecode-tools, special case, use file://PATH.tar.gz#egg=rhodecode-tools==X.Y.Z, to test local version
rhodecode-tools @ https://code.rhodecode.com/_file_store/download/0-36d03a63-36f7-47af-a33c-d81c39f88251.0.0.tar.gz#egg=rhodecode-tools
rhodecode-tools==3.0.0

View file

@ -1,16 +1,46 @@
# test related requirements
pytest==4.6.5
py==1.8.0
pytest-cov==2.7.1
pytest-sugar==0.9.2
pytest-runner==5.1.0
pytest-profiling==1.7.0
pytest-timeout==1.3.3
gprof2dot==2017.9.19
mock==3.0.5
cov-core==1.15.0
coverage==4.5.4
coverage==7.2.3
mock==5.0.2
py==1.11.0
pytest-cov==4.0.0
coverage==7.2.3
pytest==7.3.1
attrs==22.2.0
iniconfig==2.0.0
packaging==23.1
pluggy==1.0.0
pytest-rerunfailures==12.0
pytest-profiling==1.7.0
gprof2dot==2022.7.29
pytest==7.3.1
attrs==22.2.0
iniconfig==2.0.0
packaging==23.1
pluggy==1.0.0
six==1.16.0
pytest-runner==6.0.0
pytest-sugar==0.9.7
packaging==23.1
pytest==7.3.1
attrs==22.2.0
iniconfig==2.0.0
packaging==23.1
pluggy==1.0.0
termcolor==2.3.0
pytest-timeout==2.1.0
pytest==7.3.1
attrs==22.2.0
iniconfig==2.0.0
packaging==23.1
pluggy==1.0.0
webtest==3.0.0
beautifulsoup4==4.11.2
soupsieve==2.4
waitress==3.0.0
webob==1.8.7
webtest==2.0.34
beautifulsoup4==4.6.3
# RhodeCode test-data
rc_testdata @ https://code.rhodecode.com/upstream/rc-testdata-dist/raw/77378e9097f700b4c1b9391b56199fe63566b5c9/rc_testdata-0.11.0.tar.gz#egg=rc_testdata
rc_testdata==0.11.0

View file

@ -1 +1 @@
4.27.1
5.0.0

View file

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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
@ -19,15 +17,22 @@
# and proprietary license terms, please see https://rhodecode.com/licenses/
import os
from collections import OrderedDict
import datetime
import collections
import logging
now = datetime.datetime.now()
now = now.strftime("%Y-%m-%d %H:%M:%S") + '.' + f"{int(now.microsecond/1000):03d}"
log = logging.getLogger(__name__)
log.debug(f'{now} Starting RhodeCode imports...')
import sys
import platform
VERSION = tuple(open(os.path.join(
os.path.dirname(__file__), 'VERSION')).read().split('.'))
BACKENDS = OrderedDict()
BACKENDS = collections.OrderedDict()
BACKENDS['hg'] = 'Mercurial repository'
BACKENDS['git'] = 'Git repository'
@ -40,6 +45,35 @@ CELERY_EAGER = False
# link to config for pyramid
CONFIG = {}
class ConfigGet:
NotGiven = object()
def _get_val_or_missing(self, key, missing):
if key not in CONFIG:
if missing == self.NotGiven:
return missing
# we don't get key, we don't get missing value, return nothing similar as config.get(key)
return None
else:
val = CONFIG[key]
return val
def get_str(self, key, missing=NotGiven):
from rhodecode.lib.str_utils import safe_str
val = self._get_val_or_missing(key, missing)
return safe_str(val)
def get_int(self, key, missing=NotGiven):
from rhodecode.lib.str_utils import safe_int
val = self._get_val_or_missing(key, missing)
return safe_int(val)
def get_bool(self, key, missing=NotGiven):
from rhodecode.lib.type_utils import str2bool
val = self._get_val_or_missing(key, missing)
return str2bool(val)
# Populated with the settings dictionary from application init in
# rhodecode.conf.environment.load_pyramid_environment
PYRAMID_SETTINGS = {}
@ -48,13 +82,10 @@ PYRAMID_SETTINGS = {}
EXTENSIONS = {}
__version__ = ('.'.join((str(each) for each in VERSION[:3])))
__dbversion__ = 113 # defines current db version for migrations
__platform__ = platform.system()
__dbversion__ = 114 # defines current db version for migrations
__license__ = 'AGPLv3, and Commercial License'
__author__ = 'RhodeCode GmbH'
__url__ = 'https://code.rhodecode.com'
is_windows = __platform__ in ['Windows']
is_unix = not is_windows
is_test = False
disable_error_handler = False

View file

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2011-2020 RhodeCode GmbH
# Copyright (C) 2011-2023 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
@ -21,10 +19,10 @@
import itertools
import logging
import sys
import types
import fnmatch
import decorator
import typing
import venusian
from collections import OrderedDict
@ -39,7 +37,7 @@ from rhodecode.apps._base import TemplateArgs
from rhodecode.lib.auth import AuthUser
from rhodecode.lib.base import get_ip_addr, attach_context_attributes
from rhodecode.lib.exc_tracking import store_exception
from rhodecode.lib.ext_json import json
from rhodecode.lib import ext_json
from rhodecode.lib.utils2 import safe_str
from rhodecode.lib.plugins.utils import get_plugin_settings
from rhodecode.model.db import User, UserApiKeys
@ -64,15 +62,12 @@ def find_methods(jsonrpc_methods, pattern):
class ExtJsonRenderer(object):
"""
Custom renderer that mkaes use of our ext_json lib
Custom renderer that makes use of our ext_json lib
"""
def __init__(self, serializer=json.dumps, **kw):
""" Any keyword arguments will be passed to the ``serializer``
function."""
self.serializer = serializer
self.kw = kw
def __init__(self):
self.serializer = ext_json.formatted_json
def __call__(self, info):
""" Returns a plain JSON-encoded string with content-type
@ -87,25 +82,17 @@ class ExtJsonRenderer(object):
if ct == response.default_content_type:
response.content_type = 'application/json'
return self.serializer(value, **self.kw)
return self.serializer(value)
return _render
def jsonrpc_response(request, result):
rpc_id = getattr(request, 'rpc_id', None)
response = request.response
# store content_type before render is called
ct = response.content_type
ret_value = ''
if rpc_id:
ret_value = {
'id': rpc_id,
'result': result,
'error': None,
}
ret_value = {'id': rpc_id, 'result': result, 'error': None}
# fetch deprecation warnings, and store it inside results
deprecation = getattr(request, 'rpc_deprecation', None)
@ -113,30 +100,36 @@ def jsonrpc_response(request, result):
ret_value['DEPRECATION_WARNING'] = deprecation
raw_body = render(DEFAULT_RENDERER, ret_value, request=request)
response.body = safe_str(raw_body, response.charset)
if ct == response.default_content_type:
response.content_type = 'application/json'
return response
content_type = 'application/json'
content_type_header = 'Content-Type'
headers = {
content_type_header: content_type
}
return Response(
body=raw_body,
content_type=content_type,
headerlist=[(k, v) for k, v in headers.items()]
)
def jsonrpc_error(request, message, retid=None, code=None, headers=None):
def jsonrpc_error(request, message, retid=None, code: int | None = None, headers: dict | None = None):
"""
Generate a Response object with a JSON-RPC error body
:param code:
:param retid:
:param message:
"""
headers = headers or {}
content_type = 'application/json'
content_type_header = 'Content-Type'
if content_type_header not in headers:
headers[content_type_header] = content_type
err_dict = {'id': retid, 'result': None, 'error': message}
body = render(DEFAULT_RENDERER, err_dict, request=request).encode('utf-8')
raw_body = render(DEFAULT_RENDERER, err_dict, request=request)
return Response(
body=body,
body=raw_body,
status=code,
content_type='application/json',
headerlist=headers
content_type=content_type,
headerlist=[(k, v) for k, v in headers.items()]
)
@ -144,7 +137,7 @@ def exception_view(exc, request):
rpc_id = getattr(request, 'rpc_id', None)
if isinstance(exc, JSONRPCError):
fault_message = safe_str(exc.message)
fault_message = safe_str(exc)
log.debug('json-rpc error rpc_id:%s "%s"', rpc_id, fault_message)
elif isinstance(exc, JSONRPCValidationError):
colander_exc = exc.colander_exception
@ -158,11 +151,11 @@ def exception_view(exc, request):
method = request.rpc_method
log.debug('json-rpc method `%s` not found in list of '
'api calls: %s, rpc_id:%s',
method, request.registry.jsonrpc_methods.keys(), rpc_id)
method, list(request.registry.jsonrpc_methods.keys()), rpc_id)
similar = 'none'
try:
similar_paterns = ['*{}*'.format(x) for x in method.split('_')]
similar_paterns = [f'*{x}*' for x in method.split('_')]
similar_found = find_methods(
request.registry.jsonrpc_methods, similar_paterns)
similar = ', '.join(similar_found.keys()) or similar
@ -170,13 +163,18 @@ def exception_view(exc, request):
# make the whole above block safe
pass
fault_message = "No such method: {}. Similar methods: {}".format(
method, similar)
fault_message = f"No such method: {method}. Similar methods: {similar}"
else:
fault_message = 'undefined error'
exc_info = exc.exc_info()
store_exception(id(exc_info), exc_info, prefix='rhodecode-api')
statsd = request.registry.statsd
if statsd:
exc_type = f"{exc.__class__.__module__}.{exc.__class__.__name__}"
statsd.incr('rhodecode_exception_total',
tags=["exc_source:api", f"type:{exc_type}"])
return jsonrpc_error(request, fault_message, rpc_id)
@ -209,14 +207,14 @@ def request_view(request):
if not auth_u.ip_allowed:
return jsonrpc_error(
request, retid=request.rpc_id,
message='Request from IP:%s not allowed' % (
request.rpc_ip_addr,))
message='Request from IP:{} not allowed'.format(
request.rpc_ip_addr))
else:
log.info('Access for IP:%s allowed', request.rpc_ip_addr)
# register our auth-user
request.rpc_user = auth_u
request.environ['rc_auth_user_id'] = auth_u.user_id
request.environ['rc_auth_user_id'] = str(auth_u.user_id)
# now check if token is valid for API
auth_token = request.rpc_api_key
@ -240,13 +238,15 @@ def request_view(request):
# now that we have a method, add request._req_params to
# self.kargs and dispatch control to WGIController
argspec = inspect.getargspec(func)
arglist = argspec[0]
defaults = map(type, argspec[3] or [])
default_empty = types.NotImplementedType
defs = argspec[3] or []
defaults = [type(a) for a in defs]
default_empty = type(NotImplemented)
# kw arguments required by this method
func_kwargs = dict(itertools.izip_longest(
func_kwargs = dict(itertools.zip_longest(
reversed(arglist), reversed(defaults), fillvalue=default_empty))
# This attribute will need to be first param of a method that uses
@ -279,7 +279,7 @@ def request_view(request):
)
# sanitize extra passed arguments
for k in request.rpc_params.keys()[:]:
for k in list(request.rpc_params.keys()):
if k not in func_kwargs:
del request.rpc_params[k]
@ -292,9 +292,14 @@ def request_view(request):
# register some common functions for usage
attach_context_attributes(TemplateArgs(), request, request.rpc_user.user_id)
statsd = request.registry.statsd
try:
ret_value = func(**call_params)
return jsonrpc_response(request, ret_value)
resp = jsonrpc_response(request, ret_value)
if statsd:
statsd.incr('rhodecode_api_call_success_total')
return resp
except JSONRPCBaseError:
raise
except Exception:
@ -302,11 +307,16 @@ def request_view(request):
exc_info = sys.exc_info()
exc_id, exc_type_name = store_exception(
id(exc_info), exc_info, prefix='rhodecode-api')
error_headers = [('RhodeCode-Exception-Id', str(exc_id)),
('RhodeCode-Exception-Type', str(exc_type_name))]
return jsonrpc_error(
error_headers = {
'RhodeCode-Exception-Id': str(exc_id),
'RhodeCode-Exception-Type': str(exc_type_name)
}
err_resp = jsonrpc_error(
request, retid=request.rpc_id, message='Internal server error',
headers=error_headers)
if statsd:
statsd.incr('rhodecode_api_call_fail_total')
return err_resp
def setup_request(request):
@ -341,10 +351,10 @@ def setup_request(request):
raw_body = request.body
log.debug("Loading JSON body now")
try:
json_body = json.loads(raw_body)
json_body = ext_json.json.loads(raw_body)
except ValueError as e:
# catch JSON errors Here
raise JSONRPCError("JSON parse error ERR:%s RAW:%r" % (e, raw_body))
raise JSONRPCError(f"JSON parse error ERR:{e} RAW:{raw_body!r}")
request.rpc_id = json_body.get('id')
request.rpc_method = json_body.get('method')
@ -368,7 +378,7 @@ def setup_request(request):
log.debug('method: %s, params: %.10240r', request.rpc_method, request.rpc_params)
except KeyError as e:
raise JSONRPCError('Incorrect JSON data. Missing %s' % e)
raise JSONRPCError(f'Incorrect JSON data. Missing {e}')
log.debug('setup complete, now handling method:%s rpcid:%s',
request.rpc_method, request.rpc_id, )
@ -379,7 +389,7 @@ class RoutePredicate(object):
self.val = val
def text(self):
return 'jsonrpc route = %s' % self.val
return f'jsonrpc route = {self.val}'
phash = text
@ -399,7 +409,7 @@ class NotFoundPredicate(object):
self.methods = config.registry.jsonrpc_methods
def text(self):
return 'jsonrpc method not found = {}.'.format(self.val)
return f'jsonrpc method not found = {self.val}'
phash = text
@ -412,7 +422,7 @@ class MethodPredicate(object):
self.method = val
def text(self):
return 'jsonrpc method = %s' % self.method
return f'jsonrpc method = {self.method}'
phash = text
@ -547,8 +557,7 @@ def includeme(config):
config.add_view_predicate('jsonrpc_method', MethodPredicate)
config.add_view_predicate('jsonrpc_method_not_found', NotFoundPredicate)
config.add_renderer(DEFAULT_RENDERER, ExtJsonRenderer(
serializer=json.dumps, indent=4))
config.add_renderer(DEFAULT_RENDERER, ExtJsonRenderer())
config.add_directive('add_jsonrpc_method', add_jsonrpc_method)
config.add_route_predicate(

View file

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2011-2020 RhodeCode GmbH
# Copyright (C) 2011-2023 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
@ -22,7 +20,7 @@
class JSONRPCBaseError(Exception):
def __init__(self, message='', *args):
self.message = message
super(JSONRPCBaseError, self).__init__(message, *args)
super().__init__(message, *args)
class JSONRPCError(JSONRPCBaseError):
@ -33,7 +31,7 @@ class JSONRPCValidationError(JSONRPCBaseError):
def __init__(self, *args, **kwargs):
self.colander_exception = kwargs.pop('colander_exc')
super(JSONRPCValidationError, self).__init__(
super().__init__(
message=self.colander_exception, *args)

View file

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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
@ -45,7 +43,7 @@ def testuser_api(request, baseapp):
# create TOKEN for user, if he doesn't have one
if not cls.test_user.api_key:
AuthTokenModel().create(
user=cls.test_user, description=u'TEST_USER_TOKEN')
user=cls.test_user, description='TEST_USER_TOKEN')
Session().commit()
cls.TEST_USER_LOGIN = cls.test_user.username

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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
@ -32,7 +30,7 @@ class TestApi(object):
def test_Optional_object(self):
option1 = Optional(None)
assert '<Optional:%s>' % (None,) == repr(option1)
assert '<Optional:{}>'.format(None) == repr(option1)
assert option1() is None
assert 1 == Optional.extract(Optional(1))
@ -63,7 +61,7 @@ class TestApi(object):
def test_api_missing_non_optional_param_args_null(self):
id_, params = build_data(self.apikey, 'get_repo')
params = params.replace('"args": {}', '"args": null')
params = params.replace(b'"args": {}', b'"args": null')
response = api_call(self.app, params)
expected = 'Missing non optional `repoid` arg in JSON DATA'
@ -71,7 +69,7 @@ class TestApi(object):
def test_api_missing_non_optional_param_args_bad(self):
id_, params = build_data(self.apikey, 'get_repo')
params = params.replace('"args": {}', '"args": 1')
params = params.replace(b'"args": {}', b'"args": 1')
response = api_call(self.app, params)
expected = 'Missing non optional `repoid` arg in JSON DATA'
@ -111,13 +109,13 @@ class TestApi(object):
def test_api_args_is_null(self):
__, params = build_data(self.apikey, 'get_users', )
params = params.replace('"args": {}', '"args": null')
params = params.replace(b'"args": {}', b'"args": null')
response = api_call(self.app, params)
assert response.status == '200 OK'
def test_api_args_is_bad(self):
__, params = build_data(self.apikey, 'get_users', )
params = params.replace('"args": {}', '"args": 1')
params = params.replace(b'"args": {}', b'"args": 1')
response = api_call(self.app, params)
assert response.status == '200 OK'

View file

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2017-2020 RhodeCode GmbH
# Copyright (C) 2017-2023 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

View file

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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
@ -129,26 +128,30 @@ class TestCommentPullRequest(object):
assert_ok(id_, expected, response.body)
@pytest.mark.backends("git", "hg")
def test_api_comment_pull_request_change_status_with_specific_commit_id(
def test_api_comment_pull_request_change_status_with_specific_commit_id_and_test_commit(
self, pr_util, no_notifications):
pull_request = pr_util.create_pull_request()
pull_request_id = pull_request.pull_request_id
latest_commit_id = 'test_commit'
# inject additional revision, to fail test the status change on
# non-latest commit
pull_request.revisions = pull_request.revisions + ['test_commit']
id_, params = build_data(
self.apikey, 'comment_pull_request',
message='test-change-of-status-not-allowed',
repoid=pull_request.target_repo.repo_name,
pullrequestid=pull_request.pull_request_id,
status='approved', commit_id=latest_commit_id)
response = api_call(self.app, params)
pull_request = PullRequestModel().get(pull_request_id)
comments = CommentsModel().get_comments(
pull_request.target_repo.repo_id, pull_request=pull_request)
expected = {
'pull_request_id': pull_request.pull_request_id,
'comment_id': None,
'comment_id': comments[-1].comment_id,
'status': {'given': 'approved', 'was_changed': False}
}
assert_ok(id_, expected, response.body)
@ -230,19 +233,6 @@ class TestCommentPullRequest(object):
expected = 'userid is not the same as your user'
assert_error(id_, expected, given=response.body)
@pytest.mark.backends("git", "hg")
def test_api_comment_pull_request_non_admin_with_userid_error(self, pr_util):
pull_request = pr_util.create_pull_request()
id_, params = build_data(
self.apikey_regular, 'comment_pull_request',
repoid=pull_request.target_repo.repo_name,
pullrequestid=pull_request.pull_request_id,
userid=TEST_USER_ADMIN_LOGIN)
response = api_call(self.app, params)
expected = 'userid is not the same as your user'
assert_error(id_, expected, given=response.body)
@pytest.mark.backends("git", "hg")
def test_api_comment_pull_request_wrong_commit_id_error(self, pr_util):
pull_request = pr_util.create_pull_request()
@ -288,7 +278,7 @@ class TestCommentPullRequest(object):
assert message_after_edit == text_form_db
@pytest.mark.backends("git", "hg")
def test_api_edit_comment_wrong_version(self, pr_util):
def test_api_edit_comment_wrong_version_mismatch(self, pr_util):
pull_request = pr_util.create_pull_request()
id_, params = build_data(
@ -302,7 +292,7 @@ class TestCommentPullRequest(object):
message_after_edit = 'just message'
id_, params = build_data(
self.apikey_regular,
self.apikey,
'edit_comment',
comment_id=comment_id,
message=message_after_edit,
@ -333,7 +323,7 @@ class TestCommentPullRequest(object):
version=0,
)
response = api_call(self.app, params)
expected = "comment ({}) can't be changed with empty string".format(comment_id, 1)
expected = f"comment ({comment_id}) can't be changed with empty string"
assert_error(id_, expected, given=response.body)
@pytest.mark.backends("git", "hg")

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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
@ -343,7 +342,7 @@ class TestCreatePullRequestApi(object):
commits = [
{'message': 'initial'},
{'message': 'change'},
{'message': 'new-feature', 'parents': ['initial']},
{'message': 'new-feature', 'parents': ['initial'], 'branch': 'feature'},
]
self.commit_ids = backend.create_master_repo(commits)
self.source = backend.create_repo(heads=[source_head])

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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
@ -18,12 +17,9 @@
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import json
import mock
import pytest
from rhodecode.lib.utils2 import safe_unicode
from rhodecode.lib.vcs import settings
from rhodecode.model.meta import Session
from rhodecode.model.repo import RepoModel
@ -32,6 +28,8 @@ from rhodecode.tests import TEST_USER_ADMIN_LOGIN
from rhodecode.api.tests.utils import (
build_data, api_call, assert_ok, assert_error, crash)
from rhodecode.tests.fixture import Fixture
from rhodecode.lib.ext_json import json
from rhodecode.lib.str_utils import safe_str
fixture = Fixture()
@ -66,7 +64,7 @@ class TestCreateRepo(object):
expected = ret
assert_ok(id_, expected, given=response.body)
repo = RepoModel().get_by_repo_name(safe_unicode(expected_name))
repo = RepoModel().get_by_repo_name(safe_str(expected_name))
assert repo is not None
id_, params = build_data(self.apikey, 'get_repo', repoid=expected_name)
@ -77,7 +75,7 @@ class TestCreateRepo(object):
assert body['result']['enable_locking'] is False
assert body['result']['enable_statistics'] is False
fixture.destroy_repo(safe_unicode(expected_name))
fixture.destroy_repo(safe_str(expected_name))
def test_api_create_restricted_repo_type(self, backend):
repo_name = 'api-repo-type-{0}'.format(backend.alias)

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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
@ -181,7 +180,7 @@ class TestCreateUser(object):
personal_group = RepoGroup.get_by_group_name(username)
assert personal_group
assert personal_group.personal == True
assert personal_group.personal is True
assert personal_group.user.username == username
try:

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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
@ -21,6 +20,7 @@
import pytest
from rhodecode.lib.str_utils import safe_bytes
from rhodecode.model.db import Gist
from rhodecode.api.tests.utils import (
build_data, api_call, assert_error, assert_ok)
@ -54,8 +54,8 @@ class TestApiGetGist(object):
def test_api_get_gist_with_content(self, gist_util, http_host_only_stub):
mapping = {
u'filename1.txt': {'content': u'hello world'},
u'filename1ą.txt': {'content': u'hello worldę'}
b'filename1.txt': {'content': b'hello world'},
safe_bytes('filename1ą.txt'): {'content': safe_bytes('hello worldę')}
}
gist = gist_util.create_gist(gist_mapping=mapping)
gist_id = gist.gist_access_id

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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
@ -50,7 +49,7 @@ class TestGetMethod(object):
expected = ['comment_commit',
{'apiuser': '<RequiredType>',
'comment_type': "<Optional:u'note'>",
'comment_type': "<Optional:'note'>",
'commit_id': '<RequiredType>',
'extra_recipients': '<Optional:[]>',
'message': '<RequiredType>',

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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
@ -25,7 +24,8 @@ import urlobject
from rhodecode.api.tests.utils import (
build_data, api_call, assert_error, assert_ok)
from rhodecode.lib import helpers as h
from rhodecode.lib.utils2 import safe_unicode
from rhodecode.lib.str_utils import safe_str
pytestmark = pytest.mark.backends("git", "hg")
@ -50,13 +50,13 @@ class TestGetPullRequest(object):
repo_name=pull_request.target_repo.repo_name,
pull_request_id=pull_request.pull_request_id))
pr_url = safe_unicode(
pr_url = safe_str(
url_obj.with_netloc(http_host_only_stub))
source_url = safe_unicode(
source_url = safe_str(
pull_request.source_repo.clone_url().with_netloc(http_host_only_stub))
target_url = safe_unicode(
target_url = safe_str(
pull_request.target_repo.clone_url().with_netloc(http_host_only_stub))
shadow_url = safe_unicode(
shadow_url = safe_str(
PullRequestModel().get_shadow_clone_url(pull_request))
expected = {

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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
@ -20,12 +19,9 @@
import pytest
import urlobject
from rhodecode.api.tests.utils import (
build_data, api_call, assert_error, assert_ok)
from rhodecode.lib import helpers as h
from rhodecode.lib.utils2 import safe_unicode
pytestmark = pytest.mark.backends("git", "hg")

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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
@ -54,7 +53,7 @@ class TestGetRepoChangeset(object):
details=details,
)
response = api_call(self.app, params)
expected = "commit_id must be a string value got <type 'int'> instead"
expected = "commit_id must be a string value got <class 'int'> instead"
assert_error(id_, expected, given=response.body)
@pytest.mark.parametrize("details", ['basic', 'extended', 'full'])
@ -70,11 +69,11 @@ class TestGetRepoChangeset(object):
result = response.json['result']
assert result
assert len(result) == limit
for x in xrange(limit):
for x in range(limit):
assert result[x]['revision'] == x
if details == 'full':
for x in xrange(limit):
for x in range(limit):
assert 'bookmarks' in result[x]['refs']
assert 'branches' in result[x]['refs']
assert 'tags' in result[x]['refs']
@ -98,7 +97,7 @@ class TestGetRepoChangeset(object):
result = response.json['result']
assert result
assert len(result) == limit
for i in xrange(limit):
for i in range(limit):
assert result[i]['revision'] == int(expected_revision) + i
@pytest.mark.parametrize("details", ['basic', 'extended', 'full'])
@ -126,7 +125,7 @@ class TestGetRepoChangeset(object):
result = response.json['result']
assert result
assert len(result) == limit
for i in xrange(limit):
for i in range(limit):
assert result[i]['revision'] == int(expected_revision) + i
@pytest.mark.parametrize("details", ['basic', 'extended', 'full'])
@ -137,5 +136,5 @@ class TestGetRepoChangeset(object):
details=details,
)
response = api_call(self.app, params)
expected = "commit_id must be a string value got <type 'int'> instead"
expected = "commit_id must be a string value got <class 'int'> instead"
assert_error(id_, expected, given=response.body)

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2020 RhodeCode GmbH
# Copyright (C) 2010-2023 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

Some files were not shown because too many files have changed in this diff Show more