diff --git a/plugins/redmine_git_hosting/.github/workflows/brakeman.yml b/plugins/redmine_git_hosting/.github/workflows/brakeman.yml deleted file mode 100644 index ca17e38..0000000 --- a/plugins/redmine_git_hosting/.github/workflows/brakeman.yml +++ /dev/null @@ -1,35 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/.github/workflows/linters.yml b/plugins/redmine_git_hosting/.github/workflows/linters.yml deleted file mode 100644 index a616939..0000000 --- a/plugins/redmine_git_hosting/.github/workflows/linters.yml +++ /dev/null @@ -1,44 +0,0 @@ -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() diff --git a/plugins/redmine_git_hosting/.github/workflows/test.yml b/plugins/redmine_git_hosting/.github/workflows/test.yml deleted file mode 100644 index 84dfc74..0000000 --- a/plugins/redmine_git_hosting/.github/workflows/test.yml +++ /dev/null @@ -1,162 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/.gitignore b/plugins/redmine_git_hosting/.gitignore deleted file mode 100644 index e9bbcc2..0000000 --- a/plugins/redmine_git_hosting/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -.*.swp -Gemfile.lock -settings.yml -/tmp -/rdoc -/coverage -/junit -custom_hooks.rb -/ssh_keys/redmine_gitolite_admin_id_rsa* -.DS_Store -coverage/ diff --git a/plugins/redmine_git_hosting/.rubocop.yml b/plugins/redmine_git_hosting/.rubocop.yml deleted file mode 100644 index 66e7a3f..0000000 --- a/plugins/redmine_git_hosting/.rubocop.yml +++ /dev/null @@ -1,84 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/.rubocop_todo.yml b/plugins/redmine_git_hosting/.rubocop_todo.yml deleted file mode 100644 index 7aeb559..0000000 --- a/plugins/redmine_git_hosting/.rubocop_todo.yml +++ /dev/null @@ -1,968 +0,0 @@ -# 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 diff --git a/plugins/redmine_git_hosting/.slim-lint.yml b/plugins/redmine_git_hosting/.slim-lint.yml deleted file mode 100644 index 54689e6..0000000 --- a/plugins/redmine_git_hosting/.slim-lint.yml +++ /dev/null @@ -1,40 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/AUTHORS b/plugins/redmine_git_hosting/AUTHORS deleted file mode 100644 index 01eeaf2..0000000 --- a/plugins/redmine_git_hosting/AUTHORS +++ /dev/null @@ -1,66 +0,0 @@ -Aaron Fellin -Alexander Meindl -allen-t -Andrea Piccinelli -Boris Bera -bullshit -ciaranj -Clemens Hammacher -crocket -Daniel Dehennin -Daniel Stoeckel -danomatika -David Cramer -DFYX -Eric Bishop -Evgeny Generalov -Federico Ramallo -fjuan -Gartz -Geoffroy Desvernay -Greg Cymbalski -Greg Thornton -hboyet -IceArmy -Jan Schulz-Hofen -Jean-Sébastien Bour -John Axel Eriksson -John Kubiatowicz -Joshua Hogendorn -Kovalev Vladimir -Ludovic Schoepps -Lukas Mika -Marco Nenciarini -Mario Werner -Mathieu Marache -Matthew Meng -Matt Meng -nicesw123 -Nicholas Clark -Nicolas Rodriguez -Nils Rokita <0rokita@informatik.uni-hamburg.de> -Patrick Naubert -Patrick Roberts -Pedro Algarvio -Petter Uvesten -Philip Schiffer -Rocket Rentals -root -root -rposborne -Ryan Thompson -Sebastian Harl -Simon Peeters -Slotos -Soeren Helbig -Strnadj -takahashim -Thomas Debesse -Tom Kazimiers -U-catsby\oddpoet -Untoldwind -Warren Volz -wilsoc5 -Yarema -Yunsang Choi -Zsolt Parragi diff --git a/plugins/redmine_git_hosting/CHANGELOG.md b/plugins/redmine_git_hosting/CHANGELOG.md deleted file mode 100644 index 2db4886..0000000 --- a/plugins/redmine_git_hosting/CHANGELOG.md +++ /dev/null @@ -1,614 +0,0 @@ -# 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 # when triggers are enabled on PostReceiveUrls and pushing on a non-triggering branch -* Fix # 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 ```/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. diff --git a/plugins/redmine_git_hosting/Gemfile b/plugins/redmine_git_hosting/Gemfile deleted file mode 100644 index 7ae82ea..0000000 --- a/plugins/redmine_git_hosting/Gemfile +++ /dev/null @@ -1,56 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/LICENSE b/plugins/redmine_git_hosting/LICENSE deleted file mode 100644 index 72dc60d..0000000 --- a/plugins/redmine_git_hosting/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -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. diff --git a/plugins/redmine_git_hosting/README.md b/plugins/redmine_git_hosting/README.md deleted file mode 100644 index 9e4e8dc..0000000 --- a/plugins/redmine_git_hosting/README.md +++ /dev/null @@ -1,31 +0,0 @@ -## ![logo](https://raw.github.com/jbox-web/redmine_git_hosting/gh-pages/images/git_logo.png) Redmine Git Hosting Plugin - -[![GitHub license](https://img.shields.io/github/license/jbox-web/redmine_git_hosting.svg)](https://github.com/jbox-web/redmine_git_hosting/blob/devel/LICENSE) -[![GitHub release](https://img.shields.io/github/release/jbox-web/redmine_git_hosting.svg)](https://github.com/jbox-web/redmine_git_hosting/releases/latest) -[![Brakeman security tests](../../workflows/Run%20Brakeman/badge.svg)](../../actions?query=workflow%3A%22Run+Brakeman%22) -[![Coding standards](../../workflows/Run%20Linters/badge.svg)](../../actions?query=workflow%3A%22Run+Linters%22) -[![Tests](../../workflows/Test/badge.svg)](../../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 diff --git a/plugins/redmine_git_hosting/app/controllers/archived_repositories_controller.rb b/plugins/redmine_git_hosting/app/controllers/archived_repositories_controller.rb deleted file mode 100644 index f2539d1..0000000 --- a/plugins/redmine_git_hosting/app/controllers/archived_repositories_controller.rb +++ /dev/null @@ -1,17 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/controllers/concerns/xitolite_repository_finder.rb b/plugins/redmine_git_hosting/app/controllers/concerns/xitolite_repository_finder.rb deleted file mode 100644 index 2d65f2b..0000000 --- a/plugins/redmine_git_hosting/app/controllers/concerns/xitolite_repository_finder.rb +++ /dev/null @@ -1,29 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/controllers/download_git_revision_controller.rb b/plugins/redmine_git_hosting/app/controllers/download_git_revision_controller.rb deleted file mode 100644 index dcf6b0b..0000000 --- a/plugins/redmine_git_hosting/app/controllers/download_git_revision_controller.rb +++ /dev/null @@ -1,46 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/controllers/gitolite_public_keys_controller.rb b/plugins/redmine_git_hosting/app/controllers/gitolite_public_keys_controller.rb deleted file mode 100644 index a1a446c..0000000 --- a/plugins/redmine_git_hosting/app/controllers/gitolite_public_keys_controller.rb +++ /dev/null @@ -1,88 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/controllers/go_redirector_controller.rb b/plugins/redmine_git_hosting/app/controllers/go_redirector_controller.rb deleted file mode 100644 index d9a6ab3..0000000 --- a/plugins/redmine_git_hosting/app/controllers/go_redirector_controller.rb +++ /dev/null @@ -1,10 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/controllers/redmine_git_hosting_controller.rb b/plugins/redmine_git_hosting/app/controllers/redmine_git_hosting_controller.rb deleted file mode 100644 index 7cb1e47..0000000 --- a/plugins/redmine_git_hosting/app/controllers/redmine_git_hosting_controller.rb +++ /dev/null @@ -1,72 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/controllers/repository_deployment_credentials_controller.rb b/plugins/redmine_git_hosting/app/controllers/repository_deployment_credentials_controller.rb deleted file mode 100644 index e3f0185..0000000 --- a/plugins/redmine_git_hosting/app/controllers/repository_deployment_credentials_controller.rb +++ /dev/null @@ -1,124 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/controllers/repository_git_config_keys_controller.rb b/plugins/redmine_git_hosting/app/controllers/repository_git_config_keys_controller.rb deleted file mode 100644 index 87de8ee..0000000 --- a/plugins/redmine_git_hosting/app/controllers/repository_git_config_keys_controller.rb +++ /dev/null @@ -1,73 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/controllers/repository_git_extras_controller.rb b/plugins/redmine_git_hosting/app/controllers/repository_git_extras_controller.rb deleted file mode 100644 index aab2280..0000000 --- a/plugins/redmine_git_hosting/app/controllers/repository_git_extras_controller.rb +++ /dev/null @@ -1,46 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/controllers/repository_mirrors_controller.rb b/plugins/redmine_git_hosting/app/controllers/repository_mirrors_controller.rb deleted file mode 100644 index 4159b8e..0000000 --- a/plugins/redmine_git_hosting/app/controllers/repository_mirrors_controller.rb +++ /dev/null @@ -1,66 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/controllers/repository_post_receive_urls_controller.rb b/plugins/redmine_git_hosting/app/controllers/repository_post_receive_urls_controller.rb deleted file mode 100644 index fb0689c..0000000 --- a/plugins/redmine_git_hosting/app/controllers/repository_post_receive_urls_controller.rb +++ /dev/null @@ -1,52 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/controllers/repository_protected_branches_controller.rb b/plugins/redmine_git_hosting/app/controllers/repository_protected_branches_controller.rb deleted file mode 100644 index 58bb2e6..0000000 --- a/plugins/redmine_git_hosting/app/controllers/repository_protected_branches_controller.rb +++ /dev/null @@ -1,80 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/forms/base_form.rb b/plugins/redmine_git_hosting/app/forms/base_form.rb deleted file mode 100644 index 34e1725..0000000 --- a/plugins/redmine_git_hosting/app/forms/base_form.rb +++ /dev/null @@ -1,26 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/forms/move_repository_form.rb b/plugins/redmine_git_hosting/app/forms/move_repository_form.rb deleted file mode 100644 index 7196dd1..0000000 --- a/plugins/redmine_git_hosting/app/forms/move_repository_form.rb +++ /dev/null @@ -1,39 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/forms/plugin_settings_form.rb b/plugins/redmine_git_hosting/app/forms/plugin_settings_form.rb deleted file mode 100644 index 9595bcb..0000000 --- a/plugins/redmine_git_hosting/app/forms/plugin_settings_form.rb +++ /dev/null @@ -1,59 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/cache_config.rb b/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/cache_config.rb deleted file mode 100644 index 3fc235c..0000000 --- a/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/cache_config.rb +++ /dev/null @@ -1,18 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/gitolite_access_config.rb b/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/gitolite_access_config.rb deleted file mode 100644 index e9b184c..0000000 --- a/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/gitolite_access_config.rb +++ /dev/null @@ -1,37 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/gitolite_config.rb b/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/gitolite_config.rb deleted file mode 100644 index 9d444a3..0000000 --- a/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/gitolite_config.rb +++ /dev/null @@ -1,61 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/hooks_config.rb b/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/hooks_config.rb deleted file mode 100644 index 4ebd1bb..0000000 --- a/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/hooks_config.rb +++ /dev/null @@ -1,22 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/mailing_list_config.rb b/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/mailing_list_config.rb deleted file mode 100644 index a0cef81..0000000 --- a/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/mailing_list_config.rb +++ /dev/null @@ -1,34 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/redmine_config.rb b/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/redmine_config.rb deleted file mode 100644 index a3b3dce..0000000 --- a/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/redmine_config.rb +++ /dev/null @@ -1,55 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/ssh_config.rb b/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/ssh_config.rb deleted file mode 100644 index 79c1d9e..0000000 --- a/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/ssh_config.rb +++ /dev/null @@ -1,33 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/storage_config.rb b/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/storage_config.rb deleted file mode 100644 index 15befef..0000000 --- a/plugins/redmine_git_hosting/app/forms/plugin_settings_validation/storage_config.rb +++ /dev/null @@ -1,26 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/helpers/extend_projects_helper.rb b/plugins/redmine_git_hosting/app/helpers/extend_projects_helper.rb deleted file mode 100644 index 1f7625e..0000000 --- a/plugins/redmine_git_hosting/app/helpers/extend_projects_helper.rb +++ /dev/null @@ -1,81 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/helpers/extend_repositories_helper.rb b/plugins/redmine_git_hosting/app/helpers/extend_repositories_helper.rb deleted file mode 100644 index c14159a..0000000 --- a/plugins/redmine_git_hosting/app/helpers/extend_repositories_helper.rb +++ /dev/null @@ -1,68 +0,0 @@ -module ExtendRepositoriesHelper - def encoding_field(form, _repository) - tag.p do - form.select( - :path_encoding, [nil] + Setting::ENCODINGS, - label: l(:field_scm_path_encoding) - ) + '
'.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 diff --git a/plugins/redmine_git_hosting/app/helpers/git_hosting_helper.rb b/plugins/redmine_git_hosting/app/helpers/git_hosting_helper.rb deleted file mode 100644 index fad102d..0000000 --- a/plugins/redmine_git_hosting/app/helpers/git_hosting_helper.rb +++ /dev/null @@ -1,31 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/helpers/git_hosting_users_helper.rb b/plugins/redmine_git_hosting/app/helpers/git_hosting_users_helper.rb deleted file mode 100644 index aa0b09b..0000000 --- a/plugins/redmine_git_hosting/app/helpers/git_hosting_users_helper.rb +++ /dev/null @@ -1,28 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/helpers/gitolite_plugin_settings_helper.rb b/plugins/redmine_git_hosting/app/helpers/gitolite_plugin_settings_helper.rb deleted file mode 100644 index 461de80..0000000 --- a/plugins/redmine_git_hosting/app/helpers/gitolite_plugin_settings_helper.rb +++ /dev/null @@ -1,128 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/helpers/gitolite_public_keys_helper.rb b/plugins/redmine_git_hosting/app/helpers/gitolite_public_keys_helper.rb deleted file mode 100644 index e38e483..0000000 --- a/plugins/redmine_git_hosting/app/helpers/gitolite_public_keys_helper.rb +++ /dev/null @@ -1,14 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/helpers/repository_deployment_credentials_helper.rb b/plugins/redmine_git_hosting/app/helpers/repository_deployment_credentials_helper.rb deleted file mode 100644 index 3a0262e..0000000 --- a/plugins/redmine_git_hosting/app/helpers/repository_deployment_credentials_helper.rb +++ /dev/null @@ -1,17 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/helpers/repository_git_config_keys_helper.rb b/plugins/redmine_git_hosting/app/helpers/repository_git_config_keys_helper.rb deleted file mode 100644 index 54e059d..0000000 --- a/plugins/redmine_git_hosting/app/helpers/repository_git_config_keys_helper.rb +++ /dev/null @@ -1,8 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/helpers/repository_mirrors_helper.rb b/plugins/redmine_git_hosting/app/helpers/repository_mirrors_helper.rb deleted file mode 100644 index 4a01be2..0000000 --- a/plugins/redmine_git_hosting/app/helpers/repository_mirrors_helper.rb +++ /dev/null @@ -1,43 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/helpers/repository_post_receive_urls_helper.rb b/plugins/redmine_git_hosting/app/helpers/repository_post_receive_urls_helper.rb deleted file mode 100644 index c90f0f7..0000000 --- a/plugins/redmine_git_hosting/app/helpers/repository_post_receive_urls_helper.rb +++ /dev/null @@ -1,13 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/models/concerns/gitolitable.rb b/plugins/redmine_git_hosting/app/models/concerns/gitolitable.rb deleted file mode 100644 index c715676..0000000 --- a/plugins/redmine_git_hosting/app/models/concerns/gitolitable.rb +++ /dev/null @@ -1,13 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/authorizations.rb b/plugins/redmine_git_hosting/app/models/concerns/gitolitable/authorizations.rb deleted file mode 100644 index fe2ef2b..0000000 --- a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/authorizations.rb +++ /dev/null @@ -1,73 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/cache.rb b/plugins/redmine_git_hosting/app/models/concerns/gitolitable/cache.rb deleted file mode 100644 index b07320c..0000000 --- a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/cache.rb +++ /dev/null @@ -1,83 +0,0 @@ -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 /// and return the specified - # repository. If either 'repo_ident_unique?' is true or the is a project - # identifier, just return the last component. Otherwise, - # use the immediate parent () 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 : - # - # - # - 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: / - # - 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 diff --git a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/config.rb b/plugins/redmine_git_hosting/app/models/concerns/gitolitable/config.rb deleted file mode 100644 index 43bec74..0000000 --- a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/config.rb +++ /dev/null @@ -1,78 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/features.rb b/plugins/redmine_git_hosting/app/models/concerns/gitolitable/features.rb deleted file mode 100644 index 79b5d9b..0000000 --- a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/features.rb +++ /dev/null @@ -1,79 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/notifications.rb b/plugins/redmine_git_hosting/app/models/concerns/gitolitable/notifications.rb deleted file mode 100644 index 6d07c44..0000000 --- a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/notifications.rb +++ /dev/null @@ -1,29 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/paths.rb b/plugins/redmine_git_hosting/app/models/concerns/gitolitable/paths.rb deleted file mode 100644 index df85dc2..0000000 --- a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/paths.rb +++ /dev/null @@ -1,90 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/permissions.rb b/plugins/redmine_git_hosting/app/models/concerns/gitolitable/permissions.rb deleted file mode 100644 index fcd8996..0000000 --- a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/permissions.rb +++ /dev/null @@ -1,60 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/urls.rb b/plugins/redmine_git_hosting/app/models/concerns/gitolitable/urls.rb deleted file mode 100644 index 01daa31..0000000 --- a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/urls.rb +++ /dev/null @@ -1,114 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/users.rb b/plugins/redmine_git_hosting/app/models/concerns/gitolitable/users.rb deleted file mode 100644 index 00efdc9..0000000 --- a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/users.rb +++ /dev/null @@ -1,95 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/validations.rb b/plugins/redmine_git_hosting/app/models/concerns/gitolitable/validations.rb deleted file mode 100644 index cd54780..0000000 --- a/plugins/redmine_git_hosting/app/models/concerns/gitolitable/validations.rb +++ /dev/null @@ -1,113 +0,0 @@ -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 : - # => 1 - # => 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 diff --git a/plugins/redmine_git_hosting/app/models/git_cache.rb b/plugins/redmine_git_hosting/app/models/git_cache.rb deleted file mode 100644 index f796d25..0000000 --- a/plugins/redmine_git_hosting/app/models/git_cache.rb +++ /dev/null @@ -1,21 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/models/github_comment.rb b/plugins/redmine_git_hosting/app/models/github_comment.rb deleted file mode 100644 index 8453f88..0000000 --- a/plugins/redmine_git_hosting/app/models/github_comment.rb +++ /dev/null @@ -1,8 +0,0 @@ -class GithubComment < ActiveRecord::Base - ## Relations - belongs_to :journal - - ## Validations - validates :github_id, presence: true - validates :journal_id, presence: true, uniqueness: { scope: :github_id } -end diff --git a/plugins/redmine_git_hosting/app/models/github_issue.rb b/plugins/redmine_git_hosting/app/models/github_issue.rb deleted file mode 100644 index a3b0482..0000000 --- a/plugins/redmine_git_hosting/app/models/github_issue.rb +++ /dev/null @@ -1,8 +0,0 @@ -class GithubIssue < ActiveRecord::Base - ## Relations - belongs_to :issue - - ## Validations - validates :github_id, presence: true - validates :issue_id, presence: true, uniqueness: { scope: :github_id } -end diff --git a/plugins/redmine_git_hosting/app/models/gitolite_public_key.rb b/plugins/redmine_git_hosting/app/models/gitolite_public_key.rb deleted file mode 100644 index 14a3763..0000000 --- a/plugins/redmine_git_hosting/app/models/gitolite_public_key.rb +++ /dev/null @@ -1,203 +0,0 @@ -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 //.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 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 diff --git a/plugins/redmine_git_hosting/app/models/protected_branches_member.rb b/plugins/redmine_git_hosting/app/models/protected_branches_member.rb deleted file mode 100644 index 02d8d8e..0000000 --- a/plugins/redmine_git_hosting/app/models/protected_branches_member.rb +++ /dev/null @@ -1,24 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/models/repository/xitolite.rb b/plugins/redmine_git_hosting/app/models/repository/xitolite.rb deleted file mode 100644 index a627100..0000000 --- a/plugins/redmine_git_hosting/app/models/repository/xitolite.rb +++ /dev/null @@ -1,74 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/models/repository_deployment_credential.rb b/plugins/redmine_git_hosting/app/models/repository_deployment_credential.rb deleted file mode 100644 index fe4bee0..0000000 --- a/plugins/redmine_git_hosting/app/models/repository_deployment_credential.rb +++ /dev/null @@ -1,56 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/models/repository_git_config_key.rb b/plugins/redmine_git_hosting/app/models/repository_git_config_key.rb deleted file mode 100644 index b97c3c7..0000000 --- a/plugins/redmine_git_hosting/app/models/repository_git_config_key.rb +++ /dev/null @@ -1,42 +0,0 @@ -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 : _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 diff --git a/plugins/redmine_git_hosting/app/models/repository_git_config_key/git_config.rb b/plugins/redmine_git_hosting/app/models/repository_git_config_key/git_config.rb deleted file mode 100644 index e75ad9d..0000000 --- a/plugins/redmine_git_hosting/app/models/repository_git_config_key/git_config.rb +++ /dev/null @@ -1,7 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/models/repository_git_config_key/option.rb b/plugins/redmine_git_hosting/app/models/repository_git_config_key/option.rb deleted file mode 100644 index bfb1c40..0000000 --- a/plugins/redmine_git_hosting/app/models/repository_git_config_key/option.rb +++ /dev/null @@ -1,4 +0,0 @@ -class RepositoryGitConfigKey::Option < RepositoryGitConfigKey - validates :key, presence: true, - uniqueness: { case_sensitive: false, scope: %i[type repository_id] } -end diff --git a/plugins/redmine_git_hosting/app/models/repository_git_extra.rb b/plugins/redmine_git_hosting/app/models/repository_git_extra.rb deleted file mode 100644 index 0d68fa5..0000000 --- a/plugins/redmine_git_hosting/app/models/repository_git_extra.rb +++ /dev/null @@ -1,115 +0,0 @@ -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 : _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 diff --git a/plugins/redmine_git_hosting/app/models/repository_mirror.rb b/plugins/redmine_git_hosting/app/models/repository_mirror.rb deleted file mode 100644 index 5236ad0..0000000 --- a/plugins/redmine_git_hosting/app/models/repository_mirror.rb +++ /dev/null @@ -1,107 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/models/repository_post_receive_url.rb b/plugins/redmine_git_hosting/app/models/repository_post_receive_url.rb deleted file mode 100644 index 04384be..0000000 --- a/plugins/redmine_git_hosting/app/models/repository_post_receive_url.rb +++ /dev/null @@ -1,61 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/models/repository_protected_branche.rb b/plugins/redmine_git_hosting/app/models/repository_protected_branche.rb deleted file mode 100644 index 19db961..0000000 --- a/plugins/redmine_git_hosting/app/models/repository_protected_branche.rb +++ /dev/null @@ -1,48 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/overrides/repositories/navigation.rb b/plugins/redmine_git_hosting/app/overrides/repositories/navigation.rb deleted file mode 100644 index 94382fc..0000000 --- a/plugins/redmine_git_hosting/app/overrides/repositories/navigation.rb +++ /dev/null @@ -1,5 +0,0 @@ -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) %>' diff --git a/plugins/redmine_git_hosting/app/overrides/repositories/show.rb b/plugins/redmine_git_hosting/app/overrides/repositories/show.rb deleted file mode 100644 index 5855dbf..0000000 --- a/plugins/redmine_git_hosting/app/overrides/repositories/show.rb +++ /dev/null @@ -1,11 +0,0 @@ -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' diff --git a/plugins/redmine_git_hosting/app/presenters/repository_presenter.rb b/plugins/redmine_git_hosting/app/presenters/repository_presenter.rb deleted file mode 100644 index b8a6e91..0000000 --- a/plugins/redmine_git_hosting/app/presenters/repository_presenter.rb +++ /dev/null @@ -1,77 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/reports/report_base.rb b/plugins/redmine_git_hosting/app/reports/report_base.rb deleted file mode 100644 index 41c0ef1..0000000 --- a/plugins/redmine_git_hosting/app/reports/report_base.rb +++ /dev/null @@ -1,11 +0,0 @@ -class ReportBase - include Redmine::I18n - include ReportHelper - include ReportQuery - - attr_reader :repository - - def initialize(repository) - @repository = repository - end -end diff --git a/plugins/redmine_git_hosting/app/reports/report_helper.rb b/plugins/redmine_git_hosting/app/reports/report_helper.rb deleted file mode 100644 index 0e0cb5e..0000000 --- a/plugins/redmine_git_hosting/app/reports/report_helper.rb +++ /dev/null @@ -1,44 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/reports/report_query.rb b/plugins/redmine_git_hosting/app/reports/report_query.rb deleted file mode 100644 index 85599d7..0000000 --- a/plugins/redmine_git_hosting/app/reports/report_query.rb +++ /dev/null @@ -1,47 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/reports/repository_commits_stats.rb b/plugins/redmine_git_hosting/app/reports/repository_commits_stats.rb deleted file mode 100644 index b104c67..0000000 --- a/plugins/redmine_git_hosting/app/reports/repository_commits_stats.rb +++ /dev/null @@ -1,91 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/reports/repository_contributors_stats.rb b/plugins/redmine_git_hosting/app/reports/repository_contributors_stats.rb deleted file mode 100644 index e92613b..0000000 --- a/plugins/redmine_git_hosting/app/reports/repository_contributors_stats.rb +++ /dev/null @@ -1,105 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/reports/repository_global_stats.rb b/plugins/redmine_git_hosting/app/reports/repository_global_stats.rb deleted file mode 100644 index 595b1b3..0000000 --- a/plugins/redmine_git_hosting/app/reports/repository_global_stats.rb +++ /dev/null @@ -1,43 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/services/permissions_builder/base.rb b/plugins/redmine_git_hosting/app/services/permissions_builder/base.rb deleted file mode 100644 index 37b9830..0000000 --- a/plugins/redmine_git_hosting/app/services/permissions_builder/base.rb +++ /dev/null @@ -1,27 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/services/permissions_builder/protected_branches.rb b/plugins/redmine_git_hosting/app/services/permissions_builder/protected_branches.rb deleted file mode 100644 index ff323c3..0000000 --- a/plugins/redmine_git_hosting/app/services/permissions_builder/protected_branches.rb +++ /dev/null @@ -1,24 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/services/permissions_builder/standard.rb b/plugins/redmine_git_hosting/app/services/permissions_builder/standard.rb deleted file mode 100644 index 1f5daae..0000000 --- a/plugins/redmine_git_hosting/app/services/permissions_builder/standard.rb +++ /dev/null @@ -1,60 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/services/redmine_hooks/base.rb b/plugins/redmine_git_hosting/app/services/redmine_hooks/base.rb deleted file mode 100644 index b9ad486..0000000 --- a/plugins/redmine_git_hosting/app/services/redmine_hooks/base.rb +++ /dev/null @@ -1,54 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/services/redmine_hooks/call_webservices.rb b/plugins/redmine_git_hosting/app/services/redmine_hooks/call_webservices.rb deleted file mode 100644 index cba0880..0000000 --- a/plugins/redmine_git_hosting/app/services/redmine_hooks/call_webservices.rb +++ /dev/null @@ -1,111 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/services/redmine_hooks/fetch_changesets.rb b/plugins/redmine_git_hosting/app/services/redmine_hooks/fetch_changesets.rb deleted file mode 100644 index ca9454e..0000000 --- a/plugins/redmine_git_hosting/app/services/redmine_hooks/fetch_changesets.rb +++ /dev/null @@ -1,30 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/services/redmine_hooks/github_issues_sync.rb b/plugins/redmine_git_hosting/app/services/redmine_hooks/github_issues_sync.rb deleted file mode 100644 index 38d63de..0000000 --- a/plugins/redmine_git_hosting/app/services/redmine_hooks/github_issues_sync.rb +++ /dev/null @@ -1,138 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/services/redmine_hooks/http_helper.rb b/plugins/redmine_git_hosting/app/services/redmine_hooks/http_helper.rb deleted file mode 100644 index 68bb023..0000000 --- a/plugins/redmine_git_hosting/app/services/redmine_hooks/http_helper.rb +++ /dev/null @@ -1,11 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/services/redmine_hooks/update_mirrors.rb b/plugins/redmine_git_hosting/app/services/redmine_hooks/update_mirrors.rb deleted file mode 100644 index 64a1591..0000000 --- a/plugins/redmine_git_hosting/app/services/redmine_hooks/update_mirrors.rb +++ /dev/null @@ -1,63 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/use_cases/gitolite_public_keys/generate_identifier.rb b/plugins/redmine_git_hosting/app/use_cases/gitolite_public_keys/generate_identifier.rb deleted file mode 100644 index d905be6..0000000 --- a/plugins/redmine_git_hosting/app/use_cases/gitolite_public_keys/generate_identifier.rb +++ /dev/null @@ -1,59 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/use_cases/projects/base.rb b/plugins/redmine_git_hosting/app/use_cases/projects/base.rb deleted file mode 100644 index d8b502d..0000000 --- a/plugins/redmine_git_hosting/app/use_cases/projects/base.rb +++ /dev/null @@ -1,22 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/use_cases/projects/create_repository.rb b/plugins/redmine_git_hosting/app/use_cases/projects/create_repository.rb deleted file mode 100644 index 009b68e..0000000 --- a/plugins/redmine_git_hosting/app/use_cases/projects/create_repository.rb +++ /dev/null @@ -1,27 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/use_cases/projects/execute_hooks.rb b/plugins/redmine_git_hosting/app/use_cases/projects/execute_hooks.rb deleted file mode 100644 index adcb3d5..0000000 --- a/plugins/redmine_git_hosting/app/use_cases/projects/execute_hooks.rb +++ /dev/null @@ -1,27 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/use_cases/projects/update.rb b/plugins/redmine_git_hosting/app/use_cases/projects/update.rb deleted file mode 100644 index 1d30a23..0000000 --- a/plugins/redmine_git_hosting/app/use_cases/projects/update.rb +++ /dev/null @@ -1,24 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/use_cases/repositories/base.rb b/plugins/redmine_git_hosting/app/use_cases/repositories/base.rb deleted file mode 100644 index bca556a..0000000 --- a/plugins/redmine_git_hosting/app/use_cases/repositories/base.rb +++ /dev/null @@ -1,29 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/use_cases/repositories/build_payload.rb b/plugins/redmine_git_hosting/app/use_cases/repositories/build_payload.rb deleted file mode 100644 index c0e9022..0000000 --- a/plugins/redmine_git_hosting/app/use_cases/repositories/build_payload.rb +++ /dev/null @@ -1,83 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/use_cases/repositories/create.rb b/plugins/redmine_git_hosting/app/use_cases/repositories/create.rb deleted file mode 100644 index 7ffb8b7..0000000 --- a/plugins/redmine_git_hosting/app/use_cases/repositories/create.rb +++ /dev/null @@ -1,61 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/use_cases/repositories/download_revision.rb b/plugins/redmine_git_hosting/app/use_cases/repositories/download_revision.rb deleted file mode 100644 index 3df9928..0000000 --- a/plugins/redmine_git_hosting/app/use_cases/repositories/download_revision.rb +++ /dev/null @@ -1,78 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/use_cases/repositories/execute_hooks.rb b/plugins/redmine_git_hosting/app/use_cases/repositories/execute_hooks.rb deleted file mode 100644 index 15d1df5..0000000 --- a/plugins/redmine_git_hosting/app/use_cases/repositories/execute_hooks.rb +++ /dev/null @@ -1,65 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/use_cases/repository_mirrors/base.rb b/plugins/redmine_git_hosting/app/use_cases/repository_mirrors/base.rb deleted file mode 100644 index d7fcaa9..0000000 --- a/plugins/redmine_git_hosting/app/use_cases/repository_mirrors/base.rb +++ /dev/null @@ -1,20 +0,0 @@ -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 diff --git a/plugins/redmine_git_hosting/app/use_cases/repository_mirrors/push.rb b/plugins/redmine_git_hosting/app/use_cases/repository_mirrors/push.rb deleted file mode 100644 index eb14e0f..0000000 --- a/plugins/redmine_git_hosting/app/use_cases/repository_mirrors/push.rb +++ /dev/null @@ -1,46 +0,0 @@ -module RepositoryMirrors - class Push < Base - def call - push! - end - - def push! - begin - push_message = repository.mirror_push(*command) - push_failed = false - rescue RedmineGitHosting::Error::GitoliteCommandException => e - push_message = e.output - push_failed = true - end - - return push_failed, push_message - end - - def command - [mirror.url, branch, push_args] - end - - private - - def push_args - mirror.mirror_mode? ? ['--mirror'] : mirror_args - end - - def mirror_args - push_args = [] - push_args << '--force' if mirror.force_mode? - push_args << '--all' if mirror.include_all_branches? - push_args << '--tags' if mirror.include_all_tags? - push_args - end - - def branch - "#{dequote(mirror.explicit_refspec)}" unless mirror.explicit_refspec.blank? - end - - # Put backquote in front of crucial characters - def dequote(in_string) - in_string.gsub(/[$,"\\\n]/) { |x| "\\" + x } - end - end -end diff --git a/plugins/redmine_git_hosting/app/use_cases/repository_protected_branches/member_manager.rb b/plugins/redmine_git_hosting/app/use_cases/repository_protected_branches/member_manager.rb deleted file mode 100644 index 5939b3a..0000000 --- a/plugins/redmine_git_hosting/app/use_cases/repository_protected_branches/member_manager.rb +++ /dev/null @@ -1,79 +0,0 @@ -module RepositoryProtectedBranches - class MemberManager - attr_reader :protected_branch - - def initialize(protected_branch) - @protected_branch = protected_branch - end - - def current_user_ids - protected_branch.users.map(&:id) - end - - def current_group_ids - protected_branch.groups.map(&:id) - end - - def current_members - protected_branch.protected_branches_members - end - - def users_by_group_id(id) - current_members.select { |pbm| pbm.principal.class.name == 'User' && pbm.inherited_by == id }.map(&:principal) - end - - def add_users(ids) - create_user_member(ids, current_user_ids) - end - - def add_groups(ids) - create_group_member(ids, current_group_ids) do |group| - ids = group.users.map(&:id) - current_ids = users_by_group_id(group.id).map(&:id) - create_user_member(ids, current_ids, inherited_by: group.id, destroy: false) - end - end - - def create_user_member(ids, current_ids, opts = {}, &block) - create_member(ids, current_ids, 'User', opts, &block) - end - - def create_group_member(ids, current_ids, opts = {}, &block) - create_member(ids, current_ids, 'Group', opts, &block) - end - - def add_user_from_group(user, group_id) - ids = users_by_group_id(group_id).push(user).map(&:id) - current_ids = users_by_group_id(group_id).map(&:id) - create_user_member(ids, current_ids, inherited_by: group_id, destroy: false) - end - - def remove_user_from_group(user, group_id) - return unless users_by_group_id(group_id).include?(user) - - member = current_members.find_by_protected_branch_id_and_principal_id_and_inherited_by(protected_branch.id, user.id, group_id) - member&.destroy! - end - - def create_member(ids, current_ids, klass, opts = {}, &block) - destroy = opts.fetch(:destroy, true) - inherited_by = opts.fetch(:inherited_by, nil) - - ids = (ids || []).collect(&:to_i) - [0] - new_ids = ids - current_ids - - new_ids.each do |id| - object = klass.constantize.find_by_id(id) - next if object.nil? - - current_members.create(principal_id: object.id, inherited_by: inherited_by) - yield object if block_given? - end - - if destroy - member_to_destroy = current_members.select { |m| m.principal.class.name == klass && !ids.include?(m.principal.id) } - member_to_destroy.each(&:destroy) if member_to_destroy.any? - end - end - end -end diff --git a/plugins/redmine_git_hosting/app/use_cases/settings/apply.rb b/plugins/redmine_git_hosting/app/use_cases/settings/apply.rb deleted file mode 100644 index 1a3d534..0000000 --- a/plugins/redmine_git_hosting/app/use_cases/settings/apply.rb +++ /dev/null @@ -1,149 +0,0 @@ -module Settings - class Apply - include RedmineGitHosting::GitoliteAccessor::Methods - - attr_reader :previous_settings, :resync_projects, :resync_ssh_keys, :regenerate_ssh_keys, :flush_cache, :delete_trash_repo - - def initialize(previous_settings, opts = {}) - @previous_settings = previous_settings - @resync_projects = opts.delete(:resync_all_projects) { false } - @resync_ssh_keys = opts.delete(:resync_all_ssh_keys) { false } - @regenerate_ssh_keys = opts.delete(:regenerate_all_ssh_keys) { false } - @flush_cache = opts.delete(:flush_gitolite_cache) { false } - @delete_trash_repo = opts.delete(:delete_trash_repo) { [] } - end - - class << self - def call(previous_settings, opts = {}) - new(previous_settings, opts).call - end - end - - def call - gitolite_accessor.flush_settings_cache - apply_settings - end - - private - - def apply_settings - check_gitolite_location - check_repo_hierarchy - check_gitolite_config - check_gitolite_default_values - check_hook_config - check_cache_config - - do_resync_projects - do_resync_ssh_keys - do_regenerate_ssh_keys - do_flush_cache - do_delete_trash_repo - do_add_redmine_rw_access - end - - def current_setting(setting) - Setting.plugin_redmine_git_hosting[setting] - end - - def value_has_changed?(setting) - previous_settings[setting] != current_setting(setting) - end - - def check_gitolite_location - ## Gitolite location has changed. Remove temp directory, it will be recloned. - if value_has_changed?(:gitolite_server_host) || - value_has_changed?(:gitolite_server_port) || - value_has_changed?(:gitolite_user) || - value_has_changed?(:gitolite_temp_dir) - - RedmineGitHosting.logger.info("Temp dir has changed, remove the previous one : '#{previous_settings[:gitolite_temp_dir]}'") - FileUtils.rm_rf previous_settings[:gitolite_temp_dir] - end - end - - def check_repo_hierarchy - ## Storage infos has changed, move repositories! - if value_has_changed?(:gitolite_global_storage_dir) || - value_has_changed?(:gitolite_redmine_storage_dir) || - value_has_changed?(:hierarchical_organisation) - - # Need to update everyone! - # We take all root projects (even those who are closed) and move each hierarchy individually - count = Project.includes(:repositories).all.count { |x| x if x.parent_id.nil? } - gitolite_accessor.move_repositories_tree(count) if count.positive? - end - end - - def check_gitolite_config - ## Gitolite config file has changed, create a new one! - if value_has_changed?(:gitolite_config_file) || - value_has_changed?(:gitolite_identifier_prefix) || - value_has_changed?(:gitolite_identifier_strip_user_id) - options = { message: 'Gitolite configuration has been modified, resync all projects (active, closed, archived)...' } - gitolite_accessor.update_projects('all', options) - end - end - - def check_gitolite_default_values - ## Gitolite default values has changed, update active projects - if value_has_changed?(:gitolite_notify_global_prefix) || - value_has_changed?(:gitolite_notify_global_sender_address) || - value_has_changed?(:gitolite_notify_global_include) || - value_has_changed?(:gitolite_notify_global_exclude) - - # Need to update everyone! - options = { message: 'Gitolite configuration has been modified, resync all active projects...' } - gitolite_accessor.update_projects('active', options) - end - end - - def check_hook_config - ## Gitolite hooks config has changed, update our .gitconfig! - if value_has_changed?(:gitolite_hooks_debug) || - value_has_changed?(:gitolite_hooks_url) || - value_has_changed?(:gitolite_hooks_are_asynchronous) - - # Need to update our .gitconfig - RedmineGitHosting::Config.update_hook_params! - end - end - - def check_cache_config - ## Gitolite cache has changed, clear cache entries! - RedmineGitHosting::Cache.clear_obsolete_cache_entries if value_has_changed?(:gitolite_cache_max_time) - end - - def do_resync_projects - ## A resync has been asked within the interface, update all projects in force mode - options = { message: 'Forced resync of all projects (active, closed, archived)...', force: true } - gitolite_accessor.update_projects('all', options) if resync_projects - end - - def do_resync_ssh_keys - ## A resync has been asked within the interface, update all projects in force mode - gitolite_accessor.resync_ssh_keys if resync_ssh_keys - end - - def do_regenerate_ssh_keys - gitolite_accessor.regenerate_ssh_keys if regenerate_ssh_keys - end - - def do_flush_cache - ## A cache flush has been asked within the interface - gitolite_accessor.flush_git_cache if flush_cache - end - - def do_delete_trash_repo - gitolite_accessor.delete_from_recycle_bin(delete_trash_repo) unless delete_trash_repo.empty? - end - - def do_add_redmine_rw_access - if Additionals.true? current_setting(:redmine_has_rw_access_on_all_repos) - gitolite_accessor.enable_rw_access - else - gitolite_accessor.disable_rw_access - end - end - end -end diff --git a/plugins/redmine_git_hosting/app/views/common/_git_hosting_js_headers.html.slim b/plugins/redmine_git_hosting/app/views/common/_git_hosting_js_headers.html.slim deleted file mode 100644 index 5f10262..0000000 --- a/plugins/redmine_git_hosting/app/views/common/_git_hosting_js_headers.html.slim +++ /dev/null @@ -1,3 +0,0 @@ -- content_for :header_tags do - = stylesheet_link_tag 'application', plugin: 'redmine_git_hosting' - = javascript_include_tag 'application', plugin: 'redmine_git_hosting' diff --git a/plugins/redmine_git_hosting/app/views/common/_git_urls.html.slim b/plugins/redmine_git_hosting/app/views/common/_git_urls.html.slim deleted file mode 100644 index 8d3b52b..0000000 --- a/plugins/redmine_git_hosting/app/views/common/_git_urls.html.slim +++ /dev/null @@ -1,23 +0,0 @@ -- content_for :header_tags do - = additionals_library_load :clipboardjs - - = stylesheet_link_tag 'git_urls', plugin: 'redmine_git_hosting' - = javascript_include_tag 'git_urls', plugin: 'redmine_git_hosting' - - javascript: - $(function() { - setFirstGitUrl('.git_url_list'); setGitUrls('.git_url'); - $('.clipboard-button').tooltip(); - }) - -- repositories ||= Array.wrap(repository) -- if repositories.map(&:available_urls_sorted).any? - - repositories.sort_by { |r| r.is_default ? 0 : 1 }.each do |repository| - - next if repository.available_urls_sorted.empty? - - present repository do |p| - .repository-urls - = p.link_to_repository if repositories.count > 1 - = p.git_urls_box - -- else - #git_url_box = l(:label_repository_access_not_configured) diff --git a/plugins/redmine_git_hosting/app/views/dashboards/blocks/_git_urls.html.slim b/plugins/redmine_git_hosting/app/views/dashboards/blocks/_git_urls.html.slim deleted file mode 100644 index 7509978..0000000 --- a/plugins/redmine_git_hosting/app/views/dashboards/blocks/_git_urls.html.slim +++ /dev/null @@ -1,16 +0,0 @@ -- if @project.module_enabled?(:repository) && \ - @project.repository.is_a?(Repository::Xitolite) && \ - User.current.allowed_to?(:view_changesets, @project) - .git_hosting - h3 - = @project.repositories.count > 1 ? l(:label_repository_plural) : l(:label_repository) - = render partial: 'common/git_urls', locals: { repositories: @project.gitolite_repos } - - if @project.repositories.count > 1 - .clear-both - p - = link_to l(:label_see_other_repositories), { controller: '/repositories', - action: 'show', - id: @project, - repository_id: @project.repository.identifier_param, - rev: nil, - path: nil } diff --git a/plugins/redmine_git_hosting/app/views/gitolite_public_keys/_form.html.slim b/plugins/redmine_git_hosting/app/views/gitolite_public_keys/_form.html.slim deleted file mode 100644 index 7d15cab..0000000 --- a/plugins/redmine_git_hosting/app/views/gitolite_public_keys/_form.html.slim +++ /dev/null @@ -1,29 +0,0 @@ -#validation_messages - = error_messages_for 'gitolite_public_key' - -= labelled_form_for :gitolite_public_key, GitolitePublicKey.new, - url: { controller: 'gitolite_public_keys', action: 'create', user_id: params[:id], tab: params[:id] && 'keys' }, - html: { method: :post } do |f| - p - = f.text_field :title, label: :label_identifier_can_be_arbitrary, required: true, style: 'width: 97%;' - - - if can_create_deployment_keys_for_some_project(@user) - p - = f.select :key_type, - options_for_select([[l(:label_user_key), 0], [l(:label_deploy_key), 1]]), - { required: true, label: :label_key_type }, - { class: 'select_key_type' } - #key_type_options style="display: none;" - p - = f.check_box :delete_when_unused, required: true, label: :label_deployment_credential_delete_when_unused - p - = f.text_area :key, label: :label_public_key, required: true, - style: 'width: 97%; height: 200px; overflow: auto;', - cols: nil, - rows: nil - em - = l(:label_cut_and_paste) - br - br - = submit_tag l(:button_create), name: 'create_button' - = submit_tag l(:button_cancel), name: 'cancel_button' diff --git a/plugins/redmine_git_hosting/app/views/gitolite_public_keys/_ssh_keys.html.slim b/plugins/redmine_git_hosting/app/views/gitolite_public_keys/_ssh_keys.html.slim deleted file mode 100644 index c3368ea..0000000 --- a/plugins/redmine_git_hosting/app/views/gitolite_public_keys/_ssh_keys.html.slim +++ /dev/null @@ -1,21 +0,0 @@ -table.list - - if ssh_keys.empty? - tr - td - label = l(:label_no_public_keys) - - else - - ssh_keys.each do |key| - tr class="#{'highlight' if @gitolite_public_key == key}" - td style="text-align: left;" - = h(key) - td style="text-align: left;" - i.fas.fa-check style="color: green; margin-left: 5px; margin-right: 5px;" - = key.fingerprint - - if params[:id] - td style="text-align: left;" - = key.gitolite_path - td.buttons style="width: 10%;" - = link_to l(:button_delete), public_key_path(key, user_id: params[:id]), - method: 'delete', - class: 'icon icon-del', - data: { confirm: l(:text_gitolite_key_destroy_confirmation, title: keylabel(key)) } diff --git a/plugins/redmine_git_hosting/app/views/gitolite_public_keys/_view.html.slim b/plugins/redmine_git_hosting/app/views/gitolite_public_keys/_view.html.slim deleted file mode 100644 index acadeda..0000000 --- a/plugins/redmine_git_hosting/app/views/gitolite_public_keys/_view.html.slim +++ /dev/null @@ -1,37 +0,0 @@ -h3 = l(:label_my_public_keys) - -fieldset.public_key_view - legend = l(:label_current_user_keys) - = render partial: 'gitolite_public_keys/ssh_keys', locals: { ssh_keys: @gitolite_user_keys } - -br - -fieldset.public_key_view - legend = l(:label_current_deploy_keys) - = render partial: 'gitolite_public_keys/ssh_keys', locals: { ssh_keys: @gitolite_deploy_keys } - -br - -fieldset.public_key_view - legend = l(:label_public_key_new) - = render partial: 'gitolite_public_keys/form', locals: { user: @user } - -- content_for :header_tags do - = stylesheet_link_tag 'application', plugin: 'redmine_git_hosting' - -javascript: - function key_type_change(element) { - var idx = element.selectedIndex; - if (idx == 0) { - $('#key_type_options').hide(); - $('#gitolite_public_key_delete_when_unused').prop("checked", true); - } else { - $('#key_type_options').show(); - } - } - - $(document).ready(function() { - $('#gitolite_public_key_key_type').on('change', function() { - key_type_change(this) - }); - }); diff --git a/plugins/redmine_git_hosting/app/views/gitolite_public_keys/index.html.slim b/plugins/redmine_git_hosting/app/views/gitolite_public_keys/index.html.slim deleted file mode 100644 index f1f5215..0000000 --- a/plugins/redmine_git_hosting/app/views/gitolite_public_keys/index.html.slim +++ /dev/null @@ -1 +0,0 @@ -= render partial: 'gitolite_public_keys/view' diff --git a/plugins/redmine_git_hosting/app/views/go_redirector/index.html.slim b/plugins/redmine_git_hosting/app/views/go_redirector/index.html.slim deleted file mode 100644 index 769e9ad..0000000 --- a/plugins/redmine_git_hosting/app/views/go_redirector/index.html.slim +++ /dev/null @@ -1,2 +0,0 @@ -- content_for :header_tags do - meta name="go-import" content="#{@repository.go_url} git #{@repository.go_access_url}" diff --git a/plugins/redmine_git_hosting/app/views/hooks/_show_repositories_sidebar.html.slim b/plugins/redmine_git_hosting/app/views/hooks/_show_repositories_sidebar.html.slim deleted file mode 100644 index a33076e..0000000 --- a/plugins/redmine_git_hosting/app/views/hooks/_show_repositories_sidebar.html.slim +++ /dev/null @@ -1,3 +0,0 @@ -- if @repositories.size > 1 - - content_for :sidebar do - = call_hook(:view_repositories_show_sidebar, repository: @repository) diff --git a/plugins/redmine_git_hosting/app/views/projects/settings/_repositories.html.slim b/plugins/redmine_git_hosting/app/views/projects/settings/_repositories.html.slim deleted file mode 100644 index 20bc078..0000000 --- a/plugins/redmine_git_hosting/app/views/projects/settings/_repositories.html.slim +++ /dev/null @@ -1,64 +0,0 @@ -- if User.current.admin? - .contextual - = link_to l(:label_administration), plugin_settings_path(id: 'redmine_git_hosting'), class: 'icon icon-settings' - -- if User.current.allowed_to? :manage_repository, @project - p = link_to l(:label_repository_new), - new_project_repository_path(@project), - class: 'icon icon-add' - -- if @project.repositories.any? - .autoscroll - table.list - thead - tr - th = l :field_identifier - th = l :field_repository_is_default - th = l :label_scm - th = l :label_repository - th = l :label_repository_default_branch - th = l :label_repository_enabled_capabilities - th - tbody - - @project.repositories.sort.each do |repository| - tr - td = repository.identifier.presence || '' - td = checked_image repository.is_default? - td = repository.scm_name - td = link_to h(repository.url), - { controller: 'repositories', - action: 'show', - id: @project, - repository_id: repository.identifier_param } - td - - if repository.is_a? Repository::Xitolite - span.label.label-info = repository.git_default_branch - td align='center' - - if repository.is_a? Repository::Xitolite - - if repository.git_annex_enabled? - = render_feature repository, :git_annex - - else - = render_feature repository, :deployment_credentials - = render_feature repository, :post_receive_urls - = render_feature repository, :mirrors - = render_feature repository, :git_daemon - = render_feature repository, :git_http - = render_feature repository, :git_notify - = render_feature repository, :protected_branch - = render_feature repository, :public_repo - - td.buttons - - if User.current.allowed_to? :manage_repository, @project - = link_to l(:label_user_plural), committers_repository_path(repository), class: 'icon icon-user' - = link_to l(:button_edit), edit_repository_path(repository), class: 'icon icon-edit' - - if repository.is_a?(Repository::Xitolite) && repository.movable? - = link_to l(:button_move), move_repository_git_extras_path(repository), class: 'icon icon-move' - = delete_link repository_path(repository) - - javascript: - $(function() { - $('.icon-git').tooltip(); - }) - -- else - p.nodata = l :label_no_data diff --git a/plugins/redmine_git_hosting/app/views/repositories/_download_revision.html.slim b/plugins/redmine_git_hosting/app/views/repositories/_download_revision.html.slim deleted file mode 100644 index 60bd734..0000000 --- a/plugins/redmine_git_hosting/app/views/repositories/_download_revision.html.slim +++ /dev/null @@ -1,6 +0,0 @@ -- if repository.downloadable? - = font_awesome_icon 'fas_download', post_text: l(:label_download_format) - ' - = select_tag :download, options_for_select(available_download_format(repository, @rev)), - prompt: l(:label_download_select_format), - onchange: "if (this.value != '') { window.location = this.value; }" diff --git a/plugins/redmine_git_hosting/app/views/repositories/_edit_bottom.html.slim b/plugins/redmine_git_hosting/app/views/repositories/_edit_bottom.html.slim deleted file mode 100644 index f63f035..0000000 --- a/plugins/redmine_git_hosting/app/views/repositories/_edit_bottom.html.slim +++ /dev/null @@ -1,30 +0,0 @@ -- if @repository.is_a?(Repository::Xitolite) && !@repository.git_annex_enabled? - #repository-tabs - ul - - if User.current.git_allowed_to?(:view_repository_deployment_credentials, @repository) - li#tab-repository_deployment_credentials - = link_to font_awesome_icon('fas_lock', post_text: l(:label_deployment_credentials)), - repository_deployment_credentials_path(@repository) - - - if User.current.git_allowed_to?(:view_repository_mirrors, @repository) - li#tab-repository_mirrors - = link_to font_awesome_icon('fas_cloud-upload-alt', post_text: l(:label_repository_mirrors)), - repository_mirrors_path(@repository) - - - if User.current.git_allowed_to?(:view_repository_post_receive_urls, @repository) - li#tab-repository_post_receive_urls - = link_to font_awesome_icon('fas_external-link-alt', post_text: l(:label_post_receive_urls)), - repository_post_receive_urls_path(@repository) - - - if User.current.git_allowed_to?(:view_repository_git_config_keys, @repository) - li#tab-repository_git_config_keys - = link_to font_awesome_icon('fas_th-list', post_text: l(:label_git_config_keys)), - repository_git_config_keys_path(@repository) - - - if User.current.git_allowed_to?(:view_repository_protected_branches, @repository) - li#tab-repository_protected_branches - = link_to font_awesome_icon('fas_shield-alt', post_text: l(:label_protected_branches)), - repository_protected_branches_path(@repository) - - javascript: - $(document).ready(function() { setRepositoryActiveTab('#{@tab}'); }); diff --git a/plugins/redmine_git_hosting/app/views/repositories/_edit_top.html.slim b/plugins/redmine_git_hosting/app/views/repositories/_edit_top.html.slim deleted file mode 100644 index 6651b7d..0000000 --- a/plugins/redmine_git_hosting/app/views/repositories/_edit_top.html.slim +++ /dev/null @@ -1,13 +0,0 @@ -- if @repository.is_a?(Repository::Xitolite) - = render partial: 'common/git_hosting_js_headers' - - .git_hosting.box - h3 - = l(:label_repository_access_url) - - unless @repository.git_annex_enabled? - ' - = link_to l(:label_sort_urls), - sort_urls_repository_git_extras_path(@repository), - remote: true - - = render 'common/git_urls', repository: @repository diff --git a/plugins/redmine_git_hosting/app/views/repositories/_git_hosting_navigation.html.slim b/plugins/redmine_git_hosting/app/views/repositories/_git_hosting_navigation.html.slim deleted file mode 100644 index c257860..0000000 --- a/plugins/redmine_git_hosting/app/views/repositories/_git_hosting_navigation.html.slim +++ /dev/null @@ -1,2 +0,0 @@ -- if User.current.allowed_to? :add_repository_xitolite_watchers, @project - = watcher_link @repository, User.current diff --git a/plugins/redmine_git_hosting/app/views/repositories/_git_hosting_sidebar.html.slim b/plugins/redmine_git_hosting/app/views/repositories/_git_hosting_sidebar.html.slim deleted file mode 100644 index 084e470..0000000 --- a/plugins/redmine_git_hosting/app/views/repositories/_git_hosting_sidebar.html.slim +++ /dev/null @@ -1,17 +0,0 @@ -ul.repository.git - - @repositories.sort.each do |repo| - li class="#{'repository git' if repo.is_a? Repository::Xitolite}" - = link_to_repository repo, @repository - - if User.current.allowed_to? :manage_repository, @project - ' - = link_to "(#{l(:label_settings)})", edit_repository_path(repo) - -- if @repository.try(:watchers) && \ - (User.current.allowed_to?(:add_repository_xitolite_watchers, @project) || \ - (@repository.watchers.present? && User.current.allowed_to?(:view_repository_xitolite_watchers, @project))) - - #watchers - = render 'watchers/watchers', watched: @repository - -javascript: - $(document).ready(function() { $('#sidebar p').remove(); }); diff --git a/plugins/redmine_git_hosting/app/views/repositories/_readme.html.slim b/plugins/redmine_git_hosting/app/views/repositories/_readme.html.slim deleted file mode 100644 index 5112895..0000000 --- a/plugins/redmine_git_hosting/app/views/repositories/_readme.html.slim +++ /dev/null @@ -1,14 +0,0 @@ -#readme_container.box - h2.readme_trigger style='cursor: pointer;' - | README - - hr - - #readme_at_repo_dir.wiki - - if html.html_safe.respond_to?(:force_encoding) - = html.html_safe.force_encoding('UTF-8') - - else - = html.html_safe - -javascript: - $(document).ready(function() { $("#readme_trigger").click(function(){ $("#readme_at_repo_dir").toggle(500); }); }); diff --git a/plugins/redmine_git_hosting/app/views/repositories/_show_top.html.slim b/plugins/redmine_git_hosting/app/views/repositories/_show_top.html.slim deleted file mode 100644 index a8e2829..0000000 --- a/plugins/redmine_git_hosting/app/views/repositories/_show_top.html.slim +++ /dev/null @@ -1,13 +0,0 @@ -- if @repository.is_a? Repository::Xitolite - - content_for :header_tags do - = stylesheet_link_tag 'application', plugin: 'redmine_git_hosting' - = stylesheet_link_tag 'markdown', plugin: 'redmine_git_hosting' - - .git_hosting_urls.box - .container - .row - .col-md-8 style='vertical-align: middle;' - = render 'common/git_urls', repository: @repository - .col-md-4 style='text-align: right; vertical-align: middle;' - - if RedmineGitHosting::Config.download_revision_enabled? - = render 'repositories/download_revision', repository: @repository diff --git a/plugins/redmine_git_hosting/app/views/repositories/_xitolite_options.html.slim b/plugins/redmine_git_hosting/app/views/repositories/_xitolite_options.html.slim deleted file mode 100644 index 16aa0c0..0000000 --- a/plugins/redmine_git_hosting/app/views/repositories/_xitolite_options.html.slim +++ /dev/null @@ -1,85 +0,0 @@ -- if repository.is_a? Repository::Xitolite - = form_for repository.extra, url: repository_git_extras_path(repository), html: { method: :put, remote: true } do |f| - .box.tabular - .container - - .row - .col-md-12 - #xitolite-messages - = error_messages_for repository.extra - - .row - .col-md-6 - - unless repository.git_annex_enabled? - p - = label_tag 'repository_git_extra[git_daemon]', l(:label_enable_git_daemon) - = f.check_box :git_daemon, disabled: (!repository.public_project? && !repository.public_repo?) - - - if User.current.git_allowed_to?(:create_repository_protected_branches, repository) - p - = label_tag 'repository_git_extra[protected_branch]', l(:label_enable_protected_branches) - = f.check_box :protected_branch - - p - = label_tag 'repository_git_extra[public_repo]', l(:label_enable_public_repo) - = f.check_box :public_repo - - p - = label_tag 'repository_git_extra[git_http]', l(:label_enable_smart_http) - = f.check_box :git_http - - p - = label_tag 'repository_git_extra[git_https]', l(:label_enable_smart_https) - = f.check_box :git_https - - p - = label_tag 'repository_git_extra[git_go]', l(:label_enable_go_url) - = f.check_box :git_go - - p - = label_tag 'repository_git_extra[git_ssh]', l(:label_enable_ssh_url) - = f.check_box :git_ssh - - .col-md-6 - - p - = label_tag 'repository_git_extra[git_notify]', l(:label_enable_git_notify) - = f.check_box :git_notify - - if repository.git_notification_enabled? - p - = label_tag 'repository_git_extra[notification_sender]', l(:label_git_notification_sender) - = f.text_field :notification_sender - p - = label_tag 'repository_git_extra[notification_prefix]', l(:label_git_notification_prefix) - = f.text_field :notification_prefix - - - unless repository.git_annex_enabled? - p - = label_tag 'repository_git_extra[default_branch]', l(:label_repository_default_branch) - - if repository.branches.present? - = f.select :default_branch, repository_branches_list(repository.branches) - - else - span.label.label-info = repository.git_default_branch - - p - label = l :label_mirroring_keys_installed - = image_tag(RedmineGitHosting::Config.mirroring_keys_installed? ? 'true.png' : 'exclamation.png') - - p - label = l :label_repository_exists_in_gitolite - = image_tag(repository.exists_in_gitolite? ? 'true.png' : 'exclamation.png') - - p - - if repository.empty_in_gitolite? - label = l :label_empty_repository - = image_tag 'true.png' - - else - label = l :label_git_objects_count - = repository.git_objects_count - - p - label = l :label_browse_repository - = link_to h(repository.url), - { controller: 'repositories', action: 'show', id: @project, repository_id: repository.identifier_param } - - p = f.submit l(:button_save) diff --git a/plugins/redmine_git_hosting/app/views/repositories/edit.html.slim b/plugins/redmine_git_hosting/app/views/repositories/edit.html.slim deleted file mode 100644 index 0f3c6e0..0000000 --- a/plugins/redmine_git_hosting/app/views/repositories/edit.html.slim +++ /dev/null @@ -1,24 +0,0 @@ -.contextual - = render_repository_quick_jump(@repository) - -h2 - = link_to l(:label_settings), settings_project_path(@project, tab: 'repositories') - ' - = Additionals::LIST_SEPARATOR - = l(:label_repository) - ' - = Additionals::LIST_SEPARATOR - = @repository.redmine_name - -.splitcontent - .splitcontentleft - = call_hook(:view_repository_edit_top, repository: @repository, project: @project) - - = labelled_form_for :repository, @repository, url: repository_path(@repository), html: { method: :put, id: 'repository-form' } do |f| - = render partial: 'form', locals: { f: f } - - .splitcontentright - #xitolite-options style='vertical-align: top;' - = render 'xitolite_options', repository: @repository - -= call_hook(:view_repository_edit_bottom, repository: @repository, project: @project) diff --git a/plugins/redmine_git_hosting/app/views/repositories/git_instructions.html.slim b/plugins/redmine_git_hosting/app/views/repositories/git_instructions.html.slim deleted file mode 100644 index af80696..0000000 --- a/plugins/redmine_git_hosting/app/views/repositories/git_instructions.html.slim +++ /dev/null @@ -1,88 +0,0 @@ -#flash_warning.flash.warning = l :notice_empty_repository - -- if @repository.urls_are_viewable? - - content_for :header_tags do - = stylesheet_link_tag 'application', plugin: 'redmine_git_hosting' - - .git_hosting_urls.box - .container - .row - .col-md-8 style='vertical-align: middle;' - = render 'common/git_urls', repository: @repository - .col-md-4 style='text-align: right; vertical-align: middle;' - -.box - - if User.current.allowed_to? :view_changesets, @project - h3 - = l :label_help_git_setup - | : - pre - code.shell.syntaxhl - = link_to l(:label_download_and_install_git), 'https://git-scm.com/download', class: 'external' - br - == render_shell_text "git config --global user.name \"#{User.current.name(:firstname_lastname)}\"" - br - == render_shell_text "git config --global user.email #{User.current.mail || 'mail@example.com'}" - - if !User.current.anonymous? && User.current.gitolite_public_keys.empty? - br - = link_to 'Upload SSH Public Key', public_keys_path - - - if User.current.allowed_to? :commit_access, @project - #repository_setup - h3 - = l :label_help_repository_setup_new - | : - pre - code.shell.syntaxhl - == render_shell_text "mkdir #{@repository.redmine_name}" - br - == render_shell_text "cd #{@repository.redmine_name}" - br - == render_shell_text 'git init' - br - == render_shell_text 'touch readme.txt' - br - == render_shell_text 'git add readme.txt' - br - == render_shell_text "git commit -m 'Initializing #{@repository.redmine_name} repository'" - br - ' git remote add origin - span.git_url_access - br - == render_shell_text 'git push -u origin master' - - h3 - = l :label_help_repository_setup_existing - | : - pre - code.shell.syntaxhl - == render_shell_text 'cd existing_git_rep' - br - ' git remote add origin - span.git_url_access - br - == render_shell_text 'git push -u origin master' - - h3 - = l :label_help_repository_clone - | : - pre - code.shell.syntaxhl - ' git clone - span.git_url_access - - - else - = l :label_help_no_repo_rights - -- content_for :sidebar do - h3 = l :label_repository_plural - ul.repository.git - - @repositories.sort.each do |repo| - li class="#{'repository git' if repo.is_a?(Repository::Xitolite)}" - = link_to_repository(repo, @repository) - - if User.current.allowed_to?(:manage_repository, @project) - ' - = link_to "(#{l(:label_settings)})", edit_repository_path(repo) - -javascript: - $(document).ready(function() { setGitUrlsInstructions('.git_url'); }); diff --git a/plugins/redmine_git_hosting/app/views/repositories/statistics/_commits.html.slim b/plugins/redmine_git_hosting/app/views/repositories/statistics/_commits.html.slim deleted file mode 100644 index 4bc576f..0000000 --- a/plugins/redmine_git_hosting/app/views/repositories/statistics/_commits.html.slim +++ /dev/null @@ -1,49 +0,0 @@ -- report = RepositoryCommitsStats.new(repository) - -#chart_commits_per_month style='height: 300px; width: 47%; margin: 10px; float: left;' -#chart_commits_per_day style='height: 300px; width: 47%; margin: 10px; float: left;' - -.clear-both style='margin: 10px;' - -#chart_commits_per_hour style = 'height: 500px; width: 47%; margin: 10px; float: left;' -#chart_commits_per_weekday style= 'height: 300px; width: 47%; margin: 10px; float: left;' - -#chart_commits_per_weekday style='margin-top: 20px;' - -javascript: - var chart_commits_per_month = new Object(); - chart_commits_per_month.label = "#{l(:label_commits_per_month)}"; - chart_commits_per_month.label_y_axis = "#{l(:label_commits_number)}"; - chart_commits_per_month.target = '#chart_commits_per_month'; - chart_commits_per_month.categories = #{report.commits_per_month[:categories].to_json.html_safe}; - chart_commits_per_month.series = #{report.commits_per_month[:series].to_json.html_safe}; - - var chart_commits_per_day = new Object(); - chart_commits_per_day.label = "#{l(:label_commits_per_day)}"; - chart_commits_per_day.label_y_axis = "#{l(:label_commits_number)}"; - chart_commits_per_day.target = '#chart_commits_per_day'; - chart_commits_per_day.categories = #{report.commits_per_day[:categories].to_json.html_safe}; - chart_commits_per_day.series = #{report.commits_per_day[:series].to_json.html_safe}; - chart_commits_per_day.legend = { - layout: 'vertical', - align: 'left', - verticalAlign: 'top', - x: 50, - y: 50, - floating: true, - borderWidth: 1, - backgroundColor: '#fff' - }; - - var chart_commits_per_hour = new Object(); - chart_commits_per_hour.label = "#{l(:label_commits_per_hour)}"; - chart_commits_per_hour.label_y_axis = "#{l(:label_hour)}"; - chart_commits_per_hour.label_x_axis = "#{l(:label_commits_number)}"; - chart_commits_per_hour.target = '#chart_commits_per_hour'; - chart_commits_per_hour.categories = #{report.commits_per_hours[:categories].to_json.html_safe}; - chart_commits_per_hour.series = #{report.commits_per_hours[:series].to_json.html_safe}; - - var chart_commits_per_weekday = new Object(); - chart_commits_per_weekday.label = "#{l(:label_commits_per_weekday)}"; - chart_commits_per_weekday.target = '#chart_commits_per_weekday'; - chart_commits_per_weekday.series = #{report.commits_per_weekday.to_json.html_safe}; diff --git a/plugins/redmine_git_hosting/app/views/repositories/statistics/_contributors.html.slim b/plugins/redmine_git_hosting/app/views/repositories/statistics/_contributors.html.slim deleted file mode 100644 index ca76401..0000000 --- a/plugins/redmine_git_hosting/app/views/repositories/statistics/_contributors.html.slim +++ /dev/null @@ -1,34 +0,0 @@ -- report = RepositoryContributorsStats.new(repository) - -ul.thumbnails - - @author_charts = [] - - report.commits_per_author.each do |commits_data| - - idx = report.commits_per_author.index(commits_data) - - @author_charts.push("chart_commits_per_author_#{idx}") - javascript: - var chart_commits_per_author_#{idx} = new Object(); - chart_commits_per_author_#{idx}.label = ""; - chart_commits_per_author_#{idx}.label_y_axis = "#{l(:label_commits_number)}"; - chart_commits_per_author_#{idx}.target = '#chart_commits_per_author_#{idx}'; - chart_commits_per_author_#{idx}.categories = #{commits_data[:categories].to_json.html_safe}; - chart_commits_per_author_#{idx}.series = #{commits_data[:series].to_json.html_safe}; - chart_commits_per_author_#{idx}.legend = {}; - - li.span6 - .thumbnail id="contributor-#{idx}" - h4 - = commits_data[:author_name] - ' - small = commits_data[:author_mail] - - h5 = commits_data[:total_commits] - div id="chart_commits_per_author_#{idx}" style='height: 200px; width: 100%' - -#chart_commits_per_author -javascript: - var chart_commits_per_author = new Object(); - chart_commits_per_author.label = "#{l(:label_commits_per_author)}"; - chart_commits_per_author.label_y_axis = "#{l(:label_commits_number)}"; - chart_commits_per_author.target = '#chart_commits_per_author'; - chart_commits_per_author.categories = #{report.commits_per_author_global[:categories].to_json.html_safe}; - chart_commits_per_author.series = #{report.commits_per_author_global[:series].to_json.html_safe}; diff --git a/plugins/redmine_git_hosting/app/views/repositories/statistics/_global.html.slim b/plugins/redmine_git_hosting/app/views/repositories/statistics/_global.html.slim deleted file mode 100644 index ca3f6a3..0000000 --- a/plugins/redmine_git_hosting/app/views/repositories/statistics/_global.html.slim +++ /dev/null @@ -1,8 +0,0 @@ -- report = RepositoryGlobalStats.new(repository).build - -ul.thumbnails - - report.each do |key, value| - li.span4 - .thumbnail - .title = key - .value = value diff --git a/plugins/redmine_git_hosting/app/views/repositories/stats.html.slim b/plugins/redmine_git_hosting/app/views/repositories/stats.html.slim deleted file mode 100644 index 3c6a344..0000000 --- a/plugins/redmine_git_hosting/app/views/repositories/stats.html.slim +++ /dev/null @@ -1,43 +0,0 @@ -h2 = l :label_statistics - -#statistics-tabs - ul - li - a href="#statistics-global" - = l(:label_repository_statistics_global) - li - a href="#statistics-commits" - = l(:label_repository_statistics_commits) - li - a href="#statistics-contributors" - = l(:label_repository_statistics_contributors) - #statistics-global - = render 'repositories/statistics/global', repository: @repository - #statistics-commits - = render 'repositories/statistics/commits', repository: @repository - #statistics-contributors - = render 'repositories/statistics/contributors', repository: @repository - -.clear-both style="margin: 10px;" - -p = link_to l(:button_back), action: 'show', id: @project - -- html_title(l(:label_repository), l(:label_statistics)) - -- content_for :header_tags do - = javascript_include_tag('highcharts/highcharts', plugin: 'redmine_git_hosting') - = javascript_include_tag('highcharts/modules/drilldown', plugin: 'redmine_git_hosting') - = stylesheet_link_tag 'application', plugin: 'redmine_git_hosting' - = javascript_include_tag 'set_highcharts', plugin: 'redmine_git_hosting' - -- charts = @author_charts.map { |chart| "createZoomableAreaChart(#{chart});" } -javascript: - $(document).ready(function() { - createAreaChart(chart_commits_per_month); - createZoomableAreaChart(chart_commits_per_day); - createBarChart(chart_commits_per_hour); - createPieChart(chart_commits_per_weekday); - #{raw charts.join("\n")} - createColumnChart(chart_commits_per_author); - $("#statistics-tabs").tabs(); - }); diff --git a/plugins/redmine_git_hosting/app/views/repository_deployment_credentials/_edit_modal.html.slim b/plugins/redmine_git_hosting/app/views/repository_deployment_credentials/_edit_modal.html.slim deleted file mode 100644 index af31e9f..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_deployment_credentials/_edit_modal.html.slim +++ /dev/null @@ -1,17 +0,0 @@ -h3.title = l :label_deployment_credential_edit - -= labelled_form_for :repository_deployment_credential, @credential, - url: repository_deployment_credential_path(@repository, @credential), - authenticity_token: form_authenticity_token, - html: { method: :put, class: 'tabular', remote: true } do |f| - - .flash-messages = error_messages_for 'credential' - - .box - p = f.select :perm, options_for_select(RepositoryDeploymentCredential::VALID_PERMS, @credential.perm), required: true - p = f.check_box :active - - .buttons - = submit_tag l :button_save - ' - = link_to_function l(:button_cancel), 'hideModal(this);' diff --git a/plugins/redmine_git_hosting/app/views/repository_deployment_credentials/_new_modal.html.slim b/plugins/redmine_git_hosting/app/views/repository_deployment_credentials/_new_modal.html.slim deleted file mode 100644 index 4497b31..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_deployment_credentials/_new_modal.html.slim +++ /dev/null @@ -1,25 +0,0 @@ -h3.title = l(:label_deployment_credential_add) - -= labelled_form_for :repository_deployment_credential, @credential, - url: repository_deployment_credentials_path(@repository), - html: { method: :post, class: 'tabular', remote: true } do |f| - - .flash-messages = error_messages_for 'credential' - - .box - - if @user_keys.present? || @other_keys.present? - p = f.select :gitolite_public_key_id, - build_list_of_keys(@user_keys, @other_keys, @disabled_keys), - required: true, - label: :label_deployment_credential_select_deploy_key - p = f.select :perm, - options_for_select(RepositoryDeploymentCredential::VALID_PERMS, RepositoryDeploymentCredential::DEFAULT_PERM), - required: true, - label: :label_permissions - - else - = link_to l(:label_deployment_credential_create_key_first), public_keys_path - - .buttons - = submit_tag l(:button_add) - ' - = link_to_function l(:button_cancel), 'hideModal(this);' diff --git a/plugins/redmine_git_hosting/app/views/repository_deployment_credentials/edit.js.erb b/plugins/redmine_git_hosting/app/views/repository_deployment_credentials/edit.js.erb deleted file mode 100644 index a0d0426..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_deployment_credentials/edit.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$('#ajax-modal').html('<%= escape_javascript(render partial: 'repository_deployment_credentials/edit_modal') %>'); -showModal('ajax-modal', '600px'); diff --git a/plugins/redmine_git_hosting/app/views/repository_deployment_credentials/index.html.slim b/plugins/redmine_git_hosting/app/views/repository_deployment_credentials/index.html.slim deleted file mode 100644 index ccceccb..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_deployment_credentials/index.html.slim +++ /dev/null @@ -1,54 +0,0 @@ -div - - if User.current.git_allowed_to?(:create_repository_deployment_credentials, @repository) - .contextual - = link_to l(:label_deployment_credential_add), - new_repository_deployment_credential_path(@repository), - remote: true, - class: 'icon icon-add' - - h3 = l(:label_deployment_credentials) - - - if @repository_deployment_credentials.any? - table.list - thead - tr - th = l(:label_deployment_credential_owner) - th = l(:label_deployment_credential_public_key_name) - th = l(:label_deployment_credential_public_key_file) - th = l(:label_permissions) - th = l(:label_deployment_credential_honored) - th = l(:field_active) - th - tbody - - @repository_deployment_credentials.sort_by { |x| [x.user.login, x.gitolite_public_key.title] }.each do |credential| - tr - td = credential.user.login - td - - if credential.user == User.current - = link_to credential.gitolite_public_key.title, public_keys_path - - elsif User.current.admin? - = link_to credential.gitolite_public_key.title, edit_user_path(credential.user, tab: 'keys') - - else - = credential.gitolite_public_key.title - - td = credential.gitolite_public_key.gitolite_path - td = credential.perm - td.tick = checked_image_with_exclamation credential.honored? - td.tick = checked_image_with_exclamation credential.active? - - td.buttons - - if User.current.git_allowed_to?(:edit_repository_deployment_credentials, @repository) && \ - (User.current.admin? || User.current == credential.user) - = link_to l(:button_edit), - edit_repository_deployment_credential_path(@repository, credential), - remote: true, - class: 'icon icon-edit' - = link_to l(:button_delete), - repository_deployment_credential_path(@repository, credential), - remote: true, - method: :delete, - data: { confirm: l(:text_are_you_sure) }, - class: 'icon icon-del' - - - else - p.nodata = l :label_no_data diff --git a/plugins/redmine_git_hosting/app/views/repository_deployment_credentials/new.js.erb b/plugins/redmine_git_hosting/app/views/repository_deployment_credentials/new.js.erb deleted file mode 100644 index e92cc58..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_deployment_credentials/new.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$('#ajax-modal').html('<%= escape_javascript(render partial: 'repository_deployment_credentials/new_modal') %>'); -showModal('ajax-modal', '600px'); diff --git a/plugins/redmine_git_hosting/app/views/repository_git_config_keys/_config_keys.html.slim b/plugins/redmine_git_hosting/app/views/repository_git_config_keys/_config_keys.html.slim deleted file mode 100644 index 9b0a56e..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_git_config_keys/_config_keys.html.slim +++ /dev/null @@ -1,28 +0,0 @@ -- if git_config_keys.any? - table.list - thead - tr - th = l :label_key - th = l :field_value - th - tbody - - git_config_keys.each do |git_config_key| - tr - td - span.label.label-info = git_config_key.key - td - span.label.label-success = git_config_key.value - td.buttons - - if User.current.git_allowed_to?(:edit_repository_git_config_keys, @repository) - = link_to l(:button_edit), - edit_repository_git_config_key_path(@repository, git_config_key), - class: 'icon icon-edit' - = link_to l(:button_delete), - repository_git_config_key_path(@repository, git_config_key), - remote: true, - method: :delete, - data: { confirm: l(:text_are_you_sure) }, - class: 'icon icon-del' - -- else - p.nodata = l :label_no_data diff --git a/plugins/redmine_git_hosting/app/views/repository_git_config_keys/_edit_modal.html.slim b/plugins/redmine_git_hosting/app/views/repository_git_config_keys/_edit_modal.html.slim deleted file mode 100644 index 4f70e4c..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_git_config_keys/_edit_modal.html.slim +++ /dev/null @@ -1,12 +0,0 @@ -h3.title = l :label_git_config_keys - -= labelled_form_for :repository_git_config_key, @git_config_key, - url: repository_git_config_key_path(@repository, @git_config_key), - authenticity_token: form_authenticity_token, - html: { method: :put, class: 'tabular', remote: true } do |f| - - = render partial: 'form', locals: { f: f } - .buttons - = submit_tag l(:button_save) - ' - = link_to_function l(:button_cancel), 'hideModal(this);' diff --git a/plugins/redmine_git_hosting/app/views/repository_git_config_keys/_form.html.slim b/plugins/redmine_git_hosting/app/views/repository_git_config_keys/_form.html.slim deleted file mode 100644 index c285fbc..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_git_config_keys/_form.html.slim +++ /dev/null @@ -1,9 +0,0 @@ -.flash-messages = error_messages_for 'git_config_key' - -.box - p = f.select :type, - options_for_select(git_config_key_options, @git_config_key.type), - { required: @git_config_key.new_record?, prompt: 'Select a key type' }, - { disabled: !@git_config_key.new_record? } - p = f.text_field :key, required: true, size: 65, label: :label_key - p = f.text_field :value, required: true, size: 65 diff --git a/plugins/redmine_git_hosting/app/views/repository_git_config_keys/_new_modal.html.slim b/plugins/redmine_git_hosting/app/views/repository_git_config_keys/_new_modal.html.slim deleted file mode 100644 index d093ebb..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_git_config_keys/_new_modal.html.slim +++ /dev/null @@ -1,12 +0,0 @@ -h3.title = l(:label_git_config_keys) - -= labelled_form_for :repository_git_config_key, @git_config_key, - url: repository_git_config_keys_path(@repository), - authenticity_token: form_authenticity_token, - html: { method: :post, class: 'tabular', remote: true } do |f| - - = render partial: 'form', locals: { f: f } - .buttons - = submit_tag l(:button_add) - ' - = link_to_function l(:button_cancel), 'hideModal(this);' diff --git a/plugins/redmine_git_hosting/app/views/repository_git_config_keys/edit.js.erb b/plugins/redmine_git_hosting/app/views/repository_git_config_keys/edit.js.erb deleted file mode 100644 index e7fe480..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_git_config_keys/edit.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$('#ajax-modal').html('<%= escape_javascript(render partial: 'repository_git_config_keys/edit_modal') %>'); -showModal('ajax-modal', '600px'); diff --git a/plugins/redmine_git_hosting/app/views/repository_git_config_keys/index.api.rsb b/plugins/redmine_git_hosting/app/views/repository_git_config_keys/index.api.rsb deleted file mode 100644 index dce9046..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_git_config_keys/index.api.rsb +++ /dev/null @@ -1,9 +0,0 @@ -api.array :repository_git_config_keys, api_meta(total_count: @repository_git_config_keys.count) do - @repository_git_config_keys.each do |git_config_key| - api.git_config_key do - api.id git_config_key.id - api.key git_config_key.key - api.value git_config_key.value - end - end -end diff --git a/plugins/redmine_git_hosting/app/views/repository_git_config_keys/index.html.slim b/plugins/redmine_git_hosting/app/views/repository_git_config_keys/index.html.slim deleted file mode 100644 index dd32bdd..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_git_config_keys/index.html.slim +++ /dev/null @@ -1,32 +0,0 @@ -div - - if User.current.git_allowed_to?(:create_repository_git_config_keys, @repository) - .contextual - = link_to l(:label_git_config_key_add), - new_repository_git_config_key_path(@repository, type: 'git_config'), - remote: true, - class: 'icon icon-add' - - h3 - = l(:label_git_config_keys) - ' - = link_to "(#{l(:label_gitolite_documentation)})", - 'https://gitolite.com/gitolite/git-config.html', - class: 'external' - - = render 'config_keys', git_config_keys: @repository_git_config_keys - - - if User.current.git_allowed_to?(:create_repository_git_config_keys, @repository) - .contextual - = link_to l(:label_git_option_key_add), - new_repository_git_config_key_path(@repository, type: 'git_option'), - remote: true, - class: 'icon icon-add' - - h3 - = l(:label_git_option_keys) - ' - = link_to "(#{l(:label_gitolite_documentation)})", - 'https://gitolite.com/gitolite/options.html', - class: 'external' - - = render 'config_keys', git_config_keys: @repository_git_option_keys diff --git a/plugins/redmine_git_hosting/app/views/repository_git_config_keys/new.js.erb b/plugins/redmine_git_hosting/app/views/repository_git_config_keys/new.js.erb deleted file mode 100644 index d1f0d5c..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_git_config_keys/new.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$('#ajax-modal').html('<%= escape_javascript(render partial: 'repository_git_config_keys/new_modal') %>'); -showModal('ajax-modal', '600px'); diff --git a/plugins/redmine_git_hosting/app/views/repository_git_config_keys/show.api.rsb b/plugins/redmine_git_hosting/app/views/repository_git_config_keys/show.api.rsb deleted file mode 100644 index 2deeeac..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_git_config_keys/show.api.rsb +++ /dev/null @@ -1,5 +0,0 @@ -api.git_config_key do - api.id @git_config_key.id - api.key @git_config_key.key - api.value @git_config_key.value -end diff --git a/plugins/redmine_git_hosting/app/views/repository_git_extras/_sort_urls_modal.html.slim b/plugins/redmine_git_hosting/app/views/repository_git_extras/_sort_urls_modal.html.slim deleted file mode 100644 index 9af0176..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_git_extras/_sort_urls_modal.html.slim +++ /dev/null @@ -1,10 +0,0 @@ -ul#sortable-url.list-unstyled data-remote="true" data-update-url="#{sort_urls_repository_git_extras_path(@repository)}" - - @repository.available_urls_sorted.each_key do |url_type| - li.url_type.draggable id="repository_git_extra_#{url_type}" - = icon_for_url_type url_type - ' - span - = label_for_url_type url_type - -javascript: - $(document).ready(function() { setSortableElement('#sortable-url', '#sortable-url'); }); diff --git a/plugins/redmine_git_hosting/app/views/repository_git_extras/move.html.slim b/plugins/redmine_git_hosting/app/views/repository_git_extras/move.html.slim deleted file mode 100644 index a5c9aa8..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_git_extras/move.html.slim +++ /dev/null @@ -1,17 +0,0 @@ -h2 = l :label_move_repository, repo_name: @repository.gitolite_repository_name - -.box - = labelled_form_for :repository_mover, @move_repository_form, - url: move_repository_git_extras_path(@repository), - authenticity_token: form_authenticity_token, - html: { method: :post, class: 'tabular', data: { confirm: l(:text_are_you_sure) } } do |f| - - .flash-messages = error_messages_for 'move_repository_form' - p - = f.select :project_id, - render_options_for_move_repo_select_box(@project), - required: true - p - = f.submit l(:button_move) - ' - = link_to l(:button_cancel), settings_project_path(@project, tab: 'repositories') diff --git a/plugins/redmine_git_hosting/app/views/repository_git_extras/sort_urls.js.erb b/plugins/redmine_git_hosting/app/views/repository_git_extras/sort_urls.js.erb deleted file mode 100644 index 3c25374..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_git_extras/sort_urls.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$('#ajax-modal').html('<%= escape_javascript(render partial: 'repository_git_extras/sort_urls_modal') %>'); -showModal('ajax-modal', '400px'); diff --git a/plugins/redmine_git_hosting/app/views/repository_git_extras/update.js.erb b/plugins/redmine_git_hosting/app/views/repository_git_extras/update.js.erb deleted file mode 100644 index fc10e38..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_git_extras/update.js.erb +++ /dev/null @@ -1,3 +0,0 @@ -$('#xitolite-options').html("<%= escape_javascript(render 'repositories/xitolite_options', repository: @repository) %>"); -$('#xitolite-messages').append("<%= escape_javascript render_flash_messages %>"); -$('#xitolite-messages').children().each(function(index, element){ $(element).delay(3000).slideUp(200, function(){$(this).alert('close')}) }); diff --git a/plugins/redmine_git_hosting/app/views/repository_mirrors/_edit_modal.html.slim b/plugins/redmine_git_hosting/app/views/repository_mirrors/_edit_modal.html.slim deleted file mode 100644 index d0dae84..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_mirrors/_edit_modal.html.slim +++ /dev/null @@ -1,12 +0,0 @@ -h3.title = l :label_mirror_edit - -= labelled_form_for :repository_mirror, @mirror, - url: repository_mirror_path(@repository, @mirror), - authenticity_token: form_authenticity_token, - html: { method: :put, class: 'tabular', remote: true } do |f| - - = render partial: 'form', locals: { f: f } - .buttons - = submit_tag l(:button_save) - ' - = link_to_function l(:button_cancel), 'hideModal(this);' diff --git a/plugins/redmine_git_hosting/app/views/repository_mirrors/_form.html.slim b/plugins/redmine_git_hosting/app/views/repository_mirrors/_form.html.slim deleted file mode 100644 index e20f5f7..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_mirrors/_form.html.slim +++ /dev/null @@ -1,23 +0,0 @@ -.flash-messages = error_messages_for 'mirror' - -.box - p = f.text_field :url, required: true, size: 65 - em - p - = l :label_mirror_url_accepted_format - ' : - br - | ssh://git@redmine.example.org/project1/project2/project3/project4.git - br - | ssh://git@redmine.example.org:2222/project1/project2/project3/project4.git - - p = f.check_box :active - p = f.select :push_mode, - options_for_select(mirrors_options, @mirror.push_mode), - { label: :label_mirror_push_mode }, - onchange: 'push_mode_change(this); return false;' - - #ref_spec_options style="#{'display: none;' if @mirror.mirror_mode?}" - p = f.check_box :include_all_branches, label: :label_mirror_include_all_branches - p = f.check_box :include_all_tags, label: :label_mirror_include_all_tags - p = f.text_field :explicit_refspec, label: :label_mirror_explicit_refspec, size: 65 diff --git a/plugins/redmine_git_hosting/app/views/repository_mirrors/_new_modal.html.slim b/plugins/redmine_git_hosting/app/views/repository_mirrors/_new_modal.html.slim deleted file mode 100644 index e7cd6b9..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_mirrors/_new_modal.html.slim +++ /dev/null @@ -1,12 +0,0 @@ -h3.title = l :label_mirror_add - -= labelled_form_for :repository_mirror, @mirror, - url: repository_mirrors_path(@repository), - authenticity_token: form_authenticity_token, - html: { method: :post, class: 'tabular', remote: true } do |f| - - = render partial: 'form', locals: { f: f } - .buttons - = submit_tag l(:button_add) - ' - = link_to_function l(:button_cancel), 'hideModal(this);' diff --git a/plugins/redmine_git_hosting/app/views/repository_mirrors/_push_modal.html.slim b/plugins/redmine_git_hosting/app/views/repository_mirrors/_push_modal.html.slim deleted file mode 100644 index dc8e115..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_mirrors/_push_modal.html.slim +++ /dev/null @@ -1,9 +0,0 @@ -p style='white-space: nowrap;' - = render_push_state @mirror, @push_failed - -strong - = l :label_mirror_push_output - ' : - -pre class="mirror-push-#{'error' if @push_failed}" - = @shellout diff --git a/plugins/redmine_git_hosting/app/views/repository_mirrors/edit.js.erb b/plugins/redmine_git_hosting/app/views/repository_mirrors/edit.js.erb deleted file mode 100644 index ef141e1..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_mirrors/edit.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$('#ajax-modal').html('<%= escape_javascript(render partial: 'repository_mirrors/edit_modal') %>'); -showModal('ajax-modal', '600px'); diff --git a/plugins/redmine_git_hosting/app/views/repository_mirrors/index.api.rsb b/plugins/redmine_git_hosting/app/views/repository_mirrors/index.api.rsb deleted file mode 100644 index 1f5043b..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_mirrors/index.api.rsb +++ /dev/null @@ -1,13 +0,0 @@ -api.array :repository_mirrors, api_meta(total_count: @repository_mirrors.count) do - @repository_mirrors.each do |mirror| - api.mirror do - api.id mirror.id - api.url mirror.url - api.active mirror.active - api.push_mode mirror.push_mode_to_s - api.include_all_branches mirror.include_all_branches - api.include_all_tags mirror.include_all_tags - api.explicit_refspec mirror.explicit_refspec - end - end -end diff --git a/plugins/redmine_git_hosting/app/views/repository_mirrors/index.html.slim b/plugins/redmine_git_hosting/app/views/repository_mirrors/index.html.slim deleted file mode 100644 index a5333da..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_mirrors/index.html.slim +++ /dev/null @@ -1,67 +0,0 @@ -div - - if User.current.git_allowed_to? :create_repository_mirrors, @repository - .contextual - = link_to l(:label_mirror_add), - new_repository_mirror_path(@repository), - remote: true, - class: 'icon icon-add' - - h3 = l :label_repository_mirrors - - - if @repository_mirrors.any? - table.list - thead - tr - th = l :field_url - th = l :label_mirror_refspec - th = l :label_mode - th = l :field_active - th - tbody - - @repository_mirrors.each do |mirror| - tr - td - = mirror.url - - td - = refspec mirror, 64 - - td - = mirror_mode mirror - - td.tick - = checked_image_with_exclamation mirror.active? - - td.buttons - - if User.current.git_allowed_to?(:push_repository_mirrors, @repository) - = link_to font_awesome_icon('fas_rocket', post_text: l(:label_mirror_push), class: 'fa-lg'), - push_repository_mirror_path(@repository, mirror), remote: true - - - if User.current.git_allowed_to?(:edit_repository_mirrors, @repository) - = link_to l(:button_edit), edit_repository_mirror_path(@repository, mirror), remote: true, class: 'icon icon-edit' - = link_to l(:button_delete), - repository_mirror_path(@repository, mirror), - remote: true, - method: :delete, - data: { confirm: l(:text_are_you_sure) }, - class: 'icon icon-del' - - - else - p.nodata = l :label_no_data - - .git_hosting_spacer - - div style='margin: 2px 3px; width: 99%;' - div - = clipboardjs_button_for 'mirror_pubkey' - - span style='margin-left: 10px;' - = l :label_mirror_help - ' : - - .git_hosting_spacer - - textarea#mirror_pubkey readonly='readonly' style='height: 100px; width: 99%; font-family: sans-serif;' - = RedmineGitHosting::Config.mirroring_public_key - - .git_hosting_spacer diff --git a/plugins/redmine_git_hosting/app/views/repository_mirrors/new.js.erb b/plugins/redmine_git_hosting/app/views/repository_mirrors/new.js.erb deleted file mode 100644 index f2222a6..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_mirrors/new.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$('#ajax-modal').html('<%= escape_javascript(render partial: 'repository_mirrors/new_modal') %>'); -showModal('ajax-modal', '600px'); diff --git a/plugins/redmine_git_hosting/app/views/repository_mirrors/push.js.erb b/plugins/redmine_git_hosting/app/views/repository_mirrors/push.js.erb deleted file mode 100644 index bca1dd2..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_mirrors/push.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$('#ajax-modal').html('<%= escape_javascript(render partial: 'repository_mirrors/push_modal') %>'); -showModal('ajax-modal', '600px'); diff --git a/plugins/redmine_git_hosting/app/views/repository_mirrors/show.api.rsb b/plugins/redmine_git_hosting/app/views/repository_mirrors/show.api.rsb deleted file mode 100644 index a71fa89..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_mirrors/show.api.rsb +++ /dev/null @@ -1,9 +0,0 @@ -api.mirror do - api.id @mirror.id - api.url @mirror.url - api.active @mirror.active - api.push_mode @mirror.push_mode_to_s - api.include_all_branches @mirror.include_all_branches - api.include_all_tags @mirror.include_all_tags - api.explicit_refspec @mirror.explicit_refspec -end diff --git a/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/_edit_modal.html.slim b/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/_edit_modal.html.slim deleted file mode 100644 index f202d19..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/_edit_modal.html.slim +++ /dev/null @@ -1,12 +0,0 @@ -h3.title = l :label_post_receive_url_edit - -= labelled_form_for :repository_post_receive_url, @post_receive_url, - url: repository_post_receive_url_path(@repository, @post_receive_url), - authenticity_token: form_authenticity_token, - html: { method: :put, class: 'tabular', remote: true } do |f| - - = render partial: 'form', locals: { f: f } - .buttons - = submit_tag l(:button_save) - ' - = link_to_function l(:button_cancel), 'hideModal(this);' diff --git a/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/_form.html.slim b/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/_form.html.slim deleted file mode 100644 index 8d2e1b7..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/_form.html.slim +++ /dev/null @@ -1,30 +0,0 @@ -.flash-messages = error_messages_for 'post_receive_url' - -.box - p = f.url_field :url, - size: 65, - placeholder: 'https://example.com', - required: true - - p = f.check_box :active - - p = f.select :mode, - [['Github-style POST', :github], - ['Empty POST request', :post], - ['Empty GET request', :get]], - {}, - onchange: 'post_mode_change(this); return false;' - - #payload_options style="#{@post_receive_url.github_mode? ? '' : 'display: none;'}" - p = f.check_box :split_payloads - - - if @repository.branches.any? - p = f.check_box :use_triggers, onchange: 'trigger_mode_change(this); return false;' - - #triggers_options style="#{@post_receive_url.use_triggers? ? '' : 'display: none;'}" - = hidden_field_tag 'repository_post_receive_url[triggers][]', '' - - @repository.branches.each do |branch| - p - label - = check_box_tag 'repository_post_receive_url[triggers][]', branch.to_s, @post_receive_url.triggers.include?(branch.to_s) - = branch.to_s diff --git a/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/_new_modal.html.slim b/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/_new_modal.html.slim deleted file mode 100644 index bf5e3d3..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/_new_modal.html.slim +++ /dev/null @@ -1,12 +0,0 @@ -h3.title = l :label_post_receive_url_add - -= labelled_form_for :repository_post_receive_url, @post_receive_url, - url: repository_post_receive_urls_path(@repository), - authenticity_token: form_authenticity_token, - html: { method: :post, class: 'tabular', remote: true } do |f| - - = render partial: 'form', locals: { f: f } - .buttons - = submit_tag l(:button_add) - ' - = link_to_function l(:button_cancel), 'hideModal(this);' diff --git a/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/edit.js.erb b/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/edit.js.erb deleted file mode 100644 index 993747c..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/edit.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$('#ajax-modal').html('<%= escape_javascript(render partial: 'repository_post_receive_urls/edit_modal') %>'); -showModal('ajax-modal', '600px'); diff --git a/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/index.api.rsb b/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/index.api.rsb deleted file mode 100644 index 4828dba..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/index.api.rsb +++ /dev/null @@ -1,13 +0,0 @@ -api.array :repository_post_receive_urls, api_meta(total_count: @repository_post_receive_urls.count) do - @repository_post_receive_urls.each do |post_receive_url| - api.post_receive_url do - api.id post_receive_url.id - api.url post_receive_url.url - api.mode post_receive_url.mode.to_s - api.active post_receive_url.active - api.use_triggers post_receive_url.use_triggers - api.triggers post_receive_url.triggers - api.split_payloads post_receive_url.split_payloads - end - end -end diff --git a/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/index.html.slim b/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/index.html.slim deleted file mode 100644 index 9019073..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/index.html.slim +++ /dev/null @@ -1,54 +0,0 @@ -div - - if User.current.git_allowed_to? :create_repository_post_receive_urls, @repository - .contextual - = link_to l(:label_post_receive_url_add), - new_repository_post_receive_url_path(@repository), - remote: true, class: 'icon icon-add' - - h3 = l(:label_post_receive_urls) - - - if @repository_post_receive_urls.any? - table.list - thead - tr - th = l :field_url - th = l :label_mode - th = l :field_active - th = l :label_use_triggers - th = l :label_triggers - th - tbody - - @repository_post_receive_urls.each do |post_receive_url| - tr - td - = post_receive_url.url - - td - = post_receive_mode post_receive_url - - td.tick - = checked_image_with_exclamation post_receive_url.active? - - td.tick - = checked_image_with_exclamation post_receive_url.use_triggers? - - td - - post_receive_url.triggers.each do |trigger| - span.label.label-info - = trigger - - td.buttons - - if User.current.git_allowed_to?(:edit_repository_post_receive_urls, @repository) - = link_to l(:button_edit), - edit_repository_post_receive_url_path(@repository, post_receive_url), - remote: true, - class: 'icon icon-edit' - = link_to l(:button_delete), - repository_post_receive_url_path(@repository, post_receive_url), - remote: true, - method: :delete, - data: { confirm: l(:text_are_you_sure) }, - class: 'icon icon-del' - - - else - p.nodata = l :label_no_data diff --git a/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/new.js.erb b/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/new.js.erb deleted file mode 100644 index ced54c6..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/new.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$('#ajax-modal').html('<%= escape_javascript(render partial: 'repository_post_receive_urls/new_modal') %>'); -showModal('ajax-modal', '600px'); diff --git a/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/show.api.rsb b/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/show.api.rsb deleted file mode 100644 index 33d533c..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_post_receive_urls/show.api.rsb +++ /dev/null @@ -1,9 +0,0 @@ -api.post_receive_url do - api.id @post_receive_url.id - api.url @post_receive_url.url - api.mode @post_receive_url.mode.to_s - api.active @post_receive_url.active - api.use_triggers @post_receive_url.use_triggers - api.triggers @post_receive_url.triggers - api.split_payloads @post_receive_url.split_payloads -end diff --git a/plugins/redmine_git_hosting/app/views/repository_protected_branches/_edit_modal.html.slim b/plugins/redmine_git_hosting/app/views/repository_protected_branches/_edit_modal.html.slim deleted file mode 100644 index 5f01cf7..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_protected_branches/_edit_modal.html.slim +++ /dev/null @@ -1,12 +0,0 @@ -h3.title = l :label_protected_branch_edit - -= labelled_form_for :repository_protected_branche, @protected_branch, - url: repository_protected_branch_path(@repository, @protected_branch), - authenticity_token: form_authenticity_token, - html: { method: :put, class: 'tabular', remote: true } do |f| - - = render partial: 'form', locals: { f: f } - .buttons - = submit_tag l(:button_save) - ' - = link_to_function l(:button_cancel), 'hideModal(this);' diff --git a/plugins/redmine_git_hosting/app/views/repository_protected_branches/_form.html.slim b/plugins/redmine_git_hosting/app/views/repository_protected_branches/_form.html.slim deleted file mode 100644 index 7bb673d..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_protected_branches/_form.html.slim +++ /dev/null @@ -1,35 +0,0 @@ -.flash-messages = error_messages_for 'protected_branch' - -.box - p = f.text_field :path, required: true, size: 65, label: l(:label_branch_path) - p = f.select :permissions, - options_for_select(RepositoryProtectedBranche::VALID_PERMS, @protected_branch.permissions), - required: true, - label: :label_permissions - - = hidden_field_tag 'user_ids[]', '' - = hidden_field_tag 'group_ids[]', '' - - .container - .row - .col-md-6 - h4 - = font_awesome_icon 'fas_user', post_text: l(:label_user_plural), class: 'fa-lg' - - - @project.users_available.each do |user| - p style='padding: 0px;' - label style='margin-left: 0; width: auto; font-weight: lighter;' - = check_box_tag 'user_ids[]', user.id, @protected_branch.users.include?(user) - = user - br - - .col-md-6 - h4 - = font_awesome_icon 'fas_users', post_text: l(:label_group_plural), class: 'fa-lg' - - - @project.groups_available.each do |group| - p style= 'padding: 0px;' - label style='margin-left: 0; width: auto; font-weight: lighter;' - = check_box_tag 'group_ids[]', group.id, @protected_branch.groups.include?(group) - = group - br diff --git a/plugins/redmine_git_hosting/app/views/repository_protected_branches/_new_modal.html.slim b/plugins/redmine_git_hosting/app/views/repository_protected_branches/_new_modal.html.slim deleted file mode 100644 index 2ce1f95..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_protected_branches/_new_modal.html.slim +++ /dev/null @@ -1,12 +0,0 @@ -h3.title = l :label_protected_branch_add - -= labelled_form_for :repository_protected_branche, @protected_branch, - url: repository_protected_branches_path(@repository), - authenticity_token: form_authenticity_token, - html: { method: :post, class: 'tabular', remote: true } do |f| - - = render partial: 'form', locals: { f: f } - .buttons - = submit_tag l(:button_add) - ' - = link_to_function l(:button_cancel), 'hideModal(this);' diff --git a/plugins/redmine_git_hosting/app/views/repository_protected_branches/edit.js.erb b/plugins/redmine_git_hosting/app/views/repository_protected_branches/edit.js.erb deleted file mode 100644 index c57013f..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_protected_branches/edit.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$('#ajax-modal').html('<%= escape_javascript(render partial: 'repository_protected_branches/edit_modal') %>'); -showModal('ajax-modal', '600px'); diff --git a/plugins/redmine_git_hosting/app/views/repository_protected_branches/index.api.rsb b/plugins/redmine_git_hosting/app/views/repository_protected_branches/index.api.rsb deleted file mode 100644 index b708ecf..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_protected_branches/index.api.rsb +++ /dev/null @@ -1,11 +0,0 @@ -api.array :repository_protected_branches, api_meta(total_count: @repository_protected_branches.count) do - @repository_protected_branches.each do |protected_branch| - api.protected_branch do - api.id protected_branch.id - api.path protected_branch.path - api.permissions protected_branch.permissions - api.user_list protected_branch.user_list - api.position protected_branch.position - end - end -end diff --git a/plugins/redmine_git_hosting/app/views/repository_protected_branches/index.html.slim b/plugins/redmine_git_hosting/app/views/repository_protected_branches/index.html.slim deleted file mode 100644 index d5421e8..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_protected_branches/index.html.slim +++ /dev/null @@ -1,70 +0,0 @@ -div - - if User.current.git_allowed_to? :create_repository_protected_branches, @repository - .contextual - = link_to l(:label_protected_branch_add), - new_repository_protected_branch_path(@repository), - remote: true, class: 'icon icon-add' - - h3 - = l(:label_protected_branches) - = link_to "(#{l(:label_gitolite_documentation)})", 'https://gitolite.com/gitolite/conf.html#rules', class: 'external' - - - if @repository_protected_branches.any? - table#protected_branches.list[ - data-update-url="#{sort_repository_protected_branches_url}" - style="opacity: #{@repository.protected_branches_enabled? ? '1' : '0.5'}"] - thead - tr - th - th = l :label_permissions - th = l :label_branch_path - th = l :label_user_list - th - - tbody - - @repository_protected_branches.each do |protected_branch| - tr.protected_branch id="protected_branch_#{protected_branch.id}" - td - span.handle - | [drag] - td - - color = protected_branch.permissions == '-' ? 'error' : 'success' - span.label class="label-#{color}" - = protected_branch.permissions - - td style='font-family: Consolas;' - = protected_branch.path - - td - - cnt = 0 - - protected_branch.users.each do |user| - - if cnt.positive? - ' , - = link_to_user user - - cnt += 1 - - td.buttons - - if User.current.git_allowed_to?(:edit_repository_protected_branches, @repository) - = link_to l(:button_edit), - edit_repository_protected_branch_path(@repository, protected_branch), - remote: true, - class: 'icon icon-edit' - = link_to l(:button_clone), - clone_repository_protected_branch_path(@repository, protected_branch), - remote: true, - class: 'icon icon-copy' - = link_to l(:button_delete), - repository_protected_branch_path(@repository, protected_branch), - remote: true, - method: :delete, - data: { confirm: l(:text_are_you_sure) }, - class: 'icon icon-del' - - - unless @repository.protected_branches_enabled? - em = l :protected_branches_reminder - - - else - p.nodata = l :label_no_data - -javascript: - $(document).ready(function() { setSortableElement('#protected_branches tbody', '#protected_branches'); }); diff --git a/plugins/redmine_git_hosting/app/views/repository_protected_branches/new.js.erb b/plugins/redmine_git_hosting/app/views/repository_protected_branches/new.js.erb deleted file mode 100644 index fc6c984..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_protected_branches/new.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$('#ajax-modal').html('<%= escape_javascript(render partial: 'repository_protected_branches/new_modal') %>'); -showModal('ajax-modal', '600px'); diff --git a/plugins/redmine_git_hosting/app/views/repository_protected_branches/show.api.rsb b/plugins/redmine_git_hosting/app/views/repository_protected_branches/show.api.rsb deleted file mode 100644 index 83daaef..0000000 --- a/plugins/redmine_git_hosting/app/views/repository_protected_branches/show.api.rsb +++ /dev/null @@ -1,7 +0,0 @@ -api.protected_branch do - api.id @protected_branch.id - api.path @protected_branch.path - api.permissions @protected_branch.permissions - api.user_list @protected_branch.user_list - api.position @protected_branch.position -end diff --git a/plugins/redmine_git_hosting/app/views/settings/_redmine_git_hosting.html.slim b/plugins/redmine_git_hosting/app/views/settings/_redmine_git_hosting.html.slim deleted file mode 100644 index dbabe2a..0000000 --- a/plugins/redmine_git_hosting/app/views/settings/_redmine_git_hosting.html.slim +++ /dev/null @@ -1,23 +0,0 @@ -= render partial: 'common/git_hosting_js_headers' -- content_for :header_tags do - = additionals_library_load :select2 - -span - = l :label_need_help - ' : - = link_to l(:label_redmine_git_hosting_wiki), RedmineGitHosting::Config::GITHUB_WIKI, class: 'external' - -br - -span - = l :label_open_issue - ' : - = link_to l(:label_redmine_git_hosting_issue), RedmineGitHosting::Config::GITHUB_ISSUE, class: 'external' - -br -br - -= render_tabs gitolite_plugin_settings_tabs - -javascript: - $(document).ready(function() { setSettingsActiveTab(); }); diff --git a/plugins/redmine_git_hosting/app/views/settings/authors.html.slim b/plugins/redmine_git_hosting/app/views/settings/authors.html.slim deleted file mode 100644 index 61d60ae..0000000 --- a/plugins/redmine_git_hosting/app/views/settings/authors.html.slim +++ /dev/null @@ -1,4 +0,0 @@ -div style='height: 50%;' - ul.authors-list - - @authors.each do |author| - li = mail_to author.email, author.name diff --git a/plugins/redmine_git_hosting/app/views/settings/install_gitolite_hooks.js.erb b/plugins/redmine_git_hosting/app/views/settings/install_gitolite_hooks.js.erb deleted file mode 100644 index cf4ed63..0000000 --- a/plugins/redmine_git_hosting/app/views/settings/install_gitolite_hooks.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$('#ajax-modal').html("<%= escape_javascript(render partial: 'settings/redmine_git_hosting/install_hooks_result') %>"); -showModal('ajax-modal', '600px'); diff --git a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_access.html.slim b/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_access.html.slim deleted file mode 100644 index 8a6ade7..0000000 --- a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_access.html.slim +++ /dev/null @@ -1,53 +0,0 @@ -/ Gitolite Access Config -ruby: - ssh_server_domain = RedmineGitHosting::Config.get_setting :ssh_server_domain - http_server_domain = RedmineGitHosting::Config.get_setting :http_server_domain - https_server_domain = RedmineGitHosting::Config.get_setting :https_server_domain - http_server_subdir = RedmineGitHosting::Config.get_setting :http_server_subdir - gitolite_http_by_default = RedmineGitHosting::Config.get_setting :gitolite_http_by_default - -h3 = l :label_gitolite_access_config - -p - label = l :label_ssh_server_domain - = text_field_tag 'settings[ssh_server_domain]', ssh_server_domain, size: 60, required: true - br - em.info - = l :label_default_domain_name - ' : - = Setting.host_name.split('/').first - -p - label = l :label_http_server_domain - = text_field_tag 'settings[http_server_domain]', http_server_domain, size: 60, required: true - br - em.info - = l :label_default_domain_name - ' : - = Setting.host_name.split('/').first - -p - label = l :label_https_server_domain - = text_field_tag 'settings[https_server_domain]', https_server_domain, size: 60 - br - em.info - = l :label_https_server_domain_desc - -p - label = l :label_http_server_subdir - = text_field_tag 'settings[http_server_subdir]', http_server_subdir, size: 60 - -p - label = l :label_gitolite_http_by_default - = select_tag 'settings[gitolite_http_by_default]', options_for_select(RepositoryGitExtra::SMART_HTTP_OPTIONS, gitolite_http_by_default) - -p - = additionals_settings_checkbox :gitolite_daemon_by_default, - value: RedmineGitHosting::Config.get_setting(:gitolite_daemon_by_default, true), - value_is_bool: true - -p - = additionals_settings_checkbox :download_revision_enabled, - value: RedmineGitHosting::Config.get_setting(:download_revision_enabled, true), - value_is_bool: true, - label: l(:label_gitolite_download_revision_enabled) diff --git a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_cache.html.slim b/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_cache.html.slim deleted file mode 100644 index 7c9c345..0000000 --- a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_cache.html.slim +++ /dev/null @@ -1,37 +0,0 @@ -/ Gitolite Cache Config -ruby: - gitolite_cache_max_time = RedmineGitHosting::Config.get_setting :gitolite_cache_max_time - gitolite_cache_max_size = RedmineGitHosting::Config.get_setting :gitolite_cache_max_size - gitolite_cache_max_elements = RedmineGitHosting::Config.get_setting :gitolite_cache_max_elements - gitolite_cache_adapter = RedmineGitHosting::Config.get_setting :gitolite_cache_adapter - -h3 = l :label_gitolite_cache_config - -p - label = l :label_gitolite_cache_max_time - = select_tag 'settings[gitolite_cache_max_time]', options_for_select(git_cache_options, gitolite_cache_max_time) - br - -p - label = l :label_gitolite_cache_max_size - = number_field_tag 'settings[gitolite_cache_max_size]', - gitolite_cache_max_size, - size: 20, - min: -1 - em< - ' MB - br - -p - label = l :label_gitolite_cache_max_elements - = number_field_tag 'settings[gitolite_cache_max_elements]', - gitolite_cache_max_elements, - size: 20, - min: 1 - br - -p - label = l :label_gitolite_cache_adapter - = select_tag 'settings[gitolite_cache_adapter]', options_for_select(GitCache::CACHE_ADAPTERS, gitolite_cache_adapter) - br - em = l :label_gitolite_cache_adapter_desc diff --git a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_file.html.slim b/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_file.html.slim deleted file mode 100644 index ca4c21c..0000000 --- a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_file.html.slim +++ /dev/null @@ -1,55 +0,0 @@ -/ Gitolite Config File -ruby: - gitolite_config_file = RedmineGitHosting::Config.get_setting(:gitolite_config_file) - gitolite_identifier_prefix = RedmineGitHosting::Config.get_setting(:gitolite_identifier_prefix) - gitolite_identifier_strip_user_id = RedmineGitHosting::Config.get_setting(:gitolite_identifier_strip_user_id, true) - disable_button = gitolite_config_file == RedmineGitHosting::Config::GITOLITE_DEFAULT_CONFIG_FILE - -h3 = l :label_gitolite_config_file - -p - label = l :label_gitolite_config_file - = text_field_tag 'settings[gitolite_config_file]', gitolite_config_file, size: 60, required: true - -p - label = l :label_gitolite_identifier_prefix - - if disable_button - = hidden_field_tag 'settings[gitolite_identifier_prefix]', gitolite_identifier_prefix - = text_field_tag 'settings[gitolite_identifier_prefix]', gitolite_identifier_prefix, size: 60, disabled: disable_button - br - em.info - = l :label_gitolite_identifier_prefix_desc - -p - = additionals_settings_checkbox :gitolite_identifier_strip_user_id, - value: gitolite_identifier_strip_user_id, - value_is_bool: true, - disabled: disable_button - br - em.info - = l :label_gitolite_identifier_strip_user_id_desc -br - -.git_hosting_access_box - h3 = l :label_ssh_keys_current_access_patterns - - - gitolite_identifier_suffix = gitolite_identifier_strip_user_id ? '' : '_user_id' - - pre - div - | SSH Key: #{gitolite_identifier_prefix}admin#{gitolite_identifier_suffix}@redmine_1394507971_600081.pub - div - | SSH Key: #{gitolite_identifier_prefix}bob#{gitolite_identifier_suffix}@redmine_1394507971_600081.pub - - br - - div - | repo repositories/test - - div - | RW+ = #{gitolite_identifier_prefix}admin#{gitolite_identifier_suffix} - | #{gitolite_identifier_prefix}john#{gitolite_identifier_suffix} - div - | RW = #{gitolite_identifier_prefix}bob#{gitolite_identifier_suffix} alice - div - | R = #{gitolite_identifier_prefix}reporter#{gitolite_identifier_suffix} mike gitweb diff --git a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_global.html.slim b/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_global.html.slim deleted file mode 100644 index c099e02..0000000 --- a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_global.html.slim +++ /dev/null @@ -1,55 +0,0 @@ -/ Gitolite Global Config -ruby: - gitolite_recycle_bin_expiration_time = RedmineGitHosting::Config.get_setting :gitolite_recycle_bin_expiration_time - gitolite_temp_dir = RedmineGitHosting::Config.get_setting :gitolite_temp_dir - gitolite_log_level = RedmineGitHosting::Config.get_setting :gitolite_log_level - git_config_username = RedmineGitHosting::Config.get_setting :git_config_username - git_config_email = RedmineGitHosting::Config.get_setting :git_config_email - -h3 = l :label_gitolite_global_config - -p - label = l :label_gitolite_temp_dir - = text_field_tag 'settings[gitolite_temp_dir]', gitolite_temp_dir, size: 60, required: true - br - em.info - = l :label_gitolite_temp_dir_desc - -p - label = l :label_gitolite_recycle_bin_expiration_time - = number_field_tag 'settings[gitolite_recycle_bin_expiration_time]', - gitolite_recycle_bin_expiration_time, - size: 10, - required: true, - min: -1 - - br - em.info - = l :label_gitolite_recycle_bin_expiration_time_desc - -p - label = l :label_gitolite_log_level - = select_tag 'settings[gitolite_log_level]', options_for_select(log_level_options, gitolite_log_level) - br - em.info - = l :label_gitolite_log_level_desc - -p - label = l :label_git_config_username - = text_field_tag 'settings[git_config_username]', - git_config_username.to_s, - size: 60, - required: true - br - em.info - = l :label_git_config_username_desc - -p - label = l :label_git_config_email - = text_field_tag 'settings[git_config_email]', - git_config_email.to_s, - size: 60, - required: true - br - em.info - = l :label_git_config_email_desc diff --git a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_hooks.html.slim b/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_hooks.html.slim deleted file mode 100644 index c5a8d1b..0000000 --- a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_hooks.html.slim +++ /dev/null @@ -1,45 +0,0 @@ -/ Gitolite Hooks Config -- gitolite_hooks_url = RedmineGitHosting::Config.get_setting :gitolite_hooks_url - -.contextual - = link_to font_awesome_icon('fas_rocket', post_text: l(:label_install_gitolite_hooks), class: 'fa-lg'), - install_gitolite_hooks_path('redmine_git_hosting'), - remote: true - -h3 = l :label_gitolite_hooks_config - -.container - .col-md-6 style='vertical-align: top;' - p - = additionals_settings_checkbox :gitolite_overwrite_existing_hooks, - value: RedmineGitHosting::Config.get_setting(:gitolite_overwrite_existing_hooks, true), - value_is_bool: true - - p - = additionals_settings_checkbox :gitolite_hooks_are_asynchronous, - value: RedmineGitHosting::Config.get_setting(:gitolite_hooks_are_asynchronous, true), - value_is_bool: true - - p - = additionals_settings_checkbox :gitolite_hooks_debug, - value: RedmineGitHosting::Config.get_setting(:gitolite_hooks_debug, true), - value_is_bool: true - - p - label = l :label_gitolite_hooks_url - = url_field_tag 'settings[gitolite_hooks_url]', gitolite_hooks_url, size: 60, required: true - br - em.info - = l :label_default_gitolite_hooks_url - ' : - = "#{Setting.protocol}://#{Setting.host_name.split('/').first}" - - p - label = l :label_gitolite_hooks_url - span.label.label-info = RedmineGitHosting::Config.gitolite_hooks_url - - p - label = l :label_gitolite_hooks_namespace - span.label.label-info = RedmineGitHosting::Config.gitolite_hooks_namespace - -#install_gitolite_hooks diff --git a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_notify.html.slim b/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_notify.html.slim deleted file mode 100644 index 6552fb8..0000000 --- a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_notify.html.slim +++ /dev/null @@ -1,39 +0,0 @@ -/ Gitolite Notifications Config -ruby: - gitolite_notify_global_prefix = RedmineGitHosting::Config.get_setting :gitolite_notify_global_prefix - gitolite_notify_global_sender_address = RedmineGitHosting::Config.get_setting :gitolite_notify_global_sender_address - gitolite_notify_global_include = RedmineGitHosting::Config.get_setting :gitolite_notify_global_include - gitolite_notify_global_exclude = RedmineGitHosting::Config.get_setting :gitolite_notify_global_exclude - -h3 = l :label_gitolite_notify_config - -p - = additionals_settings_checkbox :gitolite_notify_by_default, - value: RedmineGitHosting::Config.get_setting(:gitolite_notify_by_default, true), - value_is_bool: true - -p - label = l :label_gitolite_notify_global_prefix - = text_field_tag 'settings[gitolite_notify_global_prefix]', gitolite_notify_global_prefix, size: 60 - -p - label = l :label_gitolite_notify_global_sender_address - = text_field_tag 'settings[gitolite_notify_global_sender_address]', gitolite_notify_global_sender_address, size: 60 - -p - label = l :label_gitolite_notify_global_include - = additionals_select2_tag 'settings[gitolite_notify_global_include]', - options_for_select(gitolite_notify_global_include.map { |mail| [mail, mail] }, gitolite_notify_global_include), - data: gitolite_notify_global_include, - multiple: true, - placeholder: '+ add email', - tags: true - -p - label = l :label_gitolite_notify_global_exclude - = additionals_select2_tag 'settings[gitolite_notify_global_exclude]', - options_for_select(gitolite_notify_global_exclude.map { |mail| [mail, mail] }, gitolite_notify_global_exclude), - data: gitolite_notify_global_exclude, - multiple: true, - placeholder: '+ add email', - tags: true diff --git a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_ssh.html.slim b/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_ssh.html.slim deleted file mode 100644 index d8d6f10..0000000 --- a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_ssh.html.slim +++ /dev/null @@ -1,46 +0,0 @@ -/ Gitolite SSH Config -ruby: - gitolite_user = RedmineGitHosting::Config.get_setting :gitolite_user - gitolite_server_host = RedmineGitHosting::Config.get_setting :gitolite_server_host - gitolite_server_port = RedmineGitHosting::Config.get_setting :gitolite_server_port - gitolite_ssh_private_key = RedmineGitHosting::Config.get_setting :gitolite_ssh_private_key - gitolite_ssh_public_key = RedmineGitHosting::Config.get_setting :gitolite_ssh_public_key - -h3 = l :label_gitolite_ssh_config - -p - label = l(:label_gitolite_user) - = text_field_tag 'settings[gitolite_user]', - gitolite_user, - size: 20, - required: true - -p - label = l(:label_gitolite_ssh_private_key) - = text_field_tag 'settings[gitolite_ssh_private_key]', - gitolite_ssh_private_key, - size: 110, - required: true - -p - label = l(:label_gitolite_ssh_public_key) - = text_field_tag 'settings[gitolite_ssh_public_key]', - gitolite_ssh_public_key, - size: 110, - required: true - -p - label = l(:label_gitolite_server_host) - = text_field_tag 'settings[gitolite_server_host]', - gitolite_server_host, - size: 20, - required: true - -p - label = l(:label_gitolite_server_port) - = number_field_tag 'settings[gitolite_server_port]', - gitolite_server_port, - size: 5, - min: 1, - max: 65_535, - required: true diff --git a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_storage.html.slim b/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_storage.html.slim deleted file mode 100644 index dcdcc6d..0000000 --- a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_storage.html.slim +++ /dev/null @@ -1,33 +0,0 @@ -/ Gitolite Storage Config -- gitolite_global_storage_dir = RedmineGitHosting::Config.get_setting(:gitolite_global_storage_dir) -- gitolite_redmine_storage_dir = RedmineGitHosting::Config.get_setting(:gitolite_redmine_storage_dir) -- gitolite_recycle_bin_dir = RedmineGitHosting::Config.get_setting(:gitolite_recycle_bin_dir) - -h3 = l(:label_gitolite_storage_config) - -p - label = l(:label_gitolite_global_storage_dir) - = text_field_tag 'settings[gitolite_global_storage_dir]', - gitolite_global_storage_dir, - size: 60, - required: true - br - em.info - = l(:label_gitolite_global_storage_dir_desc) - -p - label = l(:label_gitolite_recycle_bin_dir) - = text_field_tag 'settings[gitolite_recycle_bin_dir]', - gitolite_recycle_bin_dir, - size: 60, - required: true - br - em.info - = l(:label_gitolite_recycle_bin_dir_desc) - -p - label = l(:label_gitolite_redmine_storage_dir) - = text_field_tag 'settings[gitolite_redmine_storage_dir]', gitolite_redmine_storage_dir, size: 60 - br - em.info - = l(:label_gitolite_redmine_storage_dir_desc) diff --git a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_test.html.slim b/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_test.html.slim deleted file mode 100644 index ba6bed3..0000000 --- a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_config_test.html.slim +++ /dev/null @@ -1,94 +0,0 @@ -h3 = l :label_permissions_header - -table.list.git-results - tr - td = l(:label_temp_dir_writeable) - td = render_temp_dir_writeable(RedmineGitHosting::Config.temp_dir_writeable?(reset: true), RedmineGitHosting::Config.gitolite_admin_dir) - - tr - td = l(:label_redmine_user) - td - span.label.label-success = RedmineGitHosting::Config.redmine_user - - tr - td = l(:label_gitolite_user) - td - span.label.label-success = RedmineGitHosting::Config.gitolite_user - - tr - td = l(:label_sudo_redmine_to_gitolite_user) - td - = image_tag(RedmineGitHosting::Config.can_redmine_sudo_to_gitolite_user? ? 'true.png' : 'exclamation.png') - - tr - td = l :label_gitolite_bin_dir - td - - if RedmineGitHosting::Config.gitolite_bin_dir - span.label.label-success RedmineGitHosting::Config.gitolite_bin_dir - - else - = image_tag 'exclamation.png' - - tr - td = l :label_gitolite_lib_dir - td - - if RedmineGitHosting::Config.gitolite_lib_dir - span.label.label-success RedmineGitHosting::Config.gitolite_lib_dir - - else - = image_tag 'exclamation.png' - - tr - td = l :label_gitolite_local_code_dir - td - - if RedmineGitHosting::Config.gitolite_local_code_dir - span.label.label-success = RedmineGitHosting::Config.gitolite_local_code_dir - - else - = image_tag('exclamation.png') - - - gitolite_checks = RedmineGitHosting::Config.check_hooks_install! - - tr - td = l :label_gitolite_hooks_installed - td = render_gitolite_params_status(gitolite_checks[:hook_files]) - - tr - td = l :label_gitolite_hooks_params_installed - td = render_gitolite_params_status(gitolite_checks[:global_params]) - - tr - td = l :label_gitolite_mailer_params_installed - td = render_gitolite_params_status(gitolite_checks[:mailer_params]) - - tr - td = l :label_mirroring_keys_installed - td - = image_tag(RedmineGitHosting::Config.mirroring_keys_installed? ? 'true.png' : 'exclamation.png') - - tr - td = l :label_git_version - td - span.label.label-success = Repository::Xitolite.scm_version_string - - tr - td = l :label_gitolite_version - td = render_gitolite_version(RedmineGitHosting::Config.gitolite_version) - - tr - td = l(:label_gitolite_repository_count) - td - span.label.label-success = RedmineGitHosting::Config.gitolite_repository_count - - tr - td = l :label_gitolite_rugged_features - td - = render_rugged_mandatory_features - = render_rugged_optional_features - -br -fieldset.box.tabular - legend = l :label_gitolite_banner - pre == RedmineGitHosting::Config.gitolite_banner - -br -fieldset.box.tabular - legend = l(:label_path_directories) - pre == (ENV['PATH']).gsub(/:/, '
') diff --git a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_display_access.html.slim b/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_display_access.html.slim deleted file mode 100644 index a7b1768..0000000 --- a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_display_access.html.slim +++ /dev/null @@ -1,130 +0,0 @@ -/ Gitolite Display Access -ruby: - gitolite_user = RedmineGitHosting::Config.get_setting :gitolite_user - ssh_server_domain = RedmineGitHosting::Config.get_setting :ssh_server_domain - git_shp = ssh_server_domain.match(/:\d+$/) - gitolite_global_storage_dir = RedmineGitHosting::Config.get_setting :gitolite_global_storage_dir - gitolite_redmine_storage_dir = RedmineGitHosting::Config.get_setting :gitolite_redmine_storage_dir - http_server_subdir = RedmineGitHosting::Config.get_setting :http_server_subdir - http_server_domain = RedmineGitHosting::Config.http_root_url - https_server_domain = RedmineGitHosting::Config.https_root_url - hierarchical_organisation = RedmineGitHosting::Config.get_setting :hierarchical_organisation, true - -.git_hosting_access_box - - h3 = l :label_repos_current_access_patterns - - span = t :display_access_setup1_html - br - br - span = t :display_access_setup2_html - br - br - span = t :display_access_setup3_html - - p - label = l(:label_default_repository) - br - - label - = l :label_storage_directory - ' : - - = "~#{gitolite_user}/#{gitolite_global_storage_dir}#{gitolite_redmine_storage_dir}" - em - = "#{'project1/project2/' if hierarchical_organisation}project3.git" - - br - - label - = l :label_ssh_access - ' : - - = "#{'ssh://' if git_shp}#{gitolite_user}@#{ssh_server_domain}#{git_shp ? '/' : ':'}#{gitolite_redmine_storage_dir}" - em - = "#{'project1/project2/' if hierarchical_organisation}project3.git" - - br - - label - = l :label_http_access - ' : - - | http:// - em - | redmine-user - = "@#{https_server_domain}/#{http_server_subdir}" - em - = "#{'project1/project2/' if hierarchical_organisation}project3.git" - - br - - label - = l :label_https_access - ' : - - | https:// - em - | redmine-user - = "@#{https_server_domain}/#{http_server_subdir}" - em - = "#{'project1/project2/' if hierarchical_organisation}project3.git" - - p - label = l :label_example_repository - br - - label - = l :label_storage_directory - ' : - - = "~#{gitolite_user}/#{gitolite_global_storage_dir}#{gitolite_redmine_storage_dir}" - em - = "#{'project1/project2/project3/' if hierarchical_organisation}example.git" - - br - - label - = l :label_ssh_access - ' : - - = "#{'ssh://' if git_shp}#{gitolite_user}@#{ssh_server_domain}#{git_shp ? '/' : ':'}#{gitolite_redmine_storage_dir}" - em - = "#{'project1/project2/project3/' if hierarchical_organisation}example.git" - - br - - label - = l :label_http_access - ' : - - | http:// - em - | redmine-user - = "@#{https_server_domain}/#{http_server_subdir}" - em - = "#{'project1/project2/project3/' if hierarchical_organisation}example.git" - - br - - label - = l :label_https_access - ' : - - | https:// - em - | redmine-user - = "@#{https_server_domain}/#{http_server_subdir}" - em - = "#{'project1/project2/project3/' if hierarchical_organisation}example.git" - - br - br - - label - = l :label_etcetera - | ... - - = t :display_access_emphasis_html - ' - == hierarchical_organisation ? l(:display_access_hierarchical) : l(:display_access_flat) diff --git a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_recycle_bin.html.slim b/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_recycle_bin.html.slim deleted file mode 100644 index effd9f1..0000000 --- a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_recycle_bin.html.slim +++ /dev/null @@ -1,28 +0,0 @@ -h3 = l(:label_empty_recycle_bin) - -- if !RedmineGitHosting::RecycleBin || !RedmineGitHosting::RecycleBin.content.empty? - table.list - tr - th = l(:label_repository) - th = l(:label_recycle_bin_content_size) - th - = l(:label_delete_from_recyle_bin) - | ( - = link_to l(:label_select_all), 'javascript:void(0);', id: 'select_all_delete' - | ) - - - RedmineGitHosting::RecycleBin.content.each do |trash_object| - tr - td = trash_object.path - td = trash_object.size - td = check_box_tag 'settings[rescue][delete_trash_repo][]', trash_object.path, false, class: 'empty_trash' - - #delete_warning.alert.alert-error style='display: none;' - = l(:label_delete_warning) - -- else - p.nodata style='padding: 5px 0 0;' - = l(:label_no_data) - -javascript: - $(document).ready(function() { setRecycleBinWarnings(); }); diff --git a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_rescue.html.slim b/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_rescue.html.slim deleted file mode 100644 index 9758818..0000000 --- a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_gitolite_rescue.html.slim +++ /dev/null @@ -1,11 +0,0 @@ -p - = label_tag 'settings[rescue][resync_all_projects]', l(:label_resync_all_projects) - = check_box_tag 'settings[rescue][resync_all_projects]', 'true', false - -p - = label_tag 'settings[rescue][resync_all_ssh_keys]', l(:label_resync_all_ssh_keys) - = check_box_tag 'settings[rescue][resync_all_ssh_keys]', 'true', false - -p - = label_tag 'settings[rescue][flush_gitolite_cache]', l(:label_flush_cache) - = check_box_tag 'settings[rescue][flush_gitolite_cache]', 'true', false diff --git a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_install_hooks_result.html.slim b/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_install_hooks_result.html.slim deleted file mode 100644 index 5ce8a1b..0000000 --- a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_install_hooks_result.html.slim +++ /dev/null @@ -1,15 +0,0 @@ -h3.title = l :label_install_hook_results - -table.list.git-results - tr - td = l :label_gitolite_hooks_installed - td = render_gitolite_params_status @gitolite_checks[:hook_files] - tr - td = l :label_gitolite_hooks_params_installed - td = render_gitolite_params_status @gitolite_checks[:global_params] - tr - td = l :label_gitolite_mailer_params_installed - td = render_gitolite_params_status @gitolite_checks[:mailer_params] - -.buttons - = link_to_function l(:button_cancel), 'hideModal(this);' diff --git a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_redmine_config.html.slim b/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_redmine_config.html.slim deleted file mode 100644 index 3f97631..0000000 --- a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_redmine_config.html.slim +++ /dev/null @@ -1,34 +0,0 @@ -/ Redmine Config -- all_projects_use_git = RedmineGitHosting::Config.get_setting(:all_projects_use_git, true) - -h3 = l :label_redmine_config - -p - = additionals_settings_checkbox :redmine_has_rw_access_on_all_repos, - value: RedmineGitHosting::Config.get_setting(:redmine_has_rw_access_on_all_repos, true), - value_is_bool: true - -p - = additionals_settings_checkbox :all_projects_use_git, value: all_projects_use_git, value_is_bool: true - -p - = additionals_settings_checkbox :init_repositories_on_create, - value: RedmineGitHosting::Config.get_setting(:init_repositories_on_create, true), - value_is_bool: true, - disabled: !all_projects_use_git - -p - = additionals_settings_checkbox :delete_git_repositories, - value: RedmineGitHosting::Config.get_setting(:delete_git_repositories, true), - value_is_bool: true - em.info - = l(:info_delete_git_repositories) - -p - = additionals_settings_checkbox :hierarchical_organisation, - value: RedmineGitHosting::Config.get_setting(:hierarchical_organisation, true), - value_is_bool: true - -br - -= render partial: 'settings/redmine_git_hosting/gitolite_display_access' diff --git a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_sidekiq_interface.html.slim b/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_sidekiq_interface.html.slim deleted file mode 100644 index ddbaa44..0000000 --- a/plugins/redmine_git_hosting/app/views/settings/redmine_git_hosting/_sidekiq_interface.html.slim +++ /dev/null @@ -1,5 +0,0 @@ -/ Gitolite Sidekiq Config -p - = additionals_settings_checkbox :gitolite_use_sidekiq, - value: RedmineGitHosting::Config.get_setting(:gitolite_use_sidekiq, true), - value_is_bool: true diff --git a/plugins/redmine_git_hosting/app/views/users/index.api.rsb b/plugins/redmine_git_hosting/app/views/users/index.api.rsb deleted file mode 100644 index 14f583f..0000000 --- a/plugins/redmine_git_hosting/app/views/users/index.api.rsb +++ /dev/null @@ -1,29 +0,0 @@ -api.array :users, api_meta(total_count: @user_count, offset: @offset, limit: @limit) do - @users.each do |user| - api.user do - api.id user.id - api.login user.login - api.admin user.admin? - api.firstname user.firstname - api.lastname user.lastname - api.mail user.mail - api.created_on user.created_on - api.updated_on user.updated_on - api.last_login_on user.last_login_on - api.passwd_changed_on user.passwd_changed_on - - 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 - - render_api_custom_values user.visible_custom_field_values, api - end - end -end diff --git a/plugins/redmine_git_hosting/app/workers/githosting_shell_worker.rb b/plugins/redmine_git_hosting/app/workers/githosting_shell_worker.rb deleted file mode 100644 index 2c3b34a..0000000 --- a/plugins/redmine_git_hosting/app/workers/githosting_shell_worker.rb +++ /dev/null @@ -1,19 +0,0 @@ -class GithostingShellWorker - include Sidekiq::Worker - - sidekiq_options queue: :redmine_git_hosting, retry: false - - def self.maybe_do(command, object, options = {}) - args = [command.to_s, object, options] - Sidekiq::Queue.new(:redmine_git_hosting).each do |job| - return if job.args == args - end - - perform_async(command, object, options) - end - - def perform(command, object, options = {}) - logger.info("#{command} | #{object} | #{options}") - RedmineGitHosting::GitoliteWrapper.resync_gitolite(command, object, options) - end -end diff --git a/plugins/redmine_git_hosting/assets/images/button.svg b/plugins/redmine_git_hosting/assets/images/button.svg deleted file mode 100644 index 85f84a8..0000000 --- a/plugins/redmine_git_hosting/assets/images/button.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/plugins/redmine_git_hosting/assets/images/button_focus.svg b/plugins/redmine_git_hosting/assets/images/button_focus.svg deleted file mode 100644 index 564b1a3..0000000 --- a/plugins/redmine_git_hosting/assets/images/button_focus.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/plugins/redmine_git_hosting/assets/images/button_selected.svg b/plugins/redmine_git_hosting/assets/images/button_selected.svg deleted file mode 100644 index 3aeba71..0000000 --- a/plugins/redmine_git_hosting/assets/images/button_selected.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/plugins/redmine_git_hosting/assets/javascripts/application.js b/plugins/redmine_git_hosting/assets/javascripts/application.js deleted file mode 100644 index d1c8d9e..0000000 --- a/plugins/redmine_git_hosting/assets/javascripts/application.js +++ /dev/null @@ -1,115 +0,0 @@ -function post_mode_change(element) { - if (!element) return; - var idx = element.selectedIndex; - if (idx == 0) { - $('#payload_options').show(); - } else { - $('#payload_options').hide(); - } -} - -function push_mode_change(element) { - if (!element) return; - var idx = element.selectedIndex; - if (idx == 0) { - $('#ref_spec_options').hide(); - } else { - $('#ref_spec_options').show(); - } -} - -function key_mode_change(element) { - if (!element) return; - var idx = element.selectedIndex; - if (idx == 0) { - $('#new_key_window').show(); - } else { - $('#new_key_window').hide(); - } -} - -function trigger_mode_change(element) { - element = $('#'+element.id); - if(element.is(":checked")) { - $('#triggers_options').show(); - } else { - $('#triggers_options').hide(); - } -} - - -// REPOSITORY EDIT -function setRepositoryActiveTab(current_tab) { - var all_tabs = $("#repository-tabs li"); - var active_tab = ''; - - all_tabs.each(function(){ - if ($(this).attr('id').replace('tab-', '') == current_tab) { - active_tab = all_tabs.index(this); - } - }); - - $("#repository-tabs").tabs({ - active: active_tab, - activate: function(event, ui) { - var new_tab_name = $(ui.newTab).attr('id').replace('tab-', ''); - if ("replaceState" in window.history) { - window.history.replaceState(null, document.title, 'edit?tab=' + new_tab_name); - } - } - }); -} - -function setSettingsActiveTab() { - groups = $('[id^=tab-gitolite_]'); - - $.each(groups, function(key, elem) { - $(elem).on('click', function(){ - if ("replaceState" in window.history) { - window.history.replaceState(null, document.title, 'redmine_git_hosting?tab=' + $(this).attr('id').replace('tab-', '')); - } - }); - }); -} - -function displayWarning(){ - var checked_list = $(".empty_trash:checked"); - if(checked_list.length === 0){ - $('#delete_warning').hide(); - } else { - $('#delete_warning').show(); - } -} - -function setRecycleBinWarnings() { - $("#select_all_delete").on('click', function(){ - $('.empty_trash').each(function(){ - $(this).attr('checked', !$(this).attr('checked')); - displayWarning(); - }); - }); - - $(".empty_trash").on('change', function(){ - displayWarning(); - }); -} - - -// table sort -// Return a helper with preserved width of cells -var fixHelper = function(e, ui) { - ui.children().each(function() { - $(this).width($(this).width()); - }); - return ui; -}; - -function setSortableElement(element, form) { - $(element).sortable({ - helper: fixHelper, - axis: 'y', - update: function(event, ui) { - $.post($(form).data('update-url'), $(this).sortable('serialize'), null, 'script'); - } - }); -} diff --git a/plugins/redmine_git_hosting/assets/javascripts/git_urls.js b/plugins/redmine_git_hosting/assets/javascripts/git_urls.js deleted file mode 100644 index 9de3454..0000000 --- a/plugins/redmine_git_hosting/assets/javascripts/git_urls.js +++ /dev/null @@ -1,48 +0,0 @@ -// GIT URLS -function updateUrl(element) { - var url = $(element).data('url'); - var target = $(element).data('target'); - var committer = $(element).data('committer'); - $('#git_url_text_' + target).val(url); - $('#git_url_permissions_' + target).html(committer); - $(element).parent().find('li').removeClass('selected'); - $(element).addClass('selected'); -} - -function setGitUrls(elements) { - $(elements).each(function(index, element){ - $(element).on('click', function(){ - updateUrl($(this)); - }); - }); -} - -function setFirstGitUrl(elements) { - $(elements).each(function(index, element){ - var first_url = $(element).children().first(); - updateUrl(first_url); - }); -} - -// GIT INSTRUCTIONS -function updateInstructionUrl(element) { - var url = $(element).data('url'); - var committer = $(element).data('committer'); - $('.git_url_access').html(url); - if (committer == 'RW') { - $('#repository_setup').show(); - } else { - $('#repository_setup').hide(); - } -} - -function setGitUrlsInstructions(elements) { - $(elements).each(function(index, element){ - if (index == 0){ - updateInstructionUrl(element); - }; - $(element).on('click', function(){ - updateInstructionUrl($(this)); - }); - }); -} diff --git a/plugins/redmine_git_hosting/assets/javascripts/highcharts/highcharts.js b/plugins/redmine_git_hosting/assets/javascripts/highcharts/highcharts.js deleted file mode 100644 index 81ce353..0000000 --- a/plugins/redmine_git_hosting/assets/javascripts/highcharts/highcharts.js +++ /dev/null @@ -1,324 +0,0 @@ -/* - Highcharts JS v4.1.4 (2015-03-10) - - (c) 2009-2014 Torstein Honsi - - License: www.highcharts.com/license -*/ -(function(){function z(){var a,b=arguments,c,d={},e=function(a,b){var c,d;typeof a!=="object"&&(a={});for(d in b)b.hasOwnProperty(d)&&(c=b[d],a[d]=c&&typeof c==="object"&&Object.prototype.toString.call(c)!=="[object Array]"&&d!=="renderTo"&&typeof c.nodeType!=="number"?e(a[d]||{},c):b[d]);return a};b[0]===!0&&(d=b[1],b=Array.prototype.slice.call(b,2));c=b.length;for(a=0;a-1?h.thousandsSep:""))):e=Oa(f,e)}j.push(e);a=a.slice(c+1);c=(d=!d)?"}":"{"}j.push(a);return j.join("")}function ob(a){return V.pow(10,U(V.log(a)/V.LN10))}function pb(a,b,c,d,e){var f,g=a,c=p(c,1);f=a/c;b||(b=[1,2,2.5,5,10],d===!1&&(c=== -1?b=[1,2,5,10]:c<=0.1&&(b=[1/c])));for(d=0;d=a||!e&&f<=(b[d]+(b[d+1]||b[d]))/2)break;g*=c;return g}function qb(a,b){var c=a.length,d,e;for(e=0;ec&&(c=a[b]);return c}function Qa(a,b){for(var c in a)a[c]&&a[c]!==b&&a[c].destroy&&a[c].destroy(), -delete a[c]}function Ra(a){fb||(fb=Z(Ka));a&&fb.appendChild(a);fb.innerHTML=""}function ka(a,b){var c="Highcharts error #"+a+": www.highcharts.com/errors/"+a;if(b)throw c;O.console&&console.log(c)}function da(a){return parseFloat(a.toPrecision(14))}function Sa(a,b){za=p(a,b.animation)}function Cb(){var a=S.global,b=a.useUTC,c=b?"getUTC":"get",d=b?"setUTC":"set";Aa=a.Date||window.Date;nb=b&&a.timezoneOffset;eb=b&&a.getTimezoneOffset;gb=function(a,c,d,h,i,j){var k;b?(k=Aa.UTC.apply(0,arguments),k+= -Wa(k)):k=(new Aa(a,c,p(d,1),p(h,0),p(i,0),p(j,0))).getTime();return k};rb=c+"Minutes";sb=c+"Hours";tb=c+"Day";Xa=c+"Date";Ya=c+"Month";Za=c+"FullYear";Db=d+"Minutes";Eb=d+"Hours";ub=d+"Date";vb=d+"Month";wb=d+"FullYear"}function L(){}function Ta(a,b,c,d){this.axis=a;this.pos=b;this.type=c||"";this.isNew=!0;!c&&!d&&this.addLabel()}function Fb(a,b,c,d,e){var f=a.chart.inverted;this.axis=a;this.isNegative=c;this.options=b;this.x=d;this.total=null;this.points={};this.stack=e;this.alignOptions={align:b.align|| -(f?c?"left":"right":"center"),verticalAlign:b.verticalAlign||(f?"middle":c?"bottom":"top"),y:p(b.y,f?4:c?14:-6),x:p(b.x,f?c?-6:6:0)};this.textAlign=b.textAlign||(f?c?"right":"left":"center")}var v,D=document,O=window,V=Math,w=V.round,U=V.floor,sa=V.ceil,t=V.max,H=V.min,P=V.abs,W=V.cos,$=V.sin,la=V.PI,ga=la*2/360,Ba=navigator.userAgent,Gb=O.opera,ya=/(msie|trident)/i.test(Ba)&&!Gb,hb=D.documentMode===8,xb=/AppleWebKit/.test(Ba),La=/Firefox/.test(Ba),Hb=/(Mobile|Android|Windows Phone)/.test(Ba),Ca= -"http://www.w3.org/2000/svg",ba=!!D.createElementNS&&!!D.createElementNS(Ca,"svg").createSVGRect,Lb=La&&parseInt(Ba.split("Firefox/")[1],10)<4,ea=!ba&&!ya&&!!D.createElement("canvas").getContext,$a,ab,Ib={},yb=0,fb,S,Oa,za,zb,F,ma=function(){return v},X=[],bb=0,Ka="div",M="none",Mb=/^[0-9]+$/,ib=["plotTop","marginRight","marginBottom","plotLeft"],Nb="stroke-width",Aa,gb,nb,eb,rb,sb,tb,Xa,Ya,Za,Db,Eb,ub,vb,wb,N={},y;y=O.Highcharts=O.Highcharts?ka(16,!0):{};y.seriesTypes=N;var q=y.extend=function(a, -b){var c;a||(a={});for(c in b)a[c]=b[c];return a},p=y.pick=function(){var a=arguments,b,c,d=a.length;for(b=0;b3?c.length%3:0;return e+(g?c.substr(0,g)+d:"")+c.substr(g).replace(/(\d{3})(?=\d)/g,"$1"+d)+(f?b+P(a-c).toFixed(f).slice(2):"")};zb={init:function(a,b,c){var b=b||"",d=a.shift,e=b.indexOf("C")>-1,f=e?7:3,g,b=b.split(" "),c=[].concat(c),h,i,j=function(a){for(g=a.length;g--;)a[g]==="M"&&a.splice(g+ -1,0,a[g+1],a[g+2],a[g+1],a[g+2])};e&&(j(b),j(c));a.isArea&&(h=b.splice(b.length-6,6),i=c.splice(c.length-6,6));if(d<=c.length/f&&b.length===c.length)for(;d--;)c=[].concat(c).splice(0,f).concat(c);a.shift=0;if(b.length)for(a=c.length;b.length{point.key}
',pointFormat:' {series.name}: {point.y}
', -shadow:!0,snap:Hb?25:10,style:{color:"#333333",cursor:"default",fontSize:"12px",padding:"8px",whiteSpace:"nowrap"}},credits:{enabled:!0,text:"Highcharts.com",href:"http://www.highcharts.com",position:{align:"right",x:-10,verticalAlign:"bottom",y:-5},style:{cursor:"pointer",color:"#909090",fontSize:"9px"}}};var aa=S.plotOptions,Q=aa.line;Cb();var Rb=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/,Sb=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/, -Tb=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/,na=function(a){var b=[],c,d;(function(a){a&&a.stops?d=Ua(a.stops,function(a){return na(a[1])}):(c=Rb.exec(a))?b=[C(c[1]),C(c[2]),C(c[3]),parseFloat(c[4],10)]:(c=Sb.exec(a))?b=[C(c[1],16),C(c[2],16),C(c[3],16),1]:(c=Tb.exec(a))&&(b=[C(c[1]),C(c[2]),C(c[3]),1])})(a);return{get:function(c){var f;d?(f=z(a),f.stops=[].concat(f.stops),m(d,function(a,b){f.stops[b]=[f.stops[b][0],a.get(c)]})):f=b&&!isNaN(b[0])?c==="rgb"?"rgb("+b[0]+","+ -b[1]+","+b[2]+")":c==="a"?b[3]:"rgba("+b.join(",")+")":a;return f},brighten:function(a){if(d)m(d,function(b){b.brighten(a)});else if(qa(a)&&a!==0){var c;for(c=0;c<3;c++)b[c]+=C(a*255),b[c]<0&&(b[c]=0),b[c]>255&&(b[c]=255)}return this},rgba:b,setOpacity:function(a){b[3]=a;return this},raw:a}};L.prototype={opacity:1,textProps:"fontSize,fontWeight,fontFamily,color,lineHeight,width,textDecoration,textShadow".split(","),init:function(a,b){this.element=b==="span"?Z(b):D.createElementNS(Ca,b);this.renderer= -a},animate:function(a,b,c){b=p(b,za,!0);db(this);if(b){b=z(b,{});if(c)b.complete=c;lb(this,a,b)}else this.attr(a),c&&c();return this},colorGradient:function(a,b,c){var d=this.renderer,e,f,g,h,i,j,k,l,n,o,s=[];a.linearGradient?f="linearGradient":a.radialGradient&&(f="radialGradient");if(f){g=a[f];h=d.gradients;j=a.stops;n=c.radialReference;Ha(g)&&(a[f]=g={x1:g[0],y1:g[1],x2:g[2],y2:g[3],gradientUnits:"userSpaceOnUse"});f==="radialGradient"&&n&&!r(g.gradientUnits)&&(g=z(g,{cx:n[0]-n[2]/2+g.cx*n[2], -cy:n[1]-n[2]/2+g.cy*n[2],r:g.r*n[2],gradientUnits:"userSpaceOnUse"}));for(o in g)o!=="id"&&s.push(o,g[o]);for(o in j)s.push(j[o]);s=s.join(",");h[s]?a=h[s].attr("id"):(g.id=a="highcharts-"+yb++,h[s]=i=d.createElement(f).attr(g).add(d.defs),i.stops=[],m(j,function(a){a[1].indexOf("rgba")===0?(e=na(a[1]),k=e.get("rgb"),l=e.get("a")):(k=a[1],l=1);a=d.createElement("stop").attr({offset:a[0],"stop-color":k,"stop-opacity":l}).add(i);i.stops.push(a)}));c.setAttribute(b,"url("+d.url+"#"+a+")")}},applyTextShadow:function(a){var b= -this.element,c,d=a.indexOf("contrast")!==-1,e=this.renderer.forExport||b.style.textShadow!==v&&!ya;d&&(a=a.replace(/contrast/g,this.renderer.getContrast(b.style.fill)));e?d&&J(b,{textShadow:a}):(this.fakeTS=!0,this.ySetter=this.xSetter,c=[].slice.call(b.getElementsByTagName("tspan")),m(a.split(/\s?,\s?/g),function(a){var d=b.firstChild,e,i,a=a.split(" ");e=a[a.length-1];(i=a[a.length-2])&&m(c,function(a,c){var f;c===0&&(a.setAttribute("x",b.getAttribute("x")),c=b.getAttribute("y"),a.setAttribute("y", -c||0),c===null&&b.setAttribute("y",0));f=a.cloneNode(1);I(f,{"class":"highcharts-text-shadow",fill:e,stroke:e,"stroke-opacity":1/t(C(i),3),"stroke-width":i,"stroke-linejoin":"round"});b.insertBefore(f,d)})}))},attr:function(a,b){var c,d,e=this.element,f,g=this,h;typeof a==="string"&&b!==v&&(c=a,a={},a[c]=b);if(typeof a==="string")g=(this[a+"Getter"]||this._defaultGetter).call(this,a,e);else{for(c in a){d=a[c];h=!1;this.symbolName&&/^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)/.test(c)&& -(f||(this.symbolAttr(a),f=!0),h=!0);if(this.rotation&&(c==="x"||c==="y"))this.doTransform=!0;h||(this[c+"Setter"]||this._defaultSetter).call(this,d,c,e);this.shadows&&/^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test(c)&&this.updateShadows(c,d)}if(this.doTransform)this.updateTransform(),this.doTransform=!1}return g},updateShadows:function(a,b){for(var c=this.shadows,d=c.length;d--;)c[d].setAttribute(a,a==="height"?t(b-(c[d].cutHeight||0),0):a==="d"?this.d:b)},addClass:function(a){var b=this.element, -c=I(b,"class")||"";c.indexOf(a)===-1&&I(b,"class",c+" "+a);return this},symbolAttr:function(a){var b=this;m("x,y,r,start,end,width,height,innerR,anchorX,anchorY".split(","),function(c){b[c]=p(a[c],b[c])});b.attr({d:b.renderer.symbols[b.symbolName](b.x,b.y,b.width,b.height,b)})},clip:function(a){return this.attr("clip-path",a?"url("+this.renderer.url+"#"+a.id+")":M)},crisp:function(a){var b,c={},d,e=a.strokeWidth||this.strokeWidth||0;d=w(e)%2/2;a.x=U(a.x||this.x||0)+d;a.y=U(a.y||this.y||0)+d;a.width= -U((a.width||this.width||0)-2*d);a.height=U((a.height||this.height||0)-2*d);a.strokeWidth=e;for(b in a)this[b]!==a[b]&&(this[b]=c[b]=a[b]);return c},css:function(a){var b=this.styles,c={},d=this.element,e,f,g="";e=!b;if(a&&a.color)a.fill=a.color;if(b)for(f in a)a[f]!==b[f]&&(c[f]=a[f],e=!0);if(e){e=this.textWidth=a&&a.width&&d.nodeName.toLowerCase()==="text"&&C(a.width)||this.textWidth;b&&(a=q(b,c));this.styles=a;e&&(ea||!ba&&this.renderer.forExport)&&delete a.width;if(ya&&!ba)J(this.element,a);else{b= -function(a,b){return"-"+b.toLowerCase()};for(f in a)g+=f.replace(/([A-Z])/g,b)+":"+a[f]+";";I(d,"style",g)}e&&this.added&&this.renderer.buildText(this)}return this},on:function(a,b){var c=this,d=c.element;ab&&a==="click"?(d.ontouchstart=function(a){c.touchEventFired=Aa.now();a.preventDefault();b.call(d,a)},d.onclick=function(a){(Ba.indexOf("Android")===-1||Aa.now()-(c.touchEventFired||0)>1100)&&b.call(d,a)}):d["on"+a]=b;return this},setRadialReference:function(a){this.element.radialReference=a;return this}, -translate:function(a,b){return this.attr({translateX:a,translateY:b})},invert:function(){this.inverted=!0;this.updateTransform();return this},updateTransform:function(){var a=this.translateX||0,b=this.translateY||0,c=this.scaleX,d=this.scaleY,e=this.inverted,f=this.rotation,g=this.element;e&&(a+=this.attr("width"),b+=this.attr("height"));a=["translate("+a+","+b+")"];e?a.push("rotate(90) scale(-1,1)"):f&&a.push("rotate("+f+" "+(g.getAttribute("x")||0)+" "+(g.getAttribute("y")||0)+")");(r(c)||r(d))&& -a.push("scale("+p(c,1)+" "+p(d,1)+")");a.length&&g.setAttribute("transform",a.join(" "))},toFront:function(){var a=this.element;a.parentNode.appendChild(a);return this},align:function(a,b,c){var d,e,f,g,h={};e=this.renderer;f=e.alignedObjects;if(a){if(this.alignOptions=a,this.alignByTranslate=b,!c||Da(c))this.alignTo=d=c||"renderer",ia(f,this),f.push(this),c=null}else a=this.alignOptions,b=this.alignByTranslate,d=this.alignTo;c=p(c,e[d],e);d=a.align;e=a.verticalAlign;f=(c.x||0)+(a.x||0);g=(c.y||0)+ -(a.y||0);if(d==="right"||d==="center")f+=(c.width-(a.width||0))/{right:1,center:2}[d];h[b?"translateX":"x"]=w(f);if(e==="bottom"||e==="middle")g+=(c.height-(a.height||0))/({bottom:1,middle:2}[e]||1);h[b?"translateY":"y"]=w(g);this[this.placed?"animate":"attr"](h);this.placed=!0;this.alignAttr=h;return this},getBBox:function(a){var b,c=this.renderer,d,e=this.rotation,f=this.element,g=this.styles,h=e*ga;d=this.textStr;var i,j=f.style,k,l;d!==v&&(l=["",e||0,g&&g.fontSize,f.style.width].join(","),l=d=== -""||Mb.test(d)?"num:"+d.toString().length+l:d+l);l&&!a&&(b=c.cache[l]);if(!b){if(f.namespaceURI===Ca||c.forExport){try{k=this.fakeTS&&function(a){m(f.querySelectorAll(".highcharts-text-shadow"),function(b){b.style.display=a})},La&&j.textShadow?(i=j.textShadow,j.textShadow=""):k&&k(M),b=f.getBBox?q({},f.getBBox()):{width:f.offsetWidth,height:f.offsetHeight},i?j.textShadow=i:k&&k("")}catch(n){}if(!b||b.width<0)b={width:0,height:0}}else b=this.htmlGetBBox();if(c.isSVG){a=b.width;d=b.height;if(ya&&g&& -g.fontSize==="11px"&&d.toPrecision(3)==="16.9")b.height=d=14;if(e)b.width=P(d*$(h))+P(a*W(h)),b.height=P(d*W(h))+P(a*$(h))}c.cache[l]=b}return b},show:function(a){a&&this.element.namespaceURI===Ca?this.element.removeAttribute("visibility"):this.attr({visibility:a?"inherit":"visible"});return this},hide:function(){return this.attr({visibility:"hidden"})},fadeOut:function(a){var b=this;b.animate({opacity:0},{duration:a||150,complete:function(){b.attr({y:-9999})}})},add:function(a){var b=this.renderer, -c=this.element,d;if(a)this.parentGroup=a;this.parentInverted=a&&a.inverted;this.textStr!==void 0&&b.buildText(this);this.added=!0;if(!a||a.handleZ||this.zIndex)d=this.zIndexSetter();d||(a?a.element:b.box).appendChild(c);if(this.onAdd)this.onAdd();return this},safeRemoveChild:function(a){var b=a.parentNode;b&&b.removeChild(a)},destroy:function(){var a=this,b=a.element||{},c=a.shadows,d=a.renderer.isSVG&&b.nodeName==="SPAN"&&a.parentGroup,e,f;b.onclick=b.onmouseout=b.onmouseover=b.onmousemove=b.point= -null;db(a);if(a.clipPath)a.clipPath=a.clipPath.destroy();if(a.stops){for(f=0;f]*>/g, -"")},textSetter:function(a){if(a!==this.textStr)delete this.bBox,this.textStr=a,this.added&&this.renderer.buildText(this)},fillSetter:function(a,b,c){typeof a==="string"?c.setAttribute(b,a):a&&this.colorGradient(a,b,c)},zIndexSetter:function(a,b){var c=this.renderer,d=this.parentGroup,c=(d||c).element||c.box,e,f,g=this.element,h;e=this.added;var i;r(a)&&(g.setAttribute(b,a),a=+a,this[b]===a&&(e=!1),this[b]=a);if(e){if((a=this.zIndex)&&d)d.handleZ=!0;d=c.childNodes;for(i=0;ia||!r(a)&&r(f)))c.insertBefore(g,e),h=!0;h||c.appendChild(g)}return h},_defaultSetter:function(a,b,c){c.setAttribute(b,a)}};L.prototype.yGetter=L.prototype.xGetter;L.prototype.translateXSetter=L.prototype.translateYSetter=L.prototype.rotationSetter=L.prototype.verticalAlignSetter=L.prototype.scaleXSetter=L.prototype.scaleYSetter=function(a,b){this[b]=a;this.doTransform=!0};L.prototype["stroke-widthSetter"]=L.prototype.strokeSetter=function(a,b,c){this[b]=a;if(this.stroke&& -this["stroke-width"])this.strokeWidth=this["stroke-width"],L.prototype.fillSetter.call(this,this.stroke,"stroke",c),c.setAttribute("stroke-width",this["stroke-width"]),this.hasStroke=!0;else if(b==="stroke-width"&&a===0&&this.hasStroke)c.removeAttribute("stroke"),this.hasStroke=!1};var ta=function(){this.init.apply(this,arguments)};ta.prototype={Element:L,init:function(a,b,c,d,e){var f=location,g,d=this.createElement("svg").attr({version:"1.1"}).css(this.getStyle(d));g=d.element;a.appendChild(g); -a.innerHTML.indexOf("xmlns")===-1&&I(g,"xmlns",Ca);this.isSVG=!0;this.box=g;this.boxWrapper=d;this.alignedObjects=[];this.url=(La||xb)&&D.getElementsByTagName("base").length?f.href.replace(/#.*?$/,"").replace(/([\('\)])/g,"\\$1").replace(/ /g,"%20"):"";this.createElement("desc").add().element.appendChild(D.createTextNode("Created with Highcharts 4.1.4"));this.defs=this.createElement("defs").add();this.forExport=e;this.gradients={};this.cache={};this.setSize(b,c,!1);var h;if(La&&a.getBoundingClientRect)this.subPixelFix= -b=function(){J(a,{left:0,top:0});h=a.getBoundingClientRect();J(a,{left:sa(h.left)-h.left+"px",top:sa(h.top)-h.top+"px"})},b(),K(O,"resize",b)},getStyle:function(a){return this.style=q({fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif',fontSize:"12px"},a)},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a=this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();Qa(this.gradients||{});this.gradients=null;if(a)this.defs=a.destroy(); -this.subPixelFix&&Y(O,"resize",this.subPixelFix);return this.alignedObjects=null},createElement:function(a){var b=new this.Element;b.init(this,a);return b},draw:function(){},buildText:function(a){for(var b=a.element,c=this,d=c.forExport,e=p(a.textStr,"").toString(),f=e.indexOf("<")!==-1,g=b.childNodes,h,i,j=I(b,"x"),k=a.styles,l=a.textWidth,n=k&&k.lineHeight,o=k&&k.textShadow,s=k&&k.textOverflow==="ellipsis",x=g.length,T=l&&!a.added&&this.box,B=function(a){return n?C(n):c.fontMetrics(/(px|em)$/.test(a&& -a.style.fontSize)?a.style.fontSize:k&&k.fontSize||c.style.fontSize||12,a).h},u=function(a){return a.replace(/</g,"<").replace(/>/g,">")};x--;)b.removeChild(g[x]);!f&&!o&&!s&&e.indexOf(" ")===-1?b.appendChild(D.createTextNode(u(e))):(h=/<.*style="([^"]+)".*>/,i=/<.*href="(http[^"]+)".*>/,T&&T.appendChild(b),e=f?e.replace(/<(b|strong)>/g,'').replace(/<(i|em)>/g,'').replace(//g,"").split(//g): -[e],e[e.length-1]===""&&e.pop(),m(e,function(e,f){var g,n=0,e=e.replace(//g,"|||");g=e.split("|||");m(g,function(e){if(e!==""||g.length===1){var o={},x=D.createElementNS(Ca,"tspan"),p;h.test(e)&&(p=e.match(h)[1].replace(/(;| |^)color([ :])/,"$1fill$2"),I(x,"style",p));i.test(e)&&!d&&(I(x,"onclick",'location.href="'+e.match(i)[1]+'"'),J(x,{cursor:"pointer"}));e=u(e.replace(/<(.|\n)*?>/g,"")||" ");if(e!==" "){x.appendChild(D.createTextNode(e));if(n)o.dx=0; -else if(f&&j!==null)o.x=j;I(x,o);b.appendChild(x);!n&&f&&(!ba&&d&&J(x,{display:"block"}),I(x,"dy",B(x)));if(l){for(var o=e.replace(/([^\^])-/g,"$1- ").split(" "),m=g.length>1||f||o.length>1&&k.whiteSpace!=="nowrap",T,r,ua,v=[],t=B(x),w=1,q=a.rotation,z=e,y=z.length;(m||s)&&(o.length||v.length);)a.rotation=0,T=a.getBBox(!0),ua=T.width,!ba&&c.forExport&&(ua=c.measureSpanWidth(x.firstChild.data,a.styles)),T=ua>l,r===void 0&&(r=T),s&&r?(y/=2,z===""||!T&&y<0.5?o=[]:(T&&(r=!0),z=e.substring(0,z.length+ -(T?-1:1)*sa(y)),o=[z+"…"],x.removeChild(x.firstChild))):!T||o.length===1?(o=v,v=[],o.length&&(w++,x=D.createElementNS(Ca,"tspan"),I(x,{dy:t,x:j}),p&&I(x,"style",p),b.appendChild(x)),ua>l&&(l=ua)):(x.removeChild(x.firstChild),v.unshift(o.pop())),o.length&&x.appendChild(D.createTextNode(o.join(" ").replace(/- /g,"-")));r&&a.attr("title",a.textStr);a.rotation=q}n++}}})}),T&&T.removeChild(b),o&&a.applyTextShadow&&a.applyTextShadow(o))},getContrast:function(a){a=na(a).rgba;return a[0]+a[1]+a[2]>384?"#000": -"#FFF"},button:function(a,b,c,d,e,f,g,h,i){var j=this.label(a,b,c,i,null,null,null,null,"button"),k=0,l,n,o,s,x,p,a={x1:0,y1:0,x2:0,y2:1},e=z({"stroke-width":1,stroke:"#CCCCCC",fill:{linearGradient:a,stops:[[0,"#FEFEFE"],[1,"#F6F6F6"]]},r:2,padding:5,style:{color:"black"}},e);o=e.style;delete e.style;f=z(e,{stroke:"#68A",fill:{linearGradient:a,stops:[[0,"#FFF"],[1,"#ACF"]]}},f);s=f.style;delete f.style;g=z(e,{stroke:"#68A",fill:{linearGradient:a,stops:[[0,"#9BD"],[1,"#CDF"]]}},g);x=g.style;delete g.style; -h=z(e,{style:{color:"#CCC"}},h);p=h.style;delete h.style;K(j.element,ya?"mouseover":"mouseenter",function(){k!==3&&j.attr(f).css(s)});K(j.element,ya?"mouseout":"mouseleave",function(){k!==3&&(l=[e,f,g][k],n=[o,s,x][k],j.attr(l).css(n))});j.setState=function(a){(j.state=k=a)?a===2?j.attr(g).css(x):a===3&&j.attr(h).css(p):j.attr(e).css(o)};return j.on("click",function(){k!==3&&d.call(j)}).attr(e).css(q({cursor:"default"},o))},crispLine:function(a,b){a[1]===a[4]&&(a[1]=a[4]=w(a[1])-b%2/2);a[2]===a[5]&& -(a[2]=a[5]=w(a[2])+b%2/2);return a},path:function(a){var b={fill:M};Ha(a)?b.d=a:ca(a)&&q(b,a);return this.createElement("path").attr(b)},circle:function(a,b,c){a=ca(a)?a:{x:a,y:b,r:c};b=this.createElement("circle");b.xSetter=function(a){this.element.setAttribute("cx",a)};b.ySetter=function(a){this.element.setAttribute("cy",a)};return b.attr(a)},arc:function(a,b,c,d,e,f){if(ca(a))b=a.y,c=a.r,d=a.innerR,e=a.start,f=a.end,a=a.x;a=this.symbol("arc",a||0,b||0,c||0,c||0,{innerR:d||0,start:e||0,end:f||0}); -a.r=c;return a},rect:function(a,b,c,d,e,f){var e=ca(a)?a.r:e,g=this.createElement("rect"),a=ca(a)?a:a===v?{}:{x:a,y:b,width:t(c,0),height:t(d,0)};if(f!==v)a.strokeWidth=f,a=g.crisp(a);if(e)a.r=e;g.rSetter=function(a){I(this.element,{rx:a,ry:a})};return g.attr(a)},setSize:function(a,b,c){var d=this.alignedObjects,e=d.length;this.width=a;this.height=b;for(this.boxWrapper[p(c,!0)?"animate":"attr"]({width:a,height:b});e--;)d[e].align()},g:function(a){var b=this.createElement("g");return r(a)?b.attr({"class":"highcharts-"+ -a}):b},image:function(a,b,c,d,e){var f={preserveAspectRatio:M};arguments.length>1&&q(f,{x:b,y:c,width:d,height:e});f=this.createElement("image").attr(f);f.element.setAttributeNS?f.element.setAttributeNS("http://www.w3.org/1999/xlink","href",a):f.element.setAttribute("hc-svg-href",a);return f},symbol:function(a,b,c,d,e,f){var g,h=this.symbols[a],h=h&&h(w(b),w(c),d,e,f),i=/^url\((.*?)\)$/,j,k;if(h)g=this.path(h),q(g,{symbolName:a,x:b,y:c,width:d,height:e}),f&&q(g,f);else if(i.test(a))k=function(a,b){a.element&& -(a.attr({width:b[0],height:b[1]}),a.alignByTranslate||a.translate(w((d-b[0])/2),w((e-b[1])/2)))},j=a.match(i)[1],a=Ib[j]||f&&f.width&&f.height&&[f.width,f.height],g=this.image(j).attr({x:b,y:c}),g.isImg=!0,a?k(g,a):(g.attr({width:0,height:0}),Z("img",{onload:function(){k(g,Ib[j]=[this.width,this.height])},src:j}));return g},symbols:{circle:function(a,b,c,d){var e=0.166*c;return["M",a+c/2,b,"C",a+c+e,b,a+c+e,b+d,a+c/2,b+d,"C",a-e,b+d,a-e,b,a+c/2,b,"Z"]},square:function(a,b,c,d){return["M",a,b,"L", -a+c,b,a+c,b+d,a,b+d,"Z"]},triangle:function(a,b,c,d){return["M",a+c/2,b,"L",a+c,b+d,a,b+d,"Z"]},"triangle-down":function(a,b,c,d){return["M",a,b,"L",a+c,b,a+c/2,b+d,"Z"]},diamond:function(a,b,c,d){return["M",a+c/2,b,"L",a+c,b+d/2,a+c/2,b+d,a,b+d/2,"Z"]},arc:function(a,b,c,d,e){var f=e.start,c=e.r||c||d,g=e.end-0.001,d=e.innerR,h=e.open,i=W(f),j=$(f),k=W(g),g=$(g),e=e.end-fc&&i>b+g&&ib+g&&id&&h>a+g&&ha+g&&hn&&/[ \-]/.test(b.textContent||b.innerText))J(b,{width:n+"px",display:"block",whiteSpace:j&&j.whiteSpace||"normal"}),i=n;this.getSpanCorrection(i,l,h,k,g)}J(b,{left:e+(this.xCorr||0)+"px",top:f+(this.yCorr||0)+"px"});if(xb)l=b.offsetHeight;this.cTT=o}}else this.alignOnAdd=!0},setSpanRotation:function(a,b,c){var d={},e=ya?"-ms-transform":xb?"-webkit-transform":La?"MozTransform":Gb?"-o-transform":"";d[e]=d.transform="rotate("+a+"deg)"; -d[e+(La?"Origin":"-origin")]=d.transformOrigin=b*100+"% "+c+"px";J(this.element,d)},getSpanCorrection:function(a,b,c){this.xCorr=-a*c;this.yCorr=-b}});q(ta.prototype,{html:function(a,b,c){var d=this.createElement("span"),e=d.element,f=d.renderer;d.textSetter=function(a){a!==e.innerHTML&&delete this.bBox;e.innerHTML=this.textStr=a};d.xSetter=d.ySetter=d.alignSetter=d.rotationSetter=function(a,b){b==="align"&&(b="textAlign");d[b]=a;d.htmlUpdateTransform()};d.attr({text:a,x:w(b),y:w(c)}).css({position:"absolute", -fontFamily:this.style.fontFamily,fontSize:this.style.fontSize});e.style.whiteSpace="nowrap";d.css=d.htmlCss;if(f.isSVG)d.add=function(a){var b,c=f.box.parentNode,j=[];if(this.parentGroup=a){if(b=a.div,!b){for(;a;)j.push(a),a=a.parentGroup;m(j.reverse(),function(a){var d;b=a.div=a.div||Z(Ka,{className:I(a.element,"class")},{position:"absolute",left:(a.translateX||0)+"px",top:(a.translateY||0)+"px"},b||c);d=b.style;q(a,{translateXSetter:function(b,c){d.left=b+"px";a[c]=b;a.doTransform=!0},translateYSetter:function(b, -c){d.top=b+"px";a[c]=b;a.doTransform=!0},visibilitySetter:function(a,b){d[b]=a}})})}}else b=c;b.appendChild(e);d.added=!0;d.alignOnAdd&&d.htmlUpdateTransform();return d};return d}});if(!ba&&!ea){A={init:function(a,b){var c=["<",b,' filled="f" stroked="f"'],d=["position: ","absolute",";"],e=b===Ka;(b==="shape"||e)&&d.push("left:0;top:0;width:1px;height:1px;");d.push("visibility: ",e?"hidden":"visible");c.push(' style="',d.join(""),'"/>');if(b)c=e||b==="span"||b==="img"?c.join(""):a.prepVML(c),this.element= -Z(c);this.renderer=a},add:function(a){var b=this.renderer,c=this.element,d=b.box,d=a?a.element||a:d;a&&a.inverted&&b.invertChild(c,d);d.appendChild(c);this.added=!0;this.alignOnAdd&&!this.deferUpdateTransform&&this.updateTransform();if(this.onAdd)this.onAdd();return this},updateTransform:L.prototype.htmlUpdateTransform,setSpanRotation:function(){var a=this.rotation,b=W(a*ga),c=$(a*ga);J(this.element,{filter:a?["progid:DXImageTransform.Microsoft.Matrix(M11=",b,", M12=",-c,", M21=",c,", M22=",b,", sizingMethod='auto expand')"].join(""): -M})},getSpanCorrection:function(a,b,c,d,e){var f=d?W(d*ga):1,g=d?$(d*ga):0,h=p(this.elemHeight,this.element.offsetHeight),i;this.xCorr=f<0&&-a;this.yCorr=g<0&&-h;i=f*g<0;this.xCorr+=g*b*(i?1-c:c);this.yCorr-=f*b*(d?i?c:1-c:1);e&&e!=="left"&&(this.xCorr-=a*c*(f<0?-1:1),d&&(this.yCorr-=h*c*(g<0?-1:1)),J(this.element,{textAlign:e}))},pathToVML:function(a){for(var b=a.length,c=[];b--;)if(qa(a[b]))c[b]=w(a[b]*10)-5;else if(a[b]==="Z")c[b]="x";else if(c[b]=a[b],a.isArc&&(a[b]==="wa"||a[b]==="at"))c[b+5]=== -c[b+7]&&(c[b+7]+=a[b+7]>a[b+5]?1:-1),c[b+6]===c[b+8]&&(c[b+8]+=a[b+8]>a[b+6]?1:-1);return c.join(" ")||"x"},clip:function(a){var b=this,c;a?(c=a.members,ia(c,b),c.push(b),b.destroyClip=function(){ia(c,b)},a=a.getCSS(b)):(b.destroyClip&&b.destroyClip(),a={clip:hb?"inherit":"rect(auto)"});return b.css(a)},css:L.prototype.htmlCss,safeRemoveChild:function(a){a.parentNode&&Ra(a)},destroy:function(){this.destroyClip&&this.destroyClip();return L.prototype.destroy.apply(this)},on:function(a,b){this.element["on"+ -a]=function(){var a=O.event;a.target=a.srcElement;b(a)};return this},cutOffPath:function(a,b){var c,a=a.split(/[ ,]/);c=a.length;if(c===9||c===11)a[c-4]=a[c-2]=C(a[c-2])-10*b;return a.join(" ")},shadow:function(a,b,c){var d=[],e,f=this.element,g=this.renderer,h,i=f.style,j,k=f.path,l,n,o,s;k&&typeof k.value!=="string"&&(k="x");n=k;if(a){o=p(a.width,3);s=(a.opacity||0.15)/o;for(e=1;e<=3;e++){l=o*2+1-2*e;c&&(n=this.cutOffPath(k.value,l+0.5));j=[''];h=Z(g.prepVML(j),null,{left:C(i.left)+p(a.offsetX,1),top:C(i.top)+p(a.offsetY,1)});if(c)h.cutOff=l+1;j=[''];Z(g.prepVML(j),null,null,h);b?b.element.appendChild(h):f.parentNode.insertBefore(h,f);d.push(h)}this.shadows=d}return this},updateShadows:ma,setAttr:function(a,b){hb?this.element[a]=b:this.element.setAttribute(a,b)},classSetter:function(a){this.element.className=a},dashstyleSetter:function(a, -b,c){(c.getElementsByTagName("stroke")[0]||Z(this.renderer.prepVML([""]),null,null,c))[b]=a||"solid";this[b]=a},dSetter:function(a,b,c){var d=this.shadows,a=a||[];this.d=a.join&&a.join(" ");c.path=a=this.pathToVML(a);if(d)for(c=d.length;c--;)d[c].path=d[c].cutOff?this.cutOffPath(a,d[c].cutOff):a;this.setAttr(b,a)},fillSetter:function(a,b,c){var d=c.nodeName;if(d==="SPAN")c.style.color=a;else if(d!=="IMG")c.filled=a!==M,this.setAttr("fillcolor",this.renderer.color(a,c,b,this))},opacitySetter:ma, -rotationSetter:function(a,b,c){c=c.style;this[b]=c[b]=a;c.left=-w($(a*ga)+1)+"px";c.top=w(W(a*ga))+"px"},strokeSetter:function(a,b,c){this.setAttr("strokecolor",this.renderer.color(a,c,b))},"stroke-widthSetter":function(a,b,c){c.stroked=!!a;this[b]=a;qa(a)&&(a+="px");this.setAttr("strokeweight",a)},titleSetter:function(a,b){this.setAttr(b,a)},visibilitySetter:function(a,b,c){a==="inherit"&&(a="visible");this.shadows&&m(this.shadows,function(c){c.style[b]=a});c.nodeName==="DIV"&&(a=a==="hidden"?"-999em": -0,hb||(c.style[b]=a?"visible":"hidden"),b="top");c.style[b]=a},xSetter:function(a,b,c){this[b]=a;b==="x"?b="left":b==="y"&&(b="top");this.updateClipping?(this[b]=a,this.updateClipping()):c.style[b]=a},zIndexSetter:function(a,b,c){c.style[b]=a}};y.VMLElement=A=ja(L,A);A.prototype.ySetter=A.prototype.widthSetter=A.prototype.heightSetter=A.prototype.xSetter;var Na={Element:A,isIE8:Ba.indexOf("MSIE 8.0")>-1,init:function(a,b,c,d){var e;this.alignedObjects=[];d=this.createElement(Ka).css(q(this.getStyle(d), -{position:"relative"}));e=d.element;a.appendChild(d.element);this.isVML=!0;this.box=e;this.boxWrapper=d;this.cache={};this.setSize(b,c,!1);if(!D.namespaces.hcv){D.namespaces.add("hcv","urn:schemas-microsoft-com:vml");try{D.createStyleSheet().cssText="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "}catch(f){D.styleSheets[0].cssText+="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "}}}, -isHidden:function(){return!this.box.offsetWidth},clipRect:function(a,b,c,d){var e=this.createElement(),f=ca(a);return q(e,{members:[],count:0,left:(f?a.x:a)+1,top:(f?a.y:b)+1,width:(f?a.width:c)-1,height:(f?a.height:d)-1,getCSS:function(a){var b=a.element,c=b.nodeName,a=a.inverted,d=this.top-(c==="shape"?b.offsetTop:0),e=this.left,b=e+this.width,f=d+this.height,d={clip:"rect("+w(a?e:d)+"px,"+w(a?f:b)+"px,"+w(a?b:f)+"px,"+w(a?d:e)+"px)"};!a&&hb&&c==="DIV"&&q(d,{width:b+"px",height:f+"px"});return d}, -updateClipping:function(){m(e.members,function(a){a.element&&a.css(e.getCSS(a))})}})},color:function(a,b,c,d){var e=this,f,g=/^rgba/,h,i,j=M;a&&a.linearGradient?i="gradient":a&&a.radialGradient&&(i="pattern");if(i){var k,l,n=a.linearGradient||a.radialGradient,o,s,x,p,B,u="",a=a.stops,r,fa=[],t=function(){h=[''];Z(e.prepVML(h),null,null,b)};o=a[0];r=a[a.length-1];o[0]>0&&a.unshift([0,o[1]]); -r[0]<1&&a.push([1,r[1]]);m(a,function(a,b){g.test(a[1])?(f=na(a[1]),k=f.get("rgb"),l=f.get("a")):(k=a[1],l=1);fa.push(a[0]*100+"% "+k);b?(x=l,p=k):(s=l,B=k)});if(c==="fill")if(i==="gradient")c=n.x1||n[0]||0,a=n.y1||n[1]||0,o=n.x2||n[2]||0,n=n.y2||n[3]||0,u='angle="'+(90-V.atan((n-a)/(o-c))*180/la)+'"',t();else{var j=n.r,v=j*2,w=j*2,q=n.cx,E=n.cy,z=b.radialReference,y,j=function(){z&&(y=d.getBBox(),q+=(z[0]-y.x)/y.width-0.5,E+=(z[1]-y.y)/y.height-0.5,v*=z[2]/y.width,w*=z[2]/y.height);u='src="'+S.global.VMLRadialGradientURL+ -'" size="'+v+","+w+'" origin="0.5,0.5" position="'+q+","+E+'" color2="'+B+'" ';t()};d.added?j():d.onAdd=j;j=p}else j=k}else if(g.test(a)&&b.tagName!=="IMG")f=na(a),h=["<",c,' opacity="',f.get("a"),'"/>'],Z(this.prepVML(h),null,null,b),j=f.get("rgb");else{j=b.getElementsByTagName(c);if(j.length)j[0].opacity=1,j[0].type="solid";j=a}return j},prepVML:function(a){var b=this.isIE8,a=a.join("");b?(a=a.replace("/>",' xmlns="urn:schemas-microsoft-com:vml" />'),a=a.indexOf('style="')===-1?a.replace("/>",' style="display:inline-block;behavior:url(#default#VML);" />'): -a.replace('style="','style="display:inline-block;behavior:url(#default#VML);')):a=a.replace("<","1&&f.attr({x:b,y:c,width:d,height:e});return f},createElement:function(a){return a==="rect"?this.symbol(a):ta.prototype.createElement.call(this,a)},invertChild:function(a,b){var c=this,d=b.style,e=a.tagName==="IMG"&&a.style;J(a,{flip:"x",left:C(d.width)-(e?C(e.top):1),top:C(d.height)-(e?C(e.left):1),rotation:-90});m(a.childNodes,function(b){c.invertChild(b,a)})},symbols:{arc:function(a,b,c,d,e){var f=e.start,g=e.end,h=e.r||c|| -d,c=e.innerR,d=W(f),i=$(f),j=W(g),k=$(g);if(g-f===0)return["x"];f=["wa",a-h,b-h,a+h,b+h,a+h*d,b+h*i,a+h*j,b+h*k];e.open&&!c&&f.push("e","M",a,b);f.push("at",a-c,b-c,a+c,b+c,a+c*j,b+c*k,a+c*d,b+c*i,"x","e");f.isArc=!0;return f},circle:function(a,b,c,d,e){e&&(c=d=2*e.r);e&&e.isCircle&&(a-=c/2,b-=d/2);return["wa",a,b,a+c,b+d,a+c,b+d/2,a+c,b+d/2,"e"]},rect:function(a,b,c,d,e){return ta.prototype.symbols[!r(e)||!e.r?"square":"callout"].call(0,a,b,c,d,e)}}};y.VMLRenderer=A=function(){this.init.apply(this, -arguments)};A.prototype=z(ta.prototype,Na);$a=A}ta.prototype.measureSpanWidth=function(a,b){var c=D.createElement("span"),d;d=D.createTextNode(a);c.appendChild(d);J(c,b);this.box.appendChild(c);d=c.offsetWidth;Ra(c);return d};var Jb;if(ea)y.CanVGRenderer=A=function(){Ca="http://www.w3.org/1999/xhtml"},A.prototype.symbols={},Jb=function(){function a(){var a=b.length,d;for(d=0;d0&&c+i*j>e&&(k=w((d-c)/W(h*ga)));else{d=c-i*j;c+=i*j;if(de)b-=c-e,a.x=e,g.attr({align:"right"});j>b&&(k=b)}k&&g.css({width:k,textOverflow:"ellipsis"})},getPosition:function(a,b,c,d){var e=this.axis,f=e.chart,g=d&&f.oldChartHeight||f.chartHeight;return{x:a?e.translate(b+c,null,null,d)+e.transB:e.left+e.offset+(e.opposite?(d&&f.oldChartWidth||f.chartWidth)-e.right-e.left:0),y:a?g-e.bottom+e.offset-(e.opposite?e.height:0):g-e.translate(b+c,null,null,d)-e.transB}},getLabelPosition:function(a,b,c,d,e,f,g,h){var i=this.axis,j=i.transA,k=i.reversed, -l=i.staggerLines,n=i.tickRotCorr||{x:0,y:0},c=p(e.y,n.y+(i.side===2?8:-(c.getBBox().height/2))),a=a+e.x+n.x-(f&&d?f*j*(k?-1:1):0),b=b+c-(f&&!d?f*j*(k?1:-1):0);l&&(b+=g/(h||1)%l*(i.labelOffset/l));return{x:a,y:w(b)}},getMarkPath:function(a,b,c,d,e,f){return f.crispLine(["M",a,b,"L",a+(e?0:-c),b+(e?c:0)],d)},render:function(a,b,c){var d=this.axis,e=d.options,f=d.chart.renderer,g=d.horiz,h=this.type,i=this.label,j=this.pos,k=e.labels,l=this.gridLine,n=h?h+"Grid":"grid",o=h?h+"Tick":"tick",s=e[n+"LineWidth"], -x=e[n+"LineColor"],m=e[n+"LineDashStyle"],B=e[o+"Length"],n=e[o+"Width"]||0,u=e[o+"Color"],r=e[o+"Position"],o=this.mark,fa=k.step,t=!0,w=d.tickmarkOffset,q=this.getPosition(g,j,w,b),y=q.x,q=q.y,z=g&&y===d.pos+d.len||!g&&q===d.pos?-1:1,c=p(c,1);this.isActive=!0;if(s){j=d.getPlotLinePath(j+w,s*z,b,!0);if(l===v){l={stroke:x,"stroke-width":s};if(m)l.dashstyle=m;if(!h)l.zIndex=1;if(b)l.opacity=0;this.gridLine=l=s?f.path(j).attr(l).add(d.gridGroup):null}if(!b&&l&&j)l[this.isNew?"attr":"animate"]({d:j, -opacity:c})}if(n&&B)r==="inside"&&(B=-B),d.opposite&&(B=-B),h=this.getMarkPath(y,q,B,n*z,g,f),o?o.animate({d:h,opacity:c}):this.mark=f.path(h).attr({stroke:u,"stroke-width":n,opacity:c}).add(d.axisGroup);if(i&&!isNaN(y))i.xy=q=this.getLabelPosition(y,q,i,g,k,w,a,fa),this.isFirst&&!this.isLast&&!p(e.showFirstLabel,1)||this.isLast&&!this.isFirst&&!p(e.showLastLabel,1)?t=!1:g&&!d.isRadial&&!k.step&&!k.rotation&&!b&&c!==0&&this.handleOverflow(q),fa&&a%fa&&(t=!1),t&&!isNaN(q.y)?(q.opacity=c,i[this.isNew? -"attr":"animate"](q),this.isNew=!1):i.attr("y",-9999)},destroy:function(){Qa(this,this.axis)}};y.PlotLineOrBand=function(a,b){this.axis=a;if(b)this.options=b,this.id=b.id};y.PlotLineOrBand.prototype={render:function(){var a=this,b=a.axis,c=b.horiz,d=a.options,e=d.label,f=a.label,g=d.width,h=d.to,i=d.from,j=r(i)&&r(h),k=d.value,l=d.dashStyle,n=a.svgElem,o=[],s,x=d.color,p=d.zIndex,m=d.events,u={},t=b.chart.renderer;b.isLog&&(i=Ea(i),h=Ea(h),k=Ea(k));if(g){if(o=b.getPlotLinePath(k,g),u={stroke:x,"stroke-width":g}, -l)u.dashstyle=l}else if(j){o=b.getPlotBandPath(i,h,d);if(x)u.fill=x;if(d.borderWidth)u.stroke=d.borderColor,u["stroke-width"]=d.borderWidth}else return;if(r(p))u.zIndex=p;if(n)if(o)n.animate({d:o},null,n.onGetPath);else{if(n.hide(),n.onGetPath=function(){n.show()},f)a.label=f=f.destroy()}else if(o&&o.length&&(a.svgElem=n=t.path(o).attr(u).add(),m))for(s in d=function(b){n.on(b,function(c){m[b].apply(a,[c])})},m)d(s);if(e&&r(e.text)&&o&&o.length&&b.width>0&&b.height>0){e=z({align:c&&j&&"center",x:c? -!j&&4:10,verticalAlign:!c&&j&&"middle",y:c?j?16:10:j?6:-4,rotation:c&&!j&&90},e);if(!f){u={align:e.textAlign||e.align,rotation:e.rotation};if(r(p))u.zIndex=p;a.label=f=t.text(e.text,0,0,e.useHTML).attr(u).css(e.style).add()}b=[o[1],o[4],j?o[6]:o[1]];j=[o[2],o[5],j?o[7]:o[2]];o=Pa(b);c=Pa(j);f.align(e,!1,{x:o,y:c,width:Fa(b)-o,height:Fa(j)-c});f.show()}else f&&f.hide();return a},destroy:function(){ia(this.axis.plotLinesAndBands,this);delete this.axis;Qa(this)}};var va=y.Axis=function(){this.init.apply(this, -arguments)};va.prototype={defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L",second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y",year:"%Y"},endOnTick:!1,gridLineColor:"#D8D8D8",labels:{enabled:!0,style:{color:"#606060",cursor:"default",fontSize:"11px"},x:0,y:15},lineColor:"#C0D0E0",lineWidth:1,minPadding:0.01,maxPadding:0.01,minorGridLineColor:"#E0E0E0",minorGridLineWidth:1,minorTickColor:"#A0A0A0",minorTickLength:2,minorTickPosition:"outside",startOfWeek:1, -startOnTick:!1,tickColor:"#C0D0E0",tickLength:10,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",tickWidth:1,title:{align:"middle",style:{color:"#707070"}},type:"linear"},defaultYAxisOptions:{endOnTick:!0,gridLineWidth:1,tickPixelInterval:72,showLastLabel:!0,labels:{x:-8,y:3},lineWidth:0,maxPadding:0.05,minPadding:0.05,startOnTick:!0,tickWidth:0,title:{rotation:270,text:"Values"},stackLabels:{enabled:!1,formatter:function(){return y.numberFormat(this.total,-1)},style:z(aa.line.dataLabels.style, -{color:"#000000"})}},defaultLeftAxisOptions:{labels:{x:-15,y:null},title:{rotation:270}},defaultRightAxisOptions:{labels:{x:15,y:null},title:{rotation:90}},defaultBottomAxisOptions:{labels:{autoRotation:[-45],x:0,y:null},title:{rotation:0}},defaultTopAxisOptions:{labels:{autoRotation:[-45],x:0,y:-15},title:{rotation:0}},init:function(a,b){var c=b.isX;this.horiz=a.inverted?!c:c;this.coll=(this.isXAxis=c)?"xAxis":"yAxis";this.opposite=b.opposite;this.side=b.side||(this.horiz?this.opposite?0:2:this.opposite? -1:3);this.setOptions(b);var d=this.options,e=d.type;this.labelFormatter=d.labels.formatter||this.defaultLabelFormatter;this.userOptions=b;this.minPixelPadding=0;this.chart=a;this.reversed=d.reversed;this.zoomEnabled=d.zoomEnabled!==!1;this.categories=d.categories||e==="category";this.names=this.names||[];this.isLog=e==="logarithmic";this.isDatetimeAxis=e==="datetime";this.isLinked=r(d.linkedTo);this.ticks={};this.labelEdge=[];this.minorTicks={};this.plotLinesAndBands=[];this.alternateBands={};this.len= -0;this.minRange=this.userMinRange=d.minRange||d.maxZoom;this.range=d.range;this.offset=d.offset||0;this.stacks={};this.oldStacks={};this.min=this.max=null;this.crosshair=p(d.crosshair,ra(a.options.tooltip.crosshairs)[c?0:1],!1);var f,d=this.options.events;Ma(this,a.axes)===-1&&(c&&!this.isColorAxis?a.axes.splice(a.xAxis.length,0,this):a.axes.push(this),a[this.coll].push(this));this.series=this.series||[];if(a.inverted&&c&&this.reversed===v)this.reversed=!0;this.removePlotLine=this.removePlotBand= -this.removePlotBandOrLine;for(f in d)K(this,f,d[f]);if(this.isLog)this.val2lin=Ea,this.lin2val=ha},setOptions:function(a){this.options=z(this.defaultOptions,this.isXAxis?{}:this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions,this.defaultLeftAxisOptions][this.side],z(S[this.coll],a))},defaultLabelFormatter:function(){var a=this.axis,b=this.value,c=a.categories,d=this.dateTimeLabelFormat,e=S.lang.numericSymbols,f=e&&e.length,g,h=a.options.labels.format, -a=a.isLog?b:a.tickInterval;if(h)g=Ja(h,this);else if(c)g=b;else if(d)g=Oa(d,b);else if(f&&a>=1E3)for(;f--&&g===v;)c=Math.pow(1E3,f+1),a>=c&&e[f]!==null&&(g=y.numberFormat(b/c,-1)+e[f]);g===v&&(g=P(b)>=1E4?y.numberFormat(b,0):y.numberFormat(b,-1,v,""));return g},getSeriesExtremes:function(){var a=this,b=a.chart;a.hasVisibleSeries=!1;a.dataMin=a.dataMax=a.ignoreMinPadding=a.ignoreMaxPadding=null;a.buildStacks&&a.buildStacks();m(a.series,function(c){if(c.visible||!b.options.chart.ignoreHiddenSeries){var d; -d=c.options.threshold;var e;a.hasVisibleSeries=!0;a.isLog&&d<=0&&(d=null);if(a.isXAxis){if(d=c.xData,d.length)a.dataMin=H(p(a.dataMin,d[0]),Pa(d)),a.dataMax=t(p(a.dataMax,d[0]),Fa(d))}else{c.getExtremes();e=c.dataMax;c=c.dataMin;if(r(c)&&r(e))a.dataMin=H(p(a.dataMin,c),c),a.dataMax=t(p(a.dataMax,e),e);if(r(d))if(a.dataMin>=d)a.dataMin=d,a.ignoreMinPadding=!0;else if(a.dataMaxc)d?a=H(t(b,a),c):n=!0;return a},e=p(e,this.translate(a,null,null,c)),a=c=w(e+i);i=j=w(k-e-i);isNaN(e)?n=!0:this.horiz?(i=h,j=k-this.bottom,a=c=o(a,g,g+this.width)):(a=g,c=l-this.right,i=j=o(i,h,h+this.height));return n&&!d?null:f.renderer.crispLine(["M",a,i,"L",c,j],b||1)},getLinearTickPositions:function(a, -b,c){var d,e=da(U(b/a)*a),f=da(sa(c/a)*a),g=[];if(b===c&&qa(b))return[b];for(b=e;b<=f;){g.push(b);b=da(b+a);if(b===d)break;d=b}return g},getMinorTickPositions:function(){var a=this.options,b=this.tickPositions,c=this.minorTickInterval,d=[],e,f=this.min;e=this.max;var g=e-f;if(g&&g/c=this.minRange,f,g,h,i,j;if(this.isXAxis&&this.minRange===v&&!this.isLog)r(a.min)||r(a.max)?this.minRange=null:(m(this.series,function(a){i=a.xData;for(g=j=a.xIncrement?1:i.length-1;g>0;g--)if(h=i[g]-i[g-1],f===v||hc&&(h=0);d=t(d,h);b.single||(f=t(f,Da(j)?0:h/2),g=t(g,j==="on"?0:h));!a.noSharedTooltip&&r(s)&&(e=r(e)?H(e,s):s)}),h=b.ordinalSlope&&e?b.ordinalSlope/e:1,b.minPointOffset=f*=h,b.pointRangePadding=g*=h,b.pointRange=H(d,c),k)b.closestPointRange=e;if(a)b.oldTransA=j;b.translationSlope=b.transA=j=b.len/(c+g||1);b.transB=b.horiz?b.left:b.bottom;b.minPixelPadding=j*f},setTickInterval:function(a){var b=this,c=b.chart,d=b.options,e=b.isLog,f=b.isDatetimeAxis,g=b.isXAxis,h=b.isLinked,i=d.maxPadding,j=d.minPadding, -k=d.tickInterval,l=d.tickPixelInterval,n=b.categories;!f&&!n&&!h&&this.getTickAmount();h?(b.linkedParent=c[b.coll][d.linkedTo],c=b.linkedParent.getExtremes(),b.min=p(c.min,c.dataMin),b.max=p(c.max,c.dataMax),d.type!==b.linkedParent.options.type&&ka(11,1)):(b.min=p(b.userMin,d.min,b.dataMin),b.max=p(b.userMax,d.max,b.dataMax));if(e)!a&&H(b.min,p(b.dataMin,b.min))<=0&&ka(10,1),b.min=da(Ea(b.min)),b.max=da(Ea(b.max));if(b.range&&r(b.max))b.userMin=b.min=t(b.min,b.max-b.range),b.userMax=b.max,b.range= -null;b.beforePadding&&b.beforePadding();b.adjustForMinRange();if(!n&&!b.axisPointRange&&!b.usePercentage&&!h&&r(b.min)&&r(b.max)&&(c=b.max-b.min)){if(!r(d.min)&&!r(b.userMin)&&j&&(b.dataMin<0||!b.ignoreMinPadding))b.min-=c*j;if(!r(d.max)&&!r(b.userMax)&&i&&(b.dataMax>0||!b.ignoreMaxPadding))b.max+=c*i}if(qa(d.floor))b.min=t(b.min,d.floor);if(qa(d.ceiling))b.max=H(b.max,d.ceiling);b.tickInterval=b.min===b.max||b.min===void 0||b.max===void 0?1:h&&!k&&l===b.linkedParent.options.tickPixelInterval?b.linkedParent.tickInterval: -p(k,this.tickAmount?(b.max-b.min)/t(this.tickAmount-1,1):void 0,n?1:(b.max-b.min)*l/t(b.len,l));g&&!a&&m(b.series,function(a){a.processData(b.min!==b.oldMin||b.max!==b.oldMax)});b.setAxisTranslation(!0);b.beforeSetTickPositions&&b.beforeSetTickPositions();if(b.postProcessTickInterval)b.tickInterval=b.postProcessTickInterval(b.tickInterval);if(b.pointRange)b.tickInterval=t(b.pointRange,b.tickInterval);a=p(d.minTickInterval,b.isDatetimeAxis&&b.closestPointRange);if(!k&&b.tickInterval0.5&&b.tickInterval<5&&b.max>1E3&&b.max<9999)),!!this.tickAmount);if(!this.tickAmount&&this.len)b.tickInterval=b.unsquish();this.setTickPositions()},setTickPositions:function(){var a=this.options,b,c=a.tickPositions,d=a.tickPositioner,e=a.startOnTick,f=a.endOnTick,g;this.tickmarkOffset=this.categories&&a.tickmarkPlacement==="between"&&this.tickInterval===1?0.5:0;this.minorTickInterval=a.minorTickInterval=== -"auto"&&this.tickInterval?this.tickInterval/5:a.minorTickInterval;this.tickPositions=b=a.tickPositions&&a.tickPositions.slice();if(!b&&(this.tickPositions=b=this.isDatetimeAxis?this.getTimeTicks(this.normalizeTimeTickInterval(this.tickInterval,a.units),this.min,this.max,a.startOfWeek,this.ordinalPositions,this.closestPointRange,!0):this.isLog?this.getLogTickPositions(this.tickInterval,this.min,this.max):this.getLinearTickPositions(this.tickInterval,this.min,this.max),d&&(d=d.apply(this,[this.min, -this.max]))))this.tickPositions=b=d;if(!this.isLinked)this.trimTicks(b,e,f),this.min===this.max&&r(this.min)&&!this.tickAmount&&(g=!0,this.min-=0.5,this.max+=0.5),this.single=g,!c&&!d&&this.adjustTickAmount()},trimTicks:function(a,b,c){var d=a[0],e=a[a.length-1],f=this.minPointOffset||0;b?this.min=d:this.min-f>d&&a.shift();c?this.max=e:this.max+fc&&(this.tickInterval*=2,this.setTickPositions());if(r(d)){for(a=c=b.length;a--;)(d===3&&a%2===1||d<=2&&a>0&&a=t(d,p(e.max,d))&&(b=v));this.displayBtn=a!==v||b!==v;this.setExtremes(a,b,!1,v,{trigger:"zoom"});return!0},setAxisSize:function(){var a=this.chart,b=this.options,c=b.offsetLeft|| -0,d=this.horiz,e=p(b.width,a.plotWidth-c+(b.offsetRight||0)),f=p(b.height,a.plotHeight),g=p(b.top,a.plotTop),b=p(b.left,a.plotLeft+c),c=/%$/;c.test(f)&&(f=parseFloat(f)/100*a.plotHeight);c.test(g)&&(g=parseFloat(g)/100*a.plotHeight+a.plotTop);this.left=b;this.top=g;this.width=e;this.height=f;this.bottom=a.chartHeight-f-g;this.right=a.chartWidth-e-b;this.len=t(d?e:f,0);this.pos=d?b:g},getExtremes:function(){var a=this.isLog;return{min:a?da(ha(this.min)):this.min,max:a?da(ha(this.max)):this.max,dataMin:this.dataMin, -dataMax:this.dataMax,userMin:this.userMin,userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,c=b?ha(this.min):this.min,b=b?ha(this.max):this.max;c>a||a===null?a=c:b15&&a<165?"right":a>195&&a<345?"left":"center"},unsquish:function(){var a=this.ticks,b=this.options.labels,c=this.horiz,d=this.tickInterval,e=d,f=this.len/(((this.categories?1:0)+this.max-this.min)/d),g,h=b.rotation, -i=this.chart.renderer.fontMetrics(b.style.fontSize,a[0]&&a[0].label),j,k=Number.MAX_VALUE,l,n=function(a){a/=f||1;a=a>1?sa(a):1;return a*d};c?(l=r(h)?[h]:f<80&&!b.staggerLines&&!b.step&&b.autoRotation)&&m(l,function(a){var b;if(a===h||a&&a>=-90&&a<=90)j=n(P(i.h/$(ga*a))),b=j+P(a/360),bl)l=a.labelLength}),l>i&&l>g.h?j.rotation=this.labelRotation:this.labelRotation=0;else if(h){k={width:i+"px",textOverflow:"clip"};for(h=c.length;!f&&h--;)if(i=c[h],(i=d[i].label)&& -this.len/c.length-4a.chartHeight*0.5?a.chartHeight*0.33:a.chartHeight)+"px",textOverflow:"ellipsis"});this.labelAlign=j.align=e.align||this.autoLabelAlign(this.labelRotation);m(c,function(a){var b=(a=d[a])&&a.label;if(b)k&&b.css(z(k,b.specCss)),delete b.specCss,b.attr(j),a.rotation=j.rotation});this.tickRotCorr=b.rotCorr(g.b,this.labelRotation||0,this.side===2)},getOffset:function(){var a=this,b=a.chart,c=b.renderer, -d=a.options,e=a.tickPositions,f=a.ticks,g=a.horiz,h=a.side,i=b.inverted?[1,0,3,2][h]:h,j,k,l=0,n,o=0,s=d.title,x=d.labels,T=0,B=b.axisOffset,b=b.clipOffset,u=[-1,1,1,-1][h],q;a.hasData=j=a.hasVisibleSeries||r(a.min)&&r(a.max)&&!!e;a.showAxis=k=j||p(d.showEmpty,!0);a.staggerLines=a.horiz&&x.staggerLines;if(!a.axisGroup)a.gridGroup=c.g("grid").attr({zIndex:d.gridZIndex||1}).add(),a.axisGroup=c.g("axis").attr({zIndex:d.zIndex||2}).add(),a.labelGroup=c.g("axis-labels").attr({zIndex:x.zIndex||7}).addClass("highcharts-"+ -a.coll.toLowerCase()+"-labels").add();if(j||a.isLinked){if(m(e,function(b){f[b]?f[b].addLabel():f[b]=new Ta(a,b)}),a.renderUnsquish(),m(e,function(b){if(h===0||h===2||{1:"left",3:"right"}[h]===a.labelAlign)T=t(f[b].getLabelSize(),T)}),a.staggerLines)T*=a.staggerLines,a.labelOffset=T}else for(q in f)f[q].destroy(),delete f[q];if(s&&s.text&&s.enabled!==!1){if(!a.axisTitle)a.axisTitle=c.text(s.text,0,0,s.useHTML).attr({zIndex:7,rotation:s.rotation||0,align:s.textAlign||{low:"left",middle:"center",high:"right"}[s.align]}).addClass("highcharts-"+ -this.coll.toLowerCase()+"-title").css(s.style).add(a.axisGroup),a.axisTitle.isNew=!0;if(k)l=a.axisTitle.getBBox()[g?"height":"width"],n=s.offset,o=r(n)?0:p(s.margin,g?5:10);a.axisTitle[k?"show":"hide"]()}a.offset=u*p(d.offset,B[h]);a.tickRotCorr=a.tickRotCorr||{x:0,y:0};c=h===2?a.tickRotCorr.y:0;g=T+o+(T&&u*(g?p(x.y,a.tickRotCorr.y+8):x.x)-c);a.axisTitleMargin=p(n,g);B[h]=t(B[h],a.axisTitleMargin+l+u*a.offset,g);b[i]=t(b[i],U(d.lineWidth/2)*2)},getLinePath:function(a){var b=this.chart,c=this.opposite, -d=this.offset,e=this.horiz,f=this.left+(c?this.width:0)+d,d=b.chartHeight-this.bottom-(c?this.height:0)+d;c&&(a*=-1);return b.renderer.crispLine(["M",e?this.left:f,e?d:this.top,"L",e?b.chartWidth-this.right:f,e?d:b.chartHeight-this.bottom],a)},getTitlePosition:function(){var a=this.horiz,b=this.left,c=this.top,d=this.len,e=this.options.title,f=a?b:c,g=this.opposite,h=this.offset,i=C(e.style.fontSize||12),d={low:f+(a?0:d),middle:f+d/2,high:f+(a?d:0)}[e.align],b=(a?c+this.height:b)+(a?1:-1)*(g?-1:1)* -this.axisTitleMargin+(this.side===2?i:0);return{x:a?d:b+(g?this.width:0)+h+(e.x||0),y:a?b-(g?this.height:0)+h:d+(e.y||0)}},render:function(){var a=this,b=a.chart,c=b.renderer,d=a.options,e=a.isLog,f=a.isLinked,g=a.tickPositions,h=a.axisTitle,i=a.ticks,j=a.minorTicks,k=a.alternateBands,l=d.stackLabels,n=d.alternateGridColor,o=a.tickmarkOffset,s=d.lineWidth,x,p=b.hasRendered&&r(a.oldMin)&&!isNaN(a.oldMin);x=a.hasData;var B=a.showAxis,u,q;a.labelEdge.length=0;a.overlap=!1;m([i,j,k],function(a){for(var b in a)a[b].isActive= -!1});if(x||f){a.minorTickInterval&&!a.categories&&m(a.getMinorTickPositions(),function(b){j[b]||(j[b]=new Ta(a,b,"minor"));p&&j[b].isNew&&j[b].render(null,!0);j[b].render(null,!1,1)});if(g.length&&(m(g,function(b,c){if(!f||b>=a.min&&b<=a.max)i[b]||(i[b]=new Ta(a,b)),p&&i[b].isNew&&i[b].render(c,!0,0.1),i[b].render(c)}),o&&(a.min===0||a.single)))i[-1]||(i[-1]=new Ta(a,-1,null,!0)),i[-1].render(-1);n&&m(g,function(b,c){if(c%2===0&&b= -F.second?0:k*U(i.getMilliseconds()/k));j>=F.second&&i.setSeconds(j>=F.minute?0:k*U(i.getSeconds()/k));if(j>=F.minute)i[Db](j>=F.hour?0:k*U(i[rb]()/k));if(j>=F.hour)i[Eb](j>=F.day?0:k*U(i[sb]()/k));if(j>=F.day)i[ub](j>=F.month?1:k*U(i[Xa]()/k));j>=F.month&&(i[vb](j>=F.year?0:k*U(i[Ya]()/k)),h=i[Za]());j>=F.year&&(h-=h%k,i[wb](h));if(j===F.week)i[ub](i[Xa]()-i[tb]()+p(d,1));b=1;if(nb||eb)i=i.getTime(),i=new Aa(i+Wa(i));h=i[Za]();for(var d=i.getTime(),l=i[Ya](),n=i[Xa](),o=(F.day+(g?Wa(i):i.getTimezoneOffset()* -6E4))%F.day;d=0.5)a=w(a),g=this.getLinearTickPositions(a,b,c);else if(a>=0.08)for(var f=U(b),h, -i,j,k,l,e=a>0.3?[1,2,4]:a>0.15?[1,2,4,6,8]:[1,2,3,4,5,6,7,8,9];fb&&(!d||k<=c)&&k!==v&&g.push(k),k>c&&(l=!0),k=j}else if(b=ha(b),c=ha(c),a=e[d?"minorTickInterval":"tickInterval"],a=p(a==="auto"?null:a,this._minorAutoInterval,(c-b)*(e.tickPixelInterval/(d?5:1))/((d?f/this.tickPositions.length:f)||1)),a=pb(a,null,ob(a)),g=Ua(this.getLinearTickPositions(a,b,c),Ea),!d)this._minorAutoInterval=a/5;if(!d)this.tickInterval=a;return g};var Kb= -y.Tooltip=function(){this.init.apply(this,arguments)};Kb.prototype={init:function(a,b){var c=b.borderWidth,d=b.style,e=C(d.padding);this.chart=a;this.options=b;this.crosshairs=[];this.now={x:0,y:0};this.isHidden=!0;this.label=a.renderer.label("",0,0,b.shape||"callout",null,null,b.useHTML,null,"tooltip").attr({padding:e,fill:b.backgroundColor,"stroke-width":c,r:b.borderRadius,zIndex:8}).css(d).css({padding:0}).add().attr({y:-9999});ea||this.label.shadow(b.shadow);this.shared=b.shared},destroy:function(){if(this.label)this.label= -this.label.destroy();clearTimeout(this.hideTimer);clearTimeout(this.tooltipTimeout)},move:function(a,b,c,d){var e=this,f=e.now,g=e.options.animation!==!1&&!e.isHidden&&(P(a-f.x)>1||P(b-f.y)>1),h=e.followPointer||e.len>1;q(f,{x:g?(2*f.x+a)/3:a,y:g?(f.y+b)/2:b,anchorX:h?v:g?(2*f.anchorX+c)/3:c,anchorY:h?v:g?(f.anchorY+d)/2:d});e.label.attr(f);if(g)clearTimeout(this.tooltipTimeout),this.tooltipTimeout=setTimeout(function(){e&&e.move(a,b,c,d)},32)},hide:function(a){var b=this,c;clearTimeout(this.hideTimer); -if(!this.isHidden)c=this.chart.hoverPoints,this.hideTimer=setTimeout(function(){b.label.fadeOut();b.isHidden=!0},p(a,this.options.hideDelay,500)),c&&m(c,function(a){a.setState()}),this.chart.hoverPoints=null,this.chart.hoverSeries=null},getAnchor:function(a,b){var c,d=this.chart,e=d.inverted,f=d.plotTop,g=d.plotLeft,h=0,i=0,j,k,a=ra(a);c=a[0].tooltipPos;this.followPointer&&b&&(b.chartX===v&&(b=d.pointer.normalize(b)),c=[b.chartX-d.plotLeft,b.chartY-f]);c||(m(a,function(a){j=a.series.yAxis;k=a.series.xAxis; -h+=a.plotX+(!e&&k?k.left-g:0);i+=(a.plotLow?(a.plotLow+a.plotHigh)/2:a.plotY)+(!e&&j?j.top-f:0)}),h/=a.length,i/=a.length,c=[e?d.plotWidth-i:h,this.shared&&!e&&a.length>1&&b?b.chartY-f:e?d.plotHeight-h:i]);return Ua(c,w)},getPosition:function(a,b,c){var d=this.chart,e=this.distance,f={},g,h=["y",d.chartHeight,b,c.plotY+d.plotTop],i=["x",d.chartWidth,a,c.plotX+d.plotLeft],j=p(c.ttBelow,d.inverted&&!c.negative||!d.inverted&&c.negative),k=function(a,b,c,d){var g=cb-e)return!1;else f[a]=db-c/2?b-c-2:d-c/2},n=function(a){var b=h;h=i;i=b;g=a},o=function(){k.apply(0,h)!==!1?l.apply(0,i)===!1&&!g&&(n(!0),o()):g?f.x=f.y=0:(n(!0),o())};(d.inverted||this.len>1)&&n();o();return f},defaultFormatter:function(a){var b=this.points||ra(this),c;c=[a.tooltipFooterHeaderFormatter(b[0])];c=c.concat(a.bodyFormatter(b));c.push(a.tooltipFooterHeaderFormatter(b[0],!0)); -return c.join("")},refresh:function(a,b){var c=this.chart,d=this.label,e=this.options,f,g,h={},i,j=[];i=e.formatter||this.defaultFormatter;var h=c.hoverPoints,k,l=this.shared;clearTimeout(this.hideTimer);this.followPointer=ra(a)[0].series.tooltipOptions.followPointer;g=this.getAnchor(a,b);f=g[0];g=g[1];l&&(!a.series||!a.series.noSharedTooltip)?(c.hoverPoints=a,h&&m(h,function(a){a.setState()}),m(a,function(a){a.setState("hover");j.push(a.getLabelConfig())}),h={x:a[0].category,y:a[0].y},h.points=j, -this.len=j.length,a=a[0]):h=a.getLabelConfig();i=i.call(h,this);h=a.series;this.distance=p(h.tooltipOptions.distance,16);i===!1?this.hide():(this.isHidden&&(db(d),d.attr("opacity",1).show()),d.attr({text:i}),k=e.borderColor||a.color||h.color||"#606060",d.attr({stroke:k}),this.updatePosition({plotX:f,plotY:g,negative:a.negative,ttBelow:a.ttBelow}),this.isHidden=!1);G(c,"tooltipRefresh",{text:i,x:f+c.plotLeft,y:g+c.plotTop,borderColor:k})},updatePosition:function(a){var b=this.chart,c=this.label,c= -(this.options.positioner||this.getPosition).call(this,c.width,c.height,a);this.move(w(c.x),w(c.y),a.plotX+b.plotLeft,a.plotY+b.plotTop)},getXDateFormat:function(a,b,c){var d,b=b.dateTimeLabelFormats,e=c&&c.closestPointRange,f,g={millisecond:15,second:12,minute:9,hour:6,day:3},h,i;if(e){h=Oa("%m-%d %H:%M:%S.%L",a.x);for(f in F){if(e===F.week&&+Oa("%w",a.x)===c.options.startOfWeek&&h.substr(6)==="00:00:00.000"){f="week";break}else if(F[f]>e){f=i;break}else if(g[f]&&h.substr(g[f])!=="01-01 00:00:00.000".substr(g[f]))break; -f!=="week"&&(i=f)}f&&(d=b[f])}else d=b.day;return d||b.year},tooltipFooterHeaderFormatter:function(a,b){var c=b?"footer":"header",d=a.series,e=d.tooltipOptions,f=e.xDateFormat,g=d.xAxis,h=g&&g.options.type==="datetime"&&qa(a.key),c=e[c+"Format"];h&&!f&&(f=this.getXDateFormat(a,e,g));h&&f&&(c=c.replace("{point.key}","{point.key:"+f+"}"));return Ja(c,{point:a,series:d})},bodyFormatter:function(a){return Ua(a,function(a){var c=a.series.tooltipOptions;return(c.pointFormatter||a.point.tooltipFormatter).call(a.point, -c.pointFormat)})}};var oa;ab=D.documentElement.ontouchstart!==v;var Va=y.Pointer=function(a,b){this.init(a,b)};Va.prototype={init:function(a,b){var c=b.chart,d=c.events,e=ea?"":c.zoomType,c=a.inverted,f;this.options=b;this.chart=a;this.zoomX=f=/x/.test(e);this.zoomY=e=/y/.test(e);this.zoomHor=f&&!c||e&&c;this.zoomVert=e&&!c||f&&c;this.hasZoom=f||e;this.runChartClick=d&&!!d.click;this.pinchDown=[];this.lastValidTouch={};if(y.Tooltip&&b.tooltip.enabled)a.tooltip=new Kb(a,b.tooltip),this.followTouchMove= -p(b.tooltip.followTouchMove,!0);this.setDOMEvents()},normalize:function(a,b){var c,d,a=a||window.event,a=Qb(a);if(!a.target)a.target=a.srcElement;d=a.touches?a.touches.length?a.touches.item(0):a.changedTouches[0]:a;if(!b)this.chartPosition=b=Pb(this.chart.container);d.pageX===v?(c=t(a.x,a.clientX-b.left),d=a.y):(c=d.pageX-b.left,d=d.pageY-b.top);return q(a,{chartX:w(c),chartY:w(d)})},getCoordinates:function(a){var b={xAxis:[],yAxis:[]};m(this.chart.axes,function(c){b[c.isXAxis?"xAxis":"yAxis"].push({axis:c, -value:c.toValue(a[c.horiz?"chartX":"chartY"])})});return b},runPointActions:function(a){var b=this.chart,c=b.series,d=b.tooltip,e=d?d.shared:!1,f,g=b.hoverPoint,h=b.hoverSeries,i=b.chartWidth,j=b.chartWidth,k,l=[],n,o;if(!e&&!h)for(f=0;f1)&&a.dist.distRh+j&&(d=h+j);ei+k&&(e= -i+k);this.hasDragged=Math.sqrt(Math.pow(n-d,2)+Math.pow(o-e,2));if(this.hasDragged>10){l=b.isInsidePlot(n-h,o-i);if(b.hasCartesianSeries&&(this.zoomX||this.zoomY)&&l&&!s&&!this.selectionMarker)this.selectionMarker=b.renderer.rect(h,i,f?1:j,g?1:k,0).attr({fill:c.selectionMarkerFill||"rgba(69,114,167,0.25)",zIndex:7}).add();this.selectionMarker&&f&&(d-=n,this.selectionMarker.attr({width:P(d),x:(d>0?0:d)+n}));this.selectionMarker&&g&&(d=e-o,this.selectionMarker.attr({height:P(d),y:(d>0?0:d)+o}));l&& -!this.selectionMarker&&c.panning&&b.pan(a,c.panning)}},drop:function(a){var b=this,c=this.chart,d=this.hasPinched;if(this.selectionMarker){var e={xAxis:[],yAxis:[],originalEvent:a.originalEvent||a},f=this.selectionMarker,g=f.attr?f.attr("x"):f.x,h=f.attr?f.attr("y"):f.y,i=f.attr?f.attr("width"):f.width,j=f.attr?f.attr("height"):f.height,k;if(this.hasDragged||d)m(c.axes,function(c){if(c.zoomEnabled&&r(c.min)&&(d||b[{xAxis:"zoomX",yAxis:"zoomY"}[c.coll]])){var f=c.horiz,o=a.type==="touchend"?c.minPixelPadding: -0,s=c.toValue((f?g:h)+o),f=c.toValue((f?g+i:h+j)-o);e[c.coll].push({axis:c,min:H(s,f),max:t(s,f)});k=!0}}),k&&G(c,"selection",e,function(a){c.zoom(q(a,d?{animation:!1}:null))});this.selectionMarker=this.selectionMarker.destroy();d&&this.scaleGroups()}if(c)J(c.container,{cursor:c._cursor}),c.cancelClick=this.hasDragged>10,c.mouseIsDown=this.hasDragged=this.hasPinched=!1,this.pinchDown=[]},onContainerMouseDown:function(a){a=this.normalize(a);a.preventDefault&&a.preventDefault();this.dragStart(a)},onDocumentMouseUp:function(a){X[oa]&& -X[oa].pointer.drop(a)},onDocumentMouseMove:function(a){var b=this.chart,c=this.chartPosition,a=this.normalize(a,c);c&&!this.inClass(a.target,"highcharts-tracker")&&!b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop)&&this.reset()},onContainerMouseLeave:function(){var a=X[oa];if(a)a.pointer.reset(),a.pointer.chartPosition=null},onContainerMouseMove:function(a){var b=this.chart;oa=b.index;a=this.normalize(a);a.returnValue=!1;b.mouseIsDown==="mousedown"&&this.drag(a);(this.inClass(a.target,"highcharts-tracker")|| -b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop))&&!b.openMenu&&this.runPointActions(a)},inClass:function(a,b){for(var c;a;){if(c=I(a,"class"))if(c.indexOf(b)!==-1)return!0;else if(c.indexOf("highcharts-container")!==-1)return!1;a=a.parentNode}},onTrackerMouseOut:function(a){var b=this.chart.hoverSeries,c=(a=a.relatedTarget||a.toElement)&&a.point&&a.point.series;if(b&&!b.options.stickyTracking&&!this.inClass(a,"highcharts-tooltip")&&c!==b)b.onMouseOut()},onContainerClick:function(a){var b=this.chart, -c=b.hoverPoint,d=b.plotLeft,e=b.plotTop,a=this.normalize(a);a.originalEvent=a;a.cancelBubble=!0;b.cancelClick||(c&&this.inClass(a.target,"highcharts-tracker")?(G(c.series,"click",q(a,{point:c})),b.hoverPoint&&c.firePointEvent("click",a)):(q(a,this.getCoordinates(a)),b.isInsidePlot(a.chartX-d,a.chartY-e)&&G(b,"click",a)))},setDOMEvents:function(){var a=this,b=a.chart.container;b.onmousedown=function(b){a.onContainerMouseDown(b)};b.onmousemove=function(b){a.onContainerMouseMove(b)};b.onclick=function(b){a.onContainerClick(b)}; -K(b,"mouseleave",a.onContainerMouseLeave);bb===1&&K(D,"mouseup",a.onDocumentMouseUp);if(ab)b.ontouchstart=function(b){a.onContainerTouchStart(b)},b.ontouchmove=function(b){a.onContainerTouchMove(b)},bb===1&&K(D,"touchend",a.onDocumentTouchEnd)},destroy:function(){var a;Y(this.chart.container,"mouseleave",this.onContainerMouseLeave);bb||(Y(D,"mouseup",this.onDocumentMouseUp),Y(D,"touchend",this.onDocumentTouchEnd));clearInterval(this.tooltipTimeout);for(a in this)this[a]=null}};q(y.Pointer.prototype, -{pinchTranslate:function(a,b,c,d,e,f){(this.zoomHor||this.pinchHor)&&this.pinchTranslateDirection(!0,a,b,c,d,e,f);(this.zoomVert||this.pinchVert)&&this.pinchTranslateDirection(!1,a,b,c,d,e,f)},pinchTranslateDirection:function(a,b,c,d,e,f,g,h){var i=this.chart,j=a?"x":"y",k=a?"X":"Y",l="chart"+k,n=a?"width":"height",o=i["plot"+(a?"Left":"Top")],s,p,m=h||1,B=i.inverted,u=i.bounds[a?"h":"v"],r=b.length===1,q=b[0][l],t=c[0][l],v=!r&&b[1][l],w=!r&&c[1][l],y,c=function(){!r&&P(q-v)>20&&(m=h||P(t-w)/P(q- -v));p=(o-t)/m+q;s=i["plot"+(a?"Width":"Height")]/m};c();b=p;bu.max&&(b=u.max-s,y=!0);y?(t-=0.8*(t-g[j][0]),r||(w-=0.8*(w-g[j][1])),c()):g[j]=[t,w];B||(f[j]=p-o,f[n]=s);f=B?1/m:m;e[n]=s;e[j]=b;d[B?a?"scaleY":"scaleX":"scale"+k]=m;d["translate"+k]=f*o+(t-f*q)},pinch:function(a){var b=this,c=b.chart,d=b.pinchDown,e=a.touches,f=e.length,g=b.lastValidTouch,h=b.hasZoom,i=b.selectionMarker,j={},k=f===1&&(b.inClass(a.target,"highcharts-tracker")&&c.runTrackerClick||b.runChartClick), -l={};h&&!k&&a.preventDefault();Ua(e,function(a){return b.normalize(a)});if(a.type==="touchstart")m(e,function(a,b){d[b]={chartX:a.chartX,chartY:a.chartY}}),g.x=[d[0].chartX,d[1]&&d[1].chartX],g.y=[d[0].chartY,d[1]&&d[1].chartY],m(c.axes,function(a){if(a.zoomEnabled){var b=c.bounds[a.horiz?"h":"v"],d=a.minPixelPadding,e=a.toPixels(p(a.options.min,a.dataMin)),f=a.toPixels(p(a.options.max,a.dataMax)),g=H(e,f),e=t(e,f);b.min=H(a.pos,g-d);b.max=t(a.pos+a.len,e+d)}}),b.res=!0;else if(d.length){if(!i)b.selectionMarker= -i=q({destroy:ma},c.plotBox);b.pinchTranslate(d,e,j,i,l,g);b.hasPinched=h;b.scaleGroups(j,l);if(!h&&b.followTouchMove&&f===1)this.runPointActions(b.normalize(a));else if(b.res)b.res=!1,this.reset(!1,0)}},onContainerTouchStart:function(a){var b=this.chart;oa=b.index;a.touches.length===1?(a=this.normalize(a),b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop)&&!b.openMenu?(this.runPointActions(a),this.pinch(a)):this.reset()):a.touches.length===2&&this.pinch(a)},onContainerTouchMove:function(a){(a.touches.length=== -1||a.touches.length===2)&&this.pinch(a)},onDocumentTouchEnd:function(a){X[oa]&&X[oa].pointer.drop(a)}});if(O.PointerEvent||O.MSPointerEvent){var wa={},Ab=!!O.PointerEvent,Ub=function(){var a,b=[];b.item=function(a){return this[a]};for(a in wa)wa.hasOwnProperty(a)&&b.push({pageX:wa[a].pageX,pageY:wa[a].pageY,target:wa[a].target});return b},Bb=function(a,b,c,d){a=a.originalEvent||a;if((a.pointerType==="touch"||a.pointerType===a.MSPOINTER_TYPE_TOUCH)&&X[oa])d(a),d=X[oa].pointer,d[b]({type:c,target:a.currentTarget, -preventDefault:ma,touches:Ub()})};q(Va.prototype,{onContainerPointerDown:function(a){Bb(a,"onContainerTouchStart","touchstart",function(a){wa[a.pointerId]={pageX:a.pageX,pageY:a.pageY,target:a.currentTarget}})},onContainerPointerMove:function(a){Bb(a,"onContainerTouchMove","touchmove",function(a){wa[a.pointerId]={pageX:a.pageX,pageY:a.pageY};if(!wa[a.pointerId].target)wa[a.pointerId].target=a.currentTarget})},onDocumentPointerUp:function(a){Bb(a,"onContainerTouchEnd","touchend",function(a){delete wa[a.pointerId]})}, -batchMSEvents:function(a){a(this.chart.container,Ab?"pointerdown":"MSPointerDown",this.onContainerPointerDown);a(this.chart.container,Ab?"pointermove":"MSPointerMove",this.onContainerPointerMove);a(D,Ab?"pointerup":"MSPointerUp",this.onDocumentPointerUp)}});cb(Va.prototype,"init",function(a,b,c){a.call(this,b,c);(this.hasZoom||this.followTouchMove)&&J(b.container,{"-ms-touch-action":M,"touch-action":M})});cb(Va.prototype,"setDOMEvents",function(a){a.apply(this);(this.hasZoom||this.followTouchMove)&& -this.batchMSEvents(K)});cb(Va.prototype,"destroy",function(a){this.batchMSEvents(Y);a.call(this)})}var mb=y.Legend=function(a,b){this.init(a,b)};mb.prototype={init:function(a,b){var c=this,d=b.itemStyle,e=b.itemMarginTop||0;this.options=b;if(b.enabled)c.itemStyle=d,c.itemHiddenStyle=z(d,b.itemHiddenStyle),c.itemMarginTop=e,c.padding=d=p(b.padding,8),c.initialItemX=d,c.initialItemY=d-5,c.maxItemWidth=0,c.chart=a,c.itemHeight=0,c.symbolWidth=p(b.symbolWidth,16),c.pages=[],c.render(),K(c.chart,"endResize", -function(){c.positionCheckboxes()})},colorizeItem:function(a,b){var c=this.options,d=a.legendItem,e=a.legendLine,f=a.legendSymbol,g=this.itemHiddenStyle.color,c=b?c.itemStyle.color:g,h=b?a.legendColor||a.color||"#CCC":g,g=a.options&&a.options.marker,i={fill:h},j;d&&d.css({fill:c,color:c});e&&e.attr({stroke:h});if(f){if(g&&f.isMarker)for(j in i.stroke=h,g=a.convertAttribs(g),g)d=g[j],d!==v&&(i[j]=d);f.attr(i)}},positionItem:function(a){var b=this.options,c=b.symbolPadding,b=!b.rtl,d=a._legendItemPos, -e=d[0],d=d[1],f=a.checkbox;a.legendGroup&&a.legendGroup.translate(b?e:this.legendWidth-e-2*c-4,d);if(f)f.x=e,f.y=d},destroyItem:function(a){var b=a.checkbox;m(["legendItem","legendLine","legendSymbol","legendGroup"],function(b){a[b]&&(a[b]=a[b].destroy())});b&&Ra(a.checkbox)},clearItems:function(){var a=this;m(a.getAllItems(),function(b){a.destroyItem(b)})},destroy:function(){var a=this.group,b=this.box;if(b)this.box=b.destroy();if(a)this.group=a.destroy()},positionCheckboxes:function(a){var b=this.group.alignAttr, -c,d=this.clipHeight||this.legendHeight;if(b)c=b.translateY,m(this.allItems,function(e){var f=e.checkbox,g;f&&(g=c+f.y+(a||0)+3,J(f,{left:b.translateX+e.checkboxOffset+f.x-20+"px",top:g+"px",display:g>c-6&&g(n||b.chartWidth-2*j-x-d.x))this.itemX=x,this.itemY+=s+this.lastLineHeight+o;this.maxItemWidth=t(this.maxItemWidth,f);this.lastItemY=s+this.itemY+o;this.lastLineHeight=t(g,this.lastLineHeight);a._legendItemPos=[this.itemX,this.itemY];e?this.itemX+=f:(this.itemY+=s+g+o,this.lastLineHeight=g);this.offsetWidth=n||t((e?this.itemX-x-k:f)+j,this.offsetWidth)},getAllItems:function(){var a= -[];m(this.chart.series,function(b){var c=b.options;if(p(c.showInLegend,!r(c.linkedTo)?v:!1,!0))a=a.concat(b.legendItems||(c.legendType==="point"?b.data:b))});return a},adjustMargins:function(a,b){var c=this.chart,d=this.options,e=d.align[0]+d.verticalAlign[0]+d.layout[0];this.display&&!d.floating&&m([/(lth|ct|rth)/,/(rtv|rm|rbv)/,/(rbh|cb|lbh)/,/(lbv|lm|ltv)/],function(f,g){f.test(e)&&!r(a[g])&&(c[ib[g]]=t(c[ib[g]],c.legend[(g+1)%2?"legendHeight":"legendWidth"]+[1,-1,-1,1][g]*d[g%2?"x":"y"]+p(d.margin, -12)+b[g]))})},render:function(){var a=this,b=a.chart,c=b.renderer,d=a.group,e,f,g,h,i=a.box,j=a.options,k=a.padding,l=j.borderWidth,n=j.backgroundColor;a.itemX=a.initialItemX;a.itemY=a.initialItemY;a.offsetWidth=0;a.lastItemY=0;if(!d)a.group=d=c.g("legend").attr({zIndex:7}).add(),a.contentGroup=c.g().attr({zIndex:1}).add(d),a.scrollGroup=c.g().add(a.contentGroup);a.renderTitle();e=a.getAllItems();qb(e,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)}); -j.reversed&&e.reverse();a.allItems=e;a.display=f=!!e.length;a.lastLineHeight=0;m(e,function(b){a.renderItem(b)});g=(j.width||a.offsetWidth)+k;h=a.lastItemY+a.lastLineHeight+a.titleHeight;h=a.handleOverflow(h);h+=k;if(l||n){if(i){if(g>0&&h>0)i[i.isNew?"attr":"animate"](i.crisp({width:g,height:h})),i.isNew=!1}else a.box=i=c.rect(0,0,g,h,j.borderRadius,l||0).attr({stroke:j.borderColor,"stroke-width":l||0,fill:n||M}).add(d).shadow(j.shadow),i.isNew=!0;i[f?"show":"hide"]()}a.legendWidth=g;a.legendHeight= -h;m(e,function(b){a.positionItem(b)});f&&d.align(q({width:g,height:h},j),!0,"spacingBox");b.isResizing||this.positionCheckboxes()},handleOverflow:function(a){var b=this,c=this.chart,d=c.renderer,e=this.options,f=e.y,f=c.spacingBox.height+(e.verticalAlign==="top"?-f:f)-this.padding,g=e.maxHeight,h,i=this.clipRect,j=e.navigation,k=p(j.animation,!0),l=j.arrowSize||12,n=this.nav,o=this.pages,s,x=this.allItems;e.layout==="horizontal"&&(f/=2);g&&(f=H(f,g));o.length=0;if(a>f&&!e.useHTML){this.clipHeight= -h=t(f-20-this.titleHeight-this.padding,0);this.currentPage=p(this.currentPage,1);this.fullHeight=a;m(x,function(a,b){var c=a._legendItemPos[1],d=w(a.legendItem.getBBox().height),e=o.length;if(!e||c-o[e-1]>h&&(s||c)!==o[e-1])o.push(s||c),e++;b===x.length-1&&c+d-o[e-1]>h&&o.push(c);c!==s&&(s=c)});if(!i)i=b.clipRect=d.clipRect(0,this.padding,9999,0),b.contentGroup.clip(i);i.attr({height:h});if(!n)this.nav=n=d.g().attr({zIndex:1}).add(this.group),this.up=d.symbol("triangle",0,0,l,l).on("click",function(){b.scroll(-1, -k)}).add(n),this.pager=d.text("",15,10).css(j.style).add(n),this.down=d.symbol("triangle-down",0,0,l,l).on("click",function(){b.scroll(1,k)}).add(n);b.scroll(0);a=f}else if(n)i.attr({height:c.chartHeight}),n.hide(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0;return a},scroll:function(a,b){var c=this.pages,d=c.length,e=this.currentPage+a,f=this.clipHeight,g=this.options.navigation,h=g.activeColor,g=g.inactiveColor,i=this.pager,j=this.padding;e>d&&(e=d);if(e>0)b!==v&&Sa(b,this.chart),this.nav.attr({translateX:j, -translateY:f+this.padding+7+this.titleHeight,visibility:"visible"}),this.up.attr({fill:e===1?g:h}).css({cursor:e===1?"default":"pointer"}),i.attr({text:e+"/"+d}),this.down.attr({x:18+this.pager.getBBox().width,fill:e===d?g:h}).css({cursor:e===d?"default":"pointer"}),c=-c[e-1]+this.initialItemY,this.scrollGroup.animate({translateY:c}),this.currentPage=e,this.positionCheckboxes(c)}};Na=y.LegendSymbolMixin={drawRectangle:function(a,b){var c=a.options.symbolHeight||12;b.legendSymbol=this.chart.renderer.rect(0, -a.baseline-5-c/2,a.symbolWidth,c,a.options.symbolRadius||0).attr({zIndex:3}).add(b.legendGroup)},drawLineMarker:function(a){var b=this.options,c=b.marker,d;d=a.symbolWidth;var e=this.chart.renderer,f=this.legendGroup,a=a.baseline-w(e.fontMetrics(a.options.itemStyle.fontSize,this.legendItem).b*0.3),g;if(b.lineWidth){g={"stroke-width":b.lineWidth};if(b.dashStyle)g.dashstyle=b.dashStyle;this.legendLine=e.path(["M",0,a,"L",d,a]).attr(g).add(f)}if(c&&c.enabled!==!1)b=c.radius,this.legendSymbol=d=e.symbol(this.symbol, -d/2-b,a-b,2*b,2*b).add(f),d.isMarker=!0}};(/Trident\/7\.0/.test(Ba)||La)&&cb(mb.prototype,"positionItem",function(a,b){var c=this,d=function(){b._legendItemPos&&a.call(c,b)};d();setTimeout(d)});A=y.Chart=function(){this.init.apply(this,arguments)};A.prototype={callbacks:[],init:function(a,b){var c,d=a.series;a.series=null;c=z(S,a);c.series=a.series=d;this.userOptions=a;d=c.chart;this.margin=this.splashArray("margin",d);this.spacing=this.splashArray("spacing",d);var e=d.events;this.bounds={h:{},v:{}}; -this.callback=b;this.isResizing=0;this.options=c;this.axes=[];this.series=[];this.hasCartesianSeries=d.showAxes;var f=this,g;f.index=X.length;X.push(f);bb++;d.reflow!==!1&&K(f,"load",function(){f.initReflow()});if(e)for(g in e)K(f,g,e[g]);f.xAxis=[];f.yAxis=[];f.animation=ea?!1:p(d.animation,!0);f.pointCount=f.colorCounter=f.symbolCounter=0;f.firstRender()},initSeries:function(a){var b=this.options.chart;(b=N[a.type||b.type||b.defaultSeriesType])||ka(17,!0);b=new b;b.init(this,a);return b},isInsidePlot:function(a, -b,c){var d=c?b:a,a=c?a:b;return d>=0&&d<=this.plotWidth&&a>=0&&a<=this.plotHeight},redraw:function(a){var b=this.axes,c=this.series,d=this.pointer,e=this.legend,f=this.isDirtyLegend,g,h,i=this.hasCartesianSeries,j=this.isDirtyBox,k=c.length,l=k,n=this.renderer,o=n.isHidden(),s=[];Sa(a,this);o&&this.cloneRenderTo();for(this.layOutTitles();l--;)if(a=c[l],a.options.stacking&&(g=!0,a.isDirty)){h=!0;break}if(h)for(l=k;l--;)if(a=c[l],a.options.stacking)a.isDirty=!0;m(c,function(a){a.isDirty&&a.options.legendType=== -"point"&&(f=!0)});if(f&&e.options.enabled)e.render(),this.isDirtyLegend=!1;g&&this.getStacks();if(i&&!this.isResizing)this.maxTicks=null,m(b,function(a){a.setScale()});this.getMargins();i&&(m(b,function(a){a.isDirty&&(j=!0)}),m(b,function(a){if(a.isDirtyExtremes)a.isDirtyExtremes=!1,s.push(function(){G(a,"afterSetExtremes",q(a.eventArgs,a.getExtremes()));delete a.eventArgs});(j||g)&&a.redraw()}));j&&this.drawChartBox();m(c,function(a){a.isDirty&&a.visible&&(!a.isCartesian||a.xAxis)&&a.redraw()}); -d&&d.reset(!0);n.draw();G(this,"redraw");o&&this.cloneRenderTo(!0);m(s,function(a){a.call()})},get:function(a){var b=this.axes,c=this.series,d,e;for(d=0;d19?this.containerHeight:400))},cloneRenderTo:function(a){var b=this.renderToClone,c=this.container;a?b&&(this.renderTo.appendChild(c),Ra(b),delete this.renderToClone):(c&& -c.parentNode===this.renderTo&&this.renderTo.removeChild(c),this.renderToClone=b=this.renderTo.cloneNode(0),J(b,{position:"absolute",top:"-9999px",display:"block"}),b.style.setProperty&&b.style.setProperty("display","block","important"),D.body.appendChild(b),c&&b.appendChild(c))},getContainer:function(){var a,b=this.options.chart,c,d,e;this.renderTo=a=b.renderTo;e="highcharts-"+yb++;if(Da(a))this.renderTo=a=D.getElementById(a);a||ka(13,!0);c=C(I(a,"data-highcharts-chart"));!isNaN(c)&&X[c]&&X[c].hasRendered&& -X[c].destroy();I(a,"data-highcharts-chart",this.index);a.innerHTML="";!b.skipClone&&!a.offsetWidth&&this.cloneRenderTo();this.getChartSize();c=this.chartWidth;d=this.chartHeight;this.container=a=Z(Ka,{className:"highcharts-container"+(b.className?" "+b.className:""),id:e},q({position:"relative",overflow:"hidden",width:c+"px",height:d+"px",textAlign:"left",lineHeight:"normal",zIndex:0,"-webkit-tap-highlight-color":"rgba(0,0,0,0)"},b.style),this.renderToClone||a);this._cursor=a.style.cursor;this.renderer= -b.forExport?new ta(a,c,d,b.style,!0):new $a(a,c,d,b.style);ea&&this.renderer.create(this,a,c,d);this.renderer.chartIndex=this.index},getMargins:function(a){var b=this.spacing,c=this.margin,d=this.titleOffset;this.resetMargins();if(d&&!r(c[0]))this.plotTop=t(this.plotTop,d+this.options.title.margin+b[0]);this.legend.adjustMargins(c,b);this.extraBottomMargin&&(this.marginBottom+=this.extraBottomMargin);this.extraTopMargin&&(this.plotTop+=this.extraTopMargin);a||this.getAxisMargins()},getAxisMargins:function(){var a= -this,b=a.axisOffset=[0,0,0,0],c=a.margin;a.hasCartesianSeries&&m(a.axes,function(a){a.getOffset()});m(ib,function(d,e){r(c[e])||(a[d]+=b[e])});a.setChartSize()},reflow:function(a){var b=this,c=b.options.chart,d=b.renderTo,e=c.width||jb(d,"width"),f=c.height||jb(d,"height"),c=a?a.target:O,d=function(){if(b.container)b.setSize(e,f,!1),b.hasUserSize=null};if(!b.hasUserSize&&!b.isPrinting&&e&&f&&(c===O||c===D)){if(e!==b.containerWidth||f!==b.containerHeight)clearTimeout(b.reflowTimeout),a?b.reflowTimeout= -setTimeout(d,100):d();b.containerWidth=e;b.containerHeight=f}},initReflow:function(){var a=this,b=function(b){a.reflow(b)};K(O,"resize",b);K(a,"destroy",function(){Y(O,"resize",b)})},setSize:function(a,b,c){var d=this,e,f,g;d.isResizing+=1;g=function(){d&&G(d,"endResize",null,function(){d.isResizing-=1})};Sa(c,d);d.oldChartHeight=d.chartHeight;d.oldChartWidth=d.chartWidth;if(r(a))d.chartWidth=e=t(0,w(a)),d.hasUserSize=!!e;if(r(b))d.chartHeight=f=t(0,w(b));(za?lb:J)(d.container,{width:e+"px",height:f+ -"px"},za);d.setChartSize(!0);d.renderer.setSize(e,f,c);d.maxTicks=null;m(d.axes,function(a){a.isDirty=!0;a.setScale()});m(d.series,function(a){a.isDirty=!0});d.isDirtyLegend=!0;d.isDirtyBox=!0;d.layOutTitles();d.getMargins();d.redraw(c);d.oldChartHeight=null;G(d,"resize");za===!1?g():setTimeout(g,za&&za.duration||500)},setChartSize:function(a){var b=this.inverted,c=this.renderer,d=this.chartWidth,e=this.chartHeight,f=this.options.chart,g=this.spacing,h=this.clipOffset,i,j,k,l;this.plotLeft=i=w(this.plotLeft); -this.plotTop=j=w(this.plotTop);this.plotWidth=k=t(0,w(d-i-this.marginRight));this.plotHeight=l=t(0,w(e-j-this.marginBottom));this.plotSizeX=b?l:k;this.plotSizeY=b?k:l;this.plotBorderWidth=f.plotBorderWidth||0;this.spacingBox=c.spacingBox={x:g[3],y:g[0],width:d-g[3]-g[1],height:e-g[0]-g[2]};this.plotBox=c.plotBox={x:i,y:j,width:k,height:l};d=2*U(this.plotBorderWidth/2);b=sa(t(d,h[3])/2);c=sa(t(d,h[0])/2);this.clipBox={x:b,y:c,width:U(this.plotSizeX-t(d,h[1])/2-b),height:t(0,U(this.plotSizeY-t(d,h[2])/ -2-c))};a||m(this.axes,function(a){a.setAxisSize();a.setAxisTranslation()})},resetMargins:function(){var a=this;m(ib,function(b,c){a[b]=p(a.margin[c],a.spacing[c])});a.axisOffset=[0,0,0,0];a.clipOffset=[0,0,0,0]},drawChartBox:function(){var a=this.options.chart,b=this.renderer,c=this.chartWidth,d=this.chartHeight,e=this.chartBackground,f=this.plotBackground,g=this.plotBorder,h=this.plotBGImage,i=a.borderWidth||0,j=a.backgroundColor,k=a.plotBackgroundColor,l=a.plotBackgroundImage,n=a.plotBorderWidth|| -0,o,s=this.plotLeft,p=this.plotTop,m=this.plotWidth,r=this.plotHeight,u=this.plotBox,q=this.clipRect,t=this.clipBox;o=i+(a.shadow?8:0);if(i||j)if(e)e.animate(e.crisp({width:c-o,height:d-o}));else{e={fill:j||M};if(i)e.stroke=a.borderColor,e["stroke-width"]=i;this.chartBackground=b.rect(o/2,o/2,c-o,d-o,a.borderRadius,i).attr(e).addClass("highcharts-background").add().shadow(a.shadow)}if(k)f?f.animate(u):this.plotBackground=b.rect(s,p,m,r,0).attr({fill:k}).add().shadow(a.plotShadow);if(l)h?h.animate(u): -this.plotBGImage=b.image(l,s,p,m,r).add();q?q.animate({width:t.width,height:t.height}):this.clipRect=b.clipRect(t);if(n)g?g.animate(g.crisp({x:s,y:p,width:m,height:r,strokeWidth:-n})):this.plotBorder=b.rect(s,p,m,r,0,-n).attr({stroke:a.plotBorderColor,"stroke-width":n,fill:M,zIndex:1}).add();this.isDirtyBox=!1},propFromSeries:function(){var a=this,b=a.options.chart,c,d=a.options.series,e,f;m(["inverted","angular","polar"],function(g){c=N[b.type||b.defaultSeriesType];f=a[g]||b[g]||c&&c.prototype[g]; -for(e=d&&d.length;!f&&e--;)(c=N[d[e].type])&&c.prototype[g]&&(f=!0);a[g]=f})},linkSeries:function(){var a=this,b=a.series;m(b,function(a){a.linkedSeries.length=0});m(b,function(b){var d=b.options.linkedTo;if(Da(d)&&(d=d===":previous"?a.series[b.index-1]:a.get(d)))d.linkedSeries.push(b),b.linkedParent=d})},renderSeries:function(){m(this.series,function(a){a.translate();a.render()})},renderLabels:function(){var a=this,b=a.options.labels;b.items&&m(b.items,function(c){var d=q(b.style,c.style),e=C(d.left)+ -a.plotLeft,f=C(d.top)+a.plotTop+12;delete d.left;delete d.top;a.renderer.text(c.html,e,f).attr({zIndex:2}).css(d).add()})},render:function(){var a=this.axes,b=this.renderer,c=this.options,d,e,f,g;this.setTitle();this.legend=new mb(this,c.legend);this.getStacks();this.getMargins(!0);this.setChartSize();d=this.plotWidth;e=this.plotHeight-=13;m(a,function(a){a.setScale()});this.getAxisMargins();f=d/this.plotWidth>1.2;g=e/this.plotHeight>1.1;if(f||g)this.maxTicks=null,m(a,function(a){(a.horiz&&f||!a.horiz&& -g)&&a.setTickInterval(!0)}),this.getMargins();this.drawChartBox();this.hasCartesianSeries&&m(a,function(a){a.render()});if(!this.seriesGroup)this.seriesGroup=b.g("series-group").attr({zIndex:3}).add();this.renderSeries();this.renderLabels();this.showCredits(c.credits);this.hasRendered=!0},showCredits:function(a){if(a.enabled&&!this.credits)this.credits=this.renderer.text(a.text,0,0).on("click",function(){if(a.href)location.href=a.href}).attr({align:a.position.align,zIndex:8}).css(a.style).add().align(a.position)}, -destroy:function(){var a=this,b=a.axes,c=a.series,d=a.container,e,f=d&&d.parentNode;G(a,"destroy");X[a.index]=v;bb--;a.renderTo.removeAttribute("data-highcharts-chart");Y(a);for(e=b.length;e--;)b[e]=b[e].destroy();for(e=c.length;e--;)c[e]=c[e].destroy();m("title,subtitle,chartBackground,plotBackground,plotBGImage,plotBorder,seriesGroup,clipRect,credits,pointer,scroller,rangeSelector,legend,resetZoomButton,tooltip,renderer".split(","),function(b){var c=a[b];c&&c.destroy&&(a[b]=c.destroy())});if(d)d.innerHTML= -"",Y(d),f&&Ra(d);for(e in a)delete a[e]},isReadyToRender:function(){var a=this;return!ba&&O==O.top&&D.readyState!=="complete"||ea&&!O.canvg?(ea?Jb.push(function(){a.firstRender()},a.options.global.canvasToolsURL):D.attachEvent("onreadystatechange",function(){D.detachEvent("onreadystatechange",a.firstRender);D.readyState==="complete"&&a.firstRender()}),!1):!0},firstRender:function(){var a=this,b=a.options,c=a.callback;if(a.isReadyToRender()){a.getContainer();G(a,"init");a.resetMargins();a.setChartSize(); -a.propFromSeries();a.getAxes();m(b.series||[],function(b){a.initSeries(b)});a.linkSeries();G(a,"beforeRender");if(y.Pointer)a.pointer=new Va(a,b);a.render();a.renderer.draw();c&&c.apply(a,[a]);m(a.callbacks,function(b){a.index!==v&&b.apply(a,[a])});G(a,"load");a.cloneRenderTo(!0)}},splashArray:function(a,b){var c=b[a],c=ca(c)?c:[c,c,c,c];return[p(b[a+"Top"],c[0]),p(b[a+"Right"],c[1]),p(b[a+"Bottom"],c[2]),p(b[a+"Left"],c[3])]}};var Vb=y.CenteredSeriesMixin={getCenter:function(){var a=this.options, -b=this.chart,c=2*(a.slicedOffset||0),d=b.plotWidth-2*c,b=b.plotHeight-2*c,e=a.center,e=[p(e[0],"50%"),p(e[1],"50%"),a.size||"100%",a.innerSize||0],f=H(d,b),g,h,i;for(h=0;h<4;++h)i=e[h],g=/%$/.test(i),a=h<2||h===2&&g,e[h]=(g?[d,b,f,e[2]][h]*C(i)/100:C(i))+(a?c:0);return e}},Ga=function(){};Ga.prototype={init:function(a,b,c){this.series=a;this.color=a.color;this.applyOptions(b,c);this.pointAttr={};if(a.options.colorByPoint&&(b=a.options.colors||a.chart.options.colors,this.color=this.color||b[a.colorCounter++], -a.colorCounter===b.length))a.colorCounter=0;a.chart.pointCount++;return this},applyOptions:function(a,b){var c=this.series,d=c.options.pointValKey||c.pointValKey,a=Ga.prototype.optionsToObject.call(this,a);q(this,a);this.options=this.options?q(this.options,a):a;if(d)this.y=this[d];if(this.x===v&&c)this.x=b===v?c.autoIncrement():b;return this},optionsToObject:function(a){var b={},c=this.series,d=c.pointArrayMap||["y"],e=d.length,f=0,g=0;if(typeof a==="number"||a===null)b[d[0]]=a;else if(Ha(a)){if(a.length> -e){c=typeof a[0];if(c==="string")b.name=a[0];else if(c==="number")b.x=a[0];f++}for(;ga+1&&b.push(d.slice(a+1,g)),a=g):g===e-1&&b.push(d.slice(a+1,g+1))});this.segments=b},setOptions:function(a){var b= -this.chart,c=b.options.plotOptions,b=b.userOptions||{},d=b.plotOptions||{},e=c[this.type];this.userOptions=a;c=z(e,c.series,a);this.tooltipOptions=z(S.tooltip,S.plotOptions[this.type].tooltip,b.tooltip,d.series&&d.series.tooltip,d[this.type]&&d[this.type].tooltip,a.tooltip);e.marker===null&&delete c.marker;this.zoneAxis=c.zoneAxis;a=this.zones=(c.zones||[]).slice();if((c.negativeColor||c.negativeFillColor)&&!c.zones)a.push({value:c[this.zoneAxis+"Threshold"]||c.threshold||0,color:c.negativeColor, -fillColor:c.negativeFillColor});a.length&&r(a[a.length-1].value)&&a.push({color:this.color,fillColor:this.fillColor});return c},getCyclic:function(a,b,c){var d=this.userOptions,e="_"+a+"Index",f=a+"Counter";b||(r(d[e])?b=d[e]:(d[e]=b=this.chart[f]%c.length,this.chart[f]+=1),b=c[b]);this[a]=b},getColor:function(){this.options.colorByPoint||this.getCyclic("color",this.options.color||aa[this.type].color,this.chart.options.colors)},getSymbol:function(){var a=this.options.marker;this.getCyclic("symbol", -a.symbol,this.chart.options.symbols);if(/^url/.test(this.symbol))a.radius=0},drawLegendSymbol:Na.drawLineMarker,setData:function(a,b,c,d){var e=this,f=e.points,g=f&&f.length||0,h,i=e.options,j=e.chart,k=null,l=e.xAxis,n=l&&!!l.categories,o=i.turboThreshold,s=this.xData,x=this.yData,r=(h=e.pointArrayMap)&&h.length,a=a||[];h=a.length;b=p(b,!0);if(d!==!1&&h&&g===h&&!e.cropped&&!e.hasGroupedData&&e.visible)m(a,function(a,b){f[b].update(a,!1,null,!1)});else{e.xIncrement=null;e.pointRange=n?1:i.pointRange; -e.colorCounter=0;m(this.parallelArrays,function(a){e[a+"Data"].length=0});if(o&&h>o){for(c=0;k===null&&ci||this.forceCrop))if(b[d- -1]n)b=[],c=[];else if(b[0]n)e=this.cropData(this.xData,this.yData,l,n),b=e.xData,c=e.yData,e=e.start,f=!0;for(i=b.length-1;i>=0;i--)d=b[i]-b[i-1],d>0&&(g===v||d=c){f=t(0,i-h);break}for(;i -d){g=i+h;break}return{xData:a.slice(f,g),yData:b.slice(f,g),start:f,end:g}},generatePoints:function(){var a=this.options.data,b=this.data,c,d=this.processedXData,e=this.processedYData,f=this.pointClass,g=d.length,h=this.cropStart||0,i,j=this.hasGroupedData,k,l=[],n;if(!b&&!j)b=[],b.length=a.length,b=this.data=b;for(n=0;n0),j=this.getExtremesFromAll||this.cropped||(c[l+1]||j)>=g&&(c[l-1]||j)<=h,i&&j)if(i=k.length)for(;i--;)k[i]!==null&&(e[f++]=k[i]);else e[f++]= -k;this.dataMin=p(void 0,Pa(e));this.dataMax=p(void 0,Fa(e))},translate:function(){this.processedXData||this.processData();this.generatePoints();for(var a=this.options,b=a.stacking,c=this.xAxis,d=c.categories,e=this.yAxis,f=this.points,g=f.length,h=!!this.modifyValue,i=a.pointPlacement,j=i==="between"||qa(i),k=a.threshold,l,n,o,s=Number.MAX_VALUE,a=0;a=0&&n<=e.len&&l>=0&&l<=c.len; -m.clientX=j?c.translate(q,0,0,0,1):l;m.negative=m.y<(k||0);m.category=d&&d[m.x]!==v?d[m.x]:m.x;a&&(s=H(s,P(l-o)));o=l}this.closestPointRangePx=s;this.getSegments()},setClip:function(a){var b=this.chart,c=b.renderer,d=b.inverted,e=this.clipBox,f=e||b.clipBox,g=this.sharedClipKey||["_sharedClip",a&&a.duration,a&&a.easing,f.height].join(","),h=b[g],i=b[g+"m"];if(!h){if(a)f.width=0,b[g+"m"]=i=c.clipRect(-99,d?-b.plotLeft:-b.plotTop,99,d?b.chartWidth:b.chartHeight);b[g]=h=c.clipRect(f)}a&&(h.count+=1); -if(this.options.clip!==!1)this.group.clip(a||e?h:b.clipRect),this.markerGroup.clip(i),this.sharedClipKey=g;a||(h.count-=1,h.count<=0&&g&&b[g]&&(e||(b[g]=b[g].destroy()),b[g+"m"]&&(b[g+"m"]=b[g+"m"].destroy())))},animate:function(a){var b=this.chart,c=this.options.animation,d;if(c&&!ca(c))c=aa[this.type].animation;a?this.setClip(c):(d=this.sharedClipKey,(a=b[d])&&a.animate({width:b.plotSizeX},c),b[d+"m"]&&b[d+"m"].animate({width:b.plotSizeX+99},c),this.animate=null)},afterAnimate:function(){this.setClip(); -G(this,"afterAnimate")},drawPoints:function(){var a,b=this.points,c=this.chart,d,e,f,g,h,i,j,k,l=this.options.marker,n=this.pointAttr[""],o,m,x,r=this.markerGroup,t=p(l.enabled,this.xAxis.isRadial,this.closestPointRangePx>2*l.radius);if(l.enabled!==!1||this._hasPointMarkers)for(f=b.length;f--;)if(g=b[f],d=U(g.plotX),e=g.plotY,k=g.graphic,o=g.marker||{},m=!!g.marker,a=t&&o.enabled===v||o.enabled,x=g.isInside,a&&e!==v&&!isNaN(e)&&g.y!==null)if(a=g.pointAttr[g.selected?"select":""]||n,h=a.r,i=p(o.symbol, -this.symbol),j=i.indexOf("url")===0,k)k[x?"show":"hide"](!0).animate(q({x:d-h,y:e-h},k.symbolName?{width:2*h,height:2*h}:{}));else{if(x&&(h>0||j))g.graphic=c.renderer.symbol(i,d-h,e-h,2*h,2*h,m?o:l).attr(a).add(r)}else if(k)g.graphic=k.destroy()},convertAttribs:function(a,b,c,d){var e=this.pointAttrToOptions,f,g,h={},a=a||{},b=b||{},c=c||{},d=d||{};for(f in e)g=e[f],h[f]=p(a[g],b[f],c[f],d[f]);return h},getAttribs:function(){var a=this,b=a.options,c=aa[a.type].marker?b.marker:b,d=c.states,e=d.hover, -f,g=a.color,h=a.options.negativeColor;f={stroke:g,fill:g};var i=a.points||[],j,k=[],l,n=a.pointAttrToOptions;l=a.hasPointSpecificOptions;var o=c.lineColor,s=c.fillColor;j=b.turboThreshold;var p=a.zones,t=a.zoneAxis||"y",B;b.marker?(e.radius=e.radius||c.radius+e.radiusPlus,e.lineWidth=e.lineWidth||c.lineWidth+e.lineWidthPlus):(e.color=e.color||na(e.color||g).brighten(e.brightness).get(),e.negativeColor=e.negativeColor||na(e.negativeColor||h).brighten(e.brightness).get());k[""]=a.convertAttribs(c,f); -m(["hover","select"],function(b){k[b]=a.convertAttribs(d[b],k[""])});a.pointAttr=k;g=i.length;if(!j||g=f.value;)f=p[++l];j.color=j.fillColor=f.color}l=b.colorByPoint||j.color;if(j.options)for(B in n)r(c[n[B]])&&(l=!0);if(l){c=c||{};l=[];d=c.states||{};f=d.hover=d.hover||{};if(!b.marker)f.color=f.color||!j.options.color&&e[j.negative&&h?"negativeColor":"color"]||na(j.color).brighten(f.brightness|| -e.brightness).get();f={color:j.color};if(!s)f.fillColor=j.color;if(!o)f.lineColor=j.color;l[""]=a.convertAttribs(q(f,c),k[""]);l.hover=a.convertAttribs(d.hover,k.hover,l[""]);l.select=a.convertAttribs(d.select,k.select,l[""])}else l=k;j.pointAttr=l}},destroy:function(){var a=this,b=a.chart,c=/AppleWebKit\/533/.test(Ba),d,e,f=a.data||[],g,h,i;G(a,"destroy");Y(a);m(a.axisTypes||[],function(b){if(i=a[b])ia(i.series,a),i.isDirty=i.forceRedraw=!0});a.legendItem&&a.chart.legend.destroyItem(a);for(e=f.length;e--;)(g= -f[e])&&g.destroy&&g.destroy();a.points=null;clearTimeout(a.animationTimeout);m("area,graph,dataLabelsGroup,group,markerGroup,tracker,graphNeg,areaNeg,posClip,negClip".split(","),function(b){a[b]&&(d=c&&b==="group"?"hide":"destroy",a[b][d]())});if(b.hoverSeries===a)b.hoverSeries=null;ia(b.series,a);for(h in a)delete a[h]},getSegmentPath:function(a){var b=this,c=[],d=b.options.step;m(a,function(e,f){var g=e.plotX,h=e.plotY,i;b.getPointSpline?c.push.apply(c,b.getPointSpline(a,e,f)):(c.push(f?"L":"M"), -d&&f&&(i=a[f-1],d==="right"?c.push(i.plotX,h):d==="center"?c.push((i.plotX+g)/2,i.plotY,(i.plotX+g)/2,h):c.push(g,i.plotY)),c.push(e.plotX,e.plotY))});return c},getGraphPath:function(){var a=this,b=[],c,d=[];m(a.segments,function(e){c=a.getSegmentPath(e);e.length>1?b=b.concat(c):d.push(e[0])});a.singlePoints=d;return a.graphPath=b},drawGraph:function(){var a=this,b=this.options,c=[["graph",b.lineColor||this.color,b.dashStyle]],d=b.lineWidth,e=b.linecap!=="square",f=this.getGraphPath(),g=this.fillGraph&& -this.color||M;m(this.zones,function(d,e){c.push(["colorGraph"+e,d.color||a.color,d.dashStyle||b.dashStyle])});m(c,function(c,i){var j=c[0],k=a[j];if(k)db(k),k.animate({d:f});else if((d||g)&&f.length)k={stroke:c[1],"stroke-width":d,fill:g,zIndex:1},c[2]?k.dashstyle=c[2]:e&&(k["stroke-linecap"]=k["stroke-linejoin"]="round"),a[j]=a.chart.renderer.path(f).attr(k).add(a.group).shadow(i<2&&b.shadow)})},applyZones:function(){var a=this,b=this.chart,c=b.renderer,d=this.zones,e,f,g=this.clips||[],h,i=this.graph, -j=this.area,k=t(b.chartWidth,b.chartHeight),l=this[(this.zoneAxis||"y")+"Axis"],n=l.reversed,o=l.horiz,s=!1;if(d.length&&(i||j))i.hide(),j&&j.hide(),m(d,function(d,i){e=p(f,n?o?b.plotWidth:0:o?0:l.toPixels(l.min));f=w(l.toPixels(p(d.value,l.max),!0));s&&(e=f=l.toPixels(l.max));if(l.isXAxis){if(h={x:n?f:e,y:0,width:Math.abs(e-f),height:k},!o)h.x=b.plotHeight-h.x}else if(h={x:0,y:n?e:f,width:k,height:Math.abs(e-f)},o)h.y=b.plotWidth-h.y;b.inverted&&c.isVML&&(h=l.isXAxis?{x:0,y:n?e:f,height:h.width, -width:b.chartWidth}:{x:h.y-b.plotLeft-b.spacingBox.x,y:0,width:h.height,height:b.chartHeight});g[i]?g[i].animate(h):(g[i]=c.clipRect(h),a["colorGraph"+i].clip(g[i]),j&&a["colorArea"+i].clip(g[i]));s=d.value>l.max}),this.clips=g},invertGroups:function(){function a(){var a={width:b.yAxis.len,height:b.xAxis.len};m(["group","markerGroup"],function(c){b[c]&&b[c].attr(a).invert()})}var b=this,c=b.chart;if(b.xAxis)K(c,"resize",a),K(b,"destroy",function(){Y(c,"resize",a)}),a(),b.invertGroups=a},plotGroup:function(a, -b,c,d,e){var f=this[a],g=!f;g&&(this[a]=f=this.chart.renderer.g(b).attr({visibility:c,zIndex:d||0.1}).add(e));f[g?"attr":"animate"](this.getPlotBox());return f},getPlotBox:function(){var a=this.chart,b=this.xAxis,c=this.yAxis;if(a.inverted)b=c,c=this.xAxis;return{translateX:b?b.left:a.plotLeft,translateY:c?c.top:a.plotTop,scaleX:1,scaleY:1}},render:function(){var a=this,b=a.chart,c,d=a.options,e=(c=d.animation)&&!!a.animate&&b.renderer.isSVG&&p(c.duration,500)||0,f=a.visible?"visible":"hidden",g= -d.zIndex,h=a.hasRendered,i=b.seriesGroup;c=a.plotGroup("group","series",f,g,i);a.markerGroup=a.plotGroup("markerGroup","markers",f,g,i);e&&a.animate(!0);a.getAttribs();c.inverted=a.isCartesian?b.inverted:!1;a.drawGraph&&(a.drawGraph(),a.applyZones());m(a.points,function(a){a.redraw&&a.redraw()});a.drawDataLabels&&a.drawDataLabels();a.visible&&a.drawPoints();a.drawTracker&&a.options.enableMouseTracking!==!1&&a.drawTracker();b.inverted&&a.invertGroups();d.clip!==!1&&!a.sharedClipKey&&!h&&c.clip(b.clipRect); -e&&a.animate();if(!h)e?a.animationTimeout=setTimeout(function(){a.afterAnimate()},e):a.afterAnimate();a.isDirty=a.isDirtyData=!1;a.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirtyData,c=this.isDirty,d=this.group,e=this.xAxis,f=this.yAxis;d&&(a.inverted&&d.attr({width:a.plotWidth,height:a.plotHeight}),d.animate({translateX:p(e&&e.left,a.plotLeft),translateY:p(f&&f.top,a.plotTop)}));this.translate();this.render();b&&G(this,"updatedData");(c||b)&&delete this.kdTree},kdDimensions:1,kdTree:null, -kdAxisArray:["plotX","plotY"],kdComparer:"distX",searchPoint:function(a){var b=this.xAxis,c=this.yAxis,d=this.chart.inverted;a.plotX=d?b.len-a.chartY+b.pos:a.chartX-b.pos;a.plotY=d?c.len-a.chartX+c.pos:a.chartY-c.pos;return this.searchKDTree(a)},buildKDTree:function(){function a(b,d,g){var h,i;if(i=b&&b.length)return h=c.kdAxisArray[d%g],b.sort(function(a,b){return a[h]-b[h]}),i=Math.floor(i/2),{point:b[i],left:a(b.slice(0,i),d+1,g),right:a(b.slice(i+1),d+1,g)}}function b(){var b=kb(c.points,function(a){return a.y!== -null});c.kdTree=a(b,d,d)}var c=this,d=c.kdDimensions;delete c.kdTree;c.options.kdSync?b():setTimeout(b)},searchKDTree:function(a){function b(a,h,i,j){var k=h.point,l=c.kdAxisArray[i%j],n,o=k;n=r(a[e])&&r(k[e])?Math.pow(a[e]-k[e],2):null;var m=r(a[f])&&r(k[f])?Math.pow(a[f]-k[f],2):null,p=(n||0)+(m||0);n={distX:r(n)?Math.sqrt(n):Number.MAX_VALUE,distY:r(m)?Math.sqrt(m):Number.MAX_VALUE,distR:r(p)?Math.sqrt(p):Number.MAX_VALUE};k.dist=n;l=a[l]-k[l];n=l<0?"left":"right";h[n]&&(n=b(a,h[n],i+1,j),o=n.dist[d]< -o.dist[d]?n:k,k=l<0?"right":"left",h[k]&&Math.sqrt(l*l)g;)h--;this.updateParallelArrays(d,"splice",h,0,0);this.updateParallelArrays(d, -h);if(j&&d.name)j[g]=d.name;l.splice(h,0,a);n&&(this.data.splice(h,0,null),this.processData());e.legendType==="point"&&this.generatePoints();c&&(f[0]&&f[0].remove?f[0].remove(!1):(f.shift(),this.updateParallelArrays(d,"shift"),l.shift()));this.isDirtyData=this.isDirty=!0;b&&(this.getAttribs(),i.redraw())},removePoint:function(a,b,c){var d=this,e=d.data,f=e[a],g=d.points,h=d.chart,i=function(){e.length===g.length&&g.splice(a,1);e.splice(a,1);d.options.data.splice(a,1);d.updateParallelArrays(f||{series:d}, -"splice",a,1);f&&f.destroy();d.isDirty=!0;d.isDirtyData=!0;b&&h.redraw()};Sa(c,h);b=p(b,!0);f?f.firePointEvent("remove",null,i):i()},remove:function(a,b){var c=this,d=c.chart,a=p(a,!0);if(!c.isRemoving)c.isRemoving=!0,G(c,"remove",null,function(){c.destroy();d.isDirtyLegend=d.isDirtyBox=!0;d.linkSeries();a&&d.redraw(b)});c.isRemoving=!1},update:function(a,b){var c=this,d=this.chart,e=this.userOptions,f=this.type,g=N[f].prototype,h=["group","markerGroup","dataLabelsGroup"],i;if(a.type&&a.type!==f|| -a.zIndex!==void 0)h.length=0;m(h,function(a){h[a]=c[a];delete c[a]});a=z(e,{animation:!1,index:this.index,pointStart:this.xData[0]},{data:this.options.data},a);this.remove(!1);for(i in g)this[i]=v;q(this,N[a.type||f].prototype);m(h,function(a){c[a]=h[a]});this.init(d,a);d.linkSeries();p(b,!0)&&d.redraw(!1)}});q(va.prototype,{update:function(a,b){var c=this.chart,a=c.options[this.coll][this.options.index]=z(this.userOptions,a);this.destroy(!0);this._addedPlotLB=v;this.init(c,q(a,{events:v}));c.isDirtyBox= -!0;p(b,!0)&&c.redraw()},remove:function(a){for(var b=this.chart,c=this.coll,d=this.series,e=d.length;e--;)d[e]&&d[e].remove(!1);ia(b.axes,this);ia(b[c],this);b.options[c].splice(this.options.index,1);m(b[c],function(a,b){a.options.index=b});this.destroy();b.isDirtyBox=!0;p(a,!0)&&b.redraw()},setTitle:function(a,b){this.update({title:a},b)},setCategories:function(a,b){this.update({categories:a},b)}});var xa=ja(R);N.line=xa;aa.area=z(Q,{threshold:0});var pa=ja(R,{type:"area",getSegments:function(){var a= -this,b=[],c=[],d=[],e=this.xAxis,f=this.yAxis,g=f.stacks[this.stackKey],h={},i,j,k=this.points,l=this.options.connectNulls,n,o;if(this.options.stacking&&!this.cropped){for(n=0;n=0;d--)g=p(a[d].yBottom,f),da&&i>e?(i=t(a,e),k=2*e-i):ig&&k>e?(k=t(g,e),i=2*e-k):kg?d-g:f-(e.translate(c.y,0,1,0,1)<=f?g:0)));c.barX=m;c.pointWidth=i;c.tooltipPos=b.inverted?[e.len+e.pos-b.plotLeft-h,a.xAxis.len-m-r/2]:[m+r/2,h+e.pos-b.plotTop];r=w(m+r)+l;m=w(m)+l;r-=m;d=P(q)<0.5;v=H(w(q+v)+n,9E4);q=w(q)+n;v-=q;d&&(q-=1,v+=1);c.shapeType="rect";c.shapeArgs={x:m,y:q,width:r,height:v}})},getSymbol:ma,drawLegendSymbol:Na.drawRectangle, -drawGraph:ma,drawPoints:function(){var a=this,b=this.chart,c=a.options,d=b.renderer,e=c.animationLimit||250,f,g;m(a.points,function(h){var i=h.plotY,j=h.graphic;if(i!==v&&!isNaN(i)&&h.y!==null)f=h.shapeArgs,i=r(a.borderWidth)?{"stroke-width":a.borderWidth}:{},g=h.pointAttr[h.selected?"select":""]||a.pointAttr[""],j?(db(j),j.attr(i)[b.pointCount {series.name}
',pointFormat:"x: {point.x}
y: {point.y}
"}});pa=ja(R,{type:"scatter",sorted:!1,requireSorting:!1,noSharedTooltip:!0,trackerGroups:["group","markerGroup","dataLabelsGroup"],takeOrdinalPosition:!1,kdDimensions:2,kdComparer:"distR",drawGraph:function(){this.options.lineWidth&& -R.prototype.drawGraph.call(this)}});N.scatter=pa;aa.pie=z(Q,{borderColor:"#FFFFFF",borderWidth:1,center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{distance:30,enabled:!0,formatter:function(){return this.point.name},x:0},ignoreHiddenPoint:!0,legendType:"point",marker:null,size:null,showInLegend:!1,slicedOffset:10,states:{hover:{brightness:0.1,shadow:!1}},stickyTracking:!1,tooltip:{followPointer:!0}});Q={type:"pie",isCartesian:!1,pointClass:ja(Ga,{init:function(){Ga.prototype.init.apply(this,arguments); -var a=this,b;q(a,{visible:a.visible!==!1,name:p(a.name,"Slice")});b=function(b){a.slice(b.type==="select")};K(a,"select",b);K(a,"unselect",b);return a},setVisible:function(a){var b=this,c=b.series,d=c.chart,e=!c.isDirty&&c.options.ignoreHiddenPoint;b.visible=b.options.visible=a=a===v?!b.visible:a;c.options.data[Ma(b,c.data)]=b.options;m(["graphic","dataLabel","connector","shadowGroup"],function(c){if(b[c])b[c][a?"show":"hide"](!0)});b.legendItem&&(d.hasRendered&&(c.updateTotals(),d.legend.clearItems(), -e||d.legend.render()),d.legend.colorizeItem(b,a));if(e)c.isDirty=!0,d.redraw()},slice:function(a,b,c){var d=this.series;Sa(c,d.chart);p(b,!0);this.sliced=this.options.sliced=a=r(a)?a:!this.sliced;d.options.data[Ma(this,d.data)]=this.options;a=a?this.slicedTranslation:{translateX:0,translateY:0};this.graphic.animate(a);this.shadowGroup&&this.shadowGroup.animate(a)},haloPath:function(a){var b=this.shapeArgs,c=this.series.chart;return this.sliced||!this.visible?[]:this.series.chart.renderer.symbols.arc(c.plotLeft+ -b.x,c.plotTop+b.y,b.r+a,b.r+a,{innerR:this.shapeArgs.r,start:b.start,end:b.end})}}),requireSorting:!1,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],axisTypes:[],pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",fill:"color"},getColor:ma,animate:function(a){var b=this,c=b.points,d=b.startAngleRad;if(!a)m(c,function(a){var c=a.graphic,a=a.shapeArgs;c&&(c.attr({r:b.center[3]/2,start:d,end:d}),c.animate({r:a.r,start:a.start,end:a.end},b.options.animation))}),b.animate= -null},setData:function(a,b,c,d){R.prototype.setData.call(this,a,!1,c,d);this.processData();this.generatePoints();p(b,!0)&&this.chart.redraw(c)},updateTotals:function(){var a,b=0,c,d,e,f=this.options.ignoreHiddenPoint;c=this.points;d=c.length;for(a=0;a0&&(e.visible||!f)?e.y/b*100:0,e.total=b},generatePoints:function(){R.prototype.generatePoints.call(this);this.updateTotals()},translate:function(a){this.generatePoints(); -var b=0,c=this.options,d=c.slicedOffset,e=d+c.borderWidth,f,g,h,i=c.startAngle||0,j=this.startAngleRad=la/180*(i-90),i=(this.endAngleRad=la/180*(p(c.endAngle,i+360)-90))-j,k=this.points,l=c.dataLabels.distance,c=c.ignoreHiddenPoint,n,o=k.length,m;if(!a)this.center=a=this.getCenter();this.getX=function(b,c){h=V.asin(H((b-a[1])/(a[2]/2+l),1));return a[0]+(c?-1:1)*W(h)*(a[2]/2+l)};for(n=0;n1.5*la?h-=2*la:h<-la/2&&(h+=2*la);m.slicedTranslation={translateX:w(W(h)*d),translateY:w($(h)*d)};f=W(h)*a[2]/2;g=$(h)*a[2]/2;m.tooltipPos=[a[0]+f*0.7,a[1]+g*0.7];m.half=h<-la/2||h>la/2?1:0;m.angle=h;e=H(e,l/2);m.labelPos=[a[0]+f+W(h)*l,a[1]+g+$(h)*l,a[0]+f+W(h)*e,a[1]+g+$(h)*e,a[0]+f,a[1]+g,l<0?"center":m.half?"right":"left",h]}},drawGraph:null,drawPoints:function(){var a=this,b=a.chart.renderer,c,d,e=a.options.shadow,f,g;if(e&& -!a.shadowGroup)a.shadowGroup=b.g("shadow").add(a.group);m(a.points,function(h){d=h.graphic;g=h.shapeArgs;f=h.shadowGroup;if(e&&!f)f=h.shadowGroup=b.g("shadow").add(a.shadowGroup);c=h.sliced?h.slicedTranslation:{translateX:0,translateY:0};f&&f.attr(c);d?d.animate(q(g,c)):h.graphic=d=b[h.shapeType](g).setRadialReference(a.center).attr(h.pointAttr[h.selected?"select":""]).attr({"stroke-linejoin":"round"}).attr(c).add(a.group).shadow(e,f);h.visible!==void 0&&h.setVisible(h.visible)})},searchPoint:ma, -sortByAngle:function(a,b){a.sort(function(a,d){return a.angle!==void 0&&(d.angle-a.angle)*b})},drawLegendSymbol:Na.drawRectangle,getCenter:Vb.getCenter,getSymbol:ma};Q=ja(R,Q);N.pie=Q;R.prototype.drawDataLabels=function(){var a=this,b=a.options,c=b.cursor,d=b.dataLabels,e=a.points,f,g,h=a.hasRendered||0,i,j,k=a.chart.renderer;if(d.enabled||a._hasPointLabels)a.dlProcessOptions&&a.dlProcessOptions(d),j=a.plotGroup("dataLabelsGroup","data-labels",d.defer?"hidden":"visible",d.zIndex||6),p(d.defer,!0)&& -(j.attr({opacity:+h}),h||K(a,"afterAnimate",function(){a.visible&&j.show();j[b.animation?"animate":"attr"]({opacity:1},{duration:200})})),g=d,m(e,function(e){var h,m=e.dataLabel,s,t,w=e.connector,B=!0,u,y={};f=e.dlOptions||e.options&&e.options.dataLabels;h=p(f&&f.enabled,g.enabled);if(m&&!h)e.dataLabel=m.destroy();else if(h){d=z(g,f);u=d.style;h=d.rotation;s=e.getLabelConfig();i=d.format?Ja(d.format,s):d.formatter.call(s,d);u.color=p(d.color,u.color,a.color,"black");if(m)if(r(i))m.attr({text:i}), -B=!1;else{if(e.dataLabel=m=m.destroy(),w)e.connector=w.destroy()}else if(r(i)){m={fill:d.backgroundColor,stroke:d.borderColor,"stroke-width":d.borderWidth,r:d.borderRadius||0,rotation:h,padding:d.padding,zIndex:1};if(u.color==="contrast")y.color=d.inside||d.distance<0||b.stacking?k.getContrast(e.color||a.color):"#000000";if(c)y.cursor=c;for(t in m)m[t]===v&&delete m[t];m=e.dataLabel=k[h?"text":"label"](i,0,-999,d.shape,null,null,d.useHTML).attr(m).css(q(u,y)).add(j).shadow(d.shadow)}m&&a.alignDataLabel(e, -m,d,null,B)}})};R.prototype.alignDataLabel=function(a,b,c,d,e){var f=this.chart,g=f.inverted,h=p(a.plotX,-999),i=p(a.plotY,-999),j=b.getBBox(),k=f.renderer.fontMetrics(c.style.fontSize).b,l=this.visible&&(a.series.forceDL||f.isInsidePlot(h,w(i),g)||d&&f.isInsidePlot(h,g?d.x+1:d.y+d.height-1,g));if(l)d=q({x:g?f.plotWidth-i:h,y:w(g?f.plotHeight-h:i),width:0,height:0},d),q(c,{width:j.width,height:j.height}),c.rotation?(a=f.renderer.rotCorr(k,c.rotation),b[e?"attr":"animate"]({x:d.x+c.x+d.width/2+a.x, -y:d.y+c.y+d.height/2}).attr({align:c.align})):(b.align(c,null,d),g=b.alignAttr,p(c.overflow,"justify")==="justify"?this.justifyDataLabel(b,c,g,j,d,e):p(c.crop,!0)&&(l=f.isInsidePlot(g.x,g.y)&&f.isInsidePlot(g.x+j.width,g.y+j.height)),c.shape&&b.attr({anchorX:a.plotX,anchorY:a.plotY}));if(!l)b.attr({y:-999}),b.placed=!1};R.prototype.justifyDataLabel=function(a,b,c,d,e,f){var g=this.chart,h=b.align,i=b.verticalAlign,j,k,l=a.box?0:a.padding||0;j=c.x+l;if(j<0)h==="right"?b.align="left":b.x=-j,k=!0;j= -c.x+d.width-l;if(j>g.plotWidth)h==="left"?b.align="right":b.x=g.plotWidth-j,k=!0;j=c.y+l;if(j<0)i==="bottom"?b.verticalAlign="top":b.y=-j,k=!0;j=c.y+d.height-l;if(j>g.plotHeight)i==="top"?b.verticalAlign="bottom":b.y=g.plotHeight-j,k=!0;if(k)a.placed=!f,a.align(b,null,e)};if(N.pie)N.pie.prototype.drawDataLabels=function(){var a=this,b=a.data,c,d=a.chart,e=a.options.dataLabels,f=p(e.connectorPadding,10),g=p(e.connectorWidth,1),h=d.plotWidth,i=d.plotHeight,j,k,l=p(e.softConnector,!0),n=e.distance,o= -a.center,q=o[2]/2,r=o[1],v=n>0,y,u,z,D=[[],[]],C,A,F,J,E,G=[0,0,0,0],N=function(a,b){return b.y-a.y};if(a.visible&&(e.enabled||a._hasPointLabels)){R.prototype.drawDataLabels.apply(a);m(b,function(a){a.dataLabel&&a.visible&&D[a.half].push(a)});for(J=2;J--;){var K=[],O=[],I=D[J],M=I.length,L;if(M){a.sortByAngle(I,J-0.5);for(E=b=0;!b&&I[E];)b=I[E]&&I[E].dataLabel&&(I[E].dataLabel.getBBox().height||21),E++;if(n>0){u=H(r+q+n,d.plotHeight);for(E=t(0,r-q-n);E<=u;E+=b)K.push(E);u=K.length;if(M>u){c=[].concat(I); -c.sort(N);for(E=M;E--;)c[E].rank=E;for(E=M;E--;)I[E].rank>=u&&I.splice(E,1);M=I.length}for(E=0;E0){if(u=O.pop(),L=u.i,A=u.y,c>A&&K[L+1]!==null||ch-f&&(G[1]=t(w(C+u-h+f),G[1])),A-b/2<0?G[0]=t(w(-A+b/2),G[0]):A+b/2>i&&(G[2]=t(w(A+b/2-i),G[2]))}}}if(Fa(G)===0||this.verifyDataLabelOverflow(G))this.placeDataLabels(),v&&g&&m(this.points,function(b){j=b.connector;z=b.labelPos;if((y=b.dataLabel)&&y._pos)F= -y._attr.visibility,C=y.connX,A=y.connY,k=l?["M",C+(z[6]==="left"?5:-5),A,"C",C,A,2*z[2]-z[4],2*z[3]-z[5],z[2],z[3],"L",z[4],z[5]]:["M",C+(z[6]==="left"?5:-5),A,"L",z[2],z[3],"L",z[4],z[5]],j?(j.animate({d:k}),j.attr("visibility",F)):b.connector=j=a.chart.renderer.path(k).attr({"stroke-width":g,stroke:e.connectorColor||b.color||"#606060",visibility:F}).add(a.dataLabelsGroup);else if(j)b.connector=j.destroy()})}},N.pie.prototype.placeDataLabels=function(){m(this.points,function(a){var a=a.dataLabel, -b;if(a)(b=a._pos)?(a.attr(a._attr),a[a.moved?"animate":"attr"](b),a.moved=!0):a&&a.attr({y:-999})})},N.pie.prototype.alignDataLabel=ma,N.pie.prototype.verifyDataLabelOverflow=function(a){var b=this.center,c=this.options,d=c.center,e=c=c.minSize||80,f;d[0]!==null?e=t(b[2]-t(a[1],a[3]),c):(e=t(b[2]-a[1]-a[3],c),b[0]+=(a[3]-a[1])/2);d[1]!==null?e=t(H(e,b[2]-t(a[0],a[2])),c):(e=t(H(e,b[2]-a[0]-a[2]),c),b[1]+=(a[0]-a[2])/2);ep(this.translatedThreshold,g.yAxis.len),j=p(c.inside,!!this.options.stacking);if(h&&(d=z(h),f&&(d={x:g.yAxis.len-d.y-d.height,y:g.xAxis.len-d.x-d.width,width:d.height,height:d.width}),!j))f?(d.x+=i?0:d.width,d.width=0):(d.y+=i?d.height:0,d.height=0);c.align=p(c.align,!f||j?"center":i?"right": -"left");c.verticalAlign=p(c.verticalAlign,f||j?"middle":i?"top":"bottom");R.prototype.alignDataLabel.call(this,a,b,c,d,e)};(function(a){var b=a.Chart,c=a.each,d=HighchartsAdapter.addEvent;b.prototype.callbacks.push(function(a){function b(){var d=[];c(a.series,function(a){var b=a.options.dataLabels;(b.enabled||a._hasPointLabels)&&!b.allowOverlap&&a.visible&&c(a.points,function(a){if(a.dataLabel)a.dataLabel.labelrank=a.labelrank,d.push(a.dataLabel)})});a.hideOverlappingLabels(d)}b();d(a,"redraw",b)}); -b.prototype.hideOverlappingLabels=function(a){var b=a.length,c,d,i,j;for(d=0;di.alignAttr.x+i.width||j.alignAttr.x+j.widthi.alignAttr.y+i.height||j.alignAttr.y+j.heightd;if(h.series.length&&(i||l>H(k.dataMin,k.min))&&(!i||j0)a=b[b.length-1].levelNumber,j(this.drilldownLevels,function(b){b.levelNumber===a&&j(b.levelSeries,function(b){b.options&&b.options._levelNumber===a&&b.remove(!1)})});this.redraw();this.showDrillUpButton()};h.prototype.getDrilldownBackText= -function(){var b=this.drilldownLevels;if(b&&b.length>0)return b=b[b.length-1],b.series=b.seriesOptions,z(this.options.lang.drillUpText,b)};h.prototype.showDrillUpButton=function(){var b=this,a=this.getDrilldownBackText(),c=b.options.drilldown.drillUpButton,e,f;this.drillUpButton?this.drillUpButton.attr({text:a}).align():(f=(e=c.theme)&&e.states,this.drillUpButton=this.renderer.button(a,null,null,function(){b.drillUp()},e,f&&f.hover,f&&f.select).attr({align:c.position.align,zIndex:9}).add().align(c.position, -!1,c.relativeTo||"plotBox"))};h.prototype.drillUp=function(){for(var b=this,a=b.drilldownLevels,c=a[a.length-1].levelNumber,e=a.length,f=b.series,d,i,g,h,k=function(a){var c;j(f,function(b){b.options._ddSeriesId===a._ddSeriesId&&(c=b)});c=c||b.addSeries(a,!1);if(c.type===g.type&&c.animateDrillupTo)c.animate=c.animateDrillupTo;a===i.seriesOptions&&(h=c)};e--;)if(i=a[e],i.levelNumber===c){a.pop();g=i.lowerSeries;if(!g.chart)for(d=f.length;d--;)if(f[d].options.id===i.lowerSeriesOptions.id){g=f[d];break}g.xData= -[];j(i.levelSeriesOptions,k);u(b,"drillup",{seriesOptions:i.seriesOptions});if(h.type===g.type)h.drilldownLevel=i,h.options.animation=b.options.drilldown.animation,g.animateDrillupFrom&&g.chart&&g.animateDrillupFrom(i);h.options._levelNumber=c;g.remove(!1);if(h.xAxis)d=i.oldExtremes,h.xAxis.setExtremes(d.xMin,d.xMax,!1),h.yAxis.setExtremes(d.yMin,d.yMax,!1)}this.redraw();this.drilldownLevels.length===0?this.drillUpButton=this.drillUpButton.destroy():this.drillUpButton.attr({text:this.getDrilldownBackText()}).align(); -p.length=[]};l.prototype.supportsDrilldown=!0;l.prototype.animateDrillupTo=function(b){if(!b){var a=this,c=a.drilldownLevel;j(this.points,function(a){a.graphic&&a.graphic.hide();a.dataLabel&&a.dataLabel.hide();a.connector&&a.connector.hide()});setTimeout(function(){a.points&&j(a.points,function(a,b){var d=b===(c&&c.pointIndex)?"show":"fadeIn",i=d==="show"?!0:void 0;if(a.graphic)a.graphic[d](i);if(a.dataLabel)a.dataLabel[d](i);if(a.connector)a.connector[d](i)})},Math.max(this.chart.options.drilldown.animation.duration- -50,0));this.animate=r}};l.prototype.animateDrilldown=function(b){var a=this,c=this.chart.drilldownLevels,e,f=this.chart.options.drilldown.animation,d=this.xAxis;if(!b)j(c,function(b){if(a.options._ddSeriesId===b.lowerSeriesOptions._ddSeriesId)e=b.shapeArgs,e.fill=b.color}),e.x+=s(d.oldPos,d.pos)-d.pos,j(this.points,function(a){a.graphic&&a.graphic.attr(e).animate(k(a.shapeArgs,{fill:a.color}),f);a.dataLabel&&a.dataLabel.fadeIn(f)}),this.animate=null};l.prototype.animateDrillupFrom=function(b){var a= -this.chart.options.drilldown.animation,c=this.group,e=this;j(e.trackerGroups,function(a){if(e[a])e[a].on("mouseover")});delete this.group;j(this.points,function(e){var d=e.graphic,i=function(){d.destroy();c&&(c=c.destroy())};d&&(delete e.graphic,a?d.animate(k(b.shapeArgs,{fill:b.color}),g.merge(a,{complete:i})):(d.attr(b.shapeArgs),i()))})};t&&k(t.prototype,{supportsDrilldown:!0,animateDrillupTo:l.prototype.animateDrillupTo,animateDrillupFrom:l.prototype.animateDrillupFrom,animateDrilldown:function(b){var a= -this.chart.drilldownLevels[this.chart.drilldownLevels.length-1],c=this.chart.options.drilldown.animation,e=a.shapeArgs,f=e.start,d=(e.end-f)/this.points.length;if(!b)j(this.points,function(b,h){b.graphic.attr(g.merge(e,{start:f+h*d,end:f+(h+1)*d,fill:a.color}))[c?"animate":"attr"](k(b.shapeArgs,{fill:b.color}),c)}),this.animate=null}});g.Point.prototype.doDrilldown=function(b,a){for(var c=this.series.chart,e=c.options.drilldown,f=(e.series||[]).length,d;f--&&!d;)e.series[f].id===this.drilldown&&v(this.drilldown, -p)===-1&&(d=e.series[f],p.push(this.drilldown));u(c,"drilldown",{point:this,seriesOptions:d,category:a,points:a!==void 0&&this.series.xAxis.ticks[a].label.ddPoints.slice(0)});d&&(b?c.addSingleSeriesAsDrilldown(this,d):c.addSeriesAsDrilldown(this,d))};g.Axis.prototype.drilldownCategory=function(b){j(this.ticks[b].label.ddPoints,function(a){a.series&&a.series.visible&&a.doDrilldown&&a.doDrilldown(!0,b)});this.chart.applyDrilldown()};o(g.Point.prototype,"init",function(b,a,c,e){var f=b.call(this,a,c, -e),b=a.chart;if(c=(c=a.xAxis&&a.xAxis.ticks[e])&&c.label){if(!c.ddPoints)c.ddPoints=[];if(c.levelNumber!==a.options._levelNumber)c.ddPoints.length=0}if(f.drilldown){if(g.addEvent(f,"click",function(){f.doDrilldown()}),c){if(!c.basicStyles)c.basicStyles=g.merge(c.styles);c.addClass("highcharts-drilldown-axis-label").css(b.options.drilldown.activeAxisLabelStyle).on("click",function(){a.xAxis.drilldownCategory(e)});c.ddPoints.push(f);c.levelNumber=a.options._levelNumber}}else if(c&&c.basicStyles&&c.levelNumber!== -a.options._levelNumber)c.styles={},c.css(c.basicStyles),c.on("click",null);return f});o(g.Series.prototype,"drawDataLabels",function(b){var a=this.chart.options.drilldown.activeDataLabelStyle;b.call(this);j(this.points,function(b){if(b.drilldown&&b.dataLabel)b.dataLabel.attr({"class":"highcharts-drilldown-data-label"}).css(a).on("click",function(){b.doDrilldown()})})});var q,n=function(b){b.call(this);j(this.points,function(a){a.drilldown&&a.graphic&&a.graphic.attr({"class":"highcharts-drilldown-point"}).css({cursor:"pointer"})})}; -for(q in m)m[q].prototype.supportsDrilldown&&o(m[q].prototype,"drawTracker",n)})(Highcharts); diff --git a/plugins/redmine_git_hosting/assets/javascripts/plugin.js b/plugins/redmine_git_hosting/assets/javascripts/plugin.js deleted file mode 100644 index d6dec7a..0000000 --- a/plugins/redmine_git_hosting/assets/javascripts/plugin.js +++ /dev/null @@ -1,39 +0,0 @@ -/* -REDMINE PLUGIN LIST VIEW OVERRIDE -*/ -function openAuthorModalBox(element) { - $('#ajax-modal').dialog({ - resizable: false, - autoOpen: false, - height: 'auto', - width: 'auto', - modal: true, - hide: { - effect: "fade", - duration: 500 - }, - buttons: { Ok: function(){ $(this).dialog('close'); } } - }); - - var title = $(element).html(); - $.get($(element).attr('href'), function(data){ - $('#ajax-modal').html(data); - $('#ajax-modal').dialog('option', 'title', title); - $('#ajax-modal').dialog('open'); - }); -} - -function enhanceAuthorsUrlForPlugin(plugin_name) { - var link = $('#plugin-' + plugin_name + ' > td.author > a'); - if (link.length) { - link.addClass('modal-box'); - $(document).on('click', 'a.modal-box', function(e){ - e.preventDefault(); - openAuthorModalBox(this); - }); - } -} - -$(document).ready(function() { - enhanceAuthorsUrlForPlugin('redmine_git_hosting'); -}); diff --git a/plugins/redmine_git_hosting/assets/javascripts/set_highcharts.js b/plugins/redmine_git_hosting/assets/javascripts/set_highcharts.js deleted file mode 100644 index cabfb04..0000000 --- a/plugins/redmine_git_hosting/assets/javascripts/set_highcharts.js +++ /dev/null @@ -1,169 +0,0 @@ -function createColumnChart(element){ - $(element.target).highcharts({ - chart: { - type: 'column' - }, - title: { - text: element.label - }, - credits: { - enabled: false - }, - xAxis: { - categories: element.categories, - title: { - text: null - } - }, - yAxis: { - min: 0, - title: { - text: element.label_y_axis, - } - }, - plotOptions: { - column: { - pointPadding: 0.2, - borderWidth: 0 - } - }, - tooltip: { - headerFormat: '{point.key}', - pointFormat: '' + - '', - footerFormat: '
{series.name}: {point.y}
', - shared: true, - useHTML: true - }, - series: element.series - }); -} - -function createZoomableAreaChart(element){ - $(element.target).highcharts({ - chart: { - type: "areaspline", - zoomType: "x" - }, - title: { - text: element.label - }, - credits: { - enabled: false - }, - xAxis: { - categories: element.categories, - tickInterval: parseInt(element.categories.length / 10), - labels: { - rotation: -45, - y: 35 - } - }, - yAxis: { - title: { - text: "" - } - }, - legend: element.legend, - plotOptions: { - areaspline: { - fillOpacity: 0.2 - }, - series: { - lineWidth: 1, - marker: { - enabled: false - } - } - }, - series: element.series - }); -} - -function createAreaChart(element){ - $(element.target).highcharts({ - chart: { - type: 'areaspline' - }, - title: { - text: element.label - }, - credits: { - enabled: false - }, - legend: { - layout: 'vertical', - align: 'left', - verticalAlign: 'top', - x: 50, - y: 50, - floating: true, - borderWidth: 1, - backgroundColor: '#FFFFFF' - }, - xAxis: { - categories: element.categories, - tickmarkPlacement: 'on', - title: { - text: null - } - }, - yAxis: { - title: { - text: "" - } - }, - tooltip: { - shared: true, - }, - plotOptions: { - areaspline: { - fillOpacity: 0.2 - } - }, - series: element.series - }); -} - -function createPieChart(element){ - $(element.target).highcharts({ - chart: { - type: "pie" - }, - title: { - text: element.label - }, - credits: { - enabled: false - }, - yAxis: { - title: { - text: "" - } - }, - series: element.series - }); -} - -function createBarChart(element){ - $(element.target).highcharts({ - chart: { - type: "bar" - }, - title: { - text: element.label - }, - xAxis: { - categories: element.categories, - title: { - text: element.label_y_axis - } - }, - yAxis: { - title: { - text: element.label_x_axis - } - }, - series: element.series - }); -} diff --git a/plugins/redmine_git_hosting/assets/stylesheets/application.css b/plugins/redmine_git_hosting/assets/stylesheets/application.css deleted file mode 100644 index 697ecd0..0000000 --- a/plugins/redmine_git_hosting/assets/stylesheets/application.css +++ /dev/null @@ -1,296 +0,0 @@ -/* -PLUGIN SETTINGS -*/ -.git_hosting_access_box { - border: 2px solid; - background-color: #dfffdf; - border-color: #9fcf9f; - color: #005f00; - margin: -6px; - padding: 4px; -} - -.git_hosting_access_box p { - padding-left:100px; - margin-top: 8px; - margin-bottom: 8px; -} - -.git_hosting_access_box label { - margin-left: -100px; - width: 95px; -} - -.git_hosting_access_box em { - font-style: italic; - font-weight: bold; - font-size: 110%; - color: #467AA7; -} - -#settings p { - margin-bottom: 15px; - margin-top: 15px; -} - - -/* -REPOSITORY EDIT -*/ -#repository-tabs li i { - padding-right: 10px; -} - - -/* -REPOSITORY VIEW -*/ - -#sidebar li.repository.git::before { - font-family: Font Awesome\ 5 Brands; - font-size: 1.2em; - content: "\f841"; /* fab fa-git-alt */ - padding-right: 4px; -} - -#sidebar ul.repository.git { - padding-left: 0; -} - -#git_hosting_download_buttons { - margin-top: 20px; -} - -#git_hosting_download_buttons ul li { - margin-top: 5px; - margin-bottom: 5px; -} - -#sidebar li.git_url { - margin: 0; -} - -.git_hosting_urls { - display: block; - margin-top: 10px; - margin-bottom: 10px; -} - -.git_hosting_urls .repository-urls { - margin-top: 0; -} - -#git_hosting_download_buttons i { - color: #FFFFFF; - padding-right: 10px; -} - -#git_hosting_download_buttons .button { - background: none repeat scroll 0 0 #2996CC; - border: 1px solid #E0E2E3; - border-color: rgba(0, 0, 0, 0); - border-radius: 4px; - color: #FFFFFF; - cursor: pointer; - display: block; - font-size: 14px; - font-weight: 500; - height: 32px; - line-height: 30px; - margin-bottom: 1px; - margin-top: 1px; - -moz-appearance: none; - padding: 0 14px; - vertical-align: middle; - text-align: center; - transition: background-color 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, opacity 0.2s ease-in-out 0s; -} - - -/* -REPOSITORY SETTINGS -*/ -#git_hosting_settings label { - margin-left: -190px; - padding-left: 10px; - padding-right: 10px; - width: 190px; -} - - -/* -MISC -*/ -.git_hosting_spacer { display: block; height: 10px; clear: both; } - -td.buttons { width: 20%; } - -.select_key_type { margin-left: 10px; } - - -/* -STATISTICS -*/ -#statistics-global { - color: #FFFFFF; - font-weight: bold; -} - -.thumbnails:before, .thumbnails:after { - content: ''; - display: table; - line-height: 0; -} - -.thumbnails:after { - clear: both; -} - -.thumbnails:before, .thumbnails:after { - content: ""; - display: table; - line-height: 0; -} - -.thumbnails { - list-style: none outside none; - margin-left: -20px; -} - -#statistics-global .thumbnail { - background: none repeat scroll 0 0 #3498DB; - padding: 10px; -} - -.thumbnail { - position: relative; -} - -.thumbnail { - border: 1px solid #DDDDDD; - border-radius: 4px; - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); - display: block; - line-height: 20px; - padding: 4px; - transition: all 0.2s ease-in-out 0s; -} - -.thumbnails > li { - float: left; - margin-bottom: 20px; - margin-left: 20px; -} - -.span4 { - width: 300px; -} - -[class*="span"] { - float: left; - margin-left: 20px; - min-height: 1px; -} - -#statistics-global .thumbnail .title { - font-size: 1.1em; -} - -#statistics-global .thumbnail .value { - font-size: 3em; - line-height: 1em; - padding-top: 10px; - text-align: right; -} - -.span6 { - width: 500px; -} - -.thumbnail h5 { - background: none repeat scroll 0 0 #1ABC9C; - color: #FFFFFF; - padding: 10px; - position: absolute; - right: 10px; - top: 0; - font-size: 16px; - font-weight: 500; - text-transform: uppercase; - margin: 10px 0; -} - -.thumbnail h4 { - font-size: 18px; - font-weight: 500; - margin: 15px; - border-bottom: 0 none; -} - -.thumbnail h4 small { - color: #999999; - font-weight: normal; - line-height: 1; -} - -li.url_type { - margin: 10px; - padding: 5px; -} - -.draggable { - cursor: move; -} - -.label { - display: inline-block; - padding: 2px 4px; - font-size: 11.844px; - font-weight: bold; - line-height: 14px; - color: #ffffff; - vertical-align: baseline; - white-space: nowrap; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - border-radius: 3px; - background-color: #999999; -} - - -.label:empty - display: none; -} - -.label-important { - background-color: #b94a48; -} - -.label-error { - background-color: #b94a48; -} - -.label-warning { - background-color: #f89406; -} - -.label-success { - background-color: #468847; -} - -.label-info { - background-color: #3a87ad; -} - -table.git-results td { - vertical-align: top; - text-align: left; - padding: 5px; -} - -table.git-results ul, table.git-results li { - padding-left: 0; -} - -ul.list-unstyled, ol.list-unstyled { - list-style-type: none; -} diff --git a/plugins/redmine_git_hosting/assets/stylesheets/git_urls.css b/plugins/redmine_git_hosting/assets/stylesheets/git_urls.css deleted file mode 100644 index 0d8dc37..0000000 --- a/plugins/redmine_git_hosting/assets/stylesheets/git_urls.css +++ /dev/null @@ -1,112 +0,0 @@ -.repository_name { color: #505050; margin-top: 5px; } - -/*PROJECT OVERVIEW*/ -.repository-urls { - margin-top: 15px; -} - -/* -GIT_URL_BOX -*/ -.git_url_box { height: 25px; padding: 0; margin: 0px; } -.git_url_desc { color: #666666; display: block; font-size: 11px; line-height: 25px; padding-top: 5px; } -.git_url_permissions { float: left; width: 44px; height: 23px; margin: 0; padding: 0; border-style: solid; border-width: 1px; border-right: 0; border-color: #BBBBBB; } -.git_url_permissions span { - display: block; - font-weight: bold; - padding: 0; - text-align: center; - vertical-align: middle; -} - -.git_url_list { float: left; height: 23px; list-style-type: none; margin: 0px; padding: 0px; } -.git_url_list li { float: left; } - -.git_url_text { - background-color: #FFFFFF; - border-color: #BBBBBB; - border-style: solid; - border-width: 1px 0 1px 1px; - color: #000000; - float: left; - font-family: "DejaVu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace; - font-size: 10px; - height: 25px; - margin: 0; - min-width: 55%; - padding: 3px 5px 2px; - width: auto; -} - -.git_url_list li a { - background-color: #EEEEEE; - background: url('../images/button.svg') 0 0 repeat; /* Opera needs an "image" :( - using svg for this so it will scale properly without looking too ugly */ - background: -khtml-gradient(linear, left top, left bottom, from(#F8F8F8), to(#DDDDDD)); /* Konquerer */ - background: -moz-linear-gradient(top, #F8F8F8, #DDDDDD); /* Gecko (Firefox, ...) */ - background: -webkit-gradient(linear, left top, left bottom, from(#F8F8F8), to(#DDDDDD)); /* Webkit (Chrome, Safari, ...) */ - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F8F8F8', endColorstr='#DDDDDD'); /* IE 5.5 - 7 */ - -ms-filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F8F8F8', endColorstr='#DDDDDD'); /* IE 8 */ - - border-style: solid; - border-width: 1px 0 1px 1px; - - display: block; - font-size: 11px; - font-weight: bold; - line-height: 23px; - margin: 0; - padding: 0 10px 0 11px; - text-decoration: none; - outline: none; - - color: #333333; - text-shadow: 1px 1px 0 #FFFFFF; - border-color: #BBBBBB; -} - -.git_url_list li a:hover, -.git_url_list li a:focus { - background-color: #507AAA; - background: url('../images/button_focus.svg') 0 0 repeat; /* Opera needs an "image" :( - using svg for this so it will scale properly without looking too ugly */ - background: -khtml-gradient(linear, left top, left bottom, from(#759FCF), to(#507AAA)); /* Konquerer */ - background: -moz-linear-gradient(top, #759FCF, #507AAA); /* Gecko (Firefox, ...) */ - background: -webkit-gradient(linear, left top, left bottom, from(#759FCF), to(#507AAA)); /* Webkit (Chrome, Safari, ...) */ - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#759FCF', endColorstr='#507AAA'); /* IE 5.5 - IE 7 */ - -ms-filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#759FCF', endColorstr='#507AAA'); /* IE 8 */ - - color: #FFFFFF; - text-shadow: -1px -1px 0 rgba(0,0,0,0.4); - border-top-color: #759FCF; - border-bottom-color: #507AAA; -} - -.git_url_list li.selected a { - background-color: #BBBBBB; - background: url('../images/button_selected.svg') 0 0 repeat; /* Opera needs an "image" :( - using svg for this so it will scale properly without looking too ugly */ - background: -webkit-gradient(linear, left top, left bottom, from(#CCCCCC), to(#AAAAAA)); /* Konquerer */ - background: -moz-linear-gradient(top, #CCCCCC, #AAAAAA); /* Gecko (Firefox, ...) */ - background: -webkit-gradient(linear, left top, left bottom, from(#CCCCCC), to(#AAAAAA)); /* Webkit (Chrome, Safari, ...) */ - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#CCCCCC', endColorstr='#AAAAAA'); /* IE 5.5 - IE 7 */ - -ms-filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#CCCCCC', endColorstr='#AAAAAA'); /* IE 8 */ - - color: #000; - text-shadow: 1px 1px 0 rgba(255,255,255,0.4); - border-color: #BBBBBB; -} - -.git_hosting h3::before { - font-family: Font Awesome\ 5 Brands; - content: "\f841"; /* fab git-alt */ - padding-right: 4px; - font-size: 18px; -} - -.clipboard-button { - padding-left: 6px; - border-color: #bbb; - border-style: solid; - border-width: 1px; - width: 24px; - height: 25px; - margin: 0; -} diff --git a/plugins/redmine_git_hosting/assets/stylesheets/markdown.css b/plugins/redmine_git_hosting/assets/stylesheets/markdown.css deleted file mode 100644 index 6a54f16..0000000 --- a/plugins/redmine_git_hosting/assets/stylesheets/markdown.css +++ /dev/null @@ -1,228 +0,0 @@ -.highlight table { - display: block; - width: 100%; - overflow: auto; - padding-bottom: 10px; -} -.highlight table th { - font-weight: 600; -} -.highlight table th, -.highlight table td { - padding: 6px 13px; - border: 1px solid #dfe2e5; -} -.highlight table tr { - background-color: #fff; - border: 1px solid #c6cbd1; -} -.highlight table pre { - margin: 0; -} -.highlight .cm { - color: #999988; - font-style: italic; -} -.highlight .cp { - color: #999999; - font-weight: bold; -} -.highlight .c1 { - color: #999988; - font-style: italic; -} -.highlight .cs { - color: #999999; - font-weight: bold; - font-style: italic; -} -.highlight .c, .highlight .cd { - color: #999988; - font-style: italic; -} -.highlight .err { - color: #a61717; - background-color: #e3d2d2; -} -.highlight .gd { - color: #000000; - background-color: #ffdddd; -} -.highlight .ge { - color: #000000; - font-style: italic; -} -.highlight .gr { - color: #aa0000; -} -.highlight .gh { - color: #999999; -} -.highlight .gi { - color: #000000; - background-color: #ddffdd; -} -.highlight .go { - color: #888888; -} -.highlight .gp { - color: #555555; -} -.highlight .gs { - font-weight: bold; -} -.highlight .gu { - color: #aaaaaa; -} -.highlight .gt { - color: #aa0000; -} -.highlight .kc { - color: #000000; - font-weight: bold; -} -.highlight .kd { - color: #000000; - font-weight: bold; -} -.highlight .kn { - color: #000000; - font-weight: bold; -} -.highlight .kp { - color: #000000; - font-weight: bold; -} -.highlight .kr { - color: #000000; - font-weight: bold; -} -.highlight .kt { - color: #445588; - font-weight: bold; -} -.highlight .k, .highlight .kv { - color: #000000; - font-weight: bold; -} -.highlight .mf { - color: #009999; -} -.highlight .mh { - color: #009999; -} -.highlight .il { - color: #009999; -} -.highlight .mi { - color: #009999; -} -.highlight .mo { - color: #009999; -} -.highlight .m, .highlight .mb, .highlight .mx { - color: #009999; -} -.highlight .sb { - color: #d14; -} -.highlight .sc { - color: #d14; -} -.highlight .sd { - color: #d14; -} -.highlight .s2 { - color: #d14; -} -.highlight .se { - color: #d14; -} -.highlight .sh { - color: #d14; -} -.highlight .si { - color: #d14; -} -.highlight .sx { - color: #d14; -} -.highlight .sr { - color: #009926; -} -.highlight .s1 { - color: #d14; -} -.highlight .ss { - color: #990073; -} -.highlight .s { - color: #d14; -} -.highlight .na { - color: #008080; -} -.highlight .bp { - color: #999999; -} -.highlight .nb { - color: #0086B3; -} -.highlight .nc { - color: #445588; - font-weight: bold; -} -.highlight .no { - color: #008080; -} -.highlight .nd { - color: #3c5d5d; - font-weight: bold; -} -.highlight .ni { - color: #800080; -} -.highlight .ne { - color: #990000; - font-weight: bold; -} -.highlight .nf { - color: #990000; - font-weight: bold; -} -.highlight .nl { - color: #990000; - font-weight: bold; -} -.highlight .nn { - color: #555555; -} -.highlight .nt { - color: #000080; -} -.highlight .vc { - color: #008080; -} -.highlight .vg { - color: #008080; -} -.highlight .vi { - color: #008080; -} -.highlight .nv { - color: #008080; -} -.highlight .ow { - color: #000000; - font-weight: bold; -} -.highlight .o { - color: #000000; - font-weight: bold; -} -.highlight .w { - color: #bbbbbb; -} -.highlight { - background-color: #f8f8f8; -} diff --git a/plugins/redmine_git_hosting/assets/stylesheets/plugin.css b/plugins/redmine_git_hosting/assets/stylesheets/plugin.css deleted file mode 100644 index 0181c6d..0000000 --- a/plugins/redmine_git_hosting/assets/stylesheets/plugin.css +++ /dev/null @@ -1,23 +0,0 @@ -/* -PLUGIN ICON -*/ - -#admin-menu a.redmine-git-hosting::before { - font-family: Font Awesome\ 5 Brands; - font-size: 1.4em; - content: "\f841"; /* fab fa-git-alt */ - padding-right: 4px; -} - -#admin-menu a.redmine-git-hosting { - padding-left: 0; -} - -.authors-list { - columns: 2; - -webkit-columns: 2; - -moz-columns: 2; -} - -.icon-git { padding-right: 10px; } -.icon-git-disabled { opacity: 0.5; } diff --git a/plugins/redmine_git_hosting/config/locales/de.yml b/plugins/redmine_git_hosting/config/locales/de.yml deleted file mode 100644 index 8887cac..0000000 --- a/plugins/redmine_git_hosting/config/locales/de.yml +++ /dev/null @@ -1,410 +0,0 @@ -de: - activemodel: - errors: - models: - move_repository_form: - attributes: - base: - identifier_empty: Repository ohne Kennung ist nicht verschiebbar - identifier_taken: Repository Kennung ist schon in Verwendung - wrong_target_project: Zielprojekt stimmt mit Quellprojekt überein - activerecord: - errors: - models: - gitolite_public_key: - attributes: - key: - corrupted: scheint beschädigt zu sein. - taken_by_you: 'wird bereits von Dir verwendet als Benutzer "%{name}".' - taken_by_other: 'wird bereits verwendet von Benutzer "%{login}" als "%{name}".' - taken_by_someone: wird bereits verwendet. Gehört einem anderen Benutzer (kontaktiere den Administrator für weitere Details). - taken_by_gitolite_admin: wird bereits verwendet als Gitolite Administrator Key. - project: - attributes: - identifier: - invalid: "ungültige Kennung" - taken: matches existing repository identifier - repository_deployment_credential: - attributes: - base: - invalid_key: "Öffentlicher Schlüssel muss ein Deployment Schlüssel sein" - invalid_user: "Credential Owner darf sich vom Key Owner nicht unterscheiden" - repository_git_config_key: - attributes: - key: - invalid: "Falsches Schlüsselformat (es muss mindestens ein '.' vorhanden sein)" - repository_mirror: - attributes: - base: - nothing_to_push: "Muss mindestens ein Element enthalten, das zu pushen ist" - explicit_refspec: - bad_format: ist schlecht formatiert - have_null_component: "kann nicht null erste Komponente haben (würde remote branch(es) entfernen)" - repository/xitolite: - attributes: - base: - blank_default_exists: "Kann das Respository nicht anlegen, da bereits ein leeres Repository existiert." - invalid_options: "Du kannst eine README Datei nicht in einem Repository mit GitAnnex initialisieren" - identifier: - cannot_equal_project: "can not match the ID of an existing project" - taken: "wird bereits verwendet." - invalid: "ungültig" - cannot_change: "kann nicht geändert werden" - all_branches: Alle Branches - all_references: Alle Refs - all_tags: Alle TAGs - button_clone: Klonen - display_access_emphasis_html: "In the above patterns, emphasized components represent context-dependent elements." - display_access_flat: "Eltern Projekte sind nicht in der URL enthalten, da das Repository in einem Flat Modus ist." - display_access_hierarchical: "Eltern Projekte sind in der URL enthalten, da das Repository in einem Hierarchical Modus ist." - display_access_setup1_html: "Geh davon aus, dass project1 das Elternprojekt von project2, und project2 das Elternprojekt von project3 ist." - display_access_setup2_html: "Geh auch davon aus, dass das project3 2 Repositories hat: ein default Repository und ein example Repository." - display_access_setup3_html: "Bezogen auf die aktuelle Konfiguration, hat Projekt project3 folgende Optionen:" - error_download_revision_no_such_commit: "Kein Commit %{commit}" - error_project_not_found: "Kein Projekt mit dem Identifier gefunden" - error_public_key_create_failed: Public key konnte nicht erzeugt werden. - error_public_key_update_failed: Public key konnte nicht aktualisiert werden. - error_repository_not_found: "Kein Repository mit dem Identifier gefunden" - error_xitolite_repositories_disabled: "Gitolite Repositories sind deaktiviert, kann kein Repository erzeugen!" - field_key: dieser Key - field_mode: Modus - field_perm: Zugriffsberechtigung - field_split_payloads: Die globale payload in viele payloads aufteilen - field_use_triggers: Verwende Triggers - label_active_for: Aktiv seit - label_all_projects_use_git: Git repositories für neue Projekte automatisch initialisieren? - label_average_commit_per_day: Durchschnitt Commits pro Tag - label_average_contributor_commits: Durchschnitt Commits pro Mitwirkenden - label_backup_in_progress: Wird gespeichert... - label_branch_path: Branch Path - label_browse_repository: Browse Repository - label_commit_plural: Commits - label_commits_number: Anzahl Commits - label_commits_per_day: Commits am Tag - label_commits_per_hour: Commits in der Stunde - label_commits_per_weekday: Commits an Wochentagen - label_current_deploy_keys: Aktuelle Deployment Keys - label_current_public_keys: Aktuelle Public Keys - label_current_user_keys: Aktuelle Benutzer Keys - label_cut_and_paste: Ausschneiden und einfügen des kompletten .pub File. - label_debug: Debug - label_default_domain_name: Default Domainname - label_default_gitolite_hooks_url: Default URL - label_default_repository: Standard Repository - label_delete_from_recyle_bin: Alles im Papierkorb löschen - label_delete_git_repositories: Git Repository löschen, wenn Projekt gelöscht wird? - info_delete_git_repositories: (wird in den Papierkorb verschoben) - label_delete_in_progress: Lösche... - label_delete_warning: Warnung! Löschvorgang kann nicht rückgängig gemacht werden! - label_deploy_key: Deployment Schlüssel - label_deployment_credential_add: Deployment Credential hinzufügen - label_deployment_credential_create_key_first: Deployment Key(s) nicht gefunden. Du solltest erst einen erzeugen. - label_deployment_credential_create: Neue Deployment Credential erzeugen - label_deployment_credential_delete_when_unused: Schlüssel entfernen, wenn unbenutzt? - label_deployment_credential_delete: Deployment Credential löschen - label_deployment_credential_edit: Deployment Credential bearbeiten - label_deployment_credential_honored: Honored? - label_deployment_credential_owner: Owner - label_deployment_credential_public_key_file: Public Key Datei - label_deployment_credential_public_key_name: Public Key Name - label_deployment_credential_select_deploy_key: Deployment Key auswählen - label_deployment_credentials: Deployment Credentials - label_download_and_install_git: Download und installiere Git - label_download_format: Herunterladen als - label_download_select_format: Format auswählen - label_empty_get: Empty GET - label_empty_recycle_bin: Papierkorb leeren - label_empty_repository: Repository leeren? - label_enable_git_daemon: Git Daemon aktivieren - label_enable_git_notify: Mailing-Liste aktivieren - label_enable_go_url: GO URL aktivieren - label_enable_protected_branches: Geschützte Branches aktivieren - label_enable_public_repo: Repository öffentlich machen - label_enable_smart_http: Smart HTTP Mode - label_enable_smart_https: Smart HTTPS Mode - label_enable_ssh_url: SSH URL aktivieren - label_error: Fehler - label_etcetera: etc - label_example_repository: Beispiel Repository - label_first_commit_date: Erster Commit - label_flat: Flat - label_flush_cache: Flush Git Cache? - label_git_annex: GitAnnex - label_git_config_email_desc: Wird als Autoren E-Mail in Commits verwendet - label_git_config_email: Git Autor E-mail - label_git_config_key_add: Git Config Key hinzufügen - label_git_config_key_create: Neuen Git Config Key erzeugen - label_git_config_key_delete: Git Config Key löschen - label_git_config_key_edit: Git Config Key bearbeiten - label_git_config_keys: Git Config Keys - label_git_config_username_desc: Wird als Autor Name in Commits verwendet - label_git_config_username: Git Autor Name - label_git_daemon: Git Daemon - label_git_key_type_config: Git Config Key - label_git_key_type_option: Gitolite Option - label_git_notification_prefix: Mailing Liste prefix - label_git_notification_sender: Mailing Liste Absenderadresse - label_git_notify: Git Benachrichtigungen - label_git_objects_count: Git Objekte Zähler - label_git_option_key_add: Gitolite Option hinzufügen - label_git_option_keys: Gitolite Konfigurationsoptionen - label_git_version: Git Version - label_github_post: GitHub POST - label_gitolite_access_config: Gitolite Access Konfiguration - label_gitolite_banner: Gitolite banner - label_gitolite_bin_dir: Gitolite binaries directory - label_gitolite_cache_adapter_desc: Redmine neu starten, damit die Änderungen greifen. - label_gitolite_cache_adapter: Cache Adapter - label_gitolite_cache_config: Gitolite Cache Konfiguration - label_gitolite_cache_max_elements: Max Cache Elemente - label_gitolite_cache_max_size: "Max Cache Elemente, Größe" - label_gitolite_cache_max_time: Max Cache Zeit - label_gitolite_config_file: Gitolite Konfigurationsdatei - label_gitolite_daemon_by_default: "Git Daemon Modus für neue Repositories standardmäßig aktivieren?" - label_gitolite_documentation: Gitolite Dokumentation - label_gitolite_download_revision_enabled: Aktiviere Git Revisions Download - label_gitolite_global_config: Gitolite Global Konfiguration - label_gitolite_global_storage_dir_desc: Relative zu Gitolite User Home - label_gitolite_global_storage_dir: Gitolite repositories base path - label_gitolite_hook_dirs_installed: Hook dirs installiert? - label_gitolite_hook_untouched: Hook left unberührt - label_gitolite_hooks_are_asynchronous: Run Hooks asynchron - label_gitolite_hooks_config: Gitolite Hooks Konfiguration - label_gitolite_hooks_debug: Run Hooks in Debug mode - label_gitolite_hooks_installed: Hooks installiert? - label_gitolite_hooks_namespace: Hooks Git Namespace - label_gitolite_hooks_params_installed: Hooks Parameter installiert? - label_gitolite_hooks_url: Hooks URL - label_gitolite_http_by_default: Smart HTTP Modus für neue Repositories standardmäßig aktivieren? - label_gitolite_identifier_prefix_desc: Wird zur Generierung von SSH Keys Identifiers verwendet - label_gitolite_identifier_prefix: Gitolite prefix - label_gitolite_identifier_strip_user_id_desc: Redmine neu starten, damit die Änderungen greifen. - label_gitolite_identifier_strip_user_id: User ID von Gitolite identifier entfernen - label_gitolite_lib_dir: Gitolite librairies directory - label_gitolite_libgit2_version: libgit2 Version - label_gitolite_local_code_dir: Gitolite non-core Hooks directory - label_gitolite_log_level_desc: Redmine neu starten, damit die Änderungen greifen. - label_gitolite_log_level: Gitolite Log Level - label_gitolite_mailer_params_installed: Mailer Parameter installiert? - label_gitolite_notify_by_default: "Enable 'Git Notifications' hook for new repositories by default?" - label_gitolite_notify_config: Git Mailing Liste Konfiguration - label_gitolite_notify_global_exclude: Git mailing list global exclude list - label_gitolite_notify_global_include: Git mailing list global include list - label_gitolite_notify_global_prefix: Git mailing list global prefix - label_gitolite_notify_global_sender_address: Git mailing list global sender address - label_gitolite_overwrite_existing_hooks: "Existierende Hooks überschreiben" - label_gitolite_recycle_bin_dir_desc: Relative to Gitolite user home - label_gitolite_recycle_bin_dir: Gitolite recycle bin base path - label_gitolite_recycle_bin_expiration_time_desc: In Stunden - label_gitolite_recycle_bin_expiration_time: Ablaufzeit für Repositories im Papierkorb - label_gitolite_redmine_storage_dir_desc: Relative to Gitolite repositories base path - label_gitolite_redmine_storage_dir: Subdirectory for Redmine-managed repositories - label_gitolite_repository_count: Count of physical repositories in Gitolite - label_gitolite_rescue: Gitolite Rescue - label_gitolite_rugged_features: Rugged compiled features - label_gitolite_server_host: SSH/Gitolite server host - label_gitolite_server_port: SSH/Gitolite server port - label_gitolite_ssh_config: Gitolite SSH Configuration - label_gitolite_ssh_private_key: Gitolite SSH private key - label_gitolite_ssh_public_key: Gitolite SSH public key - label_gitolite_storage_config: Gitolite Storage Configuration - label_gitolite_temp_dir_desc: Muss absolut sein - label_gitolite_temp_dir: Temporary dir for lock file and data - label_gitolite_use_sidekiq: Use Sidekiq to launch async jobs - label_gitolite_user: Gitolite Username - label_gitolite_version: Gitolite Version - label_help_git_setup: Git Setup - label_help_no_repo_rights: "Sorry, auf dieses Repository hast Du keinen Zugriff. Hier gibt es nichts für Dich zu tun." - label_help_repository_clone: Klone Repository - label_help_repository_setup_existing: Setup besthendes Repository - label_help_repository_setup_new: Setup neues Repository - label_hierarchical_organisation: Verzeichnis und URL Struktur für Redmine-managed Repositories - label_hierarchical: hierarchisch - label_http_access: HTTP Zugriff - label_http_only: Nur HTTP - label_http_server_domain: HTTP server domain - label_http_server_subdir_desc: Relative to Redmine root url - label_http_server_subdir: Unterverzeichnis für HTTP access - label_https_access: HTTPS Zugriff - label_https_and_http: HTTPS und HTTP - label_https_only: Nur HTTPS - label_https_server_domain_desc: Leer lassen, wenn es nicht verwendet wird - label_https_server_domain: HTTPS Server Domain - label_identifier_can_be_arbitrary_desc: (Kann jeder sinnvolle String sein) - label_identifier_can_be_arbitrary: Identifier - label_identifier_cannot_be_changed: Identifier
(Kann nicht geändert werden) - label_info: Info - label_init_repo_with_git_annex: Dieses Repository mit GitAnnex initialisieren - label_init_repo_with_readme: Dieses Repository mit einer README initialisieren - label_init_repositories_on_create: Automatisch Git Repositories mit einer README Datei initialisieren (à la Github) - label_install_gitolite_hooks: Installiere Hooks! - label_key_cannot_be_changed_please_create_new_key: 'Der Key kann nicht mehr geändert werden. Du kannst ihn jedoch löschen und einen Neuen erzeugen.' - label_key_type: Öffentlicher Schlüsseltyp - label_key: "Schlüssel (Key)" - label_latest_commit_date: Neuster Commit - label_main_git_repository: Main Git Repository - label_mirror_add: Repository Mirror hinzufügen - label_mirror_create: Repository Mirror erstellen - label_mirror_delete: Repository Mirror löschen - label_mirror_edit: Repository Mirror bearbeiten - label_mirror_explicit_refspec: Explicit Reference Spec - label_mirror_fast_forward: Fast Forward (Unforced) - label_mirror_forced_update: Force Update Remote - label_mirror_full_mirror: Complete Mirroring - label_mirror_help: Mirrors müssen Schreibzugriff auf den folgenden Public Key gewähren - label_mirror_include_all_branches: Push alle Branches - label_mirror_include_all_tags: Push alle Tags - label_mirror_push_fail: Fehlgeschlagen - label_mirror_push_info_html: "Pushing changes to mirror %{mirror_url} : %{status}" - label_mirror_push_mode: Mirror update mode - label_mirror_push_output: Output - label_mirror_push_sucess: Erfolgreich - label_mirror_push_title: Push to mirror - label_mirror_push: Push - label_mirror_refspec: Refspec - label_mirror_url_accepted_format: Erlaubtes URL format - label_mirror: Mirror - label_mirroring_keys_installed: Mirror keys installiert? - label_mode: Mode - label_move_repository: "Repository verschieben: '%{repo_name}'" - label_my_public_keys: Meine öffentlichen Schlüssel - label_need_help: Hilfe? - label_no_public_keys: Keine öffentlichen Schlüssel definiert - label_open_issue: Ticket öffnen - label_path_directories: PATH directories - label_permissions_header: Notwendige Berechtigungen - label_post_receive_url_add: Post Receive URL hinzufügen - label_post_receive_url_create: Repository Post-receive URL erstellen - label_post_receive_url_delete: Repository Post-receive URL löschen - label_post_receive_url_edit: Repository Post-receive URL bearbeiten - label_post_receive_urls: Post Receive URLs - label_protected_branch_add: Protected Branch hinzufügen - label_protected_branch_create: Protected Branch erstellen - label_protected_branch_delete: Protected Branch löschen - label_protected_branch_edit: Protected branch bearbeiten - label_protected_branch: Protected Branches - label_protected_branches: Protected branches - label_public_key_edit: Edit existing public key - label_public_key_new: Enter new public key - label_public_key: Öffentlicher Schlüssel - label_public_keys: Öffentliche Schlüssel - label_public_repo: Öffentliches Repository - label_read_only_permission: RO - label_read_write_permission: RW - label_recycle_bin_content_size: Größe - label_redmine_config: Redmine Konfiguration - label_redmine_git_hosting_issue: Redmine Git Hosting - Open Issue - label_redmine_git_hosting_wiki: Redmine Git Hosting - Wiki - label_redmine_has_rw_access_on_all_repos: Redmine has RW access on all Gitolite repositories - label_redmine_user: Redmine Benutzername - label_regenerate_all_ssh_keys_desc: "This will regenerate SSH keys identifier." - label_regenerate_all_ssh_keys_desc2: "This can be long : all SSH keys will be removed and re-added in Gitolite one by one." - label_regenerate_all_ssh_keys: Regenerate all SSH keys ? - label_repos_current_access_patterns: Current Repository Access Patterns - label_repository_access_not_configured: Repository Zugriff ist nicht konfiguriert, bitte kontaktiere einen Administrator. - label_repository_access_url: Repository access links - label_repository_default_branch: Repository default branch - label_repository_enabled_capabilities: Repository Enabled Capabilities - label_repository_exists_in_gitolite: Repository exists in Gitolite - label_repository_mirrors: Repository Mirrors - label_repository_options: Repository Optionen - label_repository_statistics_commits: Commits - label_repository_statistics_contributors: Mitwirkende - label_repository_statistics_global: Übersicht - label_resync_all_projects: Resync alle Projekte? - label_resync_all_ssh_keys: Resync alle SSH keys? - label_see_other_repositories: Andere Repositories ansehen - label_select_all: Alle auswählen - label_smart_http: Smart HTTP - label_sort_urls: (Sort urls) - label_split_payloads: Splitte payloads - label_ssh_access: SSH Zugriff - label_ssh_keys_current_access_patterns: SSH keys Access Patterns - label_ssh_server_domain: SSH server domain - label_storage_directory: Storage directory - label_sudo_gitolite_to_redmine_user: Git user is able to sudo to Redmine user? - label_sudo_redmine_to_gitolite_user: Redmine user is able to sudo to Git user? - label_tab_access: Zugriff - label_tab_cache: Cache - label_tab_config_file: Konfigurationsdatei - label_tab_config_test: Config Test - label_tab_gitolite_recycle_bin: Papierkorb - label_tab_gitolite_rescue: Rescue - label_tab_global: Global - label_tab_hooks: Hooks - label_tab_notify: Benachrichtigungen - label_tab_redmine: Redmine - label_tab_sidekiq_interface: Sidekiq - label_tab_ssh: SSH - label_tab_storage: Storage - label_temp_dir_writeable: Temp directory writeable? - label_this_urls_has_permissions: "Diese URL hat Zugriff." - label_total_commits: Anzahl Commits - label_total_contributors: Anzahl Mitwirkende - label_triggers: Triggers - label_unique_repo_identifier: Repository identifiers sind global eindeutig? - label_unknown_gitolite_version: Unbekannte Version - label_use_triggers: Trigger verwenden - label_user_key: User key - label_user_list: Users allowed - label_warn: Warning - notice_deployment_credential_create_failed: Erstellung von Deployment Credential fehlgeschlagen - notice_deployment_credential_created: Deployment Credential erfolgreich erstellt. - notice_deployment_credential_deleted_with_key: Both Deployment Credential and Key were successfully deleted. - notice_deployment_credential_deleted: Deployment Credential erfolgreich gelöscht. - notice_deployment_credential_update_failed: Deployment Credential Update fehlgeschlagen. - notice_deployment_credential_updated: Deployment Credential erfolgreich aktualisiert. - notice_empty_repository: Leeres Repository. Verwende die nachfolgenden Anweisungen, um Git zu verwenden. - notice_git_config_key_create_failed: Erstellung eines Git config key fehlgeschlagen - notice_git_config_key_created: Git config key erfolgreich erstellt. - notice_git_config_key_deleted: Git config key erfolgreich gelöscht. - notice_git_config_key_update_failed: Git config key Update fehlgeschlagen. - notice_git_config_key_updated: Git config key erfolgreich aktualisiert. - notice_gitolite_extra_update_failed: Errors while updating options - notice_gitolite_extra_updated: Options successfully updated - notice_mirror_create_failed: Failed to create mirror. - notice_mirror_created: Mirror was successfully created. - notice_mirror_deleted: Mirror was successfully deleted. - notice_mirror_update_failed: Failed to update mirror. - notice_mirror_updated: Mirror was successfully updated. - notice_post_receive_url_create_failed: Failed to create post-receive URL. - notice_post_receive_url_created: Post-receive URL was successfully created. - notice_post_receive_url_deleted: Post-receive URL was successfully deleted. - notice_post_receive_url_update_failed: Failed to update post-receive URL. - notice_post_receive_url_updated: Post-receive URL was successfully updated. - notice_protected_branch_create_failed: Failed to create protected branch - notice_protected_branch_created: Protected branch was successfully created. - notice_protected_branch_deleted: Protected branch was successfully deleted. - notice_protected_branch_update_failed: Failed to update protected branch - notice_protected_branch_updated: Protected branch was successfully updated. - notice_public_key_created: Public key %{title} erfolgreich erzeugt. - notice_public_key_deleted: Public key %{title} erfolgreich gelöscht. - notice_public_key_updated: Public key %{title} erfolgreich aktualisiert. - permission_add_repository_xitolite_watchers: Watcher hinzufügen - permission_create_gitolite_ssh_key: Erstelle SSH Schlüssel - permission_create_repository_deployment_credentials: Deployment keys erstellen - permission_create_repository_git_config_keys: Git config keys erstellen - permission_create_repository_mirrors: Repository mirrors erstellen - permission_create_repository_post_receive_urls: Post-receive URLs erstellen - permission_create_repository_protected_branches: Protected branches erstellen - permission_delete_repository_xitolite_watchers: Watcher löschen - permission_download_git_revision: Download Git Revision Archive - permission_edit_repository_deployment_credentials: Deployment keys bearbeiten - permission_edit_repository_git_config_keys: Git config keys bearbeiten - permission_edit_repository_mirrors: Repository mirrors bearbeiten - permission_edit_repository_post_receive_urls: Post-receive URLs bearbeiten - permission_edit_repository_protected_branches: Protected branches bearbeiten - permission_push_repository_mirrors: Push changes to repository mirrors - permission_view_repository_deployment_credentials: View deployment keys - permission_view_repository_git_config_keys: View Git config keys - permission_view_repository_mirrors: View repository mirrors - permission_view_repository_post_receive_urls: View post-receive URLs - permission_view_repository_protected_branches: View protected branches - permission_view_repository_xitolite_watchers: View watchers - protected_branches_reminder: Die obigen protected branches sind nicht aktiviert. Bitte aktiviere die Protected Branches in den Repository Einstellungen oben. - redmine_git_hosting: Redmine Git Hosting - select_other_keys: Andere keys - text_gitolite_key_destroy_confirmation: "Sicher, dass Du den folgenden Schlüssel (Key) zerstören willst: %{title} ?" - text_scm_command_not_available_git_hosting: SCM command nicht verfügbar. Bitte überprüfe die Einstellungen im Adminbereich des Redmine Git Hosting Plugin. - label_install_hook_results: Install hook results - label_repository_url_plural: Repository URLs diff --git a/plugins/redmine_git_hosting/config/locales/en.yml b/plugins/redmine_git_hosting/config/locales/en.yml deleted file mode 100644 index 2ce12e5..0000000 --- a/plugins/redmine_git_hosting/config/locales/en.yml +++ /dev/null @@ -1,410 +0,0 @@ -en: - activemodel: - errors: - models: - move_repository_form: - attributes: - base: - identifier_empty: Can't move repository with empty identifier - identifier_taken: Repository identifier already used by the new project - wrong_target_project: Target project is identical to source project - activerecord: - errors: - models: - gitolite_public_key: - attributes: - key: - corrupted: seems to be corrupted. - taken_by_you: 'is already in use by you as "%{name}".' - taken_by_other: 'is already in use by user "%{login}" as "%{name}".' - taken_by_someone: is already in use. It belongs to another user (ask administrator for details). - taken_by_gitolite_admin: is already in use as the Gitolite administrator key. - project: - attributes: - identifier: - invalid: invalid identifier - taken: matches existing repository identifier - repository_deployment_credential: - attributes: - base: - invalid_key: Public Key Must Be a Deployment Key - invalid_user: Credential owner cannot be different than owner of Key - repository_git_config_key: - attributes: - key: - invalid: "Wrong key format (is has to be at least one '.')" - repository_mirror: - attributes: - base: - nothing_to_push: Must include at least one item to push - explicit_refspec: - bad_format: is badly formatted - have_null_component: cannot have null first component (will delete remote branch(es)) - repository/xitolite: - attributes: - base: - blank_default_exists: "Can not create the respository as a blank repository already exists." - invalid_options: "You can not initialize a README file in a repository with GitAnnex" - identifier: - cannot_equal_project: "can not match the ID of an existing project" - taken: "is already taken." - invalid: invalid - cannot_change: cannot change - all_branches: All Branches - all_references: All Refs - all_tags: All Tags - button_clone: Clone - display_access_emphasis_html: "In the above patterns, emphasized components represent context-dependent elements." - display_access_flat: "Parent projects are not included in the URLs, since the repository is in Flat mode." - display_access_hierarchical: "Parent projects are included in the URLs, since the repository is in Hierarchical mode." - display_access_setup1_html: "Assume that project1 is a parent of project2, and project2 is a parent of project3." - display_access_setup2_html: "Also, assume that project project3 has 2 repositories : the default repository and a repository example." - display_access_setup3_html: "Given the current configuration, project project3 has the following properties :" - error_download_revision_no_such_commit: "No such commit %{commit}" - error_project_not_found: "No project with this identifier was found" - error_public_key_create_failed: Failed to create public key. - error_public_key_update_failed: Failed to update public key. - error_repository_not_found: "No repository with this identifier was found" - error_xitolite_repositories_disabled: "Gitolite repositories are disabled, cannot create repository!" - field_key: this key - field_mode: Mode - field_perm: Access Permissions - field_split_payloads: Split the global payload in many payloads - field_use_triggers: Use triggers - label_active_for: Active for - label_all_projects_use_git: Automatically initialize Git repositories for new projects? - label_average_commit_per_day: Average commits per day - label_average_contributor_commits: Average commits per contributor - label_backup_in_progress: Saving... - label_branch_path: Branch path - label_browse_repository: Browse repository - label_commit_plural: Commits - label_commits_number: Number of commits - label_commits_per_day: Commits per day - label_commits_per_hour: Commits per hour - label_commits_per_weekday: Commits per weekday - label_current_deploy_keys: Current deployment keys - label_current_public_keys: Current public keys - label_current_user_keys: Current user keys - label_cut_and_paste: Cut and paste entire .pub file. - label_debug: Debug - label_default_domain_name: Default domain name - label_default_gitolite_hooks_url: Default URL - label_default_repository: Default repository - label_delete_from_recyle_bin: Delete from recycle bin - label_delete_git_repositories: Delete Git repository when project deleted? - info_delete_git_repositories: (will be place in recycle bin) - label_delete_in_progress: Deleting... - label_delete_warning: Warning! Deletion is forever! - label_deploy_key: Deploy key - label_deployment_credential_add: Add Deployment Credential - label_deployment_credential_create_key_first: Deployment key(s) not detected. You should create one first. - label_deployment_credential_create: Create New Deployment Credential - label_deployment_credential_delete_when_unused: Delete key when unused? - label_deployment_credential_delete: Delete Deployment Credential - label_deployment_credential_edit: Edit Deployment Credential - label_deployment_credential_honored: Honored? - label_deployment_credential_owner: Owner - label_deployment_credential_public_key_file: Public key file - label_deployment_credential_public_key_name: Public key name - label_deployment_credential_select_deploy_key: Select Deployment Key - label_deployment_credentials: Deployment Credentials - label_download_and_install_git: Download and install Git - label_download_format: Download as - label_download_select_format: Select format - label_empty_get: Empty GET - label_empty_recycle_bin: Empty recycle bin - label_empty_repository: Empty repository? - label_enable_git_daemon: Enable Git Daemon - label_enable_git_notify: Enable Mailing list - label_enable_go_url: Enable GO URL - label_enable_protected_branches: Enable protected branches - label_enable_public_repo: Make repository public - label_enable_smart_http: Smart HTTP Mode - label_enable_smart_https: Smart HTTPS Mode - label_enable_ssh_url: Enable SSH URL - label_error: Error - label_etcetera: etc - label_example_repository: Example repository - label_first_commit_date: First commit date - label_flat: Flat - label_flush_cache: Flush Git Cache? - label_git_annex: GitAnnex - label_git_config_email_desc: Will be used as author email in commits - label_git_config_email: Git author email - label_git_config_key_add: Add Git Config Key - label_git_config_key_create: Create New Git Config Key - label_git_config_key_delete: Delete Git Config Key - label_git_config_key_edit: Edit Git Config Key - label_git_config_keys: Git Config Keys - label_git_config_username_desc: Will be used as author name in commits - label_git_config_username: Git author name - label_git_daemon: Git Daemon - label_git_key_type_config: Git Config Key - label_git_key_type_option: Gitolite Option - label_git_notification_prefix: Mailing list prefix - label_git_notification_sender: Mailing list sender address - label_git_notify: Git Notifications - label_git_objects_count: Git objects count - label_git_option_key_add: Add Gitolite option - label_git_option_keys: Gitolite configuration options - label_git_version: Git version - label_github_post: GitHub POST - label_gitolite_access_config: Gitolite Access Configuration - label_gitolite_banner: Gitolite banner - label_gitolite_bin_dir: Gitolite binaries directory - label_gitolite_cache_adapter_desc: You must restart Redmine to take effects - label_gitolite_cache_adapter: Cache Adapter - label_gitolite_cache_config: Gitolite Cache Configuration - label_gitolite_cache_max_elements: Max cache elements - label_gitolite_cache_max_size: Max cache element size - label_gitolite_cache_max_time: Max cache time - label_gitolite_config_file: Gitolite configuration file - label_gitolite_daemon_by_default: Enable Git Daemon mode for new repositories by default? - label_gitolite_documentation: Gitolite Documentation - label_gitolite_download_revision_enabled: Enable Git revisions download - label_gitolite_global_config: Gitolite Global Configuration - label_gitolite_global_storage_dir_desc: Relative to Gitolite user home - label_gitolite_global_storage_dir: Gitolite repositories base path - label_gitolite_hook_dirs_installed: Hook dirs installed? - label_gitolite_hook_untouched: hook left untouched - label_gitolite_hooks_are_asynchronous: Run hooks asynchronously - label_gitolite_hooks_config: Gitolite Hooks Configuration - label_gitolite_hooks_debug: Run hooks in Debug mode - label_gitolite_hooks_installed: Hooks installed? - label_gitolite_hooks_namespace: Hooks Git namespace - label_gitolite_hooks_params_installed: Hooks parameters installed? - label_gitolite_hooks_url: Hooks URL - label_gitolite_http_by_default: Enable Smart HTTP mode for new repositories by default? - label_gitolite_identifier_prefix_desc: Will be used to generate SSH keys identifiers - label_gitolite_identifier_prefix: Gitolite prefix - label_gitolite_identifier_strip_user_id_desc: You must restart Redmine to take effects - label_gitolite_identifier_strip_user_id: Remove user ID from Gitolite identifier - label_gitolite_lib_dir: Gitolite librairies directory - label_gitolite_libgit2_version: libgit2 version - label_gitolite_local_code_dir: Gitolite non-core hooks directory - label_gitolite_log_level_desc: You must restart Redmine to take effects - label_gitolite_log_level: Gitolite log level - label_gitolite_mailer_params_installed: Mailer parameters installed? - label_gitolite_notify_by_default: "Enable 'Git Notifications' hook for new repositories by default?" - label_gitolite_notify_config: Git Mailing List Configuration - label_gitolite_notify_global_exclude: Git mailing list global exclude list - label_gitolite_notify_global_include: Git mailing list global include list - label_gitolite_notify_global_prefix: Git mailing list global prefix - label_gitolite_notify_global_sender_address: Git mailing list global sender address - label_gitolite_overwrite_existing_hooks: Overwrite existing hooks - label_gitolite_recycle_bin_dir_desc: Relative to Gitolite user home - label_gitolite_recycle_bin_dir: Gitolite recycle bin base path - label_gitolite_recycle_bin_expiration_time_desc: In hours - label_gitolite_recycle_bin_expiration_time: Expiration time for repositories in recycle bin - label_gitolite_redmine_storage_dir_desc: Relative to Gitolite repositories base path - label_gitolite_redmine_storage_dir: Subdirectory for Redmine-managed repositories - label_gitolite_repository_count: Count of physical repositories in Gitolite - label_gitolite_rescue: Gitolite Rescue - label_gitolite_rugged_features: Rugged compiled features - label_gitolite_server_host: SSH/Gitolite server host - label_gitolite_server_port: SSH/Gitolite server port - label_gitolite_ssh_config: Gitolite SSH Configuration - label_gitolite_ssh_private_key: Gitolite SSH private key - label_gitolite_ssh_public_key: Gitolite SSH public key - label_gitolite_storage_config: Gitolite Storage Configuration - label_gitolite_temp_dir_desc: Must be absolute - label_gitolite_temp_dir: Temporary dir for lock file and data - label_gitolite_use_sidekiq: Use Sidekiq to launch async jobs - label_gitolite_user: Gitolite username - label_gitolite_version: Gitolite version - label_help_git_setup: Git Setup - label_help_no_repo_rights: "Sorry, you don't have access to this repository. There's nothing you can do." - label_help_repository_clone: Clone Repository - label_help_repository_setup_existing: Setup Existing Repository - label_help_repository_setup_new: Setup New Repository - label_hierarchical_organisation: Directory and URL structure for Redmine-managed repositories - label_hierarchical: Hierarchical - label_http_access: HTTP access - label_http_only: HTTP Only - label_http_server_domain: HTTP server domain - label_http_server_subdir_desc: Relative to Redmine root url - label_http_server_subdir: Subdirectory for HTTP access - label_https_access: HTTPS access - label_https_and_http: HTTPS and HTTP - label_https_only: HTTPS Only - label_https_server_domain_desc: Let it blank if you don't use it - label_https_server_domain: HTTPS server domain - label_identifier_can_be_arbitrary_desc: (Can be any meaningful string) - label_identifier_can_be_arbitrary: Identifier - label_identifier_cannot_be_changed: Identifier
(Cannot be changed) - label_info: Info - label_init_repo_with_git_annex: Initialize this repository with GitAnnex - label_init_repo_with_readme: Initialize this repository with a README - label_init_repositories_on_create: Automatically initialize Git repositories with a README file (à la Github) - label_install_gitolite_hooks: Install hooks ! - label_key_cannot_be_changed_please_create_new_key: 'The key cannot be altered anymore. However, you can delete it and create a new one.' - label_key_type: Public key type - label_key: Key - label_latest_commit_date: Latest commit date - label_main_git_repository: Main Git Repository - label_mirror_add: Add Repository Mirror - label_mirror_create: Create Repository Mirror - label_mirror_delete: Delete Repository Mirror - label_mirror_edit: Edit Repository Mirror - label_mirror_explicit_refspec: Explicit Reference Spec - label_mirror_fast_forward: Fast Forward (Unforced) - label_mirror_forced_update: Force Update Remote - label_mirror_full_mirror: Complete Mirroring - label_mirror_help: Mirrors must grant write access to the following public key - label_mirror_include_all_branches: Push all Branches - label_mirror_include_all_tags: Push all Tags - label_mirror_push_fail: Failed - label_mirror_push_info_html: "Pushing changes to mirror %{mirror_url} : %{status}" - label_mirror_push_mode: Mirror update mode - label_mirror_push_output: Output - label_mirror_push_sucess: Success - label_mirror_push_title: Push to mirror - label_mirror_push: Push - label_mirror_refspec: Refspec - label_mirror_url_accepted_format: Accepted URL format - label_mirror: Mirror - label_mirroring_keys_installed: Mirrors keys installed? - label_mode: Mode - label_move_repository: "Move repository: '%{repo_name}'" - label_my_public_keys: My public keys - label_need_help: Need Help? - label_no_public_keys: No public keys defined - label_open_issue: Open Issue - label_path_directories: PATH directories - label_permissions_header: Required Permissions - label_post_receive_url_add: Add Post Receive URL - label_post_receive_url_create: Create Repository Post-receive URL - label_post_receive_url_delete: Delete Repository Post-receive URL - label_post_receive_url_edit: Edit Repository Post-receive URL - label_post_receive_urls: Post Receive URLs - label_protected_branch_add: Add protected branch - label_protected_branch_create: Create protected branch - label_protected_branch_delete: Delete protected branch - label_protected_branch_edit: Edit protected branch - label_protected_branch: Protected Branches - label_protected_branches: Protected branches - label_public_key_edit: Edit existing public key - label_public_key_new: Enter new public key - label_public_key: Public key - label_public_keys: Public keys - label_public_repo: Public repository - label_read_only_permission: RO - label_read_write_permission: RW - label_recycle_bin_content_size: Size - label_redmine_config: Redmine Configuration - label_redmine_git_hosting_issue: Redmine Git Hosting - Open Issue - label_redmine_git_hosting_wiki: Redmine Git Hosting - Wiki - label_redmine_has_rw_access_on_all_repos: Redmine has RW access on all Gitolite repositories - label_redmine_user: Redmine username - label_regenerate_all_ssh_keys_desc: "This will regenerate SSH keys identifier." - label_regenerate_all_ssh_keys_desc2: "This can be long : all SSH keys will be removed and re-added in Gitolite one by one." - label_regenerate_all_ssh_keys: Regenerate all SSH keys ? - label_repos_current_access_patterns: Current Repository Access Patterns - label_repository_access_not_configured: Repository access not configured, please contact your adminstrator. - label_repository_access_url: Repository access links - label_repository_default_branch: Repository default branch - label_repository_enabled_capabilities: Repository Enabled Capabilities - label_repository_exists_in_gitolite: Repository exists in Gitolite - label_repository_mirrors: Repository Mirrors - label_repository_options: Repository options - label_repository_statistics_commits: Commits statistics - label_repository_statistics_contributors: Contributors statistics - label_repository_statistics_global: Global statistics - label_resync_all_projects: Resync all projects ? - label_resync_all_ssh_keys: Resync all SSH keys ? - label_see_other_repositories: See other repositories - label_select_all: Select all - label_smart_http: Smart HTTP - label_sort_urls: (Sort urls) - label_split_payloads: split payloads - label_ssh_access: SSH access - label_ssh_keys_current_access_patterns: SSH keys Access Patterns - label_ssh_server_domain: SSH server domain - label_storage_directory: Storage directory - label_sudo_gitolite_to_redmine_user: Git user is able to sudo to Redmine user? - label_sudo_redmine_to_gitolite_user: Redmine user is able to sudo to Git user? - label_tab_access: Access - label_tab_cache: Cache - label_tab_config_file: Configuration file - label_tab_config_test: Config Test - label_tab_gitolite_recycle_bin: Recycle Bin - label_tab_gitolite_rescue: Rescue - label_tab_global: Global - label_tab_hooks: Hooks - label_tab_notify: Notifications - label_tab_redmine: Redmine - label_tab_sidekiq_interface: Sidekiq - label_tab_ssh: SSH - label_tab_storage: Storage - label_temp_dir_writeable: Temp directory writeable? - label_this_urls_has_permissions: "This URL has access." - label_total_commits: Total commits - label_total_contributors: Total contributors - label_triggers: Triggers - label_unique_repo_identifier: Repository identifiers are globally unique? - label_unknown_gitolite_version: Unknown version - label_use_triggers: Use triggers - label_user_key: User key - label_user_list: Users allowed - label_warn: Warning - notice_deployment_credential_create_failed: Failed to create deployment credential - notice_deployment_credential_created: Deployment Credential was successfully created. - notice_deployment_credential_deleted_with_key: Both Deployment Credential and Key were successfully deleted. - notice_deployment_credential_deleted: Deployment Credential was successfully deleted. - notice_deployment_credential_update_failed: Failed to update deployment credential - notice_deployment_credential_updated: Deployment Credential was successfully updated. - notice_empty_repository: Repository is empty. Get started by following the instructions below. - notice_git_config_key_create_failed: Failed to create Git config key - notice_git_config_key_created: Git config key was successfully created. - notice_git_config_key_deleted: Git config key was successfully deleted. - notice_git_config_key_update_failed: Failed to update Git config key - notice_git_config_key_updated: Git config key was successfully updated. - notice_gitolite_extra_update_failed: Errors while updating options - notice_gitolite_extra_updated: Options successfully updated - notice_mirror_create_failed: Failed to create mirror. - notice_mirror_created: Mirror was successfully created. - notice_mirror_deleted: Mirror was successfully deleted. - notice_mirror_update_failed: Failed to update mirror. - notice_mirror_updated: Mirror was successfully updated. - notice_post_receive_url_create_failed: Failed to create post-receive URL. - notice_post_receive_url_created: Post-receive URL was successfully created. - notice_post_receive_url_deleted: Post-receive URL was successfully deleted. - notice_post_receive_url_update_failed: Failed to update post-receive URL. - notice_post_receive_url_updated: Post-receive URL was successfully updated. - notice_protected_branch_create_failed: Failed to create protected branch - notice_protected_branch_created: Protected branch was successfully created. - notice_protected_branch_deleted: Protected branch was successfully deleted. - notice_protected_branch_update_failed: Failed to update protected branch - notice_protected_branch_updated: Protected branch was successfully updated. - notice_public_key_created: Public key %{title} was successfully created. - notice_public_key_deleted: Public key %{title} was successfully deleted. - notice_public_key_updated: Public key %{title} was successfully updated. - permission_add_repository_xitolite_watchers: Add watchers - permission_create_gitolite_ssh_key: Create SSH keys - permission_create_repository_deployment_credentials: Create deployment keys - permission_create_repository_git_config_keys: Create Git config keys - permission_create_repository_mirrors: Create repository mirrors - permission_create_repository_post_receive_urls: Create post-receive URLs - permission_create_repository_protected_branches: Create protected branches - permission_delete_repository_xitolite_watchers: Delete watchers - permission_download_git_revision: Download Git Revision Archive - permission_edit_repository_deployment_credentials: Edit deployment keys - permission_edit_repository_git_config_keys: Edit Git config keys - permission_edit_repository_mirrors: Edit repository mirrors - permission_edit_repository_post_receive_urls: Edit post-receive URLs - permission_edit_repository_protected_branches: Edit protected branches - permission_push_repository_mirrors: Push changes to repository mirrors - permission_view_repository_deployment_credentials: View deployment keys - permission_view_repository_git_config_keys: View Git config keys - permission_view_repository_mirrors: View repository mirrors - permission_view_repository_post_receive_urls: View post-receive URLs - permission_view_repository_protected_branches: View protected branches - permission_view_repository_xitolite_watchers: View watchers - protected_branches_reminder: The protected branches above are not enabled. Please enable Protected Branches in the repository settings above. - redmine_git_hosting: Redmine Git Hosting - select_other_keys: Other keys - text_gitolite_key_destroy_confirmation: "Are you sure you want to destroy this key : %{title} ?" - text_scm_command_not_available_git_hosting: SCM command is not available. Please check settings on the administration panel of Redmine Git Hosting plugin. - label_install_hook_results: Install hook results - label_repository_url_plural: Repository URLs diff --git a/plugins/redmine_git_hosting/config/locales/es.yml b/plugins/redmine_git_hosting/config/locales/es.yml deleted file mode 100644 index 0fc14c5..0000000 --- a/plugins/redmine_git_hosting/config/locales/es.yml +++ /dev/null @@ -1,406 +0,0 @@ -es: - activemodel: - errors: - models: - move_repository_form: - attributes: - base: - identifier_empty: No es posible mover un repositorio con el identificador vacío - identifier_taken: El identificador del repositorio ya está siendo usado por el proyecto nuevo - wrong_target_project: El proyecto de destino es idéntico al proyecto de origen - activerecord: - errors: - models: - gitolite_public_key: - attributes: - key: - corrupted: parece estar corrompida. - taken_by_you: 'ya se está utilizando por usted como "%{name}".' - taken_by_other: 'ya se está utilizando por el usuario "%{login}" como "%{name}".' - taken_by_someone: ya se está utilizando. Pertenece a otro usuario (pregunte al administrador acerca de los detalles). - taken_by_gitolite_admin: ya se está utilizando como la clave de administrador de Gitolite. - project: - attributes: - identifier: - invalid: identificador inválido - taken: coincide con un identificador de repositorio preexistente - repository_deployment_credential: - attributes: - base: - invalid_key: La clave pública debe ser una clave de despliegue - invalid_user: El propietario de la credencial no puede ser distinto al propietario de la clave - repository_git_config_key: - attributes: - key: - invalid: "Formato de clave incorrecto (debe contener al menos un '.')" - repository_mirror: - attributes: - base: - nothing_to_push: Debe incluir al menos un elemento a enviar - explicit_refspec: - bad_format: tiene un formato incorrecto - have_null_component: no puede tener un primer componente nulo (borrará la(s) rama(s) remota(s)) - repository/xitolite: - attributes: - base: - blank_default_exists: "No se puede crear el repositiorio puesto que ya existe un repositorio en blanco." - invalid_options: "No se puede inicializar un fichero README en un repositorio con GitAnnex" - identifier: - cannot_equal_project: "no se puede asociar con la ID de un proyecto existente" - taken: "ya está en uso." - invalid: inválido - cannot_change: no se puede cambiar - all_branches: Todas las ramas - all_references: Todas las referencias - all_tags: Todas las etiquetas - button_clone: Clonar - display_access_emphasis_html: "En los patrones de arriba, los componentes resaltados representan elementos dependientes del contexto." - display_access_flat: "Los proyectos padre no se incluyen en las URLs, ya que el repositorio está en modo plano." - display_access_hierarchical: "Los proyectos padre se incluyen en las URLs, ya que el repositorio está en modo jerárquico." - display_access_setup1_html: "Asumiendo que proyecto1 es padre de proyecto2, y que proyecto2 es padre de proyecto3." - display_access_setup2_html: "Además, asumiendo que el proyecto proyecto3 tiene 2 repositorios: el repositorio pordefecto y el repositorio ejemplo." - display_access_setup3_html: "Con dicha configuración, el proyecto proyecto3 tiene las siguientes propiedades:" - error_download_revision_no_such_commit: "No existe el commit %{commit}" - error_project_not_found: "No se ha encontrado ningún proyecto con este identificador" - error_public_key_create_failed: Ha fallado la creación de la clave pública. - error_public_key_update_failed: Ha fallado la actualización de la clave pública. - error_repository_not_found: "No se ha encontrado ningún repositorio con este identificador" - error_xitolite_repositories_disabled: "los repositorios Gitolite están deshabilitados, no se puede crear el repositorio!" - field_key: esta clave - field_mode: Modo - field_perm: Permisos de acceso - field_split_payloads: Dividir el payload global en varios payloads - field_use_triggers: Usar triggers - label_active_for: Activo durante - label_all_projects_use_git: ¿Inicializar automáticamente un repositorio Git en los proyectos nuevos? - label_average_commit_per_day: Media de commits por día - label_average_contributor_commits: Media de commits por contribuidor - label_backup_in_progress: Guardando... - label_branch_path: Camino de la rama - label_browse_repository: Navegar por el repositorio - label_commit_plural: Commits - label_commits_number: Número de commits - label_commits_per_day: Commits por día - label_commits_per_hour: Commits por hora - label_commits_per_weekday: Commits por día de la semana - label_current_deploy_keys: Claves de despliegue actuales - label_current_public_keys: Claves públicas actuales - label_current_user_keys: Claves de usuario actuales - label_cut_and_paste: Corte y pegue el fichero .pub entero. - label_debug: Depuración - label_default_domain_name: Nombre de dominio por defecto - label_default_gitolite_hooks_url: URL por defecto - label_default_repository: Repository por defecto - label_delete_from_recyle_bin: Borrar de la papelera de reciclaje - label_delete_git_repositories: ¿Borrar el repositorio de Git cuando se borre el proyecto? - info_delete_git_repositories: (se moverá a la papelera de reciclaje) - label_delete_in_progress: Borrando... - label_delete_warning: ¡Atención! ¡El borrado es permanente! - label_deploy_key: Clave de despliegue - label_deployment_credential_add: Añadir credencial de despliegue - label_deployment_credential_create_key_first: No se ha detectado ninguna clave de despliegue. Debe crear una antes. - label_deployment_credential_create: Crear nueva credencial de despliegue - label_deployment_credential_delete_when_unused: ¿Borrar la clave cuando no se use? - label_deployment_credential_delete: Borrar credencial de despliegue - label_deployment_credential_edit: Editar credencial de despliegue - label_deployment_credential_honored: ¿Autorizado? - label_deployment_credential_owner: Propietario - label_deployment_credential_public_key_file: Fichero de la clave pública - label_deployment_credential_public_key_name: Nombre de la clave pública - label_deployment_credential_select_deploy_key: Seleccione una clave de despliegue - label_deployment_credentials: Credenciales de despliegue - label_download_and_install_git: Descargar e instalar Git - label_download_format: Descargar como - label_download_select_format: Seleccionar formato - label_empty_get: GET vacío - label_empty_recycle_bin: Vaciar la papelera de reciclaje - label_empty_repository: ¿Repositorio vacío? - label_enable_git_daemon: Activar el daemon de Git - label_enable_git_notify: Activar la lista de correo - label_enable_protected_branches: Activar las ramas protegidas - label_enable_public_repo: Hacer público el repositorio - label_enable_smart_http: Modo HTTP inteligente - label_error: Error - label_etcetera: etc. - label_example_repository: Repository de ejemplo - label_first_commit_date: Fecha del primer commit - label_flat: Plano - label_flush_cache: ¿Desechar la caché de Git? - label_git_annex: GitAnnex - label_git_config_email_desc: Se usará como la dirección de correo del autor en los commits - label_git_config_email: Dirección de correo del autor de Git - label_git_config_key_add: Añadir una clave de configuración de Git - label_git_config_key_create: Crear una nueva clave de configuración de Git - label_git_config_key_delete: Borrar la clave de configuración de Git - label_git_config_key_edit: Crear la clave de configuración de Git - label_git_config_keys: Claves de configuración de Git - label_git_config_username_desc: Se usará como el nombre del autor en los commits - label_git_config_username: Nombre del autor de Git - label_git_daemon: Daemon de Git - label_git_key_type_config: Clave de configuración de Git - label_git_key_type_option: Opciones de Gitolite - label_git_notification_prefix: Prefijo de la lista de correo - label_git_notification_sender: Remitente de la lista de correo - label_git_notify: Notificaciones de Git - label_git_objects_count: Recuento de objetos de Git - label_git_option_key_add: Añadir una opción de Gitolite - label_git_option_keys: Optiones de configuración de Gitolite - label_git_version: Versión de Git - label_github_post: POST GitHub - label_gitolite_access_config: Configuración de acceso de Gitolite - label_gitolite_banner: Banner de Gitolite - label_gitolite_bin_dir: Carpeta de binarios de Gitolite - label_gitolite_cache_adapter_desc: Debe reiniciar Redmine para que surja efecto - label_gitolite_cache_adapter: Adaptador de caché - label_gitolite_cache_config: Configuración de la caché de Gitolite - label_gitolite_cache_max_elements: Máximo de elementos en caché - label_gitolite_cache_max_size: Tamaño máximo de elementos en caché - label_gitolite_cache_max_time: Tiempo máximo de caché - label_gitolite_config_file: Fichero de configuración de Gitolite - label_gitolite_daemon_by_default: ¿Activar por defecto el modo Daemon de Git en los reposiotios nuevos? - label_gitolite_documentation: Documentación de Gitolite - label_gitolite_download_revision_enabled: Activar la descarga de revisiones de Git - label_gitolite_global_config: Configuración global de Gitolite - label_gitolite_global_storage_dir_desc: Relativa al directorio del usuario de Gitolite - label_gitolite_global_storage_dir: Ruta base de los repositorios de Gitolite - label_gitolite_hook_dirs_installed: ¿Está instalada la carpeta de hooks? - label_gitolite_hook_untouched: no se ha modificado el hook - label_gitolite_hooks_are_asynchronous: Ejecutar los hooks asíncronamente - label_gitolite_hooks_config: Configuración de los Hooks de Gitolite - label_gitolite_hooks_debug: Ejecutar los hooks en modo de depuración - label_gitolite_hooks_installed: ¿Están los hooks instalados? - label_gitolite_hooks_namespace: Espacio de nombres de hooks de Git - label_gitolite_hooks_params_installed: ¿Están instalados los parámetros de hooks? - label_gitolite_hooks_url: URL de hooks - label_gitolite_http_by_default: ¿Activar por defecto el modo HTTP inteligente en los reposiotios nuevos? - label_gitolite_identifier_prefix_desc: Se usará para generar los identificadores de las claves SSH - label_gitolite_identifier_prefix: Prefijo de Gitolite - label_gitolite_identifier_strip_user_id: Eliminar el ID de usuario del identificador de Gitolite - label_gitolite_lib_dir: Carpeta de bibliotecas de Gitolite - label_gitolite_libgit2_version: Versión de libgit2 - label_gitolite_local_code_dir: Carpeta de hooks non-core de Gitolite - label_gitolite_log_level_desc: Debe reiniciar Redmine para que surja efecto - label_gitolite_log_level: Nivel de registro de Gitolite - label_gitolite_mailer_params_installed: ¿Están instalados lo parámetros del Mailer? - label_gitolite_notify_by_default: "Activar por defecto el hook de 'Notificationes de Git' en los repositorios nuevos?" - label_gitolite_notify_config: Configuración de la lista de correo de Git - label_gitolite_notify_global_exclude: Listado global de exclusiones de la lista de correo de Git - label_gitolite_notify_global_include: Listado global de inclusiones de la lista de correo de Git - label_gitolite_notify_global_prefix: Prefijo global de la lista de correo de Git - label_gitolite_notify_global_sender_address: Remitente global de la lista de correo de Git - label_gitolite_overwrite_existing_hooks: Sobreescribir los hooks preexistentes - label_gitolite_recycle_bin_dir_desc: Relativa al directorio del usuario de Gitolite - label_gitolite_recycle_bin_dir: Ruta base de la papelera de reciclaje de Gitolite - label_gitolite_recycle_bin_expiration_time_desc: En horas - label_gitolite_recycle_bin_expiration_time: Tiempo de expiración de los repositorios en la papelera de reciclaje - label_gitolite_redmine_storage_dir_desc: Relativa al directorio de repositorios de Gitolite - label_gitolite_redmine_storage_dir: Subcarpeta para los repositorios gestionados por Redmine-managed - label_gitolite_repository_count: Recuento de repositorios físicos en Gitolite - label_gitolite_rescue: Rescate de Gitolite - label_gitolite_rugged_features: Características de Rugged compiladas - label_gitolite_server_host: host del servidor SSH/Gitolite - label_gitolite_server_port: puerto del servidor SSH/Gitolite - label_gitolite_ssh_config: Configuración SSH de Gitolite - label_gitolite_ssh_private_key: Clave privada SSH de Gitolite - label_gitolite_ssh_public_key: Clave pública SSH de Gitolite - label_gitolite_storage_config: Configuración del almacenamiento de Gitolite - label_gitolite_temp_dir_desc: Debe ser absoluta - label_gitolite_temp_dir: Carpeta temporal para los datos y el fichero de bloqueo - label_gitolite_use_sidekiq: Usar Sidekiq para lanzar tareas asíncronas - label_gitolite_user: Usuario de Gitolite - label_gitolite_version: Versión de Gitolite - label_help_git_setup: Configuración de Git - label_help_no_repo_rights: "Vaya, no tiene acceso a este repositorio. No hay nada que pueda hacer aquí." - label_help_repository_clone: Clonar repositorio - label_help_repository_setup_existing: Configurar repositorio preexistente - label_help_repository_setup_new: Configurar nuevo repositorio - label_hierarchical_organisation: Estructura de carpetas y URL para los repositorios gestionados por Redmine - label_hierarchical: Jerárquico - label_http_access: Acceso HTTP - label_http_only: Solo HTTP - label_http_server_domain: Dominio del servidor HTTP - label_http_server_subdir_desc: Relativa a la URL raíz de Redmine - label_http_server_subdir: Subcarpeta para el acceso HTTP - label_https_access: Acceso HTTPS - label_https_and_http: HTTPS y HTTP - label_https_only: Solo HTTPS - label_https_server_domain_desc: Déjelo en blanco si no lo usa - label_https_server_domain: Dominio del servidor HTTPS - label_identifier_can_be_arbitrary_desc: (Puede ser cualquier cadena de texto con significado) - label_identifier_can_be_arbitrary: Identificador - label_identifier_cannot_be_changed: Identificador
(no puede cambiarse) - label_info: Info - label_init_repo_with_git_annex: Inicializar este repositorio con GitAnnex - label_init_repo_with_readme: Inicializar este repositorio con un fichero README - label_init_repositories_on_create: Inicializar los repositorios de Git automaticamente con un fichero README - label_install_gitolite_hooks: ¡Instalar los hooks! - label_key_cannot_be_changed_please_create_new_key: 'No es posible modificar la clave. Sin embargo, puede borrarla y crear una nueva.' - label_key_type: Tipo de clave pública - label_key: Clave - label_latest_commit_date: Fecha del último commit - label_main_git_repository: Repositorio principal de Git - label_mirror_add: Añadir una réplica del repositorio - label_mirror_create: Crear una réplica del repositorio - label_mirror_delete: Borrar una réplica del repositorio - label_mirror_edit: Modificar una réplica del repositorio - label_mirror_explicit_refspec: Especificación de referencias explícitas - label_mirror_fast_forward: Avance rápido (no forzado) - label_mirror_forced_update: Forzar la actualización de la réplica - label_mirror_full_mirror: Réplica completa - label_mirror_help: Las réplicas deben autorizar el acceso de escritura a la siguiente clave pública - label_mirror_include_all_branches: Enviar todas las ramas - label_mirror_include_all_tags: Enviar todas las etiquetas - label_mirror_push_fail: Erróneo - label_mirror_push_info_html: "Enviando cambios a la réplica %{mirror_url} : %{status}" - label_mirror_push_mode: Método de actualización de la réplica - label_mirror_push_output: Resultado - label_mirror_push_sucess: Satisfactorio - label_mirror_push_title: Enviar a la réplica - label_mirror_push: Enviar - label_mirror_refspec: Refspec - label_mirror_url_accepted_format: Formatos de URL aceptado - label_mirror: Réplica - label_mirroring_keys_installed: ¿Están instaladas las claves de réplicas? - label_mode: Modo - label_move_repository: "Mover repositorio: '%{repo_name}'" - label_my_public_keys: Mis claves públicas - label_need_help: ¿Necesita ayuda? - label_no_public_keys: No se ha definido ninguna clave pública - label_open_issue: Abrir un asunto - label_path_directories: Carpetas del PATH - label_permissions_header: Permisos requeridos - label_post_receive_url_add: Añadir una URL de post-recepción - label_post_receive_url_create: Crear una URL de post-recepción - label_post_receive_url_delete: Borrar la URL de post-recepción - label_post_receive_url_edit: Editar la URL de post-recepción - label_post_receive_urls: URL de post-recepción - label_protected_branch_add: Añadir una rama protegida - label_protected_branch_create: Crear una rama protegida - label_protected_branch_delete: Borrar una rama protegida - label_protected_branch_edit: Editar una rama protegida - label_protected_branch: Ramas protegidas - label_protected_branches: Ramas protegidas - label_public_key_edit: Editar una clave pública existente - label_public_key_new: Introducir una nueva clave pública - label_public_key: Clave pública - label_public_keys: Claves públicas - label_public_repo: Repositorio pública - label_read_only_permission: RO - label_read_write_permission: RW - label_recycle_bin_content_size: Tamaño - label_redmine_config: Configuración de Redmine - label_redmine_git_hosting_issue: Redmine Git Hosting - Abrir un asunto - label_redmine_git_hosting_wiki: Redmine Git Hosting - Wiki - label_redmine_has_rw_access_on_all_repos: Redmine tiene acceso RW a todos los repositorios de Gitolite - label_redmine_user: Usuario de Redmine - label_regenerate_all_ssh_keys_desc: "Esto regenerará todos los identificadores de las claves SSH." - label_regenerate_all_ssh_keys_desc2: "Esto puede tomar un tiempo: todas las claves SSH serán eliminadas y añadidas de nuevo a Gitolite una por una." - label_regenerate_all_ssh_keys: ¿Regenerar todas las claves SSH? - label_repos_current_access_patterns: Patrones de acceso a repositorio actuales - label_repository_access_not_configured: El acceso al repositorio no está configurado, por favor contacte con su administrador. - label_repository_access_url: Enlaces de acceso al repositorio - label_repository_default_branch: Rama por defecto del repositorio - label_repository_enabled_capabilities: Características del repositorio activas - label_repository_exists_in_gitolite: El repositorio existe en Gitolite - label_repository_mirrors: Réplicas del repositorio - label_repository_options: Opciones del repositorio - label_repository_statistics_commits: Estadísticas de commits - label_repository_statistics_contributors: Estadísticas de contribuidores - label_repository_statistics_global: Estadísticas globales - label_resync_all_projects: ¿Resincronizar todos los proyectos? - label_resync_all_ssh_keys: ¿Resincronizar todas las claves SSH? - label_see_other_repositories: Ver otros repositorios - label_select_all: Seleccionar todo - label_smart_http: HTTP inteligente - label_sort_urls: (Ordenar URLs) - label_split_payloads: dividir payloads - label_ssh_access: Acceso SSH - label_ssh_keys_current_access_patterns: Patrones de acceso de las claves SSH - label_ssh_server_domain: Dominio del servidor SSH - label_storage_directory: Directorio - label_sudo_gitolite_to_redmine_user: ¿Puede el usuario de Git hacer sudo al usuario de Redmine? - label_sudo_redmine_to_gitolite_user: ¿Puede el usuario de Redmine hacer sudo al usuario de Git? - label_tab_access: Acceso - label_tab_cache: Caché - label_tab_config_file: Fichero de configuración - label_tab_config_test: Test de configuración - label_tab_gitolite_recycle_bin: Papelera de reciclaje - label_tab_gitolite_rescue: Rescate - label_tab_global: Global - label_tab_hooks: Hooks - label_tab_notify: Notificaciones - label_tab_redmine: Redmine - label_tab_sidekiq_interface: Sidekiq - label_tab_ssh: SSH - label_tab_storage: Almacenamiento - label_temp_dir_writeable: ¿Se puede escribir en la carpeta temporal? - label_this_urls_has_permissions: "Esta URL tiene acceso ." - label_total_commits: Commits totales - label_total_contributors: Contribuidores totales - label_triggers: Triggers - label_unique_repo_identifier: ¿Los identificadores del repositorio son únicos a nivel global? - label_unknown_gitolite_version: Versión desconocida - label_use_triggers: Usar triggers - label_user_key: Clave de usuario - label_user_list: Usuarios autorizados - label_warn: Alerta - notice_deployment_credential_create_failed: No ha sido posible crear la credencial de despliegue - notice_deployment_credential_created: La credencial de despliegue se ha creado correctamente. - notice_deployment_credential_deleted_with_key: La credencial y la clave de despliegue se han borrado correctamente. - notice_deployment_credential_deleted: La credencial de despliegue se ha borrado correctamente. - notice_deployment_credential_update_failed: No ha sido posible actualizar la credencial de despliegue - notice_deployment_credential_updated: La credencial de despliegue se ha actualizado correctamente. - notice_empty_repository: El repositorio está vacío. Empieze a usarlo siguiendo las instrucciones a continuación. - notice_git_config_key_create_failed: No ha sido posible crear la clave de configuración de Git - notice_git_config_key_created: La clave de configuración de Git se ha creado correctamente. - notice_git_config_key_deleted: La clave de configuración de Git se ha borrado correctamente. - notice_git_config_key_update_failed: No ha sido posible actualizar la clave de configuración de Git - notice_git_config_key_updated: La clave de configuración de Git se ha actualizado correctamente. - notice_gitolite_extra_update_failed: Ha habido un error al actualizar las opciones - notice_gitolite_extra_updated: Las opciones se han actualizado correctamente - notice_mirror_create_failed: No ha sido posible crear la réplica. - notice_mirror_created: La réplica se ha creado correctamente. - notice_mirror_deleted: La réplica se ha borrado correctamente. - notice_mirror_update_failed: No ha sido posible actualizar la réplica. - notice_mirror_updated: La réplica se ha actualizado correctamente. - notice_post_receive_url_create_failed: No ha sido posible crear la URL de post-recepción. - notice_post_receive_url_created: La URL de post-recepción se ha creado correctamente. - notice_post_receive_url_deleted: La URL de post-recepción se ha borrado correctamente. - notice_post_receive_url_update_failed: No ha sido posible actualizar la URL de post-recepción. - notice_post_receive_url_updated: La URL de post-recepción se ha actualizado correctamente. - notice_protected_branch_create_failed: No ha sido posible crear la rama protegida - notice_protected_branch_created: La rama protegida se ha creado correctamente. - notice_protected_branch_deleted: La rama protegida se ha borrado correctamente. - notice_protected_branch_update_failed: No ha sido posible actualizar la rama protegida - notice_protected_branch_updated: La rama protegida se ha actualizado correctamente. - notice_public_key_created: La clave pública %{title} se ha creado correctamente. - notice_public_key_deleted: La clave pública %{title} se ha borrado correctamente. - notice_public_key_updated: La clave pública %{title} se ha actualizado correctamente. - permission_add_repository_xitolite_watchers: Añadir watchers - permission_create_gitolite_ssh_key: Crear claves SSH - permission_create_repository_deployment_credentials: Crear claves de despliegue - permission_create_repository_git_config_keys: Crear claves de configuración de Git - permission_create_repository_mirrors: Crear réplicas de repositorios - permission_create_repository_post_receive_urls: Crear URLs de post-recepción - permission_create_repository_protected_branches: Crear ramas protegidas - permission_delete_repository_xitolite_watchers: Borrar watchers - permission_download_git_revision: Descargar el archivo de revisiones de Git - permission_edit_repository_deployment_credentials: Editar las claves de despliegue - permission_edit_repository_git_config_keys: Editar las claves de configuración de Git - permission_edit_repository_mirrors: Editar réplicas de repositorios - permission_edit_repository_post_receive_urls: Editar las URLs de post-recepción - permission_edit_repository_protected_branches: Editar las ramas protegidas - permission_push_repository_mirrors: Enviar cambios a réplicas de repositorios - permission_view_repository_deployment_credentials: Ver las claves de despliegue - permission_view_repository_git_config_keys: Ver las claves de configuración de Git - permission_view_repository_mirrors: Ver las réplicas de repositorios - permission_view_repository_post_receive_urls: Ver las URLs de post-recepción - permission_view_repository_protected_branches: Ver las ramas protegidas - permission_view_repository_xitolite_watchers: Ver los watchers - protected_branches_reminder: Las ramas protegidas listadas arriba no están activadas. Por favor, active las Ramas protegidas más arriba en los parámetros del repositorio. - redmine_git_hosting: Redmine Git Hosting - select_other_keys: Otras claves - text_gitolite_key_destroy_confirmation: "¿Seguro que quiere destruir esta clave: %{title}?" - text_scm_command_not_available_git_hosting: el comando SCM no está disponible. Por favor, compruebe la configuración en el panel de administración del conector Redmine Git Hosting. - label_install_hook_results: Install hook results - label_repository_url_plural: Repository URLs diff --git a/plugins/redmine_git_hosting/config/locales/fr.yml b/plugins/redmine_git_hosting/config/locales/fr.yml deleted file mode 100644 index 48b096b..0000000 --- a/plugins/redmine_git_hosting/config/locales/fr.yml +++ /dev/null @@ -1,410 +0,0 @@ -fr: - activemodel: - errors: - models: - move_repository_form: - attributes: - base: - identifier_empty: Ne peut déplacer un dépôt avec un identifiant vide - identifier_taken: Identifiant de dépôt déjà utilisé par le nouveau projet - wrong_target_project: Le projet de destination est identique au projet source - activerecord: - errors: - models: - gitolite_public_key: - attributes: - key: - corrupted: semble être corrompue. - taken_by_you: "est déjà utilisée par vous comme « %{name} »." - taken_by_other: "est déjà utilisée par l'utilisateur « %{login} » comme « %{name} »." - taken_by_someone: est déjà utilisé. Elle appartient à une autre utilisateur (demandez à vôtre administrateur pour les détails). - taken_by_gitolite_admin: est déjà utilisée comme clé d'administration Gitolite. - project: - attributes: - identifier: - invalid: identifiant invalide - taken: correspond à un identifiant de dépôt existant - repository_deployment_credential: - attributes: - base: - invalid_key: Public Key Must Be a Deployment Key - invalid_user: Credential owner cannot be different than owner of Key - repository_git_config_key: - attributes: - key: - invalid: "Mauvais format de clé (doit contenir au moin un '.')" - repository_mirror: - attributes: - base: - nothing_to_push: Must include at least one item to push - explicit_refspec: - bad_format: is badly formatted - have_null_component: cannot have null first component (will delete remote branch(es)) - repository/xitolite: - attributes: - base: - blank_default_exists: "Ne peut pas mettre le dépôt par défaut, car le dépôt par défaut courant a un identifiant vide." - invalid_options: "Vous ne pouvez pas initialiser de fichier README dans un dépot GitAnnex" - identifier: - cannot_equal_project: "ne peut pas correspondre à l'identifiant d'un projet existant" - taken: "correspond à un identifiant de dépôt existant" - invalid: invalide - cannot_change: ne peut pas changer - all_branches: "Toutes les branches" - all_references: "Toutes les références" - all_tags: "Toutes les étiquettes" - button_clone: Cloner - display_access_emphasis_html: "Dans l'exemple ci-dessus, les termes en emphase représentent des éléments qui dépendent du contexte." - display_access_flat: "Les projets parents ne sont pas inclus dans l'URL, car le dépôt est en mode Plat." - display_access_hierarchical: "Les projets parents sont inclus dans l'URL, car le dépôt est en mode Hiérarchique." - display_access_setup1_html: "Assumez que project1 est le parent de project2 et que project2 est le parent de project3." - display_access_setup2_html: "Assumez aussi que le projet project3 a 2 dépôts : le dépôt par défaut et un dépôt example." - display_access_setup3_html: "Avec la configuration courante, le projet project3 a les propriétés suivantes :" - error_download_revision_no_such_commit: "Le commit %{commit} n'a pas été trouvé" - error_project_not_found: "Aucun projet avec cet identifiant n'a été trouvé" - error_public_key_create_failed: Échec de création de clé publique. - error_public_key_update_failed: Échec de modification de clé publique. - error_repository_not_found: "Aucun dépôt avec cet identifiant n'a été trouvé" - error_xitolite_repositories_disabled: "Les dépôts Gitolite sont désactivés, ne peut créer le dépôt!" - field_key: cette clé - field_mode: Mode - field_perm: Permissions d'accès - field_split_payloads: Découper le payload global en plusieurs payloads - field_use_triggers: Utiliser les déclencheurs - label_active_for: Actif depuis - label_all_projects_use_git: Créer automatiquement un dépôt Git pour les nouveaux projets - label_average_commit_per_day: Moyenne des commits par jour - label_average_contributor_commits: Moyenne des commits par contributeur - label_backup_in_progress: Enregistrement... - label_branch_path: Chemin de la branche - label_browse_repository: Parcourir les sources - label_commit_plural: Commits - label_commits_number: Nombre de commits - label_commits_per_day: Commits par jour - label_commits_per_hour: Commits par heure - label_commits_per_weekday: Commits par jour de la semaine - label_current_deploy_keys: Clés de déploiement courantes - label_current_public_keys: Clés publiques courantes - label_current_user_keys: Clés de l'utilisateur courant - label_cut_and_paste: Copiez-collez le contenu du fichier .pub au complet. - label_debug: Débogue - label_default_domain_name: Nom de domaine par défaut - label_default_gitolite_hooks_url: URL par défaut - label_default_repository: Dépôt par défaut - label_delete_from_recyle_bin: Supprimer de la corbeille - label_delete_git_repositories: Effacer les dépôts Git d'un projet quand celui-ci est effacé? - info_delete_git_repositories: (seront mis dans la corbeille) - label_delete_in_progress: Effacement... - label_delete_warning: Attention! La suppression est définitive! - label_deploy_key: Clé de déploiement - label_deployment_credential_add: Ajouter une pièce d'identité de déploiement - label_deployment_credential_create_key_first: Aucune clé de déploiement n'a été détectée. Vous devriez commencer par en créer une. - label_deployment_credential_create: Créer une nouvelle pièce d'identité de déploiement - label_deployment_credential_delete_when_unused: Effacer la clé quand elle n'est plus utilisée - label_deployment_credential_delete: Supprimer la pièce d'identité de déploiement - label_deployment_credential_edit: Modifier la pièce d'identité de déploiement - label_deployment_credential_honored: Honorée? - label_deployment_credential_owner: Propriétaire - label_deployment_credential_public_key_file: Fichier de la clé publique - label_deployment_credential_public_key_name: Nom de la clé publique - label_deployment_credential_select_deploy_key: Sélectionnez une clé de déploiement - label_deployment_credentials: Pièces d'identités de déploiement - label_download_and_install_git: Téléchargez et installez Git - label_download_format: Télécharger au format - label_download_select_format: Sélectionnez un format - label_empty_get: "GET vide" - label_empty_recycle_bin: Vider la corbeille - label_empty_repository: Dépot vide? - label_enable_git_daemon: Activer le daemon Git - label_enable_git_notify: Activer la liste de diffusion - label_enable_go_url: Activer l'url Go - label_enable_protected_branches: Activer les branches protégées - label_enable_public_repo: Rendre le dépôt public - label_enable_smart_http: Activer SmartHTTP - label_enable_smart_https: Activer SmartHTTPS - label_enable_ssh_url: Afficher l'url SSH - label_error: Erreur - label_etcetera: etc - label_example_repository: Dépôt example - label_first_commit_date: Date du premier commit - label_flat: Plat - label_flush_cache: Vider le cache Git - label_git_annex: GitAnnex - label_git_config_email_desc: Sera utilisé comme email de l'auteur dans les commits - label_git_config_email: Email de l'auteur Git - label_git_config_key_add: Ajouter une clé de configuration Git - label_git_config_key_create: Créer une clé de configuration Git - label_git_config_key_delete: Supprimer la clé de configuration Git - label_git_config_key_edit: Modifier une clé de configuration Git - label_git_config_keys: Clés de configuration Git - label_git_config_username_desc: Sera utilisé comme nom de l'auteur dans les commits - label_git_config_username: Nom de l'auteur Git - label_git_daemon: Daemon Git - label_git_key_type_config: Clé de configuration Git - label_git_key_type_option: Option de configuration Gitolite - label_git_notification_prefix: Préfixe de la liste de diffusion - label_git_notification_sender: "Adresse de l'expéditeur de la liste de diffusion" - label_git_notify: Notifications Git - label_git_objects_count: Nombre d'objets dans Git - label_git_option_key_add: Ajouter une option de configuration Gitolite - label_git_option_keys: Options de configuration Gitolite - label_git_version: Version de Git - label_github_post: "POST GitHub" - label_gitolite_access_config: Configuration des accès Gitolite - label_gitolite_banner: Gitolite banner - label_gitolite_bin_dir: Répertoire des binaires Gitolite - label_gitolite_cache_adapter_desc: (Vous devrez redémarrer Redmine pour que le changement soit pris en compte) - label_gitolite_cache_adapter: Cache Adapter - label_gitolite_cache_config: Configuration du cache de Gitolite - label_gitolite_cache_max_elements: Nombre maximal d'éléments dans le cache - label_gitolite_cache_max_size: Taille maximale d'un élément du cache - label_gitolite_cache_max_time: Temps maximal du cache - label_gitolite_config_file: Fichier de configuration de Gitolite - label_gitolite_daemon_by_default: Activer le daemon Git pour les nouveaux dépôts par défaut - label_gitolite_documentation: Documentation Gitolite - label_gitolite_download_revision_enabled: Activer le téléchargement des révisions Git - label_gitolite_global_config: Configuration globale du plugin - label_gitolite_global_storage_dir_desc: Relatif au répertoire personnel de l'utilisateur Gitolite - label_gitolite_global_storage_dir: Chemin de base des dépôts Gitolite - label_gitolite_hook_dirs_installed: Répertoires des hooks installés? - label_gitolite_hook_untouched: hook non mis à jour - label_gitolite_hooks_are_asynchronous: Lancer les hooks de manière asynchrone - label_gitolite_hooks_config: Configuration des hooks de Gitolite - label_gitolite_hooks_debug: Lancer les hooks en mode debug - label_gitolite_hooks_installed: Hooks installés? - label_gitolite_hooks_namespace: Espace de nom Git des hooks - label_gitolite_hooks_params_installed: Paramètres des hooks installés? - label_gitolite_hooks_url: URL des hooks - label_gitolite_http_by_default: Activer le mode Smart HTTP pour les nouveaux dépôts par défaut - label_gitolite_identifier_prefix_desc: Sera utilisé pour générer les identifiants de clé SSH - label_gitolite_identifier_prefix: Préfixe Gitolite - label_gitolite_identifier_strip_user_id_desc: Vous devrez redémarrer Redmine pour que le changement soit pris en compte - label_gitolite_identifier_strip_user_id: Supprimer l'ID de l'utilisateur de l'identifiant Gitolite - label_gitolite_lib_dir: Répertoire des librairies Gitolite - label_gitolite_libgit2_version: Version de libgit2 - label_gitolite_local_code_dir: Répertoire de stockage des hooks non-core - label_gitolite_log_level_desc: Vous devrez redémarrer Redmine pour que le changement soit pris en compte - label_gitolite_log_level: Niveau de journalisation - label_gitolite_mailer_params_installed: Paramètres des notifications installés? - label_gitolite_notify_by_default: Activer le hook « Notifications Git » pour les nouveaux dépôts par défaut - label_gitolite_notify_config: Configuration des listes de diffusions de Git - label_gitolite_notify_global_exclude: Liste d'exclusion globale des notifications - label_gitolite_notify_global_include: Liste d'inclusion globale des notifications - label_gitolite_notify_global_prefix: Préfixe global des notifications - label_gitolite_notify_global_sender_address: Adresse de l'expéditeur des notifications - label_gitolite_overwrite_existing_hooks: Ecraser les hooks existants - label_gitolite_recycle_bin_dir_desc: Relatif au répertoire personnel de l'utilisateur Gitolite - label_gitolite_recycle_bin_dir: Chemin de la corbeille Gitolite - label_gitolite_recycle_bin_expiration_time_desc: En heures - label_gitolite_recycle_bin_expiration_time: Temps d'expiration pour les dépôts dans la corbeille - label_gitolite_redmine_storage_dir_desc: Relatif au répertoire personnel de l'utilisateur Gitolite - label_gitolite_redmine_storage_dir: Sous-répertoire pour les dépôts gérés par Redmine - label_gitolite_repository_count: Nombre de dépôts physiques dans Gitolite - label_gitolite_rescue: Sauvetage de Gitolite - label_gitolite_rugged_features: Fonctionnalités compilées dans Rugged - label_gitolite_server_host: Adresse du serveur SSH/Gitolite - label_gitolite_server_port: Port du serveur SSH/Gitolite - label_gitolite_ssh_config: Configuration SSH de Gitolite - label_gitolite_ssh_private_key: Clé privée SSH de Gitolite - label_gitolite_ssh_public_key: Clé publique SSH de Gitolite - label_gitolite_storage_config: Configuration du stockage dans Gitolite - label_gitolite_temp_dir_desc: Doit être absolu - label_gitolite_temp_dir: Répertoire temporaire pour les fichiers de verrouillage et les données - label_gitolite_use_sidekiq: Utiliser Sidekiq pour lancer les taches en mode asynchrone - label_gitolite_user: Nom d'utilisateur Gitolite - label_gitolite_version: Version de Gitolite - label_help_git_setup: Configuration de Git - label_help_no_repo_rights: "Désolé, vous n'avez pas accès à ce dépôt. Vous ne pouvez rien faire." - label_help_repository_clone: Cloner un dépôt - label_help_repository_setup_existing: Configurer un dépôt existant - label_help_repository_setup_new: Configurer un nouveau dépôt - label_hierarchical_organisation: Structure des répertoires et des URL pour les dépôts gérés par Redmine - label_hierarchical: Hiérarchique - label_http_access: Accès HTTP - label_http_only: HTTP seulement - label_http_server_domain: Nom de domaine du serveur HTTP - label_http_server_subdir_desc: Relatif à la racine de Redmine - label_http_server_subdir: Sous-répertoire pour l'accès HTTP - label_https_access: Accès HTTPS - label_https_and_http: HTTPS et HTTP - label_https_only: HTTPS seulement - label_https_server_domain_desc: Laissez vide si vous n'utilisez pas HTTPS - label_https_server_domain: Nom de domaine du serveur HTTPS - label_identifier_can_be_arbitrary_desc: (Peut être significative) - label_identifier_can_be_arbitrary: Identifiant - label_identifier_cannot_be_changed: Identifiant
(Ne peut pas être changé) - label_info: Info - label_init_repo_with_git_annex: Initialiser le dépôt avec GitAnnex - label_init_repo_with_readme: Initialiser le dépôt avec un fichier README - label_init_repositories_on_create: Initialiser automatiquement les dépôts Git avec un fichier README (à la Github) - label_install_gitolite_hooks: Installer les hooks ! - label_key_cannot_be_changed_please_create_new_key: La clé ne peut plus être modifiée. Vous pouvez l'effacer et en créer une nouvelle. - label_key_type: Type de clé publique - label_key: Clé - label_latest_commit_date: Date du dernier commit - label_main_git_repository: Dépôt Git Principal - label_mirror_add: Ajouter un miroir de dépôt - label_mirror_create: Créer un miroir de dépôt - label_mirror_delete: Supprimer un miroir de dépôt - label_mirror_edit: Modifier un miroir de dépôt - label_mirror_explicit_refspec: Spécification de références explicites - label_mirror_fast_forward: Avance rapide (non forcé) - label_mirror_forced_update: Forcer la mise à jour du miroir - label_mirror_full_mirror: Miroir complet - label_mirror_help: Le miroir doit donner les droits d'écriture à la clé publique suivante - label_mirror_include_all_branches: Envoyer toutes les branches - label_mirror_include_all_tags: Envoyer toutes les étiquettes - label_mirror_push_fail: Échec - label_mirror_push_info_html: "Envoi des changements au miroir %{mirror_url} : %{status}" - label_mirror_push_mode: Mode de mise à jour du miroir - label_mirror_push_output: Sortie - label_mirror_push_sucess: Succès - label_mirror_push_title: Envoyer au miroir - label_mirror_push: Envoyer - label_mirror_refspec: Refspec - label_mirror_url_accepted_format: Formats d'URL acceptés - label_mirror: Miroir - label_mirroring_keys_installed: Clés de miroir installées? - label_mode: Mode - label_move_repository: "Déplacement du dépôt: '%{repo_name}'" - label_my_public_keys: Mes clés publiques - label_need_help: Besoin d'aide? - label_no_public_keys: Aucune clé publique définie - label_open_issue: Ouvrir une demande - label_path_directories: Répertoires du PATH - label_permissions_header: Permissions requises - label_post_receive_url_add: Ajouter une URL après réception - label_post_receive_url_create: Créer une URL après réception - label_post_receive_url_delete: Supprimer l'URL après réception - label_post_receive_url_edit: Modifier l'URL après réception - label_post_receive_urls: URL après réception - label_protected_branch_add: Ajouter une branche protégée - label_protected_branch_create: Créer une branche protégée - label_protected_branch_delete: Supprimer la branche protégée - label_protected_branch_edit: Modifier une branche protégée - label_protected_branch: Branches Protégées - label_protected_branches: Branches protégées - label_public_key_edit: Modifier une clé publique existante - label_public_key_new: Entrez une nouvelle clé publique - label_public_key: Clé publique - label_public_keys: Clés publiques - label_public_repo: Dépôt public - label_read_only_permission: RO - label_read_write_permission: RW - label_recycle_bin_content_size: Taille - label_redmine_config: Configuration de Redmine - label_redmine_git_hosting_issue: Redmine Git Hosting - Ouvrir une demande - label_redmine_git_hosting_wiki: Redmine Git Hosting - Wiki - label_redmine_has_rw_access_on_all_repos: Redmine a accès en lecture/écriture à tous les dépôts Gitolite - label_redmine_user: Nom d'utilisateur Redmine - label_regenerate_all_ssh_keys_desc: "Permet de regénérer l'identifiant des clés SSH." - label_regenerate_all_ssh_keys_desc2: "Peut être assez long : les clés seront supprimées et ajoutés dans Gitolite une par une." - label_regenerate_all_ssh_keys: Regénérer toutes les clés SSH dans Gitolite - label_repos_current_access_patterns: Modèles d'accès courant pour les dépôts - label_repository_access_not_configured: Les accès au dépôt n'ont pas été configurés, veuillez contacter vôtre administrateur. - label_repository_access_url: URL d'accès au dépôt - label_repository_default_branch: Branche par défaut - label_repository_enabled_capabilities: Fonctionnalité activées du dépôt - label_repository_exists_in_gitolite: Le dépôt existe dans Gitolite - label_repository_mirrors: Miroirs du dépôt - label_repository_options: Options du dépôt - label_repository_statistics_commits: Statistiques des commits - label_repository_statistics_contributors: Statistiques des contributeurs - label_repository_statistics_global: Statistiques globales - label_resync_all_projects: Resynchroniser tous les projets - label_resync_all_ssh_keys: Resynchroniser toutes les clés SSH - label_see_other_repositories: Voir les autres dépôts - label_select_all: Tout sélectionner - label_smart_http: Smart HTTP - label_sort_urls: (Trier les urls) - label_split_payloads: split payloads - label_ssh_access: Accès SSH - label_ssh_keys_current_access_patterns: Modèles d'accès courant pour les clés SSH - label_ssh_server_domain: Nom de domaine du serveur SSH - label_storage_directory: Répertoire de stockage - label_sudo_gitolite_to_redmine_user: L'utilisateur Git peut sudo vers l'utilisateur Redmine? - label_sudo_redmine_to_gitolite_user: L'utilisateur Redmine peut sudo vers l'utilisateur Git? - label_tab_access: Accès - label_tab_cache: Cache - label_tab_config_file: Fichier de configuration - label_tab_config_test: Test de la Configuration - label_tab_gitolite_recycle_bin: Corbeille - label_tab_gitolite_rescue: Sauvetage - label_tab_global: Global - label_tab_hooks: Hooks - label_tab_notify: Notifications - label_tab_redmine: Redmine - label_tab_sidekiq_interface: Sidekiq - label_tab_ssh: SSH - label_tab_storage: Stockage - label_temp_dir_writeable: Le répertoire temporaire est accessible en écriture? - label_this_urls_has_permissions: "Cette URL est accessilbe en ." - label_total_commits: Nombre total de commits - label_total_contributors: Nombre total de contributeurs - label_triggers: Déclencheurs - label_unique_repo_identifier: Les identifiants de dépôts sont unique - label_unknown_gitolite_version: Version inconnue - label_use_triggers: Utilise les déclencheurs - label_user_key: Clé utilisateur - label_user_list: Liste des utilisateurs autorisés - label_warn: Avertissement - notice_deployment_credential_create_failed: Échec de création de la pièce d'identité de déploiement - notice_deployment_credential_created: La pièce d'identité de déploiement a été créée avec succès. - notice_deployment_credential_deleted_with_key: La pièce d'identité de déploiement et la clé associée ont été supprimées avec succès. - notice_deployment_credential_deleted: La pièce d'identité de déploiement a été supprimée avec succès. - notice_deployment_credential_update_failed: Échec de modification de la pièce d'identité de déploiement - notice_deployment_credential_updated: La pièce d'identité de déploiement a été modifiée avec succès. - notice_empty_repository: Le dépôt est vide. Commencez en suivant les instructions ci-dessous. - notice_git_config_key_create_failed: Échec de création de la clé de configuration Git - notice_git_config_key_created: Clé de configuration Git créée avec succès - notice_git_config_key_deleted: Clé de configuration Git supprimée avec succès - notice_git_config_key_update_failed: Échec de modification de la clé de configuration Git - notice_git_config_key_updated: Clé de configuration Git modifiée avec succès - notice_gitolite_extra_update_failed: Erreurs lors de la mise à jour des options - notice_gitolite_extra_updated: Options mises à jour avec succès - notice_mirror_create_failed: Échec de création du miroir. - notice_mirror_created: Miroir crée avec succès. - notice_mirror_deleted: Miroir supprimé avec succès. - notice_mirror_update_failed: Échec de modification du miroir. - notice_mirror_updated: Miroir modifié avec succès. - notice_post_receive_url_create_failed: Échec de création de l'URL après réception. - notice_post_receive_url_created: L'URL après réception a été créé avec succès. - notice_post_receive_url_deleted: L'URL après réception a été supprimée avec succès. - notice_post_receive_url_update_failed: Échec de modification de l'URL après réception. - notice_post_receive_url_updated: L'URL après réception a été modifié avec succès. - notice_protected_branch_create_failed: Échec de création de la branche protégée - notice_protected_branch_created: Branche protégée créée avec succès - notice_protected_branch_deleted: Branche protégée supprimée avec succès - notice_protected_branch_update_failed: Échec de modification de la branche protégée - notice_protected_branch_updated: Branche protégée modifiée avec succès - notice_public_key_created: Clé publique %{title} a été créée avec succès. - notice_public_key_deleted: Clé publique %{title} a été effacée avec succès. - notice_public_key_updated: Clé publique %{title} a été modifiée avec succès. - permission_add_repository_xitolite_watchers: Ajouter des observateurs - permission_create_gitolite_ssh_key: Créer des clés SSH - permission_create_repository_deployment_credentials: Créer des clés de déploiement - permission_create_repository_git_config_keys: Créer des clés de configuration Git - permission_create_repository_mirrors: Créer des miroirs de dépôts - permission_create_repository_post_receive_urls: Créer des URL après réception - permission_create_repository_protected_branches: Créer des branches protégées - permission_delete_repository_xitolite_watchers: Supprimer des observateurs - permission_download_git_revision: Télécharger les révisions Git sous forme d'archive - permission_edit_repository_deployment_credentials: Modifier des clés de déploiement - permission_edit_repository_git_config_keys: Modifier des clés de configuration Git - permission_edit_repository_mirrors: Modifier des miroirs de dépôts - permission_edit_repository_post_receive_urls: Modifier les URL après réception - permission_edit_repository_protected_branches: Modifier des branches protégées - permission_push_repository_mirrors: Pousser des modifications vers des miroirs de dépôts - permission_view_repository_deployment_credentials: Voir des clés de déploiement - permission_view_repository_git_config_keys: Voir des clés de configuration Git - permission_view_repository_mirrors: Voir des miroirs de dépôts - permission_view_repository_post_receive_urls: Voir les URL après réception - permission_view_repository_protected_branches: Voir des branches protégées - permission_view_repository_xitolite_watchers: Voir la liste des observateurs - protected_branches_reminder: Les branches protégées ci-dessus ne sont pas actives. Pour les activer veuillez d'abord cocher la case "Activer les branches protégées" dans les paramètres du dépôt ci-dessus. - redmine_git_hosting: Redmine Git Hosting - select_other_keys: Autres clés - text_gitolite_key_destroy_confirmation: "Êtes-vous sûr de vouloir détruire cette clé : %{title} ?" - text_scm_command_not_available_git_hosting: Ce SCM n'est pas disponible. Vérifier les paramètres dans la section administration du plugin Redmine Git Hosting. - label_install_hook_results: Install hook results - label_repository_url_plural: Repository URLs diff --git a/plugins/redmine_git_hosting/config/locales/ja.yml b/plugins/redmine_git_hosting/config/locales/ja.yml deleted file mode 100644 index f4d1484..0000000 --- a/plugins/redmine_git_hosting/config/locales/ja.yml +++ /dev/null @@ -1,423 +0,0 @@ -ja: - activemodel: - errors: - models: - move_repository_form: - attributes: - base: - identifier_empty: 空タイトルのリポジトリは移動できません - identifier_taken: 指定したリポジトリのタイトルは既に他のプロジェクトに使用されています - wrong_target_project: 移動先と移動元のプロジェクトは同じです - activerecord: - errors: - models: - gitolite_public_key: - attributes: - key: - corrupted: は破損したようです。 - taken_by_you: 'はあなた("%{name}")により既に使用されています。' - taken_by_other: 'は他のユーザー("%{login}" - "%{name}")により既に使用されています。' - taken_by_someone: 'は既に使用されています。詳細はシステム管理者に連絡してください。' - taken_by_gitolite_admin: 'はGitoliteの管理キーとして既に使用されています。' - project: - attributes: - identifier: - invalid: タイトルは不正です - taken: タイトルは既に存在しています - repository_deployment_credential: - attributes: - base: - invalid_key: パプリックキーはデプロイキーでなければなりません - invalid_user: クレデンシャルの所有者はキーの所有者でなければなりません - repository_git_config_key: - attributes: - key: - invalid: "キーの形式は不正です (ドット「.」が含まれる必要があります)" - repository_mirror: - attributes: - base: - nothing_to_push: プッシュするためのアイテムを少なくとも1つが必要です - explicit_refspec: - bad_format: は不正な形式です - have_null_component: cannot have null first component (will delete remote branch(es)) - repository/xitolite: - attributes: - base: - blank_default_exists: "空リポジトリが既に存在しているためリポジトリは作成できません。" - invalid_options: "GitAnnexによりREADMEファイルありのリポジトリは作成できません。" - identifier: - cannot_equal_project: "既存プロジェクトのIDは使用できません。" - taken: "は既に使用されています。" - invalid: 不正 - cannot_change: 編集不可 - all_branches: 全ブランチ - all_references: 全参照 - all_tags: 全タグ - button_clone: クローン - display_access_emphasis_html: "上記の記載では, 斜体部分は要素依存部分を表しています。" - display_access_flat: "フラットモードのため、親ディレクトリはURLに含まれていません。" - display_access_hierarchical: "階層モードのため、親ディレクトリもURLに含まれています。" - display_access_setup1_html: "project1project2の親、なおproject2project3の親とします。" - display_access_setup2_html: "それにproject3は次の2つのリポジトリを持っているとします:defaultexample。" - display_access_setup3_html: "現在の設定により、プロジェクトproject3のパス構造は次のようになります。" - error_download_revision_no_such_commit: "コミット%{commit}が存在しません" - error_project_not_found: "このタイトルのプロジェクトが見つかりません。" - error_public_key_create_failed: パプリックキー作成エラー - error_public_key_update_failed: パプリックキー編集エラー - error_repository_not_found: "このタイトルのリポジトリが見つかりません。" - error_xitolite_repositories_disabled: "Gitoliteは無効になっています。リポジトリを作成できません。" - field_key: this key - field_mode: モード - field_perm: アクセス権限 - field_split_payloads: グローバルペイロードを複数ペイロードに分割する - field_use_triggers: 使用トリガー - git_notifications_reminder: 上記のメールリストは有効化されていません。上記のリポジトリの設定で有効化を行ってください。 - label_active_for: 活動経過日数 - label_all_projects_use_git: 新プロジェクト作成時にGitリポジトリを自動作成する? - label_average_commit_per_day: 1日あたりの平均コミット数 - label_average_contributor_commits: 開発者あたりの平均コミット数 - label_backup_in_progress: 保存中... - label_branch_path: ブランチパス - label_browse_repository: リポジトリ閲覧 - label_commit_plural: コミット - label_commits_number: コミット数 - label_commits_per_day: 日別のコミット - label_commits_per_hour: 時間別のコミット - label_commits_per_weekday: 曜日別のコミット - label_current_deploy_keys: 現在のデプロイキー - label_current_public_keys: 現在のパプリックキー - label_current_user_keys: 現在のユーザーキー - label_cut_and_paste: パプリックキー(通常は.pubの拡張子のファイル)の内容を上記に貼り付けてください。 - label_debug: Debug - label_default_domain_name: 既定ドメイン名 - label_default_gitolite_hooks_url: 既定URL - label_default_repository: defaultリポジトリ - label_delete_from_recyle_bin: ゴミ箱から削除 - label_delete_git_repositories: プロジェクト削除時にGitリポジトリを削除する? - info_delete_git_repositories: (ゴミ箱に移動します) - label_delete_in_progress: 削除中... - label_delete_warning: 注意!完全に削除してもいいですか? - label_deploy_key: デプロイキー - label_deployment_credential_add: デプロイクレデンシャル情報の追加 - label_deployment_credential_create_key_first: デプロイキーが見つかりません。新しいデプロイキーを作成してください。 - label_deployment_credential_create: デプロイクレデンシャル情報の作成 - label_deployment_credential_delete_when_unused: 使用しないキーを削除する? - label_deployment_credential_delete: デプロイクレデンシャル情報の作成 - label_deployment_credential_edit: デプロイクレデンシャル情報の編集 - label_deployment_credential_honored: Honored? - label_deployment_credential_owner: 所有者 - label_deployment_credential_public_key_file: パプリックキーファイル - label_deployment_credential_public_key_name: パプリックキー名 - label_deployment_credential_select_deploy_key: デプロイキーの選択 - label_deployment_credentials: デプロイクレデンシャル - label_download_and_install_git: Gitのダウンロードとインストール - label_download_format: ダウンロード - label_download_select_format: タイプ選択 - label_empty_get: Empty GET - label_empty_recycle_bin: ゴミ箱を空にする - label_empty_repository: 空リポジトリ? - label_enable_git_daemon: Git Daemon有効化 - label_enable_git_notify: メールリスト有効化 - label_enable_protected_branches: ブランチ保護有効化 - label_enable_public_repo: リポジトリを公開する - label_enable_smart_http: Smart HTTPモード - label_error: Error - label_etcetera: etc - label_example_repository: exampleリポジトリ - label_first_commit_date: 最初コミット日 - label_flat: フラット - label_flush_cache: Gitキャッシュをフラッシュする? - label_git_annex: GitAnnex - label_git_config_email_desc: コミットの作者メールアドレスに使用します - label_git_config_email: Git作者メール - label_git_config_key_add: Git設定キー追加 - label_git_config_key_create: 新しいGit設定キー作成 - label_git_config_key_delete: Git設定キー削除 - label_git_config_key_edit: Git設定キー修正 - label_git_config_keys: Git設定キー - label_git_config_username_desc: コミットの作者名に使用します - label_git_config_username: Git作者名 - label_git_daemon: Git Daemon - label_git_key_type_config: Git設定キー - label_git_key_type_option: Gitoliteオプション - label_git_notification_default_list: 既定トリスト - label_git_notification_effective_list: 効果リスト - label_git_notification_exclude_list: 除外リスト - label_git_notification_include_list: 包含リスト - label_git_notifications_add: メールリスト追加 - label_git_notifications_create: メールリスト作成 - label_git_notifications_delete: メールリスト削除 - label_git_notifications_edit: メールリスト編集 - label_git_notifications: メールリスト - label_git_notify: Git通知 - label_git_objects_count: Gitオブジェクト数 - label_git_option_key_add: Gitoliteオプション追加 - label_git_option_keys: Gitolite設定オプション - label_git_version: Gitバージョン - label_github_post: GitHub POST - label_gitolite_access_config: Gitoliteアクセス設定 - label_gitolite_banner: Gitoliteバーナー - label_gitolite_bin_dir: Gitolite実行ディレクトリ - label_gitolite_cache_adapter_desc: 有効にするにはRedmineの再起動が必要です - label_gitolite_cache_adapter: キャッシュアダプター - label_gitolite_cache_config: Gitoliteキャッシュ設定 - label_gitolite_cache_max_elements: 最大キャッシュ要素数 - label_gitolite_cache_max_size: 最大キャッシュ要素サイズ - label_gitolite_cache_max_time: 最大キャッシュ時間 - label_gitolite_config_file: Gitolite設定ファイル - label_gitolite_daemon_by_default: 新リポジトリ作成時にGit Daemonモードをデフォルトに有効化? - label_gitolite_documentation: Gitoliteドキュメント - label_gitolite_download_revision_enabled: Gitリビジョンダウンロードを有効化 - label_gitolite_global_config: Gitolite全般設定 - label_gitolite_global_storage_dir_desc: Gitoliteユーザーホームに対する相対パス - label_gitolite_global_storage_dir: Gitoliteリポジトリのバースパス - label_gitolite_hook_dirs_installed: フックディレクトリインストール済み? - label_gitolite_hook_untouched: フックアクセス不可 - label_gitolite_hooks_are_asynchronous: フックを非同期実行 - label_gitolite_hooks_config: Gitoliteフック設定 - label_gitolite_hooks_debug: フックのデバグモード有効化 - label_gitolite_hooks_installed: フックインストール済み? - label_gitolite_hooks_namespace: フックGit名前空間 - label_gitolite_hooks_params_installed: フックパラメータインストール済み? - label_gitolite_hooks_url: フックURL - label_gitolite_http_by_default: 新リポジトリ作成時にSmart HTTPモードをデフォルトに有効化? - label_gitolite_identifier_prefix_desc: SSHキータイトルの生成に使用します - label_gitolite_identifier_prefix: Gitolite接頭辞 - label_gitolite_identifier_strip_user_id_desc: 有効にするにはRedmineの再起動が必要です - label_gitolite_identifier_strip_user_id: GitoliteタイトルからユーザーIDを除外する - label_gitolite_lib_dir: Gitoliteライブラリディレクトリ - label_gitolite_libgit2_version: libgit2バージョン - label_gitolite_local_code_dir: Gitoliteでないフックディレクトリ - label_gitolite_log_level_desc: 有効にするにはRedmineの再起動が必要です - label_gitolite_log_level: Gitoliteログレベル - label_gitolite_mailer_params_installed: メーラーパラメータインストール済み? - label_gitolite_notify_by_default: 新リポジトリ作成時にGit通知をデフォルトに有効化? - label_gitolite_notify_config: Gitメールリスト設定 - label_gitolite_notify_global_exclude: Gitメールリストのグローバル除外リスト - label_gitolite_notify_global_include: Gitメールリストのグローバル包含リスト - label_gitolite_notify_global_prefix: Gitメールリストのグローバル接頭辞 - label_gitolite_notify_global_sender_address: Gitメールリストのグローバル宛先 - label_gitolite_notify_prefix: メールリスト接頭辞 - label_gitolite_notify_sender_address: メールリスト宛先 - label_gitolite_overwrite_existing_hooks: 既存のフックを上書き - label_gitolite_recycle_bin_dir_desc: Gitoliteユーザーホームに対する相対パス - label_gitolite_recycle_bin_dir: Gitoliteゴミ箱のベースパス - label_gitolite_recycle_bin_expiration_time_desc: 時 - label_gitolite_recycle_bin_expiration_time: ゴミ箱内のリポジトリの有効期間 - label_gitolite_redmine_storage_dir_desc: Gitoliteリポジトリのベースパスに対する相対パス - label_gitolite_redmine_storage_dir: Redmine管理上のリポジトリのサブディレクトリ - label_gitolite_repository_count: Gitolite上の物理的なリポジトリ数 - label_gitolite_rescue: Gitoliteレスキュー - label_gitolite_rugged_features: Ruggedコンパイル機能 - label_gitolite_server_host: SSH/Gitoliteサーバーホスト - label_gitolite_server_port: SSH/Gitoliteサーバーポート - label_gitolite_ssh_config: Gitolite SSH設定 - label_gitolite_ssh_private_key: Gitolite SSHプライベートキー - label_gitolite_ssh_public_key: Gitolite SSHパプリックキー - label_gitolite_storage_config: Gitoliteのストレージの設定 - label_gitolite_temp_dir_desc: 絶対パス - label_gitolite_temp_dir: ロックファイルとデータ用の一時的なディレクトリ - label_gitolite_use_sidekiq: 非同期ジョブの立ち上げにSidekiqを使用する - label_gitolite_user: Gitoliteユーザー名 - label_gitolite_version: Gitoliteバージョン - label_help_git_setup: Git設定 - label_help_no_repo_rights: このリポジトリへのアクセス権限がありません。" - label_help_repository_clone: リポジトリのクローン - label_help_repository_setup_existing: 既存リポジトリの設定 - label_help_repository_setup_new: 新しいリポジトリの設定 - label_hierarchical_organisation: Redmine管理上のリポジトリのディレクトリとURLの形式 - label_hierarchical: 階層 - label_http_access: HTTPアクセス - label_http_only: HTTPのみ - label_http_server_domain: HTTPサーバードメイン - label_http_server_subdir_desc: RedmineルートURLに対する相対パス - label_http_server_subdir: HTTPアクセス用のサブディレクトリ - label_https_access: HTTPSアクセス - label_https_and_http: HTTPSおよびHTTP - label_https_only: HTTPSのみ - label_https_server_domain_desc: 使用しない場合は空にしてもいいです - label_https_server_domain: HTTPSサーバードメイン - label_identifier_can_be_arbitrary_desc: (任意文字列) - label_identifier_can_be_arbitrary: タイトル - label_identifier_cannot_be_changed: タイトル
(編集できません) - label_info: Info - label_init_repo_with_git_annex: GitAnnexによりリポジトリを作成する - label_init_repo_with_readme: READMEありのリポジトリを作成する - label_init_repositories_on_create: Gitリポジトリ作成時にREADMEを自動作成する?(Githubと同様) - label_install_gitolite_hooks: フックインストール! - label_key_cannot_be_changed_please_create_new_key: 'キーの内容は編集できません。ただしキーを削除し新しいキーを作成することはできます。' - label_key_type: パプリックキー種類 - label_key: キー - label_latest_commit_date: 最後コミット日 - label_main_git_repository: メインのGitリポジトリ - label_mirror_add: ミラーリポジトリ追加 - label_mirror_create: ミラーリポジトリ作成 - label_mirror_delete: ミラーリポジトリ削除 - label_mirror_edit: ミラーリポジトリ編集 - label_mirror_explicit_refspec: 明示参照仕様 - label_mirror_fast_forward: ファストフォワード (非強制) - label_mirror_forced_update: リモート更新強制 - label_mirror_full_mirror: 複製完了 - label_mirror_help: ミラーリポジトリに以下のパプリックキーの書き込み権限の付与が必要です - label_mirror_include_all_branches: 全ブランチプッシュ - label_mirror_include_all_tags: 全タグプッシュ - label_mirror_push_fail: エラー - label_mirror_push_info_html: "ミラーリポジトリへプッシュ中%{mirror_url}%{status}" - label_mirror_push_mode: ミラーリポジトリ編集モード - label_mirror_push_output: 出力 - label_mirror_push_sucess: 成功 - label_mirror_push_title: ミラーリポジトリへプッシュ - label_mirror_push: プッシュ - label_mirror_refspec: 参照仕様 - label_mirror_url_accepted_format: 許可されたURL形式 - label_mirror: ミラーリポジトリ - label_mirroring_keys_installed: ミラーキーインストール済み? - label_mode: モード - label_move_repository: "リポジトリを移動する:'%{repo_name}'" - label_my_public_keys: パプリックキー - label_need_help: Need Help? - label_no_public_keys: パプリックキーがまだ作成されていません - label_open_issue: Open Issue - label_path_directories: PATHディレクトリ - label_permissions_header: 必要なアクセス許可 - label_post_receive_url_add: Post Receive URL追加 - label_post_receive_url_create: Post-receive URLレポジトリ作成 - label_post_receive_url_delete: Post-receive URLレポジトリ削除 - label_post_receive_url_edit: Post-receive URLレポジトリ編集 - label_post_receive_urls: Post Receive URLs - label_protected_branch_add: 保護ブランチ追加 - label_protected_branch_create: 保護ブランチ作成 - label_protected_branch_delete: 保護ブランチ削除 - label_protected_branch_edit: 保護ブランチ編集 - label_protected_branch: 保護ブランチ - label_protected_branches: 保護ブランチ - label_public_key_edit: 現在のパプリックキーの編集 - label_public_key_new: 新パプリックキーの作成 - label_public_key: パプリックキー - label_public_keys: パプリックキー - label_public_repo: 公開リポジトリ - label_read_only_permission: RO - label_read_write_permission: RW - label_recycle_bin_content_size: サイズ - label_redmine_config: Redmine設定 - label_redmine_git_hosting_issue: Redmine Git Hosting - Open Issue - label_redmine_git_hosting_wiki: Redmine Git Hosting - Wiki - label_redmine_has_rw_access_on_all_repos: Redmineは全GitoliteリポジトリのRWアクセス権限を持っています - label_redmine_user: Redmineユーザー名 - label_regenerate_all_ssh_keys_desc: "本処理はSSHキーのタイトルを再作成します" - label_regenerate_all_ssh_keys_desc2: "時間がかかる場合があります。全SSHキーを1つずつ削除してからGitoliteに再追加します。" - label_regenerate_all_ssh_keys: 全SSHキーを再作成する? - label_repos_current_access_patterns: 現リポジトリのアクセスパターン - label_repository_access_not_configured: リポジトリのアクセスが設定されていません。システム管理者に連絡してください。 - label_repository_access_url: リポジトリアクセスリンク - label_repository_default_branch: リポジトリのデフォルトブランチ - label_repository_enabled_capabilities: リポジトリの有効化済機能 - label_repository_exists_in_gitolite: Gitoliteにリポジトリは既に存在しています - label_repository_mirrors: ミラーリポジトリ - label_repository_options: リポジトリ設定 - label_repository_statistics_commits: コミット統計 - label_repository_statistics_contributors: 開発者統計 - label_repository_statistics_global: 全体統計 - label_resync_all_projects: 全プロジェクトを再同期する? - label_resync_all_ssh_keys: 全SSHキーを再同期する? - label_see_other_repositories: 他のリポジトリの閲覧 - label_select_all: 全選択 - label_smart_http: Smart HTTP - label_sort_urls: (Urls並び替え) - label_split_payloads: ペイロード分割 - label_ssh_access: SSHアクセス - label_ssh_keys_current_access_patterns: SSHキーアクセスパターン - label_ssh_server_domain: SSHサーバードメイン - label_storage_directory: Git格納ディレクトリ - label_sudo_gitolite_to_redmine_user: GitユーザーはRedmineユーザーに対してsudo可能? - label_sudo_redmine_to_gitolite_user: RedmineユーザーはGitユーザーに対してsudo可能? - label_tab_access: アクセス - label_tab_cache: キャッシュ - label_tab_config_file: 設定ファイル - label_tab_config_test: 設定テスト - label_tab_gitolite_recycle_bin: ゴミ箱 - label_tab_gitolite_rescue: レスキュー - label_tab_global: 全般 - label_tab_hooks: フック - label_tab_notify: 通知 - label_tab_redmine: Redmine - label_tab_sidekiq_interface: Sidekiq - label_tab_ssh: SSH - label_tab_storage: ストレージ - label_temp_dir_writeable: テンプディレクトリへ書き込み可能? - label_this_urls_has_permissions: "このURLにのアクセス権限があります。" - label_total_commits: コミット数 - label_total_contributors: 開発者数 - label_triggers: トリガー - label_unique_repo_identifier: リポジトリのタイトルは全体的にユニークですか? - label_unknown_gitolite_version: バージョン不明 - label_use_triggers: 使用トリガー - label_user_key: ユーザーキー - label_user_list: 許可ユーザー - label_warn: Warning - notice_deployment_credential_create_failed: デプロイクレデンシャル情報作成エラー - notice_deployment_credential_created: デプロイクレデンシャル情報は正常に作成できました。 - notice_deployment_credential_deleted_with_key: デプロイクレデンシャル情報およびキーは正常に削除できました。 - notice_deployment_credential_deleted: デプロイクレデンシャル情報は正常に削除できました。 - notice_deployment_credential_update_failed: デプロイクレデンシャル情報編集エラー - notice_deployment_credential_updated: デプロイクレデンシャル情報は正常に編集できました。 - notice_empty_repository: 空リポジトリです。リポジトリの使用開始は以下の手順を参考してください。 - notice_git_config_key_create_failed: Git設定キー作成エラー - notice_git_config_key_created: Git設定キーは正常に作成できました。 - notice_git_config_key_deleted: Git設定キーは正常に削除できました。 - notice_git_config_key_update_failed: Git設定キー編集エラー - notice_git_config_key_updated: Git設定キーは正常に編集できました。 - notice_git_notifications_create_failed: メールリスト作成エラー。 - notice_git_notifications_created: メールリストは正常に作成できました。 - notice_git_notifications_deleted: メールリストは正常に削除できました。 - notice_git_notifications_update_failed: メールリスト編集エラー。 - notice_git_notifications_updated: メールリストは正常に編集できました。 - notice_gitolite_extra_update_failed: 設定更新エラー - notice_gitolite_extra_updated: 設定更新成功 - notice_mirror_create_failed: ミラーリポジトリ作成エラー。 - notice_mirror_created: ミラーリポジトリは正常に作成できました。 - notice_mirror_deleted: ミラーリポジトリは正常に削除できました。 - notice_mirror_update_failed: ミラーリポジトリ編集エラー。 - notice_mirror_updated: ミラーリポジトリは正常に編集できました。 - notice_post_receive_url_create_failed: Post-receive URL作成エラー。 - notice_post_receive_url_created: Post-receive URLは正常に作成できました。 - notice_post_receive_url_deleted: Post-receive URLは正常に削除できました。 - notice_post_receive_url_update_failed: Post-receive URL編集エラー。 - notice_post_receive_url_updated: Post-receive URLは正常に編集できました。 - notice_protected_branch_create_failed: 保護ブランチ作成エラー - notice_protected_branch_created: 保護ブランチは正常に作成できました。 - notice_protected_branch_deleted: 保護ブランチは正常に削除できました。 - notice_protected_branch_update_failed: 保護ブランチ編集エラー - notice_protected_branch_updated: 保護ブランチは正常に編集できました。 - notice_public_key_created: パプリックキー %{title}は正常に作成できました。 - notice_public_key_deleted: パプリックキー %{title}は正常に削除できました。 - notice_public_key_updated: パプリックキー %{title}は正常に編集できました。 - permission_create_gitolite_ssh_key: SSHキーの作成 - permission_create_repository_deployment_credentials: デプロイキーの作成 - permission_create_repository_git_config_keys: Git設定キーの作成 - permission_create_repository_git_notifications: Gitメールリストの作成 - permission_create_repository_mirrors: ミラーリポジトリの作成 - permission_create_repository_post_receive_urls: Post-receive URLの作成 - permission_create_repository_protected_branches: 保護ブランチの作成 - permission_download_git_revision: アーカイブGitリビジョンのダウンロード - permission_edit_repository_deployment_credentials: デプロイキーの編集 - permission_edit_repository_git_config_keys: Git設定キーの編集 - permission_edit_repository_git_notifications: Gitメールリストの編集 - permission_edit_repository_mirrors: ミラーリポジトリの編集 - permission_edit_repository_post_receive_urls: Post-receive URLの編集 - permission_edit_repository_protected_branches: 保護ブランチの編集 - permission_push_repository_mirrors: ミラーリポジトリへのプッシュ - permission_receive_git_notifications: コミット時のGit通知の受信 - permission_view_repository_deployment_credentials: デプロイキーの閲覧 - permission_view_repository_git_config_keys: Git設定キーの閲覧 - permission_view_repository_git_notifications: Gitメールリストの閲覧 - permission_view_repository_mirrors: ミラーリポジトリの閲覧 - permission_view_repository_post_receive_urls: Post-receive URLの閲覧 - permission_view_repository_protected_branches: 保護ブランチの閲覧 - protected_branches_reminder: 上記の保護ブランチは有効化されていません。上記のリポジトリの設定で有効化を行ってください。 - redmine_git_hosting: Redmine Git Hosting - select_other_keys: 他のキー - text_gitolite_key_destroy_confirmation: "このキーを削除してもよろしいですか: %{title}?" - text_scm_command_not_available_git_hosting: SMCコマンドが使用できません。Redmine Git Hostingの管理設定を確認してください。 - label_install_hook_results: Install hook results - label_repository_url_plural: Repository URLs diff --git a/plugins/redmine_git_hosting/config/locales/ru.yml b/plugins/redmine_git_hosting/config/locales/ru.yml deleted file mode 100644 index be1d804..0000000 --- a/plugins/redmine_git_hosting/config/locales/ru.yml +++ /dev/null @@ -1,405 +0,0 @@ -ru: - activemodel: - errors: - models: - move_repository_form: - attributes: - base: - identifier_empty: Не возможно переместить репозиторий с пустым идентификатором - identifier_taken: Идентификатор репозитория уже используется новым проектом - wrong_target_project: Целевой проект совпадает с исходным - activerecord: - errors: - models: - gitolite_public_key: - attributes: - key: - corrupted: возможно поврежден. - taken_by_you: 'уже используется вами как "%{name}".' - taken_by_other: 'уже используется пользователем "%{login}" как "%{name}".' - taken_by_someone: уже используется и принадлежит другому пользователю (обратитесь к Администратору) - taken_by_gitolite_admin: уже используется в качестве ключа Администратора Gitolite. - project: - attributes: - identifier: - invalid: неверный идентификатор - taken: совпадает с существующим идентификатором репозитория - repository_deployment_credential: - attributes: - base: - invalid_key: Публичный ключ должен быть Ключем развертывания (Deployment Key) - invalid_user: Владалец полномочий не может отличаться от владельца ключа - repository_git_config_key: - attributes: - key: - invalid: "Неправильный формат ключа (должен содержать '.')" - repository_mirror: - attributes: - base: - nothing_to_push: Должен включать в себя по меньшей мере один элемент для зеркалирования - explicit_refspec: - bad_format: неверный формат - have_null_component: первый компонент не может быть пустым (будет удалена remote-ветка(и)) - repository/xitolite: - attributes: - base: - blank_default_exists: "Невозможно создать пустой репозиторий, репозиторий уже существует." - invalid_options: "Вы не можете инициализировать репозиторий файлом README при подключенном GitAnnex" - identifier: - cannot_equal_project: "может не совпадать с ID существующего проекта" - taken: "уже получен." - invalid: ошибочный - cannot_change: невозможно изменить - all_branches: Все ветки - all_references: Все ссылки - all_tags: Все теги - button_clone: Клонировать - display_access_emphasis_html: "В приведенных шаблонах, курсивом выделены контекстно зависимые элементы." - display_access_flat: "Родителские проекты не включены в URL для Плоского режима." - display_access_hierarchical: "Родителские проекты включены в URL для Иерархического режима." - display_access_setup1_html: "Предположим что project1 является родительским для project2, а project2 является родительским для project3." - display_access_setup2_html: "Также, предположим что проект project3 имеет 2 репозитория: default и example." - display_access_setup3_html: "С учетом текущей конфигурации проекта project3, он имеет следующие параметры:" - error_download_revision_no_such_commit: "Не найден комит %{commit}" - error_project_not_found: "Проект с данными идентификатором не найден" - error_public_key_create_failed: Ошибка при создании публичного ключа. - error_public_key_update_failed: Ошибка при обновлении публичного ключа. - error_repository_not_found: "Репозиторий с данными идентификатором не найден" - error_xitolite_repositories_disabled: "Репозитории Gitolite отключены, невозможно создать репозиторий!" - field_key: ключ - field_mode: Режим - field_perm: Права доступа - field_split_payloads: Разбить payload - field_use_triggers: Использовать тригеры - label_active_for: Активность за - label_all_projects_use_git: Автоматически инициализировать Git репозитории для новых проектов? - label_average_commit_per_day: В среднем комитов в день - label_average_contributor_commits: В среднем комитов на участника - label_backup_in_progress: Сохранение... - label_branch_path: Путь к ветке - label_browse_repository: Просмотр репозитория - label_commit_plural: Комиты - label_commits_number: Количество комитов - label_commits_per_day: Комитов в день - label_commits_per_hour: Комитов в час - label_commits_per_weekday: Комитов в неделю - label_current_deploy_keys: Текущие полномочные ключи (Deployment Keys) - label_current_public_keys: Текущие публичные ключи - label_current_user_keys: Текущие ключи пользователя - label_cut_and_paste: Скопируйте и вставьте содержимое .pub файла - label_debug: Отладка - label_default_domain_name: Домен по умолчанию - label_default_gitolite_hooks_url: URL по умолчанию - label_default_repository: "Репозиторий 'default'" - label_delete_from_recyle_bin: Удалить из корзины - label_delete_git_repositories: Удалять Git репозиторий при удалении проекта? - info_delete_git_repositories: (будет перемещен в корзину) - label_delete_in_progress: Удаление... - label_delete_warning: Внимание! Удаление безвозвратно! - label_deploy_key: Полномочный deploy-ключ - label_deployment_credential_add: Добавить полномочия - label_deployment_credential_create_key_first: Ключ(и) не определены. Вы должны создать один для начала. - label_deployment_credential_create: Создать новые полномочия - label_deployment_credential_delete_when_unused: Удалять ключ когда не используется? - label_deployment_credential_delete: Удалить полномочия - label_deployment_credential_edit: Редактировать полномочия - label_deployment_credential_honored: Привелегированный? - label_deployment_credential_owner: Владелец - label_deployment_credential_public_key_file: Файл публичного ключа - label_deployment_credential_public_key_name: Имя публичного ключа - label_deployment_credential_select_deploy_key: Выбрать ключ - label_deployment_credentials: Полномочия - label_download_and_install_git: Скачать и установить Git - label_download_format: Загрузить как - label_download_select_format: Выбрать формат - label_empty_get: Пустой GET - label_empty_recycle_bin: Очистка корзины - label_empty_repository: Пустой? - label_enable_git_daemon: Включить режим Git Daemon - label_enable_git_notify: Включить почтовую рассылку - label_enable_protected_branches: Включить защищенные ветки - label_enable_public_repo: Сделать публичным - label_enable_smart_http: Включить Smart HTTP - label_error: Ошибка - label_etcetera: и.т.д. - label_example_repository: "Репозиторий 'example'" - label_first_commit_date: Дата первого комита - label_flat: Плоский - label_flush_cache: Очищать кэш Git? - label_git_annex: GitAnnex - label_git_config_email_desc: Будет использовано как e-mail при комитах - label_git_config_email: E-mail git-автора - label_git_config_key_add: Добавить парметр Git - label_git_config_key_create: Создать парметр Git - label_git_config_key_delete: Удалить парметр Git - label_git_config_key_edit: Изменить парметр Git - label_git_config_keys: Конфиг. ключи Git - label_git_config_username_desc: Будет использовано как имя автора при комитах - label_git_config_username: Git-автор - label_git_daemon: Git Daemon - label_git_key_type_config: Парметр Git - label_git_key_type_option: Парметр Gitolite - label_git_notify: Уведомления Git - label_git_objects_count: Кол-во объектов в Git - label_git_option_key_add: Добавить параметр Gitolite - label_git_option_keys: Конфиг. опции Gitolite - label_git_version: Версия Git - label_github_post: GitHub POST - label_gitolite_access_config: Настройки доступа - label_gitolite_banner: Баннер Gitolite - label_gitolite_bin_dir: Каталог с двоичный Gitolite - label_gitolite_cache_adapter_desc: Необходим рестарт Redmine после внесения изменений - label_gitolite_cache_adapter: Кэш-адаптер - label_gitolite_cache_config: Настройки кэша Gitolite - label_gitolite_cache_max_elements: Макс. кол-во кэшируемых элементов - label_gitolite_cache_max_size: Макс. размер элемента в кэше - label_gitolite_cache_max_time: Макс. время кэша - label_gitolite_config_file: Конфигурационный файл Gitolite - label_gitolite_daemon_by_default: Включать по умолчанию режим Git Daemon для новых репозиториев? - label_gitolite_documentation: Документация Gitolite - label_gitolite_download_revision_enabled: Включить скачивание git-ревизий - label_gitolite_global_config: Общие настройки Gitolite - label_gitolite_global_storage_dir_desc: Относительно домашнего каталога пользователя Gitolite - label_gitolite_global_storage_dir: Каталог репозиториев Gitolite - label_gitolite_hook_dirs_installed: Каталог хуков установлен? - label_gitolite_hook_untouched: хук без изменений - label_gitolite_hooks_are_asynchronous: Запускать хуки асинхронно - label_gitolite_hooks_config: Настройка Gitolite хуков - label_gitolite_hooks_debug: Запускать хуки в режиме отладки - label_gitolite_hooks_installed: Хуки установлены? - label_gitolite_hooks_namespace: Git namespace - label_gitolite_hooks_params_installed: Установленны параметры хуков? - label_gitolite_hooks_url: Хук-URL - label_gitolite_http_by_default: Включать по умолчанию режим Smart HTTP для новых репозиториев? - label_gitolite_identifier_prefix_desc: Будет использован при генерации идентификаторов SSH-ключей - label_gitolite_identifier_prefix: Префикс Gitolite - label_gitolite_identifier_strip_user_id: Удалить идентификатор пользователя из Gitolite идентификатора - label_gitolite_lib_dir: Каталог с библиотеками Gitolite - label_gitolite_libgit2_version: Версия libgit2 - label_gitolite_local_code_dir: Каталог внешних хуков Gitolite - label_gitolite_log_level_desc: Необходим рестарт Redmine после внесения изменений - label_gitolite_log_level: Уровень журналирования Gitolite - label_gitolite_mailer_params_installed: Установленны параметры доставки почты? - label_gitolite_notify_by_default: "Включить по умолчанию 'Git Notifications' хук для новых репозиториев?" - label_gitolite_notify_config: Настройка Git-рассылки - label_gitolite_notify_global_exclude: Исключить из Git-рассылки - label_gitolite_notify_global_include: Вклчить в Git-рассылку - label_gitolite_notify_global_prefix: Глобальный префикс Git-рассылки - label_gitolite_notify_global_sender_address: Глобальный адрес отправителя Git-рассылки - label_gitolite_overwrite_existing_hooks: Перекрывать существующие хуки - label_gitolite_recycle_bin_dir_desc: Относительно домашнего каталога пользователя Gitolite - label_gitolite_recycle_bin_dir: Каталог корзины - label_gitolite_recycle_bin_expiration_time_desc: Часы - label_gitolite_recycle_bin_expiration_time: Время хранения репозитория в корзине - label_gitolite_redmine_storage_dir_desc: Относительно каталога репозиториев Gitolite - label_gitolite_redmine_storage_dir: Подкаталог управляемых через Redmine репозиториев - label_gitolite_repository_count: Количество репозиториев в Gitolite - label_gitolite_rescue: Восстановление Gitolite - label_gitolite_rugged_features: Rugged скомпилирован с поддержкой - label_gitolite_server_host: SSH/Gitolite хост - label_gitolite_server_port: SSH/Gitolite порт - label_gitolite_ssh_config: Настройки SSH для Gitolite - label_gitolite_ssh_private_key: Приватный ключ Gitolite/SSH - label_gitolite_ssh_public_key: Публичный ключ Gitolite/SSH - label_gitolite_storage_config: Конфигурация хранилища Gitolite - label_gitolite_temp_dir_desc: Абсолютный путь - label_gitolite_temp_dir: Временный каталог для lock-файлов и данных - label_gitolite_use_sidekiq: Использовать Sidekiq для запуска асинхронных задач - label_gitolite_user: Системный пользователь Gitolite - label_gitolite_version: Версия Gitolite - label_help_git_setup: Установка Git - label_help_no_repo_rights: "Простите, вы не имеете доступа к данному репозиторию. Вы не можете производить никакие действия." - label_help_repository_clone: Клонирование репозитория - label_help_repository_setup_existing: Настройка существующего репозитория - label_help_repository_setup_new: Настройка нового репозитория - label_hierarchical_organisation: Структура каталогов для репозиториев под управлением Redmine - label_hierarchical: Иерарх. - label_http_access: HTTP доступ - label_http_only: Только HTTP - label_http_server_domain: Домен HTTP-сервера - label_http_server_subdir_desc: Относительно корневного URL Redmine - label_http_server_subdir: Подкаталог для HTTP доступа - label_https_access: HTTPS доступ - label_https_and_http: HTTPS и HTTP - label_https_only: Только HTTPS - label_https_server_domain_desc: Оставьте пустым, если не используется - label_https_server_domain: Домен HTTPS-сервера - label_identifier_can_be_arbitrary_desc: (Может быть любой значимой строкой) - label_identifier_can_be_arbitrary: Идентификатор - label_identifier_cannot_be_changed: Идентификатор
(Не может быть изменен) - label_info: Инфо - label_init_repo_with_git_annex: Инициализировать репозиторий c GitAnnex - label_init_repo_with_readme: Инициализировать репозиторий README файлом - label_init_repositories_on_create: Автоматически инициализировать Git репозиторий с README файлом (а-ля Github) - label_install_gitolite_hooks: Установить хуки! - label_key_cannot_be_changed_please_create_new_key: 'Ключ не может быть изменен, но вы можете удалить его и создать новый.' - label_key_type: Тип публичного ключа - label_key: Ключ - label_latest_commit_date: Дата последнего копита - label_main_git_repository: Основной Git репозиторий - label_mirror_add: Добавить зеркало - label_mirror_create: Создать зеркало - label_mirror_delete: Удалить зеркало - label_mirror_edit: Редактировать зеркало - label_mirror_explicit_refspec: Явное определение - label_mirror_fast_forward: Fast Forward (Unforced) - label_mirror_forced_update: Force Update Remote - label_mirror_full_mirror: Complete Mirroring - label_mirror_help: Зеркала должны предоставлять доступ на запись следующему публичному ключу - label_mirror_include_all_branches: Зеркалировать все ветки - label_mirror_include_all_tags: Зеркалировать все теги - label_mirror_push_fail: Ошибка - label_mirror_push_info_html: "Зеркалирование в %{mirror_url} : %{status}" - label_mirror_push_mode: Режим обновления - label_mirror_push_output: Отправлено - label_mirror_push_sucess: Успешно - label_mirror_push_title: Зеркалировать - label_mirror_push: Зеркалировать - label_mirror_refspec: Refspec - label_mirror_url_accepted_format: Формат URL - label_mirror: Зеркало - label_mirroring_keys_installed: Установлены ключи зеркалирования? - label_mode: Режим - label_move_repository: "Перемещение репозитория: '%{repo_name}'" - label_my_public_keys: Мои публичные ключи - label_need_help: Нужна помощь? - label_no_public_keys: Публичные ключи не определены - label_open_issue: Открытые проблемы - label_path_directories: Каталоги входящие в PATH - label_permissions_header: Необходимые разрешения - label_post_receive_url_add: Добавить Post Receive URL - label_post_receive_url_create: Создать Post-receive URL - label_post_receive_url_delete: Удалить Post-receive URL - label_post_receive_url_edit: Изменить Post-receive URL - label_post_receive_urls: Post Receive URLs - label_protected_branch_add: Добавить защищенную ветку - label_protected_branch_create: Создать защищенную ветку - label_protected_branch_delete: Удалить защищенную ветку - label_protected_branch_edit: Редактировать защищенную ветку - label_protected_branch: Защищенные ветки - label_protected_branches: Защищенные ветки - label_public_key_edit: Редактировать публичный ключ - label_public_key_new: Ввод нового публичного ключа - label_public_key: Публичный ключ - label_public_keys: Публичные ключи - label_public_repo: Публичный - label_read_only_permission: RO - label_read_write_permission: RW - label_recycle_bin_content_size: Размер - label_redmine_config: Настройки Redmine - label_redmine_git_hosting_issue: Redmine Git Hosting - Открытые проблемы - label_redmine_git_hosting_wiki: Redmine Git Hosting - Wiki - label_redmine_has_rw_access_on_all_repos: Redmine имеет RW доступ ко всем Gitolite репозиториям - label_redmine_user: Системный пользователь Redmine - label_regenerate_all_ssh_keys_desc: "Это позволить восстановить идентификаторы SSH ключей" - label_regenerate_all_ssh_keys_desc2: "Можеть занять время: все ключи SSH будут удалены и повторно добавлены в Gitolite один за другим." - label_regenerate_all_ssh_keys: Перегенерировать SSH ключи? - label_repos_current_access_patterns: Текущий шаблон доступа - label_repository_access_not_configured: Доступ к репозиторию не настроен. Обратитесь к Администратору! - label_repository_access_url: Ссылки для доступа - label_repository_default_branch: Ветка по умолчанию - label_repository_enabled_capabilities: Подключенные опции - label_repository_exists_in_gitolite: Репозиторий существует в Gitolite - label_repository_mirrors: Зеркала - label_repository_options: Параметры репозитория - label_repository_statistics_commits: Статистика комитов - label_repository_statistics_contributors: Статистика участников - label_repository_statistics_global: Глобальная статистика - label_resync_all_projects: Синхронизировать проекты? - label_resync_all_ssh_keys: Синхронизировать SSH ключи? - label_see_other_repositories: Другие репозитории - label_select_all: Выбрать всё - label_smart_http: Smart HTTP - label_sort_urls: (Изменить порядок) - label_split_payloads: Разбить payload - label_ssh_access: SSH доступ - label_ssh_keys_current_access_patterns: Шаблон доступа по SSH-ключам - label_ssh_server_domain: Домен SSH-сервера - label_storage_directory: Каталог хранилища - label_sudo_gitolite_to_redmine_user: Git пользователь имеет sudo для Redmine пользователя? - label_sudo_redmine_to_gitolite_user: Пользователь Redmine имеет sudo для Git пользователя? - label_tab_access: Доступ - label_tab_cache: Кэш - label_tab_config_file: Конфиг. файл - label_tab_config_test: Тест настроек - label_tab_gitolite_recycle_bin: Корзина - label_tab_gitolite_rescue: Восстановление - label_tab_global: Общие - label_tab_hooks: Хуки - label_tab_notify: Уведомления - label_tab_redmine: Redmine - label_tab_sidekiq_interface: Sidekiq - label_tab_ssh: SSH - label_tab_storage: Хранилище - label_temp_dir_writeable: Временный каталог доступен для записи? - label_this_urls_has_permissions: "Данный URL имеет доступ." - label_total_commits: Всего комитов - label_total_contributors: Всего участников - label_triggers: Тригеры - label_unique_repo_identifier: Глобально уникальный идентификатор репозитория? - label_unknown_gitolite_version: Незвестная версия - label_use_triggers: Использовать тригеры - label_user_key: Пользовательский ключ - label_user_list: Разрешенные пользователи - label_warn: Предупреждение - notice_deployment_credential_create_failed: Ошибка при создании полномочий - notice_deployment_credential_created: Полномочия успешно созданы. - notice_deployment_credential_deleted_with_key: Полномочия и Ключ успешно удалены. - notice_deployment_credential_deleted: Полномочия успешно удалены. - notice_deployment_credential_update_failed: Ошибка при обновлении полномочий - notice_deployment_credential_updated: Полномочия успешно обновлены. - notice_empty_repository: Репозиторий пуст. Следуйте расположенным ниже инструкциям. - notice_git_config_key_create_failed: Ошибка при создании параметра Git - notice_git_config_key_created: Парметр Git успешно создан. - notice_git_config_key_deleted: Парметр Git успешно удален. - notice_git_config_key_update_failed: Ошибка при обновлении параметра Git - notice_git_config_key_updated: Парметр Git успешно обновлен. - notice_gitolite_extra_update_failed: Ошибка при обновлении параметров - notice_gitolite_extra_updated: Параметры успешно обновлены - notice_mirror_create_failed: Ошибка при создании зеркала. - notice_mirror_created: Зеркало успешно создано. - notice_mirror_deleted: Зеркало успешно удалено. - notice_mirror_update_failed: Ошибка при обновлении зеркала. - notice_mirror_updated: Зеркало успешно обновлена. - notice_post_receive_url_create_failed: Ошибка при создании post-receive URL. - notice_post_receive_url_created: Post-receive URL успешно создан. - notice_post_receive_url_deleted: Post-receive URL успешно удален. - notice_post_receive_url_update_failed: Ошибка при обновлении post-receive URL. - notice_post_receive_url_updated: Post-receive URL успешно обновлен. - notice_protected_branch_create_failed: Ошибка при создании защищенной ветки - notice_protected_branch_created: Защищенная ветка успешно создана. - notice_protected_branch_deleted: Защищенная ветка успешно удалена. - notice_protected_branch_update_failed: Ошибка при обновлении защищенной ветки - notice_protected_branch_updated: Защищенная ветка успешно обновлена. - notice_public_key_created: Публичный ключ %{title} успешно создан. - notice_public_key_deleted: Публичный ключ %{title} успешно удален. - notice_public_key_updated: Публичный ключ %{title} успешно обновлен. - permission_create_gitolite_ssh_key: Создание SSH ключей - permission_create_repository_deployment_credentials: Создание полномочий (Deployment Keys) - permission_create_repository_git_config_keys: Создание Git-config ключей - permission_create_repository_git_notifications: Создание рассылок - permission_create_repository_mirrors: Создание зеркал - permission_create_repository_post_receive_urls: Создание post-receive URLs - permission_create_repository_protected_branches: Создание защищенных веток - permission_download_git_revision: Загрузка zip-архива ревизии - permission_edit_repository_deployment_credentials: Изменение полномочий (Deployment Keys) - permission_edit_repository_git_config_keys: Изменение Git-config ключей - permission_edit_repository_git_notifications: Изменение рассылок - permission_edit_repository_mirrors: Изменение зеркал - permission_edit_repository_post_receive_urls: Изменение post-receive URLs - permission_edit_repository_protected_branches: Изменение защищенных веток - permission_push_repository_mirrors: Зеркалирование - permission_receive_git_notifications: Получение уведомлений о комитах - permission_view_repository_deployment_credentials: Просмотр полномочий (Deployment Keys) - permission_view_repository_git_config_keys: Просмотр Git-config ключей - permission_view_repository_git_notifications: Просмотр рассылок - permission_view_repository_mirrors: Просмотр зеркал - permission_view_repository_post_receive_urls: Просмотр post-receive URLs - permission_view_repository_protected_branches: Просмотр защищенных веток - protected_branches_reminder: Защищенные ветки не включены. Включите защищенные ветки в настройках репозитария. - redmine_git_hosting: Redmine Git Hosting - select_other_keys: Другие ключи - text_gitolite_key_destroy_confirmation: "Вы уверены, что хотите удалить данный ключ: %{title}?" - text_scm_command_not_available_git_hosting: SCM команда недоступна. Проверьте настройки плагина Redmine Git Hosting. - label_install_hook_results: Install hook results - label_repository_url_plural: Repository URLs diff --git a/plugins/redmine_git_hosting/config/routes.rb b/plugins/redmine_git_hosting/config/routes.rb deleted file mode 100644 index baabb85..0000000 --- a/plugins/redmine_git_hosting/config/routes.rb +++ /dev/null @@ -1,49 +0,0 @@ -Rails.application.routes.draw do - # Handle the public keys plugin to my/account. - scope 'my' do - resources :public_keys, controller: 'gitolite_public_keys' - end - - # Don't create routes for repositories resources with only: [] - # to not override Redmine's routes. - resources :repositories, only: [] do - member do - get 'download_revision', to: 'download_git_revision#index', as: 'download_git_revision' - end - - resource :git_extras, controller: 'repository_git_extras', only: [:update] do - match 'sort_urls', via: %i[get post] - member do - match 'move', via: %i[get post] - end - end - - resources :post_receive_urls, controller: 'repository_post_receive_urls' - resources :deployment_credentials, controller: 'repository_deployment_credentials' - resources :git_config_keys, controller: 'repository_git_config_keys' - - resources :mirrors, controller: 'repository_mirrors' do - member { get :push } - end - - resources :protected_branches, controller: 'repository_protected_branches' do - member { get :clone } - collection { post :sort } - end - end - - # Enable Redirector for Go Lang repositories - get 'go/:repo_path', repo_path: %r{([^/]+/)*?[^/]+}, to: 'go_redirector#index' - - get 'admin/settings/plugin/:id/authors', to: 'settings#authors', as: 'plugin_authors' - get 'admin/settings/plugin/:id/install_gitolite_hooks', to: 'settings#install_gitolite_hooks', as: 'install_gitolite_hooks' - - # Enable SmartHTTP Grack support - mount Grack::Bundle.new({}), - at: RedmineGitHosting::Config.http_server_subdir, - constraints: ->(request) { %r{[-/\w.]+\.git/}.match(request.path_info) }, - via: %i[get post] - - # Post Receive Hooks - mount Hrack::Bundle.new({}), at: 'githooks/post-receive/:type/:projectid', via: [:post] -end diff --git a/plugins/redmine_git_hosting/config/sidekiq.yml b/plugins/redmine_git_hosting/config/sidekiq.yml deleted file mode 100644 index f1807f0..0000000 --- a/plugins/redmine_git_hosting/config/sidekiq.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -:pidfile: tmp/pids/sidekiq_redmine_git_hosting.pid -:concurrency: 1 -:timeout: 15 -:queues: - - redmine_git_hosting diff --git a/plugins/redmine_git_hosting/contrib/github/database-mysql.yml b/plugins/redmine_git_hosting/contrib/github/database-mysql.yml deleted file mode 100644 index 160f66c..0000000 --- a/plugins/redmine_git_hosting/contrib/github/database-mysql.yml +++ /dev/null @@ -1,26 +0,0 @@ -production: - adapter: mysql2 - database: redmine - host: 127.0.0.1 - port: 3306 - username: root - password: - encoding: utf8mb4 - -development: - adapter: mysql2 - database: redmine - port: 3306 - host: 127.0.0.1 - username: root - password: - encoding: utf8mb4 - -test: - adapter: mysql2 - database: redmine - port: 3306 - host: 127.0.0.1 - username: root - password: - encoding: utf8mb4 diff --git a/plugins/redmine_git_hosting/contrib/github/database-postgres.yml b/plugins/redmine_git_hosting/contrib/github/database-postgres.yml deleted file mode 100644 index 97802de..0000000 --- a/plugins/redmine_git_hosting/contrib/github/database-postgres.yml +++ /dev/null @@ -1,23 +0,0 @@ -production: - adapter: postgresql - host: localhost - database: redmine - username: postgres - password: postgres - encoding: utf8 - -development: - adapter: postgresql - host: localhost - database: redmine - username: postgres - password: postgres - encoding: utf8 - -test: - adapter: postgresql - host: localhost - database: redmine - username: postgres - password: postgres - encoding: utf8 diff --git a/plugins/redmine_git_hosting/contrib/hooks/post-receive/lib/git_hosting_config.rb b/plugins/redmine_git_hosting/contrib/hooks/post-receive/lib/git_hosting_config.rb deleted file mode 100644 index 668afcd..0000000 --- a/plugins/redmine_git_hosting/contrib/hooks/post-receive/lib/git_hosting_config.rb +++ /dev/null @@ -1,103 +0,0 @@ -require 'digest/sha1' - -module GitHosting - class Config - IGNORE_PARAMS = %w[redmineurl projectid debugmode asyncmode repositorykey].freeze - REDMINE_PARAMS = %w[redminegitolite.redmineurl - redminegitolite.projectid - redminegitolite.repositoryid - redminegitolite.repositorykey - redminegitolite.debugmode - redminegitolite.asyncmode].freeze - - attr_reader :config - - def initialize - @config = {} - load_gitolite_vars - end - - def valid? - config_errors.nil? - end - - def project_url - "#{redmine_url}/#{project_name}" - end - - def redmine_url - config['redmineurl'] - end - - def project_name - config['projectid'] - end - - def repository_name - if config.key?('repositoryid') && !config['repositoryid'].empty? - "#{project_name}/#{config['repositoryid']}" - else - project_name - end - end - - def repository_key - config['repositorykey'] - end - - def debug_mode? - config['debugmode'] == 'true' - end - - def loglevel - if debug_mode? - 'debug' - else - 'info' - end - end - - def post_data - post_data = {} - post_data['clear_time'] = clear_time - post_data['encoded_time'] = auth_token - config.each_key do |key| - post_data[key] = config[key] unless IGNORE_PARAMS.include?(key) - end - post_data - end - - def clear_time - @clear_time ||= Time.new.utc.to_i.to_s - end - - def auth_token - Digest::SHA1.hexdigest(clear_time.to_s + repository_key) - end - - # Detect blank params in config. - # Allow blank repositoryid (as default). - # - def config_errors - config.detect { |k, v| k != 'repositoryid' && v == '' } - end - - private - - def load_gitolite_vars - REDMINE_PARAMS.each do |var_name| - var_value = get_gitolite_config(var_name) - var_name = sanitize(var_name) - @config[var_name] = var_value - end - end - - def get_gitolite_config(var_name) - (%x[git config #{var_name}]).chomp.strip - end - - def sanitize(var_name) - var_name.gsub(/^.*\./, '') - end - end -end diff --git a/plugins/redmine_git_hosting/contrib/hooks/post-receive/lib/git_hosting_custom_hook.rb b/plugins/redmine_git_hosting/contrib/hooks/post-receive/lib/git_hosting_custom_hook.rb deleted file mode 100644 index 3c0608d..0000000 --- a/plugins/redmine_git_hosting/contrib/hooks/post-receive/lib/git_hosting_custom_hook.rb +++ /dev/null @@ -1,89 +0,0 @@ -module GitHosting - class CustomHook - attr_reader :repo_path, :refs, :git_config - - def initialize(repo_path, refs) - @repo_path = repo_path - @refs = refs - @git_config = Config.new - end - - def exec - ## Execute extra hooks - extra_hooks = get_extra_hooks - return if extra_hooks.nil? || extra_hooks.none? - - logger.info 'Calling additional post-receive hooks...' - call_extra_hooks extra_hooks - logger.info '' - end - - private - - def get_extra_hooks - # Get global extra hooks - logger.debug('Looking for additional global post-receive hooks...') - global_extra_hooks = get_executables('hooks/post-receive.d') - if global_extra_hooks.empty? - logger.debug(' - No global hooks found') - else - logger.debug(" - Global hooks found : #{global_extra_hooks}") - end - - logger.debug('') - - # Get local extra hooks - logger.debug('Looking for additional local post-receive hooks...') - local_extra_hooks = get_executables('hooks/post-receive.local.d') - if local_extra_hooks.empty? - logger.debug(' - No local hooks found') - else - logger.debug(" - Local hooks found : #{local_extra_hooks}") - end - - logger.debug('') - - global_extra_hooks + local_extra_hooks - end - - def get_executables(directory) - executables = [] - if File.directory?(directory) - Dir.foreach(directory) do |item| - next if item == '.' || item == '..' - - # Use full relative path - path = "#{directory}/#{item}" - # Test if the file is executable - if File.executable?(path) - # Remember it, if so - executables.push(path) - end - end - end - executables - end - - def call_extra_hooks(extra_hooks) - # Call each exectuble found with the parameters we got - extra_hooks.each do |extra_hook| - logger.info(" - Executing extra hook '#{extra_hook}'") - - IO.popen(extra_hook.to_s, 'w+') do |pipe| - begin - pipe.puts refs - pipe.close_write - logger.info pipe.read.to_s - rescue => e - logger.error "Error while executing hook #{extra_hook}" - logger.error e.message.to_s - end - end - end - end - - def logger - @logger ||= GitHosting::HookLogger.new(loglevel: git_config.loglevel) - end - end -end diff --git a/plugins/redmine_git_hosting/contrib/hooks/post-receive/lib/git_hosting_hook_logger.rb b/plugins/redmine_git_hosting/contrib/hooks/post-receive/lib/git_hosting_hook_logger.rb deleted file mode 100644 index 6bbece8..0000000 --- a/plugins/redmine_git_hosting/contrib/hooks/post-receive/lib/git_hosting_hook_logger.rb +++ /dev/null @@ -1,29 +0,0 @@ -module GitHosting - class HookLogger - attr_reader :loglevel - - def initialize(opts = {}) - @loglevel = opts.delete(:loglevel) { 'info' } - end - - def debug(message) - write(message) if loglevel == 'debug' - end - - def info(message) - write(message) - end - - def error(message) - write(message) - end - - private - - def write(message) - $stdout.sync = true - $stdout.puts "\e[1G#{message}" - $stdout.flush - end - end -end diff --git a/plugins/redmine_git_hosting/contrib/hooks/post-receive/lib/git_hosting_http_helper.rb b/plugins/redmine_git_hosting/contrib/hooks/post-receive/lib/git_hosting_http_helper.rb deleted file mode 100644 index 88ebe9c..0000000 --- a/plugins/redmine_git_hosting/contrib/hooks/post-receive/lib/git_hosting_http_helper.rb +++ /dev/null @@ -1,114 +0,0 @@ -require 'json' -require 'net/http' -require 'net/https' -require 'uri' - -module GitHosting - module HttpHelper - def http_post(url, opts = {}, &block) - http, request = build_post_request url, opts - send_http_request http, request, &block - end - - def http_get(url, opts = {}, &block) - http, request = build_get_request url, opts - send_http_request http, request, &block - end - - def valid_url?(url) - uri = URI.parse url - uri.is_a?(URI::HTTP) - rescue URI::InvalidURIError - false - end - - def serialize_params(params) - params.map do |key, value| - if value.instance_of?(Array) - value.map { |e| "#{urlencode(key.to_s)}=#{urlencode(e.to_s)}" }.join('&') - else - "#{urlencode(key.to_s)}=#{urlencode(value.to_s)}" - end - end.join('&') - end - - private - - def urlencode(string) - URI.encode(string, /[^a-zA-Z0-9_.\-]/) - end - - def build_post_request(url, opts = {}) - # Get params - params = opts.delete(:params) { {} } - - # Build request - uri, http = build_http_request url, opts - request = Net::HTTP::Post.new uri.request_uri - - # Set request - request.body = serialize_params params - request.content_type = 'application/x-www-form-urlencoded' - - [http, request] - end - - def build_get_request(url, opts = {}) - # Get params - params = opts.delete(:params) { {} } - params = serialize_params params - - # Build request - uri, http = build_http_request url, opts - request = Net::HTTP::Get.new uri.request_uri - - [http, request] - end - - def build_http_request(url, opts = {}) - # Get HTTP options - open_timeout = opts.delete(:open_timeout) { 5 } - read_timeout = opts.delete(:read_timeout) { 10 } - - uri = URI(url) - http = Net::HTTP.new(uri.host, uri.port) - if uri.scheme == 'https' - http.use_ssl = true - http.verify_mode = OpenSSL::SSL::VERIFY_NONE - end - - # Set HTTP options - http.open_timeout = open_timeout - http.read_timeout = read_timeout - - [uri, http] - end - - def send_http_request(http, request) - if block_given? - yield(http, request) - else - one_shot_request(http, request) - end - end - - def one_shot_request(http, request) - message = '' - begin - res = http.start { |openhttp| openhttp.request request } - if !res.is_a?(Net::HTTPSuccess) - message = "Return code : #{res.code} (#{res.message})." - failed = true - else - message = res.body - failed = false - end - rescue StandardError => e - message = "Exception : #{e.message}" - failed = true - end - - [failed, message] - end - end -end diff --git a/plugins/redmine_git_hosting/contrib/hooks/post-receive/lib/git_hosting_post_receive.rb b/plugins/redmine_git_hosting/contrib/hooks/post-receive/lib/git_hosting_post_receive.rb deleted file mode 100644 index 3fab980..0000000 --- a/plugins/redmine_git_hosting/contrib/hooks/post-receive/lib/git_hosting_post_receive.rb +++ /dev/null @@ -1,61 +0,0 @@ -module GitHosting - class PostReceive - include HttpHelper - - attr_reader :repo_path, :refs, :git_config - - def initialize(repo_path, refs) - @repo_path = repo_path - @refs = refs - @git_config = Config.new - end - - def exec - notify_redmine if git_config.valid? - end - - private - - def notify_redmine - logger.info('') - logger.info("Notifying Redmine about changes to this repository : '#{git_config.repository_name}' ...") - - http_post(git_config.project_url, { params: http_post_data }) do |http, request| - begin - http.request(request) { |response| check_response(response) } - rescue => e - logger.error("HTTP_ERROR : #{e.message}") - end - end - - logger.info('') - end - - def http_post_data - git_config.post_data.merge('refs[]' => parsed_refs) - end - - def parsed_refs - parsed = [] - refs.split("\n").each do |line| - r = line.chomp.strip.split - parsed << [r[0].to_s, r[1].to_s, r[2].to_s].join(',') - end - parsed - end - - def check_response(response) - if response.code.to_i == 200 - response.read_body do |body_frag| - body_frag.split("\n").each { |line| logger.info(line) } - end - else - logger.error(" - Error while notifying Redmine ! (status code: #{response.code})") - end - end - - def logger - @logger ||= GitHosting::HookLogger.new(loglevel: git_config.loglevel) - end - end -end diff --git a/plugins/redmine_git_hosting/contrib/hooks/post-receive/lib/git_multimail.py b/plugins/redmine_git_hosting/contrib/hooks/post-receive/lib/git_multimail.py deleted file mode 100644 index 8823399..0000000 --- a/plugins/redmine_git_hosting/contrib/hooks/post-receive/lib/git_multimail.py +++ /dev/null @@ -1,4346 +0,0 @@ -#! /usr/bin/env python - -__version__ = '1.5.0' - -# Copyright (c) 2015-2016 Matthieu Moy and others -# Copyright (c) 2012-2014 Michael Haggerty and others -# Derived from contrib/hooks/post-receive-email, which is -# Copyright (c) 2007 Andy Parkins -# and also includes contributions by other authors. -# -# This file is part of git-multimail. -# -# git-multimail is free software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License version -# 2 as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -"""Generate notification emails for pushes to a git repository. - -This hook sends emails describing changes introduced by pushes to a -git repository. For each reference that was changed, it emits one -ReferenceChange email summarizing how the reference was changed, -followed by one Revision email for each new commit that was introduced -by the reference change. - -Each commit is announced in exactly one Revision email. If the same -commit is merged into another branch in the same or a later push, then -the ReferenceChange email will list the commit's SHA1 and its one-line -summary, but no new Revision email will be generated. - -This script is designed to be used as a "post-receive" hook in a git -repository (see githooks(5)). It can also be used as an "update" -script, but this usage is not completely reliable and is deprecated. - -To help with debugging, this script accepts a --stdout option, which -causes the emails to be written to standard output rather than sent -using sendmail. - -See the accompanying README file for the complete documentation. - -""" - -import sys -import os -import re -import bisect -import socket -import subprocess -import shlex -import optparse -import logging -import smtplib -try: - import ssl -except ImportError: - # Python < 2.6 do not have ssl, but that's OK if we don't use it. - pass -import time - -import uuid -import base64 - -PYTHON3 = sys.version_info >= (3, 0) - -if sys.version_info <= (2, 5): - def all(iterable): - for element in iterable: - if not element: - return False - return True - - -def is_ascii(s): - return all(ord(c) < 128 and ord(c) > 0 for c in s) - - -if PYTHON3: - def is_string(s): - return isinstance(s, str) - - def str_to_bytes(s): - return s.encode(ENCODING) - - def bytes_to_str(s, errors='strict'): - return s.decode(ENCODING, errors) - - unicode = str - - def write_str(f, msg): - # Try outputing with the default encoding. If it fails, - # try UTF-8. - try: - f.buffer.write(msg.encode(sys.getdefaultencoding())) - except UnicodeEncodeError: - f.buffer.write(msg.encode(ENCODING)) - - def read_line(f): - # Try reading with the default encoding. If it fails, - # try UTF-8. - out = f.buffer.readline() - try: - return out.decode(sys.getdefaultencoding()) - except UnicodeEncodeError: - return out.decode(ENCODING) - - import html - - def html_escape(s): - return html.escape(s) - -else: - def is_string(s): - try: - return isinstance(s, basestring) - except NameError: # Silence Pyflakes warning - raise - - def str_to_bytes(s): - return s - - def bytes_to_str(s, errors='strict'): - return s - - def write_str(f, msg): - f.write(msg) - - def read_line(f): - return f.readline() - - def next(it): - return it.next() - - import cgi - - def html_escape(s): - return cgi.escape(s, True) - -try: - from email.charset import Charset - from email.utils import make_msgid - from email.utils import getaddresses - from email.utils import formataddr - from email.utils import formatdate - from email.header import Header -except ImportError: - # Prior to Python 2.5, the email module used different names: - from email.Charset import Charset - from email.Utils import make_msgid - from email.Utils import getaddresses - from email.Utils import formataddr - from email.Utils import formatdate - from email.Header import Header - - -DEBUG = False - -ZEROS = '0' * 40 -LOGBEGIN = '- Log -----------------------------------------------------------------\n' -LOGEND = '-----------------------------------------------------------------------\n' - -ADDR_HEADERS = set(['from', 'to', 'cc', 'bcc', 'reply-to', 'sender']) - -# It is assumed in many places that the encoding is uniformly UTF-8, -# so changing these constants is unsupported. But define them here -# anyway, to make it easier to find (at least most of) the places -# where the encoding is important. -(ENCODING, CHARSET) = ('UTF-8', 'utf-8') - - -REF_CREATED_SUBJECT_TEMPLATE = ( - '%(emailprefix)s%(refname_type)s %(short_refname)s created' - ' (now %(newrev_short)s)' - ) -REF_UPDATED_SUBJECT_TEMPLATE = ( - '%(emailprefix)s%(refname_type)s %(short_refname)s updated' - ' (%(oldrev_short)s -> %(newrev_short)s)' - ) -REF_DELETED_SUBJECT_TEMPLATE = ( - '%(emailprefix)s%(refname_type)s %(short_refname)s deleted' - ' (was %(oldrev_short)s)' - ) - -COMBINED_REFCHANGE_REVISION_SUBJECT_TEMPLATE = ( - '%(emailprefix)s%(refname_type)s %(short_refname)s updated: %(oneline)s' - ) - -REFCHANGE_HEADER_TEMPLATE = """\ -Date: %(send_date)s -To: %(recipients)s -Subject: %(subject)s -MIME-Version: 1.0 -Content-Type: text/%(contenttype)s; charset=%(charset)s -Content-Transfer-Encoding: 8bit -Message-ID: %(msgid)s -From: %(fromaddr)s -Reply-To: %(reply_to)s -Thread-Index: %(thread_index)s -X-Git-Host: %(fqdn)s -X-Git-Repo: %(repo_shortname)s -X-Git-Refname: %(refname)s -X-Git-Reftype: %(refname_type)s -X-Git-Oldrev: %(oldrev)s -X-Git-Newrev: %(newrev)s -X-Git-NotificationType: ref_changed -X-Git-Multimail-Version: %(multimail_version)s -Auto-Submitted: auto-generated -""" - -REFCHANGE_INTRO_TEMPLATE = """\ -This is an automated email from the git hooks/post-receive script. - -%(pusher)s pushed a change to %(refname_type)s %(short_refname)s -in repository %(repo_shortname)s. - -""" - - -FOOTER_TEMPLATE = """\ - --- \n\ -To stop receiving notification emails like this one, please contact -%(administrator)s. -""" - - -REWIND_ONLY_TEMPLATE = """\ -This update removed existing revisions from the reference, leaving the -reference pointing at a previous point in the repository history. - - * -- * -- N %(refname)s (%(newrev_short)s) - \\ - O -- O -- O (%(oldrev_short)s) - -Any revisions marked "omit" are not gone; other references still -refer to them. Any revisions marked "discard" are gone forever. -""" - - -NON_FF_TEMPLATE = """\ -This update added new revisions after undoing existing revisions. -That is to say, some revisions that were in the old version of the -%(refname_type)s are not in the new version. This situation occurs -when a user --force pushes a change and generates a repository -containing something like this: - - * -- * -- B -- O -- O -- O (%(oldrev_short)s) - \\ - N -- N -- N %(refname)s (%(newrev_short)s) - -You should already have received notification emails for all of the O -revisions, and so the following emails describe only the N revisions -from the common base, B. - -Any revisions marked "omit" are not gone; other references still -refer to them. Any revisions marked "discard" are gone forever. -""" - - -NO_NEW_REVISIONS_TEMPLATE = """\ -No new revisions were added by this update. -""" - - -DISCARDED_REVISIONS_TEMPLATE = """\ -This change permanently discards the following revisions: -""" - - -NO_DISCARDED_REVISIONS_TEMPLATE = """\ -The revisions that were on this %(refname_type)s are still contained in -other references; therefore, this change does not discard any commits -from the repository. -""" - - -NEW_REVISIONS_TEMPLATE = """\ -The %(tot)s revisions listed above as "new" are entirely new to this -repository and will be described in separate emails. The revisions -listed as "add" were already present in the repository and have only -been added to this reference. - -""" - - -TAG_CREATED_TEMPLATE = """\ - at %(newrev_short)-8s (%(newrev_type)s) -""" - - -TAG_UPDATED_TEMPLATE = """\ -*** WARNING: tag %(short_refname)s was modified! *** - - from %(oldrev_short)-8s (%(oldrev_type)s) - to %(newrev_short)-8s (%(newrev_type)s) -""" - - -TAG_DELETED_TEMPLATE = """\ -*** WARNING: tag %(short_refname)s was deleted! *** - -""" - - -# The template used in summary tables. It looks best if this uses the -# same alignment as TAG_CREATED_TEMPLATE and TAG_UPDATED_TEMPLATE. -BRIEF_SUMMARY_TEMPLATE = """\ -%(action)8s %(rev_short)-8s %(text)s -""" - - -NON_COMMIT_UPDATE_TEMPLATE = """\ -This is an unusual reference change because the reference did not -refer to a commit either before or after the change. We do not know -how to provide full information about this reference change. -""" - - -REVISION_HEADER_TEMPLATE = """\ -Date: %(send_date)s -To: %(recipients)s -Cc: %(cc_recipients)s -Subject: %(emailprefix)s%(num)02d/%(tot)02d: %(oneline)s -MIME-Version: 1.0 -Content-Type: text/%(contenttype)s; charset=%(charset)s -Content-Transfer-Encoding: 8bit -From: %(fromaddr)s -Reply-To: %(reply_to)s -In-Reply-To: %(reply_to_msgid)s -References: %(reply_to_msgid)s -Thread-Index: %(thread_index)s -X-Git-Host: %(fqdn)s -X-Git-Repo: %(repo_shortname)s -X-Git-Refname: %(refname)s -X-Git-Reftype: %(refname_type)s -X-Git-Rev: %(rev)s -X-Git-NotificationType: diff -X-Git-Multimail-Version: %(multimail_version)s -Auto-Submitted: auto-generated -""" - -REVISION_INTRO_TEMPLATE = """\ -This is an automated email from the git hooks/post-receive script. - -%(pusher)s pushed a commit to %(refname_type)s %(short_refname)s -in repository %(repo_shortname)s. - -""" - -LINK_TEXT_TEMPLATE = """\ -View the commit online: -%(browse_url)s - -""" - -LINK_HTML_TEMPLATE = """\ -

View the commit online.

-""" - - -REVISION_FOOTER_TEMPLATE = FOOTER_TEMPLATE - - -# Combined, meaning refchange+revision email (for single-commit additions) -COMBINED_HEADER_TEMPLATE = """\ -Date: %(send_date)s -To: %(recipients)s -Subject: %(subject)s -MIME-Version: 1.0 -Content-Type: text/%(contenttype)s; charset=%(charset)s -Content-Transfer-Encoding: 8bit -Message-ID: %(msgid)s -From: %(fromaddr)s -Reply-To: %(reply_to)s -X-Git-Host: %(fqdn)s -X-Git-Repo: %(repo_shortname)s -X-Git-Refname: %(refname)s -X-Git-Reftype: %(refname_type)s -X-Git-Oldrev: %(oldrev)s -X-Git-Newrev: %(newrev)s -X-Git-Rev: %(rev)s -X-Git-NotificationType: ref_changed_plus_diff -X-Git-Multimail-Version: %(multimail_version)s -Auto-Submitted: auto-generated -""" - -COMBINED_INTRO_TEMPLATE = """\ -This is an automated email from the git hooks/post-receive script. - -%(pusher)s pushed a commit to %(refname_type)s %(short_refname)s -in repository %(repo_shortname)s. - -""" - -COMBINED_FOOTER_TEMPLATE = FOOTER_TEMPLATE - - -class CommandError(Exception): - def __init__(self, cmd, retcode): - self.cmd = cmd - self.retcode = retcode - Exception.__init__( - self, - 'Command "%s" failed with retcode %s' % (' '.join(cmd), retcode,) - ) - - -class ConfigurationException(Exception): - pass - - -# The "git" program (this could be changed to include a full path): -GIT_EXECUTABLE = 'git' - - -# How "git" should be invoked (including global arguments), as a list -# of words. This variable is usually initialized automatically by -# read_git_output() via choose_git_command(), but if a value is set -# here then it will be used unconditionally. -GIT_CMD = None - - -def choose_git_command(): - """Decide how to invoke git, and record the choice in GIT_CMD.""" - - global GIT_CMD - - if GIT_CMD is None: - try: - # Check to see whether the "-c" option is accepted (it was - # only added in Git 1.7.2). We don't actually use the - # output of "git --version", though if we needed more - # specific version information this would be the place to - # do it. - cmd = [GIT_EXECUTABLE, '-c', 'foo.bar=baz', '--version'] - read_output(cmd) - GIT_CMD = [GIT_EXECUTABLE, '-c', 'i18n.logoutputencoding=%s' % (ENCODING,)] - except CommandError: - GIT_CMD = [GIT_EXECUTABLE] - - -def read_git_output(args, input=None, keepends=False, **kw): - """Read the output of a Git command.""" - - if GIT_CMD is None: - choose_git_command() - - return read_output(GIT_CMD + args, input=input, keepends=keepends, **kw) - - -def read_output(cmd, input=None, keepends=False, **kw): - if input: - stdin = subprocess.PIPE - input = str_to_bytes(input) - else: - stdin = None - errors = 'strict' - if 'errors' in kw: - errors = kw['errors'] - del kw['errors'] - p = subprocess.Popen( - tuple(str_to_bytes(w) for w in cmd), - stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kw - ) - (out, err) = p.communicate(input) - out = bytes_to_str(out, errors=errors) - retcode = p.wait() - if retcode: - raise CommandError(cmd, retcode) - if not keepends: - out = out.rstrip('\n\r') - return out - - -def read_git_lines(args, keepends=False, **kw): - """Return the lines output by Git command. - - Return as single lines, with newlines stripped off.""" - - return read_git_output(args, keepends=True, **kw).splitlines(keepends) - - -def git_rev_list_ish(cmd, spec, args=None, **kw): - """Common functionality for invoking a 'git rev-list'-like command. - - Parameters: - * cmd is the Git command to run, e.g., 'rev-list' or 'log'. - * spec is a list of revision arguments to pass to the named - command. If None, this function returns an empty list. - * args is a list of extra arguments passed to the named command. - * All other keyword arguments (if any) are passed to the - underlying read_git_lines() function. - - Return the output of the Git command in the form of a list, one - entry per output line. - """ - if spec is None: - return [] - if args is None: - args = [] - args = [cmd, '--stdin'] + args - spec_stdin = ''.join(s + '\n' for s in spec) - return read_git_lines(args, input=spec_stdin, **kw) - - -def git_rev_list(spec, **kw): - """Run 'git rev-list' with the given list of revision arguments. - - See git_rev_list_ish() for parameter and return value - documentation. - """ - return git_rev_list_ish('rev-list', spec, **kw) - - -def git_log(spec, **kw): - """Run 'git log' with the given list of revision arguments. - - See git_rev_list_ish() for parameter and return value - documentation. - """ - return git_rev_list_ish('log', spec, **kw) - - -def header_encode(text, header_name=None): - """Encode and line-wrap the value of an email header field.""" - - # Convert to unicode, if required. - if not isinstance(text, unicode): - text = unicode(text, 'utf-8') - - if is_ascii(text): - charset = 'ascii' - else: - charset = 'utf-8' - - return Header(text, header_name=header_name, charset=Charset(charset)).encode() - - -def addr_header_encode(text, header_name=None): - """Encode and line-wrap the value of an email header field containing - email addresses.""" - - # Convert to unicode, if required. - if not isinstance(text, unicode): - text = unicode(text, 'utf-8') - - text = ', '.join( - formataddr((header_encode(name), emailaddr)) - for name, emailaddr in getaddresses([text]) - ) - - if is_ascii(text): - charset = 'ascii' - else: - charset = 'utf-8' - - return Header(text, header_name=header_name, charset=Charset(charset)).encode() - - -class Config(object): - def __init__(self, section, git_config=None): - """Represent a section of the git configuration. - - If git_config is specified, it is passed to "git config" in - the GIT_CONFIG environment variable, meaning that "git config" - will read the specified path rather than the Git default - config paths.""" - - self.section = section - if git_config: - self.env = os.environ.copy() - self.env['GIT_CONFIG'] = git_config - else: - self.env = None - - @staticmethod - def _split(s): - """Split NUL-terminated values.""" - - words = s.split('\0') - assert words[-1] == '' - return words[:-1] - - @staticmethod - def add_config_parameters(c): - """Add configuration parameters to Git. - - c is either an str or a list of str, each element being of the - form 'var=val' or 'var', with the same syntax and meaning as - the argument of 'git -c var=val'. - """ - if isinstance(c, str): - c = (c,) - parameters = os.environ.get('GIT_CONFIG_PARAMETERS', '') - if parameters: - parameters += ' ' - # git expects GIT_CONFIG_PARAMETERS to be of the form - # "'name1=value1' 'name2=value2' 'name3=value3'" - # including everything inside the double quotes (but not the double - # quotes themselves). Spacing is critical. Also, if a value contains - # a literal single quote that quote must be represented using the - # four character sequence: '\'' - parameters += ' '.join("'" + x.replace("'", "'\\''") + "'" for x in c) - os.environ['GIT_CONFIG_PARAMETERS'] = parameters - - def get(self, name, default=None): - try: - values = self._split(read_git_output( - ['config', '--get', '--null', '%s.%s' % (self.section, name)], - env=self.env, keepends=True, - )) - assert len(values) == 1 - return values[0] - except CommandError: - return default - - def get_bool(self, name, default=None): - try: - value = read_git_output( - ['config', '--get', '--bool', '%s.%s' % (self.section, name)], - env=self.env, - ) - except CommandError: - return default - return value == 'true' - - def get_all(self, name, default=None): - """Read a (possibly multivalued) setting from the configuration. - - Return the result as a list of values, or default if the name - is unset.""" - - try: - return self._split(read_git_output( - ['config', '--get-all', '--null', '%s.%s' % (self.section, name)], - env=self.env, keepends=True, - )) - except CommandError: - t, e, traceback = sys.exc_info() - if e.retcode == 1: - # "the section or key is invalid"; i.e., there is no - # value for the specified key. - return default - else: - raise - - def set(self, name, value): - read_git_output( - ['config', '%s.%s' % (self.section, name), value], - env=self.env, - ) - - def add(self, name, value): - read_git_output( - ['config', '--add', '%s.%s' % (self.section, name), value], - env=self.env, - ) - - def __contains__(self, name): - return self.get_all(name, default=None) is not None - - # We don't use this method anymore internally, but keep it here in - # case somebody is calling it from their own code: - def has_key(self, name): - return name in self - - def unset_all(self, name): - try: - read_git_output( - ['config', '--unset-all', '%s.%s' % (self.section, name)], - env=self.env, - ) - except CommandError: - t, e, traceback = sys.exc_info() - if e.retcode == 5: - # The name doesn't exist, which is what we wanted anyway... - pass - else: - raise - - def set_recipients(self, name, value): - self.unset_all(name) - for pair in getaddresses([value]): - self.add(name, formataddr(pair)) - - -def generate_summaries(*log_args): - """Generate a brief summary for each revision requested. - - log_args are strings that will be passed directly to "git log" as - revision selectors. Iterate over (sha1_short, subject) for each - commit specified by log_args (subject is the first line of the - commit message as a string without EOLs).""" - - cmd = [ - 'log', '--abbrev', '--format=%h %s', - ] + list(log_args) + ['--'] - for line in read_git_lines(cmd): - yield tuple(line.split(' ', 1)) - - -def limit_lines(lines, max_lines): - for (index, line) in enumerate(lines): - if index < max_lines: - yield line - - if index >= max_lines: - yield '... %d lines suppressed ...\n' % (index + 1 - max_lines,) - - -def limit_linelength(lines, max_linelength): - for line in lines: - # Don't forget that lines always include a trailing newline. - if len(line) > max_linelength + 1: - line = line[:max_linelength - 7] + ' [...]\n' - yield line - - -class CommitSet(object): - """A (constant) set of object names. - - The set should be initialized with full SHA1 object names. The - __contains__() method returns True iff its argument is an - abbreviation of any the names in the set.""" - - def __init__(self, names): - self._names = sorted(names) - - def __len__(self): - return len(self._names) - - def __contains__(self, sha1_abbrev): - """Return True iff this set contains sha1_abbrev (which might be abbreviated).""" - - i = bisect.bisect_left(self._names, sha1_abbrev) - return i < len(self) and self._names[i].startswith(sha1_abbrev) - - -class GitObject(object): - def __init__(self, sha1, type=None): - if sha1 == ZEROS: - self.sha1 = self.type = self.commit_sha1 = None - else: - self.sha1 = sha1 - self.type = type or read_git_output(['cat-file', '-t', self.sha1]) - - if self.type == 'commit': - self.commit_sha1 = self.sha1 - elif self.type == 'tag': - try: - self.commit_sha1 = read_git_output( - ['rev-parse', '--verify', '%s^0' % (self.sha1,)] - ) - except CommandError: - # Cannot deref tag to determine commit_sha1 - self.commit_sha1 = None - else: - self.commit_sha1 = None - - self.short = read_git_output(['rev-parse', '--short', sha1]) - - def get_summary(self): - """Return (sha1_short, subject) for this commit.""" - - if not self.sha1: - raise ValueError('Empty commit has no summary') - - return next(iter(generate_summaries('--no-walk', self.sha1))) - - def __eq__(self, other): - return isinstance(other, GitObject) and self.sha1 == other.sha1 - - def __ne__(self, other): - return not self == other - - def __hash__(self): - return hash(self.sha1) - - def __nonzero__(self): - return bool(self.sha1) - - def __bool__(self): - """Python 2 backward compatibility""" - return self.__nonzero__() - - def __str__(self): - return self.sha1 or ZEROS - - -class Change(object): - """A Change that has been made to the Git repository. - - Abstract class from which both Revisions and ReferenceChanges are - derived. A Change knows how to generate a notification email - describing itself.""" - - def __init__(self, environment): - self.environment = environment - self._values = None - self._contains_html_diff = False - - def _contains_diff(self): - # We do contain a diff, should it be rendered in HTML? - if self.environment.commit_email_format == "html": - self._contains_html_diff = True - - def _compute_values(self): - """Return a dictionary {keyword: expansion} for this Change. - - Derived classes overload this method to add more entries to - the return value. This method is used internally by - get_values(). The return value should always be a new - dictionary.""" - - values = self.environment.get_values() - fromaddr = self.environment.get_fromaddr(change=self) - if fromaddr is not None: - values['fromaddr'] = fromaddr - values['multimail_version'] = get_version() - return values - - # Aliases usable in template strings. Tuple of pairs (destination, - # source). - VALUES_ALIAS = ( - ("id", "newrev"), - ) - - def get_values(self, **extra_values): - """Return a dictionary {keyword: expansion} for this Change. - - Return a dictionary mapping keywords to the values that they - should be expanded to for this Change (used when interpolating - template strings). If any keyword arguments are supplied, add - those to the return value as well. The return value is always - a new dictionary.""" - - if self._values is None: - self._values = self._compute_values() - - values = self._values.copy() - if extra_values: - values.update(extra_values) - - for alias, val in self.VALUES_ALIAS: - values[alias] = values[val] - return values - - def expand(self, template, **extra_values): - """Expand template. - - Expand the template (which should be a string) using string - interpolation of the values for this Change. If any keyword - arguments are provided, also include those in the keywords - available for interpolation.""" - - return template % self.get_values(**extra_values) - - def expand_lines(self, template, html_escape_val=False, **extra_values): - """Break template into lines and expand each line.""" - - values = self.get_values(**extra_values) - if html_escape_val: - for k in values: - if is_string(values[k]): - values[k] = html_escape(values[k]) - for line in template.splitlines(True): - yield line % values - - def expand_header_lines(self, template, **extra_values): - """Break template into lines and expand each line as an RFC 2822 header. - - Encode values and split up lines that are too long. Silently - skip lines that contain references to unknown variables.""" - - values = self.get_values(**extra_values) - if self._contains_html_diff: - self._content_type = 'html' - else: - self._content_type = 'plain' - values['contenttype'] = self._content_type - - for line in template.splitlines(): - (name, value) = line.split(': ', 1) - - try: - value = value % values - except KeyError: - t, e, traceback = sys.exc_info() - if DEBUG: - self.environment.log_warning( - 'Warning: unknown variable %r in the following line; line skipped:\n' - ' %s\n' - % (e.args[0], line,) - ) - else: - if name.lower() in ADDR_HEADERS: - value = addr_header_encode(value, name) - else: - value = header_encode(value, name) - for splitline in ('%s: %s\n' % (name, value)).splitlines(True): - yield splitline - - def generate_email_header(self): - """Generate the RFC 2822 email headers for this Change, a line at a time. - - The output should not include the trailing blank line.""" - - raise NotImplementedError() - - def generate_browse_link(self, base_url): - """Generate a link to an online repository browser.""" - return iter(()) - - def generate_email_intro(self, html_escape_val=False): - """Generate the email intro for this Change, a line at a time. - - The output will be used as the standard boilerplate at the top - of the email body.""" - - raise NotImplementedError() - - def generate_email_body(self, push): - """Generate the main part of the email body, a line at a time. - - The text in the body might be truncated after a specified - number of lines (see multimailhook.emailmaxlines).""" - - raise NotImplementedError() - - def generate_email_footer(self, html_escape_val): - """Generate the footer of the email, a line at a time. - - The footer is always included, irrespective of - multimailhook.emailmaxlines.""" - - raise NotImplementedError() - - def _wrap_for_html(self, lines): - """Wrap the lines in HTML
 tag when using HTML format.
-
-        Escape special HTML characters and add 
 and 
tags around - the given lines if we should be generating HTML as indicated by - self._contains_html_diff being set to true. - """ - if self._contains_html_diff: - yield "
\n"
-
-            for line in lines:
-                yield html_escape(line)
-
-            yield '
\n' - else: - for line in lines: - yield line - - def generate_email(self, push, body_filter=None, extra_header_values={}): - """Generate an email describing this change. - - Iterate over the lines (including the header lines) of an - email describing this change. If body_filter is not None, - then use it to filter the lines that are intended for the - email body. - - The extra_header_values field is received as a dict and not as - **kwargs, to allow passing other keyword arguments in the - future (e.g. passing extra values to generate_email_intro()""" - - for line in self.generate_email_header(**extra_header_values): - yield line - yield '\n' - html_escape_val = (self.environment.html_in_intro and - self._contains_html_diff) - intro = self.generate_email_intro(html_escape_val) - if not self.environment.html_in_intro: - intro = self._wrap_for_html(intro) - for line in intro: - yield line - - if self.environment.commitBrowseURL: - for line in self.generate_browse_link(self.environment.commitBrowseURL): - yield line - - body = self.generate_email_body(push) - if body_filter is not None: - body = body_filter(body) - - diff_started = False - if self._contains_html_diff: - # "white-space: pre" is the default, but we need to - # specify it again in case the message is viewed in a - # webmail which wraps it in an element setting white-space - # to something else (Zimbra does this and sets - # white-space: pre-line). - yield '
'
-        for line in body:
-            if self._contains_html_diff:
-                # This is very, very naive. It would be much better to really
-                # parse the diff, i.e. look at how many lines do we have in
-                # the hunk headers instead of blindly highlighting everything
-                # that looks like it might be part of a diff.
-                bgcolor = ''
-                fgcolor = ''
-                if line.startswith('--- a/'):
-                    diff_started = True
-                    bgcolor = 'e0e0ff'
-                elif line.startswith('diff ') or line.startswith('index '):
-                    diff_started = True
-                    fgcolor = '808080'
-                elif diff_started:
-                    if line.startswith('+++ '):
-                        bgcolor = 'e0e0ff'
-                    elif line.startswith('@@'):
-                        bgcolor = 'e0e0e0'
-                    elif line.startswith('+'):
-                        bgcolor = 'e0ffe0'
-                    elif line.startswith('-'):
-                        bgcolor = 'ffe0e0'
-                elif line.startswith('commit '):
-                    fgcolor = '808000'
-                elif line.startswith('    '):
-                    fgcolor = '404040'
-
-                # Chop the trailing LF, we don't want it inside 
.
-                line = html_escape(line[:-1])
-
-                if bgcolor or fgcolor:
-                    style = 'display:block; white-space:pre;'
-                    if bgcolor:
-                        style += 'background:#' + bgcolor + ';'
-                    if fgcolor:
-                        style += 'color:#' + fgcolor + ';'
-                    # Use a %s\n" % (style, line)
-                else:
-                    line = line + '\n'
-
-            yield line
-        if self._contains_html_diff:
-            yield '
' - html_escape_val = (self.environment.html_in_footer and - self._contains_html_diff) - footer = self.generate_email_footer(html_escape_val) - if not self.environment.html_in_footer: - footer = self._wrap_for_html(footer) - for line in footer: - yield line - - def get_specific_fromaddr(self): - """For kinds of Changes which specify it, return the kind-specific - From address to use.""" - return None - - -class Revision(Change): - """A Change consisting of a single git commit.""" - - CC_RE = re.compile(r'^\s*C[Cc]:\s*(?P[^#]+@[^\s#]*)\s*(#.*)?$') - - def __init__(self, reference_change, rev, num, tot): - Change.__init__(self, reference_change.environment) - self.reference_change = reference_change - self.rev = rev - self.change_type = self.reference_change.change_type - self.refname = self.reference_change.refname - self.num = num - self.tot = tot - self.author = read_git_output(['log', '--no-walk', '--format=%aN <%aE>', self.rev.sha1]) - self.recipients = self.environment.get_revision_recipients(self) - - # -s is short for --no-patch, but -s works on older git's (e.g. 1.7) - self.parents = read_git_lines(['show', '-s', '--format=%P', - self.rev.sha1])[0].split() - - self.cc_recipients = '' - if self.environment.get_scancommitforcc(): - self.cc_recipients = ', '.join(to.strip() for to in self._cc_recipients()) - if self.cc_recipients: - self.environment.log_msg( - 'Add %s to CC for %s' % (self.cc_recipients, self.rev.sha1)) - - def _cc_recipients(self): - cc_recipients = [] - message = read_git_output(['log', '--no-walk', '--format=%b', self.rev.sha1]) - lines = message.strip().split('\n') - for line in lines: - m = re.match(self.CC_RE, line) - if m: - cc_recipients.append(m.group('to')) - - return cc_recipients - - def _compute_values(self): - values = Change._compute_values(self) - - oneline = read_git_output( - ['log', '--format=%s', '--no-walk', self.rev.sha1] - ) - - max_subject_length = self.environment.get_max_subject_length() - if max_subject_length > 0 and len(oneline) > max_subject_length: - oneline = oneline[:max_subject_length - 6] + ' [...]' - - values['rev'] = self.rev.sha1 - values['parents'] = ' '.join(self.parents) - values['rev_short'] = self.rev.short - values['change_type'] = self.change_type - values['refname'] = self.refname - values['newrev'] = self.rev.sha1 - values['short_refname'] = self.reference_change.short_refname - values['refname_type'] = self.reference_change.refname_type - values['reply_to_msgid'] = self.reference_change.msgid - values['thread_index'] = self.reference_change.thread_index - values['num'] = self.num - values['tot'] = self.tot - values['recipients'] = self.recipients - if self.cc_recipients: - values['cc_recipients'] = self.cc_recipients - values['oneline'] = oneline - values['author'] = self.author - - reply_to = self.environment.get_reply_to_commit(self) - if reply_to: - values['reply_to'] = reply_to - - return values - - def generate_email_header(self, **extra_values): - for line in self.expand_header_lines( - REVISION_HEADER_TEMPLATE, **extra_values - ): - yield line - - def generate_browse_link(self, base_url): - if '%(' not in base_url: - base_url += '%(id)s' - url = "".join(self.expand_lines(base_url)) - if self._content_type == 'html': - for line in self.expand_lines(LINK_HTML_TEMPLATE, - html_escape_val=True, - browse_url=url): - yield line - elif self._content_type == 'plain': - for line in self.expand_lines(LINK_TEXT_TEMPLATE, - html_escape_val=False, - browse_url=url): - yield line - else: - raise NotImplementedError("Content-type %s unsupported. Please report it as a bug.") - - def generate_email_intro(self, html_escape_val=False): - for line in self.expand_lines(REVISION_INTRO_TEMPLATE, - html_escape_val=html_escape_val): - yield line - - def generate_email_body(self, push): - """Show this revision.""" - - for line in read_git_lines( - ['log'] + self.environment.commitlogopts + ['-1', self.rev.sha1], - keepends=True, - errors='replace'): - if line.startswith('Date: ') and self.environment.date_substitute: - yield self.environment.date_substitute + line[len('Date: '):] - else: - yield line - - def generate_email_footer(self, html_escape_val): - return self.expand_lines(REVISION_FOOTER_TEMPLATE, - html_escape_val=html_escape_val) - - def generate_email(self, push, body_filter=None, extra_header_values={}): - self._contains_diff() - return Change.generate_email(self, push, body_filter, extra_header_values) - - def get_specific_fromaddr(self): - return self.environment.from_commit - - -class ReferenceChange(Change): - """A Change to a Git reference. - - An abstract class representing a create, update, or delete of a - Git reference. Derived classes handle specific types of reference - (e.g., tags vs. branches). These classes generate the main - reference change email summarizing the reference change and - whether it caused any any commits to be added or removed. - - ReferenceChange objects are usually created using the static - create() method, which has the logic to decide which derived class - to instantiate.""" - - REF_RE = re.compile(r'^refs\/(?P[^\/]+)\/(?P.*)$') - - @staticmethod - def create(environment, oldrev, newrev, refname): - """Return a ReferenceChange object representing the change. - - Return an object that represents the type of change that is being - made. oldrev and newrev should be SHA1s or ZEROS.""" - - old = GitObject(oldrev) - new = GitObject(newrev) - rev = new or old - - # The revision type tells us what type the commit is, combined with - # the location of the ref we can decide between - # - working branch - # - tracking branch - # - unannotated tag - # - annotated tag - m = ReferenceChange.REF_RE.match(refname) - if m: - area = m.group('area') - short_refname = m.group('shortname') - else: - area = '' - short_refname = refname - - if rev.type == 'tag': - # Annotated tag: - klass = AnnotatedTagChange - elif rev.type == 'commit': - if area == 'tags': - # Non-annotated tag: - klass = NonAnnotatedTagChange - elif area == 'heads': - # Branch: - klass = BranchChange - elif area == 'remotes': - # Tracking branch: - environment.log_warning( - '*** Push-update of tracking branch %r\n' - '*** - incomplete email generated.' - % (refname,) - ) - klass = OtherReferenceChange - else: - # Some other reference namespace: - environment.log_warning( - '*** Push-update of strange reference %r\n' - '*** - incomplete email generated.' - % (refname,) - ) - klass = OtherReferenceChange - else: - # Anything else (is there anything else?) - environment.log_warning( - '*** Unknown type of update to %r (%s)\n' - '*** - incomplete email generated.' - % (refname, rev.type,) - ) - klass = OtherReferenceChange - - return klass( - environment, - refname=refname, short_refname=short_refname, - old=old, new=new, rev=rev, - ) - - @staticmethod - def make_thread_index(): - """Return a string appropriate for the Thread-Index header, - needed by MS Outlook to get threading right. - - The format is (base64-encoded): - - 1 byte must be 1 - - 5 bytes encode a date (hardcoded here) - - 16 bytes for a globally unique identifier - - FIXME: Unfortunately, even with the Thread-Index field, MS - Outlook doesn't seem to do the threading reliably (see - https://github.com/git-multimail/git-multimail/pull/194). - """ - thread_index = b'\x01\x00\x00\x12\x34\x56' + uuid.uuid4().bytes - return base64.standard_b64encode(thread_index).decode('ascii') - - def __init__(self, environment, refname, short_refname, old, new, rev): - Change.__init__(self, environment) - self.change_type = { - (False, True): 'create', - (True, True): 'update', - (True, False): 'delete', - }[bool(old), bool(new)] - self.refname = refname - self.short_refname = short_refname - self.old = old - self.new = new - self.rev = rev - self.msgid = make_msgid() - self.thread_index = self.make_thread_index() - self.diffopts = environment.diffopts - self.graphopts = environment.graphopts - self.logopts = environment.logopts - self.commitlogopts = environment.commitlogopts - self.showgraph = environment.refchange_showgraph - self.showlog = environment.refchange_showlog - - self.header_template = REFCHANGE_HEADER_TEMPLATE - self.intro_template = REFCHANGE_INTRO_TEMPLATE - self.footer_template = FOOTER_TEMPLATE - - def _compute_values(self): - values = Change._compute_values(self) - - values['change_type'] = self.change_type - values['refname_type'] = self.refname_type - values['refname'] = self.refname - values['short_refname'] = self.short_refname - values['msgid'] = self.msgid - values['thread_index'] = self.thread_index - values['recipients'] = self.recipients - values['oldrev'] = str(self.old) - values['oldrev_short'] = self.old.short - values['newrev'] = str(self.new) - values['newrev_short'] = self.new.short - - if self.old: - values['oldrev_type'] = self.old.type - if self.new: - values['newrev_type'] = self.new.type - - reply_to = self.environment.get_reply_to_refchange(self) - if reply_to: - values['reply_to'] = reply_to - - return values - - def send_single_combined_email(self, known_added_sha1s): - """Determine if a combined refchange/revision email should be sent - - If there is only a single new (non-merge) commit added by a - change, it is useful to combine the ReferenceChange and - Revision emails into one. In such a case, return the single - revision; otherwise, return None. - - This method is overridden in BranchChange.""" - - return None - - def generate_combined_email(self, push, revision, body_filter=None, extra_header_values={}): - """Generate an email describing this change AND specified revision. - - Iterate over the lines (including the header lines) of an - email describing this change. If body_filter is not None, - then use it to filter the lines that are intended for the - email body. - - The extra_header_values field is received as a dict and not as - **kwargs, to allow passing other keyword arguments in the - future (e.g. passing extra values to generate_email_intro() - - This method is overridden in BranchChange.""" - - raise NotImplementedError - - def get_subject(self): - template = { - 'create': REF_CREATED_SUBJECT_TEMPLATE, - 'update': REF_UPDATED_SUBJECT_TEMPLATE, - 'delete': REF_DELETED_SUBJECT_TEMPLATE, - }[self.change_type] - return self.expand(template) - - def generate_email_header(self, **extra_values): - if 'subject' not in extra_values: - extra_values['subject'] = self.get_subject() - - for line in self.expand_header_lines( - self.header_template, **extra_values - ): - yield line - - def generate_email_intro(self, html_escape_val=False): - for line in self.expand_lines(self.intro_template, - html_escape_val=html_escape_val): - yield line - - def generate_email_body(self, push): - """Call the appropriate body-generation routine. - - Call one of generate_create_summary() / - generate_update_summary() / generate_delete_summary().""" - - change_summary = { - 'create': self.generate_create_summary, - 'delete': self.generate_delete_summary, - 'update': self.generate_update_summary, - }[self.change_type](push) - for line in change_summary: - yield line - - for line in self.generate_revision_change_summary(push): - yield line - - def generate_email_footer(self, html_escape_val): - return self.expand_lines(self.footer_template, - html_escape_val=html_escape_val) - - def generate_revision_change_graph(self, push): - if self.showgraph: - args = ['--graph'] + self.graphopts - for newold in ('new', 'old'): - has_newold = False - spec = push.get_commits_spec(newold, self) - for line in git_log(spec, args=args, keepends=True): - if not has_newold: - has_newold = True - yield '\n' - yield 'Graph of %s commits:\n\n' % ( - {'new': 'new', 'old': 'discarded'}[newold],) - yield ' ' + line - if has_newold: - yield '\n' - - def generate_revision_change_log(self, new_commits_list): - if self.showlog: - yield '\n' - yield 'Detailed log of new commits:\n\n' - for line in read_git_lines( - ['log', '--no-walk'] + - self.logopts + - new_commits_list + - ['--'], - keepends=True, - ): - yield line - - def generate_new_revision_summary(self, tot, new_commits_list, push): - for line in self.expand_lines(NEW_REVISIONS_TEMPLATE, tot=tot): - yield line - for line in self.generate_revision_change_graph(push): - yield line - for line in self.generate_revision_change_log(new_commits_list): - yield line - - def generate_revision_change_summary(self, push): - """Generate a summary of the revisions added/removed by this change.""" - - if self.new.commit_sha1 and not self.old.commit_sha1: - # A new reference was created. List the new revisions - # brought by the new reference (i.e., those revisions that - # were not in the repository before this reference - # change). - sha1s = list(push.get_new_commits(self)) - sha1s.reverse() - tot = len(sha1s) - new_revisions = [ - Revision(self, GitObject(sha1), num=i + 1, tot=tot) - for (i, sha1) in enumerate(sha1s) - ] - - if new_revisions: - yield self.expand('This %(refname_type)s includes the following new commits:\n') - yield '\n' - for r in new_revisions: - (sha1, subject) = r.rev.get_summary() - yield r.expand( - BRIEF_SUMMARY_TEMPLATE, action='new', text=subject, - ) - yield '\n' - for line in self.generate_new_revision_summary( - tot, [r.rev.sha1 for r in new_revisions], push): - yield line - else: - for line in self.expand_lines(NO_NEW_REVISIONS_TEMPLATE): - yield line - - elif self.new.commit_sha1 and self.old.commit_sha1: - # A reference was changed to point at a different commit. - # List the revisions that were removed and/or added *from - # that reference* by this reference change, along with a - # diff between the trees for its old and new values. - - # List of the revisions that were added to the branch by - # this update. Note this list can include revisions that - # have already had notification emails; we want such - # revisions in the summary even though we will not send - # new notification emails for them. - adds = list(generate_summaries( - '--topo-order', '--reverse', '%s..%s' - % (self.old.commit_sha1, self.new.commit_sha1,) - )) - - # List of the revisions that were removed from the branch - # by this update. This will be empty except for - # non-fast-forward updates. - discards = list(generate_summaries( - '%s..%s' % (self.new.commit_sha1, self.old.commit_sha1,) - )) - - if adds: - new_commits_list = push.get_new_commits(self) - else: - new_commits_list = [] - new_commits = CommitSet(new_commits_list) - - if discards: - discarded_commits = CommitSet(push.get_discarded_commits(self)) - else: - discarded_commits = CommitSet([]) - - if discards and adds: - for (sha1, subject) in discards: - if sha1 in discarded_commits: - action = 'discard' - else: - action = 'omit' - yield self.expand( - BRIEF_SUMMARY_TEMPLATE, action=action, - rev_short=sha1, text=subject, - ) - for (sha1, subject) in adds: - if sha1 in new_commits: - action = 'new' - else: - action = 'add' - yield self.expand( - BRIEF_SUMMARY_TEMPLATE, action=action, - rev_short=sha1, text=subject, - ) - yield '\n' - for line in self.expand_lines(NON_FF_TEMPLATE): - yield line - - elif discards: - for (sha1, subject) in discards: - if sha1 in discarded_commits: - action = 'discard' - else: - action = 'omit' - yield self.expand( - BRIEF_SUMMARY_TEMPLATE, action=action, - rev_short=sha1, text=subject, - ) - yield '\n' - for line in self.expand_lines(REWIND_ONLY_TEMPLATE): - yield line - - elif adds: - (sha1, subject) = self.old.get_summary() - yield self.expand( - BRIEF_SUMMARY_TEMPLATE, action='from', - rev_short=sha1, text=subject, - ) - for (sha1, subject) in adds: - if sha1 in new_commits: - action = 'new' - else: - action = 'add' - yield self.expand( - BRIEF_SUMMARY_TEMPLATE, action=action, - rev_short=sha1, text=subject, - ) - - yield '\n' - - if new_commits: - for line in self.generate_new_revision_summary( - len(new_commits), new_commits_list, push): - yield line - else: - for line in self.expand_lines(NO_NEW_REVISIONS_TEMPLATE): - yield line - for line in self.generate_revision_change_graph(push): - yield line - - # The diffstat is shown from the old revision to the new - # revision. This is to show the truth of what happened in - # this change. There's no point showing the stat from the - # base to the new revision because the base is effectively a - # random revision at this point - the user will be interested - # in what this revision changed - including the undoing of - # previous revisions in the case of non-fast-forward updates. - yield '\n' - yield 'Summary of changes:\n' - for line in read_git_lines( - ['diff-tree'] + - self.diffopts + - ['%s..%s' % (self.old.commit_sha1, self.new.commit_sha1,)], - keepends=True, - ): - yield line - - elif self.old.commit_sha1 and not self.new.commit_sha1: - # A reference was deleted. List the revisions that were - # removed from the repository by this reference change. - - sha1s = list(push.get_discarded_commits(self)) - tot = len(sha1s) - discarded_revisions = [ - Revision(self, GitObject(sha1), num=i + 1, tot=tot) - for (i, sha1) in enumerate(sha1s) - ] - - if discarded_revisions: - for line in self.expand_lines(DISCARDED_REVISIONS_TEMPLATE): - yield line - yield '\n' - for r in discarded_revisions: - (sha1, subject) = r.rev.get_summary() - yield r.expand( - BRIEF_SUMMARY_TEMPLATE, action='discard', text=subject, - ) - for line in self.generate_revision_change_graph(push): - yield line - else: - for line in self.expand_lines(NO_DISCARDED_REVISIONS_TEMPLATE): - yield line - - elif not self.old.commit_sha1 and not self.new.commit_sha1: - for line in self.expand_lines(NON_COMMIT_UPDATE_TEMPLATE): - yield line - - def generate_create_summary(self, push): - """Called for the creation of a reference.""" - - # This is a new reference and so oldrev is not valid - (sha1, subject) = self.new.get_summary() - yield self.expand( - BRIEF_SUMMARY_TEMPLATE, action='at', - rev_short=sha1, text=subject, - ) - yield '\n' - - def generate_update_summary(self, push): - """Called for the change of a pre-existing branch.""" - - return iter([]) - - def generate_delete_summary(self, push): - """Called for the deletion of any type of reference.""" - - (sha1, subject) = self.old.get_summary() - yield self.expand( - BRIEF_SUMMARY_TEMPLATE, action='was', - rev_short=sha1, text=subject, - ) - yield '\n' - - def get_specific_fromaddr(self): - return self.environment.from_refchange - - -class BranchChange(ReferenceChange): - refname_type = 'branch' - - def __init__(self, environment, refname, short_refname, old, new, rev): - ReferenceChange.__init__( - self, environment, - refname=refname, short_refname=short_refname, - old=old, new=new, rev=rev, - ) - self.recipients = environment.get_refchange_recipients(self) - self._single_revision = None - - def send_single_combined_email(self, known_added_sha1s): - if not self.environment.combine_when_single_commit: - return None - - # In the sadly-all-too-frequent usecase of people pushing only - # one of their commits at a time to a repository, users feel - # the reference change summary emails are noise rather than - # important signal. This is because, in this particular - # usecase, there is a reference change summary email for each - # new commit, and all these summaries do is point out that - # there is one new commit (which can readily be inferred by - # the existence of the individual revision email that is also - # sent). In such cases, our users prefer there to be a combined - # reference change summary/new revision email. - # - # So, if the change is an update and it doesn't discard any - # commits, and it adds exactly one non-merge commit (gerrit - # forces a workflow where every commit is individually merged - # and the git-multimail hook fired off for just this one - # change), then we send a combined refchange/revision email. - try: - # If this change is a reference update that doesn't discard - # any commits... - if self.change_type != 'update': - return None - - if read_git_lines( - ['merge-base', self.old.sha1, self.new.sha1] - ) != [self.old.sha1]: - return None - - # Check if this update introduced exactly one non-merge - # commit: - - def split_line(line): - """Split line into (sha1, [parent,...]).""" - - words = line.split() - return (words[0], words[1:]) - - # Get the new commits introduced by the push as a list of - # (sha1, [parent,...]) - new_commits = [ - split_line(line) - for line in read_git_lines( - [ - 'log', '-3', '--format=%H %P', - '%s..%s' % (self.old.sha1, self.new.sha1), - ] - ) - ] - - if not new_commits: - return None - - # If the newest commit is a merge, save it for a later check - # but otherwise ignore it - merge = None - tot = len(new_commits) - if len(new_commits[0][1]) > 1: - merge = new_commits[0][0] - del new_commits[0] - - # Our primary check: we can't combine if more than one commit - # is introduced. We also currently only combine if the new - # commit is a non-merge commit, though it may make sense to - # combine if it is a merge as well. - if not ( - len(new_commits) == 1 and - len(new_commits[0][1]) == 1 and - new_commits[0][0] in known_added_sha1s - ): - return None - - # We do not want to combine revision and refchange emails if - # those go to separate locations. - rev = Revision(self, GitObject(new_commits[0][0]), 1, tot) - if rev.recipients != self.recipients: - return None - - # We ignored the newest commit if it was just a merge of the one - # commit being introduced. But we don't want to ignore that - # merge commit it it involved conflict resolutions. Check that. - if merge and merge != read_git_output(['diff-tree', '--cc', merge]): - return None - - # We can combine the refchange and one new revision emails - # into one. Return the Revision that a combined email should - # be sent about. - return rev - except CommandError: - # Cannot determine number of commits in old..new or new..old; - # don't combine reference/revision emails: - return None - - def generate_combined_email(self, push, revision, body_filter=None, extra_header_values={}): - values = revision.get_values() - if extra_header_values: - values.update(extra_header_values) - if 'subject' not in extra_header_values: - values['subject'] = self.expand(COMBINED_REFCHANGE_REVISION_SUBJECT_TEMPLATE, **values) - - self._single_revision = revision - self._contains_diff() - self.header_template = COMBINED_HEADER_TEMPLATE - self.intro_template = COMBINED_INTRO_TEMPLATE - self.footer_template = COMBINED_FOOTER_TEMPLATE - - def revision_gen_link(base_url): - # revision is used only to generate the body, and - # _content_type is set while generating headers. Get it - # from the BranchChange object. - revision._content_type = self._content_type - return revision.generate_browse_link(base_url) - self.generate_browse_link = revision_gen_link - for line in self.generate_email(push, body_filter, values): - yield line - - def generate_email_body(self, push): - '''Call the appropriate body generation routine. - - If this is a combined refchange/revision email, the special logic - for handling this combined email comes from this function. For - other cases, we just use the normal handling.''' - - # If self._single_revision isn't set; don't override - if not self._single_revision: - for line in super(BranchChange, self).generate_email_body(push): - yield line - return - - # This is a combined refchange/revision email; we first provide - # some info from the refchange portion, and then call the revision - # generate_email_body function to handle the revision portion. - adds = list(generate_summaries( - '--topo-order', '--reverse', '%s..%s' - % (self.old.commit_sha1, self.new.commit_sha1,) - )) - - yield self.expand("The following commit(s) were added to %(refname)s by this push:\n") - for (sha1, subject) in adds: - yield self.expand( - BRIEF_SUMMARY_TEMPLATE, action='new', - rev_short=sha1, text=subject, - ) - - yield self._single_revision.rev.short + " is described below\n" - yield '\n' - - for line in self._single_revision.generate_email_body(push): - yield line - - -class AnnotatedTagChange(ReferenceChange): - refname_type = 'annotated tag' - - def __init__(self, environment, refname, short_refname, old, new, rev): - ReferenceChange.__init__( - self, environment, - refname=refname, short_refname=short_refname, - old=old, new=new, rev=rev, - ) - self.recipients = environment.get_announce_recipients(self) - self.show_shortlog = environment.announce_show_shortlog - - ANNOTATED_TAG_FORMAT = ( - '%(*objectname)\n' - '%(*objecttype)\n' - '%(taggername)\n' - '%(taggerdate)' - ) - - def describe_tag(self, push): - """Describe the new value of an annotated tag.""" - - # Use git for-each-ref to pull out the individual fields from - # the tag - [tagobject, tagtype, tagger, tagged] = read_git_lines( - ['for-each-ref', '--format=%s' % (self.ANNOTATED_TAG_FORMAT,), self.refname], - ) - - yield self.expand( - BRIEF_SUMMARY_TEMPLATE, action='tagging', - rev_short=tagobject, text='(%s)' % (tagtype,), - ) - if tagtype == 'commit': - # If the tagged object is a commit, then we assume this is a - # release, and so we calculate which tag this tag is - # replacing - try: - prevtag = read_git_output(['describe', '--abbrev=0', '%s^' % (self.new,)]) - except CommandError: - prevtag = None - if prevtag: - yield ' replaces %s\n' % (prevtag,) - else: - prevtag = None - yield ' length %s bytes\n' % (read_git_output(['cat-file', '-s', tagobject]),) - - yield ' by %s\n' % (tagger,) - yield ' on %s\n' % (tagged,) - yield '\n' - - # Show the content of the tag message; this might contain a - # change log or release notes so is worth displaying. - yield LOGBEGIN - contents = list(read_git_lines(['cat-file', 'tag', self.new.sha1], keepends=True)) - contents = contents[contents.index('\n') + 1:] - if contents and contents[-1][-1:] != '\n': - contents.append('\n') - for line in contents: - yield line - - if self.show_shortlog and tagtype == 'commit': - # Only commit tags make sense to have rev-list operations - # performed on them - yield '\n' - if prevtag: - # Show changes since the previous release - revlist = read_git_output( - ['rev-list', '--pretty=short', '%s..%s' % (prevtag, self.new,)], - keepends=True, - ) - else: - # No previous tag, show all the changes since time - # began - revlist = read_git_output( - ['rev-list', '--pretty=short', '%s' % (self.new,)], - keepends=True, - ) - for line in read_git_lines(['shortlog'], input=revlist, keepends=True): - yield line - - yield LOGEND - yield '\n' - - def generate_create_summary(self, push): - """Called for the creation of an annotated tag.""" - - for line in self.expand_lines(TAG_CREATED_TEMPLATE): - yield line - - for line in self.describe_tag(push): - yield line - - def generate_update_summary(self, push): - """Called for the update of an annotated tag. - - This is probably a rare event and may not even be allowed.""" - - for line in self.expand_lines(TAG_UPDATED_TEMPLATE): - yield line - - for line in self.describe_tag(push): - yield line - - def generate_delete_summary(self, push): - """Called when a non-annotated reference is updated.""" - - for line in self.expand_lines(TAG_DELETED_TEMPLATE): - yield line - - yield self.expand(' tag was %(oldrev_short)s\n') - yield '\n' - - -class NonAnnotatedTagChange(ReferenceChange): - refname_type = 'tag' - - def __init__(self, environment, refname, short_refname, old, new, rev): - ReferenceChange.__init__( - self, environment, - refname=refname, short_refname=short_refname, - old=old, new=new, rev=rev, - ) - self.recipients = environment.get_refchange_recipients(self) - - def generate_create_summary(self, push): - """Called for the creation of an annotated tag.""" - - for line in self.expand_lines(TAG_CREATED_TEMPLATE): - yield line - - def generate_update_summary(self, push): - """Called when a non-annotated reference is updated.""" - - for line in self.expand_lines(TAG_UPDATED_TEMPLATE): - yield line - - def generate_delete_summary(self, push): - """Called when a non-annotated reference is updated.""" - - for line in self.expand_lines(TAG_DELETED_TEMPLATE): - yield line - - for line in ReferenceChange.generate_delete_summary(self, push): - yield line - - -class OtherReferenceChange(ReferenceChange): - refname_type = 'reference' - - def __init__(self, environment, refname, short_refname, old, new, rev): - # We use the full refname as short_refname, because otherwise - # the full name of the reference would not be obvious from the - # text of the email. - ReferenceChange.__init__( - self, environment, - refname=refname, short_refname=refname, - old=old, new=new, rev=rev, - ) - self.recipients = environment.get_refchange_recipients(self) - - -class Mailer(object): - """An object that can send emails.""" - - def __init__(self, environment): - self.environment = environment - - def close(self): - pass - - def send(self, lines, to_addrs): - """Send an email consisting of lines. - - lines must be an iterable over the lines constituting the - header and body of the email. to_addrs is a list of recipient - addresses (can be needed even if lines already contains a - "To:" field). It can be either a string (comma-separated list - of email addresses) or a Python list of individual email - addresses. - - """ - - raise NotImplementedError() - - -class SendMailer(Mailer): - """Send emails using 'sendmail -oi -t'.""" - - SENDMAIL_CANDIDATES = [ - '/usr/sbin/sendmail', - '/usr/lib/sendmail', - ] - - @staticmethod - def find_sendmail(): - for path in SendMailer.SENDMAIL_CANDIDATES: - if os.access(path, os.X_OK): - return path - else: - raise ConfigurationException( - 'No sendmail executable found. ' - 'Try setting multimailhook.sendmailCommand.' - ) - - def __init__(self, environment, command=None, envelopesender=None): - """Construct a SendMailer instance. - - command should be the command and arguments used to invoke - sendmail, as a list of strings. If an envelopesender is - provided, it will also be passed to the command, via '-f - envelopesender'.""" - super(SendMailer, self).__init__(environment) - if command: - self.command = command[:] - else: - self.command = [self.find_sendmail(), '-oi', '-t'] - - if envelopesender: - self.command.extend(['-f', envelopesender]) - - def send(self, lines, to_addrs): - try: - p = subprocess.Popen(self.command, stdin=subprocess.PIPE) - except OSError: - self.environment.get_logger().error( - '*** Cannot execute command: %s\n' % ' '.join(self.command) + - '*** %s\n' % sys.exc_info()[1] + - '*** Try setting multimailhook.mailer to "smtp"\n' + - '*** to send emails without using the sendmail command.\n' - ) - sys.exit(1) - try: - lines = (str_to_bytes(line) for line in lines) - p.stdin.writelines(lines) - except Exception: - self.environment.get_logger().error( - '*** Error while generating commit email\n' - '*** - mail sending aborted.\n' - ) - if hasattr(p, 'terminate'): - # subprocess.terminate() is not available in Python 2.4 - p.terminate() - else: - import signal - os.kill(p.pid, signal.SIGTERM) - raise - else: - p.stdin.close() - retcode = p.wait() - if retcode: - raise CommandError(self.command, retcode) - - -class SMTPMailer(Mailer): - """Send emails using Python's smtplib.""" - - def __init__(self, environment, - envelopesender, smtpserver, - smtpservertimeout=10.0, smtpserverdebuglevel=0, - smtpencryption='none', - smtpuser='', smtppass='', - smtpcacerts='' - ): - super(SMTPMailer, self).__init__(environment) - if not envelopesender: - self.environment.get_logger().error( - 'fatal: git_multimail: cannot use SMTPMailer without a sender address.\n' - 'please set either multimailhook.envelopeSender or user.email\n' - ) - sys.exit(1) - if smtpencryption == 'ssl' and not (smtpuser and smtppass): - raise ConfigurationException( - 'Cannot use SMTPMailer with security option ssl ' - 'without options username and password.' - ) - self.envelopesender = envelopesender - self.smtpserver = smtpserver - self.smtpservertimeout = smtpservertimeout - self.smtpserverdebuglevel = smtpserverdebuglevel - self.security = smtpencryption - self.username = smtpuser - self.password = smtppass - self.smtpcacerts = smtpcacerts - self.loggedin = False - try: - def call(klass, server, timeout): - try: - return klass(server, timeout=timeout) - except TypeError: - # Old Python versions do not have timeout= argument. - return klass(server) - if self.security == 'none': - self.smtp = call(smtplib.SMTP, self.smtpserver, timeout=self.smtpservertimeout) - elif self.security == 'ssl': - if self.smtpcacerts: - raise smtplib.SMTPException( - "Checking certificate is not supported for ssl, prefer starttls" - ) - self.smtp = call(smtplib.SMTP_SSL, self.smtpserver, timeout=self.smtpservertimeout) - elif self.security == 'tls': - if 'ssl' not in sys.modules: - self.environment.get_logger().error( - '*** Your Python version does not have the ssl library installed\n' - '*** smtpEncryption=tls is not available.\n' - '*** Either upgrade Python to 2.6 or later\n' - ' or use git_multimail.py version 1.2.\n') - if ':' not in self.smtpserver: - self.smtpserver += ':587' # default port for TLS - self.smtp = call(smtplib.SMTP, self.smtpserver, timeout=self.smtpservertimeout) - # start: ehlo + starttls - # equivalent to - # self.smtp.ehlo() - # self.smtp.starttls() - # with acces to the ssl layer - self.smtp.ehlo() - if not self.smtp.has_extn("starttls"): - raise smtplib.SMTPException("STARTTLS extension not supported by server") - resp, reply = self.smtp.docmd("STARTTLS") - if resp != 220: - raise smtplib.SMTPException("Wrong answer to the STARTTLS command") - if self.smtpcacerts: - self.smtp.sock = ssl.wrap_socket( - self.smtp.sock, - ca_certs=self.smtpcacerts, - cert_reqs=ssl.CERT_REQUIRED - ) - else: - self.smtp.sock = ssl.wrap_socket( - self.smtp.sock, - cert_reqs=ssl.CERT_NONE - ) - self.environment.get_logger().error( - '*** Warning, the server certificat is not verified (smtp) ***\n' - '*** set the option smtpCACerts ***\n' - ) - if not hasattr(self.smtp.sock, "read"): - # using httplib.FakeSocket with Python 2.5.x or earlier - self.smtp.sock.read = self.smtp.sock.recv - self.smtp.file = smtplib.SSLFakeFile(self.smtp.sock) - self.smtp.helo_resp = None - self.smtp.ehlo_resp = None - self.smtp.esmtp_features = {} - self.smtp.does_esmtp = 0 - # end: ehlo + starttls - self.smtp.ehlo() - else: - sys.stdout.write('*** Error: Control reached an invalid option. ***') - sys.exit(1) - if self.smtpserverdebuglevel > 0: - sys.stdout.write( - "*** Setting debug on for SMTP server connection (%s) ***\n" - % self.smtpserverdebuglevel) - self.smtp.set_debuglevel(self.smtpserverdebuglevel) - except Exception: - self.environment.get_logger().error( - '*** Error establishing SMTP connection to %s ***\n' - '*** %s\n' - % (self.smtpserver, sys.exc_info()[1])) - sys.exit(1) - - def close(self): - if hasattr(self, 'smtp'): - self.smtp.quit() - del self.smtp - - def __del__(self): - self.close() - - def send(self, lines, to_addrs): - try: - if self.username or self.password: - if not self.loggedin: - self.smtp.login(self.username, self.password) - self.loggedin = True - msg = ''.join(lines) - # turn comma-separated list into Python list if needed. - if is_string(to_addrs): - to_addrs = [email for (name, email) in getaddresses([to_addrs])] - self.smtp.sendmail(self.envelopesender, to_addrs, msg) - except socket.timeout: - self.environment.get_logger().error( - '*** Error sending email ***\n' - '*** SMTP server timed out (timeout is %s)\n' - % self.smtpservertimeout) - except smtplib.SMTPResponseException: - err = sys.exc_info()[1] - self.environment.get_logger().error( - '*** Error sending email ***\n' - '*** Error %d: %s\n' - % (err.smtp_code, bytes_to_str(err.smtp_error))) - try: - smtp = self.smtp - # delete the field before quit() so that in case of - # error, self.smtp is deleted anyway. - del self.smtp - smtp.quit() - except: - self.environment.get_logger().error( - '*** Error closing the SMTP connection ***\n' - '*** Exiting anyway ... ***\n' - '*** %s\n' % sys.exc_info()[1]) - sys.exit(1) - - -class OutputMailer(Mailer): - """Write emails to an output stream, bracketed by lines of '=' characters. - - This is intended for debugging purposes.""" - - SEPARATOR = '=' * 75 + '\n' - - def __init__(self, f, environment=None): - super(OutputMailer, self).__init__(environment=environment) - self.f = f - - def send(self, lines, to_addrs): - write_str(self.f, self.SEPARATOR) - for line in lines: - write_str(self.f, line) - write_str(self.f, self.SEPARATOR) - - -def get_git_dir(): - """Determine GIT_DIR. - - Determine GIT_DIR either from the GIT_DIR environment variable or - from the working directory, using Git's usual rules.""" - - try: - return read_git_output(['rev-parse', '--git-dir']) - except CommandError: - sys.stderr.write('fatal: git_multimail: not in a git directory\n') - sys.exit(1) - - -class Environment(object): - """Describes the environment in which the push is occurring. - - An Environment object encapsulates information about the local - environment. For example, it knows how to determine: - - * the name of the repository to which the push occurred - - * what user did the push - - * what users want to be informed about various types of changes. - - An Environment object is expected to have the following methods: - - get_repo_shortname() - - Return a short name for the repository, for display - purposes. - - get_repo_path() - - Return the absolute path to the Git repository. - - get_emailprefix() - - Return a string that will be prefixed to every email's - subject. - - get_pusher() - - Return the username of the person who pushed the changes. - This value is used in the email body to indicate who - pushed the change. - - get_pusher_email() (may return None) - - Return the email address of the person who pushed the - changes. The value should be a single RFC 2822 email - address as a string; e.g., "Joe User " - if available, otherwise "user@example.com". If set, the - value is used as the Reply-To address for refchange - emails. If it is impossible to determine the pusher's - email, this attribute should be set to None (in which case - no Reply-To header will be output). - - get_sender() - - Return the address to be used as the 'From' email address - in the email envelope. - - get_fromaddr(change=None) - - Return the 'From' email address used in the email 'From:' - headers. If the change is known when this function is - called, it is passed in as the 'change' parameter. (May - be a full RFC 2822 email address like 'Joe User - '.) - - get_administrator() - - Return the name and/or email of the repository - administrator. This value is used in the footer as the - person to whom requests to be removed from the - notification list should be sent. Ideally, it should - include a valid email address. - - get_reply_to_refchange() - get_reply_to_commit() - - Return the address to use in the email "Reply-To" header, - as a string. These can be an RFC 2822 email address, or - None to omit the "Reply-To" header. - get_reply_to_refchange() is used for refchange emails; - get_reply_to_commit() is used for individual commit - emails. - - get_ref_filter_regex() - - Return a tuple -- a compiled regex, and a boolean indicating - whether the regex picks refs to include (if False, the regex - matches on refs to exclude). - - get_default_ref_ignore_regex() - - Return a regex that should be ignored for both what emails - to send and when computing what commits are considered new - to the repository. Default is "^refs/notes/". - - get_max_subject_length() - - Return an int giving the maximal length for the subject - (git log --oneline). - - They should also define the following attributes: - - announce_show_shortlog (bool) - - True iff announce emails should include a shortlog. - - commit_email_format (string) - - If "html", generate commit emails in HTML instead of plain text - used by default. - - html_in_intro (bool) - html_in_footer (bool) - - When generating HTML emails, the introduction (respectively, - the footer) will be HTML-escaped iff html_in_intro (respectively, - the footer) is true. When false, only the values used to expand - the template are escaped. - - refchange_showgraph (bool) - - True iff refchanges emails should include a detailed graph. - - refchange_showlog (bool) - - True iff refchanges emails should include a detailed log. - - diffopts (list of strings) - - The options that should be passed to 'git diff' for the - summary email. The value should be a list of strings - representing words to be passed to the command. - - graphopts (list of strings) - - Analogous to diffopts, but contains options passed to - 'git log --graph' when generating the detailed graph for - a set of commits (see refchange_showgraph) - - logopts (list of strings) - - Analogous to diffopts, but contains options passed to - 'git log' when generating the detailed log for a set of - commits (see refchange_showlog) - - commitlogopts (list of strings) - - The options that should be passed to 'git log' for each - commit mail. The value should be a list of strings - representing words to be passed to the command. - - date_substitute (string) - - String to be used in substitution for 'Date:' at start of - line in the output of 'git log'. - - quiet (bool) - On success do not write to stderr - - stdout (bool) - Write email to stdout rather than emailing. Useful for debugging - - combine_when_single_commit (bool) - - True if a combined email should be produced when a single - new commit is pushed to a branch, False otherwise. - - from_refchange, from_commit (strings) - - Addresses to use for the From: field for refchange emails - and commit emails respectively. Set from - multimailhook.fromRefchange and multimailhook.fromCommit - by ConfigEnvironmentMixin. - - log_file, error_log_file, debug_log_file (string) - - Name of a file to which logs should be sent. - - verbose (int) - - How verbose the system should be. - - 0 (default): show info, errors, ... - - 1 : show basic debug info - """ - - REPO_NAME_RE = re.compile(r'^(?P.+?)(?:\.git)$') - - def __init__(self, osenv=None): - self.osenv = osenv or os.environ - self.announce_show_shortlog = False - self.commit_email_format = "text" - self.html_in_intro = False - self.html_in_footer = False - self.commitBrowseURL = None - self.maxcommitemails = 500 - self.excludemergerevisions = False - self.diffopts = ['--stat', '--summary', '--find-copies-harder'] - self.graphopts = ['--oneline', '--decorate'] - self.logopts = [] - self.refchange_showgraph = False - self.refchange_showlog = False - self.commitlogopts = ['-C', '--stat', '-p', '--cc'] - self.date_substitute = 'AuthorDate: ' - self.quiet = False - self.stdout = False - self.combine_when_single_commit = True - self.logger = None - - self.COMPUTED_KEYS = [ - 'administrator', - 'charset', - 'emailprefix', - 'pusher', - 'pusher_email', - 'repo_path', - 'repo_shortname', - 'sender', - ] - - self._values = None - - def get_logger(self): - """Get (possibly creates) the logger associated to this environment.""" - if self.logger is None: - self.logger = Logger(self) - return self.logger - - def get_repo_shortname(self): - """Use the last part of the repo path, with ".git" stripped off if present.""" - - basename = os.path.basename(os.path.abspath(self.get_repo_path())) - m = self.REPO_NAME_RE.match(basename) - if m: - return m.group('name') - else: - return basename - - def get_pusher(self): - raise NotImplementedError() - - def get_pusher_email(self): - return None - - def get_fromaddr(self, change=None): - config = Config('user') - fromname = config.get('name', default='') - fromemail = config.get('email', default='') - if fromemail: - return formataddr([fromname, fromemail]) - return self.get_sender() - - def get_administrator(self): - return 'the administrator of this repository' - - def get_emailprefix(self): - return '' - - def get_repo_path(self): - if read_git_output(['rev-parse', '--is-bare-repository']) == 'true': - path = get_git_dir() - else: - path = read_git_output(['rev-parse', '--show-toplevel']) - return os.path.abspath(path) - - def get_charset(self): - return CHARSET - - def get_values(self): - """Return a dictionary {keyword: expansion} for this Environment. - - This method is called by Change._compute_values(). The keys - in the returned dictionary are available to be used in any of - the templates. The dictionary is created by calling - self.get_NAME() for each of the attributes named in - COMPUTED_KEYS and recording those that do not return None. - The return value is always a new dictionary.""" - - if self._values is None: - values = {'': ''} # %()s expands to the empty string. - - for key in self.COMPUTED_KEYS: - value = getattr(self, 'get_%s' % (key,))() - if value is not None: - values[key] = value - - self._values = values - - return self._values.copy() - - def get_refchange_recipients(self, refchange): - """Return the recipients for notifications about refchange. - - Return the list of email addresses to which notifications - about the specified ReferenceChange should be sent.""" - - raise NotImplementedError() - - def get_announce_recipients(self, annotated_tag_change): - """Return the recipients for notifications about annotated_tag_change. - - Return the list of email addresses to which notifications - about the specified AnnotatedTagChange should be sent.""" - - raise NotImplementedError() - - def get_reply_to_refchange(self, refchange): - return self.get_pusher_email() - - def get_revision_recipients(self, revision): - """Return the recipients for messages about revision. - - Return the list of email addresses to which notifications - about the specified Revision should be sent. This method - could be overridden, for example, to take into account the - contents of the revision when deciding whom to notify about - it. For example, there could be a scheme for users to express - interest in particular files or subdirectories, and only - receive notification emails for revisions that affecting those - files.""" - - raise NotImplementedError() - - def get_reply_to_commit(self, revision): - return revision.author - - def get_default_ref_ignore_regex(self): - # The commit messages of git notes are essentially meaningless - # and "filenames" in git notes commits are an implementational - # detail that might surprise users at first. As such, we - # would need a completely different method for handling emails - # of git notes in order for them to be of benefit for users, - # which we simply do not have right now. - return "^refs/notes/" - - def get_max_subject_length(self): - """Return the maximal subject line (git log --oneline) length. - Longer subject lines will be truncated.""" - raise NotImplementedError() - - def filter_body(self, lines): - """Filter the lines intended for an email body. - - lines is an iterable over the lines that would go into the - email body. Filter it (e.g., limit the number of lines, the - line length, character set, etc.), returning another iterable. - See FilterLinesEnvironmentMixin and MaxlinesEnvironmentMixin - for classes implementing this functionality.""" - - return lines - - def log_msg(self, msg): - """Write the string msg on a log file or on stderr. - - Sends the text to stderr by default, override to change the behavior.""" - self.get_logger().info(msg) - - def log_warning(self, msg): - """Write the string msg on a log file or on stderr. - - Sends the text to stderr by default, override to change the behavior.""" - self.get_logger().warning(msg) - - def log_error(self, msg): - """Write the string msg on a log file or on stderr. - - Sends the text to stderr by default, override to change the behavior.""" - self.get_logger().error(msg) - - def check(self): - pass - - -class ConfigEnvironmentMixin(Environment): - """A mixin that sets self.config to its constructor's config argument. - - This class's constructor consumes the "config" argument. - - Mixins that need to inspect the config should inherit from this - class (1) to make sure that "config" is still in the constructor - arguments with its own constructor runs and/or (2) to be sure that - self.config is set after construction.""" - - def __init__(self, config, **kw): - super(ConfigEnvironmentMixin, self).__init__(**kw) - self.config = config - - -class ConfigOptionsEnvironmentMixin(ConfigEnvironmentMixin): - """An Environment that reads most of its information from "git config".""" - - @staticmethod - def forbid_field_values(name, value, forbidden): - for forbidden_val in forbidden: - if value is not None and value.lower() == forbidden: - raise ConfigurationException( - '"%s" is not an allowed setting for %s' % (value, name) - ) - - def __init__(self, config, **kw): - super(ConfigOptionsEnvironmentMixin, self).__init__( - config=config, **kw - ) - - for var, cfg in ( - ('announce_show_shortlog', 'announceshortlog'), - ('refchange_showgraph', 'refchangeShowGraph'), - ('refchange_showlog', 'refchangeshowlog'), - ('quiet', 'quiet'), - ('stdout', 'stdout'), - ): - val = config.get_bool(cfg) - if val is not None: - setattr(self, var, val) - - commit_email_format = config.get('commitEmailFormat') - if commit_email_format is not None: - if commit_email_format != "html" and commit_email_format != "text": - self.log_warning( - '*** Unknown value for multimailhook.commitEmailFormat: %s\n' % - commit_email_format + - '*** Expected either "text" or "html". Ignoring.\n' - ) - else: - self.commit_email_format = commit_email_format - - html_in_intro = config.get_bool('htmlInIntro') - if html_in_intro is not None: - self.html_in_intro = html_in_intro - - html_in_footer = config.get_bool('htmlInFooter') - if html_in_footer is not None: - self.html_in_footer = html_in_footer - - self.commitBrowseURL = config.get('commitBrowseURL') - - self.excludemergerevisions = config.get('excludeMergeRevisions') - - maxcommitemails = config.get('maxcommitemails') - if maxcommitemails is not None: - try: - self.maxcommitemails = int(maxcommitemails) - except ValueError: - self.log_warning( - '*** Malformed value for multimailhook.maxCommitEmails: %s\n' - % maxcommitemails + - '*** Expected a number. Ignoring.\n' - ) - - diffopts = config.get('diffopts') - if diffopts is not None: - self.diffopts = shlex.split(diffopts) - - graphopts = config.get('graphOpts') - if graphopts is not None: - self.graphopts = shlex.split(graphopts) - - logopts = config.get('logopts') - if logopts is not None: - self.logopts = shlex.split(logopts) - - commitlogopts = config.get('commitlogopts') - if commitlogopts is not None: - self.commitlogopts = shlex.split(commitlogopts) - - date_substitute = config.get('dateSubstitute') - if date_substitute == 'none': - self.date_substitute = None - elif date_substitute is not None: - self.date_substitute = date_substitute - - reply_to = config.get('replyTo') - self.__reply_to_refchange = config.get('replyToRefchange', default=reply_to) - self.forbid_field_values('replyToRefchange', - self.__reply_to_refchange, - ['author']) - self.__reply_to_commit = config.get('replyToCommit', default=reply_to) - - self.from_refchange = config.get('fromRefchange') - self.forbid_field_values('fromRefchange', - self.from_refchange, - ['author', 'none']) - self.from_commit = config.get('fromCommit') - self.forbid_field_values('fromCommit', - self.from_commit, - ['none']) - - combine = config.get_bool('combineWhenSingleCommit') - if combine is not None: - self.combine_when_single_commit = combine - - self.log_file = config.get('logFile', default=None) - self.error_log_file = config.get('errorLogFile', default=None) - self.debug_log_file = config.get('debugLogFile', default=None) - if config.get_bool('Verbose', default=False): - self.verbose = 1 - else: - self.verbose = 0 - - def get_administrator(self): - return ( - self.config.get('administrator') or - self.get_sender() or - super(ConfigOptionsEnvironmentMixin, self).get_administrator() - ) - - def get_repo_shortname(self): - return ( - self.config.get('reponame') or - super(ConfigOptionsEnvironmentMixin, self).get_repo_shortname() - ) - - def get_emailprefix(self): - emailprefix = self.config.get('emailprefix') - if emailprefix is not None: - emailprefix = emailprefix.strip() - if emailprefix: - emailprefix += ' ' - else: - emailprefix = '[%(repo_shortname)s] ' - short_name = self.get_repo_shortname() - try: - return emailprefix % {'repo_shortname': short_name} - except: - self.get_logger().error( - '*** Invalid multimailhook.emailPrefix: %s\n' % emailprefix + - '*** %s\n' % sys.exc_info()[1] + - "*** Only the '%(repo_shortname)s' placeholder is allowed\n" - ) - raise ConfigurationException( - '"%s" is not an allowed setting for emailPrefix' % emailprefix - ) - - def get_sender(self): - return self.config.get('envelopesender') - - def process_addr(self, addr, change): - if addr.lower() == 'author': - if hasattr(change, 'author'): - return change.author - else: - return None - elif addr.lower() == 'pusher': - return self.get_pusher_email() - elif addr.lower() == 'none': - return None - else: - return addr - - def get_fromaddr(self, change=None): - fromaddr = self.config.get('from') - if change: - specific_fromaddr = change.get_specific_fromaddr() - if specific_fromaddr: - fromaddr = specific_fromaddr - if fromaddr: - fromaddr = self.process_addr(fromaddr, change) - if fromaddr: - return fromaddr - return super(ConfigOptionsEnvironmentMixin, self).get_fromaddr(change) - - def get_reply_to_refchange(self, refchange): - if self.__reply_to_refchange is None: - return super(ConfigOptionsEnvironmentMixin, self).get_reply_to_refchange(refchange) - else: - return self.process_addr(self.__reply_to_refchange, refchange) - - def get_reply_to_commit(self, revision): - if self.__reply_to_commit is None: - return super(ConfigOptionsEnvironmentMixin, self).get_reply_to_commit(revision) - else: - return self.process_addr(self.__reply_to_commit, revision) - - def get_scancommitforcc(self): - return self.config.get('scancommitforcc') - - -class FilterLinesEnvironmentMixin(Environment): - """Handle encoding and maximum line length of body lines. - - email_max_line_length (int or None) - - The maximum length of any single line in the email body. - Longer lines are truncated at that length with ' [...]' - appended. - - strict_utf8 (bool) - - If this field is set to True, then the email body text is - expected to be UTF-8. Any invalid characters are - converted to U+FFFD, the Unicode replacement character - (encoded as UTF-8, of course). - - """ - - def __init__(self, strict_utf8=True, - email_max_line_length=500, max_subject_length=500, - **kw): - super(FilterLinesEnvironmentMixin, self).__init__(**kw) - self.__strict_utf8 = strict_utf8 - self.__email_max_line_length = email_max_line_length - self.__max_subject_length = max_subject_length - - def filter_body(self, lines): - lines = super(FilterLinesEnvironmentMixin, self).filter_body(lines) - if self.__strict_utf8: - if not PYTHON3: - lines = (line.decode(ENCODING, 'replace') for line in lines) - # Limit the line length in Unicode-space to avoid - # splitting characters: - if self.__email_max_line_length > 0: - lines = limit_linelength(lines, self.__email_max_line_length) - if not PYTHON3: - lines = (line.encode(ENCODING, 'replace') for line in lines) - elif self.__email_max_line_length: - lines = limit_linelength(lines, self.__email_max_line_length) - - return lines - - def get_max_subject_length(self): - return self.__max_subject_length - - -class ConfigFilterLinesEnvironmentMixin( - ConfigEnvironmentMixin, - FilterLinesEnvironmentMixin, - ): - """Handle encoding and maximum line length based on config.""" - - def __init__(self, config, **kw): - strict_utf8 = config.get_bool('emailstrictutf8', default=None) - if strict_utf8 is not None: - kw['strict_utf8'] = strict_utf8 - - email_max_line_length = config.get('emailmaxlinelength') - if email_max_line_length is not None: - kw['email_max_line_length'] = int(email_max_line_length) - - max_subject_length = config.get('subjectMaxLength', default=email_max_line_length) - if max_subject_length is not None: - kw['max_subject_length'] = int(max_subject_length) - - super(ConfigFilterLinesEnvironmentMixin, self).__init__( - config=config, **kw - ) - - -class MaxlinesEnvironmentMixin(Environment): - """Limit the email body to a specified number of lines.""" - - def __init__(self, emailmaxlines, **kw): - super(MaxlinesEnvironmentMixin, self).__init__(**kw) - self.__emailmaxlines = emailmaxlines - - def filter_body(self, lines): - lines = super(MaxlinesEnvironmentMixin, self).filter_body(lines) - if self.__emailmaxlines > 0: - lines = limit_lines(lines, self.__emailmaxlines) - return lines - - -class ConfigMaxlinesEnvironmentMixin( - ConfigEnvironmentMixin, - MaxlinesEnvironmentMixin, - ): - """Limit the email body to the number of lines specified in config.""" - - def __init__(self, config, **kw): - emailmaxlines = int(config.get('emailmaxlines', default='0')) - super(ConfigMaxlinesEnvironmentMixin, self).__init__( - config=config, - emailmaxlines=emailmaxlines, - **kw - ) - - -class FQDNEnvironmentMixin(Environment): - """A mixin that sets the host's FQDN to its constructor argument.""" - - def __init__(self, fqdn, **kw): - super(FQDNEnvironmentMixin, self).__init__(**kw) - self.COMPUTED_KEYS += ['fqdn'] - self.__fqdn = fqdn - - def get_fqdn(self): - """Return the fully-qualified domain name for this host. - - Return None if it is unavailable or unwanted.""" - - return self.__fqdn - - -class ConfigFQDNEnvironmentMixin( - ConfigEnvironmentMixin, - FQDNEnvironmentMixin, - ): - """Read the FQDN from the config.""" - - def __init__(self, config, **kw): - fqdn = config.get('fqdn') - super(ConfigFQDNEnvironmentMixin, self).__init__( - config=config, - fqdn=fqdn, - **kw - ) - - -class ComputeFQDNEnvironmentMixin(FQDNEnvironmentMixin): - """Get the FQDN by calling socket.getfqdn().""" - - def __init__(self, **kw): - super(ComputeFQDNEnvironmentMixin, self).__init__( - fqdn=socket.getfqdn(), - **kw - ) - - -class PusherDomainEnvironmentMixin(ConfigEnvironmentMixin): - """Deduce pusher_email from pusher by appending an emaildomain.""" - - def __init__(self, **kw): - super(PusherDomainEnvironmentMixin, self).__init__(**kw) - self.__emaildomain = self.config.get('emaildomain') - - def get_pusher_email(self): - if self.__emaildomain: - # Derive the pusher's full email address in the default way: - return '%s@%s' % (self.get_pusher(), self.__emaildomain) - else: - return super(PusherDomainEnvironmentMixin, self).get_pusher_email() - - -class StaticRecipientsEnvironmentMixin(Environment): - """Set recipients statically based on constructor parameters.""" - - def __init__( - self, - refchange_recipients, announce_recipients, revision_recipients, scancommitforcc, - **kw - ): - super(StaticRecipientsEnvironmentMixin, self).__init__(**kw) - - # The recipients for various types of notification emails, as - # RFC 2822 email addresses separated by commas (or the empty - # string if no recipients are configured). Although there is - # a mechanism to choose the recipient lists based on on the - # actual *contents* of the change being reported, we only - # choose based on the *type* of the change. Therefore we can - # compute them once and for all: - self.__refchange_recipients = refchange_recipients - self.__announce_recipients = announce_recipients - self.__revision_recipients = revision_recipients - - def check(self): - if not (self.get_refchange_recipients(None) or - self.get_announce_recipients(None) or - self.get_revision_recipients(None) or - self.get_scancommitforcc()): - raise ConfigurationException('No email recipients configured!') - super(StaticRecipientsEnvironmentMixin, self).check() - - def get_refchange_recipients(self, refchange): - if self.__refchange_recipients is None: - return super(StaticRecipientsEnvironmentMixin, - self).get_refchange_recipients(refchange) - return self.__refchange_recipients - - def get_announce_recipients(self, annotated_tag_change): - if self.__announce_recipients is None: - return super(StaticRecipientsEnvironmentMixin, - self).get_refchange_recipients(annotated_tag_change) - return self.__announce_recipients - - def get_revision_recipients(self, revision): - if self.__revision_recipients is None: - return super(StaticRecipientsEnvironmentMixin, - self).get_refchange_recipients(revision) - return self.__revision_recipients - - -class CLIRecipientsEnvironmentMixin(Environment): - """Mixin storing recipients information coming from the - command-line.""" - - def __init__(self, cli_recipients=None, **kw): - super(CLIRecipientsEnvironmentMixin, self).__init__(**kw) - self.__cli_recipients = cli_recipients - - def get_refchange_recipients(self, refchange): - if self.__cli_recipients is None: - return super(CLIRecipientsEnvironmentMixin, - self).get_refchange_recipients(refchange) - return self.__cli_recipients - - def get_announce_recipients(self, annotated_tag_change): - if self.__cli_recipients is None: - return super(CLIRecipientsEnvironmentMixin, - self).get_announce_recipients(annotated_tag_change) - return self.__cli_recipients - - def get_revision_recipients(self, revision): - if self.__cli_recipients is None: - return super(CLIRecipientsEnvironmentMixin, - self).get_revision_recipients(revision) - return self.__cli_recipients - - -class ConfigRecipientsEnvironmentMixin( - ConfigEnvironmentMixin, - StaticRecipientsEnvironmentMixin - ): - """Determine recipients statically based on config.""" - - def __init__(self, config, **kw): - super(ConfigRecipientsEnvironmentMixin, self).__init__( - config=config, - refchange_recipients=self._get_recipients( - config, 'refchangelist', 'mailinglist', - ), - announce_recipients=self._get_recipients( - config, 'announcelist', 'refchangelist', 'mailinglist', - ), - revision_recipients=self._get_recipients( - config, 'commitlist', 'mailinglist', - ), - scancommitforcc=config.get('scancommitforcc'), - **kw - ) - - def _get_recipients(self, config, *names): - """Return the recipients for a particular type of message. - - Return the list of email addresses to which a particular type - of notification email should be sent, by looking at the config - value for "multimailhook.$name" for each of names. Use the - value from the first name that is configured. The return - value is a (possibly empty) string containing RFC 2822 email - addresses separated by commas. If no configuration could be - found, raise a ConfigurationException.""" - - for name in names: - lines = config.get_all(name) - if lines is not None: - lines = [line.strip() for line in lines] - # Single "none" is a special value equivalen to empty string. - if lines == ['none']: - lines = [''] - return ', '.join(lines) - else: - return '' - - -class StaticRefFilterEnvironmentMixin(Environment): - """Set branch filter statically based on constructor parameters.""" - - def __init__(self, ref_filter_incl_regex, ref_filter_excl_regex, - ref_filter_do_send_regex, ref_filter_dont_send_regex, - **kw): - super(StaticRefFilterEnvironmentMixin, self).__init__(**kw) - - if ref_filter_incl_regex and ref_filter_excl_regex: - raise ConfigurationException( - "Cannot specify both a ref inclusion and exclusion regex.") - self.__is_inclusion_filter = bool(ref_filter_incl_regex) - default_exclude = self.get_default_ref_ignore_regex() - if ref_filter_incl_regex: - ref_filter_regex = ref_filter_incl_regex - elif ref_filter_excl_regex: - ref_filter_regex = ref_filter_excl_regex + '|' + default_exclude - else: - ref_filter_regex = default_exclude - try: - self.__compiled_regex = re.compile(ref_filter_regex) - except Exception: - raise ConfigurationException( - 'Invalid Ref Filter Regex "%s": %s' % (ref_filter_regex, sys.exc_info()[1])) - - if ref_filter_do_send_regex and ref_filter_dont_send_regex: - raise ConfigurationException( - "Cannot specify both a ref doSend and dontSend regex.") - self.__is_do_send_filter = bool(ref_filter_do_send_regex) - if ref_filter_do_send_regex: - ref_filter_send_regex = ref_filter_do_send_regex - elif ref_filter_dont_send_regex: - ref_filter_send_regex = ref_filter_dont_send_regex - else: - ref_filter_send_regex = '.*' - self.__is_do_send_filter = True - try: - self.__send_compiled_regex = re.compile(ref_filter_send_regex) - except Exception: - raise ConfigurationException( - 'Invalid Ref Filter Regex "%s": %s' % - (ref_filter_send_regex, sys.exc_info()[1])) - - def get_ref_filter_regex(self, send_filter=False): - if send_filter: - return self.__send_compiled_regex, self.__is_do_send_filter - else: - return self.__compiled_regex, self.__is_inclusion_filter - - -class ConfigRefFilterEnvironmentMixin( - ConfigEnvironmentMixin, - StaticRefFilterEnvironmentMixin - ): - """Determine branch filtering statically based on config.""" - - def _get_regex(self, config, key): - """Get a list of whitespace-separated regex. The refFilter* config - variables are multivalued (hence the use of get_all), and we - allow each entry to be a whitespace-separated list (hence the - split on each line). The whole thing is glued into a single regex.""" - values = config.get_all(key) - if values is None: - return values - items = [] - for line in values: - for i in line.split(): - items.append(i) - if items == []: - return None - return '|'.join(items) - - def __init__(self, config, **kw): - super(ConfigRefFilterEnvironmentMixin, self).__init__( - config=config, - ref_filter_incl_regex=self._get_regex(config, 'refFilterInclusionRegex'), - ref_filter_excl_regex=self._get_regex(config, 'refFilterExclusionRegex'), - ref_filter_do_send_regex=self._get_regex(config, 'refFilterDoSendRegex'), - ref_filter_dont_send_regex=self._get_regex(config, 'refFilterDontSendRegex'), - **kw - ) - - -class ProjectdescEnvironmentMixin(Environment): - """Make a "projectdesc" value available for templates. - - By default, it is set to the first line of $GIT_DIR/description - (if that file is present and appears to be set meaningfully).""" - - def __init__(self, **kw): - super(ProjectdescEnvironmentMixin, self).__init__(**kw) - self.COMPUTED_KEYS += ['projectdesc'] - - def get_projectdesc(self): - """Return a one-line descripition of the project.""" - - git_dir = get_git_dir() - try: - projectdesc = open(os.path.join(git_dir, 'description')).readline().strip() - if projectdesc and not projectdesc.startswith('Unnamed repository'): - return projectdesc - except IOError: - pass - - return 'UNNAMED PROJECT' - - -class GenericEnvironmentMixin(Environment): - def get_pusher(self): - return self.osenv.get('USER', self.osenv.get('USERNAME', 'unknown user')) - - -class GitoliteEnvironmentHighPrecMixin(Environment): - def get_pusher(self): - return self.osenv.get('GL_USER', 'unknown user') - - -class GitoliteEnvironmentLowPrecMixin( - ConfigEnvironmentMixin, - Environment): - - def get_repo_shortname(self): - # The gitolite environment variable $GL_REPO is a pretty good - # repo_shortname (though it's probably not as good as a value - # the user might have explicitly put in his config). - return ( - self.osenv.get('GL_REPO', None) or - super(GitoliteEnvironmentLowPrecMixin, self).get_repo_shortname() - ) - - @staticmethod - def _compile_regex(re_template): - return ( - re.compile(re_template % x) - for x in ( - r'BEGIN\s+USER\s+EMAILS', - r'([^\s]+)\s+(.*)', - r'END\s+USER\s+EMAILS', - )) - - def get_fromaddr(self, change=None): - GL_USER = self.osenv.get('GL_USER') - if GL_USER is not None: - # Find the path to gitolite.conf. Note that gitolite v3 - # did away with the GL_ADMINDIR and GL_CONF environment - # variables (they are now hard-coded). - GL_ADMINDIR = self.osenv.get( - 'GL_ADMINDIR', - os.path.expanduser(os.path.join('~', '.gitolite'))) - GL_CONF = self.osenv.get( - 'GL_CONF', - os.path.join(GL_ADMINDIR, 'conf', 'gitolite.conf')) - - mailaddress_map = self.config.get('MailaddressMap') - # If relative, consider relative to GL_CONF: - if mailaddress_map: - mailaddress_map = os.path.join(os.path.dirname(GL_CONF), - mailaddress_map) - if os.path.isfile(mailaddress_map): - f = open(mailaddress_map, 'rU') - try: - # Leading '#' is optional - re_begin, re_user, re_end = self._compile_regex( - r'^(?:\s*#)?\s*%s\s*$') - for l in f: - l = l.rstrip('\n') - if re_begin.match(l) or re_end.match(l): - continue # Ignore these lines - m = re_user.match(l) - if m: - if m.group(1) == GL_USER: - return m.group(2) - else: - continue # Not this user, but not an error - raise ConfigurationException( - "Syntax error in mail address map.\n" - "Check file {}.\n" - "Line: {}".format(mailaddress_map, l)) - - finally: - f.close() - - if os.path.isfile(GL_CONF): - f = open(GL_CONF, 'rU') - try: - in_user_emails_section = False - re_begin, re_user, re_end = self._compile_regex( - r'^\s*#\s*%s\s*$') - for l in f: - l = l.rstrip('\n') - if not in_user_emails_section: - if re_begin.match(l): - in_user_emails_section = True - continue - if re_end.match(l): - break - m = re_user.match(l) - if m and m.group(1) == GL_USER: - return m.group(2) - finally: - f.close() - return super(GitoliteEnvironmentLowPrecMixin, self).get_fromaddr(change) - - -class IncrementalDateTime(object): - """Simple wrapper to give incremental date/times. - - Each call will result in a date/time a second later than the - previous call. This can be used to falsify email headers, to - increase the likelihood that email clients sort the emails - correctly.""" - - def __init__(self): - self.time = time.time() - self.next = self.__next__ # Python 2 backward compatibility - - def __next__(self): - formatted = formatdate(self.time, True) - self.time += 1 - return formatted - - -class StashEnvironmentHighPrecMixin(Environment): - def __init__(self, user=None, repo=None, **kw): - super(StashEnvironmentHighPrecMixin, - self).__init__(user=user, repo=repo, **kw) - self.__user = user - self.__repo = repo - - def get_pusher(self): - return re.match(r'(.*?)\s*<', self.__user).group(1) - - def get_pusher_email(self): - return self.__user - - -class StashEnvironmentLowPrecMixin(Environment): - def __init__(self, user=None, repo=None, **kw): - super(StashEnvironmentLowPrecMixin, self).__init__(**kw) - self.__repo = repo - self.__user = user - - def get_repo_shortname(self): - return self.__repo - - def get_fromaddr(self, change=None): - return self.__user - - -class GerritEnvironmentHighPrecMixin(Environment): - def __init__(self, project=None, submitter=None, update_method=None, **kw): - super(GerritEnvironmentHighPrecMixin, - self).__init__(submitter=submitter, project=project, **kw) - self.__project = project - self.__submitter = submitter - self.__update_method = update_method - "Make an 'update_method' value available for templates." - self.COMPUTED_KEYS += ['update_method'] - - def get_pusher(self): - if self.__submitter: - if self.__submitter.find('<') != -1: - # Submitter has a configured email, we transformed - # __submitter into an RFC 2822 string already. - return re.match(r'(.*?)\s*<', self.__submitter).group(1) - else: - # Submitter has no configured email, it's just his name. - return self.__submitter - else: - # If we arrive here, this means someone pushed "Submit" from - # the gerrit web UI for the CR (or used one of the programmatic - # APIs to do the same, such as gerrit review) and the - # merge/push was done by the Gerrit user. It was technically - # triggered by someone else, but sadly we have no way of - # determining who that someone else is at this point. - return 'Gerrit' # 'unknown user'? - - def get_pusher_email(self): - if self.__submitter: - return self.__submitter - else: - return super(GerritEnvironmentHighPrecMixin, self).get_pusher_email() - - def get_default_ref_ignore_regex(self): - default = super(GerritEnvironmentHighPrecMixin, self).get_default_ref_ignore_regex() - return default + '|^refs/changes/|^refs/cache-automerge/|^refs/meta/' - - def get_revision_recipients(self, revision): - # Merge commits created by Gerrit when users hit "Submit this patchset" - # in the Web UI (or do equivalently with REST APIs or the gerrit review - # command) are not something users want to see an individual email for. - # Filter them out. - committer = read_git_output(['log', '--no-walk', '--format=%cN', - revision.rev.sha1]) - if committer == 'Gerrit Code Review': - return [] - else: - return super(GerritEnvironmentHighPrecMixin, self).get_revision_recipients(revision) - - def get_update_method(self): - return self.__update_method - - -class GerritEnvironmentLowPrecMixin(Environment): - def __init__(self, project=None, submitter=None, **kw): - super(GerritEnvironmentLowPrecMixin, self).__init__(**kw) - self.__project = project - self.__submitter = submitter - - def get_repo_shortname(self): - return self.__project - - def get_fromaddr(self, change=None): - if self.__submitter and self.__submitter.find('<') != -1: - return self.__submitter - else: - return super(GerritEnvironmentLowPrecMixin, self).get_fromaddr(change) - - -class Push(object): - """Represent an entire push (i.e., a group of ReferenceChanges). - - It is easy to figure out what commits were added to a *branch* by - a Reference change: - - git rev-list change.old..change.new - - or removed from a *branch*: - - git rev-list change.new..change.old - - But it is not quite so trivial to determine which entirely new - commits were added to the *repository* by a push and which old - commits were discarded by a push. A big part of the job of this - class is to figure out these things, and to make sure that new - commits are only detailed once even if they were added to multiple - references. - - The first step is to determine the "other" references--those - unaffected by the current push. They are computed by listing all - references then removing any affected by this push. The results - are stored in Push._other_ref_sha1s. - - The commits contained in the repository before this push were - - git rev-list other1 other2 other3 ... change1.old change2.old ... - - Where "changeN.old" is the old value of one of the references - affected by this push. - - The commits contained in the repository after this push are - - git rev-list other1 other2 other3 ... change1.new change2.new ... - - The commits added by this push are the difference between these - two sets, which can be written - - git rev-list \ - ^other1 ^other2 ... \ - ^change1.old ^change2.old ... \ - change1.new change2.new ... - - The commits removed by this push can be computed by - - git rev-list \ - ^other1 ^other2 ... \ - ^change1.new ^change2.new ... \ - change1.old change2.old ... - - The last point is that it is possible that other pushes are - occurring simultaneously to this one, so reference values can - change at any time. It is impossible to eliminate all race - conditions, but we reduce the window of time during which problems - can occur by translating reference names to SHA1s as soon as - possible and working with SHA1s thereafter (because SHA1s are - immutable).""" - - # A map {(changeclass, changetype): integer} specifying the order - # that reference changes will be processed if multiple reference - # changes are included in a single push. The order is significant - # mostly because new commit notifications are threaded together - # with the first reference change that includes the commit. The - # following order thus causes commits to be grouped with branch - # changes (as opposed to tag changes) if possible. - SORT_ORDER = dict( - (value, i) for (i, value) in enumerate([ - (BranchChange, 'update'), - (BranchChange, 'create'), - (AnnotatedTagChange, 'update'), - (AnnotatedTagChange, 'create'), - (NonAnnotatedTagChange, 'update'), - (NonAnnotatedTagChange, 'create'), - (BranchChange, 'delete'), - (AnnotatedTagChange, 'delete'), - (NonAnnotatedTagChange, 'delete'), - (OtherReferenceChange, 'update'), - (OtherReferenceChange, 'create'), - (OtherReferenceChange, 'delete'), - ]) - ) - - def __init__(self, environment, changes, ignore_other_refs=False): - self.changes = sorted(changes, key=self._sort_key) - self.__other_ref_sha1s = None - self.__cached_commits_spec = {} - self.environment = environment - - if ignore_other_refs: - self.__other_ref_sha1s = set() - - @classmethod - def _sort_key(klass, change): - return (klass.SORT_ORDER[change.__class__, change.change_type], change.refname,) - - @property - def _other_ref_sha1s(self): - """The GitObjects referred to by references unaffected by this push. - """ - if self.__other_ref_sha1s is None: - # The refnames being changed by this push: - updated_refs = set( - change.refname - for change in self.changes - ) - - # The SHA-1s of commits referred to by all references in this - # repository *except* updated_refs: - sha1s = set() - fmt = ( - '%(objectname) %(objecttype) %(refname)\n' - '%(*objectname) %(*objecttype) %(refname)' - ) - ref_filter_regex, is_inclusion_filter = \ - self.environment.get_ref_filter_regex() - for line in read_git_lines( - ['for-each-ref', '--format=%s' % (fmt,)]): - (sha1, type, name) = line.split(' ', 2) - if (sha1 and type == 'commit' and - name not in updated_refs and - include_ref(name, ref_filter_regex, is_inclusion_filter)): - sha1s.add(sha1) - - self.__other_ref_sha1s = sha1s - - return self.__other_ref_sha1s - - def _get_commits_spec_incl(self, new_or_old, reference_change=None): - """Get new or old SHA-1 from one or each of the changed refs. - - Return a list of SHA-1 commit identifier strings suitable as - arguments to 'git rev-list' (or 'git log' or ...). The - returned identifiers are either the old or new values from one - or all of the changed references, depending on the values of - new_or_old and reference_change. - - new_or_old is either the string 'new' or the string 'old'. If - 'new', the returned SHA-1 identifiers are the new values from - each changed reference. If 'old', the SHA-1 identifiers are - the old values from each changed reference. - - If reference_change is specified and not None, only the new or - old reference from the specified reference is included in the - return value. - - This function returns None if there are no matching revisions - (e.g., because a branch was deleted and new_or_old is 'new'). - """ - - if not reference_change: - incl_spec = sorted( - getattr(change, new_or_old).sha1 - for change in self.changes - if getattr(change, new_or_old) - ) - if not incl_spec: - incl_spec = None - elif not getattr(reference_change, new_or_old).commit_sha1: - incl_spec = None - else: - incl_spec = [getattr(reference_change, new_or_old).commit_sha1] - return incl_spec - - def _get_commits_spec_excl(self, new_or_old): - """Get exclusion revisions for determining new or discarded commits. - - Return a list of strings suitable as arguments to 'git - rev-list' (or 'git log' or ...) that will exclude all - commits that, depending on the value of new_or_old, were - either previously in the repository (useful for determining - which commits are new to the repository) or currently in the - repository (useful for determining which commits were - discarded from the repository). - - new_or_old is either the string 'new' or the string 'old'. If - 'new', the commits to be excluded are those that were in the - repository before the push. If 'old', the commits to be - excluded are those that are currently in the repository. """ - - old_or_new = {'old': 'new', 'new': 'old'}[new_or_old] - excl_revs = self._other_ref_sha1s.union( - getattr(change, old_or_new).sha1 - for change in self.changes - if getattr(change, old_or_new).type in ['commit', 'tag'] - ) - return ['^' + sha1 for sha1 in sorted(excl_revs)] - - def get_commits_spec(self, new_or_old, reference_change=None): - """Get rev-list arguments for added or discarded commits. - - Return a list of strings suitable as arguments to 'git - rev-list' (or 'git log' or ...) that select those commits - that, depending on the value of new_or_old, are either new to - the repository or were discarded from the repository. - - new_or_old is either the string 'new' or the string 'old'. If - 'new', the returned list is used to select commits that are - new to the repository. If 'old', the returned value is used - to select the commits that have been discarded from the - repository. - - If reference_change is specified and not None, the new or - discarded commits are limited to those that are reachable from - the new or old value of the specified reference. - - This function returns None if there are no added (or discarded) - revisions. - """ - key = (new_or_old, reference_change) - if key not in self.__cached_commits_spec: - ret = self._get_commits_spec_incl(new_or_old, reference_change) - if ret is not None: - ret.extend(self._get_commits_spec_excl(new_or_old)) - self.__cached_commits_spec[key] = ret - return self.__cached_commits_spec[key] - - def get_new_commits(self, reference_change=None): - """Return a list of commits added by this push. - - Return a list of the object names of commits that were added - by the part of this push represented by reference_change. If - reference_change is None, then return a list of *all* commits - added by this push.""" - - spec = self.get_commits_spec('new', reference_change) - return git_rev_list(spec) - - def get_discarded_commits(self, reference_change): - """Return a list of commits discarded by this push. - - Return a list of the object names of commits that were - entirely discarded from the repository by the part of this - push represented by reference_change.""" - - spec = self.get_commits_spec('old', reference_change) - return git_rev_list(spec) - - def send_emails(self, mailer, body_filter=None): - """Use send all of the notification emails needed for this push. - - Use send all of the notification emails (including reference - change emails and commit emails) needed for this push. Send - the emails using mailer. If body_filter is not None, then use - it to filter the lines that are intended for the email - body.""" - - # The sha1s of commits that were introduced by this push. - # They will be removed from this set as they are processed, to - # guarantee that one (and only one) email is generated for - # each new commit. - unhandled_sha1s = set(self.get_new_commits()) - send_date = IncrementalDateTime() - for change in self.changes: - sha1s = [] - for sha1 in reversed(list(self.get_new_commits(change))): - if sha1 in unhandled_sha1s: - sha1s.append(sha1) - unhandled_sha1s.remove(sha1) - - # Check if we've got anyone to send to - if not change.recipients: - change.environment.log_warning( - '*** no recipients configured so no email will be sent\n' - '*** for %r update %s->%s' - % (change.refname, change.old.sha1, change.new.sha1,) - ) - else: - if not change.environment.quiet: - change.environment.log_msg( - 'Sending notification emails to: %s' % (change.recipients,)) - extra_values = {'send_date': next(send_date)} - - rev = change.send_single_combined_email(sha1s) - if rev: - mailer.send( - change.generate_combined_email(self, rev, body_filter, extra_values), - rev.recipients, - ) - # This change is now fully handled; no need to handle - # individual revisions any further. - continue - else: - mailer.send( - change.generate_email(self, body_filter, extra_values), - change.recipients, - ) - - max_emails = change.environment.maxcommitemails - if max_emails and len(sha1s) > max_emails: - change.environment.log_warning( - '*** Too many new commits (%d), not sending commit emails.\n' % len(sha1s) + - '*** Try setting multimailhook.maxCommitEmails to a greater value\n' + - '*** Currently, multimailhook.maxCommitEmails=%d' % max_emails - ) - return - - for (num, sha1) in enumerate(sha1s): - rev = Revision(change, GitObject(sha1), num=num + 1, tot=len(sha1s)) - if len(rev.parents) > 1 and change.environment.excludemergerevisions: - # skipping a merge commit - continue - if not rev.recipients and rev.cc_recipients: - change.environment.log_msg('*** Replacing Cc: with To:') - rev.recipients = rev.cc_recipients - rev.cc_recipients = None - if rev.recipients: - extra_values = {'send_date': next(send_date)} - mailer.send( - rev.generate_email(self, body_filter, extra_values), - rev.recipients, - ) - - # Consistency check: - if unhandled_sha1s: - change.environment.log_error( - 'ERROR: No emails were sent for the following new commits:\n' - ' %s' - % ('\n '.join(sorted(unhandled_sha1s)),) - ) - - -def include_ref(refname, ref_filter_regex, is_inclusion_filter): - does_match = bool(ref_filter_regex.search(refname)) - if is_inclusion_filter: - return does_match - else: # exclusion filter -- we include the ref if the regex doesn't match - return not does_match - - -def run_as_post_receive_hook(environment, mailer): - environment.check() - send_filter_regex, send_is_inclusion_filter = environment.get_ref_filter_regex(True) - ref_filter_regex, is_inclusion_filter = environment.get_ref_filter_regex(False) - changes = [] - while True: - line = read_line(sys.stdin) - if line == '': - break - (oldrev, newrev, refname) = line.strip().split(' ', 2) - environment.get_logger().debug( - "run_as_post_receive_hook: oldrev=%s, newrev=%s, refname=%s" % - (oldrev, newrev, refname)) - - if not include_ref(refname, ref_filter_regex, is_inclusion_filter): - continue - if not include_ref(refname, send_filter_regex, send_is_inclusion_filter): - continue - changes.append( - ReferenceChange.create(environment, oldrev, newrev, refname) - ) - if not changes: - mailer.close() - return - push = Push(environment, changes) - try: - push.send_emails(mailer, body_filter=environment.filter_body) - finally: - mailer.close() - - -def run_as_update_hook(environment, mailer, refname, oldrev, newrev, force_send=False): - environment.check() - send_filter_regex, send_is_inclusion_filter = environment.get_ref_filter_regex(True) - ref_filter_regex, is_inclusion_filter = environment.get_ref_filter_regex(False) - if not include_ref(refname, ref_filter_regex, is_inclusion_filter): - return - if not include_ref(refname, send_filter_regex, send_is_inclusion_filter): - return - changes = [ - ReferenceChange.create( - environment, - read_git_output(['rev-parse', '--verify', oldrev]), - read_git_output(['rev-parse', '--verify', newrev]), - refname, - ), - ] - if not changes: - mailer.close() - return - push = Push(environment, changes, force_send) - try: - push.send_emails(mailer, body_filter=environment.filter_body) - finally: - mailer.close() - - -def check_ref_filter(environment): - send_filter_regex, send_is_inclusion = environment.get_ref_filter_regex(True) - ref_filter_regex, ref_is_inclusion = environment.get_ref_filter_regex(False) - - def inc_exc_lusion(b): - if b: - return 'inclusion' - else: - return 'exclusion' - - if send_filter_regex: - sys.stdout.write("DoSend/DontSend filter regex (" + - (inc_exc_lusion(send_is_inclusion)) + - '): ' + send_filter_regex.pattern + - '\n') - if send_filter_regex: - sys.stdout.write("Include/Exclude filter regex (" + - (inc_exc_lusion(ref_is_inclusion)) + - '): ' + ref_filter_regex.pattern + - '\n') - sys.stdout.write(os.linesep) - - sys.stdout.write( - "Refs marked as EXCLUDE are excluded by either refFilterInclusionRegex\n" - "or refFilterExclusionRegex. No emails will be sent for commits included\n" - "in these refs.\n" - "Refs marked as DONT-SEND are excluded by either refFilterDoSendRegex or\n" - "refFilterDontSendRegex, but not by either refFilterInclusionRegex or\n" - "refFilterExclusionRegex. Emails will be sent for commits included in these\n" - "refs only when the commit reaches a ref which isn't excluded.\n" - "Refs marked as DO-SEND are not excluded by any filter. Emails will\n" - "be sent normally for commits included in these refs.\n") - - sys.stdout.write(os.linesep) - - for refname in read_git_lines(['for-each-ref', '--format', '%(refname)']): - sys.stdout.write(refname) - if not include_ref(refname, ref_filter_regex, ref_is_inclusion): - sys.stdout.write(' EXCLUDE') - elif not include_ref(refname, send_filter_regex, send_is_inclusion): - sys.stdout.write(' DONT-SEND') - else: - sys.stdout.write(' DO-SEND') - - sys.stdout.write(os.linesep) - - -def show_env(environment, out): - out.write('Environment values:\n') - for (k, v) in sorted(environment.get_values().items()): - if k: # Don't show the {'' : ''} pair. - out.write(' %s : %r\n' % (k, v)) - out.write('\n') - # Flush to avoid interleaving with further log output - out.flush() - - -def check_setup(environment): - environment.check() - show_env(environment, sys.stdout) - sys.stdout.write("Now, checking that git-multimail's standard input " - "is properly set ..." + os.linesep) - sys.stdout.write("Please type some text and then press Return" + os.linesep) - stdin = sys.stdin.readline() - sys.stdout.write("You have just entered:" + os.linesep) - sys.stdout.write(stdin) - sys.stdout.write("git-multimail seems properly set up." + os.linesep) - - -def choose_mailer(config, environment): - mailer = config.get('mailer', default='sendmail') - - if mailer == 'smtp': - smtpserver = config.get('smtpserver', default='localhost') - smtpservertimeout = float(config.get('smtpservertimeout', default=10.0)) - smtpserverdebuglevel = int(config.get('smtpserverdebuglevel', default=0)) - smtpencryption = config.get('smtpencryption', default='none') - smtpuser = config.get('smtpuser', default='') - smtppass = config.get('smtppass', default='') - smtpcacerts = config.get('smtpcacerts', default='') - mailer = SMTPMailer( - environment, - envelopesender=(environment.get_sender() or environment.get_fromaddr()), - smtpserver=smtpserver, smtpservertimeout=smtpservertimeout, - smtpserverdebuglevel=smtpserverdebuglevel, - smtpencryption=smtpencryption, - smtpuser=smtpuser, - smtppass=smtppass, - smtpcacerts=smtpcacerts - ) - elif mailer == 'sendmail': - command = config.get('sendmailcommand') - if command: - command = shlex.split(command) - mailer = SendMailer(environment, - command=command, envelopesender=environment.get_sender()) - else: - environment.log_error( - 'fatal: multimailhook.mailer is set to an incorrect value: "%s"\n' % mailer + - 'please use one of "smtp" or "sendmail".' - ) - sys.exit(1) - return mailer - - -KNOWN_ENVIRONMENTS = { - 'generic': {'highprec': GenericEnvironmentMixin}, - 'gitolite': {'highprec': GitoliteEnvironmentHighPrecMixin, - 'lowprec': GitoliteEnvironmentLowPrecMixin}, - 'stash': {'highprec': StashEnvironmentHighPrecMixin, - 'lowprec': StashEnvironmentLowPrecMixin}, - 'gerrit': {'highprec': GerritEnvironmentHighPrecMixin, - 'lowprec': GerritEnvironmentLowPrecMixin}, - } - - -def choose_environment(config, osenv=None, env=None, recipients=None, - hook_info=None): - env_name = choose_environment_name(config, env, osenv) - environment_klass = build_environment_klass(env_name) - env = build_environment(environment_klass, env_name, config, - osenv, recipients, hook_info) - return env - - -def choose_environment_name(config, env, osenv): - if not osenv: - osenv = os.environ - - if not env: - env = config.get('environment') - - if not env: - if 'GL_USER' in osenv and 'GL_REPO' in osenv: - env = 'gitolite' - else: - env = 'generic' - return env - - -COMMON_ENVIRONMENT_MIXINS = [ - ConfigRecipientsEnvironmentMixin, - CLIRecipientsEnvironmentMixin, - ConfigRefFilterEnvironmentMixin, - ProjectdescEnvironmentMixin, - ConfigMaxlinesEnvironmentMixin, - ComputeFQDNEnvironmentMixin, - ConfigFilterLinesEnvironmentMixin, - PusherDomainEnvironmentMixin, - ConfigOptionsEnvironmentMixin, - ] - - -def build_environment_klass(env_name): - if 'class' in KNOWN_ENVIRONMENTS[env_name]: - return KNOWN_ENVIRONMENTS[env_name]['class'] - - environment_mixins = [] - known_env = KNOWN_ENVIRONMENTS[env_name] - if 'highprec' in known_env: - high_prec_mixin = known_env['highprec'] - environment_mixins.append(high_prec_mixin) - environment_mixins = environment_mixins + COMMON_ENVIRONMENT_MIXINS - if 'lowprec' in known_env: - low_prec_mixin = known_env['lowprec'] - environment_mixins.append(low_prec_mixin) - environment_mixins.append(Environment) - klass_name = env_name.capitalize() + 'Environment' - environment_klass = type( - klass_name, - tuple(environment_mixins), - {}, - ) - KNOWN_ENVIRONMENTS[env_name]['class'] = environment_klass - return environment_klass - - -GerritEnvironment = build_environment_klass('gerrit') -StashEnvironment = build_environment_klass('stash') -GitoliteEnvironment = build_environment_klass('gitolite') -GenericEnvironment = build_environment_klass('generic') - - -def build_environment(environment_klass, env, config, - osenv, recipients, hook_info): - environment_kw = { - 'osenv': osenv, - 'config': config, - } - - if env == 'stash': - environment_kw['user'] = hook_info['stash_user'] - environment_kw['repo'] = hook_info['stash_repo'] - elif env == 'gerrit': - environment_kw['project'] = hook_info['project'] - environment_kw['submitter'] = hook_info['submitter'] - environment_kw['update_method'] = hook_info['update_method'] - - environment_kw['cli_recipients'] = recipients - - return environment_klass(**environment_kw) - - -def get_version(): - oldcwd = os.getcwd() - try: - try: - os.chdir(os.path.dirname(os.path.realpath(__file__))) - git_version = read_git_output(['describe', '--tags', 'HEAD']) - if git_version == __version__: - return git_version - else: - return '%s (%s)' % (__version__, git_version) - except: - pass - finally: - os.chdir(oldcwd) - return __version__ - - -def compute_gerrit_options(options, args, required_gerrit_options, - raw_refname): - if None in required_gerrit_options: - raise SystemExit("Error: Specify all of --oldrev, --newrev, --refname, " - "and --project; or none of them.") - - if options.environment not in (None, 'gerrit'): - raise SystemExit("Non-gerrit environments incompatible with --oldrev, " - "--newrev, --refname, and --project") - options.environment = 'gerrit' - - if args: - raise SystemExit("Error: Positional parameters not allowed with " - "--oldrev, --newrev, and --refname.") - - # Gerrit oddly omits 'refs/heads/' in the refname when calling - # ref-updated hook; put it back. - git_dir = get_git_dir() - if (not os.path.exists(os.path.join(git_dir, raw_refname)) and - os.path.exists(os.path.join(git_dir, 'refs', 'heads', - raw_refname))): - options.refname = 'refs/heads/' + options.refname - - # New revisions can appear in a gerrit repository either due to someone - # pushing directly (in which case options.submitter will be set), or they - # can press "Submit this patchset" in the web UI for some CR (in which - # case options.submitter will not be set and gerrit will not have provided - # us the information about who pressed the button). - # - # Note for the nit-picky: I'm lumping in REST API calls and the ssh - # gerrit review command in with "Submit this patchset" button, since they - # have the same effect. - if options.submitter: - update_method = 'pushed' - # The submitter argument is almost an RFC 2822 email address; change it - # from 'User Name (email@domain)' to 'User Name ' so it is - options.submitter = options.submitter.replace('(', '<').replace(')', '>') - else: - update_method = 'submitted' - # Gerrit knew who submitted this patchset, but threw that information - # away when it invoked this hook. However, *IF* Gerrit created a - # merge to bring the patchset in (project 'Submit Type' is either - # "Always Merge", or is "Merge if Necessary" and happens to be - # necessary for this particular CR), then it will have the committer - # of that merge be 'Gerrit Code Review' and the author will be the - # person who requested the submission of the CR. Since this is fairly - # likely for most gerrit installations (of a reasonable size), it's - # worth the extra effort to try to determine the actual submitter. - rev_info = read_git_lines(['log', '--no-walk', '--merges', - '--format=%cN%n%aN <%aE>', options.newrev]) - if rev_info and rev_info[0] == 'Gerrit Code Review': - options.submitter = rev_info[1] - - # We pass back refname, oldrev, newrev as args because then the - # gerrit ref-updated hook is much like the git update hook - return (options, - [options.refname, options.oldrev, options.newrev], - {'project': options.project, 'submitter': options.submitter, - 'update_method': update_method}) - - -def check_hook_specific_args(options, args): - raw_refname = options.refname - # Convert each string option unicode for Python3. - if PYTHON3: - opts = ['environment', 'recipients', 'oldrev', 'newrev', 'refname', - 'project', 'submitter', 'stash_user', 'stash_repo'] - for opt in opts: - if not hasattr(options, opt): - continue - obj = getattr(options, opt) - if obj: - enc = obj.encode('utf-8', 'surrogateescape') - dec = enc.decode('utf-8', 'replace') - setattr(options, opt, dec) - - # First check for stash arguments - if (options.stash_user is None) != (options.stash_repo is None): - raise SystemExit("Error: Specify both of --stash-user and " - "--stash-repo or neither.") - if options.stash_user: - options.environment = 'stash' - return options, args, {'stash_user': options.stash_user, - 'stash_repo': options.stash_repo} - - # Finally, check for gerrit specific arguments - required_gerrit_options = (options.oldrev, options.newrev, options.refname, - options.project) - if required_gerrit_options != (None,) * 4: - return compute_gerrit_options(options, args, required_gerrit_options, - raw_refname) - - # No special options in use, just return what we started with - return options, args, {} - - -class Logger(object): - def parse_verbose(self, verbose): - if verbose > 0: - return logging.DEBUG - else: - return logging.INFO - - def create_log_file(self, environment, name, path, verbosity): - log_file = logging.getLogger(name) - file_handler = logging.FileHandler(path) - log_fmt = logging.Formatter("%(asctime)s [%(levelname)-5.5s] %(message)s") - file_handler.setFormatter(log_fmt) - log_file.addHandler(file_handler) - log_file.setLevel(verbosity) - return log_file - - def __init__(self, environment): - self.environment = environment - self.loggers = [] - stderr_log = logging.getLogger('git_multimail.stderr') - - class EncodedStderr(object): - def write(self, x): - write_str(sys.stderr, x) - - def flush(self): - sys.stderr.flush() - - stderr_handler = logging.StreamHandler(EncodedStderr()) - stderr_log.addHandler(stderr_handler) - stderr_log.setLevel(self.parse_verbose(environment.verbose)) - self.loggers.append(stderr_log) - - if environment.debug_log_file is not None: - debug_log_file = self.create_log_file( - environment, 'git_multimail.debug', environment.debug_log_file, logging.DEBUG) - self.loggers.append(debug_log_file) - - if environment.log_file is not None: - log_file = self.create_log_file( - environment, 'git_multimail.file', environment.log_file, logging.INFO) - self.loggers.append(log_file) - - if environment.error_log_file is not None: - error_log_file = self.create_log_file( - environment, 'git_multimail.error', environment.error_log_file, logging.ERROR) - self.loggers.append(error_log_file) - - def info(self, msg, *args, **kwargs): - for l in self.loggers: - l.info(msg, *args, **kwargs) - - def debug(self, msg, *args, **kwargs): - for l in self.loggers: - l.debug(msg, *args, **kwargs) - - def warning(self, msg, *args, **kwargs): - for l in self.loggers: - l.warning(msg, *args, **kwargs) - - def error(self, msg, *args, **kwargs): - for l in self.loggers: - l.error(msg, *args, **kwargs) - - -def main(args): - parser = optparse.OptionParser( - description=__doc__, - usage='%prog [OPTIONS]\n or: %prog [OPTIONS] REFNAME OLDREV NEWREV', - ) - - parser.add_option( - '--environment', '--env', action='store', type='choice', - choices=list(KNOWN_ENVIRONMENTS.keys()), default=None, - help=( - 'Choose type of environment is in use. Default is taken from ' - 'multimailhook.environment if set; otherwise "generic".' - ), - ) - parser.add_option( - '--stdout', action='store_true', default=False, - help='Output emails to stdout rather than sending them.', - ) - parser.add_option( - '--recipients', action='store', default=None, - help='Set list of email recipients for all types of emails.', - ) - parser.add_option( - '--show-env', action='store_true', default=False, - help=( - 'Write to stderr the values determined for the environment ' - '(intended for debugging purposes), then proceed normally.' - ), - ) - parser.add_option( - '--force-send', action='store_true', default=False, - help=( - 'Force sending refchange email when using as an update hook. ' - 'This is useful to work around the unreliable new commits ' - 'detection in this mode.' - ), - ) - parser.add_option( - '-c', metavar="=", action='append', - help=( - 'Pass a configuration parameter through to git. The value given ' - 'will override values from configuration files. See the -c option ' - 'of git(1) for more details. (Only works with git >= 1.7.3)' - ), - ) - parser.add_option( - '--version', '-v', action='store_true', default=False, - help=( - "Display git-multimail's version" - ), - ) - - parser.add_option( - '--python-version', action='store_true', default=False, - help=( - "Display the version of Python used by git-multimail" - ), - ) - - parser.add_option( - '--check-ref-filter', action='store_true', default=False, - help=( - 'List refs and show information on how git-multimail ' - 'will process them.' - ) - ) - - # The following options permit this script to be run as a gerrit - # ref-updated hook. See e.g. - # code.google.com/p/gerrit/source/browse/Documentation/config-hooks.txt - # We suppress help for these items, since these are specific to gerrit, - # and we don't want users directly using them any way other than how the - # gerrit ref-updated hook is called. - parser.add_option('--oldrev', action='store', help=optparse.SUPPRESS_HELP) - parser.add_option('--newrev', action='store', help=optparse.SUPPRESS_HELP) - parser.add_option('--refname', action='store', help=optparse.SUPPRESS_HELP) - parser.add_option('--project', action='store', help=optparse.SUPPRESS_HELP) - parser.add_option('--submitter', action='store', help=optparse.SUPPRESS_HELP) - - # The following allow this to be run as a stash asynchronous post-receive - # hook (almost identical to a git post-receive hook but triggered also for - # merges of pull requests from the UI). We suppress help for these items, - # since these are specific to stash. - parser.add_option('--stash-user', action='store', help=optparse.SUPPRESS_HELP) - parser.add_option('--stash-repo', action='store', help=optparse.SUPPRESS_HELP) - - (options, args) = parser.parse_args(args) - (options, args, hook_info) = check_hook_specific_args(options, args) - - if options.version: - sys.stdout.write('git-multimail version ' + get_version() + '\n') - return - - if options.python_version: - sys.stdout.write('Python version ' + sys.version + '\n') - return - - if options.c: - Config.add_config_parameters(options.c) - - config = Config('multimailhook') - - environment = None - try: - environment = choose_environment( - config, osenv=os.environ, - env=options.environment, - recipients=options.recipients, - hook_info=hook_info, - ) - - if options.show_env: - show_env(environment, sys.stderr) - - if options.stdout or environment.stdout: - mailer = OutputMailer(sys.stdout, environment) - else: - mailer = choose_mailer(config, environment) - - must_check_setup = os.environ.get('GIT_MULTIMAIL_CHECK_SETUP') - if must_check_setup == '': - must_check_setup = False - if options.check_ref_filter: - check_ref_filter(environment) - elif must_check_setup: - check_setup(environment) - # Dual mode: if arguments were specified on the command line, run - # like an update hook; otherwise, run as a post-receive hook. - elif args: - if len(args) != 3: - parser.error('Need zero or three non-option arguments') - (refname, oldrev, newrev) = args - environment.get_logger().debug( - "run_as_update_hook: refname=%s, oldrev=%s, newrev=%s, force_send=%s" % - (refname, oldrev, newrev, options.force_send)) - run_as_update_hook(environment, mailer, refname, oldrev, newrev, options.force_send) - else: - run_as_post_receive_hook(environment, mailer) - except ConfigurationException: - sys.exit(sys.exc_info()[1]) - except SystemExit: - raise - except Exception: - t, e, tb = sys.exc_info() - import traceback - sys.stderr.write('\n') # Avoid mixing message with previous output - msg = ( - 'Exception \'' + t.__name__ + - '\' raised. Please report this as a bug to\n' - 'https://github.com/git-multimail/git-multimail/issues\n' - 'with the information below:\n\n' - 'git-multimail version ' + get_version() + '\n' - 'Python version ' + sys.version + '\n' + - traceback.format_exc()) - try: - environment.get_logger().error(msg) - except: - sys.stderr.write(msg) - sys.exit(1) - - -if __name__ == '__main__': - main(sys.argv[1:]) diff --git a/plugins/redmine_git_hosting/contrib/hooks/post-receive/mail_notifications.py b/plugins/redmine_git_hosting/contrib/hooks/post-receive/mail_notifications.py deleted file mode 100644 index cce9f6c..0000000 --- a/plugins/redmine_git_hosting/contrib/hooks/post-receive/mail_notifications.py +++ /dev/null @@ -1,35 +0,0 @@ -#! /usr/bin/env python - -import sys -import os - -import git_multimail - - -# It is possible to modify the output templates here; e.g.: - -git_multimail.FOOTER_TEMPLATE = """\ - --- \n\ -This email was generated by the wonderful git-multimail tool from JBox Web. -""" - - -# Specify which "git config" section contains the configuration for -# git-multimail: -config = git_multimail.Config('multimailhook') - -# check if hook is enabled -enabled = config.get_bool('enabled') - -if enabled: - # Select the type of environment: - environment = git_multimail.GitoliteEnvironment(config=config) - - # Choose the method of sending emails based on the git config: - mailer = git_multimail.choose_mailer(config, environment) - - # Read changes from stdin and send notification emails: - git_multimail.run_as_post_receive_hook(environment, mailer) -else: - print(" multimailhook is disabled") diff --git a/plugins/redmine_git_hosting/contrib/hooks/post-receive/redmine_gitolite.rb b/plugins/redmine_git_hosting/contrib/hooks/post-receive/redmine_gitolite.rb deleted file mode 100644 index 079ee23..0000000 --- a/plugins/redmine_git_hosting/contrib/hooks/post-receive/redmine_gitolite.rb +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env ruby - -# This file was placed here by Redmine Git Hosting. It makes sure that your pushed commits -# will be processed properly. - -refs = ARGF.read -repo_path = Dir.pwd - -require_relative 'lib/git_hosting/http_helper' -require_relative 'lib/git_hosting/hook_logger' -require_relative 'lib/git_hosting/config' -require_relative 'lib/git_hosting/post_receive' -require_relative 'lib/git_hosting/custom_hook' - -if GitHosting::PostReceive.new(repo_path, refs).exec && GitHosting::CustomHook.new(repo_path, refs).exec - exit 0 -else - exit 1 -end diff --git a/plugins/redmine_git_hosting/contrib/scripts/puma.rb b/plugins/redmine_git_hosting/contrib/scripts/puma.rb deleted file mode 100644 index 00f01dd..0000000 --- a/plugins/redmine_git_hosting/contrib/scripts/puma.rb +++ /dev/null @@ -1,7 +0,0 @@ -stdout_redirect '/home/redmine/redmine/log/puma.stderr.log', '/home/redmine/redmine/log/puma.stdout.log' - -on_worker_boot do - ActiveSupport.on_load(:active_record) do - ActiveRecord::Base.establish_connection - end -end diff --git a/plugins/redmine_git_hosting/contrib/scripts/redmine b/plugins/redmine_git_hosting/contrib/scripts/redmine deleted file mode 100644 index e84b712..0000000 --- a/plugins/redmine_git_hosting/contrib/scripts/redmine +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh -### BEGIN INIT INFO -# Provides: redmine -# Required-Start: $local_fs $remote_fs $network $mysql $named -# Required-Stop: $local_fs $remote_fs $network $mysql $named -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Redmine projects manager -# Description: This file should be used to start and stop Redmine. -### END INIT INFO - -[ -f /etc/default/rcS ] && . /etc/default/rcS -. /lib/lsb/init-functions - -REDMINE_USER="redmine" - -WEBSERVER="server_puma" -WORKER1="sidekiq_git_hosting" - -case "$1" in - start) - su - $REDMINE_USER -c "${WEBSERVER}.sh start" - su - $REDMINE_USER -c "${WORKER1}.sh start" - ;; - stop) - su - $REDMINE_USER -c "${WEBSERVER}.sh stop" - su - $REDMINE_USER -c "${WORKER1}.sh stop" - ;; - restart) - su - $REDMINE_USER -c "${WEBSERVER}.sh restart" - su - $REDMINE_USER -c "${WORKER1}.sh restart" - ;; - *) - echo "Usage : /etc/init.d/redmine {start|stop|restart}" - ;; -esac diff --git a/plugins/redmine_git_hosting/contrib/scripts/server_puma.sh b/plugins/redmine_git_hosting/contrib/scripts/server_puma.sh deleted file mode 100644 index 3b6a6c9..0000000 --- a/plugins/redmine_git_hosting/contrib/scripts/server_puma.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/bash - -# You should place this script in user's home bin dir like : -# /home/redmine/bin/server_puma.sh -# -# Normally the user's bin directory should be in the PATH. -# If not, add this in /home/redmine/.profile : -# -# ------------------>8 -# #set PATH so it includes user's private bin if it exists -# if [ -d "$HOME/bin" ] ; then -# PATH="$HOME/bin:$PATH" -# fi -# ------------------>8 -# -# -# This script *must* be run by the Redmine user so -# switch user *before* running the script : -# root$ su - redmine -# -# Then : -# redmine$ server_puma.sh start -# redmine$ server_puma.sh stop -# redmine$ server_puma.sh restart - -SERVER_NAME="redmine" - -RAILS_ENV="production" - -REDMINE_PATH="$HOME/redmine" -CONFIG_FILE="$HOME/etc/puma.rb" - -PID_FILE="$REDMINE_PATH/tmp/pids/puma.pid" -SOCK_FILE="$REDMINE_PATH/tmp/sockets/redmine.sock" - -BIND_URI="unix://$SOCK_FILE" - -THREADS="0:8" -WORKERS=2 - -function start () { - echo "Start Puma Server..." - puma --daemon --preload --bind $BIND_URI \ - --environment $RAILS_ENV --dir $REDMINE_PATH \ - --workers $WORKERS --threads $THREADS \ - --pidfile $PID_FILE --tag $SERVER_NAME \ - --config $CONFIG_FILE - echo "Done" -} - -function stop () { - echo "Stop Puma Server..." - if [ -f $PID_FILE ] ; then - kill $(cat $PID_FILE) 2>/dev/null - rm -f $PID_FILE - rm -f $SOCK_FILE - fi - echo "Done" -} - -case "$1" in - start) - start - ;; - stop) - stop - ;; - restart) - stop - start - ;; - *) - echo "Usage : server_puma.sh {start|stop|restart}" - ;; -esac diff --git a/plugins/redmine_git_hosting/contrib/scripts/sidekiq_git_hosting.sh b/plugins/redmine_git_hosting/contrib/scripts/sidekiq_git_hosting.sh deleted file mode 100644 index c0be9e2..0000000 --- a/plugins/redmine_git_hosting/contrib/scripts/sidekiq_git_hosting.sh +++ /dev/null @@ -1,169 +0,0 @@ -#!/bin/bash - -# You should place this script in user's home bin dir like : -# /home/redmine/bin/sidekiq_git_hosting.sh -# -# Normally the user's bin directory should be in the PATH. -# If not, add this in /home/redmine/.profile : -# -# ------------------>8 -# #set PATH so it includes user's private bin if it exists -# if [ -d "$HOME/bin" ] ; then -# PATH="$HOME/bin:$PATH" -# fi -# ------------------>8 -# -# -# This script *must* be run by the Redmine user so -# switch user *before* running the script : -# root$ su - redmine -# -# Then : -# redmine$ sidekiq_git_hosting.sh start -# redmine$ sidekiq_git_hosting.sh stop -# redmine$ sidekiq_git_hosting.sh restart - -# WORKER_NAME is used to identify the worker among the processus list -# Example : sidekiq 3.2.1 redmine_git_hosting [0 of 1 busy] -WORKER_NAME="redmine_git_hosting" - -# The Rails environment, default : production -RAILS_ENV=${RAILS_ENV:-production} - -# The absolute path to Redmine -REDMINE_PATH=${REDMINE_PATH:-$HOME/redmine} - -# The start detection timeout -TIMEOUT=${TIMEOUT:-15} - -DESC="Sidekiq worker '$WORKER_NAME'" - -LOG_DIR="$REDMINE_PATH/log" -PID_DIR="$REDMINE_PATH/tmp/pids" - -LOG_FILE="$LOG_DIR/worker_${WORKER_NAME}.log" -PID_FILE="$PID_DIR/worker_${WORKER_NAME}.pid" - -# Do not change these values ! -# See here for more details : -# https://github.com/jbox-web/redmine_git_hosting/wiki/Configuration-notes#sidekiq--concurrency -CONCURRENCY=1 -QUEUE="redmine_git_hosting,1" - -if [ "$RAILS_ENV" = "production" ] ; then - DAEMON_OPTS="--daemon --logfile $LOG_FILE --pidfile $PID_FILE" -else - DAEMON_OPTS= -fi - -if [ ! -d $PID_DIR ] ; then - mkdir $PID_DIR -fi - - -RETVAL=0 - - -################################ -success() { - echo -e "\t\t[ \e[32mOK\e[0m ]" -} - - -failure() { - echo -e "\t\t[ \e[31mFailure\e[0m ]" -} - - -start () { - pid=$(get_pid) - if [ $pid -gt 1 ] ; then - echo "$DESC is already running (pid $pid)" - RETVAL=1 - return $RETVAL - fi - - echo -n "Starting $DESC ..." - - sidekiq $DAEMON_OPTS --verbose --concurrency $CONCURRENCY \ - --environment $RAILS_ENV --require $REDMINE_PATH \ - --queue $QUEUE --tag $WORKER_NAME - - if [ ! -z "$DAEMON_OPTS" ] ; then - for ((i=1; i<=TIMEOUT; i++)) ; do - pid=$(get_pid) - if [ $pid -gt 1 ] ; then - break - fi - echo -n '.' && sleep 1 - done - echo -n " " - - pid=$(get_pid) - if [ $pid -gt 1 ] ; then - success - RETVAL=0 - else - failure - RETVAL=1 - fi - fi -} - - -stop () { - echo -n "Shutting down $DESC ..." - kill $(cat $PID_FILE 2>/dev/null) >/dev/null 2>&1 - RETVAL=$? - [ $RETVAL -eq 0 ] && success || failure - rm -f $PID_FILE >/dev/null 2>&1 -} - - -status () { - # show status - pid=$(get_pid) - if [ $pid -gt 1 ] ; then - echo "$DESC is running (pid $pid)" - else - echo "$DESC is stopped" - fi - RETVAL=0 -} - - -get_pid () { - # get status - pid=$(ps axo pid,command | grep sidekiq | grep $WORKER_NAME | awk '{print $1}') - if [ -z $pid ] ; then - rc=1 - else - rc=$pid - fi - echo $rc -} - -################################ - -case "$1" in - start) - start - ;; - stop) - stop - ;; - restart) - stop - sleep 1 - start - ;; - status) - status - ;; - *) - echo "Usage: $0 {start|stop|restart|status}" - exit 1 - ;; -esac - -exit $RETVAL diff --git a/plugins/redmine_git_hosting/custom_hooks.rb.example b/plugins/redmine_git_hosting/custom_hooks.rb.example deleted file mode 100644 index fda4bf3..0000000 --- a/plugins/redmine_git_hosting/custom_hooks.rb.example +++ /dev/null @@ -1,38 +0,0 @@ -# You can declare here you own hooks to install globally in Gitolite. -# You must set the source directory of the files with the *source_dir* method and -# declare your hooks with *gitolite_hook* method. -# -# *RedmineGitHosting::GitoliteHooks.register_hooks* can be called multiple times -# with a different *source_dir*. -# -# *name* : the hook name (just a name to identify the hook) -# *source* : the source path concatenated with *source_dir* -# *destination* : the destination path on Gitolite side. -# -# The *destination* must be relative. -# The final destination will depend on your Gitolite version : -# -# Gitolite v2 : /.gitolite/hooks/common -# Gitolite v3 : /local/hooks/common/ -# -# RedmineGitHosting::GitoliteHooks.register_hooks do -# source_dir '/tmp/global-hooks' -# -# gitolite_hook do -# name 'global/check-branch' -# source 'pre-receive/check_branch.rb' -# destination 'pre-receive.d/check_branch.rb' -# executable true -# end -# end -# -# RedmineGitHosting::GitoliteHooks.register_hooks do -# source_dir '/tmp/custom-hooks' -# -# gitolite_hook do -# name 'custom/notify-users' -# source 'post-receive/notify_users.rb' -# destination 'post-receive.d/notify_users.rb' -# executable true -# end -# end diff --git a/plugins/redmine_git_hosting/db/migrate/20091119162426_set_mirror_role_permissions.rb b/plugins/redmine_git_hosting/db/migrate/20091119162426_set_mirror_role_permissions.rb deleted file mode 100644 index 7b39ab4..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20091119162426_set_mirror_role_permissions.rb +++ /dev/null @@ -1,53 +0,0 @@ -class SetMirrorRolePermissions < ActiveRecord::Migration[4.2] - def up - manager_role_name = I18n.t(:default_role_manager, locale: Setting.default_language) - say "Updating role : '#{manager_role_name}'..." - manager_role = Role.find_by(name: manager_role_name) - if !manager_role.nil? - manager_role.add_permission! :view_repository_mirrors - manager_role.add_permission! :create_repository_mirrors - manager_role.add_permission! :edit_repository_mirrors - manager_role.save - say 'Done !' - else - say "Role '#{manager_role_name}' not found, exit !" - end - - developer_role_name = I18n.t(:default_role_developer, locale: Setting.default_language) - say "Updating role : '#{developer_role_name}'..." - developer_role = Role.find_by(name: developer_role_name) - if !developer_role.nil? - developer_role.add_permission! :view_repository_mirrors - developer_role.save - say 'Done !' - else - say "Role '#{developer_role_name}' not found, exit !" - end - end - - def down - manager_role_name = I18n.t(:default_role_manager, locale: Setting.default_language) - say "Updating role : '#{manager_role_name}'..." - manager_role = Role.find_by(name: manager_role_name) - if !manager_role.nil? - manager_role.remove_permission! :view_repository_mirrors - manager_role.remove_permission! :create_repository_mirrors - manager_role.remove_permission! :edit_repository_mirrors - manager_role.save - say 'Done !' - else - say "Role '#{manager_role_name}' not found, exit !" - end - - developer_role_name = I18n.t(:default_role_developer, locale: Setting.default_language) - say "Updating role : '#{developer_role_name}'..." - developer_role = Role.find_by(name: developer_role_name) - if !developer_role.nil? - developer_role.remove_permission! :view_repository_mirrors - developer_role.save - say 'Done !' - else - say "Role '#{developer_role_name}' not found, exit !" - end - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20091119162427_create_gitolite_public_keys.rb b/plugins/redmine_git_hosting/db/migrate/20091119162427_create_gitolite_public_keys.rb deleted file mode 100644 index 6a194ea..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20091119162427_create_gitolite_public_keys.rb +++ /dev/null @@ -1,12 +0,0 @@ -class CreateGitolitePublicKeys < ActiveRecord::Migration[4.2] - def change - create_table :gitolite_public_keys do |t| - t.column :title, :string - t.column :identifier, :string - t.column :key, :text - t.column :active, :integer, default: 1 - t.references :user - t.timestamps - end - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20091119162428_create_git_caches.rb b/plugins/redmine_git_hosting/db/migrate/20091119162428_create_git_caches.rb deleted file mode 100644 index a023436..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20091119162428_create_git_caches.rb +++ /dev/null @@ -1,10 +0,0 @@ -class CreateGitCaches < ActiveRecord::Migration[4.2] - def change - create_table :git_caches do |t| - t.column :command, :text - t.column :command_output, :binary - t.column :proj_identifier, :string - t.timestamps - end - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20110726000000_extend_changesets_notified_cia.rb b/plugins/redmine_git_hosting/db/migrate/20110726000000_extend_changesets_notified_cia.rb deleted file mode 100644 index 7718edf..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20110726000000_extend_changesets_notified_cia.rb +++ /dev/null @@ -1,14 +0,0 @@ -class ExtendChangesetsNotifiedCia < ActiveRecord::Migration[4.2] - def up - add_column :changesets, :notified_cia, :integer, default: 0 - end - - def down - # Deal with fact that one of next migrations doesn't restore :notified_cia - remove_column :changesets, :notified_cia if column_exists?(:changesets, :notified_cia) - end - - def column_exists?(table_name, column_name) - columns(table_name).any? { |c| c.name == column_name.to_s } - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20110807000000_create_repository_mirrors.rb b/plugins/redmine_git_hosting/db/migrate/20110807000000_create_repository_mirrors.rb deleted file mode 100644 index 26ed46d..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20110807000000_create_repository_mirrors.rb +++ /dev/null @@ -1,11 +0,0 @@ -class CreateRepositoryMirrors < ActiveRecord::Migration[4.2] - def change - create_table :repository_mirrors do |t| - t.column :project_id, :integer - t.column :active, :integer, default: 1 - t.column :url, :string - t.references :project - t.timestamps - end - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20110813000000_create_git_repository_extras.rb b/plugins/redmine_git_hosting/db/migrate/20110813000000_create_git_repository_extras.rb deleted file mode 100644 index 3caf537..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20110813000000_create_git_repository_extras.rb +++ /dev/null @@ -1,29 +0,0 @@ -class CreateGitRepositoryExtras < ActiveRecord::Migration[4.2] - def up - drop_table :git_repository_extras if table_exists?(:git_repository_extras) - - create_table :git_repository_extras do |t| - t.column :repository_id, :integer - t.column :git_daemon, :integer, default: 1 - t.column :git_http, :integer, default: 1 - t.column :notify_cia, :integer, default: 0 - t.column :key, :string - end - - drop_table :git_hook_keys if table_exists?('git_hook_keys') - remove_column :repositories, :git_daemon if column_exists?(:repositories, :git_daemon) - remove_column :repositories, :git_http if column_exists?(:repositories, :git_http) - end - - def down - drop_table :git_repository_extras - end - - def table_exists?(name) - ActiveRecord::Base.connection.tables.include?(name) - end - - def column_exists?(table_name, column_name) - columns(table_name).any? { |c| c.name == column_name.to_s } - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20110817000000_move_notified_cia_to_git_cia_notifications.rb b/plugins/redmine_git_hosting/db/migrate/20110817000000_move_notified_cia_to_git_cia_notifications.rb deleted file mode 100644 index a3b519e..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20110817000000_move_notified_cia_to_git_cia_notifications.rb +++ /dev/null @@ -1,30 +0,0 @@ -class MoveNotifiedCiaToGitCiaNotifications < ActiveRecord::Migration[4.2] - def up - drop_table :git_cia_notifications if table_exists?(:git_cia_notifications) - - create_table :git_cia_notifications do |t| - t.column :repository_id, :integer - t.column :scmid, :string - end - - # Speed up searches - add_index(:git_cia_notifications, :scmid) - - # Make sure uniqueness of the two columns, :scmid, :repository_id - add_index(:git_cia_notifications, %i[scmid repository_id], unique: true) - - remove_column :changesets, :notified_cia if column_exists?(:changesets, :notified_cia) - end - - def down - drop_table :git_cia_notifications - end - - def table_exists?(name) - ActiveRecord::Base.connection.tables.include?(name) - end - - def column_exists?(table_name, column_name) - columns(table_name).any? { |c| c.name == column_name.to_s } - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20111119170948_add_indexes_to_gitolite_public_key.rb b/plugins/redmine_git_hosting/db/migrate/20111119170948_add_indexes_to_gitolite_public_key.rb deleted file mode 100644 index 4e18e99..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20111119170948_add_indexes_to_gitolite_public_key.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddIndexesToGitolitePublicKey < ActiveRecord::Migration[4.2] - def change - add_index :gitolite_public_keys, :identifier - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20111123214911_add_settings_to_plugin.rb b/plugins/redmine_git_hosting/db/migrate/20111123214911_add_settings_to_plugin.rb deleted file mode 100644 index 5e05baa..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20111123214911_add_settings_to_plugin.rb +++ /dev/null @@ -1,34 +0,0 @@ -class AddSettingsToPlugin < ActiveRecord::Migration[4.2] - def up - # Add some new settings to settings page, if they don't exist - valuehash = Setting.plugin_redmine_git_hosting.clone - valuehash['gitRecycleBasePath'] ||= 'recycle_bin/' - valuehash['gitRecycleExpireTime'] ||= '24.0' - valuehash['gitLockWaitTime'] ||= '10' - valuehash['httpServer'] ||= RedmineGitHosting::Config.my_root_url - - if Setting.plugin_redmine_git_hosting != valuehash - Setting.plugin_redmine_git_hosting = valuehash - say 'Added redmine_git_hosting settings: gitRecycleBasePath, getRecycleExpireTime, getLockWaitTime, httpServer' - end - rescue => e - say e.message - end - - def down - # Remove above settings from plugin page - valuehash = Setting.plugin_redmine_git_hosting.clone - valuehash.delete('gitRecycleBasePath') - valuehash.delete('gitRecycleExpireTime') - valuehash.delete('gitLockWaitTime') - valuehash.delete('gitLockWaitTime') - - if Setting.plugin_redmine_git_hosting != valuehash - Setting.plugin_redmine_git_hosting = valuehash - say 'Removed redmine_git_hosting settings: gitRecycleBasePath, getRecycleExpireTime, getLockWaitTime, httpServer' - end - Setting.plugin_redmine_git_hosting = valuehash - rescue => e - say e.message - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20111220055819_add_settings_to_plugin_2.rb b/plugins/redmine_git_hosting/db/migrate/20111220055819_add_settings_to_plugin_2.rb deleted file mode 100644 index 359bae4..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20111220055819_add_settings_to_plugin_2.rb +++ /dev/null @@ -1,47 +0,0 @@ -class AddSettingsToPlugin2 < ActiveRecord::Migration[4.2] - def up - # Add some new settings to settings page, if they don't exist - valuehash = Setting.plugin_redmine_git_hosting.clone - valuehash['httpServerSubdir'] ||= '' - valuehash['gitRedmineSubdir'] ||= '' - valuehash['gitRepositoryHierarchy'] ||= 'true' - - # Fix httpServer by removing directory components - valuehash['httpServer'] = (valuehash['httpServer'][%r{^[^\/]*}]) - - if Setting.plugin_redmine_git_hosting != valuehash - say 'Added redmine_git_hosting settings: httpServerSubdir, gitRedmineSubdir, gitRepositoryHierarchy' - - if Setting.plugin_redmine_git_hosting['httpServer'] != valuehash['httpServer'] - say "Updated 'httpServer' from '#{Setting.plugin_redmine_git_hosting['httpServer']}' to '#{valuehash['httpServer']}'." - end - - Setting.plugin_redmine_git_hosting = valuehash - end - rescue => e - say e.message - end - - def down - # Remove above settings from plugin page - valuehash = Setting.plugin_redmine_git_hosting.clone - valuehash.delete('httpServerSubdir') - valuehash.delete('gitRedmineSubdir') - valuehash.delete('gitRepositoryHierarchy') - - # Restore redmine root directory to httpServer (remove trailing '/') - valuehash['httpServer'] = RedmineGitHosting::Config.my_root_url - - if Setting.plugin_redmine_git_hosting != valuehash - say 'Removed redmine_git_hosting settings: httpServerSubdir, gitRedmineSubdir, gitRepositoryHierarchy' - - if Setting.plugin_redmine_git_hosting['httpServer'] != valuehash['httpServer'] - say "Updated 'httpServer' from '#{Setting.plugin_redmine_git_hosting['httpServer']}' to '#{valuehash['httpServer']}'." - end - - Setting.plugin_redmine_git_hosting = valuehash - end - rescue => e - say e.message - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20120226013750_add_settings_to_plugin_3.rb b/plugins/redmine_git_hosting/db/migrate/20120226013750_add_settings_to_plugin_3.rb deleted file mode 100644 index 5c1db4c..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20120226013750_add_settings_to_plugin_3.rb +++ /dev/null @@ -1,40 +0,0 @@ -class AddSettingsToPlugin3 < ActiveRecord::Migration[4.2] - def up - # Add some new settings to settings page, if they don't exist - valuehash = Setting.plugin_redmine_git_hosting.clone - valuehash['gitDaemonDefault'] ||= '1' - valuehash['gitHttpDefault'] ||= '1' - valuehash['gitNotifyCIADefault'] ||= '0' - valuehash['gitTempDataDir'] ||= '/tmp/redmine_git_hosting/' - valuehash['gitScriptDir'] ||= '' - - if Setting.plugin_redmine_git_hosting != valuehash - say 'Added redmine_git_hosting settings: gitDaemonDefault, gitHttpDefault, gitNotifyCIADefault, gitTempDataDir, gitScriptDir' - - if Setting.plugin_redmine_git_hosting['httpServer'] != valuehash['httpServer'] - say "Updated 'httpServer' from '#{Setting.plugin_redmine_git_hosting['httpServer']}' to '#{valuehash['httpServer']}'." - end - - Setting.plugin_redmine_git_hosting = valuehash - end - rescue => e - say e.message - end - - def down - # Remove above settings from plugin page - valuehash = Setting.plugin_redmine_git_hosting.clone - valuehash.delete('gitDaemonDefault') - valuehash.delete('gitHttpDefault') - valuehash.delete('gitNotifyDIADefault') - valuehash.delete('gitTempDataDir') - valuehash.delete('gitScriptDir') - - if Setting.plugin_redmine_git_hosting != valuehash - say 'Removed redmine_git_hosting settings: gitDaemonDefault, gitHttpDefault, gitNotifyCIADefault, gitTempDataDir, gitScriptDir' - Setting.plugin_redmine_git_hosting = valuehash - end - rescue => e - say e.message - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20120521000000_create_repository_post_receive_urls.rb b/plugins/redmine_git_hosting/db/migrate/20120521000000_create_repository_post_receive_urls.rb deleted file mode 100644 index 33fff7c..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20120521000000_create_repository_post_receive_urls.rb +++ /dev/null @@ -1,11 +0,0 @@ -class CreateRepositoryPostReceiveUrls < ActiveRecord::Migration[4.2] - def change - create_table :repository_post_receive_urls do |t| - t.column :project_id, :integer - t.column :active, :integer, default: 1 - t.column :url, :string - t.references :project - t.timestamps - end - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20120521000010_set_post_receive_url_role_permissions.rb b/plugins/redmine_git_hosting/db/migrate/20120521000010_set_post_receive_url_role_permissions.rb deleted file mode 100644 index 6127c2a..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20120521000010_set_post_receive_url_role_permissions.rb +++ /dev/null @@ -1,53 +0,0 @@ -class SetPostReceiveUrlRolePermissions < ActiveRecord::Migration[4.2] - def up - manager_role_name = I18n.t(:default_role_manager, locale: Setting.default_language) - say "Updating role : '#{manager_role_name}'..." - manager_role = Role.find_by(name: manager_role_name) - if !manager_role.nil? - manager_role.add_permission! :view_repository_post_receive_urls - manager_role.add_permission! :create_repository_post_receive_urls - manager_role.add_permission! :edit_repository_post_receive_urls - manager_role.save - say 'Done !' - else - say "Role '#{manager_role_name}' not found, exit !" - end - - developer_role_name = I18n.t(:default_role_developer, locale: Setting.default_language) - say "Updating role : '#{developer_role_name}'..." - developer_role = Role.find_by(name: developer_role_name) - if !developer_role.nil? - developer_role.add_permission! :view_repository_post_receive_urls - developer_role.save - say 'Done !' - else - say "Role '#{developer_role_name}' not found, exit !" - end - end - - def down - manager_role_name = I18n.t(:default_role_manager, locale: Setting.default_language) - say "Updating role : '#{manager_role_name}'..." - manager_role = Role.find_by(name: manager_role_name) - if !manager_role.nil? - manager_role.remove_permission! :view_repository_post_receive_urls - manager_role.remove_permission! :create_repository_post_receive_urls - manager_role.remove_permission! :edit_repository_post_receive_urls - manager_role.save - say 'Done !' - else - say "Role '#{manager_role_name}' not found, exit !" - end - - developer_role_name = I18n.t(:default_role_developer, locale: Setting.default_language) - say "Updating role : '#{developer_role_name}'..." - developer_role = Role.find_by(name: developer_role_name) - if !developer_role.nil? - developer_role.remove_permission! :view_repository_post_receive_urls - developer_role.save - say 'Done !' - else - say "Role '#{developer_role_name}' not found, exit !" - end - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20120522000000_add_post_receive_url_modes.rb b/plugins/redmine_git_hosting/db/migrate/20120522000000_add_post_receive_url_modes.rb deleted file mode 100644 index 9d2c209..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20120522000000_add_post_receive_url_modes.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddPostReceiveUrlModes < ActiveRecord::Migration[4.2] - def change - add_column :repository_post_receive_urls, :mode, :string, default: 'github' - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20120708070841_add_settings_to_plugin_4.rb b/plugins/redmine_git_hosting/db/migrate/20120708070841_add_settings_to_plugin_4.rb deleted file mode 100644 index 4616ebf..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20120708070841_add_settings_to_plugin_4.rb +++ /dev/null @@ -1,27 +0,0 @@ -class AddSettingsToPlugin4 < ActiveRecord::Migration[4.2] - def up - # Add some new settings to settings page, if they don't exist - valuehash = Setting.plugin_redmine_git_hosting.clone - valuehash['gitForceHooksUpdate'] ||= 'true' - - if Setting.plugin_redmine_git_hosting != valuehash - say 'Added redmine_git_hosting settings: gitForceHooksUpdate' - Setting.plugin_redmine_git_hosting = valuehash - end - rescue => e - say e.message - end - - def down - # Remove above settings from plugin page - valuehash = Setting.plugin_redmine_git_hosting.clone - valuehash.delete('gitForceHooksUpdate') - - if Setting.plugin_redmine_git_hosting != valuehash - say 'Removed redmine_git_hosting settings: gitForceHooksUpdate' - Setting.plugin_redmine_git_hosting = valuehash - end - rescue => e - say e.message - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20120710204007_add_repository_mirror_fields.rb b/plugins/redmine_git_hosting/db/migrate/20120710204007_add_repository_mirror_fields.rb deleted file mode 100644 index 4aaf0d3..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20120710204007_add_repository_mirror_fields.rb +++ /dev/null @@ -1,8 +0,0 @@ -class AddRepositoryMirrorFields < ActiveRecord::Migration[4.2] - def change - add_column :repository_mirrors, :push_mode, :integer, default: 0 - add_column :repository_mirrors, :include_all_branches, :boolean, default: false - add_column :repository_mirrors, :include_all_tags, :boolean, default: false - add_column :repository_mirrors, :explicit_refspec, :string, default: '' - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20120724211806_add_settings_to_plugin_5.rb b/plugins/redmine_git_hosting/db/migrate/20120724211806_add_settings_to_plugin_5.rb deleted file mode 100644 index 06b43d9..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20120724211806_add_settings_to_plugin_5.rb +++ /dev/null @@ -1,29 +0,0 @@ -class AddSettingsToPlugin5 < ActiveRecord::Migration[4.2] - def up - # Add some new settings to settings page, if they don't exist - valuehash = Setting.plugin_redmine_git_hosting.clone - valuehash['gitConfigFile'] ||= 'gitolite.conf' - valuehash['gitConfigHasAdminKey'] ||= 'true' - - if Setting.plugin_redmine_git_hosting != valuehash - say 'Added redmine_git_hosting settings: gitConfigFile, gitConfigHasAdminKey' - Setting.plugin_redmine_git_hosting = valuehash - end - rescue => e - say e.message - end - - def down - # Remove above settings from plugin page - valuehash = Setting.plugin_redmine_git_hosting.clone - valuehash.delete('gitConfigFile') - valuehash.delete('gitConfigHasAdminKey') - - if Setting.plugin_redmine_git_hosting != valuehash - say 'Removed redmine_git_hosting settings: gitConfigFile, gitConfigHasAdminKey' - Setting.plugin_redmine_git_hosting = valuehash - end - rescue => e - say e.message - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20120803043256_create_deployment_credentials.rb b/plugins/redmine_git_hosting/db/migrate/20120803043256_create_deployment_credentials.rb deleted file mode 100644 index 4fb0b2b..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20120803043256_create_deployment_credentials.rb +++ /dev/null @@ -1,72 +0,0 @@ -class CreateDeploymentCredentials < ActiveRecord::Migration[4.2] - def up - create_table :deployment_credentials do |t| - t.references :repository - t.references :gitolite_public_key - t.references :user - - t.column :active, :integer, default: 1 - t.column :perm, :string, null: false - end - - add_index :deployment_credentials, :repository_id - add_index :deployment_credentials, :gitolite_public_key_id - - add_column :gitolite_public_keys, :key_type, :integer, default: GitolitePublicKey::KEY_TYPE_USER - add_column :gitolite_public_keys, :delete_when_unused, :boolean, default: true - - manager_role_name = I18n.t(:default_role_manager, locale: Setting.default_language) - say "Updating role : '#{manager_role_name}'..." - manager_role = Role.find_by(name: manager_role_name) - if !manager_role.nil? - manager_role.add_permission! :view_repository_deployment_credentials - manager_role.add_permission! :create_repository_deployment_credentials - manager_role.add_permission! :edit_repository_deployment_credentials - manager_role.save - say 'Done !' - else - say "Role '#{manager_role_name}' not found, exit !" - end - - developer_role_name = I18n.t(:default_role_developer, locale: Setting.default_language) - say "Updating role : '#{developer_role_name}'..." - developer_role = Role.find_by(name: developer_role_name) - if !developer_role.nil? - developer_role.add_permission! :view_repository_deployment_credentials - developer_role.save - say 'Done !' - else - say "Role '#{developer_role_name}' not found, exit !" - end - end - - def down - drop_table :deployment_credentials - remove_column :gitolite_public_keys, :key_type - remove_column :gitolite_public_keys, :delete_when_unused - - manager_role_name = I18n.t(:default_role_manager, locale: Setting.default_language) - say "Updating role : '#{manager_role_name}'..." - manager_role = Role.find_by(name: manager_role_name) - if !manager_role.nil? - manager_role.remove_permission! :view_repository_deployment_credentials - manager_role.remove_permission! :create_repository_deployment_credentials - manager_role.remove_permission! :edit_repository_deployment_credentials - manager_role.save - say 'Done !' - else - say "Role '#{manager_role_name}' not found, exit !" - end - - developer_role_name = I18n.t(:default_role_developer, locale: Setting.default_language) - say "Updating role : '#{developer_role_name}'..." - developer_role = Role.find_by(name: developer_role_name) - if !developer_role.nil? - developer_role.remove_permission! :view_repository_deployment_credentials - developer_role.save - say 'Done !' - else - say "Role '#{developer_role_name}' not found, exit !" - end - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20120904060609_update_multi_repo_per_project.rb b/plugins/redmine_git_hosting/db/migrate/20120904060609_update_multi_repo_per_project.rb deleted file mode 100644 index b4b0fb6..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20120904060609_update_multi_repo_per_project.rb +++ /dev/null @@ -1,126 +0,0 @@ -class UpdateMultiRepoPerProject < ActiveRecord::Migration[4.2] - def up - unless columns('repository_mirrors').index { |x| x.name == 'repository_id' } - add_column :repository_mirrors, :repository_id, :integer - begin - say 'Detaching repository mirrors from projects; attaching them to repositories...' - RepositoryMirror.all.each do |mirror| - mirror.repository_id = Project.find(mirror.project_id).repository.id - mirror.save! - end - say "Success. Changed #{RepositoryMirror.all.count} records." - rescue => e - say 'Failed to attach repository mirrors to repositories.' - say "Error: #{e.message}" - end - - remove_column :repository_mirrors, :project_id if columns('repository_mirrors').index { |x| x.name == 'project_id' } - end - - unless columns('repository_post_receive_urls').index { |x| x.name == 'repository_id' } - add_column :repository_post_receive_urls, :repository_id, :integer - begin - say 'Detaching repository post-receive-urls from projects; attaching them to repositories...' - RepositoryPostReceiveUrl.all.each do |prurl| - prurl.repository_id = Project.find(prurl.project_id).repository.id - prurl.save! - end - say "Success. Changed #{RepositoryPostReceiveUrl.all.count} records." - rescue => e - say 'Failed to attach repositories post-receive-urls to repositories.' - say "Error: #{e.message}" - end - - if columns('repository_post_receive_urls').index { |x| x.name == 'project_id' } - remove_column :repository_post_receive_urls, :project_id - end - end - - add_index :projects, [:identifier] unless index_exists?(:projects, :identifier) - if columns('repositories').index { |x| x.name == 'identifier' } - add_index :repositories, [:identifier] - add_index :repositories, %i[identifier project_id] - end - rename_column :git_caches, :proj_identifier, :repo_identifier - - begin - # Add some new settings to settings page, if they don't exist - valuehash = Setting.plugin_redmine_git_hosting.clone - if (Repository.all.map(&:identifier).inject(Hash.new(0) do |h, x| - h[x] += 1 if x.present? - h - end.values.max) || 0) > 1 - # Oops -- have duplication. Force to false. - valuehash['gitRepositoryIdentUnique'] = 'false' - else - # If no duplication -- set to true only if it doesn't already exist - valuehash['gitRepositoryIdentUnique'] ||= 'true' - end - - if Setting.plugin_redmine_git_hosting != valuehash - say "Added redmine_git_hosting settings: 'gitRepositoryIdentUnique' => #{valuehash['gitRepositoryIdentUnique']}" - Setting.plugin_redmine_git_hosting = valuehash - end - rescue => e - say "Error: #{e.message}" - end - end - - def down - unless columns('repository_mirrors').index { |x| x.name == 'project_id' } - add_column :repository_mirrors, :project_id, :integer - begin - say 'Detaching repository mirrors from repositories; re-attaching them to projects...' - RepositoryMirror.all.each do |mirror| - mirror.project_id = Repository.find(mirror.repository_id).project.id - mirror.save! - end - say "Success. Changed #{RepositoryMirror.all.count} records." - rescue => e - say 'Failed to re-attach repository mirrors to projects.' - say "Error: #{e.message}" - end - - remove_column :repository_mirrors, :repository_id if columns('repository_mirrors').index { |x| x.name == 'repository_id' } - end - - unless columns('repository_post_receive_urls').index { |x| x.name == 'project_id' } - add_column :repository_post_receive_urls, :project_id, :integer - begin - say 'Detaching repository post-receive-urls from repositories; re-attaching them to projects...' - RepositoryPostReceiveUrl.all.each do |prurl| - prurl.project_id = Repository.find(prurl.repository_id).project.id - prurl.save! - end - say "Success. Changed #{RepositoryPostReceiveUrl.all.count} records." - rescue => e - say 'Failed to re-attach repository post-receive urls to projects.' - say "Error: #{e.message}" - end - - if columns('repository_post_receive_urls').index { |x| x.name == 'repository_id' } - remove_column :repository_post_receive_urls, :repository_id - end - end - - remove_index :projects, [:identifier] - if columns('repositories').index { |x| x.name == 'identifier' } - remove_index :repositories, [:identifier] - remove_index :repositories, %i[identifier project_id] - end - rename_column :git_caches, :repo_identifier, :proj_identifier - - begin - # Remove above settings from plugin page - valuehash = Setting.plugin_redmine_git_hosting.clone - valuehash.delete('gitRepositoryIdentUnique') - - if Setting.plugin_redmine_git_hosting != valuehash - say 'Removed redmine_git_hosting settings: gitRepositoryIdentUnique' - Setting.plugin_redmine_git_hosting = valuehash - end - rescue => e - say "Error: #{e.message}" - end - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20130807223227_migrate_parameters.rb b/plugins/redmine_git_hosting/db/migrate/20130807223227_migrate_parameters.rb deleted file mode 100644 index ddc7801..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20130807223227_migrate_parameters.rb +++ /dev/null @@ -1,181 +0,0 @@ -class MigrateParameters < ActiveRecord::Migration[4.2] - def up - ## Prepare default values in case we install Redmine from scratch - new_setting = { - # Legacy settings - gitolite_user: 'git', - gitolite_server_port: '22', - gitolite_ssh_private_key: Rails.root.join('plugins/redmine_git_hosting/ssh_keys/redmine_gitolite_admin_id_rsa').to_s, - gitolite_ssh_public_key: Rails.root.join('plugins/redmine_git_hosting/ssh_keys/redmine_gitolite_admin_id_rsa.pub').to_s, - - gitolite_global_storage_dir: 'repositories/', - gitolite_redmine_storage_dir: '', - gitolite_recycle_bin_dir: 'recycle_bin/', - - gitolite_temp_dir: Rails.root.join('tmp/redmine_git_hosting').to_s, - gitolite_scripts_dir: './', - gitolite_timeout: '10', - gitolite_config_file: 'gitolite.conf', - gitolite_recycle_bin_expiration_time: '24.0', - - gitolite_overwrite_existing_hooks: 'true', - gitolite_hooks_are_asynchronous: 'false', - gitolite_hooks_debug: 'false', - - gitolite_cache_max_time: '86400', - gitolite_cache_max_size: '16', - gitolite_cache_max_elements: '2000', - - ssh_server_domain: 'localhost', - http_server_domain: 'localhost', - https_server_domain: '', - http_server_subdir: '', - show_repositories_url: 'true', - - gitolite_daemon_by_default: 'false', - gitolite_http_by_default: '1', - - all_projects_use_git: 'false', - delete_git_repositories: 'true', - hierarchical_organisation: 'true', - unique_repo_identifier: 'false', - - # New features settings - gitolite_log_level: 'info', - - gitolite_server_host: '127.0.0.1', - - git_config_username: 'Redmine Git Hosting', - git_config_email: 'redmine@example.net', - - gitolite_use_sidekiq: 'false', - init_repositories_on_create: 'false', - download_revision_enabled: 'true', - gitolite_identifier_prefix: 'redmine_', - gitolite_identifier_strip_user_id: 'false', - - gitolite_resync_all: 'false', - - gitolite_notify_by_default: 'false', - gitolite_notify_global_prefix: '[REDMINE]', - gitolite_notify_global_sender_address: 'redmine@example.net', - gitolite_notify_global_include: [], - gitolite_notify_global_exclude: [] - } - - ## Grab current values and update existing settings - Setting.plugin_redmine_git_hosting&.each do |key, value| - case key - # Gitolite SSH Config - when 'gitUser' then - new_setting[:gitolite_user] = value - - when 'sshServerLocalPort' then - new_setting[:gitolite_server_port] = value - - when 'gitoliteIdentityFile' then - new_setting[:gitolite_ssh_private_key] = value - - when 'gitoliteIdentityPublicKeyFile' then - new_setting[:gitolite_ssh_public_key] = value - - # Gitolite Storage Config - when 'gitRepositoryBasePath' then - new_setting[:gitolite_global_storage_dir] = value - - when 'gitRedmineSubdir' then - new_setting[:gitolite_redmine_storage_dir] = value - - when 'gitRecycleBasePath' then - new_setting[:gitolite_recycle_bin_dir] = value - - # Gitolite Global Config - when 'gitTempDataDir' then - new_setting[:gitolite_temp_dir] = value - - when 'gitScriptDir' then - new_setting[:gitolite_scripts_dir] = value - - when 'gitConfigFile' then - new_setting[:gitolite_config_file] = value - - when 'gitRecycleExpireTime' then - new_setting[:gitolite_recycle_bin_expiration_time] = value - - when 'gitLockWaitTime' then - new_setting[:gitolite_timeout] = value - - # Gitolite Hooks Config - when 'gitHooksAreAsynchronous' then - new_setting[:gitolite_hooks_are_asynchronous] = value - - when 'gitForceHooksUpdate' then - new_setting[:gitolite_overwrite_existing_hooks] = value - - when 'gitHooksDebug' then - new_setting[:gitolite_hooks_debug] = value - - # Gitolite Cache Config - when 'gitCacheMaxTime' then - new_setting[:gitolite_cache_max_time] = value - - when 'gitCacheMaxSize' then - new_setting[:gitolite_cache_max_size] = value - - when 'gitCacheMaxElements' then - new_setting[:gitolite_cache_max_elements] = value - - # Gitolite Access Config - when 'gitServer' then - new_setting[:ssh_server_domain] = value - - when 'httpServer' then - new_setting[:http_server_domain] = value - new_setting[:https_server_domain] = value - - when 'httpServerSubdir' then - new_setting[:http_server_subdir] = value - - when 'gitRepositoriesShowUrl' then - new_setting[:show_repositories_url] = value - - when 'gitDaemonDefault' then - new_setting[:gitolite_daemon_by_default] = if value == 1 - 'true' - else - 'false' - end - - when 'gitHttpDefault' then - new_setting[:gitolite_http_by_default] = value - - # Redmine Config - when 'allProjectsUseGit' then - new_setting[:all_projects_use_git] = value - - when 'deleteGitRepositories' then - new_setting[:delete_git_repositories] = value - - when 'gitRepositoryHierarchy' then - if Additionals.true? value - new_setting[:hierarchical_organisation] = 'true' - new_setting[:unique_repo_identifier] = 'false' - else - new_setting[:hierarchical_organisation] = 'false' - new_setting[:unique_repo_identifier] = 'true' - end - end - end - - say 'Applying configuration update ...' - say YAML.dump(new_setting) - - begin - Setting.plugin_redmine_git_hosting = new_setting - rescue => e - say "Error : #{e.message}" - else - say 'Done!' - end - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20130909195727_create_repository_git_notifications.rb b/plugins/redmine_git_hosting/db/migrate/20130909195727_create_repository_git_notifications.rb deleted file mode 100644 index 14d11b3..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20130909195727_create_repository_git_notifications.rb +++ /dev/null @@ -1,9 +0,0 @@ -class CreateRepositoryGitNotifications < ActiveRecord::Migration[4.2] - def change - create_table :repository_git_notifications do |t| - t.column :repository_id, :integer - t.column :include_list, :text - t.column :exclude_list, :text - end - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20130909195828_rename_table_git_repository_extras.rb b/plugins/redmine_git_hosting/db/migrate/20130909195828_rename_table_git_repository_extras.rb deleted file mode 100644 index 3bbc98b..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20130909195828_rename_table_git_repository_extras.rb +++ /dev/null @@ -1,5 +0,0 @@ -class RenameTableGitRepositoryExtras < ActiveRecord::Migration[4.2] - def change - rename_table :git_repository_extras, :repository_git_extras - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20130909195929_rename_table_deployment_credentials.rb b/plugins/redmine_git_hosting/db/migrate/20130909195929_rename_table_deployment_credentials.rb deleted file mode 100644 index 5ec5ce1..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20130909195929_rename_table_deployment_credentials.rb +++ /dev/null @@ -1,11 +0,0 @@ -class RenameTableDeploymentCredentials < ActiveRecord::Migration[4.2] - def up - remove_index :deployment_credentials, :gitolite_public_key_id - rename_table :deployment_credentials, :repository_deployment_credentials - end - - def down - rename_table :repository_deployment_credentials, :deployment_credentials - add_index :deployment_credentials, :gitolite_public_key_id - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20130910195930_add_columns_to_repository_git_extra.rb b/plugins/redmine_git_hosting/db/migrate/20130910195930_add_columns_to_repository_git_extra.rb deleted file mode 100644 index 6180cbc..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20130910195930_add_columns_to_repository_git_extra.rb +++ /dev/null @@ -1,11 +0,0 @@ -class AddColumnsToRepositoryGitExtra < ActiveRecord::Migration[4.2] - def up - return if RepositoryGitExtra.column_names.include? 'git_notify' - - add_column :repository_git_extras, :git_notify, :integer, default: 0, after: :git_http - end - - def down - remove_column :repository_git_extras, :git_notify - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20130910195931_add_columns_to_repository_git_notification.rb b/plugins/redmine_git_hosting/db/migrate/20130910195931_add_columns_to_repository_git_notification.rb deleted file mode 100644 index a619e46..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20130910195931_add_columns_to_repository_git_notification.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddColumnsToRepositoryGitNotification < ActiveRecord::Migration[4.2] - def change - add_column :repository_git_notifications, :prefix, :string - add_column :repository_git_notifications, :sender_address, :string - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20140305053200_remove_notify_cia.rb b/plugins/redmine_git_hosting/db/migrate/20140305053200_remove_notify_cia.rb deleted file mode 100644 index 8454593..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20140305053200_remove_notify_cia.rb +++ /dev/null @@ -1,13 +0,0 @@ -class RemoveNotifyCia < ActiveRecord::Migration[4.2] - def up - drop_table :git_cia_notifications - remove_column :repository_git_extras, :notify_cia - end - - def down - create_table :git_cia_notifications do |t| - t.column :repository_id, :integer - t.column :scmid, :string - end - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20140305083200_add_default_branch_to_repository_git_extra.rb b/plugins/redmine_git_hosting/db/migrate/20140305083200_add_default_branch_to_repository_git_extra.rb deleted file mode 100644 index 542bd91..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20140305083200_add_default_branch_to_repository_git_extra.rb +++ /dev/null @@ -1,16 +0,0 @@ -class AddDefaultBranchToRepositoryGitExtra < ActiveRecord::Migration[4.2] - def up - add_column :repository_git_extras, :default_branch, :string, after: :git_notify - - RepositoryGitExtra.reset_column_information - RepositoryGitExtra.all.each do |extra| - extra.update_attribute(:default_branch, 'master') - end - - change_column :repository_git_extras, :default_branch, :string, null: false - end - - def down - remove_column :repository_git_extras, :default_branch - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20140306002300_create_repository_git_config_keys.rb b/plugins/redmine_git_hosting/db/migrate/20140306002300_create_repository_git_config_keys.rb deleted file mode 100644 index 0f3db9a..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20140306002300_create_repository_git_config_keys.rb +++ /dev/null @@ -1,9 +0,0 @@ -class CreateRepositoryGitConfigKeys < ActiveRecord::Migration[4.2] - def change - create_table :repository_git_config_keys do |t| - t.column :repository_id, :integer - t.column :key, :string - t.column :value, :string - end - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20140327015700_create_github_issues.rb b/plugins/redmine_git_hosting/db/migrate/20140327015700_create_github_issues.rb deleted file mode 100644 index fc8f381..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20140327015700_create_github_issues.rb +++ /dev/null @@ -1,8 +0,0 @@ -class CreateGithubIssues < ActiveRecord::Migration[4.2] - def change - create_table :github_issues do |t| - t.column :github_id, :integer, null: false - t.column :issue_id, :integer, null: false - end - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20140327015701_create_github_comments.rb b/plugins/redmine_git_hosting/db/migrate/20140327015701_create_github_comments.rb deleted file mode 100644 index 0852202..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20140327015701_create_github_comments.rb +++ /dev/null @@ -1,8 +0,0 @@ -class CreateGithubComments < ActiveRecord::Migration[4.2] - def change - create_table :github_comments do |t| - t.column :github_id, :integer, null: false - t.column :journal_id, :integer, null: false - end - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20140417004100_enforce_models_constraints.rb b/plugins/redmine_git_hosting/db/migrate/20140417004100_enforce_models_constraints.rb deleted file mode 100644 index 4ead7e9..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20140417004100_enforce_models_constraints.rb +++ /dev/null @@ -1,16 +0,0 @@ -class EnforceModelsConstraints < ActiveRecord::Migration[4.2] - def up - change_column :git_caches, :command_output, :binary, limit: 16_777_216 - remove_column :repository_mirrors, :created_at - remove_column :repository_mirrors, :updated_at - remove_column :repository_post_receive_urls, :created_at - remove_column :repository_post_receive_urls, :updated_at - end - - def down - add_column :repository_mirrors, :created_at, :datetime - add_column :repository_mirrors, :updated_at, :datetime - add_column :repository_post_receive_urls, :created_at, :datetime - add_column :repository_post_receive_urls, :updated_at, :datetime - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20140423224900_convert_boolean.rb b/plugins/redmine_git_hosting/db/migrate/20140423224900_convert_boolean.rb deleted file mode 100644 index f7860e3..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20140423224900_convert_boolean.rb +++ /dev/null @@ -1,78 +0,0 @@ -class ConvertBoolean < ActiveRecord::Migration[4.2] - def up - ## GitolitePublicKey - add_column :gitolite_public_keys, :active_temp, :boolean, default: true, after: :key - GitolitePublicKey.reset_column_information - GitolitePublicKey.all.each do |p| - active_temp = p.active == 1 - say 'Update!' - p.update_column(:active_temp, active_temp) - end - remove_column :gitolite_public_keys, :active - rename_column :gitolite_public_keys, :active_temp, :active - - add_column :gitolite_public_keys, :delete_when_unused_temp, :boolean, default: true, after: :active - GitolitePublicKey.reset_column_information - GitolitePublicKey.all.each do |p| - delete_when_unused_temp = p.delete_when_unused == 1 - say 'Update!' - p.update_column(:delete_when_unused_temp, delete_when_unused_temp) - end - remove_column :gitolite_public_keys, :delete_when_unused - rename_column :gitolite_public_keys, :delete_when_unused_temp, :delete_when_unused - - ## RepositoryGitExtra - add_column :repository_git_extras, :git_daemon_temp, :boolean, default: true, after: :git_daemon - RepositoryGitExtra.reset_column_information - RepositoryGitExtra.all.each do |p| - git_daemon_temp = p.git_daemon == 1 - say 'Update!' - p.update_column(:git_daemon_temp, git_daemon_temp) - end - remove_column :repository_git_extras, :git_daemon - rename_column :repository_git_extras, :git_daemon_temp, :git_daemon - - add_column :repository_git_extras, :git_notify_temp, :boolean, default: true, after: :git_notify - RepositoryGitExtra.reset_column_information - RepositoryGitExtra.all.each do |p| - git_notify_temp = p.git_notify == 1 - say 'Update!' - p.update_column(:git_notify_temp, git_notify_temp) - end - remove_column :repository_git_extras, :git_notify - rename_column :repository_git_extras, :git_notify_temp, :git_notify - - ## RepositoryDeploymentCredential - add_column :repository_deployment_credentials, :active_temp, :boolean, default: true, after: :active - RepositoryDeploymentCredential.reset_column_information - RepositoryDeploymentCredential.all.each do |p| - active_temp = p.active == 1 - say 'Update!' - p.update_column(:active_temp, active_temp) - end - remove_column :repository_deployment_credentials, :active - rename_column :repository_deployment_credentials, :active_temp, :active - - ## RepositoryMirror - add_column :repository_mirrors, :active_temp, :boolean, default: true, after: :active - RepositoryMirror.reset_column_information - RepositoryMirror.all.each do |p| - active_temp = p.active == 1 - say 'Update!' - p.update_column(:active_temp, active_temp) - end - remove_column :repository_mirrors, :active - rename_column :repository_mirrors, :active_temp, :active - - ## RepositoryPostReceiveUrl - add_column :repository_post_receive_urls, :active_temp, :boolean, default: true, after: :active - RepositoryPostReceiveUrl.reset_column_information - RepositoryPostReceiveUrl.all.each do |p| - active_temp = p.active == 1 - say 'Update!' - p.update_column(:active_temp, active_temp) - end - remove_column :repository_post_receive_urls, :active - rename_column :repository_post_receive_urls, :active_temp, :active - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20140516224900_add_trigger_to_post_receive.rb b/plugins/redmine_git_hosting/db/migrate/20140516224900_add_trigger_to_post_receive.rb deleted file mode 100644 index bf18fff..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20140516224900_add_trigger_to_post_receive.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddTriggerToPostReceive < ActiveRecord::Migration[4.2] - def change - add_column :repository_post_receive_urls, :use_triggers, :boolean, default: false - add_column :repository_post_receive_urls, :triggers, :text - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20140523013000_add_split_payloads_to_post_receive.rb b/plugins/redmine_git_hosting/db/migrate/20140523013000_add_split_payloads_to_post_receive.rb deleted file mode 100644 index e0faa99..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20140523013000_add_split_payloads_to_post_receive.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddSplitPayloadsToPostReceive < ActiveRecord::Migration[4.2] - def change - add_column :repository_post_receive_urls, :split_payloads, :boolean, default: false - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20140618224954_add_fingerprint_to_gitolite_public_keys.rb b/plugins/redmine_git_hosting/db/migrate/20140618224954_add_fingerprint_to_gitolite_public_keys.rb deleted file mode 100644 index e20851f..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20140618224954_add_fingerprint_to_gitolite_public_keys.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddFingerprintToGitolitePublicKeys < ActiveRecord::Migration[4.2] - def change - add_column :gitolite_public_keys, :fingerprint, :string, after: 'key' - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20140618231512_create_unique_indexes.rb b/plugins/redmine_git_hosting/db/migrate/20140618231512_create_unique_indexes.rb deleted file mode 100644 index 66b3f22..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20140618231512_create_unique_indexes.rb +++ /dev/null @@ -1,48 +0,0 @@ -class CreateUniqueIndexes < ActiveRecord::Migration[4.2] - def up - add_index :repository_git_extras, :repository_id, unique: true - - add_index :repository_git_notifications, :repository_id, unique: true - - add_index :repository_git_config_keys, :repository_id - add_index :repository_git_config_keys, %i[key repository_id], unique: true - - add_index :repository_post_receive_urls, :repository_id - add_index :repository_post_receive_urls, %i[url repository_id], unique: true - - add_index :repository_mirrors, :repository_id - add_index :repository_mirrors, %i[url repository_id], unique: true - - add_index :repository_deployment_credentials, - %i[repository_id gitolite_public_key_id], - unique: true, - name: 'index_deployment_credentials_on_repo_id_and_public_key_id' - - add_index :gitolite_public_keys, %i[title user_id], unique: true - - add_index :github_comments, %i[github_id journal_id], unique: true - add_index :github_issues, %i[github_id issue_id], unique: true - end - - def down - remove_index :repository_git_extras, :repository_id - remove_index :repository_git_notifications, :repository_id - - remove_index :repository_git_config_keys, :repository_id - remove_index :repository_git_config_keys, %i[key repository_id] - - remove_index :repository_post_receive_urls, :repository_id - remove_index :repository_post_receive_urls, %i[url repository_id] - - remove_index :repository_mirrors, :repository_id - remove_index :repository_mirrors, %i[url repository_id] - - remove_index :repository_deployment_credentials, - name: 'index_deployment_credentials_on_repo_id_and_public_key_id' - - remove_index :gitolite_public_keys, %i[title user_id] - - remove_index :github_comments, %i[github_id journal_id] - remove_index :github_issues, %i[github_id issue_id] - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20140621004200_create_repository_protected_branches.rb b/plugins/redmine_git_hosting/db/migrate/20140621004200_create_repository_protected_branches.rb deleted file mode 100644 index d331731..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20140621004200_create_repository_protected_branches.rb +++ /dev/null @@ -1,13 +0,0 @@ -class CreateRepositoryProtectedBranches < ActiveRecord::Migration[4.2] - def change - create_table :repository_protected_branches do |t| - t.column :repository_id, :integer - t.column :path, :string - t.column :permissions, :string - t.column :user_list, :text - t.column :position, :integer - end - - add_index :repository_protected_branches, :repository_id - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20140621004300_add_protected_branch_to_repository_git_extra.rb b/plugins/redmine_git_hosting/db/migrate/20140621004300_add_protected_branch_to_repository_git_extra.rb deleted file mode 100644 index 4a7ba1b..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20140621004300_add_protected_branch_to_repository_git_extra.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddProtectedBranchToRepositoryGitExtra < ActiveRecord::Migration[4.2] - def change - add_column :repository_git_extras, :protected_branch, :boolean, default: false, after: :default_branch - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20140624150200_remove_gitolite_public_keys_active_column.rb b/plugins/redmine_git_hosting/db/migrate/20140624150200_remove_gitolite_public_keys_active_column.rb deleted file mode 100644 index 38c9ffc..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20140624150200_remove_gitolite_public_keys_active_column.rb +++ /dev/null @@ -1,9 +0,0 @@ -class RemoveGitolitePublicKeysActiveColumn < ActiveRecord::Migration[4.2] - def up - remove_column :gitolite_public_keys, :active - end - - def down - add_column :gitolite_public_keys, :active, :boolean, default: true, after: :fingerprint - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20141228193500_add_git_annex_to_git_extras.rb b/plugins/redmine_git_hosting/db/migrate/20141228193500_add_git_annex_to_git_extras.rb deleted file mode 100644 index 1074b88..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20141228193500_add_git_annex_to_git_extras.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddGitAnnexToGitExtras < ActiveRecord::Migration[4.2] - def change - add_column :repository_git_extras, :git_annex, :boolean, default: false, after: :git_notify - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20150125234500_add_public_repo_to_repository_git_extra.rb b/plugins/redmine_git_hosting/db/migrate/20150125234500_add_public_repo_to_repository_git_extra.rb deleted file mode 100644 index f461b17..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20150125234500_add_public_repo_to_repository_git_extra.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddPublicRepoToRepositoryGitExtra < ActiveRecord::Migration[4.2] - def change - add_column :repository_git_extras, :public_repo, :boolean, default: false, after: :protected_branch - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20150410031920_add_urls_order_to_repository_git_extra.rb b/plugins/redmine_git_hosting/db/migrate/20150410031920_add_urls_order_to_repository_git_extra.rb deleted file mode 100644 index 6c1d6e2..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20150410031920_add_urls_order_to_repository_git_extra.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddUrlsOrderToRepositoryGitExtra < ActiveRecord::Migration[4.2] - def change - add_column :repository_git_extras, :urls_order, :text - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20150604051500_add_unique_index_to_fingerprint.rb b/plugins/redmine_git_hosting/db/migrate/20150604051500_add_unique_index_to_fingerprint.rb deleted file mode 100644 index 6840444..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20150604051500_add_unique_index_to_fingerprint.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddUniqueIndexToFingerprint < ActiveRecord::Migration[4.2] - def change - add_index :gitolite_public_keys, :fingerprint, unique: true - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20150703050000_add_type_field_to_git_config_keys.rb b/plugins/redmine_git_hosting/db/migrate/20150703050000_add_type_field_to_git_config_keys.rb deleted file mode 100644 index 6b6c4b8..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20150703050000_add_type_field_to_git_config_keys.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddTypeFieldToGitConfigKeys < ActiveRecord::Migration[4.2] - def change - add_column :repository_git_config_keys, :type, :string - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20150705180400_rename_git_config_keys_index.rb b/plugins/redmine_git_hosting/db/migrate/20150705180400_rename_git_config_keys_index.rb deleted file mode 100644 index 2007fc6..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20150705180400_rename_git_config_keys_index.rb +++ /dev/null @@ -1,11 +0,0 @@ -class RenameGitConfigKeysIndex < ActiveRecord::Migration[4.2] - def up - remove_index :repository_git_config_keys, %i[key repository_id] - add_index :repository_git_config_keys, %i[key type repository_id], unique: true, name: :unique_key_name - end - - def down - remove_index :repository_git_config_keys, name: :unique_key_name - add_index :repository_git_config_keys, %i[key repository_id], unique: true - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20150823030000_create_protected_branches_members.rb b/plugins/redmine_git_hosting/db/migrate/20150823030000_create_protected_branches_members.rb deleted file mode 100644 index 86d9d52..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20150823030000_create_protected_branches_members.rb +++ /dev/null @@ -1,14 +0,0 @@ -class CreateProtectedBranchesMembers < ActiveRecord::Migration[4.2] - def change - create_table :protected_branches_members do |t| - t.column :protected_branch_id, :integer - t.column :principal_id, :integer - t.column :inherited_by, :integer - end - - add_index :protected_branches_members, - %i[protected_branch_id principal_id inherited_by], - unique: true, - name: 'unique_protected_branch_member' - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20150823030100_migrate_protected_branches_users.rb b/plugins/redmine_git_hosting/db/migrate/20150823030100_migrate_protected_branches_users.rb deleted file mode 100644 index 9299583..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20150823030100_migrate_protected_branches_users.rb +++ /dev/null @@ -1,23 +0,0 @@ -class RepositoryProtectedBrancheWrapped < RepositoryProtectedBranche - serialize :user_list, Array -end - -class MigrateProtectedBranchesUsers < ActiveRecord::Migration[4.2] - def up - RepositoryProtectedBrancheWrapped.all.each do |protected_branch| - users = protected_branch.user_list.map { |u| User.find_by(login: u) }.compact.uniq - manager = RepositoryProtectedBranches::MemberManager.new(protected_branch) - manager.add_users(users.map(&:id)) - end - remove_column :repository_protected_branches, :user_list - end - - def down - add_column :repository_protected_branches, :user_list, :text, after: :permissions - RepositoryProtectedBrancheWrapped.all.each do |protected_branch| - users = protected_branch.users.map(&:login).compact.uniq - protected_branch.user_list = users - protected_branch.save! - end - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20151127024000_shrink_git_notifications.rb b/plugins/redmine_git_hosting/db/migrate/20151127024000_shrink_git_notifications.rb deleted file mode 100644 index f434213..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20151127024000_shrink_git_notifications.rb +++ /dev/null @@ -1,22 +0,0 @@ -class ShrinkGitNotifications < ActiveRecord::Migration[4.2] - def up - add_column :repository_git_extras, :notification_sender, :string - add_column :repository_git_extras, :notification_prefix, :string - drop_table :repository_git_notifications - end - - def down - remove_column :repository_git_extras, :notification_sender - remove_column :repository_git_extras, :notification_prefix - - create_table :repository_git_notifications do |t| - t.integer :repository_id - t.text :include_list - t.text :exclude_list - t.string :prefix - t.string :sender_address - end - - add_index :repository_git_notifications, :repository_id, unique: true - end -end diff --git a/plugins/redmine_git_hosting/db/migrate/20170102234000_split_smart_http.rb b/plugins/redmine_git_hosting/db/migrate/20170102234000_split_smart_http.rb deleted file mode 100644 index d603771..0000000 --- a/plugins/redmine_git_hosting/db/migrate/20170102234000_split_smart_http.rb +++ /dev/null @@ -1,49 +0,0 @@ -class SplitSmartHttp < ActiveRecord::Migration[4.2] - def up - add_column :repository_git_extras, :git_https, :boolean, default: false, after: :git_http - add_column :repository_git_extras, :git_ssh, :boolean, default: true, after: :git_https - add_column :repository_git_extras, :git_go, :boolean, default: false, after: :git_https - - add_column :repository_git_extras, :git_http_temp, :boolean, default: false, after: :git_http - - RepositoryGitExtra.reset_column_information - - RepositoryGitExtra.all.each do |git_extra| - case git_extra[:git_http] - when 1 # HTTPS only - git_extra.update_column(:git_https, true) - when 2 # HTTPS and HTTP - git_extra.update_column(:git_https, true) - git_extra.update_column(:git_http_temp, true) - else # HTTP only - git_extra.update_column(:git_http_temp, true) - end - end - - remove_column :repository_git_extras, :git_http - rename_column :repository_git_extras, :git_http_temp, :git_http - end - - def down - add_column :repository_git_extras, :git_http_temp, :integer, after: :git_http - - RepositoryGitExtra.reset_column_information - - RepositoryGitExtra.all.each do |git_extra| - if git_extra[:git_https] && git_extra[:git_http] - git_extra.update_column(:git_http_temp, 2) - elsif git_extra[:git_https] - git_extra.update_column(:git_http_temp, 1) - elsif git_extra[:git_http] - git_extra.update_column(:git_http_temp, 3) - end - end - - remove_column :repository_git_extras, :git_https - remove_column :repository_git_extras, :git_ssh - remove_column :repository_git_extras, :git_go - - remove_column :repository_git_extras, :git_http - rename_column :repository_git_extras, :git_http_temp, :git_http - end -end diff --git a/plugins/redmine_git_hosting/init.rb b/plugins/redmine_git_hosting/init.rb deleted file mode 100644 index efb04aa..0000000 --- a/plugins/redmine_git_hosting/init.rb +++ /dev/null @@ -1,34 +0,0 @@ -require 'redmine' -require 'redmine_git_hosting' - -Redmine::Plugin.register :redmine_git_hosting do - name 'Redmine Git Hosting Plugin' - author 'A lot of people! A big thank to them for their contribution!' - description 'Enables Redmine to control hosting of Git repositories through Gitolite' - version RedmineGitHosting::VERSION - url 'http://redmine-git-hosting.io/' - author_url 'settings/plugin/redmine_git_hosting/authors' - - settings(partial: 'settings/redmine_git_hosting', default: RedmineGitHosting.settings) - requires_redmine version_or_higher: '4.1.0' - - menu :project_menu, - :new_repository, - { controller: 'repositories', action: 'new' }, - param: :project_id, - caption: :label_repository_new, - parent: :new_object - - begin - requires_redmine_plugin :additionals, version_or_higher: '3.0.1' - rescue Redmine::PluginNotFound - raise 'Please install additionals plugin (https://github.com/alphanodes/additionals)' - end -end - -# This *must stay after* Redmine::Plugin.register statement -# because it needs to access to plugin settings... -# so we need the plugin to be fully registered... -Rails.configuration.to_prepare do - require_dependency 'load_gitolite_hooks' -end diff --git a/plugins/redmine_git_hosting/lib/default_settings.yml b/plugins/redmine_git_hosting/lib/default_settings.yml deleted file mode 100644 index 1b4a16e..0000000 --- a/plugins/redmine_git_hosting/lib/default_settings.yml +++ /dev/null @@ -1,69 +0,0 @@ ---- -# Gitolite SSH Config -gitolite_user: 'git' -gitolite_server_host: '127.0.0.1' -gitolite_server_port: '22' -gitolite_ssh_private_key: <%= Rails.root.join('plugins', 'redmine_git_hosting', 'ssh_keys', 'redmine_gitolite_admin_id_rsa') %> -gitolite_ssh_public_key: <%= Rails.root.join('plugins', 'redmine_git_hosting', 'ssh_keys', 'redmine_gitolite_admin_id_rsa.pub') %> - -# Gitolite Storage Config -gitolite_global_storage_dir: 'repositories/' -gitolite_redmine_storage_dir: '' -gitolite_recycle_bin_dir: 'recycle_bin/' - -# Gitolite Config File -gitolite_config_file: 'gitolite.conf' -gitolite_identifier_prefix: 'redmine_' -gitolite_identifier_strip_user_id: 'false' - -# Gitolite Global Config -gitolite_temp_dir: <%= Rails.root.join('tmp', 'redmine_git_hosting') %> -gitolite_recycle_bin_expiration_time: '24.0' -gitolite_log_level: 'info' -git_config_username: 'Redmine Git Hosting' -git_config_email: 'redmine@example.net' - -# Gitolite Hooks Config -gitolite_overwrite_existing_hooks: 'true' -gitolite_hooks_are_asynchronous: 'false' -gitolite_hooks_debug: 'false' -gitolite_hooks_url: 'http://localhost:3000' - -# Gitolite Cache Config -gitolite_cache_max_time: '86400' -gitolite_cache_max_size: '16' -gitolite_cache_max_elements: '2000' -gitolite_cache_adapter: 'database' - -# Gitolite Access Config -ssh_server_domain: 'localhost' -http_server_domain: 'localhost' -https_server_domain: 'localhost' -http_server_subdir: '' -gitolite_daemon_by_default: 'false' -gitolite_http_by_default: '1' - -# Redmine Config -redmine_has_rw_access_on_all_repos: 'true' -all_projects_use_git: 'false' -init_repositories_on_create: 'false' -delete_git_repositories: 'true' - -# This params work together! -# When hierarchical_organisation = true unique_repo_identifier MUST be false -# When hierarchical_organisation = false unique_repo_identifier MUST be true -hierarchical_organisation: 'true' -unique_repo_identifier: 'false' - -# Download Revision Config -download_revision_enabled: 'true' - -# Git Mailing List Config -gitolite_notify_by_default: 'false' -gitolite_notify_global_prefix: '[REDMINE]' -gitolite_notify_global_sender_address: 'redmine@example.net' -gitolite_notify_global_include: [] -gitolite_notify_global_exclude: [] - -# Sidekiq Config -gitolite_use_sidekiq: 'false' diff --git a/plugins/redmine_git_hosting/lib/hrack/init.rb b/plugins/redmine_git_hosting/lib/hrack/init.rb deleted file mode 100644 index 68ce805..0000000 --- a/plugins/redmine_git_hosting/lib/hrack/init.rb +++ /dev/null @@ -1,2 +0,0 @@ -$LOAD_PATH.push File.expand_path('lib', __dir__) -require 'hrack' diff --git a/plugins/redmine_git_hosting/lib/hrack/lib/hrack.rb b/plugins/redmine_git_hosting/lib/hrack/lib/hrack.rb deleted file mode 100644 index d18f786..0000000 --- a/plugins/redmine_git_hosting/lib/hrack/lib/hrack.rb +++ /dev/null @@ -1,3 +0,0 @@ -module Hrack - require 'hrack/bundle' -end diff --git a/plugins/redmine_git_hosting/lib/hrack/lib/hrack/bundle.rb b/plugins/redmine_git_hosting/lib/hrack/lib/hrack/bundle.rb deleted file mode 100644 index c3d38ee..0000000 --- a/plugins/redmine_git_hosting/lib/hrack/lib/hrack/bundle.rb +++ /dev/null @@ -1,16 +0,0 @@ -require 'rack/builder' -require 'rack/parser' -require 'hrack/server' - -module Hrack - module Bundle - module_function - - def new(config) - Rack::Builder.new do - use Rack::Parser - run Hrack::Server.new(config) - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/hrack/lib/hrack/server.rb b/plugins/redmine_git_hosting/lib/hrack/lib/hrack/server.rb deleted file mode 100644 index de18b97..0000000 --- a/plugins/redmine_git_hosting/lib/hrack/lib/hrack/server.rb +++ /dev/null @@ -1,119 +0,0 @@ -require 'digest/sha1' - -module Hrack - class Server - attr_reader :params - - PLAIN_TYPE = { 'Content-Type' => 'text/plain' } - - def initialize(config = {}) - end - - def call(env) - dup._call(env) - end - - def _call(env) - @env = env - @req = Rack::Request.new(env) - @params = @req.params.deep_symbolize_keys - - command, @project = match_routing - - return render_404('Command Not Found') unless command - return render_404('Project Not Found') unless @project - - self.method(command).call() - end - - def post_receive_redmine - @repository = find_repository - return render_404('Repository Not Found') if @repository.nil? - if !valid_encoded_time?(params[:clear_time], params[:encoded_time], @repository.gitolite_hook_key) - return render_403('The hook key provided is not valid. Please let your server admin know about it') - end - - @res = Rack::Response.new - @res.status = 200 - @res['Content-Type'] = 'text/plain;' - @res.finish do - @res.write Repositories::ExecuteHooks.call(@repository, :fetch_changesets) - @res.write Repositories::ExecuteHooks.call(@repository, :update_mirrors, payloads) - @res.write Repositories::ExecuteHooks.call(@repository, :call_webservices, payloads) - end - end - - def post_receive_github - Projects::ExecuteHooks.call(@project, :github, params) - render_200('OK!') - end - - private - - def payloads - @payloads ||= Repositories::BuildPayload.call(@repository, params[:refs]) - end - - def match_routing - command = find_command - project = find_project - return command, project - end - - def find_command - return nil unless path_parameters.key?(:type) - - case path_parameters[:type] - when 'redmine' - :post_receive_redmine - when 'github' - :post_receive_github - end - end - - def find_project - Project.find_by_identifier(path_parameters[:projectid]) if path_parameters.key?(:projectid) - end - - # Locate that actual repository that is in use here. - # Notice that an empty "repositoryid" is assumed to refer to the default repo for a project - def find_repository - if params[:repositoryid].present? - @project.repositories.find_by_identifier(params[:repositoryid]) - else - # return default or first repo with blank identifier - @project.repository || @project.repo_blank_ident - end - end - - def render_200(message) - [200, PLAIN_TYPE, [message]] - end - - def render_404(message) - [404, PLAIN_TYPE, [message]] - end - - def render_403(message) - [403, PLAIN_TYPE, [message]] - end - - def path_parameters - @env['action_dispatch.request.path_parameters'] - end - - def valid_encoded_time?(clear_time, encoded_time, key) - cur_time = Time.new.utc.to_i - test_time = clear_time.to_i - not_to_late?(cur_time, test_time) && encode_key(clear_time, key) == encoded_time.to_s - end - - def not_to_late?(cur_time, test_time) - cur_time - test_time < 5 * 60 - end - - def encode_key(time, key) - Digest::SHA1.hexdigest(time.to_s + key.to_s).to_s - end - end -end diff --git a/plugins/redmine_git_hosting/lib/hrack/lib/hrack/version.rb b/plugins/redmine_git_hosting/lib/hrack/lib/hrack/version.rb deleted file mode 100644 index 78e54f5..0000000 --- a/plugins/redmine_git_hosting/lib/hrack/lib/hrack/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module Hrack - VERSION = '1.0.0'.freeze -end diff --git a/plugins/redmine_git_hosting/lib/load_gitolite_hooks.rb b/plugins/redmine_git_hosting/lib/load_gitolite_hooks.rb deleted file mode 100644 index 991233f..0000000 --- a/plugins/redmine_git_hosting/lib/load_gitolite_hooks.rb +++ /dev/null @@ -1,72 +0,0 @@ -RedmineGitHosting::GitoliteHooks.register_hooks do - # Set source dir - source_dir Rails.root.join('plugins/redmine_git_hosting/contrib/hooks').to_s - - # Declare GitoliteHooks to install - - # Install executable - gitolite_hook do - name 'redmine_gitolite.rb' - source 'post-receive/redmine_gitolite.rb' - destination 'post-receive' - executable true - end - - gitolite_hook do - name 'mail_notifications.py' - source 'post-receive/mail_notifications.py' - destination 'post-receive.d/mail_notifications' - executable true - end - - # Install libs - gitolite_hook do - name 'git_hosting_config.rb' - source 'post-receive/lib/git_hosting_config.rb' - destination 'lib/git_hosting/config.rb' - executable false - end - - gitolite_hook do - name 'git_hosting_custom_hook.rb' - source 'post-receive/lib/git_hosting_custom_hook.rb' - destination 'lib/git_hosting/custom_hook.rb' - executable false - end - - gitolite_hook do - name 'git_hosting_http_helper.rb' - source 'post-receive/lib/git_hosting_http_helper.rb' - destination 'lib/git_hosting/http_helper.rb' - executable false - end - - gitolite_hook do - name 'git_hosting_hook_logger.rb' - source 'post-receive/lib/git_hosting_hook_logger.rb' - destination 'lib/git_hosting/hook_logger.rb' - executable false - end - - gitolite_hook do - name 'git_hosting_post_receive.rb' - source 'post-receive/lib/git_hosting_post_receive.rb' - destination 'lib/git_hosting/post_receive.rb' - executable false - end - - gitolite_hook do - name 'git_multimail.py' - source 'post-receive/lib/git_multimail.py' - destination 'post-receive.d/git_multimail.py' - executable false - end -end - -# Gitolite hooks can be found in Redmine root dir or in plugin root dir -[ - Rails.root.join('redmine_git_hosting_hooks.rb').to_s, - Rails.root.join('plugins/redmine_git_hosting/custom_hooks.rb').to_s -].each do |file| - require_dependency file if File.exist? file -end diff --git a/plugins/redmine_git_hosting/lib/redmine/scm/adapters/xitolite_adapter.rb b/plugins/redmine_git_hosting/lib/redmine/scm/adapters/xitolite_adapter.rb deleted file mode 100644 index 36905d3..0000000 --- a/plugins/redmine_git_hosting/lib/redmine/scm/adapters/xitolite_adapter.rb +++ /dev/null @@ -1,531 +0,0 @@ -require 'redmine/scm/adapters/abstract_adapter' - -# XitoliteAdapter inherits from GitAdapter but some classes which are define directly in GitAdapter are not inherited -# (GitBranch, ScmCommandAborted and maybe others) so it raises NameError exception. -# To fix this I had to reimplement (copy/past) the whole GitAdapter class in XitoliteAdapter... -# I wanted to avoid it to avoid code duplication but it seems to be the only way... - -module Redmine - module Scm - module Adapters - class XitoliteAdapter < AbstractAdapter - # Git executable name - XITOLITE_BIN = Redmine::Configuration['scm_git_command'] || 'git' - - class GitBranch < Branch - attr_accessor :is_default - end - - class << self - def client_command - @@bin ||= XITOLITE_BIN - end - - def sq_bin - @@sq_bin ||= shell_quote_command - end - - def client_version - @@client_version ||= (scm_command_version || []) - end - - def client_available - !client_version.empty? - end - - def scm_command_version - scm_version = scm_version_from_command_line.dup - if scm_version.respond_to?(:force_encoding) - scm_version.force_encoding('ASCII-8BIT') - end - if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)}) - m[2].scan(%r{\d+}).collect(&:to_i) - end - end - - # Change from the original method - def scm_version_from_command_line - RedmineGitHosting::Commands.git_version - end - end - - def initialize(url, root_url = nil, login = nil, password = nil, path_encoding = nil) - super - @path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding - end - - def path_encoding - @path_encoding - end - - def info - begin - Info.new(root_url: url, lastrev: lastrev('', nil)) - rescue - nil - end - end - - def branches - return @branches if !@branches.nil? - - @branches = [] - cmd_args = %w|branch --no-color --verbose --no-abbrev| - git_cmd(cmd_args) do |io| - io.each_line do |line| - branch_rev = line.match('\s*(\*?)\s*(.*?)\s*([0-9a-f]{40}).*$') - bran = GitBranch.new(branch_rev[2].to_s.force_encoding(Encoding::UTF_8)) - bran.revision = branch_rev[3] - bran.scmid = branch_rev[3] - bran.is_default = (branch_rev[1] == '*') - @branches << bran - end - end - @branches.sort! - rescue ScmCommandAborted => e - logger.error(e.message) - [] - end - - def tags - return @tags if !@tags.nil? - - @tags = [] - cmd_args = %w|tag| - git_cmd(cmd_args) do |io| - @tags = io.readlines.sort!.map { |t| t.strip.force_encoding(Encoding::UTF_8) } - end - @tags - rescue ScmCommandAborted => e - logger.error(e.message) - [] - end - - def default_branch - bras = branches - return nil if bras.nil? - - default_bras = bras.select { |x| x.is_default == true } - return default_bras.first.to_s unless default_bras.empty? - - master_bras = bras.select { |x| x.to_s == 'master' } - master_bras.empty? ? bras.first.to_s : 'master' - end - - def entry(path = nil, identifier = nil) - parts = path.to_s.split(%r{[\/\\]}).select { |n| !n.blank? } - search_path = parts[0..-2].join('/') - search_name = parts[-1] - if search_path.blank? && search_name.blank? - # Root entry - Entry.new(path: '', kind: 'dir') - else - # Search for the entry in the parent directory - es = entries(search_path, identifier, report_last_commit: false) - es ? es.detect { |e| e.name == search_name } : nil - end - end - - def entries(path = nil, identifier = nil, options = {}) - path ||= '' - p = scm_iconv(@path_encoding, 'UTF-8', path) - entries = Entries.new - cmd_args = %w|ls-tree -l| - cmd_args << "HEAD:#{p}" if identifier.nil? - cmd_args << "#{identifier}:#{p}" if identifier - git_cmd(cmd_args) do |io| - io.each_line do |line| - e = line.chomp.to_s - if e =~ /^\d+\s+(\w+)\s+([0-9a-f]{40})\s+([0-9-]+)\t(.+)$/ - type = $1 - sha = $2 - size = $3 - name = $4 - name.force_encoding(@path_encoding) if name.respond_to?(:force_encoding) - full_path = p.empty? ? name : "#{p}/#{name}" - n = scm_iconv('UTF-8', @path_encoding, name) - full_p = scm_iconv('UTF-8', @path_encoding, full_path) - unless entries.detect { |entry| entry.name == name } - entries << Entry.new({ name: n, - path: full_p, - kind: (type == 'tree') ? 'dir' : 'file', - size: (type == 'tree') ? nil : size, - lastrev: options[:report_last_commit] ? lastrev(full_path, identifier) : Revision.new }) - end - end - end - end - entries.sort_by_name - rescue ScmCommandAborted => e - logger.error(e.message) - [] - end - - def lastrev(path, rev) - return nil if path.nil? - - cmd_args = %w|log --no-color --encoding=UTF-8 --date=iso --pretty=fuller --no-merges -n 1| - cmd_args << rev if rev - cmd_args << '--' << path unless path.empty? - lines = [] - git_cmd(cmd_args) { |io| lines = io.readlines } - begin - id = lines[0].split[1] - author = lines[1].match('Author:\s+(.*)$')[1] - time = Time.parse(lines[4].match('CommitDate:\s+(.*)$')[1]) - - Revision.new({ identifier: id, - scmid: id, - author: author, - time: time, - message: nil, - paths: nil }) - rescue NoMethodError => e - logger.error("The revision '#{path}' has a wrong format") - nil - end - rescue ScmCommandAborted => e - logger.error(e.message) - nil - end - - def revisions(path, identifier_from, identifier_to, options = {}) - revs = Revisions.new - cmd_args = %w|log --no-color --encoding=UTF-8 --raw --date=iso --pretty=fuller --parents --stdin| - cmd_args << '--reverse' if options[:reverse] - cmd_args << '-n' << "#{options[:limit].to_i}" if options[:limit] - cmd_args << '--' << scm_iconv(@path_encoding, 'UTF-8', path) if path && !path.empty? - revisions = [] - if identifier_from || identifier_to - revisions << '' - revisions[0] << "#{identifier_from}.." if identifier_from - revisions[0] << "#{identifier_to}" if identifier_to - else - revisions += options[:includes] unless options[:includes].blank? - revisions += options[:excludes].map { |r| "^#{r}" } unless options[:excludes].blank? - end - - git_cmd(cmd_args, { write_stdin: true }) do |io| - io.binmode - io.puts(revisions.join("\n")) - io.close_write - - files = [] - changeset = {} - - # 0: not parsing desc or files - # 1: parsing desc - # 2: parsing files - parsing_descr = 0 - - io.each_line do |line| - if line =~ /^commit ([0-9a-f]{40})(( [0-9a-f]{40})*)$/ - key = 'commit' - value = $1 - parents_str = $2 - if parsing_descr == 1 || parsing_descr == 2 - parsing_descr = 0 - revision = Revision.new({ identifier: changeset[:commit], - scmid: changeset[:commit], - author: changeset[:author], - time: Time.parse(changeset[:date]), - message: changeset[:description], - paths: files, - parents: changeset[:parents] }) - if block_given? - yield revision - else - revs << revision - end - changeset = {} - files = [] - end - changeset[:commit] = $1 - unless parents_str.nil? || parents_str == '' - changeset[:parents] = parents_str.strip.split(' ') - end - elsif (parsing_descr == 0) && line =~ /^(\w+):\s*(.*)$/ - key = $1 - value = $2 - if key == 'Author' - changeset[:author] = value - elsif key == 'CommitDate' - changeset[:date] = value - end - elsif (parsing_descr == 0) && line.chomp.to_s == '' - parsing_descr = 1 - changeset[:description] = '' - elsif (parsing_descr == 1 || parsing_descr == 2) \ - && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\t(.+)$/ - parsing_descr = 2 - fileaction = $1 - filepath = $2 - p = scm_iconv('UTF-8', @path_encoding, filepath) - files << { action: fileaction, path: p } - elsif (parsing_descr == 1 || parsing_descr == 2) \ - && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\d+\s+(\S+)\t(.+)$/ - parsing_descr = 2 - fileaction = $1 - filepath = $3 - p = scm_iconv('UTF-8', @path_encoding, filepath) - files << { action: fileaction, path: p } - elsif (parsing_descr == 1) && line.chomp.to_s == '' - parsing_descr = 2 - elsif (parsing_descr == 1) - changeset[:description] << line[4..-1] - end - end - - if changeset[:commit] - revision = Revision.new({ identifier: changeset[:commit], - scmid: changeset[:commit], - author: changeset[:author], - time: Time.parse(changeset[:date]), - message: changeset[:description], - paths: files, - parents: changeset[:parents] }) - if block_given? - yield revision - else - revs << revision - end - end - end - revs - rescue ScmCommandAborted => e - err_msg = "git log error: #{e.message}" - logger.error(err_msg) - if block_given? - raise CommandFailed, err_msg - else - revs - end - end - - # Override the original method to accept options hash - # which may contain *bypass_cache* flag and pass the options hash to *git_cmd*. - # - def diff(path, identifier_from, identifier_to = nil, opts = {}) - path ||= '' - cmd_args = [] - if identifier_to - cmd_args << 'diff' << '--no-color' << identifier_to << identifier_from - else - cmd_args << 'show' << '--no-color' << identifier_from - end - cmd_args << '--' << scm_iconv(@path_encoding, 'UTF-8', path) unless path.empty? - diff = [] - git_cmd(cmd_args, opts) do |io| - io.each_line do |line| - diff << line - end - end - diff - rescue ScmCommandAborted => e - logger.error(e.message) - nil - end - - def annotate(path, identifier = nil) - identifier = 'HEAD' if identifier.blank? - cmd_args = %w|blame --encoding=UTF-8| - cmd_args << '-p' << identifier << '--' << scm_iconv(@path_encoding, 'UTF-8', path) - blame = Annotate.new - content = nil - git_cmd(cmd_args) { |io| io.binmode; content = io.read } - # git annotates binary files - return nil if binary_data?(content) - - identifier = '' - # git shows commit author on the first occurrence only - authors_by_commit = {} - content.split("\n").each do |line| - if line =~ /^([0-9a-f]{39,40})\s.*/ - identifier = $1 - elsif line =~ /^author (.+)/ - authors_by_commit[identifier] = $1.strip - elsif line =~ /^\t(.*)/ - blame.add_line($1, Revision.new(identifier: identifier, - revision: identifier, - scmid: identifier, - author: authors_by_commit[identifier])) - identifier = '' - author = '' - end - end - blame - rescue ScmCommandAborted => e - logger.error(e.message) - nil - end - - def cat(path, identifier = nil) - identifier = 'HEAD' if identifier.nil? - cmd_args = %w|show --no-color| - cmd_args << "#{identifier}:#{scm_iconv(@path_encoding, 'UTF-8', path)}" - cat = nil - git_cmd(cmd_args) do |io| - io.binmode - cat = io.read - end - cat - rescue ScmCommandAborted => e - logger.error(e.message) - nil - end - - # Added to be compatible with EmailDiff plugin - # - def changed_files(path = nil, rev = 'HEAD') - path ||= '' - cmd_args = [] - cmd_args << 'log' << '--no-color' << '--pretty=format:%cd' << '--name-status' << '-1' << rev - cmd_args << '--' << scm_iconv(@path_encoding, 'UTF-8', path) unless path.empty? - changed_files = [] - git_cmd(cmd_args) do |io| - io.each_line do |line| - changed_files << line - end - end - changed_files - end - - # Added for GitDownloadRevision - # - def rev_list(revision, args) - cmd_args = ['rev-list', *args, revision] - git_cmd(cmd_args) do |io| - @revisions_list = io.readlines.map(&:strip) - end - @revisions_list - rescue ScmCommandAborted => e - logger.error(e.message) - [] - end - - # Added for GitDownloadRevision / GithubPayload - # - def rev_parse(revision) - cmd_args = ['rev-parse', '--quiet', '--verify', revision] - git_cmd(cmd_args) do |io| - @parsed_revision = io.readlines.map(&:strip).first - end - @parsed_revision - rescue ScmCommandAborted => e - logger.error(e.message) - nil - end - - # Added for GitDownloadRevision - # - def archive(revision, format) - cmd_args = ['archive'] - case format - when 'tar.gz' then - cmd_args << '--format=tar.gz' - cmd_args << '-7' - when 'zip' then - cmd_args << '--format=zip' - cmd_args << '-7' - else - cmd_args << '--format=tar' - end - cmd_args << revision - git_cmd(cmd_args, bypass_cache: true) do |io| - io.binmode - @content = io.read - end - @content - rescue ScmCommandAborted => e - logger.error(e.message) - nil - end - - # Added for MirrorPush - # - def mirror_push(mirror_url, branch = nil, args = []) - cmd_args = git_mirror_cmd.concat(['push', *args, mirror_url, branch]).compact - cmd = cmd_args.shift - RedmineGitHosting::Utils::Exec.capture(cmd, cmd_args, { merge_output: true }) - end - - class Revision < Redmine::Scm::Adapters::Revision - # Returns the readable identifier - def format_identifier - identifier[0, 8] - end - end - - private - - def logger - RedmineGitHosting.logger - end - - def git_cmd(args, options = {}, &block) - # Get options - bypass_cache = options.delete(:bypass_cache) { false } - - # Build git command line - cmd_str = prepare_command(args) - - # Insert cache between shell execution and caller - if !git_cache_id.nil? && git_cache_enabled? && !bypass_cache - RedmineGitHosting::ShellRedirector.execute(cmd_str, git_cache_id, options, &block) - else - Redmine::Scm::Adapters::AbstractAdapter.shellout(cmd_str, options, &block) - end - end - - def prepare_command(args) - # Get our basics args - full_args = base_args - # Concat with Redmine args - full_args += args - # Quote args - full_args.map { |e| shell_quote(e.to_s) }.join(' ') - end - - # Compute string from repo_path that should be same as: repo.git_cache_id - # If only we had access to the repo (we don't). - # We perform caching here to speed this up, since this function gets called - # many times during the course of a repository lookup. - def git_cache_id - logger.debug("Lookup for git_cache_id with repository path '#{repo_path}' ... ") - @git_cache_id ||= Repository::Xitolite.repo_path_to_git_cache_id(repo_path) - logger.warn("Unable to find git_cache_id for '#{repo_path}', bypass cache... ") if @git_cache_id.nil? - logger.debug("git_cache_id found : #{@git_cache_id}") unless @git_cache_id.nil? - @git_cache_id - end - - def base_args - RedmineGitHosting::Commands.sudo_git_args_for_repo(repo_path).concat(git_args) - end - - def git_mirror_cmd - RedmineGitHosting::Commands.sudo_git_args_for_repo(repo_path, git_push_args) - end - - def git_push_args - ['env', "GIT_SSH=#{RedmineGitHosting::Config.gitolite_mirroring_script}"] - end - - def repo_path - root_url || url - end - - def git_args - self.class.client_version_above?([1, 7, 2]) ? ['-c', 'core.quotepath=false', '-c', 'log.decorate=no'] : [] - end - - def git_cache_enabled? - RedmineGitHosting::Config.gitolite_cache_max_time != 0 - end - - def binary_data?(content) - ScmData.binary? content - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting.rb deleted file mode 100644 index e507799..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting.rb +++ /dev/null @@ -1,69 +0,0 @@ -# Redmine Permissions -require 'redmine_permissions' - -# Redmine Menus -require 'redmine_menus' - -# Redmine Hooks -require 'redmine_git_hosting/hooks' - -# Redmine SCM -Redmine::Scm::Base.add 'Xitolite' - -module RedmineGitHosting - extend self - - # Load RedminePluginLoader - require 'redmine_git_hosting/redmine_plugin_loader' - extend RedminePluginLoader - - set_plugin_name 'redmine_git_hosting' - - set_autoloaded_paths 'forms', - 'presenters', - 'reports', - 'services', - 'use_cases', - %w[controllers concerns], - %w[models concerns] - - def logger - @logger ||= if ['Journald::Logger', 'Journald::TraceLogger'].include? Rails.logger.class.to_s - RedmineGitHosting::JournalLogger.init_logs! logprogname, loglevel - else - RedmineGitHosting::FileLogger.init_logs! logprogname, logfile, loglevel - end - end - - def logprogname - 'redmine_git_hosting' - end - - def logfile - Rails.root.join('log/git_hosting.log') - end - - def loglevel - case RedmineGitHosting::Config.gitolite_log_level - when 'debug' - Logger::DEBUG - when 'warn' - Logger::WARN - when 'error' - Logger::ERROR - else - Logger::INFO - end - end -end - -# Set up autoload of patches -Rails.configuration.to_prepare do - # Redmine Git Hosting Libs and Patches - RedmineGitHosting.load_plugin! - - # Redmine SCM adapter - require_dependency 'redmine/scm/adapters/xitolite_adapter' - - require 'hrack/init' -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/auth.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/auth.rb deleted file mode 100644 index de8b2a5..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/auth.rb +++ /dev/null @@ -1,12 +0,0 @@ -module RedmineGitHosting - class Auth - def find(login, password) - user = User.find_by_login(login) - # Return if user not found - return nil if user.nil? - - # Return user if password matches - user if user.check_password?(password) - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/cache.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/cache.rb deleted file mode 100644 index 34b1a21..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/cache.rb +++ /dev/null @@ -1,60 +0,0 @@ -module RedmineGitHosting - module Cache - extend self - - # Used in ShellRedirector but define here to keep a clean interface. - # - def max_cache_size - RedmineGitHosting::Config.gitolite_cache_max_size - end - - def set_cache(repo_id, out_value, primary_key, secondary_key = nil) - return if out_value.strip.empty? - - command = compose_key(primary_key, secondary_key) - adapter.apply_cache_limit if adapter.set_cache(repo_id, command, out_value) - end - - def get_cache(repo_id, primary_key, secondary_key = nil) - command = compose_key(primary_key, secondary_key) - cached = adapter.get_cache(repo_id, command) - # Return result as a string stream - cached.nil? ? nil : StringIO.new(cached) - end - - def flush_cache! - adapter.flush_cache! - end - - # After resetting cache timing parameters -- delete entries that no-longer match - def clear_obsolete_cache_entries - adapter.clear_obsolete_cache_entries - end - - # Clear the cache entries for given repository / git_cache_id - def clear_cache_for_repository(repo_id) - adapter.clear_cache_for_repository(repo_id) - end - - def adapter - case RedmineGitHosting::Config.gitolite_cache_adapter - when 'memcached' - Memcached - when 'redis' - Redis - else - Database - end - end - - private - - def compose_key(key1, key2) - if key2&.present? - key1 + "\n" + key2 - else - key1 - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/cache/abstract_cache.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/cache/abstract_cache.rb deleted file mode 100644 index 3d4ec75..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/cache/abstract_cache.rb +++ /dev/null @@ -1,64 +0,0 @@ -module RedmineGitHosting - module Cache - class AbstractCache - class << self - def max_cache_size - @max_cache_size ||= RedmineGitHosting::Config.gitolite_cache_max_size - end - - def max_cache_time - @max_cache_time ||= RedmineGitHosting::Config.gitolite_cache_max_time - end - - def max_cache_elements - @max_cache_elements ||= RedmineGitHosting::Config.gitolite_cache_max_elements - end - - def set_cache(repo_id, command, output) - raise NotImplementedError - end - - def get_cache(repo_id, command) - raise NotImplementedError - end - - def flush_cache! - raise NotImplementedError - end - - def clear_obsolete_cache_entries - raise NotImplementedError - end - - def clear_cache_for_repository(repo_id) - raise NotImplementedError - end - - def apply_cache_limit - raise NotImplementedError - end - - private - - def logger - RedmineGitHosting.logger - end - - def time_limit - return if max_cache_time.to_i.negative? # No expiration needed - - current_time = ActiveRecord::Base.default_timezone == :utc ? Time.now.utc : Time.now - current_time - max_cache_time - end - - def valid_cache_entry?(cached_entry_date) - return true if max_cache_time.to_i.negative? # No expiration needed - - current_time = ActiveRecord::Base.default_timezone == :utc ? Time.now.utc : Time.now - expired = current_time.to_i - cached_entry_date.to_i > max_cache_time - !expired - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/cache/database.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/cache/database.rb deleted file mode 100644 index 771b5ad..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/cache/database.rb +++ /dev/null @@ -1,55 +0,0 @@ -module RedmineGitHosting - module Cache - class Database < AbstractCache - class << self - def set_cache(repo_id, command, output) - logger.debug("DB Adapter : inserting cache entry for repository '#{repo_id}'") - begin - GitCache.create(command: command, command_output: output, repo_identifier: repo_id) - true - rescue => e - logger.error("DB Adapter : could not insert in cache, this is the error : '#{e.message}'") - false - end - end - - def get_cache(repo_id, command) - cached = GitCache.find_by(repo_identifier: repo_id, command: command) - if cached - if valid_cache_entry?(cached.created_at) - # Update updated_at flag - cached.touch unless cached.command_output.nil? - out = cached.command_output - else - cached.destroy - out = nil - end - else - out = nil - end - out - end - - def flush_cache! - ActiveRecord::Base.connection.execute('TRUNCATE git_caches') - end - - def clear_obsolete_cache_entries - return if time_limit.nil? - - deleted = GitCache.where('created_at < ?', time_limit).delete_all - logger.info("DB Adapter : removed '#{deleted}' expired cache entries among all repositories") - end - - def clear_cache_for_repository(repo_id) - deleted = GitCache.where(repo_identifier: repo_id).delete_all - logger.info("DB Adapter : removed '#{deleted}' expired cache entries for repository '#{repo_id}'") - end - - def apply_cache_limit - GitCache.order(:created_at).first.destroy if max_cache_elements >= 0 && GitCache.count > max_cache_elements - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/cache/memcached.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/cache/memcached.rb deleted file mode 100644 index f7e6ad5..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/cache/memcached.rb +++ /dev/null @@ -1,88 +0,0 @@ -require 'dalli' -require 'digest/sha1' - -module RedmineGitHosting - module Cache - class Memcached < AbstractCache - class << self - def set_cache(repo_id, command, output) - logger.debug("Memcached Adapter : inserting cache entry for repository '#{repo_id}'") - - # Create a SHA256 of the Git command as key id - hashed_command = hash_key(command) - - begin - create_or_update_repo_references(repo_id, hashed_command) - client.set(hashed_command, output) - true - rescue => e - logger.error("Memcached Adapter : could not insert in cache, this is the error : '#{e.message}'") - false - end - end - - def get_cache(repo_id, command) - client.get(hash_key(command)) - end - - def flush_cache! - client.flush - end - - # Return true, this is done automatically by Memcached with the - # *max_cache_time* params (see below) - # - def clear_obsolete_cache_entries - true - end - - def clear_cache_for_repository(repo_id) - # Create a SHA256 of the repo_id as key id - hashed_repo_id = hash_key(repo_id) - # Find repository references in Memcached - repo_references = client.get(hashed_repo_id) - return true if repo_references.nil? - - # Delete reference keys - repo_references = repo_references.split(',').select { |r| !r.empty? } - repo_references.map { |key| client.delete(key) } - logger.info("Memcached Adapter : removed '#{repo_references.size}' expired cache entries for repository '#{repo_id}'") - # Reset references count - client.set(hashed_repo_id, '', max_cache_time, raw: true) - end - - # Return true. If cache is full, Memcached drop the oldest objects to add new ones. - # - def apply_cache_limit - true - end - - private - - def create_or_update_repo_references(repo_id, reference) - # Create a SHA256 of the repo_id as key id - hashed_repo_id = hash_key(repo_id) - # Find it in Memcached - repo_references = client.get(hashed_repo_id) - if repo_references.nil? - client.set(hashed_repo_id, reference, max_cache_time, raw: true) - else - client.append(hashed_repo_id, ',' + reference) - end - end - - def hash_key(key) - Digest::SHA256.hexdigest(key) - end - - def client - @client ||= Dalli::Client.new('localhost:11211', memcached_options) - end - - def memcached_options - { namespace: 'redmine_git_hosting', compress: true, expires_in: max_cache_time, value_max_bytes: max_cache_size } - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/cache/redis.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/cache/redis.rb deleted file mode 100644 index 11f9b82..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/cache/redis.rb +++ /dev/null @@ -1,102 +0,0 @@ -require 'redis' -require 'digest/sha1' - -module RedmineGitHosting - module Cache - class Redis < AbstractCache - class << self - def set_cache(repo_id, command, output) - logger.debug("Redis Adapter : inserting cache entry for repository '#{repo_id}'") - - # Create a SHA256 of the Git command as key id - hashed_command = hash_key(repo_id, command) - - # If *max_cache_time* is set to -1 (until next commit) then - # set the cache time to 1 day (we don't know when will be the next commit) - cache_time = max_cache_time.to_i.negative? ? 86_400 : max_cache_time - - begin - client.set(hashed_command, output, ex: cache_time) - true - rescue => e - logger.error("Redis Adapter : could not insert in cache, this is the error : '#{e.message}'") - false - end - end - - def get_cache(repo_id, command) - logger.debug("Redis Adapter : getting cache entry for repository '#{repo_id}'") - client.get(hash_key(repo_id, command)) - end - - def flush_cache! - deleted = 0 - client.scan_each(match: all_entries) do |key| - client.del(key) - deleted += 1 - end - logger.info("Redis Adapter : removed '#{deleted}' expired cache entries among all repositories") - end - - # Return true, this is done automatically by Redis with the - # *max_cache_time* params (see above) - # - def clear_obsolete_cache_entries - true - end - - def clear_cache_for_repository(repo_id) - deleted = 0 - client.scan_each(match: all_entries_for_repo(repo_id)) do |key| - client.del(key) - deleted += 1 - end - logger.info("Redis Adapter : removed '#{deleted}' expired cache entries for repository '#{repo_id}'") - end - - # Return true. - # - def apply_cache_limit - true - end - - private - - def redis_namespace - 'git_hosting_cache' - end - - def all_entries - "#{redis_namespace}:*" - end - - def all_entries_for_repo(repo_id) - "#{redis_namespace}:#{digest(repo_id)}:*" - end - - # Prefix each key with *git_hosting_cache:* to store them in a subdirectory. - # When flushing cache, get all keys with this prefix and delete them. - # Make SHA256 of the Git command as identifier - # - def hash_key(repo_id, command) - "#{redis_namespace}:#{digest(repo_id)}:#{digest(command)}" - end - - def digest(string) - Digest::SHA256.hexdigest(string)[0..16] - end - - def client - @client ||= ::Redis.new(redis_options) - end - - # Specify the Redis DB. - # However, I don't know exactly how it's used by Redis... - # - def redis_options - { db: redis_namespace, driver: :hiredis } - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/commands.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/commands.rb deleted file mode 100644 index ef4a751..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/commands.rb +++ /dev/null @@ -1,9 +0,0 @@ -module RedmineGitHosting - module Commands - extend Commands::Base - extend Commands::Git - extend Commands::Gitolite - extend Commands::Ssh - extend Commands::Sudo - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/commands/base.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/commands/base.rb deleted file mode 100644 index eba9808..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/commands/base.rb +++ /dev/null @@ -1,27 +0,0 @@ -module RedmineGitHosting - module Commands - module Base - extend self - - # Wrapper to Open3.capture. - # - def capture(args = [], opts = {}) - cmd = args.shift - RedmineGitHosting::Utils::Exec.capture(cmd, args, opts) - end - - # Wrapper to Open3.capture. - # - def execute(args = [], opts = {}) - cmd = args.shift - RedmineGitHosting::Utils::Exec.execute(cmd, args, opts) - end - - private - - def logger - RedmineGitHosting.logger - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/commands/git.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/commands/git.rb deleted file mode 100644 index 7ed5a3c..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/commands/git.rb +++ /dev/null @@ -1,122 +0,0 @@ -module RedmineGitHosting - module Commands - module Git - extend self - - ############################ - # # - # Sudo+Git Shell Wrapper # - # # - ############################ - - # Send Git command with Sudo - # - def sudo_git(*params) - cmd = if RedmineGitHosting::Config.gitolite_use_sudo? - sudo_git_cmd.concat(params) - else - ['git'].concat(params) - end - - capture cmd - end - - def sudo_git_cmd(args = []) - sudo.concat git(args) - end - - def sudo_git_args_for_repo(repo_path, args = []) - sudo.concat(git(args)).concat(git_args_for_repo(repo_path)) - end - - def sudo_unset_git_global_param(key) - logger.info("Unset Git global parameter : #{key}") - - begin - _, _, code = sudo_shell('git', 'config', '--global', '--unset', key) - true - rescue RedmineGitHosting::Error::GitoliteCommandException => e - if code == 5 - true - else - logger.error("Error while removing Git global parameter : #{key}") - logger.error(e.output) - false - end - end - end - - def sudo_set_git_global_param(namespace, key, value) - key = prefix_key(namespace, key) - - return sudo_unset_git_global_param(key) if value == '' - - logger.info("Set Git global parameter : #{key} (#{value})") - - begin - sudo_git('config', '--global', key, value) - true - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error("Error while setting Git global parameter : #{key} (#{value})") - logger.error(e.output) - false - end - end - - # Return a hash with global config parameters. - def sudo_get_git_global_params(namespace) - begin - params = sudo_git('config', '--get-regexp', namespace).split("\n") - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error("Problems to retrieve Gitolite hook parameters in Gitolite config 'namespace : #{namespace}'") - params = [] - end - - git_config_as_hash(namespace, params) - end - - def git_version - sudo_git('--version') - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error("Can't retrieve Git version: #{e.output}") - 'unknown' - end - - private - - # Return the Git command with prepend args (mainly env vars like FOO=BAR git push). - # - def git(args = []) - [*args, Repository::Xitolite.scm_command] - end - - def git_args_for_repo(repo_path) - ['--git-dir', repo_path] - end - - # Returns the global gitconfig prefix for - # a config with that given key under the - # hooks namespace. - # - def prefix_key(namespace, key) - [namespace, '.', key].join - end - - def git_config_as_hash(namespace, params) - value_hash = {} - - params.each do |value_pair| - next if value_pair.empty? - next unless value_pair.start_with? namespace - - global_key = value_pair.split(' ')[0] - value = value_pair.split(' ')[1] - key = global_key.split('.')[1] - value_hash[key] = value - end - - value_hash - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/commands/gitolite.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/commands/gitolite.rb deleted file mode 100644 index 4ec0f8c..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/commands/gitolite.rb +++ /dev/null @@ -1,81 +0,0 @@ -module RedmineGitHosting - module Commands - module Gitolite - extend self - - ################################# - # # - # Sudo+Gitolite Shell Wrapper # - # # - ################################# - - def gitolite_infos - ssh_capture 'info' - end - - def sudo_gitolite_query_rc(param) - sudo_capture('gitolite', 'query-rc', param).try(:chomp) - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error("Can't retrieve Gitolite param : #{e.output}") - nil - end - - def sudo_update_gitolite! - if gitolite_command.nil? - logger.error("gitolite_command is nil, can't update Gitolite !") - return - end - logger.info("Running '#{gitolite_command.join(' ')}' on the Gitolite install ...") - begin - sudo_shell(*gitolite_command) - true - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error(e.output) - false - end - end - - def gitolite_repository_count - sudo_capture('gitolite', 'list-phy-repos').split("\n").length - end - - # Test if repository is empty on Gitolite side - # - def sudo_repository_empty?(repo_path) - if gitolite_home_dir.nil? - logger.info('gitolite_home_dir is not set, because of incomplete/incorrect gitolite setup') - return true - end - - repo_path = File.join(gitolite_home_dir, repo_path, 'objects') - count = sudo_git_objects_count(repo_path) - count.to_i.zero? - end - - def sudo_git_objects_count(repo_path) - cmd = if RedmineGitHosting::Config.gitolite_use_sudo? - ['eval', 'find', repo_path, '-type', 'f', '|', 'wc', '-l'] - else - ['bash', '-c', "find #{repo_path} -type f | wc -l"] - end - - begin - sudo_capture(*cmd) - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error("Can't retrieve Git objects count : #{e.output}") - 0 - end - end - - private - - def gitolite_command - RedmineGitHosting::Config.gitolite_command - end - - def gitolite_home_dir - RedmineGitHosting::Config.gitolite_home_dir - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/commands/ssh.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/commands/ssh.rb deleted file mode 100644 index 95c9ef2..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/commands/ssh.rb +++ /dev/null @@ -1,55 +0,0 @@ -module RedmineGitHosting - module Commands - module Ssh - extend self - - # Return only the output from the ssh command. - # - def ssh_capture(*params) - cmd = ssh.concat(params) - - capture cmd - end - - # Execute a command in the gitolite forced environment through this user - # i.e., executes 'ssh git@localhost ' - # - # Returns stdout, stderr and the exit code - # - def ssh_shell(*params) - cmd = ssh.concat(params) - - execute cmd - end - - private - - # Return the SSH command with basic args - # - def ssh - ['ssh', *ssh_shell_params] - end - - # Returns the ssh prefix arguments for all ssh_* commands. - # - # These are as follows: - # * (-T) Never request tty - # * (-i ) Use the SSH keys given in Settings - # * (-p ) Use port from settings - # * (-o BatchMode=yes) Never ask for a password - # * @ (see +gitolite_url+) - # - def ssh_shell_params - [ - '-T', - '-o', 'BatchMode=yes', - '-o', 'UserKnownHostsFile=/dev/null', - '-o', 'StrictHostKeyChecking=no', - '-p', RedmineGitHosting::Config.gitolite_server_port, - '-i', RedmineGitHosting::Config.gitolite_ssh_private_key, - RedmineGitHosting::Config.gitolite_url - ] - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/commands/sudo.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/commands/sudo.rb deleted file mode 100644 index 36690eb..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/commands/sudo.rb +++ /dev/null @@ -1,203 +0,0 @@ -require 'digest/md5' - -module RedmineGitHosting - module Commands - module Sudo - extend self - - ########################## - # # - # SUDO Shell Wrapper # - # # - ########################## - - # Pipe file content via sudo to dest_file. - # Expect file content to end with EOL (\n) - # - def sudo_install_file(content, dest_file, filemode) - stdin = ['cat', '<<\EOF', '>' + dest_file, "\n" + content.to_s + "EOF"].join(' ') - - begin - sudo_pipe_data(stdin) - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error(e.output) - false - else - begin - sudo_chmod(filemode, dest_file) - true - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error(e.output) - false - end - end - end - - # Test if a file exists with size > 0 - # - def sudo_file_exists?(filename) - sudo_test filename, '-s' - end - - # Test if a directory exists - # - def sudo_dir_exists?(dirname) - sudo_test dirname, '-r' - end - - # Test properties of a path from the git user. - # - # e.g., Test if a directory exists: sudo_test('~/somedir', '-d') - # - def sudo_test(path, testarg) - _, _, code = sudo_shell('test', testarg, path) - code.to_i.zero? - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.debug("File check for #{path} failed : #{e.message}") - false - end - - # Calls mkdir with the given arguments on the git user's side. - # - # e.g., sudo_mkdir('-p', '/some/path') - # - def sudo_mkdir(*args) - sudo_shell('mkdir', *args) - end - - # Syntaxic sugar for 'mkdir -p' - # - def sudo_mkdir_p(path) - sudo_mkdir '-p', path - end - - # Calls chmod with the given arguments on the git user's side. - # - # e.g., sudo_chmod('755', '/some/path') - # - def sudo_chmod(mode, file) - sudo_shell('chmod', mode, file) - end - - # Removes a directory and all subdirectories below gitolite_user's $HOME. - # - # Assumes a relative path. - # - # If force=true, it will delete using 'rm -rf ', otherwise - # it uses rmdir - # - def sudo_rmdir(path, force = false) - if force - sudo_shell('rm', '-rf', path) - else - sudo_shell('rmdir', path) - end - end - - # Syntaxic sugar for 'rm -rf' command - # - def sudo_rm_rf(path) - sudo_rmdir(path, true) - end - - # Moves a file/directory to a new target. - # - def sudo_move(old_path, new_path) - sudo_shell('mv', old_path, new_path) - end - - def sudo_get_dir_size(directory) - sudo_capture('du', '-sh', directory).split(' ')[0] rescue '' - end - - def sudo_cat(file) - sudo_capture('cat', file) rescue '' - end - - # Test if file content has changed - # - def sudo_file_changed?(source_file, dest_file) - hash_content(content_from_redmine_side(source_file)) != hash_content(content_from_gitolite_side(dest_file)) - end - - # Test if file permissions has changed - # - def sudo_file_perms_changed?(filemode, dest_file) - current_mode = sudo_capture('stat', '-c', '%a', dest_file) - current_mode.chomp != filemode - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error(e.output) - false - end - - # Return only the output of the shell command. - # Throws an exception if the shell command does not exit with code 0. - # - def sudo_capture(*params) - cmd = sudo.concat(params) - capture(cmd) - end - - # Execute a command as the gitolite user defined in +GitoliteWrapper.gitolite_user+. - # - # Will shell out to +sudo -n -u params+ - # - def sudo_shell(*params) - cmd = sudo.concat(params) - execute(cmd) - end - - # Write data on stdin and return the output of the shell command. - # Throws an exception if the shell command does not exit with code 0. - # - def sudo_pipe_data(stdin) - cmd = sudo.push('sh') - capture(cmd, { stdin_data: stdin, binmode: true }) - end - - private - - # Return the Sudo command with basic args. - # - def sudo - if RedmineGitHosting::Config.gitolite_use_sudo? - ['sudo', *sudo_shell_params] - else - [] - end - end - - # Returns the sudo prefix to all sudo_* commands. - # - # These are as follows: - # * (-i) login as `gitolite_user` (setting ENV['HOME') - # * (-n) non-interactive - # * (-u `gitolite_user`) target user - # - def sudo_shell_params - ['-n', '-u', RedmineGitHosting::Config.gitolite_user, '-i'] - end - - # Return a md5 hash of the string passed. - # - def hash_content(content) - Digest::MD5.hexdigest(content) - end - - # Return the content of a local (Redmine side) file. - # - def content_from_redmine_side(file) - File.read(file) - rescue Errno::ENOENT => e - logger.error(e.message) - '' - end - - # Return the content of a file on Gitolite side. - # - def content_from_gitolite_side(destination_path) - sudo_cat(destination_path) - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/config.rb deleted file mode 100644 index b02cab0..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config.rb +++ /dev/null @@ -1,21 +0,0 @@ -module RedmineGitHosting - module Config - GITHUB_ISSUE = 'https://github.com/jbox-web/redmine_git_hosting/issues' - GITHUB_WIKI = 'http://redmine-git-hosting.io/configuration/variables/' - - GITOLITE_DEFAULT_CONFIG_FILE = 'gitolite.conf' - GITOLITE_IDENTIFIER_DEFAULT_PREFIX = 'redmine_' - - extend Config::Base - extend Config::GitoliteAccess - extend Config::GitoliteBase - extend Config::GitoliteCache - extend Config::GitoliteConfigTests - extend Config::GitoliteHooks - extend Config::GitoliteInfos - extend Config::GitoliteNotifications - extend Config::GitoliteStorage - extend Config::Mirroring - extend Config::RedmineConfig - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/base.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/base.rb deleted file mode 100644 index 61c4b94..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/base.rb +++ /dev/null @@ -1,97 +0,0 @@ -module RedmineGitHosting - module Config - module Base - extend self - - ############################### - ## ## - ## CONFIGURATION ACCESSORS ## - ## ## - ############################### - - def get_setting(setting, bool = false) - if bool - Additionals.true? do_get_setting(setting) - else - do_get_setting(setting) - end - end - - def reload_from_file! - ## Get default config from init.rb - default_hash = Redmine::Plugin.find('redmine_git_hosting').settings[:default] - do_reload_config(default_hash) - end - - def dump_settings - puts YAML.dump Redmine::Plugin.find('redmine_git_hosting').settings[:default] - end - - private - - def do_get_setting(setting) - setting = setting.to_sym - - ## Wrap this in a begin/rescue statement because Setting table - ## may not exist on first migration - begin - value = Setting.plugin_redmine_git_hosting[setting] - rescue - value = Redmine::Plugin.find('redmine_git_hosting').settings[:default][setting] - else - ## The Setting table exist but does not contain the value yet, fallback to default - value = Redmine::Plugin.find('redmine_git_hosting').settings[:default][setting] if value.nil? - end - - value - end - - def do_reload_config(default_hash) - ## Refresh Settings cache - Setting.check_cache - - ## Get actual values - valuehash = (Setting.plugin_redmine_git_hosting).clone rescue {} - - ## Update! - changes = 0 - - default_hash.each do |key, value| - if valuehash[key] != value - console_logger.info("Changing '#{key}' : #{valuehash[key]} => #{value}") - valuehash[key] = value - changes += 1 - end - end - - if changes.zero? - console_logger.info('No changes necessary.') - else - commit_changes(valuehash) - end - end - - def commit_changes(valuehash) - console_logger.info('Committing changes ... ') - begin - ## Update Settings - Setting.plugin_redmine_git_hosting = valuehash - ## Refresh Settings cache - Setting.check_cache - console_logger.info('Success!') - rescue => e - console_logger.error('Failure.') - console_logger.error(e.message) - end - end - - def console_logger - RedmineGitHosting::ConsoleLogger - end - - def file_logger - RedmineGitHosting.logger - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_access.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_access.rb deleted file mode 100644 index ba5b068..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_access.rb +++ /dev/null @@ -1,59 +0,0 @@ -module RedmineGitHosting - module Config - module GitoliteAccess - extend self - - def gitolite_http_by_default? - get_setting(:gitolite_http_by_default) - end - - def gitolite_daemon_by_default? - get_setting(:gitolite_daemon_by_default, true) - end - - def gitolite_notify_by_default? - get_setting(:gitolite_notify_by_default, true) - end - - def ssh_server_domain - get_setting(:ssh_server_domain) - end - - def http_server_domain - get_setting(:http_server_domain) - end - - def https_server_domain - get_setting(:https_server_domain) - end - - def http_server_subdir - get_setting(:http_server_subdir) - end - - def http_root_url - my_root_url(false) - end - - def https_root_url - my_root_url(true) - end - - def redmine_root_url - Redmine::Utils::relative_url_root - end - - def my_root_url(ssl = false) - if ssl && https_server_domain != '' - server_domain = https_server_domain - else - server_domain = http_server_domain - end - - # Remove any path from httpServer. - # No trailing /. - File.join(server_domain[/^[^\/]*/], redmine_root_url, '/')[0..-2] - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_base.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_base.rb deleted file mode 100644 index ef888f9..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_base.rb +++ /dev/null @@ -1,109 +0,0 @@ -require 'etc' - -module RedmineGitHosting - module Config - module GitoliteBase - extend self - - def check_cache - @gitolite_home_dir = nil - @mirroring_keys_installed = nil - @mirroring_public_key = nil - @gitolite_ssh_fingerprint = nil - end - - def redmine_user - @redmine_user ||= (%x[whoami]).chomp.strip - end - - def gitolite_use_sudo? - redmine_user != gitolite_user - end - - def gitolite_home_dir - @gitolite_home_dir ||= Etc.getpwnam(gitolite_user).dir rescue nil - end - - def gitolite_bin_dir - @gitolite_bin_dir ||= RedmineGitHosting::Commands.sudo_gitolite_query_rc('GL_BINDIR') - end - - def gitolite_lib_dir - @gitolite_lib_dir ||= RedmineGitHosting::Commands.sudo_gitolite_query_rc('GL_LIBDIR') - end - - def gitolite_user - get_setting(:gitolite_user) - end - - def gitolite_server_host - get_setting(:gitolite_server_host) - end - - def gitolite_server_port - get_setting(:gitolite_server_port) - end - - def gitolite_ssh_private_key - get_setting(:gitolite_ssh_private_key) - end - - def gitolite_ssh_public_key - get_setting(:gitolite_ssh_public_key) - end - - def gitolite_ssh_public_key_fingerprint - @gitolite_ssh_fingerprint ||= RedmineGitHosting::Utils::Ssh.ssh_fingerprint(File.read(gitolite_ssh_public_key)) - end - - def gitolite_config_file - File.basename(get_setting(:gitolite_config_file)) - end - - def gitolite_config_dir - dirs = File.dirname(gitolite_config_file).split('/') - if dirs[0] != '.' - File.join('conf', *dirs) - else - 'conf' - end - end - - def gitolite_identifier_prefix - get_setting(:gitolite_identifier_prefix) - end - - def gitolite_identifier_strip_user_id? - get_setting(:gitolite_identifier_strip_user_id, true) - end - - def gitolite_key_subdir - 'redmine_git_hosting' - end - - def git_config_username - get_setting(:git_config_username) - end - - def git_config_email - get_setting(:git_config_email) - end - - def gitolite_temp_dir - get_setting(:gitolite_temp_dir) - end - - def gitolite_url - [gitolite_user, '@', gitolite_server_host].join - end - - def gitolite_admin_dir - File.join(gitolite_temp_dir, gitolite_user, 'gitolite-admin.git') - end - - def gitolite_log_level - get_setting(:gitolite_log_level) - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_cache.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_cache.rb deleted file mode 100644 index e539ec1..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_cache.rb +++ /dev/null @@ -1,23 +0,0 @@ -module RedmineGitHosting - module Config - module GitoliteCache - extend self - - def gitolite_cache_max_time - get_setting(:gitolite_cache_max_time).to_i - end - - def gitolite_cache_max_elements - get_setting(:gitolite_cache_max_elements).to_i - end - - def gitolite_cache_max_size - get_setting(:gitolite_cache_max_size).to_i * 1024 * 1024 - end - - def gitolite_cache_adapter - get_setting(:gitolite_cache_adapter) - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_config_tests.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_config_tests.rb deleted file mode 100644 index edea394..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_config_tests.rb +++ /dev/null @@ -1,92 +0,0 @@ -module RedmineGitHosting - module Config - module GitoliteConfigTests - extend self - - ############################### - ## ## - ## TEMP DIR ## - ## ## - ############################### - - @temp_dir_path = nil - @previous_temp_dir_path = nil - - def create_temp_dir - if @previous_temp_dir_path != gitolite_temp_dir - @previous_temp_dir_path = gitolite_temp_dir - @temp_dir_path = gitolite_admin_dir - end - - unless File.directory? @temp_dir_path - file_logger.info("Create Gitolite Admin directory : '#{@temp_dir_path}'") - begin - FileUtils.mkdir_p @temp_dir_path - FileUtils.chmod 0700, @temp_dir_path - rescue => e - file_logger.error("Cannot create Gitolite Admin directory : '#{@temp_dir_path}'") - end - end - - @temp_dir_path - end - - @temp_dir_writeable = false - - def temp_dir_writeable?(opts = {}) - @temp_dir_writeable = false if opts.key?(:reset) && opts[:reset] == true - - unless @temp_dir_writeable - file_logger.debug("Testing if Gitolite Admin directory '#{create_temp_dir}' is writeable ...") - mytestfile = File.join(create_temp_dir, 'writecheck') - if !File.directory?(create_temp_dir) - @temp_dir_writeable = false - else - begin - FileUtils.touch mytestfile - FileUtils.rm mytestfile - rescue => e - @temp_dir_writeable = false - else - @temp_dir_writeable = true - end - end - end - - @temp_dir_writeable - end - - ############################### - ## ## - ## SUDO TESTS ## - ## ## - ############################### - - ## SUDO TEST1 - def can_redmine_sudo_to_gitolite_user? - return true unless gitolite_use_sudo? - - file_logger.info("Testing if Redmine user '#{redmine_user}' can sudo to Gitolite user '#{gitolite_user}'...") - result = execute_sudo_test(gitolite_user) do - RedmineGitHosting::Commands.sudo_capture('whoami') - end - result ? file_logger.info('OK!') : file_logger.error('Error while testing can_redmine_sudo_to_gitolite_user') - result - end - - def execute_sudo_test(user, &block) - begin - test = yield if block_given? - rescue RedmineGitHosting::Error::GitoliteCommandException => e - false - else - if test.match(/#{user}/) - true - else - false - end - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_hooks.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_hooks.rb deleted file mode 100644 index 0221d0d..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_hooks.rb +++ /dev/null @@ -1,59 +0,0 @@ -module RedmineGitHosting - module Config - module GitoliteHooks - extend self - - def gitolite_hooks_namespace - 'redminegitolite' - end - - def gitolite_hooks_url - [get_setting(:gitolite_hooks_url), '/githooks/post-receive/redmine'].join - end - - def gitolite_hooks_debug - get_setting(:gitolite_hooks_debug, true) - end - - def gitolite_hooks_are_asynchronous - get_setting(:gitolite_hooks_are_asynchronous, true) - end - - def gitolite_overwrite_existing_hooks? - get_setting(:gitolite_overwrite_existing_hooks, true) - end - - def gitolite_local_code_dir - @gitolite_local_code_dir ||= RedmineGitHosting::Commands.sudo_gitolite_query_rc('LOCAL_CODE') - end - - def gitolite_hooks_dir - if gitolite_version == 3 - File.join(gitolite_local_code_dir, 'hooks', 'common') - else - File.join(gitolite_home_dir, '.gitolite', 'hooks', 'common') - end - end - - def check_hooks_install! - { - hook_files: RedmineGitHosting::GitoliteHooks.hooks_installed?, - global_params: RedmineGitHosting::GitoliteParams::GlobalParams.new.installed?, - mailer_params: RedmineGitHosting::GitoliteParams::MailerParams.new.installed? - } - end - - def install_hooks! - { - hook_files: RedmineGitHosting::GitoliteHooks.install_hooks!, - global_params: RedmineGitHosting::GitoliteParams::GlobalParams.new.install!, - mailer_params: RedmineGitHosting::GitoliteParams::MailerParams.new.install! - } - end - - def update_hook_params! - RedmineGitHosting::GitoliteParams::GlobalParams.new.install! - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_infos.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_infos.rb deleted file mode 100644 index 6e646b0..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_infos.rb +++ /dev/null @@ -1,79 +0,0 @@ -module RedmineGitHosting - module Config - module GitoliteInfos - extend self - - ########################## - # # - # GITOLITE INFOS # - # # - ########################## - - def rugged_features - Rugged.features - end - - def rugged_mandatory_features - [:threads, :ssh] - end - - def libgit2_version - Rugged.libgit2_version.join('.') - end - - def gitolite_infos - begin - RedmineGitHosting::Commands.gitolite_infos - rescue RedmineGitHosting::Error::GitoliteCommandException => e - file_logger.error('Error while getting Gitolite infos, check your SSH keys (path, permissions) or your Git user.') - nil - end - end - - def gitolite_version - file_logger.debug('Getting Gitolite version...') - @gitolite_version ||= find_version(gitolite_infos) - end - - def gitolite_banner - file_logger.debug('Getting Gitolite banner...') - gitolite_infos - end - - def find_version(output) - return nil if output.blank? - - line = output.split("\n")[0] - if line =~ /gitolite[ -]v?2./ - 2 - elsif line.include?('running gitolite3') - 3 - else - nil - end - end - - def gitolite_command - if gitolite_version == 2 - ['gl-setup'] - elsif gitolite_version == 3 - ['gitolite', 'setup'] - else - nil - end - end - - def gitolite_repository_count - return 'This is Gitolite v2, not implemented...' if gitolite_version != 3 - - file_logger.debug('Getting Gitolite physical repositories list...') - begin - RedmineGitHosting::Commands.gitolite_repository_count - rescue RedmineGitHosting::Error::GitoliteCommandException => e - file_logger.error('Error while getting Gitolite physical repositories list') - 0 - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_notifications.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_notifications.rb deleted file mode 100644 index b34133f..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_notifications.rb +++ /dev/null @@ -1,23 +0,0 @@ -module RedmineGitHosting - module Config - module GitoliteNotifications - extend self - - def gitolite_notify_global_prefix - get_setting(:gitolite_notify_global_prefix) - end - - def gitolite_notify_global_sender_address - get_setting(:gitolite_notify_global_sender_address) - end - - def gitolite_notify_global_include - get_setting(:gitolite_notify_global_include) - end - - def gitolite_notify_global_exclude - get_setting(:gitolite_notify_global_exclude) - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_storage.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_storage.rb deleted file mode 100644 index 07f84d4..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/gitolite_storage.rb +++ /dev/null @@ -1,23 +0,0 @@ -module RedmineGitHosting - module Config - module GitoliteStorage - extend self - - def gitolite_global_storage_dir - get_setting(:gitolite_global_storage_dir) - end - - def gitolite_redmine_storage_dir - get_setting(:gitolite_redmine_storage_dir) - end - - def gitolite_recycle_bin_dir - get_setting(:gitolite_recycle_bin_dir) - end - - def recycle_bin_dir - File.join(gitolite_home_dir, gitolite_recycle_bin_dir) rescue nil - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/mirroring.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/mirroring.rb deleted file mode 100644 index 303c1ae..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/mirroring.rb +++ /dev/null @@ -1,21 +0,0 @@ -module RedmineGitHosting - module Config - module Mirroring - extend self - - def mirroring_public_key - @mirroring_public_key ||= MirrorKeysInstaller.mirroring_public_key(gitolite_ssh_public_key) - end - - def mirroring_keys_installed? - @mirroring_keys_installed ||= MirrorKeysInstaller.new(gitolite_home_dir, - gitolite_ssh_public_key, - gitolite_ssh_private_key).installed? - end - - def gitolite_mirroring_script - File.join gitolite_home_dir, '.ssh', 'run_gitolite_admin_ssh' - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/redmine_config.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/redmine_config.rb deleted file mode 100644 index ffa2c88..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/config/redmine_config.rb +++ /dev/null @@ -1,51 +0,0 @@ -module RedmineGitHosting - module Config - module RedmineConfig - extend self - - def gitolite_use_sidekiq? - get_setting(:gitolite_use_sidekiq, true) - end - - def sidekiq_available? - @sidekiq_available ||= - begin - require 'sidekiq' - require 'sidekiq/api' - rescue LoadError - false - else - true - end - end - - def hierarchical_organisation? - get_setting(:hierarchical_organisation, true) - end - - def unique_repo_identifier? - get_setting(:unique_repo_identifier, true) - end - - def all_projects_use_git? - get_setting(:all_projects_use_git, true) - end - - def init_repositories_on_create? - get_setting(:init_repositories_on_create, true) - end - - def download_revision_enabled? - get_setting(:download_revision_enabled, true) - end - - def delete_git_repositories? - get_setting(:delete_git_repositories, true) - end - - def gitolite_recycle_bin_expiration_time - (get_setting(:gitolite_recycle_bin_expiration_time).to_f * 60).to_i - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/console_logger.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/console_logger.rb deleted file mode 100644 index f73f06f..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/console_logger.rb +++ /dev/null @@ -1,41 +0,0 @@ -module RedmineGitHosting - module ConsoleLogger - extend self - - def title(message, &block) - info("\n * #{message} :") - yield if block_given? - info(" Done !\n\n") - end - - def debug(message) - to_console message - logger.debug message.strip - end - - def info(message) - to_console message - logger.info message.strip - end - - def warn - to_console message - logger.warn message.strip - end - - def error(message) - to_console message - logger.error message.strip - end - - private - - def to_console(message) - puts message # rubocop: disable Rails/Output - end - - def logger - RedmineGitHosting.logger - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/error.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/error.rb deleted file mode 100644 index 35c5a9b..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/error.rb +++ /dev/null @@ -1,27 +0,0 @@ -module RedmineGitHosting - module Error - # Used to register errors when pulling and pushing the conf file - class GitoliteException < StandardError; end - - class GitoliteWrapperException < GitoliteException; end - - class InvalidSshKey < GitoliteException; end - - class InvalidRefspec < GitoliteException - class BadFormat < InvalidRefspec; end - - class NullComponent < InvalidRefspec; end - end - - # Used to register errors when pulling and pushing the conf file - class GitoliteCommandException < GitoliteException - attr_reader :command - attr_reader :output - - def initialize(command, output) - @command = command - @output = output - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/file_logger.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/file_logger.rb deleted file mode 100644 index 9ffb63f..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/file_logger.rb +++ /dev/null @@ -1,17 +0,0 @@ -require 'logger' - -module RedmineGitHosting - class FileLogger < ::Logger - LOG_LEVELS = %w[debug info warn error].freeze - - def self.init_logs!(appname, logfile, loglevel) - logger = new logfile - logger.progname = appname - logger.level = loglevel - logger.formatter = proc do |severity, time, _progname, msg| - "#{time} [#{severity}] #{msg}\n" - end - logger - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/git_access.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/git_access.rb deleted file mode 100644 index bf0aec1..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/git_access.rb +++ /dev/null @@ -1,83 +0,0 @@ -module RedmineGitHosting - class GitAccess - DOWNLOAD_COMMANDS = %w[git-upload-pack git-upload-archive].freeze - PUSH_COMMANDS = %w[git-receive-pack].freeze - - def download_access_check(actor, repository, is_ssl = false) - # First check that SmartHTTP is enabled for repository - return smart_http_is_disabled!(repository) unless smart_http_enabled_for_download?(repository, is_ssl) - - # Then check user permissions - if actor.is_a?(User) - user_download_access_check(actor, repository) - else - raise 'Wrong actor' - end - end - - def upload_access_check(actor, repository) - # First check that SmartHTTP is enabled for repository - return smart_http_is_disabled!(repository) unless smart_http_enabled_for_upload?(repository) - - # Then check user permissions - if actor.is_a?(User) - user_upload_access_check(actor, repository) - else - raise 'Wrong actor' - end - end - - def user_download_access_check(user, repository) - if user&.allowed_to_clone?(repository) - build_status_object(true) - else - build_status_object(false, "You don't have access") - end - end - - def user_upload_access_check(user, repository) - if user&.allowed_to_commit?(repository) - build_status_object(true) - else - build_status_object(false, "You don't have access") - end - end - - protected - - def build_status_object(status, message = '') - logger.warn(message) unless status - GitAccessStatus.new(status, message) - end - - private - - def smart_http_is_disabled!(repository) - build_status_object(false, "SmartHTTP is disabled for repository '#{repository.gitolite_repository_name}' !") - end - - def smart_http_enabled_for_download?(repository, is_ssl = false) - # SmartHTTP is disabled - return false unless repository.smart_http_enabled? - # HTTPS only but no SSL - return false if repository.only_https_access_enabled? && !is_ssl - # HTTP only but have SSL (weird..) - return false if repository.only_http_access_enabled? && is_ssl - - # Else return true - true - end - - def smart_http_enabled_for_upload?(repository) - # HTTPS only - return true if repository.pushable_via_http? - - # Else - false - end - - def logger - RedmineGitHosting.logger - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/git_access_status.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/git_access_status.rb deleted file mode 100644 index 1663c4b..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/git_access_status.rb +++ /dev/null @@ -1,15 +0,0 @@ -module RedmineGitHosting - class GitAccessStatus - attr_accessor :status, :message - alias_method :allowed?, :status - - def initialize(status, message = '') - @status = status - @message = message - end - - def to_json - { status: @status, message: @message }.to_json - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_accessor.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_accessor.rb deleted file mode 100644 index 823de9e..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_accessor.rb +++ /dev/null @@ -1,127 +0,0 @@ -module RedmineGitHosting - module GitoliteAccessor - extend self - - module Methods - private - - def gitolite_accessor - RedmineGitHosting::GitoliteAccessor - end - end - - def create_ssh_key(ssh_key, opts = {}) - logger.info("User '#{User.current.login}' has added a SSH key") - resync_gitolite(:add_ssh_key, ssh_key.id, opts) - end - - def destroy_ssh_key(ssh_key, opts = {}) - ssh_key = ssh_key.data_for_destruction if ssh_key.is_a?(GitolitePublicKey) - logger.info("User '#{User.current.login}' has deleted a SSH key") - resync_gitolite(:delete_ssh_key, ssh_key, opts) - end - - def resync_ssh_keys(opts = {}) - logger.info('Forced resync of all ssh keys...') - resync_gitolite(:resync_ssh_keys, 'all', opts) - end - - def regenerate_ssh_keys(opts = {}) - logger.info('Forced regenerate of all ssh keys...') - resync_gitolite(:regenerate_ssh_keys, 'all', opts) - end - - def create_repository(repository, opts = {}) - logger.info("User '#{User.current.login}' has created a new repository '#{repository.gitolite_repository_name}'") - resync_gitolite(:add_repository, repository.id, opts) - end - - def update_repository(repository, opts = {}) - logger.info("User '#{User.current.login}' has modified repository '#{repository.gitolite_repository_name}'") - resync_gitolite(:update_repository, repository.id, opts) - end - - def move_repository(repository, opts = {}) - logger.info("User '#{User.current.login}' has moved repository '#{repository.gitolite_repository_name}'") - resync_gitolite(:move_repository, repository.id, opts) - end - - def destroy_repository(repository, opts = {}) - logger.info("User '#{User.current.login}' has removed repository '#{repository.gitolite_repository_name}'") - resync_gitolite(:delete_repository, repository.data_for_destruction, opts) - end - - def destroy_repositories(repositories, opts = {}) - message = opts.delete(:message) { ' ' } - logger.info(message) - repositories.each do |repository| - resync_gitolite(:delete_repository, repository) - end - end - - def update_projects(projects, opts = {}) - message = opts.delete(:message) { ' ' } - logger.info(message) - resync_gitolite(:update_projects, projects, opts) - end - - def move_project_hierarchy(project) - logger.info("Move repositories of project : '#{project}'") - resync_gitolite(:move_repositories, project.id) - end - - def move_repositories_tree(count) - logger.info('Gitolite configuration has been modified : repositories hierarchy') - logger.info("Resync all projects (root projects : '#{count}')...") - resync_gitolite(:move_repositories_tree, count) - end - - def purge_recycle_bin - resync_gitolite(:purge_recycle_bin, 'all') - end - - def delete_from_recycle_bin(repositories) - resync_gitolite(:delete_from_recycle_bin, repositories) - end - - def flush_git_cache - logger.info('Flush Git Cache !') - RedmineGitHosting::Cache.flush_cache! - end - - def flush_settings_cache - resync_gitolite(:flush_settings_cache, 'flush!', { flush_cache: true }) - end - - def enable_rw_access - logger.info('Enable RW access on all Gitolite repositories') - resync_gitolite(:enable_rw_access, 'enable_rw_access') - end - - def disable_rw_access - logger.info('Disable RW access on all Gitolite repositories') - resync_gitolite(:disable_rw_access, 'disable_rw_access') - end - - private - - def logger - RedmineGitHosting.logger - end - - def resync_gitolite(command, object, options = {}) - bypass = if options.key?(:bypass_sidekiq) && options[:bypass_sidekiq] == true - true - else - false - end - - if RedmineGitHosting::Config.gitolite_use_sidekiq? && - RedmineGitHosting::Config.sidekiq_available? && !bypass - GithostingShellWorker.maybe_do command, object, options - else - GitoliteWrapper.resync_gitolite command, object, options - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/repositories/add_repository.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/repositories/add_repository.rb deleted file mode 100644 index 1f4bc58..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/repositories/add_repository.rb +++ /dev/null @@ -1,39 +0,0 @@ -module RedmineGitHosting - module GitoliteHandlers - module Repositories - class AddRepository < Base - def call - if !configuration_exists? - # Create repository in Gitolite - log_repo_not_exist('create it ...') - create_repository_config - - elsif configuration_exists? && force - # Recreate repository in Gitolite - log_repo_already_exist('force mode !') - recreate_repository_config - - else - log_repo_already_exist('exit !') - end - end - - def gitolite_repo_name - repository.gitolite_repository_name - end - - def gitolite_repo_path - repository.gitolite_repository_path - end - - attr_reader :force - - def initialize(*args) - super - @force = options.delete(:force) { false } - @old_perms = options.delete(:old_perms) { {} } - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/repositories/base.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/repositories/base.rb deleted file mode 100644 index 1ab1a25..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/repositories/base.rb +++ /dev/null @@ -1,110 +0,0 @@ -module RedmineGitHosting - module GitoliteHandlers - module Repositories - class Base - attr_reader :gitolite_config - attr_reader :repository - attr_reader :context - attr_reader :options - - def initialize(gitolite_config, repository, context, options = {}) - @gitolite_config = gitolite_config - @repository = repository - @context = context - @options = options.dup - @old_perms = {} - end - - class << self - def call(gitolite_config, repository, context, options = {}) - new(gitolite_config, repository, context, options).call - end - end - - def call - raise NotImplementedError - end - - private - - def logger - RedmineGitHosting.logger - end - - def backup_old_perms - @old_perms = repository.backup_gitolite_permissions(gitolite_repo_conf.permissions[0]) - end - - def configuration_exists? - !gitolite_repo_conf.nil? - end - - def gitolite_repo_conf - gitolite_config.repos[gitolite_repo_name] - end - - def create_repository_config - # Create Gitolite config - repo_conf = build_repository_config - - # Update permissions - repo_conf.permissions = repository.build_gitolite_permissions(@old_perms) - - # Add it to Gitolite - gitolite_config.add_repo(repo_conf) - - # Return repository conf - repo_conf - end - - def update_repository_config - recreate_repository_config - end - - def delete_repository_config - gitolite_config.rm_repo(gitolite_repo_name) - end - - def recreate_repository_config - # Backup old perms - backup_old_perms - - # Remove repo from Gitolite conf, we're gonna recreate it - delete_repository_config - - # Recreate repository in Gitolite - create_repository_config - end - - def build_repository_config - repo_conf = ::Gitolite::Config::Repo.new(repository.gitolite_repository_name) - - repository.git_config.each do |key, value| - repo_conf.set_git_config(key, value) - end - - repository.gitolite_options.each do |key, value| - repo_conf.set_gitolite_option(key, value) - end - - repo_conf - end - - def log_ok_and_continue(message) - logger.info("#{context} : repository '#{gitolite_repo_name}' exists in Gitolite, #{message}") - logger.debug("#{context} : repository path '#{gitolite_repo_path}'") - end - - def log_repo_not_exist(message) - logger.warn("#{context} : repository '#{gitolite_repo_name}' does not exist in Gitolite, #{message}") - logger.debug("#{context} : repository path '#{gitolite_repo_path}'") - end - - def log_repo_already_exist(message) - logger.warn("#{context} : repository '#{gitolite_repo_name}' already exists in Gitolite, #{message}") - logger.debug("#{context} : repository path '#{gitolite_repo_path}'") - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/repositories/delete_repository.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/repositories/delete_repository.rb deleted file mode 100644 index 796cfd9..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/repositories/delete_repository.rb +++ /dev/null @@ -1,26 +0,0 @@ -module RedmineGitHosting - module GitoliteHandlers - module Repositories - class DeleteRepository < Base - def call - if configuration_exists? - log_ok_and_continue('delete it ...') - - # Delete Gitolite repository - delete_repository_config - else - log_repo_not_exist('exit !') - end - end - - def gitolite_repo_name - repository[:repo_name] - end - - def gitolite_repo_path - repository[:repo_path] - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/repositories/move_repository.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/repositories/move_repository.rb deleted file mode 100644 index 1d4726e..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/repositories/move_repository.rb +++ /dev/null @@ -1,186 +0,0 @@ -module RedmineGitHosting - module GitoliteHandlers - module Repositories - class MoveRepository < Base - def call - if configuration_exists? - perform_repository_move - else - logger.error("#{context} : repository '#{old_repo_name}' does not exist in Gitolite, exit !") - nil - end - end - - def perform_repository_move - logger.info("#{context} : Moving '#{old_repo_name}' to '#{new_repo_name}' ...") - - debug_output - - if move_physical_repo(old_relative_path, new_relative_path, new_relative_parent_path) - # Update repository paths in database - update_repository_fields - - # Update Gitolite configuration - update_gitolite - - # Return old path to delete it - old_relative_parent_path - else - nil - end - end - - private - - def update_repository_fields - repository.update_column(:url, new_relative_path) - repository.update_column(:root_url, new_relative_path) - end - - def update_gitolite - # Get old repository permissions - old_perms = repository.backup_gitolite_permissions(gitolite_repo_conf.permissions[0]) - - # Remove repository from Gitolite configuration - gitolite_config.rm_repo(old_repo_name) - - # Recreate it - AddRepository.call(gitolite_config, repository, context, old_perms: old_perms) - end - - def gitolite_repo_conf - @repo_conf ||= gitolite_config.repos[old_repo_name] - end - - def repo_id - @repo_id ||= repository.redmine_name - end - - def old_repo_name - @old_repo_name ||= repository.old_repository_name - end - - def new_repo_name - @new_repo_name ||= repository.new_repository_name - end - - def old_relative_path - @old_relative_path ||= repository.url - end - - def new_relative_path - @new_relative_path ||= repository.gitolite_repository_path - end - - def old_relative_parent_path - @old_relative_parent_path ||= old_relative_path.gsub(repo_id + '.git', '') - end - - def new_relative_parent_path - @new_relative_parent_path ||= new_relative_path.gsub(repo_id + '.git', '') - end - - def debug_output - logger.debug("#{context} : Old repository name (for Gitolite) : #{old_repo_name}") - logger.debug("#{context} : New repository name (for Gitolite) : #{new_repo_name}") - logger.debug("#{context} : Old relative path (for Redmine code browser) : #{old_relative_path}") - logger.debug("#{context} : New relative path (for Redmine code browser) : #{new_relative_path}") - logger.debug("#{context} : Old relative parent path (for Gitolite) : #{old_relative_parent_path}") - logger.debug("#{context} : New relative parent path (for Gitolite) : #{new_relative_parent_path}") - end - - def move_physical_repo(old_path, new_path, new_parent_path) - ## CASE 0 - if old_path == new_path - logger.info("#{context} : old repository and new repository are identical '#{old_path}', nothing to do, exit !") - return true - end - - # Now we have multiple options, due to the way gitolite sets up repositories - new_path_exists = directory_exists?(new_path) - old_path_exists = directory_exists?(old_path) - - ## CASE 1 - if new_path_exists && old_path_exists - return move_physical_repo_case_1(old_path, new_path) - - ## CASE 2 - elsif !new_path_exists && old_path_exists - return move_physical_repo_case_2(old_path, new_path, new_parent_path) - - ## CASE 3 - elsif !new_path_exists && !old_path_exists - logger.error "#{context} : both old repository '#{old_path}' and new repository '#{new_path}' does not exist, cannot move it," \ - ' exit but let Gitolite create the new repo !' - return true - - ## CASE 4 - elsif new_path_exists && !old_path_exists - logger.error("#{context} : old repository '#{old_path}' does not exist, but the new one does, use it !") - return true - end - end - - def move_physical_repo_case_1(old_path, new_path) - if empty_repository?(new_path) - logger.warn("#{context} : target repository '#{new_path}' already exists and is empty, remove it ...") - delete_directory!(new_path, :target) - else - logger.warn "#{context} : target repository '#{new_path}' exists and is not empty, considered as already moved, try to remove" \ - ' the old_path if empty' - if empty_repository?(old_path) - delete_directory!(old_path, :source) - else - logger.error("#{context} : the source repository directory is not empty, cannot remove it, exit ! (This repo will be orphan)") - false - end - end - end - - def move_physical_repo_case_2(old_path, new_path, new_parent_path) - logger.debug("#{context} : really moving Gitolite repository from '#{old_path}' to '#{new_path}'") - - create_parent_directory(new_parent_path) if !directory_exists?(new_parent_path) - - begin - RedmineGitHosting::Commands.sudo_move(old_path, new_path) - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error("move_physical_repo(#{old_path}, #{new_path}) failed") - return false - else - logger.info("#{context} : done !") - return true - end - end - - def delete_directory!(dir, type) - begin - RedmineGitHosting::Commands.sudo_rm_rf(dir) - return true - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error("#{context} : removing existing #{type} repository failed, exit !") - return false - end - end - - def empty_repository?(dir) - RedmineGitHosting::Commands.sudo_repository_empty?(dir) - end - - def directory_exists?(dir) - RedmineGitHosting::Commands.sudo_dir_exists?(dir) - end - - def create_parent_directory(new_parent_path) - begin - RedmineGitHosting::Commands.sudo_mkdir_p(new_parent_path) - return true - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error("#{context} : creation of parent path '#{new_parent_path}' failed, exit !") - return false - end - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/repositories/update_repository.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/repositories/update_repository.rb deleted file mode 100644 index 2cb0440..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/repositories/update_repository.rb +++ /dev/null @@ -1,26 +0,0 @@ -module RedmineGitHosting - module GitoliteHandlers - module Repositories - class UpdateRepository < Base - def call - if configuration_exists? - log_ok_and_continue('update it ...') - - # Update Gitolite repository - update_repository_config - else - log_repo_not_exist('exit !') - end - end - - def gitolite_repo_name - repository.gitolite_repository_name - end - - def gitolite_repo_path - repository.gitolite_repository_path - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/ssh_keys/add_ssh_key.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/ssh_keys/add_ssh_key.rb deleted file mode 100644 index 468ba43..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/ssh_keys/add_ssh_key.rb +++ /dev/null @@ -1,23 +0,0 @@ -module RedmineGitHosting - module GitoliteHandlers - module SshKeys - class AddSshKey < Base - def call - repo_key = find_gitolite_key(key.owner, key.location) - - # Add it if not found - if repo_key.nil? - admin.add_key(build_gitolite_key(key)) - else - logger.info("#{context} : SSH key '#{key.owner}@#{key.location}' already exists in Gitolite, update it ...") - repo_key.type = key.type - repo_key.blob = key.blob - repo_key.email = key.email - repo_key.owner = key.owner - repo_key.location = key.location - end - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/ssh_keys/base.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/ssh_keys/base.rb deleted file mode 100644 index fdd9170..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/ssh_keys/base.rb +++ /dev/null @@ -1,41 +0,0 @@ -module RedmineGitHosting - module GitoliteHandlers - module SshKeys - class Base - attr_reader :admin - attr_reader :key - attr_reader :context - - def initialize(admin, key, context) - @admin = admin - @key = key - @context = context - end - - class << self - def call(admin, key, context) - new(admin, key, context).call - end - end - - def call - raise NotImplementedError - end - - private - - def logger - RedmineGitHosting.logger - end - - def find_gitolite_key(owner, location) - admin.ssh_keys[owner].find_all { |k| k.location == location && k.owner == owner }.first - end - - def build_gitolite_key(key) - ::Gitolite::SSHKey.new(key.type, key.blob, key.email, key.owner, key.location) - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/ssh_keys/delete_ssh_key.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/ssh_keys/delete_ssh_key.rb deleted file mode 100644 index f9ff83d..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_handlers/ssh_keys/delete_ssh_key.rb +++ /dev/null @@ -1,18 +0,0 @@ -module RedmineGitHosting - module GitoliteHandlers - module SshKeys - class DeleteSshKey < Base - def call - repo_key = find_gitolite_key(key[:owner], key[:location]) - - # Remove it if found - if repo_key - admin.rm_key(repo_key) - else - logger.info("#{context} : SSH key '#{key[:owner]}@#{key[:location]}' does not exits in Gitolite, exit !") - end - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_hook.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_hook.rb deleted file mode 100644 index 814fd34..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_hook.rb +++ /dev/null @@ -1,134 +0,0 @@ -module RedmineGitHosting - class GitoliteHook - class << self - def def_field(*names) - class_eval do - names.each do |name| - define_method(name) do |*args| - args.empty? ? instance_variable_get("@#{name}") : instance_variable_set("@#{name}", *args) - end - end - end - end - end - - def_field :name, :source, :destination, :executable - - attr_reader :source_dir - - def initialize(source_dir, &block) - @source_dir = source_dir - instance_eval(&block) - end - - def source_path - File.join(source_dir, source) - end - - def destination_path - File.join(gitolite_hooks_dir, destination) - end - - def parent_path - dirname = File.dirname(destination) - dirname = '' if dirname == '.' - File.join(gitolite_hooks_dir, dirname) - end - - def filemode - executable ? '755' : '644' - end - - def installed? - if !file_exists? - 1 - elsif hook_file_has_changed? - 2 - else - 0 - end - end - - def install! - if !file_exists? - logger.info("Hook '#{name}' does not exist, installing it ...") - install_hook - elsif hook_file_has_changed? - logger.warn("Hook '#{name}' is already present but it's not ours!") - if force_update? - logger.info("Restoring '#{name}' hook since forceInstallHook == true") - install_hook - else - logger.info("Leaving '#{name}' hook untouched since forceInstallHook == false") - end - else - logger.info("Hook '#{name}' is correcly installed") - end - installed? - end - - private - - def install_hook - create_parent_dir unless directory_exists? - return unless install_hook_file - - logger.info("Hook '#{name}' installed") - update_gitolite - end - - def force_update? - RedmineGitHosting::Config.gitolite_overwrite_existing_hooks? - end - - def logger - RedmineGitHosting.logger - end - - def hook_file_has_changed? - RedmineGitHosting::Commands.sudo_file_changed?(source_path, destination_path) || - RedmineGitHosting::Commands.sudo_file_perms_changed?(filemode, destination_path) - end - - def file_exists? - RedmineGitHosting::Commands.sudo_file_exists?(destination_path) - end - - def install_hook_file - logger.info("Installing hook '#{source_path}' in '#{destination_path}'") - begin - content = File.read(source_path) - rescue Errno::ENOENT => e - logger.error("Errors while installing hook '#{e.message}'") - false - else - RedmineGitHosting::Commands.sudo_install_file(content, destination_path, filemode) - end - end - - def update_gitolite - RedmineGitHosting::Commands.sudo_update_gitolite! - end - - def gitolite_hooks_dir - RedmineGitHosting::Config.gitolite_hooks_dir - end - - def directory_exists? - RedmineGitHosting::Commands.sudo_dir_exists?(parent_path) - end - - def create_parent_dir - logger.info("Installing hook directory '#{parent_path}'") - - begin - RedmineGitHosting::Commands.sudo_mkdir_p(parent_path) - true - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error("Problems installing hook directory '#{parent_path}'") - logger.error(e.output) - false - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_hooks.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_hooks.rb deleted file mode 100644 index 5d27814..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_hooks.rb +++ /dev/null @@ -1,42 +0,0 @@ -module RedmineGitHosting - module GitoliteHooks - class << self - def register_hooks(&block) - @gitolite_hooks ||= [] - class_eval(&block) - end - - def registered_hooks - @gitolite_hooks - end - - def source_dir(source_dir) - @source_dir = source_dir - end - - def hooks_installed? - installed = {} - registered_hooks.each do |hook| - begin - installed[hook.name] = hook.installed? - rescue Exception => msg - installed[hook.name] = false - end - end - installed - end - - def install_hooks! - installed = {} - registered_hooks.each do |hook| - installed[hook.name] = hook.install! - end - installed - end - - def gitolite_hook(&block) - @gitolite_hooks << RedmineGitHosting::GitoliteHook.new(@source_dir, &block) - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_params/base_param.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_params/base_param.rb deleted file mode 100644 index a0c7452..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_params/base_param.rb +++ /dev/null @@ -1,21 +0,0 @@ -module RedmineGitHosting - module GitoliteParams - module BaseParam - private - - # Return a hash with global config parameters. - # - def get_git_config_params(namespace) - RedmineGitHosting::Commands.sudo_get_git_global_params(namespace) - end - - def set_git_config_param(namespace, key, value) - RedmineGitHosting::Commands.sudo_set_git_global_param(namespace, key, value) - end - - def unset_git_config_param(key) - RedmineGitHosting::Commands.sudo_unset_git_global_param(key) - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_params/global_params.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_params/global_params.rb deleted file mode 100644 index 6676494..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_params/global_params.rb +++ /dev/null @@ -1,44 +0,0 @@ -module RedmineGitHosting - module GitoliteParams - class GlobalParams - include BaseParam - - attr_reader :gitolite_hooks_url - attr_reader :debug_mode - attr_reader :async_mode - - attr_reader :namespace - attr_reader :current_params - - def initialize - # Params to set - @gitolite_hooks_url = RedmineGitHosting::Config.gitolite_hooks_url - @debug_mode = RedmineGitHosting::Config.gitolite_hooks_debug.to_s - @async_mode = RedmineGitHosting::Config.gitolite_hooks_are_asynchronous.to_s - - # Namespace where to set params - @namespace = RedmineGitHosting::Config.gitolite_hooks_namespace - - # Get current params - @current_params = get_git_config_params(@namespace) - - # Build hash of installed params - @installed = {} - end - - def installed? - @installed['redmineurl'] = (current_params['redmineurl'] == gitolite_hooks_url) - @installed['debugmode'] = (current_params['debugmode'] == debug_mode) - @installed['asyncmode'] = (current_params['asyncmode'] == async_mode) - @installed - end - - def install! - @installed['redmineurl'] = set_git_config_param(namespace, 'redmineurl', gitolite_hooks_url) - @installed['debugmode'] = set_git_config_param(namespace, 'debugmode', debug_mode) - @installed['asyncmode'] = set_git_config_param(namespace, 'asyncmode', async_mode) - @installed - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_params/mailer_params.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_params/mailer_params.rb deleted file mode 100644 index e7c35bf..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_params/mailer_params.rb +++ /dev/null @@ -1,68 +0,0 @@ -module RedmineGitHosting - module GitoliteParams - class MailerParams - include BaseParam - - attr_reader :namespace - attr_reader :current_params - attr_reader :current_mailer_params - - def initialize - ## Namespace where to set params - @namespace = 'multimailhook' - - ## Get current params - @current_params = get_git_config_params(@namespace) - @current_mailer_params = get_mailer_params - - # Build hash of installed params - @installed = {} - end - - def installed? - mailer_params.each do |param| - next if current_mailer_params[param].empty? - - @installed[param] = (current_params[param] == current_mailer_params[param]) - end - @installed - end - - def install! - mailer_params.each do |param| - next if current_mailer_params[param].empty? - - @installed[param] = set_git_config_param(namespace, param, current_mailer_params[param]) - end - @installed - end - - private - - def mailer_params - %w[mailer environment smtpauth smtpserver smtpport smtpuser smtppass] - end - - def get_mailer_params - params = {} - params['environment'] = 'gitolite' - params['mailer'] = mailer - params['smtpauth'] = smtpauth_enabled?.to_s - params['smtpserver'] = ActionMailer::Base.smtp_settings[:address].to_s - params['smtpport'] = ActionMailer::Base.smtp_settings[:port].to_s - params['smtpuser'] = ActionMailer::Base.smtp_settings[:user_name] || '' - params['smtppass'] = ActionMailer::Base.smtp_settings[:password] || '' - params - end - - def mailer - ActionMailer::Base.delivery_method == :smtp ? 'smtp' : 'sendmail' - end - - def smtpauth_enabled? - auth = ActionMailer::Base.smtp_settings[:authentication] - auth != nil && auth != '' && auth != :none - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrapper.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrapper.rb deleted file mode 100644 index 78fba91..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrapper.rb +++ /dev/null @@ -1,99 +0,0 @@ -require 'gitolite' - -module RedmineGitHosting - module GitoliteWrapper - extend self - - # Update the Gitolite Repository - # - # action: An API action defined in one of the gitolite/* classes. - # - def resync_gitolite(action, object, options = {}) - # Symbolize keys before using them - action = action.to_sym - options = options.symbolize_keys - - # Flush cache if needed - flush_cache(options) - - # Return if the action is only to flush cache on Sidekiq side - if action == :flush_settings_cache - logger.info('Settings cache flushed!') - else - execute_action(action, object, options) - end - end - - private - - def flush_cache(options = {}) - if options.key?(:flush_cache) && options[:flush_cache] == true - logger.info('Flush Settings Cache !') - Setting.check_cache if Setting.respond_to?(:check_cache) - end - end - - # Be sure to have a Gitolite::GitoliteAdmin object. - # Return if issues. - # - def execute_action(action, object, options = {}) - begin - admin = gitolite_admin - rescue Rugged::SshError => e - logger.error 'Invalid Gitolite Admin SSH Keys' - logger.error(e.message) - rescue Rugged::NetworkError => e - logger.error 'Access denied for Gitolite Admin SSH Keys' - logger.error(e.message) - rescue Rugged::OSError => e - logger.error 'Invalid connection params' - logger.error(e.message) - rescue Rugged::RepositoryError => e - logger.error "Gitolite couldn't write to its admin repo copy" - logger.error "Try recreating '#{gitolite_admin_dir}'" - logger.error(e.message) - else - call_gitolite_wrapper(action, admin, object, options) - end - end - - def gitolite_admin - RedmineGitHosting::Config.create_temp_dir - logger.debug("Accessing gitolite-admin.git at '#{gitolite_admin_dir}'") - ::Gitolite::GitoliteAdmin.new(gitolite_admin_dir, gitolite_admin_settings) - end - - def gitolite_admin_dir - RedmineGitHosting::Config.gitolite_admin_dir - end - - def call_gitolite_wrapper(action, admin, object, options = {}) - begin - klass = GitoliteWrappers::Base.find_by_action_name(action) - rescue RedmineGitHosting::Error::GitoliteWrapperException => e - logger.error(e.message) - else - klass.call(admin, object, options) - end - end - - def gitolite_admin_settings - { - git_user: RedmineGitHosting::Config.gitolite_user, - hostname: "#{RedmineGitHosting::Config.gitolite_server_host}:#{RedmineGitHosting::Config.gitolite_server_port}", - host: "#{RedmineGitHosting::Config.gitolite_server_host}:#{RedmineGitHosting::Config.gitolite_server_port}", - author_name: RedmineGitHosting::Config.git_config_username, - author_email: RedmineGitHosting::Config.git_config_email, - public_key: RedmineGitHosting::Config.gitolite_ssh_public_key, - private_key: RedmineGitHosting::Config.gitolite_ssh_private_key, - key_subdir: RedmineGitHosting::Config.gitolite_key_subdir, - config_file: RedmineGitHosting::Config.gitolite_config_file, - config_dir: RedmineGitHosting::Config.gitolite_config_dir - } - end - - def logger - RedmineGitHosting.logger - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/base.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/base.rb deleted file mode 100644 index 7d37128..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/base.rb +++ /dev/null @@ -1,91 +0,0 @@ -module RedmineGitHosting - module GitoliteWrappers - class Base - include RedmineGitHosting::GitoliteAccessor::Methods - - attr_reader :admin - attr_reader :object_id - attr_reader :options - attr_reader :gitolite_config - - def initialize(admin, object_id, options = {}) - @admin = admin - @object_id = object_id - @options = options - @gitolite_config = admin.config - end - - class << self - def call(admin, object_id, options = {}) - new(admin, object_id, options).call - end - - def inherited(klass) - @wrappers ||= {} - @wrappers[klass.name.demodulize.underscore.to_sym] = klass - end - - def wrappers - @wrappers ||= {} - end - - def find_by_action_name(action) - if wrappers.key?(action) - wrappers[action] - else - raise RedmineGitHosting::Error::GitoliteWrapperException, "No available Wrapper for action '#{action}' found." - end - end - end - - def call - raise NotImplementedError - end - - def gitolite_admin_repo_commit(message = '') - logger.info("#{context} : commiting to Gitolite...") - admin.save("#{context} : #{message}") - rescue => e - logger.error(e.message) - end - - def create_gitolite_repository(repository) - GitoliteHandlers::Repositories::AddRepository.call(gitolite_config, repository, context, options) - end - - def update_gitolite_repository(repository) - GitoliteHandlers::Repositories::UpdateRepository.call(gitolite_config, repository, context, options) - end - - def delete_gitolite_repository(repository) - GitoliteHandlers::Repositories::DeleteRepository.call(gitolite_config, repository, context, options) - end - - def move_gitolite_repository(repository) - GitoliteHandlers::Repositories::MoveRepository.call(gitolite_config, repository, context, options) - end - - def create_gitolite_key(key) - GitoliteHandlers::SshKeys::AddSshKey.call(admin, key, context) - end - - def delete_gitolite_key(key) - GitoliteHandlers::SshKeys::DeleteSshKey.call(admin, key, context) - end - - private - - def context - self.class.name.demodulize.underscore - end - - def logger - RedmineGitHosting.logger - end - - def log_object_dont_exist - logger.error("#{context} : repository does not exist anymore, object is nil, exit !") - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/global/common.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/global/common.rb deleted file mode 100644 index 107d33d..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/global/common.rb +++ /dev/null @@ -1,46 +0,0 @@ -module RedmineGitHosting - module GitoliteWrappers - module Global - module Common - def redmine_gitolite_key - 'redmine_gitolite_admin_id_rsa' - end - - def all_repository - '@all' - end - - def all_repository_config - gitolite_config.repos[all_repository] - end - - def rw_access_config - repo_conf = ::Gitolite::Config::Repo.new(all_repository) - repo_conf.permissions = rw_access_perms - repo_conf - end - - def rw_access_perms - permissions = {} - permissions['RW+'] = {} - permissions['RW+'][''] = [redmine_gitolite_key] - [permissions] - end - - def repo_conf - all_repository_config - end - - def perms - repo_conf.permissions.select { |p| p.key? 'RW+' } - end - - # RedmineGitHosting key can act on any refspec ('') so it should be in that 'subgroup' - # - def users - perms[0]['RW+'][''] - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/global/delete_from_recycle_bin.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/global/delete_from_recycle_bin.rb deleted file mode 100644 index 0253373..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/global/delete_from_recycle_bin.rb +++ /dev/null @@ -1,12 +0,0 @@ -module RedmineGitHosting - module GitoliteWrappers - module Global - class DeleteFromRecycleBin < GitoliteWrappers::Base - def call - RedmineGitHosting::RecycleBin.delete_content(object_id) - RedmineGitHosting.logger.info('delete_from_recycle_bin : done !') - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/global/disable_rw_access.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/global/disable_rw_access.rb deleted file mode 100644 index 83fbe62..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/global/disable_rw_access.rb +++ /dev/null @@ -1,38 +0,0 @@ -module RedmineGitHosting - module GitoliteWrappers - module Global - class DisableRwAccess < GitoliteWrappers::Base - include Common - - def call - if all_repository_config.nil? - logger.info("#{context} : RW access on all Gitolite repositories already disabled.") - return - else - admin.transaction do - remove_redmine_key - gitolite_admin_repo_commit('Disable RW access on all Gitolite repositories') - end - end - end - - def remove_redmine_key - # RedmineGitHosting key must be in [RW+][''] group - # Return if those groups are absent : it means that our key is not here - return if perms.empty? || !perms[0]['RW+'].include?('') - - # Check for key presence - return unless users.include?(redmine_gitolite_key) - - # Delete the key - repo_conf.permissions[0]['RW+'][''].delete(redmine_gitolite_key) - - # We cannot remove this repository as it may contains other configuration that we didn't check. - # Instead add a dummy key so the repo_conf is still valid for Gitolite - # RW+ = is not valid - repo_conf.permissions[0]['RW+'][''].push('DUMMY_REDMINE_KEY') if repo_conf.permissions[0]['RW+'][''].empty? - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/global/enable_rw_access.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/global/enable_rw_access.rb deleted file mode 100644 index 56795d8..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/global/enable_rw_access.rb +++ /dev/null @@ -1,46 +0,0 @@ -module RedmineGitHosting - module GitoliteWrappers - module Global - class EnableRwAccess < GitoliteWrappers::Base - include Common - - def call - if all_repository_config.nil? - admin.transaction do - gitolite_config.add_repo(rw_access_config) - gitolite_admin_repo_commit('Enable RW access on all Gitolite repositories') - end - else - logger.info("#{context} : '@all' repository already configured, check for RedmineGitHosting key presence") - admin.transaction do - add_redmine_key - gitolite_admin_repo_commit('Enable RW access on all Gitolite repositories') - end - end - end - - def add_redmine_key - # RedmineGitHosting key must be in RW+ group - # If not create the RW+ group and add the key - if perms.empty? - logger.info("#{context} : No permissions set for '@all' repository, add RedmineGitHosting key") - repo_conf.permissions = rw_access_perms - elsif users.nil? - logger.info("#{context} : RedmineGitHosting key is not present, add it !") - repo_conf.permissions[0]['RW+'][''] = [redmine_gitolite_key] - elsif !users.include?(redmine_gitolite_key) - logger.info("#{context} : RedmineGitHosting key is not present, add it !") - repo_conf.permissions[0]['RW+'][''].push(redmine_gitolite_key) - else - logger.info("#{context} : RedmineGitHosting key is present, nothing to do.") - end - - # Delete DUMMY_REDMINE_KEY if present - return unless repo_conf.permissions[0]['RW+'][''].include?('DUMMY_REDMINE_KEY') - - repo_conf.permissions[0]['RW+'][''].delete('DUMMY_REDMINE_KEY') - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/global/purge_recycle_bin.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/global/purge_recycle_bin.rb deleted file mode 100644 index bd28b8f..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/global/purge_recycle_bin.rb +++ /dev/null @@ -1,12 +0,0 @@ -module RedmineGitHosting - module GitoliteWrappers - module Global - class PurgeRecycleBin < GitoliteWrappers::Base - def call - RedmineGitHosting::RecycleBin.delete_expired_content - RedmineGitHosting.logger.info('purge_recycle_bin : done !') - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/projects/common.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/projects/common.rb deleted file mode 100644 index 329dd4e..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/projects/common.rb +++ /dev/null @@ -1,35 +0,0 @@ -module RedmineGitHosting - module GitoliteWrappers - module Projects - module Common - def handle_repositories_move(projects) - repo_list = [] - delete_parent_path = [] - projects.reverse.each do |project| - project.gitolite_repos.reverse.each do |repository| - repo_list << repository.gitolite_repository_name - delete_parent_path << move_gitolite_repository(repository) - end - gitolite_admin_repo_commit("#{context} : #{project.identifier} | #{repo_list}") - end - delete_parent_path - end - - def clean_path(path_list) - path_list.compact.uniq.sort.reverse.each do |path| - rmdir(path) - end - end - - def rmdir(path) - logger.info("#{context} : cleaning repository path : '#{path}'") - begin - RedmineGitHosting::Commands.sudo_rmdir(path) - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error("#{context} : error while cleaning repository path '#{path}'") - end - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/projects/move_repositories.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/projects/move_repositories.rb deleted file mode 100644 index 2b39dc5..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/projects/move_repositories.rb +++ /dev/null @@ -1,28 +0,0 @@ -module RedmineGitHosting - module GitoliteWrappers - module Projects - class MoveRepositories < GitoliteWrappers::Base - include Common - - def call - return if git_projects.empty? - - admin.transaction do - @delete_parent_path = [] - @delete_parent_path += handle_repositories_move(git_projects) - # Remove empty directories - clean_path(@delete_parent_path) - end - end - - def git_projects - @git_projects ||= projects.uniq.select { |p| p.gitolite_repos.any? } - end - - def projects - @projects ||= Project.find_by_id(object_id).self_and_descendants - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/projects/move_repositories_tree.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/projects/move_repositories_tree.rb deleted file mode 100644 index feb7376..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/projects/move_repositories_tree.rb +++ /dev/null @@ -1,30 +0,0 @@ -module RedmineGitHosting - module GitoliteWrappers - module Projects - class MoveRepositoriesTree < GitoliteWrappers::Base - include Common - - # Move repositories tree in a single transaction - # - def call - admin.transaction do - @delete_parent_path = [] - projects.each do |project| - # Only take projects that have Git repos. - git_projects = project.self_and_descendants.uniq.select { |p| p.gitolite_repos.any? } - next if git_projects.empty? - - @delete_parent_path += handle_repositories_move(git_projects) - end - # Remove empty directories - clean_path(@delete_parent_path) - end - end - - def projects - @projects ||= Project.includes(:repositories).all.select { |x| x.parent_id.nil? } - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/projects/update_projects.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/projects/update_projects.rb deleted file mode 100644 index 142fabc..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/projects/update_projects.rb +++ /dev/null @@ -1,44 +0,0 @@ -module RedmineGitHosting - module GitoliteWrappers - module Projects - class UpdateProjects < GitoliteWrappers::Base - def call - return if git_projects.empty? - - admin.transaction do - git_projects.each do |project| - if project.gitolite_repos.any? - handle_project_update(project) - gitolite_admin_repo_commit(project.identifier) - end - end - end - end - - def git_projects - @git_projects ||= projects.uniq.select { |p| p.gitolite_repos.any? } - end - - def projects - @projects ||= - case object_id - when 'all' - Project.includes(:repositories).all - when 'active' - Project.active.includes(:repositories).all - when 'active_or_closed' - Project.active_or_closed.includes(:repositories).all - else - object_id.map { |project_id| Project.find_by_id(project_id) } - end - end - - def handle_project_update(project) - project.gitolite_repos.each do |repository| - options[:force] == true ? create_gitolite_repository(repository) : update_gitolite_repository(repository) - end - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/repositories/add_repository.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/repositories/add_repository.rb deleted file mode 100644 index a77bde4..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/repositories/add_repository.rb +++ /dev/null @@ -1,44 +0,0 @@ -module RedmineGitHosting - module GitoliteWrappers - module Repositories - class AddRepository < GitoliteWrappers::Base - def call - if !repository.nil? - create_repository - else - log_object_dont_exist - end - end - - def repository - @repository ||= Repository.find_by_id(object_id) - end - - def create_repository - admin.transaction do - create_gitolite_repository(repository) - gitolite_admin_repo_commit(repository.gitolite_repository_name) - - @recovered = RedmineGitHosting::RecycleBin.restore_object_from_recycle repository.gitolite_repository_name, - repository.gitolite_full_repository_path - - if !@recovered - logger.info("#{context} : let Gitolite create empty repository '#{repository.gitolite_repository_path}'") - else - logger.info("#{context} : restored existing Gitolite repository '#{repository.gitolite_repository_path}' for update") - end - end - - # Call Gitolite plugins - logger.info('Execute Gitolite Plugins') - - # Create README file or initialize GitAnnex - RedmineGitHosting::Plugins.execute(:post_create, repository, options.merge(recovered: @recovered)) - - # Fetch changeset - repository.fetch_changesets - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/repositories/delete_repository.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/repositories/delete_repository.rb deleted file mode 100644 index f1f16bc..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/repositories/delete_repository.rb +++ /dev/null @@ -1,32 +0,0 @@ -module RedmineGitHosting - module GitoliteWrappers - module Repositories - class DeleteRepository < GitoliteWrappers::Base - def call - if !repository.nil? && !repository.empty? - delete_repository - else - log_object_dont_exist - end - end - - def repository - @repository ||= object_id.symbolize_keys - end - - def delete_repository - admin.transaction do - delete_gitolite_repository(repository) - gitolite_admin_repo_commit(repository[:repo_name]) - end - - # Call Gitolite plugins - logger.info('Execute Gitolite Plugins') - - # Move repository to RecycleBin - RedmineGitHosting::Plugins.execute(:post_delete, repository) - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/repositories/move_repository.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/repositories/move_repository.rb deleted file mode 100644 index 1d8b410..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/repositories/move_repository.rb +++ /dev/null @@ -1,29 +0,0 @@ -module RedmineGitHosting - module GitoliteWrappers - module Repositories - class MoveRepository < GitoliteWrappers::Base - def call - if !repository.nil? - move_repository - else - log_object_dont_exist - end - end - - def repository - @repository ||= Repository.find_by_id(object_id) - end - - def move_repository - admin.transaction do - move_gitolite_repository(repository) - gitolite_admin_repo_commit(repository.gitolite_repository_name) - end - - # Fetch changeset - repository.fetch_changesets - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/repositories/update_repository.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/repositories/update_repository.rb deleted file mode 100644 index 4f0401f..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/repositories/update_repository.rb +++ /dev/null @@ -1,35 +0,0 @@ -module RedmineGitHosting - module GitoliteWrappers - module Repositories - class UpdateRepository < GitoliteWrappers::Base - def call - if !repository.nil? - update_repository - else - log_object_dont_exist - end - end - - def repository - @repository ||= Repository.find_by_id(object_id) - end - - def update_repository - admin.transaction do - update_gitolite_repository(repository) - gitolite_admin_repo_commit(repository.gitolite_repository_name) - end - - # Call Gitolite plugins - logger.info('Execute Gitolite Plugins') - - # Delete Git Config Keys - RedmineGitHosting::Plugins.execute(:post_update, repository, options) - - # Fetch changeset - repository.fetch_changesets - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/users/add_ssh_key.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/users/add_ssh_key.rb deleted file mode 100644 index 07810aa..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/users/add_ssh_key.rb +++ /dev/null @@ -1,19 +0,0 @@ -module RedmineGitHosting - module GitoliteWrappers - module Users - class AddSshKey < GitoliteWrappers::Base - def call - logger.info("Adding SSH key '#{ssh_key.identifier}'") - admin.transaction do - create_gitolite_key(ssh_key) - gitolite_admin_repo_commit("Add SSH key : #{ssh_key.identifier}") - end - end - - def ssh_key - @ssh_key ||= GitolitePublicKey.find_by_id(object_id) - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/users/delete_ssh_key.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/users/delete_ssh_key.rb deleted file mode 100644 index 679b1b0..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/users/delete_ssh_key.rb +++ /dev/null @@ -1,19 +0,0 @@ -module RedmineGitHosting - module GitoliteWrappers - module Users - class DeleteSshKey < GitoliteWrappers::Base - def call - logger.info("Deleting SSH key '#{ssh_key[:title]}'") - admin.transaction do - delete_gitolite_key(ssh_key) - gitolite_admin_repo_commit("Delete SSH key : #{ssh_key[:title]}") - end - end - - def ssh_key - @ssh_key ||= object_id.symbolize_keys - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/users/regenerate_ssh_keys.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/users/regenerate_ssh_keys.rb deleted file mode 100644 index 8478738..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/users/regenerate_ssh_keys.rb +++ /dev/null @@ -1,15 +0,0 @@ -module RedmineGitHosting - module GitoliteWrappers - module Users - class RegenerateSshKeys < GitoliteWrappers::Base - def call - GitolitePublicKey.all.each do |ssh_key| - gitolite_accessor.destroy_ssh_key(ssh_key, bypass_sidekiq: true) - ssh_key.reset_identifiers(skip_auto_increment: true) - gitolite_accessor.create_ssh_key(ssh_key, bypass_sidekiq: true) - end - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/users/resync_ssh_keys.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/users/resync_ssh_keys.rb deleted file mode 100644 index 7b77883..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/gitolite_wrappers/users/resync_ssh_keys.rb +++ /dev/null @@ -1,16 +0,0 @@ -module RedmineGitHosting - module GitoliteWrappers - module Users - class ResyncSshKeys < GitoliteWrappers::Base - def call - admin.transaction do - GitolitePublicKey.all.each do |ssh_key| - create_gitolite_key(ssh_key) - gitolite_admin_repo_commit("Add SSH key : #{ssh_key.identifier}") - end - end - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/hooks.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/hooks.rb deleted file mode 100644 index aef5183..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/hooks.rb +++ /dev/null @@ -1,76 +0,0 @@ -require 'github/markup' - -module RedmineGitHosting - class GitHostingHookListener < Redmine::Hook::ViewListener - render_on :view_repository_edit_top, partial: 'repositories/edit_top' - render_on :view_repositories_show_contextual, partial: 'repositories/show_top' - render_on :view_repository_edit_bottom, partial: 'repositories/edit_bottom' - render_on :view_repositories_show_sidebar, partial: 'repositories/git_hosting_sidebar' - render_on :view_repositories_navigation, partial: 'repositories/git_hosting_navigation' - - def view_layouts_base_html_head(_context = {}) - header = '' - header << stylesheet_link_tag(:plugin, plugin: 'redmine_git_hosting') + "\n" - header << javascript_include_tag(:plugin, plugin: 'redmine_git_hosting') + "\n" - header - end - - def view_my_account_contextual(context) - user = context[:user] - link_to(l(:label_my_public_keys), public_keys_path, class: 'icon icon-passwd') if user.allowed_to_create_ssh_keys? - end - - def self.default_url_options - { script_name: Redmine::Utils.relative_url_root } - end - - def view_repositories_show_bottom(context) - path = get_path(context) - rev = get_rev(context) - repository = context[:repository] - readme_file = find_readme_file(repository, path, rev) - - return '' if readme_file.nil? - - content = get_formated_text(repository, readme_file, rev) - - context[:controller].send(:render_to_string, partial: 'repositories/readme', locals: { html: content }) - end - - private - - def get_path(context) - context[:request].params['path'] || '' - end - - def get_rev(context) - rev = context[:request].params['rev'] - rev.presence - end - - def find_readme_file(repository, path, rev) - (repository.entries(path, rev) || []).find { |f| f.name =~ /README((\.).*)?/i } - end - - def get_formated_text(repository, file, rev) - raw_readme_text = Redmine::CodesetUtil.to_utf8_by_setting(repository.cat(file.path, rev)) - - if redmine_file?(file) - formatter_name = Redmine::WikiFormatting.format_names.find { |name| name =~ /markdown/i } - Redmine::WikiFormatting.formatter_for(formatter_name).new(raw_readme_text).to_html - elsif github_file?(file) - RedmineGitHosting::MarkdownRenderer.to_html(raw_readme_text) - else - GitHub::Markup.render(file.path, raw_readme_text) - end - end - - def redmine_file?(file) - %w[.txt].include?(File.extname(file.path)) - end - - def github_file?(file) - %w[.markdown .mdown .mkdn .md].include?(File.extname(file.path)) - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/journal_logger.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/journal_logger.rb deleted file mode 100644 index 10b70da..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/journal_logger.rb +++ /dev/null @@ -1,38 +0,0 @@ -module RedmineGitHosting - # @see https://github.com/theforeman/journald-logger - if defined? ::Journald::Logger - class JournalLogger < ::Journald::Logger - def self.init_logs!(progname, loglevel) - logger = new progname, type: progname - logger.level = loglevel - - logger - end - - def debug(msg) - super msg2str(msg) - end - - def info(msg) - super msg2str(msg) - end - - def warn(msg) - super msg2str(msg) - end - - def error(msg) - super msg2str(msg) - end - - def msg2str(msg) - case msg - when ::String - msg - else - msg.inspect - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/markdown_renderer.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/markdown_renderer.rb deleted file mode 100644 index d19aedf..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/markdown_renderer.rb +++ /dev/null @@ -1,26 +0,0 @@ -require 'html/pipeline' -require 'task_list/filter' -require 'task_list/railtie' - -module RedmineGitHosting - module MarkdownRenderer - extend self - - def to_html(markdown) - pipeline.call(markdown)[:output].to_s - end - - private - - def pipeline - HTML::Pipeline.new(filters) - end - - def filters - [RedmineGitHosting::RedcarpetFilter, - TaskList::Filter, - HTML::Pipeline::AutolinkFilter, - HTML::Pipeline::TableOfContentsFilter] - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/mirror_keys_installer.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/mirror_keys_installer.rb deleted file mode 100644 index c86a9f0..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/mirror_keys_installer.rb +++ /dev/null @@ -1,105 +0,0 @@ -module RedmineGitHosting - class MirrorKeysInstaller - attr_reader :gitolite_home_dir, :gitolite_ssh_public_key, :gitolite_ssh_private_key - - GITOLITE_MIRRORING_KEYS_NAME = 'redmine_gitolite_admin_id_rsa_mirroring'.freeze - - def initialize(gitolite_home_dir, gitolite_ssh_public_key, gitolite_ssh_private_key) - @gitolite_home_dir = gitolite_home_dir - @gitolite_ssh_public_key = gitolite_ssh_public_key - @gitolite_ssh_private_key = gitolite_ssh_private_key - end - - class << self - def mirroring_public_key(gitolite_ssh_public_key) - format_mirror_key(File.read(gitolite_ssh_public_key)) - rescue => e - RedmineGitHosting.logger.error("Error while loading mirroring public key : #{e.inspect}") - nil - end - - def format_mirror_key(key) - key = key.chomp.strip - key.split(/[\t ]+/)[0].to_s + ' ' + key.split(/[\t ]+/)[1].to_s - end - end - - def installed? - installable? && install! - end - - def installable? - return false if gitolite_home_dir.nil? - return false if gitolite_ssh_public_key_content.nil? - return false if gitolite_ssh_private_key_content.nil? - - true - end - - def install! - logger.info('Installing Redmine Gitolite mirroring SSH keys ...') - installed = install_public_key && install_private_key && install_mirroring_script - logger.info('Done!') - installed - end - - def install_public_key - install_file(gitolite_ssh_public_key_content, gitolite_ssh_public_key_dest_path, '644') do - logger.error("Failed to install Redmine Git Hosting mirroring SSH public key : #{e.output}") - end - end - - def install_private_key - install_file(gitolite_ssh_private_key_content, gitolite_ssh_private_key_dest_path, '600') do - logger.error("Failed to install Redmine Git Hosting mirroring SSH private key : #{e.output}") - end - end - - def install_mirroring_script - install_file(mirroring_script_content, RedmineGitHosting::Config.gitolite_mirroring_script, '700') do - logger.error("Failed to install Redmine Git Hosting mirroring script : #{e.output}") - end - end - - private - - def logger - RedmineGitHosting.logger - end - - def mirroring_script_content - [ - '#!/bin/sh', "\n", - 'exec', 'ssh', '-T', '-o', 'BatchMode=yes', '-o', 'StrictHostKeyChecking=no', '-i', gitolite_ssh_private_key_dest_path, '"$@"', - "\n" - ].join(' ') - end - - def gitolite_ssh_public_key_content - File.read(gitolite_ssh_public_key) - rescue => e - nil - end - - def gitolite_ssh_private_key_content - File.read(gitolite_ssh_private_key) - rescue => e - nil - end - - def gitolite_ssh_public_key_dest_path - File.join(gitolite_home_dir, '.ssh', "#{GITOLITE_MIRRORING_KEYS_NAME}.pub") - end - - def gitolite_ssh_private_key_dest_path - File.join(gitolite_home_dir, '.ssh', GITOLITE_MIRRORING_KEYS_NAME) - end - - def install_file(source, destination, perms, &block) - RedmineGitHosting::Commands.sudo_install_file(source, destination, perms) - rescue RedmineGitHosting::Error::GitoliteCommandException => e - yield - false - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/changeset_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/changeset_patch.rb deleted file mode 100644 index 60ac9d9..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/changeset_patch.rb +++ /dev/null @@ -1,60 +0,0 @@ -require_dependency 'changeset' - -module RedmineGitHosting - module Patches - module ChangesetPatch - def github_payload - data = {} - data[:id] = revision - data[:message] = comments - data[:timestamp] = committed_on - data[:author] = author_data - data[:added] = added_files - data[:modified] = modified_files - data[:removed] = removed_files - data[:url] = url_for_revision(revision) - data - end - - def author_data - { name: author_name, email: author_email } - end - - def author_name - RedmineGitHosting::Utils::Git.author_name(committer) - end - - def author_email - RedmineGitHosting::Utils::Git.author_email(committer) - end - - def added_files - filechanges_by_action('A') - end - - def modified_files - filechanges_by_action('M') - end - - def removed_files - filechanges_by_action('D') - end - - def filechanges_by_action(action) - filechanges.select { |c| c.action == action }.map(&:path) - end - - def url_for_revision(revision) - Rails.application.routes.url_helpers.url_for( - controller: 'repositories', action: 'revision', - id: project, repository_id: repository.identifier_param, rev: revision, - only_path: false, host: Setting['host_name'], protocol: Setting['protocol'] - ) - end - end - end -end - -unless Changeset.included_modules.include?(RedmineGitHosting::Patches::ChangesetPatch) - Changeset.prepend RedmineGitHosting::Patches::ChangesetPatch -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/dashboard_content_project_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/dashboard_content_project_patch.rb deleted file mode 100644 index 52e0622..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/dashboard_content_project_patch.rb +++ /dev/null @@ -1,28 +0,0 @@ -module RedmineGitHosting - module Patches - module DashboardContentProjectPatch - extend ActiveSupport::Concern - - included do - prepend InstanceOverwriteMethods - end - - module InstanceOverwriteMethods - def block_definitions - blocks = super - - blocks['giturls'] = { label: l(:label_repository_url_plural), - permission: :manage_repository, - no_settings: true, - partial: 'dashboards/blocks/git_urls' } - - blocks - end - end - end - end -end - -if DashboardContentProject.included_modules.exclude? RedmineGitHosting::Patches::DashboardContentProjectPatch - DashboardContentProject.include RedmineGitHosting::Patches::DashboardContentProjectPatch -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/grack_auth_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/grack_auth_patch.rb deleted file mode 100644 index aa60776..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/grack_auth_patch.rb +++ /dev/null @@ -1,127 +0,0 @@ -require 'grack/auth' - -module RedmineGitHosting - module Patches - module GrackAuthPatch - def call(env) - @env = env - @request = Rack::Request.new(env) - @auth = Rack::Auth::Basic::Request.new(env) - - # Need this patch due to the rails mount - - # Need this if under RELATIVE_URL_ROOT - # unless Gitlab.config.gitlab.relative_url_root.empty? - # # If website is mounted using relative_url_root need to remove it first - # @env['PATH_INFO'] = @request.path.sub(Gitlab.config.gitlab.relative_url_root,'') - # else - # @env['PATH_INFO'] = @request.path - # end - - if repository - auth! - else - render_not_found - end - end - - private - - def auth! - if @auth.provided? - return bad_request unless @auth.basic? - - # Authentication with username and password - login, password = @auth.credentials - @user = authenticate_user(login, password) - - @env['REMOTE_USER'] = @user.gitolite_identifier if @user - end - - if authorized_request? - @app.call(@env) - else - unauthorized - end - end - - def authenticate_user(login, password) - auth = RedmineGitHosting::Auth.new - auth.find(login, password) - end - - def authorized_request? - case git_cmd - when *RedmineGitHosting::GitAccess::DOWNLOAD_COMMANDS - if @user - RedmineGitHosting::GitAccess.new.download_access_check(@user, repository, is_ssl?).allowed? - elsif repository.public_project? || repository.public_repo? - # Allow clone/fetch for public projects - true - else - false - end - when *RedmineGitHosting::GitAccess::PUSH_COMMANDS - # Push requires valid SSL - if !is_ssl? - logger.error('SmartHttp : your are trying to push data without SSL!, exiting !') - false - elsif @user - RedmineGitHosting::GitAccess.new.upload_access_check(@user, repository).allowed? - else - false - end - else - false - end - end - - def git_cmd - if @request.get? - @request.params['service'] - elsif @request.post? - File.basename(@request.path) - end - end - - def repository - @repository ||= repository_by_path(@request.path_info) - end - - def repository_by_path(path) - if m = /([^\/]+\/)*?[^\/]+\.git/.match(path).to_a - repo_path = m.first - Repository::Xitolite.find_by_path(repo_path, loose: true) - end - end - - def is_ssl? - @request.ssl? || https_headers? || x_forwarded_proto_headers? || x_forwarded_ssl_headers? - end - - def https_headers? - @request.env['HTTPS'].to_s == 'on' - end - - def x_forwarded_proto_headers? - @request.env['HTTP_X_FORWARDED_PROTO'].to_s == 'https' - end - - def x_forwarded_ssl_headers? - @request.env['HTTP_X_FORWARDED_SSL'].to_s == 'on' - end - - def render_not_found - [404, { 'Content-Type' => 'text/plain' }, ['Not Found']] - end - - def logger - RedmineGitHosting.logger - end - end - end -end - -unless Grack::Auth.included_modules.include?(RedmineGitHosting::Patches::GrackAuthPatch) - Grack::Auth.prepend RedmineGitHosting::Patches::GrackAuthPatch -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/grack_git_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/grack_git_patch.rb deleted file mode 100644 index 170115c..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/grack_git_patch.rb +++ /dev/null @@ -1,117 +0,0 @@ -require 'grack/git' - -module RedmineGitHosting - module Patches - module GrackGitPatch - def initialize(git_path, repo_path, user) - @user = user - super(git_path, repo_path) - end - - # Override original *valid_repo?* method to test directory presence with Sudo - def valid_repo? - directory_exists?(repo) - end - - # Override original *command* method to prefix the command with Sudo and other args. - # - def command(cmd) - git_command_with_sudo(cmd) - end - - # Override original *capture* method because the original IO.popen().read let zombie process behind. - # This method is called : - # * to get repository Git config (http.uploadpack || http.receivepack) - # * to get repository info refs : - # 0087deab8f3d612a47e7e153ed21bbc52a480205035a refs/heads/devel report-status delete-refs side-band-64k quiet \ - # ofs-delta agent=git/1.9.1 - # * to get repository refs : - # 003f91a7b1dad21020e96d52119c585881c02f2fae45 refs/heads/master - - # Note : *service_rpc* also calls IO.popen but pass a block !. - # Passing a block to IO.popen auto-close the pipe/thread. - - def capture(command) - # Extract Args - cmd = command.shift - args = command - - begin - RedmineGitHosting::Utils::Exec.capture(cmd, args) - rescue => e - logger.error('Problems while getting SmartHttp params') - # Return empty string since the next method will call *chomp* on it - '' - end - end - - # Override original *popen_options* method. - # The original one try to chdir before executing the command by - # passing 'chdir: @dir' option to IO.popen. - # This is wrong as we can't chdir to Gitolite directory. - # Notes : this method is called in *service_rpc* (not overriden) - # - def popen_options - { unsetenv_others: true } - end - - # Override original *popen_env* method. - # The original one passes useless arg (GL_ID) to IO.popen. - # Notes : this method is called in *service_rpc* (not overriden) - # - def popen_env - { 'PATH' => ENV['PATH'] } - end - - private - - def directory_exists?(dir) - RedmineGitHosting::Commands.sudo_dir_exists?(dir) - end - - # We sometimes need to add *--git-dir* arg to Git command otherwise - # Git looks for the repository in the current path. - def git_command_with_sudo(params) - if command_require_chdir?(params.last) - git_command_with_chdir.concat(params) - else - git_command_without_chdir.concat(params) - end - end - - def command_require_chdir?(cmd) - cmd == 'update-server-info' || cmd == 'http.receivepack' || cmd == 'http.uploadpack' || cmd == 'rev-parse' - end - - def git_command_without_chdir - RedmineGitHosting::Commands.sudo_git_cmd(smart_http_args) - end - - def git_command_with_chdir - RedmineGitHosting::Commands.sudo_git_args_for_repo(@repo, smart_http_args) - end - - def smart_http_args - [ - 'env', - "GL_BINDIR=#{RedmineGitHosting::Config.gitolite_bin_dir}", - "GL_LIBDIR=#{RedmineGitHosting::Config.gitolite_lib_dir}", - "GL_REPO=#{repository_object.gitolite_repository_name}", - "GL_USER=#{@user}" - ] - end - - def logger - RedmineGitHosting.logger - end - - def repository_object - @repository_object ||= Repository::Xitolite.find_by_path(@repo, loose: true) - end - end - end -end - -unless Grack::Git.included_modules.include?(RedmineGitHosting::Patches::GrackGitPatch) - Grack::Git.prepend RedmineGitHosting::Patches::GrackGitPatch -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/grack_server_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/grack_server_patch.rb deleted file mode 100644 index a85233d..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/grack_server_patch.rb +++ /dev/null @@ -1,27 +0,0 @@ -require 'grack/server' - -module RedmineGitHosting - module Patches - module GrackServerPatch - # Override original *get_git* method to set the right path for the repository. - # Also pass the *@env['REMOTE_USER']* variable to the Git constructor so we - # can pass it to Gitolite hooks later. - def get_git(path) - path = gitolite_path(path) - Grack::Git.new(@config[:git_path], path, @env['REMOTE_USER']) - end - - private - - def gitolite_path(path) - File.join(RedmineGitHosting::Config.gitolite_home_dir, - RedmineGitHosting::Config.gitolite_global_storage_dir, - RedmineGitHosting::Config.gitolite_redmine_storage_dir, path) - end - end - end -end - -unless Grack::Server.included_modules.include?(RedmineGitHosting::Patches::GrackServerPatch) - Grack::Server.prepend RedmineGitHosting::Patches::GrackServerPatch -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/group_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/group_patch.rb deleted file mode 100644 index 39390d4..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/group_patch.rb +++ /dev/null @@ -1,31 +0,0 @@ -require_dependency 'group' - -module RedmineGitHosting - module Patches - module GroupPatch - def self.prepended(base) - base.class_eval do - # Relations - has_many :protected_branches_members, dependent: :destroy, foreign_key: :principal_id - has_many :protected_branches, through: :protected_branches_members - end - end - - def user_added(user) - super - protected_branches.each do |pb| - RepositoryProtectedBranches::MemberManager.new(pb).add_user_from_group(user, id) - end - end - - def user_removed(user) - super - protected_branches.each do |pb| - RepositoryProtectedBranches::MemberManager.new(pb).remove_user_from_group(user, id) - end - end - end - end -end - -Group.prepend RedmineGitHosting::Patches::GroupPatch unless Group.included_modules.include?(RedmineGitHosting::Patches::GroupPatch) diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/issue_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/issue_patch.rb deleted file mode 100644 index a81c107..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/issue_patch.rb +++ /dev/null @@ -1,15 +0,0 @@ -require_dependency 'issue' - -module RedmineGitHosting - module Patches - module IssuePatch - def self.prepended(base) - base.class_eval do - has_one :github_issue, foreign_key: 'issue_id', class_name: 'GithubIssue', dependent: :destroy - end - end - end - end -end - -Issue.prepend RedmineGitHosting::Patches::IssuePatch unless Issue.included_modules.include?(RedmineGitHosting::Patches::IssuePatch) diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/journal_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/journal_patch.rb deleted file mode 100644 index 67333a4..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/journal_patch.rb +++ /dev/null @@ -1,15 +0,0 @@ -require_dependency 'journal' - -module RedmineGitHosting - module Patches - module JournalPatch - def self.prepended(base) - base.class_eval do - has_one :github_comment, foreign_key: 'journal_id', class_name: 'GithubComment', dependent: :destroy - end - end - end - end -end - -Journal.prepend RedmineGitHosting::Patches::JournalPatch unless Journal.included_modules.include?(RedmineGitHosting::Patches::JournalPatch) diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/member_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/member_patch.rb deleted file mode 100644 index 90e80f9..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/member_patch.rb +++ /dev/null @@ -1,24 +0,0 @@ -require_dependency 'member' - -module RedmineGitHosting - module Patches - module MemberPatch - include RedmineGitHosting::GitoliteAccessor::Methods - - def self.prepended(base) - base.class_eval do - after_commit :update_project - end - end - - private - - def update_project - options = { message: "Membership changes on project '#{project}', update!" } - gitolite_accessor.update_projects([project.id], options) - end - end - end -end - -Member.prepend RedmineGitHosting::Patches::MemberPatch unless Member.included_modules.include?(RedmineGitHosting::Patches::MemberPatch) diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/project_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/project_patch.rb deleted file mode 100644 index 0818372..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/project_patch.rb +++ /dev/null @@ -1,53 +0,0 @@ -require_dependency 'project' - -module RedmineGitHosting - module Patches - module ProjectPatch - def self.prepended(base) - base.class_eval do - # Add custom scope - scope :active_or_closed, -> { where("status = #{Project::STATUS_ACTIVE} OR status = #{Project::STATUS_CLOSED}") } - - # 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 - end - end - - # Find all repositories owned by project which are Repository::Xitolite - def gitolite_repos - repositories.select { |x| x.is_a?(Repository::Xitolite) }.sort { |x, y| x.id <=> y.id } - end - - # Return first repo with a blank identifier (should be only one!) - def repo_blank_ident - Repository.where("project_id = ? and (identifier = '' or identifier is null)", id).first - end - - def users_available - get_members_available('User') - end - - def groups_available - get_members_available('Group') - end - - private - - def get_members_available(klass) - memberships.active.map(&:principal).select { |m| m.class.name == klass }.uniq.sort - end - - def additional_constraints_on_identifier - if new_record? && identifier.present? - # Make sure that identifier does not match existing repository identifier - errors.add(:identifier, :taken) if Repository.find_by_identifier_and_type(identifier, 'Repository::Xitolite') - end - end - end - end -end - -Project.prepend RedmineGitHosting::Patches::ProjectPatch unless Project.included_modules.include?(RedmineGitHosting::Patches::ProjectPatch) diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/projects_controller_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/projects_controller_patch.rb deleted file mode 100644 index 483ccda..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/projects_controller_patch.rb +++ /dev/null @@ -1,132 +0,0 @@ -require_dependency 'projects_controller' - -module RedmineGitHosting - module Patches - module ProjectsControllerPatch - include RedmineGitHosting::GitoliteAccessor::Methods - - def self.prepended(base) - base.class_eval do - helper :git_hosting - helper :additionals_clipboardjs - helper :extend_projects - end - end - - def create - super - # Only create repo if project creation worked - create_project_repository if valid_project? - end - - def update - super - if @project.gitolite_repos.detect { |repo| repo.url != repo.gitolite_repository_path || repo.url != repo.root_url } - # Hm... something about parent hierarchy changed. Update us and our children - move_project_hierarchy - else - update_project("Set Git daemon for repositories of project : '#{@project}'") - end - end - - def destroy - # Build repositories list before project destruction. - repositories_list = repositories_to_destroy - # Destroy project - super - # Destroy repositories - destroy_repositories(repositories_list) if api_request? || params[:confirm] - end - - def archive - super - update_project_hierarchy("User '#{User.current.login}' has archived project '#{@project}', update it !") - end - - def unarchive - super - update_project("User '#{User.current.login}' has unarchived project '#{@project}', update it !") - end - - def close - super - update_project_hierarchy("User '#{User.current.login}' has closed project '#{@project}', update it !") - end - - def reopen - super - update_project_hierarchy("User '#{User.current.login}' has reopened project '#{@project}', update it !") - end - - private - - def valid_project? - if Rails::VERSION::MAJOR == 3 - validate_parent_id && @project.save - else - @project.save - end - end - - # Call UseCase object that will complete Project repository creation : - # it will create the Repository::Xitolite association, the GitExtra association and then - # the repository in Gitolite. - # - def create_project_repository - if @project.module_enabled?('repository') && RedmineGitHosting::Config.all_projects_use_git? - if Setting.enabled_scm.include?('Xitolite') - Projects::CreateRepository.call(@project) - else - flash[:error] = l(:error_xitolite_repositories_disabled) - end - end - end - - def move_project_hierarchy - gitolite_accessor.move_project_hierarchy(@project) - end - - def update_project(message) - options = { message: message } - Projects::Update.call(@project, options) - end - - def update_project_hierarchy(message) - options = { message: message } - gitolite_accessor.update_projects(hierarchy_to_update, options) - end - - def hierarchy_to_update - # Only take projects that have Git repos. - @project.self_and_descendants.uniq.select { |p| p.gitolite_repos.any? }.map(&:id) - end - - def destroy_repositories(repositories_list) - options = { message: "User '#{User.current.login}' has destroyed project '#{@project}', delete all Gitolite repositories !" } - gitolite_accessor.destroy_repositories(repositories_list, options) - end - - def repositories_to_destroy - destroy_repositories = [] - - # Get all projects hierarchy - projects = @project.self_and_descendants - - # Only take projects that have Git repos. - git_projects = projects.uniq.select { |p| p.gitolite_repos.any? } - - git_projects.reverse.each do |project| - project.gitolite_repos.reverse.each do |repository| - destroy_repositories << repository.data_for_destruction - end - end - - destroy_repositories - end - end - end -end - -unless ProjectsController.included_modules.include?(RedmineGitHosting::Patches::ProjectsControllerPatch) - ProjectsController.send(:prepend, RedmineGitHosting::Patches::ProjectsControllerPatch) -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/repositories_controller_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/repositories_controller_patch.rb deleted file mode 100644 index 08c36dd..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/repositories_controller_patch.rb +++ /dev/null @@ -1,162 +0,0 @@ -require_dependency 'repositories_controller' - -module RedmineGitHosting - module Patches - module RepositoriesControllerPatch - include RedmineGitHosting::GitoliteAccessor::Methods - def self.prepended(base) - base.class_eval do - before_action :set_current_tab, only: :edit - - helper :git_hosting - helper :additionals_clipboardjs - helper :watchers - - # Load ExtendRepositoriesHelper so we can call our - # additional methods. - helper :extend_repositories - end - end - - def show - if @repository.is_a?(Repository::Xitolite) && @repository.empty? - # Fake list of repos - @repositories = @project.gitolite_repos - render 'git_instructions' - else - super - end - end - - def create - super - call_use_cases - end - - def update - super - call_use_cases - end - - def destroy - super - call_use_cases - end - - # Monkey patch *diff* method to pass the *bypass_cache* flag - # on diff download. - # - def diff - if @repository.is_a?(Repository::Xitolite) - diff_with_options - else - super - end - end - - private - - def set_current_tab - @tab = params[:tab] || '' - end - - def call_use_cases - return unless @repository.is_a?(Repository::Xitolite) - return if @repository.errors.any? - - case action_name - when 'create' - # Call UseCase object that will complete Repository creation : - # it will create GitExtra association and then the repository in Gitolite. - Repositories::Create.call(@repository, creation_options) - when 'update' - gitolite_accessor.update_repository(@repository) - when 'destroy' - gitolite_accessor.destroy_repository(@repository) - end - end - - def creation_options - { create_readme_file: create_readme_file?, enable_git_annex: enable_git_annex? } - end - - def create_readme_file? - Additionals.true? @repository.create_readme - end - - def enable_git_annex? - Additionals.true? @repository.enable_git_annex - end - - REV_PARAM_RE = %r{\A[a-f0-9]*\Z}i - - # Monkey patch *find_project_repository* method to render Git instructions - # if repository has no branch - # - def find_project_repository - @project = Project.find(params[:id]) - if params[:repository_id].present? - @repository = @project.repositories.find_by_identifier_param(params[:repository_id]) - else - @repository = @project.repository - end - (render_404; return false) unless @repository - @path = params[:path].is_a?(Array) ? params[:path].join('/') : params[:path].to_s - @rev = params[:rev].blank? ? @repository.default_branch : params[:rev].to_s.strip - @rev_to = params[:rev_to] - - unless @rev.to_s.match(REV_PARAM_RE) && @rev_to.to_s.match(REV_PARAM_RE) - raise InvalidRevisionParam if @repository.branches.empty? - end - rescue ActiveRecord::RecordNotFound - render_404 - rescue InvalidRevisionParam - # Fake list of repos - @repositories = @project.gitolite_repos - render 'git_instructions' - end - - # This is the original diff method with the *bypass_cache* flag - # for diff download. We keep the cache for the diff view. - # - def diff_with_options - if params[:format] == 'diff' - @diff = @repository.diff(@path, @rev, @rev_to, bypass_cache: true) - (show_error_not_found; return) unless @diff - filename = "changeset_r#{@rev}" - filename << "_r#{@rev_to}" if @rev_to - send_data @diff.join, filename: "#{filename}.diff", - type: 'text/x-patch', - disposition: 'attachment' - else - @diff_type = params[:type] || User.current.pref[:diff_type] || 'inline' - @diff_type = 'inline' unless %w[inline sbs].include?(@diff_type) - - # Save diff type as user preference - if User.current.logged? && @diff_type != User.current.pref[:diff_type] - User.current.pref[:diff_type] = @diff_type - User.current.preference.save - end - @cache_key = "repositories/diff/#{@repository.id}/" + - Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}-#{current_language}") - unless read_fragment(@cache_key) - @diff = @repository.diff(@path, @rev, @rev_to) - unless @diff - show_error_not_found - return - end - end - - @changeset = @repository.find_changeset_by_name(@rev) - @changeset_to = @rev_to ? @repository.find_changeset_by_name(@rev_to) : nil - @diff_format_revisions = @repository.diff_format_revisions(@changeset, @changeset_to) - render :diff, formats: :html - end - end - end - end -end - -unless RepositoriesController.included_modules.include?(RedmineGitHosting::Patches::RepositoriesControllerPatch) - RepositoriesController.send(:prepend, RedmineGitHosting::Patches::RepositoriesControllerPatch) -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/repositories_helper_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/repositories_helper_patch.rb deleted file mode 100644 index 1054338..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/repositories_helper_patch.rb +++ /dev/null @@ -1,17 +0,0 @@ -require_dependency 'repositories_helper' - -module RedmineGitHosting - module Patches - module RepositoriesHelperPatch - def xitolite_field_tags(form, repository) - encoding_field(form, repository) + - create_readme_field(form, repository) + - enable_git_annex_field(form, repository) - end - end - end -end - -unless RepositoriesHelper.included_modules.include?(RedmineGitHosting::Patches::RepositoriesHelperPatch) - RepositoriesHelper.prepend RedmineGitHosting::Patches::RepositoriesHelperPatch -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/repository_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/repository_patch.rb deleted file mode 100644 index 1eddb11..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/repository_patch.rb +++ /dev/null @@ -1,16 +0,0 @@ -require_dependency 'repository' - -module RedmineGitHosting - module Patches - module RepositoryPatch - # This is the (possibly non-unique) basename for the Gitolite repository - def redmine_name - identifier.presence || project.identifier - end - end - end -end - -unless Repository.included_modules.include?(RedmineGitHosting::Patches::RepositoryPatch) - Repository.prepend RedmineGitHosting::Patches::RepositoryPatch -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/roles_controller_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/roles_controller_patch.rb deleted file mode 100644 index f16655d..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/roles_controller_patch.rb +++ /dev/null @@ -1,40 +0,0 @@ -require_dependency 'roles_controller' - -module RedmineGitHosting - module Patches - module RolesControllerPatch - include RedmineGitHosting::GitoliteAccessor::Methods - - def create - super - call_gitolite('created') - end - - def update - super - call_gitolite('modified') - end - - def destroy - super - call_gitolite('deleted') - end - - def permissions - super - call_gitolite('modified') if request.post? - end - - private - - def call_gitolite(message) - options = { message: "Role has been #{message}, resync all projects (active or closed)..." } - gitolite_accessor.update_projects('active_or_closed', options) - end - end - end -end - -unless RolesController.included_modules.include?(RedmineGitHosting::Patches::RolesControllerPatch) - RolesController.prepend RedmineGitHosting::Patches::RolesControllerPatch -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/setting_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/setting_patch.rb deleted file mode 100644 index 070d2aa..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/setting_patch.rb +++ /dev/null @@ -1,25 +0,0 @@ -require_dependency 'setting' - -module RedmineGitHosting - module Patches - module SettingPatch - def self.prepended(base) - class << base - prepend ClassMethods - end - end - - module ClassMethods - def check_cache - settings_updated_on = Setting.maximum(:updated_on) - if settings_updated_on && @cached_cleared_on <= settings_updated_on - clear_cache - RedmineGitHosting::Config.check_cache - end - end - end - end - end -end - -Setting.prepend RedmineGitHosting::Patches::SettingPatch unless Setting.included_modules.include?(RedmineGitHosting::Patches::SettingPatch) diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/settings_controller_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/settings_controller_patch.rb deleted file mode 100644 index 06c7dae..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/settings_controller_patch.rb +++ /dev/null @@ -1,76 +0,0 @@ -require_dependency 'settings_controller' - -module RedmineGitHosting - module Patches - module SettingsControllerPatch - def self.prepended(base) - base.class_eval do - helper :git_hosting - helper :gitolite_plugin_settings - end - end - - def authors - @plugin = Redmine::Plugin.find(params[:id]) - return render_404 unless @plugin.id == :redmine_git_hosting - - @authors = RedmineGitHosting.authors - render layout: false - end - - def install_gitolite_hooks - @plugin = Redmine::Plugin.find(params[:id]) - return render_404 unless @plugin.id == :redmine_git_hosting - - @gitolite_checks = RedmineGitHosting::Config.install_hooks! - end - - def plugin - @plugin = Redmine::Plugin.find(params[:id]) - return super unless @plugin.id == :redmine_git_hosting - - if request.post? - handle_settings_update - redirect_to plugin_settings_path(@plugin) - else - @partial = @plugin.settings[:partial] - @settings = Setting.send "plugin_#{@plugin.id}" - end - end - - private - - def handle_settings_update - # Create FormObject - settings_form = PluginSettingsForm.new(@plugin) - - # Strip *rescue* hash from params as we don't want to save them - options = params[:settings].delete(:rescue) { {} } - - # Validate form - if settings_form.submit(params[:settings]) - # Backup old settings - old_settings = Setting.send("plugin_#{@plugin.id}") - - # Save settings for real - Setting.send "plugin_#{@plugin.id}=", settings_form.params - - # Execute post actions - execute_post_actions(old_settings, options) - - flash[:notice] = l(:notice_successful_update) - else - flash[:error] = settings_form.errors.full_messages.join('
') - end - end - - def execute_post_actions(old_settings, opts = {}) - Settings::Apply.call(old_settings, opts) - end - end - end -end - -unless SettingsController.included_modules.include?(RedmineGitHosting::Patches::SettingsControllerPatch) - SettingsController.prepend RedmineGitHosting::Patches::SettingsControllerPatch -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/sys_controller_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/sys_controller_patch.rb deleted file mode 100644 index 427ddb3..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/sys_controller_patch.rb +++ /dev/null @@ -1,23 +0,0 @@ -require_dependency 'sys_controller' - -module RedmineGitHosting - module Patches - module SysControllerPatch - include RedmineGitHosting::GitoliteAccessor::Methods - - def fetch_changesets - # Flush GitCache - gitolite_accessor.flush_git_cache - - super - - # Purge RecycleBin - gitolite_accessor.purge_recycle_bin - end - end - end -end - -unless SysController.included_modules.include?(RedmineGitHosting::Patches::SysControllerPatch) - SysController.prepend RedmineGitHosting::Patches::SysControllerPatch -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/user_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/user_patch.rb deleted file mode 100644 index 32d37be..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/user_patch.rb +++ /dev/null @@ -1,89 +0,0 @@ -require_dependency 'user' - -module RedmineGitHosting - module Patches - module UserPatch - def self.prepended(base) - base.class_eval do - # Virtual attribute - attr_accessor :status_has_changed - - # Relations - has_many :gitolite_public_keys, dependent: :destroy - - has_many :protected_branches_members, dependent: :destroy, foreign_key: :principal_id - has_many :protected_branches, through: :protected_branches_members - - # Callbacks - after_save :check_if_status_changed - end - end - - # Returns a unique identifier for this user to use for gitolite keys. - # As login names may change (i.e., user renamed), we use the user id - # with its login name as a prefix for readibility. - def gitolite_identifier - identifier = [RedmineGitHosting::Config.gitolite_identifier_prefix, stripped_login] - identifier.concat(['_', id]) unless RedmineGitHosting::Config.gitolite_identifier_strip_user_id? - identifier.join - end - - def gitolite_projects - projects.uniq.select { |p| p.gitolite_repos.any? } - end - - # Syntaxic sugar - def status_has_changed? - status_has_changed - end - - def allowed_to_manage_repository?(repository) - !roles_for_project(repository.project).select { |role| role.allowed_to?(:manage_repository) }.empty? - end - - def allowed_to_commit?(repository) - allowed_to?(:commit_access, repository.project) - end - - def allowed_to_clone?(repository) - allowed_to?(:view_changesets, repository.project) - end - - def allowed_to_create_ssh_keys? - allowed_to?(:create_gitolite_ssh_key, nil, global: true) - end - - def allowed_to_download?(repository) - git_allowed_to?(:download_git_revision, repository) - end - - def git_allowed_to?(permission, repository) - if repository.project.active? - allowed_to?(permission, repository.project) - else - allowed_to?(permission, nil, global: true) - end - end - - private - - # This is Rails method : _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_status_changed - self.status_has_changed = if status_changed? - true - else - false - end - end - - def stripped_login - login.underscore.gsub(/[^0-9a-zA-Z]/, '_') - end - end - end -end - -User.prepend RedmineGitHosting::Patches::UserPatch unless User.included_modules.include?(RedmineGitHosting::Patches::UserPatch) diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/users_controller_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/users_controller_patch.rb deleted file mode 100644 index bac1d54..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/users_controller_patch.rb +++ /dev/null @@ -1,74 +0,0 @@ -require_dependency 'users_controller' - -module RedmineGitHosting - module Patches - module UsersControllerPatch - include RedmineGitHosting::GitoliteAccessor::Methods - - def self.prepended(base) - base.class_eval do - helper :gitolite_public_keys - helper :git_hosting - helper :git_hosting_users - end - end - - def edit - # Set public key values for view - set_public_key_values - super - end - - def update - # Set public key values for view (in case of invalid form) - set_public_key_values - super - - # Update projects if needed - update_projects if @user.status_has_changed? - end - - def destroy - # Build SSH keys list before user destruction. - ssh_keys_list = ssh_keys_to_destroy - - # Destroy user - super - - # Destroy SSH keys - destroy_ssh_keys(ssh_keys_list) - end - - private - - # Add in values for viewing public keys: - def set_public_key_values - @gitolite_user_keys = @user.gitolite_public_keys.user_key.order(:title, :created_at) - @gitolite_deploy_keys = @user.gitolite_public_keys.deploy_key.order(:title, :created_at) - end - - def update_projects - gitolite_accessor.update_projects(projects_to_update, message: "Status of '#{@user.login}' has changed, update projects") - end - - def projects_to_update - @user.gitolite_projects.map(&:id) - end - - def ssh_keys_to_destroy - @user.gitolite_public_keys.map(&:data_for_destruction) - end - - def destroy_ssh_keys(ssh_keys_list) - RedmineGitHosting.logger.info("User '#{@user.login}' has been deleted from Redmine, delete membership and SSH keys !") - ssh_keys_list.each do |ssh_key| - gitolite_accessor.destroy_ssh_key(ssh_key) - end - end - end - end -end - -unless UsersController.included_modules.include?(RedmineGitHosting::Patches::UsersControllerPatch) - UsersController.prepend RedmineGitHosting::Patches::UsersControllerPatch -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/watchers_controller_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/watchers_controller_patch.rb deleted file mode 100644 index bb4c146..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/watchers_controller_patch.rb +++ /dev/null @@ -1,42 +0,0 @@ -require_dependency 'watchers_controller' - -module RedmineGitHosting - module Patches - module WatchersControllerPatch - include RedmineGitHosting::GitoliteAccessor::Methods - - def create - super - update_repository(@watched) - end - - def destroy - super - update_repository(@watched) - end - - def watch - super - update_repository(@watchables.first) - end - - def unwatch - super - update_repository(@watchables.first) - end - - private - - def update_repository(repo) - return unless repo.is_a?(Repository::Xitolite) - - options = { message: "Watcher changes on repository '#{repo}', update!" } - gitolite_accessor.update_repository(repo, options) - end - end - end -end - -unless WatchersController.included_modules.include?(RedmineGitHosting::Patches::WatchersControllerPatch) - WatchersController.prepend RedmineGitHosting::Patches::WatchersControllerPatch -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/watchers_helper_patch.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/watchers_helper_patch.rb deleted file mode 100644 index 75ba31d..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/patches/watchers_helper_patch.rb +++ /dev/null @@ -1,51 +0,0 @@ -require_dependency 'watchers_helper' - -# This patch fix http://www.redmine.org/issues/12348 - -module RedmineGitHosting - module Patches - module WatchersHelperPatch - def self.prepended(base) - base.class_eval do - alias_method :watcher_css_without_git_hosting, :watcher_css - alias_method :watcher_css, :watcher_css_with_git_hosting - - alias_method :watchers_list_without_git_hosting, :watchers_list - alias_method :watchers_list, :watchers_list_with_git_hosting - end - end - - def watcher_css_with_git_hosting(objects) - watcher_css_without_git_hosting(objects).tr '/', '-' - end - - def watchers_list_with_git_hosting(object) - remove_allowed = User.current.allowed_to? "delete_#{object.class.name.underscore}_watchers".tr('/', '_').to_sym, object.project - content = ''.html_safe - object.watcher_users.preload(:email_address).each do |user| - s = ''.html_safe - s << avatar(user, size: '16').to_s - s << link_to_user(user, class: 'user') - if remove_allowed - url = { controller: 'watchers', - action: 'destroy', - object_type: object.class.to_s.underscore, - object_id: object.id, - user_id: user } - s << ' ' - s << link_to(l(:button_delete), url, - remote: true, method: 'delete', - class: 'delete icon-only icon-del', - title: l(:button_delete)) - end - content << tag.li(s, class: "user-#{user.id}") - end - content.present? ? tag.ul(content, class: 'watchers') : content - end - end - end -end - -unless WatchersHelper.included_modules.include?(RedmineGitHosting::Patches::WatchersHelperPatch) - WatchersHelper.prepend RedmineGitHosting::Patches::WatchersHelperPatch -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugin_author.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugin_author.rb deleted file mode 100644 index 928c351..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugin_author.rb +++ /dev/null @@ -1,17 +0,0 @@ -module RedmineGitHosting - class PluginAuthor - attr_reader :author - - def initialize(author) - @author = author - end - - def name - RedmineGitHosting::Utils::Git.author_name(author) - end - - def email - RedmineGitHosting::Utils::Git.author_email(author).downcase - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins.rb deleted file mode 100644 index 99ce078..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins.rb +++ /dev/null @@ -1,13 +0,0 @@ -module RedmineGitHosting - module Plugins - extend self - - def execute(step, repository, opts = {}) - Plugins::GitolitePlugin.all_plugins.each do |plugin| - plugin.new(repository, opts).send(step) if plugin.method_defined?(step) - end - rescue => e - RedmineGitHosting.logger.error e.message - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/extenders/base_extender.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/extenders/base_extender.rb deleted file mode 100644 index b587ef2..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/extenders/base_extender.rb +++ /dev/null @@ -1,24 +0,0 @@ -module RedmineGitHosting::Plugins::Extenders - class BaseExtender < RedmineGitHosting::Plugins::GitolitePlugin - attr_reader :repository, :recovered, :gitolite_repo_name, :gitolite_repo_path, :git_default_branch, :options - - def initialize(repository, options = {}) - @repository = repository - @recovered = options.delete(:recovered) { false } - @gitolite_repo_name = repository.gitolite_repository_name - @gitolite_repo_path = repository.gitolite_repository_path - @git_default_branch = repository.git_default_branch - @options = options - end - - private - - def recovered? - recovered - end - - def installable? - false - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/extenders/branch_updater.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/extenders/branch_updater.rb deleted file mode 100644 index 9453aea..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/extenders/branch_updater.rb +++ /dev/null @@ -1,34 +0,0 @@ -module RedmineGitHosting::Plugins::Extenders - class BranchUpdater < BaseExtender - attr_reader :update_default_branch - - def initialize(*args) - super - @update_default_branch = options.delete(:update_default_branch) { false } - end - - def post_update - # Update default branch if needed - do_update_default_branch if update_default_branch? - end - - private - - def update_default_branch? - Additionals.true? update_default_branch - end - - def do_update_default_branch - sudo_git('symbolic-ref', 'HEAD', new_default_branch) - rescue RedmineGitHosting::GitHosting::GitHostingException - logger.error("Error while updating default branch for repository '#{gitolite_repo_name}'") - else - logger.info("Default branch successfully updated for repository '#{gitolite_repo_name}'") - repository.empty_cache! - end - - def new_default_branch - "refs/heads/#{git_default_branch}" - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/extenders/config_key_deletor.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/extenders/config_key_deletor.rb deleted file mode 100644 index 85ea1fc..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/extenders/config_key_deletor.rb +++ /dev/null @@ -1,25 +0,0 @@ -module RedmineGitHosting::Plugins::Extenders - class ConfigKeyDeletor < BaseExtender - attr_reader :delete_git_config_key - - def initialize(*args) - super - @delete_git_config_key = options.delete(:delete_git_config_key) { '' } - end - - def post_update - # Delete hook param if needed - delete_hook_param if delete_git_config_key.present? - end - - private - - def delete_hook_param - sudo_git('config', '--local', '--unset', delete_git_config_key) - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error("Error while deleting Git config key '#{delete_git_config_key}' for repository '#{gitolite_repo_name}'") - else - logger.info("Git config key '#{delete_git_config_key}' successfully deleted for repository '#{gitolite_repo_name}'") - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/extenders/git_annex_creator.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/extenders/git_annex_creator.rb deleted file mode 100644 index 1007159..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/extenders/git_annex_creator.rb +++ /dev/null @@ -1,42 +0,0 @@ -module RedmineGitHosting::Plugins::Extenders - class GitAnnexCreator < BaseExtender - attr_reader :enable_git_annex - - def initialize(*args) - super - @enable_git_annex = options.delete(:enable_git_annex) { false } - end - - def post_create - return unless installable? - - if !git_annex_installed? - install_git_annex - else - logger.warn("GitAnnex already exists in path '#{gitolite_repo_path}'") - end - end - - private - - def installable? - enable_git_annex? && !recovered? - end - - def enable_git_annex? - Additionals.true? enable_git_annex - end - - def git_annex_installed? - directory_exists?(File.join(gitolite_repo_path, 'annex')) - end - - def install_git_annex - sudo_git('annex', 'init') - rescue RedmineGitHosting::Error::GitoliteCommandException - logger.error("Error while enabling GitAnnex for repository '#{gitolite_repo_name}'") - else - logger.info("GitAnnex successfully enabled for repository '#{gitolite_repo_name}'") - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/extenders/readme_creator.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/extenders/readme_creator.rb deleted file mode 100644 index 4080090..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/extenders/readme_creator.rb +++ /dev/null @@ -1,102 +0,0 @@ -require 'rugged' - -module RedmineGitHosting::Plugins::Extenders - class ReadmeCreator < BaseExtender - attr_reader :create_readme_file - - def initialize(*args) - super - @create_readme_file = options.delete(:create_readme_file) { false } - end - - def post_create - if repository_empty? - do_create_readme_file - else - logger.warn("Repository is not empty, cannot create README file in path '#{gitolite_repo_path}'") - end if installable? - end - - private - - def installable? - create_readme_file? && !recovered? - end - - def create_readme_file? - Additionals.true? create_readme_file - end - - def do_create_readme_file - logger.info("Creating README file for repository '#{gitolite_repo_name}'") - temp_dir = Dir.mktmpdir - - begin - ## Clone repository - repo = clone_repo(temp_dir) - - ## Create file - index = create_file(repo) - - ## Create commit - create_commit(repo, index) - - ## Push - push_commit(repo) - rescue => e - logger.error("Error while creating README file for repository '#{gitolite_repo_name}'") - logger.error(e.message) - else - logger.info('README file successfully created.') - ensure - FileUtils.rm_rf temp_dir - end - end - - def clone_repo(temp_dir) - Rugged::Repository.clone_at(repository.ssh_url, temp_dir, credentials: credentials) - end - - def create_file(repo) - oid = repo.write("## #{gitolite_repo_name}", :blob) - index = repo.index - index.add(path: 'README.md', oid: oid, mode: 0100644) - index - end - - def create_commit(repo, index) - commit_tree = index.write_tree(repo) - Rugged::Commit.create(repo, - author: commit_author, - committer: commit_author, - message: 'Add README file', - parents: repo.empty? ? [] : [repo.head.target].compact, - tree: commit_tree, - update_ref: 'HEAD') - end - - def push_commit(repo) - repo.push('origin', [remote_branch], credentials: credentials) - end - - def remote_branch - "refs/heads/#{git_default_branch}" - end - - def credentials - Rugged::Credentials::SshKey.new( - username: RedmineGitHosting::Config.gitolite_user, - publickey: RedmineGitHosting::Config.gitolite_ssh_public_key, - privatekey: RedmineGitHosting::Config.gitolite_ssh_private_key - ) - end - - def commit_author - @commit_author ||= { - email: RedmineGitHosting::Config.git_config_username, - name: RedmineGitHosting::Config.git_config_email, - time: Time.now - } - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/gitolite_plugin.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/gitolite_plugin.rb deleted file mode 100644 index bb1ee55..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/gitolite_plugin.rb +++ /dev/null @@ -1,58 +0,0 @@ -module RedmineGitHosting::Plugins - class GitolitePlugin - class << self - def plugins - @plugins ||= [] - end - - def all_plugins - sweepers + extenders - end - - def sweepers - plugins.select { |p| p.name.demodulize == 'BaseSweeper' }.first.subclasses - end - - def extenders - plugins.select { |p| p.name.demodulize == 'BaseExtender' }.first.subclasses - end - - def inherited(klass) - @plugins ||= [] - @plugins << klass - end - end - - private - - def logger - RedmineGitHosting.logger - end - - def repository_empty? - RedmineGitHosting::Commands.sudo_repository_empty?(gitolite_repo_path) - end - - def directory_exists?(dir) - RedmineGitHosting::Commands.sudo_dir_exists?(dir) - end - - def sudo_git(*params) - cmd = RedmineGitHosting::Commands.sudo_git_args_for_repo(gitolite_repo_path, git_args).concat(params) - RedmineGitHosting::Commands.capture(cmd, git_opts) - end - - # You may override this method to prepend args like environment variables - # to the git command. - # - def git_args - [] - end - - # You may override this method to pass opts to Open3.capture. - # - def git_opts - {} - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/sweepers/base_sweeper.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/sweepers/base_sweeper.rb deleted file mode 100644 index 81e5c8e..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/sweepers/base_sweeper.rb +++ /dev/null @@ -1,19 +0,0 @@ -module RedmineGitHosting::Plugins::Sweepers - class BaseSweeper < RedmineGitHosting::Plugins::GitolitePlugin - attr_reader :repository_data, :gitolite_repo_name, :gitolite_repo_path, :delete_repository, :git_cache_id - - def initialize(repository_data, _options = {}) - @repository_data = repository_data - @gitolite_repo_name = repository_data[:repo_name] - @gitolite_repo_path = repository_data[:repo_path] - @delete_repository = repository_data[:delete_repository] - @git_cache_id = repository_data[:git_cache_id] - end - - private - - def delete_repository? - Additionals.true? delete_repository - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/sweepers/repository_deletor.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/sweepers/repository_deletor.rb deleted file mode 100644 index 6772394..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/plugins/sweepers/repository_deletor.rb +++ /dev/null @@ -1,26 +0,0 @@ -module RedmineGitHosting::Plugins::Sweepers - class RepositoryDeletor < BaseSweeper - def post_delete - # Delete hook param if needed - move_repository_to_recycle if delete_repository? - remove_git_cache - end - - private - - def move_repository_to_recycle - if repository_data.is_a?(Hash) - RedmineGitHosting::RecycleBin.move_object_to_recycle(repository_data[:repo_name], repository_data[:repo_path]) - elsif repository_data.is_a?(Array) - repository_data.each do |object_data| - RedmineGitHosting::RecycleBin.move_object_to_recycle(object_data[:repo_name], object_data[:repo_path]) - end - end - end - - def remove_git_cache - logger.info("Clean cache for repository '#{gitolite_repo_name}'") - RedmineGitHosting::Cache.clear_cache_for_repository(git_cache_id) - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/recycle_bin.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/recycle_bin.rb deleted file mode 100644 index e80284c..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/recycle_bin.rb +++ /dev/null @@ -1,35 +0,0 @@ -module RedmineGitHosting - module RecycleBin - extend self - - def content - recycle_bin.content - end - - def delete_expired_content(expiration_time = default_expiration_time) - recycle_bin.delete_expired_content(expiration_time) - end - - def delete_content(content_list = []) - recycle_bin.delete_content(content_list) - end - - def move_object_to_recycle(object_name, source_path) - recycle_bin.move_object_to_recycle(object_name, source_path) - end - - def restore_object_from_recycle(object_name, target_path) - recycle_bin.restore_object_from_recycle(object_name, target_path) - end - - private - - def default_expiration_time - RedmineGitHosting::Config.gitolite_recycle_bin_expiration_time - end - - def recycle_bin - @recycle_bin ||= RecycleBin::Manager.new(RedmineGitHosting::Config.recycle_bin_dir) - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/recycle_bin/deletable_item.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/recycle_bin/deletable_item.rb deleted file mode 100644 index 4375424..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/recycle_bin/deletable_item.rb +++ /dev/null @@ -1,33 +0,0 @@ -module RedmineGitHosting - module RecycleBin - class DeletableItem - include RecycleBin::ItemBase - - def move!(source_path) - if !directory_exists?(source_path) - logger.warn("Source directory does not exist '#{source_path}', exiting!") - false - else - logger.info("Moving '#{object_name}' to Recycle Bin...") - logger.debug("'#{source_path}' => '#{target_path}'") - do_move(source_path) - end - end - - def target_path - @target_path ||= File.join(recycle_bin_dir, "#{Time.now.to_i.to_s}#{TRASH_DIR_SEP}#{trash_name}.git") - end - - private - - def do_move(source_path) - RedmineGitHosting::Commands.sudo_move(source_path, target_path) - logger.info('Done !') - true - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error("Attempt to move '#{source_path}' to Recycle Bin failed !") - false - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/recycle_bin/item.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/recycle_bin/item.rb deleted file mode 100644 index 7017bf2..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/recycle_bin/item.rb +++ /dev/null @@ -1,31 +0,0 @@ -module RedmineGitHosting - module RecycleBin - class Item - attr_reader :path - - def initialize(path) - @path = path - end - - def size - RedmineGitHosting::Commands.sudo_get_dir_size(path) - end - - def destroy! - logger.info("Deleting '#{path}' from Recycle Bin") - begin - RedmineGitHosting::Commands.sudo_rmdir(path, true) - logger.info('Done !') - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error("Errors while deleting '#{path}' from Recycle Bin !") - end - end - - private - - def logger - RedmineGitHosting.logger - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/recycle_bin/item_base.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/recycle_bin/item_base.rb deleted file mode 100644 index 9b60f48..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/recycle_bin/item_base.rb +++ /dev/null @@ -1,36 +0,0 @@ -module RedmineGitHosting - module RecycleBin - module ItemBase - TRASH_DIR_SEP = '__' - - attr_reader :object_name - attr_reader :recycle_bin_dir - - def initialize(recycle_bin_dir, object_name) - @recycle_bin_dir = recycle_bin_dir - @object_name = object_name - end - - def trash_name - object_name.gsub(/\//, TRASH_DIR_SEP) - end - - private - - def logger - RedmineGitHosting.logger - end - - def directory_exists?(dir) - RedmineGitHosting::Commands.sudo_dir_exists?(dir) - end - - def find_trashed_object(regex) - RedmineGitHosting::Commands.sudo_capture('find', recycle_bin_dir, '-type', 'd', '-regex', regex, '-prune', '-print') - .chomp - .split("\n") - .sort { |x, y| y <=> x } - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/recycle_bin/manager.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/recycle_bin/manager.rb deleted file mode 100644 index e9e2af9..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/recycle_bin/manager.rb +++ /dev/null @@ -1,71 +0,0 @@ -module RedmineGitHosting - module RecycleBin - class Manager - attr_reader :recycle_bin_dir - - def initialize(recycle_bin_dir) - @recycle_bin_dir = recycle_bin_dir - create_recycle_bin_directory - end - - def content - load_recycle_bin_content(get_recycle_bin_content) - rescue RedmineGitHosting::Error::GitoliteCommandException => e - [] - end - - def delete_expired_content(expiration_time) - expired_content = load_recycle_bin_content(get_expired_content(expiration_time)) - logger.info("Removing #{expired_content.length} expired objects from Recycle Bin :") - expired_content.map(&:destroy!) - rescue RedmineGitHosting::Error::GitoliteCommandException => e - [] - end - - def delete_content(content_list = []) - load_recycle_bin_content(content_list).map(&:destroy!) - end - - def move_object_to_recycle(object_name, source_path) - RedmineGitHosting::RecycleBin::DeletableItem.new(recycle_bin_dir, object_name).move!(source_path) - end - - def restore_object_from_recycle(object_name, target_path) - RedmineGitHosting::RecycleBin::RestorableItem.new(recycle_bin_dir, object_name).restore!(target_path) - end - - private - - def logger - RedmineGitHosting.logger - end - - def load_recycle_bin_content(content_list = []) - content_list.map { |dir| RedmineGitHosting::RecycleBin::Item.new(dir) } - end - - def get_recycle_bin_content - RedmineGitHosting::Commands.sudo_capture('find', recycle_bin_dir, - '-type', 'd', '-regex', '.*\.git', '-prune', '-print') - .chomp - .split("\n") - end - - def get_expired_content(expiration_time) - RedmineGitHosting::Commands.sudo_capture('find', recycle_bin_dir, - '-type', 'd', '-regex', '.*\.git', '-cmin', "+#{expiration_time}", '-prune', '-print') - .chomp - .split("\n") - end - - def create_recycle_bin_directory - RedmineGitHosting::Commands.sudo_mkdir_p(recycle_bin_dir) - RedmineGitHosting::Commands.sudo_chmod('770', recycle_bin_dir) - true - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error("Attempt to create recycle bin directory '#{recycle_bin_dir}' failed !") - false - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/recycle_bin/restorable_item.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/recycle_bin/restorable_item.rb deleted file mode 100644 index 45f9b88..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/recycle_bin/restorable_item.rb +++ /dev/null @@ -1,56 +0,0 @@ -module RedmineGitHosting - module RecycleBin - class RestorableItem - include RecycleBin::ItemBase - - def restore!(target_path) - if trashed_object.nil? - logger.warn("No matching item found for '#{object_name}' in Recycle Bin, exiting !") - false - else - logger.info("Restoring '#{object_name}' from Recycle Bin...") - logger.debug("'#{trashed_object}' => '#{target_path}'") - create_parent_dir(target_path) && do_restore(target_path) - end - end - - def source_path - File.join(recycle_bin_dir, "[0-9]+#{TRASH_DIR_SEP}#{trash_name}.git") - end - - # Pull up any matching repositories. Sort them (beginning is representation of time) - # - def trashed_objects - begin - find_trashed_object(source_path) - rescue RedmineGitHosting::Error::GitoliteCommandException => e - [] - end - end - - def trashed_object - trashed_objects.first - end - - private - - def create_parent_dir(target_path) - logger.info("Creating parent dir : '#{File.dirname(target_path)}'") - RedmineGitHosting::Commands.sudo_mkdir_p(File.dirname(target_path)) - true - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error("Attempt to create parent dir for '#{trashed_object}' failed !") - false - end - - def do_restore(target_path) - RedmineGitHosting::Commands.sudo_move(trashed_object, target_path) - logger.info('Done !') - true - rescue RedmineGitHosting::Error::GitoliteCommandException => e - logger.error("Attempt to recover '#{trashed_object}' from Recycle Bin failed !") - false - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/redcarpet_filter.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/redcarpet_filter.rb deleted file mode 100644 index 4ea55aa..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/redcarpet_filter.rb +++ /dev/null @@ -1,47 +0,0 @@ -require 'html/pipeline/filter' -require 'html/pipeline/text_filter' -require 'redcarpet' -require 'rouge' -require 'rouge/plugins/redcarpet' - -module RedmineGitHosting - class HTMLwithRouge < Redcarpet::Render::HTML - include Rouge::Plugins::Redcarpet - end - - class RedcarpetFilter < HTML::Pipeline::TextFilter - def initialize(text, context = nil, result = nil) - super text, context, result - @text = @text.delete "\r" - end - - # Convert Markdown to HTML using the best available implementation - # and convert into a DocumentFragment. - # - def call - html = self.class.renderer.render(@text) - html.rstrip! - html - end - - def self.renderer - @renderer ||= begin - Redcarpet::Markdown.new(HTMLwithRouge, markdown_options) - end - end - - def self.markdown_options - @markdown_options ||= { - fenced_code_blocks: true, - lax_spacing: true, - strikethrough: true, - autolink: true, - tables: true, - underline: true, - highlight: true - }.freeze - end - - private_class_method :markdown_options - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/redmine_plugin_loader.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/redmine_plugin_loader.rb deleted file mode 100644 index 1105885..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/redmine_plugin_loader.rb +++ /dev/null @@ -1,139 +0,0 @@ -module RedmineGitHosting - module RedminePluginLoader - extend self - - def set_plugin_name(name) - @name ||= name - end - - def plugin_name - @name - end - - def set_autoloaded_paths(*dirs) - @autoloaded_paths ||= dirs.map { |dir| plugin_app_dir(*dir) } - end - - def autoloaded_paths - @autoloaded_paths - end - - def authors - load_authors_file - end - - def authors_file - plugin_dir('AUTHORS') - end - - def settings - default_settings.merge(global_settings).merge(local_settings) - end - - def global_settings - load_setting_file(global_settings_file) - end - - def local_settings - load_setting_file(local_settings_file) - end - - def default_settings - load_setting_file(default_settings_file) - end - - def default_settings_file - plugin_lib_dir('default_settings.yml') - end - - def global_settings_file - Rails.root.join("#{plugin_name}.yml") - end - - def local_settings_file - plugin_dir('settings.yml') - end - - def plugin_patches_dir - plugin_lib_dir(plugin_name, 'patches') - end - - def plugin_hooks_dir - plugin_lib_dir(plugin_name, 'hooks') - end - - def plugin_locales_dir - plugin_conf_dir('locales', '**', '*.yml') - end - - def required_lib_dirs - plugin_lib_dir(plugin_name, '**', '*.rb') - end - - def plugin_dir(*dirs) - Rails.root.join('plugins', plugin_name, *dirs) - end - - def plugin_app_dir(*dirs) - plugin_dir('app', *dirs) - end - - def plugin_conf_dir(*dirs) - plugin_dir('config', *dirs) - end - - def plugin_lib_dir(*dirs) - plugin_dir('lib', *dirs) - end - - def plugin_spec_dir(*dirs) - plugin_dir('spec', *dirs) - end - - def load_plugin! - autoload_libs! - autoload_paths! - autoload_locales! - end - - private - - def load_setting_file(file) - return {} unless File.exist? file - - data = YAML.safe_load(ERB.new(IO.read(file)).result) || {} - data.symbolize_keys - end - - def load_authors_file - return [] unless File.exist? authors_file - - File.read(authors_file).split("\n").map { |a| RedmineGitHosting::PluginAuthor.new(a) } - end - - def hook_file?(file) - File.dirname(file) == plugin_hooks_dir.to_s - end - - def skip_lib_file?(file) - # Exclude Redmine Views Hooks from Rails loader to avoid multiple calls to hooks on reload in dev environment. - true if hook_file?(file) || (file.include?('journal_logger.rb') && !Object.const_defined?('Account')) - end - - def autoload_libs! - Dir.glob(required_lib_dirs).each do |file| - require_dependency file unless skip_lib_file?(file) - end - end - - def autoload_paths! - autoloaded_paths.each do |dir| - ActiveSupport::Dependencies.autoload_paths += [dir] if Dir.exist?(dir) - end - end - - def autoload_locales! - ::I18n.load_path += Dir.glob(plugin_locales_dir) - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/shell_redirector.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/shell_redirector.rb deleted file mode 100644 index f403a28..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/shell_redirector.rb +++ /dev/null @@ -1,327 +0,0 @@ -require 'stringio' - -module RedmineGitHosting - class ShellRedirector - # Redirector states - WAIT_TO_CHECK = 0 - RUNNING_SHELL = 1 - STRING_IO = 2 - DEAD = 3 - - class << self - def logger - RedmineGitHosting.logger - end - - # Rewritten version of caching functionality to accommodate Redmine 1.4+ - # When the shell is called with options[:write_stdin], then part of the - # argument on which caching is based is written to the input stream of the shell. - # Thus, we may need to wait for this write to occur before checking the cache. - # - # The basic mechanism here is a duck-typed IO stream (the ShellRedirector) which - # intercepts the output of Git and places it in the cache. In addition, this mechanism - # can intercept the stdin heading toward Git so as to have a complete key for examining - # the cache. - # - # Primary calling sequence is to use the "execute" method which will allocate a new - # ShellRedirector only if required. - # - # This is the primary interface: execute given command and send IO to block. - # - # *options[:write_stdin]* will derive caching key from data that block writes to io stream. - # - def execute(cmd_str, repo_id, options = {}, &block) - if !options[:write_stdin] && out = RedmineGitHosting::Cache.get_cache(repo_id, cmd_str) - # Simple case -- have cached result that depends only on cmd_str - block.call(out) - retio = out - status = nil - else - # Create redirector stream and call block - redirector = self.new(cmd_str, repo_id, options) - block.call(redirector) - retio, status = redirector.exit_shell - end - - if status && status.exitstatus.to_i != 0 - logger.error("Git exited with non-zero status : #{status.exitstatus} : #{cmd_str}") - raise Redmine::Scm::Adapters::XitoliteAdapter::ScmCommandAborted, - "Git exited with non-zero status : #{status.exitstatus} : #{cmd_str}" - end - - retio - end - end - - def initialize(cmd_str, repo_id, options = {}) - @cmd_str = cmd_str - @repo_id = repo_id - @options = options - @buffer = '' - @buffer_full = false - @extra_args = '' - @read_stream = nil - @status = nil - - if options[:write_stdin] - @state = WAIT_TO_CHECK - else - startup_shell - end - end - - def startup_shell - Thread.abort_on_exception = true - proxy_started = false - @wrap_thread = Thread.new(@cmd_str, @options) do |cmd_str, options| - if options[:write_stdin] - @retio = Redmine::Scm::Adapters::AbstractAdapter.shellout(cmd_str, options) do |io| - io.binmode - io.puts(@extra_args) - io.close_write - @read_stream = io - - proxy_started = true - - # Wait before closing io - Thread.stop - end - else - @retio = Redmine::Scm::Adapters::AbstractAdapter.shellout(cmd_str) do |io| - @read_stream = io - - proxy_started = true - - # Wait before closing io - Thread.stop - end - end - @status = $? - end - - # Wait until subthread gets far enough - while !proxy_started - Thread.pass - end - @state = RUNNING_SHELL - end - - def exit_shell - # If shell was running, kill off wrapper thread - if @state == RUNNING_SHELL - @wrap_thread.run - @wrap_thread.join - @state = DEAD - unless @buffer_full - # Insert result into cache - RedmineGitHosting::Cache.set_cache(@repo_id, @buffer, @cmd_str, @extra_args) - end - end - - [@retio, @status] - end - - # Catch any extra args placed into stdin. We explicitly code the - # output (write) functions here. Below, 'method_missing' traps the - # read functions (since there are a lot of them) and any control functions - # and dynamically defines them as needed. - # - def puts(*args) - @extra_args << args.join("\n") + "\n" - end - - def write(obj) - @extra_args << obj.to_s - end - - # Ignore this -- must handle it before we have chosen output stream - # - def binmode; end - - def close_write - cached = RedmineGitHosting::Cache.get_cache(@repo_id, @cmd_str, @extra_args) - if cached - @state = STRING_IO - @read_stream = @retio = cached - else - startup_shell - end - end - - def logger - RedmineGitHosting.logger - end - - # This class wraps a given enumerator and produces another one - # that logs all read data into the buffer. - # - class EnumerableRedirector - include Enumerable - - def initialize(enum, redirector) - @enum = enum - @redirector = redirector - end - - def each - return to_enum :each unless block_given? - - @enum.each do |value| - @redirector.add_to_buffer(value) - yield value - end - end - end - - def add_to_buffer(value) - return if @buffer_full - - if value.is_a?(Array) - value.each { |next_value| push_to_buffer(next_value) } - else - push_to_buffer(value) - end - end - - def push_to_buffer(value) - next_chunk = value.is_a?(Integer) ? value.chr : value - if @buffer.length + next_chunk.length <= RedmineGitHosting::Cache.max_cache_size - @buffer << next_chunk - else - @buffer_full = true - end - end - - ############################################### - # Duck-typing of an IO interface # - ############################################### - - def respond_to?(method) - io_method?(method) || super(method, *args, &block) - end - - def io_method?(method) - IO.instance_methods.map(&:to_sym).include?(method.to_sym) - end - - # On-the-fly compilation of any missing functions, including all of the - # read functions (with and without blocks), which we divert into the buffer - # for potential caching. Other functions are compiled as "proxies", which - # simply call the corresponding functions on the current read stream (@read_stream). - # In this way, we pretty much get a complete I/O interface which diverts the - # returns from reads. - # - # Note that missing I/O functions are of 3 classes here: - # 1) Those that take a block and/or return enumerators - # 2) Those that returns Array, String, or Integer - # 3) Everything else - # - # The little bit of trickery with "class_eval" below is to compile custom functions - # for each encountered missing function (so that method_missing only gets called - # once for each function. Note that we don't use define_method here, since - # Ruby 1.8 define_method doesn't work with blocks. - # - # This will handle IO methods only! - # - def method_missing(method, *args, &block) - return super(method, *args, &block) unless io_method?(method) - - # Shouldn't happen, but might be problem - if @read_stream.nil? - logger.error("Call to #{method} before IO-handlers wrapped.") - raise Redmine::Scm::Adapters::XitoliteAdapter::ScmCommandAborted, "Call to #{method} before IO-handlers wrapped." - end - - # Buffer up results from read operations. Proxy everything else directly to IO stream. - method_name = method.to_s - - if method_name =~ /^(each|bytes)/ - inject_enumerator_method(method) - elsif method_name =~ /^(get|read)/ - inject_read_method(method) - else - inject_proxy_method(method) - end - - # Call new function once - self.send(method, *args, &block) - end - - def inject_enumerator_method(method) - self.class.class_eval <<-EOF, __FILE__, __LINE__ - def #{method}(*args, &block) - if @state == RUNNING_SHELL - # Must Divert results into buffer. - if block_given? - @read_stream.#{method}(*args) do |value| - add_to_buffer(value) - block.call(value) - end - else - value = @read_stream.#{method}(*args) - EnumerableRedirector.new(value, self) - end - else - @read_stream.#{method}(*args, &block) - end - end - EOF - end - - def inject_read_method(method) - self.class.class_eval <<-EOF, __FILE__, __LINE__ - def #{method}(*args, &block) - value = @read_stream.#{method}(*args) - add_to_buffer(value) if @state == RUNNING_SHELL - value - end - EOF - end - - def inject_proxy_method(method) - self.class.class_eval <<-EOF, __FILE__, __LINE__ - def #{method}(*args, &block) - @read_stream.#{method}(*args, &block) - end - EOF - end - - ############################################################################## - # The following three functions are the generic versions of what is # - # currently "compiled" into function definitions above in missing_method(). # - ############################################################################## - - # Class #1 functions (Read functions with block/enumerator behavior) - # - def enumerator_diverter(method, *args, &block) - if @state == RUNNING_SHELL - # Must Divert results into buffer. - if block_given? - @read_stream.send(method, *args) do |value| - add_to_buffer(value) - block.call(value) - end - else - value = @read_stream.send(method, *args) - EnumerableRedirector.new(value, self) - end - else - @read_stream.send(method, *args, &block) - end - end - - # Class #2 functions (Return of Array, String, or Integer) - # - def normal_diverter(method, *args) - value = @read_stream.send(method, *args) - add_to_buffer(value) if @state == RUNNING_SHELL - value - end - - # Class #3 functions (Everything by read functions) - # - def simple_proxy(method, *args, &block) - @read_stream.send(method, *args, &block) - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/utils/crypto.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/utils/crypto.rb deleted file mode 100644 index 06aa77d..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/utils/crypto.rb +++ /dev/null @@ -1,17 +0,0 @@ -require 'securerandom' - -module RedmineGitHosting - module Utils - module Crypto - extend self - - def generate_secret(length) - length = length.to_i - secret = SecureRandom.base64(length * 2) - secret = secret.gsub(/[\=\_\-\+\/]/, '') - secret = secret.split(//).sample(length).join('') - secret - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/utils/exec.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/utils/exec.rb deleted file mode 100644 index bc9875d..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/utils/exec.rb +++ /dev/null @@ -1,39 +0,0 @@ -require 'open3' - -module RedmineGitHosting - module Utils - module Exec - extend self - - # Executes the given command and a list of parameters on the shell - # and returns the result. - # - # If the operation throws an exception or the operation yields a non-zero exit code - # we rethrow a +GitoliteCommandException+ with a meaningful error message. - def capture(command, args = [], opts = {}, &block) - merge_output = opts.delete(:merge_output) { false } - stdout, stderr, code = execute(command, args, opts, &block) - if code != 0 - error_msg = "Non-zero exit code #{code} for `#{command} #{args.join(" ")}`" - RedmineGitHosting.logger.debug(error_msg) - raise RedmineGitHosting::Error::GitoliteCommandException.new(command, error_msg) - end - - merge_output ? stdout + stderr : stdout - end - - # Executes the given command and a list of parameters on the shell - # and returns stdout, stderr, and the exit code. - # - # If the operation throws an exception or the operation we rethrow a - # +GitoliteCommandException+ with a meaningful error message. - def execute(command, args = [], opts = {}, &block) - Open3.capture3(command, *args, opts, &block) - rescue => e - error_msg = "Exception occured executing `#{command} #{args.join(" ")}` : #{e.message}" - RedmineGitHosting.logger.debug(error_msg) - raise RedmineGitHosting::Error::GitoliteCommandException.new(command, error_msg) - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/utils/git.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/utils/git.rb deleted file mode 100644 index 4a67fe6..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/utils/git.rb +++ /dev/null @@ -1,37 +0,0 @@ -module RedmineGitHosting - module Utils - module Git - extend self - - REF_COMPONENT_PART = '[\\.\\-\\w_\\*]+' - REF_COMPONENT_REGEX = /\A(refs\/)?((#{REF_COMPONENT_PART})\/)?(#{REF_COMPONENT_PART}(\/#{REF_COMPONENT_PART})*)\z/ - - # Parse a reference component. Two possibilities: - # - # 1) refs/type/name - # 2) name - # - def parse_refspec(spec) - parsed_refspec = spec.match(REF_COMPONENT_REGEX) - return nil if parsed_refspec.nil? - - if parsed_refspec[1] - # Should be first class. If no type component, return fail - { type: parsed_refspec[3], name: parsed_refspec[4] } if parsed_refspec[3] - elsif parsed_refspec[3] - { type: nil, name: "#{parsed_refspec[3]}/#{parsed_refspec[4]}" } - else - { type: nil, name: parsed_refspec[4] } - end - end - - def author_name(committer) - committer.gsub(/\A([^<]+)\s+.*\z/, '\1') - end - - def author_email(committer) - committer.gsub(/\A.*<([^>]+)>.*\z/, '\1') - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/utils/http.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/utils/http.rb deleted file mode 100644 index 1d14304..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/utils/http.rb +++ /dev/null @@ -1,88 +0,0 @@ -require 'json' -require 'net/http' -require 'net/https' -require 'uri' - -module RedmineGitHosting - module Utils - module Http - extend self - - def http_post(url, opts = {}) - data = opts.delete(:data) { {} } - data = serialize_data data - http, request = build_post_request url, data - send_http_request http, request - end - - def http_get(url, _opts = {}) - http, request = build_get_request url - send_http_request http, request - end - - def valid_url?(url) - uri = URI.parse(url) - uri.is_a?(URI::HTTP) - rescue URI::InvalidURIError - false - end - - private - - def serialize_data(data) - return data if data.empty? - - serialized = {} - data.each do |k, v| - serialized[k.to_s] = v.to_json - end - serialized - end - - def build_post_request(url, data) - uri, http = build_http_request url - request = Net::HTTP::Post.new uri.request_uri - request.basic_auth(uri.user, uri.password) if uri.user.present? && uri.password.present? - request.set_form_data data - [http, request] - end - - def build_get_request(url) - uri, http = build_http_request url - request = Net::HTTP::Get.new uri.request_uri - [http, request] - end - - def build_http_request(url) - uri = URI url - http = Net::HTTP.new uri.host, uri.port - if uri.scheme == 'https' - http.use_ssl = true - # @NOTE: do not allow requests with invalid certificates - # http.verify_mode = OpenSSL::SSL::VERIFY_NONE - end - [uri, http] - end - - def send_http_request(http, request) - message = '' - - begin - res = http.start { |openhttp| openhttp.request request } - if !res.is_a?(Net::HTTPSuccess) - message = "Return code : #{res.code} (#{res.message})." - failed = true - else - message = res.body - failed = false - end - rescue StandardError => e - message = "Exception : #{e.message}" - failed = true - end - - [failed, message] - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/utils/ssh.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/utils/ssh.rb deleted file mode 100644 index 93af9a6..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/utils/ssh.rb +++ /dev/null @@ -1,40 +0,0 @@ -module RedmineGitHosting - module Utils - module Ssh - extend self - - def ssh_fingerprint(key) - file = Tempfile.new('keytest') - file.write(key) - file.close - - begin - output = Utils::Exec.capture('ssh-keygen', ['-l', '-f', file.path]) - rescue RedmineGitHosting::Error::GitoliteCommandException => e - raise RedmineGitHosting::Error::InvalidSshKey, "Invalid Ssh Key : #{key}" - else - output.split[1] - ensure - file.unlink - end - end - - def sanitize_ssh_key(key) - # First -- let the first control char or space stand (to divide key type from key) - # Really, this is catching a special case in which there is a \n between type and key. - # Most common case turns first space back into space.... - key = key.sub(/[ \r\n\t]/, ' ') - - # Next, if comment divided from key by control char, let that one stand as well - # We can only tell this if there is an "=" in the key. So, won't help 1/3 times. - key = key.sub(/=[ \r\n\t]/, '= ') - - # Delete any remaining control characters.... - key = key.gsub(/[\a\r\n\t]/, '').strip - - # Return the sanitized key - key - end - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/validators.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/validators.rb deleted file mode 100644 index e277bb1..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/validators.rb +++ /dev/null @@ -1,64 +0,0 @@ -module RedmineGitHosting - module Validators - extend self - - # Validate a Git SSH urls - # ssh://git@redmine.example.org/project1/project2/project3/project4.git - # ssh://git@redmine.example.org:2222/project1/project2/project3/project4.git - # - GIT_SSH_URL_REGEX = /\A(ssh:\/\/)([\w\-\.@]+)(\:[\d]+)?([\w\/\-\.~]+)(\.git)?\z/i - - def valid_git_ssh_url?(url) - url.match(GIT_SSH_URL_REGEX) - end - - # Validate a Git refspec - # [+]: - # [+]refs//:refs// - # - GIT_REFSPEC_REGEX = /\A\+?([^:]*)(:([^:]*))?\z/.freeze - - def valid_git_refspec?(refspec) - refspec.match(GIT_REFSPEC_REGEX) - end - - def valid_git_refspec_path?(refspec) - refspec_parsed = valid_git_refspec?(refspec) - if refspec_parsed.nil? || !valid_refspec_path?(refspec_parsed[1]) || !valid_refspec_path?(refspec_parsed[3]) - raise RedmineGitHosting::Error::InvalidRefspec::BadFormat - elsif !refspec_parsed[1] || refspec_parsed[1] == '' - raise RedmineGitHosting::Error::InvalidRefspec::NullComponent - end - end - - # Allow null or empty components - # - def valid_refspec_path?(refspec) - !refspec || refspec == '' || RedmineGitHosting::Utils::Git.parse_refspec(refspec) ? true : false - end - - private_class_method :valid_refspec_path? - - # Validate a domain name with optional port - # redmine.example.net - # redmine.example.net:8080 - # - DOMAIN_REGEX = /\A[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)*(:\d+)?\z/i.freeze - - def valid_domain?(domain) - domain.match(DOMAIN_REGEX) - end - - def valid_email?(email) - email.match(URI::MailTo::EMAIL_REGEXP) - end - - # Validate that data passed through forms are boolean-like. - # - BOOLEAN_FIELDS = %w[true false 0 1].freeze - - def valid_boolean_field?(field) - BOOLEAN_FIELDS.include?(field) - end - end -end diff --git a/plugins/redmine_git_hosting/lib/redmine_git_hosting/version.rb b/plugins/redmine_git_hosting/lib/redmine_git_hosting/version.rb deleted file mode 100644 index 980cd3e..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_git_hosting/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module RedmineGitHosting - VERSION = '5.0.0'.freeze -end diff --git a/plugins/redmine_git_hosting/lib/redmine_menus.rb b/plugins/redmine_git_hosting/lib/redmine_menus.rb deleted file mode 100644 index ae8daf9..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_menus.rb +++ /dev/null @@ -1,4 +0,0 @@ -Redmine::MenuManager.map :admin_menu do |menu| - menu.push :redmine_git_hosting, { controller: 'settings', action: 'plugin', id: 'redmine_git_hosting' }, - caption: :redmine_git_hosting, html: { class: 'icon' } -end diff --git a/plugins/redmine_git_hosting/lib/redmine_permissions.rb b/plugins/redmine_git_hosting/lib/redmine_permissions.rb deleted file mode 100644 index d418ca4..0000000 --- a/plugins/redmine_git_hosting/lib/redmine_permissions.rb +++ /dev/null @@ -1,32 +0,0 @@ -Redmine::AccessControl.map do |main| - main.permission :create_gitolite_ssh_key, gitolite_public_keys: %i[index create destroy], require: :loggedin - - main.project_module :repository do |map| - map.permission :create_repository_mirrors, repository_mirrors: %i[new create] - map.permission :view_repository_mirrors, repository_mirrors: %i[indexshow] - map.permission :edit_repository_mirrors, repository_mirrors: %i[edit update destroy] - map.permission :push_repository_mirrors, repository_mirrors: [:push] - - map.permission :create_repository_post_receive_urls, repository_post_receive_urls: %i[new create] - map.permission :view_repository_post_receive_urls, repository_post_receive_urls: %i[index show] - map.permission :edit_repository_post_receive_urls, repository_post_receive_urls: %i[edit update destroy] - - map.permission :create_repository_deployment_credentials, repository_deployment_credentials: %i[new create] - map.permission :view_repository_deployment_credentials, repository_deployment_credentials: %i[index show] - map.permission :edit_repository_deployment_credentials, repository_deployment_credentials: %i[edit update destroy] - - map.permission :create_repository_git_config_keys, repository_git_config_keys: %i[new create] - map.permission :view_repository_git_config_keys, repository_git_config_keys: %i[index show] - map.permission :edit_repository_git_config_keys, repository_git_config_keys: %i[edit update destroy] - - map.permission :create_repository_protected_branches, repository_protected_branches: %i[new create] - map.permission :view_repository_protected_branches, repository_protected_branches: %i[index show] - map.permission :edit_repository_protected_branches, repository_protected_branches: %i[edit update destroy] - - map.permission :view_repository_xitolite_watchers, repositories: :show - map.permission :add_repository_xitolite_watchers, watchers: :create - map.permission :delete_repository_xitolite_watchers, watchers: :destroy - - map.permission :download_git_revision, download_git_revision: :index - end -end diff --git a/plugins/redmine_git_hosting/lib/tasks/ci_tools.rake b/plugins/redmine_git_hosting/lib/tasks/ci_tools.rake deleted file mode 100644 index c5aa511..0000000 --- a/plugins/redmine_git_hosting/lib/tasks/ci_tools.rake +++ /dev/null @@ -1,55 +0,0 @@ -namespace :redmine_git_hosting do - namespace :ci do - unless Rails.env.production? - RSpec::Core::RakeTask.new do |task| - task.rspec_opts = '--pattern plugins/redmine_git_hosting/spec/\*\*\{,/\*/\*\*\}/\*_spec.rb --color' - end - end - - desc 'Check unit tests results' - task check_unit_tests_results: [:environment] do - gitolite_admin_dir = RedmineGitHosting::Config.gitolite_admin_dir - gitolite_temp_dir = RedmineGitHosting::Config.gitolite_temp_dir - - puts '#####################' - puts 'TESTS RESULTS' - puts '' - puts "gitolite_temp_dir : #{gitolite_temp_dir}" - puts "gitolite_admin_dir : #{gitolite_admin_dir}" - puts '' - - ls_dir(gitolite_temp_dir) - ls_dir("#{gitolite_temp_dir}/git") - ls_dir("#{gitolite_temp_dir}/git/gitolite-admin.git") - - begin - repo = Rugged::Repository.new(gitolite_admin_dir) - puts "git repo work dir : #{repo.workdir}" - puts "git repo path : #{repo.path}" - puts '' - puts 'GIT STATUS :' - puts '------------' - puts %x[git --work-tree "#{repo.workdir}" --git-dir "#{repo.path}" status] - puts '' - puts 'GIT LOG :' - puts '---------' - puts %x[git --work-tree "#{repo.workdir}" --git-dir "#{repo.path}" log] - rescue => e - puts 'Error while getting tests results' - puts e.message - end - end - - task all: ['spec', 'check_unit_tests_results'] - - def ls_dir(dir) - puts "* ls -hal #{dir}" - puts %x[ls -hal "#{dir}"] - puts '' - end - end - - task default: 'redmine_git_hosting:ci:all' - task rspec: 'redmine_git_hosting:ci:all' - task test: 'redmine_git_hosting:ci:all' -end diff --git a/plugins/redmine_git_hosting/lib/tasks/migration_tools.rake b/plugins/redmine_git_hosting/lib/tasks/migration_tools.rake deleted file mode 100644 index 53a75f9..0000000 --- a/plugins/redmine_git_hosting/lib/tasks/migration_tools.rake +++ /dev/null @@ -1,158 +0,0 @@ -namespace :redmine_git_hosting do - namespace :migration_tools do - desc 'Fix migration numbers (add missing trailing 0 to some migrations)' - task fix_migration_numbers: [:environment] do - puts '' - - %w[2011072600000 2011080700000 2011081300000 2011081700000 2012052100000 2012052100001 2012052200000].each do |migration| - old_name = "#{migration}-redmine_git_hosting" - new_name = "#{migration}0-redmine_git_hosting" - puts "old_name : #{old_name}" - puts "new_name : #{new_name}" - - # Get the old migration name - query = "SELECT * FROM #{ActiveRecord::Base.connection.quote_string('schema_migrations')}" \ - " WHERE #{ActiveRecord::Base.connection.quote_string('version')} =" \ - " '#{ActiveRecord::Base.connection.quote_string(old_name)}';" - result = ActiveRecord::Base.connection.execute query - - # If present, rename - if !result.to_a.empty? - query = "DELETE FROM #{ActiveRecord::Base.connection.quote_string('schema_migrations')}" \ - " WHERE #{ActiveRecord::Base.connection.quote_string('version')} =" \ - " '#{ActiveRecord::Base.connection.quote_string(old_name)}';" - ActiveRecord::Base.connection.execute query - - query = "INSERT INTO #{ActiveRecord::Base.connection.quote_string('schema_migrations')} (VERSION)" \ - " VALUES ('#{ActiveRecord::Base.connection.quote_string(new_name)}');" - ActiveRecord::Base.connection.execute query - else - # Check the new name is present - query = "SELECT * FROM #{ActiveRecord::Base.connection.quote_string('schema_migrations')}" \ - " WHERE #{ActiveRecord::Base.connection.quote_string('version')} =" \ - " '#{ActiveRecord::Base.connection.quote_string(new_name)}';" - result = ActiveRecord::Base.connection.execute query - - if result.to_a.empty? - puts "Error : migration is missing #{new_name}" - else - puts 'Already migrated, pass!' - puts '' - end - next - end - puts '' - end - - puts 'Done!' - end - - desc 'Rename SSH keys' - task rename_ssh_keys: [:environment] do - puts '' - puts 'Delete SSH keys in Gitolite and reset identifier :' - puts '' - - GitolitePublicKey.all.each do |ssh_key| - puts " - Delete SSH key #{ssh_key.identifier}" - RedmineGitHosting::GitoliteAccessor.destroy_ssh_key(ssh_key, bypass_sidekiq: true) - ssh_key.reset_identifiers - end - puts '' - - puts 'Add SSH keys with new name in Gitolite :' - puts '' - - GitolitePublicKey.all.each do |ssh_key| - puts " - Add SSH key : #{ssh_key.identifier}" - RedmineGitHosting::GitoliteAccessor.create_ssh_key(ssh_key, bypass_sidekiq: true) - end - - puts '' - - options = { message: 'Gitolite configuration has been modified, resync all projects...', bypass_sidekiq: true } - RedmineGitHosting::GitoliteAccessor.update_projects('all', options) - - puts 'Done!' - end - - desc 'Update repositories type (from Git to Xitolite)' - task update_repositories_type: [:environment] do - puts '' - puts 'Update repositories type (from Git to Xitolite) :' - puts '' - - Repository::Git.all.each do |repository| - # Don't update real Git repositories - next if repository.url.start_with?('/') - - # Don't update orphan repositories - if repository.project.nil? - puts "Repository with id: '#{repository.id}' doesn't have a project, skipping!!" - puts '' - next - end - - # Update Gitolite repositories - if repository.identifier.blank? - puts repository.project.identifier - repository.update_attribute(:type, 'Repository::Xitolite') - puts 'Done!' - puts '' - else - puts repository.identifier - repository.update_attribute(:type, 'Repository::Xitolite') - puts 'Done!' - puts '' - end - end - end - - desc 'Check GitExtras presence' - task check_git_extras_presence: [:environment] do - puts '' - puts 'Checking for GitExtras presence' - puts '' - - Repository::Xitolite.all.each do |repository| - if repository.project.nil? - puts " - ERROR : Repository with id '##{repository.id}' has no associated project ! You should take a look at it !" - puts '' - next - elsif !repository.extra.nil? - puts " - Repository '#{repository.redmine_name}' has an entry in RepositoryGitExtras table, update it :" - repository.extra.save! - else - puts " - Repository '#{repository.redmine_name}' has no entry in RepositoryGitExtras table, create it :" - default_extra_options = { - git_http: RedmineGitHosting::Config.gitolite_http_by_default?, - 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) - } - extra = repository.build_extra(default_extra_options) - extra.save! - end - puts ' Done!' - puts '' - end - - puts 'Done!' - end - end - - desc 'Migrate to v1.0 version' - task migrate_to_v1: [:environment] do - ## First step : rename migrations in DB - task('redmine_git_hosting:migration_tools:fix_migration_numbers').invoke - ## Migrate DB only for redmine_git_hosting plugin - ENV['NAME'] = 'redmine_git_hosting' - task('redmine:plugins:migrate').invoke - ## Rename SSH keys (reset identifier) - task('redmine_git_hosting:migration_tools:rename_ssh_keys').invoke - ## Update repositories type - task('redmine_git_hosting:migration_tools:update_repositories_type').invoke - end -end diff --git a/plugins/redmine_git_hosting/lib/tasks/redmine_git_hosting.rake b/plugins/redmine_git_hosting/lib/tasks/redmine_git_hosting.rake deleted file mode 100644 index b6a1aa0..0000000 --- a/plugins/redmine_git_hosting/lib/tasks/redmine_git_hosting.rake +++ /dev/null @@ -1,90 +0,0 @@ -namespace :redmine_git_hosting do - desc <<-DESCRIPTION - Update plugin settings in database (This will read settings from `/redmine_git_hosting.yml` - and `/settings.yml`) - DESCRIPTION - task update_settings: [:environment] do - RedmineGitHosting::ConsoleLogger.title('Reloading settings from command line') do - RedmineGitHosting::Config.reload_from_file! - end - end - - desc 'Dump plugin settings in console' - task dump_settings: [:environment] do - RedmineGitHosting::Config.dump_settings - end - - desc 'Purge expired repositories from Recycle Bin' - task purge_recycle_bin: [:environment] do - RedmineGitHosting::ConsoleLogger.title('Purging Recycle Bin from command line') do - RedmineGitHosting::GitoliteAccessor.purge_recycle_bin - end - end - - desc 'Update/repair Gitolite configuration' - task update_repositories: [:environment] do - RedmineGitHosting::ConsoleLogger.title('Performing manual update_repositories operation from command line') do - RedmineGitHosting::GitoliteAccessor.update_projects('all', { message: "Resync all projects (#{Project.all.length})..." }) - end - end - - desc 'Fetch commits from gitolite repositories/update gitolite configuration' - task fetch_changesets: [:environment] do - RedmineGitHosting::ConsoleLogger.title('Performing manual fetch_changesets operation from command line') do - RedmineGitHosting::GitoliteAccessor.flush_git_cache - Repository.fetch_changesets - end - end - - desc 'Check repositories identifier uniqueness' - task check_repository_uniqueness: [:environment] do - RedmineGitHosting::ConsoleLogger.title('Checking repositories identifier uniqueness...') do - if Repository::Xitolite.have_duplicated_identifier? - RedmineGitHosting::ConsoleLogger.warn('Detected non-unique repository identifiers!') - puts YAML.dump(Repository::Xitolite.identifiers_to_hash.reject! { |_k, v| v == 1 }) - else - RedmineGitHosting::ConsoleLogger.info('No duplication detected, good !') - end - end - end - - desc 'Resync ssh_keys' - task resync_ssh_keys: [:environment] do - RedmineGitHosting::ConsoleLogger.title('Performing manual resync_ssh_keys operation from command line') do - RedmineGitHosting::GitoliteAccessor.resync_ssh_keys(bypass_sidekiq: true) - end - end - - desc 'Regenerate ssh_keys' - task regenerate_ssh_keys: [:environment] do - RedmineGitHosting::ConsoleLogger.title('Performing manual regenerate_ssh_keys operation from command line') do - RedmineGitHosting::GitoliteAccessor.regenerate_ssh_keys(bypass_sidekiq: true) - end - end - - desc 'Install/update Gitolite hooks' - task install_hook_files: [:environment] do - RedmineGitHosting::ConsoleLogger.title('Installing/updating Gitolite hooks') do - puts YAML.dump(RedmineGitHosting::Config.install_hooks!) - end - end - - desc 'Install/update Gitolite hook parameters' - task install_hook_parameters: [:environment] do - RedmineGitHosting::ConsoleLogger.title('Installing/updating Gitolite hook parameters') do - puts YAML.dump(RedmineGitHosting::Config.update_hook_params!) - end - end - - task install_gitolite_hooks: %i[install_hook_files install_hook_parameters] - - desc 'Show library version' - task :version do - puts "Redmine Git Hosting #{version('plugins/redmine_git_hosting/init.rb')}" - end - - def version(path) - line = File.read(Rails.root.join(path))[/^\s*version\s*.*/] - line.match(/.*version\s*['"](.*)['"]/)[1] - end -end diff --git a/plugins/redmine_git_hosting/spec/controllers/go_redirector_controller_spec.rb b/plugins/redmine_git_hosting/spec/controllers/go_redirector_controller_spec.rb deleted file mode 100644 index 60a6a9c..0000000 --- a/plugins/redmine_git_hosting/spec/controllers/go_redirector_controller_spec.rb +++ /dev/null @@ -1,82 +0,0 @@ -require File.expand_path('../spec_helper', __dir__) - -describe GoRedirectorController do - def check_response_with_smart_http(repository, opts = {}) - enable_go_url(repository) - yield - call_page(repository, opts[:status]) - end - - def check_response_without_smart_http(repository, opts = {}) - disable_go_url(repository) - yield - call_page(repository, opts[:status]) - end - - def call_page(repository, status) - get :index, params: { repo_path: repository.redmine_repository_path } - expect(response.status).to eq status - end - - def enable_go_url(repository) - repository.extra[:git_http] = true - repository.extra[:git_go] = true - repository.extra.save! - end - - def disable_go_url(repository) - repository.extra[:git_http] = false - repository.extra[:git_go] = false - repository.extra.save! - end - - def enable_public_repo(repository) - repository.extra[:public_repo] = true - repository.extra.save! - end - - describe 'GET #index' do - context 'when project is public' do - let(:project) { FactoryBot.create(:project, is_public: true) } - let(:repository) { create_git_repository(project: project) } - let(:anonymous_user) { create_anonymous_user } - - context 'and SmartHTTP is enabled' do - it 'renders 200' do - check_response_with_smart_http(repository, status: 200) { set_session_user(anonymous_user) } - end - end - - context 'and SmartHTTP is disabled' do - it 'renders 403' do - check_response_without_smart_http(repository, status: 403) { set_session_user(anonymous_user) } - end - end - end - - context 'when project is private' do - let(:project) { FactoryBot.create(:project, is_public: false) } - let(:repository) { create_git_repository(project: project) } - let(:anonymous_user) { create_anonymous_user } - - context 'and SmartHTTP is enabled' do - it 'renders 403' do - check_response_with_smart_http(repository, status: 403) { set_session_user(anonymous_user) } - end - - context 'when repository is public' do - it 'renders 200' do - enable_public_repo(repository) - check_response_with_smart_http(repository, status: 200) { set_session_user(anonymous_user) } - end - end - end - - context 'and SmartHTTP is disabled' do - it 'renders 403' do - check_response_without_smart_http(repository, status: 403) { set_session_user(anonymous_user) } - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/spec/controllers/repository_deployment_credentials_controller_spec.rb b/plugins/redmine_git_hosting/spec/controllers/repository_deployment_credentials_controller_spec.rb deleted file mode 100644 index 57248b5..0000000 --- a/plugins/redmine_git_hosting/spec/controllers/repository_deployment_credentials_controller_spec.rb +++ /dev/null @@ -1,70 +0,0 @@ -require File.expand_path "#{File.dirname __FILE__}/../spec_helper" - -require 'sshkey' - -describe RepositoryDeploymentCredentialsController do - def self.skip_actions - ['show'] - end - - include CrudControllerSpec::Base - - def permissions - %i[manage_repository create_repository_deployment_credentials view_repository_deployment_credentials - edit_repository_deployment_credentials] - end - - def create_object - FactoryBot.create(:repository_deployment_credential, - repository_id: @repository.id, - user_id: @member_user.id, - gitolite_public_key_id: FactoryBot.create(:gitolite_public_key, - user_id: @member_user.id, - key_type: 1, - key: SSHKey.generate.ssh_public_key).id) - end - - def success_url - "/repositories/#{@repository.id}/edit?tab=repository_deployment_credentials" - end - - def variable_for_index - :repository_deployment_credentials - end - - def main_variable - :credential - end - - def tested_klass - RepositoryDeploymentCredential - end - - def valid_params_for_create - public_key = FactoryBot.create(:gitolite_public_key, - user_id: @member_user.id, - key_type: 1, - key: SSHKey.generate.ssh_public_key) - { repository_deployment_credential: { gitolite_public_key_id: public_key.id, perm: 'RW+' } } - end - - def invalid_params_for_create - { repository_deployment_credential: { url: 'git@example.com:john_doe3/john_doe3/john_doe3.git', push_mode: 0 } } - end - - def valid_params_for_update - { id: @object.id, repository_deployment_credential: { perm: 'R' } } - end - - def updated_attribute - :perm - end - - def updated_attribute_value - 'R' - end - - def invalid_params_for_update - { id: @object.id, repository_deployment_credential: { perm: '' } } - end -end diff --git a/plugins/redmine_git_hosting/spec/controllers/repository_git_config_keys_controller_spec.rb b/plugins/redmine_git_hosting/spec/controllers/repository_git_config_keys_controller_spec.rb deleted file mode 100644 index f8b0653..0000000 --- a/plugins/redmine_git_hosting/spec/controllers/repository_git_config_keys_controller_spec.rb +++ /dev/null @@ -1,59 +0,0 @@ -require File.expand_path "#{File.dirname __FILE__}/../spec_helper" - -describe RepositoryGitConfigKeysController do - include CrudControllerSpec::Base - - def permissions - %i[manage_repository create_repository_git_config_keys view_repository_git_config_keys edit_repository_git_config_keys] - end - - def create_object - FactoryBot.create(:repository_git_config_key, repository_id: @repository.id) - end - - def success_url - "/repositories/#{@repository.id}/edit?tab=repository_git_config_keys" - end - - def variable_for_index - :repository_git_config_keys - end - - def main_variable - :git_config_key - end - - def tested_klass - RepositoryGitConfigKey - end - - def valid_params_for_create - { repository_git_config_key: { key: 'foo.bar1', value: 0, type: 'RepositoryGitConfigKey::GitConfig' } } - end - - def invalid_params_for_create - { repository_git_config_key: { key: '', value: 0 } } - end - - def valid_params_for_update - { id: @object.id, repository_git_config_key: { key: 'foo.bar1', value: 1 } } - end - - def updated_attribute - :value - end - - def updated_attribute_value - '1' - end - - def invalid_params_for_update - { id: @object.id, repository_git_config_key: { key: 'foo', value: 1 } } - end - - private - - def base_options - { repository_id: @repository.id, type: 'git_keys' }.clone - end -end diff --git a/plugins/redmine_git_hosting/spec/controllers/repository_mirrors_controller_spec.rb b/plugins/redmine_git_hosting/spec/controllers/repository_mirrors_controller_spec.rb deleted file mode 100644 index 50b241b..0000000 --- a/plugins/redmine_git_hosting/spec/controllers/repository_mirrors_controller_spec.rb +++ /dev/null @@ -1,72 +0,0 @@ -require File.expand_path "#{File.dirname __FILE__}/../spec_helper" - -describe RepositoryMirrorsController do - include CrudControllerSpec::Base - - def permissions - %i[manage_repository create_repository_mirrors view_repository_mirrors edit_repository_mirrors push_repository_mirrors] - end - - def create_object - FactoryBot.create(:repository_mirror, repository_id: @repository.id) - end - - def success_url - "/repositories/#{@repository.id}/edit?tab=repository_mirrors" - end - - def variable_for_index - :repository_mirrors - end - - def main_variable - :mirror - end - - def tested_klass - RepositoryMirror - end - - def valid_params_for_create - { repository_mirror: { url: 'ssh://git@example.com:22/john_doe2/john_doe2/john_doe2.git', push_mode: 0 } } - end - - def invalid_params_for_create - { repository_mirror: { url: 'git@example.com:john_doe3/john_doe3/john_doe3.git', push_mode: 0 } } - end - - def valid_params_for_update - { id: @object.id, repository_mirror: { url: 'ssh://git@redmine.example.org/project1/project2/project3/project14.git' } } - end - - def updated_attribute - :url - end - - def updated_attribute_value - 'ssh://git@redmine.example.org/project1/project2/project3/project14.git' - end - - def invalid_params_for_update - { id: @object.id, repository_mirror: { url: 'git@example.com:john_doe3/john_doe3/john_doe3.git' } } - end - - describe 'GET #push' do - context 'with sufficient permissions' do - it 'renders the :push view' do - set_session_user(@member_user) - get :push, - params: { repository_id: @repository.id, id: @object.id } - end - end - - context 'with unsufficient permissions' do - it 'renders 403' do - set_session_user(@anonymous_user) - get :push, - params: { repository_id: @repository.id, id: @object.id } - check_status(403) - end - end - end -end diff --git a/plugins/redmine_git_hosting/spec/controllers/repository_post_receive_urls_controller_spec.rb b/plugins/redmine_git_hosting/spec/controllers/repository_post_receive_urls_controller_spec.rb deleted file mode 100644 index 39ec295..0000000 --- a/plugins/redmine_git_hosting/spec/controllers/repository_post_receive_urls_controller_spec.rb +++ /dev/null @@ -1,53 +0,0 @@ -require File.expand_path "#{File.dirname __FILE__}/../spec_helper" - -describe RepositoryPostReceiveUrlsController do - include CrudControllerSpec::Base - - def permissions - %i[manage_repository create_repository_post_receive_urls view_repository_post_receive_urls edit_repository_post_receive_urls] - end - - def create_object - FactoryBot.create(:repository_post_receive_url, repository_id: @repository.id) - end - - def success_url - "/repositories/#{@repository.id}/edit?tab=repository_post_receive_urls" - end - - def variable_for_index - :repository_post_receive_urls - end - - def main_variable - :post_receive_url - end - - def tested_klass - RepositoryPostReceiveUrl - end - - def valid_params_for_create - { repository_post_receive_url: { url: 'http://example.com', mode: :github } } - end - - def invalid_params_for_create - { repository_post_receive_url: { url: 'example.com', push_mode: 0 } } - end - - def valid_params_for_update - { id: @object.id, repository_post_receive_url: { url: 'http://example.com/toto.php' } } - end - - def updated_attribute - :url - end - - def updated_attribute_value - 'http://example.com/toto.php' - end - - def invalid_params_for_update - { id: @object.id, repository_post_receive_url: { url: 'example.com' } } - end -end diff --git a/plugins/redmine_git_hosting/spec/controllers/users_controller_spec.rb b/plugins/redmine_git_hosting/spec/controllers/users_controller_spec.rb deleted file mode 100644 index d670371..0000000 --- a/plugins/redmine_git_hosting/spec/controllers/users_controller_spec.rb +++ /dev/null @@ -1,37 +0,0 @@ -require File.expand_path "#{File.dirname __FILE__}/../spec_helper" - -require 'sshkey' - -describe UsersController do - describe 'GET #edit' do - context 'with git hosting patch' do - let(:user) { create_admin_user } - let(:user_key) do - create_ssh_key(user_id: user.id, - title: 'user_key', - key: SSHKey.generate(comment: 'faker_user_key@john_doe').ssh_public_key, - key_type: 0) - end - let(:deploy_key) do - create_ssh_key(user_id: user.id, - title: 'deploy_key', - key: SSHKey.generate(comment: 'faker_deploy_key@john_doe').ssh_public_key, - key_type: 1) - end - - it 'populates an array of gitolite_user_keys' do - set_session_user(user) - get :edit, - params: { id: user.id } - expect(assigns(:gitolite_user_keys)).to eq [user_key] - end - - # it 'populates an array of gitolite_deploy_keys' do - # set_session_user(user) - # get :edit, - # params: { id: user.id } - # expect(assigns(:gitolite_deploy_keys)).to eq [deploy_key] - # end - end - end -end diff --git a/plugins/redmine_git_hosting/spec/factories/gitolite_public_key.rb b/plugins/redmine_git_hosting/spec/factories/gitolite_public_key.rb deleted file mode 100644 index 7500275..0000000 --- a/plugins/redmine_git_hosting/spec/factories/gitolite_public_key.rb +++ /dev/null @@ -1,13 +0,0 @@ -FactoryBot.define do - factory :gitolite_public_key do - sequence(:title) { |n| "test-key#{n}" } - key do - 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDpqFJzsx3wTi3t3X/eOizU6rdtNQoqg5uSjL89F+Ojjm2/sah3ouzx+3E461FDYaoJL58Qs9eRhL+ev0BY7khYXp' \ - 'h8nIVDzNEjhLqjevX+YhpaW9Ll7V807CwAyvMNm08aup/NrrlI/jO+At348/ivJrfO7ClcPhq4+Id9RZfvbrKaitGOURD7q6Bd7xjUjELUN8wmYxu5zvx/2n/5woVd' \ - 'BUMXamTPxOY5y6DxTNJ+EYzrCr+bNb7459rWUvBHUQGI2fXDGmFpGiv6ShKRhRtwob1JHI8QC9OtxonrIUesa2dW6RFneUaM7tfRfffC704Uo7yuSswb7YK+p1A9QI' \ - 't5 nicolas@tchoum' - end - key_type { 0 } - association :user - end -end diff --git a/plugins/redmine_git_hosting/spec/factories/group.rb b/plugins/redmine_git_hosting/spec/factories/group.rb deleted file mode 100644 index a440064..0000000 --- a/plugins/redmine_git_hosting/spec/factories/group.rb +++ /dev/null @@ -1,5 +0,0 @@ -FactoryBot.define do - factory :group do - sequence(:lastname) { |n| "GroupTest#{n}" } - end -end diff --git a/plugins/redmine_git_hosting/spec/factories/member.rb b/plugins/redmine_git_hosting/spec/factories/member.rb deleted file mode 100644 index ea082c7..0000000 --- a/plugins/redmine_git_hosting/spec/factories/member.rb +++ /dev/null @@ -1,4 +0,0 @@ -FactoryBot.define do - factory :member do |member| - end -end diff --git a/plugins/redmine_git_hosting/spec/factories/project.rb b/plugins/redmine_git_hosting/spec/factories/project.rb deleted file mode 100644 index b435e01..0000000 --- a/plugins/redmine_git_hosting/spec/factories/project.rb +++ /dev/null @@ -1,6 +0,0 @@ -FactoryBot.define do - factory :project do - sequence(:identifier) { |n| "project#{n}" } - sequence(:name) { |n| "Project#{n}" } - end -end diff --git a/plugins/redmine_git_hosting/spec/factories/protected_branches_member.rb b/plugins/redmine_git_hosting/spec/factories/protected_branches_member.rb deleted file mode 100644 index 98b183d..0000000 --- a/plugins/redmine_git_hosting/spec/factories/protected_branches_member.rb +++ /dev/null @@ -1,11 +0,0 @@ -FactoryBot.define do - factory :protected_branch_user_member, class: 'ProtectedBranchesMember' do - association :protected_branch, factory: :repository_protected_branche - association :principal, factory: :user - end - - factory :protected_branch_group_member, class: 'ProtectedBranchesMember' do - association :protected_branch, factory: :repository_protected_branche - association :principal, factory: :group - end -end diff --git a/plugins/redmine_git_hosting/spec/factories/repository_deployment_credential.rb b/plugins/redmine_git_hosting/spec/factories/repository_deployment_credential.rb deleted file mode 100644 index de0d8c2..0000000 --- a/plugins/redmine_git_hosting/spec/factories/repository_deployment_credential.rb +++ /dev/null @@ -1,8 +0,0 @@ -FactoryBot.define do - factory :repository_deployment_credential do - perm { 'RW+' } - association :repository, factory: :repository_gitolite - association :user - association :gitolite_public_key - end -end diff --git a/plugins/redmine_git_hosting/spec/factories/repository_git_config_key.rb b/plugins/redmine_git_hosting/spec/factories/repository_git_config_key.rb deleted file mode 100644 index cb86826..0000000 --- a/plugins/redmine_git_hosting/spec/factories/repository_git_config_key.rb +++ /dev/null @@ -1,21 +0,0 @@ -FactoryBot.define do - factory :repository_git_config_key_base, class: 'RepositoryGitConfigKey' do - sequence(:key) { |n| "hookfoo.foo#{n}" } - value { 'bar' } - association :repository, factory: :repository_gitolite - end - - factory :repository_git_config_key, class: 'RepositoryGitConfigKey::GitConfig' do - sequence(:key) { |n| "hookfoo.foo#{n}" } - value { 'bar' } - type { 'RepositoryGitConfigKey::GitConfig' } - association :repository, factory: :repository_gitolite - end - - factory :repository_git_option_key, class: 'RepositoryGitConfigKey::Option' do - sequence(:key) { |n| "hookfoo.foo#{n}" } - value { 'bar' } - type { 'RepositoryGitConfigKey::Option' } - association :repository, factory: :repository_gitolite - end -end diff --git a/plugins/redmine_git_hosting/spec/factories/repository_git_extra.rb b/plugins/redmine_git_hosting/spec/factories/repository_git_extra.rb deleted file mode 100644 index aa3ea55..0000000 --- a/plugins/redmine_git_hosting/spec/factories/repository_git_extra.rb +++ /dev/null @@ -1,8 +0,0 @@ -FactoryBot.define do - factory :repository_git_extra do - git_http { 0 } - default_branch { 'master' } - association :repository, factory: :repository_gitolite - key { RedmineGitHosting::Utils::Crypto.generate_secret(64) } - end -end diff --git a/plugins/redmine_git_hosting/spec/factories/repository_gitolite.rb b/plugins/redmine_git_hosting/spec/factories/repository_gitolite.rb deleted file mode 100644 index a199046..0000000 --- a/plugins/redmine_git_hosting/spec/factories/repository_gitolite.rb +++ /dev/null @@ -1,6 +0,0 @@ -FactoryBot.define do - factory :repository_gitolite, class: 'Repository::Xitolite' do - is_default { false } - association :project - end -end diff --git a/plugins/redmine_git_hosting/spec/factories/repository_mirror.rb b/plugins/redmine_git_hosting/spec/factories/repository_mirror.rb deleted file mode 100644 index aed1928..0000000 --- a/plugins/redmine_git_hosting/spec/factories/repository_mirror.rb +++ /dev/null @@ -1,7 +0,0 @@ -FactoryBot.define do - factory :repository_mirror do - sequence(:url) { |n| "ssh://git@example.com:22/john_doe/john_doe/john_doe_#{n}.git" } - push_mode { 0 } - association :repository, factory: :repository_gitolite - end -end diff --git a/plugins/redmine_git_hosting/spec/factories/repository_post_receive_url.rb b/plugins/redmine_git_hosting/spec/factories/repository_post_receive_url.rb deleted file mode 100644 index fce6dfc..0000000 --- a/plugins/redmine_git_hosting/spec/factories/repository_post_receive_url.rb +++ /dev/null @@ -1,6 +0,0 @@ -FactoryBot.define do - factory :repository_post_receive_url do - sequence(:url) { |n| "http://example.com/toto#{n}.php" } - association :repository, factory: :repository_gitolite - end -end diff --git a/plugins/redmine_git_hosting/spec/factories/repository_protected_branche.rb b/plugins/redmine_git_hosting/spec/factories/repository_protected_branche.rb deleted file mode 100644 index bc960d0..0000000 --- a/plugins/redmine_git_hosting/spec/factories/repository_protected_branche.rb +++ /dev/null @@ -1,7 +0,0 @@ -FactoryBot.define do - factory :repository_protected_branche do - path { 'master' } - permissions { 'RW+' } - association :repository, factory: :repository_gitolite - end -end diff --git a/plugins/redmine_git_hosting/spec/factories/repository_svn.rb b/plugins/redmine_git_hosting/spec/factories/repository_svn.rb deleted file mode 100644 index 777fade..0000000 --- a/plugins/redmine_git_hosting/spec/factories/repository_svn.rb +++ /dev/null @@ -1,5 +0,0 @@ -FactoryBot.define do - factory :repository_svn, class: 'Repository::Subversion' do - is_default { false } - end -end diff --git a/plugins/redmine_git_hosting/spec/factories/role.rb b/plugins/redmine_git_hosting/spec/factories/role.rb deleted file mode 100644 index 20306f1..0000000 --- a/plugins/redmine_git_hosting/spec/factories/role.rb +++ /dev/null @@ -1,21 +0,0 @@ -FactoryBot.define do - factory :role do - name { 'Manager' } - builtin { 0 } - issues_visibility { 'all' } - position { 1 } - permissions do - %i[add_project edit_project close_project select_project_modules manage_members - manage_versions manage_categories view_issues add_issues edit_issues manage_issue_relations - manage_subtasks add_issue_notes move_issues delete_issues view_issue_watchers add_issue_watchers - set_issues_private set_notes_private view_private_notes delete_issue_watchers - manage_public_queries save_queries view_gantt view_calendar log_time view_time_entries - edit_time_entries delete_time_entries manage_news comment_news view_documents - add_documents edit_documents delete_documents view_wiki_pages export_wiki_pages - view_wiki_edits edit_wiki_pages delete_wiki_pages_attachments protect_wiki_pages - delete_wiki_pages rename_wiki_pages add_messages edit_messages delete_messages - manage_boards view_files manage_files browse_repository manage_repository view_changesets - manage_related_issues manage_project_activities create_gitolite_ssh_key commit_access] - end - end -end diff --git a/plugins/redmine_git_hosting/spec/factories/user.rb b/plugins/redmine_git_hosting/spec/factories/user.rb deleted file mode 100644 index b5f7487..0000000 --- a/plugins/redmine_git_hosting/spec/factories/user.rb +++ /dev/null @@ -1,11 +0,0 @@ -FactoryBot.define do - factory :user do - sequence(:login) { |n| "user#{n}" } - sequence(:firstname) { |n| "User#{n}" } - sequence(:lastname) { |n| "Test#{n}" } - sequence(:mail) { |n| "user#{n}@awesome.com" } - language { 'fr' } - hashed_password { '66eb4812e268747f89ec309178e2ea50410653fb' } - salt { '5abd4e59ac0d483daf2f68d3b6544ff3' } - end -end diff --git a/plugins/redmine_git_hosting/spec/fixtures/branches_payload.yml b/plugins/redmine_git_hosting/spec/fixtures/branches_payload.yml deleted file mode 100644 index f673275..0000000 --- a/plugins/redmine_git_hosting/spec/fixtures/branches_payload.yml +++ /dev/null @@ -1,225 +0,0 @@ ---- -- :before: 349873f6780acce61770d755f460082f939c35de - :after: 4754c319e4565d56d1d680e5a67032f38d7b1686 - :ref: refs/heads/branch1 - :commits: - - :id: 39eec0e81dd0619f2039e19df6d9b62b5740f15c - :message: test - :timestamp: 2014-05-22 21:20:54.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/39eec0e81dd0619f2039e19df6d9b62b5740f15c - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: c6d5b7772692a0c94c2bc49aa0801c004e5a6b73 - :message: test - :timestamp: 2014-05-22 21:20:54.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/c6d5b7772692a0c94c2bc49aa0801c004e5a6b73 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 0116d0a680943e6ff5b41aa1b0d0842c39f20458 - :message: test - :timestamp: 2014-05-22 21:20:55.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/0116d0a680943e6ff5b41aa1b0d0842c39f20458 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: b914656d7a3de10fa70979771875078ffe7d5f75 - :message: test - :timestamp: 2014-05-22 21:20:55.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/b914656d7a3de10fa70979771875078ffe7d5f75 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: a6e1da9c875171bb6f15cf4ec97a2c6b75d43eda - :message: test - :timestamp: 2014-05-22 21:20:55.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/a6e1da9c875171bb6f15cf4ec97a2c6b75d43eda - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 8034f3c4c7c18845c3e4a3bebc6cefc14083cc78 - :message: test - :timestamp: 2014-05-22 21:20:55.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/8034f3c4c7c18845c3e4a3bebc6cefc14083cc78 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 4754c319e4565d56d1d680e5a67032f38d7b1686 - :message: test - :timestamp: 2014-05-22 21:20:56.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/4754c319e4565d56d1d680e5a67032f38d7b1686 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - :repository: - :description: '' - :fork: false - :forks: 0 - :homepage: '' - :name: test - :open_issues: 0 - :watchers: 0 - :private: false - :url: http://redmine.example.net/projects/test/repository - :owner: - :name: Redmine - :email: redmine@example.net -- :before: 1e063b23e50d274bc667808b1273911b7796b583 - :after: c51932336314bad33b6a2b7d735205a0686442de - :ref: refs/heads/branch2 - :commits: - - :id: 4caf42c4681f39e27c08776a0005c24ef4e76515 - :message: test - :timestamp: 2014-05-22 21:21:03.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/4caf42c4681f39e27c08776a0005c24ef4e76515 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 95d0cddef1682766cbf28e2b101f5ecc61299b46 - :message: test - :timestamp: 2014-05-22 21:21:04.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/95d0cddef1682766cbf28e2b101f5ecc61299b46 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 01e059c50d418da831afdc6175335a86efef4b64 - :message: test - :timestamp: 2014-05-22 21:21:04.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/01e059c50d418da831afdc6175335a86efef4b64 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: c794954ac2f31a195557bef66dc5b1e1d9253248 - :message: test - :timestamp: 2014-05-22 21:21:04.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/c794954ac2f31a195557bef66dc5b1e1d9253248 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 02b802617b55424a408c4cee9b4c58017d186e4b - :message: test - :timestamp: 2014-05-22 21:21:04.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/02b802617b55424a408c4cee9b4c58017d186e4b - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: ff0ae3c64e48de2b33a511694a72118f12a12951 - :message: test - :timestamp: 2014-05-22 21:21:05.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/ff0ae3c64e48de2b33a511694a72118f12a12951 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 7f8af614170833d59ba5d8e09b8aba36f69ac11f - :message: test - :timestamp: 2014-05-22 21:21:05.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/7f8af614170833d59ba5d8e09b8aba36f69ac11f - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 08c1a24b67f6a6113238dfe681ba2c649b678336 - :message: test - :timestamp: 2014-05-22 21:21:05.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/08c1a24b67f6a6113238dfe681ba2c649b678336 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 942d348461ebaa47c7bca2874de1556af7b30aea - :message: test - :timestamp: 2014-05-22 21:21:06.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/942d348461ebaa47c7bca2874de1556af7b30aea - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: a96c9d802c0f5ffe42fde052ee9e37ecfb3a8069 - :message: test - :timestamp: 2014-05-22 21:21:06.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/a96c9d802c0f5ffe42fde052ee9e37ecfb3a8069 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 5eb8b5a5f2ab6a794974975914cb661f56fe443f - :message: test - :timestamp: 2014-05-22 21:21:06.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/5eb8b5a5f2ab6a794974975914cb661f56fe443f - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: c51932336314bad33b6a2b7d735205a0686442de - :message: test - :timestamp: 2014-05-22 21:21:06.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/c51932336314bad33b6a2b7d735205a0686442de - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - :repository: - :description: '' - :fork: false - :forks: 0 - :homepage: '' - :name: test - :open_issues: 0 - :watchers: 0 - :private: false - :url: http://redmine.example.net/projects/test/repository - :owner: - :name: Redmine - :email: redmine@example.net diff --git a/plugins/redmine_git_hosting/spec/fixtures/global_payload.yml b/plugins/redmine_git_hosting/spec/fixtures/global_payload.yml deleted file mode 100644 index 78d0613..0000000 --- a/plugins/redmine_git_hosting/spec/fixtures/global_payload.yml +++ /dev/null @@ -1,322 +0,0 @@ ---- -- :before: 349873f6780acce61770d755f460082f939c35de - :after: 4754c319e4565d56d1d680e5a67032f38d7b1686 - :ref: refs/heads/branch1 - :commits: - - :id: 39eec0e81dd0619f2039e19df6d9b62b5740f15c - :message: test - :timestamp: 2014-05-22 21:20:54.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/39eec0e81dd0619f2039e19df6d9b62b5740f15c - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: c6d5b7772692a0c94c2bc49aa0801c004e5a6b73 - :message: test - :timestamp: 2014-05-22 21:20:54.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/c6d5b7772692a0c94c2bc49aa0801c004e5a6b73 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 0116d0a680943e6ff5b41aa1b0d0842c39f20458 - :message: test - :timestamp: 2014-05-22 21:20:55.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/0116d0a680943e6ff5b41aa1b0d0842c39f20458 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: b914656d7a3de10fa70979771875078ffe7d5f75 - :message: test - :timestamp: 2014-05-22 21:20:55.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/b914656d7a3de10fa70979771875078ffe7d5f75 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: a6e1da9c875171bb6f15cf4ec97a2c6b75d43eda - :message: test - :timestamp: 2014-05-22 21:20:55.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/a6e1da9c875171bb6f15cf4ec97a2c6b75d43eda - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 8034f3c4c7c18845c3e4a3bebc6cefc14083cc78 - :message: test - :timestamp: 2014-05-22 21:20:55.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/8034f3c4c7c18845c3e4a3bebc6cefc14083cc78 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 4754c319e4565d56d1d680e5a67032f38d7b1686 - :message: test - :timestamp: 2014-05-22 21:20:56.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/4754c319e4565d56d1d680e5a67032f38d7b1686 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - :repository: - :description: '' - :fork: false - :forks: 0 - :homepage: '' - :name: test - :open_issues: 0 - :watchers: 0 - :private: false - :url: http://redmine.example.net/projects/test/repository - :owner: - :name: Redmine - :email: redmine@example.net -- :before: 1e063b23e50d274bc667808b1273911b7796b583 - :after: c51932336314bad33b6a2b7d735205a0686442de - :ref: refs/heads/branch2 - :commits: - - :id: 4caf42c4681f39e27c08776a0005c24ef4e76515 - :message: test - :timestamp: 2014-05-22 21:21:03.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/4caf42c4681f39e27c08776a0005c24ef4e76515 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 95d0cddef1682766cbf28e2b101f5ecc61299b46 - :message: test - :timestamp: 2014-05-22 21:21:04.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/95d0cddef1682766cbf28e2b101f5ecc61299b46 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 01e059c50d418da831afdc6175335a86efef4b64 - :message: test - :timestamp: 2014-05-22 21:21:04.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/01e059c50d418da831afdc6175335a86efef4b64 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: c794954ac2f31a195557bef66dc5b1e1d9253248 - :message: test - :timestamp: 2014-05-22 21:21:04.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/c794954ac2f31a195557bef66dc5b1e1d9253248 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 02b802617b55424a408c4cee9b4c58017d186e4b - :message: test - :timestamp: 2014-05-22 21:21:04.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/02b802617b55424a408c4cee9b4c58017d186e4b - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: ff0ae3c64e48de2b33a511694a72118f12a12951 - :message: test - :timestamp: 2014-05-22 21:21:05.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/ff0ae3c64e48de2b33a511694a72118f12a12951 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 7f8af614170833d59ba5d8e09b8aba36f69ac11f - :message: test - :timestamp: 2014-05-22 21:21:05.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/7f8af614170833d59ba5d8e09b8aba36f69ac11f - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 08c1a24b67f6a6113238dfe681ba2c649b678336 - :message: test - :timestamp: 2014-05-22 21:21:05.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/08c1a24b67f6a6113238dfe681ba2c649b678336 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 942d348461ebaa47c7bca2874de1556af7b30aea - :message: test - :timestamp: 2014-05-22 21:21:06.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/942d348461ebaa47c7bca2874de1556af7b30aea - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: a96c9d802c0f5ffe42fde052ee9e37ecfb3a8069 - :message: test - :timestamp: 2014-05-22 21:21:06.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/a96c9d802c0f5ffe42fde052ee9e37ecfb3a8069 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 5eb8b5a5f2ab6a794974975914cb661f56fe443f - :message: test - :timestamp: 2014-05-22 21:21:06.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/5eb8b5a5f2ab6a794974975914cb661f56fe443f - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: c51932336314bad33b6a2b7d735205a0686442de - :message: test - :timestamp: 2014-05-22 21:21:06.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/c51932336314bad33b6a2b7d735205a0686442de - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - :repository: - :description: '' - :fork: false - :forks: 0 - :homepage: '' - :name: test - :open_issues: 0 - :watchers: 0 - :private: false - :url: http://redmine.example.net/projects/test/repository - :owner: - :name: Redmine - :email: redmine@example.net -- :before: 410516ba13d39aa719e129804865643b37b2bbcc - :after: ba2cd4a1bf6d18fbb89da2b6359f5938289444cb - :ref: refs/heads/master - :commits: - - :id: 16d1777a57eabeae5a3ed7a19da4734b1357bc18 - :message: test - :timestamp: 2014-05-22 21:20:41.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/16d1777a57eabeae5a3ed7a19da4734b1357bc18 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: fac18fd941b691493e9d106a726c5ba1b5e05a72 - :message: test - :timestamp: 2014-05-22 21:20:42.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/fac18fd941b691493e9d106a726c5ba1b5e05a72 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 50134028ea9b384eab19512e5da762b77425babf - :message: test - :timestamp: 2014-05-22 21:20:42.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/50134028ea9b384eab19512e5da762b77425babf - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 8171ba3fa3370f04afb660216a55407534e57ac0 - :message: test - :timestamp: 2014-05-22 21:20:42.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/8171ba3fa3370f04afb660216a55407534e57ac0 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: d698705a10a2db8144781e3e8cb0f0414da7eb40 - :message: test - :timestamp: 2014-05-22 21:20:43.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/d698705a10a2db8144781e3e8cb0f0414da7eb40 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 124ba40066c77899de4515577749d7272d43fcbd - :message: test - :timestamp: 2014-05-22 21:20:43.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/124ba40066c77899de4515577749d7272d43fcbd - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 2cc238c9250b90c392f0ab8162842e576cce75c0 - :message: test - :timestamp: 2014-05-22 21:20:43.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/2cc238c9250b90c392f0ab8162842e576cce75c0 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: ba2cd4a1bf6d18fbb89da2b6359f5938289444cb - :message: test - :timestamp: 2014-05-22 21:20:43.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/ba2cd4a1bf6d18fbb89da2b6359f5938289444cb - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - :repository: - :description: '' - :fork: false - :forks: 0 - :homepage: '' - :name: test - :open_issues: 0 - :watchers: 0 - :private: false - :url: http://redmine.example.net/projects/test/repository - :owner: - :name: Redmine - :email: redmine@example.net diff --git a/plugins/redmine_git_hosting/spec/fixtures/master_payload.yml b/plugins/redmine_git_hosting/spec/fixtures/master_payload.yml deleted file mode 100644 index bdc5a1b..0000000 --- a/plugins/redmine_git_hosting/spec/fixtures/master_payload.yml +++ /dev/null @@ -1,98 +0,0 @@ ---- -- :before: 410516ba13d39aa719e129804865643b37b2bbcc - :after: ba2cd4a1bf6d18fbb89da2b6359f5938289444cb - :ref: refs/heads/master - :commits: - - :id: 16d1777a57eabeae5a3ed7a19da4734b1357bc18 - :message: test - :timestamp: 2014-05-22 21:20:41.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/16d1777a57eabeae5a3ed7a19da4734b1357bc18 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: fac18fd941b691493e9d106a726c5ba1b5e05a72 - :message: test - :timestamp: 2014-05-22 21:20:42.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/fac18fd941b691493e9d106a726c5ba1b5e05a72 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 50134028ea9b384eab19512e5da762b77425babf - :message: test - :timestamp: 2014-05-22 21:20:42.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/50134028ea9b384eab19512e5da762b77425babf - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 8171ba3fa3370f04afb660216a55407534e57ac0 - :message: test - :timestamp: 2014-05-22 21:20:42.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/8171ba3fa3370f04afb660216a55407534e57ac0 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: d698705a10a2db8144781e3e8cb0f0414da7eb40 - :message: test - :timestamp: 2014-05-22 21:20:43.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/d698705a10a2db8144781e3e8cb0f0414da7eb40 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 124ba40066c77899de4515577749d7272d43fcbd - :message: test - :timestamp: 2014-05-22 21:20:43.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/124ba40066c77899de4515577749d7272d43fcbd - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: 2cc238c9250b90c392f0ab8162842e576cce75c0 - :message: test - :timestamp: 2014-05-22 21:20:43.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/2cc238c9250b90c392f0ab8162842e576cce75c0 - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - - :id: ba2cd4a1bf6d18fbb89da2b6359f5938289444cb - :message: test - :timestamp: 2014-05-22 21:20:43.000000000 Z - :added: [] - :modified: [] - :removed: [] - :url: http://redmine.example.net/projects/test/repository/revisions/ba2cd4a1bf6d18fbb89da2b6359f5938289444cb - :author: - :name: Nicolas - :email: nrodriguez@jbox-web.com - :repository: - :description: '' - :fork: false - :forks: 0 - :homepage: '' - :name: test - :open_issues: 0 - :watchers: 0 - :private: false - :url: http://redmine.example.net/projects/test/repository - :owner: - :name: Redmine - :email: redmine@example.net diff --git a/plugins/redmine_git_hosting/spec/helpers/gitolite_public_keys_helper_spec.rb b/plugins/redmine_git_hosting/spec/helpers/gitolite_public_keys_helper_spec.rb deleted file mode 100644 index 69f9eec..0000000 --- a/plugins/redmine_git_hosting/spec/helpers/gitolite_public_keys_helper_spec.rb +++ /dev/null @@ -1,44 +0,0 @@ -require File.expand_path "#{File.dirname __FILE__}/../spec_helper" - -describe GitolitePublicKeysHelper do - TEST_KEY = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCpOU1DzQzU4/acdt3wWhk43acGs3Jp7jVlnEtc+2C8QFAUiJMrAOzyUnEliwxarGonJ5gKbI9NkqqPpz9LATB' \ - 'Qw382+3FjAlptgqn7eGBih0DgwN6wdHflTRdE6sRn7hxB5h50p547n26FpbX9GSOHPhgxSnyvGXnC+YZyTfMiw5JMhw68SfLS8YENrXukg2ItJPspn6mPqIHrcM' \ - '2NJOG4Bm+1ibYpDfrWJqYp3Q6disgwrsN08pS6lDfoQRiRHXg8WFbQbHloVaYFpdT6VoBQiAydeSpDSYTBJd/v3qTpK8aheC8sdnrddZf1T6L51z7WZ6vPVKQYP' \ - 'jpAxZ4p6eef nicolas@tchoum' - - # before(:all) do - # @admin_user = create_admin_user - # @user_without_perm = create_anonymous_user - # @user_with_perm = create_user_with_permissions(FactoryBot.create(:project), - # permissions: [:create_repository_deployment_credentials]) - # @gitolite_public_key = create_ssh_key(user_id: @user_without_perm.id, key_type: 1, title: 'foo1', key: TEST_KEY) - # end - - # describe '.keylabel' do - # context 'when current user is the key owner' do - # before { User.current = @user_without_perm } - - # it { expect(helper.keylabel(@gitolite_public_key)).to eq 'foo1' } - # end - - # context 'when current user is not the key owner' do - # before { User.current = @admin_user } - - # it { expect(helper.keylabel(@gitolite_public_key)).to eq 'git_anonymous@foo1' } - # end - # end - - # describe '.can_create_deployment_keys_for_some_project' do - # context 'when current user is admin' do - # it { expect(helper.can_create_deployment_keys_for_some_project(@admin_user)).to eq true } - # end - - # context 'when current user can create_deployment_keys' do - # it { expect(helper.can_create_deployment_keys_for_some_project(@user_with_perm)).to eq true } - # end - - # context 'when current user cannot create_deployment_keys' do - # it { expect(helper.can_create_deployment_keys_for_some_project(@user_without_perm)).to eq false } - # end - # end -end diff --git a/plugins/redmine_git_hosting/spec/lib/redmine_git_hosting/config_spec.rb b/plugins/redmine_git_hosting/spec/lib/redmine_git_hosting/config_spec.rb deleted file mode 100644 index c5f8451..0000000 --- a/plugins/redmine_git_hosting/spec/lib/redmine_git_hosting/config_spec.rb +++ /dev/null @@ -1,28 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') - -describe RedmineGitHosting::Config do - GITOLITE_VERSION_2 = [ - 'hello redmine_gitolite_admin_id_rsa, this is gitolite v2.3.1-0-g912a8bd-dt running on git 1.7.2.5', - 'hello gitolite_admin_id_rsa, this is gitolite gitolite-2.3.1 running on git 1.8.1.5', - 'hello gitolite_admin_id_rsa, this is gitolite 2.3.1-1.el6 running on git 1.7.1', - 'hello gitolite_admin_id_rsa, this is gitolite 2.2-1 (Debian) running on git 1.7.9.5' - ].freeze - - GITOLITE_VERSION_3 = [ - 'hello redmine_gitolite_admin_id_rsa, this is git@dev running gitolite3 v3.3-11-ga1aba93 on git 1.7.2.5' - ].freeze - - GITOLITE_VERSION_2.each do |gitolite_version| - it 'should recognize Gitolite2' do - version = RedmineGitHosting::Config.find_version(gitolite_version) - expect(version).to eq 2 - end - end - - GITOLITE_VERSION_3.each do |gitolite_version| - it 'should recognize Gitolite3' do - version = RedmineGitHosting::Config.find_version(gitolite_version) - expect(version).to eq 3 - end - end -end diff --git a/plugins/redmine_git_hosting/spec/lib/redmine_git_hosting/utils/git_spec.rb b/plugins/redmine_git_hosting/spec/lib/redmine_git_hosting/utils/git_spec.rb deleted file mode 100644 index 82b1184..0000000 --- a/plugins/redmine_git_hosting/spec/lib/redmine_git_hosting/utils/git_spec.rb +++ /dev/null @@ -1,29 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper') - -describe RedmineGitHosting::Utils::Git do - include RedmineGitHosting::Utils::Git - - describe '.parse_refspec' do - context 'it should accept different refspec format' do - it 'should accept ' do - expect(parse_refspec('dev')).to eq({ type: nil, name: 'dev' }) - end - - it 'should accept a branch path' do - expect(parse_refspec('refs/branches/dev')).to eq({ type: 'branches', name: 'dev' }) - end - - it 'should accept the wildcard param (*)' do - expect(parse_refspec('refs/branches/dev/*')).to eq({ type: 'branches', name: 'dev/*' }) - expect(parse_refspec('refs/tags/*')).to eq({ type: 'tags', name: '*' }) - end - - it 'should parse different refspec path' do - expect(parse_refspec('refs/remotes/origin/experiment/*')).to eq({ type: 'remotes', name: 'origin/experiment/*' }) - expect(parse_refspec('refs/remotes/origin/experiment/master')).to eq({ type: 'remotes', name: 'origin/experiment/master' }) - expect(parse_refspec('refs/remotes/origin/experiment')).to eq({ type: 'remotes', name: 'origin/experiment' }) - expect(parse_refspec('refs/heads/experiment')).to eq({ type: 'heads', name: 'experiment' }) - end - end - end -end diff --git a/plugins/redmine_git_hosting/spec/models/gitolite_public_key_spec.rb b/plugins/redmine_git_hosting/spec/models/gitolite_public_key_spec.rb deleted file mode 100644 index f387ed9..0000000 --- a/plugins/redmine_git_hosting/spec/models/gitolite_public_key_spec.rb +++ /dev/null @@ -1,282 +0,0 @@ -require File.expand_path "#{File.dirname __FILE__}/../spec_helper" - -describe GitolitePublicKey do - SSH_KEY_0 = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDpqFJzsx3wTi3t3X/eOizU6rdtNQoqg5uSjL89F+Ojjm2/sah3ouzx+3E461FDYaoJL58Qs9eRhL+ev0BY7k' \ - 'hYXph8nIVDzNEjhLqjevX+YhpaW9Ll7V807CwAyvMNm08aup/NrrlI/jO+At348/ivJrfO7ClcPhq4+Id9RZfvbrKaitGOURD7q6Bd7xjUjELUN8wmYxu5zvx/' \ - '2n/5woVdBUMXamTPxOY5y6DxTNJ+EYzrCr+bNb7459rWUvBHUQGI2fXDGmFpGiv6ShKRhRtwob1JHI8QC9OtxonrIUesa2dW6RFneUaM7tfRfffC704Uo7yuSs' \ - 'wb7YK+p1A9QIt5 nicolas@tchoum'.freeze - SSH_KEY_1 = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCz0pLXcQWS4gLUimUSLwDOvEmQF8l8EKoj0LjxOyM3y2dpLsn0aiqS0ecA0G/ROomaawop8EZGFetoJKJM46' \ - '8OZlx2aKoQemzvFIq0Mn1ZhcrlA1alAsDYqzZI8iHO4JIS3YbeLLkVGAlYA+bmA5enXN9mGhC9cgoMC79EZiLD9XvOw4iXDjqXaCzFZHU1shMWwaJfpyxBm+Mx' \ - 's2vtZzwETDqeu9rohNMl60dODf6+JoXYiahP+B+P2iKlL7ORb1YsAH/4ZMsVgRckj8snb4uc3XgwLRNNw+oB78ApZGr0j3Zc32U9rpmulbHIroWO07OV4Xspln' \ - 'u8lhGvfodA2gjb nicolas@tchoum'.freeze - SSH_KEY_2 = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC5+JfM82k03J98GWL6ghJ4TYM8DbvDnVh1s1rUDNlM/1U5rwbgXHOR4xV3lulgYEYRtYeMoL3rt4ZpEyXWkO' \ - 'reOVsUlkW66SZJR5aGVTNJOLX7HruEDqj7RWlt0u0MH6DgBVAJimQrxYN50jYD4XnDUjb/qv55EhPvbJ3jcAb3zuyRXMKZYGNVzVFLUagbvVaOwR23csWSLDTs' \ - 'AEI9JzaxMKvCNRwk3jFepiCovXbw+g0iyvJdp0+AJpC57ZupyxHeX9J2oz7im2UaHHqLa2qUZL6c4PNV/D2p0Bts4Tcnn3OFPL90RF/ao0tjiUFxM3ti8pRHOq' \ - 'RcZHcOgIhKiaLX nicolas@tchoum'.freeze - SSH_KEY_3 = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/pSRh11xbadAh24fQlc0i0dneG0lI+DCkng+bVmumgRvfD0w79vcJ2U1qir2ChjpNvi2n96HUGIEGNV60/V' \ - 'G05JY70mEb//YVBmQ3w0QPO7toEWNms9SQlwR0PN6tarATumFik4MI+8M23P6W8O8OYwsnMmYwaiEU5hDopH88x74MQKjPiRSrhMkGiThMZhLVK6j8yfNPoj9y' \ - 'UxPBWc7zsMCC2uAOfR5Fg6hl2TKGxTi0vecTh1csDcO2agXx42RRiZeIQbv9j0IJjVL8KhXvbndVnJRjGGbxQFAedicw8OrPH7jz6NimmaTooqU9SwaPInK/x3' \ - 'omd297/zzcQm3p nicolas@tchoum'.freeze - SSH_KEY_4 = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDCScLGus1vrZ9OyzOj3TtYa+IHUp5V+2hwcMW7pphGIAPRi5Pe6GwSbSV5GnanerOH9ucmEREaCIdGOzO2zV' \ - 'I35e3RD6wTeW28Ck7JN1r2LSgSvXGvxGyzu0H4Abf66Kajt+lN0/71tbFtoTaJTGSYE3W0rNU6OQBvHf1o4wIyBEFm3cu+e2OrmW/nVIqk8hCN2cU/0OutOWT+' \ - 'vaRLbIU3VQmHftqa4NVxdc4OG48vpZxlJwKexqAHj8Ok/sn3k4CIo8zR0vRaeGPqAmOpm84uEfRWoA71NNS4tIhENlikuD5SJIdyXE9d8CwGTth4jP9/BNT0y4' \ - 'C8cGYljjUWkx3v nicolas@tchoum'.freeze - - before(:all) do - @user1 = create_user 'git_user1' - @user2 = create_user 'git_user2' - end - - # There is an isolation issue in tests. - # Try to workaround it... - def test_user - 'redmine_git_user1_12' - end - - describe 'Valid SSH key build' do - before(:each) do - @ssh_key = build_ssh_key(title: 'test-key') - end - - subject { @ssh_key } - - ## Relations - it { is_expected.to belong_to(:user) } - it { is_expected.to have_many(:repository_deployment_credentials) } - - ## Validations - it { is_expected.to be_valid } - - it { is_expected.to validate_presence_of(:title) } - it { is_expected.to validate_presence_of(:user_id) } - it { is_expected.to validate_presence_of(:key) } - it { is_expected.to validate_presence_of(:key_type) } - - it { is_expected.to validate_numericality_of(:key_type) } - - it { is_expected.to validate_inclusion_of(:key_type).in_array(%w[0 1]) } - - it { is_expected.to ensure_length_of(:title).is_at_most(60) } - - it { is_expected.not_to allow_value('toto@toto', 'ma_clé').for(:title) } - - it { is_expected.to respond_to(:identifier) } - it { is_expected.to respond_to(:fingerprint) } - it { is_expected.to respond_to(:owner) } - it { is_expected.to respond_to(:location) } - it { is_expected.to respond_to(:gitolite_path) } - it { is_expected.to respond_to(:data_for_destruction) } - - ## Attributes content - it 'can render as string' do - expect(@ssh_key.to_s).to eq 'test-key' - end - - it 'has a title' do - expect(@ssh_key.title).to eq 'test-key' - end - - it 'is a user key' do - expect(@ssh_key.user_key?).to be true - end - - it 'is not a deploy key' do - expect(@ssh_key.deploy_key?).to be false - end - - it 'must be deleted when unused' do - expect(@ssh_key.delete_when_unused?).to be true - end - - ## Test data integrity - it 'should not truncate key' do - expect(@ssh_key.key.length).to be == SSH_KEY_0.length - end - - ## Test change validation - describe 'when delete_when_unused is false' do - it 'should not be deleted when unused' do - @ssh_key.delete_when_unused = false - expect(@ssh_key.delete_when_unused?).to be false - end - end - - describe 'when delete_when_unused is true' do - it 'should be deleted when unused' do - @ssh_key.delete_when_unused = true - expect(@ssh_key.delete_when_unused?).to be true - end - end - end - - describe 'Valid SSH key creation' do - let(:ssh_key) { create_ssh_key(user_id: @user1.id, title: 'test-key') } - - subject { ssh_key } - - it 'has an identifier' do - expect(ssh_key.identifier).to eq "#{test_user}@redmine_test_key" - end - - it 'has a fingerprint' do - expect(ssh_key.fingerprint).to eq 'SHA256:VgXjWgUbURtD6go5HV7Eop2UqVjmIAI68shaB66yv+c' - end - - it 'has a owner' do - expect(ssh_key.owner).to eq test_user - end - - it 'has a location' do - expect(ssh_key.location).to eq 'redmine_test_key' - end - - it 'has a gitolite_path' do - expect(ssh_key.gitolite_path).to eq "keydir/redmine_git_hosting/#{test_user}/redmine_test_key/#{test_user}.pub" - end - - it 'it has data hash for destruction' do - valid_hash = { key: SSH_KEY_0, location: 'redmine_test_key', owner: test_user, title: "#{test_user}@redmine_test_key" } - expect(ssh_key.data_for_destruction).to eq valid_hash - end - - context 'when identifier is changed' do - before { ssh_key.identifier = 'foo' } - - it { is_expected.not_to be_valid } - end - - context 'when key is changed' do - before { ssh_key.key = 'foo' } - - it { is_expected.not_to be_valid } - end - - context 'when user_id is changed' do - before { ssh_key.user_id = @user2.id } - - it { is_expected.not_to be_valid } - end - - context 'when key_type is changed' do - before { ssh_key.key_type = 1 } - - it { is_expected.not_to be_valid } - end - - # Test reset_identifiers - context 'when identifiers are reset' do - before do - @old_identifier = ssh_key.identifier - @old_fingerprint = ssh_key.fingerprint - - ssh_key.reset_identifiers - end - - it { is_expected.to be_valid } - - it 'should have the same identifier' do - expect(ssh_key.identifier).to eq @old_identifier - end - - it 'should have the same fingerprint' do - expect(ssh_key.fingerprint).to eq @old_fingerprint - end - end - end - - describe 'Valid SSH key format' do - describe 'when ssh key format is valid' do - ssh_keys = [ - 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/Ec2gummukPxlpPHZ7K96iBdG5n8v0PJEDvTVZRRFlS0QYa407gj9HuMrPjwEfVHqy+3KZmvKLWQBsSlf0Fn+eAPg' \ - 'noqwVfZaJnfgkSxJiAzRraKQZX1m2wx2SVMfjw7/1j59zV60UhFiwEQ3Eqlg3xjQmjvrwDM+SoshrWB+TeqwO/K+QEP1ZbURYoCxc92GrLYWKixsAov/zr0loXqul9fy' \ - 'dZcWwJE3H/BWC7PTtn4jfjG9+9F+SZ0OMwQvSGKhVlj3GBDtaDBnsuoHGh/CA2W240nwpQysG2BJ5DWXu6vKbjNn6uV91wXeKDEDpuWqv5Vi2XAxGTWKc5lF0IJ5' \ - ' nicolas@tchoum', - 'ssh-dss AAAAB3NzaC1kc3MAAACBAKscxrmjRgXtb0ZUaaBUteBtF2cI0vStnni9KVQd94L8qqxvKLbDl5JTKjUvG2s7rD4sVRzBoTkuDGb7OZLf56wJyF3k+k8uNRJz' \ - 'vH/CZbkKM2hjuRVYVort1EwcH7JiEQr7bCLe7MRaltuo/M1vhapwy7fhKxAo9YoYVWiGoFTVAAAAFQDPywT8yFDahFvxtt/95Q9Emq8R7QAAAIBHYnvt3hT9NYy+nOuZ' \ - 'G+cQTz0hnVzUIWuj0XF2iyx52s2eSmF0HxIsZ0D9g2A0L1Xr/vlkWBMq/zJZJgJw2Ifys8L47HzjhL8K0Skdm23Z6rQR9hlOEZ5Rcank98U6VRYPWpYk7OLdRDruwXb+' \ - 'Ms5YhIztxsGO3YfRBdSBrW4DMAAAAIAJmmwivw3XoFP6C97LB+tJAjWRYJHpiDwOWNDKu0dZewUzUAo40NuHNgKJS2nsxW0sphaeMtf70IbvDsFQG45I+G2dlt+s19t4' \ - 'YCbVcz7xrw7LceEz+f0UR2/Z+LIK2GPIIoyymOq/kIIxni3xgKDl4mvvt45TTsQzs0zhkmEy/g== nicolas@tchoum', - 'ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLIcYw8NbJc28tDsC+8sf/o14hQmQfdC31OFP0eb5qFVRgEjMJ9mwolq' \ - 'WIW+AcbIAhX2GJVdTLZoUJj6T5PiUtM= nicolas@tchoum' - ] - - ssh_keys.each do |valid_key| - it 'should be valid' do - expect(build_ssh_key(key: valid_key)).to be_valid - end - end - end - end - - context 'when SSH key already exist' do - before { create_ssh_key(user_id: @user1.id, title: 'test-key2') } - - ## Test uniqueness validation - context 'and title is already taken' do - it { expect(build_ssh_key(user_id: @user1.id, title: 'test-key2', key: SSH_KEY_1)).not_to be_valid } - end - - context 'and is already taken by someone' do - it { expect(build_ssh_key(user_id: @user1.id, title: 'foo')).not_to be_valid } - end - - context 'and is already taken by current user' do - it 'should_not be_valid' do - User.current = @user1 - expect(build_ssh_key(user_id: @user1.id, title: 'foo')).not_to be_valid - end - end - - context 'and is already taken by other user and current user is admin' do - it 'should_not be_valid' do - @user2.admin = true - User.current = @user2 - expect(build_ssh_key(user_id: @user1.id, title: 'foo')).not_to be_valid - end - end - - context 'and is already taken by other user and current user is not admin' do - it 'should_not be_valid' do - User.current = @user2 - expect(build_ssh_key(user_id: @user1.id, title: 'foo')).not_to be_valid - end - end - end - - context 'when Gitolite Admin ssh key is reused' do - it 'should not be valid' do - expect(build_ssh_key(user_id: @user1.id, - title: 'foo', - key: File.read(RedmineGitHosting::Config.gitolite_ssh_public_key))).not_to be_valid - end - end - - context 'when many keys are saved' do - before do - create_ssh_key(user: @user1, title: 'active1', key: SSH_KEY_1, key_type: 1) - create_ssh_key(user: @user1, title: 'active2', key: SSH_KEY_2, key_type: 1) - create_ssh_key(user: @user2, title: 'active3', key: SSH_KEY_3) - create_ssh_key(user: @user2, title: 'active4', key: SSH_KEY_4) - end - - it 'should have 6 keys' do - expect(GitolitePublicKey.all.length).to be == 5 - end - - it 'should have 2 user keys' do - expect(GitolitePublicKey.user_key.length).to be == 2 - end - - it 'should have 4 deploy keys' do - expect(GitolitePublicKey.deploy_key.length).to be == 3 - end - - it 'user1 should have 2 keys' do - expect(@user1.gitolite_public_keys.length).to be == 2 - end - - it 'user2 should have 2 keys' do - expect(@user2.gitolite_public_keys.length).to be == 2 - end - end -end diff --git a/plugins/redmine_git_hosting/spec/models/group_spec.rb b/plugins/redmine_git_hosting/spec/models/group_spec.rb deleted file mode 100644 index d6e8d29..0000000 --- a/plugins/redmine_git_hosting/spec/models/group_spec.rb +++ /dev/null @@ -1,10 +0,0 @@ -require File.expand_path('../spec_helper', __dir__) - -describe Group do - subject { group } - - let(:group) { build(:group) } - - it { is_expected.to have_many(:protected_branches_members).dependent(:destroy) } - it { is_expected.to have_many(:protected_branches).through(:protected_branches_members) } -end diff --git a/plugins/redmine_git_hosting/spec/models/project_spec.rb b/plugins/redmine_git_hosting/spec/models/project_spec.rb deleted file mode 100644 index c52be6c..0000000 --- a/plugins/redmine_git_hosting/spec/models/project_spec.rb +++ /dev/null @@ -1,36 +0,0 @@ -require File.expand_path "#{File.dirname __FILE__}/../spec_helper" - -describe Project do - before(:all) do - @project = create(:project) - @git_repo_1 = create_git_repository(project: @project, is_default: true) - @git_repo_2 = create_git_repository(project: @project, identifier: 'git-repo-test') - @svn_repo_1 = create_svn_repository(project: @project, identifier: 'svn-repo-test', url: 'http://svn-repo-test') - end - - subject { @project } - - ## Test relations - it { should respond_to(:gitolite_repos) } - it { should respond_to(:repo_blank_ident) } - - it 'should have 1 repository with blank ident' do - expect(@project.repo_blank_ident).to eq @git_repo_1 - end - - it 'should have 2 Git repositories' do - expect(@project.gitolite_repos).to include @git_repo_1, @git_repo_2 - end - - it 'should have 3 repositories' do - expect(@project.repositories).to include @git_repo_1, @git_repo_2, @svn_repo_1 - end - - it 'should not match existing repository identifier' do - expect(build(:project, identifier: 'git-repo-test')).to be_invalid - end - - it 'should not match Gitolite Admin repository identifier' do - expect(build(:project, identifier: 'gitolite-admin')).to be_invalid - end -end diff --git a/plugins/redmine_git_hosting/spec/models/repository_deployment_credential_spec.rb b/plugins/redmine_git_hosting/spec/models/repository_deployment_credential_spec.rb deleted file mode 100644 index d25b82b..0000000 --- a/plugins/redmine_git_hosting/spec/models/repository_deployment_credential_spec.rb +++ /dev/null @@ -1,72 +0,0 @@ -require File.expand_path "#{File.dirname __FILE__}/../spec_helper" - -describe RepositoryDeploymentCredential do - DEPLOY_KEY = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCz0pLXcQWS4gLUimUSLwDOvEmQF8l8EKoj0LjxOyM3y2dpLsn0aiqS0ecA0G/ROomaawop8EZGFetoJKJM4' \ - '68OZlx2aKoQemzvFIq0Mn1ZhcrlA1alAsDYqzZI8iHO4JIS3YbeLLkVGAlYA+bmA5enXN9mGhC9cgoMC79EZiLD9XvOw4iXDjqXaCzFZHU1shMWwaJfpyxBm+' \ - 'Mxs2vtZzwETDqeu9rohNMl60dODf6+JoXYiahP+B+P2iKlL7ORb1YsAH/4ZMsVgRckj8snb4uc3XgwLRNNw+oB78ApZGr0j3Zc32U9rpmulbHIroWO07OV4Xs' \ - 'plnu8lhGvfodA2gjb nicolas@tchoum' - USER_KEY = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC5+JfM82k03J98GWL6ghJ4TYM8DbvDnVh1s1rUDNlM/1U5rwbgXHOR4xV3lulgYEYRtYeMoL3rt4ZpEyXWk' \ - 'OreOVsUlkW66SZJR5aGVTNJOLX7HruEDqj7RWlt0u0MH6DgBVAJimQrxYN50jYD4XnDUjb/qv55EhPvbJ3jcAb3zuyRXMKZYGNVzVFLUagbvVaOwR23csWSLD' \ - 'TsAEI9JzaxMKvCNRwk3jFepiCovXbw+g0iyvJdp0+AJpC57ZupyxHeX9J2oz7im2UaHHqLa2qUZL6c4PNV/D2p0Bts4Tcnn3OFPL90RF/ao0tjiUFxM3ti8pR' \ - 'HOqRcZHcOgIhKiaLX nicolas@tchoum' - - before(:all) do - users = create_list(:user, 2) - @user1 = users[0] - @user2 = users[1] - - @deploy_key = create(:gitolite_public_key, user: @user1, key_type: 1, title: 'foo1', key: DEPLOY_KEY) - @user_key = create(:gitolite_public_key, user: @user1, key_type: 0, title: 'foo2', key: USER_KEY) - end - - def build_deployment_credential(opts = {}) - build(:repository_deployment_credential, opts) - end - - describe 'Valid RepositoryDeploymentCredential creation' do - before(:each) do - @deployment_credential = build_deployment_credential(user: @user1, gitolite_public_key: @deploy_key) - end - - subject { @deployment_credential } - - ## Relations - it { should belong_to(:repository) } - it { should belong_to(:gitolite_public_key) } - it { should belong_to(:user) } - - ## Validations - it { should be_valid } - - it { should validate_presence_of(:repository_id) } - it { should validate_presence_of(:gitolite_public_key_id) } - it { should validate_presence_of(:user_id) } - it { should validate_presence_of(:perm) } - - it { should validate_inclusion_of(:perm).in_array(%w[R RW+]) } - - ## Attributes content - it 'is a active credential' do - expect(@deployment_credential.active?).to be true - end - - describe 'when active is false' do - before { @deployment_credential.active = false } - it 'shoud be inactive' do - expect(@deployment_credential.active?).to be false - end - end - end - - context 'when key is not a deployment key' do - it 'should not be valid' do - expect(build_deployment_credential(user: @user1, gitolite_public_key: @user_key)).not_to be_valid - end - end - - context 'when user id is not the owner of deployment key' do - it 'should not be valid' do - expect(build_deployment_credential(user: @user2, gitolite_public_key: @user_key)).not_to be_valid - end - end -end diff --git a/plugins/redmine_git_hosting/spec/models/repository_git_config_key/git_config_spec.rb b/plugins/redmine_git_hosting/spec/models/repository_git_config_key/git_config_spec.rb deleted file mode 100644 index bf8765e..0000000 --- a/plugins/redmine_git_hosting/spec/models/repository_git_config_key/git_config_spec.rb +++ /dev/null @@ -1,26 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') - -describe RepositoryGitConfigKey::GitConfig do - before(:each) do - @git_config_key = build(:repository_git_config_key) - end - - subject { @git_config_key } - - ## Validations - it { should be_valid } - it { should validate_presence_of(:key) } - it { should validate_uniqueness_of(:key).scoped_to(:repository_id) } - it { should allow_value('hookfoo.foo', 'hookfoo.foo.bar').for(:key) } - it { should_not allow_value('hookfoo').for(:key) } - - context 'when key is updated' do - before do - @git_config_key.save - @git_config_key.key = 'hookbar.foo' - @git_config_key.save - end - - it { should be_valid } - end -end diff --git a/plugins/redmine_git_hosting/spec/models/repository_git_config_key/option_spec.rb b/plugins/redmine_git_hosting/spec/models/repository_git_config_key/option_spec.rb deleted file mode 100644 index 22fa232..0000000 --- a/plugins/redmine_git_hosting/spec/models/repository_git_config_key/option_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') - -describe RepositoryGitConfigKey::Option do - before(:each) do - @git_config_key = build(:repository_git_option_key) - end - - subject { @git_config_key } - - ## Validations - it { should be_valid } - it { should validate_presence_of(:key) } - it { should validate_uniqueness_of(:key).scoped_to(:repository_id) } - it { should allow_value('hookfoo', 'hookfoo.foo', 'hookfoo.foo.bar').for(:key) } - - context 'when key is updated' do - before do - @git_config_key.save - @git_config_key.key = 'hookbar.foo' - @git_config_key.save - end - - it { should be_valid } - end -end diff --git a/plugins/redmine_git_hosting/spec/models/repository_git_config_key_spec.rb b/plugins/redmine_git_hosting/spec/models/repository_git_config_key_spec.rb deleted file mode 100644 index 0c0abb8..0000000 --- a/plugins/redmine_git_hosting/spec/models/repository_git_config_key_spec.rb +++ /dev/null @@ -1,14 +0,0 @@ -require File.expand_path "#{File.dirname __FILE__}/../spec_helper" - -describe RepositoryGitConfigKey do - let(:git_config_key) { build(:repository_git_config_key_base) } - - subject { git_config_key } - - ## Relations - it { should belong_to(:repository) } - - ## Validations - it { should validate_presence_of(:repository_id) } - it { should validate_presence_of(:value) } -end diff --git a/plugins/redmine_git_hosting/spec/models/repository_git_extra_spec.rb b/plugins/redmine_git_hosting/spec/models/repository_git_extra_spec.rb deleted file mode 100644 index 54e3a94..0000000 --- a/plugins/redmine_git_hosting/spec/models/repository_git_extra_spec.rb +++ /dev/null @@ -1,76 +0,0 @@ -require File.expand_path "#{File.dirname __FILE__}/../spec_helper" - -describe RepositoryGitExtra do - let(:git_extra) { build(:repository_git_extra) } - - subject { git_extra } - - ## Relations - it { should belong_to(:repository) } - - ## Validations - it { should be_valid } - - it { should validate_presence_of(:repository_id) } - it { should validate_presence_of(:default_branch) } - it { should validate_presence_of(:key) } - - it { should validate_uniqueness_of(:repository_id) } - - ## Serializations - # it { should serialize(:urls_order) } - - describe '#git_daemon' do - it 'should return the value for git_daemon' do - expect(git_extra.git_daemon).to be true - end - end - - describe '#git_http' do - it 'should return the value for git_http' do - expect(git_extra.git_http).to be false - end - end - - describe '#git_https' do - it 'should return the value for git_https' do - expect(git_extra.git_https).to be false - end - end - - describe '#git_go' do - it 'should return the value for git_go' do - expect(git_extra.git_go).to be false - end - end - - describe '#git_ssh' do - it 'should return the value for git_ssh' do - expect(git_extra.git_ssh).to be true - end - end - - describe '#git_notify' do - it 'should return the value for git_notify' do - expect(git_extra.git_notify).to be true - end - end - - describe '#default_branch' do - it 'should return the value for default_branch' do - expect(git_extra.default_branch).to eq 'master' - end - end - - describe '#protected_branch' do - it 'should return the value for protected_branch' do - expect(git_extra.protected_branch).to be false - end - end - - describe '#key' do - it 'should return the value for key' do - expect(git_extra.key).to match(/\A[a-zA-Z0-9]+\z/) - end - end -end diff --git a/plugins/redmine_git_hosting/spec/models/repository_mirror_spec.rb b/plugins/redmine_git_hosting/spec/models/repository_mirror_spec.rb deleted file mode 100644 index d4e585b..0000000 --- a/plugins/redmine_git_hosting/spec/models/repository_mirror_spec.rb +++ /dev/null @@ -1,156 +0,0 @@ -require File.expand_path "#{File.dirname __FILE__}/../spec_helper" - -describe RepositoryMirror do - VALID_URLS = [ - 'ssh://user@host.xz:2222/path/to/repo.git', - 'ssh://user@host.xz/path/to/repo.git', - 'ssh://user-name@long.host-domain.xz/path.git', - 'ssh://host.xz:2222/path/to/repo.git', - 'ssh://host.xz/path/to/repo.git', - 'ssh://user@host.xz/path/to/repo.git', - 'ssh://host.xz/path/to/repo.git', - 'ssh://user@host.xz/~user/path/to/repo.git', - 'ssh://host.xz/~user/path/to/repo.git', - 'ssh://user@host.xz/~/path/to/repo.git', - 'ssh://host.xz/~/path/to/repo.git', - 'ssh://host.xz/~/path.to/repo.git' - ] - - def build_mirror(opts = {}) - build(:repository_mirror, opts) - end - - def expect_invalid_refspec(refspec) - expect(build_mirror(push_mode: 1, explicit_refspec: refspec)).not_to be_valid - end - - def expect_valid_refspec(refspec) - expect(build_mirror(push_mode: 1, explicit_refspec: refspec)).to be_valid - end - - describe 'Valid RepositoryMirror creation' do - before(:each) do - @mirror = build(:repository_mirror) - end - - subject { @mirror } - - ## Relations - it { should belong_to(:repository) } - - ## Validations - it { should be_valid } - - it { should validate_presence_of(:repository_id) } - it { should validate_presence_of(:url) } - it { should validate_presence_of(:push_mode) } - - it { should validate_uniqueness_of(:url).scoped_to(:repository_id) } - - it { should allow_value(*VALID_URLS).for(:url) } - - it { should validate_numericality_of(:push_mode) } - - it { should validate_inclusion_of(:push_mode).in_array(%w(0 1 2)) } - - ## Attributes content - it { expect(@mirror.active).to be true } - it { expect(@mirror.include_all_branches).to be false } - it { expect(@mirror.include_all_tags).to be false } - it { expect(@mirror.explicit_refspec).to eq '' } - it { expect(@mirror.push_mode).to eq 0 } - it { expect(@mirror.push_mode).to be_a(Integer) } - - ## Test changes - describe 'when active is true' do - before { @mirror.active = true } - it 'shoud be active' do - expect(@mirror.active).to be true - end - end - - describe 'when active is false' do - before { @mirror.active = false } - it 'should be inactive' do - expect(@mirror.active).to be false - end - end - - context 'it should accept different refspec format' do - it 'should accept ' do - expect_valid_refspec 'devel' - end - - it 'should accept a branch path' do - expect_valid_refspec 'refs/branches/dev' - end - - it 'should accept the update param (+)' do - expect_valid_refspec '+refs/branches/dev' - end - - it 'should accept the wildcard param (*)' do - expect_valid_refspec '+refs/branches/*' - end - - it 'should accept a destination' do - expect_valid_refspec '+refs/branches/*:refs/branches/*' - expect_valid_refspec '+refs/heads/experiment:refs/remotes/origin/experiment' - expect_valid_refspec '+devel:devel' - expect_valid_refspec '+devel:devel/*' - end - end - end - - describe 'Invalid Mirror creation' do - ## Test presence conflicts - it 'is invalid when include_all_branches && include_all_tags' do - expect(build_mirror(push_mode: 1, include_all_branches: true, include_all_tags: true)).not_to be_valid - end - - it 'is invalid when include_all_branches && explicit_refspec' do - expect(build_mirror(push_mode: 1, include_all_branches: true, explicit_refspec: 'devel')).not_to be_valid - end - - ## Validate push mode : forced - it 'is invalid when push_mode forced without params' do - expect(build_mirror(push_mode: 1)).not_to be_valid - end - - ## Validate push mode : fast_forward - it 'is invalid when push_mode fast_forward without params' do - expect(build_mirror(push_mode: 2)).not_to be_valid - end - - ## Validate explicit_refspec - it 'should check that and are well formated' do - expect_invalid_refspec ':' - expect_invalid_refspec ':devel' - expect_invalid_refspec ':/devel' - expect_invalid_refspec '/devel:/devel' - expect_invalid_refspec 'devel:/devel' - expect_invalid_refspec '/devel:devel' - expect_invalid_refspec '/devel:devel/*' - expect_invalid_refspec '+refs/branches*:refs/branches*' - expect_invalid_refspec '+refs/branches*:refs/branches/*' - expect_invalid_refspec '+refs/branches/*:refs/branches' - expect_invalid_refspec '+refs/branches/*:refs/branches/' - expect_invalid_refspec '+refs/branches:refs/branches/*' - expect_invalid_refspec '+refs/branches/:refs/branches/*' - expect_invalid_refspec '+refs/branches/v[0-9]:refs/branches/v[0-9]' - expect_invalid_refspec '+refs/branches/v[0-9]/refs/branches/v[0-9]' - end - end - - context 'when many mirror are saved' do - before do - create(:repository_mirror, active: true) - create(:repository_mirror, active: true) - create(:repository_mirror, active: false) - create(:repository_mirror, active: false) - end - - it { expect(RepositoryMirror.active.length).to be == 3 } - it { expect(RepositoryMirror.inactive.length).to be == 2 } - end -end diff --git a/plugins/redmine_git_hosting/spec/models/repository_post_receive_url_spec.rb b/plugins/redmine_git_hosting/spec/models/repository_post_receive_url_spec.rb deleted file mode 100644 index 50a7c60..0000000 --- a/plugins/redmine_git_hosting/spec/models/repository_post_receive_url_spec.rb +++ /dev/null @@ -1,47 +0,0 @@ -require File.expand_path "#{File.dirname __FILE__}/../spec_helper" - -describe RepositoryPostReceiveUrl do - let(:post_receive_url) { build(:repository_post_receive_url) } - - subject { post_receive_url } - - ## Relations - it { should belong_to(:repository) } - - ## Validations - it { should be_valid } - - it { should validate_presence_of(:repository_id) } - it { should validate_presence_of(:url) } - it { should validate_presence_of(:mode) } - - it { should validate_uniqueness_of(:url).scoped_to(:repository_id) } - - it { should validate_inclusion_of(:mode).in_array(%i[github get]) } - - it { should allow_value('http://foo.com', 'https://bar.com/baz').for(:url) } - - ## Serializations - # it { should serialize(:triggers) } - - ## Attributes content - it { expect(post_receive_url.active).to be true } - it { expect(post_receive_url.mode).to eq :github } - it { expect(post_receive_url.use_triggers).to be false } - it { expect(post_receive_url.triggers).to be_a(Array) } - it { expect(post_receive_url.split_payloads).to be false } - - # describe '.active' do - # it 'should return an array of active post_receive_urls' do - # expect(RepositoryPostReceiveUrl).to receive(:where).with(active: true) - # RepositoryPostReceiveUrl.active - # end - # end - - # describe '.inactive' do - # it 'should return an array of inactive post_receive_urls' do - # expect(RepositoryPostReceiveUrl).to receive(:where).with(active: false) - # RepositoryPostReceiveUrl.inactive - # end - # end -end diff --git a/plugins/redmine_git_hosting/spec/models/repository_protected_branche_spec.rb b/plugins/redmine_git_hosting/spec/models/repository_protected_branche_spec.rb deleted file mode 100644 index 5cbe667..0000000 --- a/plugins/redmine_git_hosting/spec/models/repository_protected_branche_spec.rb +++ /dev/null @@ -1,50 +0,0 @@ -require File.expand_path "#{File.dirname __FILE__}/../spec_helper" - -describe RepositoryProtectedBranche do - let(:protected_branch) { build(:repository_protected_branche) } - - subject { protected_branch } - - ## Relations - it { should belong_to(:repository) } - it { should have_many(:protected_branches_members).with_foreign_key(:protected_branch_id).dependent(:destroy) } - it { should have_many(:members).through(:protected_branches_members) } - - ## Validations - it { should be_valid } - - it { should validate_presence_of(:repository_id) } - it { should validate_presence_of(:path) } - it { should validate_presence_of(:permissions) } - - it { should validate_uniqueness_of(:path).scoped_to(%i[permissions repository_id]) } - - it { should validate_inclusion_of(:permissions).in_array RepositoryProtectedBranche::VALID_PERMS } - - describe '#users' do - it 'should return an array of users' do - user = build(:user) - group = build(:group) - expect(protected_branch).to receive(:members).and_return([user, user, group]) - expect(protected_branch.users).to eq [user] - end - end - - describe '#groups' do - it 'should return an array of groups' do - user = build(:user) - group = build(:group) - expect(protected_branch).to receive(:members).and_return([group, user, group]) - expect(protected_branch.groups).to eq [group] - end - end - - describe '#allowed_users' do - it 'should return an array of gitolite identifiers' do - user1 = build(:user) - user2 = build(:user) - expect(protected_branch).to receive(:users).and_return([user1, user2]) - expect(protected_branch.allowed_users).to eq [user1.gitolite_identifier, user2.gitolite_identifier] - end - end -end diff --git a/plugins/redmine_git_hosting/spec/models/repository_xitolite_spec.rb b/plugins/redmine_git_hosting/spec/models/repository_xitolite_spec.rb deleted file mode 100644 index 85601f1..0000000 --- a/plugins/redmine_git_hosting/spec/models/repository_xitolite_spec.rb +++ /dev/null @@ -1,298 +0,0 @@ -require File.expand_path "#{File.dirname __FILE__}/../spec_helper" - -describe Repository::Xitolite do - GIT_USER = 'git'.freeze - - before(:all) do - Setting.plugin_redmine_git_hosting[:gitolite_redmine_storage_dir] = 'redmine/' - Setting.plugin_redmine_git_hosting[:http_server_subdir] = 'git/' - User.current = nil - - @project_parent = FactoryBot.create(:project, identifier: 'project-parent') - @project_child = FactoryBot.create(:project, identifier: 'project-child', parent_id: @project_parent.id, is_public: false) - end - - describe 'common_tests : fast tests' do - before(:each) do - Setting.plugin_redmine_git_hosting[:hierarchical_organisation] = 'true' - Setting.plugin_redmine_git_hosting[:unique_repo_identifier] = 'false' - - @repository_1 = build_git_repository(project: @project_child, is_default: true) - @repository_1.valid? - @repository_1.build_extra(default_branch: 'master', key: RedmineGitHosting::Utils::Crypto.generate_secret(64), git_https: true) - end - - subject { @repository_1 } - - it { should be_valid } - - ## Relations - it { should have_many(:mirrors) } - it { should have_many(:post_receive_urls) } - it { should have_many(:deployment_credentials) } - it { should have_many(:git_config_keys) } - it { should have_many(:protected_branches) } - - it { should have_one(:extra) } - - ## Attributes - it { expect(@repository_1.report_last_commit).to be true } - it { expect(@repository_1.extra_report_last_commit).to be true } - it { expect(@repository_1.git_default_branch).to eq 'master' } - it { expect(@repository_1.gitolite_hook_key).to match(/\A[a-zA-Z0-9]+\z/) } - it { expect(@repository_1.git_daemon_enabled?).to be true } - it { expect(@repository_1.git_annex_enabled?).to be false } - it { expect(@repository_1.git_notification_enabled?).to be true } - it { expect(@repository_1.smart_http_enabled?).to be true } - it { expect(@repository_1.https_access_enabled?).to be true } - it { expect(@repository_1.http_access_enabled?).to be false } - it { expect(@repository_1.only_https_access_enabled?).to be true } - it { expect(@repository_1.only_http_access_enabled?).to be false } - it { expect(@repository_1.protected_branches_enabled?).to be false } - it { expect(@repository_1.public_project?).to be false } - it { expect(@repository_1.public_repo?).to be false } - it { expect(@repository_1.urls_order).to eq [] } - - it 'should not allow identifier gitolite-admin' do - expect(build_git_repository(project: @project_parent, identifier: 'gitolite-admin')).to be_invalid - end - - describe '#exists_in_gitolite?' do - it 'should check if repository exists on Gitolite side' do - expect(RedmineGitHosting::Commands).to receive(:sudo_dir_exists?).with('repositories/redmine/project-parent/project-child.git') - @repository_1.exists_in_gitolite? - end - end - - describe '#empty_in_gitolite?' do - it 'should check if repository is empty on Gitolite side' do - expect(RedmineGitHosting::Commands).to receive(:sudo_repository_empty?) - .with('repositories/redmine/project-parent/project-child.git') - @repository_1.empty_in_gitolite? - end - end - - describe '#git_objects_count' do - it 'should return repository objects count' do - expect(RedmineGitHosting::Commands).to receive(:sudo_git_objects_count) - .with('repositories/redmine/project-parent/project-child.git/objects') - @repository_1.git_objects_count - end - end - - describe '#data_for_destruction' do - it 'should return a hash of data' do - expect(@repository_1.data_for_destruction).to eq( - { - delete_repository: true, - git_cache_id: 'project-child', - repo_name: 'redmine/project-parent/project-child', - repo_path: "#{HOME_BASE_DIR}/git/repositories/redmine/project-parent/project-child.git" - } - ) - end - end - - describe '#empty?' do - it 'should check if repository is empty from Redmine point of view' do - expect(@repository_1.empty?).to be true - end - end - - describe '#empty_cache!' do - it 'should flush the repository git cache' do - expect(RedmineGitHosting::Cache).to receive(:clear_cache_for_repository).with('project-child') - @repository_1.empty_cache! - end - end - - describe '#available_urls' do - context 'with no option' do - my_hash = {} - - it 'should return an empty Hash' do - @repository_1.extra[:git_daemon] = false - @repository_1.extra[:git_http] = false - @repository_1.extra[:git_https] = false - @repository_1.extra[:git_go] = false - @repository_1.extra[:git_ssh] = false - expect(@repository_1.available_urls).to eq my_hash - end - end - - context 'with all options' do - my_hash = { - ssh: { url: "ssh://#{GIT_USER}@localhost/redmine/project-parent/project-child.git", committer: 'true' }, - https: { url: 'https://redmine-test-user@localhost/git/project-parent/project-child.git', committer: 'true' }, - http: { url: 'http://redmine-test-user@localhost/git/project-parent/project-child.git', committer: 'false' }, - go: { url: 'localhost/go/project-parent/project-child', committer: 'false' }, - git: { url: 'git://localhost/redmine/project-parent/project-child.git', committer: 'false' } - } - - it 'should return a Hash of Git url' do - @user = create_user_with_permissions(@project_child, login: 'redmine-test-user') - User.current = @user - @project_child.is_public = true - @repository_1.extra[:git_daemon] = true - @repository_1.extra[:git_http] = true - @repository_1.extra[:git_https] = true - @repository_1.extra[:git_go] = true - @repository_1.extra[:git_ssh] = true - @repository_1.extra.save - expect(@repository_1.available_urls).to eq my_hash - end - end - - context 'with git daemon' do - my_hash = { git: { url: 'git://localhost/redmine/project-parent/project-child.git', committer: 'false' } } - - it 'should return a Hash of Git url' do - User.current = nil - @project_child.is_public = true - @repository_1.extra[:git_daemon] = true - @repository_1.extra[:git_http] = false - @repository_1.extra[:git_https] = false - @repository_1.extra[:git_go] = false - @repository_1.extra[:git_ssh] = false - @repository_1.extra.save - expect(@repository_1.available_urls).to eq my_hash - end - end - - context 'with ssh' do - my_hash = { ssh: { url: "ssh://#{GIT_USER}@localhost/redmine/project-parent/project-child.git", committer: 'true' } } - - it 'should return a Hash of Git url' do - @user = create_user_with_permissions(@project_child, login: 'redmine-test-user') - User.current = @user - @repository_1.extra[:git_daemon] = false - @repository_1.extra[:git_http] = false - @repository_1.extra[:git_https] = false - @repository_1.extra[:git_go] = false - @repository_1.extra[:git_ssh] = true - @repository_1.extra.save - expect(@repository_1.available_urls).to eq my_hash - end - end - - context 'with http' do - my_hash = { http: { url: 'http://localhost/git/project-parent/project-child.git', committer: 'false' } } - - it 'should return a Hash of Git url' do - User.current = nil - @project_child.is_public = false - @repository_1.extra[:git_daemon] = false - @repository_1.extra[:git_http] = true - @repository_1.extra[:git_https] = false - @repository_1.extra[:git_go] = false - @repository_1.extra[:git_ssh] = false - @repository_1.extra.save - expect(@repository_1.available_urls).to eq my_hash - end - end - - context 'with https' do - my_hash = { https: { url: 'https://localhost/git/project-parent/project-child.git', committer: 'false' } } - - it 'should return a Hash of Git url' do - User.current = nil - @project_child.is_public = false - @repository_1.extra[:git_daemon] = false - @repository_1.extra[:git_http] = false - @repository_1.extra[:git_https] = true - @repository_1.extra[:git_go] = false - @repository_1.extra[:git_ssh] = false - @repository_1.extra.save - expect(@repository_1.available_urls).to eq my_hash - end - end - - context 'with http and https' do - my_hash = { - https: { url: 'https://localhost/git/project-parent/project-child.git', committer: 'false' }, - http: { url: 'http://localhost/git/project-parent/project-child.git', committer: 'false' } - } - - it 'should return a Hash of Git url' do - User.current = nil - @project_child.is_public = false - @repository_1.extra[:git_daemon] = false - @repository_1.extra[:git_http] = true - @repository_1.extra[:git_https] = true - @repository_1.extra[:git_go] = false - @repository_1.extra[:git_ssh] = false - @repository_1.extra.save - expect(@repository_1.available_urls).to eq my_hash - end - end - end - - describe 'Repository::Xitolite class' do - it { expect(Repository::Xitolite).to respond_to(:repo_ident_unique?) } - it { expect(Repository::Xitolite).to respond_to(:have_duplicated_identifier?) } - it { expect(Repository::Xitolite).to respond_to(:repo_path_to_git_cache_id) } - it { expect(Repository::Xitolite).to respond_to(:find_by_path) } - end - end - - describe 'common_tests : long tests' do - before do - Setting.plugin_redmine_git_hosting[:hierarchical_organisation] = 'true' - Setting.plugin_redmine_git_hosting[:unique_repo_identifier] = 'false' - - @repository_1 = create_git_repository(project: @project_child, is_default: true) - extra = @repository_1.build_extra(default_branch: 'master', key: RedmineGitHosting::Utils::Crypto.generate_secret(64)) - extra.save! - - @repository_2 = create_git_repository(project: @project_child, identifier: 'repo-test') - end - - context 'when blank identifier' do - it 'should not allow identifier changes' do - @repository_1.identifier = 'new_repo' - expect(@repository_1).to be_invalid - expect(@repository_1.identifier).to eq 'new_repo' - end - end - - context 'when non blank identifier' do - it 'should not allow identifier changes' do - @repository_2.identifier = 'new_repo2' - expect(@repository_2).to be_valid - expect(@repository_2.identifier).to eq 'repo-test' - end - end - - describe 'Test uniqueness' do - context 'when blank identifier is already taken by a repository' do - it { expect(build_git_repository(project: @project_child, identifier: '')).to be_invalid } - end - - context 'when set as default and blank identifier is already taken by a repository' do - it { expect(build_git_repository(project: @project_child, identifier: '', is_default: true)).to be_invalid } - end - - context 'when identifier is already taken by a project' do - it { expect(build_git_repository(project: @project_child, identifier: 'project-child')).to be_invalid } - end - - context 'when identifier is already taken by a repository with same project' do - it { expect(build_git_repository(project: @project_child, identifier: 'repo-test')).to be_invalid } - end - - context 'when identifier are not unique' do - it { expect(build_git_repository(project: @project_parent, identifier: 'repo-test')).to be_valid } - end - - context 'when identifier are unique' do - it 'should refuse duplicated identifier' do - Setting.plugin_redmine_git_hosting[:unique_repo_identifier] = 'true' - expect(build_git_repository(project: @project_parent, identifier: 'repo-test')).to be_invalid - end - end - end - end - - include_context 'flat_organisation' - include_context 'hierarchical_organisation' -end diff --git a/plugins/redmine_git_hosting/spec/models/setting_spec.rb b/plugins/redmine_git_hosting/spec/models/setting_spec.rb deleted file mode 100644 index 39512f2..0000000 --- a/plugins/redmine_git_hosting/spec/models/setting_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require File.expand_path "#{File.dirname __FILE__}/../spec_helper" - -describe Setting do - before do - RedmineGitHosting::Config.reload_from_file! - @settings = Setting.plugin_redmine_git_hosting - @default_settings = Redmine::Plugin.find('redmine_git_hosting').settings[:default] - end - - subject { @settings } - - it { should be_an_instance_of(Hash) } - - # it { expect(@settings).to eq @default_settings } -end diff --git a/plugins/redmine_git_hosting/spec/models/user_spec.rb b/plugins/redmine_git_hosting/spec/models/user_spec.rb deleted file mode 100644 index d8f0665..0000000 --- a/plugins/redmine_git_hosting/spec/models/user_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require File.expand_path('../spec_helper', __dir__) - -describe User do - let(:user) { build(:user) } - - it { is_expected.to have_many(:protected_branches_members).dependent(:destroy) } - it { is_expected.to have_many(:protected_branches).through(:protected_branches_members) } - - describe '#gitolite_identifier' do - it 'return the gitolite_identifier' do - user = build(:user, login: 'adam.30', id: 12) - expect(user.gitolite_identifier).to eq 'redmine_adam_30_12' - end - end -end diff --git a/plugins/redmine_git_hosting/spec/root_spec_helper.rb b/plugins/redmine_git_hosting/spec/root_spec_helper.rb deleted file mode 100644 index 428e068..0000000 --- a/plugins/redmine_git_hosting/spec/root_spec_helper.rb +++ /dev/null @@ -1,55 +0,0 @@ -if ENV['COVERAGE'] - require 'simplecov' - - ## Start Simplecov - SimpleCov.start 'rails' do - add_group 'Redmine Git Hosting', 'plugins/redmine_git_hosting' - end -end - -unless defined? 'HOME_BASE_DIR' - HOME_BASE_DIR = RUBY_PLATFORM.include?('darwin') ? '/Users' : '/home' -end - -## Load Redmine App -ENV['RAILS_ENV'] = 'test' -require File.expand_path "#{File.dirname __FILE__}/../config/environment" -require 'rspec/rails' - -## Load FactoryBots factories -Dir[Rails.root.join('plugins/*/spec/factories/**/*.rb')].each { |f| require f } - -Dir[Rails.root.join('plugins/*/spec/support/**/*.rb')].each { |f| require f } - -## Configure RSpec -RSpec.configure do |config| - config.include FactoryBot::Syntax::Methods - - config.infer_spec_type_from_file_location! - - config.color = true - config.fail_fast = false - - config.expect_with :rspec do |c| - c.syntax = :expect - end - - config.before(:suite) do - DatabaseCleaner.clean_with(:truncation) - end - - config.before(:each) do - DatabaseCleaner.strategy = :transaction - end - - config.before(:each) do - DatabaseCleaner.start - end - - config.after(:each) do - DatabaseCleaner.clean - end -end - -# Disable Test::Unit automatic runner -Test::Unit::AutoRunner.need_auto_run = false if defined?(Test::Unit::AutoRunner) diff --git a/plugins/redmine_git_hosting/spec/services/redmine_hooks/call_webservices_spec.rb b/plugins/redmine_git_hosting/spec/services/redmine_hooks/call_webservices_spec.rb deleted file mode 100644 index 19605dc..0000000 --- a/plugins/redmine_git_hosting/spec/services/redmine_hooks/call_webservices_spec.rb +++ /dev/null @@ -1,52 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') - -describe RedmineHooks::CallWebservices do - let(:global_payload) { load_yaml_fixture('global_payload.yml') } - let(:master_payload) { load_yaml_fixture('master_payload.yml') } - let(:branches_payload) { load_yaml_fixture('branches_payload.yml') } - - def build_web_hook(payload, opts = {}) - post_receive_url = build(:repository_post_receive_url, opts) - RedmineHooks::CallWebservices.new(post_receive_url, payload) - end - - describe '#needs_push' do - context 'when payload is empty' do - it 'shoud return false' do - web_hook = build_web_hook([]) - expect(web_hook.needs_push?).to be false - end - end - - context 'when triggers are not used' do - it 'should return the global payload to push' do - web_hook = build_web_hook(global_payload) - expect(web_hook.needs_push?).to be true - expect(web_hook.payloads_to_send).to eq global_payload - end - end - - context 'when triggers are empty' do - it 'should return the global payload to push' do - web_hook = build_web_hook(global_payload, use_triggers: true) - expect(web_hook.needs_push?).to be false - expect(web_hook.payloads_to_send).to eq [] - end - end - - context 'when triggers is set to master' do - it 'should return the master payload' do - web_hook = build_web_hook(global_payload, use_triggers: true, triggers: ['master']) - expect(web_hook.needs_push?).to be true - expect(web_hook.payloads_to_send).to eq master_payload - end - end - - context 'when triggers is set to master' do - it 'should not be found in branches payload and return false' do - web_hook = build_web_hook(branches_payload, use_triggers: true, triggers: ['master']) - expect(web_hook.needs_push?).to be false - end - end - end -end diff --git a/plugins/redmine_git_hosting/spec/spec_helper.rb b/plugins/redmine_git_hosting/spec/spec_helper.rb deleted file mode 100644 index 353eaa5..0000000 --- a/plugins/redmine_git_hosting/spec/spec_helper.rb +++ /dev/null @@ -1,14 +0,0 @@ -require File.expand_path "#{File.dirname __FILE__}/../../../spec/spec_helper" - -HOME_BASE_DIR = RUBY_PLATFORM.include?('darwin') ? '/Users' : '/home' - -## Configure RSpec -RSpec.configure do |config| - # Include our helpers from support directory - config.include GlobalHelpers - - config.before(:suite) do - RedmineGitHosting::Config.reload_from_file! - Setting.enabled_scm = %w[Git Subversion Xitolite] - end -end diff --git a/plugins/redmine_git_hosting/spec/support/crud_controller_spec/base.rb b/plugins/redmine_git_hosting/spec/support/crud_controller_spec/base.rb deleted file mode 100644 index 20e4814..0000000 --- a/plugins/redmine_git_hosting/spec/support/crud_controller_spec/base.rb +++ /dev/null @@ -1,231 +0,0 @@ -module CrudControllerSpec - module Base - extend ActiveSupport::Concern - - included do - include CrudControllerSpec::Helpers - - before(:all) do - @project = create_project 'git_project' - @repository = find_or_create_git_repository project: @project, identifier: 'git_repository' - @repository2 = find_or_create_git_repository project: @project, identifier: 'git_repository2' - @member_user = create_user_with_permissions @project, member_user_options - @anonymous_user = create_anonymous_user - @object = create_object - end - - unless respond_to?(:skip_actions) && skip_actions.include?('index') - describe 'GET #index' do - context 'with sufficient permissions' do - before(:each) { set_session_user(@member_user) } - - it 'renders the :index view' do - check_index_template - end - end - - context 'with unsufficient permissions' do - it 'renders 403' do - set_session_user @anonymous_user - check_index_status 403 - end - end - end - end - - unless respond_to?(:skip_actions) && skip_actions.include?('show') - describe 'GET #show' do - before { Setting.rest_api_enabled = 1 } - - context 'with sufficient permissions' do - it 'renders 200' do - check_api_response 200, id: @object.id, key: @member_user.api_key - end - end - - context 'with unsufficient permissions' do - it 'renders 403' do - check_api_response 403, id: @object.id, key: @anonymous_user.api_key - end - end - end - end - - unless respond_to?(:skip_actions) && skip_actions.include?('new') - describe 'GET #new' do - context 'with sufficient permissions' do - before(:each) { set_session_user(@member_user) } - - it 'assigns a new @object variable' do - check_new_variable main_variable, tested_klass - end - - it 'renders the :new template' do - check_new_template - end - end - - context 'with unsufficient permissions' do - it 'renders 403' do - set_session_user @anonymous_user - check_new_status 403 - end - end - end - end - - unless respond_to?(:skip_actions) && skip_actions.include?('create') - describe 'POST #create' do - context 'with sufficient permissions' do - before(:each) do - set_session_user @member_user - allow(controller).to receive(:call_use_case) - end - - context 'with valid attributes' do - it 'saves the new object in the database' do - check_counter_incremented_on_create tested_klass, valid_params_for_create - end - - it 'redirects to the repository page' do - check_create_status 200, valid_params_for_create - end - end - - context 'with invalid attributes' do - it 'does not save the new object in the database' do - check_counter_not_changed_on_create tested_klass, invalid_params_for_create - end - - it 're-renders the :new template' do - check_create_template :create, invalid_params_for_create - end - end - end - - context 'with unsufficient permissions' do - it 'renders 403' do - set_session_user @anonymous_user - check_create_status 403, valid_params_for_create - end - end - end - end - - unless respond_to?(:skip_actions) && skip_actions.include?('edit') - describe 'GET #edit' do - context 'with sufficient permissions' do - before(:each) { set_session_user(@member_user) } - - context 'with existing object' do - it 'assigns the requested object to @object' do - check_edit_variable main_variable, @object, id: @object.id - end - - it 'renders the :edit template' do - check_edit_template id: @object.id - end - end - - context 'with non-existing object' do - it 'renders 404' do - check_edit_status 404, id: 100 - end - end - - context 'with non-matching repository' do - it 'renders 404' do - check_edit_status 404, repository_id: @repository2.id, id: @object.id - end - end - - context 'with non-existing repository' do - it 'renders 404' do - check_edit_status 404, repository_id: 345, id: @object.id - end - end - end - - context 'with unsufficient permissions' do - it 'renders 403' do - set_session_user @anonymous_user - check_edit_status 403, id: @object.id - end - end - end - end - - unless respond_to?(:skip_actions) && skip_actions.include?('update') - describe 'PUT #update' do - context 'with sufficient permissions' do - before(:each) do - set_session_user @member_user - allow(controller).to receive(:call_use_case) - end - - context 'with valid attributes' do - it 'located the requested @object' do - check_update_variable main_variable, @object, valid_params_for_update - end - - it 'changes @object attributes' do - check_attribute_has_changed updated_attribute, updated_attribute_value, valid_params_for_update - end - - it 'redirects to the repository page' do - check_update_status 200, valid_params_for_update - end - end - - context 'with invalid attributes' do - it 'located the requested @object' do - check_update_variable main_variable, @object, invalid_params_for_update - end - - it 'does not change @object attributes' do - check_attribute_has_not_changed updated_attribute, invalid_params_for_update - end - - it 're-renders the :edit template' do - check_update_template invalid_params_for_update - end - end - end - - context 'with unsufficient permissions' do - it 'renders 403' do - set_session_user @anonymous_user - check_update_status 403, valid_params_for_update - end - end - end - end - - unless respond_to?(:skip_actions) && skip_actions.include?('destroy') - describe 'DELETE #destroy' do - context 'with sufficient permissions' do - before(:each) do - set_session_user @member_user - allow(controller).to receive(:call_use_case) - end - - it 'deletes the object' do - check_counter_decremented_on_delete tested_klass, id: create_object.id - end - - it 'redirects to repositories#edit' do - check_delete_status 200, id: create_object.id - end - end - - context 'with unsufficient permissions' do - it 'renders 403' do - set_session_user @anonymous_user - check_delete_status 403, id: create_object.id - end - end - end - end - end - end -end diff --git a/plugins/redmine_git_hosting/spec/support/crud_controller_spec/helpers.rb b/plugins/redmine_git_hosting/spec/support/crud_controller_spec/helpers.rb deleted file mode 100644 index 742c3c0..0000000 --- a/plugins/redmine_git_hosting/spec/support/crud_controller_spec/helpers.rb +++ /dev/null @@ -1,143 +0,0 @@ -module CrudControllerSpec - module Helpers - ##### INDEX - def check_index_template - get :index, params: base_options - assert_response :success - end - - def check_index_status(status) - get :index, params: base_options - check_status status - end - - ##### SHOW - - def check_api_response(status, opts = {}) - get :show, params: merge_options(opts).merge(format: 'json') - check_status status - end - - ##### NEW - - def check_new_variable(_variable, _klass) - get :new, params: base_options, xhr: true - assert_response :success - end - - def check_new_template - get :new, params: base_options, xhr: true - assert_response :success - end - - def check_new_status(status) - get :new, params: base_options, xhr: true - check_status status - end - - ##### CREATE - - def check_create_template(_template, opts = {}) - xhr_post merge_options opts - end - - def check_create_status(status, opts = {}) - xhr_post merge_options opts - check_status status - end - - def check_counter_incremented_on_create(klass, opts = {}) - expect { xhr_post merge_options(opts) }.to change(klass, :count).by(1) - end - - def check_counter_not_changed_on_create(klass, opts = {}) - expect { xhr_post merge_options(opts) }.not_to change(klass, :count) - end - - ##### EDIT - - def check_edit_variable(variable, value, opts = {}) - get :edit, params: merge_options(opts), xhr: true - end - - def check_edit_template(opts = {}) - get :edit, params: merge_options(opts), xhr: true - assert_response :success - end - - def check_edit_status(status, opts = {}) - get :edit, params: merge_options(opts), xhr: true - check_status status - end - - ##### UPDATE - - def check_update_variable(variable, value, opts = {}) - xhr_put merge_options(opts) - @object.reload - end - - def check_attribute_has_changed(method, value, opts = {}) - xhr_put merge_options(opts) - @object.reload - check_equality(@object.send(method), value) - end - - def check_attribute_has_not_changed(method, opts = {}) - old_value = @object.send(method) - xhr_put merge_options(opts) - @object.reload - check_equality(@object.send(method), old_value) - end - - def check_update_template(opts = {}) - xhr_put merge_options(opts) - end - - def check_update_status(status, opts = {}) - xhr_put merge_options(opts) - check_status status - end - - ##### DELETE - - def check_counter_decremented_on_delete(klass, opts = {}) - expect { delete :destroy, params: merge_options(opts).merge(format: 'js') }.to change(klass, :count).by(-1) - end - - def check_delete_status(status, opts = {}) - delete :destroy, params: merge_options(opts).merge(format: 'js') - check_status status - end - - private - - def base_options - { repository_id: @repository.id }.clone - end - - def merge_options(opts = {}) - base_options.merge(opts) - end - - def member_user_options - { permissions: permissions } - end - - def check_status(status) - expect(response.status).to eq status - end - - def check_equality(variable, value) - expect(variable).to eq value - end - - def xhr_post(opts = {}) - post :create, params: opts, xhr: true - end - - def xhr_put(opts = {}) - put :update, params: opts, xhr: true - end - end -end diff --git a/plugins/redmine_git_hosting/spec/support/flat_organization.rb b/plugins/redmine_git_hosting/spec/support/flat_organization.rb deleted file mode 100644 index 409a30a..0000000 --- a/plugins/redmine_git_hosting/spec/support/flat_organization.rb +++ /dev/null @@ -1,186 +0,0 @@ -RSpec.shared_context 'flat_organisation' do - ################################################## - # # - # FLAT ORGANISATION / UNIQUE REPOSITORIES TESTS # - # # - ################################################## - - UNIQUE_REPOSITORIES_MATRIX = { - repository_1: { - is_default: true, - identifier: '', - url: 'repositories/redmine/project-child.git', - root_url: 'repositories/redmine/project-child.git', - git_cache_id: 'project-child', - redmine_name: 'project-child', - gitolite_repository_path: 'repositories/redmine/project-child.git', - gitolite_full_repository_path: "#{HOME_BASE_DIR}/git/repositories/redmine/project-child.git", - gitolite_repository_name: 'redmine/project-child', - redmine_repository_path: 'project-child', - new_repository_name: 'redmine/project-child', - old_repository_name: 'redmine/project-child', - http_user_login: '', - git_access_path: 'redmine/project-child.git', - http_access_path: 'git/project-child.git', - ssh_url: "ssh://#{GIT_USER}@localhost/redmine/project-child.git", - git_url: 'git://localhost/redmine/project-child.git', - http_url: 'http://localhost/git/project-child.git', - https_url: 'https://localhost/git/project-child.git' - }, - - repository_2: { - is_default: false, - identifier: 'repo1-test', - url: 'repositories/redmine/repo1-test.git', - root_url: 'repositories/redmine/repo1-test.git', - git_cache_id: 'repo1-test', - redmine_name: 'repo1-test', - gitolite_repository_path: 'repositories/redmine/repo1-test.git', - gitolite_full_repository_path: "#{HOME_BASE_DIR}/git/repositories/redmine/repo1-test.git", - gitolite_repository_name: 'redmine/repo1-test', - redmine_repository_path: 'repo1-test', - new_repository_name: 'redmine/repo1-test', - old_repository_name: 'redmine/repo1-test', - http_user_login: '', - git_access_path: 'redmine/repo1-test.git', - http_access_path: 'git/repo1-test.git', - ssh_url: "ssh://#{GIT_USER}@localhost/redmine/repo1-test.git", - git_url: 'git://localhost/redmine/repo1-test.git', - http_url: 'http://localhost/git/repo1-test.git', - https_url: 'https://localhost/git/repo1-test.git' - }, - - repository_3: { - is_default: true, - identifier: '', - url: 'repositories/redmine/project-parent.git', - root_url: 'repositories/redmine/project-parent.git', - git_cache_id: 'project-parent', - redmine_name: 'project-parent', - gitolite_repository_path: 'repositories/redmine/project-parent.git', - gitolite_full_repository_path: "#{HOME_BASE_DIR}/git/repositories/redmine/project-parent.git", - gitolite_repository_name: 'redmine/project-parent', - redmine_repository_path: 'project-parent', - new_repository_name: 'redmine/project-parent', - old_repository_name: 'redmine/project-parent', - http_user_login: '', - git_access_path: 'redmine/project-parent.git', - http_access_path: 'git/project-parent.git', - ssh_url: "ssh://#{GIT_USER}@localhost/redmine/project-parent.git", - git_url: 'git://localhost/redmine/project-parent.git', - http_url: 'http://localhost/git/project-parent.git', - https_url: 'https://localhost/git/project-parent.git' - }, - - repository_4: { - is_default: false, - identifier: 'repo2-test', - url: 'repositories/redmine/repo2-test.git', - root_url: 'repositories/redmine/repo2-test.git', - git_cache_id: 'repo2-test', - redmine_name: 'repo2-test', - gitolite_repository_path: 'repositories/redmine/repo2-test.git', - gitolite_full_repository_path: "#{HOME_BASE_DIR}/git/repositories/redmine/repo2-test.git", - gitolite_repository_name: 'redmine/repo2-test', - redmine_repository_path: 'repo2-test', - new_repository_name: 'redmine/repo2-test', - old_repository_name: 'redmine/repo2-test', - http_user_login: '', - git_access_path: 'redmine/repo2-test.git', - http_access_path: 'git/repo2-test.git', - ssh_url: "ssh://#{GIT_USER}@localhost/redmine/repo2-test.git", - git_url: 'git://localhost/redmine/repo2-test.git', - http_url: 'http://localhost/git/repo2-test.git', - https_url: 'https://localhost/git/repo2-test.git' - } - }.freeze - - def build_collection_of_unique_repositories - @repository_1 = build_git_repository(project: @project_child, is_default: true) - @repository_1.valid? - @repository_2 = build_git_repository(project: @project_child, identifier: 'repo1-test') - @repository_2.valid? - - @repository_3 = build_git_repository(project: @project_parent, is_default: true) - @repository_3.valid? - @repository_4 = build_git_repository(project: @project_parent, identifier: 'repo2-test') - @repository_4.valid? - end - - def create_collection_of_unique_repositories - @repository_1 = create_git_repository(project: @project_child, is_default: true) - @repository_2 = create_git_repository(project: @project_child, identifier: 'repo1-test') - - @repository_3 = create_git_repository(project: @project_parent, is_default: true) - @repository_4 = create_git_repository(project: @project_parent, identifier: 'repo2-test') - end - - context 'when flat_organisation with unique_identifier: fast tests' do - before(:all) do - Setting.plugin_redmine_git_hosting[:hierarchical_organisation] = 'false' - Setting.plugin_redmine_git_hosting[:unique_repo_identifier] = 'true' - build_collection_of_unique_repositories - end - - UNIQUE_REPOSITORIES_MATRIX.each do |repo, attributes| - describe repo do - attributes.each do |key, value| - if value == true || value == false - it { expect(instance_variable_get("@#{repo}").send(key)).to be value } - else - it { expect(instance_variable_get("@#{repo}").send(key)).to eq value } - end - end - end - end - end - - context 'when flat_organisation with unique_identifier: long tests' do - describe '.repo_ident_unique?' do - it 'should be true' do - Setting.plugin_redmine_git_hosting[:hierarchical_organisation] = 'false' - Setting.plugin_redmine_git_hosting[:unique_repo_identifier] = 'true' - expect(Repository::Xitolite.repo_ident_unique?).to be true - end - end - - describe '.have_duplicated_identifier?' do - it 'should be false' do - Setting.plugin_redmine_git_hosting[:hierarchical_organisation] = 'false' - Setting.plugin_redmine_git_hosting[:unique_repo_identifier] = 'true' - create_collection_of_unique_repositories - expect(Repository::Xitolite.have_duplicated_identifier?).to be false - end - end - - describe '.repo_path_to_git_cache_id' do - before do - Setting.plugin_redmine_git_hosting[:hierarchical_organisation] = 'false' - Setting.plugin_redmine_git_hosting[:unique_repo_identifier] = 'true' - create_collection_of_unique_repositories - end - - let(:repo1) { Repository::Xitolite.find_by_path(@repository_1.url, loose: true) } - let(:repo2) { Repository::Xitolite.find_by_path(@repository_2.url, loose: true) } - let(:repo3) { Repository::Xitolite.find_by_path(@repository_3.url, loose: true) } - let(:repo4) { Repository::Xitolite.find_by_path(@repository_4.url, loose: true) } - - let(:git_cache_id1) { Repository::Xitolite.repo_path_to_git_cache_id(@repository_1.url) } - let(:git_cache_id2) { Repository::Xitolite.repo_path_to_git_cache_id(@repository_2.url) } - let(:git_cache_id3) { Repository::Xitolite.repo_path_to_git_cache_id(@repository_3.url) } - let(:git_cache_id4) { Repository::Xitolite.repo_path_to_git_cache_id(@repository_4.url) } - - describe 'repositories should match' do - it { expect(repo1).to eq @repository_1 } - it { expect(repo2).to eq @repository_2 } - it { expect(repo3).to eq @repository_3 } - it { expect(repo4).to eq @repository_4 } - - it { expect(git_cache_id1).to eq 'project-child' } - it { expect(git_cache_id2).to eq 'repo1-test' } - it { expect(git_cache_id3).to eq 'project-parent' } - it { expect(git_cache_id4).to eq 'repo2-test' } - end - end - end -end diff --git a/plugins/redmine_git_hosting/spec/support/global_helpers.rb b/plugins/redmine_git_hosting/spec/support/global_helpers.rb deleted file mode 100644 index f445bcf..0000000 --- a/plugins/redmine_git_hosting/spec/support/global_helpers.rb +++ /dev/null @@ -1,91 +0,0 @@ -module GlobalHelpers - def create_user_with_permissions(project, permissions: [], login: nil) - role = Role.find_by_name('Manager') - role = FactoryBot.create(:role, name: 'Manager') if role.nil? - role.permissions += permissions - role.save! - - if login.nil? - user = FactoryBot.create(:user) - else - user = FactoryBot.create(:user, login: login) - end - - member = Member.new(role_ids: [role.id], user_id: user.id) - project.members << member - - user - end - - def create_project(identifier = nil) - if identifier.nil? - FactoryBot.create(:project) - else - project = Project.find_by_identifier(identifier) - project = FactoryBot.create(:project, identifier: identifier) if project.nil? - project - end - end - - def set_session_user(user) - request.session[:user_id] = user.id - end - - def create_anonymous_user - create_user('git_anonymous') - end - - def create_admin_user - create_user('git_admin', admin: true) - end - - def create_user(login, admin: false) - user = User.find_by_login(login) - user = FactoryBot.create(:user, login: login, admin: admin) if user.nil? - user - end - - def create_ssh_key(opts = {}) - FactoryBot.create(:gitolite_public_key, opts) - end - - def build_ssh_key(opts = {}) - FactoryBot.build(:gitolite_public_key, opts) - end - - def build_git_repository(opts = {}) - FactoryBot.build(:repository_gitolite, opts) - end - - def find_or_create_git_repository(opts = {}) - repository = Repository::Xitolite.find_by_identifier(opts[:identifier]) - if repository.nil? - repository = FactoryBot.create(:repository_gitolite, opts) - build_extra(repository) - end - repository - end - - def create_git_repository(opts = {}) - repository = FactoryBot.create(:repository_gitolite, opts) - build_extra(repository) - repository - end - - def build_extra(repository) - extra = repository.build_extra(default_branch: 'master', key: RedmineGitHosting::Utils::Crypto.generate_secret(64)) - extra.save! - end - - def create_svn_repository(opts = {}) - FactoryBot.create(:repository_svn, opts) - end - - def load_yaml_fixture(fixture) - YAML.load(load_fixture(fixture)) - end - - def load_fixture(fixture) - File.read(RedmineGitHosting.plugin_spec_dir('fixtures', fixture)) - end -end diff --git a/plugins/redmine_git_hosting/spec/support/hierarchical_organisation.rb b/plugins/redmine_git_hosting/spec/support/hierarchical_organisation.rb deleted file mode 100644 index b287170..0000000 --- a/plugins/redmine_git_hosting/spec/support/hierarchical_organisation.rb +++ /dev/null @@ -1,186 +0,0 @@ -RSpec.shared_context 'hierarchical_organisation' do - ############################################################## - # # - # HIERARCHICAL ORGANISATION / NON-UNIQUE REPOSITORIES TESTS # - # # - ############################################################## - - NON_UNIQUE_REPOSITORIES_MATRIX = { - repository_1: { - is_default: true, - identifier: '', - url: 'repositories/redmine/project-parent/project-child.git', - root_url: 'repositories/redmine/project-parent/project-child.git', - git_cache_id: 'project-child', - redmine_name: 'project-child', - gitolite_repository_path: 'repositories/redmine/project-parent/project-child.git', - gitolite_full_repository_path: "#{HOME_BASE_DIR}/git/repositories/redmine/project-parent/project-child.git", - gitolite_repository_name: 'redmine/project-parent/project-child', - redmine_repository_path: 'project-parent/project-child', - new_repository_name: 'redmine/project-parent/project-child', - old_repository_name: 'redmine/project-parent/project-child', - http_user_login: '', - git_access_path: 'redmine/project-parent/project-child.git', - http_access_path: 'git/project-parent/project-child.git', - ssh_url: "ssh://#{GIT_USER}@localhost/redmine/project-parent/project-child.git", - git_url: 'git://localhost/redmine/project-parent/project-child.git', - http_url: 'http://localhost/git/project-parent/project-child.git', - https_url: 'https://localhost/git/project-parent/project-child.git' - }, - - repository_2: { - is_default: false, - identifier: 'repo-test', - url: 'repositories/redmine/project-parent/project-child/repo-test.git', - root_url: 'repositories/redmine/project-parent/project-child/repo-test.git', - git_cache_id: 'project-child/repo-test', - redmine_name: 'repo-test', - gitolite_repository_path: 'repositories/redmine/project-parent/project-child/repo-test.git', - gitolite_full_repository_path: "#{HOME_BASE_DIR}/git/repositories/redmine/project-parent/project-child/repo-test.git", - gitolite_repository_name: 'redmine/project-parent/project-child/repo-test', - redmine_repository_path: 'project-parent/project-child/repo-test', - new_repository_name: 'redmine/project-parent/project-child/repo-test', - old_repository_name: 'redmine/project-parent/project-child/repo-test', - http_user_login: '', - git_access_path: 'redmine/project-parent/project-child/repo-test.git', - http_access_path: 'git/project-parent/project-child/repo-test.git', - ssh_url: "ssh://#{GIT_USER}@localhost/redmine/project-parent/project-child/repo-test.git", - git_url: 'git://localhost/redmine/project-parent/project-child/repo-test.git', - http_url: 'http://localhost/git/project-parent/project-child/repo-test.git', - https_url: 'https://localhost/git/project-parent/project-child/repo-test.git' - }, - - repository_3: { - is_default: true, - identifier: '', - url: 'repositories/redmine/project-parent.git', - root_url: 'repositories/redmine/project-parent.git', - git_cache_id: 'project-parent', - redmine_name: 'project-parent', - gitolite_repository_path: 'repositories/redmine/project-parent.git', - gitolite_full_repository_path: "#{HOME_BASE_DIR}/git/repositories/redmine/project-parent.git", - gitolite_repository_name: 'redmine/project-parent', - redmine_repository_path: 'project-parent', - new_repository_name: 'redmine/project-parent', - old_repository_name: 'redmine/project-parent', - http_user_login: '', - git_access_path: 'redmine/project-parent.git', - http_access_path: 'git/project-parent.git', - ssh_url: "ssh://#{GIT_USER}@localhost/redmine/project-parent.git", - git_url: 'git://localhost/redmine/project-parent.git', - http_url: 'http://localhost/git/project-parent.git', - https_url: 'https://localhost/git/project-parent.git' - }, - - repository_4: { - is_default: false, - identifier: 'repo-test', - url: 'repositories/redmine/project-parent/repo-test.git', - root_url: 'repositories/redmine/project-parent/repo-test.git', - git_cache_id: 'project-parent/repo-test', - redmine_name: 'repo-test', - gitolite_repository_path: 'repositories/redmine/project-parent/repo-test.git', - gitolite_full_repository_path: "#{HOME_BASE_DIR}/git/repositories/redmine/project-parent/repo-test.git", - gitolite_repository_name: 'redmine/project-parent/repo-test', - redmine_repository_path: 'project-parent/repo-test', - new_repository_name: 'redmine/project-parent/repo-test', - old_repository_name: 'redmine/project-parent/repo-test', - http_user_login: '', - git_access_path: 'redmine/project-parent/repo-test.git', - http_access_path: 'git/project-parent/repo-test.git', - ssh_url: "ssh://#{GIT_USER}@localhost/redmine/project-parent/repo-test.git", - git_url: 'git://localhost/redmine/project-parent/repo-test.git', - http_url: 'http://localhost/git/project-parent/repo-test.git', - https_url: 'https://localhost/git/project-parent/repo-test.git' - } - }.freeze - - def build_collection_of_non_unique_repositories - @repository_1 = build_git_repository(project: @project_child, is_default: true) - @repository_1.valid? - @repository_2 = build_git_repository(project: @project_child, identifier: 'repo-test') - @repository_2.valid? - - @repository_3 = build_git_repository(project: @project_parent, is_default: true) - @repository_3.valid? - @repository_4 = build_git_repository(project: @project_parent, identifier: 'repo-test') - @repository_4.valid? - end - - def create_collection_of_non_unique_repositories - @repository_1 = create_git_repository(project: @project_child, is_default: true) - @repository_2 = create_git_repository(project: @project_child, identifier: 'repo-test') - - @repository_3 = create_git_repository(project: @project_parent, is_default: true) - @repository_4 = create_git_repository(project: @project_parent, identifier: 'repo-test') - end - - context 'when hierarchical_organisation with non_unique_identifier: fast tests' do - before(:all) do - Setting.plugin_redmine_git_hosting[:hierarchical_organisation] = 'true' - Setting.plugin_redmine_git_hosting[:unique_repo_identifier] = 'false' - build_collection_of_non_unique_repositories - end - - NON_UNIQUE_REPOSITORIES_MATRIX.each do |repo, attributes| - describe repo do - attributes.each do |key, value| - if value == true || value == false - it { expect(instance_variable_get("@#{repo}").send(key)).to be value } - else - it { expect(instance_variable_get("@#{repo}").send(key)).to eq value } - end - end - end - end - end - - context 'when hierarchical_organisation with non_unique_identifier: long tests' do - describe '.repo_ident_unique?' do - it 'should be false' do - Setting.plugin_redmine_git_hosting[:hierarchical_organisation] = 'true' - Setting.plugin_redmine_git_hosting[:unique_repo_identifier] = 'false' - expect(Repository::Xitolite.repo_ident_unique?).to be false - end - end - - describe '.have_duplicated_identifier?' do - it 'should be true' do - Setting.plugin_redmine_git_hosting[:hierarchical_organisation] = 'true' - Setting.plugin_redmine_git_hosting[:unique_repo_identifier] = 'false' - create_collection_of_non_unique_repositories - expect(Repository::Xitolite.have_duplicated_identifier?).to be true - end - end - - describe '.repo_path_to_git_cache_id' do - before do - Setting.plugin_redmine_git_hosting[:hierarchical_organisation] = 'true' - Setting.plugin_redmine_git_hosting[:unique_repo_identifier] = 'false' - create_collection_of_non_unique_repositories - end - - let(:repo1) { Repository::Xitolite.find_by_path(@repository_1.url, loose: true) } - let(:repo2) { Repository::Xitolite.find_by_path(@repository_2.url, loose: true) } - let(:repo3) { Repository::Xitolite.find_by_path(@repository_3.url, loose: true) } - let(:repo4) { Repository::Xitolite.find_by_path(@repository_4.url, loose: true) } - - let(:git_cache_id1) { Repository::Xitolite.repo_path_to_git_cache_id(@repository_1.url) } - let(:git_cache_id2) { Repository::Xitolite.repo_path_to_git_cache_id(@repository_2.url) } - let(:git_cache_id3) { Repository::Xitolite.repo_path_to_git_cache_id(@repository_3.url) } - let(:git_cache_id4) { Repository::Xitolite.repo_path_to_git_cache_id(@repository_4.url) } - - describe 'repositories should match' do - it { expect(repo1).to eq @repository_1 } - it { expect(repo2).to eq @repository_2 } - it { expect(repo3).to eq @repository_3 } - it { expect(repo4).to eq @repository_4 } - - it { expect(git_cache_id1).to eq 'project-child' } - it { expect(git_cache_id2).to eq 'project-child/repo-test' } - it { expect(git_cache_id3).to eq 'project-parent' } - it { expect(git_cache_id4).to eq 'project-parent/repo-test' } - end - end - end -end diff --git a/plugins/redmine_git_hosting/spec/use_cases/repository_mirrors/push.rb b/plugins/redmine_git_hosting/spec/use_cases/repository_mirrors/push.rb deleted file mode 100644 index 3c5ded5..0000000 --- a/plugins/redmine_git_hosting/spec/use_cases/repository_mirrors/push.rb +++ /dev/null @@ -1,52 +0,0 @@ -require File.expand_path("#{File.dirname __FILE__}/../../spec_helper") - -describe RepositoryMirrors::Push do - let(:mirror_url) { 'ssh://git@redmine.example.org/project1/project2/project3/project4.git' } - - def build_mirror_pusher(opts = {}) - mirror = build(:repository_mirror, opts) - RepositoryMirrors::Push.new(mirror) - end - - describe 'Push args' do - ## Validate push args : forced mode - context 'when push_mode forced with params' do - it 'should have command' do - mirror_pusher = build_mirror_pusher(url: mirror_url, push_mode: 1, explicit_refspec: 'devel') - expect(mirror_pusher.command).to eq [mirror_url, 'devel', ['--force']] - end - end - - ## Validate push args : fast_forward mode - context 'when push_mode fast_forward with params' do - it 'should have command' do - mirror_pusher = build_mirror_pusher(url: mirror_url, push_mode: 2, explicit_refspec: 'devel') - expect(mirror_pusher.command).to eq [mirror_url, 'devel', []] - end - end - - ## Validate push args : mirror mode - context 'when push_mode is mirror' do - it 'should have command' do - mirror_pusher = build_mirror_pusher(url: mirror_url, push_mode: 0) - expect(mirror_pusher.command).to eq [mirror_url, nil, ['--mirror']] - end - end - - ## Validate push args : all tags mode - context 'when push_mode is all tags' do - it 'should have command' do - mirror_pusher = build_mirror_pusher(url: mirror_url, push_mode: 1, include_all_tags: true) - expect(mirror_pusher.command).to eq [mirror_url, nil, ['--force', '--tags']] - end - end - - ## Validate push args : all branches mode - context 'when push_mode is all branches' do - it 'should have command' do - mirror_pusher = build_mirror_pusher(url: mirror_url, push_mode: 1, include_all_branches: true) - expect(mirror_pusher.command).to eq [mirror_url, nil, ['--force', '--all']] - end - end - end -end diff --git a/plugins/redmine_git_hosting/spec/use_cases/repository_protected_branches/member_manager_spec.rb b/plugins/redmine_git_hosting/spec/use_cases/repository_protected_branches/member_manager_spec.rb deleted file mode 100644 index 4a35fdf..0000000 --- a/plugins/redmine_git_hosting/spec/use_cases/repository_protected_branches/member_manager_spec.rb +++ /dev/null @@ -1,138 +0,0 @@ -require File.expand_path("#{File.dirname __FILE__}/../../spec_helper") - -describe RepositoryProtectedBranches::MemberManager do - def build_member_manager(_opts = {}) - protected_branch = build(:repository_protected_branche) - member_manager = RepositoryProtectedBranches::MemberManager.new(protected_branch) - end - - let(:member_manager) { build_member_manager } - - subject { member_manager } - - describe '#current_user_ids' do - it 'should return an array of user ids' do - user = build(:user, id: 12) - expect(member_manager.protected_branch).to receive(:users).and_return([user]) - expect(member_manager.current_user_ids).to eq [12] - end - end - - describe '#current_group_ids' do - it 'should return an array of group ids' do - group = build(:group, id: 12) - expect(member_manager.protected_branch).to receive(:groups).and_return([group]) - expect(member_manager.current_group_ids).to eq [12] - end - end - - describe '#current_members' do - it 'should return the current protected_branch members' do - expect(member_manager.protected_branch).to receive(:protected_branches_members) - member_manager.current_members - end - end - - describe '#users_by_group_id' do - it 'should return the members of a protected_branch group' do - group_member = create(:protected_branch_group_member) - user_member = create(:protected_branch_user_member, inherited_by: group_member.id) - expect(member_manager).to receive(:current_members).and_return([user_member, group_member]) - expect(member_manager.users_by_group_id(1)).to eq [user_member.principal] - end - end - - describe '#add_users' do - it 'should add users passed' do - expect(member_manager).to receive(:current_user_ids).and_return([1]) - expect(member_manager).to receive(:create_member).with(['10'], [1], 'User', {}) - member_manager.add_users(['10']) - end - end - - describe '#add_groups' do - it 'should add users passed' do - user = build(:user, id: 42) - group = build(:group, id: 10) - expect(member_manager).to receive(:current_group_ids).and_return([]) - expect(member_manager).to receive(:create_group_member).with(['10'], []).and_yield(group) - expect(group).to receive(:users).and_return([user]) - expect(member_manager).to receive(:users_by_group_id).and_return([]) - expect(member_manager).to receive(:create_user_member).with([42], [], inherited_by: 10, destroy: false) - member_manager.add_groups(['10']) - end - end - - describe '#create_user_member' do - it 'should create a new user member' do - expect(member_manager).to receive(:create_member).with([1], [], 'User', {}) - member_manager.create_user_member([1], []) - end - end - - describe '#create_group_member' do - it 'should create a new group member' do - expect(member_manager).to receive(:create_member).with([1], [], 'Group', {}) - member_manager.create_group_member([1], []) - end - end - - describe '#add_user_from_group' do - it 'should add a user from a group' do - user1 = build(:user, id: 20) - user2 = build(:user, id: 22) - expect(member_manager).to receive(:users_by_group_id).once.with(10).and_return([user2]) - expect(member_manager).to receive(:users_by_group_id).once.with(10).and_return([user2]) - expect(member_manager).to receive(:create_user_member).with([user2.id, user1.id], [user2.id], inherited_by: 10, destroy: false) - member_manager.add_user_from_group(user1, 10) - end - end - - describe '#remove_user_from_group' do - context 'when user exists' do - it 'should remove a user from a group' do - user = build(:user) - expect(member_manager).to receive(:users_by_group_id).with(10).and_return([user]) - expect(member_manager.current_members).to receive(:find_by_protected_branch_id_and_principal_id_and_inherited_by) - member_manager.remove_user_from_group(user, 10) - end - end - - context 'when user doesnt no exist' do - it 'should return' do - user = build(:user) - expect(member_manager).to receive(:users_by_group_id).with(10).and_return([]) - expect(member_manager.current_members).to_not receive(:find_by_protected_branch_id_and_principal_id_and_inherited_by) - member_manager.remove_user_from_group(user, 10) - end - end - end - - describe '#create_member' do - it 'should create member' do - user = build(:user, id: 12) - expect(User).to receive(:find_by_id).with(12).and_return(user) - expect(member_manager.current_members).to receive(:create).with(principal_id: user.id, inherited_by: 10) - expect(member_manager.current_members).to receive(:select).and_return([]) - member_manager.create_member([12], [], 'User', inherited_by: 10) - end - - context 'when member is a user' do - it 'should create member' do - user = build(:user, id: 12) - expect(User).to receive(:find_by_id).with(12).and_return(user) - expect(member_manager.current_members).to receive(:create).with(principal_id: user.id, inherited_by: 10) - member_manager.create_member([12], [], 'User', inherited_by: 10, destroy: false) - end - end - - context 'when member is a group' do - it 'should create member' do - group = build(:group, id: 12) - expect(Group).to receive(:find_by_id).with(12).and_return(group) - expect(member_manager.current_members).to receive(:create).with(principal_id: group.id, inherited_by: nil) - member_manager.create_member([12], [], 'Group', destroy: false) - end - end - end -end diff --git a/plugins/redmine_git_hosting/ssh_keys/.placeholder b/plugins/redmine_git_hosting/ssh_keys/.placeholder deleted file mode 100644 index e69de29..0000000