Commit 37f0b600bc9a994136791e6838b3228c56f909b2

Authored by Robert Speicher
1 parent 94af622c

Another RefExtractor refactor

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
... ...