Skip to content

Support multiple repositories in same redmine project #36

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 15, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 62 additions & 52 deletions app/controllers/gitlab_hook_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,24 @@

class GitlabHookController < ActionController::Base

GIT_BIN = Redmine::Configuration['scm_git_command'] || 'git'
GIT_BIN = Redmine::Configuration[:scm_git_command] || 'git'
skip_before_filter :verify_authenticity_token, :check_if_login_required


def index
if request.post?
repositories = find_repositories
if repositories.empty?
render(:text => 'No repository configured!', :status => :not_found)
repository = find_repository
git_success = true
# Fetch the changes from GitLab
if Setting.plugin_redmine_gitlab_hook[:fetch_updates] == 'yes'
git_success = update_repository(repository)
end
if git_success
# Fetch the new changesets into Redmine
repository.fetch_changesets
render(:text => 'OK', :status => :ok)
else
errors = []
repositories.each do |repository|
# Fetch the changes from GitLab
if Setting.plugin_redmine_gitlab_hook['fetch_updates'] == 'yes'
git_success = update_repository(repository)
unless git_success
errors.push(repository.identifier)
else
# Fetch the new changesets into Redmine
repository.fetch_changesets
end
else
# Fetch the new changesets into Redmine
repository.fetch_changesets
end
end
if errors.empty?
render(:text => 'OK', :status => :ok)
else
render(:text => "Git command failed on repository: #{errors.join(', ')}!", :status => :not_acceptable)
end
render(:text => "Git command failed on repository: #{repository.identifier}!", :status => :not_acceptable)
end
else
raise ActionController::RoutingError.new('Not Found')
Expand Down Expand Up @@ -82,10 +69,10 @@ def clone_repository(prefix, remote_url, local_url)

# Fetches updates from the remote repository
def update_repository(repository)
Setting.plugin_redmine_gitlab_hook['prune'] == 'yes' ? prune = ' -p' : prune = ''
prefix = Setting.plugin_redmine_gitlab_hook['git_command_prefix'].to_s
Setting.plugin_redmine_gitlab_hook[:prune] == 'yes' ? prune = ' -p' : prune = ''
prefix = Setting.plugin_redmine_gitlab_hook[:git_command_prefix].to_s

if Setting.plugin_redmine_gitlab_hook['all_branches'] == 'yes'
if Setting.plugin_redmine_gitlab_hook[:all_branches] == 'yes'
command = git_command(prefix, "fetch --all#{prune}", repository)
exec(command)
else
Expand All @@ -97,69 +84,92 @@ def update_repository(repository)
end
end

def get_repository_name
return params[:repository] && params[:repository][:name].downcase
end

def get_repository_namespace
return params[:project] && params[:project][:namespace].downcase || ''
end

def get_repository_identifier
repo_namespace = get_repository_namespace
repo_name = get_repository_name
identifier = "#{repo_namespace}_#{repo_name}"
return identifier
end

# Gets the project identifier from the querystring parameters and if that's not supplied
# Gets the project identifier from the querystring parameters and if that's not supplied, assume
# the GitLab repository name is the same as the project identifier.
def get_identifier
payload = JSON.parse(params[:payload] || '{}')
identifier = params[:project_id] || payload['repository']['name']
def get_project_identifier
identifier = params[:project_id] || (params[:repository] && params[:repository][:name])
raise ActiveRecord::RecordNotFound, 'Project identifier not specified' if identifier.nil?
return identifier
end


# Finds the Redmine project in the database based on the given project identifier
def find_project
identifier = get_identifier
identifier = get_project_identifier
project = Project.find_by_identifier(identifier.downcase)
raise ActiveRecord::RecordNotFound, "No project found with identifier '#{identifier}'" if project.nil?
return project
end


# Returns the Redmine Repository object we are trying to update
def find_repositories
def find_repository
project = find_project
repositories = project.repositories.select do |repo|
repo.is_a?(Repository::Git)
end
repository_id = get_repository_identifier
repository = project.repositories.find_by_identifier_param(repository_id)

if repositories.nil? || repositories.length == 0
if Setting.plugin_redmine_gitlab_hook['auto_create'] == 'yes'
create_repository(project)
if repository.nil?
if Setting.plugin_redmine_gitlab_hook[:auto_create] == 'yes'
repository = create_repository(project)
else
raise TypeError, "Project '#{project.to_s}' ('#{project.identifier}') has no repository"
end
else
unless repository.is_a?(Repository::Git)
raise TypeError, "'#{repository_id}' is not a Git repository"
end
end

return repositories
return repository
end


def create_repository(project)
logger.debug('Trying to create repository...')
raise TypeError, 'Local repositories path is not set' unless Setting.plugin_redmine_gitlab_hook['local_repositories_path'].to_s.present?
raise TypeError, 'Local repository path is not set' unless Setting.plugin_redmine_gitlab_hook[:local_repositories_path].to_s.present?

identifier = params[:project_id] || (params['repository'] && params['repository']['name'])
remote_url = params[:repository] && params['repository']['git_ssh_url']
prefix = Setting.plugin_redmine_gitlab_hook['git_command_prefix'].to_s
identifier = get_repository_identifier
remote_url = params[:repository] && params[:repository][:git_ssh_url]
prefix = Setting.plugin_redmine_gitlab_hook[:git_command_prefix].to_s

raise TypeError, 'Remote repository URL is null' unless remote_url.present?

local_root_path = Setting.plugin_redmine_gitlab_hook['local_repositories_path']
local_url = File.join(local_root_path, identifier, File::SEPARATOR)

FileUtils.mkdir_p(local_url) unless File.exists?(local_url)

command = clone_repository(prefix, remote_url, local_url)
exec(command)

local_root_path = Setting.plugin_redmine_gitlab_hook[:local_repositories_path]
repo_namespace = get_repository_namespace
repo_name = get_repository_name
local_url = File.join(local_root_path, repo_namespace, repo_name)
git_file = File.join(local_url, 'HEAD')

unless File.exists?(git_file)
FileUtils.mkdir_p(local_url)
command = clone_repository(prefix, remote_url, local_url)
unless exec(command)
raise RuntimeError, "Can't clone URL #{remote_url}"
end
end
repository = Repository::Git.new
repository.identifier = identifier
repository.url = local_url
repository.is_default = true
repository.project = project
repository.save
return repository
end

end