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

changelog_tag_finder.rb « repositories « finders « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 3c110e6c65dcf04c8f51ff8531caca9b996ae2ac (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
# frozen_string_literal: true

module Repositories
  # A finder class for getting the tag of the last release before a given
  # version, used when generating changelogs.
  #
  # Imagine a project with the following tags:
  #
  # * v1.0.0
  # * v1.1.0
  # * v2.0.0
  #
  # If the version supplied is 2.1.0, the tag returned will be v2.0.0. And when
  # the version is 1.1.1, or 1.2.0, the returned tag will be v1.1.0.
  #
  # To obtain the tags, this finder requires a regular expression (using the re2
  # syntax) to be provided. This regex must produce the following named
  # captures:
  #
  # - major (required)
  # - minor (required)
  # - patch (required)
  # - pre
  # - meta
  #
  # If the `pre` group has a value, the tag is ignored. If any of the required
  # capture groups don't have a value, the tag is also ignored.
  class ChangelogTagFinder
    def initialize(project, regex: Gitlab::Changelog::Config::DEFAULT_TAG_REGEX)
      @project = project
      @regex = regex
    end

    def execute(new_version)
      tags = {}
      versions = [new_version]

      begin
        regex = Gitlab::UntrustedRegexp.new(@regex)
      rescue RegexpError => ex
        # The error messages produced by default are not very helpful, so we
        # raise a better one here. We raise the specific error here so its
        # message is displayed in the API (where we catch this specific
        # error).
        raise(
          Gitlab::Changelog::Error,
          "The regular expression to use for finding the previous tag for a version is invalid: #{ex.message}"
        )
      end

      @project.repository.tags.each do |tag|
        matches = regex.match(tag.name)

        next unless matches

        # When using this class for generating changelog data for a range of
        # commits, we want to compare against the tag of the last _stable_
        # release; not some random RC that came after that.
        next if matches[:pre]

        major = matches[:major]
        minor = matches[:minor]
        patch = matches[:patch]
        build = matches[:meta]

        next unless major && minor && patch

        version = "#{major}.#{minor}.#{patch}"
        version += "+#{build}" if build

        tags[version] = tag
        versions << version
      end

      VersionSorter.sort!(versions)

      index = versions.index(new_version)

      tags[versions[index - 1]] if index&.positive?
    end
  end
end