class Gitolite::Config

Attributes

filename[RW]
groups[RW]
repos[RW]

Public Class Methods

init(filename = "gitolite.conf") click to toggle source
# File lib/gitolite/config.rb, line 10
def self.init(filename = "gitolite.conf")
  file = Tempfile.new(filename)
  conf = self.new(file.path)
  conf.filename = filename #kill suffix added by Tempfile
  file.close(unlink_now = true)
  conf
end
new(config) click to toggle source
# File lib/gitolite/config.rb, line 19
def initialize(config)
  @repos = {}
  @groups = {}
  @filename = File.basename(config)
  process_config(config)
end

Public Instance Methods

add_group(group, overwrite = false) click to toggle source
# File lib/gitolite/config.rb, line 52
def add_group(group, overwrite = false)
  raise ArgumentError, "Group must be of type Gitolite::Config::Group!" unless group.instance_of? Gitolite::Config::Group
  @groups[group.name] = group
end
add_repo(repo, overwrite = false) click to toggle source

TODO: merge repo unless overwrite = true

# File lib/gitolite/config.rb, line 28
def add_repo(repo, overwrite = false)
  raise ArgumentError, "Repo must be of type Gitolite::Config::Repo!" unless repo.instance_of? Gitolite::Config::Repo
  @repos[repo.name] = repo
end
get_group(group) click to toggle source
# File lib/gitolite/config.rb, line 70
def get_group(group)
  name = normalize_group_name(group)
  @groups[name]
end
get_repo(repo) click to toggle source
# File lib/gitolite/config.rb, line 46
def get_repo(repo)
  name = normalize_repo_name(repo)
  @repos[name]
end
has_group?(group) click to toggle source
# File lib/gitolite/config.rb, line 64
def has_group?(group)
  name = normalize_group_name(group)
  @groups.has_key?(name)
end
has_repo?(repo) click to toggle source
# File lib/gitolite/config.rb, line 40
def has_repo?(repo)
  name = normalize_repo_name(repo)
  @repos.has_key?(name)
end
rm_group(group) click to toggle source
# File lib/gitolite/config.rb, line 58
def rm_group(group)
  name = normalize_group_name(group)
  @groups.delete(name)
end
rm_repo(repo) click to toggle source
# File lib/gitolite/config.rb, line 34
def rm_repo(repo)
  name = normalize_repo_name(repo)
  @repos.delete(name)
end
to_file(path=".", filename=@filename) click to toggle source
# File lib/gitolite/config.rb, line 76
def to_file(path=".", filename=@filename)
  FileUtils.mkdir_p(path) unless File.directory?(path)

  new_conf = File.join(path, filename)
  File.open(new_conf, "w") do |f|
    f.sync = true

    # Output groups
    dep_order = build_groups_depgraph
    dep_order.each {|group| f.write group.to_s }

    gitweb_descs = []
    @repos.sort.each do |k, v|
      f.write "\n"
      f.write v.to_s

      gwd = v.gitweb_description
      gitweb_descs.push(gwd) unless gwd.nil?
    end

    f.write "\n"
    f.write gitweb_descs.join("\n")
  end

  new_conf
end

Private Instance Methods

build_groups_depgraph() click to toggle source

Builds a dependency tree from the groups in order to ensure all groups are defined before they are used

# File lib/gitolite/config.rb, line 252
def build_groups_depgraph
  dp = ::GRATR::Digraph.new

  # Add each group to the graph
  @groups.each_value do |group|
    dp.add_vertex! group

    # Select group names from the users
    subgroups = group.users.select {|u| u =~ /^#{Group::PREPEND_CHAR}.*$/}.map{|g| get_group g.gsub(Group::PREPEND_CHAR, '') }

    subgroups.each do |subgroup|
      dp.add_edge! subgroup, group
    end
  end

  # Figure out if we have a good depedency graph
  dep_order = dp.topsort

  if dep_order.empty?
    raise GroupDependencyError unless @groups.empty?
  end

  dep_order
end
cleanup_config_line(line) click to toggle source

Based on github.com/sitaramc/gitolite/blob/pu/src/gl-compile-conf#cleanup_conf_line

# File lib/gitolite/config.rb, line 109
def cleanup_config_line(line)
  # remove comments, even those that happen inline
  line.gsub!(/^((".*?"|[^#"])*)#.*/) {|m| m=$1}

  # fix whitespace
  line.gsub!('=', ' = ')
  line.gsub!(/\s+/, ' ')
  line.strip
end
method_missing(meth, *args, &block) click to toggle source
Calls superclass method
# File lib/gitolite/config.rb, line 234
def method_missing(meth, *args, &block)
  if meth.to_s =~ /normalize_(\w+)_name/
    # Could use Object.const_get to figure out the constant here
    # but for only two cases, this is more readable
    case $1
      when "repo"
        normalize_name(args[0], Gitolite::Config::Repo)
      when "group"
        normalize_name(args[0], Gitolite::Config::Group)
    end
  else
    super
  end
end
normalize_name(context, constant = nil) click to toggle source

Normalizes the various different input objects to Strings

# File lib/gitolite/config.rb, line 222
def normalize_name(context, constant = nil)
  case context
    when constant
      context.name
    when Symbol
      context.to_s
    else
      context
  end
end
process_config(config) click to toggle source
# File lib/gitolite/config.rb, line 120
def process_config(config)
  context = [] #will store our context for permissions or config declarations

  # On first call with a custom *.conf, the config might not yet exist
  return unless File.exists?(config)

  #Read each line of our config
  File.open(config, 'r').each do |l|

    line = cleanup_config_line(l)
    next if line.empty? #lines are empty if we killed a comment

    case line

      # found a repo definition
      when /^repo (.*)/
        #Empty our current context
        context = []

        repos = $1.split
        repos.each do |r|
          context << r

          @repos[r] = Repo.new(r) unless has_repo?(r)
        end

      # repo permissions
      when /^(-|C|R|RW\+?(?:C?D?|D?C?)M?) (.* )?= (.+)/
        perm = $1
        refex = $2 || ""
        users = $3.split

        context.each do |c|
          @repos[c].add_permission(perm, refex, users)
        end

      # repo git config
      when /^config (.+) = ?(.*)/
        key = $1
        value = $2

        context.each do |c|
          @repos[c].set_git_config(key, value)
        end

      # repo gitolite option
      when /^option (.+) = (.*)/
        key = $1
        value = $2

        raise ParseError, "Missing gitolite option value for repo: #{repo} and key: #{key}" if value.nil?

        context.each do |c|
          @repos[c].set_gitolite_option(key, value)
        end

      # group definition
      when /^#{Group::PREPEND_CHAR}(\S+) = ?(.*)/
        group = $1
        users = $2.split

        @groups[group] = Group.new(group) unless has_group?(group)
        @groups[group].add_users(users)

      # gitweb definition
      when /^(\S+)(?: "(.*?)")? = "(.*)"$/
        repo = $1
        owner = $2
        description = $3

        #Check for missing description
        raise ParseError, "Missing Gitweb description for repo: #{repo}" if description.nil?

        #Check for groups
        raise ParseError, "Gitweb descriptions cannot be set for groups" if repo =~ /@.+/

        if has_repo? repo
          r = @repos[repo]
        else
          r = Repo.new(repo)
          add_repo(r)
        end

        r.owner = owner
        r.description = description

      when /^include "(.+)"/
        #TODO: implement includes
        #ignore includes for now

      when /^subconf (\S+)$/
        #TODO: implement subconfs
        #ignore subconfs for now

      else
        raise ParseError, "'#{line}' cannot be processed"
    end
  end
end