summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/tree_controller.rb49
-rw-r--r--app/models/tree.rb10
-rw-r--r--spec/controllers/tree_controller_spec.rb43
-rw-r--r--spec/spec_helper.rb1
4 files changed, 100 insertions, 3 deletions
diff --git a/app/controllers/tree_controller.rb b/app/controllers/tree_controller.rb
new file mode 100644
index 00000000000..15bbb1a3c77
--- /dev/null
+++ b/app/controllers/tree_controller.rb
@@ -0,0 +1,49 @@
+# Controller for viewing a repository's file structure
+class TreeController < ApplicationController
+ # Thrown when given an invalid path
+ class InvalidPathError < StandardError; end
+
+ include RefExtractor
+
+ layout "project"
+
+ before_filter :project
+
+ # Authorize
+ before_filter :add_project_abilities
+ before_filter :authorize_read_project!
+ before_filter :authorize_code_access!
+ before_filter :require_non_empty_project
+
+ before_filter :define_tree_vars
+
+ def show
+ respond_to do |format|
+ format.html
+ # Disable cache so browser history works
+ format.js { no_cache_headers }
+ end
+ end
+
+ private
+
+ def define_tree_vars
+ @ref, @path = extract_ref(params[:id])
+
+ @id = File.join(@ref, @path)
+ @repo = @project.repo
+ @commit = CommitDecorator.decorate(@project.commit(@ref))
+
+ @tree = Tree.new(@commit.tree, @project, @ref, @path.gsub(/^\//, ''))
+ @tree = TreeDecorator.new(@tree)
+
+ raise InvalidPathError if @tree.invalid?
+
+ @hex_path = Digest::SHA1.hexdigest(@path)
+
+ @history_path = project_tree_path(@project, @id)
+ @logs_path = logs_file_project_ref_path(@project, @ref, @path)
+ rescue NoMethodError, InvalidPathError
+ not_found!
+ end
+end
diff --git a/app/models/tree.rb b/app/models/tree.rb
index d65e50ab817..88e8f2f4663 100644
--- a/app/models/tree.rb
+++ b/app/models/tree.rb
@@ -1,5 +1,5 @@
class Tree
- include Linguist::BlobHelper
+ include Linguist::BlobHelper
attr_accessor :path, :tree, :project, :ref
delegate :contents,
@@ -14,8 +14,8 @@ class Tree
to: :tree
def initialize(raw_tree, project, ref = nil, path = nil)
- @project, @ref, @path = project, ref, path,
- @tree = if path
+ @project, @ref, @path = project, ref, path
+ @tree = if path.present?
raw_tree / path.dup.force_encoding('ascii-8bit')
else
raw_tree
@@ -26,6 +26,10 @@ class Tree
tree.is_a?(Grit::Blob)
end
+ def invalid?
+ tree.nil?
+ end
+
def empty?
data.blank?
end
diff --git a/spec/controllers/tree_controller_spec.rb b/spec/controllers/tree_controller_spec.rb
new file mode 100644
index 00000000000..b9295537d01
--- /dev/null
+++ b/spec/controllers/tree_controller_spec.rb
@@ -0,0 +1,43 @@
+require 'spec_helper'
+
+describe TreeController do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+
+ project.add_access(user, :read, :admin)
+
+ project.stub(:branches).and_return(['master', 'foo/bar/baz'])
+ project.stub(:tags).and_return(['v1.0.0', 'v2.0.0'])
+ controller.instance_variable_set(:@project, project)
+ end
+
+ describe "GET show" do
+ # Make sure any errors accessing the tree in our views bubble up to this spec
+ render_views
+
+ before { get :show, project_id: project.code, id: id }
+
+ context "valid branch, no path" do
+ let(:id) { 'master' }
+ it { should respond_with(:success) }
+ end
+
+ context "valid branch, valid path" do
+ let(:id) { 'master/README.md' }
+ it { should respond_with(:success) }
+ end
+
+ context "valid branch, invalid path" do
+ let(:id) { 'master/invalid-path.rb' }
+ it { should respond_with(:not_found) }
+ end
+
+ context "invalid branch, valid path" do
+ let(:id) { 'invalid-branch/README.md' }
+ it { should respond_with(:not_found) }
+ end
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index d381b3f1e2e..4700c3fe9af 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -28,6 +28,7 @@ RSpec.configure do |config|
config.include LoginHelpers, type: :request
config.include GitoliteStub
config.include FactoryGirl::Syntax::Methods
+ config.include Devise::TestHelpers, type: :controller
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false