diff --git a/Gemfile b/Gemfile index 71eafabaa91..8e2bdb9cbb5 100644 --- a/Gemfile +++ b/Gemfile @@ -57,7 +57,7 @@ gem "seed-fu" # Markdown to HTML gem "redcarpet", "~> 2.1.1" -gem "github-markup", "~> 0.7.4" +gem "github-markup", "~> 0.7.4", require: 'github/markup' # Servers gem "thin" diff --git a/app/assets/stylesheets/gitlab_bootstrap/files.scss b/app/assets/stylesheets/gitlab_bootstrap/files.scss index d39fdb27cd4..cbc58d22203 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/files.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/files.scss @@ -68,10 +68,22 @@ * Blame file */ &.blame { + table { + border:none; + box-shadow:none; + margin:0; + } tr { border-bottom: 1px solid #eee; } td { + &:first-child { + border-left:none; + } + &:last-child { + border-right:none; + } + background:#fff; padding:5px; } .author, diff --git a/app/assets/stylesheets/sections/nav.scss b/app/assets/stylesheets/sections/nav.scss index 2d9029183a6..98bc7275640 100644 --- a/app/assets/stylesheets/sections/nav.scss +++ b/app/assets/stylesheets/sections/nav.scss @@ -53,7 +53,7 @@ ul.main_menu { border-left: 0; } - &.current { + &.active { background-color:#D5D5D5; border-right: 1px solid #BBB; border-left: 1px solid #BBB; diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index a299a83b96e..c4c99204e03 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -2,7 +2,6 @@ class ApplicationController < ActionController::Base before_filter :authenticate_user! before_filter :reject_blocked! before_filter :set_current_user_for_mailer - before_filter :check_token_auth before_filter :set_current_user_for_observers before_filter :dev_tools if Rails.env == 'development' @@ -24,13 +23,6 @@ class ApplicationController < ActionController::Base protected - def check_token_auth - # Redirect to login page if not atom feed - if params[:private_token].present? && params[:format] != 'atom' - redirect_to new_user_session_path - end - end - def reject_blocked! if current_user && current_user.blocked sign_out current_user @@ -103,7 +95,7 @@ class ApplicationController < ActionController::Base end def render_404 - render file: File.join(Rails.root, "public", "404"), layout: false, status: "404" + render file: Rails.root.join("public", "404"), layout: false, status: "404" end def require_non_empty_project @@ -116,10 +108,6 @@ class ApplicationController < ActionController::Base response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT" end - def render_full_content - @full_content = true - end - def dev_tools Rack::MiniProfiler.authorize_request end diff --git a/app/controllers/blame_controller.rb b/app/controllers/blame_controller.rb new file mode 100644 index 00000000000..dd0837ea9ab --- /dev/null +++ b/app/controllers/blame_controller.rb @@ -0,0 +1,21 @@ +# Controller for viewing a file's blame +class BlameController < ApplicationController + include ExtractsPath + + 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 :assign_ref_vars + + def show + @repo = @project.repo + @blame = Grit::Blob.blame(@repo, @commit.id, @path) + end +end diff --git a/app/controllers/blob_controller.rb b/app/controllers/blob_controller.rb new file mode 100644 index 00000000000..33387842ec2 --- /dev/null +++ b/app/controllers/blob_controller.rb @@ -0,0 +1,37 @@ +# Controller for viewing a file's blame +class BlobController < ApplicationController + include ExtractsPath + include Gitlab::Encode + + 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 :assign_ref_vars + + def show + if @tree.is_blob? + if @tree.text? + encoding = detect_encoding(@tree.data) + mime_type = encoding ? "text/plain; charset=#{encoding}" : "text/plain" + else + mime_type = @tree.mime_type + end + + send_data( + @tree.data, + type: mime_type, + disposition: 'inline', + filename: @tree.name + ) + else + not_found! + end + end +end diff --git a/app/controllers/commit_controller.rb b/app/controllers/commit_controller.rb new file mode 100644 index 00000000000..de0d5b2ee7d --- /dev/null +++ b/app/controllers/commit_controller.rb @@ -0,0 +1,36 @@ +# Controller for a specific Commit +# +# Not to be confused with CommitsController, plural. +class CommitController < ApplicationController + before_filter :project + layout "project" + + # Authorize + before_filter :add_project_abilities + before_filter :authorize_read_project! + before_filter :authorize_code_access! + before_filter :require_non_empty_project + + def show + result = CommitLoad.new(project, current_user, params).execute + + @commit = result[:commit] + git_not_found! unless @commit + + @suppress_diff = result[:suppress_diff] + @note = result[:note] + @line_notes = result[:line_notes] + @notes_count = result[:notes_count] + @comments_allowed = true + + respond_to do |format| + format.html do + if result[:status] == :huge_commit + render "huge_commit" and return + end + end + + format.patch + end + end +end diff --git a/app/controllers/commits_controller.rb b/app/controllers/commits_controller.rb index c79784d6b18..81a9e90d062 100644 --- a/app/controllers/commits_controller.rb +++ b/app/controllers/commits_controller.rb @@ -1,18 +1,18 @@ require "base64" class CommitsController < ProjectController + include ExtractsPath + # Authorize before_filter :authorize_read_project! before_filter :authorize_code_access! before_filter :require_non_empty_project - before_filter :load_refs, only: :index # load @branch, @tag & @ref - before_filter :render_full_content - def index - @repo = project.repo + def show + @repo = @project.repo @limit, @offset = (params[:limit] || 40), (params[:offset] || 0) - @commits = @project.commits(@ref, params[:path], @limit, @offset) + @commits = @project.commits(@ref, @path, @limit, @offset) @commits = CommitDecorator.decorate(@commits) respond_to do |format| @@ -21,54 +21,4 @@ class CommitsController < ProjectController format.atom { render layout: false } end end - - def show - result = CommitLoad.new(project, current_user, params).execute - - @commit = result[:commit] - - if @commit - @suppress_diff = result[:suppress_diff] - @note = result[:note] - @line_notes = result[:line_notes] - @notes_count = result[:notes_count] - @comments_allowed = true - else - return git_not_found! - end - - if result[:status] == :huge_commit - render "huge_commit" and return - end - end - - def compare - result = Commit.compare(project, params[:from], params[:to]) - - @commits = result[:commits] - @commit = result[:commit] - @diffs = result[:diffs] - @refs_are_same = result[:same] - @line_notes = [] - - @commits = CommitDecorator.decorate(@commits) - end - - def patch - @commit = project.commit(params[:id]) - - send_data( - @commit.to_patch, - type: "text/plain", - disposition: 'attachment', - filename: "#{@commit.id}.patch" - ) - end - - protected - - def load_refs - @ref ||= params[:ref].presence || params[:branch].presence || params[:tag].presence - @ref ||= @ref || @project.try(:default_branch) || 'master' - end end diff --git a/app/controllers/compare_controller.rb b/app/controllers/compare_controller.rb new file mode 100644 index 00000000000..62f968fd1ed --- /dev/null +++ b/app/controllers/compare_controller.rb @@ -0,0 +1,29 @@ +class CompareController < ApplicationController + before_filter :project + layout "project" + + # Authorize + before_filter :add_project_abilities + before_filter :authorize_read_project! + before_filter :authorize_code_access! + before_filter :require_non_empty_project + + def index + end + + def show + result = Commit.compare(project, params[:from], params[:to]) + + @commits = result[:commits] + @commit = result[:commit] + @diffs = result[:diffs] + @refs_are_same = result[:same] + @line_notes = [] + + @commits = CommitDecorator.decorate(@commits) + end + + def create + redirect_to project_compare_path(@project, params[:from], params[:to]) + end +end diff --git a/app/controllers/protected_branches_controller.rb b/app/controllers/protected_branches_controller.rb index 7675d3eb899..e91c78bdd35 100644 --- a/app/controllers/protected_branches_controller.rb +++ b/app/controllers/protected_branches_controller.rb @@ -4,7 +4,6 @@ class ProtectedBranchesController < ProjectController before_filter :require_non_empty_project before_filter :authorize_admin_project!, only: [:destroy, :create] - before_filter :render_full_content def index @branches = @project.protected_branches.all diff --git a/app/controllers/refs_controller.rb b/app/controllers/refs_controller.rb index 0139c09c548..9c585c9373b 100644 --- a/app/controllers/refs_controller.rb +++ b/app/controllers/refs_controller.rb @@ -1,5 +1,3 @@ -require 'github/markup' - class RefsController < ProjectController include Gitlab::Encode @@ -9,21 +7,20 @@ class RefsController < ProjectController before_filter :require_non_empty_project before_filter :ref - before_filter :define_tree_vars, only: [:tree, :blob, :blame, :logs_tree] - before_filter :render_full_content + before_filter :define_tree_vars, only: [:blob, :logs_tree] def switch respond_to do |format| format.html do new_path = if params[:destination] == "tree" - tree_project_ref_path(@project, params[:ref]) + project_tree_path(@project, @ref) else - project_commits_path(@project, ref: params[:ref]) + project_commits_path(@project, @ref) end - redirect_to new_path + redirect_to new_path end - format.js do + format.js do @ref = params[:ref] define_tree_vars render "tree" @@ -31,19 +28,6 @@ class RefsController < ProjectController end end - # - # Repository preview - # - def tree - respond_to do |format| - format.html - format.js do - # disable cache to allow back button works - no_cache_headers - end - end - end - def logs_tree contents = @tree.contents @logs = contents.map do |content| @@ -51,36 +35,12 @@ class RefsController < ProjectController last_commit = @project.commits(@commit.id, file, 1).last last_commit = CommitDecorator.decorate(last_commit) { - file_name: content.name, + file_name: content.name, commit: last_commit } end end - def blob - if @tree.is_blob? - if @tree.text? - encoding = detect_encoding(@tree.data) - mime_type = encoding ? "text/plain; charset=#{encoding}" : "text/plain" - else - mime_type = @tree.mime_type - end - - send_data( - @tree.data, - type: mime_type, - disposition: 'inline', - filename: @tree.name - ) - else - head(404) - end - end - - def blame - @blame = Grit::Blob.blame(@repo, @commit.id, params[:path]) - end - protected def define_tree_vars @@ -91,20 +51,20 @@ class RefsController < ProjectController @commit = CommitDecorator.decorate(@commit) @tree = Tree.new(@commit.tree, project, @ref, params[:path]) @tree = TreeDecorator.new(@tree) - @hex_path = Digest::SHA1.hexdigest(params[:path] || "/") + @hex_path = Digest::SHA1.hexdigest(params[:path] || "") if params[:path] - @history_path = tree_file_project_ref_path(@project, @ref, params[:path]) - @logs_path = logs_file_project_ref_path(@project, @ref, params[:path]) + @history_path = project_tree_path(@project, File.join(@ref, params[:path])) + @logs_path = logs_file_project_ref_path(@project, @ref, params[:path]) else - @history_path = tree_project_ref_path(@project, @ref) - @logs_path = logs_tree_project_ref_path(@project, @ref) + @history_path = project_tree_path(@project, @ref) + @logs_path = logs_tree_project_ref_path(@project, @ref) end rescue return render_404 end - + def ref - @ref = params[:id] + @ref = params[:id] || params[:ref] end end diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 5f55ee432c3..ef72e2e9f02 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -3,18 +3,17 @@ class RepositoriesController < ProjectController before_filter :authorize_read_project! before_filter :authorize_code_access! before_filter :require_non_empty_project - before_filter :render_full_content def show @activities = @project.commits_with_refs(20) end def branches - @branches = @project.repo.heads.sort_by(&:name) + @branches = @project.branches end def tags - @tags = @project.repo.tags.sort_by(&:name).reverse + @tags = @project.tags end def archive diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index 3d404e67a86..03e5cc73ce3 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -50,7 +50,6 @@ class SnippetsController < ProjectController def show @note = @project.notes.new(noteable: @snippet) - render_full_content end def destroy diff --git a/app/controllers/tree_controller.rb b/app/controllers/tree_controller.rb new file mode 100644 index 00000000000..e6313783d6e --- /dev/null +++ b/app/controllers/tree_controller.rb @@ -0,0 +1,29 @@ +# Controller for viewing a repository's file structure +class TreeController < ApplicationController + include ExtractsPath + + 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 :assign_ref_vars + + def show + @hex_path = Digest::SHA1.hexdigest(@path) + + @history_path = project_tree_path(@project, @id) + @logs_path = logs_file_project_ref_path(@project, @ref, @path) + + respond_to do |format| + format.html + # Disable cache so browser history works + format.js { no_cache_headers } + end + end +end diff --git a/app/decorators/event_decorator.rb b/app/decorators/event_decorator.rb index ce0aaa039b9..312ac6517d1 100644 --- a/app/decorators/event_decorator.rb +++ b/app/decorators/event_decorator.rb @@ -21,7 +21,7 @@ class EventDecorator < ApplicationDecorator elsif self.merge_request? h.project_merge_request_url(self.project, self.merge_request) elsif self.push? - h.project_commits_url(self.project, ref: self.ref_name) + h.project_commits_url(self.project, self.ref_name) end end end diff --git a/app/decorators/tree_decorator.rb b/app/decorators/tree_decorator.rb index 80c48da75bf..38236c2c553 100644 --- a/app/decorators/tree_decorator.rb +++ b/app/decorators/tree_decorator.rb @@ -6,7 +6,7 @@ class TreeDecorator < ApplicationDecorator part_path = "" parts = path.split("\/") - #parts = parts[0...-1] if is_blob? + #parts = parts[0...-1] if is_blob? yield(h.link_to("..", "#", remote: :true)) if parts.count > max_links @@ -15,29 +15,29 @@ class TreeDecorator < ApplicationDecorator part_path = part if part_path.empty? next unless parts.last(2).include?(part) if parts.count > max_links - yield(h.link_to(h.truncate(part, length: 40), h.tree_file_project_ref_path(project, ref, path: part_path), remote: :true)) + yield(h.link_to(h.truncate(part, length: 40), h.project_tree_path(project, h.tree_join(ref, part_path)), remote: :true)) end end end def up_dir? - !!path + path.present? end def up_dir_path file = File.join(path, "..") - h.tree_file_project_ref_path(project, ref, file) + h.project_tree_path(project, h.tree_join(ref, file)) end def history_path - h.project_commits_path(project, path: path, ref: ref) + h.project_commits_path(project, h.tree_join(ref, path)) end def mb_size size = (tree.size / 1024) if size < 1024 - "#{size} KB" - else + "#{size} KB" + else "#{size/1024} MB" end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 0938dc2322a..911b46c9a30 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,6 +1,35 @@ require 'digest/md5' + module ApplicationHelper + # Check if a particular controller is the current one + # + # args - One or more controller names to check + # + # Examples + # + # # On TreeController + # current_controller?(:tree) # => true + # current_controller?(:commits) # => false + # current_controller?(:commits, :tree) # => true + def current_controller?(*args) + args.any? { |v| v.to_s.downcase == controller.controller_name } + end + + # Check if a partcular action is the current one + # + # args - One or more action names to check + # + # Examples + # + # # On Projects#new + # current_action?(:new) # => true + # current_action?(:create) # => false + # current_action?(:new, :create) # => true + def current_action?(*args) + args.any? { |v| v.to_s.downcase == action_name } + end + def gravatar_icon(user_email = '', size = 40) if Gitlab.config.disable_gravatar? || user_email.blank? 'no_avatar.png' @@ -31,8 +60,8 @@ module ApplicationHelper def grouped_options_refs(destination = :tree) options = [ - ["Branch", @project.repo.heads.map(&:name) ], - [ "Tag", @project.tags ] + ["Branch", @project.branch_names ], + [ "Tag", @project.tag_names ] ] # If reference is commit id - @@ -58,11 +87,11 @@ module ApplicationHelper if @project && !@project.new_record? project_nav = [ - { label: "#{@project.name} / Issues", url: project_issues_path(@project) }, - { label: "#{@project.name} / Wall", url: wall_project_path(@project) }, - { label: "#{@project.name} / Tree", url: tree_project_ref_path(@project, @project.root_ref) }, - { label: "#{@project.name} / Commits", url: project_commits_path(@project) }, - { label: "#{@project.name} / Team", url: project_team_index_path(@project) } + { label: "#{@project.name} / Issues", url: project_issues_path(@project) }, + { label: "#{@project.name} / Wall", url: wall_project_path(@project) }, + { label: "#{@project.name} / Tree", url: project_tree_path(@project, @ref || @project.root_ref) }, + { label: "#{@project.name} / Commits", url: project_commits_path(@project, @ref || @project.root_ref) }, + { label: "#{@project.name} / Team", url: project_team_index_path(@project) } ] end @@ -85,45 +114,6 @@ module ApplicationHelper event.project.merge_requests_enabled end - def tab_class(tab_key) - active = case tab_key - - # Project Area - when :wall; wall_tab? - when :wiki; controller.controller_name == "wikis" - when :issues; issues_tab? - when :network; current_page?(controller: "projects", action: "graph", id: @project) - when :merge_requests; controller.controller_name == "merge_requests" - - # Dashboard Area - when :help; controller.controller_name == "help" - when :search; current_page?(search_path) - when :dash_issues; current_page?(dashboard_issues_path) - when :dash_mr; current_page?(dashboard_merge_requests_path) - when :root; current_page?(dashboard_path) || current_page?(root_path) - - # Profile Area - when :profile; current_page?(controller: "profile", action: :show) - when :history; current_page?(controller: "profile", action: :history) - when :account; current_page?(controller: "profile", action: :account) - when :token; current_page?(controller: "profile", action: :token) - when :design; current_page?(controller: "profile", action: :design) - when :ssh_keys; controller.controller_name == "keys" - - # Admin Area - when :admin_root; controller.controller_name == "dashboard" - when :admin_users; controller.controller_name == 'users' - when :admin_projects; controller.controller_name == "projects" - when :admin_hooks; controller.controller_name == 'hooks' - when :admin_resque; controller.controller_name == 'resque' - when :admin_logs; controller.controller_name == 'logs' - - else - false - end - active ? "current" : nil - end - def hexdigest(string) Digest::SHA1.hexdigest string end diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb index b5d7ccb7d3c..c76c1b6f83d 100644 --- a/app/helpers/tab_helper.rb +++ b/app/helpers/tab_helper.rb @@ -1,35 +1,85 @@ module TabHelper - def issues_tab? - controller.controller_name == "issues" || controller.controller_name == "milestones" - end + # Navigation link helper + # + # Returns an `li` element with an 'active' class if the supplied + # controller(s) and/or action(s) currently active. The contents of the + # element is the value passed to the block. + # + # options - The options hash used to determine if the element is "active" (default: {}) + # :controller - One or more controller names to check (optional). + # :action - One or more action names to check (optional). + # :path - A shorthand path, such as 'dashboard#index', to check (optional). + # :html_options - Extra options to be passed to the list element (optional). + # block - An optional block that will become the contents of the returned + # `li` element. + # + # When both :controller and :action are specified, BOTH must match in order + # to be marked as active. When only one is given, either can match. + # + # Examples + # + # # Assuming we're on TreeController#show + # + # # Controller matches, but action doesn't + # nav_link(controller: [:tree, :refs], action: :edit) { "Hello" } + # # => '
  • Hello
  • ' + # + # # Controller matches + # nav_link(controller: [:tree, :refs]) { "Hello" } + # # => '
  • Hello
  • ' + # + # # Shorthand path + # nav_link(path: 'tree#show') { "Hello" } + # # => '
  • Hello
  • ' + # + # # Supplying custom options for the list element + # nav_link(controller: :tree, html_options: {class: 'home'}) { "Hello" } + # # => '
  • Hello
  • ' + # + # Returns a list item element String + def nav_link(options = {}, &block) + if path = options.delete(:path) + c, a, _ = path.split('#') + else + c = options.delete(:controller) + a = options.delete(:action) + end - def wall_tab? - current_page?(controller: "projects", action: "wall", id: @project) + if c && a + # When given both options, make sure BOTH are active + klass = current_controller?(*c) && current_action?(*a) ? 'active' : '' + else + # Otherwise check EITHER option + klass = current_controller?(*c) || current_action?(*a) ? 'active' : '' + end + + # Add our custom class into the html_options, which may or may not exist + # and which may or may not already have a :class key + o = options.delete(:html_options) || {} + o[:class] ||= '' + o[:class] += ' ' + klass + o[:class].strip! + + if block_given? + content_tag(:li, capture(&block), o) + else + content_tag(:li, nil, o) + end end def project_tab_class [:show, :files, :edit, :update].each do |action| - return "current" if current_page?(controller: "projects", action: action, id: @project) + return "active" if current_page?(controller: "projects", action: action, id: @project) end if ['snippets', 'hooks', 'deploy_keys', 'team_members'].include? controller.controller_name - "current" - end - end - - def tree_tab_class - controller.controller_name == "refs" ? "current" : nil - end - - def commit_tab_class - if ['commits', 'repositories', 'protected_branches'].include? controller.controller_name - "current" + "active" end end def branches_tab_class if current_page?(branches_project_repository_path(@project)) || - controller.controller_name == "protected_branches" || + current_controller?(:protected_branches) || current_page?(project_repository_path(@project)) 'active' end diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb index 2b7265ca19e..81a16989405 100644 --- a/app/helpers/tree_helper.rb +++ b/app/helpers/tree_helper.rb @@ -39,4 +39,9 @@ module TreeHelper def gitlab_markdown?(filename) filename.end_with?(*%w(.mdown .md .markdown)) end + + # Simple shortcut to File.join + def tree_join(*args) + File.join(*args) + end end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index bb7b53face0..717fe296934 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -1,4 +1,4 @@ -require File.join(Rails.root, "app/models/commit") +require Rails.root.join("app/models/commit") class MergeRequest < ActiveRecord::Base include IssueCommonality 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/app/roles/repository.rb b/app/roles/repository.rb index 01156ac18b7..35093a2fc75 100644 --- a/app/roles/repository.rb +++ b/app/roles/repository.rb @@ -45,8 +45,29 @@ module Repository File.exists?(hook_file) end + # Returns an Array of branch names + def branch_names + repo.branches.collect(&:name).sort + end + + # Returns an Array of Branches + def branches + repo.branches.sort_by(&:name) + end + + # Returns an Array of tag names + def tag_names + repo.tags.collect(&:name).sort.reverse + end + + # Returns an Array of Tags def tags - repo.tags.map(&:name).sort.reverse + repo.tags.sort_by(&:name).reverse + end + + # Returns an Array of branch and tag names + def ref_names + [branch_names + tag_names].flatten end def repo @@ -79,14 +100,6 @@ module Repository @heads ||= repo.heads end - def branches_names - heads.map(&:name) - end - - def ref_names - [branches_names + tags].flatten - end - def tree(fcommit, path = nil) fcommit = commit if fcommit == :head tree = fcommit.tree @@ -109,14 +122,12 @@ module Repository # - If two or more branches are present, returns the one that has a name # matching root_ref (default_branch or 'master' if default_branch is nil) def discover_default_branch - branches = heads.collect(&:name) - - if branches.length == 0 + if branch_names.length == 0 nil - elsif branches.length == 1 - branches.first + elsif branch_names.length == 1 + branch_names.first else - branches.select { |v| v == root_ref }.first + branch_names.select { |v| v == root_ref }.first end end @@ -144,7 +155,7 @@ module Repository # Build file path file_name = self.code + "-" + commit.id.to_s + ".tar.gz" - storage_path = File.join(Rails.root, "tmp", "repositories", self.code) + storage_path = Rails.root.join("tmp", "repositories", self.code) file_path = File.join(storage_path, file_name) # Put files into a directory before archiving diff --git a/app/roles/static_model.rb b/app/roles/static_model.rb index d26c8f47501..d67af2439c7 100644 --- a/app/roles/static_model.rb +++ b/app/roles/static_model.rb @@ -25,6 +25,10 @@ module StaticModel id end + def new_record? + false + end + def persisted? false end diff --git a/app/views/refs/_head.html.haml b/app/views/blame/_head.html.haml similarity index 75% rename from app/views/refs/_head.html.haml rename to app/views/blame/_head.html.haml index 3592f5737ce..3b027bdaf18 100644 --- a/app/views/refs/_head.html.haml +++ b/app/views/blame/_head.html.haml @@ -1,9 +1,8 @@ %ul.nav.nav-tabs %li = render partial: 'shared/ref_switcher', locals: {destination: 'tree', path: params[:path]} - %li{class: "#{'active' if (controller.controller_name == "refs") }"} - = link_to tree_project_ref_path(@project, @ref) do - Source + = nav_link(controller: :refs) do + = link_to 'Source', project_tree_path(@project, @ref) %li.right .input-prepend.project_clone_holder %button{class: "btn small active", :"data-clone" => @project.ssh_url_to_repo} SSH diff --git a/app/views/refs/blame.html.haml b/app/views/blame/show.html.haml similarity index 62% rename from app/views/refs/blame.html.haml rename to app/views/blame/show.html.haml index eb66f59760b..8f82b00f924 100644 --- a/app/views/refs/blame.html.haml +++ b/app/views/blame/show.html.haml @@ -4,7 +4,7 @@ %ul.breadcrumb %li %span.arrow - = link_to tree_project_ref_path(@project, @ref, path: nil) do + = link_to project_tree_path(@project, @ref) do = @project.name - @tree.breadcrumbs(6) do |link| \/ @@ -18,9 +18,9 @@ = @tree.name %small blame %span.options - = link_to "raw", blob_project_ref_path(@project, @ref, path: params[:path]), class: "btn very_small", target: "_blank" - = link_to "history", project_commits_path(@project, path: params[:path], ref: @ref), class: "btn very_small" - = link_to "source", tree_file_project_ref_path(@project, @ref, path: params[:path]), class: "btn very_small" + = link_to "raw", project_blob_path(@project, @id), class: "btn very_small", target: "_blank" + = link_to "history", project_commits_path(@project, @id), class: "btn very_small" + = link_to "source", project_tree_path(@project, @id), class: "btn very_small" .file_content.blame %table - @blame.each do |commit, lines| @@ -32,8 +32,8 @@ = commit.author_name %td.blame_commit   - %code= link_to commit.short_id, project_commit_path(@project, id: commit.id) - = link_to_gfm truncate(commit.title, length: 30), project_commit_path(@project, id: commit.id), class: "row_title" rescue "--broken encoding" + %code= link_to commit.short_id, project_commit_path(@project, commit) + = link_to_gfm truncate(commit.title, length: 30), project_commit_path(@project, commit), class: "row_title" rescue "--broken encoding" %td.lines = preserve do %pre diff --git a/app/views/commit/show.html.haml b/app/views/commit/show.html.haml new file mode 100644 index 00000000000..d12fff96835 --- /dev/null +++ b/app/views/commit/show.html.haml @@ -0,0 +1,10 @@ += render "commits/commit_box" += render "commits/diffs", diffs: @commit.diffs += render "notes/notes_with_form", tid: @commit.id, tt: "commit" += render "notes/per_line_form" + + +:javascript + $(function(){ + PerLineNotes.init(); + }); diff --git a/app/views/commit/show.patch.erb b/app/views/commit/show.patch.erb new file mode 100644 index 00000000000..ce1c3d023f5 --- /dev/null +++ b/app/views/commit/show.patch.erb @@ -0,0 +1 @@ +<%= @commit.to_patch %> diff --git a/app/views/commits/_commit.html.haml b/app/views/commits/_commit.html.haml index 61371d14c5f..259e8e26260 100644 --- a/app/views/commits/_commit.html.haml +++ b/app/views/commits/_commit.html.haml @@ -1,16 +1,15 @@ %li.commit .browse_code_link_holder %p - %strong= link_to "Browse Code »", tree_project_ref_path(@project, commit.id), class: "right" + %strong= link_to "Browse Code »", project_tree_path(@project, commit), class: "right" %p - = link_to commit.short_id(8), project_commit_path(@project, id: commit.id), class: "commit_short_id" + = link_to commit.short_id(8), project_commit_path(@project, commit), class: "commit_short_id" %strong.commit-author-name= commit.author_name %span.dash – = image_tag gravatar_icon(commit.author_email), class: "avatar", width: 16 - = link_to_gfm truncate(commit.title, length: 50), project_commit_path(@project, id: commit.id), class: "row_title" + = link_to_gfm truncate(commit.title, length: 50), project_commit_path(@project, commit.id), class: "row_title" %span.committed_ago = time_ago_in_words(commit.committed_date) ago   - diff --git a/app/views/commits/_commit_box.html.haml b/app/views/commits/_commit_box.html.haml index 572337debc8..b8151b566ef 100644 --- a/app/views/commits/_commit_box.html.haml +++ b/app/views/commits/_commit_box.html.haml @@ -5,10 +5,10 @@ %span.btn.disabled.grouped %i.icon-comment = @notes_count - = link_to patch_project_commit_path(@project, @commit.id), class: "btn small grouped" do + = link_to project_commit_path(@project, @commit, format: :patch), class: "btn small grouped" do %i.icon-download-alt Get Patch - = link_to tree_project_ref_path(@project, @commit.id), class: "browse-button primary grouped" do + = link_to project_tree_path(@project, @commit), class: "browse-button primary grouped" do %strong Browse Code » %h3.commit-title.page_title = gfm escape_once(@commit.title) diff --git a/app/views/commits/_diffs.html.haml b/app/views/commits/_diffs.html.haml index b590d64c06e..026fe27e075 100644 --- a/app/views/commits/_diffs.html.haml +++ b/app/views/commits/_diffs.html.haml @@ -5,7 +5,7 @@ %p To prevent performance issue we rejected diff information. %p But if you still want to see diff - = link_to "click this link", project_commit_path(@project, @commit.id, force_show_diff: true), class: "dark" + = link_to "click this link", project_commit_path(@project, @commit, force_show_diff: true), class: "dark" %p.cgray Showing #{pluralize(diffs.count, "changed file")} @@ -24,7 +24,7 @@ %i.icon-file %span{id: "#{diff.old_path}"}= diff.old_path - else - = link_to tree_file_project_ref_path(@project, @commit.id, diff.new_path) do + = link_to project_tree_path(@project, tree_join(@commit.id, diff.new_path)) do %i.icon-file %span{id: "#{diff.new_path}"}= diff.new_path %br/ diff --git a/app/views/commits/_head.html.haml b/app/views/commits/_head.html.haml index a8111a72ed5..26ae32ed144 100644 --- a/app/views/commits/_head.html.haml +++ b/app/views/commits/_head.html.haml @@ -1,23 +1,23 @@ %ul.nav.nav-tabs %li= render partial: 'shared/ref_switcher', locals: {destination: 'commits'} - %li{class: "#{'active' if current_page?(project_commits_path(@project)) }"} - = link_to project_commits_path(@project) do - Commits - %li{class: "#{'active' if current_page?(compare_project_commits_path(@project)) }"} - = link_to compare_project_commits_path(@project) do - Compare - %li{class: "#{branches_tab_class}"} + + = nav_link(controller: [:commit, :commits]) do + = link_to 'Commits', project_commits_path(@project, @project.root_ref) + = nav_link(controller: :compare) do + = link_to 'Compare', project_compare_index_path(@project) + + = nav_link(html_options: {class: branches_tab_class}) do = link_to project_repository_path(@project) do Branches %span.badge= @project.repo.branch_count - %li{class: "#{'active' if current_page?(tags_project_repository_path(@project)) }"} + = nav_link(controller: :repositories, action: :tags) do = link_to tags_project_repository_path(@project) do Tags %span.badge= @project.repo.tag_count - - if current_page?(project_commits_path(@project)) && current_user.private_token + - if current_controller?(:commits) && current_user.private_token %li.right %span.rss-icon - = link_to project_commits_path(@project, :atom, { private_token: current_user.private_token, ref: @ref }), title: "Feed" do + = link_to project_commits_path(@project, @ref, {format: :atom, private_token: current_user.private_token}), title: "Feed" do = image_tag "rss_ui.png", title: "feed" diff --git a/app/views/commits/index.html.haml b/app/views/commits/index.html.haml deleted file mode 100644 index 11ffdb6afc3..00000000000 --- a/app/views/commits/index.html.haml +++ /dev/null @@ -1,24 +0,0 @@ -= render "head" - -- if params[:path] - %ul.breadcrumb - %li - %span.arrow - = link_to project_commits_path(@project) do - = @project.name - %span.divider - \/ - %li - %a{href: "#"}= params[:path].split("/").join(" / ") - -%div{id: dom_id(@project)} - #commits_list= render "commits" -.clear -.loading{ style: "display:none;"} - -- if @commits.count == @limit - :javascript - $(function(){ - CommitsList.init("#{@ref}", #{@limit}); - }); - diff --git a/app/views/commits/index.atom.builder b/app/views/commits/show.atom.builder similarity index 80% rename from app/views/commits/index.atom.builder rename to app/views/commits/show.atom.builder index cca704560e4..46f9838e84a 100644 --- a/app/views/commits/index.atom.builder +++ b/app/views/commits/show.atom.builder @@ -1,8 +1,8 @@ xml.instruct! xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do xml.title "Recent commits to #{@project.name}:#{@ref}" - xml.link :href => project_commits_url(@project, :atom, :ref => @ref), :rel => "self", :type => "application/atom+xml" - xml.link :href => project_commits_url(@project), :rel => "alternate", :type => "text/html" + xml.link :href => project_commits_url(@project, @ref, format: :atom), :rel => "self", :type => "application/atom+xml" + xml.link :href => project_commits_url(@project, @ref), :rel => "alternate", :type => "text/html" xml.id project_commits_url(@project) xml.updated @commits.first.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ") if @commits.any? diff --git a/app/views/commits/show.html.haml b/app/views/commits/show.html.haml index d12fff96835..ac0636382f5 100644 --- a/app/views/commits/show.html.haml +++ b/app/views/commits/show.html.haml @@ -1,10 +1,24 @@ -= render "commits/commit_box" -= render "commits/diffs", diffs: @commit.diffs -= render "notes/notes_with_form", tid: @commit.id, tt: "commit" -= render "notes/per_line_form" += render "head" +- if @path.present? + %ul.breadcrumb + %li + %span.arrow + = link_to project_commits_path(@project) do + = @project.name + %span.divider + \/ + %li + %a{href: "#"}= @path.split("/").join(" / ") + +%div{id: dom_id(@project)} + #commits_list= render "commits" +.clear +.loading{ style: "display:none;"} + +- if @commits.count == @limit + :javascript + $(function(){ + CommitsList.init("#{@ref}", #{@limit}); + }); -:javascript - $(function(){ - PerLineNotes.init(); - }); diff --git a/app/views/commits/index.js.haml b/app/views/commits/show.js.haml similarity index 100% rename from app/views/commits/index.js.haml rename to app/views/commits/show.js.haml diff --git a/app/views/commits/compare.html.haml b/app/views/compare/_form.html.haml similarity index 64% rename from app/views/commits/compare.html.haml rename to app/views/compare/_form.html.haml index db15ba53823..07f1c818e4d 100644 --- a/app/views/commits/compare.html.haml +++ b/app/views/compare/_form.html.haml @@ -1,9 +1,3 @@ -= render "head" - -%h3.page_title - Compare View -%hr - %div %p.slead Fill input field with commit id like @@ -14,7 +8,7 @@ %br - = form_tag compare_project_commits_path(@project), method: :get do + = form_tag project_compare_index_path(@project), method: :post do .clearfix = text_field_tag :from, params[:from], placeholder: "master", class: "xlarge" = "..." @@ -25,29 +19,14 @@ .actions = submit_tag "Compare", class: "btn primary wide commits-compare-btn" -- if @commits.present? - %div.ui-box - %h5.small Commits (#{@commits.count}) - %ul.unstyled= render @commits - - - unless @diffs.empty? - %h4 Diff - = render "commits/diffs", diffs: @diffs - :javascript $(function() { var availableTags = #{@project.ref_names.to_json}; - $("#from").autocomplete({ - source: availableTags, - minLength: 1 - }); - - $("#to").autocomplete({ + $("#from, #to").autocomplete({ source: availableTags, minLength: 1 }); disableButtonIfEmptyField('#to', '.commits-compare-btn'); }); - diff --git a/app/views/compare/index.html.haml b/app/views/compare/index.html.haml new file mode 100644 index 00000000000..6c9a5fd8305 --- /dev/null +++ b/app/views/compare/index.html.haml @@ -0,0 +1,7 @@ += render "commits/head" + +%h3.page_title + Compare View +%hr + += render "form" diff --git a/app/views/compare/show.html.haml b/app/views/compare/show.html.haml new file mode 100644 index 00000000000..528c8b44af4 --- /dev/null +++ b/app/views/compare/show.html.haml @@ -0,0 +1,16 @@ += render "commits/head" + +%h3.page_title + Compare View +%hr + += render "form" + +- if @commits.present? + %div.ui-box + %h5.small Commits (#{@commits.count}) + %ul.unstyled= render @commits + + - unless @diffs.empty? + %h4 Diff + = render "commits/diffs", diffs: @diffs diff --git a/app/views/events/_commit.html.haml b/app/views/events/_commit.html.haml index ed4f33c0187..ea417aa9f30 100644 --- a/app/views/events/_commit.html.haml +++ b/app/views/events/_commit.html.haml @@ -1,7 +1,7 @@ - commit = CommitDecorator.decorate(commit) %li.commit %p - = link_to commit.short_id(8), project_commit_path(project, id: commit.id), class: "commit_short_id" + = link_to commit.short_id(8), project_commit_path(project, commit), class: "commit_short_id" %span= commit.author_name – = image_tag gravatar_icon(commit.author_email), class: "avatar", width: 16 diff --git a/app/views/events/_event_last_push.html.haml b/app/views/events/_event_last_push.html.haml index 81b9994cff5..d70be70c8df 100644 --- a/app/views/events/_event_last_push.html.haml +++ b/app/views/events/_event_last_push.html.haml @@ -4,7 +4,7 @@ = image_tag gravatar_icon(event.author_email), class: "avatar" %span You pushed to = event.ref_type - = link_to project_commits_path(event.project, ref: event.ref_name) do + = link_to project_commits_path(event.project, event.ref_name) do %strong= truncate(event.ref_name, length: 28) at %strong= link_to event.project.name, event.project diff --git a/app/views/events/_event_push.html.haml b/app/views/events/_event_push.html.haml index c0be9cf5230..9b7f10d9dd2 100644 --- a/app/views/events/_event_push.html.haml +++ b/app/views/events/_event_push.html.haml @@ -5,7 +5,7 @@ .event-title %strong.author_name #{event.author_name} %span.event_label.pushed #{event.push_action_name} #{event.ref_type} - = link_to project_commits_path(event.project, ref: event.ref_name) do + = link_to project_commits_path(event.project, event.ref_name) do %strong= event.ref_name at %strong= link_to event.project.name, event.project @@ -21,6 +21,6 @@ %li.commits-stat - if event.commits_count > 2 %span ... and #{event.commits_count - 2} more commits. - = link_to compare_project_commits_path(event.project, from: event.parent_commit.id, to: event.last_commit.id) do + = link_to project_compare_path(event.project, from: event.parent_commit.id, to: event.last_commit.id) do %strong Compare → #{event.parent_commit.id[0..7]}...#{event.last_commit.id[0..7]} .clearfix diff --git a/app/views/issues/_head.html.haml b/app/views/issues/_head.html.haml index 8ebe3e057bc..4294503c211 100644 --- a/app/views/issues/_head.html.haml +++ b/app/views/issues/_head.html.haml @@ -1,13 +1,10 @@ %ul.nav.nav-tabs - %li{class: "#{'active' if current_page?(project_issues_path(@project))}"} - = link_to project_issues_path(@project), class: "tab" do - Browse Issues - %li{class: "#{'active' if current_page?(project_milestones_path(@project))}"} - = link_to project_milestones_path(@project), class: "tab" do - Milestones - %li{class: "#{'active' if current_page?(project_labels_path(@project))}"} - = link_to project_labels_path(@project), class: "tab" do - Labels + = nav_link(controller: :issues) do + = link_to 'Browse Issues', project_issues_path(@project), class: "tab" + = nav_link(controller: :milestones) do + = link_to 'Milestones', project_milestones_path(@project), class: "tab" + = nav_link(controller: :labels) do + = link_to 'Labels', project_labels_path(@project), class: "tab" %li.right %span.rss-icon = link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do diff --git a/app/views/layouts/_app_menu.html.haml b/app/views/layouts/_app_menu.html.haml deleted file mode 100644 index 025314891f8..00000000000 --- a/app/views/layouts/_app_menu.html.haml +++ /dev/null @@ -1,19 +0,0 @@ -%ul.main_menu - %li.home{class: tab_class(:root)} - = link_to "Home", root_path, title: "Home" - - %li{class: tab_class(:dash_issues)} - = link_to dashboard_issues_path do - Issues - %span.count= current_user.assigned_issues.opened.count - - %li{class: tab_class(:dash_mr)} - = link_to dashboard_merge_requests_path do - Merge Requests - %span.count= current_user.cared_merge_requests.count - - %li{class: tab_class(:search)} - = link_to "Search", search_path - - %li{class: tab_class(:help)} - = link_to "Help", help_path diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml index c076a3a1b45..25fe9d806bc 100644 --- a/app/views/layouts/_head.html.haml +++ b/app/views/layouts/_head.html.haml @@ -10,8 +10,8 @@ - if controller_name == 'projects' && action_name == 'index' = auto_discovery_link_tag :atom, projects_url(:atom, private_token: current_user.private_token), title: "Dashboard feed" - if @project && !@project.new_record? - - if current_page?(tree_project_ref_path(@project, @project.root_ref)) || current_page?(project_commits_path(@project)) - = auto_discovery_link_tag(:atom, project_commits_url(@project, :atom, ref: @ref, private_token: current_user.private_token), title: "Recent commits to #{@project.name}:#{@ref}") - - if request.path == project_issues_path(@project) + - if current_controller?(:tree, :commits) + = auto_discovery_link_tag(:atom, project_commits_url(@project, @ref, format: :atom, private_token: current_user.private_token), title: "Recent commits to #{@project.name}:#{@ref}") + - if current_controller?(:issues) = auto_discovery_link_tag(:atom, project_issues_url(@project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues") = csrf_meta_tags diff --git a/app/views/layouts/_project_menu.html.haml b/app/views/layouts/_project_menu.html.haml deleted file mode 100644 index 04eaec5accc..00000000000 --- a/app/views/layouts/_project_menu.html.haml +++ /dev/null @@ -1,37 +0,0 @@ -%ul.main_menu - %li.home{class: project_tab_class} - = link_to @project.code, project_path(@project), title: "Project" - - - if @project.repo_exists? - - if can? current_user, :download_code, @project - %li{class: tree_tab_class} - = link_to tree_project_ref_path(@project, @project.root_ref) do - Files - %li{class: commit_tab_class} - = link_to "Commits", project_commits_path(@project) - - %li{class: tab_class(:network)} - = link_to "Network", graph_project_path(@project) - - - if @project.issues_enabled - %li{class: tab_class(:issues)} - = link_to project_issues_filter_path(@project) do - Issues - %span.count.issue_counter= @project.issues.opened.count - - - if @project.repo_exists? - - if @project.merge_requests_enabled - %li{class: tab_class(:merge_requests)} - = link_to project_merge_requests_path(@project) do - Merge Requests - %span.count.merge_counter= @project.merge_requests.opened.count - - - if @project.wall_enabled - %li{class: tab_class(:wall)} - = link_to wall_project_path(@project) do - Wall - - - if @project.wiki_enabled - %li{class: tab_class(:wiki)} - = link_to project_wiki_path(@project, :index) do - Wiki diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml index 6af0f641fc4..dbb6939dd61 100644 --- a/app/views/layouts/admin.html.haml +++ b/app/views/layouts/admin.html.haml @@ -6,17 +6,17 @@ = render "layouts/head_panel", title: "Admin area" .container %ul.main_menu - %li.home{class: tab_class(:admin_root)} + = nav_link(controller: :dashboard, html_options: {class: 'home'}) do = link_to "Stats", admin_root_path - %li{class: tab_class(:admin_projects)} + = nav_link(controller: :projects) do = link_to "Projects", admin_projects_path - %li{class: tab_class(:admin_users)} + = nav_link(controller: :users) do = link_to "Users", admin_users_path - %li{class: tab_class(:admin_logs)} + = nav_link(controller: :logs) do = link_to "Logs", admin_logs_path - %li{class: tab_class(:admin_hooks)} + = nav_link(controller: :hooks) do = link_to "Hooks", admin_hooks_path - %li{class: tab_class(:admin_resque)} + = nav_link(controller: :resque) do = link_to "Resque", admin_resque_path .content= yield diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index dda10d5d137..40f4f88cbce 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -5,6 +5,20 @@ = render "layouts/flash" = render "layouts/head_panel", title: "Dashboard" .container - = render partial: "layouts/app_menu" - .content - = yield + %ul.main_menu + = nav_link(path: 'dashboard#index', html_options: {class: 'home'}) do + = link_to "Home", root_path, title: "Home" + = nav_link(path: 'dashboard#issues') do + = link_to dashboard_issues_path do + Issues + %span.count= current_user.assigned_issues.opened.count + = nav_link(path: 'dashboard#merge_requests') do + = link_to dashboard_merge_requests_path do + Merge Requests + %span.count= current_user.cared_merge_requests.count + = nav_link(path: 'search#show') do + = link_to "Search", search_path + = nav_link(path: 'help#index') do + = link_to "Help", help_path + + .content= yield diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml index 62c8db5be12..7a54bb7cf2f 100644 --- a/app/views/layouts/profile.html.haml +++ b/app/views/layouts/profile.html.haml @@ -6,23 +6,17 @@ = render "layouts/head_panel", title: "Profile" .container %ul.main_menu - %li.home{class: tab_class(:profile)} + = nav_link(path: 'profile#show', html_options: {class: 'home'}) do = link_to "Profile", profile_path - - %li{class: tab_class(:account)} + = nav_link(path: 'profile#account') do = link_to "Account", profile_account_path - - %li{class: tab_class(:ssh_keys)} + = nav_link(controller: :keys) do = link_to keys_path do SSH Keys %span.count= current_user.keys.count - - %li{class: tab_class(:design)} + = nav_link(path: 'profile#design') do = link_to "Design", profile_design_path - - %li{class: tab_class(:history)} + = nav_link(path: 'profile#history') do = link_to "History", profile_history_path - - .content - = yield + .content= yield diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml index 56a947d2a9d..b1dbe41ce65 100644 --- a/app/views/layouts/project.html.haml +++ b/app/views/layouts/project.html.haml @@ -5,7 +5,37 @@ = render "layouts/flash" = render "layouts/head_panel", title: @project.name .container - = render partial: "layouts/project_menu" - .content - = yield + %ul.main_menu + = nav_link(html_options: {class: "home #{project_tab_class}"}) do + = link_to @project.code, project_path(@project), title: "Project" + - if @project.repo_exists? + - if can? current_user, :download_code, @project + = nav_link(controller: %w(tree blob blame)) do + = link_to 'Files', project_tree_path(@project, @ref || @project.root_ref) + = nav_link(controller: %w(commit commits compare repositories protected_branches)) do + = link_to "Commits", project_commits_path(@project, @ref || @project.root_ref) + = nav_link(path: 'projects#graph') do + = link_to "Network", graph_project_path(@project) + + - if @project.issues_enabled + = nav_link(controller: %w(issues milestones labels)) do + = link_to project_issues_filter_path(@project) do + Issues + %span.count.issue_counter= @project.issues.opened.count + + - if @project.repo_exists? && @project.merge_requests_enabled + = nav_link(controller: :merge_requests) do + = link_to project_merge_requests_path(@project) do + Merge Requests + %span.count.merge_counter= @project.merge_requests.opened.count + + - if @project.wall_enabled + = nav_link(path: 'projects#wall') do + = link_to 'Wall', wall_project_path(@project) + + - if @project.wiki_enabled + = nav_link(controller: :wikis) do + = link_to 'Wiki', project_wiki_path(@project, :index) + + .content= yield diff --git a/app/views/projects/_project_head.html.haml b/app/views/projects/_project_head.html.haml index 4f38bef8b48..47a790735f3 100644 --- a/app/views/projects/_project_head.html.haml +++ b/app/views/projects/_project_head.html.haml @@ -1,29 +1,27 @@ %ul.nav.nav-tabs - %li{ class: "#{'active' if current_page?(project_path(@project)) }" } + = nav_link(path: 'projects#show') do = link_to project_path(@project), class: "activities-tab tab" do %i.icon-home Show - %li{ class: " #{'active' if (controller.controller_name == "team_members") || current_page?(project_team_index_path(@project)) }" } + = nav_link(controller: :team_members) do = link_to project_team_index_path(@project), class: "team-tab tab" do %i.icon-user Team - %li{ class: "#{'active' if current_page?(files_project_path(@project)) }" } - = link_to files_project_path(@project), class: "files-tab tab " do - Attachments - %li{ class: " #{'active' if (controller.controller_name == "snippets") }" } - = link_to project_snippets_path(@project), class: "snippets-tab tab" do - Snippets + = nav_link(path: 'projects#files') do + = link_to 'Attachments', files_project_path(@project), class: "files-tab tab" + = nav_link(controller: :snippets) do + = link_to 'Snippets', project_snippets_path(@project), class: "snippets-tab tab" - if can? current_user, :admin_project, @project - %li.right{class: "#{'active' if controller.controller_name == "deploy_keys"}"} + = nav_link(controller: :deploy_keys, html_options: {class: 'right'}) do = link_to project_deploy_keys_path(@project) do %span Deploy Keys - %li.right{class: "#{'active' if controller.controller_name == "hooks" }"} + = nav_link(controller: :hooks, html_options: {class: 'right'}) do = link_to project_hooks_path(@project) do %span Hooks - %li.right{ class: "#{'active' if current_page?(edit_project_path(@project)) }" } + = nav_link(path: 'projects#edit', html_options: {class: 'right'}) do = link_to edit_project_path(@project), class: "stat-tab tab " do %i.icon-edit Edit diff --git a/app/views/protected_branches/index.html.haml b/app/views/protected_branches/index.html.haml index 43884de1db5..50a817124dc 100644 --- a/app/views/protected_branches/index.html.haml +++ b/app/views/protected_branches/index.html.haml @@ -34,7 +34,7 @@ - @branches.each do |branch| %tr %td - = link_to project_commits_path(@project, ref: branch.name) do + = link_to project_commits_path(@project, branch.name) do %strong= branch.name - if branch.name == @project.root_ref %span.label default diff --git a/app/views/refs/logs_tree.js.haml b/app/views/refs/logs_tree.js.haml index 61ccbaee1fe..b0ac0c4b0fd 100644 --- a/app/views/refs/logs_tree.js.haml +++ b/app/views/refs/logs_tree.js.haml @@ -6,4 +6,4 @@ :plain var row = $("table.table_#{@hex_path} tr.file_#{hexdigest(file_name)}"); row.find("td.tree_time_ago").html('#{escape_javascript(time_ago_in_words(content_commit.committed_date))} ago'); - row.find("td.tree_commit").html('#{escape_javascript(render("tree_commit", tm: tm, content_commit: content_commit))}'); + row.find("td.tree_commit").html('#{escape_javascript(render("tree/tree_commit", tm: tm, content_commit: content_commit))}'); diff --git a/app/views/refs/tree.html.haml b/app/views/refs/tree.html.haml deleted file mode 100644 index 181be6426d4..00000000000 --- a/app/views/refs/tree.html.haml +++ /dev/null @@ -1,7 +0,0 @@ -= render "head" -#tree-holder= render partial: "tree", locals: {repo: @repo, commit: @commit, tree: @tree} - -:javascript - $(function() { - Tree.init(); - }); diff --git a/app/views/repositories/_branch.html.haml b/app/views/repositories/_branch.html.haml index 64a633be8ac..3c1fe47cc43 100644 --- a/app/views/repositories/_branch.html.haml +++ b/app/views/repositories/_branch.html.haml @@ -2,12 +2,12 @@ - commit = CommitDecorator.decorate(commit) %tr %td - = link_to project_commits_path(@project, ref: branch.name) do + = link_to project_commits_path(@project, branch.name) do %strong= truncate(branch.name, length: 60) - if branch.name == @project.root_ref %span.label default %td - = link_to project_commit_path(@project, id: commit.id) do + = link_to project_commit_path(@project, commit) do %code= commit.short_id = image_tag gravatar_icon(commit.author_email), class: "", width: 16 diff --git a/app/views/repositories/_branches_head.html.haml b/app/views/repositories/_branches_head.html.haml index 6afff627b94..25a988cf01b 100644 --- a/app/views/repositories/_branches_head.html.haml +++ b/app/views/repositories/_branches_head.html.haml @@ -1,11 +1,8 @@ = render "commits/head" %ul.nav.nav-pills - %li{class: ("active" if current_page?(project_repository_path(@project)))} - = link_to project_repository_path(@project) do - Recent - %li{class: ("active" if current_page?(project_protected_branches_path(@project)))} - = link_to project_protected_branches_path(@project) do - Protected - %li{class: ("active" if current_page?(branches_project_repository_path(@project)))} - = link_to branches_project_repository_path(@project) do - All + = nav_link(path: 'repositories#show') do + = link_to 'Recent', project_repository_path(@project) + = nav_link(path: 'protected_branches#index') do + = link_to 'Protected', project_protected_branches_path(@project) + = nav_link(path: 'repositories#branches') do + = link_to 'All', branches_project_repository_path(@project) diff --git a/app/views/repositories/_feed.html.haml b/app/views/repositories/_feed.html.haml index 0c13551d607..496328baca5 100644 --- a/app/views/repositories/_feed.html.haml +++ b/app/views/repositories/_feed.html.haml @@ -2,7 +2,7 @@ - commit = CommitDecorator.new(commit) %tr %td - = link_to project_commits_path(@project, ref: commit.head.name) do + = link_to project_commits_path(@project, commit.head.name) do %strong = commit.head.name - if commit.head.name == @project.root_ref diff --git a/app/views/repositories/tags.html.haml b/app/views/repositories/tags.html.haml index a41145867e9..38cc3acafae 100644 --- a/app/views/repositories/tags.html.haml +++ b/app/views/repositories/tags.html.haml @@ -12,7 +12,7 @@ - commit = CommitDecorator.decorate(commit) %tr %td - %strong= link_to tag.name, project_commits_path(@project, ref: tag.name), class: "" + %strong= link_to tag.name, project_commits_path(@project, tag.name), class: "" %td = link_to project_commit_path(@project, commit.id) do %code= commit.short_id diff --git a/app/views/shared/_ref_switcher.html.haml b/app/views/shared/_ref_switcher.html.haml index e0c89522c11..8b44cf1944e 100644 --- a/app/views/shared/_ref_switcher.html.haml +++ b/app/views/shared/_ref_switcher.html.haml @@ -1,5 +1,5 @@ = form_tag switch_project_refs_path(@project), method: :get, class: "project-refs-form" do = select_tag "ref", grouped_options_refs, class: "project-refs-select chosen" = hidden_field_tag :destination, destination - - if respond_to?(:path) + - if defined?(path) = hidden_field_tag :path, path diff --git a/app/views/tree/_head.html.haml b/app/views/tree/_head.html.haml new file mode 100644 index 00000000000..f1b3f63fedf --- /dev/null +++ b/app/views/tree/_head.html.haml @@ -0,0 +1,10 @@ +%ul.nav.nav-tabs + %li + = render partial: 'shared/ref_switcher', locals: {destination: 'tree', path: @path} + = nav_link(controller: :tree) do + = link_to 'Source', project_tree_path(@project, @ref) + %li.right + .input-prepend.project_clone_holder + %button{class: "btn small active", :"data-clone" => @project.ssh_url_to_repo} SSH + %button{class: "btn small", :"data-clone" => @project.http_url_to_repo} HTTP + = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select span5" diff --git a/app/views/refs/_submodule_item.html.haml b/app/views/tree/_submodule_item.html.haml similarity index 100% rename from app/views/refs/_submodule_item.html.haml rename to app/views/tree/_submodule_item.html.haml diff --git a/app/views/refs/_tree.html.haml b/app/views/tree/_tree.html.haml similarity index 85% rename from app/views/refs/_tree.html.haml rename to app/views/tree/_tree.html.haml index 55078718b79..439b4ec205f 100644 --- a/app/views/refs/_tree.html.haml +++ b/app/views/tree/_tree.html.haml @@ -1,7 +1,7 @@ %ul.breadcrumb %li %span.arrow - = link_to tree_project_ref_path(@project, @ref, path: nil), remote: true do + = link_to project_tree_path(@project, @ref), remote: true do = @project.name - tree.breadcrumbs(6) do |link| \/ @@ -10,7 +10,7 @@ %div.tree_progress #tree-content-holder - if tree.is_blob? - = render partial: "refs/tree_file", locals: { name: tree.name, content: tree.data, file: tree } + = render partial: "tree/tree_file", locals: { name: tree.name, content: tree.data, file: tree } - else - contents = tree.contents %table#tree-slider{class: "table_#{@hex_path}" } @@ -31,11 +31,11 @@ - index = 0 - contents.select{ |i| i.is_a?(Grit::Tree)}.each do |content| - = render partial: "refs/tree_item", locals: { content: content, index: (index += 1) } + = render partial: "tree/tree_item", locals: { content: content, index: (index += 1) } - contents.select{ |i| i.is_a?(Grit::Blob)}.each do |content| - = render partial: "refs/tree_item", locals: { content: content, index: (index += 1) } + = render partial: "tree/tree_item", locals: { content: content, index: (index += 1) } - contents.select{ |i| i.is_a?(Grit::Submodule)}.each do |content| - = render partial: "refs/submodule_item", locals: { content: content, index: (index += 1) } + = render partial: "tree/submodule_item", locals: { content: content, index: (index += 1) } - if content = contents.select{ |c| c.is_a?(Grit::Blob) and c.name =~ /^readme/i }.first .file_holder#README diff --git a/app/views/refs/_tree_commit.html.haml b/app/views/tree/_tree_commit.html.haml similarity index 100% rename from app/views/refs/_tree_commit.html.haml rename to app/views/tree/_tree_commit.html.haml diff --git a/app/views/refs/_tree_file.html.haml b/app/views/tree/_tree_file.html.haml similarity index 69% rename from app/views/refs/_tree_file.html.haml rename to app/views/tree/_tree_file.html.haml index 76173e24246..93f7be28d21 100644 --- a/app/views/refs/_tree_file.html.haml +++ b/app/views/tree/_tree_file.html.haml @@ -5,9 +5,9 @@ = name.force_encoding('utf-8') %small #{file.mode} %span.options - = link_to "raw", blob_project_ref_path(@project, @ref, path: params[:path]), class: "btn very_small", target: "_blank" - = link_to "history", project_commits_path(@project, path: params[:path], ref: @ref), class: "btn very_small" - = link_to "blame", blame_file_project_ref_path(@project, @ref, path: params[:path]), class: "btn very_small" + = link_to "raw", project_blob_path(@project, @id), class: "btn very_small", target: "_blank" + = link_to "history", project_commits_path(@project, @id), class: "btn very_small" + = link_to "blame", project_blame_path(@project, @id), class: "btn very_small" - if file.text? - if gitlab_markdown?(name) .file_content.wiki @@ -32,7 +32,7 @@ - else .file_content.blob_file %center - = link_to blob_project_ref_path(@project, @ref, path: params[:path]) do + = link_to project_blob_path(@project, @id) do %div.padded %br = image_tag "download.png", width: 64 diff --git a/app/views/refs/_tree_item.html.haml b/app/views/tree/_tree_item.html.haml similarity index 51% rename from app/views/refs/_tree_item.html.haml rename to app/views/tree/_tree_item.html.haml index d4c4ee8de49..226c380ff82 100644 --- a/app/views/refs/_tree_item.html.haml +++ b/app/views/tree/_tree_item.html.haml @@ -1,8 +1,8 @@ - file = tree_full_path(content) -%tr{ class: "tree-item #{tree_hex_class(content)}", url: tree_file_project_ref_path(@project, @ref, file) } +%tr{ class: "tree-item #{tree_hex_class(content)}", url: project_tree_path(@project, tree_join(@id, file)) } %td.tree-item-file-name = tree_icon(content) - %strong= link_to truncate(content.name, length: 40), tree_file_project_ref_path(@project, @ref || @commit.id, file), remote: :true + %strong= link_to truncate(content.name, length: 40), project_tree_path(@project, tree_join(@id || @commit.id, file)), remote: :true %td.tree_time_ago.cgray - if index == 1 %span.log_loading diff --git a/app/views/tree/show.html.haml b/app/views/tree/show.html.haml new file mode 100644 index 00000000000..d95f90e0b54 --- /dev/null +++ b/app/views/tree/show.html.haml @@ -0,0 +1,7 @@ += render "head" +#tree-holder= render partial: "tree", locals: {commit: @commit, tree: @tree} + +:javascript + $(function() { + Tree.init(); + }); diff --git a/app/views/refs/tree.js.haml b/app/views/tree/show.js.haml similarity index 71% rename from app/views/refs/tree.js.haml rename to app/views/tree/show.js.haml index 92e90579304..174e3e03a52 100644 --- a/app/views/refs/tree.js.haml +++ b/app/views/tree/show.js.haml @@ -1,8 +1,8 @@ :plain // Load Files list - $("#tree-holder").html("#{escape_javascript(render(partial: "tree", locals: {repo: @repo, commit: @commit, tree: @tree}))}"); + $("#tree-holder").html("#{escape_javascript(render(partial: "tree", locals: {commit: @commit, tree: @tree}))}"); $("#tree-content-holder").show("slide", { direction: "right" }, 150); - $('.project-refs-form #path').val("#{params[:path]}"); + $('.project-refs-form #path').val("#{@path}"); // Load last commit log for each file in tree $('#tree-slider').waitForImages(function() { diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 7a7ca43f1d0..276707a73af 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -112,7 +112,7 @@ class Settings < Settingslogic def backup_path t = app['backup_path'] || "backups/" - t = /^\//.match(t) ? t : File.join(Rails.root + t) + t = /^\//.match(t) ? t : Rails.root .join(t) t end diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index 9e8b0131f8f..5d46ece1e1b 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -8,3 +8,24 @@ # inflect.irregular 'person', 'people' # inflect.uncountable %w( fish sheep ) # end + +# Mark "commits" as uncountable. +# +# Without this change, the routes +# +# resources :commit, only: [:show], constraints: {id: /[[:alnum:]]{6,40}/} +# resources :commits, only: [:show], constraints: {id: /.+/} +# +# would generate identical route helper methods (`project_commit_path`), resulting +# in one of them not getting a helper method at all. +# +# After this change, the helper methods are: +# +# project_commit_path(@project, @project.commit) +# # => "/gitlabhq/commit/bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a +# +# project_commits_path(@project, 'stable/README.md') +# # => "/gitlabhq/commits/stable/README.md" +ActiveSupport::Inflector.inflections do |inflect| + inflect.uncountable %w(commits) +end diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb index 72aca7e441e..3549b8362bb 100644 --- a/config/initializers/mime_types.rb +++ b/config/initializers/mime_types.rb @@ -3,3 +3,5 @@ # Add new mime types for use in respond_to blocks: # Mime::Type.register "text/richtext", :rtf # Mime::Type.register_alias "text/html", :iphone + +Mime::Type.register_alias 'text/plain', :patch diff --git a/config/routes.rb b/config/routes.rb index cfb9bdb957c..21521a979e5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -122,38 +122,14 @@ Gitlab::Application.routes.draw do end member do - get "tree", constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } + # tree viewer logs get "logs_tree", constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } - - get "blob", - constraints: { - id: /[a-zA-Z.0-9\/_\-]+/, - path: /.*/ - } - - # tree viewer - get "tree/:path" => "refs#tree", - as: :tree_file, - constraints: { - id: /[a-zA-Z.0-9\/_\-]+/, - path: /.*/ - } - - # tree viewer get "logs_tree/:path" => "refs#logs_tree", as: :logs_file, constraints: { id: /[a-zA-Z.0-9\/_\-]+/, path: /.*/ } - - # blame - get "blame/:path" => "refs#blame", - as: :blame_file, - constraints: { - id: /[a-zA-Z.0-9\/_\-]+/, - path: /.*/ - } end end @@ -182,27 +158,27 @@ Gitlab::Application.routes.draw do get :test end end - resources :commits do - collection do - get :compare - end - member do - get :patch - end - end + resources :commit, only: [:show], constraints: {id: /[[:alnum:]]{6,40}/} + resources :commits, only: [:show], constraints: {id: /.+/} + resources :compare, only: [:index, :create] + resources :blame, only: [:show], constraints: {id: /.+/} + resources :blob, only: [:show], constraints: {id: /.+/} + resources :tree, only: [:show], constraints: {id: /.+/} + match "/compare/:from...:to" => "compare#show", as: "compare", constraints: {from: /.+/, to: /.+/} + resources :team, controller: 'team_members', only: [:index] resources :team_members resources :milestones resources :labels, only: [:index] resources :issues do - collection do post :sort post :bulk_update get :search end end + resources :notes, only: [:index, :create, :destroy] do collection do post :preview diff --git a/db/fixtures/test/001_repo.rb b/db/fixtures/test/001_repo.rb index 67d4e7bfbde..18fc37cde0c 100644 --- a/db/fixtures/test/001_repo.rb +++ b/db/fixtures/test/001_repo.rb @@ -3,13 +3,13 @@ require 'fileutils' print "Unpacking seed repository..." SEED_REPO = 'seed_project.tar.gz' -REPO_PATH = File.join(Rails.root, 'tmp', 'repositories') +REPO_PATH = Rails.root.join('tmp', 'repositories') # Make whatever directories we need to make FileUtils.mkdir_p(REPO_PATH) # Copy the archive to the repo path -FileUtils.cp(File.join(Rails.root, 'spec', SEED_REPO), REPO_PATH) +FileUtils.cp(Rails.root.join('spec', SEED_REPO), REPO_PATH) # chdir to the repo path FileUtils.cd(REPO_PATH) do diff --git a/features/admin/active_tab.feature b/features/admin/active_tab.feature new file mode 100644 index 00000000000..fce85ce9901 --- /dev/null +++ b/features/admin/active_tab.feature @@ -0,0 +1,33 @@ +Feature: Admin active tab + Background: + Given I sign in as an admin + + Scenario: On Admin Home + Given I visit admin page + Then the active main tab should be Home + And no other main tabs should be active + + Scenario: On Admin Projects + Given I visit admin projects page + Then the active main tab should be Projects + And no other main tabs should be active + + Scenario: On Admin Users + Given I visit admin users page + Then the active main tab should be Users + And no other main tabs should be active + + Scenario: On Admin Logs + Given I visit admin logs page + Then the active main tab should be Logs + And no other main tabs should be active + + Scenario: On Admin Hooks + Given I visit admin hooks page + Then the active main tab should be Hooks + And no other main tabs should be active + + Scenario: On Admin Resque + Given I visit admin Resque page + Then the active main tab should be Resque + And no other main tabs should be active diff --git a/features/dashboard/active_tab.feature b/features/dashboard/active_tab.feature new file mode 100644 index 00000000000..6715ea269c7 --- /dev/null +++ b/features/dashboard/active_tab.feature @@ -0,0 +1,28 @@ +Feature: Dashboard active tab + Background: + Given I sign in as a user + + Scenario: On Dashboard Home + Given I visit dashboard page + Then the active main tab should be Home + And no other main tabs should be active + + Scenario: On Dashboard Issues + Given I visit dashboard issues page + Then the active main tab should be Issues + And no other main tabs should be active + + Scenario: On Dashboard Merge Requests + Given I visit dashboard merge requests page + Then the active main tab should be Merge Requests + And no other main tabs should be active + + Scenario: On Dashboard Search + Given I visit dashboard search page + Then the active main tab should be Search + And no other main tabs should be active + + Scenario: On Dashboard Help + Given I visit dashboard help page + Then the active main tab should be Help + And no other main tabs should be active diff --git a/features/profile/active_tab.feature b/features/profile/active_tab.feature new file mode 100644 index 00000000000..475641a33ed --- /dev/null +++ b/features/profile/active_tab.feature @@ -0,0 +1,28 @@ +Feature: Profile active tab + Background: + Given I sign in as a user + + Scenario: On Profile Home + Given I visit profile page + Then the active main tab should be Home + And no other main tabs should be active + + Scenario: On Profile Account + Given I visit profile account page + Then the active main tab should be Account + And no other main tabs should be active + + Scenario: On Profile SSH Keys + Given I visit profile SSH keys page + Then the active main tab should be SSH Keys + And no other main tabs should be active + + Scenario: On Profile Design + Given I visit profile design page + Then the active main tab should be Design + And no other main tabs should be active + + Scenario: On Profile History + Given I visit profile history page + Then the active main tab should be History + And no other main tabs should be active diff --git a/features/project/active_tab.feature b/features/project/active_tab.feature new file mode 100644 index 00000000000..2d3e41d3d33 --- /dev/null +++ b/features/project/active_tab.feature @@ -0,0 +1,147 @@ +Feature: Project active tab + Background: + Given I sign in as a user + And I own a project + + # Main Tabs + + Scenario: On Project Home + Given I visit my project's home page + Then the active main tab should be Home + And no other main tabs should be active + + Scenario: On Project Files + Given I visit my project's files page + Then the active main tab should be Files + And no other main tabs should be active + + Scenario: On Project Commits + Given I visit my project's commits page + Then the active main tab should be Commits + And no other main tabs should be active + + Scenario: On Project Network + Given I visit my project's network page + Then the active main tab should be Network + And no other main tabs should be active + + Scenario: On Project Issues + Given I visit my project's issues page + Then the active main tab should be Issues + And no other main tabs should be active + + Scenario: On Project Merge Requests + Given I visit my project's merge requests page + Then the active main tab should be Merge Requests + And no other main tabs should be active + + Scenario: On Project Wall + Given I visit my project's wall page + Then the active main tab should be Wall + And no other main tabs should be active + + Scenario: On Project Wiki + Given I visit my project's wiki page + Then the active main tab should be Wiki + And no other main tabs should be active + + # Sub Tabs: Home + + Scenario: On Project Home/Show + Given I visit my project's home page + Then the active sub tab should be Show + And no other sub tabs should be active + And the active main tab should be Home + + Scenario: On Project Home/Team + Given I visit my project's home page + And I click the "Team" tab + Then the active sub tab should be Team + And no other sub tabs should be active + And the active main tab should be Home + + Scenario: On Project Home/Attachments + Given I visit my project's home page + And I click the "Attachments" tab + Then the active sub tab should be Attachments + And no other sub tabs should be active + And the active main tab should be Home + + Scenario: On Project Home/Snippets + Given I visit my project's home page + And I click the "Snippets" tab + Then the active sub tab should be Snippets + And no other sub tabs should be active + And the active main tab should be Home + + Scenario: On Project Home/Edit + Given I visit my project's home page + And I click the "Edit" tab + Then the active sub tab should be Edit + And no other sub tabs should be active + And the active main tab should be Home + + Scenario: On Project Home/Hooks + Given I visit my project's home page + And I click the "Hooks" tab + Then the active sub tab should be Hooks + And no other sub tabs should be active + And the active main tab should be Home + + Scenario: On Project Home/Deploy Keys + Given I visit my project's home page + And I click the "Deploy Keys" tab + Then the active sub tab should be Deploy Keys + And no other sub tabs should be active + And the active main tab should be Home + + # Sub Tabs: Commits + + Scenario: On Project Commits/Commits + Given I visit my project's commits page + Then the active sub tab should be Commits + And no other sub tabs should be active + And the active main tab should be Commits + + Scenario: On Project Commits/Compare + Given I visit my project's commits page + And I click the "Compare" tab + Then the active sub tab should be Compare + And no other sub tabs should be active + And the active main tab should be Commits + + Scenario: On Project Commits/Branches + Given I visit my project's commits page + And I click the "Branches" tab + Then the active sub tab should be Branches + And no other sub tabs should be active + And the active main tab should be Commits + + Scenario: On Project Commits/Tags + Given I visit my project's commits page + And I click the "Tags" tab + Then the active sub tab should be Tags + And no other sub tabs should be active + And the active main tab should be Commits + + # Sub Tabs: Issues + + Scenario: On Project Issues/Browse + Given I visit my project's issues page + Then the active sub tab should be Browse Issues + And no other sub tabs should be active + And the active main tab should be Issues + + Scenario: On Project Issues/Milestones + Given I visit my project's issues page + And I click the "Milestones" tab + Then the active sub tab should be Milestones + And no other sub tabs should be active + And the active main tab should be Issues + + Scenario: On Project Issues/Labels + Given I visit my project's issues page + And I click the "Labels" tab + Then the active sub tab should be Labels + And no other sub tabs should be active + And the active main tab should be Issues diff --git a/features/project/commits/commits.feature b/features/project/commits/commits.feature index 53de6e6a264..df795ef71e6 100644 --- a/features/project/commits/commits.feature +++ b/features/project/commits/commits.feature @@ -1,8 +1,8 @@ Feature: Project Browse commits Background: Given I sign in as a user - And I own project "Shop" - Given I visit project commits page + And I own a project + And I visit my project's commits page Scenario: I browse commits list for master branch Then I see project commits @@ -18,4 +18,4 @@ Feature: Project Browse commits Scenario: I compare refs Given I visit compare refs page And I fill compare fields with refs - And I see compared refs + Then I see compared refs diff --git a/features/steps/admin/admin_active_tab.rb b/features/steps/admin/admin_active_tab.rb new file mode 100644 index 00000000000..29290892823 --- /dev/null +++ b/features/steps/admin/admin_active_tab.rb @@ -0,0 +1,29 @@ +class AdminActiveTab < Spinach::FeatureSteps + include SharedAuthentication + include SharedPaths + include SharedActiveTab + + Then 'the active main tab should be Home' do + ensure_active_main_tab('Stats') + end + + Then 'the active main tab should be Projects' do + ensure_active_main_tab('Projects') + end + + Then 'the active main tab should be Users' do + ensure_active_main_tab('Users') + end + + Then 'the active main tab should be Logs' do + ensure_active_main_tab('Logs') + end + + Then 'the active main tab should be Hooks' do + ensure_active_main_tab('Hooks') + end + + Then 'the active main tab should be Resque' do + ensure_active_main_tab('Resque') + end +end diff --git a/features/steps/dashboard/dashboard_active_tab.rb b/features/steps/dashboard/dashboard_active_tab.rb new file mode 100644 index 00000000000..41ecc48c0d3 --- /dev/null +++ b/features/steps/dashboard/dashboard_active_tab.rb @@ -0,0 +1,25 @@ +class DashboardActiveTab < Spinach::FeatureSteps + include SharedAuthentication + include SharedPaths + include SharedActiveTab + + Then 'the active main tab should be Home' do + ensure_active_main_tab('Home') + end + + Then 'the active main tab should be Issues' do + ensure_active_main_tab('Issues') + end + + Then 'the active main tab should be Merge Requests' do + ensure_active_main_tab('Merge Requests') + end + + Then 'the active main tab should be Search' do + ensure_active_main_tab('Search') + end + + Then 'the active main tab should be Help' do + ensure_active_main_tab('Help') + end +end diff --git a/features/steps/profile/profile_active_tab.rb b/features/steps/profile/profile_active_tab.rb new file mode 100644 index 00000000000..1924a6fa785 --- /dev/null +++ b/features/steps/profile/profile_active_tab.rb @@ -0,0 +1,25 @@ +class ProfileActiveTab < Spinach::FeatureSteps + include SharedAuthentication + include SharedPaths + include SharedActiveTab + + Then 'the active main tab should be Home' do + ensure_active_main_tab('Profile') + end + + Then 'the active main tab should be Account' do + ensure_active_main_tab('Account') + end + + Then 'the active main tab should be SSH Keys' do + ensure_active_main_tab('SSH Keys') + end + + Then 'the active main tab should be Design' do + ensure_active_main_tab('Design') + end + + Then 'the active main tab should be History' do + ensure_active_main_tab('History') + end +end diff --git a/features/steps/project/project_active_tab.rb b/features/steps/project/project_active_tab.rb new file mode 100644 index 00000000000..a5c80353862 --- /dev/null +++ b/features/steps/project/project_active_tab.rb @@ -0,0 +1,146 @@ +class ProjectActiveTab < Spinach::FeatureSteps + include SharedAuthentication + include SharedPaths + include SharedProject + include SharedActiveTab + + # Main Tabs + + Then 'the active main tab should be Home' do + ensure_active_main_tab(@project.name) + end + + Then 'the active main tab should be Files' do + ensure_active_main_tab('Files') + end + + Then 'the active main tab should be Commits' do + ensure_active_main_tab('Commits') + end + + Then 'the active main tab should be Network' do + ensure_active_main_tab('Network') + end + + Then 'the active main tab should be Issues' do + ensure_active_main_tab('Issues') + end + + Then 'the active main tab should be Merge Requests' do + ensure_active_main_tab('Merge Requests') + end + + Then 'the active main tab should be Wall' do + ensure_active_main_tab('Wall') + end + + Then 'the active main tab should be Wiki' do + ensure_active_main_tab('Wiki') + end + + # Sub Tabs: Home + + Given 'I click the "Team" tab' do + click_link('Team') + end + + Given 'I click the "Attachments" tab' do + click_link('Attachments') + end + + Given 'I click the "Snippets" tab' do + click_link('Snippets') + end + + Given 'I click the "Edit" tab' do + click_link('Edit') + end + + Given 'I click the "Hooks" tab' do + click_link('Hooks') + end + + Given 'I click the "Deploy Keys" tab' do + click_link('Deploy Keys') + end + + Then 'the active sub tab should be Show' do + ensure_active_sub_tab('Show') + end + + Then 'the active sub tab should be Team' do + ensure_active_sub_tab('Team') + end + + Then 'the active sub tab should be Attachments' do + ensure_active_sub_tab('Attachments') + end + + Then 'the active sub tab should be Snippets' do + ensure_active_sub_tab('Snippets') + end + + Then 'the active sub tab should be Edit' do + ensure_active_sub_tab('Edit') + end + + Then 'the active sub tab should be Hooks' do + ensure_active_sub_tab('Hooks') + end + + Then 'the active sub tab should be Deploy Keys' do + ensure_active_sub_tab('Deploy Keys') + end + + # Sub Tabs: Commits + + Given 'I click the "Compare" tab' do + click_link('Compare') + end + + Given 'I click the "Branches" tab' do + click_link('Branches') + end + + Given 'I click the "Tags" tab' do + click_link('Tags') + end + + Then 'the active sub tab should be Commits' do + ensure_active_sub_tab('Commits') + end + + Then 'the active sub tab should be Compare' do + ensure_active_sub_tab('Compare') + end + + Then 'the active sub tab should be Branches' do + ensure_active_sub_tab('Branches') + end + + Then 'the active sub tab should be Tags' do + ensure_active_sub_tab('Tags') + end + + # Sub Tabs: Issues + + Given 'I click the "Milestones" tab' do + click_link('Milestones') + end + + Given 'I click the "Labels" tab' do + click_link('Labels') + end + + Then 'the active sub tab should be Browse Issues' do + ensure_active_sub_tab('Browse Issues') + end + + Then 'the active sub tab should be Milestones' do + ensure_active_sub_tab('Milestones') + end + + Then 'the active sub tab should be Labels' do + ensure_active_sub_tab('Labels') + end +end diff --git a/features/steps/project/project_browse_commits.rb b/features/steps/project/project_browse_commits.rb index 014799879e8..cb5cabe98b3 100644 --- a/features/steps/project/project_browse_commits.rb +++ b/features/steps/project/project_browse_commits.rb @@ -4,8 +4,6 @@ class ProjectBrowseCommits < Spinach::FeatureSteps include SharedPaths Then 'I see project commits' do - current_path.should == project_commits_path(@project) - commit = @project.commit page.should have_content(@project.name) page.should have_content(commit.message) @@ -34,14 +32,14 @@ class ProjectBrowseCommits < Spinach::FeatureSteps end And 'I fill compare fields with refs' do - fill_in "from", :with => "master" - fill_in "to", :with => "stable" + fill_in "from", with: "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" + fill_in "to", with: "8716fc78f3c65bbf7bcf7b574febd583bc5d2812" click_button "Compare" end - And 'I see compared refs' do - page.should have_content "Commits (27)" + Then 'I see compared refs' do page.should have_content "Compare View" - page.should have_content "Showing 73 changed files" + page.should have_content "Commits (1)" + page.should have_content "Showing 2 changed files" end end diff --git a/features/steps/project/project_browse_files.rb b/features/steps/project/project_browse_files.rb index 67c553ced40..652daba01c0 100644 --- a/features/steps/project/project_browse_files.rb +++ b/features/steps/project/project_browse_files.rb @@ -10,7 +10,7 @@ class ProjectBrowseFiles < Spinach::FeatureSteps end Then 'I should see files from repository for "8470d70"' do - current_path.should == tree_project_ref_path(@project, "8470d70") + current_path.should == project_tree_path(@project, "8470d70") page.should have_content "app" page.should have_content "History" page.should have_content "Gemfile" diff --git a/features/steps/shared/active_tab.rb b/features/steps/shared/active_tab.rb new file mode 100644 index 00000000000..884f2d5fb71 --- /dev/null +++ b/features/steps/shared/active_tab.rb @@ -0,0 +1,19 @@ +module SharedActiveTab + include Spinach::DSL + + def ensure_active_main_tab(content) + page.find('ul.main_menu li.active').should have_content(content) + end + + def ensure_active_sub_tab(content) + page.find('div.content ul.nav-tabs li.active').should have_content(content) + end + + And 'no other main tabs should be active' do + page.should have_selector('ul.main_menu li.active', count: 1) + end + + And 'no other sub tabs should be active' do + page.should have_selector('div.content ul.nav-tabs li.active', count: 1) + end +end diff --git a/features/steps/shared/authentication.rb b/features/steps/shared/authentication.rb index 77d9839f5b7..2add91617fe 100644 --- a/features/steps/shared/authentication.rb +++ b/features/steps/shared/authentication.rb @@ -7,4 +7,8 @@ module SharedAuthentication Given 'I sign in as a user' do login_as :user end + + Given 'I sign in as an admin' do + login_as :admin + end end diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb index 93ad0219d3d..8efedfa1083 100644 --- a/features/steps/shared/paths.rb +++ b/features/steps/shared/paths.rb @@ -1,22 +1,38 @@ module SharedPaths include Spinach::DSL - And 'I visit dashboard search page' do - visit search_path + When 'I visit new project page' do + visit new_project_path end - And 'I visit dashboard merge requests page' do - visit dashboard_merge_requests_path + # ---------------------------------------- + # Dashboard + # ---------------------------------------- + + Given 'I visit dashboard page' do + visit dashboard_path end - And 'I visit dashboard issues page' do + Given 'I visit dashboard issues page' do visit dashboard_issues_path end - When 'I visit dashboard page' do - visit dashboard_path + Given 'I visit dashboard merge requests page' do + visit dashboard_merge_requests_path end + Given 'I visit dashboard search page' do + visit search_path + end + + Given 'I visit dashboard help page' do + visit help_path + end + + # ---------------------------------------- + # Profile + # ---------------------------------------- + Given 'I visit profile page' do visit profile_path end @@ -25,14 +41,94 @@ module SharedPaths visit profile_account_path end + Given 'I visit profile SSH keys page' do + visit keys_path + end + + Given 'I visit profile design page' do + visit profile_design_path + end + + Given 'I visit profile history page' do + visit profile_history_path + end + Given 'I visit profile token page' do visit profile_token_path end - When 'I visit new project page' do - visit new_project_path + # ---------------------------------------- + # Admin + # ---------------------------------------- + + Given 'I visit admin page' do + visit admin_root_path end + Given 'I visit admin projects page' do + visit admin_projects_path + end + + Given 'I visit admin users page' do + visit admin_users_path + end + + Given 'I visit admin logs page' do + visit admin_logs_path + end + + Given 'I visit admin hooks page' do + visit admin_hooks_path + end + + Given 'I visit admin Resque page' do + visit admin_resque_path + end + + # ---------------------------------------- + # Generic Project + # ---------------------------------------- + + Given "I visit my project's home page" do + visit project_path(@project) + end + + Given "I visit my project's files page" do + visit project_tree_path(@project, @project.root_ref) + end + + Given "I visit my project's commits page" do + visit project_commits_path(@project, @project.root_ref, {limit: 5}) + end + + Given "I visit my project's network page" do + # Stub out find_all to speed this up (10 commits vs. 650) + commits = Grit::Commit.find_all(@project.repo, nil, {max_count: 10}) + Grit::Commit.stub(:find_all).and_return(commits) + + visit graph_project_path(@project) + end + + Given "I visit my project's issues page" do + visit project_issues_path(@project) + end + + Given "I visit my project's merge requests page" do + visit project_merge_requests_path(@project) + end + + Given "I visit my project's wall page" do + visit wall_project_path(@project) + end + + Given "I visit my project's wiki page" do + visit project_wiki_path(@project, :index) + end + + # ---------------------------------------- + # "Shop" Project + # ---------------------------------------- + And 'I visit project "Shop" page' do project = Project.find_by_name("Shop") visit project_path(project) @@ -43,23 +139,27 @@ module SharedPaths end Given 'I visit compare refs page' do - visit compare_project_commits_path(@project) + visit project_compare_index_path(@project) end Given 'I visit project commits page' do - visit project_commits_path(@project) + visit project_commits_path(@project, @project.root_ref, {limit: 5}) + end + + Given 'I visit project commits page for stable branch' do + visit project_commits_path(@project, 'stable', {limit: 5}) end Given 'I visit project source page' do - visit tree_project_ref_path(@project, @project.root_ref) + visit project_tree_path(@project, @project.root_ref) end Given 'I visit blob file from repo' do - visit tree_project_ref_path(@project, ValidCommit::ID, :path => ValidCommit::BLOB_FILE_PATH) + visit project_tree_path(@project, File.join(ValidCommit::ID, ValidCommit::BLOB_FILE_PATH)) end Given 'I visit project source page for "8470d70"' do - visit tree_project_ref_path(@project, "8470d70") + visit project_tree_path(@project, "8470d70") end Given 'I visit project tags page' do diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb index 9b64ca59a3b..0f93d675786 100644 --- a/features/steps/shared/project.rb +++ b/features/steps/shared/project.rb @@ -1,6 +1,13 @@ module SharedProject include Spinach::DSL + # Create a project without caring about what it's called + And "I own a project" do + @project = create(:project) + @project.add_access(@user, :admin) + end + + # Create a specific project called "Shop" And 'I own project "Shop"' do @project = Factory :project, :name => "Shop" @project.add_access(@user, :admin) diff --git a/features/support/env.rb b/features/support/env.rb index 9c6cef07298..6d49c25a8ba 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -23,5 +23,7 @@ Spinach.hooks.after_scenario { DatabaseCleaner.clean } Spinach.hooks.before_run do RSpec::Mocks::setup self + include FactoryGirl::Syntax::Methods + stub_gitolite! end diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb new file mode 100644 index 00000000000..f36dae5289b --- /dev/null +++ b/lib/extracts_path.rb @@ -0,0 +1,114 @@ +# Module providing methods for dealing with separating a tree-ish string and a +# file path string when combined in a request parameter +module ExtractsPath + extend ActiveSupport::Concern + + # Raised when given an invalid file path + class InvalidPathError < StandardError; end + + included do + if respond_to?(:before_filter) + before_filter :assign_ref_vars, only: [:show] + end + end + + # Given a string containing both a Git tree-ish, such as a branch or tag, and + # a filesystem path joined by forward slashes, attempts to separate the two. + # + # Expects a @project instance variable to contain the active project. This is + # used to check the input against a list of valid repository refs. + # + # Examples + # + # # No @project available + # extract_ref('master') + # # => ['', ''] + # + # extract_ref('master') + # # => ['master', ''] + # + # extract_ref("f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG") + # # => ['f4b14494ef6abf3d144c28e4af0c20143383e062', 'CHANGELOG'] + # + # extract_ref("v2.0.0/README.md") + # # => ['v2.0.0', 'README.md'] + # + # extract_ref('issues/1234/app/models/project.rb') + # # => ['issues/1234', 'app/models/project.rb'] + # + # # Given an invalid branch, we fall back to just splitting on the first slash + # extract_ref('non/existent/branch/README.md') + # # => ['non', 'existent/branch/README.md'] + # + # Returns an Array where the first value is the tree-ish and the second is the + # path + def extract_ref(input) + pair = ['', ''] + + return pair unless @project + + if input.match(/^([[:alnum:]]{40})(.+)/) + # If the ref appears to be a SHA, we're done, just split the string + pair = $~.captures + else + # Otherwise, attempt to detect the ref using a list of the project's + # branches and tags + + # Append a trailing slash if we only get a ref and no file path + id = input + id += '/' unless id.include?('/') + + valid_refs = @project.branches + @project.tags + valid_refs.select! { |v| id.start_with?("#{v}/") } + + if valid_refs.length != 1 + # No exact ref match, so just try our best + pair = id.match(/([^\/]+)(.*)/).captures + else + # Partition the string into the ref and the path, ignoring the empty first value + pair = id.partition(valid_refs.first)[1..-1] + end + end + + # Remove leading slash from path + pair[1].gsub!(/^\//, '') + + pair + end + + # Assigns common instance variables for views working with Git tree-ish objects + # + # Assignments are: + # + # - @id - A string representing the joined ref and path + # - @ref - A string representing the ref (e.g., the branch, tag, or commit SHA) + # - @path - A string representing the filesystem path + # - @commit - A CommitDecorator representing the commit from the given ref + # - @tree - A TreeDecorator representing the tree at the given ref/path + # + # If the :id parameter appears to be requesting a specific response format, + # that will be handled as well. + # + # Automatically renders `not_found!` if a valid tree path could not be + # resolved (e.g., when a user inserts an invalid path or ref). + def assign_ref_vars + # Handle formats embedded in the id + if params[:id].ends_with?('.atom') + params[:id].gsub!(/\.atom$/, '') + request.format = :atom + end + + @ref, @path = extract_ref(params[:id]) + + @id = File.join(@ref, @path) + + @commit = CommitDecorator.decorate(@project.commit(@ref)) + + @tree = Tree.new(@commit.tree, @project, @ref, @path) + @tree = TreeDecorator.new(@tree) + + raise InvalidPathError if @tree.invalid? + rescue NoMethodError, InvalidPathError + not_found! + end +end diff --git a/lib/gitlab/backend/gitolite_config.rb b/lib/gitlab/backend/gitolite_config.rb index f51e8efc370..ffe15fb1123 100644 --- a/lib/gitlab/backend/gitolite_config.rb +++ b/lib/gitlab/backend/gitolite_config.rb @@ -10,7 +10,7 @@ module Gitlab attr_reader :config_tmp_dir, :ga_repo, :conf def config_tmp_dir - @config_tmp_dir ||= File.join(Rails.root, 'tmp',"gitlabhq-gitolite-#{Time.now.to_i}") + @config_tmp_dir ||= Rails.root.join('tmp',"gitlabhq-gitolite-#{Time.now.to_i}") end def ga_repo @@ -19,7 +19,7 @@ module Gitlab def apply Timeout::timeout(30) do - File.open(File.join(Rails.root, 'tmp', "gitlabhq-gitolite.lock"), "w+") do |f| + File.open(Rails.root.join('tmp', "gitlabhq-gitolite.lock"), "w+") do |f| begin # Set exclusive lock # to prevent race condition diff --git a/lib/gitlab/logger.rb b/lib/gitlab/logger.rb index 9405163dced..cf9a4c4afa2 100644 --- a/lib/gitlab/logger.rb +++ b/lib/gitlab/logger.rb @@ -15,7 +15,7 @@ module Gitlab end def self.build - new(File.join(Rails.root, "log", file_name)) + new(Rails.root.join("log", file_name)) end end end diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index 9201003e2e1..9eb35b84d42 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -174,7 +174,7 @@ module Gitlab def reference_commit(identifier) if commit = @project.commit(identifier) - link_to(identifier, project_commit_path(@project, id: commit.id), html_options.merge(title: CommitDecorator.new(commit).link_title, class: "gfm gfm-commit #{html_options[:class]}")) + link_to(identifier, project_commit_path(@project, commit), html_options.merge(title: CommitDecorator.new(commit).link_title, class: "gfm gfm-commit #{html_options[:class]}")) end end end diff --git a/lib/gitlab/merge.rb b/lib/gitlab/merge.rb index 180135745f8..de8e737a8f3 100644 --- a/lib/gitlab/merge.rb +++ b/lib/gitlab/merge.rb @@ -28,7 +28,7 @@ module Gitlab def process Grit::Git.with_timeout(30.seconds) do - lock_file = File.join(Rails.root, "tmp", "merge_repo_#{project.path}.lock") + lock_file = Rails.root.join("tmp", "merge_repo_#{project.path}.lock") File.open(lock_file, "w+") do |f| f.flock(File::LOCK_EX) @@ -36,7 +36,7 @@ module Gitlab unless project.satellite.exists? raise "You should run: rake gitlab:app:enable_automerge" end - + project.satellite.clear Dir.chdir(project.satellite.path) do diff --git a/lib/gitlab/satellite.rb b/lib/gitlab/satellite.rb index 4bcbfe8db88..9d8dfb8e0a4 100644 --- a/lib/gitlab/satellite.rb +++ b/lib/gitlab/satellite.rb @@ -1,6 +1,6 @@ module Gitlab class Satellite - + PARKING_BRANCH = "__parking_branch" attr_accessor :project @@ -14,7 +14,7 @@ module Gitlab end def path - File.join(Rails.root, "tmp", "repo_satellites", project.path) + Rails.root.join("tmp", "repo_satellites", project.path) end def exists? @@ -36,6 +36,6 @@ module Gitlab end end end - + end end diff --git a/spec/controllers/commits_controller_spec.rb b/spec/controllers/commits_controller_spec.rb new file mode 100644 index 00000000000..bf335634da9 --- /dev/null +++ b/spec/controllers/commits_controller_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe CommitsController do + let(:project) { create(:project) } + let(:user) { create(:user) } + + before do + sign_in(user) + + project.add_access(user, :read, :admin) + end + + describe "GET show" do + context "as atom feed" do + it "should render as atom" do + get :show, project_id: project.code, id: "master.atom" + response.should be_success + response.content_type.should == 'application/atom+xml' + end + end + end +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/factories.rb b/spec/factories.rb index 92790a3fdb7..e11e6d07398 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -42,8 +42,8 @@ FactoryGirl.define do factory :project do sequence(:name) { |n| "project#{n}" } - path { name } - code { name } + path { name.downcase.gsub(/\s/, '_') } + code { name.downcase.gsub(/\s/, '_') } owner end diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 9a2df31479c..a94d5505a91 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -1,6 +1,44 @@ require 'spec_helper' describe ApplicationHelper do + describe 'current_controller?' do + before do + controller.stub!(:controller_name).and_return('foo') + end + + it "returns true when controller matches argument" do + current_controller?(:foo).should be_true + end + + it "returns false when controller does not match argument" do + current_controller?(:bar).should_not be_true + end + + it "should take any number of arguments" do + current_controller?(:baz, :bar).should_not be_true + current_controller?(:baz, :bar, :foo).should be_true + end + end + + describe 'current_action?' do + before do + stub!(:action_name).and_return('foo') + end + + it "returns true when action matches argument" do + current_action?(:foo).should be_true + end + + it "returns false when action does not match argument" do + current_action?(:bar).should_not be_true + end + + it "should take any number of arguments" do + current_action?(:baz, :bar).should_not be_true + current_action?(:baz, :bar, :foo).should be_true + end + end + describe "gravatar_icon" do let(:user_email) { 'user@email.com' } diff --git a/spec/helpers/tab_helper_spec.rb b/spec/helpers/tab_helper_spec.rb new file mode 100644 index 00000000000..ef8e4cf6375 --- /dev/null +++ b/spec/helpers/tab_helper_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe TabHelper do + include ApplicationHelper + + describe 'nav_link' do + before do + controller.stub!(:controller_name).and_return('foo') + stub!(:action_name).and_return('foo') + end + + it "captures block output" do + nav_link { "Testing Blocks" }.should match(/Testing Blocks/) + end + + it "performs checks on the current controller" do + nav_link(controller: :foo).should match(/
  • /) + nav_link(controller: :bar).should_not match(/active/) + nav_link(controller: [:foo, :bar]).should match(/active/) + end + + it "performs checks on the current action" do + nav_link(action: :foo).should match(/
  • /) + nav_link(action: :bar).should_not match(/active/) + nav_link(action: [:foo, :bar]).should match(/active/) + end + + it "performs checks on both controller and action when both are present" do + nav_link(controller: :bar, action: :foo).should_not match(/active/) + nav_link(controller: :foo, action: :bar).should_not match(/active/) + nav_link(controller: :foo, action: :foo).should match(/active/) + end + + it "accepts a path shorthand" do + nav_link(path: 'foo#bar').should_not match(/active/) + nav_link(path: 'foo#foo').should match(/active/) + end + + it "passes extra html options to the list element" do + nav_link(action: :foo, html_options: {class: 'home'}).should match(/
  • /) + nav_link(html_options: {class: 'active'}).should match(/
  • /) + end + end +end diff --git a/spec/lib/extracts_path_spec.rb b/spec/lib/extracts_path_spec.rb new file mode 100644 index 00000000000..8876373dffa --- /dev/null +++ b/spec/lib/extracts_path_spec.rb @@ -0,0 +1,58 @@ +require 'spec_helper' + +describe ExtractsPath do + include ExtractsPath + + let(:project) { double('project') } + + before do + @project = project + project.stub(:branches).and_return(['master', 'foo/bar/baz']) + project.stub(:tags).and_return(['v1.0.0', 'v2.0.0']) + end + + describe '#extract_ref' do + it "returns an empty pair when no @project is set" do + @project = nil + extract_ref('master/CHANGELOG').should == ['', ''] + end + + context "without a path" do + it "extracts a valid branch" do + extract_ref('master').should == ['master', ''] + end + + it "extracts a valid tag" do + extract_ref('v2.0.0').should == ['v2.0.0', ''] + end + + it "extracts a valid commit ref without a path" do + extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062').should == + ['f4b14494ef6abf3d144c28e4af0c20143383e062', ''] + end + + it "falls back to a primitive split for an invalid ref" do + extract_ref('stable').should == ['stable', ''] + end + end + + context "with a path" do + it "extracts a valid branch" do + extract_ref('foo/bar/baz/CHANGELOG').should == ['foo/bar/baz', 'CHANGELOG'] + end + + it "extracts a valid tag" do + extract_ref('v2.0.0/CHANGELOG').should == ['v2.0.0', 'CHANGELOG'] + end + + it "extracts a valid commit SHA" do + extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG').should == + ['f4b14494ef6abf3d144c28e4af0c20143383e062', 'CHANGELOG'] + end + + it "falls back to a primitive split for an invalid ref" do + extract_ref('stable/CHANGELOG').should == ['stable', 'CHANGELOG'] + end + end + end +end diff --git a/spec/lib/ref_extractor_spec.rb b/spec/lib/ref_extractor_spec.rb new file mode 100644 index 00000000000..8876373dffa --- /dev/null +++ b/spec/lib/ref_extractor_spec.rb @@ -0,0 +1,58 @@ +require 'spec_helper' + +describe ExtractsPath do + include ExtractsPath + + let(:project) { double('project') } + + before do + @project = project + project.stub(:branches).and_return(['master', 'foo/bar/baz']) + project.stub(:tags).and_return(['v1.0.0', 'v2.0.0']) + end + + describe '#extract_ref' do + it "returns an empty pair when no @project is set" do + @project = nil + extract_ref('master/CHANGELOG').should == ['', ''] + end + + context "without a path" do + it "extracts a valid branch" do + extract_ref('master').should == ['master', ''] + end + + it "extracts a valid tag" do + extract_ref('v2.0.0').should == ['v2.0.0', ''] + end + + it "extracts a valid commit ref without a path" do + extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062').should == + ['f4b14494ef6abf3d144c28e4af0c20143383e062', ''] + end + + it "falls back to a primitive split for an invalid ref" do + extract_ref('stable').should == ['stable', ''] + end + end + + context "with a path" do + it "extracts a valid branch" do + extract_ref('foo/bar/baz/CHANGELOG').should == ['foo/bar/baz', 'CHANGELOG'] + end + + it "extracts a valid tag" do + extract_ref('v2.0.0/CHANGELOG').should == ['v2.0.0', 'CHANGELOG'] + end + + it "extracts a valid commit SHA" do + extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG').should == + ['f4b14494ef6abf3d144c28e4af0c20143383e062', 'CHANGELOG'] + end + + it "falls back to a primitive split for an invalid ref" do + extract_ref('stable/CHANGELOG').should == ['stable', 'CHANGELOG'] + end + end + end +end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index c313b58ecd6..bb975a93dfd 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -125,7 +125,7 @@ describe Project do it "should return path to repo" do project = Project.new(path: "somewhere") - project.path_to_repo.should == File.join(Rails.root, "tmp", "repositories", "somewhere") + project.path_to_repo.should == Rails.root.join("tmp", "repositories", "somewhere") end it "returns the full web URL for this repo" do diff --git a/spec/requests/atom/dashboard_spec.rb b/spec/requests/atom/dashboard_spec.rb index 9459dd01e22..c160d24ac20 100644 --- a/spec/requests/atom/dashboard_spec.rb +++ b/spec/requests/atom/dashboard_spec.rb @@ -10,12 +10,5 @@ describe "Dashboard Feed" do page.body.should have_selector("feed title") end end - - context "projects page via private token" do - it "should redirect to login page" do - visit dashboard_path(private_token: user.private_token) - current_path.should == new_user_session_path - end - end end end diff --git a/spec/requests/gitlab_flavored_markdown_spec.rb b/spec/requests/gitlab_flavored_markdown_spec.rb index 68d354b7bc7..106f6451485 100644 --- a/spec/requests/gitlab_flavored_markdown_spec.rb +++ b/spec/requests/gitlab_flavored_markdown_spec.rb @@ -40,28 +40,27 @@ describe "Gitlab Flavored Markdown" do project.add_access(@user, :read, :write) end - describe "for commits" do it "should render title in commits#index" do - visit project_commits_path(project, ref: @branch_name) + visit project_commits_path(project, @branch_name, limit: 1) page.should have_link("##{issue.id}") end it "should render title in commits#show" do - visit project_commit_path(project, id: commit.id) + visit project_commit_path(project, commit) page.should have_link("##{issue.id}") end it "should render description in commits#show" do - visit project_commit_path(project, id: commit.id) + visit project_commit_path(project, commit) page.should have_link("@#{fred.name}") end it "should render title in refs#tree", js: true do - visit tree_project_ref_path(project, id: @branch_name) + visit project_tree_path(project, @branch_name) within(".tree_commit") do page.should have_link("##{issue.id}") @@ -69,7 +68,7 @@ describe "Gitlab Flavored Markdown" do end it "should render title in refs#blame" do - visit blame_file_project_ref_path(project, id: @branch_name, path: @test_file) + visit project_blame_path(project, File.join(@branch_name, @test_file)) within(".blame_commit") do page.should have_link("##{issue.id}") @@ -89,7 +88,6 @@ describe "Gitlab Flavored Markdown" do end end - describe "for issues" do before do @other_issue = Factory :issue, @@ -175,7 +173,7 @@ describe "Gitlab Flavored Markdown" do describe "for notes" do it "should render in commits#show", js: true do - visit project_commit_path(project, id: commit.id) + visit project_commit_path(project, commit) fill_in "note_note", with: "see ##{issue.id}" click_button "Add Comment" diff --git a/spec/requests/security/project_access_spec.rb b/spec/requests/security/project_access_spec.rb index af0d5fcd3fe..060a276b740 100644 --- a/spec/requests/security/project_access_spec.rb +++ b/spec/requests/security/project_access_spec.rb @@ -14,204 +14,228 @@ describe "Application access" do end describe "Project" do + let(:project) { create(:project) } + + let(:master) { create(:user) } + let(:guest) { create(:user) } + let(:reporter) { create(:user) } + before do - @project = Factory :project - @u1 = Factory :user - @u2 = Factory :user - @u3 = Factory :user # full access - @project.users_projects.create(user: @u1, project_access: UsersProject::MASTER) + project.users_projects.create(user: master, project_access: UsersProject::MASTER) + # readonly - @project.users_projects.create(user: @u3, project_access: UsersProject::REPORTER) + project.users_projects.create(user: reporter, project_access: UsersProject::REPORTER) end describe "GET /project_code" do - subject { project_path(@project) } + subject { project_path(project) } - it { should be_allowed_for @u1 } - it { should be_allowed_for @u3 } + it { should be_allowed_for master } + it { should be_allowed_for reporter } it { should be_denied_for :admin } - it { should be_denied_for @u2 } + it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } end - describe "GET /project_code/master/tree" do - subject { tree_project_ref_path(@project, @project.root_ref) } + describe "GET /project_code/tree/master" do + subject { project_tree_path(project, project.root_ref) } - it { should be_allowed_for @u1 } - it { should be_allowed_for @u3 } + it { should be_allowed_for master } + it { should be_allowed_for reporter } it { should be_denied_for :admin } - it { should be_denied_for @u2 } + it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } end - describe "GET /project_code/commits" do - subject { project_commits_path(@project) } + describe "GET /project_code/commits/master" do + subject { project_commits_path(project, project.root_ref, limit: 1) } - it { should be_allowed_for @u1 } - it { should be_allowed_for @u3 } + it { should be_allowed_for master } + it { should be_allowed_for reporter } it { should be_denied_for :admin } - it { should be_denied_for @u2 } + it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } end - describe "GET /project_code/commit" do - subject { project_commit_path(@project, @project.commit.id) } + describe "GET /project_code/commit/:sha" do + subject { project_commit_path(project, project.commit) } - it { should be_allowed_for @u1 } - it { should be_allowed_for @u3 } + it { should be_allowed_for master } + it { should be_allowed_for reporter } it { should be_denied_for :admin } - it { should be_denied_for @u2 } + it { should be_denied_for guest } + it { should be_denied_for :user } + it { should be_denied_for :visitor } + end + + describe "GET /project_code/compare" do + subject { project_compare_index_path(project) } + + it { should be_allowed_for master } + it { should be_allowed_for reporter } + it { should be_denied_for :admin } + it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } end describe "GET /project_code/team" do - subject { project_team_index_path(@project) } + subject { project_team_index_path(project) } - it { should be_allowed_for @u1 } - it { should be_allowed_for @u3 } + it { should be_allowed_for master } + it { should be_allowed_for reporter } it { should be_denied_for :admin } - it { should be_denied_for @u2 } + it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } end describe "GET /project_code/wall" do - subject { wall_project_path(@project) } + subject { wall_project_path(project) } - it { should be_allowed_for @u1 } - it { should be_allowed_for @u3 } + it { should be_allowed_for master } + it { should be_allowed_for reporter } it { should be_denied_for :admin } - it { should be_denied_for @u2 } + it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } end describe "GET /project_code/blob" do before do - commit = @project.commit + commit = project.commit path = commit.tree.contents.select { |i| i.is_a?(Grit::Blob)}.first.name - @blob_path = blob_project_ref_path(@project, commit.id, path: path) + @blob_path = project_blob_path(project, File.join(commit.id, path)) end - it { @blob_path.should be_allowed_for @u1 } - it { @blob_path.should be_allowed_for @u3 } + it { @blob_path.should be_allowed_for master } + it { @blob_path.should be_allowed_for reporter } it { @blob_path.should be_denied_for :admin } - it { @blob_path.should be_denied_for @u2 } + it { @blob_path.should be_denied_for guest } it { @blob_path.should be_denied_for :user } it { @blob_path.should be_denied_for :visitor } end describe "GET /project_code/edit" do - subject { edit_project_path(@project) } + subject { edit_project_path(project) } - it { should be_allowed_for @u1 } - it { should be_denied_for @u3 } + it { should be_allowed_for master } + it { should be_denied_for reporter } it { should be_denied_for :admin } - it { should be_denied_for @u2 } + it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } end describe "GET /project_code/deploy_keys" do - subject { project_deploy_keys_path(@project) } + subject { project_deploy_keys_path(project) } - it { should be_allowed_for @u1 } - it { should be_denied_for @u3 } + it { should be_allowed_for master } + it { should be_denied_for reporter } it { should be_denied_for :admin } - it { should be_denied_for @u2 } + it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } end describe "GET /project_code/issues" do - subject { project_issues_path(@project) } + subject { project_issues_path(project) } - it { should be_allowed_for @u1 } - it { should be_allowed_for @u3 } + it { should be_allowed_for master } + it { should be_allowed_for reporter } it { should be_denied_for :admin } - it { should be_denied_for @u2 } + it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } end describe "GET /project_code/snippets" do - subject { project_snippets_path(@project) } + subject { project_snippets_path(project) } - it { should be_allowed_for @u1 } - it { should be_allowed_for @u3 } + it { should be_allowed_for master } + it { should be_allowed_for reporter } it { should be_denied_for :admin } - it { should be_denied_for @u2 } + it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } end describe "GET /project_code/merge_requests" do - subject { project_merge_requests_path(@project) } + subject { project_merge_requests_path(project) } - it { should be_allowed_for @u1 } - it { should be_allowed_for @u3 } + it { should be_allowed_for master } + it { should be_allowed_for reporter } it { should be_denied_for :admin } - it { should be_denied_for @u2 } + it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } end describe "GET /project_code/repository" do - subject { project_repository_path(@project) } + subject { project_repository_path(project) } - it { should be_allowed_for @u1 } - it { should be_allowed_for @u3 } + it { should be_allowed_for master } + it { should be_allowed_for reporter } it { should be_denied_for :admin } - it { should be_denied_for @u2 } + it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } end describe "GET /project_code/repository/branches" do - subject { branches_project_repository_path(@project) } + subject { branches_project_repository_path(project) } - it { should be_allowed_for @u1 } - it { should be_allowed_for @u3 } + before do + # Speed increase + Project.any_instance.stub(:branches).and_return([]) + end + + it { should be_allowed_for master } + it { should be_allowed_for reporter } it { should be_denied_for :admin } - it { should be_denied_for @u2 } + it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } end describe "GET /project_code/repository/tags" do - subject { tags_project_repository_path(@project) } + subject { tags_project_repository_path(project) } - it { should be_allowed_for @u1 } - it { should be_allowed_for @u3 } + before do + # Speed increase + Project.any_instance.stub(:tags).and_return([]) + end + + it { should be_allowed_for master } + it { should be_allowed_for reporter } it { should be_denied_for :admin } - it { should be_denied_for @u2 } + it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } end describe "GET /project_code/hooks" do - subject { project_hooks_path(@project) } + subject { project_hooks_path(project) } - it { should be_allowed_for @u1 } - it { should be_allowed_for @u3 } + it { should be_allowed_for master } + it { should be_allowed_for reporter } it { should be_denied_for :admin } - it { should be_denied_for @u2 } + it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } end describe "GET /project_code/files" do - subject { files_project_path(@project) } + subject { files_project_path(project) } - it { should be_allowed_for @u1 } - it { should be_allowed_for @u3 } + it { should be_allowed_for master } + it { should be_allowed_for reporter } it { should be_denied_for :admin } - it { should be_denied_for @u2 } + it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } end diff --git a/spec/roles/repository_spec.rb b/spec/roles/repository_spec.rb index 0fda57a3e27..3507585aa8d 100644 --- a/spec/roles/repository_spec.rb +++ b/spec/roles/repository_spec.rb @@ -21,27 +21,27 @@ describe Project, "Repository" do end describe "#discover_default_branch" do - let(:master) { double(name: 'master') } - let(:stable) { double(name: 'stable') } + let(:master) { 'master' } + let(:stable) { 'stable' } it "returns 'master' when master exists" do - project.should_receive(:heads).and_return([stable, master]) + project.should_receive(:branch_names).at_least(:once).and_return([stable, master]) project.discover_default_branch.should == 'master' end it "returns non-master when master exists but default branch is set to something else" do project.default_branch = 'stable' - project.should_receive(:heads).and_return([stable, master]) + project.should_receive(:branch_names).at_least(:once).and_return([stable, master]) project.discover_default_branch.should == 'stable' end it "returns a non-master branch when only one exists" do - project.should_receive(:heads).and_return([stable]) + project.should_receive(:branch_names).at_least(:once).and_return([stable]) project.discover_default_branch.should == 'stable' end it "returns nil when no branch exists" do - project.should_receive(:heads).and_return([]) + project.should_receive(:branch_names).at_least(:once).and_return([]) project.discover_default_branch.should be_nil end end diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb index b3f9db01ab3..dc687d2a7ac 100644 --- a/spec/routing/project_routing_spec.rb +++ b/spec/routing/project_routing_spec.rb @@ -192,34 +192,17 @@ describe ProtectedBranchesController, "routing" do end # switch_project_refs GET /:project_id/switch(.:format) refs#switch -# tree_project_ref GET /:project_id/:id/tree(.:format) refs#tree # logs_tree_project_ref GET /:project_id/:id/logs_tree(.:format) refs#logs_tree -# blob_project_ref GET /:project_id/:id/blob(.:format) refs#blob -# tree_file_project_ref GET /:project_id/:id/tree/:path(.:format) refs#tree # logs_file_project_ref GET /:project_id/:id/logs_tree/:path(.:format) refs#logs_tree -# blame_file_project_ref GET /:project_id/:id/blame/:path(.:format) refs#blame describe RefsController, "routing" do it "to #switch" do get("/gitlabhq/switch").should route_to('refs#switch', project_id: 'gitlabhq') end - it "to #tree" do - get("/gitlabhq/stable/tree").should route_to('refs#tree', project_id: 'gitlabhq', id: 'stable') - get("/gitlabhq/stable/tree/foo/bar/baz").should route_to('refs#tree', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz') - end - it "to #logs_tree" do get("/gitlabhq/stable/logs_tree").should route_to('refs#logs_tree', project_id: 'gitlabhq', id: 'stable') get("/gitlabhq/stable/logs_tree/foo/bar/baz").should route_to('refs#logs_tree', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz') end - - it "to #blob" do - get("/gitlabhq/stable/blob").should route_to('refs#blob', project_id: 'gitlabhq', id: 'stable') - end - - it "to #blame" do - get("/gitlabhq/stable/blame/foo/bar/baz").should route_to('refs#blame', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz') - end end # diffs_project_merge_request GET /:project_id/merge_requests/:id/diffs(.:format) merge_requests#diffs @@ -298,25 +281,22 @@ describe HooksController, "routing" do end end -# compare_project_commits GET /:project_id/commits/compare(.:format) commits#compare +# project_commit GET /:project_id/commit/:id(.:format) commit#show {:id=>/[[:alnum:]]{6,40}/, :project_id=>/[^\/]+/} +describe CommitController, "routing" do + it "to #show" do + get("/gitlabhq/commit/4246fb").should route_to('commit#show', project_id: 'gitlabhq', id: '4246fb') + get("/gitlabhq/commit/4246fb.patch").should route_to('commit#show', project_id: 'gitlabhq', id: '4246fb', format: 'patch') + get("/gitlabhq/commit/4246fbd13872934f72a8fd0d6fb1317b47b59cb5").should route_to('commit#show', project_id: 'gitlabhq', id: '4246fbd13872934f72a8fd0d6fb1317b47b59cb5') + end +end + # patch_project_commit GET /:project_id/commits/:id/patch(.:format) commits#patch # project_commits GET /:project_id/commits(.:format) commits#index # POST /:project_id/commits(.:format) commits#create -# new_project_commit GET /:project_id/commits/new(.:format) commits#new -# edit_project_commit GET /:project_id/commits/:id/edit(.:format) commits#edit # project_commit GET /:project_id/commits/:id(.:format) commits#show -# PUT /:project_id/commits/:id(.:format) commits#update -# DELETE /:project_id/commits/:id(.:format) commits#destroy describe CommitsController, "routing" do - it "to #compare" do - get("/gitlabhq/commits/compare").should route_to('commits#compare', project_id: 'gitlabhq') - end - - it "to #patch" do - get("/gitlabhq/commits/1/patch").should route_to('commits#patch', project_id: 'gitlabhq', id: '1') - end - it_behaves_like "RESTful project resources" do + let(:actions) { [:show] } let(:controller) { 'commits' } end end @@ -396,3 +376,42 @@ describe NotesController, "routing" do let(:controller) { 'notes' } end end + +# project_blame GET /:project_id/blame/:id(.:format) blame#show {:id=>/.+/, :project_id=>/[^\/]+/} +describe BlameController, "routing" do + it "to #show" do + get("/gitlabhq/blame/master/app/models/project.rb").should route_to('blame#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb') + end +end + +# project_blob GET /:project_id/blob/:id(.:format) blob#show {:id=>/.+/, :project_id=>/[^\/]+/} +describe BlobController, "routing" do + it "to #show" do + get("/gitlabhq/blob/master/app/models/project.rb").should route_to('blob#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb') + end +end + +# project_tree GET /:project_id/tree/:id(.:format) tree#show {:id=>/.+/, :project_id=>/[^\/]+/} +describe TreeController, "routing" do + it "to #show" do + get("/gitlabhq/tree/master/app/models/project.rb").should route_to('tree#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb') + end +end + +# project_compare_index GET /:project_id/compare(.:format) compare#index {:id=>/[^\/]+/, :project_id=>/[^\/]+/} +# POST /:project_id/compare(.:format) compare#create {:id=>/[^\/]+/, :project_id=>/[^\/]+/} +# project_compare /:project_id/compare/:from...:to(.:format) compare#show {:from=>/.+/, :to=>/.+/, :id=>/[^\/]+/, :project_id=>/[^\/]+/} +describe CompareController, "routing" do + it "to #index" do + get("/gitlabhq/compare").should route_to('compare#index', project_id: 'gitlabhq') + end + + it "to #compare" do + post("/gitlabhq/compare").should route_to('compare#create', project_id: 'gitlabhq') + end + + it "to #show" do + get("/gitlabhq/compare/master...stable").should route_to('compare#show', project_id: 'gitlabhq', from: 'master', to: 'stable') + get("/gitlabhq/compare/issue/1234...stable").should route_to('compare#show', project_id: 'gitlabhq', from: 'issue/1234', to: 'stable') + 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 diff --git a/spec/support/stubbed_repository.rb b/spec/support/stubbed_repository.rb index 90491e430b4..5bf3ea46099 100644 --- a/spec/support/stubbed_repository.rb +++ b/spec/support/stubbed_repository.rb @@ -5,11 +5,11 @@ module StubbedRepository if new_record? || path == 'newproject' # There are a couple Project specs and features that expect the Project's # path to be in the returned path, so let's patronize them. - File.join(Rails.root, 'tmp', 'repositories', path) + Rails.root.join('tmp', 'repositories', path) else # For everything else, just give it the path to one of our real seeded # repos. - File.join(Rails.root, 'tmp', 'repositories', 'gitlabhq') + Rails.root.join('tmp', 'repositories', 'gitlabhq') end end