summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorDmitriy Zaporozhets <dzaporozhets@sphereconsultinginc.com>2012-06-07 15:44:57 +0300
committerDmitriy Zaporozhets <dzaporozhets@sphereconsultinginc.com>2012-06-07 15:44:57 +0300
commit0a70aca3b177cffccd2e04579712665d10b8fd69 (patch)
tree28a2e873be1ee3559bcef7f7cfebe19c91e5d3b0 /app
parent98b841664798d075013fbf132614cc40afc0125e (diff)
downloadgitlab-ce-0a70aca3b177cffccd2e04579712665d10b8fd69.tar.gz
Models Refactoring: Move methods to roles
Diffstat (limited to 'app')
-rw-r--r--app/models/event.rb4
-rw-r--r--app/models/event/push_trait.rb92
-rw-r--r--app/models/issue.rb7
-rw-r--r--app/models/key.rb20
-rw-r--r--app/models/merge_request.rb8
-rw-r--r--app/models/project.rb80
-rw-r--r--app/models/project/hooks_trait.rb109
-rw-r--r--app/models/project/permissions_trait.rb60
-rw-r--r--app/models/project/repository_trait.rb122
-rw-r--r--app/models/project/validations_trait.rb43
-rw-r--r--app/models/user.rb50
-rw-r--r--app/roles/account.rb49
-rw-r--r--app/roles/authority.rb58
-rw-r--r--app/roles/git_merge.rb2
-rw-r--r--app/roles/git_push.rb107
-rw-r--r--app/roles/push_event.rb90
-rw-r--r--app/roles/repository.rb120
-rw-r--r--app/roles/ssh_key.rb18
-rw-r--r--app/roles/team.rb10
-rw-r--r--app/roles/upvote.rb6
20 files changed, 531 insertions, 524 deletions
diff --git a/app/models/event.rb b/app/models/event.rb
index cf8dc153a38..3f1ff3e553e 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -1,4 +1,6 @@
class Event < ActiveRecord::Base
+ include PushEvent
+
default_scope where("author_id IS NOT NULL")
Created = 1
@@ -9,8 +11,6 @@ class Event < ActiveRecord::Base
Commented = 6
Merged = 7
- does "event/push"
-
belongs_to :project
belongs_to :target, :polymorphic => true
diff --git a/app/models/event/push_trait.rb b/app/models/event/push_trait.rb
deleted file mode 100644
index f12d50bdc93..00000000000
--- a/app/models/event/push_trait.rb
+++ /dev/null
@@ -1,92 +0,0 @@
-module Event::PushTrait
- as_trait do
- def valid_push?
- data[:ref]
- rescue => ex
- false
- end
-
- def tag?
- data[:ref]["refs/tags"]
- end
-
- def new_branch?
- commit_from =~ /^00000/
- end
-
- def new_ref?
- commit_from =~ /^00000/
- end
-
- def rm_ref?
- commit_to =~ /^00000/
- end
-
- def md_ref?
- !(rm_ref? || new_ref?)
- end
-
- def commit_from
- data[:before]
- end
-
- def commit_to
- data[:after]
- end
-
- def ref_name
- if tag?
- tag_name
- else
- branch_name
- end
- end
-
- def branch_name
- @branch_name ||= data[:ref].gsub("refs/heads/", "")
- end
-
- def tag_name
- @tag_name ||= data[:ref].gsub("refs/tags/", "")
- end
-
- # Max 20 commits from push DESC
- def commits
- @commits ||= data[:commits].map { |commit| project.commit(commit[:id]) }.reverse
- end
-
- def commits_count
- data[:total_commits_count] || commits.count || 0
- end
-
- def ref_type
- tag? ? "tag" : "branch"
- end
-
- def push_action_name
- if new_ref?
- "pushed new"
- elsif rm_ref?
- "removed #{ref_type}"
- else
- "pushed to"
- end
- end
-
- def parent_commit
- project.commit(commit_from)
- rescue => ex
- nil
- end
-
- def last_commit
- project.commit(commit_to)
- rescue => ex
- nil
- end
-
- def push_with_commits?
- md_ref? && commits.any? && parent_commit && last_commit
- end
- end
-end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 5fe0e0b2b45..3ed47ef1bea 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -1,4 +1,6 @@
class Issue < ActiveRecord::Base
+ include Upvote
+
belongs_to :project
belongs_to :milestone
belongs_to :author, :class_name => "User"
@@ -53,11 +55,6 @@ class Issue < ActiveRecord::Base
def new?
today? && created_at == updated_at
end
-
- # Return the number of +1 comments (upvotes)
- def upvotes
- notes.select(&:upvote?).size
- end
end
# == Schema Information
#
diff --git a/app/models/key.rb b/app/models/key.rb
index 8fe8716cc63..2b05ef55dd8 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -1,6 +1,7 @@
require 'digest/md5'
class Key < ActiveRecord::Base
+ include SshKey
belongs_to :user
belongs_to :project
@@ -37,28 +38,11 @@ class Key < ActiveRecord::Base
end
end
- def update_repository
- Gitlab::GitHost.system.new.configure do |c|
- c.update_keys(identifier, key)
- c.update_projects(projects)
- end
- end
-
- def repository_delete_key
- Gitlab::GitHost.system.new.configure do |c|
- #delete key file is there is no identically deploy keys
- if !is_deploy_key || Key.where(:identifier => identifier).count() == 0
- c.delete_key(identifier)
- end
- c.update_projects(projects)
- end
- end
-
def is_deploy_key
true if project_id
end
- #projects that has this key
+ # projects that has this key
def projects
if is_deploy_key
[project]
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 2aba24bc46f..d532373f1b2 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -1,6 +1,8 @@
require File.join(Rails.root, "app/models/commit")
class MergeRequest < ActiveRecord::Base
+ include Upvote
+
UNCHECKED = 1
CAN_BE_MERGED = 2
CANNOT_BE_MERGED = 3
@@ -128,12 +130,6 @@ class MergeRequest < ActiveRecord::Base
self.project.events.where(:target_id => self.id, :target_type => "MergeRequest", :action => Event::Closed).last
end
-
- # Return the number of +1 comments (upvotes)
- def upvotes
- notes.select(&:upvote?).size
- end
-
def commits
st_commits || []
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 72cc833c253..12556d35202 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -1,13 +1,15 @@
require "grit"
class Project < ActiveRecord::Base
+ include Repository
+ include GitPush
+ include Authority
+ include Team
+
+ #
+ # Relations
+ #
belongs_to :owner, :class_name => "User"
-
- does "project/validations"
- does "project/repository"
- does "project/permissions"
- does "project/hooks"
-
has_many :users, :through => :users_projects
has_many :events, :dependent => :destroy
has_many :merge_requests, :dependent => :destroy
@@ -21,8 +23,14 @@ class Project < ActiveRecord::Base
has_many :wikis, :dependent => :destroy
has_many :protected_branches, :dependent => :destroy
+ #
+ # Protected attributes
+ #
attr_protected :private_flag, :owner_id
+ #
+ # Scopes
+ #
scope :public_only, where(:private_flag => false)
scope :without_user, lambda { |user| where("id not in (:ids)", :ids => user.projects.map(&:id) ) }
@@ -30,29 +38,63 @@ class Project < ActiveRecord::Base
joins(:issues, :notes, :merge_requests).order("issues.created_at, notes.created_at, merge_requests.created_at DESC")
end
- def self.access_options
- UsersProject.access_roles
- end
-
def self.search query
where("name like :query or code like :query or path like :query", :query => "%#{query}%")
end
- def to_param
- code
+ #
+ # Validations
+ #
+ validates :name,
+ :uniqueness => true,
+ :presence => true,
+ :length => { :within => 0..255 }
+
+ validates :path,
+ :uniqueness => true,
+ :presence => true,
+ :format => { :with => /^[a-zA-Z0-9_\-\.]*$/,
+ :message => "only letters, digits & '_' '-' '.' allowed" },
+ :length => { :within => 0..255 }
+
+ validates :description,
+ :length => { :within => 0..2000 }
+
+ validates :code,
+ :presence => true,
+ :uniqueness => true,
+ :format => { :with => /^[a-zA-Z0-9_\-\.]*$/,
+ :message => "only letters, digits & '_' '-' '.' allowed" },
+ :length => { :within => 1..255 }
+
+ validates :owner, :presence => true
+ validate :check_limit
+ validate :repo_name
+
+ def check_limit
+ unless owner.can_create_project?
+ errors[:base] << ("Your own projects limit is #{owner.projects_limit}! Please contact administrator to increase it")
+ end
+ rescue
+ errors[:base] << ("Cant check your ability to create project")
end
- def web_url
- [GIT_HOST['host'], code].join("/")
+ def repo_name
+ if path == "gitolite-admin"
+ errors.add(:path, " like 'gitolite-admin' is not allowed")
+ end
+ end
+
+ def self.access_options
+ UsersProject.access_roles
end
- def team_member_by_name_or_email(email = nil, name = nil)
- user = users.where("email like ? or name like ?", email, name).first
- users_projects.find_by_user_id(user.id) if user
+ def to_param
+ code
end
- def team_member_by_id(user_id)
- users_projects.find_by_user_id(user_id)
+ def web_url
+ [GIT_HOST['host'], code].join("/")
end
def common_notes
diff --git a/app/models/project/hooks_trait.rb b/app/models/project/hooks_trait.rb
deleted file mode 100644
index 2f97eb6c379..00000000000
--- a/app/models/project/hooks_trait.rb
+++ /dev/null
@@ -1,109 +0,0 @@
-module Project::HooksTrait
- as_trait do
- def observe_push(oldrev, newrev, ref, user)
- data = post_receive_data(oldrev, newrev, ref, user)
-
- Event.create(
- :project => self,
- :action => Event::Pushed,
- :data => data,
- :author_id => data[:user_id]
- )
- end
-
- def update_merge_requests(oldrev, newrev, ref, user)
- return true unless ref =~ /heads/
- branch_name = ref.gsub("refs/heads/", "")
- c_ids = self.commits_between(oldrev, newrev).map(&:id)
-
- # Update code for merge requests
- mrs = self.merge_requests.opened.find_all_by_branch(branch_name).all
- mrs.each { |merge_request| merge_request.reload_code; merge_request.mark_as_unchecked }
-
- # Close merge requests
- mrs = self.merge_requests.opened.where(:target_branch => branch_name).all
- mrs = mrs.select(&:last_commit).select { |mr| c_ids.include?(mr.last_commit.id) }
- mrs.each { |merge_request| merge_request.merge!(user.id) }
-
- true
- end
-
- def execute_web_hooks(oldrev, newrev, ref, user)
- ref_parts = ref.split('/')
-
- # Return if this is not a push to a branch (e.g. new commits)
- return if ref_parts[1] !~ /heads/ || oldrev == "00000000000000000000000000000000"
-
- data = post_receive_data(oldrev, newrev, ref, user)
-
- web_hooks.each { |web_hook| web_hook.execute(data) }
- end
-
- def post_receive_data(oldrev, newrev, ref, user)
-
- push_commits = commits_between(oldrev, newrev)
-
- # Total commits count
- push_commits_count = push_commits.size
-
- # Get latest 20 commits ASC
- push_commits_limited = push_commits.last(20)
-
- # Hash to be passed as post_receive_data
- data = {
- before: oldrev,
- after: newrev,
- ref: ref,
- user_id: user.id,
- user_name: user.name,
- repository: {
- name: name,
- url: web_url,
- description: description,
- homepage: web_url,
- },
- commits: [],
- total_commits_count: push_commits_count
- }
-
- # For perfomance purposes maximum 20 latest commits
- # will be passed as post receive hook data.
- #
- push_commits_limited.each do |commit|
- data[:commits] << {
- id: commit.id,
- message: commit.safe_message,
- timestamp: commit.date.xmlschema,
- url: "http://#{GIT_HOST['host']}/#{code}/commits/#{commit.id}",
- author: {
- name: commit.author_name,
- email: commit.author_email
- }
- }
- end
-
- data
- end
-
-
- # This method will be called after each post receive
- # and only if autor_key_id present in gitlab.
- # All callbacks for post receive should be placed here
- #
- def trigger_post_receive(oldrev, newrev, ref, author_key_id)
- user = Key.find_by_identifier(author_key_id).user
-
- # Create push event
- self.observe_push(oldrev, newrev, ref, user)
-
- # Close merged MR
- self.update_merge_requests(oldrev, newrev, ref, user)
-
- # Execute web hooks
- self.execute_web_hooks(oldrev, newrev, ref, user)
-
- # Create satellite
- self.satellite.create unless self.satellite.exists?
- end
- end
-end
diff --git a/app/models/project/permissions_trait.rb b/app/models/project/permissions_trait.rb
deleted file mode 100644
index 3b90c711c2e..00000000000
--- a/app/models/project/permissions_trait.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-module Project::PermissionsTrait
- as_trait do
- # Compatible with all access rights
- # Should be rewrited for new access rights
- def add_access(user, *access)
- access = if access.include?(:admin)
- { :project_access => UsersProject::MASTER }
- elsif access.include?(:write)
- { :project_access => UsersProject::DEVELOPER }
- else
- { :project_access => UsersProject::REPORTER }
- end
- opts = { :user => user }
- opts.merge!(access)
- users_projects.create(opts)
- end
-
- def reset_access(user)
- users_projects.where(:project_id => self.id, :user_id => user.id).destroy if self.id
- end
-
- def repository_readers
- keys = Key.joins({:user => :users_projects}).
- where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::REPORTER)
- keys.map(&:identifier) + deploy_keys.map(&:identifier)
- end
-
- def repository_writers
- keys = Key.joins({:user => :users_projects}).
- where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::DEVELOPER)
- keys.map(&:identifier)
- end
-
- def repository_masters
- keys = Key.joins({:user => :users_projects}).
- where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::MASTER)
- keys.map(&:identifier)
- end
-
- def allow_read_for?(user)
- !users_projects.where(:user_id => user.id).empty?
- end
-
- def guest_access_for?(user)
- !users_projects.where(:user_id => user.id).empty?
- end
-
- def report_access_for?(user)
- !users_projects.where(:user_id => user.id, :project_access => [UsersProject::REPORTER, UsersProject::DEVELOPER, UsersProject::MASTER]).empty?
- end
-
- def dev_access_for?(user)
- !users_projects.where(:user_id => user.id, :project_access => [UsersProject::DEVELOPER, UsersProject::MASTER]).empty?
- end
-
- def master_access_for?(user)
- !users_projects.where(:user_id => user.id, :project_access => [UsersProject::MASTER]).empty? || owner_id == user.id
- end
- end
-end
diff --git a/app/models/project/repository_trait.rb b/app/models/project/repository_trait.rb
deleted file mode 100644
index 2b9cf437bbc..00000000000
--- a/app/models/project/repository_trait.rb
+++ /dev/null
@@ -1,122 +0,0 @@
-module Project::RepositoryTrait
- as_trait do
- def valid_repo?
- repo
- rescue
- errors.add(:path, "Invalid repository path")
- false
- end
-
- def commit(commit_id = nil)
- Commit.find_or_first(repo, commit_id, root_ref)
- end
-
- def fresh_commits(n = 10)
- Commit.fresh_commits(repo, n)
- end
-
- def commits_with_refs(n = 20)
- Commit.commits_with_refs(repo, n)
- end
-
- def commits_since(date)
- Commit.commits_since(repo, date)
- end
-
- def commits(ref, path = nil, limit = nil, offset = nil)
- Commit.commits(repo, ref, path, limit, offset)
- end
-
- def commits_between(from, to)
- Commit.commits_between(repo, from, to)
- end
-
- def write_hooks
- %w(post-receive).each do |hook|
- write_hook(hook, File.read(File.join(Rails.root, 'lib', "#{hook}-hook")))
- end
- end
-
- def satellite
- @satellite ||= Gitlab::Satellite.new(self)
- end
-
- def write_hook(name, content)
- hook_file = File.join(path_to_repo, 'hooks', name)
-
- File.open(hook_file, 'w') do |f|
- f.write(content)
- end
-
- File.chmod(0775, hook_file)
- end
-
- def has_post_receive_file?
- hook_file = File.join(path_to_repo, 'hooks', 'post-receive')
- File.exists?(hook_file)
- end
-
- def tags
- repo.tags.map(&:name).sort.reverse
- end
-
- def repo
- @repo ||= Grit::Repo.new(path_to_repo)
- end
-
- def url_to_repo
- Gitlab::GitHost.url_to_repo(path)
- end
-
- def path_to_repo
- File.join(GIT_HOST["base_path"], "#{path}.git")
- end
-
- def update_repository
- Gitlab::GitHost.system.update_project(path, self)
-
- write_hooks if File.exists?(path_to_repo)
- end
-
- def destroy_repository
- Gitlab::GitHost.system.destroy_project(self)
- end
-
- def repo_exists?
- @repo_exists ||= (repo && !repo.branches.empty?)
- rescue
- @repo_exists = false
- end
-
- def heads
- @heads ||= repo.heads
- end
-
- def tree(fcommit, path = nil)
- fcommit = commit if fcommit == :head
- tree = fcommit.tree
- path ? (tree / path) : tree
- end
-
- def open_branches
- if protected_branches.empty?
- self.repo.heads
- else
- pnames = protected_branches.map(&:name)
- self.repo.heads.reject { |h| pnames.include?(h.name) }
- end.sort_by(&:name)
- end
-
- def has_commits?
- !!commit
- end
-
- def root_ref
- default_branch || "master"
- end
-
- def root_ref? branch
- root_ref == branch
- end
- end
-end
diff --git a/app/models/project/validations_trait.rb b/app/models/project/validations_trait.rb
deleted file mode 100644
index d2d207c4356..00000000000
--- a/app/models/project/validations_trait.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-module Project::ValidationsTrait
- as_trait do
- validates :name,
- :uniqueness => true,
- :presence => true,
- :length => { :within => 0..255 }
-
- validates :path,
- :uniqueness => true,
- :presence => true,
- :format => { :with => /^[a-zA-Z0-9_\-\.]*$/,
- :message => "only letters, digits & '_' '-' '.' allowed" },
- :length => { :within => 0..255 }
-
- validates :description,
- :length => { :within => 0..2000 }
-
- validates :code,
- :presence => true,
- :uniqueness => true,
- :format => { :with => /^[a-zA-Z0-9_\-\.]*$/,
- :message => "only letters, digits & '_' '-' '.' allowed" },
- :length => { :within => 1..255 }
-
- validates :owner, :presence => true
- validate :check_limit
- validate :repo_name
-
- def check_limit
- unless owner.can_create_project?
- errors[:base] << ("Your own projects limit is #{owner.projects_limit}! Please contact administrator to increase it")
- end
- rescue
- errors[:base] << ("Cant check your ability to create project")
- end
-
- def repo_name
- if path == "gitolite-admin"
- errors.add(:path, " like 'gitolite-admin' is not allowed")
- end
- end
- end
-end
diff --git a/app/models/user.rb b/app/models/user.rb
index 21b788d310c..50854bf9e50 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,4 +1,6 @@
class User < ActiveRecord::Base
+ include Account
+
devise :database_authenticatable, :token_authenticatable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable
@@ -65,30 +67,6 @@ class User < ActiveRecord::Base
where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)')
end
- def identifier
- email.gsub /[@.]/, "_"
- end
-
- def is_admin?
- admin
- end
-
- def require_ssh_key?
- keys.count == 0
- end
-
- def can_create_project?
- projects_limit > my_own_projects.count
- end
-
- def last_activity_project
- projects.first
- end
-
- def first_name
- name.split.first unless name.blank?
- end
-
def self.find_for_ldap_auth(omniauth_info)
name = omniauth_info.name.force_encoding("utf-8")
email = omniauth_info.email.downcase
@@ -105,30 +83,6 @@ class User < ActiveRecord::Base
)
end
end
-
- def cared_merge_requests
- MergeRequest.where("author_id = :id or assignee_id = :id", :id => self.id).opened
- end
-
- def project_ids
- projects.map(&:id)
- end
-
- # Remove user from all projects and
- # set blocked attribute to true
- def block
- users_projects.all.each do |membership|
- return false unless membership.destroy
- end
-
- self.blocked = true
- save
- end
-
- def projects_limit_percent
- return 100 if projects_limit.zero?
- (my_own_projects.count.to_f / projects_limit) * 100
- end
end
# == Schema Information
#
diff --git a/app/roles/account.rb b/app/roles/account.rb
new file mode 100644
index 00000000000..62492b83b9b
--- /dev/null
+++ b/app/roles/account.rb
@@ -0,0 +1,49 @@
+module Account
+ def identifier
+ email.gsub /[@.]/, "_"
+ end
+
+ def is_admin?
+ admin
+ end
+
+ def require_ssh_key?
+ keys.count == 0
+ end
+
+ def can_create_project?
+ projects_limit > my_own_projects.count
+ end
+
+ def last_activity_project
+ projects.first
+ end
+
+ def first_name
+ name.split.first unless name.blank?
+ end
+
+ def cared_merge_requests
+ MergeRequest.where("author_id = :id or assignee_id = :id", :id => self.id).opened
+ end
+
+ def project_ids
+ projects.map(&:id)
+ end
+
+ # Remove user from all projects and
+ # set blocked attribute to true
+ def block
+ users_projects.all.each do |membership|
+ return false unless membership.destroy
+ end
+
+ self.blocked = true
+ save
+ end
+
+ def projects_limit_percent
+ return 100 if projects_limit.zero?
+ (my_own_projects.count.to_f / projects_limit) * 100
+ end
+end
diff --git a/app/roles/authority.rb b/app/roles/authority.rb
new file mode 100644
index 00000000000..a03b54a3ee7
--- /dev/null
+++ b/app/roles/authority.rb
@@ -0,0 +1,58 @@
+module Authority
+ # Compatible with all access rights
+ # Should be rewrited for new access rights
+ def add_access(user, *access)
+ access = if access.include?(:admin)
+ { :project_access => UsersProject::MASTER }
+ elsif access.include?(:write)
+ { :project_access => UsersProject::DEVELOPER }
+ else
+ { :project_access => UsersProject::REPORTER }
+ end
+ opts = { :user => user }
+ opts.merge!(access)
+ users_projects.create(opts)
+ end
+
+ def reset_access(user)
+ users_projects.where(:project_id => self.id, :user_id => user.id).destroy if self.id
+ end
+
+ def repository_readers
+ keys = Key.joins({:user => :users_projects}).
+ where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::REPORTER)
+ keys.map(&:identifier) + deploy_keys.map(&:identifier)
+ end
+
+ def repository_writers
+ keys = Key.joins({:user => :users_projects}).
+ where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::DEVELOPER)
+ keys.map(&:identifier)
+ end
+
+ def repository_masters
+ keys = Key.joins({:user => :users_projects}).
+ where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::MASTER)
+ keys.map(&:identifier)
+ end
+
+ def allow_read_for?(user)
+ !users_projects.where(:user_id => user.id).empty?
+ end
+
+ def guest_access_for?(user)
+ !users_projects.where(:user_id => user.id).empty?
+ end
+
+ def report_access_for?(user)
+ !users_projects.where(:user_id => user.id, :project_access => [UsersProject::REPORTER, UsersProject::DEVELOPER, UsersProject::MASTER]).empty?
+ end
+
+ def dev_access_for?(user)
+ !users_projects.where(:user_id => user.id, :project_access => [UsersProject::DEVELOPER, UsersProject::MASTER]).empty?
+ end
+
+ def master_access_for?(user)
+ !users_projects.where(:user_id => user.id, :project_access => [UsersProject::MASTER]).empty? || owner_id == user.id
+ end
+end
diff --git a/app/roles/git_merge.rb b/app/roles/git_merge.rb
new file mode 100644
index 00000000000..95e5942fb00
--- /dev/null
+++ b/app/roles/git_merge.rb
@@ -0,0 +1,2 @@
+module GitMerge
+end
diff --git a/app/roles/git_push.rb b/app/roles/git_push.rb
new file mode 100644
index 00000000000..504aa0b51ae
--- /dev/null
+++ b/app/roles/git_push.rb
@@ -0,0 +1,107 @@
+module GitPush
+ def observe_push(oldrev, newrev, ref, user)
+ data = post_receive_data(oldrev, newrev, ref, user)
+
+ Event.create(
+ :project => self,
+ :action => Event::Pushed,
+ :data => data,
+ :author_id => data[:user_id]
+ )
+ end
+
+ def update_merge_requests(oldrev, newrev, ref, user)
+ return true unless ref =~ /heads/
+ branch_name = ref.gsub("refs/heads/", "")
+ c_ids = self.commits_between(oldrev, newrev).map(&:id)
+
+ # Update code for merge requests
+ mrs = self.merge_requests.opened.find_all_by_branch(branch_name).all
+ mrs.each { |merge_request| merge_request.reload_code; merge_request.mark_as_unchecked }
+
+ # Close merge requests
+ mrs = self.merge_requests.opened.where(:target_branch => branch_name).all
+ mrs = mrs.select(&:last_commit).select { |mr| c_ids.include?(mr.last_commit.id) }
+ mrs.each { |merge_request| merge_request.merge!(user.id) }
+
+ true
+ end
+
+ def execute_web_hooks(oldrev, newrev, ref, user)
+ ref_parts = ref.split('/')
+
+ # Return if this is not a push to a branch (e.g. new commits)
+ return if ref_parts[1] !~ /heads/ || oldrev == "00000000000000000000000000000000"
+
+ data = post_receive_data(oldrev, newrev, ref, user)
+
+ web_hooks.each { |web_hook| web_hook.execute(data) }
+ end
+
+ def post_receive_data(oldrev, newrev, ref, user)
+
+ push_commits = commits_between(oldrev, newrev)
+
+ # Total commits count
+ push_commits_count = push_commits.size
+
+ # Get latest 20 commits ASC
+ push_commits_limited = push_commits.last(20)
+
+ # Hash to be passed as post_receive_data
+ data = {
+ before: oldrev,
+ after: newrev,
+ ref: ref,
+ user_id: user.id,
+ user_name: user.name,
+ repository: {
+ name: name,
+ url: web_url,
+ description: description,
+ homepage: web_url,
+ },
+ commits: [],
+ total_commits_count: push_commits_count
+ }
+
+ # For perfomance purposes maximum 20 latest commits
+ # will be passed as post receive hook data.
+ #
+ push_commits_limited.each do |commit|
+ data[:commits] << {
+ id: commit.id,
+ message: commit.safe_message,
+ timestamp: commit.date.xmlschema,
+ url: "http://#{GIT_HOST['host']}/#{code}/commits/#{commit.id}",
+ author: {
+ name: commit.author_name,
+ email: commit.author_email
+ }
+ }
+ end
+
+ data
+ end
+
+
+ # This method will be called after each post receive
+ # and only if autor_key_id present in gitlab.
+ # All callbacks for post receive should be placed here
+ #
+ def trigger_post_receive(oldrev, newrev, ref, author_key_id)
+ user = Key.find_by_identifier(author_key_id).user
+
+ # Create push event
+ self.observe_push(oldrev, newrev, ref, user)
+
+ # Close merged MR
+ self.update_merge_requests(oldrev, newrev, ref, user)
+
+ # Execute web hooks
+ self.execute_web_hooks(oldrev, newrev, ref, user)
+
+ # Create satellite
+ self.satellite.create unless self.satellite.exists?
+ end
+end
diff --git a/app/roles/push_event.rb b/app/roles/push_event.rb
new file mode 100644
index 00000000000..acec916f893
--- /dev/null
+++ b/app/roles/push_event.rb
@@ -0,0 +1,90 @@
+module PushEvent
+ def valid_push?
+ data[:ref]
+ rescue => ex
+ false
+ end
+
+ def tag?
+ data[:ref]["refs/tags"]
+ end
+
+ def new_branch?
+ commit_from =~ /^00000/
+ end
+
+ def new_ref?
+ commit_from =~ /^00000/
+ end
+
+ def rm_ref?
+ commit_to =~ /^00000/
+ end
+
+ def md_ref?
+ !(rm_ref? || new_ref?)
+ end
+
+ def commit_from
+ data[:before]
+ end
+
+ def commit_to
+ data[:after]
+ end
+
+ def ref_name
+ if tag?
+ tag_name
+ else
+ branch_name
+ end
+ end
+
+ def branch_name
+ @branch_name ||= data[:ref].gsub("refs/heads/", "")
+ end
+
+ def tag_name
+ @tag_name ||= data[:ref].gsub("refs/tags/", "")
+ end
+
+ # Max 20 commits from push DESC
+ def commits
+ @commits ||= data[:commits].map { |commit| project.commit(commit[:id]) }.reverse
+ end
+
+ def commits_count
+ data[:total_commits_count] || commits.count || 0
+ end
+
+ def ref_type
+ tag? ? "tag" : "branch"
+ end
+
+ def push_action_name
+ if new_ref?
+ "pushed new"
+ elsif rm_ref?
+ "removed #{ref_type}"
+ else
+ "pushed to"
+ end
+ end
+
+ def parent_commit
+ project.commit(commit_from)
+ rescue => ex
+ nil
+ end
+
+ def last_commit
+ project.commit(commit_to)
+ rescue => ex
+ nil
+ end
+
+ def push_with_commits?
+ md_ref? && commits.any? && parent_commit && last_commit
+ end
+end
diff --git a/app/roles/repository.rb b/app/roles/repository.rb
new file mode 100644
index 00000000000..85ed6b7baaa
--- /dev/null
+++ b/app/roles/repository.rb
@@ -0,0 +1,120 @@
+module Repository
+ def valid_repo?
+ repo
+ rescue
+ errors.add(:path, "Invalid repository path")
+ false
+ end
+
+ def commit(commit_id = nil)
+ Commit.find_or_first(repo, commit_id, root_ref)
+ end
+
+ def fresh_commits(n = 10)
+ Commit.fresh_commits(repo, n)
+ end
+
+ def commits_with_refs(n = 20)
+ Commit.commits_with_refs(repo, n)
+ end
+
+ def commits_since(date)
+ Commit.commits_since(repo, date)
+ end
+
+ def commits(ref, path = nil, limit = nil, offset = nil)
+ Commit.commits(repo, ref, path, limit, offset)
+ end
+
+ def commits_between(from, to)
+ Commit.commits_between(repo, from, to)
+ end
+
+ def write_hooks
+ %w(post-receive).each do |hook|
+ write_hook(hook, File.read(File.join(Rails.root, 'lib', "#{hook}-hook")))
+ end
+ end
+
+ def satellite
+ @satellite ||= Gitlab::Satellite.new(self)
+ end
+
+ def write_hook(name, content)
+ hook_file = File.join(path_to_repo, 'hooks', name)
+
+ File.open(hook_file, 'w') do |f|
+ f.write(content)
+ end
+
+ File.chmod(0775, hook_file)
+ end
+
+ def has_post_receive_file?
+ hook_file = File.join(path_to_repo, 'hooks', 'post-receive')
+ File.exists?(hook_file)
+ end
+
+ def tags
+ repo.tags.map(&:name).sort.reverse
+ end
+
+ def repo
+ @repo ||= Grit::Repo.new(path_to_repo)
+ end
+
+ def url_to_repo
+ Gitlab::GitHost.url_to_repo(path)
+ end
+
+ def path_to_repo
+ File.join(GIT_HOST["base_path"], "#{path}.git")
+ end
+
+ def update_repository
+ Gitlab::GitHost.system.update_project(path, self)
+
+ write_hooks if File.exists?(path_to_repo)
+ end
+
+ def destroy_repository
+ Gitlab::GitHost.system.destroy_project(self)
+ end
+
+ def repo_exists?
+ @repo_exists ||= (repo && !repo.branches.empty?)
+ rescue
+ @repo_exists = false
+ end
+
+ def heads
+ @heads ||= repo.heads
+ end
+
+ def tree(fcommit, path = nil)
+ fcommit = commit if fcommit == :head
+ tree = fcommit.tree
+ path ? (tree / path) : tree
+ end
+
+ def open_branches
+ if protected_branches.empty?
+ self.repo.heads
+ else
+ pnames = protected_branches.map(&:name)
+ self.repo.heads.reject { |h| pnames.include?(h.name) }
+ end.sort_by(&:name)
+ end
+
+ def has_commits?
+ !!commit
+ end
+
+ def root_ref
+ default_branch || "master"
+ end
+
+ def root_ref? branch
+ root_ref == branch
+ end
+end
diff --git a/app/roles/ssh_key.rb b/app/roles/ssh_key.rb
new file mode 100644
index 00000000000..f1143c5d065
--- /dev/null
+++ b/app/roles/ssh_key.rb
@@ -0,0 +1,18 @@
+module SshKey
+ def update_repository
+ Gitlab::GitHost.system.new.configure do |c|
+ c.update_keys(identifier, key)
+ c.update_projects(projects)
+ end
+ end
+
+ def repository_delete_key
+ Gitlab::GitHost.system.new.configure do |c|
+ #delete key file is there is no identically deploy keys
+ if !is_deploy_key || Key.where(:identifier => identifier).count() == 0
+ c.delete_key(identifier)
+ end
+ c.update_projects(projects)
+ end
+ end
+end
diff --git a/app/roles/team.rb b/app/roles/team.rb
new file mode 100644
index 00000000000..2a477b6edba
--- /dev/null
+++ b/app/roles/team.rb
@@ -0,0 +1,10 @@
+module Team
+ def team_member_by_name_or_email(email = nil, name = nil)
+ user = users.where("email like ? or name like ?", email, name).first
+ users_projects.find_by_user_id(user.id) if user
+ end
+
+ def team_member_by_id(user_id)
+ users_projects.find_by_user_id(user_id)
+ end
+end
diff --git a/app/roles/upvote.rb b/app/roles/upvote.rb
new file mode 100644
index 00000000000..7efa6f20cfc
--- /dev/null
+++ b/app/roles/upvote.rb
@@ -0,0 +1,6 @@
+module Upvote
+ # Return the number of +1 comments (upvotes)
+ def upvotes
+ notes.select(&:upvote?).size
+ end
+end