Skip to content
Snippets Groups Projects
Commit f272ee6e authored by Oswaldo Ferreira's avatar Oswaldo Ferreira
Browse files

Add shorthand support to gitlab markdown references

parent 3ebb815a
No related branches found
No related tags found
No related merge requests found
Showing
with 120 additions and 137 deletions
Loading
Loading
@@ -174,7 +174,7 @@ module GitlabMarkdownHelper
# Returns a String
def cross_project_reference(project, entity)
if entity.respond_to?(:to_reference)
"#{project.to_reference}#{entity.to_reference}"
entity.to_reference(project)
else
''
end
Loading
Loading
Loading
Loading
@@ -82,12 +82,6 @@ module LabelsHelper
span.html_safe
end
 
def render_colored_cross_project_label(label, source_project = nil, tooltip: true)
label_suffix = source_project ? source_project.name_with_namespace : label.project.name_with_namespace
label_suffix = " <i>in #{escape_once(label_suffix)}</i>"
render_colored_label(label, label_suffix, tooltip: tooltip)
end
def suggested_colors
[
'#0033CC',
Loading
Loading
@@ -166,6 +160,5 @@ module LabelsHelper
end
 
# Required for Banzai::Filter::LabelReferenceFilter
module_function :render_colored_label, :render_colored_cross_project_label,
:text_color_for_bg, :escape_once
module_function :render_colored_label, :text_color_for_bg, :escape_once
end
Loading
Loading
@@ -92,19 +92,11 @@ class Commit
end
 
def to_reference(from_project = nil)
if cross_project_reference?(from_project)
project.to_reference + self.class.reference_prefix + self.id
else
self.id
end
commit_reference(from_project, id)
end
 
def reference_link_text(from_project = nil)
if cross_project_reference?(from_project)
project.to_reference + self.class.reference_prefix + self.short_id
else
self.short_id
end
commit_reference(from_project, short_id)
end
 
def diff_line_count
Loading
Loading
@@ -329,6 +321,16 @@ class Commit
 
private
 
def commit_reference(from_project, referable_commit_id)
reference = project.to_reference(from_project)
if reference.present?
"#{reference}#{self.class.reference_prefix}#{referable_commit_id}"
else
referable_commit_id
end
end
def find_author_by_any_email
User.find_by_any_email(author_email.downcase)
end
Loading
Loading
Loading
Loading
@@ -90,21 +90,24 @@ class CommitRange
alias_method :id, :to_s
 
def to_reference(from_project = nil)
if cross_project_reference?(from_project)
project.to_reference + self.class.reference_prefix + self.id
project_reference = project.to_reference(from_project)
if project_reference.present?
project_reference + self.class.reference_prefix + self.id
else
self.id
end
end
 
def reference_link_text(from_project = nil)
reference = ref_from + notation + ref_to
project_reference = project.to_reference(from_project)
reference = ref_from + notation + ref_to
 
if cross_project_reference?(from_project)
reference = project.to_reference + self.class.reference_prefix + reference
if project_reference.present?
project_reference + self.class.reference_prefix + reference
else
reference
end
reference
end
 
# Return a Hash of parameters for passing to a URL helper
Loading
Loading
Loading
Loading
@@ -72,17 +72,4 @@ module Referable
}x
end
end
private
# Check if a reference is being done cross-project
#
# from_project - Refering Project object
def cross_project_reference?(from_project)
if self.is_a?(Project)
self != from_project
else
from_project && self.project && self.project != from_project
end
end
end
Loading
Loading
@@ -153,11 +153,7 @@ class Issue < ActiveRecord::Base
def to_reference(from_project = nil)
reference = "#{self.class.reference_prefix}#{iid}"
 
if cross_project_reference?(from_project)
reference = project.to_reference + reference
end
reference
"#{project.to_reference(from_project)}#{reference}"
end
 
