Commit e563e948bb907a26c4a170eaec0f3976fdf11d74
Exists in
master
and in
4 other branches
Merge branch 'master' into simplify_controllers2
Conflicts: app/controllers/commits_controller.rb app/controllers/refs_controller.rb
Showing
119 changed files
with
1992 additions
and
882 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 119 files displayed.
Gemfile
@@ -57,7 +57,7 @@ gem "seed-fu" | @@ -57,7 +57,7 @@ gem "seed-fu" | ||
57 | 57 | ||
58 | # Markdown to HTML | 58 | # Markdown to HTML |
59 | gem "redcarpet", "~> 2.1.1" | 59 | gem "redcarpet", "~> 2.1.1" |
60 | -gem "github-markup", "~> 0.7.4" | 60 | +gem "github-markup", "~> 0.7.4", require: 'github/markup' |
61 | 61 | ||
62 | # Servers | 62 | # Servers |
63 | gem "thin" | 63 | gem "thin" |
app/assets/stylesheets/gitlab_bootstrap/files.scss
@@ -68,10 +68,22 @@ | @@ -68,10 +68,22 @@ | ||
68 | * Blame file | 68 | * Blame file |
69 | */ | 69 | */ |
70 | &.blame { | 70 | &.blame { |
71 | + table { | ||
72 | + border:none; | ||
73 | + box-shadow:none; | ||
74 | + margin:0; | ||
75 | + } | ||
71 | tr { | 76 | tr { |
72 | border-bottom: 1px solid #eee; | 77 | border-bottom: 1px solid #eee; |
73 | } | 78 | } |
74 | td { | 79 | td { |
80 | + &:first-child { | ||
81 | + border-left:none; | ||
82 | + } | ||
83 | + &:last-child { | ||
84 | + border-right:none; | ||
85 | + } | ||
86 | + background:#fff; | ||
75 | padding:5px; | 87 | padding:5px; |
76 | } | 88 | } |
77 | .author, | 89 | .author, |
app/assets/stylesheets/sections/nav.scss
@@ -53,7 +53,7 @@ ul.main_menu { | @@ -53,7 +53,7 @@ ul.main_menu { | ||
53 | border-left: 0; | 53 | border-left: 0; |
54 | } | 54 | } |
55 | 55 | ||
56 | - &.current { | 56 | + &.active { |
57 | background-color:#D5D5D5; | 57 | background-color:#D5D5D5; |
58 | border-right: 1px solid #BBB; | 58 | border-right: 1px solid #BBB; |
59 | border-left: 1px solid #BBB; | 59 | border-left: 1px solid #BBB; |
app/controllers/application_controller.rb
@@ -2,7 +2,6 @@ class ApplicationController < ActionController::Base | @@ -2,7 +2,6 @@ class ApplicationController < ActionController::Base | ||
2 | before_filter :authenticate_user! | 2 | before_filter :authenticate_user! |
3 | before_filter :reject_blocked! | 3 | before_filter :reject_blocked! |
4 | before_filter :set_current_user_for_mailer | 4 | before_filter :set_current_user_for_mailer |
5 | - before_filter :check_token_auth | ||
6 | before_filter :set_current_user_for_observers | 5 | before_filter :set_current_user_for_observers |
7 | before_filter :dev_tools if Rails.env == 'development' | 6 | before_filter :dev_tools if Rails.env == 'development' |
8 | 7 | ||
@@ -24,13 +23,6 @@ class ApplicationController < ActionController::Base | @@ -24,13 +23,6 @@ class ApplicationController < ActionController::Base | ||
24 | 23 | ||
25 | protected | 24 | protected |
26 | 25 | ||
27 | - def check_token_auth | ||
28 | - # Redirect to login page if not atom feed | ||
29 | - if params[:private_token].present? && params[:format] != 'atom' | ||
30 | - redirect_to new_user_session_path | ||
31 | - end | ||
32 | - end | ||
33 | - | ||
34 | def reject_blocked! | 26 | def reject_blocked! |
35 | if current_user && current_user.blocked | 27 | if current_user && current_user.blocked |
36 | sign_out current_user | 28 | sign_out current_user |
@@ -103,7 +95,7 @@ class ApplicationController < ActionController::Base | @@ -103,7 +95,7 @@ class ApplicationController < ActionController::Base | ||
103 | end | 95 | end |
104 | 96 | ||
105 | def render_404 | 97 | def render_404 |
106 | - render file: File.join(Rails.root, "public", "404"), layout: false, status: "404" | 98 | + render file: Rails.root.join("public", "404"), layout: false, status: "404" |
107 | end | 99 | end |
108 | 100 | ||
109 | def require_non_empty_project | 101 | def require_non_empty_project |
@@ -116,10 +108,6 @@ class ApplicationController < ActionController::Base | @@ -116,10 +108,6 @@ class ApplicationController < ActionController::Base | ||
116 | response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT" | 108 | response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT" |
117 | end | 109 | end |
118 | 110 | ||
119 | - def render_full_content | ||
120 | - @full_content = true | ||
121 | - end | ||
122 | - | ||
123 | def dev_tools | 111 | def dev_tools |
124 | Rack::MiniProfiler.authorize_request | 112 | Rack::MiniProfiler.authorize_request |
125 | end | 113 | end |
@@ -0,0 +1,21 @@ | @@ -0,0 +1,21 @@ | ||
1 | +# Controller for viewing a file's blame | ||
2 | +class BlameController < ApplicationController | ||
3 | + include ExtractsPath | ||
4 | + | ||
5 | + layout "project" | ||
6 | + | ||
7 | + before_filter :project | ||
8 | + | ||
9 | + # Authorize | ||
10 | + before_filter :add_project_abilities | ||
11 | + before_filter :authorize_read_project! | ||
12 | + before_filter :authorize_code_access! | ||
13 | + before_filter :require_non_empty_project | ||
14 | + | ||
15 | + before_filter :assign_ref_vars | ||
16 | + | ||
17 | + def show | ||
18 | + @repo = @project.repo | ||
19 | + @blame = Grit::Blob.blame(@repo, @commit.id, @path) | ||
20 | + end | ||
21 | +end |
@@ -0,0 +1,37 @@ | @@ -0,0 +1,37 @@ | ||
1 | +# Controller for viewing a file's blame | ||
2 | +class BlobController < ApplicationController | ||
3 | + include ExtractsPath | ||
4 | + include Gitlab::Encode | ||
5 | + | ||
6 | + layout "project" | ||
7 | + | ||
8 | + before_filter :project | ||
9 | + | ||
10 | + # Authorize | ||
11 | + before_filter :add_project_abilities | ||
12 | + before_filter :authorize_read_project! | ||
13 | + before_filter :authorize_code_access! | ||
14 | + before_filter :require_non_empty_project | ||
15 | + | ||
16 | + before_filter :assign_ref_vars | ||
17 | + | ||
18 | + def show | ||
19 | + if @tree.is_blob? | ||
20 | + if @tree.text? | ||
21 | + encoding = detect_encoding(@tree.data) | ||
22 | + mime_type = encoding ? "text/plain; charset=#{encoding}" : "text/plain" | ||
23 | + else | ||
24 | + mime_type = @tree.mime_type | ||
25 | + end | ||
26 | + | ||
27 | + send_data( | ||
28 | + @tree.data, | ||
29 | + type: mime_type, | ||
30 | + disposition: 'inline', | ||
31 | + filename: @tree.name | ||
32 | + ) | ||
33 | + else | ||
34 | + not_found! | ||
35 | + end | ||
36 | + end | ||
37 | +end |
@@ -0,0 +1,36 @@ | @@ -0,0 +1,36 @@ | ||
1 | +# Controller for a specific Commit | ||
2 | +# | ||
3 | +# Not to be confused with CommitsController, plural. | ||
4 | +class CommitController < ApplicationController | ||
5 | + before_filter :project | ||
6 | + layout "project" | ||
7 | + | ||
8 | + # Authorize | ||
9 | + before_filter :add_project_abilities | ||
10 | + before_filter :authorize_read_project! | ||
11 | + before_filter :authorize_code_access! | ||
12 | + before_filter :require_non_empty_project | ||
13 | + | ||
14 | + def show | ||
15 | + result = CommitLoad.new(project, current_user, params).execute | ||
16 | + | ||
17 | + @commit = result[:commit] | ||
18 | + git_not_found! unless @commit | ||
19 | + | ||
20 | + @suppress_diff = result[:suppress_diff] | ||
21 | + @note = result[:note] | ||
22 | + @line_notes = result[:line_notes] | ||
23 | + @notes_count = result[:notes_count] | ||
24 | + @comments_allowed = true | ||
25 | + | ||
26 | + respond_to do |format| | ||
27 | + format.html do | ||
28 | + if result[:status] == :huge_commit | ||
29 | + render "huge_commit" and return | ||
30 | + end | ||
31 | + end | ||
32 | + | ||
33 | + format.patch | ||
34 | + end | ||
35 | + end | ||
36 | +end |
app/controllers/commits_controller.rb
1 | require "base64" | 1 | require "base64" |
2 | 2 | ||
3 | class CommitsController < ProjectController | 3 | class CommitsController < ProjectController |
4 | + include ExtractsPath | ||
5 | + | ||
4 | # Authorize | 6 | # Authorize |
5 | before_filter :authorize_read_project! | 7 | before_filter :authorize_read_project! |
6 | before_filter :authorize_code_access! | 8 | before_filter :authorize_code_access! |
7 | before_filter :require_non_empty_project | 9 | before_filter :require_non_empty_project |
8 | - before_filter :load_refs, only: :index # load @branch, @tag & @ref | ||
9 | - before_filter :render_full_content | ||
10 | 10 | ||
11 | - def index | ||
12 | - @repo = project.repo | 11 | + def show |
12 | + @repo = @project.repo | ||
13 | @limit, @offset = (params[:limit] || 40), (params[:offset] || 0) | 13 | @limit, @offset = (params[:limit] || 40), (params[:offset] || 0) |
14 | 14 | ||
15 | - @commits = @project.commits(@ref, params[:path], @limit, @offset) | 15 | + @commits = @project.commits(@ref, @path, @limit, @offset) |
16 | @commits = CommitDecorator.decorate(@commits) | 16 | @commits = CommitDecorator.decorate(@commits) |
17 | 17 | ||
18 | respond_to do |format| | 18 | respond_to do |format| |
@@ -21,54 +21,4 @@ class CommitsController < ProjectController | @@ -21,54 +21,4 @@ class CommitsController < ProjectController | ||
21 | format.atom { render layout: false } | 21 | format.atom { render layout: false } |
22 | end | 22 | end |
23 | end | 23 | end |
24 | - | ||
25 | - def show | ||
26 | - result = CommitLoad.new(project, current_user, params).execute | ||
27 | - | ||
28 | - @commit = result[:commit] | ||
29 | - | ||
30 | - if @commit | ||
31 | - @suppress_diff = result[:suppress_diff] | ||
32 | - @note = result[:note] | ||
33 | - @line_notes = result[:line_notes] | ||
34 | - @notes_count = result[:notes_count] | ||
35 | - @comments_allowed = true | ||
36 | - else | ||
37 | - return git_not_found! | ||
38 | - end | ||
39 | - | ||
40 | - if result[:status] == :huge_commit | ||
41 | - render "huge_commit" and return | ||
42 | - end | ||
43 | - end | ||
44 | - | ||
45 | - def compare | ||
46 | - result = Commit.compare(project, params[:from], params[:to]) | ||
47 | - | ||
48 | - @commits = result[:commits] | ||
49 | - @commit = result[:commit] | ||
50 | - @diffs = result[:diffs] | ||
51 | - @refs_are_same = result[:same] | ||
52 | - @line_notes = [] | ||
53 | - | ||
54 | - @commits = CommitDecorator.decorate(@commits) | ||
55 | - end | ||
56 | - | ||
57 | - def patch | ||
58 | - @commit = project.commit(params[:id]) | ||
59 | - | ||
60 | - send_data( | ||
61 | - @commit.to_patch, | ||
62 | - type: "text/plain", | ||
63 | - disposition: 'attachment', | ||
64 | - filename: "#{@commit.id}.patch" | ||
65 | - ) | ||
66 | - end | ||
67 | - | ||
68 | - protected | ||
69 | - | ||
70 | - def load_refs | ||
71 | - @ref ||= params[:ref].presence || params[:branch].presence || params[:tag].presence | ||
72 | - @ref ||= @ref || @project.try(:default_branch) || 'master' | ||
73 | - end | ||
74 | end | 24 | end |
@@ -0,0 +1,29 @@ | @@ -0,0 +1,29 @@ | ||
1 | +class CompareController < ApplicationController | ||
2 | + before_filter :project | ||
3 | + layout "project" | ||
4 | + | ||
5 | + # Authorize | ||
6 | + before_filter :add_project_abilities | ||
7 | + before_filter :authorize_read_project! | ||
8 | + before_filter :authorize_code_access! | ||
9 | + before_filter :require_non_empty_project | ||
10 | + | ||
11 | + def index | ||
12 | + end | ||
13 | + | ||
14 | + def show | ||
15 | + result = Commit.compare(project, params[:from], params[:to]) | ||
16 | + | ||
17 | + @commits = result[:commits] | ||
18 | + @commit = result[:commit] | ||
19 | + @diffs = result[:diffs] | ||
20 | + @refs_are_same = result[:same] | ||
21 | + @line_notes = [] | ||
22 | + | ||
23 | + @commits = CommitDecorator.decorate(@commits) | ||
24 | + end | ||
25 | + | ||
26 | + def create | ||
27 | + redirect_to project_compare_path(@project, params[:from], params[:to]) | ||
28 | + end | ||
29 | +end |
app/controllers/protected_branches_controller.rb
@@ -4,7 +4,6 @@ class ProtectedBranchesController < ProjectController | @@ -4,7 +4,6 @@ class ProtectedBranchesController < ProjectController | ||
4 | before_filter :require_non_empty_project | 4 | before_filter :require_non_empty_project |
5 | 5 | ||
6 | before_filter :authorize_admin_project!, only: [:destroy, :create] | 6 | before_filter :authorize_admin_project!, only: [:destroy, :create] |
7 | - before_filter :render_full_content | ||
8 | 7 | ||
9 | def index | 8 | def index |
10 | @branches = @project.protected_branches.all | 9 | @branches = @project.protected_branches.all |
app/controllers/refs_controller.rb
1 | -require 'github/markup' | ||
2 | - | ||
3 | class RefsController < ProjectController | 1 | class RefsController < ProjectController |
4 | include Gitlab::Encode | 2 | include Gitlab::Encode |
5 | 3 | ||
@@ -9,21 +7,20 @@ class RefsController < ProjectController | @@ -9,21 +7,20 @@ class RefsController < ProjectController | ||
9 | before_filter :require_non_empty_project | 7 | before_filter :require_non_empty_project |
10 | 8 | ||
11 | before_filter :ref | 9 | before_filter :ref |
12 | - before_filter :define_tree_vars, only: [:tree, :blob, :blame, :logs_tree] | ||
13 | - before_filter :render_full_content | 10 | + before_filter :define_tree_vars, only: [:blob, :logs_tree] |
14 | 11 | ||
15 | def switch | 12 | def switch |
16 | respond_to do |format| | 13 | respond_to do |format| |
17 | format.html do | 14 | format.html do |
18 | new_path = if params[:destination] == "tree" | 15 | new_path = if params[:destination] == "tree" |
19 | - tree_project_ref_path(@project, params[:ref]) | 16 | + project_tree_path(@project, @ref) |
20 | else | 17 | else |
21 | - project_commits_path(@project, ref: params[:ref]) | 18 | + project_commits_path(@project, @ref) |
22 | end | 19 | end |
23 | 20 | ||
24 | - redirect_to new_path | 21 | + redirect_to new_path |
25 | end | 22 | end |
26 | - format.js do | 23 | + format.js do |
27 | @ref = params[:ref] | 24 | @ref = params[:ref] |
28 | define_tree_vars | 25 | define_tree_vars |
29 | render "tree" | 26 | render "tree" |
@@ -31,19 +28,6 @@ class RefsController < ProjectController | @@ -31,19 +28,6 @@ class RefsController < ProjectController | ||
31 | end | 28 | end |
32 | end | 29 | end |
33 | 30 | ||
34 | - # | ||
35 | - # Repository preview | ||
36 | - # | ||
37 | - def tree | ||
38 | - respond_to do |format| | ||
39 | - format.html | ||
40 | - format.js do | ||
41 | - # disable cache to allow back button works | ||
42 | - no_cache_headers | ||
43 | - end | ||
44 | - end | ||
45 | - end | ||
46 | - | ||
47 | def logs_tree | 31 | def logs_tree |
48 | contents = @tree.contents | 32 | contents = @tree.contents |
49 | @logs = contents.map do |content| | 33 | @logs = contents.map do |content| |
@@ -51,36 +35,12 @@ class RefsController < ProjectController | @@ -51,36 +35,12 @@ class RefsController < ProjectController | ||
51 | last_commit = @project.commits(@commit.id, file, 1).last | 35 | last_commit = @project.commits(@commit.id, file, 1).last |
52 | last_commit = CommitDecorator.decorate(last_commit) | 36 | last_commit = CommitDecorator.decorate(last_commit) |
53 | { | 37 | { |
54 | - file_name: content.name, | 38 | + file_name: content.name, |
55 | commit: last_commit | 39 | commit: last_commit |
56 | } | 40 | } |
57 | end | 41 | end |
58 | end | 42 | end |
59 | 43 | ||
60 | - def blob | ||
61 | - if @tree.is_blob? | ||
62 | - if @tree.text? | ||
63 | - encoding = detect_encoding(@tree.data) | ||
64 | - mime_type = encoding ? "text/plain; charset=#{encoding}" : "text/plain" | ||
65 | - else | ||
66 | - mime_type = @tree.mime_type | ||
67 | - end | ||
68 | - | ||
69 | - send_data( | ||
70 | - @tree.data, | ||
71 | - type: mime_type, | ||
72 | - disposition: 'inline', | ||
73 | - filename: @tree.name | ||
74 | - ) | ||
75 | - else | ||
76 | - head(404) | ||
77 | - end | ||
78 | - end | ||
79 | - | ||
80 | - def blame | ||
81 | - @blame = Grit::Blob.blame(@repo, @commit.id, params[:path]) | ||
82 | - end | ||
83 | - | ||
84 | protected | 44 | protected |
85 | 45 | ||
86 | def define_tree_vars | 46 | def define_tree_vars |
@@ -91,20 +51,20 @@ class RefsController < ProjectController | @@ -91,20 +51,20 @@ class RefsController < ProjectController | ||
91 | @commit = CommitDecorator.decorate(@commit) | 51 | @commit = CommitDecorator.decorate(@commit) |
92 | @tree = Tree.new(@commit.tree, project, @ref, params[:path]) | 52 | @tree = Tree.new(@commit.tree, project, @ref, params[:path]) |
93 | @tree = TreeDecorator.new(@tree) | 53 | @tree = TreeDecorator.new(@tree) |
94 | - @hex_path = Digest::SHA1.hexdigest(params[:path] || "/") | 54 | + @hex_path = Digest::SHA1.hexdigest(params[:path] || "") |
95 | 55 | ||
96 | if params[:path] | 56 | if params[:path] |
97 | - @history_path = tree_file_project_ref_path(@project, @ref, params[:path]) | ||
98 | - @logs_path = logs_file_project_ref_path(@project, @ref, params[:path]) | 57 | + @history_path = project_tree_path(@project, File.join(@ref, params[:path])) |
58 | + @logs_path = logs_file_project_ref_path(@project, @ref, params[:path]) | ||
99 | else | 59 | else |
100 | - @history_path = tree_project_ref_path(@project, @ref) | ||
101 | - @logs_path = logs_tree_project_ref_path(@project, @ref) | 60 | + @history_path = project_tree_path(@project, @ref) |
61 | + @logs_path = logs_tree_project_ref_path(@project, @ref) | ||
102 | end | 62 | end |
103 | rescue | 63 | rescue |
104 | return render_404 | 64 | return render_404 |
105 | end | 65 | end |
106 | - | 66 | + |
107 | def ref | 67 | def ref |
108 | - @ref = params[:id] | 68 | + @ref = params[:id] || params[:ref] |
109 | end | 69 | end |
110 | end | 70 | end |
app/controllers/repositories_controller.rb
@@ -3,18 +3,17 @@ class RepositoriesController < ProjectController | @@ -3,18 +3,17 @@ class RepositoriesController < ProjectController | ||
3 | before_filter :authorize_read_project! | 3 | before_filter :authorize_read_project! |
4 | before_filter :authorize_code_access! | 4 | before_filter :authorize_code_access! |
5 | before_filter :require_non_empty_project | 5 | before_filter :require_non_empty_project |
6 | - before_filter :render_full_content | ||
7 | 6 | ||
8 | def show | 7 | def show |
9 | @activities = @project.commits_with_refs(20) | 8 | @activities = @project.commits_with_refs(20) |
10 | end | 9 | end |
11 | 10 | ||
12 | def branches | 11 | def branches |
13 | - @branches = @project.repo.heads.sort_by(&:name) | 12 | + @branches = @project.branches |
14 | end | 13 | end |
15 | 14 | ||
16 | def tags | 15 | def tags |
17 | - @tags = @project.repo.tags.sort_by(&:name).reverse | 16 | + @tags = @project.tags |
18 | end | 17 | end |
19 | 18 | ||
20 | def archive | 19 | def archive |
app/controllers/snippets_controller.rb
@@ -50,7 +50,6 @@ class SnippetsController < ProjectController | @@ -50,7 +50,6 @@ class SnippetsController < ProjectController | ||
50 | 50 | ||
51 | def show | 51 | def show |
52 | @note = @project.notes.new(noteable: @snippet) | 52 | @note = @project.notes.new(noteable: @snippet) |
53 | - render_full_content | ||
54 | end | 53 | end |
55 | 54 | ||
56 | def destroy | 55 | def destroy |
@@ -0,0 +1,29 @@ | @@ -0,0 +1,29 @@ | ||
1 | +# Controller for viewing a repository's file structure | ||
2 | +class TreeController < ApplicationController | ||
3 | + include ExtractsPath | ||
4 | + | ||
5 | + layout "project" | ||
6 | + | ||
7 | + before_filter :project | ||
8 | + | ||
9 | + # Authorize | ||
10 | + before_filter :add_project_abilities | ||
11 | + before_filter :authorize_read_project! | ||
12 | + before_filter :authorize_code_access! | ||
13 | + before_filter :require_non_empty_project | ||
14 | + | ||
15 | + before_filter :assign_ref_vars | ||
16 | + | ||
17 | + def show | ||
18 | + @hex_path = Digest::SHA1.hexdigest(@path) | ||
19 | + | ||
20 | + @history_path = project_tree_path(@project, @id) | ||
21 | + @logs_path = logs_file_project_ref_path(@project, @ref, @path) | ||
22 | + | ||
23 | + respond_to do |format| | ||
24 | + format.html | ||
25 | + # Disable cache so browser history works | ||
26 | + format.js { no_cache_headers } | ||
27 | + end | ||
28 | + end | ||
29 | +end |
app/decorators/event_decorator.rb
@@ -21,7 +21,7 @@ class EventDecorator < ApplicationDecorator | @@ -21,7 +21,7 @@ class EventDecorator < ApplicationDecorator | ||
21 | elsif self.merge_request? | 21 | elsif self.merge_request? |
22 | h.project_merge_request_url(self.project, self.merge_request) | 22 | h.project_merge_request_url(self.project, self.merge_request) |
23 | elsif self.push? | 23 | elsif self.push? |
24 | - h.project_commits_url(self.project, ref: self.ref_name) | 24 | + h.project_commits_url(self.project, self.ref_name) |
25 | end | 25 | end |
26 | end | 26 | end |
27 | end | 27 | end |
app/decorators/tree_decorator.rb
@@ -6,7 +6,7 @@ class TreeDecorator < ApplicationDecorator | @@ -6,7 +6,7 @@ class TreeDecorator < ApplicationDecorator | ||
6 | part_path = "" | 6 | part_path = "" |
7 | parts = path.split("\/") | 7 | parts = path.split("\/") |
8 | 8 | ||
9 | - #parts = parts[0...-1] if is_blob? | 9 | + #parts = parts[0...-1] if is_blob? |
10 | 10 | ||
11 | yield(h.link_to("..", "#", remote: :true)) if parts.count > max_links | 11 | yield(h.link_to("..", "#", remote: :true)) if parts.count > max_links |
12 | 12 | ||
@@ -15,29 +15,29 @@ class TreeDecorator < ApplicationDecorator | @@ -15,29 +15,29 @@ class TreeDecorator < ApplicationDecorator | ||
15 | part_path = part if part_path.empty? | 15 | part_path = part if part_path.empty? |
16 | 16 | ||
17 | next unless parts.last(2).include?(part) if parts.count > max_links | 17 | next unless parts.last(2).include?(part) if parts.count > max_links |
18 | - yield(h.link_to(h.truncate(part, length: 40), h.tree_file_project_ref_path(project, ref, path: part_path), remote: :true)) | 18 | + yield(h.link_to(h.truncate(part, length: 40), h.project_tree_path(project, h.tree_join(ref, part_path)), remote: :true)) |
19 | end | 19 | end |
20 | end | 20 | end |
21 | end | 21 | end |
22 | 22 | ||
23 | def up_dir? | 23 | def up_dir? |
24 | - !!path | 24 | + path.present? |
25 | end | 25 | end |
26 | 26 | ||
27 | def up_dir_path | 27 | def up_dir_path |
28 | file = File.join(path, "..") | 28 | file = File.join(path, "..") |
29 | - h.tree_file_project_ref_path(project, ref, file) | 29 | + h.project_tree_path(project, h.tree_join(ref, file)) |
30 | end | 30 | end |
31 | 31 | ||
32 | def history_path | 32 | def history_path |
33 | - h.project_commits_path(project, path: path, ref: ref) | 33 | + h.project_commits_path(project, h.tree_join(ref, path)) |
34 | end | 34 | end |
35 | 35 | ||
36 | def mb_size | 36 | def mb_size |
37 | size = (tree.size / 1024) | 37 | size = (tree.size / 1024) |
38 | if size < 1024 | 38 | if size < 1024 |
39 | - "#{size} KB" | ||
40 | - else | 39 | + "#{size} KB" |
40 | + else | ||
41 | "#{size/1024} MB" | 41 | "#{size/1024} MB" |
42 | end | 42 | end |
43 | end | 43 | end |
app/helpers/application_helper.rb
1 | require 'digest/md5' | 1 | require 'digest/md5' |
2 | + | ||
2 | module ApplicationHelper | 3 | module ApplicationHelper |
3 | 4 | ||
5 | + # Check if a particular controller is the current one | ||
6 | + # | ||
7 | + # args - One or more controller names to check | ||
8 | + # | ||
9 | + # Examples | ||
10 | + # | ||
11 | + # # On TreeController | ||
12 | + # current_controller?(:tree) # => true | ||
13 | + # current_controller?(:commits) # => false | ||
14 | + # current_controller?(:commits, :tree) # => true | ||
15 | + def current_controller?(*args) | ||
16 | + args.any? { |v| v.to_s.downcase == controller.controller_name } | ||
17 | + end | ||
18 | + | ||
19 | + # Check if a partcular action is the current one | ||
20 | + # | ||
21 | + # args - One or more action names to check | ||
22 | + # | ||
23 | + # Examples | ||
24 | + # | ||
25 | + # # On Projects#new | ||
26 | + # current_action?(:new) # => true | ||
27 | + # current_action?(:create) # => false | ||
28 | + # current_action?(:new, :create) # => true | ||
29 | + def current_action?(*args) | ||
30 | + args.any? { |v| v.to_s.downcase == action_name } | ||
31 | + end | ||
32 | + | ||
4 | def gravatar_icon(user_email = '', size = 40) | 33 | def gravatar_icon(user_email = '', size = 40) |
5 | if Gitlab.config.disable_gravatar? || user_email.blank? | 34 | if Gitlab.config.disable_gravatar? || user_email.blank? |
6 | 'no_avatar.png' | 35 | 'no_avatar.png' |
@@ -31,8 +60,8 @@ module ApplicationHelper | @@ -31,8 +60,8 @@ module ApplicationHelper | ||
31 | 60 | ||
32 | def grouped_options_refs(destination = :tree) | 61 | def grouped_options_refs(destination = :tree) |
33 | options = [ | 62 | options = [ |
34 | - ["Branch", @project.repo.heads.map(&:name) ], | ||
35 | - [ "Tag", @project.tags ] | 63 | + ["Branch", @project.branch_names ], |
64 | + [ "Tag", @project.tag_names ] | ||
36 | ] | 65 | ] |
37 | 66 | ||
38 | # If reference is commit id - | 67 | # If reference is commit id - |
@@ -58,11 +87,11 @@ module ApplicationHelper | @@ -58,11 +87,11 @@ module ApplicationHelper | ||
58 | 87 | ||
59 | if @project && !@project.new_record? | 88 | if @project && !@project.new_record? |
60 | project_nav = [ | 89 | project_nav = [ |
61 | - { label: "#{@project.name} / Issues", url: project_issues_path(@project) }, | ||
62 | - { label: "#{@project.name} / Wall", url: wall_project_path(@project) }, | ||
63 | - { label: "#{@project.name} / Tree", url: tree_project_ref_path(@project, @project.root_ref) }, | ||
64 | - { label: "#{@project.name} / Commits", url: project_commits_path(@project) }, | ||
65 | - { label: "#{@project.name} / Team", url: project_team_index_path(@project) } | 90 | + { label: "#{@project.name} / Issues", url: project_issues_path(@project) }, |
91 | + { label: "#{@project.name} / Wall", url: wall_project_path(@project) }, | ||
92 | + { label: "#{@project.name} / Tree", url: project_tree_path(@project, @ref || @project.root_ref) }, | ||
93 | + { label: "#{@project.name} / Commits", url: project_commits_path(@project, @ref || @project.root_ref) }, | ||
94 | + { label: "#{@project.name} / Team", url: project_team_index_path(@project) } | ||
66 | ] | 95 | ] |
67 | end | 96 | end |
68 | 97 | ||
@@ -85,45 +114,6 @@ module ApplicationHelper | @@ -85,45 +114,6 @@ module ApplicationHelper | ||
85 | event.project.merge_requests_enabled | 114 | event.project.merge_requests_enabled |
86 | end | 115 | end |
87 | 116 | ||
88 | - def tab_class(tab_key) | ||
89 | - active = case tab_key | ||
90 | - | ||
91 | - # Project Area | ||
92 | - when :wall; wall_tab? | ||
93 | - when :wiki; controller.controller_name == "wikis" | ||
94 | - when :issues; issues_tab? | ||
95 | - when :network; current_page?(controller: "projects", action: "graph", id: @project) | ||
96 | - when :merge_requests; controller.controller_name == "merge_requests" | ||
97 | - | ||
98 | - # Dashboard Area | ||
99 | - when :help; controller.controller_name == "help" | ||
100 | - when :search; current_page?(search_path) | ||
101 | - when :dash_issues; current_page?(dashboard_issues_path) | ||
102 | - when :dash_mr; current_page?(dashboard_merge_requests_path) | ||
103 | - when :root; current_page?(dashboard_path) || current_page?(root_path) | ||
104 | - | ||
105 | - # Profile Area | ||
106 | - when :profile; current_page?(controller: "profile", action: :show) | ||
107 | - when :history; current_page?(controller: "profile", action: :history) | ||
108 | - when :account; current_page?(controller: "profile", action: :account) | ||
109 | - when :token; current_page?(controller: "profile", action: :token) | ||
110 | - when :design; current_page?(controller: "profile", action: :design) | ||
111 | - when :ssh_keys; controller.controller_name == "keys" | ||
112 | - | ||
113 | - # Admin Area | ||
114 | - when :admin_root; controller.controller_name == "dashboard" | ||
115 | - when :admin_users; controller.controller_name == 'users' | ||
116 | - when :admin_projects; controller.controller_name == "projects" | ||
117 | - when :admin_hooks; controller.controller_name == 'hooks' | ||
118 | - when :admin_resque; controller.controller_name == 'resque' | ||
119 | - when :admin_logs; controller.controller_name == 'logs' | ||
120 | - | ||
121 | - else | ||
122 | - false | ||
123 | - end | ||
124 | - active ? "current" : nil | ||
125 | - end | ||
126 | - | ||
127 | def hexdigest(string) | 117 | def hexdigest(string) |
128 | Digest::SHA1.hexdigest string | 118 | Digest::SHA1.hexdigest string |
129 | end | 119 | end |
app/helpers/tab_helper.rb
1 | module TabHelper | 1 | module TabHelper |
2 | - def issues_tab? | ||
3 | - controller.controller_name == "issues" || controller.controller_name == "milestones" | ||
4 | - end | 2 | + # Navigation link helper |
3 | + # | ||
4 | + # Returns an `li` element with an 'active' class if the supplied | ||
5 | + # controller(s) and/or action(s) currently active. The contents of the | ||
6 | + # element is the value passed to the block. | ||
7 | + # | ||
8 | + # options - The options hash used to determine if the element is "active" (default: {}) | ||
9 | + # :controller - One or more controller names to check (optional). | ||
10 | + # :action - One or more action names to check (optional). | ||
11 | + # :path - A shorthand path, such as 'dashboard#index', to check (optional). | ||
12 | + # :html_options - Extra options to be passed to the list element (optional). | ||
13 | + # block - An optional block that will become the contents of the returned | ||
14 | + # `li` element. | ||
15 | + # | ||
16 | + # When both :controller and :action are specified, BOTH must match in order | ||
17 | + # to be marked as active. When only one is given, either can match. | ||
18 | + # | ||
19 | + # Examples | ||
20 | + # | ||
21 | + # # Assuming we're on TreeController#show | ||
22 | + # | ||
23 | + # # Controller matches, but action doesn't | ||
24 | + # nav_link(controller: [:tree, :refs], action: :edit) { "Hello" } | ||
25 | + # # => '<li>Hello</li>' | ||
26 | + # | ||
27 | + # # Controller matches | ||
28 | + # nav_link(controller: [:tree, :refs]) { "Hello" } | ||
29 | + # # => '<li class="active">Hello</li>' | ||
30 | + # | ||
31 | + # # Shorthand path | ||
32 | + # nav_link(path: 'tree#show') { "Hello" } | ||
33 | + # # => '<li class="active">Hello</li>' | ||
34 | + # | ||
35 | + # # Supplying custom options for the list element | ||
36 | + # nav_link(controller: :tree, html_options: {class: 'home'}) { "Hello" } | ||
37 | + # # => '<li class="home active">Hello</li>' | ||
38 | + # | ||
39 | + # Returns a list item element String | ||
40 | + def nav_link(options = {}, &block) | ||
41 | + if path = options.delete(:path) | ||
42 | + c, a, _ = path.split('#') | ||
43 | + else | ||
44 | + c = options.delete(:controller) | ||
45 | + a = options.delete(:action) | ||
46 | + end | ||
47 | + | ||
48 | + if c && a | ||
49 | + # When given both options, make sure BOTH are active | ||
50 | + klass = current_controller?(*c) && current_action?(*a) ? 'active' : '' | ||
51 | + else | ||
52 | + # Otherwise check EITHER option | ||
53 | + klass = current_controller?(*c) || current_action?(*a) ? 'active' : '' | ||
54 | + end | ||
55 | + | ||
56 | + # Add our custom class into the html_options, which may or may not exist | ||
57 | + # and which may or may not already have a :class key | ||
58 | + o = options.delete(:html_options) || {} | ||
59 | + o[:class] ||= '' | ||
60 | + o[:class] += ' ' + klass | ||
61 | + o[:class].strip! | ||
5 | 62 | ||
6 | - def wall_tab? | ||
7 | - current_page?(controller: "projects", action: "wall", id: @project) | 63 | + if block_given? |
64 | + content_tag(:li, capture(&block), o) | ||
65 | + else | ||
66 | + content_tag(:li, nil, o) | ||
67 | + end | ||
8 | end | 68 | end |
9 | 69 | ||
10 | def project_tab_class | 70 | def project_tab_class |
11 | [:show, :files, :edit, :update].each do |action| | 71 | [:show, :files, :edit, :update].each do |action| |
12 | - return "current" if current_page?(controller: "projects", action: action, id: @project) | 72 | + return "active" if current_page?(controller: "projects", action: action, id: @project) |
13 | end | 73 | end |
14 | 74 | ||
15 | if ['snippets', 'hooks', 'deploy_keys', 'team_members'].include? controller.controller_name | 75 | if ['snippets', 'hooks', 'deploy_keys', 'team_members'].include? controller.controller_name |
16 | - "current" | ||
17 | - end | ||
18 | - end | ||
19 | - | ||
20 | - def tree_tab_class | ||
21 | - controller.controller_name == "refs" ? "current" : nil | ||
22 | - end | ||
23 | - | ||
24 | - def commit_tab_class | ||
25 | - if ['commits', 'repositories', 'protected_branches'].include? controller.controller_name | ||
26 | - "current" | 76 | + "active" |
27 | end | 77 | end |
28 | end | 78 | end |
29 | 79 | ||
30 | def branches_tab_class | 80 | def branches_tab_class |
31 | if current_page?(branches_project_repository_path(@project)) || | 81 | if current_page?(branches_project_repository_path(@project)) || |
32 | - controller.controller_name == "protected_branches" || | 82 | + current_controller?(:protected_branches) || |
33 | current_page?(project_repository_path(@project)) | 83 | current_page?(project_repository_path(@project)) |
34 | 'active' | 84 | 'active' |
35 | end | 85 | end |
app/helpers/tree_helper.rb
@@ -39,4 +39,9 @@ module TreeHelper | @@ -39,4 +39,9 @@ module TreeHelper | ||
39 | def gitlab_markdown?(filename) | 39 | def gitlab_markdown?(filename) |
40 | filename.end_with?(*%w(.mdown .md .markdown)) | 40 | filename.end_with?(*%w(.mdown .md .markdown)) |
41 | end | 41 | end |
42 | + | ||
43 | + # Simple shortcut to File.join | ||
44 | + def tree_join(*args) | ||
45 | + File.join(*args) | ||
46 | + end | ||
42 | end | 47 | end |
app/models/merge_request.rb
app/models/tree.rb
1 | class Tree | 1 | class Tree |
2 | - include Linguist::BlobHelper | 2 | + include Linguist::BlobHelper |
3 | attr_accessor :path, :tree, :project, :ref | 3 | attr_accessor :path, :tree, :project, :ref |
4 | 4 | ||
5 | delegate :contents, | 5 | delegate :contents, |
@@ -14,8 +14,8 @@ class Tree | @@ -14,8 +14,8 @@ class Tree | ||
14 | to: :tree | 14 | to: :tree |
15 | 15 | ||
16 | def initialize(raw_tree, project, ref = nil, path = nil) | 16 | def initialize(raw_tree, project, ref = nil, path = nil) |
17 | - @project, @ref, @path = project, ref, path, | ||
18 | - @tree = if path | 17 | + @project, @ref, @path = project, ref, path |
18 | + @tree = if path.present? | ||
19 | raw_tree / path.dup.force_encoding('ascii-8bit') | 19 | raw_tree / path.dup.force_encoding('ascii-8bit') |
20 | else | 20 | else |
21 | raw_tree | 21 | raw_tree |
@@ -26,6 +26,10 @@ class Tree | @@ -26,6 +26,10 @@ class Tree | ||
26 | tree.is_a?(Grit::Blob) | 26 | tree.is_a?(Grit::Blob) |
27 | end | 27 | end |
28 | 28 | ||
29 | + def invalid? | ||
30 | + tree.nil? | ||
31 | + end | ||
32 | + | ||
29 | def empty? | 33 | def empty? |
30 | data.blank? | 34 | data.blank? |
31 | end | 35 | end |
app/roles/repository.rb
@@ -45,8 +45,29 @@ module Repository | @@ -45,8 +45,29 @@ module Repository | ||
45 | File.exists?(hook_file) | 45 | File.exists?(hook_file) |
46 | end | 46 | end |
47 | 47 | ||
48 | + # Returns an Array of branch names | ||
49 | + def branch_names | ||
50 | + repo.branches.collect(&:name).sort | ||
51 | + end | ||
52 | + | ||
53 | + # Returns an Array of Branches | ||
54 | + def branches | ||
55 | + repo.branches.sort_by(&:name) | ||
56 | + end | ||
57 | + | ||
58 | + # Returns an Array of tag names | ||
59 | + def tag_names | ||
60 | + repo.tags.collect(&:name).sort.reverse | ||
61 | + end | ||
62 | + | ||
63 | + # Returns an Array of Tags | ||
48 | def tags | 64 | def tags |
49 | - repo.tags.map(&:name).sort.reverse | 65 | + repo.tags.sort_by(&:name).reverse |
66 | + end | ||
67 | + | ||
68 | + # Returns an Array of branch and tag names | ||
69 | + def ref_names | ||
70 | + [branch_names + tag_names].flatten | ||
50 | end | 71 | end |
51 | 72 | ||
52 | def repo | 73 | def repo |
@@ -79,14 +100,6 @@ module Repository | @@ -79,14 +100,6 @@ module Repository | ||
79 | @heads ||= repo.heads | 100 | @heads ||= repo.heads |
80 | end | 101 | end |
81 | 102 | ||
82 | - def branches_names | ||
83 | - heads.map(&:name) | ||
84 | - end | ||
85 | - | ||
86 | - def ref_names | ||
87 | - [branches_names + tags].flatten | ||
88 | - end | ||
89 | - | ||
90 | def tree(fcommit, path = nil) | 103 | def tree(fcommit, path = nil) |
91 | fcommit = commit if fcommit == :head | 104 | fcommit = commit if fcommit == :head |
92 | tree = fcommit.tree | 105 | tree = fcommit.tree |
@@ -109,14 +122,12 @@ module Repository | @@ -109,14 +122,12 @@ module Repository | ||
109 | # - If two or more branches are present, returns the one that has a name | 122 | # - If two or more branches are present, returns the one that has a name |
110 | # matching root_ref (default_branch or 'master' if default_branch is nil) | 123 | # matching root_ref (default_branch or 'master' if default_branch is nil) |
111 | def discover_default_branch | 124 | def discover_default_branch |
112 | - branches = heads.collect(&:name) | ||
113 | - | ||
114 | - if branches.length == 0 | 125 | + if branch_names.length == 0 |
115 | nil | 126 | nil |
116 | - elsif branches.length == 1 | ||
117 | - branches.first | 127 | + elsif branch_names.length == 1 |
128 | + branch_names.first | ||
118 | else | 129 | else |
119 | - branches.select { |v| v == root_ref }.first | 130 | + branch_names.select { |v| v == root_ref }.first |
120 | end | 131 | end |
121 | end | 132 | end |
122 | 133 | ||
@@ -144,7 +155,7 @@ module Repository | @@ -144,7 +155,7 @@ module Repository | ||
144 | 155 | ||
145 | # Build file path | 156 | # Build file path |
146 | file_name = self.code + "-" + commit.id.to_s + ".tar.gz" | 157 | file_name = self.code + "-" + commit.id.to_s + ".tar.gz" |
147 | - storage_path = File.join(Rails.root, "tmp", "repositories", self.code) | 158 | + storage_path = Rails.root.join("tmp", "repositories", self.code) |
148 | file_path = File.join(storage_path, file_name) | 159 | file_path = File.join(storage_path, file_name) |
149 | 160 | ||
150 | # Put files into a directory before archiving | 161 | # Put files into a directory before archiving |
app/roles/static_model.rb
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +%ul.nav.nav-tabs | ||
2 | + %li | ||
3 | + = render partial: 'shared/ref_switcher', locals: {destination: 'tree', path: params[:path]} | ||
4 | + = nav_link(controller: :refs) do | ||
5 | + = link_to 'Source', project_tree_path(@project, @ref) | ||
6 | + %li.right | ||
7 | + .input-prepend.project_clone_holder | ||
8 | + %button{class: "btn small active", :"data-clone" => @project.ssh_url_to_repo} SSH | ||
9 | + %button{class: "btn small", :"data-clone" => @project.http_url_to_repo} HTTP | ||
10 | + = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select span5" |
@@ -0,0 +1,40 @@ | @@ -0,0 +1,40 @@ | ||
1 | += render "head" | ||
2 | + | ||
3 | +#tree-holder | ||
4 | + %ul.breadcrumb | ||
5 | + %li | ||
6 | + %span.arrow | ||
7 | + = link_to project_tree_path(@project, @ref) do | ||
8 | + = @project.name | ||
9 | + - @tree.breadcrumbs(6) do |link| | ||
10 | + \/ | ||
11 | + %li= link | ||
12 | + .clear | ||
13 | + | ||
14 | + .file_holder | ||
15 | + .file_title | ||
16 | + %i.icon-file | ||
17 | + %span.file_name | ||
18 | + = @tree.name | ||
19 | + %small blame | ||
20 | + %span.options | ||
21 | + = link_to "raw", project_blob_path(@project, @id), class: "btn very_small", target: "_blank" | ||
22 | + = link_to "history", project_commits_path(@project, @id), class: "btn very_small" | ||
23 | + = link_to "source", project_tree_path(@project, @id), class: "btn very_small" | ||
24 | + .file_content.blame | ||
25 | + %table | ||
26 | + - @blame.each do |commit, lines| | ||
27 | + - commit = Commit.new(commit) | ||
28 | + - commit = CommitDecorator.decorate(commit) | ||
29 | + %tr | ||
30 | + %td.author | ||
31 | + = image_tag gravatar_icon(commit.author_email, 16) | ||
32 | + = commit.author_name | ||
33 | + %td.blame_commit | ||
34 | + | ||
35 | + %code= link_to commit.short_id, project_commit_path(@project, commit) | ||
36 | + = link_to_gfm truncate(commit.title, length: 30), project_commit_path(@project, commit), class: "row_title" rescue "--broken encoding" | ||
37 | + %td.lines | ||
38 | + = preserve do | ||
39 | + %pre | ||
40 | + = Gitlab::Encode.utf8 lines.join("\n") |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +<%= @commit.to_patch %> |
app/views/commits/_commit.html.haml
1 | %li.commit | 1 | %li.commit |
2 | .browse_code_link_holder | 2 | .browse_code_link_holder |
3 | %p | 3 | %p |
4 | - %strong= link_to "Browse Code »", tree_project_ref_path(@project, commit.id), class: "right" | 4 | + %strong= link_to "Browse Code »", project_tree_path(@project, commit), class: "right" |
5 | %p | 5 | %p |
6 | - = link_to commit.short_id(8), project_commit_path(@project, id: commit.id), class: "commit_short_id" | 6 | + = link_to commit.short_id(8), project_commit_path(@project, commit), class: "commit_short_id" |
7 | %strong.commit-author-name= commit.author_name | 7 | %strong.commit-author-name= commit.author_name |
8 | %span.dash – | 8 | %span.dash – |
9 | = image_tag gravatar_icon(commit.author_email), class: "avatar", width: 16 | 9 | = image_tag gravatar_icon(commit.author_email), class: "avatar", width: 16 |
10 | - = link_to_gfm truncate(commit.title, length: 50), project_commit_path(@project, id: commit.id), class: "row_title" | 10 | + = link_to_gfm truncate(commit.title, length: 50), project_commit_path(@project, commit.id), class: "row_title" |
11 | 11 | ||
12 | %span.committed_ago | 12 | %span.committed_ago |
13 | = time_ago_in_words(commit.committed_date) | 13 | = time_ago_in_words(commit.committed_date) |
14 | ago | 14 | ago |
15 | | 15 | |
16 | - |
app/views/commits/_commit_box.html.haml
@@ -5,10 +5,10 @@ | @@ -5,10 +5,10 @@ | ||
5 | %span.btn.disabled.grouped | 5 | %span.btn.disabled.grouped |
6 | %i.icon-comment | 6 | %i.icon-comment |
7 | = @notes_count | 7 | = @notes_count |
8 | - = link_to patch_project_commit_path(@project, @commit.id), class: "btn small grouped" do | 8 | + = link_to project_commit_path(@project, @commit, format: :patch), class: "btn small grouped" do |
9 | %i.icon-download-alt | 9 | %i.icon-download-alt |
10 | Get Patch | 10 | Get Patch |
11 | - = link_to tree_project_ref_path(@project, @commit.id), class: "browse-button primary grouped" do | 11 | + = link_to project_tree_path(@project, @commit), class: "browse-button primary grouped" do |
12 | %strong Browse Code » | 12 | %strong Browse Code » |
13 | %h3.commit-title.page_title | 13 | %h3.commit-title.page_title |
14 | = gfm escape_once(@commit.title) | 14 | = gfm escape_once(@commit.title) |
app/views/commits/_diffs.html.haml
@@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
5 | %p To prevent performance issue we rejected diff information. | 5 | %p To prevent performance issue we rejected diff information. |
6 | %p | 6 | %p |
7 | But if you still want to see diff | 7 | But if you still want to see diff |
8 | - = link_to "click this link", project_commit_path(@project, @commit.id, force_show_diff: true), class: "dark" | 8 | + = link_to "click this link", project_commit_path(@project, @commit, force_show_diff: true), class: "dark" |
9 | 9 | ||
10 | %p.cgray | 10 | %p.cgray |
11 | Showing #{pluralize(diffs.count, "changed file")} | 11 | Showing #{pluralize(diffs.count, "changed file")} |
@@ -24,7 +24,7 @@ | @@ -24,7 +24,7 @@ | ||
24 | %i.icon-file | 24 | %i.icon-file |
25 | %span{id: "#{diff.old_path}"}= diff.old_path | 25 | %span{id: "#{diff.old_path}"}= diff.old_path |
26 | - else | 26 | - else |
27 | - = link_to tree_file_project_ref_path(@project, @commit.id, diff.new_path) do | 27 | + = link_to project_tree_path(@project, tree_join(@commit.id, diff.new_path)) do |
28 | %i.icon-file | 28 | %i.icon-file |
29 | %span{id: "#{diff.new_path}"}= diff.new_path | 29 | %span{id: "#{diff.new_path}"}= diff.new_path |
30 | %br/ | 30 | %br/ |
app/views/commits/_head.html.haml
1 | %ul.nav.nav-tabs | 1 | %ul.nav.nav-tabs |
2 | %li= render partial: 'shared/ref_switcher', locals: {destination: 'commits'} | 2 | %li= render partial: 'shared/ref_switcher', locals: {destination: 'commits'} |
3 | - %li{class: "#{'active' if current_page?(project_commits_path(@project)) }"} | ||
4 | - = link_to project_commits_path(@project) do | ||
5 | - Commits | ||
6 | - %li{class: "#{'active' if current_page?(compare_project_commits_path(@project)) }"} | ||
7 | - = link_to compare_project_commits_path(@project) do | ||
8 | - Compare | ||
9 | - %li{class: "#{branches_tab_class}"} | 3 | + |
4 | + = nav_link(controller: [:commit, :commits]) do | ||
5 | + = link_to 'Commits', project_commits_path(@project, @project.root_ref) | ||
6 | + = nav_link(controller: :compare) do | ||
7 | + = link_to 'Compare', project_compare_index_path(@project) | ||
8 | + | ||
9 | + = nav_link(html_options: {class: branches_tab_class}) do | ||
10 | = link_to project_repository_path(@project) do | 10 | = link_to project_repository_path(@project) do |
11 | Branches | 11 | Branches |
12 | %span.badge= @project.repo.branch_count | 12 | %span.badge= @project.repo.branch_count |
13 | 13 | ||
14 | - %li{class: "#{'active' if current_page?(tags_project_repository_path(@project)) }"} | 14 | + = nav_link(controller: :repositories, action: :tags) do |
15 | = link_to tags_project_repository_path(@project) do | 15 | = link_to tags_project_repository_path(@project) do |
16 | Tags | 16 | Tags |
17 | %span.badge= @project.repo.tag_count | 17 | %span.badge= @project.repo.tag_count |
18 | 18 | ||
19 | - - if current_page?(project_commits_path(@project)) && current_user.private_token | 19 | + - if current_controller?(:commits) && current_user.private_token |
20 | %li.right | 20 | %li.right |
21 | %span.rss-icon | 21 | %span.rss-icon |
22 | - = link_to project_commits_path(@project, :atom, { private_token: current_user.private_token, ref: @ref }), title: "Feed" do | 22 | + = link_to project_commits_path(@project, @ref, {format: :atom, private_token: current_user.private_token}), title: "Feed" do |
23 | = image_tag "rss_ui.png", title: "feed" | 23 | = image_tag "rss_ui.png", title: "feed" |
app/views/commits/compare.html.haml
@@ -1,53 +0,0 @@ | @@ -1,53 +0,0 @@ | ||
1 | -= render "head" | ||
2 | - | ||
3 | -%h3.page_title | ||
4 | - Compare View | ||
5 | -%hr | ||
6 | - | ||
7 | -%div | ||
8 | - %p.slead | ||
9 | - Fill input field with commit id like | ||
10 | - %code.label_branch 4eedf23 | ||
11 | - or branch/tag name like | ||
12 | - %code.label_branch master | ||
13 | - and press compare button for commits list, code diff. | ||
14 | - | ||
15 | - %br | ||
16 | - | ||
17 | - = form_tag compare_project_commits_path(@project), method: :get do | ||
18 | - .clearfix | ||
19 | - = text_field_tag :from, params[:from], placeholder: "master", class: "xlarge" | ||
20 | - = "..." | ||
21 | - = text_field_tag :to, params[:to], placeholder: "aa8b4ef", class: "xlarge" | ||
22 | - - if @refs_are_same | ||
23 | - .alert | ||
24 | - %span Refs are the same | ||
25 | - .actions | ||
26 | - = submit_tag "Compare", class: "btn primary wide commits-compare-btn" | ||
27 | - | ||
28 | -- if @commits.present? | ||
29 | - %div.ui-box | ||
30 | - %h5.small Commits (#{@commits.count}) | ||
31 | - %ul.unstyled= render @commits | ||
32 | - | ||
33 | - - unless @diffs.empty? | ||
34 | - %h4 Diff | ||
35 | - = render "commits/diffs", diffs: @diffs | ||
36 | - | ||
37 | -:javascript | ||
38 | - $(function() { | ||
39 | - var availableTags = #{@project.ref_names.to_json}; | ||
40 | - | ||
41 | - $("#from").autocomplete({ | ||
42 | - source: availableTags, | ||
43 | - minLength: 1 | ||
44 | - }); | ||
45 | - | ||
46 | - $("#to").autocomplete({ | ||
47 | - source: availableTags, | ||
48 | - minLength: 1 | ||
49 | - }); | ||
50 | - | ||
51 | - disableButtonIfEmptyField('#to', '.commits-compare-btn'); | ||
52 | - }); | ||
53 | - |
app/views/commits/index.atom.builder
@@ -1,23 +0,0 @@ | @@ -1,23 +0,0 @@ | ||
1 | -xml.instruct! | ||
2 | -xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do | ||
3 | - xml.title "Recent commits to #{@project.name}:#{@ref}" | ||
4 | - xml.link :href => project_commits_url(@project, :atom, :ref => @ref), :rel => "self", :type => "application/atom+xml" | ||
5 | - xml.link :href => project_commits_url(@project), :rel => "alternate", :type => "text/html" | ||
6 | - xml.id project_commits_url(@project) | ||
7 | - xml.updated @commits.first.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ") if @commits.any? | ||
8 | - | ||
9 | - @commits.each do |commit| | ||
10 | - xml.entry do | ||
11 | - xml.id project_commit_url(@project, :id => commit.id) | ||
12 | - xml.link :href => project_commit_url(@project, :id => commit.id) | ||
13 | - xml.title truncate(commit.title, :length => 80) | ||
14 | - xml.updated commit.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ") | ||
15 | - xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(commit.author_email) | ||
16 | - xml.author do |author| | ||
17 | - xml.name commit.author_name | ||
18 | - xml.email commit.author_email | ||
19 | - end | ||
20 | - xml.summary gfm(commit.description) | ||
21 | - end | ||
22 | - end | ||
23 | -end |
app/views/commits/index.html.haml
@@ -1,24 +0,0 @@ | @@ -1,24 +0,0 @@ | ||
1 | -= render "head" | ||
2 | - | ||
3 | -- if params[:path] | ||
4 | - %ul.breadcrumb | ||
5 | - %li | ||
6 | - %span.arrow | ||
7 | - = link_to project_commits_path(@project) do | ||
8 | - = @project.name | ||
9 | - %span.divider | ||
10 | - \/ | ||
11 | - %li | ||
12 | - %a{href: "#"}= params[:path].split("/").join(" / ") | ||
13 | - | ||
14 | -%div{id: dom_id(@project)} | ||
15 | - #commits_list= render "commits" | ||
16 | -.clear | ||
17 | -.loading{ style: "display:none;"} | ||
18 | - | ||
19 | -- if @commits.count == @limit | ||
20 | - :javascript | ||
21 | - $(function(){ | ||
22 | - CommitsList.init("#{@ref}", #{@limit}); | ||
23 | - }); | ||
24 | - |
app/views/commits/index.js.haml
@@ -0,0 +1,23 @@ | @@ -0,0 +1,23 @@ | ||
1 | +xml.instruct! | ||
2 | +xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do | ||
3 | + xml.title "Recent commits to #{@project.name}:#{@ref}" | ||
4 | + xml.link :href => project_commits_url(@project, @ref, format: :atom), :rel => "self", :type => "application/atom+xml" | ||
5 | + xml.link :href => project_commits_url(@project, @ref), :rel => "alternate", :type => "text/html" | ||
6 | + xml.id project_commits_url(@project) | ||
7 | + xml.updated @commits.first.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ") if @commits.any? | ||
8 | + | ||
9 | + @commits.each do |commit| | ||
10 | + xml.entry do | ||
11 | + xml.id project_commit_url(@project, :id => commit.id) | ||
12 | + xml.link :href => project_commit_url(@project, :id => commit.id) | ||
13 | + xml.title truncate(commit.title, :length => 80) | ||
14 | + xml.updated commit.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ") | ||
15 | + xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(commit.author_email) | ||
16 | + xml.author do |author| | ||
17 | + xml.name commit.author_name | ||
18 | + xml.email commit.author_email | ||
19 | + end | ||
20 | + xml.summary gfm(commit.description) | ||
21 | + end | ||
22 | + end | ||
23 | +end |
app/views/commits/show.html.haml
1 | -= render "commits/commit_box" | ||
2 | -= render "commits/diffs", diffs: @commit.diffs | ||
3 | -= render "notes/notes_with_form", tid: @commit.id, tt: "commit" | ||
4 | -= render "notes/per_line_form" | 1 | += render "head" |
5 | 2 | ||
3 | +- if @path.present? | ||
4 | + %ul.breadcrumb | ||
5 | + %li | ||
6 | + %span.arrow | ||
7 | + = link_to project_commits_path(@project) do | ||
8 | + = @project.name | ||
9 | + %span.divider | ||
10 | + \/ | ||
11 | + %li | ||
12 | + %a{href: "#"}= @path.split("/").join(" / ") | ||
13 | + | ||
14 | +%div{id: dom_id(@project)} | ||
15 | + #commits_list= render "commits" | ||
16 | +.clear | ||
17 | +.loading{ style: "display:none;"} | ||
18 | + | ||
19 | +- if @commits.count == @limit | ||
20 | + :javascript | ||
21 | + $(function(){ | ||
22 | + CommitsList.init("#{@ref}", #{@limit}); | ||
23 | + }); | ||
6 | 24 | ||
7 | -:javascript | ||
8 | - $(function(){ | ||
9 | - PerLineNotes.init(); | ||
10 | - }); |
@@ -0,0 +1,32 @@ | @@ -0,0 +1,32 @@ | ||
1 | +%div | ||
2 | + %p.slead | ||
3 | + Fill input field with commit id like | ||
4 | + %code.label_branch 4eedf23 | ||
5 | + or branch/tag name like | ||
6 | + %code.label_branch master | ||
7 | + and press compare button for commits list, code diff. | ||
8 | + | ||
9 | + %br | ||
10 | + | ||
11 | + = form_tag project_compare_index_path(@project), method: :post do | ||
12 | + .clearfix | ||
13 | + = text_field_tag :from, params[:from], placeholder: "master", class: "xlarge" | ||
14 | + = "..." | ||
15 | + = text_field_tag :to, params[:to], placeholder: "aa8b4ef", class: "xlarge" | ||
16 | + - if @refs_are_same | ||
17 | + .alert | ||
18 | + %span Refs are the same | ||
19 | + .actions | ||
20 | + = submit_tag "Compare", class: "btn primary wide commits-compare-btn" | ||
21 | + | ||
22 | +:javascript | ||
23 | + $(function() { | ||
24 | + var availableTags = #{@project.ref_names.to_json}; | ||
25 | + | ||
26 | + $("#from, #to").autocomplete({ | ||
27 | + source: availableTags, | ||
28 | + minLength: 1 | ||
29 | + }); | ||
30 | + | ||
31 | + disableButtonIfEmptyField('#to', '.commits-compare-btn'); | ||
32 | + }); |
@@ -0,0 +1,16 @@ | @@ -0,0 +1,16 @@ | ||
1 | += render "commits/head" | ||
2 | + | ||
3 | +%h3.page_title | ||
4 | + Compare View | ||
5 | +%hr | ||
6 | + | ||
7 | += render "form" | ||
8 | + | ||
9 | +- if @commits.present? | ||
10 | + %div.ui-box | ||
11 | + %h5.small Commits (#{@commits.count}) | ||
12 | + %ul.unstyled= render @commits | ||
13 | + | ||
14 | + - unless @diffs.empty? | ||
15 | + %h4 Diff | ||
16 | + = render "commits/diffs", diffs: @diffs |
app/views/events/_commit.html.haml
1 | - commit = CommitDecorator.decorate(commit) | 1 | - commit = CommitDecorator.decorate(commit) |
2 | %li.commit | 2 | %li.commit |
3 | %p | 3 | %p |
4 | - = link_to commit.short_id(8), project_commit_path(project, id: commit.id), class: "commit_short_id" | 4 | + = link_to commit.short_id(8), project_commit_path(project, commit), class: "commit_short_id" |
5 | %span= commit.author_name | 5 | %span= commit.author_name |
6 | – | 6 | – |
7 | = image_tag gravatar_icon(commit.author_email), class: "avatar", width: 16 | 7 | = image_tag gravatar_icon(commit.author_email), class: "avatar", width: 16 |
app/views/events/_event_last_push.html.haml
@@ -4,7 +4,7 @@ | @@ -4,7 +4,7 @@ | ||
4 | = image_tag gravatar_icon(event.author_email), class: "avatar" | 4 | = image_tag gravatar_icon(event.author_email), class: "avatar" |
5 | %span You pushed to | 5 | %span You pushed to |
6 | = event.ref_type | 6 | = event.ref_type |
7 | - = link_to project_commits_path(event.project, ref: event.ref_name) do | 7 | + = link_to project_commits_path(event.project, event.ref_name) do |
8 | %strong= truncate(event.ref_name, length: 28) | 8 | %strong= truncate(event.ref_name, length: 28) |
9 | at | 9 | at |
10 | %strong= link_to event.project.name, event.project | 10 | %strong= link_to event.project.name, event.project |
app/views/events/_event_push.html.haml
@@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
5 | .event-title | 5 | .event-title |
6 | %strong.author_name #{event.author_name} | 6 | %strong.author_name #{event.author_name} |
7 | %span.event_label.pushed #{event.push_action_name} #{event.ref_type} | 7 | %span.event_label.pushed #{event.push_action_name} #{event.ref_type} |
8 | - = link_to project_commits_path(event.project, ref: event.ref_name) do | 8 | + = link_to project_commits_path(event.project, event.ref_name) do |
9 | %strong= event.ref_name | 9 | %strong= event.ref_name |
10 | at | 10 | at |
11 | %strong= link_to event.project.name, event.project | 11 | %strong= link_to event.project.name, event.project |
@@ -21,6 +21,6 @@ | @@ -21,6 +21,6 @@ | ||
21 | %li.commits-stat | 21 | %li.commits-stat |
22 | - if event.commits_count > 2 | 22 | - if event.commits_count > 2 |
23 | %span ... and #{event.commits_count - 2} more commits. | 23 | %span ... and #{event.commits_count - 2} more commits. |
24 | - = link_to compare_project_commits_path(event.project, from: event.parent_commit.id, to: event.last_commit.id) do | 24 | + = link_to project_compare_path(event.project, from: event.parent_commit.id, to: event.last_commit.id) do |
25 | %strong Compare → #{event.parent_commit.id[0..7]}...#{event.last_commit.id[0..7]} | 25 | %strong Compare → #{event.parent_commit.id[0..7]}...#{event.last_commit.id[0..7]} |
26 | .clearfix | 26 | .clearfix |
app/views/issues/_head.html.haml
1 | %ul.nav.nav-tabs | 1 | %ul.nav.nav-tabs |
2 | - %li{class: "#{'active' if current_page?(project_issues_path(@project))}"} | ||
3 | - = link_to project_issues_path(@project), class: "tab" do | ||
4 | - Browse Issues | ||
5 | - %li{class: "#{'active' if current_page?(project_milestones_path(@project))}"} | ||
6 | - = link_to project_milestones_path(@project), class: "tab" do | ||
7 | - Milestones | ||
8 | - %li{class: "#{'active' if current_page?(project_labels_path(@project))}"} | ||
9 | - = link_to project_labels_path(@project), class: "tab" do | ||
10 | - Labels | 2 | + = nav_link(controller: :issues) do |
3 | + = link_to 'Browse Issues', project_issues_path(@project), class: "tab" | ||
4 | + = nav_link(controller: :milestones) do | ||
5 | + = link_to 'Milestones', project_milestones_path(@project), class: "tab" | ||
6 | + = nav_link(controller: :labels) do | ||
7 | + = link_to 'Labels', project_labels_path(@project), class: "tab" | ||
11 | %li.right | 8 | %li.right |
12 | %span.rss-icon | 9 | %span.rss-icon |
13 | = link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do | 10 | = link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do |
app/views/layouts/_app_menu.html.haml
@@ -1,19 +0,0 @@ | @@ -1,19 +0,0 @@ | ||
1 | -%ul.main_menu | ||
2 | - %li.home{class: tab_class(:root)} | ||
3 | - = link_to "Home", root_path, title: "Home" | ||
4 | - | ||
5 | - %li{class: tab_class(:dash_issues)} | ||
6 | - = link_to dashboard_issues_path do | ||
7 | - Issues | ||
8 | - %span.count= current_user.assigned_issues.opened.count | ||
9 | - | ||
10 | - %li{class: tab_class(:dash_mr)} | ||
11 | - = link_to dashboard_merge_requests_path do | ||
12 | - Merge Requests | ||
13 | - %span.count= current_user.cared_merge_requests.count | ||
14 | - | ||
15 | - %li{class: tab_class(:search)} | ||
16 | - = link_to "Search", search_path | ||
17 | - | ||
18 | - %li{class: tab_class(:help)} | ||
19 | - = link_to "Help", help_path |
app/views/layouts/_head.html.haml
@@ -10,8 +10,8 @@ | @@ -10,8 +10,8 @@ | ||
10 | - if controller_name == 'projects' && action_name == 'index' | 10 | - if controller_name == 'projects' && action_name == 'index' |
11 | = auto_discovery_link_tag :atom, projects_url(:atom, private_token: current_user.private_token), title: "Dashboard feed" | 11 | = auto_discovery_link_tag :atom, projects_url(:atom, private_token: current_user.private_token), title: "Dashboard feed" |
12 | - if @project && !@project.new_record? | 12 | - if @project && !@project.new_record? |
13 | - - if current_page?(tree_project_ref_path(@project, @project.root_ref)) || current_page?(project_commits_path(@project)) | ||
14 | - = 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}") | ||
15 | - - if request.path == project_issues_path(@project) | 13 | + - if current_controller?(:tree, :commits) |
14 | + = 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}") | ||
15 | + - if current_controller?(:issues) | ||
16 | = auto_discovery_link_tag(:atom, project_issues_url(@project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues") | 16 | = auto_discovery_link_tag(:atom, project_issues_url(@project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues") |
17 | = csrf_meta_tags | 17 | = csrf_meta_tags |
app/views/layouts/_project_menu.html.haml
@@ -1,37 +0,0 @@ | @@ -1,37 +0,0 @@ | ||
1 | -%ul.main_menu | ||
2 | - %li.home{class: project_tab_class} | ||
3 | - = link_to @project.code, project_path(@project), title: "Project" | ||
4 | - | ||
5 | - - if @project.repo_exists? | ||
6 | - - if can? current_user, :download_code, @project | ||
7 | - %li{class: tree_tab_class} | ||
8 | - = link_to tree_project_ref_path(@project, @project.root_ref) do | ||
9 | - Files | ||
10 | - %li{class: commit_tab_class} | ||
11 | - = link_to "Commits", project_commits_path(@project) | ||
12 | - | ||
13 | - %li{class: tab_class(:network)} | ||
14 | - = link_to "Network", graph_project_path(@project) | ||
15 | - | ||
16 | - - if @project.issues_enabled | ||
17 | - %li{class: tab_class(:issues)} | ||
18 | - = link_to project_issues_filter_path(@project) do | ||
19 | - Issues | ||
20 | - %span.count.issue_counter= @project.issues.opened.count | ||
21 | - | ||
22 | - - if @project.repo_exists? | ||
23 | - - if @project.merge_requests_enabled | ||
24 | - %li{class: tab_class(:merge_requests)} | ||
25 | - = link_to project_merge_requests_path(@project) do | ||
26 | - Merge Requests | ||
27 | - %span.count.merge_counter= @project.merge_requests.opened.count | ||
28 | - | ||
29 | - - if @project.wall_enabled | ||
30 | - %li{class: tab_class(:wall)} | ||
31 | - = link_to wall_project_path(@project) do | ||
32 | - Wall | ||
33 | - | ||
34 | - - if @project.wiki_enabled | ||
35 | - %li{class: tab_class(:wiki)} | ||
36 | - = link_to project_wiki_path(@project, :index) do | ||
37 | - Wiki |
app/views/layouts/admin.html.haml
@@ -6,17 +6,17 @@ | @@ -6,17 +6,17 @@ | ||
6 | = render "layouts/head_panel", title: "Admin area" | 6 | = render "layouts/head_panel", title: "Admin area" |
7 | .container | 7 | .container |
8 | %ul.main_menu | 8 | %ul.main_menu |
9 | - %li.home{class: tab_class(:admin_root)} | 9 | + = nav_link(controller: :dashboard, html_options: {class: 'home'}) do |
10 | = link_to "Stats", admin_root_path | 10 | = link_to "Stats", admin_root_path |
11 | - %li{class: tab_class(:admin_projects)} | 11 | + = nav_link(controller: :projects) do |
12 | = link_to "Projects", admin_projects_path | 12 | = link_to "Projects", admin_projects_path |
13 | - %li{class: tab_class(:admin_users)} | 13 | + = nav_link(controller: :users) do |
14 | = link_to "Users", admin_users_path | 14 | = link_to "Users", admin_users_path |
15 | - %li{class: tab_class(:admin_logs)} | 15 | + = nav_link(controller: :logs) do |
16 | = link_to "Logs", admin_logs_path | 16 | = link_to "Logs", admin_logs_path |
17 | - %li{class: tab_class(:admin_hooks)} | 17 | + = nav_link(controller: :hooks) do |
18 | = link_to "Hooks", admin_hooks_path | 18 | = link_to "Hooks", admin_hooks_path |
19 | - %li{class: tab_class(:admin_resque)} | 19 | + = nav_link(controller: :resque) do |
20 | = link_to "Resque", admin_resque_path | 20 | = link_to "Resque", admin_resque_path |
21 | 21 | ||
22 | .content= yield | 22 | .content= yield |
app/views/layouts/application.html.haml
@@ -5,6 +5,20 @@ | @@ -5,6 +5,20 @@ | ||
5 | = render "layouts/flash" | 5 | = render "layouts/flash" |
6 | = render "layouts/head_panel", title: "Dashboard" | 6 | = render "layouts/head_panel", title: "Dashboard" |
7 | .container | 7 | .container |
8 | - = render partial: "layouts/app_menu" | ||
9 | - .content | ||
10 | - = yield | 8 | + %ul.main_menu |
9 | + = nav_link(path: 'dashboard#index', html_options: {class: 'home'}) do | ||
10 | + = link_to "Home", root_path, title: "Home" | ||
11 | + = nav_link(path: 'dashboard#issues') do | ||
12 | + = link_to dashboard_issues_path do | ||
13 | + Issues | ||
14 | + %span.count= current_user.assigned_issues.opened.count | ||
15 | + = nav_link(path: 'dashboard#merge_requests') do | ||
16 | + = link_to dashboard_merge_requests_path do | ||
17 | + Merge Requests | ||
18 | + %span.count= current_user.cared_merge_requests.count | ||
19 | + = nav_link(path: 'search#show') do | ||
20 | + = link_to "Search", search_path | ||
21 | + = nav_link(path: 'help#index') do | ||
22 | + = link_to "Help", help_path | ||
23 | + | ||
24 | + .content= yield |
app/views/layouts/profile.html.haml
@@ -6,23 +6,17 @@ | @@ -6,23 +6,17 @@ | ||
6 | = render "layouts/head_panel", title: "Profile" | 6 | = render "layouts/head_panel", title: "Profile" |
7 | .container | 7 | .container |
8 | %ul.main_menu | 8 | %ul.main_menu |
9 | - %li.home{class: tab_class(:profile)} | 9 | + = nav_link(path: 'profile#show', html_options: {class: 'home'}) do |
10 | = link_to "Profile", profile_path | 10 | = link_to "Profile", profile_path |
11 | - | ||
12 | - %li{class: tab_class(:account)} | 11 | + = nav_link(path: 'profile#account') do |
13 | = link_to "Account", profile_account_path | 12 | = link_to "Account", profile_account_path |
14 | - | ||
15 | - %li{class: tab_class(:ssh_keys)} | 13 | + = nav_link(controller: :keys) do |
16 | = link_to keys_path do | 14 | = link_to keys_path do |
17 | SSH Keys | 15 | SSH Keys |
18 | %span.count= current_user.keys.count | 16 | %span.count= current_user.keys.count |
19 | - | ||
20 | - %li{class: tab_class(:design)} | 17 | + = nav_link(path: 'profile#design') do |
21 | = link_to "Design", profile_design_path | 18 | = link_to "Design", profile_design_path |
22 | - | ||
23 | - %li{class: tab_class(:history)} | 19 | + = nav_link(path: 'profile#history') do |
24 | = link_to "History", profile_history_path | 20 | = link_to "History", profile_history_path |
25 | 21 | ||
26 | - | ||
27 | - .content | ||
28 | - = yield | 22 | + .content= yield |
app/views/layouts/project.html.haml
@@ -5,7 +5,37 @@ | @@ -5,7 +5,37 @@ | ||
5 | = render "layouts/flash" | 5 | = render "layouts/flash" |
6 | = render "layouts/head_panel", title: @project.name | 6 | = render "layouts/head_panel", title: @project.name |
7 | .container | 7 | .container |
8 | - = render partial: "layouts/project_menu" | ||
9 | - .content | ||
10 | - = yield | 8 | + %ul.main_menu |
9 | + = nav_link(html_options: {class: "home #{project_tab_class}"}) do | ||
10 | + = link_to @project.code, project_path(@project), title: "Project" | ||
11 | 11 | ||
12 | + - if @project.repo_exists? | ||
13 | + - if can? current_user, :download_code, @project | ||
14 | + = nav_link(controller: %w(tree blob blame)) do | ||
15 | + = link_to 'Files', project_tree_path(@project, @ref || @project.root_ref) | ||
16 | + = nav_link(controller: %w(commit commits compare repositories protected_branches)) do | ||
17 | + = link_to "Commits", project_commits_path(@project, @ref || @project.root_ref) | ||
18 | + = nav_link(path: 'projects#graph') do | ||
19 | + = link_to "Network", graph_project_path(@project) | ||
20 | + | ||
21 | + - if @project.issues_enabled | ||
22 | + = nav_link(controller: %w(issues milestones labels)) do | ||
23 | + = link_to project_issues_filter_path(@project) do | ||
24 | + Issues | ||
25 | + %span.count.issue_counter= @project.issues.opened.count | ||
26 | + | ||
27 | + - if @project.repo_exists? && @project.merge_requests_enabled | ||
28 | + = nav_link(controller: :merge_requests) do | ||
29 | + = link_to project_merge_requests_path(@project) do | ||
30 | + Merge Requests | ||
31 | + %span.count.merge_counter= @project.merge_requests.opened.count | ||
32 | + | ||
33 | + - if @project.wall_enabled | ||
34 | + = nav_link(path: 'projects#wall') do | ||
35 | + = link_to 'Wall', wall_project_path(@project) | ||
36 | + | ||
37 | + - if @project.wiki_enabled | ||
38 | + = nav_link(controller: :wikis) do | ||
39 | + = link_to 'Wiki', project_wiki_path(@project, :index) | ||
40 | + | ||
41 | + .content= yield |
app/views/projects/_project_head.html.haml
1 | %ul.nav.nav-tabs | 1 | %ul.nav.nav-tabs |
2 | - %li{ class: "#{'active' if current_page?(project_path(@project)) }" } | 2 | + = nav_link(path: 'projects#show') do |
3 | = link_to project_path(@project), class: "activities-tab tab" do | 3 | = link_to project_path(@project), class: "activities-tab tab" do |
4 | %i.icon-home | 4 | %i.icon-home |
5 | Show | 5 | Show |
6 | - %li{ class: " #{'active' if (controller.controller_name == "team_members") || current_page?(project_team_index_path(@project)) }" } | 6 | + = nav_link(controller: :team_members) do |
7 | = link_to project_team_index_path(@project), class: "team-tab tab" do | 7 | = link_to project_team_index_path(@project), class: "team-tab tab" do |
8 | %i.icon-user | 8 | %i.icon-user |
9 | Team | 9 | Team |
10 | - %li{ class: "#{'active' if current_page?(files_project_path(@project)) }" } | ||
11 | - = link_to files_project_path(@project), class: "files-tab tab " do | ||
12 | - Attachments | ||
13 | - %li{ class: " #{'active' if (controller.controller_name == "snippets") }" } | ||
14 | - = link_to project_snippets_path(@project), class: "snippets-tab tab" do | ||
15 | - Snippets | 10 | + = nav_link(path: 'projects#files') do |
11 | + = link_to 'Attachments', files_project_path(@project), class: "files-tab tab" | ||
12 | + = nav_link(controller: :snippets) do | ||
13 | + = link_to 'Snippets', project_snippets_path(@project), class: "snippets-tab tab" | ||
16 | 14 | ||
17 | - if can? current_user, :admin_project, @project | 15 | - if can? current_user, :admin_project, @project |
18 | - %li.right{class: "#{'active' if controller.controller_name == "deploy_keys"}"} | 16 | + = nav_link(controller: :deploy_keys, html_options: {class: 'right'}) do |
19 | = link_to project_deploy_keys_path(@project) do | 17 | = link_to project_deploy_keys_path(@project) do |
20 | %span | 18 | %span |
21 | Deploy Keys | 19 | Deploy Keys |
22 | - %li.right{class: "#{'active' if controller.controller_name == "hooks" }"} | 20 | + = nav_link(controller: :hooks, html_options: {class: 'right'}) do |
23 | = link_to project_hooks_path(@project) do | 21 | = link_to project_hooks_path(@project) do |
24 | %span | 22 | %span |
25 | Hooks | 23 | Hooks |
26 | - %li.right{ class: "#{'active' if current_page?(edit_project_path(@project)) }" } | 24 | + = nav_link(path: 'projects#edit', html_options: {class: 'right'}) do |
27 | = link_to edit_project_path(@project), class: "stat-tab tab " do | 25 | = link_to edit_project_path(@project), class: "stat-tab tab " do |
28 | %i.icon-edit | 26 | %i.icon-edit |
29 | Edit | 27 | Edit |
app/views/protected_branches/index.html.haml
@@ -34,7 +34,7 @@ | @@ -34,7 +34,7 @@ | ||
34 | - @branches.each do |branch| | 34 | - @branches.each do |branch| |
35 | %tr | 35 | %tr |
36 | %td | 36 | %td |
37 | - = link_to project_commits_path(@project, ref: branch.name) do | 37 | + = link_to project_commits_path(@project, branch.name) do |
38 | %strong= branch.name | 38 | %strong= branch.name |
39 | - if branch.name == @project.root_ref | 39 | - if branch.name == @project.root_ref |
40 | %span.label default | 40 | %span.label default |
app/views/refs/_head.html.haml
@@ -1,11 +0,0 @@ | @@ -1,11 +0,0 @@ | ||
1 | -%ul.nav.nav-tabs | ||
2 | - %li | ||
3 | - = render partial: 'shared/ref_switcher', locals: {destination: 'tree', path: params[:path]} | ||
4 | - %li{class: "#{'active' if (controller.controller_name == "refs") }"} | ||
5 | - = link_to tree_project_ref_path(@project, @ref) do | ||
6 | - Source | ||
7 | - %li.right | ||
8 | - .input-prepend.project_clone_holder | ||
9 | - %button{class: "btn small active", :"data-clone" => @project.ssh_url_to_repo} SSH | ||
10 | - %button{class: "btn small", :"data-clone" => @project.http_url_to_repo} HTTP | ||
11 | - = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select span5" |
app/views/refs/_submodule_item.html.haml
@@ -1,13 +0,0 @@ | @@ -1,13 +0,0 @@ | ||
1 | -- url = content.url(@ref) rescue nil | ||
2 | -- name = content.basename | ||
3 | -- return unless url | ||
4 | -%tr{ class: "tree-item", url: url } | ||
5 | - %td.tree-item-file-name | ||
6 | - = image_tag "submodule.png" | ||
7 | - %strong= truncate(name, length: 40) | ||
8 | - %td | ||
9 | - %code= content.id[0..10] | ||
10 | - %td | ||
11 | - = link_to truncate(url, length: 40), url | ||
12 | - | ||
13 | - |
app/views/refs/_tree.html.haml
@@ -1,70 +0,0 @@ | @@ -1,70 +0,0 @@ | ||
1 | -%ul.breadcrumb | ||
2 | - %li | ||
3 | - %span.arrow | ||
4 | - = link_to tree_project_ref_path(@project, @ref, path: nil), remote: true do | ||
5 | - = @project.name | ||
6 | - - tree.breadcrumbs(6) do |link| | ||
7 | - \/ | ||
8 | - %li= link | ||
9 | -.clear | ||
10 | -%div.tree_progress | ||
11 | -#tree-content-holder | ||
12 | - - if tree.is_blob? | ||
13 | - = render partial: "refs/tree_file", locals: { name: tree.name, content: tree.data, file: tree } | ||
14 | - - else | ||
15 | - - contents = tree.contents | ||
16 | - %table#tree-slider{class: "table_#{@hex_path}" } | ||
17 | - %thead | ||
18 | - %th Name | ||
19 | - %th Last Update | ||
20 | - %th | ||
21 | - Last commit | ||
22 | - = link_to "History", tree.history_path, class: "right" | ||
23 | - | ||
24 | - - if tree.up_dir? | ||
25 | - %tr{ class: "tree-item", url: tree.up_dir_path } | ||
26 | - %td.tree-item-file-name | ||
27 | - = image_tag "file_empty.png" | ||
28 | - = link_to "..", tree.up_dir_path, remote: :true | ||
29 | - %td | ||
30 | - %td | ||
31 | - | ||
32 | - - index = 0 | ||
33 | - - contents.select{ |i| i.is_a?(Grit::Tree)}.each do |content| | ||
34 | - = render partial: "refs/tree_item", locals: { content: content, index: (index += 1) } | ||
35 | - - contents.select{ |i| i.is_a?(Grit::Blob)}.each do |content| | ||
36 | - = render partial: "refs/tree_item", locals: { content: content, index: (index += 1) } | ||
37 | - - contents.select{ |i| i.is_a?(Grit::Submodule)}.each do |content| | ||
38 | - = render partial: "refs/submodule_item", locals: { content: content, index: (index += 1) } | ||
39 | - | ||
40 | - - if content = contents.select{ |c| c.is_a?(Grit::Blob) and c.name =~ /^readme/i }.first | ||
41 | - .file_holder#README | ||
42 | - .file_title | ||
43 | - %i.icon-file | ||
44 | - = content.name | ||
45 | - .file_content.wiki | ||
46 | - - if gitlab_markdown?(content.name) | ||
47 | - = preserve do | ||
48 | - = markdown(content.data) | ||
49 | - - else | ||
50 | - = raw GitHub::Markup.render(content.name, content.data) | ||
51 | - | ||
52 | -:javascript | ||
53 | - $(function(){ | ||
54 | - history.pushState({ path: this.path }, '', "#{@history_path}"); | ||
55 | - }); | ||
56 | - | ||
57 | -- unless tree.is_blob? | ||
58 | - :javascript | ||
59 | - // Load last commit log for each file in tree | ||
60 | - $(window).load(function(){ | ||
61 | - ajaxGet('#{@logs_path}'); | ||
62 | - }); | ||
63 | - | ||
64 | -- if params[:path] && request.xhr? | ||
65 | - :javascript | ||
66 | - $(window).unbind('popstate'); | ||
67 | - $(window).bind('popstate', function() { | ||
68 | - if(location.pathname.search("tree") != -1) { | ||
69 | - $.ajax({type: "GET", url: location.pathname, dataType: "script"})} | ||
70 | - else { location.href = location.pathname;}}); |
app/views/refs/_tree_commit.html.haml
app/views/refs/_tree_file.html.haml
@@ -1,40 +0,0 @@ | @@ -1,40 +0,0 @@ | ||
1 | -.file_holder | ||
2 | - .file_title | ||
3 | - %i.icon-file | ||
4 | - %span.file_name | ||
5 | - = name.force_encoding('utf-8') | ||
6 | - %small #{file.mode} | ||
7 | - %span.options | ||
8 | - = link_to "raw", blob_project_ref_path(@project, @ref, path: params[:path]), class: "btn very_small", target: "_blank" | ||
9 | - = link_to "history", project_commits_path(@project, path: params[:path], ref: @ref), class: "btn very_small" | ||
10 | - = link_to "blame", blame_file_project_ref_path(@project, @ref, path: params[:path]), class: "btn very_small" | ||
11 | - - if file.text? | ||
12 | - - if gitlab_markdown?(name) | ||
13 | - .file_content.wiki | ||
14 | - = preserve do | ||
15 | - = markdown(file.data) | ||
16 | - - elsif markup?(name) | ||
17 | - .file_content.wiki | ||
18 | - = raw GitHub::Markup.render(name, file.data) | ||
19 | - - else | ||
20 | - .file_content.code | ||
21 | - - unless file.empty? | ||
22 | - %div{class: current_user.dark_scheme ? "black" : "white"} | ||
23 | - = preserve do | ||
24 | - = raw file.colorize(options: { linenos: 'True'}) | ||
25 | - - else | ||
26 | - %h4.nothing_here_message Empty file | ||
27 | - | ||
28 | - - elsif file.image? | ||
29 | - .file_content.image_file | ||
30 | - %img{ src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} | ||
31 | - | ||
32 | - - else | ||
33 | - .file_content.blob_file | ||
34 | - %center | ||
35 | - = link_to blob_project_ref_path(@project, @ref, path: params[:path]) do | ||
36 | - %div.padded | ||
37 | - %br | ||
38 | - = image_tag "download.png", width: 64 | ||
39 | - %h3 | ||
40 | - Download (#{file.mb_size}) |
app/views/refs/_tree_item.html.haml
@@ -1,11 +0,0 @@ | @@ -1,11 +0,0 @@ | ||
1 | -- file = tree_full_path(content) | ||
2 | -%tr{ class: "tree-item #{tree_hex_class(content)}", url: tree_file_project_ref_path(@project, @ref, file) } | ||
3 | - %td.tree-item-file-name | ||
4 | - = tree_icon(content) | ||
5 | - %strong= link_to truncate(content.name, length: 40), tree_file_project_ref_path(@project, @ref || @commit.id, file), remote: :true | ||
6 | - %td.tree_time_ago.cgray | ||
7 | - - if index == 1 | ||
8 | - %span.log_loading | ||
9 | - Loading commit data.. | ||
10 | - = image_tag "ajax_loader_tree.gif", width: 14 | ||
11 | - %td.tree_commit |
app/views/refs/blame.html.haml
@@ -1,40 +0,0 @@ | @@ -1,40 +0,0 @@ | ||
1 | -= render "head" | ||
2 | - | ||
3 | -#tree-holder | ||
4 | - %ul.breadcrumb | ||
5 | - %li | ||
6 | - %span.arrow | ||
7 | - = link_to tree_project_ref_path(@project, @ref, path: nil) do | ||
8 | - = @project.name | ||
9 | - - @tree.breadcrumbs(6) do |link| | ||
10 | - \/ | ||
11 | - %li= link | ||
12 | - .clear | ||
13 | - | ||
14 | - .file_holder | ||
15 | - .file_title | ||
16 | - %i.icon-file | ||
17 | - %span.file_name | ||
18 | - = @tree.name | ||
19 | - %small blame | ||
20 | - %span.options | ||
21 | - = link_to "raw", blob_project_ref_path(@project, @ref, path: params[:path]), class: "btn very_small", target: "_blank" | ||
22 | - = link_to "history", project_commits_path(@project, path: params[:path], ref: @ref), class: "btn very_small" | ||
23 | - = link_to "source", tree_file_project_ref_path(@project, @ref, path: params[:path]), class: "btn very_small" | ||
24 | - .file_content.blame | ||
25 | - %table | ||
26 | - - @blame.each do |commit, lines| | ||
27 | - - commit = Commit.new(commit) | ||
28 | - - commit = CommitDecorator.decorate(commit) | ||
29 | - %tr | ||
30 | - %td.author | ||
31 | - = image_tag gravatar_icon(commit.author_email, 16) | ||
32 | - = commit.author_name | ||
33 | - %td.blame_commit | ||
34 | - | ||
35 | - %code= link_to commit.short_id, project_commit_path(@project, id: commit.id) | ||
36 | - = link_to_gfm truncate(commit.title, length: 30), project_commit_path(@project, id: commit.id), class: "row_title" rescue "--broken encoding" | ||
37 | - %td.lines | ||
38 | - = preserve do | ||
39 | - %pre | ||
40 | - = Gitlab::Encode.utf8 lines.join("\n") |
app/views/refs/logs_tree.js.haml
@@ -6,4 +6,4 @@ | @@ -6,4 +6,4 @@ | ||
6 | :plain | 6 | :plain |
7 | var row = $("table.table_#{@hex_path} tr.file_#{hexdigest(file_name)}"); | 7 | var row = $("table.table_#{@hex_path} tr.file_#{hexdigest(file_name)}"); |
8 | row.find("td.tree_time_ago").html('#{escape_javascript(time_ago_in_words(content_commit.committed_date))} ago'); | 8 | row.find("td.tree_time_ago").html('#{escape_javascript(time_ago_in_words(content_commit.committed_date))} ago'); |
9 | - row.find("td.tree_commit").html('#{escape_javascript(render("tree_commit", tm: tm, content_commit: content_commit))}'); | 9 | + row.find("td.tree_commit").html('#{escape_javascript(render("tree/tree_commit", tm: tm, content_commit: content_commit))}'); |
app/views/refs/tree.html.haml
app/views/refs/tree.js.haml
@@ -1,10 +0,0 @@ | @@ -1,10 +0,0 @@ | ||
1 | -:plain | ||
2 | - // Load Files list | ||
3 | - $("#tree-holder").html("#{escape_javascript(render(partial: "tree", locals: {repo: @repo, commit: @commit, tree: @tree}))}"); | ||
4 | - $("#tree-content-holder").show("slide", { direction: "right" }, 150); | ||
5 | - $('.project-refs-form #path').val("#{params[:path]}"); | ||
6 | - | ||
7 | - // Load last commit log for each file in tree | ||
8 | - $('#tree-slider').waitForImages(function() { | ||
9 | - ajaxGet('#{@logs_path}'); | ||
10 | - }); |
app/views/repositories/_branch.html.haml
@@ -2,12 +2,12 @@ | @@ -2,12 +2,12 @@ | ||
2 | - commit = CommitDecorator.decorate(commit) | 2 | - commit = CommitDecorator.decorate(commit) |
3 | %tr | 3 | %tr |
4 | %td | 4 | %td |
5 | - = link_to project_commits_path(@project, ref: branch.name) do | 5 | + = link_to project_commits_path(@project, branch.name) do |
6 | %strong= truncate(branch.name, length: 60) | 6 | %strong= truncate(branch.name, length: 60) |
7 | - if branch.name == @project.root_ref | 7 | - if branch.name == @project.root_ref |
8 | %span.label default | 8 | %span.label default |
9 | %td | 9 | %td |
10 | - = link_to project_commit_path(@project, id: commit.id) do | 10 | + = link_to project_commit_path(@project, commit) do |
11 | %code= commit.short_id | 11 | %code= commit.short_id |
12 | 12 | ||
13 | = image_tag gravatar_icon(commit.author_email), class: "", width: 16 | 13 | = image_tag gravatar_icon(commit.author_email), class: "", width: 16 |
app/views/repositories/_branches_head.html.haml
1 | = render "commits/head" | 1 | = render "commits/head" |
2 | %ul.nav.nav-pills | 2 | %ul.nav.nav-pills |
3 | - %li{class: ("active" if current_page?(project_repository_path(@project)))} | ||
4 | - = link_to project_repository_path(@project) do | ||
5 | - Recent | ||
6 | - %li{class: ("active" if current_page?(project_protected_branches_path(@project)))} | ||
7 | - = link_to project_protected_branches_path(@project) do | ||
8 | - Protected | ||
9 | - %li{class: ("active" if current_page?(branches_project_repository_path(@project)))} | ||
10 | - = link_to branches_project_repository_path(@project) do | ||
11 | - All | 3 | + = nav_link(path: 'repositories#show') do |
4 | + = link_to 'Recent', project_repository_path(@project) | ||
5 | + = nav_link(path: 'protected_branches#index') do | ||
6 | + = link_to 'Protected', project_protected_branches_path(@project) | ||
7 | + = nav_link(path: 'repositories#branches') do | ||
8 | + = link_to 'All', branches_project_repository_path(@project) |
app/views/repositories/_feed.html.haml
@@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
2 | - commit = CommitDecorator.new(commit) | 2 | - commit = CommitDecorator.new(commit) |
3 | %tr | 3 | %tr |
4 | %td | 4 | %td |
5 | - = link_to project_commits_path(@project, ref: commit.head.name) do | 5 | + = link_to project_commits_path(@project, commit.head.name) do |
6 | %strong | 6 | %strong |
7 | = commit.head.name | 7 | = commit.head.name |
8 | - if commit.head.name == @project.root_ref | 8 | - if commit.head.name == @project.root_ref |
app/views/repositories/tags.html.haml
@@ -12,7 +12,7 @@ | @@ -12,7 +12,7 @@ | ||
12 | - commit = CommitDecorator.decorate(commit) | 12 | - commit = CommitDecorator.decorate(commit) |
13 | %tr | 13 | %tr |
14 | %td | 14 | %td |
15 | - %strong= link_to tag.name, project_commits_path(@project, ref: tag.name), class: "" | 15 | + %strong= link_to tag.name, project_commits_path(@project, tag.name), class: "" |
16 | %td | 16 | %td |
17 | = link_to project_commit_path(@project, commit.id) do | 17 | = link_to project_commit_path(@project, commit.id) do |
18 | %code= commit.short_id | 18 | %code= commit.short_id |
app/views/shared/_ref_switcher.html.haml
1 | = form_tag switch_project_refs_path(@project), method: :get, class: "project-refs-form" do | 1 | = form_tag switch_project_refs_path(@project), method: :get, class: "project-refs-form" do |
2 | = select_tag "ref", grouped_options_refs, class: "project-refs-select chosen" | 2 | = select_tag "ref", grouped_options_refs, class: "project-refs-select chosen" |
3 | = hidden_field_tag :destination, destination | 3 | = hidden_field_tag :destination, destination |
4 | - - if respond_to?(:path) | 4 | + - if defined?(path) |
5 | = hidden_field_tag :path, path | 5 | = hidden_field_tag :path, path |
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +%ul.nav.nav-tabs | ||
2 | + %li | ||
3 | + = render partial: 'shared/ref_switcher', locals: {destination: 'tree', path: @path} | ||
4 | + = nav_link(controller: :tree) do | ||
5 | + = link_to 'Source', project_tree_path(@project, @ref) | ||
6 | + %li.right | ||
7 | + .input-prepend.project_clone_holder | ||
8 | + %button{class: "btn small active", :"data-clone" => @project.ssh_url_to_repo} SSH | ||
9 | + %button{class: "btn small", :"data-clone" => @project.http_url_to_repo} HTTP | ||
10 | + = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select span5" |
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +- url = content.url(@ref) rescue nil | ||
2 | +- name = content.basename | ||
3 | +- return unless url | ||
4 | +%tr{ class: "tree-item", url: url } | ||
5 | + %td.tree-item-file-name | ||
6 | + = image_tag "submodule.png" | ||
7 | + %strong= truncate(name, length: 40) | ||
8 | + %td | ||
9 | + %code= content.id[0..10] | ||
10 | + %td | ||
11 | + = link_to truncate(url, length: 40), url | ||
12 | + | ||
13 | + |
@@ -0,0 +1,70 @@ | @@ -0,0 +1,70 @@ | ||
1 | +%ul.breadcrumb | ||
2 | + %li | ||
3 | + %span.arrow | ||
4 | + = link_to project_tree_path(@project, @ref), remote: true do | ||
5 | + = @project.name | ||
6 | + - tree.breadcrumbs(6) do |link| | ||
7 | + \/ | ||
8 | + %li= link | ||
9 | +.clear | ||
10 | +%div.tree_progress | ||
11 | +#tree-content-holder | ||
12 | + - if tree.is_blob? | ||
13 | + = render partial: "tree/tree_file", locals: { name: tree.name, content: tree.data, file: tree } | ||
14 | + - else | ||
15 | + - contents = tree.contents | ||
16 | + %table#tree-slider{class: "table_#{@hex_path}" } | ||
17 | + %thead | ||
18 | + %th Name | ||
19 | + %th Last Update | ||
20 | + %th | ||
21 | + Last commit | ||
22 | + = link_to "History", tree.history_path, class: "right" | ||
23 | + | ||
24 | + - if tree.up_dir? | ||
25 | + %tr{ class: "tree-item", url: tree.up_dir_path } | ||
26 | + %td.tree-item-file-name | ||
27 | + = image_tag "file_empty.png" | ||
28 | + = link_to "..", tree.up_dir_path, remote: :true | ||
29 | + %td | ||
30 | + %td | ||
31 | + | ||
32 | + - index = 0 | ||
33 | + - contents.select{ |i| i.is_a?(Grit::Tree)}.each do |content| | ||
34 | + = render partial: "tree/tree_item", locals: { content: content, index: (index += 1) } | ||
35 | + - contents.select{ |i| i.is_a?(Grit::Blob)}.each do |content| | ||
36 | + = render partial: "tree/tree_item", locals: { content: content, index: (index += 1) } | ||
37 | + - contents.select{ |i| i.is_a?(Grit::Submodule)}.each do |content| | ||
38 | + = render partial: "tree/submodule_item", locals: { content: content, index: (index += 1) } | ||
39 | + | ||
40 | + - if content = contents.select{ |c| c.is_a?(Grit::Blob) and c.name =~ /^readme/i }.first | ||
41 | + .file_holder#README | ||
42 | + .file_title | ||
43 | + %i.icon-file | ||
44 | + = content.name | ||
45 | + .file_content.wiki | ||
46 | + - if gitlab_markdown?(content.name) | ||
47 | + = preserve do | ||
48 | + = markdown(content.data) | ||
49 | + - else | ||
50 | + = raw GitHub::Markup.render(content.name, content.data) | ||
51 | + | ||
52 | +:javascript | ||
53 | + $(function(){ | ||
54 | + history.pushState({ path: this.path }, '', "#{@history_path}"); | ||
55 | + }); | ||
56 | + | ||
57 | +- unless tree.is_blob? | ||
58 | + :javascript | ||
59 | + // Load last commit log for each file in tree | ||
60 | + $(window).load(function(){ | ||
61 | + ajaxGet('#{@logs_path}'); | ||
62 | + }); | ||
63 | + | ||
64 | +- if params[:path] && request.xhr? | ||
65 | + :javascript | ||
66 | + $(window).unbind('popstate'); | ||
67 | + $(window).bind('popstate', function() { | ||
68 | + if(location.pathname.search("tree") != -1) { | ||
69 | + $.ajax({type: "GET", url: location.pathname, dataType: "script"})} | ||
70 | + else { location.href = location.pathname;}}); |
@@ -0,0 +1,40 @@ | @@ -0,0 +1,40 @@ | ||
1 | +.file_holder | ||
2 | + .file_title | ||
3 | + %i.icon-file | ||
4 | + %span.file_name | ||
5 | + = name.force_encoding('utf-8') | ||
6 | + %small #{file.mode} | ||
7 | + %span.options | ||
8 | + = link_to "raw", project_blob_path(@project, @id), class: "btn very_small", target: "_blank" | ||
9 | + = link_to "history", project_commits_path(@project, @id), class: "btn very_small" | ||
10 | + = link_to "blame", project_blame_path(@project, @id), class: "btn very_small" | ||
11 | + - if file.text? | ||
12 | + - if gitlab_markdown?(name) | ||
13 | + .file_content.wiki | ||
14 | + = preserve do | ||
15 | + = markdown(file.data) | ||
16 | + - elsif markup?(name) | ||
17 | + .file_content.wiki | ||
18 | + = raw GitHub::Markup.render(name, file.data) | ||
19 | + - else | ||
20 | + .file_content.code | ||
21 | + - unless file.empty? | ||
22 | + %div{class: current_user.dark_scheme ? "black" : "white"} | ||
23 | + = preserve do | ||
24 | + = raw file.colorize(options: { linenos: 'True'}) | ||
25 | + - else | ||
26 | + %h4.nothing_here_message Empty file | ||
27 | + | ||
28 | + - elsif file.image? | ||
29 | + .file_content.image_file | ||
30 | + %img{ src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} | ||
31 | + | ||
32 | + - else | ||
33 | + .file_content.blob_file | ||
34 | + %center | ||
35 | + = link_to project_blob_path(@project, @id) do | ||
36 | + %div.padded | ||
37 | + %br | ||
38 | + = image_tag "download.png", width: 64 | ||
39 | + %h3 | ||
40 | + Download (#{file.mb_size}) |
@@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
1 | +- file = tree_full_path(content) | ||
2 | +%tr{ class: "tree-item #{tree_hex_class(content)}", url: project_tree_path(@project, tree_join(@id, file)) } | ||
3 | + %td.tree-item-file-name | ||
4 | + = tree_icon(content) | ||
5 | + %strong= link_to truncate(content.name, length: 40), project_tree_path(@project, tree_join(@id || @commit.id, file)), remote: :true | ||
6 | + %td.tree_time_ago.cgray | ||
7 | + - if index == 1 | ||
8 | + %span.log_loading | ||
9 | + Loading commit data.. | ||
10 | + = image_tag "ajax_loader_tree.gif", width: 14 | ||
11 | + %td.tree_commit |
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +:plain | ||
2 | + // Load Files list | ||
3 | + $("#tree-holder").html("#{escape_javascript(render(partial: "tree", locals: {commit: @commit, tree: @tree}))}"); | ||
4 | + $("#tree-content-holder").show("slide", { direction: "right" }, 150); | ||
5 | + $('.project-refs-form #path').val("#{@path}"); | ||
6 | + | ||
7 | + // Load last commit log for each file in tree | ||
8 | + $('#tree-slider').waitForImages(function() { | ||
9 | + ajaxGet('#{@logs_path}'); | ||
10 | + }); |
config/initializers/1_settings.rb
@@ -112,7 +112,7 @@ class Settings < Settingslogic | @@ -112,7 +112,7 @@ class Settings < Settingslogic | ||
112 | 112 | ||
113 | def backup_path | 113 | def backup_path |
114 | t = app['backup_path'] || "backups/" | 114 | t = app['backup_path'] || "backups/" |
115 | - t = /^\//.match(t) ? t : File.join(Rails.root + t) | 115 | + t = /^\//.match(t) ? t : Rails.root .join(t) |
116 | t | 116 | t |
117 | end | 117 | end |
118 | 118 |
config/initializers/inflections.rb
@@ -8,3 +8,24 @@ | @@ -8,3 +8,24 @@ | ||
8 | # inflect.irregular 'person', 'people' | 8 | # inflect.irregular 'person', 'people' |
9 | # inflect.uncountable %w( fish sheep ) | 9 | # inflect.uncountable %w( fish sheep ) |
10 | # end | 10 | # end |
11 | + | ||
12 | +# Mark "commits" as uncountable. | ||
13 | +# | ||
14 | +# Without this change, the routes | ||
15 | +# | ||
16 | +# resources :commit, only: [:show], constraints: {id: /[[:alnum:]]{6,40}/} | ||
17 | +# resources :commits, only: [:show], constraints: {id: /.+/} | ||
18 | +# | ||
19 | +# would generate identical route helper methods (`project_commit_path`), resulting | ||
20 | +# in one of them not getting a helper method at all. | ||
21 | +# | ||
22 | +# After this change, the helper methods are: | ||
23 | +# | ||
24 | +# project_commit_path(@project, @project.commit) | ||
25 | +# # => "/gitlabhq/commit/bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a | ||
26 | +# | ||
27 | +# project_commits_path(@project, 'stable/README.md') | ||
28 | +# # => "/gitlabhq/commits/stable/README.md" | ||
29 | +ActiveSupport::Inflector.inflections do |inflect| | ||
30 | + inflect.uncountable %w(commits) | ||
31 | +end |
config/initializers/mime_types.rb
@@ -3,3 +3,5 @@ | @@ -3,3 +3,5 @@ | ||
3 | # Add new mime types for use in respond_to blocks: | 3 | # Add new mime types for use in respond_to blocks: |
4 | # Mime::Type.register "text/richtext", :rtf | 4 | # Mime::Type.register "text/richtext", :rtf |
5 | # Mime::Type.register_alias "text/html", :iphone | 5 | # Mime::Type.register_alias "text/html", :iphone |
6 | + | ||
7 | +Mime::Type.register_alias 'text/plain', :patch |
config/routes.rb
@@ -122,38 +122,14 @@ Gitlab::Application.routes.draw do | @@ -122,38 +122,14 @@ Gitlab::Application.routes.draw do | ||
122 | end | 122 | end |
123 | 123 | ||
124 | member do | 124 | member do |
125 | - get "tree", constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } | 125 | + # tree viewer logs |
126 | get "logs_tree", constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } | 126 | get "logs_tree", constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } |
127 | - | ||
128 | - get "blob", | ||
129 | - constraints: { | ||
130 | - id: /[a-zA-Z.0-9\/_\-]+/, | ||
131 | - path: /.*/ | ||
132 | - } | ||
133 | - | ||
134 | - # tree viewer | ||
135 | - get "tree/:path" => "refs#tree", | ||
136 | - as: :tree_file, | ||
137 | - constraints: { | ||
138 | - id: /[a-zA-Z.0-9\/_\-]+/, | ||
139 | - path: /.*/ | ||
140 | - } | ||
141 | - | ||
142 | - # tree viewer | ||
143 | get "logs_tree/:path" => "refs#logs_tree", | 127 | get "logs_tree/:path" => "refs#logs_tree", |
144 | as: :logs_file, | 128 | as: :logs_file, |
145 | constraints: { | 129 | constraints: { |
146 | id: /[a-zA-Z.0-9\/_\-]+/, | 130 | id: /[a-zA-Z.0-9\/_\-]+/, |
147 | path: /.*/ | 131 | path: /.*/ |
148 | } | 132 | } |
149 | - | ||
150 | - # blame | ||
151 | - get "blame/:path" => "refs#blame", | ||
152 | - as: :blame_file, | ||
153 | - constraints: { | ||
154 | - id: /[a-zA-Z.0-9\/_\-]+/, | ||
155 | - path: /.*/ | ||
156 | - } | ||
157 | end | 133 | end |
158 | end | 134 | end |
159 | 135 | ||
@@ -182,27 +158,27 @@ Gitlab::Application.routes.draw do | @@ -182,27 +158,27 @@ Gitlab::Application.routes.draw do | ||
182 | get :test | 158 | get :test |
183 | end | 159 | end |
184 | end | 160 | end |
185 | - resources :commits do | ||
186 | - collection do | ||
187 | - get :compare | ||
188 | - end | ||
189 | 161 | ||
190 | - member do | ||
191 | - get :patch | ||
192 | - end | ||
193 | - end | 162 | + resources :commit, only: [:show], constraints: {id: /[[:alnum:]]{6,40}/} |
163 | + resources :commits, only: [:show], constraints: {id: /.+/} | ||
164 | + resources :compare, only: [:index, :create] | ||
165 | + resources :blame, only: [:show], constraints: {id: /.+/} | ||
166 | + resources :blob, only: [:show], constraints: {id: /.+/} | ||
167 | + resources :tree, only: [:show], constraints: {id: /.+/} | ||
168 | + match "/compare/:from...:to" => "compare#show", as: "compare", constraints: {from: /.+/, to: /.+/} | ||
169 | + | ||
194 | resources :team, controller: 'team_members', only: [:index] | 170 | resources :team, controller: 'team_members', only: [:index] |
195 | resources :team_members | 171 | resources :team_members |
196 | resources :milestones | 172 | resources :milestones |
197 | resources :labels, only: [:index] | 173 | resources :labels, only: [:index] |
198 | resources :issues do | 174 | resources :issues do |
199 | - | ||
200 | collection do | 175 | collection do |
201 | post :sort | 176 | post :sort |
202 | post :bulk_update | 177 | post :bulk_update |
203 | get :search | 178 | get :search |
204 | end | 179 | end |
205 | end | 180 | end |
181 | + | ||
206 | resources :notes, only: [:index, :create, :destroy] do | 182 | resources :notes, only: [:index, :create, :destroy] do |
207 | collection do | 183 | collection do |
208 | post :preview | 184 | post :preview |
db/fixtures/test/001_repo.rb
@@ -3,13 +3,13 @@ require 'fileutils' | @@ -3,13 +3,13 @@ require 'fileutils' | ||
3 | print "Unpacking seed repository..." | 3 | print "Unpacking seed repository..." |
4 | 4 | ||
5 | SEED_REPO = 'seed_project.tar.gz' | 5 | SEED_REPO = 'seed_project.tar.gz' |
6 | -REPO_PATH = File.join(Rails.root, 'tmp', 'repositories') | 6 | +REPO_PATH = Rails.root.join('tmp', 'repositories') |
7 | 7 | ||
8 | # Make whatever directories we need to make | 8 | # Make whatever directories we need to make |
9 | FileUtils.mkdir_p(REPO_PATH) | 9 | FileUtils.mkdir_p(REPO_PATH) |
10 | 10 | ||
11 | # Copy the archive to the repo path | 11 | # Copy the archive to the repo path |
12 | -FileUtils.cp(File.join(Rails.root, 'spec', SEED_REPO), REPO_PATH) | 12 | +FileUtils.cp(Rails.root.join('spec', SEED_REPO), REPO_PATH) |
13 | 13 | ||
14 | # chdir to the repo path | 14 | # chdir to the repo path |
15 | FileUtils.cd(REPO_PATH) do | 15 | FileUtils.cd(REPO_PATH) do |
@@ -0,0 +1,33 @@ | @@ -0,0 +1,33 @@ | ||
1 | +Feature: Admin active tab | ||
2 | + Background: | ||
3 | + Given I sign in as an admin | ||
4 | + | ||
5 | + Scenario: On Admin Home | ||
6 | + Given I visit admin page | ||
7 | + Then the active main tab should be Home | ||
8 | + And no other main tabs should be active | ||
9 | + | ||
10 | + Scenario: On Admin Projects | ||
11 | + Given I visit admin projects page | ||
12 | + Then the active main tab should be Projects | ||
13 | + And no other main tabs should be active | ||
14 | + | ||
15 | + Scenario: On Admin Users | ||
16 | + Given I visit admin users page | ||
17 | + Then the active main tab should be Users | ||
18 | + And no other main tabs should be active | ||
19 | + | ||
20 | + Scenario: On Admin Logs | ||
21 | + Given I visit admin logs page | ||
22 | + Then the active main tab should be Logs | ||
23 | + And no other main tabs should be active | ||
24 | + | ||
25 | + Scenario: On Admin Hooks | ||
26 | + Given I visit admin hooks page | ||
27 | + Then the active main tab should be Hooks | ||
28 | + And no other main tabs should be active | ||
29 | + | ||
30 | + Scenario: On Admin Resque | ||
31 | + Given I visit admin Resque page | ||
32 | + Then the active main tab should be Resque | ||
33 | + And no other main tabs should be active |
@@ -0,0 +1,28 @@ | @@ -0,0 +1,28 @@ | ||
1 | +Feature: Dashboard active tab | ||
2 | + Background: | ||
3 | + Given I sign in as a user | ||
4 | + | ||
5 | + Scenario: On Dashboard Home | ||
6 | + Given I visit dashboard page | ||
7 | + Then the active main tab should be Home | ||
8 | + And no other main tabs should be active | ||
9 | + | ||
10 | + Scenario: On Dashboard Issues | ||
11 | + Given I visit dashboard issues page | ||
12 | + Then the active main tab should be Issues | ||
13 | + And no other main tabs should be active | ||
14 | + | ||
15 | + Scenario: On Dashboard Merge Requests | ||
16 | + Given I visit dashboard merge requests page | ||
17 | + Then the active main tab should be Merge Requests | ||
18 | + And no other main tabs should be active | ||
19 | + | ||
20 | + Scenario: On Dashboard Search | ||
21 | + Given I visit dashboard search page | ||
22 | + Then the active main tab should be Search | ||
23 | + And no other main tabs should be active | ||
24 | + | ||
25 | + Scenario: On Dashboard Help | ||
26 | + Given I visit dashboard help page | ||
27 | + Then the active main tab should be Help | ||
28 | + And no other main tabs should be active |
@@ -0,0 +1,28 @@ | @@ -0,0 +1,28 @@ | ||
1 | +Feature: Profile active tab | ||
2 | + Background: | ||
3 | + Given I sign in as a user | ||
4 | + | ||
5 | + Scenario: On Profile Home | ||
6 | + Given I visit profile page | ||
7 | + Then the active main tab should be Home | ||
8 | + And no other main tabs should be active | ||
9 | + | ||
10 | + Scenario: On Profile Account | ||
11 | + Given I visit profile account page | ||
12 | + Then the active main tab should be Account | ||
13 | + And no other main tabs should be active | ||
14 | + | ||
15 | + Scenario: On Profile SSH Keys | ||
16 | + Given I visit profile SSH keys page | ||
17 | + Then the active main tab should be SSH Keys | ||
18 | + And no other main tabs should be active | ||
19 | + | ||
20 | + Scenario: On Profile Design | ||
21 | + Given I visit profile design page | ||
22 | + Then the active main tab should be Design | ||
23 | + And no other main tabs should be active | ||
24 | + | ||
25 | + Scenario: On Profile History | ||
26 | + Given I visit profile history page | ||
27 | + Then the active main tab should be History | ||
28 | + And no other main tabs should be active |
@@ -0,0 +1,147 @@ | @@ -0,0 +1,147 @@ | ||
1 | +Feature: Project active tab | ||
2 | + Background: | ||
3 | + Given I sign in as a user | ||
4 | + And I own a project | ||
5 | + | ||
6 | + # Main Tabs | ||
7 | + | ||
8 | + Scenario: On Project Home | ||
9 | + Given I visit my project's home page | ||
10 | + Then the active main tab should be Home | ||
11 | + And no other main tabs should be active | ||
12 | + | ||
13 | + Scenario: On Project Files | ||
14 | + Given I visit my project's files page | ||
15 | + Then the active main tab should be Files | ||
16 | + And no other main tabs should be active | ||
17 | + | ||
18 | + Scenario: On Project Commits | ||
19 | + Given I visit my project's commits page | ||
20 | + Then the active main tab should be Commits | ||
21 | + And no other main tabs should be active | ||
22 | + | ||
23 | + Scenario: On Project Network | ||
24 | + Given I visit my project's network page | ||
25 | + Then the active main tab should be Network | ||
26 | + And no other main tabs should be active | ||
27 | + | ||
28 | + Scenario: On Project Issues | ||
29 | + Given I visit my project's issues page | ||
30 | + Then the active main tab should be Issues | ||
31 | + And no other main tabs should be active | ||
32 | + | ||
33 | + Scenario: On Project Merge Requests | ||
34 | + Given I visit my project's merge requests page | ||
35 | + Then the active main tab should be Merge Requests | ||
36 | + And no other main tabs should be active | ||
37 | + | ||
38 | + Scenario: On Project Wall | ||
39 | + Given I visit my project's wall page | ||
40 | + Then the active main tab should be Wall | ||
41 | + And no other main tabs should be active | ||
42 | + | ||
43 | + Scenario: On Project Wiki | ||
44 | + Given I visit my project's wiki page | ||
45 | + Then the active main tab should be Wiki | ||
46 | + And no other main tabs should be active | ||
47 | + | ||
48 | + # Sub Tabs: Home | ||
49 | + | ||
50 | + Scenario: On Project Home/Show | ||
51 | + Given I visit my project's home page | ||
52 | + Then the active sub tab should be Show | ||
53 | + And no other sub tabs should be active | ||
54 | + And the active main tab should be Home | ||
55 | + | ||
56 | + Scenario: On Project Home/Team | ||
57 | + Given I visit my project's home page | ||
58 | + And I click the "Team" tab | ||
59 | + Then the active sub tab should be Team | ||
60 | + And no other sub tabs should be active | ||
61 | + And the active main tab should be Home | ||
62 | + | ||
63 | + Scenario: On Project Home/Attachments | ||
64 | + Given I visit my project's home page | ||
65 | + And I click the "Attachments" tab | ||
66 | + Then the active sub tab should be Attachments | ||
67 | + And no other sub tabs should be active | ||
68 | + And the active main tab should be Home | ||
69 | + | ||
70 | + Scenario: On Project Home/Snippets | ||
71 | + Given I visit my project's home page | ||
72 | + And I click the "Snippets" tab | ||
73 | + Then the active sub tab should be Snippets | ||
74 | + And no other sub tabs should be active | ||
75 | + And the active main tab should be Home | ||
76 | + | ||
77 | + Scenario: On Project Home/Edit | ||
78 | + Given I visit my project's home page | ||
79 | + And I click the "Edit" tab | ||
80 | + Then the active sub tab should be Edit | ||
81 | + And no other sub tabs should be active | ||
82 | + And the active main tab should be Home | ||
83 | + | ||
84 | + Scenario: On Project Home/Hooks | ||
85 | + Given I visit my project's home page | ||
86 | + And I click the "Hooks" tab | ||
87 | + Then the active sub tab should be Hooks | ||
88 | + And no other sub tabs should be active | ||
89 | + And the active main tab should be Home | ||
90 | + | ||
91 | + Scenario: On Project Home/Deploy Keys | ||
92 | + Given I visit my project's home page | ||
93 | + And I click the "Deploy Keys" tab | ||
94 | + Then the active sub tab should be Deploy Keys | ||
95 | + And no other sub tabs should be active | ||
96 | + And the active main tab should be Home | ||
97 | + | ||
98 | + # Sub Tabs: Commits | ||
99 | + | ||
100 | + Scenario: On Project Commits/Commits | ||
101 | + Given I visit my project's commits page | ||
102 | + Then the active sub tab should be Commits | ||
103 | + And no other sub tabs should be active | ||
104 | + And the active main tab should be Commits | ||
105 | + | ||
106 | + Scenario: On Project Commits/Compare | ||
107 | + Given I visit my project's commits page | ||
108 | + And I click the "Compare" tab | ||
109 | + Then the active sub tab should be Compare | ||
110 | + And no other sub tabs should be active | ||
111 | + And the active main tab should be Commits | ||
112 | + | ||
113 | + Scenario: On Project Commits/Branches | ||
114 | + Given I visit my project's commits page | ||
115 | + And I click the "Branches" tab | ||
116 | + Then the active sub tab should be Branches | ||
117 | + And no other sub tabs should be active | ||
118 | + And the active main tab should be Commits | ||
119 | + | ||
120 | + Scenario: On Project Commits/Tags | ||
121 | + Given I visit my project's commits page | ||
122 | + And I click the "Tags" tab | ||
123 | + Then the active sub tab should be Tags | ||
124 | + And no other sub tabs should be active | ||
125 | + And the active main tab should be Commits | ||
126 | + | ||
127 | + # Sub Tabs: Issues | ||
128 | + | ||
129 | + Scenario: On Project Issues/Browse | ||
130 | + Given I visit my project's issues page | ||
131 | + Then the active sub tab should be Browse Issues | ||
132 | + And no other sub tabs should be active | ||
133 | + And the active main tab should be Issues | ||
134 | + | ||
135 | + Scenario: On Project Issues/Milestones | ||
136 | + Given I visit my project's issues page | ||
137 | + And I click the "Milestones" tab | ||
138 | + Then the active sub tab should be Milestones | ||
139 | + And no other sub tabs should be active | ||
140 | + And the active main tab should be Issues | ||
141 | + | ||
142 | + Scenario: On Project Issues/Labels | ||
143 | + Given I visit my project's issues page | ||
144 | + And I click the "Labels" tab | ||
145 | + Then the active sub tab should be Labels | ||
146 | + And no other sub tabs should be active | ||
147 | + And the active main tab should be Issues |
features/project/commits/commits.feature
1 | Feature: Project Browse commits | 1 | Feature: Project Browse commits |
2 | Background: | 2 | Background: |
3 | Given I sign in as a user | 3 | Given I sign in as a user |
4 | - And I own project "Shop" | ||
5 | - Given I visit project commits page | 4 | + And I own a project |
5 | + And I visit my project's commits page | ||
6 | 6 | ||
7 | Scenario: I browse commits list for master branch | 7 | Scenario: I browse commits list for master branch |
8 | Then I see project commits | 8 | Then I see project commits |
@@ -18,4 +18,4 @@ Feature: Project Browse commits | @@ -18,4 +18,4 @@ Feature: Project Browse commits | ||
18 | Scenario: I compare refs | 18 | Scenario: I compare refs |
19 | Given I visit compare refs page | 19 | Given I visit compare refs page |
20 | And I fill compare fields with refs | 20 | And I fill compare fields with refs |
21 | - And I see compared refs | 21 | + Then I see compared refs |
@@ -0,0 +1,29 @@ | @@ -0,0 +1,29 @@ | ||
1 | +class AdminActiveTab < Spinach::FeatureSteps | ||
2 | + include SharedAuthentication | ||
3 | + include SharedPaths | ||
4 | + include SharedActiveTab | ||
5 | + | ||
6 | + Then 'the active main tab should be Home' do | ||
7 | + ensure_active_main_tab('Stats') | ||
8 | + end | ||
9 | + | ||
10 | + Then 'the active main tab should be Projects' do | ||
11 | + ensure_active_main_tab('Projects') | ||
12 | + end | ||
13 | + | ||
14 | + Then 'the active main tab should be Users' do | ||
15 | + ensure_active_main_tab('Users') | ||
16 | + end | ||
17 | + | ||
18 | + Then 'the active main tab should be Logs' do | ||
19 | + ensure_active_main_tab('Logs') | ||
20 | + end | ||
21 | + | ||
22 | + Then 'the active main tab should be Hooks' do | ||
23 | + ensure_active_main_tab('Hooks') | ||
24 | + end | ||
25 | + | ||
26 | + Then 'the active main tab should be Resque' do | ||
27 | + ensure_active_main_tab('Resque') | ||
28 | + end | ||
29 | +end |
@@ -0,0 +1,25 @@ | @@ -0,0 +1,25 @@ | ||
1 | +class DashboardActiveTab < Spinach::FeatureSteps | ||
2 | + include SharedAuthentication | ||
3 | + include SharedPaths | ||
4 | + include SharedActiveTab | ||
5 | + | ||
6 | + Then 'the active main tab should be Home' do | ||
7 | + ensure_active_main_tab('Home') | ||
8 | + end | ||
9 | + | ||
10 | + Then 'the active main tab should be Issues' do | ||
11 | + ensure_active_main_tab('Issues') | ||
12 | + end | ||
13 | + | ||
14 | + Then 'the active main tab should be Merge Requests' do | ||
15 | + ensure_active_main_tab('Merge Requests') | ||
16 | + end | ||
17 | + | ||
18 | + Then 'the active main tab should be Search' do | ||
19 | + ensure_active_main_tab('Search') | ||
20 | + end | ||
21 | + | ||
22 | + Then 'the active main tab should be Help' do | ||
23 | + ensure_active_main_tab('Help') | ||
24 | + end | ||
25 | +end |
@@ -0,0 +1,25 @@ | @@ -0,0 +1,25 @@ | ||
1 | +class ProfileActiveTab < Spinach::FeatureSteps | ||
2 | + include SharedAuthentication | ||
3 | + include SharedPaths | ||
4 | + include SharedActiveTab | ||
5 | + | ||
6 | + Then 'the active main tab should be Home' do | ||
7 | + ensure_active_main_tab('Profile') | ||
8 | + end | ||
9 | + | ||
10 | + Then 'the active main tab should be Account' do | ||
11 | + ensure_active_main_tab('Account') | ||
12 | + end | ||
13 | + | ||
14 | + Then 'the active main tab should be SSH Keys' do | ||
15 | + ensure_active_main_tab('SSH Keys') | ||
16 | + end | ||
17 | + | ||
18 | + Then 'the active main tab should be Design' do | ||
19 | + ensure_active_main_tab('Design') | ||
20 | + end | ||
21 | + | ||
22 | + Then 'the active main tab should be History' do | ||
23 | + ensure_active_main_tab('History') | ||
24 | + end | ||
25 | +end |
@@ -0,0 +1,146 @@ | @@ -0,0 +1,146 @@ | ||
1 | +class ProjectActiveTab < Spinach::FeatureSteps | ||
2 | + include SharedAuthentication | ||
3 | + include SharedPaths | ||
4 | + include SharedProject | ||
5 | + include SharedActiveTab | ||
6 | + | ||
7 | + # Main Tabs | ||
8 | + | ||
9 | + Then 'the active main tab should be Home' do | ||
10 | + ensure_active_main_tab(@project.name) | ||
11 | + end | ||
12 | + | ||
13 | + Then 'the active main tab should be Files' do | ||
14 | + ensure_active_main_tab('Files') | ||
15 | + end | ||
16 | + | ||
17 | + Then 'the active main tab should be Commits' do | ||
18 | + ensure_active_main_tab('Commits') | ||
19 | + end | ||
20 | + | ||
21 | + Then 'the active main tab should be Network' do | ||
22 | + ensure_active_main_tab('Network') | ||
23 | + end | ||
24 | + | ||
25 | + Then 'the active main tab should be Issues' do | ||
26 | + ensure_active_main_tab('Issues') | ||
27 | + end | ||
28 | + | ||
29 | + Then 'the active main tab should be Merge Requests' do | ||
30 | + ensure_active_main_tab('Merge Requests') | ||
31 | + end | ||
32 | + | ||
33 | + Then 'the active main tab should be Wall' do | ||
34 | + ensure_active_main_tab('Wall') | ||
35 | + end | ||
36 | + | ||
37 | + Then 'the active main tab should be Wiki' do | ||
38 | + ensure_active_main_tab('Wiki') | ||
39 | + end | ||
40 | + | ||
41 | + # Sub Tabs: Home | ||
42 | + | ||
43 | + Given 'I click the "Team" tab' do | ||
44 | + click_link('Team') | ||
45 | + end | ||
46 | + | ||
47 | + Given 'I click the "Attachments" tab' do | ||
48 | + click_link('Attachments') | ||
49 | + end | ||
50 | + | ||
51 | + Given 'I click the "Snippets" tab' do | ||
52 | + click_link('Snippets') | ||
53 | + end | ||
54 | + | ||
55 | + Given 'I click the "Edit" tab' do | ||
56 | + click_link('Edit') | ||
57 | + end | ||
58 | + | ||
59 | + Given 'I click the "Hooks" tab' do | ||
60 | + click_link('Hooks') | ||
61 | + end | ||
62 | + | ||
63 | + Given 'I click the "Deploy Keys" tab' do | ||
64 | + click_link('Deploy Keys') | ||
65 | + end | ||
66 | + | ||
67 | + Then 'the active sub tab should be Show' do | ||
68 | + ensure_active_sub_tab('Show') | ||
69 | + end | ||
70 | + | ||
71 | + Then 'the active sub tab should be Team' do | ||
72 | + ensure_active_sub_tab('Team') | ||
73 | + end | ||
74 | + | ||
75 | + Then 'the active sub tab should be Attachments' do | ||
76 | + ensure_active_sub_tab('Attachments') | ||
77 | + end | ||
78 | + | ||
79 | + Then 'the active sub tab should be Snippets' do | ||
80 | + ensure_active_sub_tab('Snippets') | ||
81 | + end | ||
82 | + | ||
83 | + Then 'the active sub tab should be Edit' do | ||
84 | + ensure_active_sub_tab('Edit') | ||
85 | + end | ||
86 | + | ||
87 | + Then 'the active sub tab should be Hooks' do | ||
88 | + ensure_active_sub_tab('Hooks') | ||
89 | + end | ||
90 | + | ||
91 | + Then 'the active sub tab should be Deploy Keys' do | ||
92 | + ensure_active_sub_tab('Deploy Keys') | ||
93 | + end | ||
94 | + | ||
95 | + # Sub Tabs: Commits | ||
96 | + | ||
97 | + Given 'I click the "Compare" tab' do | ||
98 | + click_link('Compare') | ||
99 | + end | ||
100 | + | ||
101 | + Given 'I click the "Branches" tab' do | ||
102 | + click_link('Branches') | ||
103 | + end | ||
104 | + | ||
105 | + Given 'I click the "Tags" tab' do | ||
106 | + click_link('Tags') | ||
107 | + end | ||
108 | + | ||
109 | + Then 'the active sub tab should be Commits' do | ||
110 | + ensure_active_sub_tab('Commits') | ||
111 | + end | ||
112 | + | ||
113 | + Then 'the active sub tab should be Compare' do | ||
114 | + ensure_active_sub_tab('Compare') | ||
115 | + end | ||
116 | + | ||
117 | + Then 'the active sub tab should be Branches' do | ||
118 | + ensure_active_sub_tab('Branches') | ||
119 | + end | ||
120 | + | ||
121 | + Then 'the active sub tab should be Tags' do | ||
122 | + ensure_active_sub_tab('Tags') | ||
123 | + end | ||
124 | + | ||
125 | + # Sub Tabs: Issues | ||
126 | + | ||
127 | + Given 'I click the "Milestones" tab' do | ||
128 | + click_link('Milestones') | ||
129 | + end | ||
130 | + | ||
131 | + Given 'I click the "Labels" tab' do | ||
132 | + click_link('Labels') | ||
133 | + end | ||
134 | + | ||
135 | + Then 'the active sub tab should be Browse Issues' do | ||
136 | + ensure_active_sub_tab('Browse Issues') | ||
137 | + end | ||
138 | + | ||
139 | + Then 'the active sub tab should be Milestones' do | ||
140 | + ensure_active_sub_tab('Milestones') | ||
141 | + end | ||
142 | + | ||
143 | + Then 'the active sub tab should be Labels' do | ||
144 | + ensure_active_sub_tab('Labels') | ||
145 | + end | ||
146 | +end |
features/steps/project/project_browse_commits.rb
@@ -4,8 +4,6 @@ class ProjectBrowseCommits < Spinach::FeatureSteps | @@ -4,8 +4,6 @@ class ProjectBrowseCommits < Spinach::FeatureSteps | ||
4 | include SharedPaths | 4 | include SharedPaths |
5 | 5 | ||
6 | Then 'I see project commits' do | 6 | Then 'I see project commits' do |
7 | - current_path.should == project_commits_path(@project) | ||
8 | - | ||
9 | commit = @project.commit | 7 | commit = @project.commit |
10 | page.should have_content(@project.name) | 8 | page.should have_content(@project.name) |
11 | page.should have_content(commit.message) | 9 | page.should have_content(commit.message) |
@@ -34,14 +32,14 @@ class ProjectBrowseCommits < Spinach::FeatureSteps | @@ -34,14 +32,14 @@ class ProjectBrowseCommits < Spinach::FeatureSteps | ||
34 | end | 32 | end |
35 | 33 | ||
36 | And 'I fill compare fields with refs' do | 34 | And 'I fill compare fields with refs' do |
37 | - fill_in "from", :with => "master" | ||
38 | - fill_in "to", :with => "stable" | 35 | + fill_in "from", with: "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" |
36 | + fill_in "to", with: "8716fc78f3c65bbf7bcf7b574febd583bc5d2812" | ||
39 | click_button "Compare" | 37 | click_button "Compare" |
40 | end | 38 | end |
41 | 39 | ||
42 | - And 'I see compared refs' do | ||
43 | - page.should have_content "Commits (27)" | 40 | + Then 'I see compared refs' do |
44 | page.should have_content "Compare View" | 41 | page.should have_content "Compare View" |
45 | - page.should have_content "Showing 73 changed files" | 42 | + page.should have_content "Commits (1)" |
43 | + page.should have_content "Showing 2 changed files" | ||
46 | end | 44 | end |
47 | end | 45 | end |
features/steps/project/project_browse_files.rb
@@ -10,7 +10,7 @@ class ProjectBrowseFiles < Spinach::FeatureSteps | @@ -10,7 +10,7 @@ class ProjectBrowseFiles < Spinach::FeatureSteps | ||
10 | end | 10 | end |
11 | 11 | ||
12 | Then 'I should see files from repository for "8470d70"' do | 12 | Then 'I should see files from repository for "8470d70"' do |
13 | - current_path.should == tree_project_ref_path(@project, "8470d70") | 13 | + current_path.should == project_tree_path(@project, "8470d70") |
14 | page.should have_content "app" | 14 | page.should have_content "app" |
15 | page.should have_content "History" | 15 | page.should have_content "History" |
16 | page.should have_content "Gemfile" | 16 | page.should have_content "Gemfile" |
@@ -0,0 +1,19 @@ | @@ -0,0 +1,19 @@ | ||
1 | +module SharedActiveTab | ||
2 | + include Spinach::DSL | ||
3 | + | ||
4 | + def ensure_active_main_tab(content) | ||
5 | + page.find('ul.main_menu li.active').should have_content(content) | ||
6 | + end | ||
7 | + | ||
8 | + def ensure_active_sub_tab(content) | ||
9 | + page.find('div.content ul.nav-tabs li.active').should have_content(content) | ||
10 | + end | ||
11 | + | ||
12 | + And 'no other main tabs should be active' do | ||
13 | + page.should have_selector('ul.main_menu li.active', count: 1) | ||
14 | + end | ||
15 | + | ||
16 | + And 'no other sub tabs should be active' do | ||
17 | + page.should have_selector('div.content ul.nav-tabs li.active', count: 1) | ||
18 | + end | ||
19 | +end |
features/steps/shared/authentication.rb
features/steps/shared/paths.rb
1 | module SharedPaths | 1 | module SharedPaths |
2 | include Spinach::DSL | 2 | include Spinach::DSL |
3 | 3 | ||
4 | - And 'I visit dashboard search page' do | ||
5 | - visit search_path | 4 | + When 'I visit new project page' do |
5 | + visit new_project_path | ||
6 | end | 6 | end |
7 | 7 | ||
8 | - And 'I visit dashboard merge requests page' do | ||
9 | - visit dashboard_merge_requests_path | 8 | + # ---------------------------------------- |
9 | + # Dashboard | ||
10 | + # ---------------------------------------- | ||
11 | + | ||
12 | + Given 'I visit dashboard page' do | ||
13 | + visit dashboard_path | ||
10 | end | 14 | end |
11 | 15 | ||
12 | - And 'I visit dashboard issues page' do | 16 | + Given 'I visit dashboard issues page' do |
13 | visit dashboard_issues_path | 17 | visit dashboard_issues_path |
14 | end | 18 | end |
15 | 19 | ||
16 | - When 'I visit dashboard page' do | ||
17 | - visit dashboard_path | 20 | + Given 'I visit dashboard merge requests page' do |
21 | + visit dashboard_merge_requests_path | ||
22 | + end | ||
23 | + | ||
24 | + Given 'I visit dashboard search page' do | ||
25 | + visit search_path | ||
18 | end | 26 | end |
19 | 27 | ||
28 | + Given 'I visit dashboard help page' do | ||
29 | + visit help_path | ||
30 | + end | ||
31 | + | ||
32 | + # ---------------------------------------- | ||
33 | + # Profile | ||
34 | + # ---------------------------------------- | ||
35 | + | ||
20 | Given 'I visit profile page' do | 36 | Given 'I visit profile page' do |
21 | visit profile_path | 37 | visit profile_path |
22 | end | 38 | end |
@@ -25,14 +41,94 @@ module SharedPaths | @@ -25,14 +41,94 @@ module SharedPaths | ||
25 | visit profile_account_path | 41 | visit profile_account_path |
26 | end | 42 | end |
27 | 43 | ||
44 | + Given 'I visit profile SSH keys page' do | ||
45 | + visit keys_path | ||
46 | + end | ||
47 | + | ||
48 | + Given 'I visit profile design page' do | ||
49 | + visit profile_design_path | ||
50 | + end | ||
51 | + | ||
52 | + Given 'I visit profile history page' do | ||
53 | + visit profile_history_path | ||
54 | + end | ||
55 | + | ||
28 | Given 'I visit profile token page' do | 56 | Given 'I visit profile token page' do |
29 | visit profile_token_path | 57 | visit profile_token_path |
30 | end | 58 | end |
31 | 59 | ||
32 | - When 'I visit new project page' do | ||
33 | - visit new_project_path | 60 | + # ---------------------------------------- |
61 | + # Admin | ||
62 | + # ---------------------------------------- | ||
63 | + | ||
64 | + Given 'I visit admin page' do | ||
65 | + visit admin_root_path | ||
66 | + end | ||
67 | + | ||
68 | + Given 'I visit admin projects page' do | ||
69 | + visit admin_projects_path | ||
34 | end | 70 | end |
35 | 71 | ||
72 | + Given 'I visit admin users page' do | ||
73 | + visit admin_users_path | ||
74 | + end | ||
75 | + | ||
76 | + Given 'I visit admin logs page' do | ||
77 | + visit admin_logs_path | ||
78 | + end | ||
79 | + | ||
80 | + Given 'I visit admin hooks page' do | ||
81 | + visit admin_hooks_path | ||
82 | + end | ||
83 | + | ||
84 | + Given 'I visit admin Resque page' do | ||
85 | + visit admin_resque_path | ||
86 | + end | ||
87 | + | ||
88 | + # ---------------------------------------- | ||
89 | + # Generic Project | ||
90 | + # ---------------------------------------- | ||
91 | + | ||
92 | + Given "I visit my project's home page" do | ||
93 | + visit project_path(@project) | ||
94 | + end | ||
95 | + | ||
96 | + Given "I visit my project's files page" do | ||
97 | + visit project_tree_path(@project, @project.root_ref) | ||
98 | + end | ||
99 | + | ||
100 | + Given "I visit my project's commits page" do | ||
101 | + visit project_commits_path(@project, @project.root_ref, {limit: 5}) | ||
102 | + end | ||
103 | + | ||
104 | + Given "I visit my project's network page" do | ||
105 | + # Stub out find_all to speed this up (10 commits vs. 650) | ||
106 | + commits = Grit::Commit.find_all(@project.repo, nil, {max_count: 10}) | ||
107 | + Grit::Commit.stub(:find_all).and_return(commits) | ||
108 | + | ||
109 | + visit graph_project_path(@project) | ||
110 | + end | ||
111 | + | ||
112 | + Given "I visit my project's issues page" do | ||
113 | + visit project_issues_path(@project) | ||
114 | + end | ||
115 | + | ||
116 | + Given "I visit my project's merge requests page" do | ||
117 | + visit project_merge_requests_path(@project) | ||
118 | + end | ||
119 | + | ||
120 | + Given "I visit my project's wall page" do | ||
121 | + visit wall_project_path(@project) | ||
122 | + end | ||
123 | + | ||
124 | + Given "I visit my project's wiki page" do | ||
125 | + visit project_wiki_path(@project, :index) | ||
126 | + end | ||
127 | + | ||
128 | + # ---------------------------------------- | ||
129 | + # "Shop" Project | ||
130 | + # ---------------------------------------- | ||
131 | + | ||
36 | And 'I visit project "Shop" page' do | 132 | And 'I visit project "Shop" page' do |
37 | project = Project.find_by_name("Shop") | 133 | project = Project.find_by_name("Shop") |
38 | visit project_path(project) | 134 | visit project_path(project) |
@@ -43,23 +139,27 @@ module SharedPaths | @@ -43,23 +139,27 @@ module SharedPaths | ||
43 | end | 139 | end |
44 | 140 | ||
45 | Given 'I visit compare refs page' do | 141 | Given 'I visit compare refs page' do |
46 | - visit compare_project_commits_path(@project) | 142 | + visit project_compare_index_path(@project) |
47 | end | 143 | end |
48 | 144 | ||
49 | Given 'I visit project commits page' do | 145 | Given 'I visit project commits page' do |
50 | - visit project_commits_path(@project) | 146 | + visit project_commits_path(@project, @project.root_ref, {limit: 5}) |
147 | + end | ||
148 | + | ||
149 | + Given 'I visit project commits page for stable branch' do | ||
150 | + visit project_commits_path(@project, 'stable', {limit: 5}) | ||
51 | end | 151 | end |
52 | 152 | ||
53 | Given 'I visit project source page' do | 153 | Given 'I visit project source page' do |
54 | - visit tree_project_ref_path(@project, @project.root_ref) | 154 | + visit project_tree_path(@project, @project.root_ref) |
55 | end | 155 | end |
56 | 156 | ||
57 | Given 'I visit blob file from repo' do | 157 | Given 'I visit blob file from repo' do |
58 | - visit tree_project_ref_path(@project, ValidCommit::ID, :path => ValidCommit::BLOB_FILE_PATH) | 158 | + visit project_tree_path(@project, File.join(ValidCommit::ID, ValidCommit::BLOB_FILE_PATH)) |
59 | end | 159 | end |
60 | 160 | ||
61 | Given 'I visit project source page for "8470d70"' do | 161 | Given 'I visit project source page for "8470d70"' do |
62 | - visit tree_project_ref_path(@project, "8470d70") | 162 | + visit project_tree_path(@project, "8470d70") |
63 | end | 163 | end |
64 | 164 | ||
65 | Given 'I visit project tags page' do | 165 | Given 'I visit project tags page' do |
features/steps/shared/project.rb
1 | module SharedProject | 1 | module SharedProject |
2 | include Spinach::DSL | 2 | include Spinach::DSL |
3 | 3 | ||
4 | + # Create a project without caring about what it's called | ||
5 | + And "I own a project" do | ||
6 | + @project = create(:project) | ||
7 | + @project.add_access(@user, :admin) | ||
8 | + end | ||
9 | + | ||
10 | + # Create a specific project called "Shop" | ||
4 | And 'I own project "Shop"' do | 11 | And 'I own project "Shop"' do |
5 | @project = Factory :project, :name => "Shop" | 12 | @project = Factory :project, :name => "Shop" |
6 | @project.add_access(@user, :admin) | 13 | @project.add_access(@user, :admin) |
features/support/env.rb
@@ -23,5 +23,7 @@ Spinach.hooks.after_scenario { DatabaseCleaner.clean } | @@ -23,5 +23,7 @@ Spinach.hooks.after_scenario { DatabaseCleaner.clean } | ||
23 | Spinach.hooks.before_run do | 23 | Spinach.hooks.before_run do |
24 | RSpec::Mocks::setup self | 24 | RSpec::Mocks::setup self |
25 | 25 | ||
26 | + include FactoryGirl::Syntax::Methods | ||
27 | + | ||
26 | stub_gitolite! | 28 | stub_gitolite! |
27 | end | 29 | end |
@@ -0,0 +1,114 @@ | @@ -0,0 +1,114 @@ | ||
1 | +# Module providing methods for dealing with separating a tree-ish string and a | ||
2 | +# file path string when combined in a request parameter | ||
3 | +module ExtractsPath | ||
4 | + extend ActiveSupport::Concern | ||
5 | + | ||
6 | + # Raised when given an invalid file path | ||
7 | + class InvalidPathError < StandardError; end | ||
8 | + | ||
9 | + included do | ||
10 | + if respond_to?(:before_filter) | ||
11 | + before_filter :assign_ref_vars, only: [:show] | ||
12 | + end | ||
13 | + end | ||
14 | + | ||
15 | + # Given a string containing both a Git tree-ish, such as a branch or tag, and | ||
16 | + # a filesystem path joined by forward slashes, attempts to separate the two. | ||
17 | + # | ||
18 | + # Expects a @project instance variable to contain the active project. This is | ||
19 | + # used to check the input against a list of valid repository refs. | ||
20 | + # | ||
21 | + # Examples | ||
22 | + # | ||
23 | + # # No @project available | ||
24 | + # extract_ref('master') | ||
25 | + # # => ['', ''] | ||
26 | + # | ||
27 | + # extract_ref('master') | ||
28 | + # # => ['master', ''] | ||
29 | + # | ||
30 | + # extract_ref("f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG") | ||
31 | + # # => ['f4b14494ef6abf3d144c28e4af0c20143383e062', 'CHANGELOG'] | ||
32 | + # | ||
33 | + # extract_ref("v2.0.0/README.md") | ||
34 | + # # => ['v2.0.0', 'README.md'] | ||
35 | + # | ||
36 | + # extract_ref('issues/1234/app/models/project.rb') | ||
37 | + # # => ['issues/1234', 'app/models/project.rb'] | ||
38 | + # | ||
39 | + # # Given an invalid branch, we fall back to just splitting on the first slash | ||
40 | + # extract_ref('non/existent/branch/README.md') | ||
41 | + # # => ['non', 'existent/branch/README.md'] | ||
42 | + # | ||
43 | + # Returns an Array where the first value is the tree-ish and the second is the | ||
44 | + # path | ||
45 | + def extract_ref(input) | ||
46 | + pair = ['', ''] | ||
47 | + | ||
48 | + return pair unless @project | ||
49 | + | ||
50 | + if input.match(/^([[:alnum:]]{40})(.+)/) | ||
51 | + # If the ref appears to be a SHA, we're done, just split the string | ||
52 | + pair = $~.captures | ||
53 | + else | ||
54 | + # Otherwise, attempt to detect the ref using a list of the project's | ||
55 | + # branches and tags | ||
56 | + | ||
57 | + # Append a trailing slash if we only get a ref and no file path | ||
58 | + id = input | ||
59 | + id += '/' unless id.include?('/') | ||
60 | + | ||
61 | + valid_refs = @project.branches + @project.tags | ||
62 | + valid_refs.select! { |v| id.start_with?("#{v}/") } | ||
63 | + | ||
64 | + if valid_refs.length != 1 | ||
65 | + # No exact ref match, so just try our best | ||
66 | + pair = id.match(/([^\/]+)(.*)/).captures | ||
67 | + else | ||
68 | + # Partition the string into the ref and the path, ignoring the empty first value | ||
69 | + pair = id.partition(valid_refs.first)[1..-1] | ||
70 | + end | ||
71 | + end | ||
72 | + | ||
73 | + # Remove leading slash from path | ||
74 | + pair[1].gsub!(/^\//, '') | ||
75 | + | ||
76 | + pair | ||
77 | + end | ||
78 | + | ||
79 | + # Assigns common instance variables for views working with Git tree-ish objects | ||
80 | + # | ||
81 | + # Assignments are: | ||
82 | + # | ||
83 | + # - @id - A string representing the joined ref and path | ||
84 | + # - @ref - A string representing the ref (e.g., the branch, tag, or commit SHA) | ||
85 | + # - @path - A string representing the filesystem path | ||
86 | + # - @commit - A CommitDecorator representing the commit from the given ref | ||
87 | + # - @tree - A TreeDecorator representing the tree at the given ref/path | ||
88 | + # | ||
89 | + # If the :id parameter appears to be requesting a specific response format, | ||
90 | + # that will be handled as well. | ||
91 | + # | ||
92 | + # Automatically renders `not_found!` if a valid tree path could not be | ||
93 | + # resolved (e.g., when a user inserts an invalid path or ref). | ||
94 | + def assign_ref_vars | ||
95 | + # Handle formats embedded in the id | ||
96 | + if params[:id].ends_with?('.atom') | ||
97 | + params[:id].gsub!(/\.atom$/, '') | ||
98 | + request.format = :atom | ||
99 | + end | ||
100 | + | ||
101 | + @ref, @path = extract_ref(params[:id]) | ||
102 | + | ||
103 | + @id = File.join(@ref, @path) | ||
104 | + | ||
105 | + @commit = CommitDecorator.decorate(@project.commit(@ref)) | ||
106 | + | ||
107 | + @tree = Tree.new(@commit.tree, @project, @ref, @path) | ||
108 | + @tree = TreeDecorator.new(@tree) | ||
109 | + | ||
110 | + raise InvalidPathError if @tree.invalid? | ||
111 | + rescue NoMethodError, InvalidPathError | ||
112 | + not_found! | ||
113 | + end | ||
114 | +end |
lib/gitlab/backend/gitolite_config.rb
@@ -10,7 +10,7 @@ module Gitlab | @@ -10,7 +10,7 @@ module Gitlab | ||
10 | attr_reader :config_tmp_dir, :ga_repo, :conf | 10 | attr_reader :config_tmp_dir, :ga_repo, :conf |
11 | 11 | ||
12 | def config_tmp_dir | 12 | def config_tmp_dir |
13 | - @config_tmp_dir ||= File.join(Rails.root, 'tmp',"gitlabhq-gitolite-#{Time.now.to_i}") | 13 | + @config_tmp_dir ||= Rails.root.join('tmp',"gitlabhq-gitolite-#{Time.now.to_i}") |
14 | end | 14 | end |
15 | 15 | ||
16 | def ga_repo | 16 | def ga_repo |
@@ -19,7 +19,7 @@ module Gitlab | @@ -19,7 +19,7 @@ module Gitlab | ||
19 | 19 | ||
20 | def apply | 20 | def apply |
21 | Timeout::timeout(30) do | 21 | Timeout::timeout(30) do |
22 | - File.open(File.join(Rails.root, 'tmp', "gitlabhq-gitolite.lock"), "w+") do |f| | 22 | + File.open(Rails.root.join('tmp', "gitlabhq-gitolite.lock"), "w+") do |f| |
23 | begin | 23 | begin |
24 | # Set exclusive lock | 24 | # Set exclusive lock |
25 | # to prevent race condition | 25 | # to prevent race condition |