diff options
author | Daniel Weipert <git@mail.dweipert.de> | 2025-07-22 11:16:40 +0200 |
---|---|---|
committer | Daniel Weipert <git@mail.dweipert.de> | 2025-07-22 11:16:40 +0200 |
commit | d51eee7ed707568f58d305abb750349cb2f27bcc (patch) | |
tree | d9b32a2e8466c5c9e04d769889fb9e9ed3496447 | |
parent | 4fd85782abf9005a0d27d7890023a21d9dad6ef3 (diff) |
add blob route and log parse cache
-rw-r--r-- | index.php | 93 |
1 files changed, 82 insertions, 11 deletions
@@ -1,5 +1,10 @@ <?php +/** + * find projects at $path + * + * @return array<string> + */ function find_projects(string $path, array $projects = []): array { $directories = glob($path . "/{.[!.],}*", GLOB_ONLYDIR | GLOB_BRACE); if (($idx = array_search("$path/.git", $directories)) !== false) { @@ -14,10 +19,23 @@ function find_projects(string $path, array $projects = []): array { return $projects; } -function parse_log(string $path): array|null { + +global $cache_parse_log; +$cache_parse_log = []; + +/** + * parse git log at $path + */ +function parse_log(string $path): array { + global $cache_parse_log; + + if (isset($cache_parse_log[$path])) { + return $cache_parse_log[$path]; + } + $proxy = md5(strval(microtime(true))); $process = proc_open( - "git -C {$path} log " . "--pretty=format:'{%n {$proxy}commit{$proxy}: {$proxy}%H{$proxy},%n {$proxy}author{$proxy}: {$proxy}%aN <%aE>{$proxy},%n {$proxy}date{$proxy}: {$proxy}%ad{$proxy},%n {$proxy}message{$proxy}: {$proxy}%s{$proxy}%n},'", + "git -C \"{$path}\" log " . "--pretty=format:'{%n {$proxy}commit{$proxy}: {$proxy}%H{$proxy},%n {$proxy}author{$proxy}: {$proxy}%aN <%aE>{$proxy},%n {$proxy}date{$proxy}: {$proxy}%ad{$proxy},%n {$proxy}message{$proxy}: {$proxy}%s{$proxy}%n},'", [ ["pipe", "r"], ["pipe", "w"], @@ -32,12 +50,15 @@ function parse_log(string $path): array|null { $json = json_decode($string, true); - return $json; + return $cache_parse_log[$path] = $json ?? []; } +/** + * parse git status at $path + */ function parse_status(string $path): array { $process = proc_open( - "git -C {$path} status --porcelain=v2 --branch", + "git -C \"{$path}\" status --porcelain=v2 --branch", [ ["pipe", "r"], ["pipe", "w"], @@ -117,11 +138,14 @@ function parse_status(string $path): array { return $status; } +/** + * get git file tree at $path for $revision under $tree_base_path + */ function get_file_tree(string $path, string $revision, string $tree_base_path): array { $proxy = md5(strval(microtime(true))); $process = proc_open( - "git -C {$path} ls-tree {$revision} {$tree_base_path}" . " --format='{%n {$proxy}mode{$proxy}: {$proxy}%(objectmode){$proxy},%n {$proxy}type{$proxy}: {$proxy}%(objecttype){$proxy},%n {$proxy}name{$proxy}: {$proxy}%(objectname){$proxy},%n {$proxy}size{$proxy}: {$proxy}%(objectsize){$proxy},%n {$proxy}path{$proxy}: {$proxy}%(path){$proxy}%n},'", + "git -C \"{$path}\" ls-tree {$revision} {$tree_base_path}" . " --format='{%n {$proxy}mode{$proxy}: {$proxy}%(objectmode){$proxy},%n {$proxy}type{$proxy}: {$proxy}%(objecttype){$proxy},%n {$proxy}name{$proxy}: {$proxy}%(objectname){$proxy},%n {$proxy}size{$proxy}: {$proxy}%(objectsize){$proxy},%n {$proxy}path{$proxy}: {$proxy}%(path){$proxy}%n},'", [ ["pipe", "r"], ["pipe", "w"], @@ -131,7 +155,7 @@ function get_file_tree(string $path, string $revision, string $tree_base_path): ); $output = stream_get_contents($pipes[1]); - $string = str_replace(['"', $proxy], ['\\"', '"'], $output); + $string = str_replace(['\\', '"', $proxy], ['\\\\', '\\"', '"'], $output); $string = "[" . rtrim(trim($string), ",") . "]"; $tree = json_decode($string, true); @@ -140,6 +164,9 @@ function get_file_tree(string $path, string $revision, string $tree_base_path): } +/** + * Template root + */ function template_root(string $content, array $meta = []): string { $meta = array_replace_recursive([ @@ -149,9 +176,19 @@ function template_root(string $content, array $meta = []): string ob_start(); ?> + <!doctype html> <html> <head> <title><?php echo $meta["title"]; ?></title> + <style> + .blob-code-block { + pre { + border: 1px solid; + display: inline-block; + padding: 1rem; + } + } + </style> </head> <body><?php echo $content; ?></body> </html> @@ -167,6 +204,7 @@ $url = parse_url("http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"); ob_start(); +// Route: / if ($url["path"] == "/") { $projects = find_projects($projects_path); @@ -238,10 +276,10 @@ if ($url["path"] == "/") { } -// /$project/tree/$file_path +// Route: /$project/tree/$file_path elseif (preg_match("#(.*)/tree/?(.*)#", $url["path"], $matches)) { - $project = ltrim($matches[1], "/"); - $file_path = rtrim($matches[2], "/"); + $project = urldecode(ltrim($matches[1], "/")); + $file_path = urldecode(rtrim($matches[2], "/")); // get tree $tree = get_file_tree("$projects_path/$project", "HEAD", "./{$file_path}/"); @@ -260,6 +298,7 @@ elseif (preg_match("#(.*)/tree/?(.*)#", $url["path"], $matches)) { <table> <thead> <tr> + <td>Mode</td> <td>File</td> </tr> </thead> @@ -267,11 +306,18 @@ elseif (preg_match("#(.*)/tree/?(.*)#", $url["path"], $matches)) { <?php foreach ($tree as $file) { - $relative_path = str_replace("$file_path/", "", $file["path"]); + $current_file_path = $file_path . "/"; + $basename = basename($file["path"]); ?><tr><?php - ?><td><a href="<?php echo "$url[path]/$relative_path"; ?>"><?php echo $relative_path; ?></a><td><?php + ?><td><?php echo $file["mode"]; ?></td><?php + + if ($file["type"] == "blob"): + ?><td><a href="<?php echo "/$project/blob/$current_file_path$basename"; ?>"><?php echo $basename; ?></a><td><?php + else: + ?><td><a href="<?php echo "/$project/tree/$current_file_path$basename"; ?>"><?php echo $basename; ?></a><td><?php + endif; ?></tr><?php } @@ -282,6 +328,31 @@ elseif (preg_match("#(.*)/tree/?(.*)#", $url["path"], $matches)) { <?php } +// Route: /$project/blob/$file_path +elseif (preg_match("#(.*)/blob/?(.*)#", $url["path"], $matches)) { + $project = urldecode(ltrim($matches[1], "/")); + $file_path = urldecode(rtrim($matches[2], "/")); + + // show breadcrumbs + $breadcrumbs = explode("/", $file_path); + echo "<a href='/$project/tree'>root</a>"; + $crumb_parts = ""; + foreach ($breadcrumbs as $idx => $crumb) { + $crumb_parts .= "/$crumb"; + if ($idx != count($breadcrumbs) - 1) { + echo "/<a href='/$project/tree$crumb_parts'>$crumb</a>"; + } else { + echo "/$crumb"; + } + } + + ?> + <div class="blob-code-block"> + <pre><code><?php echo file_get_contents("$projects_path/$project/$file_path"); ?></code></pre> + </div> + <?php +} + else { $path = $projects_path . $url["path"]; var_dump(parse_log($path)); |