lib/gitolite/config.rb in jbox-gitolite-1.2.0 vs lib/gitolite/config.rb in jbox-gitolite-1.2.1
- old
+ new
@@ -1,77 +1,87 @@
require 'tempfile'
-require File.join(File.dirname(__FILE__), 'config', 'repo')
-require File.join(File.dirname(__FILE__), 'config', 'group')
module Gitolite
+
class Config
+
attr_accessor :repos, :groups, :filename
- def initialize(config)
- @repos = {}
- @groups = {}
- @filename = File.basename(config)
- process_config(config)
- end
-
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
- #TODO: merge repo unless overwrite = true
+
+ def initialize(config)
+ @repos = {}
+ @groups = {}
+ @filename = File.basename(config)
+ process_config(config)
+ end
+
+
+ # TODO: merge repo unless overwrite = true
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
+
def rm_repo(repo)
name = normalize_repo_name(repo)
@repos.delete(name)
end
+
def has_repo?(repo)
name = normalize_repo_name(repo)
@repos.has_key?(name)
end
+
def get_repo(repo)
name = normalize_repo_name(repo)
@repos[name]
end
+
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
+
def rm_group(group)
name = normalize_group_name(group)
@groups.delete(name)
end
+
def has_group?(group)
name = normalize_group_name(group)
@groups.has_key?(name)
end
+
def get_group(group)
name = normalize_group_name(group)
@groups[name]
end
+
def to_file(path=".", filename=@filename)
raise ArgumentError, "Path contains a filename or does not exist" unless File.directory?(path)
new_conf = File.join(path, filename)
File.open(new_conf, "w") do |f|
f.sync = true
- #Output groups
+ # Output groups
dep_order = build_groups_depgraph
dep_order.each {|group| f.write group.to_s }
gitweb_descs = []
@repos.sort.each do |k, v|
@@ -87,169 +97,188 @@
end
new_conf
end
+
private
- #Based on
- #https://github.com/sitaramc/gitolite/blob/pu/src/gl-compile-conf#cleanup_conf_line
- 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
- def process_config(config)
- context = [] #will store our context for permissions or config declarations
+ # Based on
+ # https://github.com/sitaramc/gitolite/blob/pu/src/gl-compile-conf#cleanup_conf_line
+ def cleanup_config_line(line)
+ # remove comments, even those that happen inline
+ line.gsub!(/^((".*?"|[^#"])*)#.*/) {|m| m=$1}
- #Read each line of our config
- File.open(config, 'r').each do |l|
+ # fix whitespace
+ line.gsub!('=', ' = ')
+ line.gsub!(/\s+/, ' ')
+ line.strip
+ end
- 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 = []
+ def process_config(config)
+ context = [] #will store our context for permissions or config declarations
- repos = $1.split
- repos.each do |r|
- context << r
+ #Read each line of our config
+ File.open(config, 'r').each do |l|
- @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
+ line = cleanup_config_line(l)
+ next if line.empty? #lines are empty if we killed a comment
- context.each do |c|
- @repos[c].add_permission(perm, refex, users)
- end
- #repo git config
- when /^config (.+) = ?(.*)/
- key = $1
- value = $2
+ case line
- context.each do |c|
- @repos[c].set_git_config(key, value)
- end
- #repo gitolite option
- when /^option (.+) = (.*)/
- key = $1
- value = $2
+ # found a repo definition
+ when /^repo (.*)/
+ #Empty our current context
+ context = []
- raise ParseError, "Missing gitolite option value for repo: #{repo} and key: #{key}" if value.nil?
+ repos = $1.split
+ repos.each do |r|
+ context << r
- context.each do |c|
- @repos[c].set_gitolite_option(key, value)
- end
- #group definition
- when /^#{Group::PREPEND_CHAR}(\S+) = ?(.*)/
- group = $1
- users = $2.split
+ @repos[r] = Repo.new(r) unless has_repo?(r)
+ end
- @groups[group] = Group.new(group) unless has_group?(group)
- @groups[group].add_users(users)
- #gitweb definition
- when /^(\S+)(?: "(.*?)")? = "(.*)"$/
- repo = $1
- owner = $2
- description = $3
+ # repo permissions
+ when /^(-|C|R|RW\+?(?:C?D?|D?C?)M?) (.* )?= (.+)/
+ perm = $1
+ refex = $2 || ""
+ users = $3.split
- #Check for missing description
- raise ParseError, "Missing Gitweb description for repo: #{repo}" if description.nil?
+ context.each do |c|
+ @repos[c].add_permission(perm, refex, users)
+ end
- #Check for groups
- raise ParseError, "Gitweb descriptions cannot be set for groups" if repo =~ /@.+/
+ # repo git config
+ when /^config (.+) = ?(.*)/
+ key = $1
+ value = $2
- if has_repo? repo
- r = @repos[repo]
- else
- r = Repo.new(repo)
- add_repo(r)
- end
+ context.each do |c|
+ @repos[c].set_git_config(key, value)
+ 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
+ # 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
- raise ParseError, "'#{line}' cannot be processed"
- end
- end
- end
+ r = Repo.new(repo)
+ add_repo(r)
+ end
- # Normalizes the various different input objects to Strings
- def normalize_name(context, constant = nil)
- case context
- when constant
- context.name
- when Symbol
- context.to_s
+ 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
- context
+ raise ParseError, "'#{line}' cannot be processed"
end
end
+ end
- 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
+
+ # Normalizes the various different input objects to Strings
+ def normalize_name(context, constant = nil)
+ case context
+ when constant
+ context.name
+ when Symbol
+ context.to_s
else
- super
- end
+ context
end
+ end
- # Builds a dependency tree from the groups in order to ensure all groups
- # are defined before they are used
- def build_groups_depgraph
- dp = ::GRATR::Digraph.new
- # Add each group to the graph
- @groups.each_value do |group|
- dp.add_vertex! group
+ 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
- # 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
+ # Builds a dependency tree from the groups in order to ensure all groups
+ # are defined before they are used
+ def build_groups_depgraph
+ dp = ::Plexus::Digraph.new
- # Figure out if we have a good depedency graph
- dep_order = dp.topsort
+ # Add each group to the graph
+ @groups.each_value do |group|
+ dp.add_vertex! group
- if dep_order.empty?
- raise GroupDependencyError unless @groups.empty?
- end
+ # Select group names from the users
+ subgroups = group.users.select {|u| u =~ /^#{Group::PREPEND_CHAR}.*$/}.map{|g| get_group g.gsub(Group::PREPEND_CHAR, '') }
- dep_order
+ subgroups.each do |subgroup|
+ dp.add_edge! subgroup, group
+ end
end
- #Raised when something in a config fails to parse properly
- class ParseError < RuntimeError
- end
+ # Figure out if we have a good depedency graph
+ dep_order = dp.topsort
- # Raised when group dependencies cannot be suitably resolved for output
- class GroupDependencyError < RuntimeError
+ if dep_order.empty?
+ raise GroupDependencyError unless @groups.empty?
end
+
+ dep_order
+ end
+
+
+ #Raised when something in a config fails to parse properly
+ class ParseError < RuntimeError
+ end
+
+
+ # Raised when group dependencies cannot be suitably resolved for output
+ class GroupDependencyError < RuntimeError
+ end
+
end
end