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 / user / repo-page.php (969eeeffd64f4e05d92d9fb859985189b8258497) (8,626B) (mode 100644) [raw]
<?php
rg_log("FILE: /inc/user/repo-page");

$_repo_page = "";

if (rg_user_ok($user) !== TRUE) {
	$_repo_page .= rg_warning("Invalid user!");
	return;
}
$rg['page_ui'] = rg_user_info($db, 0, $user, "");
if ($rg['page_ui']['ok'] != 1) {
	$_repo_page .= rg_warning("Internal error!");
	return;
}
if ($rg['page_ui']['exists'] != 1) {
	$_repo_page .= rg_template("user/invalid.html", $rg, TRUE /* xss */);
	return;
}

if (rg_repo_ok($repo) !== TRUE) {
	$_repo_page .= rg_template("repo/invalid.html", $rg, TRUE /* xss */);
	return;
}
$rg['ri'] = rg_repo_info($db, 0, $rg['page_ui']['uid'], $repo);
if ($rg['ri']['ok'] != 1) {
	$_repo_page .= rg_warning("Internal error!");
	return;
}

$allow = FALSE;
while (1) {
	if ($rg['ri']['exists'] != 1)
		break;

	$x = array();
	$x['obj_id'] = $rg['ri']['repo_id'];
	$x['type'] = 'repo';
	$x['owner'] = $rg['ri']['uid'];
	$x['uid'] = $rg['login_ui']['uid'];
	$x['username'] = $rg['login_ui']['username'];
	$x['needed_rights'] = 'A';
	$x['ip'] = $rg['ip'];
	$x['misc'] = "";
	if (rg_rights_allow($db, $x) !== TRUE)
		break;

	$allow = TRUE;
	break;
}
if ($allow !== TRUE) {
	$_repo_page .= rg_template("user/repo/deny.html", $rg, TRUE /* xss */);
	return;
}

if (!isset($rg['ri']['git_dir_done']))
	$rg['ri']['git_dir_done'] = 0;

$x['needed_rights'] = 'E';
$can_admin = rg_rights_allow($db, $x) === TRUE ? 1 : 0;

$rg['url_user'] = rg_re_userpage($rg['page_ui']);
$rg['url_repo'] = rg_re_repopage($rg['page_ui'], $repo);
$rg['ssh'] = rg_re_repo_ssh($organization, $user, $repo);
$rg['git'] = rg_re_repo_git($organization, $user, $repo);
$rg['can_admin'] = $can_admin;
$rg['HTML:hints'] = '';

$repo_path = rg_repo_path_by_id($rg['ri']['uid'], $rg['ri']['repo_id']);
rg_log("repo_path=$repo_path");
putenv("GIT_DIR=$repo_path"); // TODO: this will be removed after all functios will got a path para

$rg['HTML:branches_and_tags'] = '';
$_repo_body = "";

// build urls list
$urls = array();
if ($rg_ssh_port != 0)
	$urls[]['HTML:clone_url'] = '<a href="' . $rg['ssh'] . '">' . $rg['ssh'] . '</a>';
if ($rg_git_port != 0)
	$urls[]['HTML:clone_url'] = '<a href="' . $rg['git'] . '">' . $rg['git'] . '</a>';
$rg['HTML:urls'] = rg_template_table("repo/urls", $urls, $rg);

function rg_add_clone_hints($db, &$rg, $ref)
{
	global $rg_ssh_port;
	global $rg_git_port;

	$hints = array();

	$hints[]['HTML:hint'] = rg_template("hints/repo/git_setup.html",
		$rg, TRUE /* xss */);

	if ($rg['ri']['uid'] == $rg['login_ui']['uid']) {
		$hints[]['HTML:hint'] = rg_template("hints/repo/clone_owner.html",
			$rg, TRUE /* xss */);
	} else {
		if ($rg_ssh_port != 0)
			$hints[]['HTML:hint'] = rg_template("hints/repo/clone_ssh.html",
				$rg, TRUE /* xss */);

		if ($rg_git_port != 0)
			$hints[]['HTML:hint'] = rg_template("hints/repo/clone_git.html",
				$rg, TRUE /* xss */);

		$x = array();
		$x['obj_id'] = $rg['ri']['repo_id'];
		$x['type'] = 'repo_refs';
		$x['owner'] = $rg['ri']['uid'];
		$x['uid'] = $rg['login_ui']['uid'];
		$x['username'] = $rg['login_ui']['username'];
		$x['needed_rights'] = 'H'; /* anon push */
		$x['ip'] = $rg['ip'];
		$x['misc'] = $ref;
		if (rg_rights_allow($db, $x) === TRUE)
			$hints[]['HTML:hint'] = rg_template("hints/repo/anon_push.html",
				$rg, TRUE /* xss */);
	}

	$rg['HTML:hints'] = rg_template_table("hints/list", $hints, $rg);
}

// default tab
$_subop = empty($paras) ? "history" : array_shift($paras);

