Get rid of roles
This commit is contained in:
parent
1b25a8f437
commit
cac7723451
20 changed files with 744 additions and 821 deletions
|
@ -170,4 +170,139 @@ class Event < ActiveRecord::Base
|
||||||
"opened"
|
"opened"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def valid_push?
|
||||||
|
data[:ref]
|
||||||
|
rescue => ex
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def tag?
|
||||||
|
data[:ref]["refs/tags"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def branch?
|
||||||
|
data[:ref]["refs/heads"]
|
||||||
|
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?
|
||||||
|
"deleted"
|
||||||
|
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
|
||||||
|
rescue Grit::NoSuchPathError
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def last_push_to_non_root?
|
||||||
|
branch? && project.default_branch != branch_name
|
||||||
|
end
|
||||||
|
|
||||||
|
def note_commit_id
|
||||||
|
target.commit_id
|
||||||
|
end
|
||||||
|
|
||||||
|
def note_short_commit_id
|
||||||
|
note_commit_id[0..8]
|
||||||
|
end
|
||||||
|
|
||||||
|
def note_commit?
|
||||||
|
target.noteable_type == "Commit"
|
||||||
|
end
|
||||||
|
|
||||||
|
def note_target
|
||||||
|
target.noteable
|
||||||
|
end
|
||||||
|
|
||||||
|
def note_target_id
|
||||||
|
if note_commit?
|
||||||
|
target.commit_id
|
||||||
|
else
|
||||||
|
target.noteable_id.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def wall_note?
|
||||||
|
target.noteable_type.blank?
|
||||||
|
end
|
||||||
|
|
||||||
|
def note_target_type
|
||||||
|
if target.noteable_type.present?
|
||||||
|
target.noteable_type.titleize
|
||||||
|
else
|
||||||
|
"Wall"
|
||||||
|
end.downcase
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,11 +21,7 @@
|
||||||
require "grit"
|
require "grit"
|
||||||
|
|
||||||
class Project < ActiveRecord::Base
|
class Project < ActiveRecord::Base
|
||||||
include Repository
|
include GitHost
|
||||||
include PushObserver
|
|
||||||
include Authority
|
|
||||||
include Team
|
|
||||||
include NamespacedProject
|
|
||||||
|
|
||||||
class TransferError < StandardError; end
|
class TransferError < StandardError; end
|
||||||
|
|
||||||
|
@ -277,4 +273,514 @@ class Project < ActiveRecord::Base
|
||||||
creator
|
creator
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def team_member_by_name_or_email(name = nil, email = nil)
|
||||||
|
user = users.where("name like ? or email like ?", name, email).first
|
||||||
|
users_projects.where(user: user) if user
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get Team Member record by user id
|
||||||
|
def team_member_by_id(user_id)
|
||||||
|
users_projects.find_by_user_id(user_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add user to project
|
||||||
|
# with passed access role
|
||||||
|
def add_user_to_team(user, access_role)
|
||||||
|
add_user_id_to_team(user.id, access_role)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add multiple users to project
|
||||||
|
# with same access role
|
||||||
|
def add_users_to_team(users, access_role)
|
||||||
|
add_users_ids_to_team(users.map(&:id), access_role)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add user to project
|
||||||
|
# with passed access role by user id
|
||||||
|
def add_user_id_to_team(user_id, access_role)
|
||||||
|
users_projects.create(
|
||||||
|
user_id: user_id,
|
||||||
|
project_access: access_role
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add multiple users to project
|
||||||
|
# with same access role by user ids
|
||||||
|
def add_users_ids_to_team(users_ids, access_role)
|
||||||
|
UsersProject.bulk_import(self, users_ids, access_role)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Update multiple project users
|
||||||
|
# to same access role by user ids
|
||||||
|
def update_users_ids_to_role(users_ids, access_role)
|
||||||
|
UsersProject.bulk_update(self, users_ids, access_role)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Delete multiple users from project by user ids
|
||||||
|
def delete_users_ids_from_team(users_ids)
|
||||||
|
UsersProject.bulk_delete(self, users_ids)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Remove all users from project team
|
||||||
|
def truncate_team
|
||||||
|
UsersProject.truncate_team(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
# 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
|
||||||
|
repository_members[UsersProject::REPORTER]
|
||||||
|
end
|
||||||
|
|
||||||
|
def repository_writers
|
||||||
|
repository_members[UsersProject::DEVELOPER]
|
||||||
|
end
|
||||||
|
|
||||||
|
def repository_masters
|
||||||
|
repository_members[UsersProject::MASTER]
|
||||||
|
end
|
||||||
|
|
||||||
|
def repository_members
|
||||||
|
keys = Hash.new {|h,k| h[k] = [] }
|
||||||
|
UsersProject.select("keys.identifier, project_access").
|
||||||
|
joins(user: :keys).where(project_id: id).
|
||||||
|
each {|row| keys[row.project_access] << [row.identifier] }
|
||||||
|
|
||||||
|
keys[UsersProject::REPORTER] += deploy_keys.pluck(:identifier)
|
||||||
|
keys
|
||||||
|
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?
|
||||||
|
end
|
||||||
|
|
||||||
|
def transfer(new_namespace)
|
||||||
|
Project.transaction do
|
||||||
|
old_namespace = namespace
|
||||||
|
self.namespace = new_namespace
|
||||||
|
|
||||||
|
old_dir = old_namespace.try(:path) || ''
|
||||||
|
new_dir = new_namespace.try(:path) || ''
|
||||||
|
|
||||||
|
old_repo = if old_dir.present?
|
||||||
|
File.join(old_dir, self.path)
|
||||||
|
else
|
||||||
|
self.path
|
||||||
|
end
|
||||||
|
|
||||||
|
if Project.where(path: self.path, namespace_id: new_namespace.try(:id)).present?
|
||||||
|
raise TransferError.new("Project with same path in target namespace already exists")
|
||||||
|
end
|
||||||
|
|
||||||
|
Gitlab::ProjectMover.new(self, old_dir, new_dir).execute
|
||||||
|
|
||||||
|
git_host.move_repository(old_repo, self)
|
||||||
|
|
||||||
|
save!
|
||||||
|
end
|
||||||
|
rescue Gitlab::ProjectMover::ProjectMoveError => ex
|
||||||
|
raise Project::TransferError.new(ex.message)
|
||||||
|
end
|
||||||
|
|
||||||
|
def name_with_namespace
|
||||||
|
@name_with_namespace ||= begin
|
||||||
|
if namespace
|
||||||
|
namespace.human_name + " / " + name
|
||||||
|
else
|
||||||
|
name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def namespace_owner
|
||||||
|
namespace.try(:owner)
|
||||||
|
end
|
||||||
|
|
||||||
|
def path_with_namespace
|
||||||
|
if namespace
|
||||||
|
namespace.path + '/' + path
|
||||||
|
else
|
||||||
|
path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# This method will be called after each post receive and only if the provided
|
||||||
|
# user is present in GitLab.
|
||||||
|
#
|
||||||
|
# All callbacks for post receive should be placed here.
|
||||||
|
def trigger_post_receive(oldrev, newrev, ref, user)
|
||||||
|
data = post_receive_data(oldrev, newrev, ref, user)
|
||||||
|
|
||||||
|
# Create push event
|
||||||
|
self.observe_push(data)
|
||||||
|
|
||||||
|
if push_to_branch? ref, oldrev
|
||||||
|
# Close merged MR
|
||||||
|
self.update_merge_requests(oldrev, newrev, ref, user)
|
||||||
|
|
||||||
|
# Execute web hooks
|
||||||
|
self.execute_hooks(data.dup)
|
||||||
|
|
||||||
|
# Execute project services
|
||||||
|
self.execute_services(data.dup)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Create satellite
|
||||||
|
self.satellite.create unless self.satellite.exists?
|
||||||
|
|
||||||
|
# Discover the default branch, but only if it hasn't already been set to
|
||||||
|
# something else
|
||||||
|
if default_branch.nil?
|
||||||
|
update_attributes(default_branch: discover_default_branch)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def push_to_branch? ref, oldrev
|
||||||
|
ref_parts = ref.split('/')
|
||||||
|
|
||||||
|
# Return if this is not a push to a branch (e.g. new commits)
|
||||||
|
!(ref_parts[1] !~ /heads/ || oldrev == "00000000000000000000000000000000")
|
||||||
|
end
|
||||||
|
|
||||||
|
def observe_push(data)
|
||||||
|
Event.create(
|
||||||
|
project: self,
|
||||||
|
action: Event::Pushed,
|
||||||
|
data: data,
|
||||||
|
author_id: data[:user_id]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute_hooks(data)
|
||||||
|
hooks.each { |hook| hook.execute(data) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute_services(data)
|
||||||
|
services.each do |service|
|
||||||
|
|
||||||
|
# Call service hook only if it is active
|
||||||
|
service.execute(data) if service.active
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Produce a hash of post-receive data
|
||||||
|
#
|
||||||
|
# data = {
|
||||||
|
# before: String,
|
||||||
|
# after: String,
|
||||||
|
# ref: String,
|
||||||
|
# user_id: String,
|
||||||
|
# user_name: String,
|
||||||
|
# repository: {
|
||||||
|
# name: String,
|
||||||
|
# url: String,
|
||||||
|
# description: String,
|
||||||
|
# homepage: String,
|
||||||
|
# },
|
||||||
|
# commits: Array,
|
||||||
|
# total_commits_count: Fixnum
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
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: url_to_repo,
|
||||||
|
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: "#{Gitlab.config.gitlab.url}/#{path_with_namespace}/commit/#{commit.id}",
|
||||||
|
author: {
|
||||||
|
name: commit.author_name,
|
||||||
|
email: commit.author_email
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
data
|
||||||
|
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 valid_repo?
|
||||||
|
repo
|
||||||
|
rescue
|
||||||
|
errors.add(:path, "Invalid repository path")
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def empty_repo?
|
||||||
|
!repo_exists? || !has_commits?
|
||||||
|
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 last_commit_for(ref, path = nil)
|
||||||
|
commits(ref, path, 1).first
|
||||||
|
end
|
||||||
|
|
||||||
|
def commits_between(from, to)
|
||||||
|
Commit.commits_between(repo, from, to)
|
||||||
|
end
|
||||||
|
|
||||||
|
def satellite
|
||||||
|
@satellite ||= Gitlab::Satellite::Satellite.new(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_post_receive_file?
|
||||||
|
!!hook_file
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_post_receive_file?
|
||||||
|
valid_hook_file == hook_file
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_hook_file
|
||||||
|
@valid_hook_file ||= File.read(Rails.root.join('lib', 'hooks', 'post-receive'))
|
||||||
|
end
|
||||||
|
|
||||||
|
def hook_file
|
||||||
|
@hook_file ||= begin
|
||||||
|
hook_path = File.join(path_to_repo, 'hooks', 'post-receive')
|
||||||
|
File.read(hook_path) if File.exists?(hook_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns an Array of branch names
|
||||||
|
def branch_names
|
||||||
|
repo.branches.collect(&:name).sort
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns an Array of Branches
|
||||||
|
def branches
|
||||||
|
repo.branches.sort_by(&:name)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns an Array of tag names
|
||||||
|
def tag_names
|
||||||
|
repo.tags.collect(&:name).sort.reverse
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns an Array of Tags
|
||||||
|
def tags
|
||||||
|
repo.tags.sort_by(&:name).reverse
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns an Array of branch and tag names
|
||||||
|
def ref_names
|
||||||
|
[branch_names + tag_names].flatten
|
||||||
|
end
|
||||||
|
|
||||||
|
def repo
|
||||||
|
@repo ||= Grit::Repo.new(path_to_repo)
|
||||||
|
end
|
||||||
|
|
||||||
|
def url_to_repo
|
||||||
|
git_host.url_to_repo(path_with_namespace)
|
||||||
|
end
|
||||||
|
|
||||||
|
def path_to_repo
|
||||||
|
File.join(Gitlab.config.gitolite.repos_path, "#{path_with_namespace}.git")
|
||||||
|
end
|
||||||
|
|
||||||
|
def namespace_dir
|
||||||
|
namespace.try(:path) || ''
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_repository
|
||||||
|
git_host.update_repository(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy_repository
|
||||||
|
git_host.remove_repository(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
|
||||||
|
|
||||||
|
# Discovers the default branch based on the repository's available branches
|
||||||
|
#
|
||||||
|
# - If no branches are present, returns nil
|
||||||
|
# - If one branch is present, returns its name
|
||||||
|
# - If two or more branches are present, returns the one that has a name
|
||||||
|
# matching root_ref (default_branch or 'master' if default_branch is nil)
|
||||||
|
def discover_default_branch
|
||||||
|
if branch_names.length == 0
|
||||||
|
nil
|
||||||
|
elsif branch_names.length == 1
|
||||||
|
branch_names.first
|
||||||
|
else
|
||||||
|
branch_names.select { |v| v == root_ref }.first
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_commits?
|
||||||
|
!!commit
|
||||||
|
rescue Grit::NoSuchPathError
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def root_ref
|
||||||
|
default_branch || "master"
|
||||||
|
end
|
||||||
|
|
||||||
|
def root_ref?(branch)
|
||||||
|
root_ref == branch
|
||||||
|
end
|
||||||
|
|
||||||
|
# Archive Project to .tar.gz
|
||||||
|
#
|
||||||
|
# Already packed repo archives stored at
|
||||||
|
# app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz
|
||||||
|
#
|
||||||
|
def archive_repo(ref)
|
||||||
|
ref = ref || self.root_ref
|
||||||
|
commit = self.commit(ref)
|
||||||
|
return nil unless commit
|
||||||
|
|
||||||
|
# Build file path
|
||||||
|
file_name = self.path + "-" + commit.id.to_s + ".tar.gz"
|
||||||
|
storage_path = Rails.root.join("tmp", "repositories", self.path_with_namespace)
|
||||||
|
file_path = File.join(storage_path, file_name)
|
||||||
|
|
||||||
|
# Put files into a directory before archiving
|
||||||
|
prefix = self.path + "/"
|
||||||
|
|
||||||
|
# Create file if not exists
|
||||||
|
unless File.exists?(file_path)
|
||||||
|
FileUtils.mkdir_p storage_path
|
||||||
|
file = self.repo.archive_to_file(ref, prefix, file_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
file_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def ssh_url_to_repo
|
||||||
|
url_to_repo
|
||||||
|
end
|
||||||
|
|
||||||
|
def http_url_to_repo
|
||||||
|
http_url = [Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('')
|
||||||
|
end
|
||||||
|
|
||||||
|
# Check if current branch name is marked as protected in the system
|
||||||
|
def protected_branch? branch_name
|
||||||
|
protected_branches.map(&:name).include?(branch_name)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -34,8 +34,6 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
class User < ActiveRecord::Base
|
class User < ActiveRecord::Base
|
||||||
include Account
|
|
||||||
|
|
||||||
devise :database_authenticatable, :token_authenticatable, :lockable,
|
devise :database_authenticatable, :token_authenticatable, :lockable,
|
||||||
:recoverable, :rememberable, :trackable, :validatable, :omniauthable
|
:recoverable, :rememberable, :trackable, :validatable, :omniauthable
|
||||||
|
|
||||||
|
@ -192,4 +190,92 @@ class User < ActiveRecord::Base
|
||||||
def tm_in_personal_projects
|
def tm_in_personal_projects
|
||||||
personal_projects.users_projects.where(user_id: self.id)
|
personal_projects.users_projects.where(user_id: self.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns a string for use as a Gitolite user identifier
|
||||||
|
#
|
||||||
|
# Note that Gitolite 2.x requires the following pattern for users:
|
||||||
|
#
|
||||||
|
# ^@?[0-9a-zA-Z][0-9a-zA-Z._\@+-]*$
|
||||||
|
def identifier
|
||||||
|
# Replace non-word chars with underscores, then make sure it starts with
|
||||||
|
# valid chars
|
||||||
|
email.gsub(/\W/, '_').gsub(/\A([\W\_])+/, '')
|
||||||
|
end
|
||||||
|
|
||||||
|
def is_admin?
|
||||||
|
admin
|
||||||
|
end
|
||||||
|
|
||||||
|
def require_ssh_key?
|
||||||
|
keys.count == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def can_create_project?
|
||||||
|
projects_limit > personal_projects.count
|
||||||
|
end
|
||||||
|
|
||||||
|
def can_create_group?
|
||||||
|
is_admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def abilities
|
||||||
|
@abilities ||= begin
|
||||||
|
abilities = Six.new
|
||||||
|
abilities << Ability
|
||||||
|
abilities
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def can? action, subject
|
||||||
|
abilities.allowed?(self, action, subject)
|
||||||
|
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)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Remove user from all projects and
|
||||||
|
# set blocked attribute to true
|
||||||
|
def block
|
||||||
|
users_projects.find_each do |membership|
|
||||||
|
return false unless membership.destroy
|
||||||
|
end
|
||||||
|
|
||||||
|
self.blocked = true
|
||||||
|
save
|
||||||
|
end
|
||||||
|
|
||||||
|
def projects_limit_percent
|
||||||
|
return 100 if projects_limit.zero?
|
||||||
|
(personal_projects.count.to_f / projects_limit) * 100
|
||||||
|
end
|
||||||
|
|
||||||
|
def recent_push project_id = nil
|
||||||
|
# Get push events not earlier than 2 hours ago
|
||||||
|
events = recent_events.code_push.where("created_at > ?", Time.now - 2.hours)
|
||||||
|
events = events.where(project_id: project_id) if project_id
|
||||||
|
|
||||||
|
# Take only latest one
|
||||||
|
events = events.recent.limit(1).first
|
||||||
|
end
|
||||||
|
|
||||||
|
def projects_sorted_by_activity
|
||||||
|
authorized_projects.sorted_by_activity
|
||||||
|
end
|
||||||
|
|
||||||
|
def several_namespaces?
|
||||||
|
namespaces.size > 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def namespace_id
|
||||||
|
namespace.try :id
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,95 +0,0 @@
|
||||||
# == Account role
|
|
||||||
#
|
|
||||||
# Describe behaviour of User in application
|
|
||||||
#
|
|
||||||
# Used by User
|
|
||||||
#
|
|
||||||
module Account
|
|
||||||
# Returns a string for use as a Gitolite user identifier
|
|
||||||
#
|
|
||||||
# Note that Gitolite 2.x requires the following pattern for users:
|
|
||||||
#
|
|
||||||
# ^@?[0-9a-zA-Z][0-9a-zA-Z._\@+-]*$
|
|
||||||
def identifier
|
|
||||||
# Replace non-word chars with underscores, then make sure it starts with
|
|
||||||
# valid chars
|
|
||||||
email.gsub(/\W/, '_').gsub(/\A([\W\_])+/, '')
|
|
||||||
end
|
|
||||||
|
|
||||||
def is_admin?
|
|
||||||
admin
|
|
||||||
end
|
|
||||||
|
|
||||||
def require_ssh_key?
|
|
||||||
keys.count == 0
|
|
||||||
end
|
|
||||||
|
|
||||||
def can_create_project?
|
|
||||||
projects_limit > personal_projects.count
|
|
||||||
end
|
|
||||||
|
|
||||||
def can_create_group?
|
|
||||||
is_admin?
|
|
||||||
end
|
|
||||||
|
|
||||||
def abilities
|
|
||||||
@abilities ||= begin
|
|
||||||
abilities = Six.new
|
|
||||||
abilities << Ability
|
|
||||||
abilities
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def can? action, subject
|
|
||||||
abilities.allowed?(self, action, subject)
|
|
||||||
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)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Remove user from all projects and
|
|
||||||
# set blocked attribute to true
|
|
||||||
def block
|
|
||||||
users_projects.find_each do |membership|
|
|
||||||
return false unless membership.destroy
|
|
||||||
end
|
|
||||||
|
|
||||||
self.blocked = true
|
|
||||||
save
|
|
||||||
end
|
|
||||||
|
|
||||||
def projects_limit_percent
|
|
||||||
return 100 if projects_limit.zero?
|
|
||||||
(personal_projects.count.to_f / projects_limit) * 100
|
|
||||||
end
|
|
||||||
|
|
||||||
def recent_push project_id = nil
|
|
||||||
# Get push events not earlier than 2 hours ago
|
|
||||||
events = recent_events.code_push.where("created_at > ?", Time.now - 2.hours)
|
|
||||||
events = events.where(project_id: project_id) if project_id
|
|
||||||
|
|
||||||
# Take only latest one
|
|
||||||
events = events.recent.limit(1).first
|
|
||||||
end
|
|
||||||
|
|
||||||
def projects_sorted_by_activity
|
|
||||||
authorized_projects.sorted_by_activity
|
|
||||||
end
|
|
||||||
|
|
||||||
def several_namespaces?
|
|
||||||
namespaces.size > 1
|
|
||||||
end
|
|
||||||
|
|
||||||
def namespace_id
|
|
||||||
namespace.try :id
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,68 +0,0 @@
|
||||||
# == Authority role
|
|
||||||
#
|
|
||||||
# Control access to project repository based on users role in team
|
|
||||||
#
|
|
||||||
# Used by Project
|
|
||||||
#
|
|
||||||
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
|
|
||||||
repository_members[UsersProject::REPORTER]
|
|
||||||
end
|
|
||||||
|
|
||||||
def repository_writers
|
|
||||||
repository_members[UsersProject::DEVELOPER]
|
|
||||||
end
|
|
||||||
|
|
||||||
def repository_masters
|
|
||||||
repository_members[UsersProject::MASTER]
|
|
||||||
end
|
|
||||||
|
|
||||||
def repository_members
|
|
||||||
keys = Hash.new {|h,k| h[k] = [] }
|
|
||||||
UsersProject.select("keys.identifier, project_access").
|
|
||||||
joins(user: :keys).where(project_id: id).
|
|
||||||
each {|row| keys[row.project_access] << [row.identifier] }
|
|
||||||
|
|
||||||
keys[UsersProject::REPORTER] += deploy_keys.pluck(:identifier)
|
|
||||||
keys
|
|
||||||
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?
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,60 +0,0 @@
|
||||||
# == NamespacedProject role
|
|
||||||
#
|
|
||||||
# Provides extra functionality for Project related to namespaces like:
|
|
||||||
# - transfer project between namespaces
|
|
||||||
# - name, path including namespece
|
|
||||||
# - project owner based on namespace
|
|
||||||
#
|
|
||||||
# Used by Project
|
|
||||||
#
|
|
||||||
module NamespacedProject
|
|
||||||
def transfer(new_namespace)
|
|
||||||
Project.transaction do
|
|
||||||
old_namespace = namespace
|
|
||||||
self.namespace = new_namespace
|
|
||||||
|
|
||||||
old_dir = old_namespace.try(:path) || ''
|
|
||||||
new_dir = new_namespace.try(:path) || ''
|
|
||||||
|
|
||||||
old_repo = if old_dir.present?
|
|
||||||
File.join(old_dir, self.path)
|
|
||||||
else
|
|
||||||
self.path
|
|
||||||
end
|
|
||||||
|
|
||||||
if Project.where(path: self.path, namespace_id: new_namespace.try(:id)).present?
|
|
||||||
raise TransferError.new("Project with same path in target namespace already exists")
|
|
||||||
end
|
|
||||||
|
|
||||||
Gitlab::ProjectMover.new(self, old_dir, new_dir).execute
|
|
||||||
|
|
||||||
git_host.move_repository(old_repo, self)
|
|
||||||
|
|
||||||
save!
|
|
||||||
end
|
|
||||||
rescue Gitlab::ProjectMover::ProjectMoveError => ex
|
|
||||||
raise Project::TransferError.new(ex.message)
|
|
||||||
end
|
|
||||||
|
|
||||||
def name_with_namespace
|
|
||||||
@name_with_namespace ||= begin
|
|
||||||
if namespace
|
|
||||||
namespace.human_name + " / " + name
|
|
||||||
else
|
|
||||||
name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def namespace_owner
|
|
||||||
namespace.try(:owner)
|
|
||||||
end
|
|
||||||
|
|
||||||
def path_with_namespace
|
|
||||||
if namespace
|
|
||||||
namespace.path + '/' + path
|
|
||||||
else
|
|
||||||
path
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,43 +0,0 @@
|
||||||
# == NoteEvent role
|
|
||||||
#
|
|
||||||
# Extends Event model functionality by providing extra methods related to comment events
|
|
||||||
#
|
|
||||||
# Used by Event
|
|
||||||
#
|
|
||||||
module NoteEvent
|
|
||||||
def note_commit_id
|
|
||||||
target.commit_id
|
|
||||||
end
|
|
||||||
|
|
||||||
def note_short_commit_id
|
|
||||||
note_commit_id[0..8]
|
|
||||||
end
|
|
||||||
|
|
||||||
def note_commit?
|
|
||||||
target.noteable_type == "Commit"
|
|
||||||
end
|
|
||||||
|
|
||||||
def note_target
|
|
||||||
target.noteable
|
|
||||||
end
|
|
||||||
|
|
||||||
def note_target_id
|
|
||||||
if note_commit?
|
|
||||||
target.commit_id
|
|
||||||
else
|
|
||||||
target.noteable_id.to_s
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def wall_note?
|
|
||||||
target.noteable_type.blank?
|
|
||||||
end
|
|
||||||
|
|
||||||
def note_target_type
|
|
||||||
if target.noteable_type.present?
|
|
||||||
target.noteable_type.titleize
|
|
||||||
else
|
|
||||||
"Wall"
|
|
||||||
end.downcase
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,106 +0,0 @@
|
||||||
# == PushEvent role
|
|
||||||
#
|
|
||||||
# Extends Event model functionality by providing extra methods related to push events
|
|
||||||
#
|
|
||||||
# Used by Event
|
|
||||||
#
|
|
||||||
module PushEvent
|
|
||||||
def valid_push?
|
|
||||||
data[:ref]
|
|
||||||
rescue => ex
|
|
||||||
false
|
|
||||||
end
|
|
||||||
|
|
||||||
def tag?
|
|
||||||
data[:ref]["refs/tags"]
|
|
||||||
end
|
|
||||||
|
|
||||||
def branch?
|
|
||||||
data[:ref]["refs/heads"]
|
|
||||||
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?
|
|
||||||
"deleted"
|
|
||||||
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
|
|
||||||
rescue Grit::NoSuchPathError
|
|
||||||
false
|
|
||||||
end
|
|
||||||
|
|
||||||
def last_push_to_non_root?
|
|
||||||
branch? && project.default_branch != branch_name
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,149 +0,0 @@
|
||||||
# == PushObserver role
|
|
||||||
#
|
|
||||||
# Includes methods to be triggered on push to project repository.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# Used by Project
|
|
||||||
# Triggered by PostReceive job
|
|
||||||
#
|
|
||||||
module PushObserver
|
|
||||||
# This method will be called after each post receive and only if the provided
|
|
||||||
# user is present in GitLab.
|
|
||||||
#
|
|
||||||
# All callbacks for post receive should be placed here.
|
|
||||||
def trigger_post_receive(oldrev, newrev, ref, user)
|
|
||||||
data = post_receive_data(oldrev, newrev, ref, user)
|
|
||||||
|
|
||||||
# Create push event
|
|
||||||
self.observe_push(data)
|
|
||||||
|
|
||||||
if push_to_branch? ref, oldrev
|
|
||||||
# Close merged MR
|
|
||||||
self.update_merge_requests(oldrev, newrev, ref, user)
|
|
||||||
|
|
||||||
# Execute web hooks
|
|
||||||
self.execute_hooks(data.dup)
|
|
||||||
|
|
||||||
# Execute project services
|
|
||||||
self.execute_services(data.dup)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Create satellite
|
|
||||||
self.satellite.create unless self.satellite.exists?
|
|
||||||
|
|
||||||
# Discover the default branch, but only if it hasn't already been set to
|
|
||||||
# something else
|
|
||||||
if default_branch.nil?
|
|
||||||
update_attributes(default_branch: discover_default_branch)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def push_to_branch? ref, oldrev
|
|
||||||
ref_parts = ref.split('/')
|
|
||||||
|
|
||||||
# Return if this is not a push to a branch (e.g. new commits)
|
|
||||||
!(ref_parts[1] !~ /heads/ || oldrev == "00000000000000000000000000000000")
|
|
||||||
end
|
|
||||||
|
|
||||||
def observe_push(data)
|
|
||||||
Event.create(
|
|
||||||
project: self,
|
|
||||||
action: Event::Pushed,
|
|
||||||
data: data,
|
|
||||||
author_id: data[:user_id]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def execute_hooks(data)
|
|
||||||
hooks.each { |hook| hook.execute(data) }
|
|
||||||
end
|
|
||||||
|
|
||||||
def execute_services(data)
|
|
||||||
services.each do |service|
|
|
||||||
|
|
||||||
# Call service hook only if it is active
|
|
||||||
service.execute(data) if service.active
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Produce a hash of post-receive data
|
|
||||||
#
|
|
||||||
# data = {
|
|
||||||
# before: String,
|
|
||||||
# after: String,
|
|
||||||
# ref: String,
|
|
||||||
# user_id: String,
|
|
||||||
# user_name: String,
|
|
||||||
# repository: {
|
|
||||||
# name: String,
|
|
||||||
# url: String,
|
|
||||||
# description: String,
|
|
||||||
# homepage: String,
|
|
||||||
# },
|
|
||||||
# commits: Array,
|
|
||||||
# total_commits_count: Fixnum
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
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: url_to_repo,
|
|
||||||
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: "#{Gitlab.config.gitlab.url}/#{path_with_namespace}/commit/#{commit.id}",
|
|
||||||
author: {
|
|
||||||
name: commit.author_name,
|
|
||||||
email: commit.author_email
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
data
|
|
||||||
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
|
|
||||||
end
|
|
|
@ -1,216 +0,0 @@
|
||||||
# == Repository role
|
|
||||||
#
|
|
||||||
# Provides access to git repository resources like commits, branches etc..
|
|
||||||
# Allows you to manage repository via gitolite interface(git_host)
|
|
||||||
#
|
|
||||||
# Used by Project
|
|
||||||
#
|
|
||||||
module Repository
|
|
||||||
include GitHost
|
|
||||||
|
|
||||||
def valid_repo?
|
|
||||||
repo
|
|
||||||
rescue
|
|
||||||
errors.add(:path, "Invalid repository path")
|
|
||||||
false
|
|
||||||
end
|
|
||||||
|
|
||||||
def empty_repo?
|
|
||||||
!repo_exists? || !has_commits?
|
|
||||||
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 last_commit_for(ref, path = nil)
|
|
||||||
commits(ref, path, 1).first
|
|
||||||
end
|
|
||||||
|
|
||||||
def commits_between(from, to)
|
|
||||||
Commit.commits_between(repo, from, to)
|
|
||||||
end
|
|
||||||
|
|
||||||
def satellite
|
|
||||||
@satellite ||= Gitlab::Satellite::Satellite.new(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
def has_post_receive_file?
|
|
||||||
!!hook_file
|
|
||||||
end
|
|
||||||
|
|
||||||
def valid_post_receive_file?
|
|
||||||
valid_hook_file == hook_file
|
|
||||||
end
|
|
||||||
|
|
||||||
def valid_hook_file
|
|
||||||
@valid_hook_file ||= File.read(Rails.root.join('lib', 'hooks', 'post-receive'))
|
|
||||||
end
|
|
||||||
|
|
||||||
def hook_file
|
|
||||||
@hook_file ||= begin
|
|
||||||
hook_path = File.join(path_to_repo, 'hooks', 'post-receive')
|
|
||||||
File.read(hook_path) if File.exists?(hook_path)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns an Array of branch names
|
|
||||||
def branch_names
|
|
||||||
repo.branches.collect(&:name).sort
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns an Array of Branches
|
|
||||||
def branches
|
|
||||||
repo.branches.sort_by(&:name)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns an Array of tag names
|
|
||||||
def tag_names
|
|
||||||
repo.tags.collect(&:name).sort.reverse
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns an Array of Tags
|
|
||||||
def tags
|
|
||||||
repo.tags.sort_by(&:name).reverse
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns an Array of branch and tag names
|
|
||||||
def ref_names
|
|
||||||
[branch_names + tag_names].flatten
|
|
||||||
end
|
|
||||||
|
|
||||||
def repo
|
|
||||||
@repo ||= Grit::Repo.new(path_to_repo)
|
|
||||||
end
|
|
||||||
|
|
||||||
def url_to_repo
|
|
||||||
git_host.url_to_repo(path_with_namespace)
|
|
||||||
end
|
|
||||||
|
|
||||||
def path_to_repo
|
|
||||||
File.join(Gitlab.config.gitolite.repos_path, "#{path_with_namespace}.git")
|
|
||||||
end
|
|
||||||
|
|
||||||
def namespace_dir
|
|
||||||
namespace.try(:path) || ''
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_repository
|
|
||||||
git_host.update_repository(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
def destroy_repository
|
|
||||||
git_host.remove_repository(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
|
|
||||||
|
|
||||||
# Discovers the default branch based on the repository's available branches
|
|
||||||
#
|
|
||||||
# - If no branches are present, returns nil
|
|
||||||
# - If one branch is present, returns its name
|
|
||||||
# - If two or more branches are present, returns the one that has a name
|
|
||||||
# matching root_ref (default_branch or 'master' if default_branch is nil)
|
|
||||||
def discover_default_branch
|
|
||||||
if branch_names.length == 0
|
|
||||||
nil
|
|
||||||
elsif branch_names.length == 1
|
|
||||||
branch_names.first
|
|
||||||
else
|
|
||||||
branch_names.select { |v| v == root_ref }.first
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def has_commits?
|
|
||||||
!!commit
|
|
||||||
rescue Grit::NoSuchPathError
|
|
||||||
false
|
|
||||||
end
|
|
||||||
|
|
||||||
def root_ref
|
|
||||||
default_branch || "master"
|
|
||||||
end
|
|
||||||
|
|
||||||
def root_ref?(branch)
|
|
||||||
root_ref == branch
|
|
||||||
end
|
|
||||||
|
|
||||||
# Archive Project to .tar.gz
|
|
||||||
#
|
|
||||||
# Already packed repo archives stored at
|
|
||||||
# app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz
|
|
||||||
#
|
|
||||||
def archive_repo(ref)
|
|
||||||
ref = ref || self.root_ref
|
|
||||||
commit = self.commit(ref)
|
|
||||||
return nil unless commit
|
|
||||||
|
|
||||||
# Build file path
|
|
||||||
file_name = self.path + "-" + commit.id.to_s + ".tar.gz"
|
|
||||||
storage_path = Rails.root.join("tmp", "repositories", self.path_with_namespace)
|
|
||||||
file_path = File.join(storage_path, file_name)
|
|
||||||
|
|
||||||
# Put files into a directory before archiving
|
|
||||||
prefix = self.path + "/"
|
|
||||||
|
|
||||||
# Create file if not exists
|
|
||||||
unless File.exists?(file_path)
|
|
||||||
FileUtils.mkdir_p storage_path
|
|
||||||
file = self.repo.archive_to_file(ref, prefix, file_path)
|
|
||||||
end
|
|
||||||
|
|
||||||
file_path
|
|
||||||
end
|
|
||||||
|
|
||||||
def ssh_url_to_repo
|
|
||||||
url_to_repo
|
|
||||||
end
|
|
||||||
|
|
||||||
def http_url_to_repo
|
|
||||||
http_url = [Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('')
|
|
||||||
end
|
|
||||||
|
|
||||||
# Check if current branch name is marked as protected in the system
|
|
||||||
def protected_branch? branch_name
|
|
||||||
protected_branches.map(&:name).include?(branch_name)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,63 +0,0 @@
|
||||||
# == Team role
|
|
||||||
#
|
|
||||||
# Provides functionality to manage project team
|
|
||||||
# - add user/users to project
|
|
||||||
# - update existing membership
|
|
||||||
# - remove users from project team
|
|
||||||
#
|
|
||||||
# Used by Project
|
|
||||||
#
|
|
||||||
module Team
|
|
||||||
def team_member_by_name_or_email(name = nil, email = nil)
|
|
||||||
user = users.where("name like ? or email like ?", name, email).first
|
|
||||||
users_projects.where(user: user) if user
|
|
||||||
end
|
|
||||||
|
|
||||||
# Get Team Member record by user id
|
|
||||||
def team_member_by_id(user_id)
|
|
||||||
users_projects.find_by_user_id(user_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Add user to project
|
|
||||||
# with passed access role
|
|
||||||
def add_user_to_team(user, access_role)
|
|
||||||
add_user_id_to_team(user.id, access_role)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Add multiple users to project
|
|
||||||
# with same access role
|
|
||||||
def add_users_to_team(users, access_role)
|
|
||||||
add_users_ids_to_team(users.map(&:id), access_role)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Add user to project
|
|
||||||
# with passed access role by user id
|
|
||||||
def add_user_id_to_team(user_id, access_role)
|
|
||||||
users_projects.create(
|
|
||||||
user_id: user_id,
|
|
||||||
project_access: access_role
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Add multiple users to project
|
|
||||||
# with same access role by user ids
|
|
||||||
def add_users_ids_to_team(users_ids, access_role)
|
|
||||||
UsersProject.bulk_import(self, users_ids, access_role)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Update multiple project users
|
|
||||||
# to same access role by user ids
|
|
||||||
def update_users_ids_to_role(users_ids, access_role)
|
|
||||||
UsersProject.bulk_update(self, users_ids, access_role)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Delete multiple users from project by user ids
|
|
||||||
def delete_users_ids_from_team(users_ids)
|
|
||||||
UsersProject.bulk_delete(self, users_ids)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Remove all users from project team
|
|
||||||
def truncate_team
|
|
||||||
UsersProject.truncate_team(self)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -68,5 +68,4 @@ module IssueCommonality
|
||||||
def is_being_reopened?
|
def is_being_reopened?
|
||||||
closed_changed? && !closed
|
closed_changed? && !closed
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
|
@ -185,4 +185,14 @@ describe User do
|
||||||
|
|
||||||
it { User.not_in_project(@project).should == [@user, @project.owner] }
|
it { User.not_in_project(@project).should == [@user, @project.owner] }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'normal user' do
|
||||||
|
let(:user) { create(:user, name: 'John Smith') }
|
||||||
|
|
||||||
|
it { user.is_admin?.should be_false }
|
||||||
|
it { user.require_ssh_key?.should be_true }
|
||||||
|
it { user.can_create_group?.should be_false }
|
||||||
|
it { user.can_create_project?.should be_true }
|
||||||
|
it { user.first_name.should == 'John' }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe User, "Account" do
|
|
||||||
describe 'normal user' do
|
|
||||||
let(:user) { create(:user, name: 'John Smith') }
|
|
||||||
|
|
||||||
it { user.is_admin?.should be_false }
|
|
||||||
it { user.require_ssh_key?.should be_true }
|
|
||||||
it { user.can_create_group?.should be_false }
|
|
||||||
it { user.can_create_project?.should be_true }
|
|
||||||
it { user.first_name.should == 'John' }
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Add table
Reference in a new issue