Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
gitlab-ce
Commits
a8e66564
Commit
a8e66564
authored
Apr 21, 2015
by
Robert Speicher
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add CommitRange class
parent
2c8bfedb
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
283 additions
and
0 deletions
+283
-0
app/models/commit_range.rb
app/models/commit_range.rb
+128
-0
spec/models/commit_range_spec.rb
spec/models/commit_range_spec.rb
+155
-0
No files found.
app/models/commit_range.rb
0 → 100644
View file @
a8e66564
# CommitRange makes it easier to work with commit ranges
#
# Examples:
#
# range = CommitRange.new('f3f85602...e86e1013')
# range.inclusive? # => false
# range.to_s # => "f3f85602...e86e1013"
# range.reference_title # => "Commits f3f85602 through e86e1013"
#
# range = CommitRange.new('f3f856029bc5f966c5a7ee24cf7efefdd20e6019..e86e1013709735be5bb767e2b228930c543f25ae')
# range.inclusive? # => true
# range.to_s # => "f3f85602..e86e1013"
# range.to_param # => {from: "f3f856029bc5f966c5a7ee24cf7efefdd20e6019^", to: "e86e1013709735be5bb767e2b228930c543f25ae"}
#
# # Assuming `project` is a Project with a repository containing both commits:
# range.project = project
# range.valid_commits? # => true
# range.to_a # => [#<Commit ...>, #<Commit ...>]
#
class
CommitRange
include
ActiveModel
::
Conversion
attr_reader
:sha_from
,
:notation
,
:sha_to
# Optional Project model
attr_accessor
:project
# See `inclusive?`
attr_reader
:inclusive
# The beginning and ending SHA sums can be between 6 and 40 hex characters,
# and the range selection can be double- or triple-dot.
PATTERN
=
/\h{6,40}\.{2,3}\h{6,40}/
# 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
)
range_string
.
strip!
unless
range_string
.
match
(
/\A
#{
PATTERN
}
\z/
)
raise
ArgumentError
,
"invalid CommitRange string format:
#{
range_string
}
"
end
@inclusive
=
range_string
!~
/\.{3}/
@sha_from
,
@notation
,
@sha_to
=
range_string
.
split
(
/(\.{2,3})/
,
2
)
@project
=
project
@_commit_map
=
{}
end
def
inspect
%(#<#{self.class}:#{object_id} #{to_s}>)
end
# Returns an Array of Commit objects, where the first value is the starting
# commit, and the second value is the ending commit
#
# Returns `[nil, nil]` if `valid_commits?` is falsey
def
to_a
if
valid_commits?
[
commit
(
sha_from
),
commit
(
sha_to
)]
else
[
nil
,
nil
]
end
end
def
to_s
(
short:
true
)
if
short
"
#{
sha_from
[
0
..
7
]
}#{
notation
}#{
sha_to
[
0
..
7
]
}
"
else
"
#{
sha_from
}#{
notation
}#{
sha_to
}
"
end
end
# Returns a String for use in a link's title attribute
def
reference_title
"Commits
#{
sha_from
}
through
#{
sha_to
}
"
end
# Return a Hash of parameters for passing to a URL helper
#
# See `namespace_project_compare_url`
def
to_param
{
from:
sha_from_as_param
,
to:
sha_to
}
end
# Check if the range is inclusive
#
# We consider a CommitRange "inclusive" when it uses the two-dot syntax.
def
inclusive?
inclusive
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
(
sha_from
).
present?
&&
commit
(
sha_to
).
present?
end
def
persisted?
true
end
private
def
sha_from_as_param
sha_from
+
(
inclusive?
?
'^'
:
''
)
end
def
commit
(
sha
)
unless
@_commit_map
[
sha
]
# FIXME (rspeicher): Law of Demeter
@_commit_map
[
sha
]
=
project
.
repository
.
commit
(
sha
)
end
@_commit_map
[
sha
]
end
end
spec/models/commit_range_spec.rb
0 → 100644
View file @
a8e66564
require
'spec_helper'
describe
CommitRange
do
let
(
:sha_from
)
{
'f3f85602'
}
let
(
:sha_to
)
{
'e86e1013'
}
let
(
:range
)
{
described_class
.
new
(
"
#{
sha_from
}
...
#{
sha_to
}
"
)
}
let
(
:range2
)
{
described_class
.
new
(
"
#{
sha_from
}
..
#{
sha_to
}
"
)
}
it
'raises ArgumentError when given an invalid range string'
do
expect
{
described_class
.
new
(
"Foo"
)
}.
to
raise_error
end
describe
'#to_a'
do
context
'when valid'
do
let
(
:commit1
)
{
double
(
'commit1'
)
}
let
(
:commit2
)
{
double
(
'commit2'
)
}
before
do
expect
(
range
).
to
receive
(
:valid_commits?
).
and_return
(
true
)
allow
(
range
).
to
receive
(
:commit
).
with
(
sha_from
).
and_return
(
commit1
)
allow
(
range
).
to
receive
(
:commit
).
with
(
sha_to
).
and_return
(
commit2
)
end
it
'returns an Array of Commits'
do
expect
(
range
.
to_a
).
to
eq
[
commit1
,
commit2
]
end
end
context
'when invalid'
do
before
do
expect
(
range
).
to
receive
(
:valid_commits?
).
and_return
(
false
)
end
it
'returns [nil, nil]'
do
expect
(
range
.
to_a
).
to
eq
[
nil
,
nil
]
end
end
end
describe
'#to_s'
do
context
'with short IDs'
do
it
'is correct for three-dot syntax'
do
expect
(
range
.
to_s
).
to
eq
"
#{
sha_from
[
0
..
7
]
}
...
#{
sha_to
[
0
..
7
]
}
"
end
it
'is correct for two-dot syntax'
do
expect
(
range2
.
to_s
).
to
eq
"
#{
sha_from
[
0
..
7
]
}
..
#{
sha_to
[
0
..
7
]
}
"
end
end
context
'with full IDs'
do
it
'is correct for three-dot syntax'
do
expect
(
range
.
to_s
(
short:
false
)).
to
eq
"
#{
sha_from
}
...
#{
sha_to
}
"
end
it
'is correct for two-dot syntax'
do
expect
(
range2
.
to_s
(
short:
false
)).
to
eq
"
#{
sha_from
}
..
#{
sha_to
}
"
end
end
end
describe
'#reference_title'
do
it
'returns the correct String'
do
expect
(
range
.
reference_title
).
to
eq
"Commits
#{
sha_from
}
through
#{
sha_to
}
"
end
end
describe
'#to_param'
do
it
'includes the correct keys'
do
expect
(
range
.
to_param
.
keys
).
to
eq
%i(from to)
end
it
'includes the correct values for a three-dot range'
do
expect
(
range
.
to_param
).
to
eq
({
from:
sha_from
,
to:
sha_to
})
end
it
'includes the correct values for a two-dot range'
do
expect
(
range2
.
to_param
).
to
eq
({
from:
sha_from
+
'^'
,
to:
sha_to
})
end
end
describe
'#inclusive?'
do
it
'is false for three-dot ranges'
do
expect
(
range
).
not_to
be_inclusive
end
it
'is true for two-dot ranges'
do
expect
(
range2
).
to
be_inclusive
end
end
describe
'#valid_commits?'
do
context
'without a project'
do
it
'returns nil'
do
expect
(
range
.
valid_commits?
).
to
be_nil
end
end
it
'accepts an optional project argument'
do
project1
=
double
(
'project1'
).
as_null_object
project2
=
double
(
'project2'
).
as_null_object
# project1 gets assigned through the accessor, but ignored when not given
# as an argument to `valid_commits?`
expect
(
project1
).
not_to
receive
(
:present?
)
range
.
project
=
project1
# project2 gets passed to `valid_commits?`
expect
(
project2
).
to
receive
(
:present?
).
and_return
(
false
)
range
.
valid_commits?
(
project2
)
end
context
'with a project'
do
let
(
:project
)
{
double
(
'project'
,
repository:
double
(
'repository'
))
}
context
'with a valid repo'
do
before
do
expect
(
project
).
to
receive
(
:valid_repo?
).
and_return
(
true
)
range
.
project
=
project
end
it
'is false when `sha_from` is invalid'
do
expect
(
project
.
repository
).
to
receive
(
:commit
).
with
(
sha_from
).
and_return
(
false
)
expect
(
project
.
repository
).
not_to
receive
(
:commit
).
with
(
sha_to
)
expect
(
range
).
not_to
be_valid_commits
end
it
'is false when `sha_to` is invalid'
do
expect
(
project
.
repository
).
to
receive
(
:commit
).
with
(
sha_from
).
and_return
(
true
)
expect
(
project
.
repository
).
to
receive
(
:commit
).
with
(
sha_to
).
and_return
(
false
)
expect
(
range
).
not_to
be_valid_commits
end
it
'is true when both `sha_from` and `sha_to` are valid'
do
expect
(
project
.
repository
).
to
receive
(
:commit
).
with
(
sha_from
).
and_return
(
true
)
expect
(
project
.
repository
).
to
receive
(
:commit
).
with
(
sha_to
).
and_return
(
true
)
expect
(
range
).
to
be_valid_commits
end
end
context
'without a valid repo'
do
before
do
expect
(
project
).
to
receive
(
:valid_repo?
).
and_return
(
false
)
range
.
project
=
project
end
it
'returns false'
do
expect
(
range
).
not_to
be_valid_commits
end
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment