Commit 0a94640e328ab30dcf90e65ba79242bc1aa77a57

Authored by Dmitriy Zaporozhets
2 parents e6c0673e de6fa5dd

Merge branch 'refactoring/backend'

Showing 127 changed files with 950 additions and 1127 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 127 files displayed.

.gitignore
... ... @@ -24,3 +24,4 @@ db/data.yml
24 24 .DS_Store
25 25 .chef
26 26 vendor/bundle/*
  27 +rails_best_practices_output.html
... ...
.travis.yml
... ... @@ -8,7 +8,7 @@ branches:
8 8 only:
9 9 - 'master'
10 10 rvm:
11   - - 1.9.3
  11 + - 1.9.2
12 12 services:
13 13 - mysql
14 14 - postgresql
... ...
Gemfile
... ... @@ -123,6 +123,8 @@ group :development do
123 123 gem 'better_errors'
124 124 gem 'binding_of_caller'
125 125  
  126 + gem 'rails_best_practices'
  127 +
126 128 # Docs generator
127 129 gem "sdoc"
128 130 end
... ...
Gemfile.lock
... ... @@ -132,6 +132,8 @@ GEM
132 132 chosen-rails (0.9.8)
133 133 railties (~> 3.0)
134 134 thor (~> 0.14)
  135 + code_analyzer (0.3.1)
  136 + sexp_processor
135 137 coderay (1.0.8)
136 138 coffee-rails (3.2.2)
137 139 coffee-script (>= 2.2.0)
... ... @@ -302,6 +304,7 @@ GEM
302 304 pg (0.14.1)
303 305 polyglot (0.3.3)
304 306 posix-spawn (0.3.6)
  307 + progressbar (0.12.0)
305 308 pry (0.9.10)
306 309 coderay (~> 1.0.5)
307 310 method_source (~> 0.8)
... ... @@ -335,6 +338,14 @@ GEM
335 338 rails-dev-tweaks (0.6.1)
336 339 actionpack (~> 3.1)
337 340 railties (~> 3.1)
  341 + rails_best_practices (1.13.2)
  342 + activesupport
  343 + awesome_print
  344 + code_analyzer
  345 + colored
  346 + erubis
  347 + i18n
  348 + progressbar
338 349 railties (3.2.9)
339 350 actionpack (= 3.2.9)
340 351 activesupport (= 3.2.9)
... ... @@ -393,6 +404,7 @@ GEM
393 404 multi_json (~> 1.0)
394 405 rubyzip
395 406 settingslogic (2.0.8)
  407 + sexp_processor (4.1.3)
396 408 shoulda-matchers (1.3.0)
397 409 activesupport (>= 3.0.0)
398 410 simplecov (0.7.1)
... ... @@ -512,6 +524,7 @@ DEPENDENCIES
512 524 rack-mini-profiler
513 525 rails (= 3.2.9)
514 526 rails-dev-tweaks
  527 + rails_best_practices
515 528 raphael-rails (= 1.5.2)
516 529 rb-fsevent
517 530 rb-inotify
... ...
app/assets/stylesheets/gitlab_bootstrap/blocks.scss
1 1 /**
2 2 * ===================================
3   - * Contain 3 main UI block elements:
4   - * .main_box - for show pages
5   - * .ui-box - for simple block & widgets
  3 + * Contain UI block elements:
  4 + * .ui-box - for any block & widgets
6 5 * ===================================
7 6 */
8 7  
9 8 /**
10   - * UI box element
11   - * contains top, middle, bottom blocks
  9 + * UI Block
12 10 *
13 11 */
14   -.main_box {
15   - @extend .borders;
16   - @extend .prepend-top-20;
17   - @extend .append-bottom-20;
18   - border-width: 1px;
  12 +.ui-box {
  13 + background: #F9F9F9;
  14 + margin-bottom: 25px;
  15 + border: 1px solid #CCC;
19 16 @include solid-shade;
20 17  
  18 + &.ui-box-show {
  19 + margin:20px 0;
  20 + background: #FFF;
  21 + }
21 22  
22 23 img { max-width: 100%; }
23 24  
... ... @@ -27,9 +28,9 @@
27 28 }
28 29 }
29 30  
30   - .top_box_content,
31   - .middle_box_content,
32   - .bottom_box_content {
  31 + .ui-box-head,
  32 + .ui-box-body,
  33 + .ui-box-bottom {
33 34 padding: 15px;
34 35 word-wrap: break-word;
35 36  
... ... @@ -39,19 +40,25 @@
39 40 border: none;
40 41 padding: 0;
41 42 }
  43 +
  44 + .clearfix {
  45 + margin: 0;
  46 + }
42 47 }
43 48  
44   - .top_box_content {
  49 + .ui-box-head {
45 50 .box-title {
46 51 color: $style_color;
47 52 font-size: 18px;
48 53 font-weight: normal;
49 54 line-height: 28px;
50 55 }
  56 + h3 {
  57 + margin: 0;
  58 + }
51 59 }
52 60  
53   - .middle_box_content {
54   - @include border-radius(0);
  61 + .ui-box-body {
55 62 border: none;
56 63 font-size: 12px;
57 64 background-color: #f5f5f5;
... ... @@ -59,24 +66,9 @@
59 66 border-top: 1px solid #eee;
60 67 }
61 68  
62   - .bottom_box_content {
  69 + .ui-box-bottom {
63 70 border-top: 1px solid #eee;
64 71 }
65   -}
66   -
67   -/**
68   - * Big UI Block for show page content
69   - *
70   - */
71   -.ui-box {
72   - background: #F9F9F9;
73   - margin-bottom: 25px;
74   -
75   - border: 1px solid #eaeaea;
76   - @include border-radius(4px);
77   -
78   - border-color: #CCC;
79   - @include solid-shade;
80 72  
81 73 &.white {
82 74 background: #fff;
... ... @@ -86,47 +78,47 @@
86 78 margin: 0;
87 79 }
88 80  
89   - h5, .title {
90   - padding: 0 10px;
91   - @include border-radius(4px 4px 0 0);
  81 + .title {
92 82 @include bg-gray-gradient;
93   - border-top: 1px solid #eaeaea;
94   - border-bottom: 1px solid #bbb;
  83 + border-bottom: 1px solid #CCC;
  84 + color: #456;
  85 + font-size: 16px;
  86 + text-shadow: 0 1px 1px #fff;
  87 + padding: 0px 10px;
  88 + line-height: 36px;
  89 + font-size: 14px;
  90 + font-weight: normal;
95 91  
96 92 > a {
97 93 text-shadow: 0 1px 1px #fff;
98 94 }
99 95  
100   - &.small {
101   - line-height: 28px;
102   - font-size: 14px;
103   - line-height: 28px;
104   - text-shadow: 0 1px 1px white;
105   - }
106   -
107 96 form {
108   - padding: 9px 0;
109   - margin: 0px;
  97 + margin-bottom: 0;
  98 + margin-top: 3px;
110 99 }
111 100  
112 101 .nav-pills {
113   - li {
114   - padding: 3px 0;
115   - &.active a { background-color: $style_color; }
116   - a {
117   - @include border-radius(7px);
  102 + > li {
  103 + > a {
  104 + padding: 13px;
  105 + margin: 0;
  106 + font-size: 13px;
  107 + }
  108 + &.active {
  109 + > a {
  110 + background: #D5D5D5;
  111 + color: $style_color;
  112 + @include border-radius(0);
  113 + border-radius: 0;
  114 + border-left: 1px solid #CCC;
  115 + border-right: 1px solid #CCC;
  116 + }
118 117 }
119 118 }
120 119 }
121 120 }
122 121  
123   - .bottom {
124   - @include bg-gray-gradient;
125   - @include border-radius(0 0 4px 4px);
126   - border-bottom: none;
127   - border-top: 1px solid #bbb;
128   - }
129   -
130 122 &.padded {
131 123 h5, .title {
132 124 margin: -20px;
... ... @@ -143,6 +135,7 @@
143 135 color: #777;
144 136 }
145 137 }
  138 +
146 139 .row_title {
147 140 font-weight: bold;
148 141 color: #444;
... ... @@ -151,8 +144,4 @@
151 144 text-decoration: underline;
152 145 }
153 146 }
154   -
155   - .ui-box-body {
156   - padding: 10px;
157   - }
158 147 }
... ...
app/assets/stylesheets/gitlab_bootstrap/lists.scss
... ... @@ -23,14 +23,12 @@
23 23 border-bottom: 1px solid #ADF;
24 24 }
25 25  
26   - &:first-child {
27   - @include border-radius(4px 4px 0 0);
28   - border-top: none;
29   - }
30   -
31 26 &:last-child {
32   - @include border-radius(0 0 4px 4px);
33   - border: none;
  27 + border-bottom: none;
  28 +
  29 + &.bottom {
  30 + background: #f5f5f5;
  31 + }
34 32 }
35 33  
36 34 .author { color: #999; }
... ...
app/assets/stylesheets/gitlab_bootstrap/tables.scss
... ... @@ -25,7 +25,7 @@ table {
25 25 }
26 26  
27 27 th, td {
28   - padding: 8px;
  28 + padding: 10px;
29 29 line-height: 18px;
30 30 text-align: left;
31 31 }
... ...
app/assets/stylesheets/sections/commits.scss
1   -.commit-box {
2   - @extend .main_box;
3   -
4   - .commit-head {
5   - @extend .top_box_content;
6   -
7   - .commit-title {
8   - line-height: 26px;
9   - margin: 0;
10   - }
11   -
12   - .commit-description {
13   - font-size: 14px;
14   - border: none;
15   - background-color: white;
16   - padding-top: 10px;
17   - }
18   -
19   - .browse-button {
20   - @extend .btn;
21   - @extend .btn-small;
22   - float: right;
23   - }
24   - }
25   -
26   - .commit-info {
27   - @extend .middle_box_content;
28   - @extend .clearfix;
29   -
30   - .sha-block {
31   - text-align: right;
32   - &:first-child {
33   - padding-bottom: 6px;
34   - }
35   -
36   - a {
37   - border-bottom: 1px solid #aaa;
38   - margin-left: 9px;
39   - }
40   - }
41   -
42   - &.merge-commit .sha-block {
43   - clear: right;
44   - }
45   -
46   - .committer {
47   - padding-left: 32px;
48   - }
49   -
50   - .author a,
51   - .committer a {
52   - font-size: 14px;
53   - line-height: 22px;
54   - text-shadow: 0 1px 1px #fff;
55   - color: #777;
56   - &:hover {
57   - color: #999;
58   - }
59   - }
60   -
61   - .avatar {
62   - margin-right: 10px;
63   - }
64   - }
65   -}
66   -
67 1 /**
68 2 *
69 3 * COMMIT SHOw
70 4 *
71 5 */
  6 +.commit-committer-link,
  7 +.commit-author-link {
  8 + font-size: 13px;
  9 + color: #555;
  10 + &:hover {
  11 + color: #999;
  12 + }
  13 +}
  14 +
72 15 .diff_file {
73 16 border: 1px solid #CCC;
74 17 margin-bottom: 1em;
... ... @@ -255,13 +198,6 @@
255 198 min-width: 65px;
256 199 font-family: $monospace;
257 200 }
258   -
259   - .commit-author-name {
260   - color: #777;
261   - &:hover {
262   - color: #999;
263   - }
264   - }
265 201 }
266 202  
267 203 .diff_file_header a,
... ...
app/assets/stylesheets/sections/issues.scss
1   -.issue_form_box {
2   - @extend .main_box;
3   - .issue_title {
4   - @extend .top_box_content;
5   - .clearfix {
6   - margin-bottom: 0px;
7   - input {
8   - @extend .span8;
9   - }
10   - }
11   - }
12   - .issue_middle_block {
13   - @extend .middle_box_content;
14   - height: 30px;
15   - .issue_assignee {
16   - @extend .span6;
17   - float: left;
18   - }
19   - .issue_milestone {
20   - @extend .span4;
21   - float: left;
22   - }
23   - }
24   - .issue_description {
25   - @extend .bottom_box_content;
26   - }
27   -}
28   -
29 1 .issues_table {
30 2 .issue {
31 3 padding: 7px 10px;
... ... @@ -89,31 +61,25 @@ input.check_all_issues {
89 61  
90 62 #issues-table-holder {
91 63 .issues_filters {
92   - form {
93   - padding: 0;
94   - margin: 0;
95   - margin-top:7px
96   - }
97 64 }
98 65  
99 66 .issues_bulk_update {
100 67 margin: 0;
101 68 form {
102   - padding: 0;
103   - margin: 0;
104   - margin-top:7px
  69 + float:left;
105 70 }
106 71 .update_selected_issues {
107 72 position: relative;
108   - top:-2px;
  73 + top:5px;
109 74 margin-left: 4px;
110 75 float: left;
111 76 }
112 77  
113 78 .update_issues_text {
114 79 padding: 3px;
115   - line-height: 18px;
  80 + line-height: 28px;
116 81 float: left;
  82 + color: #479;
117 83 }
118 84 }
119 85 }
... ...
app/assets/stylesheets/sections/merge_requests.scss
1   -/**
2   - * MR form
3   - *
4   - */
5   -
6   -.mr_branch_box {
7   - @extend .ui-box;
8   - margin-bottom: 20px;
9   -
10   - .body {
11   - background: #f1f1f1;
12   - }
13   -
14   -}
15 1  
16 2 /**
17 3 * MR -> show: Automerge widget
... ... @@ -121,19 +107,3 @@ li.merge_request {
121 107 .mr_direction_tip {
122 108 margin-top:40px
123 109 }
124   -
125   -.merge_requests_form_box {
126   - @extend .main_box;
127   - .merge_requests_middle_box {
128   - @extend .middle_box_content;
129   - height: 30px;
130   - .merge_requests_assignee {
131   - @extend .span6;
132   - float: left;
133   - }
134   - .merge_requests_milestone {
135   - @extend .span4;
136   - float: left;
137   - }
138   - }
139   -}
... ...
app/assets/stylesheets/sections/projects.scss
... ... @@ -8,16 +8,12 @@
8 8  
9 9 .groups_box,
10 10 .projects_box {
11   - > h5 {
12   - color: $style_color;
13   - font-size: 16px;
14   - text-shadow: 0 1px 1px #fff;
15   - padding: 2px 10px;
16   - line-height: 32px;
17   - font-size: 14px;
  11 + > .title {
  12 + padding: 2px 15px;
18 13 }
19 14 .nav-projects-tabs li { padding: 0; }
20 15 .well-list {
  16 + li { padding: 15px; }
21 17 .arrow {
22 18 float: right;
23 19 padding: 10px;
... ... @@ -109,7 +105,7 @@ ul.nav.nav-projects-tabs {
109 105  
110 106 li {
111 107 a {
112   - padding: 4px 20px;
  108 + padding: 6px 25px;
113 109 margin-top: 2px;
114 110 border-color: #DDD;
115 111 background-color: #EEE;
... ...
app/contexts/commit_load_context.rb
... ... @@ -9,7 +9,7 @@ class CommitLoadContext < BaseContext
9 9 status: :ok
10 10 }
11 11  
12   - commit = project.commit(params[:id])
  12 + commit = project.repository.commit(params[:id])
13 13  
14 14 if commit
15 15 commit = CommitDecorator.decorate(commit)
... ...
app/contexts/notes/load_context.rb
... ... @@ -9,7 +9,7 @@ module Notes
9 9  
10 10 @notes = case target_type
11 11 when "commit"
12   - project.commit_notes(project.commit(target_id)).fresh.limit(20)
  12 + project.commit_notes(project.repository.commit(target_id)).fresh.limit(20)
13 13 when "issue"
14 14 project.issues.find(target_id).notes.inc_author.fresh.limit(20)
15 15 when "merge_request"
... ... @@ -18,7 +18,7 @@ module Notes
18 18 project.snippets.find(target_id).notes.fresh
19 19 when "wall"
20 20 # this is the only case, where the order is DESC
21   - project.common_notes.order("created_at DESC, id DESC").limit(50)
  21 + project.notes.common.inc_author_project.order("created_at DESC, id DESC").limit(50)
22 22 end
23 23  
24 24 @notes = if after_id
... ...
app/contexts/test_hook_context.rb
1 1 class TestHookContext < BaseContext
2 2 def execute
3 3 hook = project.hooks.find(params[:id])
4   - commits = project.commits(project.default_branch, nil, 3)
  4 + commits = project.repository.commits(project.default_branch, nil, 3)
5 5 data = project.post_receive_data(commits.last.id, commits.first.id, "refs/heads/#{project.default_branch}", current_user)
6 6 hook.execute(data)
7 7 end
... ...
app/controllers/admin/projects_controller.rb
... ... @@ -10,6 +10,7 @@ class Admin::ProjectsController &lt; AdminController
10 10 end
11 11  
12 12 def show
  13 + @repository = @project.repository
13 14 @users = User.active
14 15 @users = @users.not_in_project(@project) if @project.users.present?
15 16 @users = @users.all
... ... @@ -19,7 +20,7 @@ class Admin::ProjectsController &lt; AdminController
19 20 end
20 21  
21 22 def team_update
22   - @project.add_users_ids_to_team(params[:user_ids], params[:project_access])
  23 + @project.team.add_users_ids(params[:user_ids], params[:project_access])
23 24  
24 25 redirect_to [:admin, @project], notice: 'Project was successfully updated.'
25 26 end
... ... @@ -36,7 +37,7 @@ class Admin::ProjectsController &lt; AdminController
36 37  
37 38 def destroy
38 39 # Delete team first in order to prevent multiple gitolite calls
39   - @project.truncate_team
  40 + @project.team.truncate
40 41  
41 42 @project.destroy
42 43  
... ...
app/controllers/admin/users_controller.rb
... ... @@ -19,9 +19,9 @@ class Admin::UsersController &lt; AdminController
19 19 def team_update
20 20 @admin_user = User.find(params[:id])
21 21  
22   - UsersProject.user_bulk_import(
23   - @admin_user,
  22 + UsersProject.add_users_into_projects(
24 23 params[:project_ids],
  24 + [@admin_user.id],
25 25 params[:project_access]
26 26 )
27 27  
... ...
app/controllers/application_controller.rb
... ... @@ -76,6 +76,12 @@ class ApplicationController &lt; ActionController::Base
76 76 end
77 77 end
78 78  
  79 + def repository
  80 + @repository ||= project.repository
  81 + rescue Grit::NoSuchPathError
  82 + nil
  83 + end
  84 +
79 85 def add_abilities
80 86 abilities << Ability
81 87 end
... ...
app/controllers/commits_controller.rb
... ... @@ -9,10 +9,10 @@ class CommitsController &lt; ProjectResourceController
9 9 before_filter :require_non_empty_project
10 10  
11 11 def show
12   - @repo = @project.repo
  12 + @repo = @project.repository
13 13 @limit, @offset = (params[:limit] || 40), (params[:offset] || 0)
14 14  
15   - @commits = @project.commits(@ref, @path, @limit, @offset)
  15 + @commits = @repo.commits(@ref, @path, @limit, @offset)
16 16 @commits = CommitDecorator.decorate(@commits)
17 17  
18 18 respond_to do |format|
... ...
app/controllers/merge_requests_controller.rb
... ... @@ -83,12 +83,12 @@ class MergeRequestsController &lt; ProjectResourceController
83 83 end
84 84  
85 85 def branch_from
86   - @commit = project.commit(params[:ref])
  86 + @commit = @repository.commit(params[:ref])
87 87 @commit = CommitDecorator.decorate(@commit)
88 88 end
89 89  
90 90 def branch_to
91   - @commit = project.commit(params[:ref])
  91 + @commit = @repository.commit(params[:ref])
92 92 @commit = CommitDecorator.decorate(@commit)
93 93 end
94 94  
... ...
app/controllers/project_resource_controller.rb
1 1 class ProjectResourceController < ApplicationController
2 2 before_filter :project
  3 + before_filter :repository
3 4 end
... ...
app/controllers/projects_controller.rb
... ... @@ -2,6 +2,7 @@ require Rails.root.join(&#39;lib&#39;, &#39;gitlab&#39;, &#39;graph&#39;, &#39;json_builder&#39;)
2 2  
3 3 class ProjectsController < ProjectResourceController
4 4 skip_before_filter :project, only: [:new, :create]
  5 + skip_before_filter :repository, only: [:new, :create]
5 6  
6 7 # Authorize
7 8 before_filter :authorize_read_project!, except: [:index, :new, :create]
... ... @@ -58,7 +59,7 @@ class ProjectsController &lt; ProjectResourceController
58 59  
59 60 respond_to do |format|
60 61 format.html do
61   - unless @project.empty_repo?
  62 + if @project.repository && !@project.repository.empty?
62 63 @last_push = current_user.recent_push(@project.id)
63 64 render :show
64 65 else
... ...
app/controllers/refs_controller.rb
... ... @@ -31,7 +31,7 @@ class RefsController &lt; ProjectResourceController
31 31 contents = @tree.contents
32 32 @logs = contents.map do |content|
33 33 file = params[:path] ? File.join(params[:path], content.name) : content.name
34   - last_commit = @project.commits(@commit.id, file, 1).last
  34 + last_commit = @repo.commits(@commit.id, file, 1).last
35 35 last_commit = CommitDecorator.decorate(last_commit)
36 36 {
37 37 file_name: content.name,
... ... @@ -45,10 +45,10 @@ class RefsController &lt; ProjectResourceController
45 45 def define_tree_vars
46 46 params[:path] = nil if params[:path].blank?
47 47  
48   - @repo = project.repo
49   - @commit = project.commit(@ref)
  48 + @repo = project.repository
  49 + @commit = @repo.commit(@ref)
50 50 @commit = CommitDecorator.decorate(@commit)
51   - @tree = Tree.new(@commit.tree, project, @ref, params[:path])
  51 + @tree = Tree.new(@commit.tree, @ref, params[:path])
52 52 @tree = TreeDecorator.new(@tree)
53 53 @hex_path = Digest::SHA1.hexdigest(params[:path] || "")
54 54  
... ...
app/controllers/repositories_controller.rb
... ... @@ -5,19 +5,19 @@ class RepositoriesController &lt; ProjectResourceController
5 5 before_filter :require_non_empty_project
6 6  
7 7 def show
8   - @activities = @project.commits_with_refs(20)
  8 + @activities = @repository.commits_with_refs(20)
9 9 end
10 10  
11 11 def branches
12   - @branches = @project.branches
  12 + @branches = @repository.branches
13 13 end
14 14  
15 15 def tags
16   - @tags = @project.tags
  16 + @tags = @repository.tags
17 17 end
18 18  
19 19 def stats
20   - @stats = Gitlab::GitStats.new(@project.repo, @project.root_ref)
  20 + @stats = Gitlab::GitStats.new(@repository.raw, @repository.root_ref)
21 21 @graph = @stats.graph
22 22 end
23 23  
... ... @@ -27,7 +27,7 @@ class RepositoriesController &lt; ProjectResourceController
27 27 end
28 28  
29 29  
30   - file_path = @project.archive_repo(params[:ref])
  30 + file_path = @repository.archive_repo(params[:ref])
31 31  
32 32 if file_path
33 33 # Send file to user
... ...
app/controllers/services_controller.rb
... ... @@ -26,7 +26,7 @@ class ServicesController &lt; ProjectResourceController
26 26 end
27 27  
28 28 def test
29   - commits = project.commits(project.default_branch, nil, 3)
  29 + commits = project.repository.commits(project.default_branch, nil, 3)
30 30 data = project.post_receive_data(commits.last.id, commits.first.id, "refs/heads/#{project.default_branch}", current_user)
31 31  
32 32 @service = project.gitlab_ci_service
... ...
app/controllers/team_members_controller.rb
... ... @@ -16,10 +16,9 @@ class TeamMembersController &lt; ProjectResourceController
16 16 end
17 17  
18 18 def create
19   - @project.add_users_ids_to_team(
20   - params[:user_ids],
21   - params[:project_access]
22   - )
  19 + users = User.where(id: params[:user_ids])
  20 +
  21 + @project.team << [users, params[:project_access]]
23 22  
24 23 if params[:redirect_to]
25 24 redirect_to params[:redirect_to]
... ... @@ -50,7 +49,7 @@ class TeamMembersController &lt; ProjectResourceController
50 49  
51 50 def apply_import
52 51 giver = Project.find(params[:source_project_id])
53   - status = UsersProject.import_team(giver, project)
  52 + status = @project.team.import(giver)
54 53 notice = status ? "Succesfully imported" : "Import failed"
55 54  
56 55 redirect_to project_team_members_path(project), notice: notice
... ...
app/controllers/tree_controller.rb
... ... @@ -22,7 +22,7 @@ class TreeController &lt; ProjectResourceController
22 22 end
23 23  
24 24 def edit
25   - @last_commit = @project.last_commit_for(@ref, @path).sha
  25 + @last_commit = @project.repository.last_commit_for(@ref, @path).sha
26 26 end
27 27  
28 28 def update
... ...
app/decorators/tree_decorator.rb
... ... @@ -6,16 +6,14 @@ class TreeDecorator &lt; ApplicationDecorator
6 6 part_path = ""
7 7 parts = path.split("\/")
8 8  
9   - #parts = parts[0...-1] if is_blob?
10   -
11   - yield(h.link_to("..", "#")) if parts.count > max_links
  9 + yield('..', nil) if parts.count > max_links
12 10  
13 11 parts.each do |part|
14 12 part_path = File.join(part_path, part) unless part_path.empty?
15 13 part_path = part if part_path.empty?
16 14  
17 15 next unless parts.last(2).include?(part) if parts.count > max_links
18   - yield(h.link_to(h.truncate(part, length: 40), h.project_tree_path(project, h.tree_join(ref, part_path))))
  16 + yield(part, h.tree_join(ref, part_path))
19 17 end
20 18 end
21 19 end
... ... @@ -26,7 +24,7 @@ class TreeDecorator &lt; ApplicationDecorator
26 24  
27 25 def up_dir_path
28 26 file = File.join(path, "..")
29   - h.project_tree_path(project, h.tree_join(ref, file))
  27 + h.tree_join(ref, file)
30 28 end
31 29  
32 30 def readme
... ...
app/helpers/application_helper.rb
... ... @@ -53,7 +53,7 @@ module ApplicationHelper
53 53  
54 54 def last_commit(project)
55 55 if project.repo_exists?
56   - time_ago_in_words(project.commit.committed_date) + " ago"
  56 + time_ago_in_words(project.repository.commit.committed_date) + " ago"
57 57 else
58 58 "Never"
59 59 end
... ... @@ -62,9 +62,11 @@ module ApplicationHelper
62 62 end
63 63  
64 64 def grouped_options_refs(destination = :tree)
  65 + repository = @project.repository
  66 +
65 67 options = [
66   - ["Branch", @project.branch_names ],
67   - [ "Tag", @project.tag_names ]
  68 + ["Branch", repository.branch_names ],
  69 + [ "Tag", repository.tag_names ]
68 70 ]
69 71  
70 72 # If reference is commit id -
... ... @@ -100,15 +102,15 @@ module ApplicationHelper
100 102 ]
101 103  
102 104 project_nav = []
103   - if @project && !@project.new_record?
  105 + if @project && @project.repository && @project.repository.root_ref
104 106 project_nav = [
105 107 { label: "#{@project.name} Issues", url: project_issues_path(@project) },
106   - { label: "#{@project.name} Commits", url: project_commits_path(@project, @ref || @project.root_ref) },
  108 + { label: "#{@project.name} Commits", url: project_commits_path(@project, @ref || @project.repository.root_ref) },
107 109 { label: "#{@project.name} Merge Requests", url: project_merge_requests_path(@project) },
108 110 { label: "#{@project.name} Milestones", url: project_milestones_path(@project) },
109 111 { label: "#{@project.name} Snippets", url: project_snippets_path(@project) },
110 112 { label: "#{@project.name} Team", url: project_team_index_path(@project) },
111   - { label: "#{@project.name} Tree", url: project_tree_path(@project, @ref || @project.root_ref) },
  113 + { label: "#{@project.name} Tree", url: project_tree_path(@project, @ref || @project.repository.root_ref) },
112 114 { label: "#{@project.name} Wall", url: wall_project_path(@project) },
113 115 { label: "#{@project.name} Wiki", url: project_wikis_path(@project) },
114 116 ]
... ... @@ -140,6 +142,7 @@ module ApplicationHelper
140 142 event.last_push_to_non_root? &&
141 143 !event.rm_ref? &&
142 144 event.project &&
  145 + event.project.repository &&
143 146 event.project.merge_requests_enabled
144 147 end
145 148  
... ...
app/helpers/events_helper.rb
... ... @@ -20,20 +20,6 @@ module EventsHelper
20 20 [event.action_name, target].join(" ")
21 21 end
22 22  
23   - def event_image event
24   - event_image_path = if event.push?
25   - "event_push.png"
26   - elsif event.merged?
27   - "event_mr_merged.png"
28   - end
29   -
30   - return nil unless event_image_path
31   -
32   - content_tag :div, class: 'event_icon' do
33   - image_tag event_image_path
34   - end
35   - end
36   -
37 23 def event_filter_link key, tooltip
38 24 key = key.to_s
39 25  
... ...
app/helpers/merge_requests_helper.rb
... ... @@ -4,7 +4,7 @@ module MergeRequestsHelper
4 4 event.project,
5 5 merge_request: {
6 6 source_branch: event.branch_name,
7   - target_branch: event.project.root_ref,
  7 + target_branch: event.project.repository.root_ref,
8 8 title: event.branch_name.titleize
9 9 }
10 10 )
... ...
app/models/ability.rb
... ... @@ -15,17 +15,19 @@ class Ability
15 15 def project_abilities(user, project)
16 16 rules = []
17 17  
  18 + team = project.team
  19 +
18 20 # Rules based on role in project
19   - if project.master_access_for?(user)
  21 + if team.masters.include?(user)
20 22 rules << project_master_rules
21 23  
22   - elsif project.dev_access_for?(user)
  24 + elsif team.developers.include?(user)
23 25 rules << project_dev_rules
24 26  
25   - elsif project.report_access_for?(user)
  27 + elsif team.reporters.include?(user)
26 28 rules << project_report_rules
27 29  
28   - elsif project.guest_access_for?(user)
  30 + elsif team.guests.include?(user)
29 31 rules << project_guest_rules
30 32 end
31 33  
... ...
app/models/commit.rb
... ... @@ -11,7 +11,7 @@ class Commit
11 11 attr_accessor :commit, :head, :refs
12 12  
13 13 delegate :message, :authored_date, :committed_date, :parents, :sha,
14   - :date, :committer, :author, :diffs, :tree, :id,
  14 + :date, :committer, :author, :diffs, :tree, :id, :stats,
15 15 :to_patch, to: :commit
16 16  
17 17 class << self
... ... @@ -83,8 +83,8 @@ class Commit
83 83  
84 84 return result unless from && to
85 85  
86   - first = project.commit(to.try(:strip))
87   - last = project.commit(from.try(:strip))
  86 + first = project.repository.commit(to.try(:strip))
  87 + last = project.repository.commit(from.try(:strip))
88 88  
89 89 if first && last
90 90 result[:same] = (first.id == last.id)
... ... @@ -98,6 +98,8 @@ class Commit
98 98 end
99 99  
100 100 def initialize(raw_commit, head = nil)
  101 + raise "Nil as raw commit passed" unless raw_commit
  102 +
101 103 @commit = raw_commit
102 104 @head = head
103 105 end
... ... @@ -136,7 +138,11 @@ class Commit
136 138 end
137 139  
138 140 def prev_commit
139   - parents.try :first
  141 + @prev_commit ||= if parents.present?
  142 + Commit.new(parents.first)
  143 + else
  144 + nil
  145 + end
140 146 end
141 147  
142 148 def prev_commit_id
... ...
app/models/event.rb
... ... @@ -110,26 +110,6 @@ class Event &lt; ActiveRecord::Base
110 110 target_type == "MergeRequest"
111 111 end
112 112  
113   - def new_issue?
114   - target_type == "Issue" &&
115   - action == Created
116   - end
117   -
118   - def new_merge_request?
119   - target_type == "MergeRequest" &&
120   - action == Created
121   - end
122   -
123   - def changed_merge_request?
124   - target_type == "MergeRequest" &&
125   - [Closed, Reopened].include?(action)
126   - end
127   -
128   - def changed_issue?
129   - target_type == "Issue" &&
130   - [Closed, Reopened].include?(action)
131   - end
132   -
133 113 def joined?
134 114 action == Joined
135 115 end
... ... @@ -224,7 +204,7 @@ class Event &lt; ActiveRecord::Base
224 204  
225 205 # Max 20 commits from push DESC
226 206 def commits
227   - @commits ||= data[:commits].map { |commit| project.commit(commit[:id]) }.reverse
  207 + @commits ||= data[:commits].map { |commit| repository.commit(commit[:id]) }.reverse
228 208 end
229 209  
230 210 def commits_count
... ... @@ -245,14 +225,18 @@ class Event &lt; ActiveRecord::Base
245 225 end
246 226 end
247 227  
  228 + def repository
  229 + project.repository
  230 + end
  231 +
248 232 def parent_commit
249   - project.commit(commit_from)
  233 + repository.commit(commit_from)
250 234 rescue => ex
251 235 nil
252 236 end
253 237  
254 238 def last_commit
255   - project.commit(commit_to)
  239 + repository.commit(commit_to)
256 240 rescue => ex
257 241 nil
258 242 end
... ...
app/models/gitlab_ci_service.rb
... ... @@ -29,10 +29,6 @@ class GitlabCiService &lt; Service
29 29 hook.save
30 30 end
31 31  
32   - def commit_badge_path sha
33   - project_url + "/status?sha=#{sha}"
34   - end
35   -
36 32 def commit_status_path sha
37 33 project_url + "/builds/#{sha}/status.json?token=#{token}"
38 34 end
... ...
app/models/note.rb
... ... @@ -4,7 +4,6 @@
4 4 #
5 5 # id :integer not null, primary key
6 6 # note :text
7   -# noteable_id :string(255)
8 7 # noteable_type :string(255)
9 8 # author_id :integer
10 9 # created_at :datetime not null
... ... @@ -12,6 +11,8 @@
12 11 # project_id :integer
13 12 # attachment :string(255)
14 13 # line_code :string(255)
  14 +# commit_id :string(255)
  15 +# noteable_id :integer
15 16 #
16 17  
17 18 require 'carrierwave/orm/activerecord'
... ... @@ -42,7 +43,7 @@ class Note &lt; ActiveRecord::Base
42 43  
43 44 # Scopes
44 45 scope :for_commits, ->{ where(noteable_type: "Commit") }
45   - scope :common, ->{ where(noteable_id: nil, commit_id: nil) }
  46 + scope :common, ->{ where(noteable_type: ["", nil]) }
46 47 scope :today, ->{ where("created_at >= :date", date: Date.today) }
47 48 scope :last_week, ->{ where("created_at >= :date", date: (Date.today - 7.days)) }
48 49 scope :since, ->(day) { where("created_at >= :date", date: (day)) }
... ... @@ -70,7 +71,7 @@ class Note &lt; ActiveRecord::Base
70 71 # override to return commits, which are not active record
71 72 def noteable
72 73 if for_commit?
73   - project.commit(commit_id)
  74 + project.repository.commit(commit_id)
74 75 else
75 76 super
76 77 end
... ...
app/models/project.rb
... ... @@ -9,7 +9,7 @@
9 9 # created_at :datetime not null
10 10 # updated_at :datetime not null
11 11 # private_flag :boolean default(TRUE), not null
12   -# owner_id :integer
  12 +# creator_id :integer
13 13 # default_branch :string(255)
14 14 # issues_enabled :boolean default(TRUE), not null
15 15 # wall_enabled :boolean default(TRUE), not null
... ... @@ -75,7 +75,6 @@ class Project &lt; ActiveRecord::Base
75 75 validate :check_limit, :repo_name
76 76  
77 77 # Scopes
78   - scope :public_only, where(private_flag: false)
79 78 scope :without_user, ->(user) { where("id NOT IN (:ids)", ids: user.authorized_projects.map(&:id) ) }
80 79 scope :not_in_group, ->(group) { where("id NOT IN (:ids)", ids: group.project_ids ) }
81 80 scope :in_namespace, ->(namespace) { where(namespace_id: namespace.id) }
... ... @@ -162,6 +161,20 @@ class Project &lt; ActiveRecord::Base
162 161 end
163 162 end
164 163  
  164 + def team
  165 + @team ||= Team.new(self)
  166 + end
  167 +
  168 + def repository
  169 + if path
  170 + @repository ||= Repository.new(path_with_namespace, default_branch)
  171 + else
  172 + nil
  173 + end
  174 + rescue Grit::NoSuchPathError
  175 + nil
  176 + end
  177 +
165 178 def git_error?
166 179 error_code == :gitolite
167 180 end
... ... @@ -198,10 +211,6 @@ class Project &lt; ActiveRecord::Base
198 211 [Gitlab.config.gitlab.url, path_with_namespace].join("/")
199 212 end
200 213  
201   - def common_notes
202   - notes.where(noteable_type: ["", nil]).inc_author_project
203   - end
204   -
205 214 def build_commit_note(commit)
206 215 notes.new(commit_id: commit.id, noteable_type: "Commit")
207 216 end
... ... @@ -214,14 +223,6 @@ class Project &lt; ActiveRecord::Base
214 223 notes.where(commit_id: commit.id, noteable_type: "Commit").where("line_code IS NOT NULL")
215 224 end
216 225  
217   - def public?
218   - !private_flag
219   - end
220   -
221   - def private?
222   - private_flag
223   - end
224   -
225 226 def last_activity
226 227 last_event
227 228 end
... ... @@ -284,110 +285,6 @@ class Project &lt; ActiveRecord::Base
284 285 users_projects.find_by_user_id(user_id)
285 286 end
286 287  
287   - # Add user to project
288   - # with passed access role
289   - def add_user_to_team(user, access_role)
290   - add_user_id_to_team(user.id, access_role)
291   - end
292   -
293   - # Add multiple users to project
294   - # with same access role
295   - def add_users_to_team(users, access_role)
296   - add_users_ids_to_team(users.map(&:id), access_role)
297   - end
298   -
299   - # Add user to project
300   - # with passed access role by user id
301   - def add_user_id_to_team(user_id, access_role)
302   - users_projects.create(
303   - user_id: user_id,
304   - project_access: access_role
305   - )
306   - end
307   -
308   - # Add multiple users to project
309   - # with same access role by user ids
310   - def add_users_ids_to_team(users_ids, access_role)
311   - UsersProject.bulk_import(self, users_ids, access_role)
312   - end
313   -
314   - # Update multiple project users
315   - # to same access role by user ids
316   - def update_users_ids_to_role(users_ids, access_role)
317   - UsersProject.bulk_update(self, users_ids, access_role)
318   - end
319   -
320   - # Delete multiple users from project by user ids
321   - def delete_users_ids_from_team(users_ids)
322   - UsersProject.bulk_delete(self, users_ids)
323   - end
324   -
325   - # Remove all users from project team
326   - def truncate_team
327   - UsersProject.truncate_team(self)
328   - end
329   -
330   - # Compatible with all access rights
331   - # Should be rewrited for new access rights
332   - def add_access(user, *access)
333   - access = if access.include?(:admin)
334   - { project_access: UsersProject::MASTER }
335   - elsif access.include?(:write)
336   - { project_access: UsersProject::DEVELOPER }
337   - else
338   - { project_access: UsersProject::REPORTER }
339   - end
340   - opts = { user: user }
341   - opts.merge!(access)
342   - users_projects.create(opts)
343   - end
344   -
345   - def reset_access(user)
346   - users_projects.where(project_id: self.id, user_id: user.id).destroy if self.id
347   - end
348   -
349   - def repository_readers
350   - repository_members[UsersProject::REPORTER]
351   - end
352   -
353   - def repository_writers
354   - repository_members[UsersProject::DEVELOPER]
355   - end
356   -
357   - def repository_masters
358   - repository_members[UsersProject::MASTER]
359   - end
360   -
361   - def repository_members
362   - keys = Hash.new {|h,k| h[k] = [] }
363   - UsersProject.select("keys.identifier, project_access").
364   - joins(user: :keys).where(project_id: id).
365   - each {|row| keys[row.project_access] << [row.identifier] }
366   -
367   - keys[UsersProject::REPORTER] += deploy_keys.pluck(:identifier)
368   - keys
369   - end
370   -
371   - def allow_read_for?(user)
372   - !users_projects.where(user_id: user.id).empty?
373   - end
374   -
375   - def guest_access_for?(user)
376   - !users_projects.where(user_id: user.id).empty?
377   - end
378   -
379   - def report_access_for?(user)
380   - !users_projects.where(user_id: user.id, project_access: [UsersProject::REPORTER, UsersProject::DEVELOPER, UsersProject::MASTER]).empty?
381   - end
382   -
383   - def dev_access_for?(user)
384   - !users_projects.where(user_id: user.id, project_access: [UsersProject::DEVELOPER, UsersProject::MASTER]).empty?
385   - end
386   -
387   - def master_access_for?(user)
388   - !users_projects.where(user_id: user.id, project_access: [UsersProject::MASTER]).empty?
389   - end
390   -
391 288 def transfer(new_namespace)
392 289 Project.transaction do
393 290 old_namespace = namespace
... ... @@ -464,8 +361,8 @@ class Project &lt; ActiveRecord::Base
464 361  
465 362 # Discover the default branch, but only if it hasn't already been set to
466 363 # something else
467   - if default_branch.nil?
468   - update_attributes(default_branch: discover_default_branch)
  364 + if repository && default_branch.nil?
  365 + update_attributes(default_branch: self.repository.discover_default_branch)
469 366 end
470 367 end
471 368  
... ... @@ -517,7 +414,7 @@ class Project &lt; ActiveRecord::Base
517 414 #
518 415 def post_receive_data(oldrev, newrev, ref, user)
519 416  
520   - push_commits = commits_between(oldrev, newrev)
  417 + push_commits = repository.commits_between(oldrev, newrev)
521 418  
522 419 # Total commits count
523 420 push_commits_count = push_commits.size
... ... @@ -564,7 +461,7 @@ class Project &lt; ActiveRecord::Base
564 461 def update_merge_requests(oldrev, newrev, ref, user)
565 462 return true unless ref =~ /heads/
566 463 branch_name = ref.gsub("refs/heads/", "")
567   - c_ids = self.commits_between(oldrev, newrev).map(&:id)
  464 + c_ids = self.repository.commits_between(oldrev, newrev).map(&:id)
568 465  
569 466 # Update code for merge requests
570 467 mrs = self.merge_requests.opened.find_all_by_branch(branch_name).all
... ... @@ -586,97 +483,21 @@ class Project &lt; ActiveRecord::Base
586 483 end
587 484  
588 485 def empty_repo?
589   - !repo_exists? || !has_commits?
590   - end
591   -
592   - def commit(commit_id = nil)
593   - Commit.find_or_first(repo, commit_id, root_ref)
594   - end
595   -
596   - def fresh_commits(n = 10)
597   - Commit.fresh_commits(repo, n)
598   - end
599   -
600   - def commits_with_refs(n = 20)
601   - Commit.commits_with_refs(repo, n)
602   - end
603   -
604   - def commits_since(date)
605   - Commit.commits_since(repo, date)
606   - end
607   -
608   - def commits(ref, path = nil, limit = nil, offset = nil)
609   - Commit.commits(repo, ref, path, limit, offset)
610   - end
611   -
612   - def last_commit_for(ref, path = nil)
613   - commits(ref, path, 1).first
614   - end
615   -
616   - def commits_between(from, to)
617   - Commit.commits_between(repo, from, to)
  486 + !repository || repository.empty?
618 487 end
619 488  
620 489 def satellite
621 490 @satellite ||= Gitlab::Satellite::Satellite.new(self)
622 491 end
623 492  
624   - def has_post_receive_file?
625   - !!hook_file
626   - end
627   -
628   - def valid_post_receive_file?
629   - valid_hook_file == hook_file
630   - end
631   -
632   - def valid_hook_file
633   - @valid_hook_file ||= File.read(Rails.root.join('lib', 'hooks', 'post-receive'))
634   - end
635   -
636   - def hook_file
637   - @hook_file ||= begin
638   - hook_path = File.join(path_to_repo, 'hooks', 'post-receive')
639   - File.read(hook_path) if File.exists?(hook_path)
640   - end
641   - end
642   -
643   - # Returns an Array of branch names
644   - def branch_names
645   - repo.branches.collect(&:name).sort
646   - end
647   -
648   - # Returns an Array of Branches
649   - def branches
650   - repo.branches.sort_by(&:name)
651   - end
652   -
653   - # Returns an Array of tag names
654   - def tag_names
655   - repo.tags.collect(&:name).sort.reverse
656   - end
657   -
658   - # Returns an Array of Tags
659   - def tags
660   - repo.tags.sort_by(&:name).reverse
661   - end
662   -
663   - # Returns an Array of branch and tag names
664   - def ref_names
665   - [branch_names + tag_names].flatten
666   - end
667   -
668 493 def repo
669   - @repo ||= Grit::Repo.new(path_to_repo)
  494 + repository.raw
670 495 end
671 496  
672 497 def url_to_repo
673 498 gitolite.url_to_repo(path_with_namespace)
674 499 end
675 500  
676   - def path_to_repo
677   - File.join(Gitlab.config.gitolite.repos_path, "#{path_with_namespace}.git")
678   - end
679   -
680 501 def namespace_dir
681 502 namespace.try(:path) || ''
682 503 end
... ... @@ -690,21 +511,11 @@ class Project &lt; ActiveRecord::Base
690 511 end
691 512  
692 513 def repo_exists?
693   - @repo_exists ||= (repo && !repo.branches.empty?)
  514 + @repo_exists ||= (repository && repository.branches.present?)
694 515 rescue
695 516 @repo_exists = false
696 517 end
697 518  
698   - def heads
699   - @heads ||= repo.heads
700   - end
701   -
702   - def tree(fcommit, path = nil)
703   - fcommit = commit if fcommit == :head
704   - tree = fcommit.tree
705   - path ? (tree / path) : tree
706   - end
707   -
708 519 def open_branches
709 520 if protected_branches.empty?
710 521 self.repo.heads
... ... @@ -714,61 +525,8 @@ class Project &lt; ActiveRecord::Base
714 525 end.sort_by(&:name)
715 526 end
716 527  
717   - # Discovers the default branch based on the repository's available branches
718   - #
719   - # - If no branches are present, returns nil
720   - # - If one branch is present, returns its name
721   - # - If two or more branches are present, returns the one that has a name
722   - # matching root_ref (default_branch or 'master' if default_branch is nil)
723   - def discover_default_branch
724   - if branch_names.length == 0
725   - nil
726   - elsif branch_names.length == 1
727   - branch_names.first
728   - else
729   - branch_names.select { |v| v == root_ref }.first
730   - end
731   - end
732   -
733   - def has_commits?
734   - !!commit
735   - rescue Grit::NoSuchPathError
736   - false
737   - end
738   -
739   - def root_ref
740   - default_branch || "master"
741   - end
742   -
743 528 def root_ref?(branch)
744   - root_ref == branch
745   - end
746   -
747   - # Archive Project to .tar.gz
748   - #
749   - # Already packed repo archives stored at
750   - # app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz
751   - #
752   - def archive_repo(ref)
753   - ref = ref || self.root_ref
754   - commit = self.commit(ref)
755   - return nil unless commit
756   -
757   - # Build file path
758   - file_name = self.path + "-" + commit.id.to_s + ".tar.gz"
759   - storage_path = Rails.root.join("tmp", "repositories", self.path_with_namespace)
760   - file_path = File.join(storage_path, file_name)
761   -
762   - # Put files into a directory before archiving
763   - prefix = self.path + "/"
764   -
765   - # Create file if not exists
766   - unless File.exists?(file_path)
767   - FileUtils.mkdir_p storage_path
768   - file = self.repo.archive_to_file(ref, prefix, file_path)
769   - end
770   -
771   - file_path
  529 + repository.root_ref == branch
772 530 end
773 531  
774 532 def ssh_url_to_repo
... ...
app/models/protected_branch.rb
... ... @@ -26,6 +26,6 @@ class ProtectedBranch &lt; ActiveRecord::Base
26 26 end
27 27  
28 28 def commit
29   - project.commit(self.name)
  29 + project.repository.commit(self.name)
30 30 end
31 31 end
... ...
app/models/repository.rb 0 → 100644
... ... @@ -0,0 +1,169 @@
  1 +class Repository
  2 + # Repository directory name with namespace direcotry
  3 + # Examples:
  4 + # gitlab/gitolite
  5 + # diaspora
  6 + #
  7 + attr_accessor :path_with_namespace
  8 +
  9 + # Grit repo object
  10 + attr_accessor :repo
  11 +
  12 + # Default branch in the repository
  13 + attr_accessor :root_ref
  14 +
  15 + def initialize(path_with_namespace, root_ref = 'master')
  16 + @root_ref = root_ref || "master"
  17 + @path_with_namespace = path_with_namespace
  18 +
  19 + # Init grit repo object
  20 + repo
  21 + end
  22 +
  23 + def raw
  24 + repo
  25 + end
  26 +
  27 + def path_to_repo
  28 + @path_to_repo ||= File.join(Gitlab.config.gitolite.repos_path, "#{path_with_namespace}.git")
  29 + end
  30 +
  31 + def repo
  32 + @repo ||= Grit::Repo.new(path_to_repo)
  33 + end
  34 +
  35 + def commit(commit_id = nil)
  36 + Commit.find_or_first(repo, commit_id, root_ref)
  37 + end
  38 +
  39 + def fresh_commits(n = 10)
  40 + Commit.fresh_commits(repo, n)
  41 + end
  42 +
  43 + def commits_with_refs(n = 20)
  44 + Commit.commits_with_refs(repo, n)
  45 + end
  46 +
  47 + def commits_since(date)
  48 + Commit.commits_since(repo, date)
  49 + end
  50 +
  51 + def commits(ref, path = nil, limit = nil, offset = nil)
  52 + Commit.commits(repo, ref, path, limit, offset)
  53 + end
  54 +
  55 + def last_commit_for(ref, path = nil)
  56 + commits(ref, path, 1).first
  57 + end
  58 +
  59 + def commits_between(from, to)
  60 + Commit.commits_between(repo, from, to)
  61 + end
  62 +
  63 + def has_post_receive_file?
  64 + !!hook_file
  65 + end
  66 +
  67 + def valid_post_receive_file?
  68 + valid_hook_file == hook_file
  69 + end
  70 +
  71 + def valid_hook_file
  72 + @valid_hook_file ||= File.read(Rails.root.join('lib', 'hooks', 'post-receive'))
  73 + end
  74 +
  75 + def hook_file
  76 + @hook_file ||= begin
  77 + hook_path = File.join(path_to_repo, 'hooks', 'post-receive')
  78 + File.read(hook_path) if File.exists?(hook_path)
  79 + end
  80 + end
  81 +
  82 + # Returns an Array of branch names
  83 + def branch_names
  84 + repo.branches.collect(&:name).sort
  85 + end
  86 +
  87 + # Returns an Array of Branches
  88 + def branches
  89 + repo.branches.sort_by(&:name)
  90 + end
  91 +
  92 + # Returns an Array of tag names
  93 + def tag_names
  94 + repo.tags.collect(&:name).sort.reverse
  95 + end
  96 +
  97 + # Returns an Array of Tags
  98 + def tags
  99 + repo.tags.sort_by(&:name).reverse
  100 + end
  101 +
  102 + # Returns an Array of branch and tag names
  103 + def ref_names
  104 + [branch_names + tag_names].flatten
  105 + end
  106 +
  107 + def heads
  108 + @heads ||= repo.heads
  109 + end
  110 +
  111 + def tree(fcommit, path = nil)
  112 + fcommit = commit if fcommit == :head
  113 + tree = fcommit.tree
  114 + path ? (tree / path) : tree
  115 + end
  116 +
  117 + def has_commits?
  118 + !!commit
  119 + rescue Grit::NoSuchPathError
  120 + false
  121 + end
  122 +
  123 + def empty?
  124 + !has_commits?
  125 + end
  126 +
  127 + # Discovers the default branch based on the repository's available branches
  128 + #
  129 + # - If no branches are present, returns nil
  130 + # - If one branch is present, returns its name
  131 + # - If two or more branches are present, returns the one that has a name
  132 + # matching root_ref (default_branch or 'master' if default_branch is nil)
  133 + def discover_default_branch
  134 + if branch_names.length == 0
  135 + nil
  136 + elsif branch_names.length == 1
  137 + branch_names.first
  138 + else
  139 + branch_names.select { |v| v == root_ref }.first
  140 + end
  141 + end
  142 +
  143 + # Archive Project to .tar.gz
  144 + #
  145 + # Already packed repo archives stored at
  146 + # app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz
  147 + #
  148 + def archive_repo(ref)
  149 + ref = ref || self.root_ref
  150 + commit = self.commit(ref)
  151 + return nil unless commit
  152 +
  153 + # Build file path
  154 + file_name = self.path + "-" + commit.id.to_s + ".tar.gz"
  155 + storage_path = Rails.root.join("tmp", "repositories", self.path_with_namespace)
  156 + file_path = File.join(storage_path, file_name)
  157 +
  158 + # Put files into a directory before archiving
  159 + prefix = self.path + "/"
  160 +
  161 + # Create file if not exists
  162 + unless File.exists?(file_path)
  163 + FileUtils.mkdir_p storage_path
  164 + file = self.repo.archive_to_file(ref, prefix, file_path)
  165 + end
  166 +
  167 + file_path
  168 + end
  169 +end
... ...
app/models/team.rb 0 → 100644
... ... @@ -0,0 +1,118 @@
  1 +class Team
  2 + attr_accessor :project
  3 +
  4 + def initialize(project)
  5 + @project = project
  6 + end
  7 +
  8 + # Shortcut to add users
  9 + #
  10 + # Use:
  11 + # @team << [@user, :master]
  12 + # @team << [@users, :master]
  13 + #
  14 + def << args
  15 + users = args.first
  16 +
  17 + if users.respond_to?(:each)
  18 + add_users(users, args.second)
  19 + else
  20 + add_user(users, args.second)
  21 + end
  22 + end
  23 +
  24 + def add_user(user, access)
  25 + add_users_ids([user.id], access)
  26 + end
  27 +
  28 + def add_users(users, access)
  29 + add_users_ids(users.map(&:id), access)
  30 + end
  31 +
  32 + def add_users_ids(user_ids, access)
  33 + UsersProject.add_users_into_projects(
  34 + [project.id],
  35 + user_ids,
  36 + access
  37 + )
  38 + end
  39 +
  40 + # Remove all users from project team
  41 + def truncate
  42 + UsersProject.truncate_team(project)
  43 + end
  44 +
  45 + def members
  46 + project.users_projects
  47 + end
  48 +
  49 + def guests
  50 + members.guests.map(&:user)
  51 + end
  52 +
  53 + def reporters
  54 + members.reporters.map(&:user)
  55 + end
  56 +
  57 + def developers
  58 + members.developers.map(&:user)
  59 + end
  60 +
  61 + def masters
  62 + members.masters.map(&:user)
  63 + end
  64 +
  65 + def repository_readers
  66 + repository_members[UsersProject::REPORTER]
  67 + end
  68 +
  69 + def repository_writers
  70 + repository_members[UsersProject::DEVELOPER]
  71 + end
  72 +
  73 + def repository_masters
  74 + repository_members[UsersProject::MASTER]
  75 + end
  76 +
  77 + def repository_members
  78 + keys = Hash.new {|h,k| h[k] = [] }
  79 + UsersProject.select("keys.identifier, project_access").
  80 + joins(user: :keys).where(project_id: project.id).
  81 + each {|row| keys[row.project_access] << [row.identifier] }
  82 +
  83 + keys[UsersProject::REPORTER] += project.deploy_keys.pluck(:identifier)
  84 + keys
  85 + end
  86 +
  87 + def import(source_project)
  88 + target_project = project
  89 +
  90 + source_team = source_project.users_projects.all
  91 + target_team = target_project.users_projects.all
  92 + target_user_ids = target_team.map(&:user_id)
  93 +
  94 + source_team.reject! do |tm|
  95 + # Skip if user already present in team
  96 + target_user_ids.include?(tm.user_id)
  97 + end
  98 +
  99 + source_team.map! do |tm|
  100 + new_tm = tm.dup
  101 + new_tm.id = nil
  102 + new_tm.project_id = target_project.id
  103 + new_tm.skip_git = true
  104 + new_tm
  105 + end
  106 +
  107 + UsersProject.transaction do
  108 + source_team.each do |tm|
  109 + tm.save
  110 + end
  111 + target_project.update_repository
  112 + end
  113 +
  114 + true
  115 + rescue
  116 + false
  117 + end
  118 +end
... ...
app/models/tree.rb
1 1 class Tree
2 2 include Linguist::BlobHelper
3   - attr_accessor :path, :tree, :project, :ref
  3 +
  4 + attr_accessor :path, :tree, :ref
4 5  
5 6 delegate :contents, :basename, :name, :data, :mime_type,
6 7 :mode, :size, :text?, :colorize, to: :tree
7 8  
8   - def initialize(raw_tree, project, ref = nil, path = nil)
9   - @project, @ref, @path = project, ref, path
  9 + def initialize(raw_tree, ref = nil, path = nil)
  10 + @ref, @path = ref, path
10 11 @tree = if path.present?
11 12 raw_tree / path
12 13 else
... ...
app/models/user.rb
... ... @@ -188,7 +188,7 @@ class User &lt; ActiveRecord::Base
188 188  
189 189 # Team membership in personal projects
190 190 def tm_in_personal_projects
191   - personal_projects.users_projects.where(user_id: self.id)
  191 + UsersProject.where(project_id: personal_projects.map(&:id), user_id: self.id)
192 192 end
193 193  
194 194 # Returns a string for use as a Gitolite user identifier
... ...
app/models/users_project.rb
... ... @@ -42,7 +42,34 @@ class UsersProject &lt; ActiveRecord::Base
42 42 scope :in_project, ->(project) { where(project_id: project.id) }
43 43  
44 44 class << self
45   - def add_users_into_projects(project_ids, user_ids, project_access)
  45 +
  46 + # Add users to project teams with passed access option
  47 + #
  48 + # access can be an integer representing a access code
  49 + # or symbol like :master representing role
  50 + #
  51 + # Ex.
  52 + # add_users_into_projects(
  53 + # project_ids,
  54 + # user_ids,
  55 + # UsersProject::MASTER
  56 + # )
  57 + #
  58 + # add_users_into_projects(
  59 + # project_ids,
  60 + # user_ids,
  61 + # :master
  62 + # )
  63 + #
  64 + def add_users_into_projects(project_ids, user_ids, access)
  65 + project_access = if roles_hash.has_key?(access)
  66 + roles_hash[access]
  67 + elsif roles_hash.values.include?(access.to_i)
  68 + access
  69 + else
  70 + raise "Non valid access"
  71 + end
  72 +
46 73 UsersProject.transaction do
47 74 project_ids.each do |project_id|
48 75 user_ids.each do |user_id|
... ... @@ -79,36 +106,6 @@ class UsersProject &lt; ActiveRecord::Base
79 106 truncate_teams [project.id]
80 107 end
81 108  
82   - def import_team(source_project, target_project)
83   - source_team = source_project.users_projects.all
84   - target_team = target_project.users_projects.all
85   - target_user_ids = target_team.map(&:user_id)
86   -
87   - source_team.reject! do |tm|
88   - # Skip if user already present in team
89   - target_user_ids.include?(tm.user_id)
90   - end
91   -
92   - source_team.map! do |tm|
93   - new_tm = tm.dup
94   - new_tm.id = nil
95   - new_tm.project_id = target_project.id
96   - new_tm.skip_git = true
97   - new_tm
98   - end
99   -
100   - UsersProject.transaction do
101   - source_team.each do |tm|
102   - tm.save
103   - end
104   - target_project.update_repository
105   - end
106   -
107   - true
108   - rescue
109   - false
110   - end
111   -
112 109 def bulk_delete(project, user_ids)
113 110 UsersProject.transaction do
114 111 UsersProject.where(user_id: user_ids, project_id: project.id).each do |users_project|
... ... @@ -131,14 +128,13 @@ class UsersProject &lt; ActiveRecord::Base
131 128 end
132 129 end
133 130  
134   - # TODO: depreceate in future in favor of add_users_into_projects
135   - def bulk_import(project, user_ids, project_access)
136   - add_users_into_projects([project.id], user_ids, project_access)
137   - end
138   -
139   - # TODO: depreceate in future in favor of add_users_into_projects
140   - def user_bulk_import(user, project_ids, project_access)
141   - add_users_into_projects(project_ids, [user.id], project_access)
  131 + def roles_hash
  132 + {
  133 + guest: GUEST,
  134 + reporter: REPORTER,
  135 + developer: DEVELOPER,
  136 + master: MASTER
  137 + }
142 138 end
143 139  
144 140 def access_roles
... ...
app/uploaders/attachment_uploader.rb
1 1 # encoding: utf-8
2 2  
3 3 class AttachmentUploader < CarrierWave::Uploader::Base
4   -
5   - # Include RMagick or ImageScience support:
6   - # include CarrierWave::RMagick
7   - # include CarrierWave::MiniMagick
8   - # include CarrierWave::ImageScience
9   -
10   - # Choose what kind of storage to use for this uploader:
11 4 storage :file
12   - # storage :fog
13 5  
14   - # Override the directory where uploaded files will be stored.
15   - # This is a sensible default for uploaders that are meant to be mounted:
16 6 def store_dir
17 7 "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
18 8 end
19 9  
20   - # Provide a default URL as a default if there hasn't been a file uploaded:
21   - # def default_url
22   - # "/images/fallback/" + [version_name, "default.png"].compact.join('_')
23   - # end
24   -
25   - # Process files as they are uploaded:
26   - # process scale: [200, 300]
27   - #
28   - # def scale(width, height)
29   - # # do something
30   - # end
31   -
32   - # Create different versions of your uploaded files:
33   - # version :thumb do
34   - # process scale: [50, 50]
35   - # end
36   -
37   - # Add a white list of extensions which are allowed to be uploaded.
38   - # For images you might use something like this:
39   - # def extension_white_list
40   - # %w(jpg jpeg gif png)
41   - # end
42   -
43   - # Override the filename of the uploaded files:
44   - # Avoid using model.id or version_name here, see uploader/store.rb for details.
45   - # def filename
46   - # "something.jpg" if original_filename
47   - # end
48   -
  10 + def image?
  11 + %w(png jpg jpeg).include?(file.extension)
  12 + end
49 13 end
... ...
app/views/admin/dashboard/index.html.haml
1 1 .admin_dash.row
2 2 .span3
3 3 .ui-box
4   - %h5 Projects
  4 + %h5.title Projects
5 5 .data.padded
6 6 = link_to admin_projects_path do
7 7 %h1= Project.count
... ... @@ -9,7 +9,7 @@
9 9 = link_to 'New Project', new_project_path, class: "btn small"
10 10 .span3
11 11 .ui-box
12   - %h5 Groups
  12 + %h5.title Groups
13 13 .data.padded
14 14 = link_to admin_groups_path do
15 15 %h1= Group.count
... ... @@ -17,7 +17,7 @@
17 17 = link_to 'New Group', new_admin_group_path, class: "btn small"
18 18 .span3
19 19 .ui-box
20   - %h5 Users
  20 + %h5.title Users
21 21 .data.padded
22 22 = link_to admin_users_path do
23 23 %h1= User.count
... ... @@ -25,7 +25,7 @@
25 25 = link_to 'New User', new_admin_user_path, class: "btn small"
26 26 .span3
27 27 .ui-box
28   - %h5
  28 + %h5.title
29 29 Resque Workers
30 30 .data.padded
31 31 - if @resque_accessible
... ...
app/views/admin/projects/_form.html.haml
... ... @@ -22,7 +22,7 @@
22 22 - if project.repo_exists?
23 23 .clearfix
24 24 = f.label :default_branch, "Default Branch"
25   - .input= f.select(:default_branch, project.heads.map(&:name), {}, style: "width:210px;")
  25 + .input= f.select(:default_branch, repository.heads.map(&:name), {}, style: "width:210px;")
26 26  
27 27 %fieldset.adv_settings
28 28 %legend Features:
... ...
app/views/admin/projects/show.html.haml
... ... @@ -4,15 +4,15 @@
4 4 %i.icon-edit
5 5 Edit
6 6  
7   -- if @project.has_commits?
8   - - if !@project.has_post_receive_file?
  7 +- if @repository && @repository.has_commits?
  8 + - if !@repository.has_post_receive_file?
9 9 %br
10 10 .alert.alert-error
11 11 %span
12 12 %strong Project has commits but missing post-receive file.
13 13 %br
14 14 If you exported project manually - make a link of post-receive hook file from gitolite to project repository
15   - - elsif !@project.valid_post_receive_file?
  15 + - elsif !@repository.valid_post_receive_file?
16 16 %br
17 17 .alert.alert-error
18 18 %span
... ... @@ -65,42 +65,43 @@
65 65 Created at:
66 66 %td
67 67 = @project.created_at.stamp("March 1, 1999")
  68 + %tr
  69 + %td
  70 + %b
  71 + Smart HTTP:
  72 + %td
  73 + = link_to @project.http_url_to_repo
  74 + %tr
  75 + %td
  76 + %b
  77 + SSH:
  78 + %td
  79 + = link_to @project.ssh_url_to_repo
68 80  
69   -%table.zebra-striped
70   - %thead
  81 +- if @repository
  82 + %table.zebra-striped
  83 + %thead
  84 + %tr
  85 + %th Repository
  86 + %th
71 87 %tr
72   - %th Repository
73   - %th
74   - %tr
75   - %td
76   - %b
77   - FS Path:
78   - %td
79   - %code= @project.path_to_repo
80   - %tr
81   - %td
82   - %b
83   - Smart HTTP:
84   - %td
85   - = link_to @project.http_url_to_repo
86   - %tr
87   - %td
88   - %b
89   - SSH:
90   - %td
91   - = link_to @project.ssh_url_to_repo
92   - %tr
93   - %td
94   - %b
95   - Last commit at:
96   - %td
97   - = last_commit(@project)
98   - %tr
99   - %td
100   - %b
101   - Post Receive File:
102   - %td
103   - = check_box_tag :post_receive_file, 1, @project.has_post_receive_file?, disabled: true
  88 + %td
  89 + %b
  90 + FS Path:
  91 + %td
  92 + %code= @repository.path_to_repo
  93 + %tr
  94 + %td
  95 + %b
  96 + Last commit at:
  97 + %td
  98 + = last_commit(@project)
  99 + %tr
  100 + %td
  101 + %b
  102 + Post Receive File:
  103 + %td
  104 + = check_box_tag :post_receive_file, 1, @repository.has_post_receive_file?, disabled: true
104 105  
105 106 %br
106 107 %h5
... ...
app/views/commit/show.html.haml
1 1 = render "commits/commit_box"
  2 +
  3 +%p.right.cgray
  4 + This commit has
  5 + %span.cgreen #{@commit.stats.additions} additions
  6 + and
  7 + %span.cred #{@commit.stats.deletions} deletions
  8 +
2 9 = render "commits/diffs", diffs: @commit.diffs
3 10 = render "notes/notes_with_form", tid: @commit.id, tt: "commit"
4 11 = render "notes/per_line_form"
5 12  
6   -
7 13 :javascript
8 14 $(function(){
9 15 PerLineNotes.init();
... ... @@ -19,7 +25,7 @@
19 25 , h = event.currentTarget.naturalHeight;
20 26 $('.image.diff_added .image-info', this).append(' | <b>W:</b> ' + w + 'px | <b>H:</b> ' + h + 'px');
21 27 }, this));
22   -
  28 +
23 29 });
24   -
  30 +
25 31 });
... ...
app/views/commits/_commit_box.html.haml
1   -.commit-box{class: @commit.parents_count > 1 ? "merge-commit" : ""}
2   - .commit-head
  1 +.ui-box.ui-box-show
  2 + .ui-box-head
3 3 .right
4 4 - if @notes_count > 0
5 5 %span.btn.disabled.grouped
6 6 %i.icon-comment
7 7 = @notes_count
8 8 .left.btn-group
9   - %a.btn.small.grouped.dropdown-toggle{ data: {toggle: :dropdown} }
  9 + %a.btn.grouped.dropdown-toggle{ data: {toggle: :dropdown} }
10 10 %i.icon-download-alt
11 11 Download as
12 12 %span.caret
13 13 %ul.dropdown-menu
14 14 %li= link_to "Email Patches", project_commit_path(@project, @commit, format: :patch)
15 15 %li= link_to "Plain Diff", project_commit_path(@project, @commit, format: :diff)
16   - = link_to project_tree_path(@project, @commit), class: "browse-button primary grouped" do
17   - %strong Browse Code »
  16 + = link_to project_tree_path(@project, @commit), class: "btn primary grouped" do
  17 + %span Browse Code »
18 18 %h3.commit-title.page_title
19 19 = gfm escape_once(@commit.title)
20 20 - if @commit.description.present?
21 21 %pre.commit-description
22 22 = gfm escape_once(@commit.description)
23   - .commit-info
  23 + .ui-box-body
24 24 .row
25 25 .span5
26 26 .author
27   - %strong= @commit.author_link avatar: true, size: 40
  27 + = @commit.author_link avatar: true, size: 32
28 28 authored
29 29 %time{title: @commit.authored_date.stamp("Aug 21, 2011 9:23pm")}
30 30 #{time_ago_in_words(@commit.authored_date)} ago
31 31 - if @commit.different_committer?
32 32 .committer
33 33 &rarr;
34   - %strong= @commit.committer_link
  34 + = @commit.committer_link
35 35 committed
36 36 %time{title: @commit.committed_date.stamp("Aug 21, 2011 9:23pm")}
37 37 #{time_ago_in_words(@commit.committed_date)} ago
38   - .span6.right
39   - .sha-block
40   - %span.cgray commit
41   - %code.label_commit= @commit.id
42   - .sha-block
43   - %span.cgray= pluralize(@commit.parents.count, "parent")
44   - - @commit.parents.each do |parent|
45   - = link_to parent.id[0...10], project_commit_path(@project, parent)
  38 + .span6.pull-right
  39 + .pull-right
  40 + .sha-block
  41 + %span.cgray commit
  42 + %span.label_commit= @commit.id
  43 + .clearfix
  44 + .pull-right
  45 + .sha-block
  46 + %span.cgray= pluralize(@commit.parents.count, "parent")
  47 + - @commit.parents.each do |parent|
  48 + = link_to parent.id[0...10], project_commit_path(@project, parent)
46 49  
47 50  
... ...
app/views/commits/_commits.html.haml
1 1 - @commits.group_by { |c| c.committed_date.to_date }.each do |day, commits|
2 2 %div.ui-box
3   - %h5.small
  3 + %h5.title
4 4 %i.icon-calendar
5 5 = day.stamp("28 Aug, 2010")
6 6 %ul.well-list= render commits
... ...
app/views/commits/_head.html.haml
... ... @@ -2,19 +2,19 @@
2 2 %li= render partial: 'shared/ref_switcher', locals: {destination: 'commits'}
3 3  
4 4 = nav_link(controller: [:commit, :commits]) do
5   - = link_to 'Commits', project_commits_path(@project, @project.root_ref)
  5 + = link_to 'Commits', project_commits_path(@project, @repository.root_ref)
6 6 = nav_link(controller: :compare) do
7 7 = link_to 'Compare', project_compare_index_path(@project)
8 8  
9 9 = nav_link(html_options: {class: branches_tab_class}) do
10 10 = link_to project_repository_path(@project) do
11 11 Branches
12   - %span.badge= @project.branches.length
  12 + %span.badge= @repository.branches.length
13 13  
14 14 = nav_link(controller: :repositories, action: :tags) do
15 15 = link_to tags_project_repository_path(@project) do
16 16 Tags
17   - %span.badge= @project.tags.length
  17 + %span.badge= @repository.tags.length
18 18  
19 19 = nav_link(controller: :repositories, action: :stats) do
20 20 = link_to stats_project_repository_path(@project) do
... ...
app/views/compare/_form.html.haml
... ... @@ -28,7 +28,7 @@
28 28  
29 29 :javascript
30 30 $(function() {
31   - var availableTags = #{@project.ref_names.to_json};
  31 + var availableTags = #{@project.repository.ref_names.to_json};
32 32  
33 33 $("#from, #to").autocomplete({
34 34 source: availableTags,
... ...
app/views/dashboard/_groups.html.haml
1 1 .groups_box
2   - %h5
  2 + %h5.title
3 3 Groups
4 4 %small
5 5 (#{groups.count})
... ...
app/views/dashboard/_projects.html.haml
1 1 .projects_box
2   - %h5
  2 + %h5.title
3 3 Projects
4 4 %small
5 5 (#{projects.total_count})
... ...
app/views/dashboard/issues.html.haml
... ... @@ -13,7 +13,8 @@
13 13 - @issues.group_by(&:project).each do |group|
14 14 %div.ui-box
15 15 - @project = group[0]
16   - %h5= link_to_project @project
  16 + %h5.title
  17 + = link_to_project @project
17 18 %ul.well-list.issues_table
18 19 - group[1].each do |issue|
19 20 = render(partial: 'issues/show', locals: {issue: issue})
... ...
app/views/dashboard/merge_requests.html.haml
... ... @@ -12,7 +12,8 @@
12 12 - @merge_requests.group_by(&:project).each do |group|
13 13 .ui-box
14 14 - @project = group[0]
15   - %h5= link_to_project @project
  15 + %h5.title
  16 + = link_to_project @project
16 17 %ul.well-list
17 18 - group[1].each do |merge_request|
18 19 = render(partial: 'merge_requests/merge_request', locals: {merge_request: merge_request})
... ...
app/views/groups/_projects.html.haml
1 1 .projects_box
2   - %h5
  2 + %h5.title
3 3 Projects
4 4 %small
5 5 (#{projects.count})
... ...
app/views/groups/issues.html.haml
... ... @@ -9,7 +9,8 @@
9 9 - @issues.group_by(&:project).each do |group|
10 10 %div.ui-box
11 11 - @project = group[0]
12   - %h5= @project.name
  12 + %h5.title
  13 + = @project.name
13 14 %ul.well-list.issues_table
14 15 - group[1].each do |issue|
15 16 = render(partial: 'issues/show', locals: {issue: issue})
... ...
app/views/groups/merge_requests.html.haml
... ... @@ -8,7 +8,8 @@
8 8 - @merge_requests.group_by(&:project).each do |group|
9 9 %ul.well-list.ui-box
10 10 - @project = group[0]
11   - %h5= @project.name
  11 + %h5.title
  12 + = @project.name
12 13 - group[1].each do |merge_request|
13 14 = render(partial: 'merge_requests/merge_request', locals: {merge_request: merge_request})
14 15 %hr
... ...
app/views/groups/people.html.haml
... ... @@ -5,7 +5,7 @@
5 5 - if can?(current_user, :manage_group, @group)
6 6 = render (@project ? "new_member" : "new_group_member")
7 7 .ui-box
8   - %h5
  8 + %h5.title
9 9 Team
10 10 %small
11 11 (#{@users.size})
... ...
app/views/issues/_form.html.haml
... ... @@ -6,26 +6,27 @@
6 6 - @issue.errors.full_messages.each do |msg|
7 7 %span= msg
8 8 %br
9   - .issue_form_box
10   - .issue_title
  9 + .ui-box.ui-box-show
  10 + .ui-box-head
11 11 .clearfix
12 12 = f.label :title do
13 13 %strong= "Subject *"
14 14 .input
15 15 = f.text_field :title, maxlength: 255, class: "xxlarge js-gfm-input", autofocus: true, required: true
16   - .issue_middle_block
17   - .issue_assignee
18   - = f.label :assignee_id do
19   - %i.icon-user
20   - Assign to
21   - .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select a user" }, {class: 'chosen'})
22   - .issue_milestone
23   - = f.label :milestone_id do
24   - %i.icon-time
25   - Milestone
26   - .input= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'})
  16 + .ui-box-body
  17 + .clearfix
  18 + .issue_assignee.pull-left
  19 + = f.label :assignee_id do
  20 + %i.icon-user
  21 + Assign to
  22 + .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select a user" }, {class: 'chosen'})
  23 + .issue_milestone.pull-left
  24 + = f.label :milestone_id do
  25 + %i.icon-time
  26 + Milestone
  27 + .input= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'})
27 28  
28   - .issue_description
  29 + .ui-box-bottom
29 30 .clearfix
30 31 = f.label :label_list do
31 32 %i.icon-tag
... ...
app/views/issues/index.html.haml
... ... @@ -30,7 +30,7 @@
30 30 = select_tag('update[milestone_id]', options_from_collection_for_select(issues_active_milestones, "id", "title", params[:milestone_id]), prompt: "Milestone")
31 31 = hidden_field_tag 'update[issues_ids]', []
32 32 = hidden_field_tag :f, params[:f]
33   - = button_tag "Save", class: "btn update_selected_issues"
  33 + = button_tag "Save", class: "btn update_selected_issues btn-small save-btn"
34 34 .issues_filters
35 35 .left
36 36 %ul.nav.nav-pills.left
... ...
app/views/issues/show.html.haml
... ... @@ -24,14 +24,14 @@
24 24 &larr; To issues list
25 25  
26 26  
27   -.main_box
28   - .top_box_content
  27 +.ui-box.ui-box-show
  28 + .ui-box-head
29 29 %h4.box-title
30 30 - if @issue.closed
31 31 .error.status_info Closed
32 32 = gfm escape_once(@issue.title)
33 33  
34   - .middle_box_content
  34 + .ui-box-body
35 35 %cite.cgray
36 36 Created by #{link_to_member(@project, @issue.author)}
37 37 - if @issue.assignee
... ... @@ -44,13 +44,13 @@
44 44  
45 45 .right
46 46 - @issue.labels.each do |label|
47   - %span.label.label-issue
  47 + %span
48 48 %i.icon-tag
49 49 = label.name
50 50 &nbsp;
51 51  
52 52 - if @issue.description.present?
53   - .bottom_box_content
  53 + .ui-box-bottom
54 54 = preserve do
55 55 = markdown @issue.description
56 56  
... ...
app/views/layouts/project_resource.html.haml
... ... @@ -14,9 +14,9 @@
14 14 - if @project.repo_exists?
15 15 - if can? current_user, :download_code, @project
16 16 = nav_link(controller: %w(tree blob blame)) do
17   - = link_to 'Files', project_tree_path(@project, @ref || @project.root_ref)
  17 + = link_to 'Files', project_tree_path(@project, @ref || @repository.root_ref)
18 18 = nav_link(controller: %w(commit commits compare repositories protected_branches)) do
19   - = link_to "Commits", project_commits_path(@project, @ref || @project.root_ref)
  19 + = link_to "Commits", project_commits_path(@project, @ref || @repository.root_ref)
20 20 = nav_link(path: 'projects#graph') do
21 21 = link_to "Network", graph_project_path(@project)
22 22  
... ...
app/views/merge_requests/_form.html.haml
... ... @@ -5,45 +5,47 @@
5 5 - @merge_request.errors.full_messages.each do |msg|
6 6 %li= msg
7 7  
8   - %h4.cdark 1. Select Branches
9   - %br
  8 + %fieldset
  9 + %legend 1. Select Branches
10 10  
11   - .row
12   - .span5
13   - .mr_branch_box
14   - %h5 From (Head Branch)
15   - .body
16   - .padded= f.select(:source_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, {class: 'chosen span4'})
17   - .mr_source_commit
  11 + .row
  12 + .span5
  13 + .mr_branch_box
  14 + %h5 From (Head Branch)
  15 + .body
  16 + .padded= f.select(:source_branch, @repository.heads.map(&:name), { include_blank: "Select branch" }, {class: 'chosen span4'})
  17 + .mr_source_commit
18 18  
19   - .span2
20   - %center= image_tag "merge.png", class: 'mr_direction_tip'
21   - .span5
22   - .mr_branch_box
23   - %h5 To (Base Branch)
24   - .body
25   - .padded= f.select(:target_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, {class: 'chosen span4'})
26   - .mr_target_commit
  19 + .span2
  20 + %center= image_tag "merge.png", class: 'mr_direction_tip'
  21 + .span5
  22 + .mr_branch_box
  23 + %h5 To (Base Branch)
  24 + .body
  25 + .padded= f.select(:target_branch, @repository.heads.map(&:name), { include_blank: "Select branch" }, {class: 'chosen span4'})
  26 + .mr_target_commit
27 27  
28   - %h4.cdark 2. Fill info
  28 + %fieldset
  29 + %legend 2. Fill info
29 30  
30   - .clearfix
31   - .merge_requests_form_box
32   - .top_box_content
33   - = f.label :title do
34   - %strong= "Title *"
35   - .input= f.text_field :title, class: "input-xxlarge pad js-gfm-input", maxlength: 255, rows: 5, required: true
36   - .merge_requests_middle_box
37   - .merge_requests_assignee
38   - = f.label :assignee_id do
39   - %i.icon-user
40   - Assign to
41   - .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, {class: 'chosen span3'})
42   - .merge_requests_milestone
43   - = f.label :milestone_id do
44   - %i.icon-time
45   - Milestone
46   - .input= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'})
  31 + .ui-box.ui-box-show
  32 + .ui-box-head
  33 + .clearfix
  34 + = f.label :title do
  35 + %strong= "Title *"
  36 + .input= f.text_field :title, class: "input-xxlarge pad js-gfm-input", maxlength: 255, rows: 5, required: true
  37 + .ui-box-body
  38 + .clearfix
  39 + .left
  40 + = f.label :assignee_id do
  41 + %i.icon-user
  42 + Assign to
  43 + .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, {class: 'chosen span3'})
  44 + .left
  45 + = f.label :milestone_id do
  46 + %i.icon-time
  47 + Milestone
  48 + .input= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'})
47 49  
48 50 .control-group
49 51  
... ...
app/views/merge_requests/show/_commits.html.haml
1 1 - if @commits.present?
2 2 .ui-box
3   - %h5
  3 + %h5.title
4 4 %i.icon-list
5 5 Commits (#{@commits.count})
6 6 .merge-request-commits
... ...
app/views/merge_requests/show/_mr_box.html.haml
1   -.main_box
2   - .top_box_content
  1 +.ui-box.ui-box-show
  2 + .ui-box-head
3 3 %h4.box-title
4 4 - if @merge_request.merged
5 5 .error.status_info
... ... @@ -9,7 +9,7 @@
9 9 .error.status_info Closed
10 10 = gfm escape_once(@merge_request.title)
11 11  
12   - .middle_box_content
  12 + .ui-box-body
13 13 %div
14 14 %cite.cgray
15 15 Created at #{@merge_request.created_at.stamp("Aug 21, 2011")} by #{link_to_member(@project, @merge_request.author)}
... ... @@ -22,7 +22,7 @@
22 22  
23 23  
24 24 - if @merge_request.closed
25   - .bottom_box_content
  25 + .ui-box-bottom
26 26 - if @merge_request.merged?
27 27 %span
28 28 Merged by #{link_to_member(@project, @merge_request.merge_event.author)}
... ...
app/views/milestones/show.html.haml
... ... @@ -27,8 +27,8 @@
27 27 %span All issues for this milestone are closed. You may close milestone now.
28 28 = link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {closed: true }), method: :put, class: "btn small danger"
29 29  
30   -.main_box
31   - .top_box_content
  30 +.ui-box.ui-box-show
  31 + .ui-box-head
32 32 %h4.box-title
33 33 - if @milestone.closed
34 34 .error.status_info Closed
... ... @@ -37,7 +37,7 @@
37 37  
38 38 = gfm escape_once(@milestone.title)
39 39  
40   - .middle_box_content
  40 + .ui-box-body
41 41 %h5
42 42 Progress:
43 43 %small
... ...
app/views/notes/_note.html.haml
... ... @@ -34,6 +34,8 @@
34 34 = preserve do
35 35 = markdown(note.note)
36 36 - if note.attachment.url
  37 + - if note.attachment.image?
  38 + = image_tag note.attachment.url, class: 'thumbnail span4'
37 39 .right
38 40 %div.file
39 41 = link_to note.attachment_identifier, note.attachment.url, target: "_blank"
... ...
app/views/projects/_form.html.haml
... ... @@ -15,13 +15,13 @@
15 15 = f.label :path do
16 16 Repository
17 17 .controls
18   - = text_field_tag :ppath, @project.path_to_repo, class: "xxlarge", readonly: true
  18 + = text_field_tag :ppath, @repository.path_to_repo, class: "xxlarge", readonly: true
19 19  
20 20  
21   - - unless @project.heads.empty?
  21 + - unless @repository.heads.empty?
22 22 .clearfix
23 23 = f.label :default_branch, "Default Branch"
24   - .input= f.select(:default_branch, @project.heads.map(&:name), {}, style: "width:210px;")
  24 + .input= f.select(:default_branch, @repository.heads.map(&:name), {}, style: "width:210px;")
25 25  
26 26 %fieldset.features
27 27 %legend Features:
... ...
app/views/protected_branches/index.html.haml
... ... @@ -36,7 +36,7 @@
36 36 %td
37 37 = link_to project_commits_path(@project, branch.name) do
38 38 %strong= branch.name
39   - - if branch.name == @project.root_ref
  39 + - if @project.root_ref?(branch.name)
40 40 %span.label default
41 41 %td
42 42 - if branch.commit
... ...
app/views/repositories/_branch.html.haml
... ... @@ -8,7 +8,7 @@
8 8 - else
9 9 %i.icon-unlock
10 10 %strong= truncate(branch.name, length: 60)
11   - - if branch.name == @project.root_ref
  11 + - if branch.name == @repository.root_ref
12 12 %span.label default
13 13 %td
14 14 = link_to project_commit_path(@project, commit.id), class: 'commit_short_id' do
... ...
app/views/repositories/_feed.html.haml
... ... @@ -5,7 +5,7 @@
5 5 = link_to project_commits_path(@project, commit.head.name) do
6 6 %strong
7 7 = commit.head.name
8   - - if commit.head.name == @project.root_ref
  8 + - if @project.root_ref?(commit.head.name)
9 9 %span.label default
10 10  
11 11 %td
... ...
app/views/repositories/stats.html.haml
... ... @@ -7,7 +7,7 @@
7 7 %b Total commits:
8 8 %span= @stats.commits_count
9 9 %p
10   - %b Total files in #{@project.root_ref}:
  10 + %b Total files in #{@repository.root_ref}:
11 11 %span= @stats.files_count
12 12 %p
13 13 %b Authors:
... ...
app/views/repositories/tags.html.haml
... ... @@ -30,4 +30,10 @@
30 30 Download
31 31  
32 32 - else
33   - %h3 No tags
  33 + %h3.nothing_here_message
  34 + Repository has no tags yet.
  35 + %br
  36 + %small
  37 + Use git tag command to add a new one:
  38 + %br
  39 + %span.monospace git tag -a v1.4 -m 'version 1.4'
... ...
app/views/team_members/_team.html.haml
1 1 - grouper_project_members(@project).each do |access, members|
2 2 .ui-box
3   - %h5
  3 + %h5.title
4 4 = Project.access_options.key(access).pluralize
5 5 %small= members.size
6 6 %ul.well-list
... ...
app/views/tree/_tree.html.haml
... ... @@ -3,9 +3,13 @@
3 3 %span.arrow
4 4 = link_to project_tree_path(@project, @ref) do
5 5 = @project.name
6   - - tree.breadcrumbs(6) do |link|
  6 + - tree.breadcrumbs(6) do |title, path|
7 7 \/
8   - %li= link
  8 + %li
  9 + - if path
  10 + = link_to truncate(title, length: 40), project_tree_path(@project, path)
  11 + - else
  12 + = link_to title, '#'
9 13  
10 14 .clear
11 15 %div.tree_progress
... ... @@ -26,7 +30,7 @@
26 30 %tr.tree-item
27 31 %td.tree-item-file-name
28 32 = image_tag "file_empty.png", size: '16x16'
29   - = link_to "..", tree.up_dir_path
  33 + = link_to "..", project_tree_path(@project, tree.up_dir_path)
30 34 %td
31 35 %td
32 36 %td
... ...
app/views/wikis/_form.html.haml
... ... @@ -6,12 +6,12 @@
6 6 - @wiki.errors.full_messages.each do |msg|
7 7 %li= msg
8 8  
9   - .main_box
10   - .top_box_content
  9 + .ui-box.ui-box-show
  10 + .ui-box-head
11 11 = f.label :title
12 12 .input= f.text_field :title, class: 'span8'
13 13 = f.hidden_field :slug
14   - .middle_box_content
  14 + .ui-box-body
15 15 .input
16 16 %span.cgray
17 17 Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
... ... @@ -19,7 +19,7 @@
19 19 %code [Link Title](page-slug)
20 20 \.
21 21  
22   - .bottom_box_content
  22 + .ui-box-bottom
23 23 = f.label :content
24 24 .input= f.text_area :content, class: 'span8 js-gfm-input'
25 25 .actions
... ...
app/workers/post_receive.rb
... ... @@ -11,7 +11,7 @@ class PostReceive
11 11  
12 12 # Ignore push from non-gitlab users
13 13 user = if identifier.eql? Gitlab.config.gitolite.admin_key
14   - email = project.commit(newrev).author.email rescue nil
  14 + email = project.repository.commit(newrev).author.email rescue nil
15 15 User.find_by_email(email) if email
16 16 elsif /^[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}$/.match(identifier)
17 17 User.find_by_email(identifier)
... ...
features/steps/admin/admin_groups.rb
... ... @@ -16,7 +16,7 @@ class AdminGroups &lt; Spinach::FeatureSteps
16 16 @project = create(:project, group: @group)
17 17 @event = create(:closed_issue_event, project: @project)
18 18  
19   - @project.add_access current_user, :admin
  19 + @project.team << [current_user, :master]
20 20 end
21 21  
22 22 And 'Create gitlab user "John"' do
... ...
features/steps/dashboard/dashboard.rb
... ... @@ -61,7 +61,7 @@ class Dashboard &lt; Spinach::FeatureSteps
61 61  
62 62 And 'I own project "Shop"' do
63 63 @project = create :project, name: 'Shop'
64   - @project.add_access(@user, :admin)
  64 + @project.team << [@user, :master]
65 65 end
66 66  
67 67 And 'I have group with projects' do
... ... @@ -69,7 +69,7 @@ class Dashboard &lt; Spinach::FeatureSteps
69 69 @project = create(:project, group: @group)
70 70 @event = create(:closed_issue_event, project: @project)
71 71  
72   - @project.add_access current_user, :admin
  72 + @project.team << [current_user, :master]
73 73 end
74 74  
75 75 And 'project "Shop" has push event' do
... ...
features/steps/dashboard/dashboard_issues.rb
... ... @@ -13,7 +13,7 @@ class DashboardIssues &lt; Spinach::FeatureSteps
13 13  
14 14 And 'I have assigned issues' do
15 15 project = create :project
16   - project.add_access(@user, :read, :write)
  16 + project.team << [@user, :master]
17 17  
18 18 2.times { create :issue, author: @user, assignee: @user, project: project }
19 19 end
... ...
features/steps/dashboard/dashboard_merge_requests.rb
... ... @@ -14,8 +14,8 @@ class DashboardMergeRequests &lt; Spinach::FeatureSteps
14 14 project1 = create :project
15 15 project2 = create :project
16 16  
17   - project1.add_access(@user, :read, :write)
18   - project2.add_access(@user, :read, :write)
  17 + project1.team << [@user, :master]
  18 + project2.team << [@user, :master]
19 19  
20 20 merge_request1 = create :merge_request, author: @user, project: project1
21 21 merge_request2 = create :merge_request, author: @user, project: project2
... ...
features/steps/dashboard/dashboard_search.rb
1 1 class DashboardSearch < Spinach::FeatureSteps
2 2 include SharedAuthentication
3 3 include SharedPaths
  4 + include SharedProject
4 5  
5 6 Given 'I search for "Sho"' do
6 7 fill_in "dashboard_search", with: "Sho"
... ... @@ -11,11 +12,6 @@ class DashboardSearch &lt; Spinach::FeatureSteps
11 12 page.should have_link "Shop"
12 13 end
13 14  
14   - And 'I own project "Shop"' do
15   - @project = create(:project, :name => "Shop")
16   - @project.add_access(@user, :admin)
17   - end
18   -
19 15 Given 'I search for "Contibuting"' do
20 16 fill_in "dashboard_search", with: "Contibuting"
21 17 click_button "Search"
... ...
features/steps/group/group.rb
... ... @@ -13,7 +13,7 @@ class Groups &lt; Spinach::FeatureSteps
13 13 @project = create(:project, group: @group)
14 14 @event = create(:closed_issue_event, project: @project)
15 15  
16   - @project.add_access current_user, :admin
  16 + @project.team << [current_user, :master]
17 17 end
18 18  
19 19 And 'I should see projects activity feed' do
... ...
features/steps/project/create_project.rb
... ... @@ -3,13 +3,13 @@ class CreateProject &lt; Spinach::FeatureSteps
3 3 include SharedPaths
4 4  
5 5 And 'fill project form with valid data' do
6   - fill_in 'project_name', :with => 'NewProject'
  6 + fill_in 'project_name', with: 'Empty'
7 7 click_button "Create project"
8 8 end
9 9  
10 10 Then 'I should see project page' do
11 11 current_path.should == project_path(Project.last)
12   - page.should have_content "NewProject"
  12 + page.should have_content "Empty"
13 13 end
14 14  
15 15 And 'I should see empty project instuctions' do
... ...
features/steps/project/project_browse_commits.rb
... ... @@ -4,7 +4,7 @@ class ProjectBrowseCommits &lt; Spinach::FeatureSteps
4 4 include SharedPaths
5 5  
6 6 Then 'I see project commits' do
7   - commit = @project.commit
  7 + commit = @project.repository.commit
8 8 page.should have_content(@project.name)
9 9 page.should have_content(commit.message)
10 10 page.should have_content(commit.id.to_s[0..5])
... ... @@ -15,7 +15,7 @@ class ProjectBrowseCommits &lt; Spinach::FeatureSteps
15 15 end
16 16  
17 17 Then 'I see commits atom feed' do
18   - commit = CommitDecorator.decorate(@project.commit)
  18 + commit = CommitDecorator.decorate(@project.repository.commit)
19 19 page.response_headers['Content-Type'].should have_content("application/atom+xml")
20 20 page.body.should have_selector("title", :text => "Recent commits to #{@project.name}")
21 21 page.body.should have_selector("author email", :text => commit.author_email)
... ... @@ -48,7 +48,7 @@ class ProjectBrowseCommits &lt; Spinach::FeatureSteps
48 48 page.should have_selector('ul.breadcrumb span.divider', count: 3)
49 49 page.should have_selector('ul.breadcrumb a', count: 4)
50 50  
51   - find('ul.breadcrumb li:first a')['href'].should match(/#{@project.path}\/commits\/master\z/)
  51 + find('ul.breadcrumb li:first a')['href'].should match(/#{@project.path_with_namespace}\/commits\/master\z/)
52 52 find('ul.breadcrumb li:last a')['href'].should match(%r{master/app/models/project\.rb\z})
53 53 end
54 54  
... ...
features/steps/project/project_team_management.rb
... ... @@ -84,18 +84,18 @@ class ProjectTeamManagement &lt; Spinach::FeatureSteps
84 84 And '"Sam" is "Shop" developer' do
85 85 user = User.find_by_name("Sam")
86 86 project = Project.find_by_name("Shop")
87   - project.add_access(user, :write)
  87 + project.team << [user, :developer]
88 88 end
89 89  
90 90 Given 'I own project "Website"' do
91 91 @project = create(:project, :name => "Website")
92   - @project.add_access(@user, :admin)
  92 + @project.team << [@user, :master]
93 93 end
94 94  
95 95 And '"Mike" is "Website" reporter' do
96 96 user = User.find_by_name("Mike")
97 97 project = Project.find_by_name("Website")
98   - project.add_access(user, :read)
  98 + project.team << [user, :reporter]
99 99 end
100 100  
101 101 And 'I click link "Import team from another project"' do
... ...
features/steps/shared/paths.rb
... ... @@ -114,15 +114,15 @@ module SharedPaths
114 114 end
115 115  
116 116 Given "I visit my project's files page" do
117   - visit project_tree_path(@project, @project.root_ref)
  117 + visit project_tree_path(@project, root_ref)
118 118 end
119 119  
120 120 Given "I visit my project's commits page" do
121   - visit project_commits_path(@project, @project.root_ref, {limit: 5})
  121 + visit project_commits_path(@project, root_ref, {limit: 5})
122 122 end
123 123  
124 124 Given "I visit my project's commits page for a specific path" do
125   - visit project_commits_path(@project, @project.root_ref + "/app/models/project.rb", {limit: 5})
  125 + visit project_commits_path(@project, root_ref + "/app/models/project.rb", {limit: 5})
126 126 end
127 127  
128 128 Given 'I visit my project\'s commits stats page' do
... ... @@ -174,7 +174,7 @@ module SharedPaths
174 174 end
175 175  
176 176 Given 'I visit project commits page' do
177   - visit project_commits_path(@project, @project.root_ref, {limit: 5})
  177 + visit project_commits_path(@project, root_ref, {limit: 5})
178 178 end
179 179  
180 180 Given 'I visit project commits page for stable branch' do
... ... @@ -182,7 +182,7 @@ module SharedPaths
182 182 end
183 183  
184 184 Given 'I visit project source page' do
185   - visit project_tree_path(@project, @project.root_ref)
  185 + visit project_tree_path(@project, root_ref)
186 186 end
187 187  
188 188 Given 'I visit blob file from repo' do
... ... @@ -240,4 +240,8 @@ module SharedPaths
240 240 Given 'I visit project wiki page' do
241 241 visit project_wiki_path(@project, :index)
242 242 end
  243 +
  244 + def root_ref
  245 + @project.repository.root_ref
  246 + end
243 247 end
... ...
features/steps/shared/project.rb
... ... @@ -4,13 +4,13 @@ module SharedProject
4 4 # Create a project without caring about what it's called
5 5 And "I own a project" do
6 6 @project = create(:project)
7   - @project.add_access(@user, :admin)
  7 + @project.team << [@user, :master]
8 8 end
9 9  
10 10 # Create a specific project called "Shop"
11 11 And 'I own project "Shop"' do
12   - @project = create(:project, :name => "Shop")
13   - @project.add_access(@user, :admin)
  12 + @project = create(:project, name: "Shop")
  13 + @project.team << [@user, :master]
14 14 end
15 15  
16 16 def current_project
... ...
lib/api/notes.rb
... ... @@ -13,7 +13,7 @@ module Gitlab
13 13 # Example Request:
14 14 # GET /projects/:id/notes
15 15 get ":id/notes" do
16   - @notes = user_project.common_notes
  16 + @notes = user_project.notes.common
17 17 present paginate(@notes), with: Entities::Note
18 18 end
19 19  
... ... @@ -25,7 +25,7 @@ module Gitlab
25 25 # Example Request:
26 26 # GET /projects/:id/notes/:note_id
27 27 get ":id/notes/:note_id" do
28   - @note = user_project.common_notes.find(params[:note_id])
  28 + @note = user_project.notes.common.find(params[:note_id])
29 29 present @note, with: Entities::Note
30 30 end
31 31  
... ...
lib/api/projects.rb
... ... @@ -257,7 +257,7 @@ module Gitlab
257 257 per_page = params[:per_page] || 20
258 258 ref = params[:ref_name] || user_project.try(:default_branch) || 'master'
259 259  
260   - commits = user_project.commits(ref, nil, per_page, page * per_page)
  260 + commits = user_project.repository.commits(ref, nil, per_page, page * per_page)
261 261 present CommitDecorator.decorate(commits), with: Entities::RepoCommit
262 262 end
263 263  
... ... @@ -375,10 +375,10 @@ module Gitlab
375 375  
376 376 ref = params[:sha]
377 377  
378   - commit = user_project.commit ref
  378 + commit = user_project.repository.commit ref
379 379 not_found! "Commit" unless commit
380 380  
381   - tree = Tree.new commit.tree, user_project, ref, params[:filepath]
  381 + tree = Tree.new commit.tree, ref, params[:filepath]
382 382 not_found! "File" unless tree.try(:tree)
383 383  
384 384 content_type tree.mime_type
... ...
lib/extracts_path.rb
... ... @@ -68,7 +68,7 @@ module ExtractsPath
68 68 id = input
69 69 id += '/' unless id.ends_with?('/')
70 70  
71   - valid_refs = @project.ref_names
  71 + valid_refs = @project.repository.ref_names
72 72 valid_refs.select! { |v| id.start_with?("#{v}/") }
73 73  
74 74 if valid_refs.length != 1
... ... @@ -114,9 +114,9 @@ module ExtractsPath
114 114  
115 115 @id = File.join(@ref, @path)
116 116  
117   - @commit = CommitDecorator.decorate(@project.commit(@ref))
  117 + @commit = CommitDecorator.decorate(@project.repository.commit(@ref))
118 118  
119   - @tree = Tree.new(@commit.tree, @project, @ref, @path)
  119 + @tree = Tree.new(@commit.tree, @ref, @path)
120 120 @tree = TreeDecorator.new(@tree)
121 121  
122 122 raise InvalidPathError if @tree.invalid?
... ...
lib/gitlab/backend/gitolite_config.rb
... ... @@ -82,7 +82,7 @@ module Gitlab
82 82 end
83 83  
84 84 def destroy_project(project)
85   - FileUtils.rm_rf(project.path_to_repo)
  85 + FileUtils.rm_rf(project.repository.path_to_repo)
86 86 conf.rm_repo(project.path_with_namespace)
87 87 end
88 88  
... ... @@ -138,9 +138,9 @@ module Gitlab
138 138 ::Gitolite::Config::Repo.new(repo_name)
139 139 end
140 140  
141   - name_readers = project.repository_readers
142   - name_writers = project.repository_writers
143   - name_masters = project.repository_masters
  141 + name_readers = project.team.repository_readers
  142 + name_writers = project.team.repository_writers
  143 + name_masters = project.team.repository_masters
144 144  
145 145 pr_br = project.protected_branches.map(&:name).join("$ ")
146 146  
... ...
lib/gitlab/markdown.rb
... ... @@ -170,7 +170,7 @@ module Gitlab
170 170 end
171 171  
172 172 def reference_commit(identifier)
173   - if @project.valid_repo? && commit = @project.commit(identifier)
  173 + if @project.valid_repo? && commit = @project.repository.commit(identifier)
174 174 link_to(identifier, project_commit_path(@project, commit), html_options.merge(title: CommitDecorator.new(commit).link_title, class: "gfm gfm-commit #{html_options[:class]}"))
175 175 end
176 176 end
... ...
lib/gitlab/satellite/merge_action.rb
... ... @@ -31,7 +31,7 @@ module Gitlab
31 31 merge_repo.git.push({raise: true, timeout: true}, :origin, merge_request.target_branch)
32 32  
33 33 # remove source branch
34   - if merge_request.should_remove_source_branch && !project.root_ref?(merge_request.source_branch)
  34 + if merge_request.should_remove_source_branch && !project.repository.root_ref?(merge_request.source_branch)
35 35 # will raise CommandFailed when push fails
36 36 merge_repo.git.push({raise: true, timeout: true}, :origin, ":#{merge_request.source_branch}")
37 37 end
... ...
lib/static_model.rb
... ... @@ -38,7 +38,7 @@ module StaticModel
38 38 end
39 39  
40 40 def ==(other)
41   - if other.is_a? StaticModel
  41 + if other.is_a? ::StaticModel
42 42 id == other.id
43 43 else
44 44 super
... ...
spec/controllers/commit_controller_spec.rb
... ... @@ -3,12 +3,12 @@ require &#39;spec_helper&#39;
3 3 describe CommitController do
4 4 let(:project) { create(:project) }
5 5 let(:user) { create(:user) }
6   - let(:commit) { project.last_commit_for("master") }
  6 + let(:commit) { project.repository.last_commit_for("master") }
7 7  
8 8 before do
9 9 sign_in(user)
10 10  
11   - project.add_access(user, :read, :admin)
  11 + project.team << [user, :master]
12 12 end
13 13  
14 14 describe "#show" do
... ...
spec/controllers/commits_controller_spec.rb
... ... @@ -7,7 +7,7 @@ describe CommitsController do
7 7 before do
8 8 sign_in(user)
9 9  
10   - project.add_access(user, :read, :admin)
  10 + project.team << [user, :master]
11 11 end
12 12  
13 13 describe "GET show" do
... ...
spec/controllers/merge_requests_controller_spec.rb
... ... @@ -7,7 +7,7 @@ describe MergeRequestsController do
7 7  
8 8 before do
9 9 sign_in(user)
10   - project.add_access(user, :read, :admin)
  10 + project.team << [user, :master]
11 11 MergeRequestsController.any_instance.stub(validates_merge_request: true)
12 12 end
13 13  
... ...
spec/controllers/tree_controller_spec.rb
... ... @@ -7,7 +7,7 @@ describe TreeController do
7 7 before do
8 8 sign_in(user)
9 9  
10   - project.add_access(user, :read, :admin)
  10 + project.team << [user, :master]
11 11  
12 12 project.stub(:branches).and_return(['master', 'foo/bar/baz'])
13 13 project.stub(:tags).and_return(['v1.0.0', 'v2.0.0'])
... ...