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 | 1 | # Module providing an extract_ref method for controllers working with Git |
| 2 | 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 | 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 | 37 | def extract_ref(input) |
| 36 | 38 | pair = ['', ''] |
| 37 | 39 | |
| ... | ... | @@ -41,24 +43,28 @@ module RefExtractor |
| 41 | 43 | # If the ref appears to be a SHA, we're done, just split the string |
| 42 | 44 | pair = $~.captures |
| 43 | 45 | else |
| 46 | + # Otherwise, attempt to detect the ref using a list of the project's | |
| 47 | + # branches and tags | |
| 48 | + | |
| 44 | 49 | # Append a trailing slash if we only get a ref and no file path |
| 45 | 50 | id = input |
| 46 | 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 | 53 | valid_refs = @project.branches + @project.tags |
| 51 | 54 | valid_refs.select! { |v| id.start_with?("#{v}/") } |
| 52 | 55 | |
| 53 | 56 | if valid_refs.length != 1 |
| 54 | 57 | # No exact ref match, so just try our best |
| 55 | - pair = id.match(/([^\/]+)(.+)/).captures | |
| 58 | + pair = id.match(/([^\/]+)(.*)/).captures | |
| 56 | 59 | else |
| 57 | 60 | # Partition the string into the ref and the path, ignoring the empty first value |
| 58 | 61 | pair = id.partition(valid_refs.first)[1..-1] |
| 59 | 62 | end |
| 60 | 63 | end |
| 61 | 64 | |
| 65 | + # Remove leading slash from path | |
| 66 | + pair[1].gsub!(/^\//, '') | |
| 67 | + | |
| 62 | 68 | pair |
| 63 | 69 | end |
| 64 | 70 | end | ... | ... |
spec/lib/ref_extractor_spec.rb
| ... | ... | @@ -11,29 +11,48 @@ describe RefExtractor do |
| 11 | 11 | project.stub(:tags).and_return(['v1.0.0', 'v2.0.0']) |
| 12 | 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 | 57 | end |
| 39 | 58 | end | ... | ... |