BigW Consortium Gitlab

gitolite.rb 4.28 KB
Newer Older
1 2 3 4
require 'gitolite'
require 'timeout'
require 'fileutils'

5
module Gitlab
6 7 8
  class Gitolite
    class AccessDenied < StandardError; end

9 10 11 12 13 14 15 16
    def self.update_project(path, project)
      self.new.configure { |git| git.update_project(path, project) }
    end

    def self.destroy_project(project)
      self.new.configure { |git| git.destroy_project(project) }
    end

17 18
    def pull
      # create tmp dir
19
      @local_dir = File.join(Rails.root, 'tmp',"gitlabhq-gitolite-#{Time.now.to_i}")
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
      Dir.mkdir @local_dir

      `git clone #{GitHost.admin_uri} #{@local_dir}/gitolite`
    end

    def push
      Dir.chdir(File.join(@local_dir, "gitolite"))
      `git add -A`
      `git commit -am "Gitlab"`
      `git push`
      Dir.chdir(Rails.root)

      FileUtils.rm_rf(@local_dir)
    end

    def configure
randx committed
36
      Timeout::timeout(30) do
37
        File.open(File.join(Rails.root, 'tmp', "gitlabhq-gitolite.lock"), "w+") do |f|
38 39 40 41 42 43 44 45 46 47 48
          begin 
            f.flock(File::LOCK_EX)
            pull
            yield(self)
            push
          ensure
            f.flock(File::LOCK_UN)
          end
        end
      end
    rescue Exception => ex
49
      Gitlab::Logger.error(ex.message)
50 51 52 53
      raise Gitolite::AccessDenied.new("gitolite timeout")
    end

    def destroy_project(project)
54
      FileUtils.rm_rf(project.path_to_repo)
55

56 57 58 59 60 61
      ga_repo = ::Gitolite::GitoliteAdmin.new(File.join(@local_dir,'gitolite'))
      conf = ga_repo.config
      conf.rm_repo(project.path)
      ga_repo.save
    end

62
    #update or create
63 64 65 66 67 68 69 70 71 72
    def update_keys(user, key)
      File.open(File.join(@local_dir, 'gitolite/keydir',"#{user}.pub"), 'w') {|f| f.write(key.gsub(/\n/,'')) }
    end

    def delete_key(user)
      File.unlink(File.join(@local_dir, 'gitolite/keydir',"#{user}.pub"))
      `cd #{File.join(@local_dir,'gitolite')} ; git rm keydir/#{user}.pub`
    end

    # update or create
73
    def update_project(repo_name, project)
74 75
      ga_repo = ::Gitolite::GitoliteAdmin.new(File.join(@local_dir,'gitolite'))
      conf = ga_repo.config
76
      repo = update_project_config(project, conf)
77
      conf.add_repo(repo, true)
78
      
79 80
      ga_repo.save
    end
81 82 83 84 85 86 87 88

    # Updates many projects and uses project.path as the repo path
    # An order of magnitude faster than update_project
    def update_projects(projects)
      ga_repo = ::Gitolite::GitoliteAdmin.new(File.join(@local_dir,'gitolite'))
      conf = ga_repo.config

      projects.each do |project|
89
        repo = update_project_config(project, conf)
90 91 92 93 94 95
        conf.add_repo(repo, true)
      end

      ga_repo.save
    end

96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
    def update_project_config(project, conf)
      repo_name = project.path

      repo = if conf.has_repo?(repo_name)
               conf.get_repo(repo_name)
             else 
               ::Gitolite::Config::Repo.new(repo_name)
             end

      name_readers = project.repository_readers
      name_writers = project.repository_writers
      name_masters = project.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, 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?

      repo
    end
127 128 129 130 131 132 133 134 135 136 137 138 139

    def admin_all_repo
      ga_repo = ::Gitolite::GitoliteAdmin.new(File.join(@local_dir,'gitolite'))
      conf = ga_repo.config
      owner_name = ""

      # Read gitolite-admin user
      #
      begin 
        repo = conf.get_repo("gitolite-admin")
        owner_name = repo.permissions[0]["RW+"][""][0]
        raise StandardError if owner_name.blank?
      rescue => ex
Robert Speicher committed
140
        puts "Can't determine gitolite-admin owner".red
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
        raise StandardError
      end

      # @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)
      ga_repo.save
    end
156 157
  end
end