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 |