diff options
author | Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> | 2013-02-04 16:28:10 +0400 |
---|---|---|
committer | Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> | 2013-02-04 16:28:10 +0400 |
commit | 6b9a60904451fb192e445774768ccb53f7f8d2f8 (patch) | |
tree | 7af50121470d555214fa043ce77e230a4fb8eefc /lib | |
parent | 85de55a120a615f8cf51a343a89789b802d776e2 (diff) |
preparing for gitlab-shell
Diffstat (limited to 'lib')
-rw-r--r-- | lib/gitlab/backend/gitolite.rb | 65 | ||||
-rw-r--r-- | lib/gitlab/backend/gitolite_config.rb | 241 |
2 files changed, 16 insertions, 290 deletions
diff --git a/lib/gitlab/backend/gitolite.rb b/lib/gitlab/backend/gitolite.rb index cd9ac1554d6..62eb500bcd6 100644 --- a/lib/gitlab/backend/gitolite.rb +++ b/lib/gitlab/backend/gitolite.rb @@ -1,5 +1,3 @@ -require_relative 'gitolite_config' - module Gitlab class Gitolite class AccessDenied < StandardError; end @@ -8,52 +6,25 @@ module Gitlab Gitlab::GitoliteConfig.new end - # Update gitolite config with new key - # - # Ex. - # set_key("m_gitlab_com_12343", "sha-rsa ...", [2, 3, 6]) - # - def set_key(key_id, key_content, project_ids) - projects = Project.where(id: project_ids) - - config.apply do |config| - config.write_key(key_id, key_content) - config.update_projects(projects) - end - end - - # Remove ssh key from gitolite config + # Add new key to gitlab-shell # # Ex. - # remove_key("m_gitlab_com_12343", [2, 3, 6]) + # add_key("randx", "sha-rsa ...") # - def remove_key(key_id, project_ids) - projects = Project.where(id: project_ids) - - config.apply do |config| - config.rm_key(key_id) - config.update_projects(projects) - end + def add_key(username, key_content) + # TODO: implement end - # Update project config in gitolite by project id + # Remove ssh key from gitlab shell # # Ex. - # update_repository(23) + # remove_key("sha-rsa") # - def update_repository(project_id) - project = Project.find(project_id) - config.update_project!(project) - end - - def move_repository(old_repo, project) - config.apply do |config| - config.clean_repo(old_repo) - config.update_project(project) - end + def remove_key(key_content) + # TODO: implement end - # Remove repository from gitolite + # Remove repository from file system # # name - project path with namespace # @@ -61,20 +32,18 @@ module Gitlab # remove_repository("gitlab/gitlab-ci") # def remove_repository(name) - config.destroy_project!(name) + # TODO: implement end - # Update projects configs in gitolite by project ids + # Init new repository + # + # name - project path with namespace # # Ex. - # update_repositories([1, 4, 6]) + # add_repository("gitlab/gitlab-ci") # - def update_repositories(project_ids) - projects = Project.where(id: project_ids) - - config.apply do |config| - config.update_projects(projects) - end + def add_repository(name) + # TODO: implement end def url_to_repo path @@ -84,7 +53,5 @@ module Gitlab def enable_automerge config.admin_all_repo! end - - alias_method :create_repository, :update_repository end end diff --git a/lib/gitlab/backend/gitolite_config.rb b/lib/gitlab/backend/gitolite_config.rb deleted file mode 100644 index 748f9d74390..00000000000 --- a/lib/gitlab/backend/gitolite_config.rb +++ /dev/null @@ -1,241 +0,0 @@ -require 'gitolite' -require 'timeout' -require 'fileutils' - -module Gitlab - class GitoliteConfig - include Gitlab::Popen - - class PullError < StandardError; end - class PushError < StandardError; end - class BrokenGitolite < StandardError; end - - attr_reader :config_tmp_dir, :tmp_dir, :ga_repo, :conf - - def initialize - @tmp_dir = Rails.root.join("tmp").to_s - @config_tmp_dir = File.join(@tmp_dir,"gitlabhq-gitolite-#{Time.now.to_i}") - end - - def ga_repo - @ga_repo ||= ::Gitolite::GitoliteAdmin.new( - File.join(config_tmp_dir,'gitolite'), - conf: Gitlab.config.gitolite.config_file - ) - end - - def apply - Timeout::timeout(30) do - File.open(File.join(tmp_dir, "gitlabhq-gitolite.lock"), "w+") do |f| - begin - # Set exclusive lock - # to prevent race condition - f.flock(File::LOCK_EX) - - # Pull gitolite-admin repo - # in tmp dir before do any changes - pull - - # Build ga_repo object and @conf - # to access gitolite-admin configuration - @conf = ga_repo.config - - # Do any changes - # in gitolite-admin - # config here - yield(self) - - # Save changes in - # gitolite-admin repo - # before push it - ga_repo.save - - # Push gitolite-admin repo - # to apply all changes - push - ensure - # Remove tmp dir - # removing the gitolite folder first is important to avoid - # NFS issues. - FileUtils.rm_rf(File.join(config_tmp_dir, 'gitolite')) - - # Remove parent tmp dir - FileUtils.rm_rf(config_tmp_dir) - - # Unlock so other task can access - # gitolite configuration - f.flock(File::LOCK_UN) - end - end - end - rescue PullError => ex - log("Pull error -> " + ex.message) - raise Gitolite::AccessDenied, ex.message - - rescue PushError => ex - log("Push error -> " + " " + ex.message) - raise Gitolite::AccessDenied, ex.message - - rescue BrokenGitolite => ex - log("Gitolite error -> " + " " + ex.message) - raise Gitolite::AccessDenied, ex.message - - rescue Exception => ex - log(ex.class.name + " " + ex.message) - raise Gitolite::AccessDenied.new("gitolite timeout") - end - - def log message - Gitlab::GitLogger.error(message) - end - - def path_to_repo(name) - File.join(Gitlab.config.gitolite.repos_path, "#{name}.git") - end - - def destroy_project(name) - full_path = path_to_repo(name) - FileUtils.rm_rf(full_path) if File.exists?(full_path) - conf.rm_repo(name) - end - - def clean_repo repo_name - conf.rm_repo(repo_name) - end - - def destroy_project!(project) - apply do |config| - config.destroy_project(project) - end - end - - def write_key(id, key) - File.open(File.join(config_tmp_dir, 'gitolite/keydir',"#{id}.pub"), 'w') do |f| - f.write(key.gsub(/\n/,'')) - end - end - - def rm_key(user) - key_path = File.join(config_tmp_dir, 'gitolite/keydir', "#{user}.pub") - ga_key = ::Gitolite::SSHKey.from_file(key_path) - ga_repo.rm_key(ga_key) - end - - # update or create - def update_project(project) - repo = update_project_config(project, conf) - conf.add_repo(repo, true) - end - - def update_project!( project) - apply do |config| - config.update_project(project) - end - end - - # Updates many projects and uses project.path_with_namespace as the repo path - # An order of magnitude faster than update_project - def update_projects(projects) - projects.each do |project| - repo = update_project_config(project, conf) - conf.add_repo(repo, true) - end - end - - def update_project_config(project, conf) - repo_name = project.path_with_namespace - - repo = if conf.has_repo?(repo_name) - conf.get_repo(repo_name) - else - ::Gitolite::Config::Repo.new(repo_name) - end - - name_readers = project.team.repository_readers - name_writers = project.team.repository_writers - name_masters = project.team.repository_masters - - pr_br = project.protected_branches.map(&:name).join("$ ") - - repo.clean_permissions - - # Deny access to protected branches for writers - unless name_writers.blank? || pr_br.blank? - repo.add_permission("-", pr_br.strip + "$ ", name_writers) - end - - # Add read permissions - repo.add_permission("R", "", name_readers) unless name_readers.blank? - - # Add write permissions - repo.add_permission("RW+", "", name_writers) unless name_writers.blank? - repo.add_permission("RW+", "", name_masters) unless name_masters.blank? - - # Add sharedRepository config - repo.set_git_config("core.sharedRepository", "0660") - - repo - end - - # Enable access to all repos for gitolite admin. - # We use it for accept merge request feature - def admin_all_repo - owner_name = Gitlab.config.gitolite.admin_key - - # @ALL repos premission for gitolite owner - repo_name = "@all" - repo = if conf.has_repo?(repo_name) - conf.get_repo(repo_name) - else - ::Gitolite::Config::Repo.new(repo_name) - end - - repo.add_permission("RW+", "", owner_name) - conf.add_repo(repo, true) - end - - def admin_all_repo! - apply { |config| config.admin_all_repo } - end - - private - - def pull - # Create config tmp dir like "RAILS_ROOT/tmp/gitlabhq-gitolite-132545" - Dir.mkdir config_tmp_dir - - # Clone gitolite-admin repo into tmp dir - popen("git clone #{Gitlab.config.gitolite.admin_uri} #{config_tmp_dir}/gitolite", tmp_dir) - - # Ensure file with config presents after cloning - unless File.exists?(File.join(config_tmp_dir, 'gitolite', 'conf', 'gitolite.conf')) - raise PullError, "unable to clone gitolite-admin repo" - end - end - - def push - output, status = popen('git add -A', tmp_conf_path) - raise "Git add failed." unless status.zero? - - # git commit returns 0 on success, and 1 if there is nothing to commit - output, status = popen('git commit -m "GitLab"', tmp_conf_path) - raise "Git add failed." unless [0,1].include?(status) - - output, status = popen('git push', tmp_conf_path) - - if output =~ /remote\: FATAL/ - raise BrokenGitolite, output - end - - if status.zero? || output =~ /Everything up\-to\-date/ - return true - else - raise PushError, "unable to push gitolite-admin repo" - end - end - - def tmp_conf_path - File.join(config_tmp_dir,'gitolite') - end - end -end |