Commit 39ba934c0a65f571214998e056e925b61f389360

Authored by Dmitriy Zaporozhets
1 parent e6c0673e

REpostiry, Team models

.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
... ...
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/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
... ... @@ -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/controllers/application_controller.rb
... ... @@ -76,6 +76,12 @@ class ApplicationController < 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/project_resource_controller.rb
1 1 class ProjectResourceController < ApplicationController
2 2 before_filter :project
  3 + before_filter :repository
3 4 end
... ...
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/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
... ... @@ -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 -
... ... @@ -103,12 +105,12 @@ module ApplicationHelper
103 105 if @project && !@project.new_record?
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 ]
... ...
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/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
... ... @@ -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)
... ...
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
... ...
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)) }
... ...
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,14 @@ 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 + @repository ||= Repository.new(path_with_namespace, default_branch)
  170 + end
  171 +
165 172 def git_error?
166 173 error_code == :gitolite
167 174 end
... ... @@ -198,10 +205,6 @@ class Project &lt; ActiveRecord::Base
198 205 [Gitlab.config.gitlab.url, path_with_namespace].join("/")
199 206 end
200 207  
201   - def common_notes
202   - notes.where(noteable_type: ["", nil]).inc_author_project
203   - end
204   -
205 208 def build_commit_note(commit)
206 209 notes.new(commit_id: commit.id, noteable_type: "Commit")
207 210 end
... ... @@ -214,14 +217,6 @@ class Project &lt; ActiveRecord::Base
214 217 notes.where(commit_id: commit.id, noteable_type: "Commit").where("line_code IS NOT NULL")
215 218 end
216 219  
217   - def public?
218   - !private_flag
219   - end
220   -
221   - def private?
222   - private_flag
223   - end
224   -
225 220 def last_activity
226 221 last_event
227 222 end
... ... @@ -284,33 +279,6 @@ class Project &lt; ActiveRecord::Base
284 279 users_projects.find_by_user_id(user_id)
285 280 end
286 281  
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 282 # Update multiple project users
315 283 # to same access role by user ids
316 284 def update_users_ids_to_role(users_ids, access_role)
... ... @@ -322,30 +290,6 @@ class Project &lt; ActiveRecord::Base
322 290 UsersProject.bulk_delete(self, users_ids)
323 291 end
324 292  
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 293 def repository_readers
350 294 repository_members[UsersProject::REPORTER]
351 295 end
... ... @@ -368,26 +312,6 @@ class Project &lt; ActiveRecord::Base
368 312 keys
369 313 end
370 314  
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 315 def transfer(new_namespace)
392 316 Project.transaction do
393 317 old_namespace = namespace
... ... @@ -586,97 +510,21 @@ class Project &lt; ActiveRecord::Base
586 510 end
587 511  
588 512 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)
  513 + !repository || repository.empty_repo?
618 514 end
619 515  
620 516 def satellite
621 517 @satellite ||= Gitlab::Satellite::Satellite.new(self)
622 518 end
623 519  
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 520 def repo
669   - @repo ||= Grit::Repo.new(path_to_repo)
  521 + repository.raw
670 522 end
671 523  
672 524 def url_to_repo
673 525 gitolite.url_to_repo(path_with_namespace)
674 526 end
675 527  
676   - def path_to_repo
677   - File.join(Gitlab.config.gitolite.repos_path, "#{path_with_namespace}.git")
678   - end
679   -
680 528 def namespace_dir
681 529 namespace.try(:path) || ''
682 530 end
... ... @@ -690,21 +538,11 @@ class Project &lt; ActiveRecord::Base
690 538 end
691 539  
692 540 def repo_exists?
693   - @repo_exists ||= (repo && !repo.branches.empty?)
  541 + @repo_exists ||= (repository && repository.branches.present?)
694 542 rescue
695 543 @repo_exists = false
696 544 end
697 545  
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 546 def open_branches
709 547 if protected_branches.empty?
710 548 self.repo.heads
... ... @@ -714,61 +552,8 @@ class Project &lt; ActiveRecord::Base
714 552 end.sort_by(&:name)
715 553 end
716 554  
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 555 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
  556 + repository.root_ref == branch
772 557 end
773 558  
774 559 def ssh_url_to_repo
... ...
app/models/repository.rb 0 → 100644
... ... @@ -0,0 +1,163 @@
  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
  17 + @path_with_namespace = path_with_namespace
  18 + @repo = Grit::Repo.new(path_to_repo)
  19 + end
  20 +
  21 + def raw
  22 + repo
  23 + end
  24 +
  25 + def path_to_repo
  26 + @path_to_repo ||= File.join(Gitlab.config.gitolite.repos_path, "#{path_with_namespace}.git")
  27 + end
  28 +
  29 + def commit(commit_id = nil)
  30 + Commit.find_or_first(repo, commit_id, root_ref)
  31 + end
  32 +
  33 + def fresh_commits(n = 10)
  34 + Commit.fresh_commits(repo, n)
  35 + end
  36 +
  37 + def commits_with_refs(n = 20)
  38 + Commit.commits_with_refs(repo, n)
  39 + end
  40 +
  41 + def commits_since(date)
  42 + Commit.commits_since(repo, date)
  43 + end
  44 +
  45 + def commits(ref, path = nil, limit = nil, offset = nil)
  46 + Commit.commits(repo, ref, path, limit, offset)
  47 + end
  48 +
  49 + def last_commit_for(ref, path = nil)
  50 + commits(ref, path, 1).first
  51 + end
  52 +
  53 + def commits_between(from, to)
  54 + Commit.commits_between(repo, from, to)
  55 + end
  56 +
  57 + def has_post_receive_file?
  58 + !!hook_file
  59 + end
  60 +
  61 + def valid_post_receive_file?
  62 + valid_hook_file == hook_file
  63 + end
  64 +
  65 + def valid_hook_file
  66 + @valid_hook_file ||= File.read(Rails.root.join('lib', 'hooks', 'post-receive'))
  67 + end
  68 +
  69 + def hook_file
  70 + @hook_file ||= begin
  71 + hook_path = File.join(path_to_repo, 'hooks', 'post-receive')
  72 + File.read(hook_path) if File.exists?(hook_path)
  73 + end
  74 + end
  75 +
  76 + # Returns an Array of branch names
  77 + def branch_names
  78 + repo.branches.collect(&:name).sort
  79 + end
  80 +
  81 + # Returns an Array of Branches
  82 + def branches
  83 + repo.branches.sort_by(&:name)
  84 + end
  85 +
  86 + # Returns an Array of tag names
  87 + def tag_names
  88 + repo.tags.collect(&:name).sort.reverse
  89 + end
  90 +
  91 + # Returns an Array of Tags
  92 + def tags
  93 + repo.tags.sort_by(&:name).reverse
  94 + end
  95 +
  96 + # Returns an Array of branch and tag names
  97 + def ref_names
  98 + [branch_names + tag_names].flatten
  99 + end
  100 +
  101 + def heads
  102 + @heads ||= repo.heads
  103 + end
  104 +
  105 + def tree(fcommit, path = nil)
  106 + fcommit = commit if fcommit == :head
  107 + tree = fcommit.tree
  108 + path ? (tree / path) : tree
  109 + end
  110 +
  111 + def has_commits?
  112 + !!commit
  113 + rescue Grit::NoSuchPathError
  114 + false
  115 + end
  116 +
  117 + def empty_repo?
  118 + !has_commits?
  119 + end
  120 +
  121 + # Discovers the default branch based on the repository's available branches
  122 + #
  123 + # - If no branches are present, returns nil
  124 + # - If one branch is present, returns its name
  125 + # - If two or more branches are present, returns the one that has a name
  126 + # matching root_ref (default_branch or 'master' if default_branch is nil)
  127 + def discover_default_branch
  128 + if branch_names.length == 0
  129 + nil
  130 + elsif branch_names.length == 1
  131 + branch_names.first
  132 + else
  133 + branch_names.select { |v| v == root_ref }.first
  134 + end
  135 + end
  136 +
  137 + # Archive Project to .tar.gz
  138 + #
  139 + # Already packed repo archives stored at
  140 + # app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz
  141 + #
  142 + def archive_repo(ref)
  143 + ref = ref || self.root_ref
  144 + commit = self.commit(ref)
  145 + return nil unless commit
  146 +
  147 + # Build file path
  148 + file_name = self.path + "-" + commit.id.to_s + ".tar.gz"
  149 + storage_path = Rails.root.join("tmp", "repositories", self.path_with_namespace)
  150 + file_path = File.join(storage_path, file_name)
  151 +
  152 + # Put files into a directory before archiving
  153 + prefix = self.path + "/"
  154 +
  155 + # Create file if not exists
  156 + unless File.exists?(file_path)
  157 + FileUtils.mkdir_p storage_path
  158 + file = self.repo.archive_to_file(ref, prefix, file_path)
  159 + end
  160 +
  161 + file_path
  162 + end
  163 +end
... ...
app/models/team.rb 0 → 100644
... ... @@ -0,0 +1,49 @@
  1 +class Team
  2 + attr_accessor :project
  3 +
  4 + def initialize(project)
  5 + @project = project
  6 + @roles = UsersProject.roles_hash
  7 + end
  8 +
  9 + def add_user(user, access)
  10 + add_users_ids([user.id], access)
  11 + end
  12 +
  13 + def add_users(users, access)
  14 + add_users_ids(users.map(&:id), access)
  15 + end
  16 +
  17 + def add_users_ids(users_ids, access)
  18 + UsersProject.add_users_into_projects(
  19 + [project.id],
  20 + user_ids,
  21 + access
  22 + )
  23 + end
  24 +
  25 + # Remove all users from project team
  26 + def truncate
  27 + UsersProject.truncate_team(project)
  28 + end
  29 +
  30 + def members
  31 + project.users_projects
  32 + end
  33 +
  34 + def guests
  35 + members.guests.map(&:user)
  36 + end
  37 +
  38 + def reporters
  39 + members.reporters.map(&:user)
  40 + end
  41 +
  42 + def developers
  43 + members.developers.map(&:user)
  44 + end
  45 +
  46 + def masters
  47 + members.masters.map(&:user)
  48 + end
  49 +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/users_project.rb
... ... @@ -42,7 +42,21 @@ 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 + def add_users_into_projects(project_ids, user_ids, access)
  52 + project_access = if @roles.has_key?(access)
  53 + @roles[access]
  54 + elsif @roles.values.include?(access)
  55 + access
  56 + else
  57 + raise "Non valid access"
  58 + end
  59 +
46 60 UsersProject.transaction do
47 61 project_ids.each do |project_id|
48 62 user_ids.each do |user_id|
... ... @@ -141,6 +155,15 @@ class UsersProject &lt; ActiveRecord::Base
141 155 add_users_into_projects(project_ids, [user.id], project_access)
142 156 end
143 157  
  158 + def roles_hash
  159 + {
  160 + guest: GUEST,
  161 + reporter: REPORTER,
  162 + developer: DEVELOPER,
  163 + master: MASTER
  164 + }
  165 + end
  166 +
144 167 def access_roles
145 168 {
146 169 "Guest" => GUEST,
... ...
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/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/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/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/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
... ...
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?
... ...
spec/models/note_spec.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 'spec_helper'
... ...
spec/models/project_spec.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
... ...