Añade plugin Redmine Git Hosting 4.0.2
This commit is contained in:
parent
472cb1ea76
commit
bdd66d941f
494 changed files with 36768 additions and 0 deletions
|
@ -0,0 +1,13 @@
|
|||
module Gitolitable
|
||||
extend ActiveSupport::Concern
|
||||
include Gitolitable::Authorizations
|
||||
include Gitolitable::Cache
|
||||
include Gitolitable::Config
|
||||
include Gitolitable::Features
|
||||
include Gitolitable::Notifications
|
||||
include Gitolitable::Paths
|
||||
include Gitolitable::Permissions
|
||||
include Gitolitable::Urls
|
||||
include Gitolitable::Users
|
||||
include Gitolitable::Validations
|
||||
end
|
|
@ -0,0 +1,89 @@
|
|||
module Gitolitable
|
||||
module Authorizations
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
# These are for repository Gitolite configuration
|
||||
|
||||
def git_daemon_available?
|
||||
User.anonymous.allowed_to?(:view_changesets, project) && git_daemon_enabled?
|
||||
end
|
||||
|
||||
|
||||
def git_web_available?
|
||||
User.anonymous.allowed_to?(:browse_repository, project) && smart_http_enabled?
|
||||
end
|
||||
|
||||
|
||||
def protected_branches_available?
|
||||
protected_branches_enabled? && project.active? && protected_branches.any?
|
||||
end
|
||||
|
||||
|
||||
def clonable_via_http?
|
||||
User.anonymous.allowed_to?(:view_changesets, project) || smart_http_enabled?
|
||||
end
|
||||
|
||||
|
||||
def pushable_via_http?
|
||||
https_access_enabled?
|
||||
end
|
||||
|
||||
|
||||
def git_notification_available?
|
||||
git_notification_enabled? && !mailing_list.empty?
|
||||
end
|
||||
|
||||
|
||||
# These are for repository URLs
|
||||
|
||||
def urls_are_viewable?
|
||||
RedmineGitHosting::Config.show_repositories_url? && User.current.allowed_to?(:view_changesets, project)
|
||||
end
|
||||
|
||||
|
||||
def ssh_access_available?
|
||||
git_ssh_enabled? && !git_annex_enabled? && User.current.allowed_to_commit?(self)
|
||||
end
|
||||
|
||||
|
||||
def https_access_available?
|
||||
https_access_enabled?
|
||||
end
|
||||
|
||||
|
||||
def http_access_available?
|
||||
http_access_enabled?
|
||||
end
|
||||
|
||||
|
||||
def git_access_available?
|
||||
(public_project? || public_repo?) && git_daemon_enabled?
|
||||
end
|
||||
|
||||
|
||||
def go_access_available?
|
||||
(public_project? || public_repo?) && smart_http_enabled? && git_go_enabled?
|
||||
end
|
||||
|
||||
|
||||
def git_annex_access_available?
|
||||
git_annex_enabled?
|
||||
end
|
||||
|
||||
|
||||
def downloadable?
|
||||
git_annex_enabled? ? false : User.current.allowed_to_download?(self)
|
||||
end
|
||||
|
||||
|
||||
def deletable?
|
||||
RedmineGitHosting::Config.delete_git_repositories?
|
||||
end
|
||||
|
||||
|
||||
def movable?
|
||||
!identifier.nil? && !identifier.empty?
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,90 @@
|
|||
module Gitolitable
|
||||
module Cache
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
class << self
|
||||
|
||||
# Are repositories identifier unique?
|
||||
#
|
||||
def repo_ident_unique?
|
||||
RedmineGitHosting::Config.unique_repo_identifier?
|
||||
end
|
||||
|
||||
|
||||
# Translate repository path into a unique ID for use in caching of git commands.
|
||||
#
|
||||
def repo_path_to_git_cache_id(repo_path)
|
||||
repo = find_by_path(repo_path, loose: true)
|
||||
repo ? repo.git_cache_id : nil
|
||||
end
|
||||
|
||||
|
||||
# Parse a path of the form <proj1>/<proj2>/<proj3>/<repo> and return the specified
|
||||
# repository. If either 'repo_ident_unique?' is true or the <repo> is a project
|
||||
# identifier, just return the last component. Otherwise,
|
||||
# use the immediate parent (<proj3>) to try to identify the repo.
|
||||
#
|
||||
# Flags:
|
||||
# :loose => true : Try to identify corresponding repo even if path is not quite correct
|
||||
#
|
||||
# Note that the :loose flag is used when interpreting the contents of the
|
||||
# repository. If switching back and forth between the "repo_ident_unique?"
|
||||
# form, it will still identify the repository (as long as there are not more than
|
||||
# one repo with the same identifier.
|
||||
#
|
||||
# Example of data captured by regex :
|
||||
# <MatchData "test/test2/test3/test4/test5.git" 1:"test4/" 2:"test4" 3:"test5" 4:".git">
|
||||
# <MatchData "blabla2.git" 1:nil 2:nil 3:"blabla2" 4:".git">
|
||||
#
|
||||
def find_by_path(path, flags = {})
|
||||
parseit = path.match(/\A.*?(([^\/]+)\/)?([^\/]+?)(\.git)?\z/)
|
||||
return nil if parseit.nil?
|
||||
|
||||
project = Project.find_by_identifier(parseit[3])
|
||||
|
||||
# return default or first repo with blank identifier (or first Git repo--very rare?)
|
||||
if project
|
||||
project.repository || project.repo_blank_ident || project.gitolite_repos.first
|
||||
|
||||
elsif repo_ident_unique? || flags[:loose] && parseit[2].nil?
|
||||
find_by_identifier(parseit[3])
|
||||
|
||||
elsif parseit[2]
|
||||
project = Project.find_by_identifier(parseit[2])
|
||||
|
||||
if project.nil?
|
||||
find_by_identifier(parseit[3])
|
||||
else
|
||||
find_by_identifier_and_project_id(parseit[3], project.id) || (flags[:loose] && find_by_identifier(parseit[3]))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# If repositories identifiers are unique, identifier forms a unique label,
|
||||
# else use directory notation: <project identifier>/<repo identifier>
|
||||
#
|
||||
def git_cache_id
|
||||
if identifier.blank?
|
||||
# Should only happen with one repo/project (the default)
|
||||
project.identifier
|
||||
elsif self.class.repo_ident_unique?
|
||||
identifier
|
||||
else
|
||||
"#{project.identifier}/#{identifier}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Note: RedmineGitHosting::Cache doesn't know about repository object, it only knows *git_cache_id*.
|
||||
#
|
||||
def empty_cache!
|
||||
RedmineGitHosting::Cache.clear_cache_for_repository(git_cache_id)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,85 @@
|
|||
module Gitolitable
|
||||
module Config
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def git_config
|
||||
repo_conf = {}
|
||||
|
||||
# This is needed for all Redmine repositories
|
||||
repo_conf['redminegitolite.projectid'] = project.identifier.to_s
|
||||
repo_conf['redminegitolite.repositoryid'] = identifier || ''
|
||||
repo_conf['redminegitolite.repositorykey'] = gitolite_hook_key
|
||||
|
||||
if project.active?
|
||||
repo_conf['http.uploadpack'] = clonable_via_http?.to_s
|
||||
repo_conf['http.receivepack'] = pushable_via_http?.to_s
|
||||
|
||||
if git_notification_available?
|
||||
repo_conf['multimailhook.enabled'] = 'true'
|
||||
repo_conf['multimailhook.mailinglist'] = mailing_list.join(', ')
|
||||
repo_conf['multimailhook.from'] = sender_address
|
||||
repo_conf['multimailhook.emailPrefix'] = email_prefix
|
||||
else
|
||||
repo_conf['multimailhook.enabled'] = 'false'
|
||||
end
|
||||
|
||||
git_config_keys.each do |git|
|
||||
repo_conf[git.key] = git.value
|
||||
end if git_config_keys.any?
|
||||
|
||||
else
|
||||
# Disable repository
|
||||
repo_conf['http.uploadpack'] = 'false'
|
||||
repo_conf['http.receivepack'] = 'false'
|
||||
repo_conf['multimailhook.enabled'] = 'false'
|
||||
end
|
||||
|
||||
repo_conf
|
||||
end
|
||||
|
||||
|
||||
def gitolite_options
|
||||
repo_conf = {}
|
||||
|
||||
git_option_keys.each do |option|
|
||||
repo_conf[option.key] = option.value
|
||||
end if git_option_keys.any?
|
||||
|
||||
repo_conf
|
||||
end
|
||||
|
||||
|
||||
def owner
|
||||
{ name: Setting['app_title'], email: Setting['mail_from'] }
|
||||
end
|
||||
|
||||
|
||||
def github_payload
|
||||
{
|
||||
repository: {
|
||||
owner: owner,
|
||||
description: project.description,
|
||||
fork: false,
|
||||
forks: 0,
|
||||
homepage: project.homepage,
|
||||
name: redmine_name,
|
||||
open_issues: project.issues.open.length,
|
||||
watchers: 0,
|
||||
private: !project.is_public,
|
||||
url: repository_url
|
||||
},
|
||||
pusher: owner,
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def repository_url
|
||||
Rails.application.routes.url_helpers.url_for(
|
||||
controller: 'repositories', action: 'show',
|
||||
id: project, repository_id: identifier_param,
|
||||
only_path: false, host: Setting['host_name'], protocol: Setting['protocol']
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,97 @@
|
|||
module Gitolitable
|
||||
module Features
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
# Always true to force repository fetch_changesets.
|
||||
def report_last_commit
|
||||
true
|
||||
end
|
||||
|
||||
|
||||
# Always true to force repository fetch_changesets.
|
||||
def extra_report_last_commit
|
||||
true
|
||||
end
|
||||
|
||||
|
||||
def git_default_branch
|
||||
extra[:default_branch]
|
||||
end
|
||||
|
||||
|
||||
def gitolite_hook_key
|
||||
extra[:key]
|
||||
end
|
||||
|
||||
|
||||
def git_daemon_enabled?
|
||||
extra[:git_daemon]
|
||||
end
|
||||
|
||||
|
||||
def git_annex_enabled?
|
||||
extra[:git_annex]
|
||||
end
|
||||
|
||||
|
||||
def git_notification_enabled?
|
||||
extra[:git_notify]
|
||||
end
|
||||
|
||||
|
||||
def git_ssh_enabled?
|
||||
extra[:git_ssh]
|
||||
end
|
||||
|
||||
|
||||
def git_go_enabled?
|
||||
extra[:git_go]
|
||||
end
|
||||
|
||||
|
||||
def https_access_enabled?
|
||||
extra[:git_https]
|
||||
end
|
||||
|
||||
|
||||
def http_access_enabled?
|
||||
extra[:git_http]
|
||||
end
|
||||
|
||||
|
||||
def smart_http_enabled?
|
||||
https_access_enabled? || http_access_enabled?
|
||||
end
|
||||
|
||||
|
||||
def only_https_access_enabled?
|
||||
https_access_enabled? && !http_access_enabled?
|
||||
end
|
||||
|
||||
|
||||
def only_http_access_enabled?
|
||||
http_access_enabled? && !https_access_enabled?
|
||||
end
|
||||
|
||||
|
||||
def protected_branches_enabled?
|
||||
extra[:protected_branch]
|
||||
end
|
||||
|
||||
|
||||
def public_project?
|
||||
project.is_public?
|
||||
end
|
||||
|
||||
|
||||
def public_repo?
|
||||
extra[:public_repo]
|
||||
end
|
||||
|
||||
|
||||
def urls_order
|
||||
extra[:urls_order]
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,43 @@
|
|||
module Gitolitable
|
||||
module Notifications
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def mailing_list
|
||||
default_list + global_include_list - global_exclude_list
|
||||
end
|
||||
|
||||
|
||||
def default_list
|
||||
watcher_users.map(&:email_address).map(&:address)
|
||||
end
|
||||
|
||||
|
||||
def global_include_list
|
||||
RedmineGitHosting::Config.gitolite_notify_global_include
|
||||
end
|
||||
|
||||
|
||||
def global_exclude_list
|
||||
RedmineGitHosting::Config.gitolite_notify_global_exclude
|
||||
end
|
||||
|
||||
|
||||
def sender_address
|
||||
if extra.notification_sender.nil? || extra.notification_sender.empty?
|
||||
RedmineGitHosting::Config.gitolite_notify_global_sender_address
|
||||
else
|
||||
extra.notification_sender
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def email_prefix
|
||||
if extra.notification_prefix.nil? || extra.notification_prefix.empty?
|
||||
RedmineGitHosting::Config.gitolite_notify_global_prefix
|
||||
else
|
||||
extra.notification_prefix
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,94 @@
|
|||
module Gitolitable
|
||||
module Paths
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
|
||||
# This is the repository path from Redmine point of view.
|
||||
# It is used to build HTTP(s) urls (including GoLang url).
|
||||
# It doesn't contain references to internal directories like *gitolite_global_storage_dir* or *gitolite_redmine_storage_dir*
|
||||
# to stay abstract from the real repository location.
|
||||
# In this case, the real repository path is deduced from the path given thanks to the *find_by_path* method.
|
||||
#
|
||||
# Example : blabla/test-blabla/uuuuuuuuuuu/oooooo
|
||||
#
|
||||
# Call File.expand_path to add then remove heading /
|
||||
#
|
||||
def redmine_repository_path
|
||||
File.expand_path(File.join('./', get_full_parent_path, git_cache_id), '/')[1..-1]
|
||||
end
|
||||
|
||||
|
||||
# This is the Gitolite repository identifier as it should appear in Gitolite config file.
|
||||
# Example : redmine/blabla/test-blabla/uuuuuuuuuuu/oooooo
|
||||
# (with 'redmine' a subdir of the Gitolite storage directory)
|
||||
#
|
||||
# Call File.expand_path to add then remove heading /
|
||||
#
|
||||
def gitolite_repository_name
|
||||
File.expand_path(File.join('./', RedmineGitHosting::Config.gitolite_redmine_storage_dir, get_full_parent_path, git_cache_id), '/')[1..-1]
|
||||
end
|
||||
|
||||
|
||||
# The Gitolite repository identifier with the .git extension.
|
||||
# Example : redmine/blabla/test-blabla/uuuuuuuuuuu/oooooo.git
|
||||
#
|
||||
def gitolite_repository_name_with_extension
|
||||
"#{gitolite_repository_name}.git"
|
||||
end
|
||||
|
||||
|
||||
# This is the relative path to the Gitolite repository.
|
||||
# Example : repositories/redmine/blabla/test-blabla/uuuuuuuuuuu/oooooo.git
|
||||
# (with 'repositories' the Gitolite storage directory).
|
||||
#
|
||||
def gitolite_repository_path
|
||||
File.join(RedmineGitHosting::Config.gitolite_global_storage_dir, gitolite_repository_name_with_extension)
|
||||
end
|
||||
|
||||
|
||||
# This is the full absolute path to the Gitolite repository.
|
||||
# Example : /home/git/repositories/redmine/blabla/test-blabla/uuuuuuuuuuu/oooooo.git
|
||||
#
|
||||
def gitolite_full_repository_path
|
||||
File.join(RedmineGitHosting::Config.gitolite_home_dir, gitolite_repository_path)
|
||||
end
|
||||
|
||||
|
||||
# A syntaxic sugar used to move repository from a location to an other
|
||||
# Example : repositories/blabla/test-blabla/uuuuuuuuuuu/oooooo
|
||||
#
|
||||
def new_repository_name
|
||||
gitolite_repository_name
|
||||
end
|
||||
|
||||
|
||||
# Used to move repository from a location to an other.
|
||||
# At this point repository url still points to the old location but
|
||||
# it contains the Gitolite storage directory in its path and the '.git' extension.
|
||||
# Strip them to get the old repository name.
|
||||
# Example :
|
||||
# before : repositories/redmine/blabla/test-blabla/uuuuuuuuuuu/oooooo.git
|
||||
# after : redmine/blabla/test-blabla/uuuuuuuuuuu/oooooo
|
||||
#
|
||||
def old_repository_name
|
||||
url.gsub(RedmineGitHosting::Config.gitolite_global_storage_dir, '').gsub('.git', '')
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
def get_full_parent_path
|
||||
return '' if !RedmineGitHosting::Config.hierarchical_organisation?
|
||||
parent_parts = []
|
||||
p = project
|
||||
while p.parent
|
||||
parent_id = p.parent.identifier.to_s
|
||||
parent_parts.unshift(parent_id)
|
||||
p = p.parent
|
||||
end
|
||||
parent_parts.join('/')
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,66 @@
|
|||
module Gitolitable
|
||||
module Permissions
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def build_gitolite_permissions(old_perms = {})
|
||||
permissions_builder.build(self, gitolite_users, old_perms)
|
||||
end
|
||||
|
||||
|
||||
# We assume here that ':gitolite_config_file' is different than 'gitolite.conf'
|
||||
# like 'redmine.conf' with 'include "redmine.conf"' in 'gitolite.conf'.
|
||||
# This way, we know that all repos in this file are managed by Redmine so we
|
||||
# don't need to backup users
|
||||
#
|
||||
def backup_gitolite_permissions(current_permissions)
|
||||
if protected_branches_available? || RedmineGitHosting::Config.gitolite_identifier_prefix == ''
|
||||
{}
|
||||
else
|
||||
extract_permissions(current_permissions)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
def permissions_builder
|
||||
if protected_branches_available?
|
||||
PermissionsBuilder::ProtectedBranches
|
||||
else
|
||||
PermissionsBuilder::Standard
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
SKIP_USERS = ['gitweb', 'daemon', 'DUMMY_REDMINE_KEY', 'REDMINE_ARCHIVED_PROJECT', 'REDMINE_CLOSED_PROJECT']
|
||||
|
||||
|
||||
def extract_permissions(current_permissions)
|
||||
old_permissions = {}
|
||||
|
||||
current_permissions.each do |perm, branch_settings|
|
||||
old_permissions[perm] = {}
|
||||
|
||||
branch_settings.each do |branch, user_list|
|
||||
next if user_list.empty?
|
||||
|
||||
new_user_list = []
|
||||
|
||||
user_list.each do |user|
|
||||
# ignore these users
|
||||
next if SKIP_USERS.include?(user)
|
||||
|
||||
# backup users that are not Redmine users
|
||||
new_user_list.push(user) if !user.include?(RedmineGitHosting::Config.gitolite_identifier_prefix)
|
||||
end
|
||||
|
||||
old_permissions[perm][branch] = new_user_list if new_user_list.any?
|
||||
end
|
||||
end
|
||||
|
||||
old_permissions
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,122 @@
|
|||
module Gitolitable
|
||||
module Urls
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def http_user_login
|
||||
User.current.anonymous? ? '' : "#{User.current.login}@"
|
||||
end
|
||||
|
||||
|
||||
def git_access_path
|
||||
gitolite_repository_name_with_extension
|
||||
end
|
||||
|
||||
|
||||
def http_access_path
|
||||
"#{RedmineGitHosting::Config.http_server_subdir}#{redmine_repository_path}.git"
|
||||
end
|
||||
|
||||
|
||||
def go_access_path
|
||||
"go/#{redmine_repository_path}"
|
||||
end
|
||||
|
||||
|
||||
def ssh_url
|
||||
"ssh://#{RedmineGitHosting::Config.gitolite_user}@#{RedmineGitHosting::Config.ssh_server_domain}/#{git_access_path}"
|
||||
end
|
||||
|
||||
|
||||
def git_url
|
||||
"git://#{RedmineGitHosting::Config.ssh_server_domain}/#{git_access_path}"
|
||||
end
|
||||
|
||||
|
||||
def http_url
|
||||
"http://#{http_user_login}#{RedmineGitHosting::Config.http_root_url}/#{http_access_path}"
|
||||
end
|
||||
|
||||
|
||||
def https_url
|
||||
"https://#{http_user_login}#{RedmineGitHosting::Config.https_root_url}/#{http_access_path}"
|
||||
end
|
||||
|
||||
|
||||
def git_annex_url
|
||||
"#{RedmineGitHosting::Config.gitolite_user}@#{RedmineGitHosting::Config.ssh_server_domain}:#{git_access_path}"
|
||||
end
|
||||
|
||||
|
||||
# This is the url used by Go to clone repository
|
||||
#
|
||||
def go_access_url
|
||||
return '' if !smart_http_enabled?
|
||||
return https_url if https_access_available?
|
||||
return http_url if http_access_available?
|
||||
end
|
||||
|
||||
|
||||
# This is the url to add in Go files
|
||||
#
|
||||
def go_url
|
||||
return '' if !smart_http_enabled?
|
||||
return "#{RedmineGitHosting::Config.https_root_url}/#{go_access_path}" if https_access_available?
|
||||
return "#{RedmineGitHosting::Config.http_root_url}/#{go_access_path}" if http_access_available?
|
||||
end
|
||||
|
||||
|
||||
def ssh_access
|
||||
{ url: ssh_url, committer: User.current.allowed_to_commit?(self).to_s }
|
||||
end
|
||||
|
||||
|
||||
## Unsecure channels (clear password), commit is disabled
|
||||
def http_access
|
||||
{ url: http_url, committer: 'false' }
|
||||
end
|
||||
|
||||
|
||||
def https_access
|
||||
{ url: https_url, committer: User.current.allowed_to_commit?(self).to_s }
|
||||
end
|
||||
|
||||
|
||||
def git_access
|
||||
{ url: git_url, committer: 'false' }
|
||||
end
|
||||
|
||||
|
||||
def git_annex_access
|
||||
{ url: git_annex_url, committer: User.current.allowed_to_commit?(self).to_s }
|
||||
end
|
||||
|
||||
|
||||
def go_access
|
||||
{ url: go_url, committer: 'false' }
|
||||
end
|
||||
|
||||
|
||||
def available_urls
|
||||
hash = {}
|
||||
hash[:ssh] = ssh_access if ssh_access_available?
|
||||
hash[:https] = https_access if https_access_available?
|
||||
hash[:http] = http_access if http_access_available?
|
||||
hash[:git] = git_access if git_access_available?
|
||||
hash[:go] = go_access if go_access_available?
|
||||
hash[:git_annex] = git_annex_access if git_annex_access_available?
|
||||
hash
|
||||
end
|
||||
|
||||
|
||||
def available_urls_sorted
|
||||
return available_urls if urls_order.nil? || urls_order.empty?
|
||||
hash = {}
|
||||
urls_order.each do |url|
|
||||
next if !available_urls[url.to_sym]
|
||||
hash[url.to_sym] = available_urls[url.to_sym]
|
||||
end
|
||||
hash
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,109 @@
|
|||
module Gitolitable
|
||||
module Users
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def gitolite_users
|
||||
if project.active?
|
||||
users_for_active_project
|
||||
elsif project.archived?
|
||||
users_for_archived_project
|
||||
else
|
||||
users_for_closed_project
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def users_for_active_project
|
||||
data = {}
|
||||
data[:rewind_users] = rewind_users + rewind_deploy_users
|
||||
data[:write_users] = write_users
|
||||
data[:read_users] = read_users + read_deploy_users
|
||||
data[:developer_team] = developer_team
|
||||
data[:all_read] = all_users
|
||||
|
||||
# Add other users
|
||||
data[:read_users] << 'DUMMY_REDMINE_KEY' if read_users.empty? && write_users.empty? && rewind_users.empty?
|
||||
data[:read_users] << 'gitweb' if git_web_available?
|
||||
data[:read_users] << 'daemon' if git_daemon_available?
|
||||
|
||||
# Return users
|
||||
data
|
||||
end
|
||||
|
||||
|
||||
def users_for_archived_project
|
||||
data = {}
|
||||
data[:read_users] = ['REDMINE_ARCHIVED_PROJECT']
|
||||
data
|
||||
end
|
||||
|
||||
|
||||
def users_for_closed_project
|
||||
data = {}
|
||||
data[:read_users] = all_users
|
||||
data[:read_users] << 'REDMINE_CLOSED_PROJECT'
|
||||
data
|
||||
end
|
||||
|
||||
|
||||
def users
|
||||
project.users_available
|
||||
end
|
||||
|
||||
|
||||
def rewind_users
|
||||
@rewind_users ||= users.select { |u| u.allowed_to?(:manage_repository, project) }.map { |u| u.gitolite_identifier }.sort
|
||||
end
|
||||
|
||||
|
||||
def write_users
|
||||
@write_users ||= users.select { |u| u.allowed_to?(:commit_access, project) }.map { |u| u.gitolite_identifier }.sort - rewind_users
|
||||
end
|
||||
|
||||
|
||||
def read_users
|
||||
@read_users ||= users.select { |u| u.allowed_to?(:view_changesets, project) }.map { |u| u.gitolite_identifier }.sort - rewind_users - write_users
|
||||
end
|
||||
|
||||
|
||||
def developer_team
|
||||
@developer_team ||= (rewind_users + write_users).sort
|
||||
end
|
||||
|
||||
|
||||
def all_users
|
||||
@all_users ||= (rewind_users + write_users + read_users).sort
|
||||
end
|
||||
|
||||
|
||||
def rewind_deploy_users
|
||||
deploy_users_for_keys(rewind_deploy_keys)
|
||||
end
|
||||
|
||||
|
||||
def read_deploy_users
|
||||
deploy_users_for_keys(read_deploy_keys)
|
||||
end
|
||||
|
||||
|
||||
def rewind_deploy_keys
|
||||
deploy_keys_by_perm('RW+')
|
||||
end
|
||||
|
||||
|
||||
def read_deploy_keys
|
||||
deploy_keys_by_perm('R')
|
||||
end
|
||||
|
||||
|
||||
def deploy_keys_by_perm(perm)
|
||||
deployment_credentials.active.select { |cred| cred.perm == perm }
|
||||
end
|
||||
|
||||
|
||||
def deploy_users_for_keys(keys)
|
||||
keys.map { |cred| cred.gitolite_public_key.owner }
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,122 @@
|
|||
module Gitolitable
|
||||
module Validations
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
# Set URL ourself as relative path.
|
||||
#
|
||||
before_validation :set_git_urls
|
||||
|
||||
# Make sure that identifier does not match Gitolite Admin repository
|
||||
#
|
||||
validates_exclusion_of :identifier, in: %w(gitolite-admin)
|
||||
|
||||
# Place additional constraints on repository identifiers
|
||||
# because of multi repos
|
||||
#
|
||||
validate :additional_constraints_on_identifier
|
||||
validate :identifier_dont_change
|
||||
validate :default_repository_has_identifier
|
||||
|
||||
class << self
|
||||
|
||||
# Build a hash of repository identifier :
|
||||
# <repo_1_identifier> => 1
|
||||
# <repo_2_identifier> => 1
|
||||
# etc...
|
||||
# If the same repository identifier is found many times, increment the corresponding counter.
|
||||
# Repository identifiers are unique if all values of the hash are 1.
|
||||
#
|
||||
def identifiers_to_hash
|
||||
self.all.map(&:identifier).inject(Hash.new(0)) do |h, x|
|
||||
h[x] += 1 unless x.blank?
|
||||
h
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def have_duplicated_identifier?
|
||||
(identifiers_to_hash.values.max || 0) > 1
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def exists_in_gitolite?
|
||||
RedmineGitHosting::Commands.sudo_dir_exists?(gitolite_repository_path)
|
||||
end
|
||||
|
||||
|
||||
def empty_in_gitolite?
|
||||
RedmineGitHosting::Commands.sudo_repository_empty?(gitolite_repository_path)
|
||||
end
|
||||
|
||||
|
||||
def git_objects_count
|
||||
RedmineGitHosting::Commands.sudo_git_objects_count(File.join(gitolite_repository_path, 'objects'))
|
||||
end
|
||||
|
||||
|
||||
def empty?
|
||||
extra_info.nil? || (!extra_info.has_key?('heads') && !extra_info.has_key?('branches'))
|
||||
end
|
||||
|
||||
|
||||
def data_for_destruction
|
||||
{
|
||||
repo_name: gitolite_repository_name,
|
||||
repo_path: gitolite_full_repository_path,
|
||||
delete_repository: deletable?,
|
||||
git_cache_id: git_cache_id
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
# Set up git urls for new repositories
|
||||
#
|
||||
def set_git_urls
|
||||
self.url = gitolite_repository_path if self.url.blank?
|
||||
self.root_url = self.url if self.root_url.blank?
|
||||
end
|
||||
|
||||
|
||||
# Check several aspects of repository identifier (only for Redmine 1.4+)
|
||||
# 1) cannot equal identifier of any project
|
||||
# 2) if repo_ident_unique? make sure that repo identifier is globally unique
|
||||
# 3) cannot make this repo the default if there will be some other repo with blank identifier
|
||||
#
|
||||
def additional_constraints_on_identifier
|
||||
if !identifier.blank? && (new_record? || identifier_changed?)
|
||||
errors.add(:identifier, :cannot_equal_project) if Project.find_by_identifier(identifier)
|
||||
|
||||
# See if a repo for another project has the same identifier (existing validations already check for current project)
|
||||
errors.add(:identifier, :taken) if self.class.repo_ident_unique? && Repository.where("identifier = ? and project_id <> ?", identifier, project.id).any?
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Make sure identifier hasn't changed. Allow null and blank
|
||||
# Note that simply using identifier_changed doesn't seem to work
|
||||
# if the identifier was "NULL" but the new identifier is ""
|
||||
#
|
||||
def identifier_dont_change
|
||||
return if new_record?
|
||||
errors.add(:identifier, :cannot_change) if (identifier_was.blank? && !identifier.blank?) || (!identifier_was.blank? && identifier_changed?)
|
||||
end
|
||||
|
||||
|
||||
# Need to make sure that we don't take the default slot away from a sibling repo with blank identifier
|
||||
#
|
||||
def default_repository_has_identifier
|
||||
if project && (is_default? || set_as_default?)
|
||||
possibles = Repository.where("project_id = ? and (identifier = '' or identifier is null)", project.id)
|
||||
errors.add(:base, :blank_default_exists) if possibles.any? && (new_record? || possibles.detect { |x| x.id != id })
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue