summaryrefslogtreecommitdiff
path: root/app/models/packages/go/module.rb
blob: a029437c82d4848dd93dc80f66daaed7c0cef28d (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
# frozen_string_literal: true

module Packages
  module Go
    class Module
      include Gitlab::Utils::StrongMemoize

      attr_reader :project, :name, :path

      def initialize(project, name, path)
        @project = project
        @name = name
        @path = path
      end

      def versions
        strong_memoize(:versions) { Packages::Go::VersionFinder.new(self).execute }
      end

      def version_by(ref: nil, commit: nil)
        raise ArgumentError, 'no filter specified' unless ref || commit
        raise ArgumentError, 'ref and commit are mutually exclusive' if ref && commit

        if commit
          return version_by_sha(commit) if commit.is_a? String

          return version_by_commit(commit)
        end

        return version_by_name(ref) if ref.is_a? String

        version_by_ref(ref)
      end

      def path_valid?(major)
        m = %r{/v(\d+)$}i.match(@name)

        case major
        when 0, 1
          m.nil?
        else
          !m.nil? && m[1].to_i == major
        end
      end

      def gomod_valid?(gomod)
        if Feature.enabled?(:go_proxy_disable_gomod_validation, @project)
          return gomod&.start_with?("module ")
        end

        gomod&.split("\n", 2)&.first == "module #{@name}"
      end

      private

      def version_by_name(name)
        # avoid a Gitaly call if possible
        if strong_memoized?(:versions)
          v = versions.find { |v| v.name == ref }
          return v if v
        end

        ref = @project.repository.find_tag(name) || @project.repository.find_branch(name)
        return unless ref

        version_by_ref(ref)
      end

      def version_by_ref(ref)
        # reuse existing versions
        if strong_memoized?(:versions)
          v = versions.find { |v| v.ref == ref }
          return v if v
        end

        commit = ref.dereferenced_target
        semver = Packages::SemVer.parse(ref.name, prefixed: true)
        Packages::Go::ModuleVersion.new(self, :ref, commit, ref: ref, semver: semver)
      end

      def version_by_sha(sha)
        commit = @project.commit_by(oid: sha)
        return unless ref

        version_by_commit(commit)
      end

      def version_by_commit(commit)
        Packages::Go::ModuleVersion.new(self, :commit, commit)
      end
    end
  end
end