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
Gemfile
app/assets/stylesheets/gitlab_bootstrap/files.scss
... | ... | @@ -68,10 +68,22 @@ |
68 | 68 | * Blame file |
69 | 69 | */ |
70 | 70 | &.blame { |
71 | + table { | |
72 | + border:none; | |
73 | + box-shadow:none; | |
74 | + margin:0; | |
75 | + } | |
71 | 76 | tr { |
72 | 77 | border-bottom: 1px solid #eee; |
73 | 78 | } |
74 | 79 | td { |
80 | + &:first-child { | |
81 | + border-left:none; | |
82 | + } | |
83 | + &:last-child { | |
84 | + border-right:none; | |
85 | + } | |
86 | + background:#fff; | |
75 | 87 | padding:5px; |
76 | 88 | } |
77 | 89 | .author, | ... | ... |
app/assets/stylesheets/sections/nav.scss
app/controllers/application_controller.rb
... | ... | @@ -2,7 +2,6 @@ class ApplicationController < ActionController::Base |
2 | 2 | before_filter :authenticate_user! |
3 | 3 | before_filter :reject_blocked! |
4 | 4 | before_filter :set_current_user_for_mailer |
5 | - before_filter :check_token_auth | |
6 | 5 | before_filter :set_current_user_for_observers |
7 | 6 | before_filter :dev_tools if Rails.env == 'development' |
8 | 7 | |
... | ... | @@ -24,13 +23,6 @@ class ApplicationController < ActionController::Base |
24 | 23 | |
25 | 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 | 26 | def reject_blocked! |
35 | 27 | if current_user && current_user.blocked |
36 | 28 | sign_out current_user |
... | ... | @@ -103,7 +95,7 @@ class ApplicationController < ActionController::Base |
103 | 95 | end |
104 | 96 | |
105 | 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 | 99 | end |
108 | 100 | |
109 | 101 | def require_non_empty_project |
... | ... | @@ -116,10 +108,6 @@ class ApplicationController < ActionController::Base |
116 | 108 | response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT" |
117 | 109 | end |
118 | 110 | |
119 | - def render_full_content | |
120 | - @full_content = true | |
121 | - end | |
122 | - | |
123 | 111 | def dev_tools |
124 | 112 | Rack::MiniProfiler.authorize_request |
125 | 113 | end | ... | ... |
... | ... | @@ -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 @@ |
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 @@ |
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 | 1 | require "base64" |
2 | 2 | |
3 | 3 | class CommitsController < ProjectController |
4 | + include ExtractsPath | |
5 | + | |
4 | 6 | # Authorize |
5 | 7 | before_filter :authorize_read_project! |
6 | 8 | before_filter :authorize_code_access! |
7 | 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 | 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 | 16 | @commits = CommitDecorator.decorate(@commits) |
17 | 17 | |
18 | 18 | respond_to do |format| |
... | ... | @@ -21,54 +21,4 @@ class CommitsController < ProjectController |
21 | 21 | format.atom { render layout: false } |
22 | 22 | end |
23 | 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 | 24 | end | ... | ... |
... | ... | @@ -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 | 4 | before_filter :require_non_empty_project |
5 | 5 | |
6 | 6 | before_filter :authorize_admin_project!, only: [:destroy, :create] |
7 | - before_filter :render_full_content | |
8 | 7 | |
9 | 8 | def index |
10 | 9 | @branches = @project.protected_branches.all | ... | ... |
app/controllers/refs_controller.rb
1 | -require 'github/markup' | |
2 | - | |
3 | 1 | class RefsController < ProjectController |
4 | 2 | include Gitlab::Encode |
5 | 3 | |
... | ... | @@ -9,21 +7,20 @@ class RefsController < ProjectController |
9 | 7 | before_filter :require_non_empty_project |
10 | 8 | |
11 | 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 | 12 | def switch |
16 | 13 | respond_to do |format| |
17 | 14 | format.html do |
18 | 15 | new_path = if params[:destination] == "tree" |
19 | - tree_project_ref_path(@project, params[:ref]) | |
16 | + project_tree_path(@project, @ref) | |
20 | 17 | else |
21 | - project_commits_path(@project, ref: params[:ref]) | |
18 | + project_commits_path(@project, @ref) | |
22 | 19 | end |
23 | 20 | |
24 | - redirect_to new_path | |
21 | + redirect_to new_path | |
25 | 22 | end |
26 | - format.js do | |
23 | + format.js do | |
27 | 24 | @ref = params[:ref] |
28 | 25 | define_tree_vars |
29 | 26 | render "tree" |
... | ... | @@ -31,19 +28,6 @@ class RefsController < ProjectController |
31 | 28 | end |
32 | 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 | 31 | def logs_tree |
48 | 32 | contents = @tree.contents |
49 | 33 | @logs = contents.map do |content| |
... | ... | @@ -51,36 +35,12 @@ class RefsController < ProjectController |
51 | 35 | last_commit = @project.commits(@commit.id, file, 1).last |
52 | 36 | last_commit = CommitDecorator.decorate(last_commit) |
53 | 37 | { |
54 | - file_name: content.name, | |
38 | + file_name: content.name, | |
55 | 39 | commit: last_commit |
56 | 40 | } |
57 | 41 | end |
58 | 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 | 44 | protected |
85 | 45 | |
86 | 46 | def define_tree_vars |
... | ... | @@ -91,20 +51,20 @@ class RefsController < ProjectController |
91 | 51 | @commit = CommitDecorator.decorate(@commit) |
92 | 52 | @tree = Tree.new(@commit.tree, project, @ref, params[:path]) |
93 | 53 | @tree = TreeDecorator.new(@tree) |
94 | - @hex_path = Digest::SHA1.hexdigest(params[:path] || "/") | |
54 | + @hex_path = Digest::SHA1.hexdigest(params[:path] || "") | |
95 | 55 | |
96 | 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 | 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 | 62 | end |
103 | 63 | rescue |
104 | 64 | return render_404 |
105 | 65 | end |
106 | - | |
66 | + | |
107 | 67 | def ref |
108 | - @ref = params[:id] | |
68 | + @ref = params[:id] || params[:ref] | |
109 | 69 | end |
110 | 70 | end | ... | ... |
app/controllers/repositories_controller.rb
... | ... | @@ -3,18 +3,17 @@ class RepositoriesController < ProjectController |
3 | 3 | before_filter :authorize_read_project! |
4 | 4 | before_filter :authorize_code_access! |
5 | 5 | before_filter :require_non_empty_project |
6 | - before_filter :render_full_content | |
7 | 6 | |
8 | 7 | def show |
9 | 8 | @activities = @project.commits_with_refs(20) |
10 | 9 | end |
11 | 10 | |
12 | 11 | def branches |
13 | - @branches = @project.repo.heads.sort_by(&:name) | |
12 | + @branches = @project.branches | |
14 | 13 | end |
15 | 14 | |
16 | 15 | def tags |
17 | - @tags = @project.repo.tags.sort_by(&:name).reverse | |
16 | + @tags = @project.tags | |
18 | 17 | end |
19 | 18 | |
20 | 19 | def archive | ... | ... |
app/controllers/snippets_controller.rb
... | ... | @@ -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 | 21 | elsif self.merge_request? |
22 | 22 | h.project_merge_request_url(self.project, self.merge_request) |
23 | 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 | 25 | end |
26 | 26 | end |
27 | 27 | end | ... | ... |
app/decorators/tree_decorator.rb
... | ... | @@ -6,7 +6,7 @@ class TreeDecorator < ApplicationDecorator |
6 | 6 | part_path = "" |
7 | 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 | 11 | yield(h.link_to("..", "#", remote: :true)) if parts.count > max_links |
12 | 12 | |
... | ... | @@ -15,29 +15,29 @@ class TreeDecorator < ApplicationDecorator |
15 | 15 | part_path = part if part_path.empty? |
16 | 16 | |
17 | 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 | 19 | end |
20 | 20 | end |
21 | 21 | end |
22 | 22 | |
23 | 23 | def up_dir? |
24 | - !!path | |
24 | + path.present? | |
25 | 25 | end |
26 | 26 | |
27 | 27 | def up_dir_path |
28 | 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 | 30 | end |
31 | 31 | |
32 | 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 | 34 | end |
35 | 35 | |
36 | 36 | def mb_size |
37 | 37 | size = (tree.size / 1024) |
38 | 38 | if size < 1024 |
39 | - "#{size} KB" | |
40 | - else | |
39 | + "#{size} KB" | |
40 | + else | |
41 | 41 | "#{size/1024} MB" |
42 | 42 | end |
43 | 43 | end | ... | ... |
app/helpers/application_helper.rb
1 | 1 | require 'digest/md5' |
2 | + | |
2 | 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 | 33 | def gravatar_icon(user_email = '', size = 40) |
5 | 34 | if Gitlab.config.disable_gravatar? || user_email.blank? |
6 | 35 | 'no_avatar.png' |
... | ... | @@ -31,8 +60,8 @@ module ApplicationHelper |
31 | 60 | |
32 | 61 | def grouped_options_refs(destination = :tree) |
33 | 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 | 67 | # If reference is commit id - |
... | ... | @@ -58,11 +87,11 @@ module ApplicationHelper |
58 | 87 | |
59 | 88 | if @project && !@project.new_record? |
60 | 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 | 96 | end |
68 | 97 | |
... | ... | @@ -85,45 +114,6 @@ module ApplicationHelper |
85 | 114 | event.project.merge_requests_enabled |
86 | 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 | 117 | def hexdigest(string) |
128 | 118 | Digest::SHA1.hexdigest string |
129 | 119 | end | ... | ... |
app/helpers/tab_helper.rb
1 | 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 | 68 | end |
9 | 69 | |
10 | 70 | def project_tab_class |
11 | 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 | 73 | end |
14 | 74 | |
15 | 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 | 77 | end |
28 | 78 | end |
29 | 79 | |
30 | 80 | def branches_tab_class |
31 | 81 | if current_page?(branches_project_repository_path(@project)) || |
32 | - controller.controller_name == "protected_branches" || | |
82 | + current_controller?(:protected_branches) || | |
33 | 83 | current_page?(project_repository_path(@project)) |
34 | 84 | 'active' |
35 | 85 | end | ... | ... |
app/helpers/tree_helper.rb
app/models/merge_request.rb
app/models/tree.rb
1 | 1 | class Tree |
2 | - include Linguist::BlobHelper | |
2 | + include Linguist::BlobHelper | |
3 | 3 | attr_accessor :path, :tree, :project, :ref |
4 | 4 | |
5 | 5 | delegate :contents, |
... | ... | @@ -14,8 +14,8 @@ class Tree |
14 | 14 | to: :tree |
15 | 15 | |
16 | 16 | def initialize(raw_tree, project, ref = nil, path = nil) |
17 | - @project, @ref, @path = project, ref, path, | |
18 | - @tree = if path | |
17 | + @project, @ref, @path = project, ref, path | |
18 | + @tree = if path.present? | |
19 | 19 | raw_tree / path.dup.force_encoding('ascii-8bit') |
20 | 20 | else |
21 | 21 | raw_tree |
... | ... | @@ -26,6 +26,10 @@ class Tree |
26 | 26 | tree.is_a?(Grit::Blob) |
27 | 27 | end |
28 | 28 | |
29 | + def invalid? | |
30 | + tree.nil? | |
31 | + end | |
32 | + | |
29 | 33 | def empty? |
30 | 34 | data.blank? |
31 | 35 | end | ... | ... |
app/roles/repository.rb
... | ... | @@ -45,8 +45,29 @@ module Repository |
45 | 45 | File.exists?(hook_file) |
46 | 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 | 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 | 71 | end |
51 | 72 | |
52 | 73 | def repo |
... | ... | @@ -79,14 +100,6 @@ module Repository |
79 | 100 | @heads ||= repo.heads |
80 | 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 | 103 | def tree(fcommit, path = nil) |
91 | 104 | fcommit = commit if fcommit == :head |
92 | 105 | tree = fcommit.tree |
... | ... | @@ -109,14 +122,12 @@ module Repository |
109 | 122 | # - If two or more branches are present, returns the one that has a name |
110 | 123 | # matching root_ref (default_branch or 'master' if default_branch is nil) |
111 | 124 | def discover_default_branch |
112 | - branches = heads.collect(&:name) | |
113 | - | |
114 | - if branches.length == 0 | |
125 | + if branch_names.length == 0 | |
115 | 126 | nil |
116 | - elsif branches.length == 1 | |
117 | - branches.first | |
127 | + elsif branch_names.length == 1 | |
128 | + branch_names.first | |
118 | 129 | else |
119 | - branches.select { |v| v == root_ref }.first | |
130 | + branch_names.select { |v| v == root_ref }.first | |
120 | 131 | end |
121 | 132 | end |
122 | 133 | |
... | ... | @@ -144,7 +155,7 @@ module Repository |
144 | 155 | |
145 | 156 | # Build file path |
146 | 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 | 159 | file_path = File.join(storage_path, file_name) |
149 | 160 | |
150 | 161 | # Put files into a directory before archiving | ... | ... |
app/roles/static_model.rb
... | ... | @@ -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 @@ |
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 @@ |
1 | +<%= @commit.to_patch %> | ... | ... |
app/views/commits/_commit.html.haml
1 | 1 | %li.commit |
2 | 2 | .browse_code_link_holder |
3 | 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 | 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 | 7 | %strong.commit-author-name= commit.author_name |
8 | 8 | %span.dash – |
9 | 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 | 12 | %span.committed_ago |
13 | 13 | = time_ago_in_words(commit.committed_date) |
14 | 14 | ago |
15 | 15 | |
16 | - | ... | ... |
app/views/commits/_commit_box.html.haml
... | ... | @@ -5,10 +5,10 @@ |
5 | 5 | %span.btn.disabled.grouped |
6 | 6 | %i.icon-comment |
7 | 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 | 9 | %i.icon-download-alt |
10 | 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 | 12 | %strong Browse Code » |
13 | 13 | %h3.commit-title.page_title |
14 | 14 | = gfm escape_once(@commit.title) | ... | ... |
app/views/commits/_diffs.html.haml
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | %p To prevent performance issue we rejected diff information. |
6 | 6 | %p |
7 | 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 | 10 | %p.cgray |
11 | 11 | Showing #{pluralize(diffs.count, "changed file")} |
... | ... | @@ -24,7 +24,7 @@ |
24 | 24 | %i.icon-file |
25 | 25 | %span{id: "#{diff.old_path}"}= diff.old_path |
26 | 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 | 28 | %i.icon-file |
29 | 29 | %span{id: "#{diff.new_path}"}= diff.new_path |
30 | 30 | %br/ | ... | ... |
app/views/commits/_head.html.haml
1 | 1 | %ul.nav.nav-tabs |
2 | 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 | 10 | = link_to project_repository_path(@project) do |
11 | 11 | Branches |
12 | 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 | 15 | = link_to tags_project_repository_path(@project) do |
16 | 16 | Tags |
17 | 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 | 20 | %li.right |
21 | 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 | 23 | = image_tag "rss_ui.png", title: "feed" | ... | ... |
app/views/commits/compare.html.haml
... | ... | @@ -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 | -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 | -= 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 @@ |
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 @@ |
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 @@ |
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 | 1 | - commit = CommitDecorator.decorate(commit) |
2 | 2 | %li.commit |
3 | 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 | 5 | %span= commit.author_name |
6 | 6 | – |
7 | 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 | 4 | = image_tag gravatar_icon(event.author_email), class: "avatar" |
5 | 5 | %span You pushed to |
6 | 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 | 8 | %strong= truncate(event.ref_name, length: 28) |
9 | 9 | at |
10 | 10 | %strong= link_to event.project.name, event.project | ... | ... |
app/views/events/_event_push.html.haml
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | .event-title |
6 | 6 | %strong.author_name #{event.author_name} |
7 | 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 | 9 | %strong= event.ref_name |
10 | 10 | at |
11 | 11 | %strong= link_to event.project.name, event.project |
... | ... | @@ -21,6 +21,6 @@ |
21 | 21 | %li.commits-stat |
22 | 22 | - if event.commits_count > 2 |
23 | 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 | 25 | %strong Compare → #{event.parent_commit.id[0..7]}...#{event.last_commit.id[0..7]} |
26 | 26 | .clearfix | ... | ... |
app/views/issues/_head.html.haml
1 | 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 | 8 | %li.right |
12 | 9 | %span.rss-icon |
13 | 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 | -%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 | 10 | - if controller_name == 'projects' && action_name == 'index' |
11 | 11 | = auto_discovery_link_tag :atom, projects_url(:atom, private_token: current_user.private_token), title: "Dashboard feed" |
12 | 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 | 16 | = auto_discovery_link_tag(:atom, project_issues_url(@project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues") |
17 | 17 | = csrf_meta_tags | ... | ... |
app/views/layouts/_project_menu.html.haml
... | ... | @@ -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 | 6 | = render "layouts/head_panel", title: "Admin area" |
7 | 7 | .container |
8 | 8 | %ul.main_menu |
9 | - %li.home{class: tab_class(:admin_root)} | |
9 | + = nav_link(controller: :dashboard, html_options: {class: 'home'}) do | |
10 | 10 | = link_to "Stats", admin_root_path |
11 | - %li{class: tab_class(:admin_projects)} | |
11 | + = nav_link(controller: :projects) do | |
12 | 12 | = link_to "Projects", admin_projects_path |
13 | - %li{class: tab_class(:admin_users)} | |
13 | + = nav_link(controller: :users) do | |
14 | 14 | = link_to "Users", admin_users_path |
15 | - %li{class: tab_class(:admin_logs)} | |
15 | + = nav_link(controller: :logs) do | |
16 | 16 | = link_to "Logs", admin_logs_path |
17 | - %li{class: tab_class(:admin_hooks)} | |
17 | + = nav_link(controller: :hooks) do | |
18 | 18 | = link_to "Hooks", admin_hooks_path |
19 | - %li{class: tab_class(:admin_resque)} | |
19 | + = nav_link(controller: :resque) do | |
20 | 20 | = link_to "Resque", admin_resque_path |
21 | 21 | |
22 | 22 | .content= yield | ... | ... |
app/views/layouts/application.html.haml
... | ... | @@ -5,6 +5,20 @@ |
5 | 5 | = render "layouts/flash" |
6 | 6 | = render "layouts/head_panel", title: "Dashboard" |
7 | 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 | 6 | = render "layouts/head_panel", title: "Profile" |
7 | 7 | .container |
8 | 8 | %ul.main_menu |
9 | - %li.home{class: tab_class(:profile)} | |
9 | + = nav_link(path: 'profile#show', html_options: {class: 'home'}) do | |
10 | 10 | = link_to "Profile", profile_path |
11 | - | |
12 | - %li{class: tab_class(:account)} | |
11 | + = nav_link(path: 'profile#account') do | |
13 | 12 | = link_to "Account", profile_account_path |
14 | - | |
15 | - %li{class: tab_class(:ssh_keys)} | |
13 | + = nav_link(controller: :keys) do | |
16 | 14 | = link_to keys_path do |
17 | 15 | SSH Keys |
18 | 16 | %span.count= current_user.keys.count |
19 | - | |
20 | - %li{class: tab_class(:design)} | |
17 | + = nav_link(path: 'profile#design') do | |
21 | 18 | = link_to "Design", profile_design_path |
22 | - | |
23 | - %li{class: tab_class(:history)} | |
19 | + = nav_link(path: 'profile#history') do | |
24 | 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 | 5 | = render "layouts/flash" |
6 | 6 | = render "layouts/head_panel", title: @project.name |
7 | 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 | 1 | %ul.nav.nav-tabs |
2 | - %li{ class: "#{'active' if current_page?(project_path(@project)) }" } | |
2 | + = nav_link(path: 'projects#show') do | |
3 | 3 | = link_to project_path(@project), class: "activities-tab tab" do |
4 | 4 | %i.icon-home |
5 | 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 | 7 | = link_to project_team_index_path(@project), class: "team-tab tab" do |
8 | 8 | %i.icon-user |
9 | 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 | 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 | 17 | = link_to project_deploy_keys_path(@project) do |
20 | 18 | %span |
21 | 19 | Deploy Keys |
22 | - %li.right{class: "#{'active' if controller.controller_name == "hooks" }"} | |
20 | + = nav_link(controller: :hooks, html_options: {class: 'right'}) do | |
23 | 21 | = link_to project_hooks_path(@project) do |
24 | 22 | %span |
25 | 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 | 25 | = link_to edit_project_path(@project), class: "stat-tab tab " do |
28 | 26 | %i.icon-edit |
29 | 27 | Edit | ... | ... |
app/views/protected_branches/index.html.haml
... | ... | @@ -34,7 +34,7 @@ |
34 | 34 | - @branches.each do |branch| |
35 | 35 | %tr |
36 | 36 | %td |
37 | - = link_to project_commits_path(@project, ref: branch.name) do | |
37 | + = link_to project_commits_path(@project, branch.name) do | |
38 | 38 | %strong= branch.name |
39 | 39 | - if branch.name == @project.root_ref |
40 | 40 | %span.label default | ... | ... |
app/views/refs/_head.html.haml
... | ... | @@ -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 | -- 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 | -%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 | -.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 | -- 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 | -= 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 | 6 | :plain |
7 | 7 | var row = $("table.table_#{@hex_path} tr.file_#{hexdigest(file_name)}"); |
8 | 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 | -: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 | 2 | - commit = CommitDecorator.decorate(commit) |
3 | 3 | %tr |
4 | 4 | %td |
5 | - = link_to project_commits_path(@project, ref: branch.name) do | |
5 | + = link_to project_commits_path(@project, branch.name) do | |
6 | 6 | %strong= truncate(branch.name, length: 60) |
7 | 7 | - if branch.name == @project.root_ref |
8 | 8 | %span.label default |
9 | 9 | %td |
10 | - = link_to project_commit_path(@project, id: commit.id) do | |
10 | + = link_to project_commit_path(@project, commit) do | |
11 | 11 | %code= commit.short_id |
12 | 12 | |
13 | 13 | = image_tag gravatar_icon(commit.author_email), class: "", width: 16 | ... | ... |
app/views/repositories/_branches_head.html.haml
1 | 1 | = render "commits/head" |
2 | 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 | 2 | - commit = CommitDecorator.new(commit) |
3 | 3 | %tr |
4 | 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 | 6 | %strong |
7 | 7 | = commit.head.name |
8 | 8 | - if commit.head.name == @project.root_ref | ... | ... |
app/views/repositories/tags.html.haml
... | ... | @@ -12,7 +12,7 @@ |
12 | 12 | - commit = CommitDecorator.decorate(commit) |
13 | 13 | %tr |
14 | 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 | 16 | %td |
17 | 17 | = link_to project_commit_path(@project, commit.id) do |
18 | 18 | %code= commit.short_id | ... | ... |
app/views/shared/_ref_switcher.html.haml
1 | 1 | = form_tag switch_project_refs_path(@project), method: :get, class: "project-refs-form" do |
2 | 2 | = select_tag "ref", grouped_options_refs, class: "project-refs-select chosen" |
3 | 3 | = hidden_field_tag :destination, destination |
4 | - - if respond_to?(:path) | |
4 | + - if defined?(path) | |
5 | 5 | = hidden_field_tag :path, path | ... | ... |
... | ... | @@ -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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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
config/initializers/inflections.rb
... | ... | @@ -8,3 +8,24 @@ |
8 | 8 | # inflect.irregular 'person', 'people' |
9 | 9 | # inflect.uncountable %w( fish sheep ) |
10 | 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
config/routes.rb
... | ... | @@ -122,38 +122,14 @@ Gitlab::Application.routes.draw do |
122 | 122 | end |
123 | 123 | |
124 | 124 | member do |
125 | - get "tree", constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } | |
125 | + # tree viewer logs | |
126 | 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 | 127 | get "logs_tree/:path" => "refs#logs_tree", |
144 | 128 | as: :logs_file, |
145 | 129 | constraints: { |
146 | 130 | id: /[a-zA-Z.0-9\/_\-]+/, |
147 | 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 | 133 | end |
158 | 134 | end |
159 | 135 | |
... | ... | @@ -182,27 +158,27 @@ Gitlab::Application.routes.draw do |
182 | 158 | get :test |
183 | 159 | end |
184 | 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 | 170 | resources :team, controller: 'team_members', only: [:index] |
195 | 171 | resources :team_members |
196 | 172 | resources :milestones |
197 | 173 | resources :labels, only: [:index] |
198 | 174 | resources :issues do |
199 | - | |
200 | 175 | collection do |
201 | 176 | post :sort |
202 | 177 | post :bulk_update |
203 | 178 | get :search |
204 | 179 | end |
205 | 180 | end |
181 | + | |
206 | 182 | resources :notes, only: [:index, :create, :destroy] do |
207 | 183 | collection do |
208 | 184 | post :preview | ... | ... |
db/fixtures/test/001_repo.rb
... | ... | @@ -3,13 +3,13 @@ require 'fileutils' |
3 | 3 | print "Unpacking seed repository..." |
4 | 4 | |
5 | 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 | 8 | # Make whatever directories we need to make |
9 | 9 | FileUtils.mkdir_p(REPO_PATH) |
10 | 10 | |
11 | 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 | 14 | # chdir to the repo path |
15 | 15 | FileUtils.cd(REPO_PATH) do | ... | ... |
... | ... | @@ -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 @@ |
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 @@ |
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 @@ |
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 | 1 | Feature: Project Browse commits |
2 | 2 | Background: |
3 | 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 | 7 | Scenario: I browse commits list for master branch |
8 | 8 | Then I see project commits |
... | ... | @@ -18,4 +18,4 @@ Feature: Project Browse commits |
18 | 18 | Scenario: I compare refs |
19 | 19 | Given I visit compare refs page |
20 | 20 | And I fill compare fields with refs |
21 | - And I see compared refs | |
21 | + Then I see compared refs | ... | ... |
... | ... | @@ -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 @@ |
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 @@ |
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 @@ |
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 | 4 | include SharedPaths |
5 | 5 | |
6 | 6 | Then 'I see project commits' do |
7 | - current_path.should == project_commits_path(@project) | |
8 | - | |
9 | 7 | commit = @project.commit |
10 | 8 | page.should have_content(@project.name) |
11 | 9 | page.should have_content(commit.message) |
... | ... | @@ -34,14 +32,14 @@ class ProjectBrowseCommits < Spinach::FeatureSteps |
34 | 32 | end |
35 | 33 | |
36 | 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 | 37 | click_button "Compare" |
40 | 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 | 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 | 44 | end |
47 | 45 | end | ... | ... |
features/steps/project/project_browse_files.rb
... | ... | @@ -10,7 +10,7 @@ class ProjectBrowseFiles < Spinach::FeatureSteps |
10 | 10 | end |
11 | 11 | |
12 | 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 | 14 | page.should have_content "app" |
15 | 15 | page.should have_content "History" |
16 | 16 | page.should have_content "Gemfile" | ... | ... |
... | ... | @@ -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 | 1 | module SharedPaths |
2 | 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 | 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 | 14 | end |
11 | 15 | |
12 | - And 'I visit dashboard issues page' do | |
16 | + Given 'I visit dashboard issues page' do | |
13 | 17 | visit dashboard_issues_path |
14 | 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 | 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 | 36 | Given 'I visit profile page' do |
21 | 37 | visit profile_path |
22 | 38 | end |
... | ... | @@ -25,14 +41,94 @@ module SharedPaths |
25 | 41 | visit profile_account_path |
26 | 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 | 56 | Given 'I visit profile token page' do |
29 | 57 | visit profile_token_path |
30 | 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 | 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 | 132 | And 'I visit project "Shop" page' do |
37 | 133 | project = Project.find_by_name("Shop") |
38 | 134 | visit project_path(project) |
... | ... | @@ -43,23 +139,27 @@ module SharedPaths |
43 | 139 | end |
44 | 140 | |
45 | 141 | Given 'I visit compare refs page' do |
46 | - visit compare_project_commits_path(@project) | |
142 | + visit project_compare_index_path(@project) | |
47 | 143 | end |
48 | 144 | |
49 | 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 | 151 | end |
52 | 152 | |
53 | 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 | 155 | end |
56 | 156 | |
57 | 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 | 159 | end |
60 | 160 | |
61 | 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 | 163 | end |
64 | 164 | |
65 | 165 | Given 'I visit project tags page' do | ... | ... |
features/steps/shared/project.rb
1 | 1 | module SharedProject |
2 | 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 | 11 | And 'I own project "Shop"' do |
5 | 12 | @project = Factory :project, :name => "Shop" |
6 | 13 | @project.add_access(@user, :admin) | ... | ... |
features/support/env.rb
... | ... | @@ -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 | 10 | attr_reader :config_tmp_dir, :ga_repo, :conf |
11 | 11 | |
12 | 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 | 14 | end |
15 | 15 | |
16 | 16 | def ga_repo |
... | ... | @@ -19,7 +19,7 @@ module Gitlab |
19 | 19 | |
20 | 20 | def apply |
21 | 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 | 23 | begin |
24 | 24 | # Set exclusive lock |
25 | 25 | # to prevent race condition | ... | ... |
lib/gitlab/logger.rb
lib/gitlab/markdown.rb
... | ... | @@ -174,7 +174,7 @@ module Gitlab |
174 | 174 | |
175 | 175 | def reference_commit(identifier) |
176 | 176 | if commit = @project.commit(identifier) |
177 | - link_to(identifier, project_commit_path(@project, id: commit.id), html_options.merge(title: CommitDecorator.new(commit).link_title, class: "gfm gfm-commit #{html_options[:class]}")) | |
177 | + link_to(identifier, project_commit_path(@project, commit), html_options.merge(title: CommitDecorator.new(commit).link_title, class: "gfm gfm-commit #{html_options[:class]}")) | |
178 | 178 | end |
179 | 179 | end |
180 | 180 | end | ... | ... |
lib/gitlab/merge.rb
... | ... | @@ -28,7 +28,7 @@ module Gitlab |
28 | 28 | |
29 | 29 | def process |
30 | 30 | Grit::Git.with_timeout(30.seconds) do |
31 | - lock_file = File.join(Rails.root, "tmp", "merge_repo_#{project.path}.lock") | |
31 | + lock_file = Rails.root.join("tmp", "merge_repo_#{project.path}.lock") | |
32 | 32 | |
33 | 33 | File.open(lock_file, "w+") do |f| |
34 | 34 | f.flock(File::LOCK_EX) |
... | ... | @@ -36,7 +36,7 @@ module Gitlab |
36 | 36 | unless project.satellite.exists? |
37 | 37 | raise "You should run: rake gitlab:app:enable_automerge" |
38 | 38 | end |
39 | - | |
39 | + | |
40 | 40 | project.satellite.clear |
41 | 41 | |
42 | 42 | Dir.chdir(project.satellite.path) do | ... | ... |
lib/gitlab/satellite.rb
1 | 1 | module Gitlab |
2 | 2 | class Satellite |
3 | - | |
3 | + | |
4 | 4 | PARKING_BRANCH = "__parking_branch" |
5 | 5 | |
6 | 6 | attr_accessor :project |
... | ... | @@ -14,7 +14,7 @@ module Gitlab |
14 | 14 | end |
15 | 15 | |
16 | 16 | def path |
17 | - File.join(Rails.root, "tmp", "repo_satellites", project.path) | |
17 | + Rails.root.join("tmp", "repo_satellites", project.path) | |
18 | 18 | end |
19 | 19 | |
20 | 20 | def exists? |
... | ... | @@ -36,6 +36,6 @@ module Gitlab |
36 | 36 | end |
37 | 37 | end |
38 | 38 | end |
39 | - | |
39 | + | |
40 | 40 | end |
41 | 41 | end | ... | ... |
... | ... | @@ -0,0 +1,22 @@ |
1 | +require 'spec_helper' | |
2 | + | |
3 | +describe CommitsController do | |
4 | + let(:project) { create(:project) } | |
5 | + let(:user) { create(:user) } | |
6 | + | |
7 | + before do | |
8 | + sign_in(user) | |
9 | + | |
10 | + project.add_access(user, :read, :admin) | |
11 | + end | |
12 | + | |
13 | + describe "GET show" do | |
14 | + context "as atom feed" do | |
15 | + it "should render as atom" do | |
16 | + get :show, project_id: project.code, id: "master.atom" | |
17 | + response.should be_success | |
18 | + response.content_type.should == 'application/atom+xml' | |
19 | + end | |
20 | + end | |
21 | + end | |
22 | +end | ... | ... |
... | ... | @@ -0,0 +1,43 @@ |
1 | +require 'spec_helper' | |
2 | + | |
3 | +describe TreeController do | |
4 | + let(:project) { create(:project) } | |
5 | + let(:user) { create(:user) } | |
6 | + | |
7 | + before do | |
8 | + sign_in(user) | |
9 | + | |
10 | + project.add_access(user, :read, :admin) | |
11 | + | |
12 | + project.stub(:branches).and_return(['master', 'foo/bar/baz']) | |
13 | + project.stub(:tags).and_return(['v1.0.0', 'v2.0.0']) | |
14 | + controller.instance_variable_set(:@project, project) | |
15 | + end | |
16 | + | |
17 | + describe "GET show" do | |
18 | + # Make sure any errors accessing the tree in our views bubble up to this spec | |
19 | + render_views | |
20 | + | |
21 | + before { get :show, project_id: project.code, id: id } | |
22 | + | |
23 | + context "valid branch, no path" do | |
24 | + let(:id) { 'master' } | |
25 | + it { should respond_with(:success) } | |
26 | + end | |
27 | + | |
28 | + context "valid branch, valid path" do | |
29 | + let(:id) { 'master/README.md' } | |
30 | + it { should respond_with(:success) } | |
31 | + end | |
32 | + | |
33 | + context "valid branch, invalid path" do | |
34 | + let(:id) { 'master/invalid-path.rb' } | |
35 | + it { should respond_with(:not_found) } | |
36 | + end | |
37 | + | |
38 | + context "invalid branch, valid path" do | |
39 | + let(:id) { 'invalid-branch/README.md' } | |
40 | + it { should respond_with(:not_found) } | |
41 | + end | |
42 | + end | |
43 | +end | ... | ... |
spec/factories.rb
spec/helpers/application_helper_spec.rb
1 | 1 | require 'spec_helper' |
2 | 2 | |
3 | 3 | describe ApplicationHelper do |
4 | + describe 'current_controller?' do | |
5 | + before do | |
6 | + controller.stub!(:controller_name).and_return('foo') | |
7 | + end | |
8 | + | |
9 | + it "returns true when controller matches argument" do | |
10 | + current_controller?(:foo).should be_true | |
11 | + end | |
12 | + | |
13 | + it "returns false when controller does not match argument" do | |
14 | + current_controller?(:bar).should_not be_true | |
15 | + end | |
16 | + | |
17 | + it "should take any number of arguments" do | |
18 | + current_controller?(:baz, :bar).should_not be_true | |
19 | + current_controller?(:baz, :bar, :foo).should be_true | |
20 | + end | |
21 | + end | |
22 | + | |
23 | + describe 'current_action?' do | |
24 | + before do | |
25 | + stub!(:action_name).and_return('foo') | |
26 | + end | |
27 | + | |
28 | + it "returns true when action matches argument" do | |
29 | + current_action?(:foo).should be_true | |
30 | + end | |
31 | + | |
32 | + it "returns false when action does not match argument" do | |
33 | + current_action?(:bar).should_not be_true | |
34 | + end | |
35 | + | |
36 | + it "should take any number of arguments" do | |
37 | + current_action?(:baz, :bar).should_not be_true | |
38 | + current_action?(:baz, :bar, :foo).should be_true | |
39 | + end | |
40 | + end | |
41 | + | |
4 | 42 | describe "gravatar_icon" do |
5 | 43 | let(:user_email) { 'user@email.com' } |
6 | 44 | ... | ... |
... | ... | @@ -0,0 +1,44 @@ |
1 | +require 'spec_helper' | |
2 | + | |
3 | +describe TabHelper do | |
4 | + include ApplicationHelper | |
5 | + | |
6 | + describe 'nav_link' do | |
7 | + before do | |
8 | + controller.stub!(:controller_name).and_return('foo') | |
9 | + stub!(:action_name).and_return('foo') | |
10 | + end | |
11 | + | |
12 | + it "captures block output" do | |
13 | + nav_link { "Testing Blocks" }.should match(/Testing Blocks/) | |
14 | + end | |
15 | + | |
16 | + it "performs checks on the current controller" do | |
17 | + nav_link(controller: :foo).should match(/<li class="active">/) | |
18 | + nav_link(controller: :bar).should_not match(/active/) | |
19 | + nav_link(controller: [:foo, :bar]).should match(/active/) | |
20 | + end | |
21 | + | |
22 | + it "performs checks on the current action" do | |
23 | + nav_link(action: :foo).should match(/<li class="active">/) | |
24 | + nav_link(action: :bar).should_not match(/active/) | |
25 | + nav_link(action: [:foo, :bar]).should match(/active/) | |
26 | + end | |
27 | + | |
28 | + it "performs checks on both controller and action when both are present" do | |
29 | + nav_link(controller: :bar, action: :foo).should_not match(/active/) | |
30 | + nav_link(controller: :foo, action: :bar).should_not match(/active/) | |
31 | + nav_link(controller: :foo, action: :foo).should match(/active/) | |
32 | + end | |
33 | + | |
34 | + it "accepts a path shorthand" do | |
35 | + nav_link(path: 'foo#bar').should_not match(/active/) | |
36 | + nav_link(path: 'foo#foo').should match(/active/) | |
37 | + end | |
38 | + | |
39 | + it "passes extra html options to the list element" do | |
40 | + nav_link(action: :foo, html_options: {class: 'home'}).should match(/<li class="home active">/) | |
41 | + nav_link(html_options: {class: 'active'}).should match(/<li class="active">/) | |
42 | + end | |
43 | + end | |
44 | +end | ... | ... |
... | ... | @@ -0,0 +1,58 @@ |
1 | +require 'spec_helper' | |
2 | + | |
3 | +describe ExtractsPath do | |
4 | + include ExtractsPath | |
5 | + | |
6 | + let(:project) { double('project') } | |
7 | + | |
8 | + before do | |
9 | + @project = project | |
10 | + project.stub(:branches).and_return(['master', 'foo/bar/baz']) | |
11 | + project.stub(:tags).and_return(['v1.0.0', 'v2.0.0']) | |
12 | + end | |
13 | + | |
14 | + describe '#extract_ref' do | |
15 | + it "returns an empty pair when no @project is set" do | |
16 | + @project = nil | |
17 | + extract_ref('master/CHANGELOG').should == ['', ''] | |
18 | + end | |
19 | + | |
20 | + context "without a path" do | |
21 | + it "extracts a valid branch" do | |
22 | + extract_ref('master').should == ['master', ''] | |
23 | + end | |
24 | + | |
25 | + it "extracts a valid tag" do | |
26 | + extract_ref('v2.0.0').should == ['v2.0.0', ''] | |
27 | + end | |
28 | + | |
29 | + it "extracts a valid commit ref without a path" do | |
30 | + extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062').should == | |
31 | + ['f4b14494ef6abf3d144c28e4af0c20143383e062', ''] | |
32 | + end | |
33 | + | |
34 | + it "falls back to a primitive split for an invalid ref" do | |
35 | + extract_ref('stable').should == ['stable', ''] | |
36 | + end | |
37 | + end | |
38 | + | |
39 | + context "with a path" do | |
40 | + it "extracts a valid branch" do | |
41 | + extract_ref('foo/bar/baz/CHANGELOG').should == ['foo/bar/baz', 'CHANGELOG'] | |
42 | + end | |
43 | + | |
44 | + it "extracts a valid tag" do | |
45 | + extract_ref('v2.0.0/CHANGELOG').should == ['v2.0.0', 'CHANGELOG'] | |
46 | + end | |
47 | + | |
48 | + it "extracts a valid commit SHA" do | |
49 | + extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG').should == | |
50 | + ['f4b14494ef6abf3d144c28e4af0c20143383e062', 'CHANGELOG'] | |
51 | + end | |
52 | + | |
53 | + it "falls back to a primitive split for an invalid ref" do | |
54 | + extract_ref('stable/CHANGELOG').should == ['stable', 'CHANGELOG'] | |
55 | + end | |
56 | + end | |
57 | + end | |
58 | +end | ... | ... |
... | ... | @@ -0,0 +1,58 @@ |
1 | +require 'spec_helper' | |
2 | + | |
3 | +describe ExtractsPath do | |
4 | + include ExtractsPath | |
5 | + | |
6 | + let(:project) { double('project') } | |
7 | + | |
8 | + before do | |
9 | + @project = project | |
10 | + project.stub(:branches).and_return(['master', 'foo/bar/baz']) | |
11 | + project.stub(:tags).and_return(['v1.0.0', 'v2.0.0']) | |
12 | + end | |
13 | + | |
14 | + describe '#extract_ref' do | |
15 | + it "returns an empty pair when no @project is set" do | |
16 | + @project = nil | |
17 | + extract_ref('master/CHANGELOG').should == ['', ''] | |
18 | + end | |
19 | + | |
20 | + context "without a path" do | |
21 | + it "extracts a valid branch" do | |
22 | + extract_ref('master').should == ['master', ''] | |
23 | + end | |
24 | + | |
25 | + it "extracts a valid tag" do | |
26 | + extract_ref('v2.0.0').should == ['v2.0.0', ''] | |
27 | + end | |
28 | + | |
29 | + it "extracts a valid commit ref without a path" do | |
30 | + extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062').should == | |
31 | + ['f4b14494ef6abf3d144c28e4af0c20143383e062', ''] | |
32 | + end | |
33 | + | |
34 | + it "falls back to a primitive split for an invalid ref" do | |
35 | + extract_ref('stable').should == ['stable', ''] | |
36 | + end | |
37 | + end | |
38 | + | |
39 | + context "with a path" do | |
40 | + it "extracts a valid branch" do | |
41 | + extract_ref('foo/bar/baz/CHANGELOG').should == ['foo/bar/baz', 'CHANGELOG'] | |
42 | + end | |
43 | + | |
44 | + it "extracts a valid tag" do | |
45 | + extract_ref('v2.0.0/CHANGELOG').should == ['v2.0.0', 'CHANGELOG'] | |
46 | + end | |
47 | + | |
48 | + it "extracts a valid commit SHA" do | |
49 | + extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG').should == | |
50 | + ['f4b14494ef6abf3d144c28e4af0c20143383e062', 'CHANGELOG'] | |
51 | + end | |
52 | + | |
53 | + it "falls back to a primitive split for an invalid ref" do | |
54 | + extract_ref('stable/CHANGELOG').should == ['stable', 'CHANGELOG'] | |
55 | + end | |
56 | + end | |
57 | + end | |
58 | +end | ... | ... |
spec/models/project_spec.rb
... | ... | @@ -125,7 +125,7 @@ describe Project do |
125 | 125 | |
126 | 126 | it "should return path to repo" do |
127 | 127 | project = Project.new(path: "somewhere") |
128 | - project.path_to_repo.should == File.join(Rails.root, "tmp", "repositories", "somewhere") | |
128 | + project.path_to_repo.should == Rails.root.join("tmp", "repositories", "somewhere") | |
129 | 129 | end |
130 | 130 | |
131 | 131 | it "returns the full web URL for this repo" do | ... | ... |
spec/requests/atom/dashboard_spec.rb
... | ... | @@ -10,12 +10,5 @@ describe "Dashboard Feed" do |
10 | 10 | page.body.should have_selector("feed title") |
11 | 11 | end |
12 | 12 | end |
13 | - | |
14 | - context "projects page via private token" do | |
15 | - it "should redirect to login page" do | |
16 | - visit dashboard_path(private_token: user.private_token) | |
17 | - current_path.should == new_user_session_path | |
18 | - end | |
19 | - end | |
20 | 13 | end |
21 | 14 | end | ... | ... |
spec/requests/gitlab_flavored_markdown_spec.rb
... | ... | @@ -40,28 +40,27 @@ describe "Gitlab Flavored Markdown" do |
40 | 40 | project.add_access(@user, :read, :write) |
41 | 41 | end |
42 | 42 | |
43 | - | |
44 | 43 | describe "for commits" do |
45 | 44 | it "should render title in commits#index" do |
46 | - visit project_commits_path(project, ref: @branch_name) | |
45 | + visit project_commits_path(project, @branch_name, limit: 1) | |
47 | 46 | |
48 | 47 | page.should have_link("##{issue.id}") |
49 | 48 | end |
50 | 49 | |
51 | 50 | it "should render title in commits#show" do |
52 | - visit project_commit_path(project, id: commit.id) | |
51 | + visit project_commit_path(project, commit) | |
53 | 52 | |
54 | 53 | page.should have_link("##{issue.id}") |
55 | 54 | end |
56 | 55 | |
57 | 56 | it "should render description in commits#show" do |
58 | - visit project_commit_path(project, id: commit.id) | |
57 | + visit project_commit_path(project, commit) | |
59 | 58 | |
60 | 59 | page.should have_link("@#{fred.name}") |
61 | 60 | end |
62 | 61 | |
63 | 62 | it "should render title in refs#tree", js: true do |
64 | - visit tree_project_ref_path(project, id: @branch_name) | |
63 | + visit project_tree_path(project, @branch_name) | |
65 | 64 | |
66 | 65 | within(".tree_commit") do |
67 | 66 | page.should have_link("##{issue.id}") |
... | ... | @@ -69,7 +68,7 @@ describe "Gitlab Flavored Markdown" do |
69 | 68 | end |
70 | 69 | |
71 | 70 | it "should render title in refs#blame" do |
72 | - visit blame_file_project_ref_path(project, id: @branch_name, path: @test_file) | |
71 | + visit project_blame_path(project, File.join(@branch_name, @test_file)) | |
73 | 72 | |
74 | 73 | within(".blame_commit") do |
75 | 74 | page.should have_link("##{issue.id}") |
... | ... | @@ -89,7 +88,6 @@ describe "Gitlab Flavored Markdown" do |
89 | 88 | end |
90 | 89 | end |
91 | 90 | |
92 | - | |
93 | 91 | describe "for issues" do |
94 | 92 | before do |
95 | 93 | @other_issue = Factory :issue, |
... | ... | @@ -175,7 +173,7 @@ describe "Gitlab Flavored Markdown" do |
175 | 173 | |
176 | 174 | describe "for notes" do |
177 | 175 | it "should render in commits#show", js: true do |
178 | - visit project_commit_path(project, id: commit.id) | |
176 | + visit project_commit_path(project, commit) | |
179 | 177 | fill_in "note_note", with: "see ##{issue.id}" |
180 | 178 | click_button "Add Comment" |
181 | 179 | ... | ... |
spec/requests/security/project_access_spec.rb
... | ... | @@ -14,204 +14,228 @@ describe "Application access" do |
14 | 14 | end |
15 | 15 | |
16 | 16 | describe "Project" do |
17 | + let(:project) { create(:project) } | |
18 | + | |
19 | + let(:master) { create(:user) } | |
20 | + let(:guest) { create(:user) } | |
21 | + let(:reporter) { create(:user) } | |
22 | + | |
17 | 23 | before do |
18 | - @project = Factory :project | |
19 | - @u1 = Factory :user | |
20 | - @u2 = Factory :user | |
21 | - @u3 = Factory :user | |
22 | 24 | # full access |
23 | - @project.users_projects.create(user: @u1, project_access: UsersProject::MASTER) | |
25 | + project.users_projects.create(user: master, project_access: UsersProject::MASTER) | |
26 | + | |
24 | 27 | # readonly |
25 | - @project.users_projects.create(user: @u3, project_access: UsersProject::REPORTER) | |
28 | + project.users_projects.create(user: reporter, project_access: UsersProject::REPORTER) | |
26 | 29 | end |
27 | 30 | |
28 | 31 | describe "GET /project_code" do |
29 | - subject { project_path(@project) } | |
32 | + subject { project_path(project) } | |
30 | 33 | |
31 | - it { should be_allowed_for @u1 } | |
32 | - it { should be_allowed_for @u3 } | |
34 | + it { should be_allowed_for master } | |
35 | + it { should be_allowed_for reporter } | |
33 | 36 | it { should be_denied_for :admin } |
34 | - it { should be_denied_for @u2 } | |
37 | + it { should be_denied_for guest } | |
35 | 38 | it { should be_denied_for :user } |
36 | 39 | it { should be_denied_for :visitor } |
37 | 40 | end |
38 | 41 | |
39 | - describe "GET /project_code/master/tree" do | |
40 | - subject { tree_project_ref_path(@project, @project.root_ref) } | |
42 | + describe "GET /project_code/tree/master" do | |
43 | + subject { project_tree_path(project, project.root_ref) } | |
41 | 44 | |
42 | - it { should be_allowed_for @u1 } | |
43 | - it { should be_allowed_for @u3 } | |
45 | + it { should be_allowed_for master } | |
46 | + it { should be_allowed_for reporter } | |
44 | 47 | it { should be_denied_for :admin } |
45 | - it { should be_denied_for @u2 } | |
48 | + it { should be_denied_for guest } | |
46 | 49 | it { should be_denied_for :user } |
47 | 50 | it { should be_denied_for :visitor } |
48 | 51 | end |
49 | 52 | |
50 | - describe "GET /project_code/commits" do | |
51 | - subject { project_commits_path(@project) } | |
53 | + describe "GET /project_code/commits/master" do | |
54 | + subject { project_commits_path(project, project.root_ref, limit: 1) } | |
52 | 55 | |
53 | - it { should be_allowed_for @u1 } | |
54 | - it { should be_allowed_for @u3 } | |
56 | + it { should be_allowed_for master } | |
57 | + it { should be_allowed_for reporter } | |
55 | 58 | it { should be_denied_for :admin } |
56 | - it { should be_denied_for @u2 } | |
59 | + it { should be_denied_for guest } | |
57 | 60 | it { should be_denied_for :user } |
58 | 61 | it { should be_denied_for :visitor } |
59 | 62 | end |
60 | 63 | |
61 | - describe "GET /project_code/commit" do | |
62 | - subject { project_commit_path(@project, @project.commit.id) } | |
64 | + describe "GET /project_code/commit/:sha" do | |
65 | + subject { project_commit_path(project, project.commit) } | |
63 | 66 | |
64 | - it { should be_allowed_for @u1 } | |
65 | - it { should be_allowed_for @u3 } | |
67 | + it { should be_allowed_for master } | |
68 | + it { should be_allowed_for reporter } | |
66 | 69 | it { should be_denied_for :admin } |
67 | - it { should be_denied_for @u2 } | |
70 | + it { should be_denied_for guest } | |
71 | + it { should be_denied_for :user } | |
72 | + it { should be_denied_for :visitor } | |
73 | + end | |
74 | + | |
75 | + describe "GET /project_code/compare" do | |
76 | + subject { project_compare_index_path(project) } | |
77 | + | |
78 | + it { should be_allowed_for master } | |
79 | + it { should be_allowed_for reporter } | |
80 | + it { should be_denied_for :admin } | |
81 | + it { should be_denied_for guest } | |
68 | 82 | it { should be_denied_for :user } |
69 | 83 | it { should be_denied_for :visitor } |
70 | 84 | end |
71 | 85 | |
72 | 86 | describe "GET /project_code/team" do |
73 | - subject { project_team_index_path(@project) } | |
87 | + subject { project_team_index_path(project) } | |
74 | 88 | |
75 | - it { should be_allowed_for @u1 } | |
76 | - it { should be_allowed_for @u3 } | |
89 | + it { should be_allowed_for master } | |
90 | + it { should be_allowed_for reporter } | |
77 | 91 | it { should be_denied_for :admin } |
78 | - it { should be_denied_for @u2 } | |
92 | + it { should be_denied_for guest } | |
79 | 93 | it { should be_denied_for :user } |
80 | 94 | it { should be_denied_for :visitor } |
81 | 95 | end |
82 | 96 | |
83 | 97 | describe "GET /project_code/wall" do |
84 | - subject { wall_project_path(@project) } | |
98 | + subject { wall_project_path(project) } | |
85 | 99 | |
86 | - it { should be_allowed_for @u1 } | |
87 | - it { should be_allowed_for @u3 } | |
100 | + it { should be_allowed_for master } | |
101 | + it { should be_allowed_for reporter } | |
88 | 102 | it { should be_denied_for :admin } |
89 | - it { should be_denied_for @u2 } | |
103 | + it { should be_denied_for guest } | |
90 | 104 | it { should be_denied_for :user } |
91 | 105 | it { should be_denied_for :visitor } |
92 | 106 | end |
93 | 107 | |
94 | 108 | describe "GET /project_code/blob" do |
95 | 109 | before do |
96 | - commit = @project.commit | |
110 | + commit = project.commit | |
97 | 111 | path = commit.tree.contents.select { |i| i.is_a?(Grit::Blob)}.first.name |
98 | - @blob_path = blob_project_ref_path(@project, commit.id, path: path) | |
112 | + @blob_path = project_blob_path(project, File.join(commit.id, path)) | |
99 | 113 | end |
100 | 114 | |
101 | - it { @blob_path.should be_allowed_for @u1 } | |
102 | - it { @blob_path.should be_allowed_for @u3 } | |
115 | + it { @blob_path.should be_allowed_for master } | |
116 | + it { @blob_path.should be_allowed_for reporter } | |
103 | 117 | it { @blob_path.should be_denied_for :admin } |
104 | - it { @blob_path.should be_denied_for @u2 } | |
118 | + it { @blob_path.should be_denied_for guest } | |
105 | 119 | it { @blob_path.should be_denied_for :user } |
106 | 120 | it { @blob_path.should be_denied_for :visitor } |
107 | 121 | end |
108 | 122 | |
109 | 123 | describe "GET /project_code/edit" do |
110 | - subject { edit_project_path(@project) } | |
124 | + subject { edit_project_path(project) } | |
111 | 125 | |
112 | - it { should be_allowed_for @u1 } | |
113 | - it { should be_denied_for @u3 } | |
126 | + it { should be_allowed_for master } | |
127 | + it { should be_denied_for reporter } | |
114 | 128 | it { should be_denied_for :admin } |
115 | - it { should be_denied_for @u2 } | |
129 | + it { should be_denied_for guest } | |
116 | 130 | it { should be_denied_for :user } |
117 | 131 | it { should be_denied_for :visitor } |
118 | 132 | end |
119 | 133 | |
120 | 134 | describe "GET /project_code/deploy_keys" do |
121 | - subject { project_deploy_keys_path(@project) } | |
135 | + subject { project_deploy_keys_path(project) } | |
122 | 136 | |
123 | - it { should be_allowed_for @u1 } | |
124 | - it { should be_denied_for @u3 } | |
137 | + it { should be_allowed_for master } | |
138 | + it { should be_denied_for reporter } | |
125 | 139 | it { should be_denied_for :admin } |
126 | - it { should be_denied_for @u2 } | |
140 | + it { should be_denied_for guest } | |
127 | 141 | it { should be_denied_for :user } |
128 | 142 | it { should be_denied_for :visitor } |
129 | 143 | end |
130 | 144 | |
131 | 145 | describe "GET /project_code/issues" do |
132 | - subject { project_issues_path(@project) } | |
146 | + subject { project_issues_path(project) } | |
133 | 147 | |
134 | - it { should be_allowed_for @u1 } | |
135 | - it { should be_allowed_for @u3 } | |
148 | + it { should be_allowed_for master } | |
149 | + it { should be_allowed_for reporter } | |
136 | 150 | it { should be_denied_for :admin } |
137 | - it { should be_denied_for @u2 } | |
151 | + it { should be_denied_for guest } | |
138 | 152 | it { should be_denied_for :user } |
139 | 153 | it { should be_denied_for :visitor } |
140 | 154 | end |
141 | 155 | |
142 | 156 | describe "GET /project_code/snippets" do |
143 | - subject { project_snippets_path(@project) } | |
157 | + subject { project_snippets_path(project) } | |
144 | 158 | |
145 | - it { should be_allowed_for @u1 } | |
146 | - it { should be_allowed_for @u3 } | |
159 | + it { should be_allowed_for master } | |
160 | + it { should be_allowed_for reporter } | |
147 | 161 | it { should be_denied_for :admin } |
148 | - it { should be_denied_for @u2 } | |
162 | + it { should be_denied_for guest } | |
149 | 163 | it { should be_denied_for :user } |
150 | 164 | it { should be_denied_for :visitor } |
151 | 165 | end |
152 | 166 | |
153 | 167 | describe "GET /project_code/merge_requests" do |
154 | - subject { project_merge_requests_path(@project) } | |
168 | + subject { project_merge_requests_path(project) } | |
155 | 169 | |
156 | - it { should be_allowed_for @u1 } | |
157 | - it { should be_allowed_for @u3 } | |
170 | + it { should be_allowed_for master } | |
171 | + it { should be_allowed_for reporter } | |
158 | 172 | it { should be_denied_for :admin } |
159 | - it { should be_denied_for @u2 } | |
173 | + it { should be_denied_for guest } | |
160 | 174 | it { should be_denied_for :user } |
161 | 175 | it { should be_denied_for :visitor } |
162 | 176 | end |
163 | 177 | |
164 | 178 | describe "GET /project_code/repository" do |
165 | - subject { project_repository_path(@project) } | |
179 | + subject { project_repository_path(project) } | |
166 | 180 | |
167 | - it { should be_allowed_for @u1 } | |
168 | - it { should be_allowed_for @u3 } | |
181 | + it { should be_allowed_for master } | |
182 | + it { should be_allowed_for reporter } | |
169 | 183 | it { should be_denied_for :admin } |
170 | - it { should be_denied_for @u2 } | |
184 | + it { should be_denied_for guest } | |
171 | 185 | it { should be_denied_for :user } |
172 | 186 | it { should be_denied_for :visitor } |
173 | 187 | end |
174 | 188 | |
175 | 189 | describe "GET /project_code/repository/branches" do |
176 | - subject { branches_project_repository_path(@project) } | |
190 | + subject { branches_project_repository_path(project) } | |
191 | + | |
192 | + before do | |
193 | + # Speed increase | |
194 | + Project.any_instance.stub(:branches).and_return([]) | |
195 | + end | |
177 | 196 | |
178 | - it { should be_allowed_for @u1 } | |
179 | - it { should be_allowed_for @u3 } | |
197 | + it { should be_allowed_for master } | |
198 | + it { should be_allowed_for reporter } | |
180 | 199 | it { should be_denied_for :admin } |
181 | - it { should be_denied_for @u2 } | |
200 | + it { should be_denied_for guest } | |
182 | 201 | it { should be_denied_for :user } |
183 | 202 | it { should be_denied_for :visitor } |
184 | 203 | end |
185 | 204 | |
186 | 205 | describe "GET /project_code/repository/tags" do |
187 | - subject { tags_project_repository_path(@project) } | |
206 | + subject { tags_project_repository_path(project) } | |
207 | + | |
208 | + before do | |
209 | + # Speed increase | |
210 | + Project.any_instance.stub(:tags).and_return([]) | |
211 | + end | |
188 | 212 | |
189 | - it { should be_allowed_for @u1 } | |
190 | - it { should be_allowed_for @u3 } | |
213 | + it { should be_allowed_for master } | |
214 | + it { should be_allowed_for reporter } | |
191 | 215 | it { should be_denied_for :admin } |
192 | - it { should be_denied_for @u2 } | |
216 | + it { should be_denied_for guest } | |
193 | 217 | it { should be_denied_for :user } |
194 | 218 | it { should be_denied_for :visitor } |
195 | 219 | end |
196 | 220 | |
197 | 221 | describe "GET /project_code/hooks" do |
198 | - subject { project_hooks_path(@project) } | |
222 | + subject { project_hooks_path(project) } | |
199 | 223 | |
200 | - it { should be_allowed_for @u1 } | |
201 | - it { should be_allowed_for @u3 } | |
224 | + it { should be_allowed_for master } | |
225 | + it { should be_allowed_for reporter } | |
202 | 226 | it { should be_denied_for :admin } |
203 | - it { should be_denied_for @u2 } | |
227 | + it { should be_denied_for guest } | |
204 | 228 | it { should be_denied_for :user } |
205 | 229 | it { should be_denied_for :visitor } |
206 | 230 | end |
207 | 231 | |
208 | 232 | describe "GET /project_code/files" do |
209 | - subject { files_project_path(@project) } | |
233 | + subject { files_project_path(project) } | |
210 | 234 | |
211 | - it { should be_allowed_for @u1 } | |
212 | - it { should be_allowed_for @u3 } | |
235 | + it { should be_allowed_for master } | |
236 | + it { should be_allowed_for reporter } | |
213 | 237 | it { should be_denied_for :admin } |
214 | - it { should be_denied_for @u2 } | |
238 | + it { should be_denied_for guest } | |
215 | 239 | it { should be_denied_for :user } |
216 | 240 | it { should be_denied_for :visitor } |
217 | 241 | end | ... | ... |
spec/roles/repository_spec.rb
... | ... | @@ -21,27 +21,27 @@ describe Project, "Repository" do |
21 | 21 | end |
22 | 22 | |
23 | 23 | describe "#discover_default_branch" do |
24 | - let(:master) { double(name: 'master') } | |
25 | - let(:stable) { double(name: 'stable') } | |
24 | + let(:master) { 'master' } | |
25 | + let(:stable) { 'stable' } | |
26 | 26 | |
27 | 27 | it "returns 'master' when master exists" do |
28 | - project.should_receive(:heads).and_return([stable, master]) | |
28 | + project.should_receive(:branch_names).at_least(:once).and_return([stable, master]) | |
29 | 29 | project.discover_default_branch.should == 'master' |
30 | 30 | end |
31 | 31 | |
32 | 32 | it "returns non-master when master exists but default branch is set to something else" do |
33 | 33 | project.default_branch = 'stable' |
34 | - project.should_receive(:heads).and_return([stable, master]) | |
34 | + project.should_receive(:branch_names).at_least(:once).and_return([stable, master]) | |
35 | 35 | project.discover_default_branch.should == 'stable' |
36 | 36 | end |
37 | 37 | |
38 | 38 | it "returns a non-master branch when only one exists" do |
39 | - project.should_receive(:heads).and_return([stable]) | |
39 | + project.should_receive(:branch_names).at_least(:once).and_return([stable]) | |
40 | 40 | project.discover_default_branch.should == 'stable' |
41 | 41 | end |
42 | 42 | |
43 | 43 | it "returns nil when no branch exists" do |
44 | - project.should_receive(:heads).and_return([]) | |
44 | + project.should_receive(:branch_names).at_least(:once).and_return([]) | |
45 | 45 | project.discover_default_branch.should be_nil |
46 | 46 | end |
47 | 47 | end | ... | ... |
spec/routing/project_routing_spec.rb
... | ... | @@ -192,34 +192,17 @@ describe ProtectedBranchesController, "routing" do |
192 | 192 | end |
193 | 193 | |
194 | 194 | # switch_project_refs GET /:project_id/switch(.:format) refs#switch |
195 | -# tree_project_ref GET /:project_id/:id/tree(.:format) refs#tree | |
196 | 195 | # logs_tree_project_ref GET /:project_id/:id/logs_tree(.:format) refs#logs_tree |
197 | -# blob_project_ref GET /:project_id/:id/blob(.:format) refs#blob | |
198 | -# tree_file_project_ref GET /:project_id/:id/tree/:path(.:format) refs#tree | |
199 | 196 | # logs_file_project_ref GET /:project_id/:id/logs_tree/:path(.:format) refs#logs_tree |
200 | -# blame_file_project_ref GET /:project_id/:id/blame/:path(.:format) refs#blame | |
201 | 197 | describe RefsController, "routing" do |
202 | 198 | it "to #switch" do |
203 | 199 | get("/gitlabhq/switch").should route_to('refs#switch', project_id: 'gitlabhq') |
204 | 200 | end |
205 | 201 | |
206 | - it "to #tree" do | |
207 | - get("/gitlabhq/stable/tree").should route_to('refs#tree', project_id: 'gitlabhq', id: 'stable') | |
208 | - get("/gitlabhq/stable/tree/foo/bar/baz").should route_to('refs#tree', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz') | |
209 | - end | |
210 | - | |
211 | 202 | it "to #logs_tree" do |
212 | 203 | get("/gitlabhq/stable/logs_tree").should route_to('refs#logs_tree', project_id: 'gitlabhq', id: 'stable') |
213 | 204 | get("/gitlabhq/stable/logs_tree/foo/bar/baz").should route_to('refs#logs_tree', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz') |
214 | 205 | end |
215 | - | |
216 | - it "to #blob" do | |
217 | - get("/gitlabhq/stable/blob").should route_to('refs#blob', project_id: 'gitlabhq', id: 'stable') | |
218 | - end | |
219 | - | |
220 | - it "to #blame" do | |
221 | - get("/gitlabhq/stable/blame/foo/bar/baz").should route_to('refs#blame', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz') | |
222 | - end | |
223 | 206 | end |
224 | 207 | |
225 | 208 | # diffs_project_merge_request GET /:project_id/merge_requests/:id/diffs(.:format) merge_requests#diffs |
... | ... | @@ -298,25 +281,22 @@ describe HooksController, "routing" do |
298 | 281 | end |
299 | 282 | end |
300 | 283 | |
301 | -# compare_project_commits GET /:project_id/commits/compare(.:format) commits#compare | |
284 | +# project_commit GET /:project_id/commit/:id(.:format) commit#show {:id=>/[[:alnum:]]{6,40}/, :project_id=>/[^\/]+/} | |
285 | +describe CommitController, "routing" do | |
286 | + it "to #show" do | |
287 | + get("/gitlabhq/commit/4246fb").should route_to('commit#show', project_id: 'gitlabhq', id: '4246fb') | |
288 | + get("/gitlabhq/commit/4246fb.patch").should route_to('commit#show', project_id: 'gitlabhq', id: '4246fb', format: 'patch') | |
289 | + get("/gitlabhq/commit/4246fbd13872934f72a8fd0d6fb1317b47b59cb5").should route_to('commit#show', project_id: 'gitlabhq', id: '4246fbd13872934f72a8fd0d6fb1317b47b59cb5') | |
290 | + end | |
291 | +end | |
292 | + | |
302 | 293 | # patch_project_commit GET /:project_id/commits/:id/patch(.:format) commits#patch |
303 | 294 | # project_commits GET /:project_id/commits(.:format) commits#index |
304 | 295 | # POST /:project_id/commits(.:format) commits#create |
305 | -# new_project_commit GET /:project_id/commits/new(.:format) commits#new | |
306 | -# edit_project_commit GET /:project_id/commits/:id/edit(.:format) commits#edit | |
307 | 296 | # project_commit GET /:project_id/commits/:id(.:format) commits#show |
308 | -# PUT /:project_id/commits/:id(.:format) commits#update | |
309 | -# DELETE /:project_id/commits/:id(.:format) commits#destroy | |
310 | 297 | describe CommitsController, "routing" do |
311 | - it "to #compare" do | |
312 | - get("/gitlabhq/commits/compare").should route_to('commits#compare', project_id: 'gitlabhq') | |
313 | - end | |
314 | - | |
315 | - it "to #patch" do | |
316 | - get("/gitlabhq/commits/1/patch").should route_to('commits#patch', project_id: 'gitlabhq', id: '1') | |
317 | - end | |
318 | - | |
319 | 298 | it_behaves_like "RESTful project resources" do |
299 | + let(:actions) { [:show] } | |
320 | 300 | let(:controller) { 'commits' } |
321 | 301 | end |
322 | 302 | end |
... | ... | @@ -396,3 +376,42 @@ describe NotesController, "routing" do |
396 | 376 | let(:controller) { 'notes' } |
397 | 377 | end |
398 | 378 | end |
379 | + | |
380 | +# project_blame GET /:project_id/blame/:id(.:format) blame#show {:id=>/.+/, :project_id=>/[^\/]+/} | |
381 | +describe BlameController, "routing" do | |
382 | + it "to #show" do | |
383 | + get("/gitlabhq/blame/master/app/models/project.rb").should route_to('blame#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb') | |
384 | + end | |
385 | +end | |
386 | + | |
387 | +# project_blob GET /:project_id/blob/:id(.:format) blob#show {:id=>/.+/, :project_id=>/[^\/]+/} | |
388 | +describe BlobController, "routing" do | |
389 | + it "to #show" do | |
390 | + get("/gitlabhq/blob/master/app/models/project.rb").should route_to('blob#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb') | |
391 | + end | |
392 | +end | |
393 | + | |
394 | +# project_tree GET /:project_id/tree/:id(.:format) tree#show {:id=>/.+/, :project_id=>/[^\/]+/} | |
395 | +describe TreeController, "routing" do | |
396 | + it "to #show" do | |
397 | + get("/gitlabhq/tree/master/app/models/project.rb").should route_to('tree#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb') | |
398 | + end | |
399 | +end | |
400 | + | |
401 | +# project_compare_index GET /:project_id/compare(.:format) compare#index {:id=>/[^\/]+/, :project_id=>/[^\/]+/} | |
402 | +# POST /:project_id/compare(.:format) compare#create {:id=>/[^\/]+/, :project_id=>/[^\/]+/} | |
403 | +# project_compare /:project_id/compare/:from...:to(.:format) compare#show {:from=>/.+/, :to=>/.+/, :id=>/[^\/]+/, :project_id=>/[^\/]+/} | |
404 | +describe CompareController, "routing" do | |
405 | + it "to #index" do | |
406 | + get("/gitlabhq/compare").should route_to('compare#index', project_id: 'gitlabhq') | |
407 | + end | |
408 | + | |
409 | + it "to #compare" do | |
410 | + post("/gitlabhq/compare").should route_to('compare#create', project_id: 'gitlabhq') | |
411 | + end | |
412 | + | |
413 | + it "to #show" do | |
414 | + get("/gitlabhq/compare/master...stable").should route_to('compare#show', project_id: 'gitlabhq', from: 'master', to: 'stable') | |
415 | + get("/gitlabhq/compare/issue/1234...stable").should route_to('compare#show', project_id: 'gitlabhq', from: 'issue/1234', to: 'stable') | |
416 | + end | |
417 | +end | ... | ... |
spec/spec_helper.rb
... | ... | @@ -28,6 +28,7 @@ RSpec.configure do |config| |
28 | 28 | config.include LoginHelpers, type: :request |
29 | 29 | config.include GitoliteStub |
30 | 30 | config.include FactoryGirl::Syntax::Methods |
31 | + config.include Devise::TestHelpers, type: :controller | |
31 | 32 | |
32 | 33 | # If you're not using ActiveRecord, or you'd prefer not to run each of your |
33 | 34 | # examples within a transaction, remove the following line or assign false | ... | ... |
spec/support/stubbed_repository.rb
... | ... | @@ -5,11 +5,11 @@ module StubbedRepository |
5 | 5 | if new_record? || path == 'newproject' |
6 | 6 | # There are a couple Project specs and features that expect the Project's |
7 | 7 | # path to be in the returned path, so let's patronize them. |
8 | - File.join(Rails.root, 'tmp', 'repositories', path) | |
8 | + Rails.root.join('tmp', 'repositories', path) | |
9 | 9 | else |
10 | 10 | # For everything else, just give it the path to one of our real seeded |
11 | 11 | # repos. |
12 | - File.join(Rails.root, 'tmp', 'repositories', 'gitlabhq') | |
12 | + Rails.root.join('tmp', 'repositories', 'gitlabhq') | |
13 | 13 | end |
14 | 14 | end |
15 | 15 | ... | ... |