def referenced_merge_requests(current_user = nil)
Loading
Loading
Loading
Loading
@@ -144,9 +144,10 @@ class Label < ActiveRecord::Base
#
# Examples:
#
# Label.first.to_reference # => "~1"
# Label.first.to_reference(format: :name) # => "~\"bug\""
# Label.first.to_reference(project1, project2) # => "gitlab-org/gitlab-ce~1"
# Label.first.to_reference # => "~1"
# Label.first.to_reference(format: :name) # => "~\"bug\""
# Label.first.to_reference(project, same_namespace_project) # => "gitlab-ce~1"
# Label.first.to_reference(project, another_namespace_project) # => "gitlab-org/gitlab-ce~1"
#
# Returns a String
#
Loading
Loading
@@ -154,8 +155,8 @@ class Label < ActiveRecord::Base
format_reference = label_format_reference(format)
reference = "#{self.class.reference_prefix}#{format_reference}"
 
if cross_project_reference?(source_project, target_project)
source_project.to_reference + reference
if source_project
"#{source_project.to_reference(target_project)}#{reference}"
else
reference
end
Loading
Loading
@@ -169,10 +170,6 @@ class Label < ActiveRecord::Base
 
private
 
def cross_project_reference?(source_project, target_project)
source_project && target_project && source_project != target_project
end
def issues_count(user, params = {})
params.merge!(subject_foreign_key => subject.id, label_name: title, scope: 'all')
IssuesFinder.new(user, params.with_indifferent_access).execute.count
Loading
Loading
Loading
Loading
@@ -176,11 +176,7 @@ class MergeRequest < ActiveRecord::Base
def to_reference(from_project = nil)
reference = "#{self.class.reference_prefix}#{iid}"
 
if cross_project_reference?(from_project)
reference = project.to_reference + reference
end
reference
"#{project.to_reference(from_project)}#{reference}"
end
 
def first_commit
Loading
Loading
Loading
Loading
@@ -113,19 +113,16 @@ class Milestone < ActiveRecord::Base
#
# Examples:
#
# Milestone.first.to_reference # => "%1"
# Milestone.first.to_reference(format: :name) # => "%\"goal\""
# Milestone.first.to_reference(project) # => "gitlab-org/gitlab-ce%1"
# Milestone.first.to_reference # => "%1"
# Milestone.first.to_reference(format: :name) # => "%\"goal\""
# Milestone.first.to_reference(cross_namespace_project) # => "gitlab-org/gitlab-ce%1"
# Milestone.first.to_reference(same_namespace_project) # => "gitlab-ce%1"
#
def to_reference(from_project = nil, format: :iid)
format_reference = milestone_format_reference(format)
reference = "#{self.class.reference_prefix}#{format_reference}"
 
if cross_project_reference?(from_project)
project.to_reference + reference
else
reference
end
"#{project.to_reference(from_project)}#{reference}"
end
 
def reference_link_text(from_project = nil)
Loading
Loading
Loading
Loading
@@ -419,7 +419,11 @@ class Project < ActiveRecord::Base
 
