Commit bf5e7252 authored by Douwe Maan's avatar Douwe Maan

Recognize commit range with named refs in compare URLs.

parent 4a292aa6
...@@ -22,16 +22,19 @@ class CommitRange ...@@ -22,16 +22,19 @@ class CommitRange
include Referable include Referable
attr_reader :commit_from, :notation, :commit_to attr_reader :commit_from, :notation, :commit_to
attr_reader :ref_from, :ref_to
# Optional Project model # Optional Project model
attr_accessor :project attr_accessor :project
# See `exclude_start?` # The beginning and ending refs can be named or SHAs, and
attr_reader :exclude_start
# The beginning and ending SHAs can be between 6 and 40 hex characters, and
# the range notation can be double- or triple-dot. # the range notation can be double- or triple-dot.
PATTERN = /\h{6,40}\.{2,3}\h{6,40}/ REF_PATTERN = /[0-9a-zA-Z][0-9a-zA-Z_.-]*[0-9a-zA-Z\^]/
PATTERN = /#{REF_PATTERN}\.{2,3}#{REF_PATTERN}/
# In text references, the beginning and ending refs can only be SHAs
# between 6 and 40 hex characters.
STRICT_PATTERN = /\h{6,40}\.{2,3}\h{6,40}/
def self.reference_prefix def self.reference_prefix
'@' '@'
...@@ -45,7 +48,7 @@ class CommitRange ...@@ -45,7 +48,7 @@ class CommitRange
#{link_reference_pattern} | #{link_reference_pattern} |
(?: (?:
(?:#{Project.reference_pattern}#{reference_prefix})? (?:#{Project.reference_pattern}#{reference_prefix})?
(?<commit_range>#{PATTERN}) (?<commit_range>#{STRICT_PATTERN})
) )
}x }x
end end
...@@ -69,12 +72,16 @@ class CommitRange ...@@ -69,12 +72,16 @@ class CommitRange
raise ArgumentError, "invalid CommitRange string format: #{range_string}" raise ArgumentError, "invalid CommitRange string format: #{range_string}"
end end
ref_from, @notation, ref_to = range_string.split(/(\.{2,3})/, 2) @ref_from, @notation, @ref_to = range_string.split(/(\.{2,3})/, 2)
@exclude_start = @notation == '..'
if project.valid_repo? if project.valid_repo?
@commit_from = project.commit(ref_from) @commit_from = project.commit(@ref_from)
@commit_to = project.commit(ref_to) @commit_to = project.commit(@ref_to)
end
if valid_commits?
@ref_from = Commit.truncate_sha(sha_from) if sha_from.start_with?(@ref_from)
@ref_to = Commit.truncate_sha(sha_to) if sha_to.start_with?(@ref_to)
end end
end end
...@@ -89,7 +96,7 @@ class CommitRange ...@@ -89,7 +96,7 @@ class CommitRange
alias_method :id, :to_s alias_method :id, :to_s
def to_reference(from_project = nil) def to_reference(from_project = nil)
reference = Commit.truncate_sha(sha_from) + notation + Commit.truncate_sha(sha_to) reference = ref_from + notation + ref_to
if cross_project_reference?(from_project) if cross_project_reference?(from_project)
reference = project.to_reference + self.class.reference_prefix + reference reference = project.to_reference + self.class.reference_prefix + reference
...@@ -111,7 +118,7 @@ class CommitRange ...@@ -111,7 +118,7 @@ class CommitRange
end end
def exclude_start? def exclude_start?
exclude_start @notation == '..'
end end
# Check if both the starting and ending commit IDs exist in a project's # Check if both the starting and ending commit IDs exist in a project's
......
...@@ -5,8 +5,8 @@ module Gitlab::Markdown ...@@ -5,8 +5,8 @@ module Gitlab::Markdown
include FilterSpecHelper include FilterSpecHelper
let(:project) { create(:project, :public) } let(:project) { create(:project, :public) }
let(:commit1) { project.commit } let(:commit1) { project.commit("HEAD~2") }
let(:commit2) { project.commit("HEAD~2") } let(:commit2) { project.commit }
let(:range) { CommitRange.new("#{commit1.id}...#{commit2.id}", project) } let(:range) { CommitRange.new("#{commit1.id}...#{commit2.id}", project) }
let(:range2) { CommitRange.new("#{commit1.id}..#{commit2.id}", project) } let(:range2) { CommitRange.new("#{commit1.id}..#{commit2.id}", project) }
...@@ -89,7 +89,7 @@ module Gitlab::Markdown ...@@ -89,7 +89,7 @@ module Gitlab::Markdown
link = doc.css('a').first link = doc.css('a').first
expect(link).to have_attribute('data-commit-range') expect(link).to have_attribute('data-commit-range')
expect(link.attr('data-commit-range')).to eq range.to_reference expect(link.attr('data-commit-range')).to eq range.to_s
end end
it 'supports an :only_path option' do it 'supports an :only_path option' do
...@@ -146,7 +146,8 @@ module Gitlab::Markdown ...@@ -146,7 +146,8 @@ module Gitlab::Markdown
context 'URL cross-project reference' do context 'URL cross-project reference' do
let(:namespace) { create(:namespace, name: 'cross-reference') } let(:namespace) { create(:namespace, name: 'cross-reference') }
let(:project2) { create(:project, :public, namespace: namespace) } let(:project2) { create(:project, :public, namespace: namespace) }
let(:reference) { urls.namespace_project_compare_url(project2.namespace, project2, range.to_param) } let(:range) { CommitRange.new("#{commit1.id}...master", project) }
let(:reference) { urls.namespace_project_compare_url(project2.namespace, project2, from: commit1.id, to: 'master') }
before do before do
range.project = project2 range.project = project2
...@@ -156,7 +157,7 @@ module Gitlab::Markdown ...@@ -156,7 +157,7 @@ module Gitlab::Markdown
doc = filter("See #{reference}") doc = filter("See #{reference}")
expect(doc.css('a').first.attr('href')). expect(doc.css('a').first.attr('href')).
to eq urls.namespace_project_compare_url(project2.namespace, project2, range.to_param) to eq reference
end end
it 'links with adjacent text' do it 'links with adjacent text' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment