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

base_template.rb « template « gitlab « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 31e11f73fe7747bed0650dd35bb994665cfdc098 (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
137
138
139
140
141
142
143
144
145
# frozen_string_literal: true

module Gitlab
  module Template
    class BaseTemplate
      attr_accessor :category

      def initialize(path, project = nil, category: nil)
        @path = path
        @category = category
        @project = project
        @finder = self.class.finder(project)
      end

      def name
        File.basename(@path, self.class.extension)
      end
      alias_method :key, :name

      def full_name
        Pathname.new(@path)
          .relative_path_from(self.class.base_dir)
          .to_s
      end

      def content
        blob = @finder.read(@path)
        [description, blob].compact.join("\n")
      end

      def description
        # override with a comment to be placed at the top of the blob.
      end

      def project_id
        @project&.id
      end

      # Present for compatibility with license templates, which can replace text
      # like `[fullname]` with a user-specified string. This is a no-op for
      # other templates
      def resolve!(_placeholders = {})
        self
      end

      def to_json(*)
        { key: key, name: name, content: content }
      end

      def <=>(other)
        name <=> other.name
      end

      class << self
        def all(project = nil)
          if categories.any?
            categories.keys.flat_map { |cat| by_category(cat, project) }
          else
            by_category("", project)
          end
        end

        def find(key, project = nil)
          path = self.finder(project).find(key)
          path.present? ? new(path, project) : nil
        end

        # Set categories as sub directories
        # Example: { "category_name_1" => "directory_path_1", "category_name_2" => "directory_name_2" }
        # Default is no category with all files in base dir of each class
        def categories
          {}
        end

        def extension
          raise NotImplementedError
        end

        def base_dir
          raise NotImplementedError
        end

        # Defines which strategy will be used to get templates files
        # RepoTemplateFinder - Finds templates on project repository, templates are filtered per project
        # GlobalTemplateFinder - Finds templates on gitlab installation source, templates can be used in all projects
        def finder(project = nil)
          raise NotImplementedError
        end

        def by_category(category, project = nil, empty_category_title: nil)
          directory = category_directory(category)
          files = finder(project).list_files_for(directory)

          files.map { |f| new(f, project, category: category.presence || empty_category_title) }.sort
        end

        def category_directory(category)
          return base_dir unless category.present?

          File.join(base_dir, categories[category])
        end

        # `repository_template_names` - reads through Gitaly the actual templates names within a
        # given project's repository. This is only used by issue and merge request templates,
        # that need to call this once and then cache the returned value.
        #
        # `template_names` - is an alias to `repository_template_names`. It would read through
        # Gitaly the actual template names within a given project's repository for all file templates
        # other than `issue` and `merge request` description templates, which would instead
        # overwrite the `template_names` method to return a redis cached version, by reading cached values
        # from `repository.issue_template_names_hash` and `repository.merge_request_template_names_hash`
        # methods.
        def repository_template_names(project)
          template_names_by_category(self.all(project))
        end
        alias_method :template_names, :repository_template_names

        def template_names_by_category(items)
          grouped = items.group_by(&:category)
          categories = grouped.keys

          categories.each_with_object({}) do |category, hash|
            hash[category] = grouped[category].map do |item|
              { name: item.name, id: item.key, key: item.key, project_id: item.try(:project_id) }
            end
          end
        end

        def template_subsets(project = nil)
          return [] if project && !project.repository.exists?

          if categories.any?
            categories.keys.to_h do |category|
              files = self.by_category(category, project)
              [category, files.map { |t| { key: t.key, name: t.name, content: t.content } }]
            end
          else
            files = self.all(project)
            files.map { |t| { key: t.key, name: t.name, content: t.content } }
          end
        end
      end
    end
  end
end