def reference_pattern
name_pattern = Gitlab::Regex::NAMESPACE_REGEX_STR
%r{(?<project>#{name_pattern}/#{name_pattern})}
%r{
((?<namespace>#{name_pattern})\/)?
(?<project>#{name_pattern})
}x
end
 
def trending
Loading
Loading
@@ -650,8 +654,20 @@ class Project < ActiveRecord::Base
end
end
 
def to_reference(_from_project = nil)
path_with_namespace
def to_reference(from_project = nil)
if cross_namespace_reference?(from_project)
path_with_namespace
elsif cross_project_reference?(from_project)
path
end
end
def to_human_reference(from_project = nil)
if cross_namespace_reference?(from_project)
name_with_namespace
elsif cross_project_reference?(from_project)
name
end
end
 
def web_url
Loading
Loading
@@ -1327,10 +1343,21 @@ class Project < ActiveRecord::Base
 
private
 
# Check if a reference is being done cross-project
#
# from_project - Refering Project object
def cross_project_reference?(from_project)
from_project && self != from_project
end
def pushes_since_gc_redis_key
"projects/#{id}/pushes_since_gc"
end
 
def cross_namespace_reference?(from_project)
from_project && namespace != from_project.namespace
end
def default_branch_protected?
current_application_settings.default_branch_protection == Gitlab::Access::PROTECTION_FULL ||
current_application_settings.default_branch_protection == Gitlab::Access::PROTECTION_DEV_CAN_MERGE
Loading
Loading
Loading
Loading
@@ -67,11 +67,11 @@ class Snippet < ActiveRecord::Base
def to_reference(from_project = nil)
reference = "#{self.class.reference_prefix}#{id}"
 
if cross_project_reference?(from_project)
reference = project.to_reference + reference
if project.present?
"#{project.to_reference(from_project)}#{reference}"
else
reference
end
reference
end
 
def self.content_types
Loading
Loading
---
title: Add shorthand support to gitlab markdown references
merge_request: 7255
author: Oswaldo Ferreira
Loading
Loading
@@ -33,7 +33,7 @@ module Banzai
# Returns a String replaced with the return of the block.
def self.references_in(text, pattern = object_class.reference_pattern)
text.gsub(pattern) do |match|
yield match, $~[object_sym].to_i, $~[:project], $~
yield match, $~[object_sym].to_i, $~[:project], $~[:namespace], $~
end
end
 
Loading
Loading
@@ -145,8 +145,9 @@ module Banzai
# Returns a String with references replaced with links. All links
# have `gfm` and `gfm-OBJECT_NAME` class names attached for styling.
def object_link_filter(text, pattern, link_content: nil)
references_in(text, pattern) do |match, id, project_ref, matches|
project = project_from_ref_cached(project_ref)
references_in(text, pattern) do |match, id, project_ref, namespace_ref, matches|
project_path = full_project_path(namespace_ref, project_ref)
project = project_from_ref_cached(project_path)
 
if project && object = find_object_cached(project, id)
title = object_link_title(object)
Loading
Loading
@@ -217,10 +218,9 @@ module Banzai
 
nodes.each do |node|
node.to_html.scan(regex) do
project = $~[:project] || current_project_path
project_path = full_project_path($~[:namespace], $~[:project])
symbol = $~[object_sym]
refs[project] << symbol if object_class.reference_valid?(symbol)
refs[project_path] << symbol if object_class.reference_valid?(symbol)
end
end
 
Loading
Loading
@@ -272,8 +272,19 @@ module Banzai
@current_project_path ||= project.path_with_namespace
end
 
def current_project_namespace_path
@current_project_namespace_path ||= project.namespace.path
end
private
 
def full_project_path(namespace, project_ref)
return current_project_path unless project_ref
namespace_ref = namespace || current_project_namespace_path
"#{namespace_ref}/#{project_ref}"
end
def project_refs_cache
RequestStore[:banzai_project_refs] ||= {}
end
Loading
Loading
Loading
Loading
@@ -12,7 +12,7 @@ module Banzai
 
def self.references_in(text, pattern = CommitRange.reference_pattern)
text.gsub(pattern) do |match|
yield match, $~[:commit_range], $~[:project], $~
yield match, $~[:commit_range], $~[:project], $~[:namespace], $~
end
end
 
Loading
Loading
Loading
Loading
@@ -12,7 +12,7 @@ module Banzai
 
def self.references_in(text, pattern = Commit.reference_pattern)
text.gsub(pattern) do |match|
yield match, $~[:commit], $~[:project], $~
yield match, $~[:commit], $~[:project], $~[:namespace], $~
end
end
 
Loading
Loading
Loading
Loading
@@ -14,16 +14,18 @@ module Banzai
 
def self.references_in(text, pattern = Label.reference_pattern)
unescape_html_entities(text).gsub(pattern) do |match|
yield match, $~[:label_id].to_i, $~[:label_name], $~[:project], $~
yield match, $~[:label_id].to_i, $~[:label_name], $~[:project], $~[:namespace], $~
end
end
 
def references_in(text, pattern = Label.reference_pattern)
unescape_html_entities(text).gsub(pattern) do |match|
label = find_label($~[:project], $~[:label_id], $~[:label_name])
namespace, project = $~[:namespace], $~[:project]
project_path = full_project_path(namespace, project)
label = find_label(project_path, $~[:label_id], $~[:label_name])
 
if label
yield match, label.id, $~[:project], $~
yield match, label.id, project, namespace, $~
else
match
end
Loading
Loading
@@ -64,48 +66,12 @@ module Banzai
end
 
def object_link_text(object, matches)
if same_group?(object) && namespace_match?(matches)
render_same_project_label(object)
elsif same_project?(object)
render_same_project_label(object)
else
render_cross_project_label(object, matches)
end
end
def same_group?(object)
object.is_a?(GroupLabel) && object.group == project.group
end
def namespace_match?(matches)
matches[:project].blank? || matches[:project] == project.path_with_namespace
end
def same_project?(object)
object.is_a?(ProjectLabel) && object.project == project
end
def user
context[:current_user] || context[:author]
end
def project
context[:project]
end
def render_same_project_label(object)
LabelsHelper.render_colored_label(object)
end
def render_cross_project_label(object, matches)
source_project =
if matches[:project]
Project.find_with_namespace(matches[:project])
else
object.project
end
project_path = full_project_path(matches[:namespace], matches[:project])
project_from_ref = project_from_ref_cached(project_path)
reference = project_from_ref.to_human_reference(project)
label_suffix = " <i>in #{reference}</i>" if reference.present?
 
LabelsHelper.render_colored_cross_project_label(object, source_project)
LabelsHelper.render_colored_label(object, label_suffix)
end
 
def unescape_html_entities(text)
Loading
Loading
Loading
Loading
@@ -19,18 +19,20 @@ module Banzai
return super(text, pattern) if pattern != Milestone.reference_pattern
 
text.gsub(pattern) do |match|
milestone = find_milestone($~[:project], $~[:milestone_iid], $~[:milestone_name])
milestone = find_milestone($~[:project], $~[:namespace], $~[:milestone_iid], $~[:milestone_name])
 
if milestone
yield match, milestone.iid, $~[:project], $~
yield match, milestone.iid, $~[:project], $~[:namespace], $~
else
match
end
end
end
 
def find_milestone(project_ref, milestone_id, milestone_name)
project = project_from_ref(project_ref)
def find_milestone(project_ref, namespace_ref, milestone_id, milestone_name)
project_path = full_project_path(namespace_ref, project_ref)
project = project_from_ref(project_path)
return unless project
 
milestone_params = milestone_params(milestone_id, milestone_name)
Loading
Loading
@@ -52,11 +54,13 @@ module Banzai
end
 
def object_link_text(object, matches)
if context[:project] == object.project
super
milestone_link = escape_once(super)
reference = object.project.to_reference(project)
if reference.present?
"#{milestone_link} <i>in #{reference}</i>".html_safe
else
"#{escape_once(super)} <i>in #{escape_once(object.project.path_with_namespace)}</i>".
html_safe
milestone_link
end
end
 
Loading
Loading
Loading
Loading
@@ -28,7 +28,7 @@ feature 'issue move to another project' do
let(:new_project) { create(:project) }
let(:new_project_search) { create(:project) }
let(:text) { "Text with #{mr.to_reference}" }
let(:cross_reference) { old_project.to_reference }
let(:cross_reference) { old_project.to_reference(new_project) }
 
background do
old_project.team << [user, :reporter]
Loading
Loading
Loading
Loading
@@ -40,7 +40,7 @@ feature 'Create New Merge Request', feature: true, js: true do
 
visit new_namespace_project_merge_request_path(project.namespace, project, merge_request: { target_project_id: private_project.id })
 
expect(page).not_to have_content private_project.to_reference
expect(page).not_to have_content private_project.path_with_namespace
end
end
 
Loading
Loading
Loading
Loading
@@ -7,7 +7,7 @@ describe LabelsHelper do
 
context 'without subject' do
it "uses the label's project" do
expect(link_to_label(label)).to match %r{<a href="/#{label.project.to_reference}/issues\?label_name%5B%5D=#{label.name}">.*</a>}
expect(link_to_label(label)).to match %r{<a href="/#{label.project.path_with_namespace}/issues\?label_name%5B%5D=#{label.name}">.*</a>}
end
end
 
Loading
Loading
@@ -32,7 +32,7 @@ describe LabelsHelper do
['issue', :issue, 'merge_request', :merge_request].each do |type|
context "set to #{type}" do
it 'links to correct page' do
expect(link_to_label(label, type: type)).to match %r{<a href="/#{label.project.to_reference}/#{type.to_s.pluralize}\?label_name%5B%5D=#{label.name}">.*</a>}
expect(link_to_label(label, type: type)).to match %r{<a href="/#{label.project.path_with_namespace}/#{type.to_s.pluralize}\?label_name%5B%5D=#{label.name}">.*</a>}
end
end
end
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment