Commit a1e68a91205186287f21fb5fd1669acebcd7e79e

Authored by Robert Speicher
1 parent a8ea8d98

Rename RefExtractor to ExtractsPath

Update docs a bit
app/controllers/blame_controller.rb
1 1 # Controller for viewing a file's blame
2 2 class BlameController < ApplicationController
3   -
4   - include RefExtractor
  3 + include ExtractsPath
5 4  
6 5 layout "project"
7 6  
... ...
app/controllers/blob_controller.rb
1 1 # Controller for viewing a file's blame
2 2 class BlobController < ApplicationController
3   - # Thrown when given an invalid path
4   - class InvalidPathError < StandardError; end
5   -
6   - include RefExtractor
  3 + include ExtractsPath
7 4 include Gitlab::Encode
8 5  
9 6 layout "project"
... ...
app/controllers/tree_controller.rb
1 1 # Controller for viewing a repository's file structure
2 2 class TreeController < ApplicationController
3   - include RefExtractor
  3 + include ExtractsPath
4 4  
5 5 layout "project"
6 6  
... ...
lib/extracts_path.rb 0 → 100644
... ... @@ -0,0 +1,114 @@
  1 +# Module providing methods for dealing with separating a tree-ish string and a
  2 +# file path string when combined in a request parameter
  3 +module ExtractsPath
  4 + extend ActiveSupport::Concern
  5 +
  6 + # Raised when given an invalid file path
  7 + class InvalidPathError < StandardError; end
  8 +
  9 + included do
  10 + if respond_to?(:before_filter)
  11 + before_filter :assign_ref_vars
  12 + end
  13 + end
  14 +
  15 + # Given a string containing both a Git tree-ish, such as a branch or tag, and
  16 + # a filesystem path joined by forward slashes, attempts to separate the two.
  17 + #
  18 + # Expects a @project instance variable to contain the active project. This is
  19 + # used to check the input against a list of valid repository refs.
  20 + #
  21 + # Examples
  22 + #
  23 + # # No @project available
  24 + # extract_ref('master')
  25 + # # => ['', '']
  26 + #
  27 + # extract_ref('master')
  28 + # # => ['master', '']
  29 + #
  30 + # extract_ref("f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG")
  31 + # # => ['f4b14494ef6abf3d144c28e4af0c20143383e062', 'CHANGELOG']
  32 + #
  33 + # extract_ref("v2.0.0/README.md")
  34 + # # => ['v2.0.0', 'README.md']
  35 + #
  36 + # extract_ref('issues/1234/app/models/project.rb')
  37 + # # => ['issues/1234', 'app/models/project.rb']
  38 + #
  39 + # # Given an invalid branch, we fall back to just splitting on the first slash
  40 + # extract_ref('non/existent/branch/README.md')
  41 + # # => ['non', 'existent/branch/README.md']
  42 + #
  43 + # Returns an Array where the first value is the tree-ish and the second is the
  44 + # path
  45 + def extract_ref(input)
  46 + pair = ['', '']
  47 +
  48 + return pair unless @project
  49 +
  50 + if input.match(/^([[:alnum:]]{40})(.+)/)
  51 + # If the ref appears to be a SHA, we're done, just split the string
  52 + pair = $~.captures
  53 + else
  54 + # Otherwise, attempt to detect the ref using a list of the project's
  55 + # branches and tags
  56 +
  57 + # Append a trailing slash if we only get a ref and no file path
  58 + id = input
  59 + id += '/' unless id.include?('/')
  60 +
  61 + valid_refs = @project.branches + @project.tags
  62 + valid_refs.select! { |v| id.start_with?("#{v}/") }
  63 +
  64 + if valid_refs.length != 1
  65 + # No exact ref match, so just try our best
  66 + pair = id.match(/([^\/]+)(.*)/).captures
  67 + else
  68 + # Partition the string into the ref and the path, ignoring the empty first value
  69 + pair = id.partition(valid_refs.first)[1..-1]
  70 + end
  71 + end
  72 +
  73 + # Remove leading slash from path
  74 + pair[1].gsub!(/^\//, '')
  75 +
  76 + pair
  77 + end
  78 +
  79 + # Assigns common instance variables for views working with Git tree-ish objects
  80 + #
  81 + # Assignments are:
  82 + #
  83 + # - @id - A string representing the joined ref and path
  84 + # - @ref - A string representing the ref (e.g., the branch, tag, or commit SHA)
  85 + # - @path - A string representing the filesystem path
  86 + # - @commit - A CommitDecorator representing the commit from the given ref
  87 + # - @tree - A TreeDecorator representing the tree at the given ref/path
  88 + #
  89 + # If the :id parameter appears to be requesting a specific response format,
  90 + # that will be handled as well.
  91 + #
  92 + # Automatically renders `not_found!` if a valid tree path could not be
  93 + # resolved (e.g., when a user inserts an invalid path or ref).
  94 + def assign_ref_vars
  95 + # Handle formats embedded in the id
  96 + if params[:id].ends_with?('.atom')
  97 + params[:id].gsub!(/\.atom$/, '')
  98 + request.format = :atom
  99 + end
  100 +
  101 + @ref, @path = extract_ref(params[:id])
  102 +
  103 + @id = File.join(@ref, @path)
  104 +
  105 + @commit = CommitDecorator.decorate(@project.commit(@ref))
  106 +
  107 + @tree = Tree.new(@commit.tree, @project, @ref, @path)
  108 + @tree = TreeDecorator.new(@tree)
  109 +
  110 + raise InvalidPathError if @tree.invalid?
  111 + rescue NoMethodError, InvalidPathError
  112 + not_found!
  113 + end
  114 +end
... ...
lib/ref_extractor.rb
... ... @@ -1,103 +0,0 @@
1   -# Module providing an extract_ref method for controllers working with Git
2   -# tree-ish + path params
3   -module RefExtractor
4   - # Raised 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
37   - def extract_ref(input)
38   - pair = ['', '']
39   -
40   - return pair unless @project
41   -
42   - if input.match(/^([[:alnum:]]{40})(.+)/)
43   - # If the ref appears to be a SHA, we're done, just split the string
44   - pair = $~.captures
45   - else
46   - # Otherwise, attempt to detect the ref using a list of the project's
47   - # branches and tags
48   -
49   - # Append a trailing slash if we only get a ref and no file path
50   - id = input
51   - id += '/' unless id.include?('/')
52   -
53   - valid_refs = @project.branches + @project.tags
54   - valid_refs.select! { |v| id.start_with?("#{v}/") }
55   -
56   - if valid_refs.length != 1
57   - # No exact ref match, so just try our best
58   - pair = id.match(/([^\/]+)(.*)/).captures
59   - else
60   - # Partition the string into the ref and the path, ignoring the empty first value
61   - pair = id.partition(valid_refs.first)[1..-1]
62   - end
63   - end
64   -
65   - # Remove leading slash from path
66   - pair[1].gsub!(/^\//, '')
67   -
68   - pair
69   - end
70   -
71   - # Assigns common instance variables for views working with Git tree-ish objects
72   - #
73   - # Assignments are:
74   - #
75   - # - @id - A string representing the joined ref and path
76   - # - @ref - A string representing the ref (e.g., the branch, tag, or commit SHA)
77   - # - @path - A string representing the filesystem path
78   - # - @commit - A CommitDecorator representing the commit from the given ref
79   - # - @tree - A TreeDecorator representing the tree at the given ref/path
80   - #
81   - # Automatically renders `not_found!` if a valid tree could not be resolved
82   - # (e.g., when a user inserts an invalid path or ref).
83   - def assign_ref_vars
84   - # Handle formats embedded in the id
85   - if params[:id].ends_with?('.atom')
86   - params[:id].gsub!(/\.atom$/, '')
87   - request.format = :atom
88   - end
89   -
90   - @ref, @path = extract_ref(params[:id])
91   -
92   - @id = File.join(@ref, @path)
93   -
94   - @commit = CommitDecorator.decorate(@project.commit(@ref))
95   -
96   - @tree = Tree.new(@commit.tree, @project, @ref, @path)
97   - @tree = TreeDecorator.new(@tree)
98   -
99   - raise InvalidPathError if @tree.invalid?
100   - rescue NoMethodError, InvalidPathError
101   - not_found!
102   - end
103   -end
spec/lib/extracts_path_spec.rb 0 → 100644
... ... @@ -0,0 +1,58 @@
  1 +require 'spec_helper'
  2 +
  3 +describe ExtractsPath do
  4 + include ExtractsPath
  5 +
  6 + let(:project) { double('project') }
  7 +
  8 + before do
  9 + @project = project
  10 + project.stub(:branches).and_return(['master', 'foo/bar/baz'])
  11 + project.stub(:tags).and_return(['v1.0.0', 'v2.0.0'])
  12 + end
  13 +
  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
  57 + end
  58 +end
... ...
spec/lib/ref_extractor_spec.rb
1 1 require 'spec_helper'
2 2  
3   -describe RefExtractor do
4   - include RefExtractor
  3 +describe ExtractsPath do
  4 + include ExtractsPath
5 5  
6 6 let(:project) { double('project') }
7 7  
... ...