Commit e33cbb9b4252e2617bcb4c3f850c47aae43e4d83
1 parent
884eb732
Exists in
master
and in
4 other branches
Add TreeController and spec
Showing
4 changed files
with
100 additions
and
3 deletions
Show diff stats
| ... | ... | @@ -0,0 +1,49 @@ |
| 1 | +# Controller for viewing a repository's file structure | |
| 2 | +class TreeController < ApplicationController | |
| 3 | + # Thrown when given an invalid path | |
| 4 | + class InvalidPathError < StandardError; end | |
| 5 | + | |
| 6 | + include RefExtractor | |
| 7 | + | |
| 8 | + layout "project" | |
| 9 | + | |
| 10 | + before_filter :project | |
| 11 | + | |
| 12 | + # Authorize | |
| 13 | + before_filter :add_project_abilities | |
| 14 | + before_filter :authorize_read_project! | |
| 15 | + before_filter :authorize_code_access! | |
| 16 | + before_filter :require_non_empty_project | |
| 17 | + | |
| 18 | + before_filter :define_tree_vars | |
| 19 | + | |
| 20 | + def show | |
| 21 | + respond_to do |format| | |
| 22 | + format.html | |
| 23 | + # Disable cache so browser history works | |
| 24 | + format.js { no_cache_headers } | |
| 25 | + end | |
| 26 | + end | |
| 27 | + | |
| 28 | + private | |
| 29 | + | |
| 30 | + def define_tree_vars | |
| 31 | + @ref, @path = extract_ref(params[:id]) | |
| 32 | + | |
| 33 | + @id = File.join(@ref, @path) | |
| 34 | + @repo = @project.repo | |
| 35 | + @commit = CommitDecorator.decorate(@project.commit(@ref)) | |
| 36 | + | |
| 37 | + @tree = Tree.new(@commit.tree, @project, @ref, @path.gsub(/^\//, '')) | |
| 38 | + @tree = TreeDecorator.new(@tree) | |
| 39 | + | |
| 40 | + raise InvalidPathError if @tree.invalid? | |
| 41 | + | |
| 42 | + @hex_path = Digest::SHA1.hexdigest(@path) | |
| 43 | + | |
| 44 | + @history_path = project_tree_path(@project, @id) | |
| 45 | + @logs_path = logs_file_project_ref_path(@project, @ref, @path) | |
| 46 | + rescue NoMethodError, InvalidPathError | |
| 47 | + not_found! | |
| 48 | + end | |
| 49 | +end | ... | ... |
app/models/tree.rb
| 1 | 1 | class Tree |
| 2 | - include Linguist::BlobHelper | |
| 2 | + include Linguist::BlobHelper | |
| 3 | 3 | attr_accessor :path, :tree, :project, :ref |
| 4 | 4 | |
| 5 | 5 | delegate :contents, |
| ... | ... | @@ -14,8 +14,8 @@ class Tree |
| 14 | 14 | to: :tree |
| 15 | 15 | |
| 16 | 16 | def initialize(raw_tree, project, ref = nil, path = nil) |
| 17 | - @project, @ref, @path = project, ref, path, | |
| 18 | - @tree = if path | |
| 17 | + @project, @ref, @path = project, ref, path | |
| 18 | + @tree = if path.present? | |
| 19 | 19 | raw_tree / path.dup.force_encoding('ascii-8bit') |
| 20 | 20 | else |
| 21 | 21 | raw_tree |
| ... | ... | @@ -26,6 +26,10 @@ class Tree |
| 26 | 26 | tree.is_a?(Grit::Blob) |
| 27 | 27 | end |
| 28 | 28 | |
| 29 | + def invalid? | |
| 30 | + tree.nil? | |
| 31 | + end | |
| 32 | + | |
| 29 | 33 | def empty? |
| 30 | 34 | data.blank? |
| 31 | 35 | end | ... | ... |
| ... | ... | @@ -0,0 +1,43 @@ |
| 1 | +require 'spec_helper' | |
| 2 | + | |
| 3 | +describe TreeController do | |
| 4 | + let(:project) { create(:project) } | |
| 5 | + let(:user) { create(:user) } | |
| 6 | + | |
| 7 | + before do | |
| 8 | + sign_in(user) | |
| 9 | + | |
| 10 | + project.add_access(user, :read, :admin) | |
| 11 | + | |
| 12 | + project.stub(:branches).and_return(['master', 'foo/bar/baz']) | |
| 13 | + project.stub(:tags).and_return(['v1.0.0', 'v2.0.0']) | |
| 14 | + controller.instance_variable_set(:@project, project) | |
| 15 | + end | |
| 16 | + | |
| 17 | + describe "GET show" do | |
| 18 | + # Make sure any errors accessing the tree in our views bubble up to this spec | |
| 19 | + render_views | |
| 20 | + | |
| 21 | + before { get :show, project_id: project.code, id: id } | |
| 22 | + | |
| 23 | + context "valid branch, no path" do | |
| 24 | + let(:id) { 'master' } | |
| 25 | + it { should respond_with(:success) } | |
| 26 | + end | |
| 27 | + | |
| 28 | + context "valid branch, valid path" do | |
| 29 | + let(:id) { 'master/README.md' } | |
| 30 | + it { should respond_with(:success) } | |
| 31 | + end | |
| 32 | + | |
| 33 | + context "valid branch, invalid path" do | |
| 34 | + let(:id) { 'master/invalid-path.rb' } | |
| 35 | + it { should respond_with(:not_found) } | |
| 36 | + end | |
| 37 | + | |
| 38 | + context "invalid branch, valid path" do | |
| 39 | + let(:id) { 'invalid-branch/README.md' } | |
| 40 | + it { should respond_with(:not_found) } | |
| 41 | + end | |
| 42 | + end | |
| 43 | +end | ... | ... |
spec/spec_helper.rb
| ... | ... | @@ -28,6 +28,7 @@ RSpec.configure do |config| |
| 28 | 28 | config.include LoginHelpers, type: :request |
| 29 | 29 | config.include GitoliteStub |
| 30 | 30 | config.include FactoryGirl::Syntax::Methods |
| 31 | + config.include Devise::TestHelpers, type: :controller | |
| 31 | 32 | |
| 32 | 33 | # If you're not using ActiveRecord, or you'd prefer not to run each of your |
| 33 | 34 | # examples within a transaction, remove the following line or assign false | ... | ... |