summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Speicher <rspeicher@gmail.com>2015-04-06 11:44:49 -0400
committerRobert Speicher <rspeicher@gmail.com>2015-04-20 13:01:42 -0400
commit4cb1cc2b6413329c89d1043975317001666db13d (patch)
treee11ca51a8c8839a35449f2ef7755f23d452f4e26
parentd520fe07ad90cb610927e833060908bdc04fa550 (diff)
downloadgitlab-ce-4cb1cc2b6413329c89d1043975317001666db13d.tar.gz
Make CommitRange and Snippets cross-referable
-rw-r--r--lib/gitlab/markdown/snippet_reference_filter.rb26
-rw-r--r--spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb45
-rw-r--r--spec/lib/gitlab/markdown/commit_reference_filter_spec.rb7
-rw-r--r--spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb85
4 files changed, 96 insertions, 67 deletions
diff --git a/lib/gitlab/markdown/snippet_reference_filter.rb b/lib/gitlab/markdown/snippet_reference_filter.rb
index 0e34ab4bc1e..42f035ce295 100644
--- a/lib/gitlab/markdown/snippet_reference_filter.rb
+++ b/lib/gitlab/markdown/snippet_reference_filter.rb
@@ -7,11 +7,14 @@ module Gitlab
# snippets that do not exist are ignored.
#
# Context options:
- # :project (required) - Current project.
+ # :project (required) - Current project, ignored when reference is
+ # cross-project.
# :reference_class - Custom CSS class added to reference links.
# :only_path - Generate path-only links.
#
class SnippetReferenceFilter < HTML::Pipeline::Filter
+ include CrossProjectReference
+
# Public: Find `$123` snippet references in text
#
# SnippetReferenceFilter.references_in(text) do |match, snippet|
@@ -20,17 +23,20 @@ module Gitlab
#
# text - String text to search.
#
- # Yields the String match and the Integer snippet ID.
+ # Yields the String match, the Integer snippet ID, and an optional String
+ # of the external project reference.
#
# Returns a String replaced with the return of the block.
def self.references_in(text)
text.gsub(SNIPPET_PATTERN) do |match|
- yield match, $~[:snippet].to_i
+ yield match, $~[:snippet].to_i, $~[:project]
end
end
# Pattern used to extract `$123` snippet references from text
- SNIPPET_PATTERN = /\$(?<snippet>\d+)/
+ #
+ # This pattern supports cross-project references.
+ SNIPPET_PATTERN = /#{PROJECT_PATTERN}?\$(?<snippet>\d+)/
# Don't look for references in text nodes that are children of these
# elements.
@@ -40,7 +46,7 @@ module Gitlab
doc.search('text()').each do |node|
content = node.to_html
- next if project.nil?
+ next if context[:project].nil?
next unless content.match(SNIPPET_PATTERN)
next if has_ancestor?(node, IGNORE_PARENTS)
@@ -66,9 +72,9 @@ module Gitlab
# Returns a String with `$123` references replaced with links. All links
# have `gfm` and `gfm-snippet` class names attached for styling.
def snippet_link_filter(text)
- project = context[:project]
+ self.class.references_in(text) do |match, id, project_ref|
+ project = self.project_from_ref(project_ref)
- self.class.references_in(text) do |match, id|
if snippet = project.snippets.find_by(id: id)
title = "Snippet: #{snippet.title}"
klass = "gfm gfm-snippet #{context[:reference_class]}".strip
@@ -77,17 +83,13 @@ module Gitlab
%(<a href="#{url}"
title="#{title}"
- class="#{klass}">$#{id}</a>)
+ class="#{klass}">#{project_ref}$#{id}</a>)
else
match
end
end
end
- def project
- context[:project]
- end
-
def url_for_snippet(snippet, project)
h = Rails.application.routes.url_helpers
h.namespace_project_snippet_url(project.namespace, project, snippet,
diff --git a/spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb b/spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb
index 3545d7f8085..67de23014f8 100644
--- a/spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb
+++ b/spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb
@@ -51,7 +51,7 @@ module Gitlab::Markdown
expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/)
end
- it 'ignores invalid issue IDs' do
+ it 'ignores invalid commit IDs' do
exp = act = "See #{commit1.id.reverse}...#{commit2.id}"
expect(project).to receive(:valid_repo?).and_return(true)
@@ -83,31 +83,32 @@ module Gitlab::Markdown
end
end
- # TODO (rspeicher): Remove or re-enable
- # context 'cross-project reference' do
- # let(:namespace) { create(:namespace, name: 'cross-reference') }
- # let(:project2) { create(:project, namespace: namespace) }
- # let(:commit1) { project.repository.commit }
- # let(:commit2) { project.repository.commit("HEAD~2") }
- # let(:reference) { "#{project2.path_with_namespace}@#{commit.id}" }
+ context 'cross-project reference' do
+ let(:namespace) { create(:namespace, name: 'cross-reference') }
+ let(:project2) { create(:project, namespace: namespace) }
+ let(:commit1) { project.repository.commit }
+ let(:commit2) { project.repository.commit("HEAD~2") }
+ let(:reference) { "#{project2.path_with_namespace}@#{commit1.id}...#{commit2.id}" }
- # it 'links to a valid reference' do
- # doc = filter("See #{reference}")
+ it 'links to a valid reference' do
+ doc = filter("See #{reference}")
- # expect(doc.css('a').first.attr('href')).
- # to eq urls.namespace_project_commit_url(project2.namespace, project2, commit.id)
- # end
+ expect(doc.css('a').first.attr('href')).
+ to eq urls.namespace_project_compare_url(project2.namespace, project2, from: commit1.id, to: commit2.id)
+ end
- # it 'links with adjacent text' do
- # doc = filter("Fixed (#{reference}.)")
- # expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/)
- # end
+ it 'links with adjacent text' do
+ doc = filter("Fixed (#{reference}.)")
+ expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/)
+ end
- # it 'ignores invalid issue IDs on the referenced project' do
- # exp = act = "Fixed #{project2.path_with_namespace}##{commit.id.reverse}"
+ it 'ignores invalid commit IDs on the referenced project' do
+ exp = act = "Fixed #{project2.path_with_namespace}##{commit1.id.reverse}...#{commit2.id}"
+ expect(filter(act).to_html).to eq exp
- # expect(filter(act).to_html).to eq exp
- # end
- # end
+ exp = act = "Fixed #{project2.path_with_namespace}##{commit1.id}...#{commit2.id.reverse}"
+ expect(filter(act).to_html).to eq exp
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/markdown/commit_reference_filter_spec.rb b/spec/lib/gitlab/markdown/commit_reference_filter_spec.rb
index 15851d3bd34..f72953fd84e 100644
--- a/spec/lib/gitlab/markdown/commit_reference_filter_spec.rb
+++ b/spec/lib/gitlab/markdown/commit_reference_filter_spec.rb
@@ -38,7 +38,7 @@ module Gitlab::Markdown
expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/)
end
- it 'ignores invalid issue IDs' do
+ it 'ignores invalid commit IDs' do
exp = act = "See #{reference.reverse}"
expect(project).to receive(:valid_repo?).and_return(true)
@@ -88,9 +88,8 @@ module Gitlab::Markdown
expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/)
end
- it 'ignores invalid issue IDs on the referenced project' do
- exp = act = "Fixed #{project2.path_with_namespace}##{commit.id.reverse}"
-
+ it 'ignores invalid commit IDs on the referenced project' do
+ exp = act = "Committed #{project2.path_with_namespace}##{commit.id.reverse}"
expect(filter(act).to_html).to eq exp
end
end
diff --git a/spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb b/spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb
index d79a7e544a3..a3285998ac1 100644
--- a/spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb
+++ b/spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb
@@ -20,45 +20,72 @@ module Gitlab::Markdown
end
end
- it 'links to a valid reference' do
- doc = filter("See #{reference}")
+ context 'internal reference' do
+ it 'links to a valid reference' do
+ doc = filter("See #{reference}")
- expect(doc.css('a').first.attr('href')).to eq urls.
- namespace_project_snippet_url(project.namespace, project, snippet)
- end
+ expect(doc.css('a').first.attr('href')).to eq urls.
+ namespace_project_snippet_url(project.namespace, project, snippet)
+ end
- it 'links with adjacent text' do
- doc = filter("Snippet (#{reference}.)")
- expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/)
- end
+ it 'links with adjacent text' do
+ doc = filter("Snippet (#{reference}.)")
+ expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/)
+ end
- it 'ignores invalid snippet IDs' do
- exp = act = "Snippet $#{snippet.id + 1}"
+ it 'ignores invalid snippet IDs' do
+ exp = act = "Snippet $#{snippet.id + 1}"
- expect(filter(act).to_html).to eq exp
- end
+ expect(filter(act).to_html).to eq exp
+ end
- it 'includes a title attribute' do
- doc = filter("Snippet #{reference}")
- expect(doc.css('a').first.attr('title')).to eq "Snippet: #{snippet.title}"
- end
+ it 'includes a title attribute' do
+ doc = filter("Snippet #{reference}")
+ expect(doc.css('a').first.attr('title')).to eq "Snippet: #{snippet.title}"
+ end
- it 'includes default classes' do
- doc = filter("Snippet #{reference}")
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-snippet'
- end
+ it 'includes default classes' do
+ doc = filter("Snippet #{reference}")
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-snippet'
+ end
- it 'includes an optional custom class' do
- doc = filter("Snippet #{reference}", reference_class: 'custom')
- expect(doc.css('a').first.attr('class')).to include 'custom'
+ it 'includes an optional custom class' do
+ doc = filter("Snippet #{reference}", reference_class: 'custom')
+ expect(doc.css('a').first.attr('class')).to include 'custom'
+ end
+
+ it 'supports an :only_path context' do
+ doc = filter("Snippet #{reference}", only_path: true)
+ link = doc.css('a').first.attr('href')
+
+ expect(link).not_to match %r(https?://)
+ expect(link).to eq urls.namespace_project_snippet_url(project.namespace, project, snippet, only_path: true)
+ end
end
- it 'supports an :only_path context' do
- doc = filter("Snippet #{reference}", only_path: true)
- link = doc.css('a').first.attr('href')
+ context 'cross-project reference' do
+ let(:namespace) { create(:namespace, name: 'cross-reference') }
+ let(:project2) { create(:empty_project, namespace: namespace) }
+ let(:snippet) { create(:project_snippet, project: project2) }
+ let(:reference) { "#{project2.path_with_namespace}$#{snippet.id}" }
+
+ it 'links to a valid reference' do
+ doc = filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).
+ to eq urls.namespace_project_snippet_url(project2.namespace, project2, snippet)
+ end
- expect(link).not_to match %r(https?://)
- expect(link).to eq urls.namespace_project_snippet_url(project.namespace, project, snippet, only_path: true)
+ it 'links with adjacent text' do
+ doc = filter("See (#{reference}.)")
+ expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/)
+ end
+
+ it 'ignores invalid snippet IDs on the referenced project' do
+ exp = act = "See #{project2.path_with_namespace}$#{snippet.id + 1}"
+
+ expect(filter(act).to_html).to eq exp
+ end
end
end
end