xaizek / rocketgit (License: AGPLv3+) (since 2018-12-09)
Light and fast Git hosting solution suitable to serve both as a hub or as a personal code storage with its tickets, pull requests, API and much more.
<root> / inc / git.inc.php (17ea73bcabad5fe32769c4c093a83449e6f66082) (4,182B) (mode 100644) [raw]
<?php
require_once($INC . "/util.inc.php");
require_once($INC . "/log.inc.php");

$rg_git_zero = "0000000000000000000000000000000000000000";

$rg_git_error = "";

function rg_git_set_error($str)
{
	global $rg_git_error;

	rg_log("\tError: $str");
	$rg_git_error = $str;
}

function rg_git_error()
{
	global $rg_git_error;
	return $rg_git_error;
}

function rg_git_install_hooks($dst)
{
	global $rg_scripts;

	rg_log("git_install_hooks: dst=$dst...");

	if (file_exists($dst . "/hooks")) {
		//rg_log("hooks folder exists...");
		$_dir = @readlink($dst . "/hooks");
		if ($_dir !== FALSE) {
			//rg_log("\treadlink returned=[$_dir]");
			if (strcmp($_dir, $rg_scripts . "/hooks") == 0)
				return TRUE;
		}

		rg_log("\tNot a link to scripts one, make it...");
		if (!rg_rmdir($dst . "/hooks")) {
			rg_git_set_error("cannot remove hooks dir ($php_errormsg)");
			return FALSE;
		}
	}

	if (!@symlink($rg_scripts . "/hooks", $dst . "/hooks")) {
		rg_git_set_error("cannot make symlink [$rg_scripts/hooks]"
			. "->[$dst/] ($php_errormsg).");
		return FALSE;
	}

	return TRUE;
}

function rg_git_init($dst)
{
	rg_log("git_init: dst=$dst...");

	$dir = dirname($dst);
	if (!file_exists($dir)) {
		$r = @mkdir($dir, 0755, TRUE);
		if ($r === FALSE) {
			rg_git_set_error("cannot create dir [$dir] ($php_errormsg)");
			return FALSE;
		}
	}

	if (!file_exists($dst . "/rocketgit")) {
		$cmd = "git init --bare '" . escapeshellcmd($dst) . "'";
		rg_log("\texec $cmd...");
		$a = exec($cmd, $output, $err);
		if ($err != 0) {
			rg_git_set_error("crror $err (" . implode("|", $output) . " ($a)");
			return FALSE;
		}

		if (!@mkdir($dst . "/rocketgit")) {
			rg_git_set_error("cannot create '$dst/rocketgit' dir ($php_errormsg)");
			return FALSE;
		}
	}

	if (rg_git_install_hooks($dst) !== TRUE)
		return FALSE;

	return TRUE;
}

function rg_git_clone($src, $dst)
{
	rg_log("git_clone: src=$src, dst=$dst...");

	$dir = dirname($dst);
	if (!file_exists($dir)) {
		$r = @mkdir($dir, 0755, TRUE);
		if ($r === FALSE) {
			rg_git_set_error("cannot create dir [$dir] ($php_errormsg)");
			return FALSE;
		}
	}

	if (!file_exists($dst . "/rocketgit")) {
		$cmd = "git clone --bare '" . escapeshellcmd($src) . "'"
			. " '" . escapeshellcmd($dst) . "'";
		rg_log("\texec $cmd...");
		$a = exec($cmd);
		if ($err != 0) {
			rg_git_set_error("error $err (" . implode("|", $output) . " ($a)");
			return FALSE;
		}

		if (!@mkdir($dst . "/rocketgit", 0700)) {
			rg_git_set_error("cannot create '$dst/rocketgit' dir ($php_errormsg)");
			return FALSE;
		}
	}

	if (rg_git_install_hooks($dst) !== TRUE)
		return FALSE;

	return TRUE;
}

/*
 * Returns type for an object
 */
function rg_git_type($obj)
{
	$cmd = "git cat-file -t '" . $obj . "'";
	rg_log("\texec $cmd...");
	$a = exec($cmd, $output, $err);
	if ($err != 0) {
		rg_git_set_error("error $err (" . implode("|", $output) . " ($a)");
		return FALSE;
	}

	return trim($a);
}

/*
 * Corrects a revision
 */
function rg_git_rev($rev)
{
	return preg_replace("/[^a-zA-Z0-9^~]/", "", $rev);
}

/*
 * Validates a reference
 */
function rg_git_reference($refname)
{
	if (!preg_match("/[a-zA-Z0-9^~\/_]/", $refname))
		return "";

	return $refname;
}

// Check a revision if is OK
// TODO: Unit testing
function rg_git_rev_ok($rev)
{
	$cmd = "git rev-parse --verify --quiet '" . $rev . "'";
	rg_log("\texec $cmd...");
	$a = @exec($cmd, $output, $err);
	if ($err != 0) {
		rg_git_set_error("error $err out=[" . implode("|", $output) . "] a=[$a]");
		return FALSE;
	}

	return TRUE;
}

// returns FALSE if bad whitespace detected
// TODO: Unit testing
function rg_git_whitespace_ok($old, $new)
{
	$cmd = "git diff --check " . $old . " " . $new;
	rg_log("\texec $cmd...");
	$a = @exec($cmd, $output, $err);
	if ($err != 0) {
		rg_git_set_error("error $err out=[" . implode("|", $output) . "] a=[$a]");
		return FALSE;
	}

	return TRUE;
}

// TODO: Unit testing
function rg_git_merge_base($old, $new)
{
	$cmd = "git merge-base " . $old . " " . $new;
	rg_log("\texec $cmd...");
	$a = @exec($cmd, $output, $err);
	if ($err != 0) {
		rg_git_set_error("error $err out=[" . implode("|", $output) . "] a=[$a]");
		return FALSE;
	}

	return trim($a);
}

?>
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/rocketgit

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/rocketgit

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master