merged default branch into stable
This commit is contained in:
commit
32c32c445c
1001 changed files with 21498 additions and 31876 deletions
17
.babelrc
17
.babelrc
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
15
MANIFEST.in
15
MANIFEST.in
|
|
@ -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
182
Makefile
|
|
@ -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"; \
|
||||
}'
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
95
configs/logging.ini
Normal 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
|
||||
|
|
@ -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
57
conftest.py
Normal 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)
|
||||
296
default.nix
296
default.nix
|
|
@ -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
|
||||
13
docs/.howto
13
docs/.howto
|
|
@ -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
24
docs/Dockerfile
Normal 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"]
|
||||
|
|
@ -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
117
docs/_templates/base.html
vendored
Normal 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>
|
||||
6
docs/_templates/footer.html
vendored
6
docs/_templates/footer.html
vendored
|
|
@ -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 %}
|
||||
18
docs/_templates/layout.html
vendored
18
docs/_templates/layout.html
vendored
|
|
@ -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
204
docs/_templates/page.html
vendored
Normal 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> © {{ copyright }}
|
||||
{%- endtrans %}
|
||||
{%- else %}
|
||||
{% trans copyright=copyright|e -%}
|
||||
Copyright © {{ 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 %}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
'''
|
||||
270
docs/conf.py
270
docs/conf.py
|
|
@ -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 don’t 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")
|
||||
|
|
|
|||
227
docs/default.nix
227
docs/default.nix
|
|
@ -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
|
||||
];
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
[pip2nix]
|
||||
requirements = -r ./requirements_docs.txt
|
||||
output = ./python-packages-generated.nix
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
83
package.json
83
package.json
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
[pip2nix]
|
||||
requirements = ., -r ./requirements.txt, -r ./requirements_pinned.txt
|
||||
output = ./pkgs/python-packages.nix
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
'';
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -1,3 +0,0 @@
|
|||
self: super: {
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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:
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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"],
|
||||
|
|
@ -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]
|
||||
|
|
@ -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"]
|
||||
|
|
@ -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"],
|
||||
|
|
@ -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={
|
||||
|
|
@ -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 = []
|
||||
|
|
@ -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):
|
||||
|
|
@ -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]
|
||||
|
|
@ -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
|
|
@ -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
|
||||
'';
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
22
release.nix
22
release.nix
|
|
@ -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;
|
||||
}
|
||||
397
requirements.txt
397
requirements.txt
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
3
requirements_rc_tools.txt
Normal file
3
requirements_rc_tools.txt
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
4.27.1
|
||||
5.0.0
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>',
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue