Añade el plugin Redmine Git Hosting 5.0.0
This commit is contained in:
parent
cfa0d58b18
commit
a3bddad233
458 changed files with 30396 additions and 1 deletions
|
@ -34,7 +34,7 @@ License v2* (GPL).
|
|||
|
||||
### Redmine Additionals plugin
|
||||
|
||||
* additionals 3.0.0
|
||||
* additionals 3.0.2-master
|
||||
* https://alphanodes.com/redmine-additionals
|
||||
* https://github.com/alphanodes/additionals.git
|
||||
|
||||
|
@ -50,6 +50,12 @@ License v2* (GPL).
|
|||
* https://www.redmine.org/plugins/redmine-ckeditor
|
||||
* http://github.com/a-ono/redmine_ckeditor
|
||||
|
||||
### Redmine Git Hosting plugin
|
||||
|
||||
* git_hosting 5.0.0
|
||||
* http://redmine-git-hosting.io
|
||||
* https://github.com/jbox-web/redmine_git_hosting
|
||||
|
||||
### Redmine Glossary Plugin
|
||||
|
||||
* glossary 1.1.0
|
||||
|
|
35
plugins/redmine_git_hosting/.github/workflows/brakeman.yml
vendored
Normal file
35
plugins/redmine_git_hosting/.github/workflows/brakeman.yml
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
name: Run Brakeman
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install package dependencies
|
||||
run: >
|
||||
sudo apt-get install --yes --quiet
|
||||
pandoc
|
||||
|
||||
- name: Set up Ruby 2.6
|
||||
uses: actions/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 2.6.x
|
||||
|
||||
- name: Setup gems
|
||||
run: |
|
||||
echo "source 'https://rubygems.org'" > Gemfile
|
||||
echo "group :test do" >> Gemfile
|
||||
echo " gem 'brakeman', require: false" >> Gemfile
|
||||
echo " gem 'pandoc-ruby', require: false" >> Gemfile
|
||||
echo "end">> Gemfile
|
||||
gem install bundler
|
||||
bundle install --jobs 4 --retry 3
|
||||
|
||||
- name: Run Brakeman
|
||||
run: |
|
||||
bundle exec brakeman -5
|
44
plugins/redmine_git_hosting/.github/workflows/linters.yml
vendored
Normal file
44
plugins/redmine_git_hosting/.github/workflows/linters.yml
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
name: Run Linters
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install package dependencies
|
||||
run: >
|
||||
sudo apt-get install --yes --quiet
|
||||
pandoc
|
||||
|
||||
- name: Set up Ruby 2.6
|
||||
uses: actions/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 2.6.x
|
||||
|
||||
- name: Setup gems
|
||||
run: |
|
||||
echo "source 'https://rubygems.org'" > Gemfile
|
||||
echo "group :test do" >> Gemfile
|
||||
echo " gem 'pandoc-ruby', require: false" >> Gemfile
|
||||
echo " gem 'rubocop', require: false" >> Gemfile
|
||||
echo " gem 'rubocop-performance', require: false" >> Gemfile
|
||||
echo " gem 'rubocop-rails', require: false" >> Gemfile
|
||||
echo " gem 'rubocop-rspec', require: false" >> Gemfile
|
||||
echo " gem 'slim_lint', require: false" >> Gemfile
|
||||
echo "end" >> Gemfile
|
||||
gem install bundler
|
||||
bundle install --jobs 4 --retry 3
|
||||
|
||||
- name: Run RuboCop
|
||||
run: |
|
||||
bundle exec rubocop -S
|
||||
|
||||
- name: Run Slim-Lint
|
||||
run: |
|
||||
bundle exec slim-lint app/views
|
||||
if: always()
|
162
plugins/redmine_git_hosting/.github/workflows/test.yml
vendored
Normal file
162
plugins/redmine_git_hosting/.github/workflows/test.yml
vendored
Normal file
|
@ -0,0 +1,162 @@
|
|||
name: Test
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: ${{ matrix.redmine }} ${{ matrix.db }} ruby-${{ matrix.ruby }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
ruby: ['2.6', '2.4']
|
||||
redmine: ['4.1-stable', 'master']
|
||||
db: ['postgres', 'mysql']
|
||||
fail-fast: false
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:13
|
||||
env:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
ports:
|
||||
- 5432:5432
|
||||
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
|
||||
mysql:
|
||||
image: mysql:5.7
|
||||
env:
|
||||
MYSQL_USER: root
|
||||
MYSQL_PASSWORD: ''
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
||||
ports:
|
||||
- 3306:3306
|
||||
options: >-
|
||||
--health-cmd="mysqladmin ping"
|
||||
--health-interval=10s
|
||||
--health-timeout=5s
|
||||
--health-retries=3
|
||||
|
||||
steps:
|
||||
- name: Verify MySQL connection from host
|
||||
run: |
|
||||
mysql --host 127.0.0.1 --port 3306 -uroot -e "SHOW DATABASES"
|
||||
if: matrix.db == 'mysql'
|
||||
|
||||
- name: Checkout Redmine
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: redmine/redmine
|
||||
ref: ${{ matrix.redmine }}
|
||||
path: redmine
|
||||
|
||||
- name: Checkout redmine_git_hosting
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: redmine/plugins/redmine_git_hosting
|
||||
|
||||
- name: Checkout additionals
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: AlphaNodes/additionals
|
||||
path: redmine/plugins/additionals
|
||||
|
||||
- name: Checkout redmine_sidekiq
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: ogom/redmine_sidekiq
|
||||
path: redmine/plugins/redmine_sidekiq
|
||||
|
||||
- name: Checkout gitolite
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: sitaramc/gitolite
|
||||
path: gitolite
|
||||
|
||||
- name: Update package archives
|
||||
run: sudo apt-get update --yes --quiet
|
||||
|
||||
- name: Install package dependencies
|
||||
run: >
|
||||
sudo apt-get install --yes --quiet
|
||||
build-essential
|
||||
cmake
|
||||
libgpg-error-dev
|
||||
libicu-dev
|
||||
libpq-dev
|
||||
libmysqlclient-dev
|
||||
libssh2-1
|
||||
libssh2-1-dev
|
||||
subversion
|
||||
|
||||
- name: Setup Ruby
|
||||
uses: actions/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: ${{ matrix.ruby }}
|
||||
|
||||
- name: Setup Cache
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: vendor
|
||||
key: v1-ruby-${{ matrix.ruby }}-redmine-${{ matrix.redmine }}
|
||||
|
||||
- name: Setup Bundler
|
||||
run: |
|
||||
gem install bundler -v '~> 1.0'
|
||||
bundle config path "$(pwd)/vendor/bundle"
|
||||
|
||||
- name: Prepare Redmine source
|
||||
working-directory: redmine
|
||||
run: |
|
||||
sed -i '/rubocop/d' Gemfile
|
||||
rm -f .rubocop*
|
||||
cp plugins/redmine_git_hosting/contrib/github/database-${{ matrix.db }}.yml config/database.yml
|
||||
|
||||
- name: Install admin ssh key
|
||||
working-directory: redmine
|
||||
run: |
|
||||
ssh-keygen -N '' -f plugins/redmine_git_hosting/ssh_keys/redmine_gitolite_admin_id_rsa
|
||||
|
||||
- name: Install Gitolite
|
||||
working-directory: redmine
|
||||
run: |
|
||||
sudo useradd --create-home git
|
||||
sudo -n -u git -i mkdir bin
|
||||
sudo -n -u git -i $GITHUB_WORKSPACE/gitolite/install -to /home/git/bin
|
||||
sudo cp plugins/redmine_git_hosting/ssh_keys/redmine_gitolite_admin_id_rsa.pub /home/git/
|
||||
sudo chown git.git /home/git/redmine_gitolite_admin_id_rsa.pub
|
||||
sudo -n -u git -i bin/gitolite setup -pk redmine_gitolite_admin_id_rsa.pub
|
||||
|
||||
- name: Install Ruby dependencies
|
||||
working-directory: redmine
|
||||
run: |
|
||||
bundle install --jobs=4 --retry=3 --without development
|
||||
|
||||
- name: Run Redmine rake tasks
|
||||
env:
|
||||
RAILS_ENV: test
|
||||
working-directory: redmine
|
||||
run: |
|
||||
bundle exec rake generate_secret_token
|
||||
bundle exec rake db:create db:migrate redmine:plugins:migrate
|
||||
bundle exec rake db:test:prepare
|
||||
|
||||
- name: Install rspec file
|
||||
working-directory: redmine
|
||||
run: |
|
||||
mkdir spec
|
||||
cp plugins/redmine_git_hosting/spec/root_spec_helper.rb spec/spec_helper.rb
|
||||
|
||||
- name: Run tests
|
||||
env:
|
||||
RAILS_ENV: test
|
||||
REDMINE_VERSION: ${{ matrix.redmine }}
|
||||
working-directory: redmine
|
||||
run: bundle exec rake redmine_git_hosting:ci:all
|
11
plugins/redmine_git_hosting/.gitignore
vendored
Normal file
11
plugins/redmine_git_hosting/.gitignore
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
.*.swp
|
||||
Gemfile.lock
|
||||
settings.yml
|
||||
/tmp
|
||||
/rdoc
|
||||
/coverage
|
||||
/junit
|
||||
custom_hooks.rb
|
||||
/ssh_keys/redmine_gitolite_admin_id_rsa*
|
||||
.DS_Store
|
||||
coverage/
|
84
plugins/redmine_git_hosting/.rubocop.yml
Normal file
84
plugins/redmine_git_hosting/.rubocop.yml
Normal file
|
@ -0,0 +1,84 @@
|
|||
inherit_from: .rubocop_todo.yml
|
||||
|
||||
require:
|
||||
- rubocop-performance
|
||||
- rubocop-rails
|
||||
|
||||
Rails:
|
||||
Enabled: true
|
||||
|
||||
AllCops:
|
||||
TargetRubyVersion: 2.4
|
||||
TargetRailsVersion: 5.2
|
||||
NewCops: enable
|
||||
Include:
|
||||
- '**/*.ruby'
|
||||
- '**/*.rake'
|
||||
- '**/*.rb'
|
||||
- '**/*.rsb'
|
||||
- '**/Rakefile'
|
||||
- '**/Gemfile'
|
||||
|
||||
Metrics/AbcSize:
|
||||
Enabled: false
|
||||
|
||||
Metrics/BlockLength:
|
||||
Enabled: false
|
||||
|
||||
Metrics/ClassLength:
|
||||
Enabled: false
|
||||
|
||||
Metrics/CyclomaticComplexity:
|
||||
Enabled: false
|
||||
|
||||
Layout/LineLength:
|
||||
Max: 140
|
||||
|
||||
Metrics/MethodLength:
|
||||
Enabled: false
|
||||
|
||||
Metrics/ModuleLength:
|
||||
Enabled: false
|
||||
|
||||
Metrics/PerceivedComplexity:
|
||||
Max: 45
|
||||
|
||||
Rails/ApplicationJob:
|
||||
Enabled: false
|
||||
|
||||
Rails/ApplicationRecord:
|
||||
Enabled: false
|
||||
|
||||
Rails/CreateTableWithTimestamps:
|
||||
Enabled: false
|
||||
|
||||
Rails/HelperInstanceVariable:
|
||||
Enabled: false
|
||||
|
||||
Rails/SkipsModelValidations:
|
||||
Enabled: false
|
||||
|
||||
Performance/ChainArrayAllocation:
|
||||
Enabled: true
|
||||
|
||||
Style/AutoResourceCleanup:
|
||||
Enabled: true
|
||||
|
||||
Style/FrozenStringLiteralComment:
|
||||
Enabled: false
|
||||
|
||||
Style/Documentation:
|
||||
Enabled: false
|
||||
|
||||
# required for travis/ci (symbolic links problem)
|
||||
Style/ExpandPathArguments:
|
||||
Enabled: false
|
||||
|
||||
Style/HashTransformKeys:
|
||||
Enabled: false
|
||||
|
||||
Style/HashTransformValues:
|
||||
Enabled: false
|
||||
|
||||
Naming/VariableNumber:
|
||||
Enabled: false
|
968
plugins/redmine_git_hosting/.rubocop_todo.yml
Normal file
968
plugins/redmine_git_hosting/.rubocop_todo.yml
Normal file
|
@ -0,0 +1,968 @@
|
|||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config`
|
||||
# on 2020-12-22 17:24:13 UTC using RuboCop version 1.6.1.
|
||||
# The point is for the user to remove these configuration records
|
||||
# one by one as the offenses are removed from the code base.
|
||||
# Note that changes in the inspected code, or installation of new
|
||||
# versions of RuboCop, may require this file to be generated again.
|
||||
|
||||
# Offense count: 35
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
||||
# URISchemes: http, https
|
||||
Layout/LineLength:
|
||||
Max: 614
|
||||
|
||||
# Offense count: 4
|
||||
# Configuration parameters: AllowSafeAssignment.
|
||||
Lint/AssignmentInCondition:
|
||||
Exclude:
|
||||
- 'app/services/redmine_hooks/update_mirrors.rb'
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
- 'lib/redmine_git_hosting/patches/grack_auth_patch.rb'
|
||||
- 'lib/redmine_git_hosting/shell_redirector.rb'
|
||||
|
||||
# Offense count: 14
|
||||
# Configuration parameters: AllowedMethods.
|
||||
# AllowedMethods: enums
|
||||
Lint/ConstantDefinitionInBlock:
|
||||
Exclude:
|
||||
- 'spec/helpers/gitolite_public_keys_helper_spec.rb'
|
||||
- 'spec/lib/redmine_git_hosting/config_spec.rb'
|
||||
- 'spec/models/gitolite_public_key_spec.rb'
|
||||
- 'spec/models/repository_deployment_credential_spec.rb'
|
||||
- 'spec/models/repository_mirror_spec.rb'
|
||||
- 'spec/models/repository_xitolite_spec.rb'
|
||||
- 'spec/support/flat_organization.rb'
|
||||
- 'spec/support/hierarchical_organisation.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: AllowComments, AllowEmptyLambdas.
|
||||
Lint/EmptyBlock:
|
||||
Exclude:
|
||||
- 'spec/factories/member.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Lint/Loop:
|
||||
Exclude:
|
||||
- 'app/use_cases/gitolite_public_keys/generate_identifier.rb'
|
||||
|
||||
# Offense count: 5
|
||||
Lint/MissingSuper:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/error.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_wrappers/base.rb'
|
||||
- 'lib/redmine_git_hosting/plugins/extenders/base_extender.rb'
|
||||
- 'lib/redmine_git_hosting/plugins/gitolite_plugin.rb'
|
||||
- 'lib/redmine_git_hosting/plugins/sweepers/base_sweeper.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
Lint/NonDeterministicRequireOrder:
|
||||
Exclude:
|
||||
- 'spec/root_spec_helper.rb'
|
||||
|
||||
# Offense count: 1
|
||||
Lint/NonLocalExitFromIterator:
|
||||
Exclude:
|
||||
- 'app/workers/githosting_shell_worker.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Lint/RedundantStringCoercion:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/recycle_bin/deletable_item.rb'
|
||||
|
||||
# Offense count: 1
|
||||
Lint/RescueException:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/gitolite_hooks.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
Lint/SendWithMixinArgument:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/patches/projects_controller_patch.rb'
|
||||
- 'lib/redmine_git_hosting/patches/repositories_controller_patch.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Lint/ToJSON:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/git_access_status.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments.
|
||||
Lint/UnusedBlockArgument:
|
||||
Exclude:
|
||||
- 'app/reports/repository_contributors_stats.rb'
|
||||
|
||||
# Offense count: 10
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods.
|
||||
Lint/UnusedMethodArgument:
|
||||
Exclude:
|
||||
- 'app/services/redmine_hooks/base.rb'
|
||||
- 'app/use_cases/repository_protected_branches/member_manager.rb'
|
||||
- 'lib/redmine_git_hosting/cache/memcached.rb'
|
||||
- 'lib/redmine_git_hosting/config/gitolite_config_tests.rb'
|
||||
- 'lib/redmine_git_hosting/console_logger.rb'
|
||||
- 'lib/redmine_git_hosting/mirror_keys_installer.rb'
|
||||
- 'spec/support/crud_controller_spec/helpers.rb'
|
||||
|
||||
# Offense count: 1
|
||||
Lint/UriEscapeUnescape:
|
||||
Exclude:
|
||||
- 'contrib/hooks/post-receive/lib/git_hosting_http_helper.rb'
|
||||
|
||||
# Offense count: 37
|
||||
Lint/UselessAssignment:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: Max, CountKeywordArgs, MaxOptionalParameters.
|
||||
Metrics/ParameterLists:
|
||||
Exclude:
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
|
||||
# Offense count: 7
|
||||
Naming/AccessorMethodName:
|
||||
Exclude:
|
||||
- 'app/models/concerns/gitolitable/paths.rb'
|
||||
- 'contrib/hooks/post-receive/lib/git_hosting_custom_hook.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_params/mailer_params.rb'
|
||||
- 'lib/redmine_git_hosting/recycle_bin/manager.rb'
|
||||
- 'lib/redmine_git_hosting/redmine_plugin_loader.rb'
|
||||
- 'spec/support/global_helpers.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Configuration parameters: ForbiddenDelimiters.
|
||||
# ForbiddenDelimiters: (?-mix:(^|\s)(EO[A-Z]{1}|END)(\s|$))
|
||||
Naming/HeredocDelimiterNaming:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/shell_redirector.rb'
|
||||
|
||||
# Offense count: 5
|
||||
# Configuration parameters: EnforcedStyleForLeadingUnderscores.
|
||||
# SupportedStylesForLeadingUnderscores: disallowed, required, optional
|
||||
Naming/MemoizedInstanceVariableName:
|
||||
Exclude:
|
||||
- 'app/reports/repository_contributors_stats.rb'
|
||||
- 'lib/redmine_git_hosting/config/gitolite_base.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_handlers/repositories/move_repository.rb'
|
||||
- 'lib/redmine_git_hosting/redmine_plugin_loader.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros.
|
||||
# NamePrefix: is_, has_, have_
|
||||
# ForbiddenPrefixes: is_, has_, have_
|
||||
# AllowedMethods: is_a?
|
||||
# MethodDefinitionMacros: define_method, define_singleton_method
|
||||
Naming/PredicateName:
|
||||
Exclude:
|
||||
- 'app/models/concerns/gitolitable/validations.rb'
|
||||
- 'app/models/gitolite_public_key.rb'
|
||||
- 'lib/redmine_git_hosting/patches/grack_auth_patch.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: PreferredName.
|
||||
Naming/RescuedExceptionsVariableName:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/gitolite_hooks.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# Cop supports --auto-correct.
|
||||
Performance/BlockGivenWithExplicitBlock:
|
||||
Exclude:
|
||||
- 'app/use_cases/repository_protected_branches/member_manager.rb'
|
||||
- 'lib/redmine_git_hosting/config/gitolite_config_tests.rb'
|
||||
- 'lib/redmine_git_hosting/console_logger.rb'
|
||||
- 'lib/redmine_git_hosting/shell_redirector.rb'
|
||||
|
||||
# Offense count: 31
|
||||
Performance/ChainArrayAllocation:
|
||||
Exclude:
|
||||
- 'app/forms/plugin_settings_form.rb'
|
||||
- 'app/models/concerns/gitolitable/notifications.rb'
|
||||
- 'app/models/concerns/gitolitable/users.rb'
|
||||
- 'app/models/repository_protected_branche.rb'
|
||||
- 'app/use_cases/repository_protected_branches/member_manager.rb'
|
||||
- 'db/migrate/20150823030100_migrate_protected_branches_users.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_wrappers/projects/common.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_wrappers/projects/move_repositories.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_wrappers/projects/move_repositories_tree.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_wrappers/projects/update_projects.rb'
|
||||
- 'lib/redmine_git_hosting/patches/changeset_patch.rb'
|
||||
- 'lib/redmine_git_hosting/patches/project_patch.rb'
|
||||
- 'lib/redmine_git_hosting/patches/projects_controller_patch.rb'
|
||||
- 'lib/redmine_git_hosting/patches/user_patch.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Performance/CompareWithBlock:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/patches/project_patch.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
Performance/Detect:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/gitolite_handlers/ssh_keys/base.rb'
|
||||
- 'lib/redmine_git_hosting/plugins/gitolite_plugin.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
Performance/RedundantBlockCall:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/shell_redirector.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
Performance/RedundantMatch:
|
||||
Exclude:
|
||||
- 'app/use_cases/repositories/build_payload.rb'
|
||||
- 'lib/redmine_git_hosting/config/gitolite_config_tests.rb'
|
||||
|
||||
# Offense count: 6
|
||||
# Cop supports --auto-correct.
|
||||
Performance/RegexpMatch:
|
||||
Exclude:
|
||||
- 'app/use_cases/repositories/build_payload.rb'
|
||||
- 'lib/redmine_git_hosting/config/gitolite_config_tests.rb'
|
||||
- 'lib/redmine_git_hosting/config/gitolite_infos.rb'
|
||||
- 'lib/redmine_git_hosting/shell_redirector.rb'
|
||||
|
||||
# Offense count: 5
|
||||
# Cop supports --auto-correct.
|
||||
Performance/ReverseEach:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/gitolite_wrappers/projects/common.rb'
|
||||
- 'lib/redmine_git_hosting/patches/projects_controller_patch.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Performance/SortReverse:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/recycle_bin/item_base.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AutoCorrect.
|
||||
Performance/StringInclude:
|
||||
Exclude:
|
||||
- 'app/use_cases/repositories/build_payload.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: strict, flexible
|
||||
Rails/Date:
|
||||
Exclude:
|
||||
- 'app/reports/report_helper.rb'
|
||||
|
||||
# Offense count: 7
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforceForPrefixed.
|
||||
Rails/Delegate:
|
||||
Exclude:
|
||||
- 'app/models/repository/xitolite.rb'
|
||||
- 'lib/redmine_git_hosting/cache.rb'
|
||||
- 'lib/redmine_git_hosting/recycle_bin.rb'
|
||||
|
||||
# Offense count: 45
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: Whitelist, AllowedMethods, AllowedReceivers.
|
||||
# Whitelist: find_by_sql
|
||||
# AllowedMethods: find_by_sql
|
||||
# AllowedReceivers: Gem::Specification
|
||||
Rails/DynamicFindBy:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 9
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/models/**/*.rb
|
||||
Rails/InverseOf:
|
||||
Exclude:
|
||||
- 'app/models/repository/xitolite.rb'
|
||||
- 'app/models/repository_protected_branche.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
Rails/NegateInclude:
|
||||
Exclude:
|
||||
- 'app/use_cases/repository_protected_branches/member_manager.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_wrappers/global/disable_rw_access.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_wrappers/global/enable_rw_access.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/**/*.rb, config/**/*.rb, db/**/*.rb, lib/**/*.rb
|
||||
Rails/Output:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/config/base.rb'
|
||||
|
||||
# Offense count: 5
|
||||
Rails/OutputSafety:
|
||||
Exclude:
|
||||
- 'app/helpers/gitolite_plugin_settings_helper.rb'
|
||||
- 'app/presenters/repository_presenter.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
Rails/Pluck:
|
||||
Exclude:
|
||||
- 'app/reports/repository_contributors_stats.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Rails/Presence:
|
||||
Exclude:
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
|
||||
# Offense count: 6
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: NotNilAndNotEmpty, NotBlank, UnlessBlank.
|
||||
Rails/Present:
|
||||
Exclude:
|
||||
- 'app/use_cases/repository_mirrors/push.rb'
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_wrappers/repositories/delete_repository.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: Include.
|
||||
# Include: **/Rakefile, **/*.rake
|
||||
Rails/RakeEnvironment:
|
||||
Exclude:
|
||||
- 'lib/tasks/redmine_git_hosting.rake'
|
||||
|
||||
# Offense count: 6
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: strict, flexible
|
||||
Rails/TimeZone:
|
||||
Exclude:
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
- 'lib/redmine_git_hosting/cache/abstract_cache.rb'
|
||||
- 'lib/redmine_git_hosting/plugins/extenders/readme_creator.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/models/**/*.rb
|
||||
Rails/UniqueValidationWithoutIndex:
|
||||
Exclude:
|
||||
- 'app/models/gitolite_public_key.rb'
|
||||
- 'app/models/repository_protected_branche.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/models/**/*.rb
|
||||
Rails/Validation:
|
||||
Exclude:
|
||||
- 'app/models/concerns/gitolitable/validations.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Rails/WhereEquals:
|
||||
Exclude:
|
||||
- 'app/reports/repository_commits_stats.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Security/YAMLLoad:
|
||||
Exclude:
|
||||
- 'spec/support/global_helpers.rb'
|
||||
|
||||
# Offense count: 23
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: separated, grouped
|
||||
Style/AccessorGrouping:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/error.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_handlers/repositories/base.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_handlers/ssh_keys/base.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_params/global_params.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_params/mailer_params.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_wrappers/base.rb'
|
||||
- 'lib/redmine_git_hosting/recycle_bin/item_base.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: prefer_alias, prefer_alias_method
|
||||
Style/Alias:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/git_access_status.rb'
|
||||
|
||||
# Offense count: 9
|
||||
# Configuration parameters: AllowedChars.
|
||||
Style/AsciiComments:
|
||||
Exclude:
|
||||
- 'app/models/gitolite_public_key.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowOnConstant.
|
||||
Style/CaseEquality:
|
||||
Exclude:
|
||||
- 'app/helpers/repository_mirrors_helper.rb'
|
||||
|
||||
# Offense count: 5
|
||||
# Cop supports --auto-correct.
|
||||
Style/CaseLikeIf:
|
||||
Exclude:
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
- 'lib/redmine_git_hosting/config/gitolite_infos.rb'
|
||||
- 'lib/redmine_git_hosting/plugins/sweepers/repository_deletor.rb'
|
||||
- 'lib/redmine_git_hosting/shell_redirector.rb'
|
||||
|
||||
# Offense count: 11
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: nested, compact
|
||||
Style/ClassAndModuleChildren:
|
||||
Exclude:
|
||||
- 'app/models/repository/xitolite.rb'
|
||||
- 'app/models/repository_git_config_key/git_config.rb'
|
||||
- 'app/models/repository_git_config_key/option.rb'
|
||||
- 'lib/redmine_git_hosting/plugins/extenders/base_extender.rb'
|
||||
- 'lib/redmine_git_hosting/plugins/extenders/branch_updater.rb'
|
||||
- 'lib/redmine_git_hosting/plugins/extenders/config_key_deletor.rb'
|
||||
- 'lib/redmine_git_hosting/plugins/extenders/git_annex_creator.rb'
|
||||
- 'lib/redmine_git_hosting/plugins/extenders/readme_creator.rb'
|
||||
- 'lib/redmine_git_hosting/plugins/gitolite_plugin.rb'
|
||||
- 'lib/redmine_git_hosting/plugins/sweepers/base_sweeper.rb'
|
||||
- 'lib/redmine_git_hosting/plugins/sweepers/repository_deletor.rb'
|
||||
|
||||
# Offense count: 6
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: IgnoredMethods.
|
||||
# IgnoredMethods: ==, equal?, eql?
|
||||
Style/ClassEqualityComparison:
|
||||
Exclude:
|
||||
- 'app/models/protected_branches_member.rb'
|
||||
- 'app/models/repository_protected_branche.rb'
|
||||
- 'app/use_cases/repository_protected_branches/member_manager.rb'
|
||||
- 'lib/redmine_git_hosting/patches/project_patch.rb'
|
||||
|
||||
# Offense count: 3
|
||||
Style/ClassVars:
|
||||
Exclude:
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Style/ColonMethodCall:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/config/gitolite_access.rb'
|
||||
|
||||
# Offense count: 5
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, AllowInnerBackticks.
|
||||
# SupportedStyles: backticks, percent_x, mixed
|
||||
Style/CommandLiteral:
|
||||
Exclude:
|
||||
- 'contrib/hooks/post-receive/lib/git_hosting_config.rb'
|
||||
- 'lib/redmine_git_hosting/config/gitolite_base.rb'
|
||||
- 'lib/tasks/ci_tools.rake'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: Keywords.
|
||||
# Keywords: TODO, FIXME, OPTIMIZE, HACK, REVIEW, NOTE
|
||||
Style/CommentAnnotation:
|
||||
Exclude:
|
||||
- 'app/models/concerns/gitolitable/cache.rb'
|
||||
- 'lib/redmine_git_hosting/patches/grack_git_patch.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SingleLineConditionsOnly, IncludeTernaryExpressions.
|
||||
# SupportedStyles: assign_to_condition, assign_inside_condition
|
||||
Style/ConditionalAssignment:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/config/gitolite_access.rb'
|
||||
- 'lib/redmine_git_hosting/patches/repositories_controller_patch.rb'
|
||||
- 'lib/redmine_git_hosting/shell_redirector.rb'
|
||||
- 'spec/support/global_helpers.rb'
|
||||
|
||||
# Offense count: 3
|
||||
Style/DocumentDynamicEvalDefinition:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/shell_redirector.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Style/EachWithObject:
|
||||
Exclude:
|
||||
- 'app/models/concerns/gitolitable/validations.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: empty, nil, both
|
||||
Style/EmptyElse:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/config/gitolite_infos.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_handlers/repositories/move_repository.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: compact, expanded
|
||||
Style/EmptyMethod:
|
||||
Exclude:
|
||||
- 'lib/hrack/lib/hrack/server.rb'
|
||||
|
||||
# Offense count: 3
|
||||
Style/EvalWithLocation:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/shell_redirector.rb'
|
||||
|
||||
# Offense count: 16
|
||||
# Configuration parameters: MinBodyLength.
|
||||
Style/GuardClause:
|
||||
Exclude:
|
||||
- 'app/models/concerns/gitolitable/validations.rb'
|
||||
- 'app/services/redmine_hooks/github_issues_sync.rb'
|
||||
- 'app/use_cases/repository_protected_branches/member_manager.rb'
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
- 'lib/redmine_git_hosting/git_access.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_handlers/repositories/move_repository.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_wrapper.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_wrappers/base.rb'
|
||||
- 'lib/redmine_git_hosting/patches/grack_auth_patch.rb'
|
||||
- 'lib/redmine_git_hosting/patches/project_patch.rb'
|
||||
- 'lib/redmine_git_hosting/patches/projects_controller_patch.rb'
|
||||
- 'lib/redmine_git_hosting/patches/setting_patch.rb'
|
||||
- 'lib/redmine_git_hosting/validators.rb'
|
||||
|
||||
# Offense count: 2
|
||||
Style/IdenticalConditionalBranches:
|
||||
Exclude:
|
||||
- 'lib/tasks/migration_tools.rake'
|
||||
|
||||
# Offense count: 6
|
||||
# Cop supports --auto-correct.
|
||||
Style/IfUnlessModifier:
|
||||
Exclude:
|
||||
- 'app/models/concerns/gitolitable/validations.rb'
|
||||
- 'lib/hrack/lib/hrack/server.rb'
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_wrappers/global/enable_rw_access.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Style/IfUnlessModifierOfIfUnless:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/plugins/extenders/readme_creator.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: InverseMethods, InverseBlocks.
|
||||
Style/InverseMethods:
|
||||
Exclude:
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
- 'lib/redmine_git_hosting/cache/memcached.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: IgnoredMethods.
|
||||
Style/MethodCallWithoutArgsParentheses:
|
||||
Exclude:
|
||||
- 'lib/hrack/lib/hrack/server.rb'
|
||||
|
||||
# Offense count: 1
|
||||
Style/MissingRespondToMissing:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/shell_redirector.rb'
|
||||
|
||||
# Offense count: 17
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, Autocorrect.
|
||||
# SupportedStyles: module_function, extend_self, forbidden
|
||||
Style/ModuleFunction:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
Style/MultilineIfModifier:
|
||||
Exclude:
|
||||
- 'app/models/concerns/gitolitable/config.rb'
|
||||
- 'lib/redmine_git_hosting/plugins/extenders/readme_creator.rb'
|
||||
|
||||
# Offense count: 30
|
||||
# Cop supports --auto-correct.
|
||||
Style/MultilineWhenThen:
|
||||
Exclude:
|
||||
- 'db/migrate/20130807223227_migrate_parameters.rb'
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
|
||||
# Offense count: 7
|
||||
# Cop supports --auto-correct.
|
||||
Style/MultipleComparison:
|
||||
Exclude:
|
||||
- 'contrib/hooks/post-receive/lib/git_hosting_custom_hook.rb'
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
- 'lib/redmine_git_hosting/patches/grack_git_patch.rb'
|
||||
- 'spec/support/flat_organization.rb'
|
||||
- 'spec/support/hierarchical_organisation.rb'
|
||||
|
||||
# Offense count: 15
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: literals, strict
|
||||
Style/MutableConstant:
|
||||
Exclude:
|
||||
- 'app/models/repository_git_config_key/git_config.rb'
|
||||
- 'lib/hrack/lib/hrack/server.rb'
|
||||
- 'lib/redmine_git_hosting/config.rb'
|
||||
- 'lib/redmine_git_hosting/patches/repositories_controller_patch.rb'
|
||||
- 'lib/redmine_git_hosting/recycle_bin/item_base.rb'
|
||||
- 'lib/redmine_git_hosting/utils/git.rb'
|
||||
- 'lib/redmine_git_hosting/validators.rb'
|
||||
- 'spec/helpers/gitolite_public_keys_helper_spec.rb'
|
||||
- 'spec/models/repository_deployment_credential_spec.rb'
|
||||
- 'spec/models/repository_mirror_spec.rb'
|
||||
|
||||
# Offense count: 6
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: both, prefix, postfix
|
||||
Style/NegatedIf:
|
||||
Exclude:
|
||||
- 'app/reports/repository_contributors_stats.rb'
|
||||
- 'app/use_cases/repositories/build_payload.rb'
|
||||
- 'lib/hrack/lib/hrack/server.rb'
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_handlers/repositories/move_repository.rb'
|
||||
|
||||
# Offense count: 23
|
||||
# Cop supports --auto-correct.
|
||||
Style/NegatedIfElseCondition:
|
||||
Exclude:
|
||||
- 'contrib/hooks/post-receive/lib/git_hosting_http_helper.rb'
|
||||
- 'db/migrate/20091119162426_set_mirror_role_permissions.rb'
|
||||
- 'db/migrate/20120521000010_set_post_receive_url_role_permissions.rb'
|
||||
- 'db/migrate/20120803043256_create_deployment_credentials.rb'
|
||||
- 'lib/redmine_git_hosting/config/gitolite_base.rb'
|
||||
- 'lib/redmine_git_hosting/config/gitolite_config_tests.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_wrappers/repositories/add_repository.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_wrappers/repositories/move_repository.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_wrappers/repositories/update_repository.rb'
|
||||
- 'lib/redmine_git_hosting/plugins/extenders/git_annex_creator.rb'
|
||||
- 'lib/redmine_git_hosting/recycle_bin/deletable_item.rb'
|
||||
- 'lib/redmine_git_hosting/utils/http.rb'
|
||||
- 'lib/tasks/migration_tools.rake'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Style/NegatedWhile:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/shell_redirector.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Style/NestedTernaryOperator:
|
||||
Exclude:
|
||||
- 'app/reports/report_helper.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, MinBodyLength.
|
||||
# SupportedStyles: skip_modifier_ifs, always
|
||||
Style/Next:
|
||||
Exclude:
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
- 'lib/redmine_git_hosting/config/base.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: IncludeSemanticChanges.
|
||||
Style/NonNilCheck:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/gitolite_params/mailer_params.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedOctalStyle.
|
||||
# SupportedOctalStyles: zero_with_o, zero_only
|
||||
Style/NumericLiteralPrefix:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/config/gitolite_config_tests.rb'
|
||||
- 'lib/redmine_git_hosting/plugins/extenders/readme_creator.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, IgnoredMethods.
|
||||
# SupportedStyles: predicate, comparison
|
||||
Style/NumericPredicate:
|
||||
Exclude:
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
|
||||
# Offense count: 6
|
||||
# Configuration parameters: AllowedMethods.
|
||||
# AllowedMethods: respond_to_missing?
|
||||
Style/OptionalBooleanParameter:
|
||||
Exclude:
|
||||
- 'app/helpers/git_hosting_helper.rb'
|
||||
- 'lib/redmine_git_hosting/commands/sudo.rb'
|
||||
- 'lib/redmine_git_hosting/config/base.rb'
|
||||
- 'lib/redmine_git_hosting/config/gitolite_access.rb'
|
||||
- 'lib/redmine_git_hosting/git_access.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowSafeAssignment, AllowInMultilineConditions.
|
||||
Style/ParenthesesAroundCondition:
|
||||
Exclude:
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
|
||||
# Offense count: 13
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: PreferredDelimiters.
|
||||
Style/PercentLiteralDelimiters:
|
||||
Exclude:
|
||||
- 'contrib/hooks/post-receive/lib/git_hosting_config.rb'
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
- 'lib/redmine_git_hosting/config/gitolite_base.rb'
|
||||
- 'lib/tasks/ci_tools.rake'
|
||||
- 'spec/models/repository_mirror_spec.rb'
|
||||
|
||||
# Offense count: 16
|
||||
# Cop supports --auto-correct.
|
||||
Style/PerlBackrefs:
|
||||
Exclude:
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowedCompactTypes.
|
||||
# SupportedStyles: compact, exploded
|
||||
Style/RaiseArgs:
|
||||
EnforcedStyle: exploded
|
||||
|
||||
# Offense count: 8
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: Methods.
|
||||
Style/RedundantArgument:
|
||||
Exclude:
|
||||
- 'app/models/gitolite_public_key.rb'
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
- 'lib/redmine_git_hosting/commands/git.rb'
|
||||
- 'lib/redmine_git_hosting/commands/sudo.rb'
|
||||
- 'lib/redmine_git_hosting/utils/crypto.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
Style/RedundantAssignment:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/utils/crypto.rb'
|
||||
- 'lib/redmine_git_hosting/utils/ssh.rb'
|
||||
|
||||
# Offense count: 8
|
||||
# Cop supports --auto-correct.
|
||||
Style/RedundantBegin:
|
||||
Exclude:
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
- 'lib/redmine_git_hosting/config/gitolite_config_tests.rb'
|
||||
- 'lib/redmine_git_hosting/config/gitolite_infos.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_handlers/repositories/move_repository.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_wrapper.rb'
|
||||
- 'lib/redmine_git_hosting/recycle_bin/restorable_item.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
Style/RedundantInterpolation:
|
||||
Exclude:
|
||||
- 'app/use_cases/repository_mirrors/push.rb'
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
Style/RedundantParentheses:
|
||||
Exclude:
|
||||
- 'contrib/hooks/post-receive/lib/git_hosting_config.rb'
|
||||
- 'lib/redmine_git_hosting/config/base.rb'
|
||||
- 'lib/redmine_git_hosting/config/gitolite_base.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Style/RedundantRegexpCharacterClass:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/validators.rb'
|
||||
|
||||
# Offense count: 8
|
||||
# Cop supports --auto-correct.
|
||||
Style/RedundantRegexpEscape:
|
||||
Exclude:
|
||||
- 'db/migrate/20111220055819_add_settings_to_plugin_2.rb'
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
- 'lib/redmine_git_hosting/utils/crypto.rb'
|
||||
- 'lib/redmine_git_hosting/validators.rb'
|
||||
|
||||
# Offense count: 13
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowMultipleReturnValues.
|
||||
Style/RedundantReturn:
|
||||
Exclude:
|
||||
- 'app/use_cases/repository_mirrors/push.rb'
|
||||
- 'lib/hrack/lib/hrack/server.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_handlers/repositories/move_repository.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_wrappers/global/disable_rw_access.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
Style/RedundantSelf:
|
||||
Exclude:
|
||||
- 'lib/hrack/lib/hrack/server.rb'
|
||||
- 'lib/redmine_git_hosting/shell_redirector.rb'
|
||||
|
||||
# Offense count: 12
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, AllowInnerSlashes.
|
||||
# SupportedStyles: slashes, percent_r, mixed
|
||||
Style/RegexpLiteral:
|
||||
Exclude:
|
||||
- 'app/models/concerns/gitolitable/cache.rb'
|
||||
- 'app/reports/repository_contributors_stats.rb'
|
||||
- 'app/use_cases/repositories/build_payload.rb'
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
- 'lib/redmine_git_hosting/config/gitolite_access.rb'
|
||||
- 'lib/redmine_git_hosting/patches/grack_auth_patch.rb'
|
||||
- 'lib/redmine_git_hosting/patches/repositories_controller_patch.rb'
|
||||
- 'lib/redmine_git_hosting/recycle_bin/item_base.rb'
|
||||
- 'lib/redmine_git_hosting/utils/crypto.rb'
|
||||
- 'lib/redmine_git_hosting/utils/git.rb'
|
||||
- 'lib/redmine_git_hosting/validators.rb'
|
||||
|
||||
# Offense count: 9
|
||||
# Cop supports --auto-correct.
|
||||
Style/RescueModifier:
|
||||
Exclude:
|
||||
- 'app/models/gitolite_public_key.rb'
|
||||
- 'app/models/repository_mirror.rb'
|
||||
- 'lib/redmine_git_hosting/commands/sudo.rb'
|
||||
- 'lib/redmine_git_hosting/config/base.rb'
|
||||
- 'lib/redmine_git_hosting/config/gitolite_base.rb'
|
||||
- 'lib/redmine_git_hosting/config/gitolite_storage.rb'
|
||||
|
||||
# Offense count: 37
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: implicit, explicit
|
||||
Style/RescueStandardError:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowAsExpressionSeparator.
|
||||
Style/Semicolon:
|
||||
Exclude:
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
- 'lib/redmine_git_hosting/patches/repositories_controller_patch.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowModifier.
|
||||
Style/SoleNestedConditional:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/patches/project_patch.rb'
|
||||
- 'lib/redmine_git_hosting/patches/repositories_controller_patch.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: use_perl_names, use_english_names
|
||||
Style/SpecialGlobalVars:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/shell_redirector.rb'
|
||||
|
||||
# Offense count: 18
|
||||
# Cop supports --auto-correct.
|
||||
Style/StringConcatenation:
|
||||
Exclude:
|
||||
- 'app/helpers/repository_deployment_credentials_helper.rb'
|
||||
- 'app/models/gitolite_public_key.rb'
|
||||
- 'app/use_cases/repository_mirrors/push.rb'
|
||||
- 'lib/redmine_git_hosting/cache.rb'
|
||||
- 'lib/redmine_git_hosting/cache/memcached.rb'
|
||||
- 'lib/redmine_git_hosting/commands/sudo.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_handlers/repositories/move_repository.rb'
|
||||
- 'lib/redmine_git_hosting/hooks.rb'
|
||||
- 'lib/redmine_git_hosting/mirror_keys_installer.rb'
|
||||
- 'lib/redmine_git_hosting/shell_redirector.rb'
|
||||
- 'spec/lib/redmine_git_hosting/config_spec.rb'
|
||||
- 'spec/lib/redmine_git_hosting/utils/git_spec.rb'
|
||||
- 'spec/models/repository_git_config_key/git_config_spec.rb'
|
||||
- 'spec/models/repository_git_config_key/option_spec.rb'
|
||||
- 'spec/services/redmine_hooks/call_webservices_spec.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
|
||||
# SupportedStyles: single_quotes, double_quotes
|
||||
Style/StringLiterals:
|
||||
Exclude:
|
||||
- 'app/models/concerns/gitolitable/validations.rb'
|
||||
- 'app/use_cases/repository_mirrors/push.rb'
|
||||
- 'lib/redmine_git_hosting/commands/sudo.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: single_quotes, double_quotes
|
||||
Style/StringLiteralsInInterpolation:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/utils/exec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: .
|
||||
# SupportedStyles: percent, brackets
|
||||
Style/SymbolArray:
|
||||
EnforcedStyle: percent
|
||||
MinSize: 3
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: IgnoredMethods.
|
||||
# IgnoredMethods: respond_to, define_method
|
||||
Style/SymbolProc:
|
||||
Exclude:
|
||||
- 'app/models/concerns/gitolitable/users.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, AllowSafeAssignment.
|
||||
# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex
|
||||
Style/TernaryParentheses:
|
||||
Exclude:
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, AllowedMethods.
|
||||
# AllowedMethods: to_ary, to_a, to_c, to_enum, to_h, to_hash, to_i, to_int, to_io, to_open, to_path, to_proc, to_r, to_regexp, to_str, to_s, to_sym
|
||||
Style/TrivialAccessors:
|
||||
Exclude:
|
||||
- 'lib/redmine/scm/adapters/xitolite_adapter.rb'
|
||||
- 'lib/redmine_git_hosting/gitolite_hooks.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Style/WhileUntilModifier:
|
||||
Exclude:
|
||||
- 'lib/redmine_git_hosting/shell_redirector.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: WordRegex.
|
||||
# SupportedStyles: percent, brackets
|
||||
Style/WordArray:
|
||||
EnforcedStyle: percent
|
||||
MinSize: 3
|
40
plugins/redmine_git_hosting/.slim-lint.yml
Normal file
40
plugins/redmine_git_hosting/.slim-lint.yml
Normal file
|
@ -0,0 +1,40 @@
|
|||
linters:
|
||||
LineLength:
|
||||
max: 140
|
||||
RuboCop:
|
||||
ignored_cops:
|
||||
- Layout/ArgumentAlignment
|
||||
- Layout/ArrayAlignment
|
||||
- Layout/BlockEndNewline
|
||||
- Layout/EmptyLineAfterGuardClause
|
||||
- Layout/HashAlignment
|
||||
- Layout/IndentationConsistency
|
||||
- Layout/IndentationWidth
|
||||
- Layout/IndentFirstArgument
|
||||
- Layout/IndentFirstArrayElement
|
||||
- Layout/IndentFirstHashElement
|
||||
- Layout/MultilineArrayBraceLayout
|
||||
- Layout/MultilineAssignmentLayout
|
||||
- Layout/MultilineBlockLayout
|
||||
- Layout/MultilineHashBraceLayout
|
||||
- Layout/MultilineMethodCallBraceLayout
|
||||
- Layout/MultilineMethodCallIndentation
|
||||
- Layout/MultilineMethodDefinitionBraceLayout
|
||||
- Layout/MultilineOperationIndentation
|
||||
- Layout/TrailingBlankLines
|
||||
- Layout/TrailingEmptyLines
|
||||
- Layout/TrailingWhitespace
|
||||
- Lint/BlockAlignment
|
||||
- Lint/EndAlignment
|
||||
- Lint/Void
|
||||
- Metrics/BlockLength
|
||||
- Metrics/BlockNesting
|
||||
- Metrics/LineLength
|
||||
- Naming/FileName
|
||||
- Rails/OutputSafety
|
||||
- Style/ConditionalAssignment
|
||||
- Style/FrozenStringLiteralComment
|
||||
- Style/IdenticalConditionalBranches
|
||||
- Style/IfUnlessModifier
|
||||
- Style/Next
|
||||
- Style/WhileUntilModifier
|
66
plugins/redmine_git_hosting/AUTHORS
Normal file
66
plugins/redmine_git_hosting/AUTHORS
Normal file
|
@ -0,0 +1,66 @@
|
|||
Aaron Fellin <aaron@tingar.uni.cx>
|
||||
Alexander Meindl <a.meindl@alphanodes.com>
|
||||
allen-t <kex.allen13@gmail.com>
|
||||
Andrea Piccinelli <frasten@gmail.com>
|
||||
Boris Bera <Boris.Bera@wolterskluwer.com>
|
||||
bullshit <oskar@biglan.at>
|
||||
ciaranj <ciaranj@gmail.com>
|
||||
Clemens Hammacher <hammacher@cs.uni-saarland.de>
|
||||
crocket <crockabiscuit@gmail.com>
|
||||
Daniel Dehennin <daniel.dehennin@baby-gnu.org>
|
||||
Daniel Stoeckel <dstoeckel@bioinf.uni-sb.de>
|
||||
danomatika <danomatika@gmail.com>
|
||||
David Cramer <dcramer@gmail.com>
|
||||
DFYX <dfyx@wecallit42.de>
|
||||
Eric Bishop <ericpaulbishop@gmail.com>
|
||||
Evgeny Generalov <e.generalov@gmail.com>
|
||||
Federico Ramallo <framallo@gmail.com>
|
||||
fjuan <fjuan@splendeo.es>
|
||||
Gartz <gabriel@intuicom.com.br>
|
||||
Geoffroy Desvernay <dgeo@centrale-marseille.fr>
|
||||
Greg Cymbalski <cymbalski@gmail.com>
|
||||
Greg Thornton <xdissent@gmail.com>
|
||||
hboyet <hugo.david-boyet@savoirfairelinux.com>
|
||||
IceArmy <roejames12@hotmail.com>
|
||||
Jan Schulz-Hofen <yeah@yeahrock.de>
|
||||
Jean-Sébastien Bour <jsb@zenexity.com>
|
||||
John Axel Eriksson <john@insane.se>
|
||||
John Kubiatowicz <kubitron@cs.berkeley.edu>
|
||||
Joshua Hogendorn <jhogendorn@gmail.com>
|
||||
Kovalev Vladimir <kovalev@em.mos.ru>
|
||||
Ludovic Schoepps <ludovic.schoepps@gmail.com>
|
||||
Lukas Mika <lukas.mika@web.de>
|
||||
Marco Nenciarini <marco.nenciarini@devise.it>
|
||||
Mario Werner <m.werner@student.tugraz.at>
|
||||
Mathieu Marache <mathieu@marache.com>
|
||||
Matthew Meng <Matthew@Lorraine.local>
|
||||
Matt Meng <maximusstrife@gmail.com>
|
||||
nicesw123 <nicesw123@users.noreply.github.com>
|
||||
Nicholas Clark <nick4jesus@gmail.com>
|
||||
Nicolas Rodriguez <nrodriguez@jbox-web.com>
|
||||
Nils Rokita <0rokita@informatik.uni-hamburg.de>
|
||||
Patrick Naubert <patrickn@xelerance.com>
|
||||
Patrick Roberts <Patrick@silentbluesystems.com>
|
||||
Pedro Algarvio <pedro@algarvio.me>
|
||||
Petter Uvesten <petter@everichon.com>
|
||||
Philip Schiffer <philip.schiffer@gmail.com>
|
||||
Rocket Rentals <contact@rocket-rentals.de>
|
||||
root <root@cori-celesti.org>
|
||||
root <root@hanzo.(none)>
|
||||
rposborne <russosborn@gmail.com>
|
||||
Ryan Thompson <rct@thompsonclan.org>
|
||||
Sebastian Harl <sh@teamix.net>
|
||||
Simon Peeters <peeters.simon@gmail.com>
|
||||
Slotos <slotos@gmail.com>
|
||||
Soeren Helbig <soerenhelbig@gmail.com>
|
||||
Strnadj <jan.strnadek@gmail.com>
|
||||
takahashim <maki@rubycolor.org>
|
||||
Thomas Debesse <thomas.debesse@rcf.fr>
|
||||
Tom Kazimiers <tom@voodoo-arts.net>
|
||||
U-catsby\oddpoet <oddpoet@catsby.(none)>
|
||||
Untoldwind <landru@untoldwind.net>
|
||||
Warren Volz <warren@warrenvolz.com>
|
||||
wilsoc5 <wilsoc5@users.noreply.github.com>
|
||||
Yarema <yds@CoolRat.org>
|
||||
Yunsang Choi <oddpoet@gmail.com>
|
||||
Zsolt Parragi <dutow@mentalstatic.info>
|
614
plugins/redmine_git_hosting/CHANGELOG.md
Normal file
614
plugins/redmine_git_hosting/CHANGELOG.md
Normal file
|
@ -0,0 +1,614 @@
|
|||
# Changelog
|
||||
|
||||
## 5.0.0 - 2020-12-24 🎄
|
||||
|
||||
### Added
|
||||
|
||||
- Basic Auth support for post_receive_urls
|
||||
- post_receive_url :post empty support
|
||||
- Logging to journal, if configured for Redmine (see https://github.com/theforeman/journald-logger)
|
||||
- Dashboard support for Repository URLs
|
||||
|
||||
### Changed
|
||||
|
||||
- Switch CI from Travis to Github Actions
|
||||
|
||||
### BREAKING CHANGE
|
||||
|
||||
- Redmine 4.1+ is required
|
||||
- Dropped archived repository view
|
||||
|
||||
## 4.0.2 - 2020-06-29
|
||||
|
||||
- Support both python 2 and 3
|
||||
- Fix repository settings form template to work with redmine 4.x
|
||||
- Fix #715 by correcting misuse of ActiveRecord API for GitCache objects
|
||||
|
||||
## 4.0.1 - 2020-02-14
|
||||
|
||||
- Resolve Redmine 4.1 incompatiblity
|
||||
- Fix unneccesary checking of duplicate repositories
|
||||
|
||||
## 4.0.0 - 2019-12-03
|
||||
|
||||
* compatible with Redmine 4 (drop Redmine 3.x support)
|
||||
* drop redmine_bootstrap_kit required plugin
|
||||
* requires additionals plugin for latest fontawesome, slim and deface support -> and better maintenance
|
||||
* switch from haml to slim templates (because this is already used in additionals plugin)
|
||||
* libraries high_charts and bootstrap are moved to this plugin (TODO: high_charts should be migrationed to charts.js, which comes with Redmine 4. Bootstrap should be drop to vanila redmine, to get better theme support)
|
||||
|
||||
## 1.2.3 - 2017-07-17
|
||||
|
||||
* Merge [#640](https://github.com/jbox-web/redmine_git_hosting/pull/640) ([Views] Fix typo while rendering partial repositories/download_revision)
|
||||
* Merge [#646](https://github.com/jbox-web/redmine_git_hosting/pull/646) (Fix compatibility with Redmine 3.3)
|
||||
* Merge [#663](https://github.com/jbox-web/redmine_git_hosting/pull/663) ([Core] Fix installation of Gitolite3 hooks)
|
||||
* Improve custom Gitolite hook loading (see `custom_hooks.rb.example` at the root of the project)
|
||||
* Fix plugin icon with Redmine 3.4.x
|
||||
* Fix author url in sub-uri mode
|
||||
* Check if hook's permissions has changed
|
||||
* Catch Errno::ENOENT exceptions when installing custom hooks
|
||||
* Add logs for well installed Gitolite hooks
|
||||
|
||||
## 1.2.2 - 2016-12-31
|
||||
|
||||
* Fix [#472](https://github.com/jbox-web/redmine_git_hosting/issues/472) ([Views] 404 on the "My public keys" link in the user panel)
|
||||
* Fix [#526](https://github.com/jbox-web/redmine_git_hosting/issues/526) ([Core] Plugin breaks if gitolite user == redmine user)
|
||||
* Fix [#551](https://github.com/jbox-web/redmine_git_hosting/issues/551) ([Core] Make Sidekiq truly optional)
|
||||
* Fix [#576](https://github.com/jbox-web/redmine_git_hosting/issues/576) ([Models] Can't add Git Config Key)
|
||||
* Fix [#630](https://github.com/jbox-web/redmine_git_hosting/issues/630) ([Core] Use "gitolite query-rc" to get Gitolite variables)
|
||||
* Fix [#632](https://github.com/jbox-web/redmine_git_hosting/issues/632) ([Core] Mirroring does not work on git push)
|
||||
* Merge [#581](https://github.com/jbox-web/redmine_git_hosting/pull/581) (Fix [#472](https://github.com/jbox-web/redmine_git_hosting/issues/472) by amelentjev)
|
||||
* Merge [#621](https://github.com/jbox-web/redmine_git_hosting/pull/621) ([Routes] Mount grack under http_server_subdir)
|
||||
* Merge [#624](https://github.com/jbox-web/redmine_git_hosting/pull/624) ([Translations] Add Spanish translation)
|
||||
* Merge [#634](https://github.com/jbox-web/redmine_git_hosting/pull/634) ([Views] Added missing mandatory param for partial repositories/download_revision)
|
||||
* Merge [#636](https://github.com/jbox-web/redmine_git_hosting/pull/636) ([Doc] "Remove user ID from Gitolite identifier" requires a restart)
|
||||
* Fix repo url in Gitolite hooks
|
||||
* Fix nil data case when loading custom settings from empty file
|
||||
* Allow to load plugin settings from a file in Redmine root (should ease deployment and upgrades)
|
||||
* Fix wrong Repository Git objects count
|
||||
* Add Russian translation
|
||||
* Rename `redmine_git_hosting:restore_defaults` task to `redmine_git_hosting:update_settings`
|
||||
* Add Rake task `redmine_git_hosting:dump_settings` to dump plugin settings in console
|
||||
|
||||
## 1.2.1 - 2016-07-25
|
||||
|
||||
* Fix [#524](https://github.com/jbox-web/redmine_git_hosting/issues/524) ([DB] Index too long)
|
||||
* Fix [#533](https://github.com/jbox-web/redmine_git_hosting/issues/533) ([Views] About readme.md preview feature)
|
||||
* Fix [#541](https://github.com/jbox-web/redmine_git_hosting/issues/541) ([Core] SSH/Gitolite server host on 1.2)
|
||||
* Fix [#553](https://github.com/jbox-web/redmine_git_hosting/issues/553) ([Controllers] Protected branches user list never updated. Mass-assign warning.)
|
||||
* Fix [#569](https://github.com/jbox-web/redmine_git_hosting/issues/569) ([Core] Connection refused when sshd doesn't listen on default port)
|
||||
* Merge [#583](https://github.com/jbox-web/redmine_git_hosting/pull/583) ([Core] force UTF-8 encoding for tags and branches)
|
||||
* Merge [#600](https://github.com/jbox-web/redmine_git_hosting/pull/600) ([Core] Improve performance)
|
||||
|
||||
## 1.2.0 - 2015-11-18
|
||||
|
||||
* Enhance protected branches permissions support : [#389](https://github.com/jbox-web/redmine_git_hosting/issues/389), [#414](https://github.com/jbox-web/redmine_git_hosting/issues/414)
|
||||
* Add support for [Gitolite options](https://gitolite.com/gitolite/options.html) : [#415](https://github.com/jbox-web/redmine_git_hosting/issues/415)
|
||||
* Enhance global repository access : [#465](https://github.com/jbox-web/redmine_git_hosting/issues/465). You can now choose if Redmine has RW access on all repositories.
|
||||
* Improve validation of plugin settings. Validation errors are now displayed in the view.
|
||||
* Use our own Rack implementation to render Gitolite hooks
|
||||
* Fix [push over HTTP](http://redmine-git-hosting.io/troubleshooting/#hook-errors-while-pushing-over-https)
|
||||
* Cleanup code/API
|
||||
* Improve coding style
|
||||
* Display contributors in plugins info page ;)
|
||||
|
||||
## 1.1.5 - 2015-11-18
|
||||
|
||||
* Fix wrong behavior of GoRedirectorController when project is private
|
||||
* Update Redcarpet to latest version (3.3.2)
|
||||
|
||||
## 1.1.4 - 2015-10-01
|
||||
|
||||
* Merge [#505](https://github.com/jbox-web/redmine_git_hosting/pull/505) ([Core] Added an error message in case that something as broken the temp directory)
|
||||
* Fix #<TypeError: no implicit conversion of nil into String> when triggers are enabled on PostReceiveUrls and pushing on a non-triggering branch
|
||||
* Fix #<TypeError: no implicit conversion of nil into String> when triggers (refspec) are enabled on RepositoryMirrors and pushing on a non-triggering branch
|
||||
|
||||
## 1.1.3 - 2015-08-30
|
||||
|
||||
* Merge [#350](https://github.com/jbox-web/redmine_git_hosting/pull/350) ([Core] return [] if error occured on branches or tags check)
|
||||
* Fix [#472](https://github.com/jbox-web/redmine_git_hosting/issues/472) ([Views] 404 on the "My public keys" link in the user panel when Redmine is installed in a subpath)
|
||||
* Fix [#484](https://github.com/jbox-web/redmine_git_hosting/issues/484) ([Core] Error 500 on repository creation & edit)
|
||||
* Fix [#501](https://github.com/jbox-web/redmine_git_hosting/issues/501) ([Controllers] Download Git Revision Archive for Anonymous user redirect to login page)
|
||||
* Fix [#502](https://github.com/jbox-web/redmine_git_hosting/issues/502) ([Core] Issues with Git 1.7.1)
|
||||
|
||||
## 1.1.2 - 2015-08-21
|
||||
|
||||
* Fix [#459](https://github.com/jbox-web/redmine_git_hosting/issues/459) ([Install] Undefined method `urls_order' for #RepositoryGitExtra during migrations)
|
||||
* Merge [#491](https://github.com/jbox-web/redmine_git_hosting/pull/491) ([Views] Fix css spacer bug for compatibility with core css)
|
||||
|
||||
## 1.1.1 - 2015-06-29
|
||||
|
||||
* Display Rugged infos in Config test tab
|
||||
* Display Rugged features status (present/absent) in Config test tab
|
||||
* Bump gitolite-rugged to v1.1.1 (Use HTTPs instead of Git protocol to download rugged gem)
|
||||
* Add [#464](https://github.com/jbox-web/redmine_git_hosting/pull/464) ([Views] Fix display of git_annex urls)
|
||||
* Add [#466](https://github.com/jbox-web/redmine_git_hosting/pull/466) ([Core] In case of git command failure, log the actual command line)
|
||||
|
||||
## 1.1.0 - 2015-06-06
|
||||
|
||||
* Add [#417](https://github.com/jbox-web/redmine_git_hosting/issues/417) ([Views] Define order of repository urls)
|
||||
* Add [#426](https://github.com/jbox-web/redmine_git_hosting/issues/426) ([Views] Direct link to repository settings page on sidebar)
|
||||
* Add [#427](https://github.com/jbox-web/redmine_git_hosting/issues/427) ([Views] Back to settings/repositories on repositories/edit page)
|
||||
* Add [#431](https://github.com/jbox-web/redmine_git_hosting/issues/431) ([Core] Add support for Redmine/Gitolite splitted configuration)
|
||||
* Add ```resync_ssh_keys``` Rake command (thx Hugodby)
|
||||
* Use ```Etc``` Ruby module to find out Gitolite user home dir (instead of doing ```eval``` with sudo)
|
||||
* Rework mirroring key installation
|
||||
* Flush internal cached variables when settings change
|
||||
* Add a jump box to switch repositories in edit view
|
||||
* Fix RepositoryMirror regex (allow dashes in user name part)
|
||||
* Bump gitolite-rugged to v1.1.0 (bundled with rugged and libgit2 in version 0.22.2)
|
||||
* Remove temp directory when Gitolite settings change (it will be recloned with the right settings)
|
||||
* Add 'Move repository' feature : you can now move repositories accross projects
|
||||
* Add unique index on fingerprint field
|
||||
* Various small fixes
|
||||
|
||||
## 1.0.7 - 2015-06-06
|
||||
|
||||
* Fix [#450](https://github.com/jbox-web/redmine_git_hosting/issues/450) (Github webhook return 404 error)
|
||||
* Display Rugged infos in Config test tab
|
||||
|
||||
## 1.0.6 - 2015-06-04
|
||||
|
||||
* Validate that people don't reuse Gitolite Admin key
|
||||
|
||||
## 1.0.5 - 2015-05-31
|
||||
|
||||
* Fix [#418](https://github.com/jbox-web/redmine_git_hosting/issues/418) ([Rugged] On delete deploy key: Rugged::NetworkError)
|
||||
* Fix [#430](https://github.com/jbox-web/redmine_git_hosting/issues/430) ([User] Error when trying to update user details)
|
||||
|
||||
## 1.0.4 - 2015-04-10
|
||||
|
||||
* Fix [#404](https://github.com/jbox-web/redmine_git_hosting/issues/404) ([Git cache] "Until next commit" param is broken for Redis adapter)
|
||||
* Fix [#406](https://github.com/jbox-web/redmine_git_hosting/issues/406) ([Protected Branch] Protected Branch Name Must be Unique Across Projects)
|
||||
* Fix [#407](https://github.com/jbox-web/redmine_git_hosting/issues/407) ([Protected Branch] 500 Error rearranging protected branches)
|
||||
* Fix [#413](https://github.com/jbox-web/redmine_git_hosting/issues/413) ([Repository view] Missing repo source in repo instructions)
|
||||
* Add [#410](https://github.com/jbox-web/redmine_git_hosting/issues/410) ([Protected Branch] Gray protected branches if not enabled by repo flag)
|
||||
|
||||
## 1.0.3 - 2015-04-01
|
||||
|
||||
* Fix [#322](https://github.com/jbox-web/redmine_git_hosting/issues/322) ([Statistics view] PG::GroupingError: ERROR: column "changesets.id" must appear in the GROUP BY clause)
|
||||
* Fix [#334](https://github.com/jbox-web/redmine_git_hosting/issues/334) ([Translations] English locale file still contains French messages)
|
||||
* Fix [#383](https://github.com/jbox-web/redmine_git_hosting/issues/383) ([Statistics view] Mysql2::Error: Unknown column 'changes.commit_date' in 'order clause')
|
||||
* Fix [#384](https://github.com/jbox-web/redmine_git_hosting/issues/384) (```rake redmine_git_hosting:fetch_changesets``` doesn't clear cache)
|
||||
* Fix [#385](https://github.com/jbox-web/redmine_git_hosting/issues/385) ([Statistics view] Commits and changes lines are shifted)
|
||||
* Fix [#401](https://github.com/jbox-web/redmine_git_hosting/issues/401) ([Git cache] "Until next commit" param is broken)
|
||||
* DRY controllers
|
||||
* Improve permissions checking
|
||||
* Improve tests on controllers
|
||||
* DRY views
|
||||
* Rework Repository URLs rendering
|
||||
* Extract some views helpers to Redmine Bootstrap Kit plugin
|
||||
* Fix TagIt loading for ProtectedBranches
|
||||
* Add the '@all' repository in ```gitolite.conf``` when auto create README file is enabled (from [#338](https://github.com/jbox-web/redmine_git_hosting/issues/338))
|
||||
* Remove useless ```:gitolite_log_split``` params
|
||||
* Improve GitCache lookup performance (for Database and Redis adapters)
|
||||
* Improve Statistics rendering performance
|
||||
* Test the plugin with Redmine latest stable branch to prevent/anticipate [this kind of bug](https://github.com/jbox-web/redmine_git_hosting/issues/387)
|
||||
* Update install doc
|
||||
* Update migration doc
|
||||
|
||||
**Notes :**
|
||||
|
||||
* Before update Redmine Git Hosting plugin you **must** update Redmine Bootstrap Kit plugin to version **0.2.3** :
|
||||
|
||||
```sh
|
||||
# Update Redmine Bootstrap Kit
|
||||
redmine$ cd REDMINE_ROOT/plugins/redmine_bootstrap_kit
|
||||
redmine$ git fetch -p
|
||||
redmine$ git checkout 0.2.3
|
||||
|
||||
# Cleanup plugins assets dir
|
||||
redmine$ cd REDMINE_ROOT/public/plugin_assets
|
||||
redmine$ rm -rf *
|
||||
```
|
||||
|
||||
* Deployment keys permissions has been renamed (from ```*_deployment_keys``` to ```*_repository_deployment_credentials```) so you will have to restore these permissions in *Administration -> Roles*.
|
||||
|
||||
## 1.0.2 - 2015-03-14
|
||||
|
||||
* Merge [#348](https://github.com/jbox-web/redmine_git_hosting/pull/348) (Use Redmine setting for Git command)
|
||||
* Fix [#345](https://github.com/jbox-web/redmine_git_hosting/issues/345) (HTTPS Push, Popen : wrong number of arguments, Ruby 1.9 compatibility)
|
||||
* Fix [#351](https://github.com/jbox-web/redmine_git_hosting/issues/351) (undefined method `split' for nil:NilClass)
|
||||
* Fix [#354](https://github.com/jbox-web/redmine_git_hosting/issues/354) (Input string is longer than NAMEDATALEN / index too long)
|
||||
* Fix [#358](https://github.com/jbox-web/redmine_git_hosting/issues/358) (undefined method `join' for nil:NilClass)
|
||||
* Fix [#364](https://github.com/jbox-web/redmine_git_hosting/issues/364) (Gitolite hook silently fails on HTTP redirect)
|
||||
* Fix [#368](https://github.com/jbox-web/redmine_git_hosting/issues/368) ("My public keys" link is still missing the subpath)
|
||||
* Fix [#375](https://github.com/jbox-web/redmine_git_hosting/issues/375) (SmartHTTP link is not properly generated when Redmine is installed in a sub-path)
|
||||
* Fix [#377](https://github.com/jbox-web/redmine_git_hosting/issues/377) ("Git user is able to sudo to Redmine user?" fails with non-login shell)
|
||||
* Fix "undefined method `identifier' for nil:NilClass" when migrating to v1
|
||||
* Add Redmine 3.x compatibility
|
||||
* Update Redmine installer script for Travis builds
|
||||
* Use Redmine Bootstrap Kit - TagIt helper
|
||||
* Use Redmine Bootstrap Kit - BootstrapSwitch helper
|
||||
|
||||
**Notes :**
|
||||
|
||||
* Depending on your Redmine version (2.x/3.x) you'll have to comment/uncomment the right lines in the plugin's ```Gemfile```
|
||||
|
||||
* Before update Redmine Git Hosting plugin you **must** update Redmine Bootstrap Kit plugin to version **0.2.2** :
|
||||
|
||||
```sh
|
||||
# Update Redmine Bootstrap Kit
|
||||
redmine$ cd REDMINE_ROOT/plugins/redmine_bootstrap_kit
|
||||
redmine$ git fetch -p
|
||||
redmine$ git checkout 0.2.2
|
||||
|
||||
# Cleanup plugins assets dir
|
||||
redmine$ cd REDMINE_ROOT/public/plugin_assets
|
||||
redmine$ rm -rf *
|
||||
```
|
||||
|
||||
* Since [support of Ruby 1.9.x has ended](https://www.ruby-lang.org/en/news/2014/01/10/ruby-1-9-3-will-end-on-2015/), **we won't support Ruby 1.9.x anymore**.
|
||||
We highly recommend that you upgrade to Ruby 2.1 or 2.0.0 as soon as possible.
|
||||
|
||||
## 1.0.1 - 2015-02-23
|
||||
|
||||
* Fix archive name in DownloadGitRevision
|
||||
* Fix [#331](https://github.com/jbox-web/redmine_git_hosting/issues/331) (Internal Server Error on user details)
|
||||
* Fix [#335](https://github.com/jbox-web/redmine_git_hosting/issues/335) (gitolite-rugged can handle subdirectories for config file, just pass them)
|
||||
* Fix [#336](https://github.com/jbox-web/redmine_git_hosting/issues/336) (TypeError no implicit conversion of nil into Array, fix 404/500 errors in repository views)
|
||||
* Fix [#340](https://github.com/jbox-web/redmine_git_hosting/issues/340) (Invalid public key link)
|
||||
* Fix [#344](https://github.com/jbox-web/redmine_git_hosting/issues/344) (Add a warning if Repository::Xitolite is disabled on repository auto-create)
|
||||
|
||||
* Add link to repositories in Project overview
|
||||
|
||||
## 1.0.0 - 2015-01-26
|
||||
|
||||
This new version is the first one of the v1.0 branch!
|
||||
|
||||
For this version the major part of the code has be rewritten to be cleaner and easier to debug.
|
||||
It also brings some new features and fixes a lot of bugs.
|
||||
|
||||
There are some major changes that should solve a lot of issues :
|
||||
|
||||
* The plugin doesn't override ```Repository::Git``` object anymore. Instead it introduces a new type of repository in Redmine : ```Gitolite``` repositories.
|
||||
That means that you can have standard Redmine Git repositories as before and Gitolite repositories in the **same time**.
|
||||
*Note that only Gitolite repositories have advanced features (mirrors, post urls, etc...).*
|
||||
|
||||
* The second major change concerns the Storage strategy already discussed [here](https://github.com/jbox-web/redmine_git_hosting/issues/199).
|
||||
```unique_repo_identifier``` and ```hierarchical_organisation``` are now combined in a single param : ```hierarchical_organisation```.
|
||||
|
||||
* And finally the third major change is the switch to [gitolite-rugged](https://github.com/oliverguenther/gitolite-rugged) thanks to Oliver Günther.
|
||||
|
||||
**Changes :**
|
||||
|
||||
* Big refactoring of GitoliteWrapper (thanks Oliver Günther)
|
||||
* Switch to Gitlab Grack to provide Git SmartHTTP feature
|
||||
* Add SSH key fingerprint field in database
|
||||
|
||||
**New features :**
|
||||
|
||||
* Export developer public ssh keys in Redmine REST API
|
||||
* Export repository extras (mirrors, post receive urls, etc...) in Redmine REST API
|
||||
* Add "go get" support for GoLang
|
||||
* GitolitePlugins Sweepers and Extenders : to execute some actions after repository create/update/delete
|
||||
* new GitCache adapters : Memcached and Redis (faster than the current database adapter)
|
||||
* GitoliteHooks DSL to install your own Gitolite hooks globally
|
||||
* Support for GitAnnex repositories
|
||||
* [Support for branch permission / protected branches](https://github.com/jbox-web/redmine_git_hosting/issues/86)
|
||||
* Add rake tasks for a fully automated install [#303](https://github.com/jbox-web/redmine_git_hosting/issues/303)
|
||||
|
||||
**Fixes :**
|
||||
|
||||
* Hooks URL should be configurable
|
||||
* Fix [#223](https://github.com/jbox-web/redmine_git_hosting/pull/223) (fix https:// notifications if TLSvX is mandatory)
|
||||
* Fix [#240](https://github.com/jbox-web/redmine_git_hosting/issues/240) (Allow modification of the gitolite-admin repository from a different location)
|
||||
* Fix [#286](https://github.com/jbox-web/redmine_git_hosting/issues/286) (Link to "my public keys" is shown even if right is not granted)
|
||||
* Fix [#310](https://github.com/jbox-web/redmine_git_hosting/issues/310) (compatibility with redmine_scm_creator plugin)
|
||||
* Fix [#311](https://github.com/jbox-web/redmine_git_hosting/issues/311) (mirror repository URLs should permit dots in repository path)
|
||||
* Purge RecycleBin on fetch_changesets ([Configuration notes]({{ site.baseurl }}/configuration/notes/#empty-recycle-bin-periodically))
|
||||
|
||||
**Other :**
|
||||
|
||||
* Bump to last version of Git Multimail hook
|
||||
* Bump ZeroClipboard to version v2.1.1
|
||||
* Bump Highcharts to version 4.0.3
|
||||
|
||||
**Notes :**
|
||||
|
||||
Thanks to the work of Oliver Günther (really thank you), the plugin is now a lot more simple in many ways :
|
||||
|
||||
* the plugin is scriptless : no more need of ```gitolite_scripts_dir``` and shell scripts to wrap calls to sudo. Now, the only required dir is the ```gitolite_temp_dir``` to clone the Gitolite admin repository.
|
||||
* SSH keys are stored in Gitolite in a directory tree under ```ssh_keys```. No more need of timestamped key name :)
|
||||
|
||||
Example :
|
||||
|
||||
```sh
|
||||
gitolite-admin.git/
|
||||
├── conf
|
||||
│ └── gitolite.conf
|
||||
└── keydir
|
||||
├── redmine_git_hosting
|
||||
│ ├── redmine_admin_1
|
||||
│ │ └── redmine_my_key
|
||||
│ │ └── redmine_admin_1.pub
|
||||
│ └── redmine_admin_1_deploy_key_1
|
||||
│ └── redmine_deploy_key_1
|
||||
│ └── redmine_admin_1_deploy_key_1.pub
|
||||
└── redmine_gitolite_admin_id_rsa.pub
|
||||
```
|
||||
|
||||
## 0.7.10 - 2015-01-26
|
||||
|
||||
* Fix [#324](https://github.com/jbox-web/redmine_git_hosting/issues/324) (Unable to flag repository as Main)
|
||||
* Fix [#326](https://github.com/jbox-web/redmine_git_hosting/issues/326) (Error occurred while loading the routes definition)
|
||||
* Fix [#329](https://github.com/jbox-web/redmine_git_hosting/issues/329) ("internal Error" when trying to edit a newly created repo)
|
||||
|
||||
**Notes :**
|
||||
|
||||
**Important !**
|
||||
|
||||
This is the last version of the v0.7 branch. **There won't be new releases under this branch**.
|
||||
|
||||
That means that everyone should migrate to the new 1.0 version :)
|
||||
|
||||
**Important !**
|
||||
|
||||
Before migrating to the new 1.0 you **MUST** migrate to this version (0.7.10).
|
||||
|
||||
It includes a Rake task that prepare the migration to 1.0, so **don't miss that step!**
|
||||
|
||||
## 0.7.9 - 2014-12-29
|
||||
|
||||
* Fix [#218](https://github.com/jbox-web/redmine_git_hosting/issues/218) (I18n warnings)
|
||||
* Fix [#288](https://github.com/jbox-web/redmine_git_hosting/issues/288) (wrong deployment key identifier attribution that may lead to a security issue)
|
||||
* Fix [#317](https://github.com/jbox-web/redmine_git_hosting/issues/317) (inconsistent url's of hierarchical repositories in sub-projects)
|
||||
* gitolite-admin is a forbiden repository identifier
|
||||
* Fix ActiveRecord translations
|
||||
* Better handling of errors on git commit
|
||||
* Add Rake task to prepare migration to V1.0
|
||||
|
||||
## 0.7.8 - 2014-11-08
|
||||
|
||||
* Fix collision in method name with Redmine Jenkins Plugin
|
||||
* Backport patch from [pull #266](https://github.com/jbox-web/redmine_git_hosting/pull/266)
|
||||
* Fix [#246](https://github.com/jbox-web/redmine_git_hosting/issues/246) (init.rb - config values not taken)
|
||||
* Fix [#258](https://github.com/jbox-web/redmine_git_hosting/issues/258) (wrong hook installation place on gitolite 3.x)
|
||||
* Fix [#289](https://github.com/jbox-web/redmine_git_hosting/issues/289) (url to wiki goes nowhere)
|
||||
|
||||
**Notes :**
|
||||
|
||||
**Important !**
|
||||
|
||||
As explained in [Gitolite documentation](https://gitolite.com/gitolite/non-core.html#localcode) hooks should be installed in a separate directory.
|
||||
This new version fixes Gitolite hooks install path for Gitolite v3.
|
||||
|
||||
Hooks are now stored by default in ```<gitolite user home dir>/local```. You can override this in the plugin settings.
|
||||
|
||||
Note that the directory must be **a relative path** to the Gitolite user home directory.
|
||||
|
||||
You'll also have to update your ```.gitolite.rc``` accordingly :
|
||||
|
||||
LOCAL_CODE => "$ENV{HOME}/local"
|
||||
|
||||
## 0.7.7 - 2014-09-10
|
||||
|
||||
* Merge [#259](https://github.com/jbox-web/redmine_git_hosting/pull/259) (Some (very old) repositories have been indentified as empty)
|
||||
* Merge [#223](https://github.com/jbox-web/redmine_git_hosting/pull/223) (Fix https:// notifications if TLSvX is mandatory #223)
|
||||
* Bump to jbox-gitolite 1.2.6 which depends on [gitlab-grit 2.7.1](https://github.com/gitlabhq/grit/blob/master/History.txt)
|
||||
|
||||
**Notes :**
|
||||
|
||||
Until this version, the plugin silently failed when pushing data to Gitolite Admin. Now when an error happens on push, you should get this in the log :
|
||||
|
||||
```sh
|
||||
2014-09-10 19:02:25 +0200 INFO [GitHosting] User 'admin' created a new repository 'test/blof'
|
||||
2014-09-10 19:02:25 +0200 INFO [GitWorker] Using Gitolite configuration file : 'gitolite.conf'
|
||||
2014-09-10 19:02:26 +0200 INFO [GitWorker] add_repository : repository 'test/blof' does not exist in Gitolite, create it ...
|
||||
2014-09-10 19:02:26 +0200 INFO [GitWorker] add_repository : commiting to Gitolite...
|
||||
2014-09-10 19:02:26 +0200 INFO [GitWorker] add_repository : let Gitolite create empty repository 'repositories/test/blof.git'
|
||||
2014-09-10 19:02:26 +0200 INFO [GitWorker] add_repository : pushing to Gitolite...
|
||||
2014-09-10 19:02:26 +0200 ERROR [GitWorker] Command failed [1]: /usr/bin/git --git-dir=/tmp/redmine_git_hosting/git/gitolite-admin.git/.git --work-tree=/tmp/redmine_git_hosting/git/gitolite-admin.git push origin master
|
||||
[GitWorker]
|
||||
[GitWorker]To ssh://git@localhost:22/gitolite-admin.git
|
||||
[GitWorker] ! [rejected] master -> master (fetch first)
|
||||
[GitWorker]error: failed to push some refs to 'ssh://git@localhost:22/gitolite-admin.git'
|
||||
[GitWorker]hint: Updates were rejected because the remote contains work that you do
|
||||
[GitWorker]hint: not have locally. This is usually caused by another repository pushing
|
||||
[GitWorker]hint: to the same ref. You may want to first integrate the remote changes
|
||||
[GitWorker]hint: (e.g., 'git pull ...') before pushing again.
|
||||
[GitWorker]hint: See the 'Note about fast-forwards' in 'git push --help' for details.
|
||||
[GitWorker]
|
||||
```
|
||||
|
||||
## 0.7.6 - 2014-07-17
|
||||
|
||||
* Bump to jbox-gitolite 1.2.3 which depends on [gitlab-grit 2.7.0](https://github.com/gitlabhq/grit/blob/master/History.txt)
|
||||
* Fix [#207](https://github.com/jbox-web/redmine_git_hosting/issues/207) (gitolite-admin does not sync anymore) and his brothers
|
||||
|
||||
## 0.7.5 - 2014-07-14
|
||||
|
||||
* Fix [#226](https://github.com/jbox-web/redmine_git_hosting/issues/226) (unable to download revision if branch has a '/' in the name)
|
||||
* Fix [#230](https://github.com/jbox-web/redmine_git_hosting/issues/230) (Unwanted access to gitolite-admin repository)
|
||||
|
||||
## 0.7.4 - 2014-07-04
|
||||
|
||||
* Fix [#184](https://github.com/jbox-web/redmine_git_hosting/issues/184 ) (truncated Bootstrap Switches)
|
||||
* Fix [#211](https://github.com/jbox-web/redmine_git_hosting/issues/211) (mixed up dates in contributors statistics graph)
|
||||
* Fix [#215](https://github.com/jbox-web/redmine_git_hosting/issues/215) (application.css conflicts)
|
||||
* Fix [#225](https://github.com/jbox-web/redmine_git_hosting/issues/225) (unable to set new repository deployment credentials)
|
||||
* Set extra_info field when auto-creating repo with project
|
||||
|
||||
## 0.7.3 - 2014-06-11
|
||||
|
||||
* Fix [#144](https://github.com/jbox-web/redmine_git_hosting/issues/144) (redcarpet dependency)
|
||||
* Bump to jbox-gitolite 1.2.2
|
||||
* Fix files changements in Github payload (files added, deleted, modified)
|
||||
* Use repository name in Github payload
|
||||
* Add pusher informations in Github payload
|
||||
* Show Redmine fields in repository/edit
|
||||
* Fix [#186](https://github.com/jbox-web/redmine_git_hosting/issues/186) (post-receive doesn't pass multiple lines through from STDIN)
|
||||
* Fetch changesets after repository creation/restore
|
||||
* Fix repository content overwrite on repo creation with README file and repository not empty
|
||||
|
||||
**Notes :**
|
||||
|
||||
You're invited to take a look at this [post](https://github.com/jbox-web/redmine_git_hosting/issues/199).
|
||||
|
||||
## 0.7.2 - 2014-04-16
|
||||
|
||||
* Fix [#160](https://github.com/jbox-web/redmine_git_hosting/issues/160)
|
||||
* Fix [#169](https://github.com/jbox-web/redmine_git_hosting/issues/169)
|
||||
|
||||
## 0.7.1 - 2014-04-14
|
||||
|
||||
* Remove ENV['HOME'] dependency
|
||||
* Remove Git config file dependency
|
||||
* Remove SSH config file dependency
|
||||
* Fix log redirection on Automatic Repository Initialization
|
||||
* Fix plugin portability (use env instead of export)
|
||||
* Fix layout bug in header navigation ([#162](https://github.com/jbox-web/redmine_git_hosting/pull/162)) (thanks soeren-helbig)
|
||||
* Fix projects update on locking/unlocking user
|
||||
* Various small fixes
|
||||
* Use last version of [jbox-gitolite](http://rubygems.org/gems/jbox-gitolite) gem (1.1.11)
|
||||
|
||||
## 0.7.0 - 2014-04-02
|
||||
|
||||
* remove Redmine 1.x support
|
||||
* remove Rails 2.x support
|
||||
* remove Ruby 1.8.x support
|
||||
* replace Rails Observers by Active Record Callbacks
|
||||
* replace 'Gitolite home made interface' by Gitolite gem (https://github.com/jbox-web/gitolite)
|
||||
* lots of code cleanup
|
||||
* lots of bug fixes
|
||||
* add [Sidekiq async jobs]({{ site.baseurl }}/features/#sidekiq-asynchronous-jobs)
|
||||
* add [Git mailing lists]({{ site.baseurl }}/features/#git-mailing-lists)
|
||||
* add [Default branch selection]({{ site.baseurl }}/features/#default-branch-selection)
|
||||
* add [Automatic Repository Initialization]({{ site.baseurl }}/features/#automatic-repository-initialization)
|
||||
* add [Git Revision Download]({{ site.baseurl }}/features/#git-revision-download)
|
||||
* add [README preview]({{ site.baseurl }}/features/#readme-preview)
|
||||
* add [Repository “config” keys management]({{ site.baseurl }}/features/#git-config-keys-management)
|
||||
* add [Improved Repository Statistics]({{ site.baseurl }}/features/#improved-repository-statistics)
|
||||
* add [Github Issues Sync]({{ site.baseurl }}/features/#github-issues-sync)
|
||||
* add [Browse Archived Repositories]({{ site.baseurl }}/features/#browse-archived-repositories)
|
||||
* add Bootstrap CSS
|
||||
* add Font Awesome icons
|
||||
|
||||
## 0.6.3 - 2014-02-23
|
||||
|
||||
This is a bugfix release.
|
||||
|
||||
This is the last release of the 0.6.x branch.
|
||||
|
||||
The 'v0.6' is kept as archive and will be no longer supported.
|
||||
|
||||
## 0.6.2 - 2013-07-29
|
||||
|
||||
This is a security and bugfix release.
|
||||
|
||||
This releases fixes a high risk vulnerability, allowing an attacker to gain shell access to the server (CVE-2013-4663).
|
||||
|
||||
We strongly advise you to update your plugin!
|
||||
|
||||
## 0.6.1 - 2013-04-05
|
||||
|
||||
This is a bugfix release.
|
||||
|
||||
## 0.6.0 - 2013-03-25
|
||||
|
||||
This is a compatibility release.
|
||||
|
||||
The plugin is now compatible with Redmine 2.x (and Redmine 1.x).
|
||||
|
||||
## 0.5.2 - 2012-12-25
|
||||
|
||||
This is a bug-fix release.
|
||||
|
||||
* Fixed a migration problem with PostGreSQL (for uninstalling).
|
||||
* Fix to allow validations to fail properly on Project creation for Redmine < 1.4
|
||||
* Fix to prevent repository creation from stealing preexisting repositories in gitolite (which could happen under specialized circumstances).
|
||||
* Fix to handle old versions of sudo (< 1.7.3) during repair of the administrative key
|
||||
* Fix to preserve other administrative keys in the gitolite configuration file. Previously, the plugin would delete all but the first one. This fix is useful for people who want to have separate administrative keys for access to the gitolite config file.
|
||||
* Fixed weird behavior on Repository page when using multiple repos/project. Showed up when on non-default repo when trying to switch to branch other than master. Would switch back to default repository.
|
||||
|
||||
## 0.5.1 - 2012-10-31
|
||||
|
||||
This is a bug-fix release.
|
||||
|
||||
* Post-Receive URLs should now work with SSL (i.e. URLs of the form "https://xxx")
|
||||
* Additional patches for backward compatibility with ChiliProject/Redmine < 1.4. In this category was a problem with editing Git repo parameters as well as a minor bug that caused problems with adding members to projects that didn't have a Git repo.
|
||||
* Additional patches to support Ruby 1.9.x. Includes fix to post-receive hook and change in meaning of Module#instance_methods.
|
||||
* Patched installation so that can install Redmine from *scratch* (i.e. run `rake db:migrate` on empty DB) with plugin already in place.
|
||||
* Latest migration should now work with PostGreSQL. This was broken in 0.5.0x.
|
||||
|
||||
## 0.5.0 - 2012-10-03
|
||||
|
||||
This is a feature release.
|
||||
|
||||
* New : Compatibility with Redmine 1.4
|
||||
* Fix : Uninstall of plugin should work properly now.
|
||||
* Fix : Problems with patching on some installations should be fixed now (introduced in a recent revision).
|
||||
|
||||
## 0.4.6 - 2012-08-22
|
||||
|
||||
This is a feature release.
|
||||
|
||||
* New: Added Deployment Credentials, which are public keys associated directly with a repository rather
|
||||
than through a user. These credentials can be created directly from the repository settings page. Since
|
||||
they are named (like other public keys), they can be reused for other repositories, if desired. Note
|
||||
that only **managers** (or **administrators**) can create deployment credentials (or deployment keys). Further, deployment keys and credentials are owned by the original creator and appear in their "my account" page.
|
||||
|
||||
* New : Key validation and uniqueness. The format, properties, and uniqueness of keys are validated before allowing them to be saved. Note that actual keys must be unique across a whole gitolite installation (otherwise the access control mechanism doesn't work). At the moment, this validation allows keys of type "ssh-rsa" and "ssh-dss".
|
||||
* New : Ability to utilize alternate gitolite configuration file.
|
||||
* New : handle archiving of projects. Archived projects stay in the gitolite repository but are deactivated in the gitolite config file. All Redmine keys are removed and replaced with a token key called "redmine_archived_project".
|
||||
* New : Post-receive URLs configured from a repository settings page. When commits occur, configured URLs will be POSTed with json information about the commit, roughly in the same format as github commits. The POSTed payload is described here: http://help.github.com/post-receive-hooks/.
|
||||
* New : Repository mirrors have more configuration options. Rather than forcing the remote repository to be a complete mirror of the local repository (i.e. --mirror), repository mirrors can now specific an explicit reference specification for which branches to update and/or select whether to force update or require nothing more than a fast-forward.
|
||||
* Fix : Change in login name on User settings screen properly changes keys in keydir.
|
||||
* Fix : Fixed cases in which delete of user from project ACL and delete of user didn't clean up gitolite.conf
|
||||
* Fix : Fixed problem with failed validation in user settings screen.
|
||||
* Fix : Remove extra control characters (such as line breaks) as well as leading and trailing whitespace in public keys
|
||||
* Fix : Validations for public keys now reflected back to the user interface.
|
||||
* Fix : Deselection of repository module now has same effect as archiving project. The repository is marked in gitolite.conf as "redmine_disabled_project". When project repository module is re-enabled, the repository is reconnected automatically.
|
||||
|
||||
Prior to this, repository module deselection was treated inconsistently.
|
||||
|
||||
## 0.4.5 - 2012-04-23
|
||||
|
||||
* Fixed missed case for compatibility with Redmine 1.1-Stable. This patch allows the mirror functionality to work.
|
||||
* Fixed bad interaction between cron cleanup of /tmp and access to gitolite-admin repository in /tmp. Behavior could cause user keys to appear to be deleted, even though they remain in the redmine database. This behavior has likely been a part of this plugin since before this branch was forked (pre 0.4.2).
|
||||
|
||||
## 0.4.4 - 2012-04-01
|
||||
|
||||
This release includes feature enhancements and bug fixes.
|
||||
|
||||
Compatibility with Redmine 1.1-Stable. A couple of patches were included to permit this plugin to work with older Redmine releases.
|
||||
|
||||
* New settings to configure the /tmp and /bin directories (**gitTemporaryDir** and **gitScriptDir** respectively).
|
||||
* New settings for the default "Daemon Mode" (**gitDaemonDefault**), "SmartHTTP mode" (**gitHttpDefault**), and "Notify CIA mode" (**gitNotifyCIADefault**) for new repositories.
|
||||
* Better script support for installing scripts in the /bin directory.
|
||||
* Updated installation instructions in the README.
|
||||
* Better recovery from loss of administrative key in gitolite -- assuming use of gitolite version >= 2.0.3.
|
||||
* Fix : Improvements to repository mirror support.
|
||||
* Fix : Support '@' in user names for http access (externally converted to '%40').
|
||||
* Fix : Syntax fixes to allow use of Ruby 1.9.
|
||||
* Fix : Support for git-daemon now working correctly. The "daemon" key was not being removed correctly and projectgs with "daemon" support were not being deleted.
|
||||
* Fix : Better handling of null-buffer condition in smart-http.
|
||||
* Fix : Fixed language tags in localization files.
|
||||
|
||||
## 0.4.3 - 2012-02-01
|
||||
|
||||
This release includes feature enhancements and bug fixes.
|
||||
|
||||
This release includes a complete rewrite of the update_repository() functionality with an eye toward better resilience.
|
||||
|
||||
This code will automatically recover from a variety of weird failure modes which originally could occur.
|
||||
Further, execution of fetch_changesets will resynchronize the gitolite.conf file, fixing any inconsistencies that might have crept into this file.
|
||||
Co-existence of Redmine-managed and non-redmine-managed repositories in the gitolite.conf file is supported. Some specific things that will be resynched :
|
||||
|
||||
* Missing keys will be added and unused keys will be removed from the keydir directory.
|
||||
* Entries in gitolite.conf will be updated with new path information as necessary.
|
||||
* If proper setting is selected, orphan repo entries will be removed from gitolite.conf file, and the repositories themselves will be moved to the new recycle bin in the gitolite homedirectory.
|
||||
* Hooks will be checked and repaired as necessary.
|
||||
|
||||
This code is now explicitly compatible with Redmine 1.3-stable.
|
||||
|
||||
* Added user-edit screen to allow administrator to examine and edit users keys.
|
||||
* Git Server parameter now supports a port specification.
|
||||
* Other bug fuxes: mirrors now report status properly.
|
||||
|
||||
## 0.4.2 - 2011-12-01
|
||||
|
||||
This release includes feature enhancements and bug fixes.
|
||||
|
||||
* One of the most important aspects of this release is a fix for the performance problems that plagued earlier versions of the plugin for post 1.2 Redmine. Fetch_changesets operations should now be possible.
|
||||
* A second aspect is support for selinux. Scripts have been placed into a separate /bin directory which is placed at the root of the plugin (i.e. REDMINE_ROOT/vendor/plugins/redmine_git_hosting/bin). A set of rake tasks have been added to assist in installing selinux tags and pre-building scripts in the bin directory.
|
56
plugins/redmine_git_hosting/Gemfile
Normal file
56
plugins/redmine_git_hosting/Gemfile
Normal file
|
@ -0,0 +1,56 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
# Gitolite Admin repository management
|
||||
gem 'gitolite-rugged', git: 'https://github.com/jbox-web/gitolite-rugged.git', tag: '1.2.0'
|
||||
|
||||
# Ruby/Rack Git Smart-HTTP Server Handler
|
||||
gem 'gitlab-grack', '~> 2.0.0', git: 'https://github.com/jbox-web/grack.git', require: 'grack', branch: 'fix_gemfile'
|
||||
|
||||
# Memcached client for GitCache
|
||||
gem 'dalli'
|
||||
|
||||
# Redis client for GitCache
|
||||
gem 'hiredis'
|
||||
gem 'redis'
|
||||
|
||||
# Markdown rendering
|
||||
gem 'deckar01-task_list'
|
||||
gem 'escape_utils'
|
||||
gem 'html-pipeline'
|
||||
gem 'rinku'
|
||||
|
||||
# Syntaxic coloration
|
||||
gem 'asciidoctor'
|
||||
gem 'creole'
|
||||
gem 'github-markup'
|
||||
gem 'org-ruby'
|
||||
gem 'RedCloth'
|
||||
|
||||
# Rack parser for Hrack
|
||||
gem 'rack-parser', require: 'rack/parser'
|
||||
|
||||
# temp autoloading fix
|
||||
gem 'sidekiq'
|
||||
gem 'sshkey'
|
||||
|
||||
group :development, :test do
|
||||
gem 'rails-controller-testing'
|
||||
gem 'rspec'
|
||||
gem 'rspec-rails', '~> 3.5', '>= 3.5.2'
|
||||
|
||||
gem 'shoulda', '~> 3.5.0'
|
||||
gem 'shoulda-context'
|
||||
gem 'shoulda-matchers', '~> 2.7.0'
|
||||
|
||||
gem 'database_cleaner'
|
||||
gem 'factory_bot_rails', '< 5.0'
|
||||
|
||||
# Publish to CodeClimate
|
||||
gem 'codeclimate-test-reporter', require: false
|
||||
end
|
||||
|
||||
group :development do
|
||||
gem 'bullet'
|
||||
gem 'spring'
|
||||
gem 'spring-commands-rspec'
|
||||
end
|
19
plugins/redmine_git_hosting/LICENSE
Normal file
19
plugins/redmine_git_hosting/LICENSE
Normal file
|
@ -0,0 +1,19 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
31
plugins/redmine_git_hosting/README.md
Normal file
31
plugins/redmine_git_hosting/README.md
Normal file
|
@ -0,0 +1,31 @@
|
|||
##  Redmine Git Hosting Plugin
|
||||
|
||||
[](https://github.com/jbox-web/redmine_git_hosting/blob/devel/LICENSE)
|
||||
[](https://github.com/jbox-web/redmine_git_hosting/releases/latest)
|
||||
[](../../actions?query=workflow%3A%22Run+Brakeman%22)
|
||||
[](../../actions?query=workflow%3A%22Run+Linters%22)
|
||||
[](../../actions?query=workflow%3ATest)
|
||||
|
||||
### A Redmine plugin which makes configuring your own Git hosting easy ;)
|
||||
|
||||
This plugin allows straightforward management of Gitolite within Redmine.
|
||||
|
||||
Looking for maintainers, mail me if you're interested.
|
||||
|
||||
## Installation
|
||||
|
||||
The installation guide is [here](http://redmine-git-hosting.io/get_started/). The migration guide is [here](http://redmine-git-hosting.io/how-to/migrate/).
|
||||
|
||||
Read the documentation and more on the [project's website](http://redmine-git-hosting.io/).
|
||||
|
||||
## Contributors
|
||||
|
||||
A big thank to [them](https://github.com/jbox-web/redmine_git_hosting/blob/devel/AUTHORS) for their contribution!
|
||||
|
||||
## Contribute
|
||||
|
||||
You can contribute to this plugin in many ways such as :
|
||||
* Helping with documentation
|
||||
* Contributing code (features or bugfixes)
|
||||
* Reporting a bug
|
||||
* Submitting translations
|
|
@ -0,0 +1,17 @@
|
|||
class ArchivedRepositoriesController < RepositoriesController
|
||||
skip_before_action :authorize
|
||||
skip_before_action :find_project_repository, only: :index
|
||||
|
||||
before_action :can_view_archived_projects
|
||||
|
||||
def index
|
||||
@archived_projects = Project.where(status: Project::STATUS_ARCHIVED)
|
||||
.includes(:repositories)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def can_view_archived_projects
|
||||
render_403 unless User.current.admin?
|
||||
end
|
||||
end
|
|
@ -0,0 +1,29 @@
|
|||
module XitoliteRepositoryFinder
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def find_xitolite_repository
|
||||
@repository = Repository::Xitolite.find(find_repository_param)
|
||||
rescue ActiveRecord::RecordNotFound => e
|
||||
render_404
|
||||
else
|
||||
@project = @repository.project
|
||||
render_404 if @project.nil?
|
||||
end
|
||||
|
||||
def find_xitolite_repository_by_path
|
||||
repo_path = "#{params[:repo_path]}.git"
|
||||
repository = Repository::Xitolite.find_by_path repo_path, loose: true
|
||||
if repository.nil?
|
||||
RedmineGitHosting.logger.error "GoRedirector : repository not found at path : '#{repo_path}'," \
|
||||
' exiting!'
|
||||
render_404
|
||||
elsif !repository.go_access_available?
|
||||
RedmineGitHosting.logger.error "GoRedirector : GoAccess is disabled for this repository '#{repository.gitolite_repository_name}'," \
|
||||
' exiting!'
|
||||
render_403
|
||||
else
|
||||
RedmineGitHosting.logger.info("GoRedirector : access granted for repository '#{repository.gitolite_repository_name}'")
|
||||
@repository = repository
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,46 @@
|
|||
class DownloadGitRevisionController < ApplicationController
|
||||
include XitoliteRepositoryFinder
|
||||
|
||||
before_action :find_xitolite_repository
|
||||
before_action :can_download_git_revision
|
||||
before_action :set_download
|
||||
before_action :validate_download
|
||||
|
||||
helper :git_hosting
|
||||
|
||||
def index
|
||||
send_data(@download.content, filename: @download.filename, type: @download.content_type)
|
||||
rescue => e
|
||||
flash.now[:error] = l(:git_archive_timeout, timeout: e.output)
|
||||
render_404
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_repository_param
|
||||
params[:id]
|
||||
end
|
||||
|
||||
def can_download_git_revision
|
||||
render_403 unless User.current.allowed_to_download?(@repository)
|
||||
end
|
||||
|
||||
def set_download
|
||||
@download = Repositories::DownloadRevision.new(@repository, download_revision, download_format)
|
||||
end
|
||||
|
||||
def download_revision
|
||||
@download_revision ||= (params[:rev] || 'master')
|
||||
end
|
||||
|
||||
def download_format
|
||||
@download_format ||= (params[:download_format] || 'tar')
|
||||
end
|
||||
|
||||
def validate_download
|
||||
return if @download.valid_commit?
|
||||
|
||||
flash.now[:error] = l(:error_download_revision_no_such_commit, commit: download_revision)
|
||||
render_404
|
||||
end
|
||||
end
|
|
@ -0,0 +1,88 @@
|
|||
class GitolitePublicKeysController < ApplicationController
|
||||
include RedmineGitHosting::GitoliteAccessor::Methods
|
||||
|
||||
before_action :require_login
|
||||
before_action :find_user
|
||||
before_action :find_gitolite_public_key, only: [:destroy]
|
||||
|
||||
helper :gitolite_public_keys
|
||||
helper :git_hosting
|
||||
|
||||
def index
|
||||
@gitolite_user_keys = @user.gitolite_public_keys.user_key.sorted
|
||||
@gitolite_deploy_keys = @user.gitolite_public_keys.deploy_key.sorted
|
||||
end
|
||||
|
||||
def create
|
||||
if params[:create_button]
|
||||
@gitolite_public_key = @user.gitolite_public_keys.new
|
||||
@gitolite_public_key.safe_attributes = params[:gitolite_public_key]
|
||||
if @gitolite_public_key.save
|
||||
create_ssh_key(@gitolite_public_key)
|
||||
flash[:notice] = l(:notice_public_key_created, title: view_context.keylabel(@gitolite_public_key))
|
||||
else
|
||||
flash[:error] = @gitolite_public_key.errors.full_messages.to_sentence
|
||||
end
|
||||
redirect_to @redirect_url
|
||||
else
|
||||
redirect_to @cancel_url
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
return unless request.delete?
|
||||
|
||||
if @gitolite_public_key.user == @user || @user.admin?
|
||||
if @gitolite_public_key.destroy
|
||||
destroy_ssh_key(@gitolite_public_key)
|
||||
flash[:notice] = l(:notice_public_key_deleted, title: view_context.keylabel(@gitolite_public_key))
|
||||
end
|
||||
redirect_to @redirect_url
|
||||
else
|
||||
render_403
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_user
|
||||
if params[:user_id]
|
||||
set_user_from_params
|
||||
else
|
||||
set_user_from_current_user
|
||||
end
|
||||
end
|
||||
|
||||
def set_user_from_params
|
||||
@user = params[:user_id] == 'current' ? User.current : User.find_by(id: params[:user_id])
|
||||
if @user
|
||||
@cancel_url = @redirect_url = url_for(controller: 'users', action: 'edit', id: params[:user_id], tab: 'keys')
|
||||
else
|
||||
render_404
|
||||
end
|
||||
end
|
||||
|
||||
def set_user_from_current_user
|
||||
if User.current.allowed_to_create_ssh_keys?
|
||||
@user = User.current
|
||||
@redirect_url = url_for(controller: 'gitolite_public_keys', action: 'index')
|
||||
@cancel_url = url_for(controller: 'my', action: 'account')
|
||||
else
|
||||
render_403
|
||||
end
|
||||
end
|
||||
|
||||
def find_gitolite_public_key
|
||||
@gitolite_public_key = @user.gitolite_public_keys.find(params[:id])
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
|
||||
def create_ssh_key(ssh_key)
|
||||
gitolite_accessor.create_ssh_key(ssh_key)
|
||||
end
|
||||
|
||||
def destroy_ssh_key(ssh_key)
|
||||
gitolite_accessor.destroy_ssh_key(ssh_key)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,10 @@
|
|||
class GoRedirectorController < ApplicationController
|
||||
include XitoliteRepositoryFinder
|
||||
|
||||
# prevents login action to be filtered by check_if_login_required application scope filter
|
||||
skip_before_action :check_if_login_required, :verify_authenticity_token
|
||||
|
||||
before_action :find_xitolite_repository_by_path
|
||||
|
||||
def index; end
|
||||
end
|
|
@ -0,0 +1,72 @@
|
|||
class RedmineGitHostingController < ApplicationController
|
||||
include XitoliteRepositoryFinder
|
||||
|
||||
before_action :require_login
|
||||
before_action :find_xitolite_repository
|
||||
before_action :check_required_permissions
|
||||
before_action :set_current_tab
|
||||
|
||||
layout(proc { |controller| controller.request.xhr? ? false : 'base' })
|
||||
|
||||
helper :git_hosting
|
||||
|
||||
def show
|
||||
respond_to do |format|
|
||||
format.api
|
||||
end
|
||||
end
|
||||
|
||||
def edit; end
|
||||
|
||||
private
|
||||
|
||||
def find_repository_param
|
||||
params[:repository_id]
|
||||
end
|
||||
|
||||
def check_required_permissions
|
||||
return render_403 unless @project.module_enabled?(:repository)
|
||||
return true if User.current.admin?
|
||||
return render_403 unless User.current.allowed_to_manage_repository?(@repository)
|
||||
end
|
||||
|
||||
def check_xitolite_permissions
|
||||
case action_name
|
||||
when 'index', 'show'
|
||||
perm = "view_#{controller_name}".to_sym
|
||||
render_403 unless User.current.git_allowed_to?(perm, @repository)
|
||||
when 'new', 'create'
|
||||
perm = "create_#{controller_name}".to_sym
|
||||
render_403 unless User.current.git_allowed_to?(perm, @repository)
|
||||
when 'edit', 'update', 'destroy'
|
||||
perm = "edit_#{controller_name}".to_sym
|
||||
render_403 unless User.current.git_allowed_to?(perm, @repository)
|
||||
end
|
||||
end
|
||||
|
||||
def render_with_api
|
||||
respond_to do |format|
|
||||
format.html { render layout: false }
|
||||
format.api
|
||||
end
|
||||
end
|
||||
|
||||
def render_js_redirect
|
||||
respond_to do |format|
|
||||
format.js { render js: "window.location = #{success_url.to_json};" }
|
||||
format.html do
|
||||
redirect_to success_url
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def success_url
|
||||
url_for(controller: 'repositories', action: 'edit', id: @repository.id, tab: @tab)
|
||||
end
|
||||
|
||||
def call_use_case_and_redirect(opts = {})
|
||||
# Update Gitolite repository
|
||||
call_use_case(opts)
|
||||
render_js_redirect
|
||||
end
|
||||
end
|
|
@ -0,0 +1,124 @@
|
|||
class RepositoryDeploymentCredentialsController < RedmineGitHostingController
|
||||
include RedmineGitHosting::GitoliteAccessor::Methods
|
||||
|
||||
before_action :check_xitolite_permissions
|
||||
before_action :find_deployment_credential, only: %i[edit update destroy]
|
||||
before_action :find_key, only: %i[edit update destroy]
|
||||
before_action :find_all_keys, only: %i[index new create]
|
||||
|
||||
helper :gitolite_public_keys
|
||||
|
||||
def index
|
||||
@repository_deployment_credentials = @repository.deployment_credentials.sorted
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def edit; end
|
||||
|
||||
def show
|
||||
render_404
|
||||
end
|
||||
|
||||
def new
|
||||
@credential = @repository.deployment_credentials.new
|
||||
end
|
||||
|
||||
def create
|
||||
@credential = build_new_credential
|
||||
return render action: 'new' unless @credential.save
|
||||
|
||||
flash[:notice] = l(:notice_deployment_credential_created)
|
||||
call_use_case_and_redirect
|
||||
end
|
||||
|
||||
def update
|
||||
@credential.safe_attributes = params[:repository_deployment_credential]
|
||||
return render action: 'edit' unless @credential.save
|
||||
|
||||
flash[:notice] = l(:notice_deployment_credential_updated)
|
||||
call_use_case_and_redirect
|
||||
end
|
||||
|
||||
def destroy
|
||||
will_delete_key = @key.deploy_key? && @key.delete_when_unused && @key.repository_deployment_credentials.count == 1
|
||||
@credential.destroy
|
||||
if will_delete_key && @key.repository_deployment_credentials.empty?
|
||||
# Key no longer used -- delete it!
|
||||
@key.destroy
|
||||
flash[:notice] = l(:notice_deployment_credential_deleted_with_key)
|
||||
else
|
||||
flash[:notice] = l(:notice_deployment_credential_deleted)
|
||||
end
|
||||
|
||||
call_use_case_and_redirect
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_current_tab
|
||||
@tab = 'repository_deployment_credentials'
|
||||
end
|
||||
|
||||
def find_deployment_credential
|
||||
credential = @repository.deployment_credentials.find(params[:id])
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
else
|
||||
if credential.user && (User.current.admin? || credential.user == User.current)
|
||||
@credential = credential
|
||||
else
|
||||
render_403
|
||||
end
|
||||
end
|
||||
|
||||
def find_key
|
||||
key = @credential.gitolite_public_key
|
||||
if key&.user && (User.current.admin? || key.user == User.current)
|
||||
@key = key
|
||||
elsif key
|
||||
render_403
|
||||
else
|
||||
render_404
|
||||
end
|
||||
end
|
||||
|
||||
def find_all_keys
|
||||
# display create_with_key view. Find preexisting keys to offer to user
|
||||
@user_keys = User.current.gitolite_public_keys.deploy_key.order(:title)
|
||||
@disabled_keys = @repository.deployment_credentials.map(&:gitolite_public_key)
|
||||
@other_keys = []
|
||||
# Admin can use other's deploy keys as well
|
||||
@other_keys = other_deployment_keys if User.current.admin?
|
||||
end
|
||||
|
||||
def other_deployment_keys
|
||||
keys = users_allowed_to_create_deployment_keys.map { |user| user.gitolite_public_keys.deploy_key.order(:title) }
|
||||
keys.flatten
|
||||
end
|
||||
|
||||
def users_allowed_to_create_deployment_keys
|
||||
@project.users.select { |user| user != User.current && user.git_allowed_to?(:create_repository_deployment_credentials, @repository) }
|
||||
end
|
||||
|
||||
def call_use_case(opts = {})
|
||||
options = opts.merge(message: "Update deploy keys for repository : '#{@repository.gitolite_repository_name}'")
|
||||
gitolite_accessor.update_repository @repository, options
|
||||
end
|
||||
|
||||
def build_new_credential
|
||||
credential = @repository.deployment_credentials.new
|
||||
credential.safe_attributes = params[:repository_deployment_credential]
|
||||
key = GitolitePublicKey.find_by(id: params[:repository_deployment_credential][:gitolite_public_key_id])
|
||||
|
||||
credential.gitolite_public_key = key unless key.nil?
|
||||
|
||||
# If admin, let credential be owned by owner of key...
|
||||
if User.current.admin?
|
||||
credential.user = key.user unless key.nil?
|
||||
else
|
||||
credential.user = User.current
|
||||
end
|
||||
|
||||
credential
|
||||
end
|
||||
end
|
|
@ -0,0 +1,73 @@
|
|||
class RepositoryGitConfigKeysController < RedmineGitHostingController
|
||||
include RedmineGitHosting::GitoliteAccessor::Methods
|
||||
|
||||
before_action :check_xitolite_permissions
|
||||
before_action :find_repository_git_config_key, except: %i[index new create]
|
||||
|
||||
accept_api_auth :index, :show
|
||||
|
||||
def index
|
||||
@repository_git_config_keys = @repository.git_config_keys.all
|
||||
@repository_git_option_keys = @repository.git_option_keys.all
|
||||
render_with_api
|
||||
end
|
||||
|
||||
def new
|
||||
@git_config_key = @repository.send(key_type).new
|
||||
end
|
||||
|
||||
def create
|
||||
@git_config_key = @repository.send(key_type).new
|
||||
@git_config_key.safe_attributes = params[:repository_git_config_key]
|
||||
return render action: 'new' unless @git_config_key.save
|
||||
|
||||
flash[:notice] = l(:notice_git_config_key_created)
|
||||
call_use_case_and_redirect
|
||||
end
|
||||
|
||||
def update
|
||||
@git_config_key.safe_attributes = params[:repository_git_config_key]
|
||||
return render action: 'edit' unless @git_config_key.save
|
||||
|
||||
flash[:notice] = l(:notice_git_config_key_updated)
|
||||
options = @git_config_key.key_has_changed? ? { delete_git_config_key: @git_config_key.old_key } : {}
|
||||
call_use_case_and_redirect(options)
|
||||
end
|
||||
|
||||
def destroy
|
||||
return unless @git_config_key.destroy
|
||||
|
||||
flash[:notice] = l(:notice_git_config_key_deleted)
|
||||
options = { delete_git_config_key: @git_config_key.key }
|
||||
call_use_case_and_redirect(options)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def key_type
|
||||
type = params[:type] || params[:repository_git_config_key][:type]
|
||||
case type
|
||||
when 'RepositoryGitConfigKey::GitConfig', 'git_config'
|
||||
:git_config_keys
|
||||
when 'RepositoryGitConfigKey::Option', 'git_option'
|
||||
:git_option_keys
|
||||
else
|
||||
:git_keys
|
||||
end
|
||||
end
|
||||
|
||||
def set_current_tab
|
||||
@tab = 'repository_git_config_keys'
|
||||
end
|
||||
|
||||
def find_repository_git_config_key
|
||||
@git_config_key = @repository.git_keys.find(params[:id])
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
|
||||
def call_use_case(opts = {})
|
||||
options = opts.merge(message: "Rebuild Git config keys respository : '#{@repository.gitolite_repository_name}'")
|
||||
gitolite_accessor.update_repository(@repository, options)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,46 @@
|
|||
class RepositoryGitExtrasController < RedmineGitHostingController
|
||||
include RedmineGitHosting::GitoliteAccessor::Methods
|
||||
|
||||
skip_before_action :set_current_tab
|
||||
|
||||
helper :extend_repositories
|
||||
|
||||
def update
|
||||
@git_extra = @repository.extra
|
||||
@git_extra.safe_attributes = params[:repository_git_extra]
|
||||
|
||||
if @git_extra.save
|
||||
flash.now[:notice] = l(:notice_gitolite_extra_updated)
|
||||
gitolite_accessor.update_repository(@repository, update_default_branch: @git_extra.default_branch_has_changed?)
|
||||
else
|
||||
flash.now[:error] = l(:notice_gitolite_extra_update_failed)
|
||||
end
|
||||
end
|
||||
|
||||
def sort_urls
|
||||
@git_extra = @repository.extra
|
||||
return unless request.post?
|
||||
|
||||
if @git_extra.update(urls_order: params[:repository_git_extra])
|
||||
flash.now[:notice] = l(:notice_gitolite_extra_updated)
|
||||
else
|
||||
flash.now[:error] = l(:notice_gitolite_extra_update_failed)
|
||||
end
|
||||
end
|
||||
|
||||
def move
|
||||
@move_repository_form = MoveRepositoryForm.new(@repository)
|
||||
return unless request.post?
|
||||
|
||||
@move_repository_form = MoveRepositoryForm.new(@repository)
|
||||
return unless @move_repository_form.submit(params[:repository_mover])
|
||||
|
||||
redirect_to settings_project_path(@repository.project, tab: 'repositories')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_git_extra
|
||||
@git_extra = @repository.extra
|
||||
end
|
||||
end
|
|
@ -0,0 +1,66 @@
|
|||
class RepositoryMirrorsController < RedmineGitHostingController
|
||||
before_action :check_xitolite_permissions
|
||||
before_action :find_repository_mirror, except: %i[index new create]
|
||||
|
||||
accept_api_auth :index, :show
|
||||
|
||||
helper :additionals_clipboardjs
|
||||
|
||||
def index
|
||||
@repository_mirrors = @repository.mirrors.sorted
|
||||
render_with_api
|
||||
end
|
||||
|
||||
def new
|
||||
@mirror = @repository.mirrors.new
|
||||
end
|
||||
|
||||
def create
|
||||
@mirror = @repository.mirrors.new
|
||||
@mirror.safe_attributes = params[:repository_mirror]
|
||||
return render action: 'new' unless @mirror.save
|
||||
|
||||
flash[:notice] = l(:notice_mirror_created)
|
||||
render_js_redirect
|
||||
end
|
||||
|
||||
def update
|
||||
@mirror.safe_attributes = params[:repository_mirror]
|
||||
return render action: 'edit' unless @mirror.save
|
||||
|
||||
flash[:notice] = l(:notice_mirror_updated)
|
||||
render_js_redirect
|
||||
end
|
||||
|
||||
def destroy
|
||||
return unless @mirror.destroy
|
||||
|
||||
flash[:notice] = l(:notice_mirror_deleted)
|
||||
render_js_redirect
|
||||
end
|
||||
|
||||
def push
|
||||
@push_failed, @shellout = RepositoryMirrors::Push.call(@mirror)
|
||||
render layout: false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_current_tab
|
||||
@tab = 'repository_mirrors'
|
||||
end
|
||||
|
||||
def find_repository_mirror
|
||||
@mirror = @repository.mirrors.find(params[:id])
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
|
||||
def check_xitolite_permissions
|
||||
if action_name == 'push'
|
||||
render_403 unless User.current.git_allowed_to?(:push_repository_mirrors, @repository)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,52 @@
|
|||
class RepositoryPostReceiveUrlsController < RedmineGitHostingController
|
||||
before_action :check_xitolite_permissions
|
||||
before_action :find_repository_post_receive_url, except: %i[index new create]
|
||||
|
||||
accept_api_auth :index, :show
|
||||
# skip_before_action :verify_authenticity_token, only: %i[create update]
|
||||
|
||||
def index
|
||||
@repository_post_receive_urls = @repository.post_receive_urls.sorted
|
||||
render_with_api
|
||||
end
|
||||
|
||||
def new
|
||||
@post_receive_url = @repository.post_receive_urls.new
|
||||
end
|
||||
|
||||
def create
|
||||
@post_receive_url = @repository.post_receive_urls.new
|
||||
@post_receive_url.safe_attributes = params[:repository_post_receive_url]
|
||||
return render action: 'new' unless @post_receive_url.save
|
||||
|
||||
flash[:notice] = l(:notice_post_receive_url_created)
|
||||
render_js_redirect
|
||||
end
|
||||
|
||||
def update
|
||||
@post_receive_url.safe_attributes = params[:repository_post_receive_url]
|
||||
return render action: 'edit' unless @post_receive_url.save
|
||||
|
||||
flash[:notice] = l(:notice_post_receive_url_updated)
|
||||
render_js_redirect
|
||||
end
|
||||
|
||||
def destroy
|
||||
return unless @post_receive_url.destroy
|
||||
|
||||
flash[:notice] = l(:notice_post_receive_url_deleted)
|
||||
render_js_redirect
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_current_tab
|
||||
@tab = 'repository_post_receive_urls'
|
||||
end
|
||||
|
||||
def find_repository_post_receive_url
|
||||
@post_receive_url = @repository.post_receive_urls.find(params[:id])
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
end
|
|
@ -0,0 +1,80 @@
|
|||
class RepositoryProtectedBranchesController < RedmineGitHostingController
|
||||
include RedmineGitHosting::GitoliteAccessor::Methods
|
||||
|
||||
before_action :check_xitolite_permissions
|
||||
before_action :find_repository_protected_branch, except: %i[index new create sort]
|
||||
|
||||
accept_api_auth :index, :show
|
||||
|
||||
def index
|
||||
@repository_protected_branches = @repository.protected_branches.sorted
|
||||
render_with_api
|
||||
end
|
||||
|
||||
def new
|
||||
@protected_branch = @repository.protected_branches.new
|
||||
end
|
||||
|
||||
def create
|
||||
@protected_branch = @repository.protected_branches.new
|
||||
@protected_branch.safe_attributes = params[:repository_protected_branche]
|
||||
return render action: 'new' unless @protected_branch.save
|
||||
|
||||
check_members
|
||||
flash[:notice] = l(:notice_protected_branch_created)
|
||||
call_use_case_and_redirect
|
||||
end
|
||||
|
||||
def update
|
||||
@protected_branch.safe_attributes = params[:repository_protected_branche]
|
||||
return render action: 'edit' unless @protected_branch.save
|
||||
|
||||
check_members
|
||||
flash[:notice] = l(:notice_protected_branch_updated)
|
||||
call_use_case_and_redirect
|
||||
end
|
||||
|
||||
def destroy
|
||||
return unless @protected_branch.destroy
|
||||
|
||||
flash[:notice] = l(:notice_protected_branch_deleted)
|
||||
call_use_case_and_redirect
|
||||
end
|
||||
|
||||
def clone
|
||||
@protected_branch = RepositoryProtectedBranche.clone_from(params[:id])
|
||||
render 'new'
|
||||
end
|
||||
|
||||
def sort
|
||||
params[:protected_branch].each_with_index do |id, index|
|
||||
@repository.protected_branches.where(id: id).update_all(position: index + 1)
|
||||
end
|
||||
# Update Gitolite repository
|
||||
call_use_case
|
||||
head :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_current_tab
|
||||
@tab = 'repository_protected_branches'
|
||||
end
|
||||
|
||||
def find_repository_protected_branch
|
||||
@protected_branch = @repository.protected_branches.find(params[:id])
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
|
||||
def call_use_case(opts = {})
|
||||
options = opts.merge(message: "Update branch permissions for repository : '#{@repository.gitolite_repository_name}'")
|
||||
gitolite_accessor.update_repository(@repository, options)
|
||||
end
|
||||
|
||||
def check_members
|
||||
member_manager = RepositoryProtectedBranches::MemberManager.new(@protected_branch)
|
||||
member_manager.add_users(params[:user_ids])
|
||||
member_manager.add_groups(params[:group_ids])
|
||||
end
|
||||
end
|
26
plugins/redmine_git_hosting/app/forms/base_form.rb
Normal file
26
plugins/redmine_git_hosting/app/forms/base_form.rb
Normal file
|
@ -0,0 +1,26 @@
|
|||
module BaseForm
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
include ActiveModel::Validations
|
||||
include ActiveModel::Validations::Callbacks
|
||||
include ActiveModel::Conversion
|
||||
extend ActiveModel::Naming
|
||||
end
|
||||
|
||||
def persisted?
|
||||
false
|
||||
end
|
||||
|
||||
def submit(attributes = {})
|
||||
attributes.each do |name, value|
|
||||
send("#{name}=", value)
|
||||
end
|
||||
if valid?
|
||||
valid_form_submitted if respond_to?(:valid_form_submitted)
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,39 @@
|
|||
class MoveRepositoryForm
|
||||
include BaseForm
|
||||
|
||||
attr_reader :repository
|
||||
attr_accessor :project_id
|
||||
|
||||
validates_presence_of :project_id
|
||||
validate :repository_is_movable
|
||||
validate :target_project
|
||||
validate :repository_uniqueness
|
||||
|
||||
def initialize(repository)
|
||||
@repository = repository
|
||||
end
|
||||
|
||||
def project
|
||||
@project ||= Project.find_by_id(project_id)
|
||||
end
|
||||
|
||||
def valid_form_submitted
|
||||
repository.update_attribute(:project_id, project.id)
|
||||
RedmineGitHosting::GitoliteAccessor.move_repository(repository)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def repository_is_movable
|
||||
errors.add(:base, :identifier_empty) unless repository.movable?
|
||||
end
|
||||
|
||||
def target_project
|
||||
errors.add(:base, :wrong_target_project) if repository.project == project
|
||||
end
|
||||
|
||||
def repository_uniqueness
|
||||
new_repo = project.repositories.find_by_identifier(repository.identifier)
|
||||
errors.add(:base, :identifier_taken) unless new_repo.nil?
|
||||
end
|
||||
end
|
|
@ -0,0 +1,59 @@
|
|||
class PluginSettingsForm
|
||||
class << self
|
||||
def add_accessor(*args)
|
||||
@accessors ||= []
|
||||
args.each do |accessor|
|
||||
@accessors << accessor
|
||||
attr_accessor accessor
|
||||
end
|
||||
end
|
||||
|
||||
def all_accessors
|
||||
@accessors
|
||||
end
|
||||
end
|
||||
|
||||
include BaseForm
|
||||
include PluginSettingsValidation::CacheConfig
|
||||
include PluginSettingsValidation::GitoliteAccessConfig
|
||||
include PluginSettingsValidation::GitoliteConfig
|
||||
include PluginSettingsValidation::HooksConfig
|
||||
include PluginSettingsValidation::MailingListConfig
|
||||
include PluginSettingsValidation::RedmineConfig
|
||||
include PluginSettingsValidation::SshConfig
|
||||
include PluginSettingsValidation::StorageConfig
|
||||
|
||||
attr_reader :plugin
|
||||
|
||||
def initialize(plugin)
|
||||
@plugin = plugin
|
||||
end
|
||||
|
||||
def params
|
||||
Hash[self.class.all_accessors.map { |v| [v, send(v)] }]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_setting(setting)
|
||||
Setting.plugin_redmine_git_hosting[setting]
|
||||
end
|
||||
|
||||
def strip_value(value)
|
||||
return '' if value.nil?
|
||||
|
||||
value.strip
|
||||
end
|
||||
|
||||
def filter_email_list(list)
|
||||
list.select(&:present?).select { |m| valid_email?(m) }
|
||||
end
|
||||
|
||||
def valid_email?(email)
|
||||
RedmineGitHosting::Validators.valid_email?(email)
|
||||
end
|
||||
|
||||
def convert_time(time)
|
||||
(time.to_f * 10).to_i / 10.0
|
||||
end
|
||||
end
|
|
@ -0,0 +1,18 @@
|
|||
module PluginSettingsValidation
|
||||
module CacheConfig
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
# Gitolite Cache Config
|
||||
add_accessor :gitolite_cache_max_time,
|
||||
:gitolite_cache_max_size,
|
||||
:gitolite_cache_max_elements,
|
||||
:gitolite_cache_adapter
|
||||
|
||||
validates :gitolite_cache_max_time, presence: true, numericality: { only_integer: true }
|
||||
validates :gitolite_cache_max_size, presence: true, numericality: { only_integer: true }
|
||||
validates :gitolite_cache_max_elements, presence: true, numericality: { only_integer: true }
|
||||
validates :gitolite_cache_adapter, presence: true, inclusion: { in: GitCache.adapters }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,37 @@
|
|||
module PluginSettingsValidation
|
||||
module GitoliteAccessConfig
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
# Gitolite Access Config
|
||||
add_accessor :ssh_server_domain,
|
||||
:http_server_domain,
|
||||
:https_server_domain,
|
||||
:http_server_subdir,
|
||||
:gitolite_daemon_by_default,
|
||||
:gitolite_http_by_default
|
||||
|
||||
before_validation do
|
||||
self.ssh_server_domain = strip_value(ssh_server_domain)
|
||||
self.http_server_domain = strip_value(http_server_domain)
|
||||
self.https_server_domain = strip_value(https_server_domain)
|
||||
self.http_server_subdir = strip_value(http_server_subdir)
|
||||
end
|
||||
|
||||
validates :ssh_server_domain, presence: true, format: { with: RedmineGitHosting::Validators::DOMAIN_REGEX }
|
||||
validates :http_server_domain, presence: true, format: { with: RedmineGitHosting::Validators::DOMAIN_REGEX }
|
||||
validates :https_server_domain, format: { with: RedmineGitHosting::Validators::DOMAIN_REGEX }, allow_blank: true
|
||||
|
||||
validates :gitolite_daemon_by_default, presence: true, inclusion: { in: RedmineGitHosting::Validators::BOOLEAN_FIELDS }
|
||||
validates :gitolite_http_by_default, presence: true, inclusion: { in: %w[0 1 2 3] }, numericality: { only_integer: true }
|
||||
|
||||
validate :http_server_subdir_is_relative
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def http_server_subdir_is_relative
|
||||
errors.add(:http_server_subdir, 'must be relative') if http_server_subdir.starts_with?('/')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,61 @@
|
|||
module PluginSettingsValidation
|
||||
module GitoliteConfig
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
# Gitolite Config File
|
||||
add_accessor :gitolite_config_file,
|
||||
:gitolite_identifier_prefix,
|
||||
:gitolite_identifier_strip_user_id
|
||||
|
||||
# Gitolite Global Config
|
||||
add_accessor :gitolite_temp_dir,
|
||||
:gitolite_recycle_bin_expiration_time,
|
||||
:gitolite_log_level,
|
||||
:git_config_username,
|
||||
:git_config_email
|
||||
|
||||
before_validation do
|
||||
self.gitolite_config_file = strip_value(gitolite_config_file)
|
||||
self.gitolite_identifier_prefix = strip_value(gitolite_identifier_prefix)
|
||||
self.gitolite_temp_dir = strip_value(gitolite_temp_dir)
|
||||
self.git_config_username = strip_value(git_config_username)
|
||||
self.git_config_email = strip_value(git_config_email)
|
||||
self.gitolite_recycle_bin_expiration_time = strip_value(gitolite_recycle_bin_expiration_time)
|
||||
end
|
||||
|
||||
# Validates Gitolite Config File
|
||||
validates :gitolite_identifier_strip_user_id, presence: true, inclusion: { in: RedmineGitHosting::Validators::BOOLEAN_FIELDS }
|
||||
|
||||
# Validates Gitolite Global Config
|
||||
validates :gitolite_temp_dir, presence: true
|
||||
validates :gitolite_recycle_bin_expiration_time, presence: true, numericality: true
|
||||
|
||||
validates :gitolite_log_level, presence: true, inclusion: { in: RedmineGitHosting::FileLogger::LOG_LEVELS }
|
||||
validates :git_config_username, presence: true
|
||||
validates :git_config_email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
|
||||
|
||||
validate :gitolite_config_file_is_relative
|
||||
validate :tmp_dir_is_absolute
|
||||
|
||||
after_validation do
|
||||
self.gitolite_recycle_bin_expiration_time = convert_time(gitolite_recycle_bin_expiration_time)
|
||||
|
||||
if gitolite_config_file == RedmineGitHosting::Config::GITOLITE_DEFAULT_CONFIG_FILE
|
||||
self.gitolite_identifier_strip_user_id = 'false'
|
||||
self.gitolite_identifier_prefix = RedmineGitHosting::Config::GITOLITE_IDENTIFIER_DEFAULT_PREFIX
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def gitolite_config_file_is_relative
|
||||
errors.add(:gitolite_config_file, 'must be relative') if gitolite_config_file.starts_with?('/')
|
||||
end
|
||||
|
||||
def tmp_dir_is_absolute
|
||||
errors.add(:gitolite_temp_dir, 'must be absolute') unless gitolite_temp_dir.starts_with?('/')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,22 @@
|
|||
module PluginSettingsValidation
|
||||
module HooksConfig
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
# Gitolite Hooks Config
|
||||
add_accessor :gitolite_overwrite_existing_hooks,
|
||||
:gitolite_hooks_are_asynchronous,
|
||||
:gitolite_hooks_debug,
|
||||
:gitolite_hooks_url
|
||||
|
||||
before_validation do
|
||||
self.gitolite_hooks_url = strip_value(gitolite_hooks_url)
|
||||
end
|
||||
|
||||
validates :gitolite_overwrite_existing_hooks, presence: true, inclusion: { in: RedmineGitHosting::Validators::BOOLEAN_FIELDS }
|
||||
validates :gitolite_hooks_are_asynchronous, presence: true, inclusion: { in: RedmineGitHosting::Validators::BOOLEAN_FIELDS }
|
||||
validates :gitolite_hooks_debug, presence: true, inclusion: { in: RedmineGitHosting::Validators::BOOLEAN_FIELDS }
|
||||
validates :gitolite_hooks_url, presence: true, format: { with: URI::DEFAULT_PARSER.make_regexp(%w[http https]) }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,34 @@
|
|||
module PluginSettingsValidation
|
||||
module MailingListConfig
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
# Git Mailing List Config
|
||||
add_accessor :gitolite_notify_by_default,
|
||||
:gitolite_notify_global_prefix,
|
||||
:gitolite_notify_global_sender_address,
|
||||
:gitolite_notify_global_include,
|
||||
:gitolite_notify_global_exclude
|
||||
|
||||
before_validation do
|
||||
self.gitolite_notify_global_include = filter_email_list(gitolite_notify_global_include)
|
||||
self.gitolite_notify_global_exclude = filter_email_list(gitolite_notify_global_exclude)
|
||||
end
|
||||
|
||||
validates :gitolite_notify_by_default, presence: true, inclusion: { in: RedmineGitHosting::Validators::BOOLEAN_FIELDS }
|
||||
validates :gitolite_notify_global_sender_address, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
|
||||
validate :git_notifications_intersection
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Validate intersection of global_include/global_exclude
|
||||
#
|
||||
def git_notifications_intersection
|
||||
intersection = gitolite_notify_global_include & gitolite_notify_global_exclude
|
||||
return unless intersection.count.positive?
|
||||
|
||||
errors.add(:base, 'duplicated entries detected in gitolite_notify_global_include and gitolite_notify_global_exclude')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,55 @@
|
|||
module PluginSettingsValidation
|
||||
module RedmineConfig
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
# Redmine Config
|
||||
add_accessor :redmine_has_rw_access_on_all_repos,
|
||||
:all_projects_use_git,
|
||||
:init_repositories_on_create,
|
||||
:delete_git_repositories,
|
||||
:download_revision_enabled,
|
||||
:gitolite_use_sidekiq
|
||||
|
||||
# This params work together!
|
||||
# When hierarchical_organisation = true, unique_repo_identifier MUST be false
|
||||
# When hierarchical_organisation = false, unique_repo_identifier MUST be true
|
||||
add_accessor :hierarchical_organisation, :unique_repo_identifier
|
||||
|
||||
# hierarchical_organisation and unique_repo_identifier are now combined
|
||||
#
|
||||
before_validation do
|
||||
self.unique_repo_identifier = if Additionals.true? hierarchical_organisation
|
||||
'false'
|
||||
else
|
||||
'true'
|
||||
end
|
||||
|
||||
## If we don't auto-create repository, we cannot create README file
|
||||
self.init_repositories_on_create = 'false' unless Additionals.true? all_projects_use_git
|
||||
end
|
||||
|
||||
validates :redmine_has_rw_access_on_all_repos, presence: true, inclusion: { in: RedmineGitHosting::Validators::BOOLEAN_FIELDS }
|
||||
validates :all_projects_use_git, presence: true, inclusion: { in: RedmineGitHosting::Validators::BOOLEAN_FIELDS }
|
||||
validates :init_repositories_on_create, presence: true, inclusion: { in: RedmineGitHosting::Validators::BOOLEAN_FIELDS }
|
||||
validates :delete_git_repositories, presence: true, inclusion: { in: RedmineGitHosting::Validators::BOOLEAN_FIELDS }
|
||||
validates :download_revision_enabled, presence: true, inclusion: { in: RedmineGitHosting::Validators::BOOLEAN_FIELDS }
|
||||
validates :gitolite_use_sidekiq, presence: true, inclusion: { in: RedmineGitHosting::Validators::BOOLEAN_FIELDS }
|
||||
validates :hierarchical_organisation, presence: true, inclusion: { in: RedmineGitHosting::Validators::BOOLEAN_FIELDS }
|
||||
validates :unique_repo_identifier, presence: true, inclusion: { in: RedmineGitHosting::Validators::BOOLEAN_FIELDS }
|
||||
|
||||
validate :check_for_duplicated_repo
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Check duplication if we are switching from a mode to another
|
||||
#
|
||||
def check_for_duplicated_repo
|
||||
return if Additionals.true?(hierarchical_organisation)
|
||||
return unless Repository::Xitolite.have_duplicated_identifier?
|
||||
|
||||
errors.add(:base, 'Detected non-unique repository identifiers. Cannot switch to flat mode')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,33 @@
|
|||
module PluginSettingsValidation
|
||||
module SshConfig
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
# Gitolite SSH Config
|
||||
add_accessor :gitolite_user,
|
||||
:gitolite_server_host,
|
||||
:gitolite_server_port,
|
||||
:gitolite_ssh_private_key,
|
||||
:gitolite_ssh_public_key
|
||||
|
||||
before_validation do
|
||||
self.gitolite_user = strip_value(gitolite_user)
|
||||
self.gitolite_server_host = strip_value(gitolite_server_host)
|
||||
self.gitolite_server_port = strip_value(gitolite_server_port)
|
||||
|
||||
self.gitolite_ssh_private_key = strip_value(gitolite_ssh_private_key)
|
||||
self.gitolite_ssh_public_key = strip_value(gitolite_ssh_public_key)
|
||||
end
|
||||
|
||||
validates :gitolite_user, :gitolite_server_host, :gitolite_ssh_private_key, :gitolite_ssh_public_key,
|
||||
presence: true
|
||||
validates :gitolite_server_port,
|
||||
presence: true,
|
||||
numericality: { only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: 65_536 }
|
||||
|
||||
validates_each :gitolite_ssh_private_key, :gitolite_ssh_public_key do |record, attr, value|
|
||||
record.errors.add(attr, 'must exists on filesystem') unless File.exist? value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,26 @@
|
|||
module PluginSettingsValidation
|
||||
module StorageConfig
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
PATHS_TO_VALIDATE = %i[gitolite_global_storage_dir gitolite_redmine_storage_dir gitolite_recycle_bin_dir].freeze
|
||||
|
||||
included do
|
||||
# Gitolite Storage Config
|
||||
add_accessor :gitolite_global_storage_dir,
|
||||
:gitolite_redmine_storage_dir,
|
||||
:gitolite_recycle_bin_dir
|
||||
|
||||
before_validation do
|
||||
self.gitolite_global_storage_dir = strip_value(gitolite_global_storage_dir)
|
||||
self.gitolite_redmine_storage_dir = strip_value(gitolite_redmine_storage_dir)
|
||||
self.gitolite_recycle_bin_dir = strip_value(gitolite_recycle_bin_dir)
|
||||
end
|
||||
|
||||
validates_presence_of :gitolite_global_storage_dir, :gitolite_recycle_bin_dir
|
||||
|
||||
validates_each PATHS_TO_VALIDATE do |record, attr, value|
|
||||
record.errors.add(attr, 'must be relative') if value.starts_with?('/')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,81 @@
|
|||
module ExtendProjectsHelper
|
||||
def render_feature(repository, feature)
|
||||
method = "#{feature}_feature"
|
||||
label, css_class, enabled = send(method, repository)
|
||||
|
||||
# Get css class
|
||||
base_class = ['icon-git']
|
||||
base_class << css_class
|
||||
base_class << 'icon-git-disabled' unless enabled
|
||||
|
||||
# Get label
|
||||
base_label = []
|
||||
base_label << label
|
||||
base_label << "(#{l(:label_disabled)})" unless enabled
|
||||
|
||||
tag.i '', title: base_label.join(' '), class: base_class
|
||||
end
|
||||
|
||||
def deployment_credentials_feature(repository)
|
||||
label = l :label_deployment_credentials
|
||||
css_class = 'fas fa-lock'
|
||||
enabled = repository.deployment_credentials.active.any?
|
||||
[label, css_class, enabled]
|
||||
end
|
||||
|
||||
def post_receive_urls_feature(repository)
|
||||
label = l :label_post_receive_urls
|
||||
css_class = 'fas fa-external-link-alt'
|
||||
enabled = repository.post_receive_urls.active.any?
|
||||
[label, css_class, enabled]
|
||||
end
|
||||
|
||||
def mirrors_feature(repository)
|
||||
label = l :label_repository_mirrors
|
||||
css_class = 'fas fa-cloud-upload-alt'
|
||||
enabled = repository.mirrors.active.any?
|
||||
[label, css_class, enabled]
|
||||
end
|
||||
|
||||
def git_daemon_feature(repository)
|
||||
label = l :label_git_daemon
|
||||
css_class = 'fab fa-git'
|
||||
enabled = repository.git_access_available?
|
||||
[label, css_class, enabled]
|
||||
end
|
||||
|
||||
def git_http_feature(repository)
|
||||
label = l :label_smart_http
|
||||
css_class = 'fas fa-cloud-download-alt'
|
||||
enabled = repository.smart_http_enabled?
|
||||
[label, css_class, enabled]
|
||||
end
|
||||
|
||||
def git_notify_feature(repository)
|
||||
label = l :label_git_notify
|
||||
css_class = 'fas fa-bullhorn'
|
||||
enabled = repository.git_notification_enabled?
|
||||
[label, css_class, enabled]
|
||||
end
|
||||
|
||||
def protected_branch_feature(repository)
|
||||
label = l :label_protected_branch
|
||||
css_class = 'fas fa-shield-alt'
|
||||
enabled = repository.protected_branches_available?
|
||||
[label, css_class, enabled]
|
||||
end
|
||||
|
||||
def git_annex_feature(repository)
|
||||
label = l :label_git_annex
|
||||
css_class = 'fas fa-cloud-upload-alt'
|
||||
enabled = repository.git_annex_enabled?
|
||||
[label, css_class, enabled]
|
||||
end
|
||||
|
||||
def public_repo_feature(repository)
|
||||
label = l :label_public_repo
|
||||
css_class = 'fas fa-users'
|
||||
enabled = repository.public_repo?
|
||||
[label, css_class, enabled]
|
||||
end
|
||||
end
|
|
@ -0,0 +1,68 @@
|
|||
module ExtendRepositoriesHelper
|
||||
def encoding_field(form, _repository)
|
||||
tag.p do
|
||||
form.select(
|
||||
:path_encoding, [nil] + Setting::ENCODINGS,
|
||||
label: l(:field_scm_path_encoding)
|
||||
) + '<br />'.html_safe + l(:text_scm_path_encoding_note)
|
||||
end
|
||||
end
|
||||
|
||||
def available_download_format(repository, rev = nil)
|
||||
%w[zip tar tar.gz].map { |f| [f, download_git_revision_repository_path(repository, rev: rev, download_format: f)] }
|
||||
end
|
||||
|
||||
def create_readme_field(_form, repository)
|
||||
return unless repository.new_record?
|
||||
|
||||
tag.p do
|
||||
hidden_field_tag('repository[create_readme]', 'false', id: '') +
|
||||
tag.label(l(:label_init_repo_with_readme), for: 'repository_create_readme') +
|
||||
check_box_tag('repository[create_readme]', 'true', RedmineGitHosting::Config.init_repositories_on_create?)
|
||||
end
|
||||
end
|
||||
|
||||
def enable_git_annex_field(_form, repository)
|
||||
return unless repository.new_record?
|
||||
|
||||
tag.p do
|
||||
hidden_field_tag('repository[enable_git_annex]', 'false', id: '') +
|
||||
tag.label(l(:label_init_repo_with_git_annex), for: 'repository_enable_git_annex') +
|
||||
check_box_tag('repository[enable_git_annex]', 'true')
|
||||
end
|
||||
end
|
||||
|
||||
def repository_branches_list(branches)
|
||||
options_for_select branches.collect { |b| [b.to_s, b.to_s] }, selected: branches.find(&:is_default).to_s
|
||||
end
|
||||
|
||||
def render_repository_quick_jump(repository)
|
||||
options = repository.project.repositories.sort
|
||||
options.map! { |r| [r.redmine_name, edit_repository_path(r)] }
|
||||
select_tag 'repository_quick_jump_box',
|
||||
options_for_select(options, selected: edit_repository_path(repository)),
|
||||
onchange: 'if (this.value != \'\') { window.location = this.value; }'
|
||||
end
|
||||
|
||||
def link_to_repository(repo, current_repo)
|
||||
css_class = ['repository', (repo == current_repo ? 'selected' : ''), current_repo.type.split('::')[1].downcase].join(' ')
|
||||
link_to h(repo.name),
|
||||
{ controller: 'repositories', action: 'show', id: @project, repository_id: repo.identifier_param, rev: nil, path: nil },
|
||||
class: css_class
|
||||
end
|
||||
|
||||
def icon_for_url_type(url_type)
|
||||
font_awesome_icon(RepositoryGitExtra::URLS_ICONS[url_type][:icon])
|
||||
end
|
||||
|
||||
def label_for_url_type(url_type)
|
||||
RepositoryGitExtra::URLS_ICONS[url_type][:label]
|
||||
end
|
||||
|
||||
def render_options_for_move_repo_select_box(project)
|
||||
projects = Project.active
|
||||
.where(Project.allowed_to_condition(User.current, :manage_repository))
|
||||
.where.not(id: project.id)
|
||||
project_tree_options_for_select(projects, selected: project) if projects.any?
|
||||
end
|
||||
end
|
|
@ -0,0 +1,31 @@
|
|||
module GitHostingHelper
|
||||
def present(object, klass = nil, *args)
|
||||
klass ||= "#{object.class.base_class}Presenter".constantize
|
||||
presenter = klass.new(object, self, *args)
|
||||
yield presenter if block_given?
|
||||
presenter
|
||||
end
|
||||
|
||||
def checked_image_with_exclamation(checked = true)
|
||||
checked ? image_tag('toggle_check.png') : image_tag('exclamation.png')
|
||||
end
|
||||
|
||||
def render_shell_text(text)
|
||||
Redmine::SyntaxHighlighting.highlight_by_language text, 'shell'
|
||||
end
|
||||
|
||||
def gitolite_project_settings_tabs
|
||||
tabs = []
|
||||
|
||||
tabs << { name: 'db',
|
||||
action: :show,
|
||||
partial: 'projects/settings/db',
|
||||
label: :label_db }
|
||||
|
||||
tabs << { name: 'db2',
|
||||
action: :show,
|
||||
partial: 'projects/settings/db',
|
||||
label: :label_db }
|
||||
tabs
|
||||
end
|
||||
end
|
|
@ -0,0 +1,28 @@
|
|||
module GitHostingUsersHelper
|
||||
def user_settings_tabs
|
||||
tabs = super
|
||||
tabs << { name: 'keys', partial: 'gitolite_public_keys/view', label: :label_public_keys }
|
||||
end
|
||||
|
||||
# Hacked render_api_custom_values to add plugin values to user api.
|
||||
# @NOTE: there is no solution for index.api, because @user is missing
|
||||
# @TODO
|
||||
def render_api_custom_values(custom_values, api)
|
||||
rc = super
|
||||
|
||||
if @user.present?
|
||||
api.array :ssh_keys do
|
||||
@user.gitolite_public_keys.each do |key|
|
||||
api.ssh_key do
|
||||
api.id key.id
|
||||
api.key_type key.key_type_as_string
|
||||
api.title key.title
|
||||
api.key key.key
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
rc
|
||||
end
|
||||
end
|
|
@ -0,0 +1,128 @@
|
|||
module GitolitePluginSettingsHelper
|
||||
def render_gitolite_params_status(params)
|
||||
tag.ul class: 'list-unstyled' do
|
||||
content = ''
|
||||
params.each do |param, installed|
|
||||
content << tag.li do
|
||||
image_tag(image_for_param(installed), style: 'vertical-align: bottom; padding-right: 5px;') +
|
||||
tag.em(label_for_param(param, installed))
|
||||
end
|
||||
end
|
||||
content.html_safe
|
||||
end
|
||||
end
|
||||
|
||||
def label_for_param(param, install_status)
|
||||
install_status == 2 ? "#{param} (#{l(:label_gitolite_hook_untouched)})" : param
|
||||
end
|
||||
|
||||
def image_for_param(install_status)
|
||||
case install_status
|
||||
when 0, true
|
||||
'true.png'
|
||||
when 1, false
|
||||
'exclamation.png'
|
||||
else
|
||||
'warning.png'
|
||||
end
|
||||
end
|
||||
|
||||
def render_gitolite_version(version)
|
||||
if version.nil?
|
||||
css_class = 'label label-error'
|
||||
label = l(:label_unknown_gitolite_version)
|
||||
else
|
||||
css_class = 'label label-success'
|
||||
label = version
|
||||
end
|
||||
tag.span label, class: css_class
|
||||
end
|
||||
|
||||
def render_temp_dir_writeable(state, label)
|
||||
css_class = state ? 'label label-success' : 'label label-error'
|
||||
tag.span label, class: css_class
|
||||
end
|
||||
|
||||
def gitolite_plugin_settings_tabs
|
||||
[
|
||||
{ name: 'gitolite_config_ssh',
|
||||
partial: 'settings/redmine_git_hosting/gitolite_config_ssh',
|
||||
label: :label_tab_ssh },
|
||||
{ name: 'gitolite_config_storage',
|
||||
partial: 'settings/redmine_git_hosting/gitolite_config_storage',
|
||||
label: :label_tab_storage },
|
||||
{ name: 'gitolite_config_file',
|
||||
partial: 'settings/redmine_git_hosting/gitolite_config_file',
|
||||
label: :label_tab_config_file },
|
||||
{ name: 'gitolite_config_global',
|
||||
partial: 'settings/redmine_git_hosting/gitolite_config_global',
|
||||
label: :label_tab_global },
|
||||
{ name: 'gitolite_config_access',
|
||||
partial: 'settings/redmine_git_hosting/gitolite_config_access',
|
||||
label: :label_tab_access },
|
||||
{ name: 'gitolite_config_hooks',
|
||||
partial: 'settings/redmine_git_hosting/gitolite_config_hooks',
|
||||
label: :label_tab_hooks },
|
||||
{ name: 'gitolite_config_cache',
|
||||
partial: 'settings/redmine_git_hosting/gitolite_config_cache',
|
||||
label: :label_tab_cache },
|
||||
{ name: 'gitolite_config_notify',
|
||||
partial: 'settings/redmine_git_hosting/gitolite_config_notify',
|
||||
label: :label_tab_notify },
|
||||
{ name: 'gitolite_redmine_config',
|
||||
partial: 'settings/redmine_git_hosting/redmine_config',
|
||||
label: :label_tab_redmine },
|
||||
{ name: 'gitolite_sidekiq_interface',
|
||||
partial: 'settings/redmine_git_hosting/sidekiq_interface',
|
||||
label: :label_tab_sidekiq_interface },
|
||||
{ name: 'gitolite_config_test',
|
||||
partial: 'settings/redmine_git_hosting/gitolite_config_test',
|
||||
label: :label_tab_config_test },
|
||||
{ name: 'gitolite_recycle_bin',
|
||||
partial: 'settings/redmine_git_hosting/gitolite_recycle_bin',
|
||||
label: :label_tab_gitolite_recycle_bin },
|
||||
{ name: 'gitolite_rescue',
|
||||
partial: 'settings/redmine_git_hosting/gitolite_rescue',
|
||||
label: :label_tab_gitolite_rescue }
|
||||
]
|
||||
end
|
||||
|
||||
def git_cache_options
|
||||
[
|
||||
['Cache Disabled', '0'],
|
||||
['Until next commit', '-1'],
|
||||
['1 Minute or until next commit', '60'],
|
||||
['15 Minutes or until next commit', '900'],
|
||||
['1 Hour or until next commit', '3600'],
|
||||
['1 Day or until next commit', '86400']
|
||||
]
|
||||
end
|
||||
|
||||
def log_level_options
|
||||
RedmineGitHosting::FileLogger::LOG_LEVELS.map { |level| [l("label_#{level}"), level] }
|
||||
end
|
||||
|
||||
def render_rugged_mandatory_features
|
||||
content = ''
|
||||
RedmineGitHosting::Config.rugged_mandatory_features.each do |feature|
|
||||
opts = if RedmineGitHosting::Config.rugged_features.include?(feature)
|
||||
{ class: 'label label-success' }
|
||||
else
|
||||
{ class: 'label label-error' }
|
||||
end
|
||||
content << "#{tag.span feature, opts}\n"
|
||||
end
|
||||
content.html_safe
|
||||
end
|
||||
|
||||
def render_rugged_optional_features
|
||||
content = ''
|
||||
RedmineGitHosting::Config.rugged_features.each do |feature|
|
||||
unless RedmineGitHosting::Config.rugged_mandatory_features.include?(feature)
|
||||
opts = { class: 'label label-success' }
|
||||
content << tag.span(feature, opts)
|
||||
end
|
||||
end
|
||||
content.html_safe
|
||||
end
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
module GitolitePublicKeysHelper
|
||||
def keylabel(key)
|
||||
key.user == User.current ? key.title&.to_s : "#{key.user.login}@#{key.title}"
|
||||
end
|
||||
|
||||
def can_create_deployment_keys_for_some_project(theuser = User.current)
|
||||
return true if theuser.admin?
|
||||
|
||||
theuser.projects_by_role.each_key do |role|
|
||||
return true if role.allowed_to?(:create_repository_deployment_credentials)
|
||||
end
|
||||
false
|
||||
end
|
||||
end
|
|
@ -0,0 +1,17 @@
|
|||
module RepositoryDeploymentCredentialsHelper
|
||||
def build_list_of_keys(user_keys, other_keys, disabled_keys)
|
||||
option_array = [[l(:label_deployment_credential_select_deploy_key), -1]]
|
||||
option_array += user_keys.map { |key| [keylabel(key), key.id] }
|
||||
|
||||
if other_keys.present?
|
||||
option_array2 = other_keys.map { |key| [keylabel(key), key.id] }
|
||||
maxlen = (option_array + option_array2).map { |x| x.first.length }.max
|
||||
|
||||
extra = [maxlen - l(:select_other_keys).length - 2, 6].max / 2
|
||||
option_array += [[('-' * extra) + ' ' + l(:select_other_keys) + ' ' + ('-' * extra), -2]]
|
||||
option_array += option_array2
|
||||
end
|
||||
|
||||
options_for_select(option_array, selected: -1, disabled: [-2] + disabled_keys.map(&:id))
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
module RepositoryGitConfigKeysHelper
|
||||
def git_config_key_options
|
||||
[
|
||||
[l(:label_git_key_type_config), 'RepositoryGitConfigKey::GitConfig'],
|
||||
[l(:label_git_key_type_option), 'RepositoryGitConfigKey::Option']
|
||||
]
|
||||
end
|
||||
end
|
|
@ -0,0 +1,43 @@
|
|||
module RepositoryMirrorsHelper
|
||||
# Mirror Mode
|
||||
def mirror_mode(mirror)
|
||||
[l(:label_mirror_full_mirror),
|
||||
l(:label_mirror_forced_update),
|
||||
l(:label_mirror_fast_forward)][mirror.push_mode]
|
||||
end
|
||||
|
||||
# Refspec for mirrors
|
||||
def refspec(mirror, max_refspec = 0)
|
||||
if mirror.mirror_mode?
|
||||
l :all_references
|
||||
else
|
||||
result = []
|
||||
result << tag.li(l(:all_branches)) if mirror.include_all_branches
|
||||
result << tag.li(l(:all_tags)) if mirror.include_all_tags
|
||||
result << tag.li(mirror.explicit_refspec) if max_refspec.zero? || ((1..max_refspec) === mirror.explicit_refspec.length)
|
||||
result << tag.li(l(:explicit)) if max_refspec.positive? && (mirror.explicit_refspec.length > max_refspec)
|
||||
|
||||
tag.ul(safe_join(result), class: 'list-unstyled') if result.any?
|
||||
end
|
||||
end
|
||||
|
||||
def mirrors_options
|
||||
[
|
||||
[l(:label_mirror_full_mirror), 0],
|
||||
[l(:label_mirror_forced_update), 1],
|
||||
[l(:label_mirror_fast_forward), 2]
|
||||
]
|
||||
end
|
||||
|
||||
def render_push_state(mirror, error)
|
||||
if error
|
||||
status = l :label_mirror_push_fail
|
||||
status_css = 'error'
|
||||
else
|
||||
status = l :label_mirror_push_sucess
|
||||
status_css = 'success'
|
||||
end
|
||||
|
||||
t :label_mirror_push_info_html, mirror_url: mirror.url, status: status, status_css: status_css
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
module RepositoryPostReceiveUrlsHelper
|
||||
# Post-receive Mode
|
||||
def post_receive_mode(prurl)
|
||||
label = []
|
||||
if prurl.github_mode?
|
||||
label << l(:label_github_post)
|
||||
label << "(#{l :label_split_payloads})" if prurl.split_payloads?
|
||||
else
|
||||
label << l(:label_empty_get)
|
||||
end
|
||||
label.join ' '
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
module Gitolitable
|
||||
extend ActiveSupport::Concern
|
||||
include Gitolitable::Authorizations
|
||||
include Gitolitable::Cache
|
||||
include Gitolitable::Config
|
||||
include Gitolitable::Features
|
||||
include Gitolitable::Notifications
|
||||
include Gitolitable::Paths
|
||||
include Gitolitable::Permissions
|
||||
include Gitolitable::Urls
|
||||
include Gitolitable::Users
|
||||
include Gitolitable::Validations
|
||||
end
|
|
@ -0,0 +1,73 @@
|
|||
module Gitolitable
|
||||
module Authorizations
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
# These are for repository Gitolite configuration
|
||||
|
||||
def git_daemon_available?
|
||||
User.anonymous.allowed_to?(:view_changesets, project) && git_daemon_enabled?
|
||||
end
|
||||
|
||||
def git_web_available?
|
||||
User.anonymous.allowed_to?(:browse_repository, project) && smart_http_enabled?
|
||||
end
|
||||
|
||||
def protected_branches_available?
|
||||
protected_branches_enabled? && project.active? && protected_branches.any?
|
||||
end
|
||||
|
||||
def clonable_via_http?
|
||||
User.anonymous.allowed_to?(:view_changesets, project) || smart_http_enabled?
|
||||
end
|
||||
|
||||
def pushable_via_http?
|
||||
https_access_enabled?
|
||||
end
|
||||
|
||||
def git_notification_available?
|
||||
git_notification_enabled? && !mailing_list.empty?
|
||||
end
|
||||
|
||||
# These are for repository URLs
|
||||
|
||||
def urls_are_viewable?
|
||||
User.current.allowed_to?(:view_changesets, project)
|
||||
end
|
||||
|
||||
def ssh_access_available?
|
||||
git_ssh_enabled? && !git_annex_enabled? && User.current.allowed_to_commit?(self)
|
||||
end
|
||||
|
||||
def https_access_available?
|
||||
https_access_enabled?
|
||||
end
|
||||
|
||||
def http_access_available?
|
||||
http_access_enabled?
|
||||
end
|
||||
|
||||
def git_access_available?
|
||||
(public_project? || public_repo?) && git_daemon_enabled?
|
||||
end
|
||||
|
||||
def go_access_available?
|
||||
(public_project? || public_repo?) && smart_http_enabled? && git_go_enabled?
|
||||
end
|
||||
|
||||
def git_annex_access_available?
|
||||
git_annex_enabled?
|
||||
end
|
||||
|
||||
def downloadable?
|
||||
git_annex_enabled? ? false : User.current.allowed_to_download?(self)
|
||||
end
|
||||
|
||||
def deletable?
|
||||
RedmineGitHosting::Config.delete_git_repositories?
|
||||
end
|
||||
|
||||
def movable?
|
||||
identifier.present?
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,83 @@
|
|||
module Gitolitable
|
||||
module Cache
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
class << self
|
||||
# Are repositories identifier unique?
|
||||
#
|
||||
def repo_ident_unique?
|
||||
RedmineGitHosting::Config.unique_repo_identifier?
|
||||
end
|
||||
|
||||
# Translate repository path into a unique ID for use in caching of git commands.
|
||||
#
|
||||
def repo_path_to_git_cache_id(repo_path)
|
||||
repo = find_by_path(repo_path, loose: true)
|
||||
repo ? repo.git_cache_id : nil
|
||||
end
|
||||
|
||||
# Parse a path of the form <proj1>/<proj2>/<proj3>/<repo> and return the specified
|
||||
# repository. If either 'repo_ident_unique?' is true or the <repo> is a project
|
||||
# identifier, just return the last component. Otherwise,
|
||||
# use the immediate parent (<proj3>) to try to identify the repo.
|
||||
#
|
||||
# Flags:
|
||||
# :loose => true : Try to identify corresponding repo even if path is not quite correct
|
||||
#
|
||||
# Note that the :loose flag is used when interpreting the contents of the
|
||||
# repository. If switching back and forth between the "repo_ident_unique?"
|
||||
# form, it will still identify the repository (as long as there are not more than
|
||||
# one repo with the same identifier.
|
||||
#
|
||||
# Example of data captured by regex :
|
||||
# <MatchData "test/test2/test3/test4/test5.git" 1:"test4/" 2:"test4" 3:"test5" 4:".git">
|
||||
# <MatchData "blabla2.git" 1:nil 2:nil 3:"blabla2" 4:".git">
|
||||
#
|
||||
def find_by_path(path, flags = {})
|
||||
parseit = path.match(/\A.*?(([^\/]+)\/)?([^\/]+?)(\.git)?\z/)
|
||||
return nil if parseit.nil?
|
||||
|
||||
project = Project.find_by_identifier(parseit[3])
|
||||
|
||||
# return default or first repo with blank identifier (or first Git repo--very rare?)
|
||||
if project
|
||||
project.repository || project.repo_blank_ident || project.gitolite_repos.first
|
||||
|
||||
elsif repo_ident_unique? || flags[:loose] && parseit[2].nil?
|
||||
find_by_identifier(parseit[3])
|
||||
|
||||
elsif parseit[2]
|
||||
project = Project.find_by_identifier(parseit[2])
|
||||
|
||||
if project.nil?
|
||||
find_by_identifier(parseit[3])
|
||||
else
|
||||
find_by_identifier_and_project_id(parseit[3], project.id) || (flags[:loose] && find_by_identifier(parseit[3]))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# If repositories identifiers are unique, identifier forms a unique label,
|
||||
# else use directory notation: <project identifier>/<repo identifier>
|
||||
#
|
||||
def git_cache_id
|
||||
if identifier.blank?
|
||||
# Should only happen with one repo/project (the default)
|
||||
project.identifier
|
||||
elsif self.class.repo_ident_unique?
|
||||
identifier
|
||||
else
|
||||
"#{project.identifier}/#{identifier}"
|
||||
end
|
||||
end
|
||||
|
||||
# Note: RedmineGitHosting::Cache doesn't know about repository object, it only knows *git_cache_id*.
|
||||
#
|
||||
def empty_cache!
|
||||
RedmineGitHosting::Cache.clear_cache_for_repository(git_cache_id)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,78 @@
|
|||
module Gitolitable
|
||||
module Config
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def git_config
|
||||
repo_conf = {}
|
||||
|
||||
# This is needed for all Redmine repositories
|
||||
repo_conf['redminegitolite.projectid'] = project.identifier.to_s
|
||||
repo_conf['redminegitolite.repositoryid'] = identifier || ''
|
||||
repo_conf['redminegitolite.repositorykey'] = gitolite_hook_key
|
||||
|
||||
if project.active?
|
||||
repo_conf['http.uploadpack'] = clonable_via_http?.to_s
|
||||
repo_conf['http.receivepack'] = pushable_via_http?.to_s
|
||||
|
||||
if git_notification_available?
|
||||
repo_conf['multimailhook.enabled'] = 'true'
|
||||
repo_conf['multimailhook.mailinglist'] = mailing_list.join(', ')
|
||||
repo_conf['multimailhook.from'] = sender_address
|
||||
repo_conf['multimailhook.emailPrefix'] = email_prefix
|
||||
else
|
||||
repo_conf['multimailhook.enabled'] = 'false'
|
||||
end
|
||||
|
||||
git_config_keys.each do |git|
|
||||
repo_conf[git.key] = git.value
|
||||
end if git_config_keys.any?
|
||||
|
||||
else
|
||||
# Disable repository
|
||||
repo_conf['http.uploadpack'] = 'false'
|
||||
repo_conf['http.receivepack'] = 'false'
|
||||
repo_conf['multimailhook.enabled'] = 'false'
|
||||
end
|
||||
|
||||
repo_conf
|
||||
end
|
||||
|
||||
def gitolite_options
|
||||
repo_conf = {}
|
||||
|
||||
git_option_keys.each do |option|
|
||||
repo_conf[option.key] = option.value
|
||||
end if git_option_keys.any?
|
||||
|
||||
repo_conf
|
||||
end
|
||||
|
||||
def owner
|
||||
{ name: Setting['app_title'], email: Setting['mail_from'] }
|
||||
end
|
||||
|
||||
def github_payload
|
||||
{
|
||||
repository: { owner: owner,
|
||||
description: project.description,
|
||||
fork: false,
|
||||
forks: 0,
|
||||
homepage: project.homepage,
|
||||
name: redmine_name,
|
||||
open_issues: project.issues.open.length,
|
||||
watchers: 0,
|
||||
private: !project.is_public,
|
||||
url: repository_url },
|
||||
pusher: owner
|
||||
}
|
||||
end
|
||||
|
||||
def repository_url
|
||||
Rails.application.routes.url_helpers.url_for(
|
||||
controller: 'repositories', action: 'show',
|
||||
id: project, repository_id: identifier_param,
|
||||
only_path: false, host: Setting['host_name'], protocol: Setting['protocol']
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,79 @@
|
|||
module Gitolitable
|
||||
module Features
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
# Always true to force repository fetch_changesets.
|
||||
def report_last_commit
|
||||
true
|
||||
end
|
||||
|
||||
# Always true to force repository fetch_changesets.
|
||||
def extra_report_last_commit
|
||||
true
|
||||
end
|
||||
|
||||
def git_default_branch
|
||||
extra[:default_branch]
|
||||
end
|
||||
|
||||
def gitolite_hook_key
|
||||
extra[:key]
|
||||
end
|
||||
|
||||
def git_daemon_enabled?
|
||||
extra[:git_daemon]
|
||||
end
|
||||
|
||||
def git_annex_enabled?
|
||||
extra[:git_annex]
|
||||
end
|
||||
|
||||
def git_notification_enabled?
|
||||
extra[:git_notify]
|
||||
end
|
||||
|
||||
def git_ssh_enabled?
|
||||
extra[:git_ssh]
|
||||
end
|
||||
|
||||
def git_go_enabled?
|
||||
extra[:git_go]
|
||||
end
|
||||
|
||||
def https_access_enabled?
|
||||
extra[:git_https]
|
||||
end
|
||||
|
||||
def http_access_enabled?
|
||||
extra[:git_http]
|
||||
end
|
||||
|
||||
def smart_http_enabled?
|
||||
https_access_enabled? || http_access_enabled?
|
||||
end
|
||||
|
||||
def only_https_access_enabled?
|
||||
https_access_enabled? && !http_access_enabled?
|
||||
end
|
||||
|
||||
def only_http_access_enabled?
|
||||
http_access_enabled? && !https_access_enabled?
|
||||
end
|
||||
|
||||
def protected_branches_enabled?
|
||||
extra[:protected_branch]
|
||||
end
|
||||
|
||||
def public_project?
|
||||
project.is_public?
|
||||
end
|
||||
|
||||
def public_repo?
|
||||
extra[:public_repo]
|
||||
end
|
||||
|
||||
def urls_order
|
||||
extra[:urls_order]
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,29 @@
|
|||
module Gitolitable
|
||||
module Notifications
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def mailing_list
|
||||
default_list + global_include_list - global_exclude_list
|
||||
end
|
||||
|
||||
def default_list
|
||||
watcher_users.map(&:email_address).map(&:address)
|
||||
end
|
||||
|
||||
def global_include_list
|
||||
RedmineGitHosting::Config.gitolite_notify_global_include
|
||||
end
|
||||
|
||||
def global_exclude_list
|
||||
RedmineGitHosting::Config.gitolite_notify_global_exclude
|
||||
end
|
||||
|
||||
def sender_address
|
||||
extra.notification_sender.presence || RedmineGitHosting::Config.gitolite_notify_global_sender_address
|
||||
end
|
||||
|
||||
def email_prefix
|
||||
extra.notification_prefix.presence || RedmineGitHosting::Config.gitolite_notify_global_prefix
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,90 @@
|
|||
module Gitolitable
|
||||
module Paths
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
# This is the repository path from Redmine point of view.
|
||||
# It is used to build HTTP(s) urls (including GoLang url).
|
||||
# It doesn't contain references to internal directories like *gitolite_global_storage_dir* or *gitolite_redmine_storage_dir*
|
||||
# to stay abstract from the real repository location.
|
||||
# In this case, the real repository path is deduced from the path given thanks to the *find_by_path* method.
|
||||
#
|
||||
# Example : blabla/test-blabla/uuuuuuuuuuu/oooooo
|
||||
#
|
||||
# Call File.expand_path to add then remove heading /
|
||||
#
|
||||
def redmine_repository_path
|
||||
File.expand_path(File.join('./',
|
||||
get_full_parent_path,
|
||||
git_cache_id), '/')[1..-1]
|
||||
end
|
||||
|
||||
# This is the Gitolite repository identifier as it should appear in Gitolite config file.
|
||||
# Example : redmine/blabla/test-blabla/uuuuuuuuuuu/oooooo
|
||||
# (with 'redmine' a subdir of the Gitolite storage directory)
|
||||
#
|
||||
# Call File.expand_path to add then remove heading /
|
||||
#
|
||||
def gitolite_repository_name
|
||||
File.expand_path(File.join('./',
|
||||
RedmineGitHosting::Config.gitolite_redmine_storage_dir,
|
||||
get_full_parent_path,
|
||||
git_cache_id), '/')[1..-1]
|
||||
end
|
||||
|
||||
# The Gitolite repository identifier with the .git extension.
|
||||
# Example : redmine/blabla/test-blabla/uuuuuuuuuuu/oooooo.git
|
||||
#
|
||||
def gitolite_repository_name_with_extension
|
||||
"#{gitolite_repository_name}.git"
|
||||
end
|
||||
|
||||
# This is the relative path to the Gitolite repository.
|
||||
# Example : repositories/redmine/blabla/test-blabla/uuuuuuuuuuu/oooooo.git
|
||||
# (with 'repositories' the Gitolite storage directory).
|
||||
#
|
||||
def gitolite_repository_path
|
||||
File.join(RedmineGitHosting::Config.gitolite_global_storage_dir, gitolite_repository_name_with_extension)
|
||||
end
|
||||
|
||||
# This is the full absolute path to the Gitolite repository.
|
||||
# Example : /home/git/repositories/redmine/blabla/test-blabla/uuuuuuuuuuu/oooooo.git
|
||||
#
|
||||
def gitolite_full_repository_path
|
||||
File.join(RedmineGitHosting::Config.gitolite_home_dir, gitolite_repository_path)
|
||||
end
|
||||
|
||||
# A syntaxic sugar used to move repository from a location to an other
|
||||
# Example : repositories/blabla/test-blabla/uuuuuuuuuuu/oooooo
|
||||
#
|
||||
def new_repository_name
|
||||
gitolite_repository_name
|
||||
end
|
||||
|
||||
# Used to move repository from a location to an other.
|
||||
# At this point repository url still points to the old location but
|
||||
# it contains the Gitolite storage directory in its path and the '.git' extension.
|
||||
# Strip them to get the old repository name.
|
||||
# Example :
|
||||
# before : repositories/redmine/blabla/test-blabla/uuuuuuuuuuu/oooooo.git
|
||||
# after : redmine/blabla/test-blabla/uuuuuuuuuuu/oooooo
|
||||
#
|
||||
def old_repository_name
|
||||
url.gsub(RedmineGitHosting::Config.gitolite_global_storage_dir, '').gsub('.git', '')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_full_parent_path
|
||||
return '' unless RedmineGitHosting::Config.hierarchical_organisation?
|
||||
|
||||
parent_parts = []
|
||||
p = project
|
||||
while p.parent
|
||||
parent_id = p.parent.identifier.to_s
|
||||
parent_parts.unshift(parent_id)
|
||||
p = p.parent
|
||||
end
|
||||
parent_parts.join('/')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,60 @@
|
|||
module Gitolitable
|
||||
module Permissions
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def build_gitolite_permissions(old_perms = {})
|
||||
permissions_builder.build(self, gitolite_users, old_perms)
|
||||
end
|
||||
|
||||
# We assume here that ':gitolite_config_file' is different than 'gitolite.conf'
|
||||
# like 'redmine.conf' with 'include "redmine.conf"' in 'gitolite.conf'.
|
||||
# This way, we know that all repos in this file are managed by Redmine so we
|
||||
# don't need to backup users
|
||||
#
|
||||
def backup_gitolite_permissions(current_permissions)
|
||||
if protected_branches_available? || RedmineGitHosting::Config.gitolite_identifier_prefix == ''
|
||||
{}
|
||||
else
|
||||
extract_permissions(current_permissions)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def permissions_builder
|
||||
if protected_branches_available?
|
||||
PermissionsBuilder::ProtectedBranches
|
||||
else
|
||||
PermissionsBuilder::Standard
|
||||
end
|
||||
end
|
||||
|
||||
SKIP_USERS = %w[gitweb daemon DUMMY_REDMINE_KEY REDMINE_ARCHIVED_PROJECT REDMINE_CLOSED_PROJECT].freeze
|
||||
|
||||
def extract_permissions(current_permissions)
|
||||
old_permissions = {}
|
||||
|
||||
current_permissions.each do |perm, branch_settings|
|
||||
old_permissions[perm] = {}
|
||||
|
||||
branch_settings.each do |branch, user_list|
|
||||
next if user_list.empty?
|
||||
|
||||
new_user_list = []
|
||||
|
||||
user_list.each do |user|
|
||||
# ignore these users
|
||||
next if SKIP_USERS.include?(user)
|
||||
|
||||
# backup users that are not Redmine users
|
||||
new_user_list.push(user) unless user.include?(RedmineGitHosting::Config.gitolite_identifier_prefix)
|
||||
end
|
||||
|
||||
old_permissions[perm][branch] = new_user_list if new_user_list.any?
|
||||
end
|
||||
end
|
||||
|
||||
old_permissions
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,114 @@
|
|||
module Gitolitable
|
||||
module Urls
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def http_user_login
|
||||
User.current.anonymous? ? '' : "#{User.current.login}@"
|
||||
end
|
||||
|
||||
def git_access_path
|
||||
gitolite_repository_name_with_extension
|
||||
end
|
||||
|
||||
def http_access_path
|
||||
"#{RedmineGitHosting::Config.http_server_subdir}#{redmine_repository_path}.git"
|
||||
end
|
||||
|
||||
def go_access_path
|
||||
"go/#{redmine_repository_path}"
|
||||
end
|
||||
|
||||
def ssh_url
|
||||
url = "ssh://#{RedmineGitHosting::Config.gitolite_user}@#{RedmineGitHosting::Config.ssh_server_domain}"
|
||||
|
||||
url << if RedmineGitHosting::Config.gitolite_server_port == '22'
|
||||
"/#{git_access_path}"
|
||||
else
|
||||
":#{RedmineGitHosting::Config.gitolite_server_port}/#{git_access_path}"
|
||||
end
|
||||
|
||||
url
|
||||
end
|
||||
|
||||
def git_url
|
||||
"git://#{RedmineGitHosting::Config.ssh_server_domain}/#{git_access_path}"
|
||||
end
|
||||
|
||||
def http_url
|
||||
"http://#{http_user_login}#{RedmineGitHosting::Config.http_root_url}/#{http_access_path}"
|
||||
end
|
||||
|
||||
def https_url
|
||||
"https://#{http_user_login}#{RedmineGitHosting::Config.https_root_url}/#{http_access_path}"
|
||||
end
|
||||
|
||||
def git_annex_url
|
||||
"#{RedmineGitHosting::Config.gitolite_user}@#{RedmineGitHosting::Config.ssh_server_domain}:#{git_access_path}"
|
||||
end
|
||||
|
||||
# This is the url used by Go to clone repository
|
||||
#
|
||||
def go_access_url
|
||||
return '' unless smart_http_enabled?
|
||||
return https_url if https_access_available?
|
||||
return http_url if http_access_available?
|
||||
end
|
||||
|
||||
# This is the url to add in Go files
|
||||
#
|
||||
def go_url
|
||||
return '' unless smart_http_enabled?
|
||||
return "#{RedmineGitHosting::Config.https_root_url}/#{go_access_path}" if https_access_available?
|
||||
return "#{RedmineGitHosting::Config.http_root_url}/#{go_access_path}" if http_access_available?
|
||||
end
|
||||
|
||||
def ssh_access
|
||||
{ url: ssh_url, committer: User.current.allowed_to_commit?(self).to_s }
|
||||
end
|
||||
|
||||
## Unsecure channels (clear password), commit is disabled
|
||||
def http_access
|
||||
{ url: http_url, committer: 'false' }
|
||||
end
|
||||
|
||||
def https_access
|
||||
{ url: https_url, committer: User.current.allowed_to_commit?(self).to_s }
|
||||
end
|
||||
|
||||
def git_access
|
||||
{ url: git_url, committer: 'false' }
|
||||
end
|
||||
|
||||
def git_annex_access
|
||||
{ url: git_annex_url, committer: User.current.allowed_to_commit?(self).to_s }
|
||||
end
|
||||
|
||||
def go_access
|
||||
{ url: go_url, committer: 'false' }
|
||||
end
|
||||
|
||||
def available_urls
|
||||
hash = {}
|
||||
hash[:ssh] = ssh_access if ssh_access_available?
|
||||
hash[:https] = https_access if https_access_available?
|
||||
hash[:http] = http_access if http_access_available?
|
||||
hash[:git] = git_access if git_access_available?
|
||||
hash[:go] = go_access if go_access_available?
|
||||
hash[:git_annex] = git_annex_access if git_annex_access_available?
|
||||
hash
|
||||
end
|
||||
|
||||
def available_urls_sorted
|
||||
return available_urls if urls_order.blank?
|
||||
|
||||
hash = {}
|
||||
urls_order.each do |url|
|
||||
available_url = available_urls[url.to_sym]
|
||||
next if available_url.blank?
|
||||
|
||||
hash[url.to_sym] = available_url
|
||||
end
|
||||
hash
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,95 @@
|
|||
module Gitolitable
|
||||
module Users
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def gitolite_users
|
||||
if project.active?
|
||||
users_for_active_project
|
||||
elsif project.archived?
|
||||
users_for_archived_project
|
||||
else
|
||||
users_for_closed_project
|
||||
end
|
||||
end
|
||||
|
||||
def users_for_active_project
|
||||
data = {}
|
||||
data[:rewind_users] = rewind_users + rewind_deploy_users
|
||||
data[:write_users] = write_users
|
||||
data[:read_users] = read_users + read_deploy_users
|
||||
data[:developer_team] = developer_team
|
||||
data[:all_read] = all_users
|
||||
|
||||
# Add other users
|
||||
data[:read_users] << 'DUMMY_REDMINE_KEY' if read_users.empty? && write_users.empty? && rewind_users.empty?
|
||||
data[:read_users] << 'gitweb' if git_web_available?
|
||||
data[:read_users] << 'daemon' if git_daemon_available?
|
||||
|
||||
# Return users
|
||||
data
|
||||
end
|
||||
|
||||
def users_for_archived_project
|
||||
data = {}
|
||||
data[:read_users] = ['REDMINE_ARCHIVED_PROJECT']
|
||||
data
|
||||
end
|
||||
|
||||
def users_for_closed_project
|
||||
data = {}
|
||||
data[:read_users] = all_users
|
||||
data[:read_users] << 'REDMINE_CLOSED_PROJECT'
|
||||
data
|
||||
end
|
||||
|
||||
def users
|
||||
project.users_available
|
||||
end
|
||||
|
||||
def rewind_users
|
||||
@rewind_users ||= users.select { |u| u.allowed_to?(:manage_repository, project) }.map { |u| u.gitolite_identifier }.sort
|
||||
end
|
||||
|
||||
def write_users
|
||||
@write_users ||= users.select { |u| u.allowed_to?(:commit_access, project) }.map { |u| u.gitolite_identifier }.sort - rewind_users
|
||||
end
|
||||
|
||||
def read_users
|
||||
@read_users ||= users.select { |u| u.allowed_to?(:view_changesets, project) }
|
||||
.map { |u| u.gitolite_identifier }
|
||||
.sort - rewind_users - write_users
|
||||
end
|
||||
|
||||
def developer_team
|
||||
@developer_team ||= (rewind_users + write_users).sort
|
||||
end
|
||||
|
||||
def all_users
|
||||
@all_users ||= (rewind_users + write_users + read_users).sort
|
||||
end
|
||||
|
||||
def rewind_deploy_users
|
||||
deploy_users_for_keys rewind_deploy_keys
|
||||
end
|
||||
|
||||
def read_deploy_users
|
||||
deploy_users_for_keys read_deploy_keys
|
||||
end
|
||||
|
||||
def rewind_deploy_keys
|
||||
deploy_keys_by_perm 'RW+'
|
||||
end
|
||||
|
||||
def read_deploy_keys
|
||||
deploy_keys_by_perm 'R'
|
||||
end
|
||||
|
||||
def deploy_keys_by_perm(perm)
|
||||
deployment_credentials.active.select { |cred| cred.perm == perm }
|
||||
end
|
||||
|
||||
def deploy_users_for_keys(keys)
|
||||
keys.map { |cred| cred.gitolite_public_key.owner }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,113 @@
|
|||
module Gitolitable
|
||||
module Validations
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
# Set URL ourself as relative path.
|
||||
#
|
||||
before_validation :set_git_urls
|
||||
|
||||
# Make sure that identifier does not match Gitolite Admin repository
|
||||
#
|
||||
validates_exclusion_of :identifier, in: %w[gitolite-admin]
|
||||
|
||||
# Place additional constraints on repository identifiers
|
||||
# because of multi repos
|
||||
#
|
||||
validate :additional_constraints_on_identifier
|
||||
validate :identifier_dont_change
|
||||
validate :default_repository_has_identifier
|
||||
|
||||
class << self
|
||||
# Build a hash of repository identifier :
|
||||
# <repo_1_identifier> => 1
|
||||
# <repo_2_identifier> => 1
|
||||
# etc...
|
||||
# If the same repository identifier is found many times, increment the corresponding counter.
|
||||
# Repository identifiers are unique if all values of the hash are 1.
|
||||
#
|
||||
def identifiers_to_hash
|
||||
all.map(&:identifier).inject(Hash.new(0)) do |h, x|
|
||||
h[x] += 1 if x.present?
|
||||
h
|
||||
end
|
||||
end
|
||||
|
||||
def have_duplicated_identifier?
|
||||
(identifiers_to_hash.values.max || 0) > 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def exists_in_gitolite?
|
||||
RedmineGitHosting::Commands.sudo_dir_exists?(gitolite_repository_path)
|
||||
end
|
||||
|
||||
def empty_in_gitolite?
|
||||
RedmineGitHosting::Commands.sudo_repository_empty?(gitolite_repository_path)
|
||||
end
|
||||
|
||||
def git_objects_count
|
||||
RedmineGitHosting::Commands.sudo_git_objects_count(File.join(gitolite_repository_path, 'objects'))
|
||||
end
|
||||
|
||||
def empty?
|
||||
extra_info.nil? || (!extra_info.key?('heads') && !extra_info.key?('branches'))
|
||||
end
|
||||
|
||||
def data_for_destruction
|
||||
{
|
||||
repo_name: gitolite_repository_name,
|
||||
repo_path: gitolite_full_repository_path,
|
||||
delete_repository: deletable?,
|
||||
git_cache_id: git_cache_id
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Set up git urls for new repositories
|
||||
#
|
||||
def set_git_urls
|
||||
self.url = gitolite_repository_path if url.blank?
|
||||
self.root_url = url if root_url.blank?
|
||||
end
|
||||
|
||||
# Check several aspects of repository identifier (only for Redmine 1.4+)
|
||||
# 1) cannot equal identifier of any project
|
||||
# 2) if repo_ident_unique? make sure that repo identifier is globally unique
|
||||
# 3) cannot make this repo the default if there will be some other repo with blank identifier
|
||||
#
|
||||
def additional_constraints_on_identifier
|
||||
if identifier.present? && (new_record? || identifier_changed?)
|
||||
errors.add(:identifier, :cannot_equal_project) if Project.find_by_identifier(identifier)
|
||||
|
||||
# See if a repo for another project has the same identifier (existing validations already check for current project)
|
||||
if self.class.repo_ident_unique? && Repository.where("identifier = ? and project_id <> ?", identifier, project.id).any?
|
||||
errors.add :identifier, :taken
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Make sure identifier hasn't changed. Allow null and blank
|
||||
# Note that simply using identifier_changed doesn't seem to work
|
||||
# if the identifier was "NULL" but the new identifier is ""
|
||||
#
|
||||
def identifier_dont_change
|
||||
return if new_record?
|
||||
|
||||
if (identifier_was.blank? && identifier.present?) || (identifier_was.present? && identifier_changed?)
|
||||
errors.add :identifier, :cannot_change
|
||||
end
|
||||
end
|
||||
|
||||
# Need to make sure that we don't take the default slot away from a sibling repo with blank identifier
|
||||
#
|
||||
def default_repository_has_identifier
|
||||
if project && (is_default? || set_as_default?)
|
||||
possibles = Repository.where("project_id = ? and (identifier = '' or identifier is null)", project.id)
|
||||
errors.add(:base, :blank_default_exists) if possibles.any? && (new_record? || possibles.detect { |x| x.id != id })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
21
plugins/redmine_git_hosting/app/models/git_cache.rb
Normal file
21
plugins/redmine_git_hosting/app/models/git_cache.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
class GitCache < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
|
||||
CACHE_ADAPTERS = [%w[Database database],
|
||||
%w[Memcached memcached],
|
||||
%w[Redis redis]].freeze
|
||||
|
||||
## Attributes
|
||||
safe_attributes 'repo_identifier', 'command', 'command_output'
|
||||
|
||||
## Validations
|
||||
validates :repo_identifier, presence: true
|
||||
validates :command, presence: true
|
||||
validates :command_output, presence: true
|
||||
|
||||
class << self
|
||||
def adapters
|
||||
CACHE_ADAPTERS.map(&:last)
|
||||
end
|
||||
end
|
||||
end
|
8
plugins/redmine_git_hosting/app/models/github_comment.rb
Normal file
8
plugins/redmine_git_hosting/app/models/github_comment.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
class GithubComment < ActiveRecord::Base
|
||||
## Relations
|
||||
belongs_to :journal
|
||||
|
||||
## Validations
|
||||
validates :github_id, presence: true
|
||||
validates :journal_id, presence: true, uniqueness: { scope: :github_id }
|
||||
end
|
8
plugins/redmine_git_hosting/app/models/github_issue.rb
Normal file
8
plugins/redmine_git_hosting/app/models/github_issue.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
class GithubIssue < ActiveRecord::Base
|
||||
## Relations
|
||||
belongs_to :issue
|
||||
|
||||
## Validations
|
||||
validates :github_id, presence: true
|
||||
validates :issue_id, presence: true, uniqueness: { scope: :github_id }
|
||||
end
|
203
plugins/redmine_git_hosting/app/models/gitolite_public_key.rb
Normal file
203
plugins/redmine_git_hosting/app/models/gitolite_public_key.rb
Normal file
|
@ -0,0 +1,203 @@
|
|||
class GitolitePublicKey < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
|
||||
TITLE_LENGTH_LIMIT = 60
|
||||
|
||||
KEY_TYPE_USER = 0
|
||||
KEY_TYPE_DEPLOY = 1
|
||||
|
||||
## Attributes
|
||||
safe_attributes 'title', 'key', 'key_type', 'delete_when_unused'
|
||||
|
||||
## Relations
|
||||
belongs_to :user
|
||||
has_many :repository_deployment_credentials, dependent: :destroy
|
||||
|
||||
## Validations
|
||||
validates :user_id, presence: true
|
||||
|
||||
validates :title, presence: true, uniqueness: { case_sensitive: false, scope: :user_id },
|
||||
length: { maximum: TITLE_LENGTH_LIMIT }, format: /\A[a-z0-9_\-]*\z/i
|
||||
|
||||
validates :identifier, presence: true, uniqueness: { case_sensitive: false, scope: :user_id }
|
||||
validates :key, presence: true
|
||||
validates :key_type, presence: true, numericality: { only_integer: true },
|
||||
inclusion: { in: [KEY_TYPE_USER, KEY_TYPE_DEPLOY] }
|
||||
|
||||
validate :has_not_been_changed
|
||||
validate :key_correctness
|
||||
validate :key_not_admin
|
||||
validate :key_uniqueness
|
||||
|
||||
## Scopes
|
||||
scope :user_key, -> { where(key_type: KEY_TYPE_USER) }
|
||||
scope :deploy_key, -> { where(key_type: KEY_TYPE_DEPLOY) }
|
||||
scope :sorted, -> { order(:title, :created_at) }
|
||||
|
||||
## Callbacks
|
||||
before_validation :strip_whitespace
|
||||
before_validation :remove_control_characters
|
||||
|
||||
before_validation :set_identifier
|
||||
before_validation :set_fingerprint
|
||||
|
||||
def key_type_as_string
|
||||
user_key? ? 'user_key' : 'deploy_key'
|
||||
end
|
||||
|
||||
def to_s
|
||||
title
|
||||
end
|
||||
|
||||
def data_for_destruction
|
||||
{ title: identifier, key: key, location: location, owner: owner }
|
||||
end
|
||||
|
||||
# Returns the path to this key under the gitolite keydir
|
||||
# resolves to <user.gitolite_identifier>/<location>/<owner>.pub
|
||||
#
|
||||
# tile: test-key
|
||||
# identifier: redmine_admin_1@redmine_test_key
|
||||
# identifier: redmine_admin_1@redmine_deploy_key_1
|
||||
#
|
||||
#
|
||||
# keydir/
|
||||
# ├── redmine_git_hosting
|
||||
# │ └── redmine_admin_1
|
||||
# │ ├── redmine_test_key
|
||||
# │ │ └── redmine_admin_1.pub
|
||||
# │ ├── redmine_deploy_key_1
|
||||
# │ │ └── redmine_admin_1.pub
|
||||
# │ └── redmine_deploy_key_2
|
||||
# │ └── redmine_admin_1.pub
|
||||
# └── redmine_gitolite_admin_id_rsa.pub
|
||||
#
|
||||
#
|
||||
# The root folder for this user is the user's identifier
|
||||
# for logical grouping of their keys, which are organized
|
||||
# by their title in subfolders.
|
||||
#
|
||||
# This is due to the new gitolite multi-keys organization
|
||||
# using folders. See https://gitolite.com/gitolite/users.html
|
||||
def gitolite_path
|
||||
File.join('keydir', RedmineGitHosting::Config.gitolite_key_subdir, user.gitolite_identifier, location, owner) + '.pub'
|
||||
end
|
||||
|
||||
# Make sure that current identifier is consistent with current user login.
|
||||
# This method explicitly overrides the static nature of the identifier
|
||||
def reset_identifiers(opts = {})
|
||||
# Fix identifier
|
||||
self.identifier = nil
|
||||
self.fingerprint = nil
|
||||
|
||||
self.identifier = GitolitePublicKeys::GenerateIdentifier.call(self, user, opts)
|
||||
set_fingerprint
|
||||
|
||||
# Need to override the "never change identifier" constraint
|
||||
save(validate: false)
|
||||
end
|
||||
|
||||
# Key type checking functions
|
||||
def user_key?
|
||||
key_type == KEY_TYPE_USER
|
||||
end
|
||||
|
||||
def deploy_key?
|
||||
key_type == KEY_TYPE_DEPLOY
|
||||
end
|
||||
|
||||
def owner
|
||||
identifier.split('@')[0]
|
||||
end
|
||||
|
||||
def location
|
||||
identifier.split('@')[1]
|
||||
end
|
||||
|
||||
def type
|
||||
key.split(' ')[0]
|
||||
end
|
||||
|
||||
def blob
|
||||
key.split(' ')[1]
|
||||
end
|
||||
|
||||
def email
|
||||
key.split(' ')[2]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Strip leading and trailing whitespace
|
||||
# Don't mess with existing keys (since cannot change key text anyway)
|
||||
#
|
||||
def strip_whitespace
|
||||
return unless new_record?
|
||||
|
||||
self.title = title.strip rescue ''
|
||||
self.key = key.strip rescue ''
|
||||
end
|
||||
|
||||
# Remove control characters from key
|
||||
# Don't mess with existing keys (since cannot change key text anyway)
|
||||
#
|
||||
def remove_control_characters
|
||||
return unless new_record?
|
||||
|
||||
self.key = RedmineGitHosting::Utils::Ssh.sanitize_ssh_key(key)
|
||||
end
|
||||
|
||||
# Returns the unique identifier for this key based on the key_type
|
||||
#
|
||||
# For user public keys, this simply is the user's gitolite_identifier.
|
||||
# For deployment keys, we use an incrementing number.
|
||||
#
|
||||
def set_identifier
|
||||
return nil if user_id.nil?
|
||||
|
||||
self.identifier ||= GitolitePublicKeys::GenerateIdentifier.call(self, user)
|
||||
end
|
||||
|
||||
def set_fingerprint
|
||||
self.fingerprint = RedmineGitHosting::Utils::Ssh.ssh_fingerprint(key)
|
||||
rescue RedmineGitHosting::Error::InvalidSshKey => e
|
||||
errors.add(:key, :corrupted)
|
||||
end
|
||||
|
||||
def has_not_been_changed
|
||||
return if new_record?
|
||||
|
||||
%w[identifier key user_id key_type title fingerprint].each do |attribute|
|
||||
method = "#{attribute}_changed?"
|
||||
errors.add(attribute, :cannot_change) if send(method)
|
||||
end
|
||||
end
|
||||
|
||||
# Test correctness of fingerprint from output
|
||||
# and general ssh-(r|d|ecd)sa <key> <id> structure
|
||||
#
|
||||
def key_correctness
|
||||
return false if key.nil?
|
||||
|
||||
key.match(/^(\S+)\s+(\S+)/) && (fingerprint =~ /^(\w{2}:?)+$/i)
|
||||
end
|
||||
|
||||
def key_not_admin
|
||||
errors.add(:key, :taken_by_gitolite_admin) if fingerprint == RedmineGitHosting::Config.gitolite_ssh_public_key_fingerprint
|
||||
end
|
||||
|
||||
def key_uniqueness
|
||||
return unless new_record?
|
||||
|
||||
existing = GitolitePublicKey.find_by_fingerprint(fingerprint)
|
||||
return unless existing
|
||||
|
||||
if existing.user == User.current
|
||||
errors.add(:key, :taken_by_you, name: existing.title)
|
||||
elsif User.current.admin?
|
||||
errors.add(:key, :taken_by_other, login: existing.user.login, name: existing.title)
|
||||
else
|
||||
errors.add(:key, :taken_by_someone)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
class ProtectedBranchesMember < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
|
||||
## Attributes
|
||||
safe_attributes 'principal_id', 'inherited_by'
|
||||
|
||||
## Relations
|
||||
belongs_to :protected_branch, class_name: 'RepositoryProtectedBranche'
|
||||
belongs_to :principal
|
||||
|
||||
## Callbacks
|
||||
after_destroy :remove_dependent_objects
|
||||
|
||||
private
|
||||
|
||||
def remove_dependent_objects
|
||||
return unless principal.class.name == 'Group'
|
||||
|
||||
principal.users.each do |user|
|
||||
member = self.class.find_by_principal_id_and_inherited_by(user.id, principal.id)
|
||||
member&.destroy!
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,74 @@
|
|||
require_dependency 'redmine/scm/adapters/xitolite_adapter'
|
||||
|
||||
class Repository::Xitolite < Repository::Git
|
||||
# Include Gitolitable concern
|
||||
include Gitolitable
|
||||
|
||||
# Virtual attributes
|
||||
attr_accessor :create_readme
|
||||
attr_accessor :enable_git_annex
|
||||
|
||||
# Redmine uses safe_attributes on Repository, so we need to declare our virtual attributes.
|
||||
safe_attributes 'create_readme', 'enable_git_annex'
|
||||
|
||||
# Relations
|
||||
has_one :extra, dependent: :destroy, foreign_key: 'repository_id', class_name: 'RepositoryGitExtra'
|
||||
has_many :mirrors, dependent: :destroy, foreign_key: 'repository_id', class_name: 'RepositoryMirror'
|
||||
has_many :post_receive_urls, dependent: :destroy, foreign_key: 'repository_id', class_name: 'RepositoryPostReceiveUrl'
|
||||
has_many :deployment_credentials, dependent: :destroy, foreign_key: 'repository_id', class_name: 'RepositoryDeploymentCredential'
|
||||
has_many :git_keys, dependent: :destroy, foreign_key: 'repository_id', class_name: 'RepositoryGitConfigKey'
|
||||
has_many :git_config_keys, dependent: :destroy, foreign_key: 'repository_id', class_name: 'RepositoryGitConfigKey::GitConfig'
|
||||
has_many :git_option_keys, dependent: :destroy, foreign_key: 'repository_id', class_name: 'RepositoryGitConfigKey::Option'
|
||||
has_many :protected_branches, dependent: :destroy, foreign_key: 'repository_id', class_name: 'RepositoryProtectedBranche'
|
||||
|
||||
# Additionnal validations
|
||||
validate :valid_repository_options, on: :create
|
||||
|
||||
acts_as_watchable
|
||||
|
||||
class << self
|
||||
def scm_adapter_class
|
||||
Redmine::Scm::Adapters::XitoliteAdapter
|
||||
end
|
||||
|
||||
def scm_name
|
||||
'Gitolite'
|
||||
end
|
||||
end
|
||||
|
||||
def sti_name
|
||||
'Repository::Xitolite'
|
||||
end
|
||||
|
||||
# Override the original method to accept options hash
|
||||
# which may contain *bypass_cache* flag.
|
||||
#
|
||||
def diff(path, rev, rev_to, opts = {})
|
||||
scm.diff(path, rev, rev_to, opts)
|
||||
end
|
||||
|
||||
def rev_list(revision, args = [])
|
||||
scm.rev_list(revision, args)
|
||||
end
|
||||
|
||||
def rev_parse(revision)
|
||||
scm.rev_parse(revision)
|
||||
end
|
||||
|
||||
def archive(revision, format = 'tar')
|
||||
scm.archive(revision, format)
|
||||
end
|
||||
|
||||
def mirror_push(url, branch, args = [])
|
||||
scm.mirror_push(url, branch, args)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def valid_repository_options
|
||||
return unless Additionals.true? create_readme
|
||||
return unless Additionals.true? enable_git_annex
|
||||
|
||||
errors.add(:base, :invalid_options)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,56 @@
|
|||
class RepositoryDeploymentCredential < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
|
||||
VALID_PERMS = ['R', 'RW+'].freeze
|
||||
DEFAULT_PERM = 'RW+'.freeze
|
||||
|
||||
## Attributes
|
||||
safe_attributes 'perm', 'active', 'gitolite_public_key_id'
|
||||
|
||||
## Relations
|
||||
belongs_to :repository
|
||||
belongs_to :gitolite_public_key
|
||||
belongs_to :user
|
||||
|
||||
## Validations
|
||||
validates :repository_id, presence: true,
|
||||
uniqueness: { scope: :gitolite_public_key_id }
|
||||
|
||||
validates :gitolite_public_key_id, presence: true, exclusion: { in: [-1] }
|
||||
validates :user_id, presence: true
|
||||
validates :perm, presence: true,
|
||||
inclusion: { in: VALID_PERMS }
|
||||
|
||||
validates_associated :repository
|
||||
validates_associated :gitolite_public_key
|
||||
validates_associated :user
|
||||
|
||||
validate :correct_key_type
|
||||
validate :owner_matches_key
|
||||
|
||||
## Scopes
|
||||
scope :active, -> { where(active: true) }
|
||||
scope :inactive, -> { where(active: false) }
|
||||
scope :sorted, -> { order(:id) }
|
||||
|
||||
def to_s
|
||||
"#{repository.identifier}-#{gitolite_public_key.identifier} : #{perm}"
|
||||
end
|
||||
|
||||
# Deployment Credentials ignored unless created by someone who still has permission to create them
|
||||
def honored?
|
||||
user.admin? || user.allowed_to?(:create_repository_deployment_credentials, repository.project)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def correct_key_type
|
||||
errors.add(:base, :invalid_key) if gitolite_public_key && gitolite_public_key.key_type_as_string != 'deploy_key'
|
||||
end
|
||||
|
||||
def owner_matches_key
|
||||
return if user.nil? || gitolite_public_key.nil?
|
||||
|
||||
errors.add(:base, :invalid_user) if user != gitolite_public_key.user
|
||||
end
|
||||
end
|
|
@ -0,0 +1,42 @@
|
|||
class RepositoryGitConfigKey < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
|
||||
## Attributes
|
||||
safe_attributes 'type', 'key', 'value'
|
||||
|
||||
## Relations
|
||||
belongs_to :repository
|
||||
|
||||
## Validations
|
||||
validates :repository_id, presence: true
|
||||
validates :type, presence: true, inclusion: { in: ['RepositoryGitConfigKey::GitConfig', 'RepositoryGitConfigKey::Option'] }
|
||||
validates :value, presence: true
|
||||
|
||||
## Callbacks
|
||||
after_save :check_if_key_changed
|
||||
|
||||
## Virtual attribute
|
||||
attr_accessor :key_has_changed
|
||||
attr_accessor :old_key
|
||||
|
||||
# Syntaxic sugar
|
||||
def key_has_changed?
|
||||
key_has_changed
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# This is Rails method : <attribute>_changed?
|
||||
# However, the value is cleared before passing the object to the controller.
|
||||
# We need to save it in virtual attribute to trigger Gitolite resync if changed.
|
||||
#
|
||||
def check_if_key_changed
|
||||
if key_changed?
|
||||
self.key_has_changed = true
|
||||
self.old_key = key_change[0]
|
||||
else
|
||||
self.key_has_changed = false
|
||||
self.old_key = ''
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,7 @@
|
|||
class RepositoryGitConfigKey::GitConfig < RepositoryGitConfigKey
|
||||
VALID_CONFIG_KEY_REGEX = /\A[a-zA-Z0-9]+\.[a-zA-Z0-9.]+\z/
|
||||
|
||||
validates :key, presence: true,
|
||||
uniqueness: { case_sensitive: false, scope: %i[type repository_id] },
|
||||
format: { with: VALID_CONFIG_KEY_REGEX }
|
||||
end
|
|
@ -0,0 +1,4 @@
|
|||
class RepositoryGitConfigKey::Option < RepositoryGitConfigKey
|
||||
validates :key, presence: true,
|
||||
uniqueness: { case_sensitive: false, scope: %i[type repository_id] }
|
||||
end
|
115
plugins/redmine_git_hosting/app/models/repository_git_extra.rb
Normal file
115
plugins/redmine_git_hosting/app/models/repository_git_extra.rb
Normal file
|
@ -0,0 +1,115 @@
|
|||
class RepositoryGitExtra < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
|
||||
SMART_HTTP_OPTIONS = [[l(:label_disabled), '0'],
|
||||
[l(:label_http_only), '3'],
|
||||
[l(:label_https_only), '1'],
|
||||
[l(:label_https_and_http), '2']].freeze
|
||||
|
||||
ALLOWED_URLS = %w[ssh http https go git git_annex].freeze
|
||||
|
||||
URLS_ICONS = { go: { label: 'Go', icon: 'fab_google' },
|
||||
http: { label: 'HTTP', icon: 'fas_external-link-alt' },
|
||||
https: { label: 'HTTPS', icon: 'fas_external-link-alt' },
|
||||
ssh: { label: 'SSH', icon: 'fas_shield-alt' },
|
||||
git: { label: 'Git', icon: 'fab_git' },
|
||||
git_annex: { label: 'GitAnnex', icon: 'fab_git' } }.freeze
|
||||
|
||||
## Attributes
|
||||
safe_attributes 'git_http', 'git_https', 'git_ssh', 'git_go', 'git_daemon', 'git_notify', 'git_annex', 'default_branch',
|
||||
'protected_branch', 'public_repo', 'key', 'urls_order', 'notification_sender', 'notification_prefix'
|
||||
|
||||
## Relations
|
||||
belongs_to :repository
|
||||
|
||||
## Validations
|
||||
validates :repository_id, presence: true, uniqueness: true
|
||||
validates :default_branch, presence: true
|
||||
validates :key, presence: true
|
||||
validates :notification_sender, format: { with: URI::MailTo::EMAIL_REGEXP, allow_blank: true }
|
||||
|
||||
validate :validate_urls_order
|
||||
|
||||
## Serializations
|
||||
serialize :urls_order, Array
|
||||
|
||||
## Callbacks
|
||||
before_save :check_urls_order_consistency
|
||||
after_save :check_if_default_branch_changed
|
||||
|
||||
## Virtual attribute
|
||||
attr_accessor :default_branch_has_changed
|
||||
|
||||
# Syntaxic sugar
|
||||
def default_branch_has_changed?
|
||||
default_branch_has_changed
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate_urls_order
|
||||
urls_order.each do |url|
|
||||
errors.add(:urls_order, :invalid) unless ALLOWED_URLS.include?(url)
|
||||
end
|
||||
end
|
||||
|
||||
# This is Rails method : <attribute>_changed?
|
||||
# However, the value is cleared before passing the object to the controller.
|
||||
# We need to save it in virtual attribute to trigger Gitolite resync if changed.
|
||||
#
|
||||
def check_if_default_branch_changed
|
||||
self.default_branch_has_changed = if default_branch_changed?
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def check_urls_order_consistency
|
||||
check_ssh_url
|
||||
check_git_http_urls
|
||||
check_go_url
|
||||
check_git_url
|
||||
check_git_annex_url
|
||||
end
|
||||
|
||||
def check_ssh_url
|
||||
git_ssh? ? add_url('ssh') : remove_url('ssh')
|
||||
end
|
||||
|
||||
def check_git_http_urls
|
||||
if git_http? && git_https?
|
||||
add_url('http')
|
||||
add_url('https')
|
||||
elsif git_http?
|
||||
add_url('http')
|
||||
remove_url('https')
|
||||
elsif git_https?
|
||||
add_url('https')
|
||||
remove_url('http')
|
||||
else
|
||||
remove_url('http')
|
||||
remove_url('https')
|
||||
end
|
||||
end
|
||||
|
||||
def check_go_url
|
||||
git_go? ? add_url('go') : remove_url('go')
|
||||
end
|
||||
|
||||
def check_git_annex_url
|
||||
git_annex? ? add_url('git_annex') : remove_url('git_annex')
|
||||
end
|
||||
|
||||
def check_git_url
|
||||
git_daemon? ? add_url('git') : remove_url('git')
|
||||
end
|
||||
|
||||
def remove_url(url)
|
||||
urls_order.delete(url)
|
||||
end
|
||||
|
||||
def add_url(url)
|
||||
urls_order.push(url).uniq!
|
||||
end
|
||||
end
|
107
plugins/redmine_git_hosting/app/models/repository_mirror.rb
Normal file
107
plugins/redmine_git_hosting/app/models/repository_mirror.rb
Normal file
|
@ -0,0 +1,107 @@
|
|||
class RepositoryMirror < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
|
||||
PUSHMODE_MIRROR = 0
|
||||
PUSHMODE_FORCE = 1
|
||||
PUSHMODE_FAST_FORWARD = 2
|
||||
|
||||
## Attributes
|
||||
safe_attributes 'url', 'push_mode', 'include_all_branches', 'include_all_tags',
|
||||
'explicit_refspec', 'active'
|
||||
|
||||
## Relations
|
||||
belongs_to :repository
|
||||
|
||||
## Validations
|
||||
validates :repository_id, presence: true
|
||||
|
||||
## Only allow SSH format
|
||||
## ssh://git@redmine.example.org/project1/project2/project3/project4.git
|
||||
## ssh://git@redmine.example.org:2222/project1/project2/project3/project4.git
|
||||
validates :url, presence: true,
|
||||
uniqueness: { case_sensitive: false, scope: :repository_id },
|
||||
format: { with: RedmineGitHosting::Validators::GIT_SSH_URL_REGEX }
|
||||
|
||||
validates :push_mode, presence: true,
|
||||
numericality: { only_integer: true },
|
||||
inclusion: { in: [PUSHMODE_MIRROR, PUSHMODE_FORCE, PUSHMODE_FAST_FORWARD] }
|
||||
|
||||
## Additional validations
|
||||
validate :mirror_configuration
|
||||
|
||||
## Scopes
|
||||
scope :active, -> { where(active: true) }
|
||||
scope :inactive, -> { where(active: false) }
|
||||
scope :has_explicit_refspec, -> { where(push_mode: '> 0') }
|
||||
scope :sorted, -> { order(:url) }
|
||||
|
||||
## Callbacks
|
||||
before_validation :strip_whitespace
|
||||
|
||||
def mirror_mode?
|
||||
push_mode == PUSHMODE_MIRROR
|
||||
end
|
||||
|
||||
def force_mode?
|
||||
push_mode == PUSHMODE_FORCE
|
||||
end
|
||||
|
||||
def push_mode_to_s
|
||||
case push_mode
|
||||
when 0
|
||||
'mirror'
|
||||
when 1
|
||||
'force'
|
||||
when 2
|
||||
'fast_forward'
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Strip leading and trailing whitespace
|
||||
def strip_whitespace
|
||||
self.url = url.strip rescue ''
|
||||
self.explicit_refspec = explicit_refspec.strip rescue ''
|
||||
end
|
||||
|
||||
def mirror_configuration
|
||||
if mirror_mode?
|
||||
reset_fields
|
||||
elsif include_all_branches? && include_all_tags?
|
||||
mutual_exclusion_error
|
||||
elsif explicit_refspec.present?
|
||||
if include_all_branches?
|
||||
errors.add(:explicit_refspec, "cannot be used with #{l(:label_mirror_include_all_branches)}.")
|
||||
else
|
||||
validate_refspec
|
||||
end
|
||||
elsif !include_all_branches? && !include_all_tags?
|
||||
errors.add(:base, :nothing_to_push)
|
||||
end
|
||||
end
|
||||
|
||||
# Check format of refspec
|
||||
#
|
||||
def validate_refspec
|
||||
RedmineGitHosting::Validators.valid_git_refspec_path?(explicit_refspec)
|
||||
rescue RedmineGitHosting::Error::InvalidRefspec::BadFormat => e
|
||||
errors.add(:explicit_refspec, :bad_format)
|
||||
rescue RedmineGitHosting::Error::InvalidRefspec::NullComponent => e
|
||||
errors.add(:explicit_refspec, :have_null_component)
|
||||
end
|
||||
|
||||
def reset_fields
|
||||
# clear out all extra parameters.. (we use javascript to hide them anyway)
|
||||
self.include_all_branches = false
|
||||
self.include_all_tags = false
|
||||
self.explicit_refspec = ''
|
||||
end
|
||||
|
||||
def mutual_exclusion_error
|
||||
errors.add(:base, "Cannot #{l(:label_mirror_include_all_branches)} and #{l(:label_mirror_include_all_tags)} at the same time.")
|
||||
return if explicit_refspec.blank?
|
||||
|
||||
errors.add(:explicit_refspec, "cannot be used with #{l(:label_mirror_include_all_branches)} or #{l(:label_mirror_include_all_tags)}")
|
||||
end
|
||||
end
|
|
@ -0,0 +1,61 @@
|
|||
require 'uri'
|
||||
|
||||
class RepositoryPostReceiveUrl < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
|
||||
## Attributes
|
||||
safe_attributes 'url', 'mode', 'active', 'use_triggers', 'triggers', 'split_payloads'
|
||||
|
||||
## Relations
|
||||
belongs_to :repository
|
||||
|
||||
## Validations
|
||||
validates :repository_id, presence: true
|
||||
|
||||
# Only allow HTTP(s) format
|
||||
validates :url, presence: true,
|
||||
uniqueness: { case_sensitive: false, scope: :repository_id },
|
||||
format: { with: URI::DEFAULT_PARSER.make_regexp(%w[http https]) }
|
||||
|
||||
validates :mode, presence: true, inclusion: { in: %i[github get post] }
|
||||
|
||||
## Serializations
|
||||
serialize :triggers, Array
|
||||
|
||||
## Scopes
|
||||
scope :active, -> { where(active: true) }
|
||||
scope :inactive, -> { where(active: false) }
|
||||
scope :sorted, -> { order(:url) }
|
||||
|
||||
## Callbacks
|
||||
before_validation :strip_whitespace
|
||||
before_validation :remove_blank_triggers
|
||||
|
||||
def mode
|
||||
self[:mode].to_sym
|
||||
end
|
||||
|
||||
def mode=(value)
|
||||
self[:mode] = value.to_s
|
||||
end
|
||||
|
||||
def github_mode?
|
||||
mode == :github
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Strip leading and trailing whitespace
|
||||
def strip_whitespace
|
||||
self.url = begin
|
||||
url.strip
|
||||
rescue StandardError
|
||||
''
|
||||
end
|
||||
end
|
||||
|
||||
# Remove blank entries in triggers
|
||||
def remove_blank_triggers
|
||||
self.triggers = triggers.select(&:present?)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,48 @@
|
|||
class RepositoryProtectedBranche < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
VALID_PERMS = ['RW+', 'RW', 'R', '-'].freeze
|
||||
DEFAULT_PERM = 'RW+'.freeze
|
||||
|
||||
acts_as_positioned
|
||||
|
||||
## Attributes
|
||||
safe_attributes 'path', 'permissions', 'position'
|
||||
|
||||
## Relations
|
||||
belongs_to :repository
|
||||
has_many :protected_branches_members, foreign_key: :protected_branch_id, dependent: :destroy
|
||||
has_many :members, through: :protected_branches_members, source: :principal
|
||||
|
||||
## Validations
|
||||
validates :repository_id, presence: true
|
||||
validates :path, presence: true, uniqueness: { scope: %i[permissions repository_id] }
|
||||
validates :permissions, presence: true, inclusion: { in: VALID_PERMS }
|
||||
|
||||
## Scopes
|
||||
default_scope { order(position: :asc) }
|
||||
scope :sorted, -> { order(:path) }
|
||||
|
||||
class << self
|
||||
def clone_from(parent)
|
||||
parent = find_by(id: parent) unless parent.is_a? RepositoryProtectedBranche
|
||||
copy = new
|
||||
copy.attributes = parent.attributes
|
||||
copy.repository = parent.repository
|
||||
copy
|
||||
end
|
||||
end
|
||||
|
||||
# Accessors
|
||||
#
|
||||
def users
|
||||
members.select { |m| m.class.name == 'User' }.uniq
|
||||
end
|
||||
|
||||
def groups
|
||||
members.select { |m| m.class.name == 'Group' }.uniq
|
||||
end
|
||||
|
||||
def allowed_users
|
||||
users.map(&:gitolite_identifier).sort
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
Deface::Override.new virtual_path: 'repositories/_navigation',
|
||||
name: 'show-repositories-hook-navigation',
|
||||
insert_before: 'erb[loud]:contains("label_statistics")',
|
||||
original: '88f120e99075ba3246901c6e970ca671d7166855',
|
||||
text: '<%= call_hook(:view_repositories_navigation, repository: @repository) %>'
|
|
@ -0,0 +1,11 @@
|
|||
Deface::Override.new virtual_path: 'repositories/show',
|
||||
name: 'show-repositories-hook-bottom',
|
||||
insert_before: 'erb[silent]:contains("other_formats_links")',
|
||||
original: 'f302d110cd10675a0a952f5f3e1ecfe57ebd38be',
|
||||
text: '<%= call_hook(:view_repositories_show_bottom, repository: @repository) %>'
|
||||
|
||||
Deface::Override.new virtual_path: 'repositories/show',
|
||||
name: 'show-repositories-hook-sidebar',
|
||||
insert_before: 'erb[silent]:contains("html_title")',
|
||||
original: '2a0a09659d76066b896016c72527d479c69463ec',
|
||||
partial: 'hooks/show_repositories_sidebar'
|
|
@ -0,0 +1,77 @@
|
|||
class RepositoryPresenter < SimpleDelegator
|
||||
attr_reader :repository
|
||||
|
||||
def initialize(repository, template)
|
||||
super(template)
|
||||
@repository = repository
|
||||
end
|
||||
|
||||
def link_to_repository
|
||||
link_to repository.name,
|
||||
controller: 'repositories',
|
||||
action: 'show',
|
||||
id: repository.project,
|
||||
repository_id: repository.identifier_param,
|
||||
rev: nil,
|
||||
path: nil
|
||||
end
|
||||
|
||||
def git_urls_box
|
||||
tag.div(class: 'git_url_box', id: urls_container_id) do
|
||||
render_git_urls +
|
||||
render_git_url_text +
|
||||
render_permissions +
|
||||
render_clipboard_button
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render_git_urls
|
||||
tag.ul(render_url_list, class: 'git_url_list')
|
||||
end
|
||||
|
||||
def render_url_list
|
||||
s = ''
|
||||
repository.available_urls_sorted.each do |key, value|
|
||||
s << tag.li(link_to(key.upcase, 'javascript:void(0)').html_safe, options_for_git_url(key, value))
|
||||
end
|
||||
s.html_safe
|
||||
end
|
||||
|
||||
def options_for_git_url(_key, value)
|
||||
{ class: 'git_url', data: { url: value[:url], target: element_name, committer: committer_label(value) } }
|
||||
end
|
||||
|
||||
def render_git_url_text
|
||||
tag.input '', class: 'git_url_text', id: url_text_container_id, readonly: 'readonly'
|
||||
end
|
||||
|
||||
def render_permissions
|
||||
tag.div tag.span('', id: permissions_container_id), class: 'git_url_permissions'
|
||||
end
|
||||
|
||||
def render_clipboard_button
|
||||
clipboardjs_button_for url_text_container_id
|
||||
end
|
||||
|
||||
def committer_label(value)
|
||||
Additionals.true?(value[:committer]) ? l(:label_read_write_permission) : l(:label_read_only_permission)
|
||||
end
|
||||
|
||||
def element_name
|
||||
"repository_#{repository.id}"
|
||||
end
|
||||
|
||||
def urls_container_id
|
||||
"git_url_box_#{element_name}"
|
||||
end
|
||||
|
||||
def permissions_container_id
|
||||
"git_url_permissions_#{element_name}"
|
||||
end
|
||||
|
||||
def url_text_container_id
|
||||
"git_url_text_#{element_name}"
|
||||
end
|
||||
end
|
11
plugins/redmine_git_hosting/app/reports/report_base.rb
Normal file
11
plugins/redmine_git_hosting/app/reports/report_base.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
class ReportBase
|
||||
include Redmine::I18n
|
||||
include ReportHelper
|
||||
include ReportQuery
|
||||
|
||||
attr_reader :repository
|
||||
|
||||
def initialize(repository)
|
||||
@repository = repository
|
||||
end
|
||||
end
|
44
plugins/redmine_git_hosting/app/reports/report_helper.rb
Normal file
44
plugins/redmine_git_hosting/app/reports/report_helper.rb
Normal file
|
@ -0,0 +1,44 @@
|
|||
module ReportHelper
|
||||
def date_to
|
||||
User.current.today
|
||||
end
|
||||
|
||||
def week_day_hash
|
||||
{ day_name(1) => 0,
|
||||
day_name(2) => 0,
|
||||
day_name(3) => 0,
|
||||
day_name(4) => 0,
|
||||
day_name(5) => 0,
|
||||
day_name(6) => 0,
|
||||
day_name(0) => 0 }
|
||||
end
|
||||
|
||||
def hours
|
||||
(0..23).step(1).map { |h| "#{h}h" }
|
||||
end
|
||||
|
||||
def months
|
||||
(1..12).map { |m| l('date.month_names')[m].capitalize }
|
||||
end
|
||||
|
||||
def get_hour_from_date(date)
|
||||
return nil unless date
|
||||
|
||||
time = date.to_time
|
||||
zone = User.current.time_zone
|
||||
local = zone ? time.in_time_zone(zone) : (time.utc? ? time.localtime : time)
|
||||
local.hour
|
||||
end
|
||||
|
||||
def total_by_month_for(method)
|
||||
total = [0] * 12
|
||||
send(method).each { |c| total[(date_to.month - c.first.to_date.month) % 12] += c.last }
|
||||
total
|
||||
end
|
||||
|
||||
def total_by_hour_for(method)
|
||||
total = [0] * 24
|
||||
send(method).each { |c| total[get_hour_from_date(c)] += 1 }
|
||||
total
|
||||
end
|
||||
end
|
47
plugins/redmine_git_hosting/app/reports/report_query.rb
Normal file
47
plugins/redmine_git_hosting/app/reports/report_query.rb
Normal file
|
@ -0,0 +1,47 @@
|
|||
module ReportQuery
|
||||
private
|
||||
|
||||
def all_changesets
|
||||
@all_changesets ||= Changeset.where(repository_id: repository.id)
|
||||
end
|
||||
|
||||
def all_changes
|
||||
@all_changes ||= Change.joins(:changeset).where("#{Changeset.table_name}.repository_id = ?", repository.id)
|
||||
end
|
||||
|
||||
def all_commits_by_day
|
||||
@all_commits_by_day ||= all_changesets.group(:commit_date)
|
||||
end
|
||||
|
||||
def all_changes_by_day
|
||||
@all_changes_by_day ||= all_changes.group(:commit_date)
|
||||
end
|
||||
|
||||
def redmine_committers
|
||||
@redmine_committers ||= all_changesets.where.not(user_id: nil).distinct.count(:user_id)
|
||||
end
|
||||
|
||||
def external_committers
|
||||
@external_committers ||= all_changesets.where(user_id: nil).distinct.count(:committer)
|
||||
end
|
||||
|
||||
def commits_by_day
|
||||
@commits_by_day ||= all_commits_by_day.count
|
||||
end
|
||||
|
||||
def changes_by_day
|
||||
@changes_by_day ||= all_changes_by_day.count
|
||||
end
|
||||
|
||||
def commits_by_hour
|
||||
@commits_by_hour ||= all_changesets.map(&:committed_on)
|
||||
end
|
||||
|
||||
def commits_by_author
|
||||
@commits_by_author ||= all_changesets.group(:committer).count
|
||||
end
|
||||
|
||||
def changes_by_author
|
||||
@changes_by_author ||= all_changes.group(:committer).count
|
||||
end
|
||||
end
|
|
@ -0,0 +1,91 @@
|
|||
class RepositoryCommitsStats < ReportBase
|
||||
def commits_per_month
|
||||
data = {}
|
||||
data[:categories] = months.reverse
|
||||
data[:series] = []
|
||||
data[:series] << { name: l(:label_commit_plural), data: total_commits_by_month[0..11].reverse }
|
||||
data[:series] << { name: l(:label_change_plural), data: total_changes_by_month[0..11].reverse }
|
||||
data
|
||||
end
|
||||
|
||||
def commits_per_day
|
||||
data = {}
|
||||
data[:categories] = total_commits_by_day.keys
|
||||
data[:series] = []
|
||||
data[:series] << { name: l(:label_commit_plural), data: total_commits_by_day.values }
|
||||
data[:series] << { name: l(:label_change_plural), data: total_changes_by_day.values }
|
||||
data
|
||||
end
|
||||
|
||||
def commits_per_hours
|
||||
data = {}
|
||||
data[:categories] = hours
|
||||
data[:series] = []
|
||||
data[:series] << { name: l(:label_commit_plural), data: total_commits_by_hour }
|
||||
data
|
||||
end
|
||||
|
||||
def commits_per_weekday
|
||||
data = {}
|
||||
data[:name] = l(:label_commit_plural)
|
||||
data[:data] = []
|
||||
total_commits_by_weekday.each do |key, value|
|
||||
data[:data] << [key, value]
|
||||
end
|
||||
[data]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def total_commits_by_month
|
||||
total_by_month_for(:commits_by_day)
|
||||
end
|
||||
|
||||
def total_changes_by_month
|
||||
total_by_month_for(:changes_by_day)
|
||||
end
|
||||
|
||||
def total_commits_by_day
|
||||
@total_commits_by_day ||= all_commits_by_day.order(:commit_date).count
|
||||
end
|
||||
|
||||
def total_changes_by_day
|
||||
return @total_changes_by_day unless @total_changes_by_day.nil?
|
||||
|
||||
@total_changes_by_day = nil
|
||||
changes = {}
|
||||
Changeset.where('repository_id = ?', repository.id).includes(:filechanges).order(:commit_date).each do |changeset|
|
||||
changes[changeset.commit_date] = 0 unless changes.key?(changeset.commit_date)
|
||||
changes[changeset.commit_date] += changeset.filechanges.size
|
||||
end
|
||||
@total_changes_by_day = changes
|
||||
@total_changes_by_day
|
||||
end
|
||||
|
||||
def total_commits_by_hour
|
||||
total_by_hour_for(:commits_by_hour)
|
||||
end
|
||||
|
||||
def total_commits_by_weekday
|
||||
week_day = week_day_hash
|
||||
commits_by_day.each do |commit_date, commit_count|
|
||||
case commit_date.to_date.wday
|
||||
when 0
|
||||
week_day[day_name(0)] += commit_count
|
||||
when 1
|
||||
week_day[day_name(1)] += commit_count
|
||||
when 2
|
||||
week_day[day_name(2)] += commit_count
|
||||
when 3
|
||||
week_day[day_name(3)] += commit_count
|
||||
when 4
|
||||
week_day[day_name(4)] += commit_count
|
||||
when 5
|
||||
week_day[day_name(5)] += commit_count
|
||||
when 6
|
||||
week_day[day_name(6)] += commit_count
|
||||
end
|
||||
end
|
||||
week_day
|
||||
end
|
||||
end
|
|
@ -0,0 +1,105 @@
|
|||
class RepositoryContributorsStats < ReportBase
|
||||
def initialize(repository)
|
||||
super
|
||||
@changes_for_committer = {}
|
||||
end
|
||||
|
||||
def commits_per_author
|
||||
data = []
|
||||
|
||||
sorted_commits_per_author_with_aliases.each do |committer_hash|
|
||||
commits = {}
|
||||
|
||||
committer_hash[:committers].each do |committer|
|
||||
commits = commits.merge(count_changes_for_committer(committer)) { |key, oldval, newval| newval + oldval }
|
||||
end
|
||||
|
||||
commits = Hash[commits.sort]
|
||||
commits_data = {}
|
||||
commits_data[:author_name] = committer_hash[:name]
|
||||
commits_data[:author_mail] = committer_hash[:mail]
|
||||
commits_data[:total_commits] = committer_hash[:commits]
|
||||
commits_data[:categories] = commits.keys
|
||||
commits_data[:series] = []
|
||||
commits_data[:series] << { name: l(:label_commit_plural), data: commits.values }
|
||||
data.push(commits_data)
|
||||
end
|
||||
|
||||
data
|
||||
end
|
||||
|
||||
def commits_per_author_global
|
||||
merged = commits_per_author_with_aliases
|
||||
data = {}
|
||||
data[:categories] = merged.map { |x| x[:name] }
|
||||
data[:series] = []
|
||||
data[:series] << { name: l(:label_commit_plural), data: merged.map { |x| x[:commits] } }
|
||||
data[:series] << { name: l(:label_change_plural), data: merged.map { |x| x[:changes] } }
|
||||
data
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Generate mappings from the registered users to the comitters
|
||||
# user_committer_mapping = { name => [comitter, ...] }
|
||||
# registered_committers = [ committer,... ]
|
||||
#
|
||||
def commits_per_author_with_aliases
|
||||
return @commits_per_author_with_aliases if !@commits_per_author_with_aliases.nil?
|
||||
|
||||
@commits_per_author_with_aliases = nil
|
||||
|
||||
registered_committers = []
|
||||
user_committer_mapping = {}
|
||||
Changeset.select('changesets.committer, changesets.user_id')
|
||||
.where(repository_id: repository.id)
|
||||
.where.not(user_id: nil)
|
||||
.group(:committer, :user_id)
|
||||
.includes(:user).each do |x|
|
||||
name = "#{x.user.firstname} #{x.user.lastname}"
|
||||
registered_committers << x.committer
|
||||
user_committer_mapping[[name, x.user.mail]] ||= []
|
||||
user_committer_mapping[[name, x.user.mail]] << x.committer
|
||||
end
|
||||
|
||||
merged = []
|
||||
commits_by_author.each do |committer, count|
|
||||
# skip all registered users
|
||||
next if registered_committers.include?(committer)
|
||||
|
||||
name = committer.gsub(%r{<.+@.+>}, '').strip
|
||||
mail = committer[/<(.+@.+)>/, 1]
|
||||
merged << { name: name, mail: mail, commits: count, changes: changes_by_author[committer] || 0, committers: [committer] }
|
||||
end
|
||||
user_committer_mapping.each do |identity, committers|
|
||||
count = 0
|
||||
changes = 0
|
||||
committers.each do |c|
|
||||
count += commits_by_author[c] || 0
|
||||
changes += changes_by_author[c] || 0
|
||||
end
|
||||
merged << { name: identity[0], mail: identity[1], commits: count, changes: changes, committers: committers }
|
||||
end
|
||||
|
||||
# sort by name
|
||||
merged.sort! { |x, y| x[:name] <=> y[:name] }
|
||||
|
||||
# merged = merged + [{name:"",commits:0,changes:0}]*(10 - merged.length) if merged.length < 10
|
||||
@commits_per_author_with_aliases = merged
|
||||
@commits_per_author_with_aliases
|
||||
end
|
||||
|
||||
def sorted_commits_per_author_with_aliases
|
||||
@committers ||= commits_per_author_with_aliases.sort! { |x, y| y[:commits] <=> x[:commits] }
|
||||
end
|
||||
|
||||
def count_changes_for_committer(committer)
|
||||
return @changes_for_committer[committer] unless @changes_for_committer[committer].nil?
|
||||
|
||||
@changes_for_committer[committer] ||= Changeset.where(repository_id: repository.id, committer: committer)
|
||||
.group(:commit_date)
|
||||
.order(:commit_date)
|
||||
.count
|
||||
@changes_for_committer[committer]
|
||||
end
|
||||
end
|
|
@ -0,0 +1,43 @@
|
|||
class RepositoryGlobalStats < ReportBase
|
||||
def build
|
||||
data = {}
|
||||
data[l(:label_total_commits)] = total_commits
|
||||
data[l(:label_total_contributors)] = committers
|
||||
data[l(:label_first_commit_date)] = format_date(first_commit.commit_date)
|
||||
data[l(:label_latest_commit_date)] = format_date(last_commit.commit_date)
|
||||
data[l(:label_active_for)] = "#{active_for} #{l(:days, active_for)}"
|
||||
data[l(:label_average_commit_per_day)] = average_commit_per_day
|
||||
data[l(:label_average_contributor_commits)] = average_contributor_commits
|
||||
data
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def total_commits
|
||||
@total_commits ||= all_changesets.count
|
||||
end
|
||||
|
||||
def committers
|
||||
@committers ||= redmine_committers + external_committers
|
||||
end
|
||||
|
||||
def first_commit
|
||||
@first_commit ||= all_changesets.order(commit_date: :asc).first
|
||||
end
|
||||
|
||||
def last_commit
|
||||
@last_commit ||= all_changesets.order(commit_date: :asc).last
|
||||
end
|
||||
|
||||
def active_for
|
||||
@active_for ||= (last_commit.commit_date - first_commit.commit_date).to_i
|
||||
end
|
||||
|
||||
def average_commit_per_day
|
||||
@average_commit_per_day ||= total_commits.fdiv(active_for).round(2)
|
||||
end
|
||||
|
||||
def average_contributor_commits
|
||||
@average_contributor_commits ||= total_commits.fdiv(committers).round(2)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
module PermissionsBuilder
|
||||
class Base
|
||||
attr_reader :repository, :gitolite_users, :old_permissions
|
||||
|
||||
def initialize(repository, gitolite_users, old_permissions = {})
|
||||
@repository = repository
|
||||
@gitolite_users = gitolite_users
|
||||
@old_permissions = old_permissions
|
||||
end
|
||||
|
||||
class << self
|
||||
def build(repository, gitolite_users, old_permissions = {})
|
||||
new(repository, gitolite_users, old_permissions).build
|
||||
end
|
||||
end
|
||||
|
||||
def build
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def no_users?(type)
|
||||
gitolite_users[type].blank?
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
module PermissionsBuilder
|
||||
class ProtectedBranches < Base
|
||||
attr_reader :permissions
|
||||
|
||||
def initialize(*args)
|
||||
super
|
||||
@permissions = []
|
||||
end
|
||||
|
||||
def build
|
||||
build_protected_branch_permissions
|
||||
permissions
|
||||
end
|
||||
|
||||
def build_protected_branch_permissions
|
||||
repository.protected_branches.each do |branch|
|
||||
perms = {}
|
||||
perms[branch.permissions] = {}
|
||||
perms[branch.permissions][branch.path] = branch.allowed_users unless branch.allowed_users.empty?
|
||||
permissions.push(perms)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,60 @@
|
|||
module PermissionsBuilder
|
||||
class Standard < Base
|
||||
attr_reader :permissions
|
||||
|
||||
def initialize(*args)
|
||||
super
|
||||
@permissions = {}
|
||||
@permissions['RW+'] = {}
|
||||
@permissions['RW'] = {}
|
||||
@permissions['R'] = {}
|
||||
end
|
||||
|
||||
def build
|
||||
# Build permissions
|
||||
build_permissions
|
||||
|
||||
# Return them
|
||||
[merge_permissions(permissions, old_permissions)]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def build_permissions
|
||||
@permissions['RW+'][''] = gitolite_users[:rewind_users] unless no_users?(:rewind_users)
|
||||
@permissions['RW'][''] = gitolite_users[:write_users] unless no_users?(:write_users)
|
||||
@permissions['R'][''] = gitolite_users[:read_users] unless no_users?(:read_users)
|
||||
end
|
||||
|
||||
def merge_permissions(current_permissions, old_permissions)
|
||||
merge_permissions = {}
|
||||
merge_permissions['RW+'] = {}
|
||||
merge_permissions['RW'] = {}
|
||||
merge_permissions['R'] = {}
|
||||
|
||||
current_permissions.each do |perm, branch_settings|
|
||||
branch_settings.each do |branch, user_list|
|
||||
next unless user_list.any?
|
||||
|
||||
merge_permissions[perm][branch] = [] unless merge_permissions[perm].key?(branch)
|
||||
merge_permissions[perm][branch] += user_list
|
||||
end
|
||||
end
|
||||
|
||||
old_permissions.each do |perm, branch_settings|
|
||||
branch_settings.each do |branch, user_list|
|
||||
next unless user_list.any?
|
||||
|
||||
merge_permissions[perm][branch] = [] unless merge_permissions[perm].key?(branch)
|
||||
merge_permissions[perm][branch] += user_list
|
||||
end
|
||||
end
|
||||
|
||||
merge_permissions.each do |perm, _branch_settings|
|
||||
merge_permissions.delete(perm) if merge_permissions[perm].empty?
|
||||
end
|
||||
|
||||
merge_permissions
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,54 @@
|
|||
module RedmineHooks
|
||||
class Base
|
||||
attr_reader :object, :payloads
|
||||
|
||||
def initialize(object, payloads = {})
|
||||
@object = object
|
||||
@payloads = payloads
|
||||
end
|
||||
|
||||
class << self
|
||||
def call(object, payloads = {})
|
||||
new(object, payloads).call
|
||||
end
|
||||
end
|
||||
|
||||
def call
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def start_message
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def logger
|
||||
RedmineGitHosting.logger
|
||||
end
|
||||
|
||||
def success_message
|
||||
" [success]\n"
|
||||
end
|
||||
|
||||
def failure_message
|
||||
" [failure]\n"
|
||||
end
|
||||
|
||||
def log_hook_succeeded
|
||||
logger.info 'Succeeded!'
|
||||
end
|
||||
|
||||
def log_hook_failed
|
||||
logger.error 'Failed!'
|
||||
end
|
||||
|
||||
def execute_hook(&block)
|
||||
y = ''
|
||||
logger.info start_message
|
||||
y << " - #{start_message} ... "
|
||||
yield y
|
||||
y
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,111 @@
|
|||
module RedmineHooks
|
||||
class CallWebservices < Base
|
||||
include HttpHelper
|
||||
|
||||
attr_reader :payloads_to_send
|
||||
|
||||
def initialize(*args)
|
||||
super
|
||||
|
||||
@payloads_to_send = []
|
||||
set_payloads_to_send
|
||||
end
|
||||
|
||||
def call
|
||||
execute_hook do |out|
|
||||
if needs_push?
|
||||
out << call_webservice
|
||||
else
|
||||
out << "#{skip_message}\n"
|
||||
logger.info skip_message
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def post_receive_url
|
||||
object
|
||||
end
|
||||
|
||||
def needs_push?
|
||||
return true if post_receive_url.mode == :post
|
||||
return false if payloads.empty?
|
||||
return true unless use_triggers?
|
||||
return false if post_receive_url.triggers.empty?
|
||||
|
||||
!payloads_to_send.empty?
|
||||
end
|
||||
|
||||
def start_message
|
||||
uri = URI post_receive_url.url
|
||||
if uri.password.present?
|
||||
uri.user = nil
|
||||
uri.password = nil
|
||||
"Notifying #{uri} (with base auth)"
|
||||
else
|
||||
"Notifying #{post_receive_url.url}"
|
||||
end
|
||||
end
|
||||
|
||||
def skip_message
|
||||
"This url doesn't need to be notified"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_payloads_to_send
|
||||
@payloads_to_send = if post_receive_url.mode == :post
|
||||
{}
|
||||
elsif use_triggers?
|
||||
extract_payloads
|
||||
else
|
||||
payloads
|
||||
end
|
||||
end
|
||||
|
||||
def extract_payloads
|
||||
new_payloads = []
|
||||
payloads.each do |payload|
|
||||
data = RedmineGitHosting::Utils::Git.parse_refspec(payload[:ref])
|
||||
new_payloads << payload if data[:type] == 'heads' && post_receive_url.triggers.include?(data[:name])
|
||||
end
|
||||
new_payloads
|
||||
end
|
||||
|
||||
def use_method
|
||||
post_receive_url.mode == :get ? :http_get : :http_post
|
||||
end
|
||||
|
||||
def use_triggers?
|
||||
post_receive_url.use_triggers?
|
||||
end
|
||||
|
||||
def split_payloads?
|
||||
post_receive_url.split_payloads?
|
||||
end
|
||||
|
||||
def call_webservice
|
||||
if use_method == :http_post && split_payloads?
|
||||
y = ''
|
||||
payloads_to_send.each do |payload|
|
||||
y << do_call_webservice(payload)
|
||||
end
|
||||
y
|
||||
else
|
||||
do_call_webservice payloads_to_send
|
||||
end
|
||||
end
|
||||
|
||||
def do_call_webservice(payload)
|
||||
post_failed, post_message = send(use_method, post_receive_url.url, { data: { payload: payload } })
|
||||
|
||||
if post_failed
|
||||
logger.error 'Failed!'
|
||||
logger.error post_message
|
||||
(split_payloads? ? failure_message.delete("\n") : failure_message)
|
||||
else
|
||||
log_hook_succeeded
|
||||
(split_payloads? ? success_message.delete("\n") : success_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,30 @@
|
|||
module RedmineHooks
|
||||
class FetchChangesets < Base
|
||||
def call
|
||||
repository.empty_cache!
|
||||
execute_hook do |out|
|
||||
out << fetch_changesets
|
||||
end
|
||||
end
|
||||
|
||||
def repository
|
||||
object
|
||||
end
|
||||
|
||||
def start_message
|
||||
"Fetching changesets for '#{repository.redmine_name}' repository"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fetch_changesets
|
||||
repository.fetch_changesets
|
||||
log_hook_succeeded
|
||||
success_message
|
||||
rescue ::Redmine::Scm::Adapters::CommandFailed => e
|
||||
log_hook_failed
|
||||
logger.error "Error during fetching changesets : #{e.message}"
|
||||
failure_message
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,138 @@
|
|||
require 'json'
|
||||
|
||||
module RedmineHooks
|
||||
class GithubIssuesSync < Base
|
||||
include HttpHelper
|
||||
|
||||
def call
|
||||
sync_with_github
|
||||
end
|
||||
|
||||
def project
|
||||
object
|
||||
end
|
||||
|
||||
def params
|
||||
payloads
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def github_issue
|
||||
GithubIssue.find_by_github_id params[:issue][:id]
|
||||
end
|
||||
|
||||
def redmine_issue
|
||||
Issue.find_by_subject params[:issue][:title]
|
||||
end
|
||||
|
||||
def sync_with_github
|
||||
create_relation = false
|
||||
|
||||
## We don't have stored relation
|
||||
if github_issue.nil?
|
||||
create_relation = true
|
||||
|
||||
## And we don't have issue in Redmine
|
||||
redmine_issue = if redmine_issue.nil?
|
||||
create_redmine_issue
|
||||
else
|
||||
## Create relation and update issue
|
||||
update_redmine_issue(redmine_issue)
|
||||
end
|
||||
else
|
||||
## We have one relation, update issue
|
||||
redmine_issue = update_redmine_issue(github_issue.issue)
|
||||
end
|
||||
|
||||
if create_relation
|
||||
github_issue = GithubIssue.new
|
||||
github_issue.github_id = params[:issue][:id]
|
||||
github_issue.issue_id = redmine_issue.id
|
||||
github_issue.save!
|
||||
end
|
||||
|
||||
if params.key?(:comment)
|
||||
issue_journal = GithubComment.find_by_github_id(params[:comment][:id])
|
||||
|
||||
if issue_journal.nil?
|
||||
issue_journal = create_issue_journal(github_issue.issue)
|
||||
|
||||
github_comment = GithubComment.new
|
||||
github_comment.github_id = params[:comment][:id]
|
||||
github_comment.journal_id = issue_journal.id
|
||||
github_comment.save!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_redmine_issue
|
||||
logger.info('Github Issues Sync : create new issue')
|
||||
|
||||
issue = project.issues.new
|
||||
issue.tracker_id = project.trackers.first.try(:id)
|
||||
issue.subject = params[:issue][:title].chomp[0, 255]
|
||||
issue.description = params[:issue][:body]
|
||||
issue.updated_on = params[:issue][:updated_at]
|
||||
issue.created_on = params[:issue][:created_at]
|
||||
|
||||
## Get user mail
|
||||
user = find_user(params[:issue][:user][:url])
|
||||
issue.author = user
|
||||
|
||||
issue.save!
|
||||
issue
|
||||
end
|
||||
|
||||
def create_issue_journal(issue)
|
||||
logger.info("Github Issues Sync : create new journal for issue '##{issue.id}'")
|
||||
|
||||
journal = Journal.new
|
||||
journal.journalized_id = issue.id
|
||||
journal.journalized_type = 'Issue'
|
||||
journal.notes = params[:comment][:body]
|
||||
journal.created_on = params[:comment][:created_at]
|
||||
|
||||
## Get user mail
|
||||
user = find_user(params[:comment][:user][:url])
|
||||
journal.user_id = user.id
|
||||
|
||||
journal.save!
|
||||
journal
|
||||
end
|
||||
|
||||
def update_redmine_issue(issue)
|
||||
logger.info("Github Issues Sync : update issue '##{issue.id}'")
|
||||
|
||||
issue.status_id = if params[:issue][:state] == 'closed'
|
||||
5
|
||||
else
|
||||
1
|
||||
end
|
||||
|
||||
issue.subject = params[:issue][:title].chomp[0, 255]
|
||||
issue.description = params[:issue][:body]
|
||||
issue.updated_on = params[:issue][:updated_at]
|
||||
|
||||
issue.save!
|
||||
issue
|
||||
end
|
||||
|
||||
def find_user(url)
|
||||
post_failed, user_data = http_get(url)
|
||||
user_data = JSON.parse(user_data)
|
||||
|
||||
user = User.find_by_mail(user_data['email'])
|
||||
|
||||
if user.nil?
|
||||
logger.info("Github Issues Sync : cannot find user '#{user_data['email']}' in Redmine, use anonymous")
|
||||
user = User.anonymous
|
||||
user.mail = user_data['email']
|
||||
user.firstname = user_data['name']
|
||||
user.lastname = user_data['login']
|
||||
end
|
||||
|
||||
user
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,11 @@
|
|||
module RedmineHooks
|
||||
module HttpHelper
|
||||
def http_post(url, opts = {})
|
||||
RedmineGitHosting::Utils::Http.http_post url, opts
|
||||
end
|
||||
|
||||
def http_get(url, opts = {})
|
||||
RedmineGitHosting::Utils::Http.http_get url, opts
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,63 @@
|
|||
module RedmineHooks
|
||||
class UpdateMirrors < Base
|
||||
def call
|
||||
execute_hook do |out|
|
||||
if needs_push?
|
||||
out << call_mirror
|
||||
else
|
||||
out << "#{skip_message}\n"
|
||||
logger.info(skip_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def mirror
|
||||
object
|
||||
end
|
||||
|
||||
# If we have an explicit refspec, check it against incoming payloads
|
||||
# Special case: if we do not pass in any payloads, return true
|
||||
def needs_push?
|
||||
return true if payloads.empty?
|
||||
return true if mirror.mirror_mode?
|
||||
|
||||
check_ref_spec
|
||||
end
|
||||
|
||||
def start_message
|
||||
"Pushing changes to #{mirror.url}"
|
||||
end
|
||||
|
||||
def skip_message
|
||||
"This mirror doesn't need to be updated"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_ref_spec
|
||||
refspec_parse = RedmineGitHosting::Validators.valid_git_refspec?(mirror.explicit_refspec)
|
||||
payloads.each do |payload|
|
||||
next unless splitpath = RedmineGitHosting::Utils::Git.parse_refspec(payload[:ref])
|
||||
|
||||
return true if payload[:ref] == refspec_parse[1] # Explicit Reference Spec complete path
|
||||
return true if splitpath[:name] == refspec_parse[1] # Explicit Reference Spec no type
|
||||
return true if mirror.include_all_branches? && splitpath[:type] == 'heads'
|
||||
return true if mirror.include_all_tags? && splitpath[:type] == 'tags'
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
def call_mirror
|
||||
push_failed, push_message = RepositoryMirrors::Push.call(mirror)
|
||||
|
||||
if push_failed
|
||||
log_hook_failed
|
||||
logger.error(push_message)
|
||||
failure_message
|
||||
else
|
||||
log_hook_succeeded
|
||||
success_message
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,59 @@
|
|||
module GitolitePublicKeys
|
||||
class GenerateIdentifier
|
||||
DEPLOY_PSEUDO_USER = 'deploy_key'.freeze
|
||||
|
||||
attr_reader :public_key, :user, :skip_auto_increment
|
||||
|
||||
def initialize(public_key, user, opts = {})
|
||||
@public_key = public_key
|
||||
@user = user
|
||||
@skip_auto_increment = opts.delete(:skip_auto_increment) { false }
|
||||
end
|
||||
|
||||
class << self
|
||||
def call(public_key, user, opts = {})
|
||||
new(public_key, user, opts).call
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the unique identifier for this key based on the key_type
|
||||
#
|
||||
# For user public keys, this simply is the user's gitolite_identifier.
|
||||
# For deployment keys, we use an incrementing number.
|
||||
#
|
||||
def call
|
||||
if public_key.user_key?
|
||||
set_identifier_for_user_key
|
||||
elsif public_key.deploy_key?
|
||||
set_identifier_for_deploy_key
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_identifier_for_user_key
|
||||
tag = public_key.title.gsub(/[^0-9a-zA-Z]/, '_')
|
||||
[user.gitolite_identifier, '@', 'redmine_', tag].join
|
||||
end
|
||||
|
||||
# Fix https://github.com/jbox-web/redmine_git_hosting/issues/288
|
||||
# Getting user deployment keys count is not sufficient to assure uniqueness of
|
||||
# deployment key identifier. So we need an 'external' counter to increment the global count
|
||||
# while a key with this identifier exists.
|
||||
#
|
||||
def set_identifier_for_deploy_key
|
||||
count = 0
|
||||
begin
|
||||
key_id = generate_deploy_key_identifier(count)
|
||||
count += 1
|
||||
end while user.gitolite_public_keys.deploy_key.map(&:owner).include?(key_id.split('@')[0])
|
||||
key_id
|
||||
end
|
||||
|
||||
def generate_deploy_key_identifier(count)
|
||||
key_count = 1 + count
|
||||
key_count += user.gitolite_public_keys.deploy_key.length unless skip_auto_increment
|
||||
[user.gitolite_identifier, '_', DEPLOY_PSEUDO_USER, '_', key_count, '@', 'redmine_', DEPLOY_PSEUDO_USER, '_', key_count].join
|
||||
end
|
||||
end
|
||||
end
|
22
plugins/redmine_git_hosting/app/use_cases/projects/base.rb
Normal file
22
plugins/redmine_git_hosting/app/use_cases/projects/base.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
module Projects
|
||||
class Base
|
||||
include RedmineGitHosting::GitoliteAccessor::Methods
|
||||
|
||||
attr_reader :project, :options
|
||||
|
||||
def initialize(project, opts = {})
|
||||
@project = project
|
||||
@options = opts
|
||||
end
|
||||
|
||||
class << self
|
||||
def call(project, opts = {})
|
||||
new(project, opts).call
|
||||
end
|
||||
end
|
||||
|
||||
def call
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
module Projects
|
||||
class CreateRepository < Base
|
||||
def call
|
||||
create_project_repository
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_project_repository
|
||||
# Create new repository
|
||||
repository = Repository.factory('Xitolite')
|
||||
repository.is_default = true
|
||||
repository.extra_info = {}
|
||||
repository.extra_info['extra_report_last_commit'] = '1'
|
||||
|
||||
# Save it to database
|
||||
project.repositories << repository
|
||||
|
||||
# Create it in Gitolite
|
||||
Repositories::Create.call(repository, creation_options)
|
||||
end
|
||||
|
||||
def creation_options
|
||||
{ create_readme_file: RedmineGitHosting::Config.init_repositories_on_create? }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
module Projects
|
||||
class ExecuteHooks
|
||||
attr_reader :project, :hook_type, :params
|
||||
|
||||
def initialize(project, hook_type, params = {})
|
||||
@project = project
|
||||
@hook_type = hook_type
|
||||
@params = params
|
||||
end
|
||||
|
||||
class << self
|
||||
def call(project, hook_type, params = {})
|
||||
new(project, hook_type, params).call
|
||||
end
|
||||
end
|
||||
|
||||
def call
|
||||
send("execute_#{hook_type}_hook")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def execute_github_hook
|
||||
RedmineHooks::GithubIssuesSync.call(project, params)
|
||||
end
|
||||
end
|
||||
end
|
24
plugins/redmine_git_hosting/app/use_cases/projects/update.rb
Normal file
24
plugins/redmine_git_hosting/app/use_cases/projects/update.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
module Projects
|
||||
class Update < Base
|
||||
def call
|
||||
# Adjust daemon status
|
||||
disable_git_daemon_if_not_public
|
||||
resync
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def disable_git_daemon_if_not_public
|
||||
# Go through all gitolite repos and disable Git daemon if necessary
|
||||
project.gitolite_repos.each do |repository|
|
||||
repository.extra[:git_daemon] = false if repository.git_daemon_enabled? && !project.is_public
|
||||
# Save GitExtra in all cases to trigger urls order consistency checks
|
||||
repository.extra.save
|
||||
end
|
||||
end
|
||||
|
||||
def resync
|
||||
gitolite_accessor.update_projects([project.id], options)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,29 @@
|
|||
module Repositories
|
||||
class Base
|
||||
include RedmineGitHosting::GitoliteAccessor::Methods
|
||||
|
||||
attr_reader :repository, :options, :project
|
||||
|
||||
def initialize(repository, opts = {})
|
||||
@repository = repository
|
||||
@options = opts
|
||||
@project = repository.project
|
||||
end
|
||||
|
||||
class << self
|
||||
def call(repository, opts = {})
|
||||
new(repository, opts).call
|
||||
end
|
||||
end
|
||||
|
||||
def call
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def logger
|
||||
RedmineGitHosting.logger
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,83 @@
|
|||
module Repositories
|
||||
class BuildPayload < Base
|
||||
def initialize(*args)
|
||||
super
|
||||
@payloads = []
|
||||
end
|
||||
|
||||
def call
|
||||
build_payloads
|
||||
end
|
||||
|
||||
def refs
|
||||
options
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Returns an array of GitHub post-receive hook style hashes
|
||||
# http://help.github.com/post-receive-hooks/
|
||||
#
|
||||
def build_payloads
|
||||
refs.each do |ref|
|
||||
# Get revisions range
|
||||
range = get_revisions_from_ref(ref)
|
||||
next if range.nil?
|
||||
|
||||
@payloads << build_payload(ref, range)
|
||||
end
|
||||
@payloads
|
||||
end
|
||||
|
||||
def get_revisions_from_ref(ref)
|
||||
oldhead, newhead, refname = ref.split ','
|
||||
|
||||
# Only pay attention to branch updates
|
||||
return nil if !refname.match(/refs\/heads\//)
|
||||
|
||||
# Get branch name
|
||||
branch_name = refname.gsub('refs/heads/', '')
|
||||
|
||||
if newhead.match(/\A0{40}\z/)
|
||||
# Deleting a branch
|
||||
logger.info("Deleting branch '#{branch_name}'")
|
||||
range = nil
|
||||
elsif oldhead.match(/\A0{40}\z/)
|
||||
# Creating a branch
|
||||
logger.info("Creating branch '#{branch_name}'")
|
||||
range = newhead
|
||||
else
|
||||
range = "#{oldhead}..#{newhead}"
|
||||
end
|
||||
|
||||
range
|
||||
end
|
||||
|
||||
def build_payload(ref, range)
|
||||
revisions_in_range = get_revisions_in_range(range)
|
||||
logger.debug("Revisions in range : #{revisions_in_range.join(' ')}")
|
||||
|
||||
# Get refs
|
||||
oldhead, newhead, refname = ref.split ','
|
||||
|
||||
# Build payload hash
|
||||
repository.github_payload
|
||||
.merge({ before: oldhead, after: newhead, ref: refname, commits: build_commits_list(revisions_in_range) })
|
||||
end
|
||||
|
||||
def build_commits_list(revisions_in_range)
|
||||
commits_list = []
|
||||
revisions_in_range.each do |rev|
|
||||
changeset = repository.find_changeset_by_name(rev)
|
||||
next if changeset.nil?
|
||||
|
||||
commits_list << changeset.github_payload
|
||||
end
|
||||
commits_list
|
||||
end
|
||||
|
||||
def get_revisions_in_range(range)
|
||||
repository.rev_list(range, ['--reverse'])
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,61 @@
|
|||
module Repositories
|
||||
class Create < Base
|
||||
def call
|
||||
set_repository_extra
|
||||
create_repository
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_repository_extra
|
||||
extra = repository.build_extra(default_extra_options)
|
||||
extra.save!
|
||||
end
|
||||
|
||||
def default_extra_options
|
||||
enable_git_annex? ? git_annex_repository_options : standard_repository_options
|
||||
end
|
||||
|
||||
def enable_git_annex?
|
||||
options[:enable_git_annex]
|
||||
end
|
||||
|
||||
def standard_repository_options
|
||||
{
|
||||
git_daemon: RedmineGitHosting::Config.gitolite_daemon_by_default?,
|
||||
git_notify: RedmineGitHosting::Config.gitolite_notify_by_default?,
|
||||
git_annex: false,
|
||||
default_branch: 'master',
|
||||
key: RedmineGitHosting::Utils::Crypto.generate_secret(64)
|
||||
}.merge(smart_http_options)
|
||||
end
|
||||
|
||||
def smart_http_options
|
||||
case RedmineGitHosting::Config.gitolite_http_by_default?
|
||||
when '1' # HTTPS only
|
||||
{ git_https: true }
|
||||
when '2' # HTTPS and HTTP
|
||||
{ git_http: true, git_https: true }
|
||||
when '3' # HTTP only
|
||||
{ git_http: true }
|
||||
else
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
def git_annex_repository_options
|
||||
{
|
||||
git_http: 0,
|
||||
git_daemon: false,
|
||||
git_notify: false,
|
||||
git_annex: true,
|
||||
default_branch: 'git-annex',
|
||||
key: RedmineGitHosting::Utils::Crypto.generate_secret(64)
|
||||
}
|
||||
end
|
||||
|
||||
def create_repository
|
||||
gitolite_accessor.create_repository(repository, options)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,78 @@
|
|||
module Repositories
|
||||
class DownloadRevision
|
||||
attr_reader :repository, :revision, :format, :gitolite_repository_path, :commit_id, :content_type, :filename
|
||||
|
||||
def initialize(repository, revision, format)
|
||||
@repository = repository
|
||||
@revision = revision
|
||||
@format = format
|
||||
@gitolite_repository_path = repository.gitolite_repository_path
|
||||
|
||||
@valid_commit = false
|
||||
@commit_id = nil
|
||||
@content_type = ''
|
||||
@filename = ''
|
||||
|
||||
validate_revision
|
||||
fill_data
|
||||
end
|
||||
|
||||
def content
|
||||
repository.archive(commit_id, format)
|
||||
end
|
||||
|
||||
def valid_commit?
|
||||
@valid_commit
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate_revision
|
||||
commit = nil
|
||||
|
||||
# is the revision a branch?
|
||||
repository.branches.each do |x|
|
||||
if x.to_s == revision
|
||||
commit = x.revision
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
# is the revision a tag?
|
||||
if commit.nil?
|
||||
repository.tags.each do |x|
|
||||
if x == revision
|
||||
commit = repository.rev_list(revision).first
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# well, let check if this is a valid commit
|
||||
commit = revision if commit.nil?
|
||||
commit = repository.rev_parse(commit)
|
||||
|
||||
if commit == ''
|
||||
@valid_commit = false
|
||||
else
|
||||
@valid_commit = true
|
||||
@commit_id = commit
|
||||
end
|
||||
end
|
||||
|
||||
def fill_data
|
||||
case format
|
||||
when 'tar.gz'
|
||||
extension = 'tar.gz'
|
||||
@content_type = 'application/x-gzip'
|
||||
when 'zip'
|
||||
extension = 'zip'
|
||||
@content_type = 'application/x-zip'
|
||||
else
|
||||
extension = 'tar'
|
||||
@content_type = 'application/x-tar'
|
||||
end
|
||||
@filename = "#{repository.redmine_name}-#{revision}.#{extension}"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,65 @@
|
|||
module Repositories
|
||||
class ExecuteHooks
|
||||
attr_reader :repository, :hook_type, :payloads
|
||||
|
||||
def initialize(repository, hook_type, payloads = {})
|
||||
@repository = repository
|
||||
@hook_type = hook_type
|
||||
@payloads = payloads
|
||||
end
|
||||
|
||||
class << self
|
||||
def call(repository, hook_type, payloads = {})
|
||||
new(repository, hook_type, payloads).call
|
||||
end
|
||||
end
|
||||
|
||||
def call
|
||||
send("execute_#{hook_type}_hook")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def logger
|
||||
RedmineGitHosting.logger
|
||||
end
|
||||
|
||||
def execute_fetch_changesets_hook
|
||||
RedmineHooks::FetchChangesets.call(repository)
|
||||
end
|
||||
|
||||
def execute_update_mirrors_hook
|
||||
message = 'Notifying mirrors about changes to this repository:'
|
||||
y = ''
|
||||
|
||||
## Post to each post-receive URL
|
||||
if repository.mirrors.active.any?
|
||||
logger.info(message)
|
||||
y << "\n#{message}\n"
|
||||
|
||||
repository.mirrors.active.each do |mirror|
|
||||
y << RedmineHooks::UpdateMirrors.call(mirror, payloads)
|
||||
end
|
||||
end
|
||||
|
||||
y
|
||||
end
|
||||
|
||||
def execute_call_webservices_hook
|
||||
message = 'Notifying post receive urls about changes to this repository:'
|
||||
y = ''
|
||||
|
||||
## Post to each post-receive URL
|
||||
if repository.post_receive_urls.active.any?
|
||||
logger.info(message)
|
||||
y << "\n#{message}\n"
|
||||
|
||||
repository.post_receive_urls.active.each do |post_receive_url|
|
||||
y << RedmineHooks::CallWebservices.call(post_receive_url, payloads)
|
||||
end
|
||||
end
|
||||
|
||||
y
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
module RepositoryMirrors
|
||||
class Base
|
||||
attr_reader :mirror, :repository
|
||||
|
||||
def initialize(mirror)
|
||||
@mirror = mirror
|
||||
@repository = mirror.repository
|
||||
end
|
||||
|
||||
class << self
|
||||
def call(mirror)
|
||||
new(mirror).call
|
||||
end
|
||||
end
|
||||
|
||||
def call
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
end
|
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