summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRobert Speicher <rspeicher@gmail.com>2015-04-13 15:45:30 -0400
committerRobert Speicher <rspeicher@gmail.com>2015-04-20 13:01:43 -0400
commit43c62ca3f262ac6bfbdbe36312d621dac0a12da1 (patch)
tree2c9e8bac057d18d81040e9da0365cb7d35bb177d /lib
parent29604ff2c3d6fc81c3ac26b590f912fea15d58a6 (diff)
downloadgitlab-ce-43c62ca3f262ac6bfbdbe36312d621dac0a12da1.tar.gz
Remove Gitlab::Markdown from Gitlab::ReferenceExtractor
Diffstat (limited to 'lib')
-rw-r--r--lib/gitlab/reference_extractor.rb68
1 files changed, 66 insertions, 2 deletions
diff --git a/lib/gitlab/reference_extractor.rb b/lib/gitlab/reference_extractor.rb
index a502a8fe9cd..64e8a650107 100644
--- a/lib/gitlab/reference_extractor.rb
+++ b/lib/gitlab/reference_extractor.rb
@@ -3,8 +3,6 @@ module Gitlab
class ReferenceExtractor
attr_accessor :project, :current_user, :references
- include ::Gitlab::Markdown
-
def initialize(project, current_user = nil)
@project = project
@current_user = current_user
@@ -87,6 +85,72 @@ module Gitlab
private
+ NAME_STR = Gitlab::Regex::NAMESPACE_REGEX_STR
+ PROJ_STR = "(?<project>#{NAME_STR}/#{NAME_STR})"
+
+ REFERENCE_PATTERN = %r{
+ (?<prefix>\W)? # Prefix
+ ( # Reference
+ @(?<user>#{NAME_STR}) # User name
+ |~(?<label>\d+) # Label ID
+ |(?<issue>([A-Z\-]+-)\d+) # JIRA Issue ID
+ |#{PROJ_STR}?\#(?<issue>([a-zA-Z\-]+-)?\d+) # Issue ID
+ |#{PROJ_STR}?!(?<merge_request>\d+) # MR ID
+ |\$(?<snippet>\d+) # Snippet ID
+ |(#{PROJ_STR}@)?(?<commit_range>[\h]{6,40}\.{2,3}[\h]{6,40}) # Commit range
+ |(#{PROJ_STR}@)?(?<commit>[\h]{6,40}) # Commit ID
+ )
+ (?<suffix>\W)? # Suffix
+ }x.freeze
+
+ TYPES = %i(user issue label merge_request snippet commit commit_range).freeze
+
+ def parse_references(text, project = @project)
+ # parse reference links
+ text.gsub!(REFERENCE_PATTERN) do |match|
+ type = TYPES.detect { |t| $~[t].present? }
+
+ actual_project = project
+ project_prefix = nil
+ project_path = $LAST_MATCH_INFO[:project]
+ if project_path
+ actual_project = ::Project.find_with_namespace(project_path)
+ actual_project = nil unless can?(current_user, :read_project, actual_project)
+ project_prefix = project_path
+ end
+
+ parse_result($LAST_MATCH_INFO, type,
+ actual_project, project_prefix) || match
+ end
+ end
+
+ # Called from #parse_references. Attempts to build a gitlab reference
+ # link. Returns nil if +type+ is nil, if the match string is an HTML
+ # entity, if the reference is invalid, or if the matched text includes an
+ # invalid project path.
+ def parse_result(match_info, type, project, project_prefix)
+ prefix = match_info[:prefix]
+ suffix = match_info[:suffix]
+
+ return nil if html_entity?(prefix, suffix) || type.nil?
+ return nil if project.nil? && !project_prefix.nil?
+
+ identifier = match_info[type]
+ ref_link = reference_link(type, identifier, project, project_prefix)
+
+ if ref_link
+ "#{prefix}#{ref_link}#{suffix}"
+ else
+ nil
+ end
+ end
+
+ # Return true if the +prefix+ and +suffix+ indicate that the matched string
+ # is an HTML entity like &amp;
+ def html_entity?(prefix, suffix)
+ prefix && suffix && prefix[0] == '&' && suffix[-1] == ';'
+ end
+
def reference_link(type, identifier, project, _)
references[type] << [project, identifier]
end