summaryrefslogtreecommitdiff
path: root/app/models/commit_range.rb
diff options
context:
space:
mode:
authorTomasz Maczukin <tomasz@maczukin.pl>2015-12-21 13:27:34 +0100
committerTomasz Maczukin <tomasz@maczukin.pl>2015-12-21 13:27:34 +0100
commit3cfd892f382d3784f614fea75f929c44fe838559 (patch)
treecb9aa9ab48ee02e8f00e8506fecc182d1e66b9ea /app/models/commit_range.rb
parent85ad95be741848fbf15a01789f065e001326cefa (diff)
parent4b4cbf0ce4925e22a635e4432e7ac8602199fa5b (diff)
downloadgitlab-ce-3cfd892f382d3784f614fea75f929c44fe838559.tar.gz
Merge branch 'master' into fix/visibility-level-setting-in-forked-projects
* master: (723 commits) Bump Rack Attack to v4.3.1 for security fix Remove duplicate entry in the changelog Remove extra spaces after branchname Fix merge-request-reopen button title Add branch and tag operation to tree dropdown Use gitlab-shell 2.6.9 Clarify Windows shell executor artifact upload support Fix feature specs: we always show the build status if ci_commit is present Do not display project group/name when issue and MR are in same project Don't create CI status for refs that doesn't have .gitlab-ci.yml, even if the builds are enabled Use gitlab-workhorse 0.5.1 Fix ci_projects migration by using the value only from latest row [ci skip] Revert sidebar position for issue and merge request Add info on using private Docker registries in CI [ci skip] Upgrade Poltergeist to 1.8.1. #4131 Fix ux issue with "This issue will be closed automatically" message Move MR Builds tab next to Commits Api support for requesting starred projects for user Fix Rubocop complain. Fix merge widget JS for buttons ... Conflicts: app/models/project.rb
Diffstat (limited to 'app/models/commit_range.rb')
-rw-r--r--app/models/commit_range.rb110
1 files changed, 73 insertions, 37 deletions
diff --git a/app/models/commit_range.rb b/app/models/commit_range.rb
index 86fc9eb01a3..14e7971fa06 100644
--- a/app/models/commit_range.rb
+++ b/app/models/commit_range.rb
@@ -2,36 +2,38 @@
#
# Examples:
#
-# range = CommitRange.new('f3f85602...e86e1013')
+# range = CommitRange.new('f3f85602...e86e1013', project)
# range.exclude_start? # => false
# range.reference_title # => "Commits f3f85602 through e86e1013"
# range.to_s # => "f3f85602...e86e1013"
#
-# range = CommitRange.new('f3f856029bc5f966c5a7ee24cf7efefdd20e6019..e86e1013709735be5bb767e2b228930c543f25ae')
+# range = CommitRange.new('f3f856029bc5f966c5a7ee24cf7efefdd20e6019..e86e1013709735be5bb767e2b228930c543f25ae', project)
# range.exclude_start? # => true
# range.reference_title # => "Commits f3f85602^ through e86e1013"
# range.to_param # => {from: "f3f856029bc5f966c5a7ee24cf7efefdd20e6019^", to: "e86e1013709735be5bb767e2b228930c543f25ae"}
# range.to_s # => "f3f85602..e86e1013"
#
-# # Assuming `project` is a Project with a repository containing both commits:
-# range.project = project
+# # Assuming the specified project has a repository containing both commits:
# range.valid_commits? # => true
#
class CommitRange
include ActiveModel::Conversion
include Referable
- attr_reader :sha_from, :notation, :sha_to
+ attr_reader :commit_from, :notation, :commit_to
+ attr_reader :ref_from, :ref_to
# Optional Project model
attr_accessor :project
- # See `exclude_start?`
- attr_reader :exclude_start
-
- # The beginning and ending SHAs can be between 6 and 40 hex characters, and
+ # The beginning and ending refs can be named or SHAs, and
# 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
'@'
@@ -43,27 +45,40 @@ class CommitRange
def self.reference_pattern
%r{
(?:#{Project.reference_pattern}#{reference_prefix})?
- (?<commit_range>#{PATTERN})
+ (?<commit_range>#{STRICT_PATTERN})
}x
end
+ def self.link_reference_pattern
+ super("compare", /(?<commit_range>#{PATTERN})/)
+ end
+
# Initialize a CommitRange
#
# range_string - The String commit range.
# project - An optional Project model.
#
# Raises ArgumentError if `range_string` does not match `PATTERN`.
- def initialize(range_string, project = nil)
+ def initialize(range_string, project)
+ @project = project
+
range_string.strip!
- unless range_string.match(/\A#{PATTERN}\z/)
+ unless range_string =~ /\A#{PATTERN}\z/
raise ArgumentError, "invalid CommitRange string format: #{range_string}"
end
- @exclude_start = !range_string.include?('...')
- @sha_from, @notation, @sha_to = range_string.split(/(\.{2,3})/, 2)
+ @ref_from, @notation, @ref_to = range_string.split(/(\.{2,3})/, 2)
- @project = project
+ if project.valid_repo?
+ @commit_from = project.commit(@ref_from)
+ @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
def inspect
@@ -71,15 +86,24 @@ class CommitRange
end
def to_s
- "#{sha_from[0..7]}#{notation}#{sha_to[0..7]}"
+ sha_from + notation + sha_to
end
+ alias_method :id, :to_s
+
def to_reference(from_project = nil)
- # Not using to_s because we want the full SHAs
- reference = sha_from + notation + sha_to
+ if cross_project_reference?(from_project)
+ project.to_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
if cross_project_reference?(from_project)
- reference = project.to_reference + '@' + reference
+ reference = project.to_reference + self.class.reference_prefix + reference
end
reference
@@ -87,46 +111,58 @@ class CommitRange
# Returns a String for use in a link's title attribute
def reference_title
- "Commits #{suffixed_sha_from} through #{sha_to}"
+ "Commits #{sha_start} through #{sha_to}"
end
# Return a Hash of parameters for passing to a URL helper
#
# See `namespace_project_compare_url`
def to_param
- { from: suffixed_sha_from, to: sha_to }
+ { from: sha_start, to: sha_to }
end
def exclude_start?
- exclude_start
+ @notation == '..'
end
# Check if both the starting and ending commit IDs exist in a project's
# repository
- #
- # project - An optional Project to check (default: `project`)
- def valid_commits?(project = project)
- return nil unless project.present?
- return false unless project.valid_repo?
-
- commit_from.present? && commit_to.present?
+ def valid_commits?
+ commit_start.present? && commit_end.present?
end
def persisted?
true
end
- def commit_from
- @commit_from ||= project.repository.commit(suffixed_sha_from)
+ def sha_from
+ return nil unless @commit_from
+
+ @commit_from.id
+ end
+
+ def sha_to
+ return nil unless @commit_to
+
+ @commit_to.id
end
- def commit_to
- @commit_to ||= project.repository.commit(sha_to)
+ def sha_start
+ return nil unless sha_from
+
+ exclude_start? ? sha_from + '^' : sha_from
end
- private
+ def commit_start
+ return nil unless sha_start
- def suffixed_sha_from
- sha_from + (exclude_start? ? '^' : '')
+ if exclude_start?
+ @commit_start ||= project.commit(sha_start)
+ else
+ commit_from
+ end
end
+
+ alias_method :sha_end, :sha_to
+ alias_method :commit_end, :commit_to
end