Commit 88d9569a33a3c66ed34db45c9b6cf4e04ea0fcf3

Authored by randx
1 parent bae4efa7

Project model refactored. Modularity gem

@@ -34,6 +34,7 @@ gem "omniauth-ldap" @@ -34,6 +34,7 @@ gem "omniauth-ldap"
34 gem 'bootstrap-sass', "1.4.4" 34 gem 'bootstrap-sass', "1.4.4"
35 gem "colored" 35 gem "colored"
36 gem 'yaml_db', :git => "https://github.com/gitlabhq/yaml_db.git" 36 gem 'yaml_db', :git => "https://github.com/gitlabhq/yaml_db.git"
  37 +gem 'modularity'
37 38
38 group :assets do 39 group :assets do
39 gem "sass-rails", "3.2.3" 40 gem "sass-rails", "3.2.3"
@@ -149,6 +149,7 @@ GEM @@ -149,6 +149,7 @@ GEM
149 treetop (~> 1.4.8) 149 treetop (~> 1.4.8)
150 method_source (0.7.0) 150 method_source (0.7.0)
151 mime-types (1.17.2) 151 mime-types (1.17.2)
  152 + modularity (0.6.1)
152 multi_json (1.0.4) 153 multi_json (1.0.4)
153 multi_xml (0.4.1) 154 multi_xml (0.4.1)
154 mysql2 (0.3.11) 155 mysql2 (0.3.11)
@@ -326,6 +327,7 @@ DEPENDENCIES @@ -326,6 +327,7 @@ DEPENDENCIES
326 kaminari 327 kaminari
327 launchy 328 launchy
328 letter_opener 329 letter_opener
  330 + modularity
329 mysql2 331 mysql2
330 omniauth-ldap 332 omniauth-ldap
331 pry 333 pry
app/models/project.rb
@@ -3,6 +3,11 @@ require "grit" @@ -3,6 +3,11 @@ require "grit"
3 class Project < ActiveRecord::Base 3 class Project < ActiveRecord::Base
4 belongs_to :owner, :class_name => "User" 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 has_many :users, :through => :users_projects 11 has_many :users, :through => :users_projects
7 has_many :events, :dependent => :destroy 12 has_many :events, :dependent => :destroy
8 has_many :merge_requests, :dependent => :destroy 13 has_many :merge_requests, :dependent => :destroy
@@ -15,32 +20,6 @@ class Project &lt; ActiveRecord::Base @@ -15,32 +20,6 @@ class Project &lt; ActiveRecord::Base
15 has_many :wikis, :dependent => :destroy 20 has_many :wikis, :dependent => :destroy
16 has_many :protected_branches, :dependent => :destroy 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 attr_protected :private_flag, :owner_id 23 attr_protected :private_flag, :owner_id
45 24
46 scope :public_only, where(:private_flag => false) 25 scope :public_only, where(:private_flag => false)
@@ -66,89 +45,6 @@ class Project &lt; ActiveRecord::Base @@ -66,89 +45,6 @@ class Project &lt; ActiveRecord::Base
66 [GIT_HOST['host'], code].join("/") 45 [GIT_HOST['host'], code].join("/")
67 end 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 def team_member_by_name_or_email(email = nil, name = nil) 48 def team_member_by_name_or_email(email = nil, name = nil)
153 user = users.where("email like ? or name like ?", email, name).first 49 user = users.where("email like ? or name like ?", email, name).first
154 users_projects.find_by_user_id(user.id) if user 50 users_projects.find_by_user_id(user.id) if user
@@ -174,71 +70,6 @@ class Project &lt; ActiveRecord::Base @@ -174,71 +70,6 @@ class Project &lt; ActiveRecord::Base
174 notes.where(:noteable_id => commit.id, :noteable_type => "Commit").where("line_code is not null") 70 notes.where(:noteable_id => commit.id, :noteable_type => "Commit").where("line_code is not null")
175 end 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 def public? 73 def public?
243 !private_flag 74 !private_flag
244 end 75 end
@@ -259,112 +90,9 @@ class Project &lt; ActiveRecord::Base @@ -259,112 +90,9 @@ class Project &lt; ActiveRecord::Base
259 end 90 end
260 end 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 def project_id 93 def project_id
308 self.id 94 self.id
309 end 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 end 96 end
369 97
370 # == Schema Information 98 # == Schema Information
app/models/project/hooks_trait.rb 0 → 100644
@@ -0,0 +1,77 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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