#!/usr/bin/env ruby require 'etc' require 'optparse' require 'ostruct' require 'rubygems' require 'repo-permissions' require 'json' require 'json/add/core' # We want everything printed on stderr $stdout = $stderr # Command line options options = OpenStruct.new options.git_repo_root = '/var/git' options.min_local_uid = 1000 options.config_dir = '/var/git/permissions' options.admin_email = 'jannis@xfce.org' # Classifications used in the git repository layout CLASSIFICATIONS = [ 'apps', 'archive', 'art', 'bindings', 'libs', 'panel-plugins', 'thunar-plugins', 'www', 'xfce', ] # Parse command line options ARGV.options do |opts| opts.banner = "Usage: #{$0} [OPTIONS] REFNAME OLD_REV NEW_REV" opts.on('-c', '--config-dir=DIR', "Location of the config files (default=#{options.config_dir})") do |dir| options.config_dir = dir end opts.on('-g', '--git-repo-root=DIR', "Location of the git repositories (default=#{options.git_repo_root})") do |dir| options.git_repo_root = dir end opts.on('-u', '--min-local-uid=UID', Integer, "Minimum UID to allow committers from system acconuts (default=#{options.min_local_uid})") do |uid| options.min_local_uid = uid end end.parse! unless ARGV.length == 3 and ENV.has_key?('GIT_DIR') and ENV.has_key?('REPO') puts ARGV.options exit 1 end # Fix GIT_DIR sometimes (always?) being set to '.' ENV['GIT_DIR'] = Dir.pwd # Determine username if ENV.has_key?('HTTP_REMOTE_USER') username = ENV['HTTP_REMOTE_USER'] else uid = Process::UID.eid if uid < options.min_local_uid puts "This script cannot be run by UIDs lower than #{options.min_local_uid}" puts 'Please ensure that the script is either run as a CGI with' puts 'the HTTP_REMOTE_USER environment variable set, or logically' puts 'with a regular user account.' puts puts "Contact #{options.admin_email} for help." exit 1 end begin pwent = Etc.getpwuid(uid) username = pwent.name rescue ArgumentError puts "Unable to resolve user id #{uid}. Contact #{options.admin_email} for help." exit 1 end end # Load users RepoPermissions::User.load do JSON.load(File.new(File.join(options.config_dir, 'users.json'))) end # Load groups RepoPermissions::Group.load do JSON.load(File.new(File.join(options.config_dir, 'groups.json'))) end # Load repositories RepoPermissions::Repository.load do repositories = CLASSIFICATIONS.collect do |base| JSON.load(File.new(File.join(options.config_dir, "#{base}.json"))) end repositories.flatten end user = RepoPermissions::User.find_by_username(username) if user.nil? puts "Unknown username '#{username}'. Contact #{options.admin_email} for help." exit 1 end repository = RepoPermissions::Repository.find_by_name(ENV['REPO']) if repository.nil? puts "Unknown repository '#{ENV['REPO']}'. Contact #{options.admin_email} for help." exit 1 end # Make update fail if the user has no commit access to this repository unless repository.allowed?(user) puts "Commit access to repository '#{repository.name}' denied for user '#{user.username}'." puts "Contact #{options.admin_email} for help." exit 1 end users = RepoPermissions::Group.find_all.collect do |group| group.users end.flatten for repository in RepoPermissions::Repository.find_all do users |= repository.groups.collect do |group| group.users end.flatten users |= repository.users end active, inactive = RepoPermissions::User.find_all.partition do |user| users.include?(user) end active_names = active.collect do |u| u.username end inactive_names = inactive.collect do |u| u.username end puts active_names puts puts inactive_names