if (strcmp($_subop, "history") == 0) {
	rg_add_clone_hints($db, $rg, '');

	$hist = rg_repo_history_load($db, $rg['ri']['repo_id'], 0, 20, 0);
	if ($hist === FALSE)
		$_repo_body .= rg_warning("Cannot load history. Try again later.");
	else
		$_repo_body .= rg_template_table("repo/history", $hist, $rg);
} else if (strcmp($_subop, "admin") == 0) {
	$_repo_body .= rg_repo_admin($db, $rg, $paras);
} else if (strcmp($_subop, "source") == 0) {
	$_subsubop = empty($paras) ? "" : array_shift($paras);
	$rg['source_menu'][$_subsubop] = 1;

	$type_ref = rg_git_parse_ref($paras);
	$ref = $type_ref['ref_path'];
	$rg = array_merge($rg, $type_ref);

	$bt = rg_git_branches_and_tags($repo_path, $rg['ri']['url_repo'],
		$type_ref['ref_url']);
	$rg = array_merge($rg, $bt);

	rg_add_clone_hints($db, $rg, $ref);

	$_repo_body .= rg_template("repo/source.html", $rg, TRUE /* xss */);

	rg_log("DEBUG: _subsubop=[$_subsubop]");
	if ($rg['ri']['git_dir_done'] == 0) {
		$_repo_body .= rg_template("repo/no_git_dir.html", $rg, TRUE /* xss */);
	} else if (strcmp($_subsubop, "tree") == 0) {
		$type = array_shift($paras);
		rg_log("DEBUG: tree: type=$type");
		if (strcmp($type, "blob") == 0) {
			// find hash of blob
			$_path = implode("/", $paras);
			$rg['path'] = "/" . $_path;
			$_tree = rg_git_ls_tree($repo_path, $ref, $_path);
			if ($_tree === FALSE) {
				$_repo_body .= "Invalid path!";
			} else {
				$blob = $_tree[0];
				$_hash = $_tree[0]['ref'];
				$c = rg_git_content($_hash);
				// TODO: error code check
				$_content = array(
					"hash" => $_hash,
					"HTML:content" => rg_template_list($c)
					);
				$blob = array_merge($blob, $_content);
				$blob = array_merge($blob, $rg);
				$_repo_body .= rg_template("repo/blob.html", $blob, TRUE /* xss */);
			}
		} else if (strcmp($type, "tree") == 0) {
			// find treeish of dir
			$_path = implode("/", $paras);
			$rg['path'] = "/" . $_path;
			$_tree = rg_git_ls_tree($repo_path, $ref, $_path);
			if ($_tree === FALSE) {
				$_repo_body .= "Invalid path!";
			} else {
				$_hash = $_tree[0]['ref'];
				$_tree = rg_git_ls_tree($repo_path, $_hash, "");
				$_repo_body .= rg_template_table("repo/tree",
					$_tree, $rg);
			}
		} else { // default is to show root tree
			$rg['path'] = "";
			$_tree = rg_git_ls_tree($repo_path, $ref, "");
			$_repo_body .= rg_template_table("repo/tree", $_tree,
				$rg);
		}
	} else { // show the log
		// TODO: improve the error report (error or empty?)
		$log = rg_git_log($repo_path, 10, "", $ref, FALSE);
		if ($log === FALSE) {
			$_repo_body .= rg_template("repo/not_init.html", $rg,
				TRUE /*xss*/);
		} else {
			//rg_log_ml("DEBUG: log: " . print_r($log, TRUE));
			$_repo_body .= rg_git_log_template($log, "repo/log", $rg);
		}

		$type = array_shift($paras);
		//rg_log("DEBUG: log: type=$type");
		if (strcmp($type, "commit") == 0) {
			if (empty($paras))
				$commit = FALSE;
			else
				$commit = rg_git_reference($paras[0]);
			if ($commit === FALSE) {
				rg_internal_error("Invalid commit"
					. " [" . $paras[0] . "]."
					. " Make it empty.");
				// TODO: give an error on the page?!
				$commit = "";
			}
			rg_log("Show diff for commit [$commit]");

			if (strstr($commit, "..")) {
				$t = explode("..", $commit);
				$first = $t[0];
				$second = $t[1];
			} else {
				$first = "";
				$second = $commit;
			}

			$log = rg_git_log($repo_path, 1, $first, $second, TRUE);
			$_repo_body .= rg_git_log2listing($log, $rg, FALSE);
		}
	}
} else if (strcmp($_subop, "bug") == 0) {
	include($INC . "/user/repo/bug/main.php");
	$_repo_body .= $bug_body;
} else if (strcmp($_subop, "stats") == 0) {
	$_repo_body .= rg_repo_stats($rg);
} else if (strcmp($_subop, "mr") == 0) {
	if ($rg['ri']['git_dir_done'] == 0) {
		$_repo_body .= rg_template("repo/no_git_dir.html",
			$rg, TRUE /*xss*/);
	} else {
		$_repo_body .= rg_template("repo/mrs.html", $rg, TRUE /*xss*/);

		while (1) {
			if (empty($paras)) {
				$r = rg_mr_load($db, $rg['ri']['repo_id'], 0 /*no limit*/);
				if ($r === FALSE) {
					$_repo_body .= "Error getting merge request list ("
						. rg_mr_error() . ").";
				} else {
					$_repo_body .= rg_template_table("repo/mr/list",
						$r, $rg);
				}
				break;
			}

			$mr = preg_replace('/[^0-9a-zA-Z_]/', '',
				array_shift($paras));
			$rg['mr'] = $mr;
			$mri = rg_mr_load_one($db, $rg['ri']['repo_id'], $mr);
			if ($mri === FALSE) {
				$_repo_body .= "Error getting merge request"
					. " (" . rg_mr_error() . ").";
				break;
			}

			$_log = rg_git_log($repo_path, 0, $mri['old_rev'],
				$mri['new_rev'], TRUE);
			if ($_log === FALSE) {
				$_repo_body .= rg_warning("Error generating patch.");
				break;
			}

			$mri['HTML:diff'] = rg_git_log2listing($_log, $rg, TRUE);
			$_repo_body .= rg_template("repo/mr/page.html", $mri,
				TRUE /*xss*/);
			break;
		}

		$hints = array();
		$hints[]['HTML:hint'] = rg_template("hints/repo/merge.html",
			$rg, TRUE /*xss*/);
		$rg['HTML:hints'] = rg_template_table("hints/list",
			$hints, $rg);
	}
}

rg_watch_hl_process($db, $rg, 'repo', $rg['ri']['repo_id'], 0 /*obj_id2*/,
	$rg['current_url']);

$rg['per_repo_menu'][$_subop] = 1;
$rg['HTML:repo_body'] = $_repo_body;
$_repo_page = rg_template("repo/main.html", $rg, TRUE /*xss*/);

?>
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