summaryrefslogtreecommitdiff
path: root/lib/gitlab/github_import/clients/search_repos.rb
blob: b72e5ac7751d513843053ac36826a3ead4bcfb17 (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
# frozen_string_literal: true

module Gitlab
  module GithubImport
    module Clients
      module SearchRepos
        def search_repos_by_name_graphql(name, options = {})
          with_retry do
            octokit.post(
              '/graphql',
              { query: graphql_search_repos_body(name, options) }.to_json
            ).to_h
          end
        end

        def search_repos_by_name(name, options = {})
          search_query = search_repos_query(name, options)

          with_retry do
            octokit.search_repositories(search_query, options).to_h
          end
        end

        private

        def graphql_search_repos_body(name, options)
          query = search_repos_query(name, options)
          query = "query: \"#{query}\""
          first = options[:first].present? ? ", first: #{options[:first]}" : ''
          after = options[:after].present? ? ", after: \"#{options[:after]}\"" : ''
          <<-TEXT
          {
              search(type: REPOSITORY, #{query}#{first}#{after}) {
                  nodes {
                      __typename
                      ... on Repository {
                          id: databaseId
                          name
                          full_name: nameWithOwner
                          owner { login }
                      }
                  }
                  pageInfo {
                      startCursor
                      endCursor
                      hasNextPage
                      hasPreviousPage
                  }
              }
          }
          TEXT
        end

        def search_repos_query(string, options = {})
          base = "#{string} in:name is:public,private"

          case options[:relation_type]
          when 'organization' then organization_repos_query(base, options)
          when 'collaborated' then collaborated_repos_query(base)
          when 'owned' then owned_repos_query(base)
          # TODO: remove after https://gitlab.com/gitlab-org/gitlab/-/issues/385113 get done
          else legacy_all_repos_query(base)
          end
        end

        def organization_repos_query(search_string, options)
          "#{search_string} org:#{options[:organization_login]}"
        end

        def collaborated_repos_query(search_string)
          "#{search_string} #{collaborations_subquery}"
        end

        def owned_repos_query(search_string)
          "#{search_string} user:#{octokit.user.to_h[:login]}"
        end

        def legacy_all_repos_query(search_string)
          [
            search_string,
            "user:#{octokit.user.to_h[:login]}",
            collaborations_subquery,
            organizations_subquery
          ].join(' ')
        end

        def collaborations_subquery
          each_object(:repos, nil, { affiliation: 'collaborator' })
            .map { |repo| "repo:#{repo[:full_name]}" }
            .join(' ')
        end

        def organizations_subquery
          each_object(:organizations)
            .map { |org| "org:#{org[:login]}" }
            .join(' ')
        end
      end
    end
  end
end