Commit a6241259 authored by Markus Koller's avatar Markus Koller

Merge branch 'fix-repository-blobs-query' into 'master'

Fix querying repository blobs in GraphQL

See merge request gitlab-org/gitlab!59272
parents 8dcf777c bee72363
......@@ -21,7 +21,7 @@ module Resolvers
# We fetch blobs from Gitaly efficiently but it still scales O(N) with the
# number of paths being fetched, so apply a scaling limit to that.
def self.resolver_complexity(args, child_complexity:)
super + args.fetch(:paths, []).size
super + (args[:paths] || []).size
end
def resolve(paths:, ref:)
......
# frozen_string_literal: true
module Types
module Repository
# rubocop: disable Graphql/AuthorizeTypes
# This is presented through `Repository` that has its own authorization
class BlobType < BaseObject
present_using BlobPresenter
graphql_name 'RepositoryBlob'
field :id, GraphQL::ID_TYPE, null: false,
description: 'ID of the blob.'
field :oid, GraphQL::STRING_TYPE, null: false, method: :id,
description: 'OID of the blob.'
field :path, GraphQL::STRING_TYPE, null: false,
description: 'Path of the blob.'
field :name, GraphQL::STRING_TYPE,
description: 'Blob name.',
null: true
field :mode, type: GraphQL::STRING_TYPE,
description: 'Blob mode.',
null: true
field :lfs_oid, GraphQL::STRING_TYPE, null: true,
calls_gitaly: true,
description: 'LFS OID of the blob.'
field :web_path, GraphQL::STRING_TYPE, null: true,
description: 'Web path of the blob.'
def lfs_oid
Gitlab::Graphql::Loaders::BatchLfsOidLoader.new(object.repository, object.id).find
end
end
end
end
......@@ -14,7 +14,7 @@ module Types
description: 'Indicates a corresponding Git repository exists on disk.'
field :tree, Types::Tree::TreeType, null: true, resolver: Resolvers::TreeResolver, calls_gitaly: true,
description: 'Tree of the repository.'
field :blobs, Types::Tree::BlobType.connection_type, null: true, resolver: Resolvers::BlobsResolver, calls_gitaly: true,
field :blobs, Types::Repository::BlobType.connection_type, null: true, resolver: Resolvers::BlobsResolver, calls_gitaly: true,
description: 'Blobs contained within the repository'
field :branch_names, [GraphQL::STRING_TYPE], null: true, calls_gitaly: true,
complexity: 170, description: 'Names of branches available in this repository that match the search pattern.',
......
......@@ -5522,13 +5522,44 @@ Autogenerated return type of RepositionImageDiffNote.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `blobs` | [`BlobConnection`](#blobconnection) | Blobs contained within the repository. |
| `blobs` | [`RepositoryBlobConnection`](#repositoryblobconnection) | Blobs contained within the repository. |
| `branchNames` | [`[String!]`](#string) | Names of branches available in this repository that match the search pattern. |
| `empty` | [`Boolean!`](#boolean) | Indicates repository has no visible content. |
| `exists` | [`Boolean!`](#boolean) | Indicates a corresponding Git repository exists on disk. |
| `rootRef` | [`String`](#string) | Default branch of the repository. |
| `tree` | [`Tree`](#tree) | Tree of the repository. |
### `RepositoryBlob`
| Field | Type | Description |
| ----- | ---- | ----------- |
| `id` | [`ID!`](#id) | ID of the blob. |
| `lfsOid` | [`String`](#string) | LFS OID of the blob. |
| `mode` | [`String`](#string) | Blob mode. |
| `name` | [`String`](#string) | Blob name. |
| `oid` | [`String!`](#string) | OID of the blob. |
| `path` | [`String!`](#string) | Path of the blob. |
| `webPath` | [`String`](#string) | Web path of the blob. |
### `RepositoryBlobConnection`
The connection type for RepositoryBlob.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `edges` | [`[RepositoryBlobEdge]`](#repositoryblobedge) | A list of edges. |
| `nodes` | [`[RepositoryBlob]`](#repositoryblob) | A list of nodes. |
| `pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
### `RepositoryBlobEdge`
An edge in a connection.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
| `node` | [`RepositoryBlob`](#repositoryblob) | The item at the end of the edge. |
### `Requirement`
Represents a requirement.
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Types::Repository::BlobType do
specify { expect(described_class.graphql_name).to eq('RepositoryBlob') }
specify { expect(described_class).to have_graphql_fields(:id, :oid, :name, :path, :web_path, :lfs_oid, :mode) }
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'getting blobs in a project repository' do
include GraphqlHelpers
let(:project) { create(:project, :repository) }
let(:current_user) { project.owner }
let(:paths) { ["CONTRIBUTING.md", "README.md"] }
let(:ref) { project.default_branch }
let(:fields) do
<<~QUERY
blobs(paths:#{paths.inspect}, ref:#{ref.inspect}) {
nodes {
#{all_graphql_fields_for('repository_blob'.classify)}
}
}
QUERY
end
let(:query) do
graphql_query_for(
'project',
{ 'fullPath' => project.full_path },
query_graphql_field('repository', {}, fields)
)
end
subject(:blobs) { graphql_data_at(:project, :repository, :blobs, :nodes) }
it 'returns the blob' do
post_graphql(query, current_user: current_user)
expect(blobs).to match_array(paths.map { |path| a_hash_including('path' => path) })
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment