Commit 88d9569a33a3c66ed34db45c9b6cf4e04ea0fcf3

Authored by randx
1 parent bae4efa7

Project model refactored. Modularity gem

Gemfile
... ... @@ -34,6 +34,7 @@ gem "omniauth-ldap"
34 34 gem 'bootstrap-sass', "1.4.4"
35 35 gem "colored"
36 36 gem 'yaml_db', :git => "https://github.com/gitlabhq/yaml_db.git"
  37 +gem 'modularity'
37 38  
38 39 group :assets do
39 40 gem "sass-rails", "3.2.3"
... ...
Gemfile.lock
... ... @@ -149,6 +149,7 @@ GEM
149 149 treetop (~> 1.4.8)
150 150 method_source (0.7.0)
151 151 mime-types (1.17.2)
  152 + modularity (0.6.1)
152 153 multi_json (1.0.4)
153 154 multi_xml (0.4.1)
154 155 mysql2 (0.3.11)
... ... @@ -326,6 +327,7 @@ DEPENDENCIES
326 327 kaminari
327 328 launchy
328 329 letter_opener
  330 + modularity
329 331 mysql2
330 332 omniauth-ldap
331 333 pry
... ...
app/models/project.rb
... ... @@ -3,6 +3,11 @@ require "grit"
3 3 class Project < ActiveRecord::Base
4 4 belongs_to :owner, :class_name => "User"
5 5  
  6 + does "project/validations"
  7 + does "project/repository"
  8 + does "project/permissions"
  9 + does "project/hooks"
  10 +
6 11 has_many :users, :through => :users_projects
7 12 has_many :events, :dependent => :destroy
8 13 has_many :merge_requests, :dependent => :destroy
... ... @@ -15,32 +20,6 @@ class Project &lt; ActiveRecord::Base
15 20 has_many :wikis, :dependent => :destroy
16 21 has_many :protected_branches, :dependent => :destroy
17 22  
18   - validates :name,
19   - :uniqueness => true,
20   - :presence => true,
21   - :length => { :within => 0..255 }
22   -
23   - validates :path,
24   - :uniqueness => true,
25   - :presence => true,
26   - :format => { :with => /^[a-zA-Z0-9_\-\.]*$/,
27   - :message => "only letters, digits & '_' '-' '.' allowed" },
28   - :length => { :within => 0..255 }
29   -
30   - validates :description,
31   - :length => { :within => 0..2000 }
32   -
33   - validates :code,
34   - :presence => true,
35   - :uniqueness => true,
36   - :format => { :with => /^[a-zA-Z0-9_\-\.]*$/,
37   - :message => "only letters, digits & '_' '-' '.' allowed" },
38   - :length => { :within => 3..255 }
39   -
40   - validates :owner, :presence => true
41   - validate :check_limit
42   - validate :repo_name
43   -
44 23 attr_protected :private_flag, :owner_id
45 24  
46 25 scope :public_only, where(:private_flag => false)
... ... @@ -66,89 +45,6 @@ class Project &lt; ActiveRecord::Base
66 45 [GIT_HOST['host'], code].join("/")
67 46 end
68 47  
69   - def observe_push(oldrev, newrev, ref, author_key_id)
70   - data = web_hook_data(oldrev, newrev, ref, author_key_id)
71   -
72   - Event.create(
73   - :project => self,
74   - :action => Event::Pushed,
75   - :data => data,
76   - :author_id => data[:user_id]
77   - )
78   - end
79   -
80   - def update_merge_requests(oldrev, newrev, ref, author_key_id)
81   - return true unless ref =~ /heads/
82   - branch_name = ref.gsub("refs/heads/", "")
83   - user = Key.find_by_identifier(author_key_id).user
84   - c_ids = self.commits_between(oldrev, newrev).map(&:id)
85   -
86   - # Update code for merge requests
87   - mrs = self.merge_requests.opened.find_all_by_branch(branch_name).all
88   - mrs.each { |merge_request| merge_request.reload_code }
89   -
90   - # Close merge requests
91   - mrs = self.merge_requests.opened.where(:target_branch => branch_name).all
92   - mrs = mrs.select(&:last_commit).select { |mr| c_ids.include?(mr.last_commit.id) }
93   - mrs.each { |merge_request| merge_request.merge!(user.id) }
94   -
95   - true
96   - end
97   -
98   - def execute_web_hooks(oldrev, newrev, ref, author_key_id)
99   - ref_parts = ref.split('/')
100   -
101   - # Return if this is not a push to a branch (e.g. new commits)
102   - return if ref_parts[1] !~ /heads/ || oldrev == "00000000000000000000000000000000"
103   -
104   - data = web_hook_data(oldrev, newrev, ref, author_key_id)
105   -
106   - web_hooks.each { |web_hook| web_hook.execute(data) }
107   - end
108   -
109   - def web_hook_data(oldrev, newrev, ref, author_key_id)
110   - key = Key.find_by_identifier(author_key_id)
111   - data = {
112   - before: oldrev,
113   - after: newrev,
114   - ref: ref,
115   - user_id: key.user.id,
116   - user_name: key.user_name,
117   - repository: {
118   - name: name,
119   - url: web_url,
120   - description: description,
121   - homepage: web_url,
122   - private: private?
123   - },
124   - commits: []
125   - }
126   -
127   - commits_between(oldrev, newrev).each do |commit|
128   - data[:commits] << {
129   - id: commit.id,
130   - message: commit.safe_message,
131   - timestamp: commit.date.xmlschema,
132   - url: "http://#{GIT_HOST['host']}/#{code}/commits/#{commit.id}",
133   - author: {
134   - name: commit.author_name,
135   - email: commit.author_email
136   - }
137   - }
138   - end
139   -
140   - data
141   - end
142   -
143   - def open_branches
144   - if protected_branches.empty?
145   - self.repo.heads
146   - else
147   - pnames = protected_branches.map(&:name)
148   - self.repo.heads.reject { |h| pnames.include?(h.name) }
149   - end.sort_by(&:name)
150   - end
151   -
152 48 def team_member_by_name_or_email(email = nil, name = nil)
153 49 user = users.where("email like ? or name like ?", email, name).first
154 50 users_projects.find_by_user_id(user.id) if user
... ... @@ -174,71 +70,6 @@ class Project &lt; ActiveRecord::Base
174 70 notes.where(:noteable_id => commit.id, :noteable_type => "Commit").where("line_code is not null")
175 71 end
176 72  
177   - def has_commits?
178   - !!commit
179   - end
180   -
181   - # Compatible with all access rights
182   - # Should be rewrited for new access rights
183   - def add_access(user, *access)
184   - access = if access.include?(:admin)
185   - { :project_access => UsersProject::MASTER }
186   - elsif access.include?(:write)
187   - { :project_access => UsersProject::DEVELOPER }
188   - else
189   - { :project_access => UsersProject::REPORTER }
190   - end
191   - opts = { :user => user }
192   - opts.merge!(access)
193   - users_projects.create(opts)
194   - end
195   -
196   - def reset_access(user)
197   - users_projects.where(:project_id => self.id, :user_id => user.id).destroy if self.id
198   - end
199   -
200   - def repository_readers
201   - keys = Key.joins({:user => :users_projects}).
202   - where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::REPORTER)
203   - keys.map(&:identifier) + deploy_keys.map(&:identifier)
204   - end
205   -
206   - def repository_writers
207   - keys = Key.joins({:user => :users_projects}).
208   - where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::DEVELOPER)
209   - keys.map(&:identifier)
210   - end
211   -
212   - def repository_masters
213   - keys = Key.joins({:user => :users_projects}).
214   - where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::MASTER)
215   - keys.map(&:identifier)
216   - end
217   -
218   - def allow_read_for?(user)
219   - !users_projects.where(:user_id => user.id).empty?
220   - end
221   -
222   - def guest_access_for?(user)
223   - !users_projects.where(:user_id => user.id).empty?
224   - end
225   -
226   - def report_access_for?(user)
227   - !users_projects.where(:user_id => user.id, :project_access => [UsersProject::REPORTER, UsersProject::DEVELOPER, UsersProject::MASTER]).empty?
228   - end
229   -
230   - def dev_access_for?(user)
231   - !users_projects.where(:user_id => user.id, :project_access => [UsersProject::DEVELOPER, UsersProject::MASTER]).empty?
232   - end
233   -
234   - def master_access_for?(user)
235   - !users_projects.where(:user_id => user.id, :project_access => [UsersProject::MASTER]).empty? || owner_id == user.id
236   - end
237   -
238   - def root_ref
239   - default_branch || "master"
240   - end
241   -
242 73 def public?
243 74 !private_flag
244 75 end
... ... @@ -259,112 +90,9 @@ class Project &lt; ActiveRecord::Base
259 90 end
260 91 end
261 92  
262   - def check_limit
263   - unless owner.can_create_project?
264   - errors[:base] << ("Your own projects limit is #{owner.projects_limit}! Please contact administrator to increase it")
265   - end
266   - rescue
267   - errors[:base] << ("Cant check your ability to create project")
268   - end
269   -
270   - def repo_name
271   - if path == "gitolite-admin"
272   - errors.add(:path, " like 'gitolite-admin' is not allowed")
273   - end
274   - end
275   -
276   - def valid_repo?
277   - repo
278   - rescue
279   - errors.add(:path, "Invalid repository path")
280   - false
281   - end
282   -
283   - def commit(commit_id = nil)
284   - Commit.find_or_first(repo, commit_id)
285   - end
286   -
287   - def fresh_commits(n = 10)
288   - Commit.fresh_commits(repo, n)
289   - end
290   -
291   - def commits_with_refs(n = 20)
292   - Commit.commits_with_refs(repo, n)
293   - end
294   -
295   - def commits_since(date)
296   - Commit.commits_since(repo, date)
297   - end
298   -
299   - def commits(ref, path = nil, limit = nil, offset = nil)
300   - Commit.commits(repo, ref, path, limit, offset)
301   - end
302   -
303   - def commits_between(from, to)
304   - Commit.commits_between(repo, from, to)
305   - end
306   -
307 93 def project_id
308 94 self.id
309 95 end
310   -
311   - def write_hooks
312   - %w(post-receive).each do |hook|
313   - write_hook(hook, File.read(File.join(Rails.root, 'lib', "#{hook}-hook")))
314   - end
315   - end
316   -
317   - def write_hook(name, content)
318   - hook_file = File.join(path_to_repo, 'hooks', name)
319   -
320   - File.open(hook_file, 'w') do |f|
321   - f.write(content)
322   - end
323   -
324   - File.chmod(0775, hook_file)
325   - end
326   -
327   - def repo
328   - @repo ||= Grit::Repo.new(path_to_repo)
329   - end
330   -
331   - def url_to_repo
332   - Gitlabhq::GitHost.url_to_repo(path)
333   - end
334   -
335   - def path_to_repo
336   - File.join(GIT_HOST["base_path"], "#{path}.git")
337   - end
338   -
339   - def update_repository
340   - Gitlabhq::GitHost.system.update_project(path, self)
341   -
342   - write_hooks if File.exists?(path_to_repo)
343   - end
344   -
345   - def destroy_repository
346   - Gitlabhq::GitHost.system.destroy_project(self)
347   - end
348   -
349   - def repo_exists?
350   - @repo_exists ||= (repo && !repo.branches.empty?)
351   - rescue
352   - @repo_exists = false
353   - end
354   -
355   - def tags
356   - repo.tags.map(&:name).sort.reverse
357   - end
358   -
359   - def heads
360   - @heads ||= repo.heads
361   - end
362   -
363   - def tree(fcommit, path = nil)
364   - fcommit = commit if fcommit == :head
365   - tree = fcommit.tree
366   - path ? (tree / path) : tree
367   - end
368 96 end
369 97  
370 98 # == Schema Information
... ...
app/models/project/hooks_trait.rb 0 → 100644
... ... @@ -0,0 +1,77 @@
  1 +module Project::HooksTrait
  2 + as_trait do
  3 + def observe_push(oldrev, newrev, ref, author_key_id)
  4 + data = web_hook_data(oldrev, newrev, ref, author_key_id)
  5 +
  6 + Event.create(
  7 + :project => self,
  8 + :action => Event::Pushed,
  9 + :data => data,
  10 + :author_id => data[:user_id]
  11 + )
  12 + end
  13 +
  14 + def update_merge_requests(oldrev, newrev, ref, author_key_id)
  15 + return true unless ref =~ /heads/
  16 + branch_name = ref.gsub("refs/heads/", "")
  17 + user = Key.find_by_identifier(author_key_id).user
  18 + c_ids = self.commits_between(oldrev, newrev).map(&:id)
  19 +
  20 + # Update code for merge requests
  21 + mrs = self.merge_requests.opened.find_all_by_branch(branch_name).all
  22 + mrs.each { |merge_request| merge_request.reload_code }
  23 +
  24 + # Close merge requests
  25 + mrs = self.merge_requests.opened.where(:target_branch => branch_name).all
  26 + mrs = mrs.select(&:last_commit).select { |mr| c_ids.include?(mr.last_commit.id) }
  27 + mrs.each { |merge_request| merge_request.merge!(user.id) }
  28 +
  29 + true
  30 + end
  31 +
  32 + def execute_web_hooks(oldrev, newrev, ref, author_key_id)
  33 + ref_parts = ref.split('/')
  34 +
  35 + # Return if this is not a push to a branch (e.g. new commits)
  36 + return if ref_parts[1] !~ /heads/ || oldrev == "00000000000000000000000000000000"
  37 +
  38 + data = web_hook_data(oldrev, newrev, ref, author_key_id)
  39 +
  40 + web_hooks.each { |web_hook| web_hook.execute(data) }
  41 + end
  42 +
  43 + def web_hook_data(oldrev, newrev, ref, author_key_id)
  44 + key = Key.find_by_identifier(author_key_id)
  45 + data = {
  46 + before: oldrev,
  47 + after: newrev,
  48 + ref: ref,
  49 + user_id: key.user.id,
  50 + user_name: key.user_name,
  51 + repository: {
  52 + name: name,
  53 + url: web_url,
  54 + description: description,
  55 + homepage: web_url,
  56 + private: private?
  57 + },
  58 + commits: []
  59 + }
  60 +
  61 + commits_between(oldrev, newrev).each do |commit|
  62 + data[:commits] << {
  63 + id: commit.id,
  64 + message: commit.safe_message,
  65 + timestamp: commit.date.xmlschema,
  66 + url: "http://#{GIT_HOST['host']}/#{code}/commits/#{commit.id}",
  67 + author: {
  68 + name: commit.author_name,
  69 + email: commit.author_email
  70 + }
  71 + }
  72 + end
  73 +
  74 + data
  75 + end
  76 + end
  77 +end
... ...
app/models/project/permissions_trait.rb 0 → 100644
... ... @@ -0,0 +1,60 @@
  1 +module Project::PermissionsTrait
  2 + as_trait do
  3 + # Compatible with all access rights
  4 + # Should be rewrited for new access rights
  5 + def add_access(user, *access)
  6 + access = if access.include?(:admin)
  7 + { :project_access => UsersProject::MASTER }
  8 + elsif access.include?(:write)
  9 + { :project_access => UsersProject::DEVELOPER }
  10 + else
  11 + { :project_access => UsersProject::REPORTER }
  12 + end
  13 + opts = { :user => user }
  14 + opts.merge!(access)
  15 + users_projects.create(opts)
  16 + end
  17 +
  18 + def reset_access(user)
  19 + users_projects.where(:project_id => self.id, :user_id => user.id).destroy if self.id
  20 + end
  21 +
  22 + def repository_readers
  23 + keys = Key.joins({:user => :users_projects}).
  24 + where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::REPORTER)
  25 + keys.map(&:identifier) + deploy_keys.map(&:identifier)
  26 + end
  27 +
  28 + def repository_writers
  29 + keys = Key.joins({:user => :users_projects}).
  30 + where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::DEVELOPER)
  31 + keys.map(&:identifier)
  32 + end
  33 +
  34 + def repository_masters
  35 + keys = Key.joins({:user => :users_projects}).
  36 + where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::MASTER)
  37 + keys.map(&:identifier)
  38 + end
  39 +
  40 + def allow_read_for?(user)
  41 + !users_projects.where(:user_id => user.id).empty?
  42 + end
  43 +
  44 + def guest_access_for?(user)
  45 + !users_projects.where(:user_id => user.id).empty?
  46 + end
  47 +
  48 + def report_access_for?(user)
  49 + !users_projects.where(:user_id => user.id, :project_access => [UsersProject::REPORTER, UsersProject::DEVELOPER, UsersProject::MASTER]).empty?
  50 + end
  51 +
  52 + def dev_access_for?(user)
  53 + !users_projects.where(:user_id => user.id, :project_access => [UsersProject::DEVELOPER, UsersProject::MASTER]).empty?
  54 + end
  55 +
  56 + def master_access_for?(user)
  57 + !users_projects.where(:user_id => user.id, :project_access => [UsersProject::MASTER]).empty? || owner_id == user.id
  58 + end
  59 + end
  60 +end
... ...
app/models/project/repository_trait.rb 0 → 100644
... ... @@ -0,0 +1,109 @@
  1 +module Project::RepositoryTrait
  2 + as_trait do
  3 + def valid_repo?
  4 + repo
  5 + rescue
  6 + errors.add(:path, "Invalid repository path")
  7 + false
  8 + end
  9 +
  10 + def commit(commit_id = nil)
  11 + Commit.find_or_first(repo, commit_id)
  12 + end
  13 +
  14 + def fresh_commits(n = 10)
  15 + Commit.fresh_commits(repo, n)
  16 + end
  17 +
  18 + def commits_with_refs(n = 20)
  19 + Commit.commits_with_refs(repo, n)
  20 + end
  21 +
  22 + def commits_since(date)
  23 + Commit.commits_since(repo, date)
  24 + end
  25 +
  26 + def commits(ref, path = nil, limit = nil, offset = nil)
  27 + Commit.commits(repo, ref, path, limit, offset)
  28 + end
  29 +
  30 + def commits_between(from, to)
  31 + Commit.commits_between(repo, from, to)
  32 + end
  33 +
  34 + def write_hooks
  35 + %w(post-receive).each do |hook|
  36 + write_hook(hook, File.read(File.join(Rails.root, 'lib', "#{hook}-hook")))
  37 + end
  38 + end
  39 +
  40 + def write_hook(name, content)
  41 + hook_file = File.join(path_to_repo, 'hooks', name)
  42 +
  43 + File.open(hook_file, 'w') do |f|
  44 + f.write(content)
  45 + end
  46 +
  47 + File.chmod(0775, hook_file)
  48 + end
  49 +
  50 + def tags
  51 + repo.tags.map(&:name).sort.reverse
  52 + end
  53 +
  54 + def repo
  55 + @repo ||= Grit::Repo.new(path_to_repo)
  56 + end
  57 +
  58 + def url_to_repo
  59 + Gitlabhq::GitHost.url_to_repo(path)
  60 + end
  61 +
  62 + def path_to_repo
  63 + File.join(GIT_HOST["base_path"], "#{path}.git")
  64 + end
  65 +
  66 + def update_repository
  67 + Gitlabhq::GitHost.system.update_project(path, self)
  68 +
  69 + write_hooks if File.exists?(path_to_repo)
  70 + end
  71 +
  72 + def destroy_repository
  73 + Gitlabhq::GitHost.system.destroy_project(self)
  74 + end
  75 +
  76 + def repo_exists?
  77 + @repo_exists ||= (repo && !repo.branches.empty?)
  78 + rescue
  79 + @repo_exists = false
  80 + end
  81 +
  82 + def heads
  83 + @heads ||= repo.heads
  84 + end
  85 +
  86 + def tree(fcommit, path = nil)
  87 + fcommit = commit if fcommit == :head
  88 + tree = fcommit.tree
  89 + path ? (tree / path) : tree
  90 + end
  91 +
  92 + def open_branches
  93 + if protected_branches.empty?
  94 + self.repo.heads
  95 + else
  96 + pnames = protected_branches.map(&:name)
  97 + self.repo.heads.reject { |h| pnames.include?(h.name) }
  98 + end.sort_by(&:name)
  99 + end
  100 +
  101 + def has_commits?
  102 + !!commit
  103 + end
  104 +
  105 + def root_ref
  106 + default_branch || "master"
  107 + end
  108 + end
  109 +end
... ...
app/models/project/validations_trait.rb 0 → 100644
... ... @@ -0,0 +1,43 @@
  1 +module Project::ValidationsTrait
  2 + as_trait do
  3 + validates :name,
  4 + :uniqueness => true,
  5 + :presence => true,
  6 + :length => { :within => 0..255 }
  7 +
  8 + validates :path,
  9 + :uniqueness => true,
  10 + :presence => true,
  11 + :format => { :with => /^[a-zA-Z0-9_\-\.]*$/,
  12 + :message => "only letters, digits & '_' '-' '.' allowed" },
  13 + :length => { :within => 0..255 }
  14 +
  15 + validates :description,
  16 + :length => { :within => 0..2000 }
  17 +
  18 + validates :code,
  19 + :presence => true,
  20 + :uniqueness => true,
  21 + :format => { :with => /^[a-zA-Z0-9_\-\.]*$/,
  22 + :message => "only letters, digits & '_' '-' '.' allowed" },
  23 + :length => { :within => 3..255 }
  24 +
  25 + validates :owner, :presence => true
  26 + validate :check_limit
  27 + validate :repo_name
  28 +
  29 + def check_limit
  30 + unless owner.can_create_project?
  31 + errors[:base] << ("Your own projects limit is #{owner.projects_limit}! Please contact administrator to increase it")
  32 + end
  33 + rescue
  34 + errors[:base] << ("Cant check your ability to create project")
  35 + end
  36 +
  37 + def repo_name
  38 + if path == "gitolite-admin"
  39 + errors.add(:path, " like 'gitolite-admin' is not allowed")
  40 + end
  41 + end
  42 + end
  43 +end
... ...