Commit 37f0b600bc9a994136791e6838b3228c56f909b2
1 parent
94af622c
Exists in
master
and in
4 other branches
Another RefExtractor refactor
Showing
2 changed files
with
83 additions
and
58 deletions
Show diff stats
lib/ref_extractor.rb
| 1 | # Module providing an extract_ref method for controllers working with Git | 1 | # Module providing an extract_ref method for controllers working with Git |
| 2 | # tree-ish + path params | 2 | # tree-ish + path params |
| 3 | -# | ||
| 4 | -# Given a string containing both a Git ref - such as a branch or tag - and a | ||
| 5 | -# filesystem path joined by forward slashes, attempts to separate the two. | ||
| 6 | -# | ||
| 7 | -# Expects a @project instance variable to contain the active project. Used to | ||
| 8 | -# check the input against a list of valid repository refs. | ||
| 9 | -# | ||
| 10 | -# Examples | ||
| 11 | -# | ||
| 12 | -# # No @project available | ||
| 13 | -# extract_ref('master') | ||
| 14 | -# # => ['', ''] | ||
| 15 | -# | ||
| 16 | -# extract_ref('master') | ||
| 17 | -# # => ['master', '/'] | ||
| 18 | -# | ||
| 19 | -# extract_ref("f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG") | ||
| 20 | -# # => ['f4b14494ef6abf3d144c28e4af0c20143383e062', '/CHANGELOG'] | ||
| 21 | -# | ||
| 22 | -# extract_ref("v2.0.0/README.md") | ||
| 23 | -# # => ['v2.0.0', '/README.md'] | ||
| 24 | -# | ||
| 25 | -# extract_ref('issues/1234/app/models/project.rb') | ||
| 26 | -# # => ['issues/1234', '/app/models/project.rb'] | ||
| 27 | -# | ||
| 28 | -# # Given an invalid branch, we fall back to just splitting on the first slash | ||
| 29 | -# extract_ref('non/existent/branch/README.md') | ||
| 30 | -# # => ['non', '/existent/branch/README.md'] | ||
| 31 | -# | ||
| 32 | -# Returns an Array where the first value is the tree-ish and the second is the | ||
| 33 | -# path | ||
| 34 | module RefExtractor | 3 | module RefExtractor |
| 4 | + # Thrown when given an invalid path | ||
| 5 | + class InvalidPathError < StandardError; end | ||
| 6 | + | ||
| 7 | + # Given a string containing both a Git ref - such as a branch or tag - and a | ||
| 8 | + # filesystem path joined by forward slashes, attempts to separate the two. | ||
| 9 | + # | ||
| 10 | + # Expects a @project instance variable to contain the active project. Used to | ||
| 11 | + # check the input against a list of valid repository refs. | ||
| 12 | + # | ||
| 13 | + # Examples | ||
| 14 | + # | ||
| 15 | + # # No @project available | ||
| 16 | + # extract_ref('master') | ||
| 17 | + # # => ['', ''] | ||
| 18 | + # | ||
| 19 | + # extract_ref('master') | ||
| 20 | + # # => ['master', ''] | ||
| 21 | + # | ||
| 22 | + # extract_ref("f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG") | ||
| 23 | + # # => ['f4b14494ef6abf3d144c28e4af0c20143383e062', 'CHANGELOG'] | ||
| 24 | + # | ||
| 25 | + # extract_ref("v2.0.0/README.md") | ||
| 26 | + # # => ['v2.0.0', 'README.md'] | ||
| 27 | + # | ||
| 28 | + # extract_ref('issues/1234/app/models/project.rb') | ||
| 29 | + # # => ['issues/1234', 'app/models/project.rb'] | ||
| 30 | + # | ||
| 31 | + # # Given an invalid branch, we fall back to just splitting on the first slash | ||
| 32 | + # extract_ref('non/existent/branch/README.md') | ||
| 33 | + # # => ['non', 'existent/branch/README.md'] | ||
| 34 | + # | ||
| 35 | + # Returns an Array where the first value is the tree-ish and the second is the | ||
| 36 | + # path | ||
| 35 | def extract_ref(input) | 37 | def extract_ref(input) |
| 36 | pair = ['', ''] | 38 | pair = ['', ''] |
| 37 | 39 | ||
| @@ -41,24 +43,28 @@ module RefExtractor | @@ -41,24 +43,28 @@ module RefExtractor | ||
| 41 | # If the ref appears to be a SHA, we're done, just split the string | 43 | # If the ref appears to be a SHA, we're done, just split the string |
| 42 | pair = $~.captures | 44 | pair = $~.captures |
| 43 | else | 45 | else |
| 46 | + # Otherwise, attempt to detect the ref using a list of the project's | ||
| 47 | + # branches and tags | ||
| 48 | + | ||
| 44 | # Append a trailing slash if we only get a ref and no file path | 49 | # Append a trailing slash if we only get a ref and no file path |
| 45 | id = input | 50 | id = input |
| 46 | id += '/' unless id.include?('/') | 51 | id += '/' unless id.include?('/') |
| 47 | 52 | ||
| 48 | - # Otherwise, attempt to detect the ref using a list of the project's | ||
| 49 | - # branches and tags | ||
| 50 | valid_refs = @project.branches + @project.tags | 53 | valid_refs = @project.branches + @project.tags |
| 51 | valid_refs.select! { |v| id.start_with?("#{v}/") } | 54 | valid_refs.select! { |v| id.start_with?("#{v}/") } |
| 52 | 55 | ||
| 53 | if valid_refs.length != 1 | 56 | if valid_refs.length != 1 |
| 54 | # No exact ref match, so just try our best | 57 | # No exact ref match, so just try our best |
| 55 | - pair = id.match(/([^\/]+)(.+)/).captures | 58 | + pair = id.match(/([^\/]+)(.*)/).captures |
| 56 | else | 59 | else |
| 57 | # Partition the string into the ref and the path, ignoring the empty first value | 60 | # Partition the string into the ref and the path, ignoring the empty first value |
| 58 | pair = id.partition(valid_refs.first)[1..-1] | 61 | pair = id.partition(valid_refs.first)[1..-1] |
| 59 | end | 62 | end |
| 60 | end | 63 | end |
| 61 | 64 | ||
| 65 | + # Remove leading slash from path | ||
| 66 | + pair[1].gsub!(/^\//, '') | ||
| 67 | + | ||
| 62 | pair | 68 | pair |
| 63 | end | 69 | end |
| 64 | end | 70 | end |
spec/lib/ref_extractor_spec.rb
| @@ -11,29 +11,48 @@ describe RefExtractor do | @@ -11,29 +11,48 @@ describe RefExtractor do | ||
| 11 | project.stub(:tags).and_return(['v1.0.0', 'v2.0.0']) | 11 | project.stub(:tags).and_return(['v1.0.0', 'v2.0.0']) |
| 12 | end | 12 | end |
| 13 | 13 | ||
| 14 | - it "extracts a ref without a path" do | ||
| 15 | - extract_ref('master').should == ['master', '/'] | ||
| 16 | - end | ||
| 17 | - | ||
| 18 | - it "extracts a valid branch ref" do | ||
| 19 | - extract_ref('foo/bar/baz/CHANGELOG').should == ['foo/bar/baz', '/CHANGELOG'] | ||
| 20 | - end | ||
| 21 | - | ||
| 22 | - it "extracts a valid tag ref" do | ||
| 23 | - extract_ref('v2.0.0/CHANGELOG').should == ['v2.0.0', '/CHANGELOG'] | ||
| 24 | - end | ||
| 25 | - | ||
| 26 | - it "extracts a valid commit ref" do | ||
| 27 | - extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG').should == | ||
| 28 | - ['f4b14494ef6abf3d144c28e4af0c20143383e062', '/CHANGELOG'] | ||
| 29 | - end | ||
| 30 | - | ||
| 31 | - it "falls back to a primitive split for an invalid ref" do | ||
| 32 | - extract_ref('stable/CHANGELOG').should == ['stable', '/CHANGELOG'] | ||
| 33 | - end | ||
| 34 | - | ||
| 35 | - it "returns an empty pair when no @project is set" do | ||
| 36 | - @project = nil | ||
| 37 | - extract_ref('master/CHANGELOG').should == ['', ''] | 14 | + describe '#extract_ref' do |
| 15 | + it "returns an empty pair when no @project is set" do | ||
| 16 | + @project = nil | ||
| 17 | + extract_ref('master/CHANGELOG').should == ['', ''] | ||
| 18 | + end | ||
| 19 | + | ||
| 20 | + context "without a path" do | ||
| 21 | + it "extracts a valid branch" do | ||
| 22 | + extract_ref('master').should == ['master', ''] | ||
| 23 | + end | ||
| 24 | + | ||
| 25 | + it "extracts a valid tag" do | ||
| 26 | + extract_ref('v2.0.0').should == ['v2.0.0', ''] | ||
| 27 | + end | ||
| 28 | + | ||
| 29 | + it "extracts a valid commit ref without a path" do | ||
| 30 | + extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062').should == | ||
| 31 | + ['f4b14494ef6abf3d144c28e4af0c20143383e062', ''] | ||
| 32 | + end | ||
| 33 | + | ||
| 34 | + it "falls back to a primitive split for an invalid ref" do | ||
| 35 | + extract_ref('stable').should == ['stable', ''] | ||
| 36 | + end | ||
| 37 | + end | ||
| 38 | + | ||
| 39 | + context "with a path" do | ||
| 40 | + it "extracts a valid branch" do | ||
| 41 | + extract_ref('foo/bar/baz/CHANGELOG').should == ['foo/bar/baz', 'CHANGELOG'] | ||
| 42 | + end | ||
| 43 | + | ||
| 44 | + it "extracts a valid tag" do | ||
| 45 | + extract_ref('v2.0.0/CHANGELOG').should == ['v2.0.0', 'CHANGELOG'] | ||
| 46 | + end | ||
| 47 | + | ||
| 48 | + it "extracts a valid commit SHA" do | ||
| 49 | + extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG').should == | ||
| 50 | + ['f4b14494ef6abf3d144c28e4af0c20143383e062', 'CHANGELOG'] | ||
| 51 | + end | ||
| 52 | + | ||
| 53 | + it "falls back to a primitive split for an invalid ref" do | ||
| 54 | + extract_ref('stable/CHANGELOG').should == ['stable', 'CHANGELOG'] | ||
| 55 | + end | ||
| 56 | + end | ||
| 38 | end | 57 | end |
| 39 | end | 58 | end |