diff --git a/app/assets/stylesheets/gitlab_bootstrap.scss b/app/assets/stylesheets/gitlab_bootstrap.scss index ea23c906973..b520c3bccf5 100644 --- a/app/assets/stylesheets/gitlab_bootstrap.scss +++ b/app/assets/stylesheets/gitlab_bootstrap.scss @@ -268,6 +268,13 @@ img.avatar { -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; + + &.s16 { + width:16px; + } + &.s24 { + width:24px; + } } img.lil_av { diff --git a/app/assets/stylesheets/tree.scss b/app/assets/stylesheets/tree.scss index a5a7f8bc21e..d3146f6a476 100644 --- a/app/assets/stylesheets/tree.scss +++ b/app/assets/stylesheets/tree.scss @@ -53,6 +53,11 @@ padding: 9px 10px; height:18px; + .options { + float:right; + margin-top: -5px; + } + .file_name { color:$style_color; font-size:14px; @@ -220,3 +225,27 @@ margin:0; } } + +.blame_file { + .view_file_content { + tr { + border-bottom: 1px solid #eee; + } + td { + padding:5px; + } + .author, + .commit { + background:#f5f5f5; + vertical-align:top; + } + .lines { + pre { + padding:0; + margin:0; + background:none; + border:none; + } + } + } +} diff --git a/app/controllers/refs_controller.rb b/app/controllers/refs_controller.rb index b8ab1bce219..e4e5b4edd42 100644 --- a/app/controllers/refs_controller.rb +++ b/app/controllers/refs_controller.rb @@ -8,7 +8,7 @@ class RefsController < ApplicationController before_filter :require_non_empty_project before_filter :ref - before_filter :define_tree_vars, :only => [:tree, :blob] + before_filter :define_tree_vars, :only => [:tree, :blob, :blame] before_filter :render_full_content layout "project" @@ -62,6 +62,10 @@ class RefsController < ApplicationController return render_404 end + def blame + @blame = Grit::Blob.blame(@repo, @commit.id, params[:path]) + end + protected def define_tree_vars diff --git a/app/views/refs/_head.html.haml b/app/views/refs/_head.html.haml new file mode 100644 index 00000000000..d76a4aca026 --- /dev/null +++ b/app/views/refs/_head.html.haml @@ -0,0 +1,10 @@ +%ul.nav.nav-tabs + %li + = form_tag switch_project_refs_path(@project), :method => :get, :class => "project-refs-form", :remote => true do + = select_tag "ref", grouped_options_refs, :onchange => "$(this.form).trigger('submit');", :class => "project-refs-select" + = hidden_field_tag :destination, "tree" + = hidden_field_tag :path, params[:path] + %li{:class => "#{'active' if (controller.controller_name == "refs") }"} + = link_to tree_project_ref_path(@project, @ref) do + Code + diff --git a/app/views/refs/_tree_file.html.haml b/app/views/refs/_tree_file.html.haml index c0a11e72113..768ff5a0446 100644 --- a/app/views/refs/_tree_file.html.haml +++ b/app/views/refs/_tree_file.html.haml @@ -1,13 +1,13 @@ -:css .view_file .view_file_header %i.icon-file %span.file_name = name %small #{file.mode} - %span.right - = link_to "raw", blob_project_ref_path(@project, @ref, :path => params[:path]), :class => "right", :target => "_blank" - = link_to "history", project_commits_path(@project, :path => params[:path], :ref => @ref), :class => "right", :style => "margin-right:10px;" + %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" - if file.text? - if name =~ /\.(md|markdown)$/i #tree-readme-holder diff --git a/app/views/refs/blame.html.haml b/app/views/refs/blame.html.haml new file mode 100644 index 00000000000..7307d557a30 --- /dev/null +++ b/app/views/refs/blame.html.haml @@ -0,0 +1,46 @@ += render "head" + +#tree-holder + %ul.breadcrumb + %li + %span.arrow + = link_to tree_project_ref_path(@project, @ref, :path => nil) do + = @project.name + - @tree.breadcrumbs(6) do |link| + \/ + %li= link + .clear + + .view_file.blame_file + .view_file_header + %i.icon-file + %span.file_name + = @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" + .view_file_content + %table + - @blame.each do |commit, lines| + - commit = Commit.new(commit) + %tr + %td.author + = image_tag gravatar_icon(commit.author_email, 16) + = commit.author_name + %td.commit +   + = link_to project_commit_path(@project, :id => commit.id) do + %code= commit.id.to_s[0..10] + %span.row_title= truncate(commit.safe_message, :length => 30) rescue "--broken encoding" + %td.lines + = preserve do + %pre + - lines.each do |line| + = line + +:javascript + $(function(){ + $('.project-refs-select').chosen(); + }); diff --git a/app/views/refs/tree.html.haml b/app/views/refs/tree.html.haml index 165d7788fa5..7d19280b820 100644 --- a/app/views/refs/tree.html.haml +++ b/app/views/refs/tree.html.haml @@ -1,13 +1,4 @@ -%ul.nav.nav-tabs - %li - = form_tag switch_project_refs_path(@project), :method => :get, :class => "project-refs-form", :remote => true do - = select_tag "ref", grouped_options_refs, :onchange => "$(this.form).trigger('submit');", :class => "project-refs-select" - = hidden_field_tag :destination, "tree" - = hidden_field_tag :path, params[:path] - %li{:class => "#{'active' if (controller.controller_name == "refs") }"} - = link_to tree_project_ref_path(@project, @ref) do - Code - += render "head" #tree-holder= render :partial => "tree", :locals => {:repo => @repo, :commit => @commit, :tree => @tree} :javascript diff --git a/config/routes.rb b/config/routes.rb index 1b8f6d3c077..e137ff717e1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -94,6 +94,14 @@ Gitlab::Application.routes.draw do :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 diff --git a/spec/requests/file_blame_spec.rb b/spec/requests/file_blame_spec.rb new file mode 100644 index 00000000000..511f340c1c8 --- /dev/null +++ b/spec/requests/file_blame_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe "Blame file" do + before { login_as :user } + + describe "GET /:projectname/:commit/blob/Gemfile" do + before do + @project = Factory :project + @project.add_access(@user, :read) + + visit tree_project_ref_path(@project, @project.root_ref, :path => "Gemfile") + click_link "blame" + end + + it "should be correct path" do + current_path.should == blame_file_project_ref_path(@project, @project.root_ref, :path => "Gemfile") + end + + it "should contain file view" do + page.should have_content("rubygems.org") + page.should have_content("Dmitriy Zaporozhets") + page.should have_content("bc3735004cb Moving to rails 3.2") + end + end +end