#!/usr/bin/perl -w
# Copyright 1999-2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

use strict;

my $inconf = 0;
my $ingroup = 0;
my $inrepo = 0;

my %SETTINGS = (); # global settings.. from [gitosis]
my %GROUPS = (); # [group ...] blocks
my %REPOS = (); # [repo ...] blocks
my %REAL_GROUPS = (); # real groups like @foo = ...

my $group = "";
my $repo = "";

my $conf = ($#ARGV eq 0) ? $ARGV[0] : "gitosis.conf";

open(GITOSIS, '<', $conf) or die "Error open(): $conf - $!\n";
while(defined(my $line = <GITOSIS>)) {
	chomp($line);
	$line =~ s/^\s//g;
	$line =~ s/\s$//g;

	next if length($line) == 0;

	# reset
	if($line =~ m/^\[/) {
		$inconf = 0;
		$ingroup = 0;
		$inrepo = 0;
	}

	# [gitosis]
	if($line =~ m/^\[gitosis\]$/) {
		$inconf = 1;
	}
	elsif($inconf eq 1 && $line =~ m/^(gitweb|daemon)\s+=\s+(.+)/) {
		$SETTINGS{$1} = lc($2);
	}

	# [group ...]
	if($line =~ m/^\[group\s+(.+)\]$/) {
		$group = $1;

		next if $group eq "gitosis-admin"; # skip the gitosis-admin repo

		if(!defined($GROUPS{$group})) {
			$GROUPS{$group} = undef;
		}
		else {
			print "GROUP $group already exist!\n";
		}
		$ingroup = 1;
		next;
	}
	elsif($ingroup eq 1 && $line =~ m/^(write?able|readonly|members)\s+=\s+(.+)/) {
		my $var = $1;
		my $values = $2;
		$var =~ s/writable/writeable/;

		foreach my $value (split(/\s+/, $values)) {
			push(@{$GROUPS{$group}{$var}}, $value);
		}
		next;
	}

	# [repo ...]
	if($line =~ m/^\[repo\s+(.+)\]$/) {
		$repo = $1;

		next if $repo eq "gitosis-admin"; # skip the gitosis-admin repo

		if(!defined($REPOS{$repo})) {
			$REPOS{$repo} = undef;
		}
		$inrepo = 1;
		next;
	}
	elsif($inrepo eq 1 && $line =~ m/^(daemon|gitweb)\s+=\s+(.+)/) {
		$REPOS{$repo}{$1} = lc($2);
		next;
	}
	elsif($inrepo eq 1 && $line =~ m/^(owner|description)\s+=\s+(.+)/) {
		$REPOS{$repo}{$1} = $2;
		next;
	}
}
close(GITOSIS);

# Add R/RW members to the specified repos
foreach my $group (keys(%GROUPS)) {
	if(keys(%{$GROUPS{$group}}) eq 1 && defined($GROUPS{$group}{"members"})) {
		$REAL_GROUPS{$group} = $GROUPS{$group}{"members"};
	}
	else {
		if(defined($GROUPS{$group}{"members"})) {
			foreach my $var (qw( writeable readonly )) {
				if(defined($GROUPS{$group}{$var})) {
					my $perm = $var;
					$perm =~ s/writeable/RW/;
					$perm =~ s/readonly/R/;

					foreach my $repo (@{$GROUPS{$group}{$var}}) {
						push(@{$REPOS{$repo}{$perm}}, @{$GROUPS{$group}{"members"}});
					}
				}
			}
		}
	}
}

print "# converted from gitosis\n";
foreach my $group (sort(keys(%REAL_GROUPS))) {
	next if $group eq "all"; # @all is _all_ in gitolite.
	@{$REAL_GROUPS{$group}} = sort {lc($a) cmp lc($b) } @{$REAL_GROUPS{$group}};
	print "\@${group} = @{$REAL_GROUPS{$group}}\n\n";
}
print "\n";

my $old = "";
foreach my $repo (sort(keys(%REPOS))) {
	my $hint = $repo;
	$hint =~ s/\/.*//;

	# for a better overview
	if($old ne $hint) {
		$old = $hint;
		print "# $hint\n";
	}

	print "repo ${repo}\n";

	# RW - writeable
	if(defined($REPOS{$repo}{"RW"})) {
		@{$REPOS{$repo}{"RW"}} = sort {lc($a) cmp lc($b) } @{$REPOS{$repo}{"RW"}};
		print "\tRW+ = @{$REPOS{$repo}{\"RW\"}}\n";
	}

	# R - readonly is a bit speacial...
	my @readonly = ();
	# gitweb and daemon first
	foreach my $extra (qw( daemon gitweb )) {
		# repo settings overwrite the global ones
		if(defined($REPOS{$repo}{$extra})) {
			if($REPOS{$repo}{$extra} eq "yes") {
				push(@readonly, $extra);
			}
		}
		else {
			if(defined($SETTINGS{$extra})) {
				if($SETTINGS{$extra} eq "yes") {
					push(@readonly, $extra);
				}
			}
		}
	}
	# now the readonly users/groups
	if(defined($REPOS{$repo}{"R"})) {
		@{$REPOS{$repo}{"R"}} = sort {lc($a) cmp lc($b) } @{$REPOS{$repo}{"R"}};
		push(@readonly, @{$REPOS{$repo}{"R"}});
	}
	if($#readonly >= 0) {
		if($#readonly eq 1 && grep(/^gitweb$/, @readonly) && grep(/^daemon$/, @readonly) ) {
			@readonly = qw( @all );
		}
		print "\tR   = @{readonly}\n";
	}
	if(defined($REPOS{$repo}{"owner"}) || defined($REPOS{$repo}{"description"})) {
		my $owner = defined($REPOS{$repo}{"owner"}) ? $REPOS{$repo}{"owner"} : "";
		my $description = defined($REPOS{$repo}{"description"}) ? $REPOS{$repo}{"description"} : "";
		print "\t${repo} \"${owner}\" = \"${description}\"\n";
	}
	print "\n";
}
