jbox-web/redmine_git_hosting

View on GitHub
lib/redmine_git_hosting/patches/repositories_controller_patch.rb

Summary

Maintainability
B
6 hrs
Test Coverage
# frozen_string_literal: true

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?
        RedminePluginKit.true? @repository.create_readme
      end

      def enable_git_annex?
        RedminePluginKit.true? @repository.enable_git_annex
      end

      REV_PARAM_RE = /\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]
        @repository = if params[:repository_id].present?
                        @project.repositories.find_by_identifier_param params[:repository_id] # rubocop: disable Rails/DynamicFindBy
                      else
                        @project.repository
                      end
        return render_404 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]

        raise InvalidRevisionParam if !@rev.to_s.match(REV_PARAM_RE) && @rev_to.to_s.match(REV_PARAM_RE) && @repository.branches.empty?
      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
          return show_error_not_found 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, layout: 'base.html.erb'
        end
      end
    end
  end
end

unless RepositoriesController.included_modules.include? RedmineGitHosting::Patches::RepositoriesControllerPatch
  RepositoriesController.prepend RedmineGitHosting::Patches::RepositoriesControllerPatch
end