Skip to content
Snippets Groups Projects
Select Git revision
  • move-gl-dropdown
  • improve-table-pagination-spec
  • move-markdown-preview
  • winh-fix-merge-request-spec
  • master default
  • index-namespaces-lower-name
  • winh-single-karma-test
  • 10-3-stable
  • 36782-replace-team-user-role-with-add_role-user-in-specs
  • winh-modal-internal-state
  • tz-ide-file-icons
  • 38869-milestone-select
  • update-autodevops-template
  • jivl-activate-repo-cookie-preferences
  • qa-add-deploy-key
  • docs-move-article-ldap
  • 40780-choose-file
  • 22643-manual-job-page
  • refactor-cluster-show-page-conservative
  • dm-sidekiq-versioning
  • v10.4.0.pre
  • v10.3.0
  • v10.3.0-rc5
  • v10.3.0-rc4
  • v10.3.0-rc3
  • v10.3.0-rc2
  • v10.2.5
  • v10.3.0-rc1
  • v10.0.7
  • v10.1.5
  • v10.2.4
  • v10.2.3
  • v10.2.2
  • v10.2.1
  • v10.3.0.pre
  • v10.2.0
  • v10.2.0-rc4
  • v10.2.0-rc3
  • v10.1.4
  • v10.2.0-rc2
40 results

reference_extractor.rb

Forked from GitLab.org / GitLab FOSS
37063 commits behind the upstream repository.
reference_extractor.rb 2.41 KiB
module Gitlab
  # Extract possible GFM references from an arbitrary String for further processing.
  class ReferenceExtractor
    attr_accessor :project, :current_user, :references

    include Markdown

    def initialize(project, current_user = nil)
      @project = project
      @current_user = current_user

      @references = Hash.new { [] }
    end

    def can?(user, action, subject)
      Ability.abilities.allowed?(user, action, subject)
    end

    def analyze(text)
      text = text.dup

      # Remove preformatted/code blocks so that references are not included
      text.gsub!(%r{<pre>.*?</pre>|<code>.*?</code>}m) { |match| '' }
      text.gsub!(%r{^```.*?^```}m) { |match| '' }

      parse_references(text)
    end

    # Given a valid project, resolve the extracted identifiers of the requested type to
    # model objects.

    def users
      references[:users].map do |entry|
        if entry[:id] == "all"
          project.team.members.flatten
        elsif namespace = Namespace.find_by(path: entry[:id])
          if namespace.is_a?(Group)
            namespace.users
          else
            namespace.owner
          end
        end
      end.flatten.compact
    end

    def labels
      references[:labels].map do |entry|
        project.labels.where(id: entry[:id]).first
      end.compact
    end

    def issues
      references[:issues].map do |entry|
        if entry[:project].default_issues_tracker?
          entry[:project].issues.where(iid: entry[:id]).first
        end
      end.compact
    end

    def merge_requests
      references[:merge_requests].map do |entry|
        entry[:project].merge_requests.where(iid: entry[:id]).first
      end.compact
    end

    def snippets
      references[:snippets].map do |entry|
        project.snippets.where(id: entry[:id]).first
      end.compact
    end

    def commits
      references[:commits].map do |entry|
        repo = entry[:project].repository
        repo.commit(entry[:id]) if repo
      end.compact
    end

    def commit_ranges
      references[:commit_ranges].map do |entry|
        repo = entry[:project].repository if entry[:project]
        if repo
          from_id, to_id = entry[:id].split(/\.{2,3}/, 2)
          [repo.commit(from_id), repo.commit(to_id)]
        end
      end.compact
    end

    private

    def reference_link(type, identifier, project, user, _)
      references[type] << { project: project, id: identifier }
    end
  end
end