#!/usr/bin/php5
<?
$vcs = array ( "git", "svn", "bzr" );

$actions = array (
	"build" => "build with make or ant",
	"diff" => "show what's changed in your working directories",
	"list" => "list repositories",
	"log" => "show last commit logs",
	"pull" => "pull repositories from origin/parent",
	"push" => "push repositories to origin/parent",
	"status" => "show statuses"
);

$cmds = array (
	"build" => array (
		"git" => "([ -f Makefile ] && make ) || ([ -f build.xml ] && ant)",
		"svn" => "([ -f Makefile ] && make ) || ([ -f build.xml ] && ant)",
		"bzr" => "([ -f Makefile ] && make ) || ([ -f build.xml ] && ant)"
	),
	"diff" => array (
		"git" => "git diff --stat",
		"svn" => "svn diff | diffstat",
		"bzr" => "bzr diff | diffstat"
	),
	"list" => array ( 
		"git" => "git config remote.origin.url", 
		"svn" => "svn info | grep URL | sed -es/'URL: '//",
		"bzr" => "bzr info | grep 'parent branch' | sed -es/'  parent branch: '//"
	),
	"log" => array (
		"git" => "git log -n 1 --oneline",
		"svn" => "svn log -l 1 | head -n 4 | tail -n 1",
		"bzr" => "bzr log -l1 --line"
	),
	"pull" => array (
		"git" => "git pull origin master", "svn" => "svn update", "bzr" => "bzr pull"
	),
	"push" => array (
		"git" => "git push origin master", "bzr" => "bzr push :parent"
	),
	"status" => array (
		"git" => "git status", 
		"svn" => "svn status",
		"bzr" => "bzr status"
	)
);

$cfg_path = getenv("HOME")."/.repost";

class Repo {
	public $path, $type;
	function __construct($path, $type) {
		$this->path = $path;
		$this->type = $type;
	}
}

function usage() {
	global $actions;

	echo "Usage: repost <action>\n";
	echo "Actions:\n";
	foreach( $actions as $k => $v) echo "\t$k\t$v\n";
	exit;
}

function systemln($str) {
	$out = shell_exec($str);
	if(substr($out,-1)!="\n") $out.="\n";
	echo $out;
}

function color_off() { system("tput sgr0"); }
function color_on() { system("echo -n \033[32m"); }

function cmd($repo, $action) {
	global $cmds;

	color_on();
	echo basename($repo->path)."\t(".$repo->type.")\t";
	color_off();
	chdir($repo->path);
	$cl = $cmds[$action][$repo->type];
	if(isset($cl)) systemln($cmds[$action][$repo->type]);
	else echo "(don't know how to '$action' this repository)\n";
}

function build_repo_list($config) {
	global $vcs;

	$repobases = explode(":", $config["repobase"]);
	$repos = array();
	foreach($repobases as $b) {
		$base = realpath($b);
		foreach (glob("$base/*") as $file) {
			if(is_dir($file)) {
				foreach($vcs as $v) if(is_dir("$file/.$v")) {
					$repos[] = new Repo($file, $v);
					break;
				}
			}
		}
	}
	return $repos;
}

function parse_config($config) {
	global $cmds;

	//user can override commands...
	foreach ($config as $k => $v) 
		if(substr_compare($k, "cmd.", 0, 4)==0) {
			$keys = explode(".", $k);
			$cmds[$keys[1]][$keys[2]] = $v;
		}
}

function gen_config_file() {
	global $cfg_path;

	echo "Type the full paths of the directories that *contains* the repositories,\n";
	echo "one per line. Terminate with an empty line.\n";
	$repobase = "";
	while($line = fgets(STDIN)) {
		$line = substr($line, 0, -1); //drop the newline
		if($line=="") break;
		$repobase = "$repobase:$line";
	}
	if($repobase=="") {
		echo "No base directory given. Quitting.\n";
		exit;
	}
	$repobase = "repobase = \"".substr($repobase,1)."\"\n";
	file_put_contents($cfg_path,$repobase);
}

/* Check args */
if(count($argv)!=2) usage();
$action = $argv[1];
if(!array_key_exists($action, $actions)) usage();

/* Read configuration */
if(!is_file($cfg_path)) gen_config_file();
$config = parse_ini_file($cfg_path);
$repos = build_repo_list($config);
parse_config($config);

/* Do things */
foreach($repos as $repo) cmd($repo, $action);	
?>
