scope(path: '*repository_path', format: false) do
  constraints(repository_path: Gitlab::PathRegex.repository_git_route_regex) do
    scope(module: :repositories) do
      # Git HTTP API
      scope(controller: :git_http) do
        get '/info/refs', action: :info_refs
        post '/git-upload-pack', action: :git_upload_pack
        post '/git-receive-pack', action: :git_receive_pack
      end

      # NOTE: LFS routes are exposed on all repository types, but we still check for
      # LFS availability on the repository container in LfsRequest#lfs_check_access!

      # Git LFS API (metadata)
      scope(path: 'info/lfs/objects', controller: :lfs_api) do
        post :batch
        post '/', action: :deprecated
        get '/*oid', action: :deprecated
      end

      scope(path: 'info/lfs') do
        resources :lfs_locks, controller: :lfs_locks_api, path: 'locks' do
          post :unlock, on: :member
          post :verify, on: :collection
        end
      end

      # GitLab LFS object storage
      scope(path: 'gitlab-lfs/objects/*oid', controller: :lfs_storage, constraints: { oid: /[a-f0-9]{64}/ }) do
        get '/', action: :download

        constraints(size: /[0-9]+/) do
          put '/*size/authorize', action: :upload_authorize
          put '/*size', action: :upload_finalize
        end
      end
    end
  end

  # Redirect /group/project.wiki.git to the project wiki
  constraints(repository_path: Gitlab::PathRegex.repository_wiki_git_route_regex) do
    wiki_redirect = redirect do |params, request|
      container_path = params[:repository_path].delete_suffix('.wiki.git')
      path = File.join(container_path, '-', 'wikis')
      path << "?#{request.query_string}" unless request.query_string.blank?
      path
    end

    get '/', to: wiki_redirect
  end

  # Redirect /group/project/info/refs to /group/project.git/info/refs
  # This allows cloning a repository without the trailing `.git`
  constraints(repository_path: Gitlab::PathRegex.repository_route_regex) do
    ref_redirect = redirect do |params, request|
      path = "#{params[:repository_path]}.git/info/refs"
      path << "?#{request.query_string}" unless request.query_string.blank?
      path
    end

    get '/info/refs', constraints: ::Constraints::RepositoryRedirectUrlConstrainer.new, to: ref_redirect
  end
end
