Welcome to mirror list, hosted at ThFree Co, Russian Federation.

repository_service.rb « gitaly_server « lib « ruby - gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 223176eb13459fbd3a13f81bd96ae9c221c9c990 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
require 'licensee'

module GitalyServer
  class RepositoryService < Gitaly::RepositoryService::Service
    include Utils

    def create_repository(_request, call)
      repo_path = GitalyServer.repo_path(call)

      Gitlab::Git::Repository.create(repo_path)

      Gitaly::CreateRepositoryResponse.new
    end

    def fetch_source_branch(request, call)
      source_repository = Gitlab::Git::GitalyRemoteRepository.new(request.source_repository, call)
      repository = Gitlab::Git::Repository.from_gitaly(request.repository, call)
      result = repository.fetch_source_branch!(source_repository, request.source_branch, request.target_ref)

      Gitaly::FetchSourceBranchResponse.new(result: result)
    end

    def fetch_remote(request, call)
      gitlab_projects = Gitlab::Git::GitlabProjects.from_gitaly(request.repository, call)

      success = Gitlab::Git::SshAuth.from_gitaly(request).setup do |env|
        gitlab_projects.fetch_remote(
          request.remote,
          request.timeout,
          force: request.force,
          tags: !request.no_tags,
          env: env
        )
      end

      raise GRPC::Unknown.new("Fetching remote #{request.remote} failed: #{gitlab_projects.output}") unless success

      Gitaly::FetchRemoteResponse.new
    end

    def write_ref(request, call)
      Gitlab::Git::Repository.from_gitaly(request.repository, call)
                             .write_ref(request.ref, request.revision, old_ref: request.old_revision)

      Gitaly::WriteRefResponse.new
    end

    def write_config(request, call)
      repo = Gitlab::Git::Repository.from_gitaly(request.repository, call)

      repo.write_config(full_path: request.full_path)

      Gitaly::WriteConfigResponse.new
    rescue Rugged::Error => ex
      Gitaly::WriteConfigResponse.new(error: ex.message.b)
    end

    def set_config(request, call)
      repo = Gitlab::Git::Repository.from_gitaly(request.repository, call)

      request.entries.each do |entry|
        key = entry.key
        value = case entry.value
                when :value_str
                  entry.value_str
                when :value_int32
                  entry.value_int32
                when :value_bool
                  entry.value_bool
                else
                  raise GRPC::InvalidArgument, "unknown entry type: #{entry.value}"
                end

        repo.rugged.config[key] = value
      end

      Gitaly::SetConfigResponse.new
    end

    def find_license(request, call)
      repo = Gitlab::Git::Repository.from_gitaly(request.repository, call)

      short_name = begin
                     ::Licensee.license(repo.path).try(:key)
                   rescue Rugged::Error
                   end

      Gitaly::FindLicenseResponse.new(license_short_name: short_name || "")
    end

    # TODO: remove after 11.8 because of https://gitlab.com/gitlab-org/gitaly/merge_requests/1026
    def get_raw_changes(request, call)
      repo = Gitlab::Git::Repository.from_gitaly(request.repository, call)

      changes = begin
                  repo
                    .raw_changes_between(request.from_revision, request.to_revision)
                    .map { |c| to_proto_raw_change(c) }
                rescue ::Gitlab::Git::Repository::GitError => e
                  raise GRPC::InvalidArgument.new(e.message)
                end

      Enumerator.new do |y|
        changes.each_slice(100) do |batch|
          y.yield Gitaly::GetRawChangesResponse.new(raw_changes: batch)
        end
      end
    end

    private

    OPERATION_MAP = {
      added:        Gitaly::GetRawChangesResponse::RawChange::Operation::ADDED,
      copied:       Gitaly::GetRawChangesResponse::RawChange::Operation::COPIED,
      deleted:      Gitaly::GetRawChangesResponse::RawChange::Operation::DELETED,
      modified:     Gitaly::GetRawChangesResponse::RawChange::Operation::MODIFIED,
      renamed:      Gitaly::GetRawChangesResponse::RawChange::Operation::RENAMED,
      type_changed: Gitaly::GetRawChangesResponse::RawChange::Operation::TYPE_CHANGED
    }.freeze

    def to_proto_raw_change(change)
      operation = OPERATION_MAP[change.operation] || Gitaly::GetRawChangesResponse::RawChange::Operation::UNKNOWN

      # Protobuf doesn't even try to call `to_s` or `to_i` where it might be needed.
      Gitaly::GetRawChangesResponse::RawChange.new(
        blob_id: change.blob_id.to_s,
        size: change.blob_size.to_i,
        new_path: change.new_path.to_s,
        old_path: change.old_path.to_s,
        operation: operation,
        old_mode: change.old_mode.to_i(8),
        new_mode: change.new_mode.to_i(8)
      )
    end
  end
end