lib/gitolite/config.rb in gitolite-0.0.2.alpha vs lib/gitolite/config.rb in gitolite-0.0.3.alpha
- old
+ new
@@ -1,85 +1,86 @@
+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 = Hash.new { |k,v| k[v] = [] }
+ @groups = {}
@filename = File.basename(config)
process_config(config)
end
- #Represents a repo inside the gitolite configuration. The name, permissions, and git config
- #options are all encapsulated in this class
- class Repo
- ALLOWED_PERMISSIONS = ['C', 'R', 'RW', 'RW+', 'RWC', 'RW+C', 'RWD', 'RW+D', 'RWCD', 'RW+CD', '-']
+ 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
- attr_accessor :permissions, :name, :config
+ #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 initialize(name)
- @name = name
- @permissions = Hash.new {|k,v| k[v] = Hash.new{|k2, v2| k2[v2] = [] }}
- @config = {}
- end
+ def rm_repo(repo)
+ name = normalize_repo_name(repo)
+ @repos.delete(name)
+ end
- def add_permission(perm, refex, *users)
- if ALLOWED_PERMISSIONS.include? perm
- @permissions[perm][refex].concat users
- else
- raise InvalidPermissionError, "#{perm} is not in the allowed list of permissions!"
- end
- end
+ def has_repo?(repo)
+ name = normalize_repo_name(repo)
+ @repos.has_key?(name)
+ end
- def set_git_config(key, value)
- @config[key] = value
- end
+ def get_repo(repo)
+ name = normalize_repo_name(repo)
+ @repos[name]
+ end
- def unset_git_config(key)
- @config.delete(key)
- 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 to_s
- repo = "repo #{@name}\n"
+ def rm_group(group)
+ name = normalize_group_name(group)
+ @groups.delete(name)
+ end
- @permissions.each do |perm, list|
- list.each do |refex, users|
- repo += " " + perm.ljust(6) + refex.ljust(20) + "= " + users.join(' ') + "\n"
- end
- end
-
- repo
- end
-
- #Gets raised if a permission that isn't in the allowed
- #list is passed in
- class InvalidPermissionError < RuntimeError
- end
+ def has_group?(group)
+ name = normalize_group_name(group)
+ @groups.has_key?(name)
end
- #TODO: merge repo unless overwrite = true
- def add_repo(repo, overwrite = false)
- raise "Repo must be of type Gitolite::Config::Repo!" unless repo.instance_of? Gitolite::Config::Repo
- @repos[repo.name] = repo
+ def get_group(group)
+ name = normalize_group_name(group)
+ @groups[name]
end
-
- def rm_repo(repo)
- raise "Repo must be of type Gitolite::Config::Repo!" unless repo.instance_of? Gitolite::Config::Repo
- @repos.delete repo.name
- end
- def to_file(path)
- new_conf = File.join(path, @filename)
+ 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|
- @groups.each do |k,v|
- members = v.join(' ')
- f.write "#{k.ljust(20)}= #{members}\n"
- end
+ #Output groups
+ @groups.each_value {|group| f.write group.to_s }
+ gitweb_descs = []
@repos.each do |k, v|
f.write v.to_s
+
+ gwd = v.gitweb_description
+ gitweb_descs.push(gwd) unless gwd.nil?
end
+
+ f.write gitweb_descs.join("\n")
end
new_conf
end
@@ -91,11 +92,11 @@
line.gsub!(/^((".*?"|[^#"])*)#.*/) {|m| m=$1}
#fix whitespace
line.gsub!('=', ' = ')
line.gsub!(/\s+/, ' ')
- line.strip!
+ line.strip
end
def process_config(config)
context = [] #will store our context for permissions or config declarations
@@ -113,11 +114,11 @@
repos = $1.split
repos.each do |r|
context << r
- @repos[r] = Repo.new(r) unless @repos.has_key? r
+ @repos[r] = Repo.new(r) unless has_repo?(r)
end
#repo permissions
when /^(-|C|R|RW\+?(?:C?D?|D?C?)) (.* )?= (.+)/
perm = $1
refex = $2 || ""
@@ -133,25 +134,73 @@
context.each do |c|
@repos[c].set_git_config(key, value)
end
#group definition
- when /^(@\S+) = ?(.*)/
+ when /^#{Group::PREPEND_CHAR}(\S+) = ?(.*)/
group = $1
users = $2.split
- @groups[group].concat users
- @groups[group].uniq!
+ @groups[group] = Group.new(group) unless has_group?(group)
+ @groups[group].add_users(users)
#gitweb definition
when /^(\S+)(?: "(.*?)")? = "(.*)"$/
- #ignore gitweb right now
- puts line
+ 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
else
- puts "The following line cannot be processed:"
- puts "'#{line}'"
+ raise ParseError, "'#{line}' cannot be processed"
end
end
+ 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
+ context
+ 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
+ else
+ super
+ end
+ end
+
+ #Raised when something in a config fails to parse properly
+ class ParseError < RuntimeError
end
end
end