Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/treetrek.git

Removes unused files

Author Dave Jarvis <email>
Date 2026-02-08 22:25:30 GMT-0800
Commit f9d2c669fb26ec1bcfa6fba47617c9fd26d76a8f
Parent f4271bc
Delta 0 lines added, 745 lines removed, 745-line decrease
includes/git_functions.php
-<?php
-/**
- * Git-related functions for repository operations
- */
-function getRepoPath($repo) {
- return REPOS_PATH . '/' . basename($repo);
-}
-
-/**
- * Executes a Git command and caches the output.
- */
-function execGitCached($repo, $command) {
- $cache_key = md5($repo . '|' . $command);
- $cache_file = CACHE_DIR . '/' . $cache_key . '.cache';
-
- if (file_exists($cache_file) && (time() - filemtime($cache_file) < CACHE_EXPIRY)) {
- return file_get_contents($cache_file);
- }
-
- $repoPath = getRepoPath($repo);
- $isBare = is_file($repoPath . '/HEAD') && !is_dir($repoPath . '/.git');
-
- // Note: $command should be built using escapeshellarg() by the caller
- if ($isBare) {
- $cmd = "git --git-dir=" . escapeshellarg($repoPath) . " " . $command . " 2>&1";
- } else {
- if (!is_dir($repoPath . '/.git')) {
- $output = '';
- } else {
- $cmd = "cd " . escapeshellarg($repoPath) . " && git " . $command . " 2>&1";
- }
- }
-
- $output = isset($cmd) ? shell_exec($cmd) : '';
-
- if (!empty($output)) {
- file_put_contents($cache_file, $output);
- }
-
- return $output;
-}
-
-/**
- * Executes a raw Git command without caching.
- */
-function execGitRaw($repo, $command) {
- $repoPath = getRepoPath($repo);
- $isBare = is_file($repoPath . '/HEAD') && !is_dir($repoPath . '/.git');
-
- if ($isBare) {
- $cmd = "git --git-dir=" . escapeshellarg($repoPath) . " " . $command . " 2>&1";
- } else {
- if (!is_dir($repoPath . '/.git')) {
- return '';
- }
- $cmd = "cd " . escapeshellarg($repoPath) . " && git " . $command . " 2>&1";
- }
-
- return shell_exec($cmd);
-}
-
-function execGit($repo, $command) {
- return execGitCached($repo, $command);
-}
-
-/**
- * Gets blob content as binary data (with caching).
- */
-function getBlobBinary($repo, $hash) {
- $cache_key = md5($repo . '|blob_binary|' . $hash);
- $cache_file = CACHE_DIR . '/' . $cache_key . '.cache';
-
- if (file_exists($cache_file) && (time() - filemtime($cache_file) < CACHE_EXPIRY)) {
- return file_get_contents($cache_file);
- }
-
- $repoPath = getRepoPath($repo);
- $isBare = is_file($repoPath . '/HEAD') && !is_dir($repoPath . '/.git');
-
- // Strictly escape the hash
- $safeHash = escapeshellarg($hash);
-
- if ($isBare) {
- $cmd = "git --git-dir=" . escapeshellarg($repoPath) . " cat-file blob " . $safeHash;
- } else {
- $cmd = "cd " . escapeshellarg($repoPath) . " && git cat-file blob " . $safeHash;
- }
-
- $descriptors = [
- 1 => ['pipe', 'w'],
- 2 => ['pipe', 'w']
- ];
-
- $process = proc_open($cmd, $descriptors, $pipes);
- if (is_resource($process)) {
- $output = stream_get_contents($pipes[1]);
- fclose($pipes[1]);
- fclose($pipes[2]);
- proc_close($process);
-
- if (!empty($output)) {
- file_put_contents($cache_file, $output);
- }
-
- return $output;
- }
- return '';
-}
-
includes/helpers.php
-<?php
-function isImageFile($filename) {
- $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
- return in_array($ext, ['png', 'jpg', 'jpeg', 'gif', 'svg', 'webp', 'bmp', 'ico']);
-}
-
-function isVideoFile($filename) {
- $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
- return in_array($ext, ['mp4', 'webm', 'ogg', 'mov', 'avi', 'mkv', 'm4v']);
-}
-
-function getImageMimeType($filename) {
- $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
- $mimeTypes = [
- 'png' => 'image/png',
- 'jpg' => 'image/jpeg',
- 'jpeg' => 'image/jpeg',
- 'gif' => 'image/gif',
- 'svg' => 'image/svg+xml',
- 'webp' => 'image/webp',
- 'bmp' => 'image/bmp',
- 'ico' => 'image/x-icon'
- ];
- return $mimeTypes[$ext] ?? 'application/octet-stream';
-}
-
-function getVideoMimeType($filename) {
- $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
- $mimeTypes = [
- 'mp4' => 'video/mp4',
- 'webm' => 'video/webm',
- 'ogg' => 'video/ogg',
- 'mov' => 'video/quicktime',
- 'avi' => 'video/x-msvideo',
- 'mkv' => 'video/x-matroska',
- 'm4v' => 'video/x-m4v'
- ];
- return $mimeTypes[$ext] ?? 'application/octet-stream';
-}
-
-function formatDate($timestamp) {
- return date('M j, Y H:i', intval($timestamp));
-}
-
-function timeAgo($timestamp) {
- $diff = time() - intval($timestamp);
-
- if ($diff < 60) {
- return 'just now';
- }
-
- $units = [
- 31536000 => 'year',
- 2592000 => 'month',
- 604800 => 'week',
- 86400 => 'day',
- 3600 => 'hour',
- 60 => 'minute',
- ];
-
- foreach ($units as $seconds => $unit_name) {
- if ($diff >= $seconds) {
- $value = floor($diff / $seconds);
- $plural = ($value > 1) ? 's' : '';
- return $value . ' ' . $unit_name . $plural . ' ago';
- }
- }
-}
-
includes/repo_functions.php
-<?php
-/**
- * Repository management functions
- */
-
-function getRepositories() {
- $repos = [];
- if (!is_dir(REPOS_PATH)) {
- return $repos;
- }
-
- $dirs = scandir(REPOS_PATH);
- foreach ($dirs as $dir) {
- if ($dir === '.' || $dir === '..') continue;
- $path = REPOS_PATH . '/' . $dir;
- if (is_dir($path) && (is_dir($path . '/.git') || is_file($path . '/HEAD'))) {
- $repos[] = $dir;
- }
- }
-
- $orderFile = __DIR__ . '/../order.txt';
- if (file_exists($orderFile)) {
- $lines = array_filter(array_map('trim', file($orderFile)));
- $blacklist = [];
- $order = [];
-
- // Parse order.txt for blacklisted (starting with -) and ordered repos
- foreach ($lines as $line) {
- if (substr($line, 0, 1) === '-') {
- // Blacklisted repo - add without the - prefix
- $blacklist[] = substr($line, 1);
- } else {
- // Normal ordered repo
- $order[] = $line;
- }
- }
-
- // Filter out blacklisted repos
- $repos = array_filter($repos, function($repo) use ($blacklist) {
- return !in_array($repo, $blacklist);
- });
-
- // Create order map and sort
- $orderMap = array_flip($order);
-
- usort($repos, function($a, $b) use ($orderMap) {
- $aPos = isset($orderMap[$a]) ? $orderMap[$a] : PHP_INT_MAX;
- $bPos = isset($orderMap[$b]) ? $orderMap[$b] : PHP_INT_MAX;
-
- if ($aPos === PHP_INT_MAX && $bPos === PHP_INT_MAX) {
- return strcmp($a, $b);
- }
-
- return $aPos - $bPos;
- });
- } else {
- sort($repos);
- }
-
- return $repos;
-}
-
-function getRepoInfo($repo) {
- $info = [];
- $repoPath = REPOS_PATH . '/' . basename($repo);
-
- $descFile = is_dir($repoPath . '/.git') ? $repoPath . '/.git/description' : $repoPath . '/description';
- $info['description'] = file_exists($descFile) ? trim(file_get_contents($descFile)) : 'No description';
- if ($info['description'] === 'Unnamed repository; edit this file \'description\' to name the repository.') {
- $info['description'] = 'No description';
- }
-
- $log = execGitCached($repo, "log -1 --format='%H|%an|%ae|%at|%s'");
- if (!empty($log) && $log !== null) {
- $parts = explode('|', trim($log));
- if (count($parts) >= 5) {
- $info['last_commit'] = [
- 'hash' => $parts[0],
- 'author' => $parts[1],
- 'email' => $parts[2],
- 'date' => $parts[3],
- 'message' => $parts[4]
- ];
- }
- }
-
- $branches = execGitCached($repo, "branch -a");
- $info['branches'] = empty($branches) ? 0 : count(array_filter(explode("\n", $branches)));
-
- $tags = execGitCached($repo, "tag");
- $info['tags'] = empty($tags) ? 0 : count(array_filter(explode("\n", $tags)));
-
- return $info;
-}
-
-function getBranches($repo) {
- $output = execGitCached($repo, "branch -a --format='%(refname:short)|%(committerdate:unix)|%(subject)'");
- $branches = [];
- if (empty($output) || $output === null) {
- return $branches;
- }
- foreach (explode("\n", trim($output)) as $line) {
- if (empty($line)) continue;
- $parts = explode('|', $line, 3);
- if (count($parts) >= 3) {
- $branches[] = [
- 'name' => $parts[0],
- 'date' => $parts[1],
- 'message' => $parts[2]
- ];
- }
- }
- return $branches;
-}
-
-function getCommits($repo, $branch = 'HEAD', $limit = 30) {
- $cmd = "log " . escapeshellarg($branch) . " -$limit --format='%H|%an|%ae|%at|%s'";
- $output = execGitCached($repo, $cmd);
- $commits = [];
- if (empty($output) || $output === null) {
- return $commits;
- }
- foreach (explode("\n", trim($output)) as $line) {
- if (empty($line)) continue;
- $parts = explode('|', $line, 5);
- if (count($parts) >= 5) {
- $commits[] = [
- 'hash' => $parts[0],
- 'author' => $parts[1],
- 'email' => $parts[2],
- 'date' => $parts[3],
- 'message' => $parts[4]
- ];
- }
- }
- return $commits;
-}
-
-function getCommitDetails($repo, $hash) {
- $info = execGitCached($repo, "show --format='%H|%an|%ae|%at|%s|%b' --stat $hash");
- $diff = execGitCached($repo, "show --format='' $hash");
- $lines = explode("\n", $info);
- $header = array_shift($lines);
- $parts = explode('|', $header, 6);
- return [
- 'hash' => $parts[0] ?? '',
- 'author' => $parts[1] ?? '',
- 'email' => $parts[2] ?? '',
- 'date' => $parts[3] ?? '',
- 'message' => $parts[4] ?? '',
- 'body' => $parts[5] ?? '',
- 'stat' => implode("\n", $lines),
- 'diff' => $diff
- ];
-}
-
-function getTree($repo, $ref = 'HEAD', $path = '') {
- $fullPath = $path ? $ref . ':' . $path : $ref;
- $cmd = "ls-tree " . escapeshellarg($fullPath);
- $output = execGitCached($repo, $cmd);
- $items = [];
- if (empty($output) || $output === null) {
- return $items;
- }
-
- foreach (explode("\n", trim($output)) as $line) {
- if (empty($line)) continue;
- if (preg_match('/^(\d+)\s+(blob|tree)\s+([a-f0-9]+)\s+(.+)$/', $line, $matches)) {
- $item = [
- 'mode' => $matches[1],
- 'type' => $matches[2],
- 'hash' => $matches[3],
- 'name' => $matches[4]
- ];
-
- // Get size for blobs
- if ($item['type'] === 'blob') {
- $sizeOutput = execGitRaw($repo, "cat-file -s " . escapeshellarg($item['hash']));
- $item['size'] = (int)trim($sizeOutput);
- }
-
- // Get last modification time for this file
- $filePath = $path ? $path . '/' . $item['name'] : $item['name'];
- $mtimeOutput = execGitRaw($repo, "log -1 --format=%ct " . escapeshellarg($ref) . " -- " . escapeshellarg($filePath));
- if (!empty($mtimeOutput)) {
- $item['mtime'] = (int)trim($mtimeOutput);
- }
-
- $items[] = $item;
- }
- }
-
- usort($items, function($a, $b) {
- if ($a['type'] !== $b['type']) {
- return $a['type'] === 'tree' ? -1 : 1;
- }
- return strcmp($a['name'], $b['name']);
- });
- return $items;
-}
-
-function getBlob($repo, $hash) {
- return execGitCached($repo, "cat-file blob $hash");
-}
-
views/blob.php
-<?php
-$name = $_GET['name'] ?? 'file';
-$isImage = isImageFile($name);
-$isVideo = isVideoFile($name);
-
-// Check file size before loading
-$repoPath = REPOS_PATH . '/' . basename($repo);
-$isBare = is_file($repoPath . '/HEAD') && !is_dir($repoPath . '/.git');
-
-if ($isBare) {
- $sizeCmd = "git --git-dir=" . escapeshellarg($repoPath) . " cat-file -s " . escapeshellarg($hash);
-} else {
- $sizeCmd = "cd " . escapeshellarg($repoPath) . " && git cat-file -s " . escapeshellarg($hash);
-}
-
-$fileSize = intval(trim(shell_exec($sizeCmd)));
-$maxDisplaySize = 10 * 1024 * 1024; // 10MB limit for display
-$maxVideoSize = 100 * 1024 * 1024; // 100MB limit for video playback
-$tooLarge = $fileSize > $maxDisplaySize;
-$videoTooLarge = $isVideo && $fileSize > $maxVideoSize;
-?>
-<div class="breadcrumb">
- <a href="?theme=<?php echo $current_theme; ?>">Repositories</a> <span>/</span>
- <a href="?action=repo&repo=<?php echo urlencode($repo); ?>&theme=<?php echo $current_theme; ?>"><?php echo htmlspecialchars($repo); ?></a> <span>/</span>
- <a href="?action=repo&repo=<?php echo urlencode($repo); ?>&view=tree&theme=<?php echo $current_theme; ?>">Files</a> <span>/</span>
- <strong><?php echo htmlspecialchars($name); ?></strong>
-</div>
-
-<div class="card">
- <div class="card-header">
- <?php echo htmlspecialchars($name); ?>
- <span style="color: #666; font-size: 0.9em; margin-left: 10px;">
- (<?php echo number_format($fileSize / 1024, 2); ?> KB)
- </span>
- </div>
- <div class="file-actions">
- <a href="?action=raw&repo=<?php echo urlencode($repo); ?>&hash=<?php echo urlencode($hash); ?>&name=<?php echo urlencode($name); ?>" class="btn" download>
- πŸ“₯ Download
- </a>
- </div>
-
- <?php if ($videoTooLarge): ?>
- <div class="empty-state">
- <div class="empty-state-icon">⚠️</div>
- <p>Video file is too large to play in browser (<?php echo number_format($fileSize / 1024 / 1024, 2); ?> MB)</p>
- <p>Please download it to view the contents.</p>
- </div>
- <?php elseif ($isVideo): ?>
- <div class="video-preview">
- <video controls style="max-width: 100%; height: auto;">
- <source src="data:<?php echo getVideoMimeType($name); ?>;base64,<?php echo base64_encode(getBlobBinary($repo, $hash)); ?>" type="<?php echo getVideoMimeType($name); ?>">
- Your browser does not support the video tag.
- </video>
- </div>
- <?php elseif ($tooLarge): ?>
- <div class="empty-state">
- <div class="empty-state-icon">⚠️</div>
- <p>File is too large to display (<?php echo number_format($fileSize / 1024 / 1024, 2); ?> MB)</p>
- <p>Please download it to view the contents.</p>
- </div>
- <?php elseif ($isImage): ?>
- <div class="image-preview">
- <img src="data:<?php echo getImageMimeType($name); ?>;base64,<?php echo base64_encode(getBlobBinary($repo, $hash)); ?>" alt="<?php echo htmlspecialchars($name); ?>">
- </div>
- <?php else:
- $content = getBlob($repo, $hash);
- if (empty($content) || mb_detect_encoding($content, 'UTF-8', true) === false):
- ?>
- <div class="empty-state">
- <div class="empty-state-icon">πŸ“¦</div>
- <p>This appears to be a binary file.</p>
- <p>Please download it to view the contents.</p>
- </div>
- <?php else: ?>
- <div class="code-block">
- <pre><?php echo htmlspecialchars($content); ?></pre>
- </div>
- <?php endif; ?>
- <?php endif; ?>
-</div>
views/commit.php
-<?php $commit = getCommitDetails($repo, $hash); ?>
-<div class="breadcrumb">
- <a href="?theme=<?php echo $current_theme; ?>">Repositories</a> <span>/</span>
- <a href="?action=repo&repo=<?php echo urlencode($repo); ?>&theme=<?php echo $current_theme; ?>"><?php echo htmlspecialchars($repo); ?></a> <span>/</span>
- <strong>Commit <?php echo substr($hash, 0, 7); ?></strong>
-</div>
-
-<div class="card">
- <div class="commit-detail">
- <div class="commit-title"><?php echo htmlspecialchars($commit['message']); ?></div>
- <?php if (!empty($commit['body'])): ?>
- <p style="color: #586069; margin-bottom: 1.5rem;"><?php echo nl2br(htmlspecialchars($commit['body'])); ?></p>
- <?php endif; ?>
-
- <div class="commit-info">
- <div class="commit-info-row">
- <div class="commit-info-label">Author:</div>
- <div><?php echo htmlspecialchars($commit['author']); ?> &lt;<?php echo htmlspecialchars($commit['email']); ?>&gt;</div>
- </div>
- <div class="commit-info-row">
- <div class="commit-info-label">Date:</div>
- <div><?php echo formatDate($commit['date']); ?> (<?php echo timeAgo($commit['date']); ?>)</div>
- </div>
- <div class="commit-info-row">
- <div class="commit-info-label">Commit:</div>
- <div style="font-family: monospace;"><?php echo htmlspecialchars($commit['hash']); ?></div>
- </div>
- </div>
-
- <?php if (!empty($commit['stat'])): ?>
- <div class="code-block" style="margin-bottom: 1.5rem;">
- <pre><?php echo htmlspecialchars($commit['stat']); ?></pre>
- </div>
- <?php endif; ?>
-
- <?php if (!empty($commit['diff'])): ?>
- <div class="code-block">
- <div class="diff">
- <?php foreach (explode("\n", $commit['diff']) as $line): ?>
- <?php
- $class = '';
- if (substr($line, 0, 1) === '+' && substr($line, 0, 3) !== '+++') {
- $class = 'diff-add';
- } elseif (substr($line, 0, 1) === '-' && substr($line, 0, 3) !== '---') {
- $class = 'diff-del';
- } elseif (substr($line, 0, 2) === '@@' || substr($line, 0, 4) === 'diff') {
- $class = 'diff-header';
- }
- ?>
- <div class="diff-line <?php echo $class; ?>"><?php echo htmlspecialchars($line); ?></div>
- <?php endforeach; ?>
- </div>
- </div>
- <?php endif; ?>
- </div>
-</div>
-
views/footer.php
-</div>
-</body>
-</html>
-
views/header.php
-<!DOCTYPE html>
-<html lang="en">
-<head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title><?php echo $page_title ?? SITE_TITLE; ?></title>
- <link rel="stylesheet" href="main.css">
- <link rel="stylesheet" href="<?php echo $css_file; ?>">
- <style>
- .header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 10px 20px;
- }
- .theme-toggle a {
- padding: 5px 10px;
- border: 1px solid currentColor;
- border-radius: 4px;
- text-decoration: none;
- color: <?php echo ($current_theme === 'light') ? '#000000' : '#FFFFFF'; ?>;
- background-color: <?php echo ($current_theme === 'light') ? '#F0F0F0' : '#333333'; ?>;
- }
- .theme-toggle a:hover {
- opacity: 0.8;
- }
- </style>
-</head>
-<body>
- <div class="header">
- <h1><a href="?action=list&theme=<?php echo $current_theme; ?>">πŸ“š <?php echo SITE_TITLE; ?></a></h1>
- <div class="theme-toggle">
- <?php
- $query_params = $_GET;
- unset($query_params['theme']);
- $opposite_theme = ($current_theme === 'light') ? 'dark' : 'light';
- $toggle_link = '?' . http_build_query(array_merge($query_params, ['theme' => $opposite_theme]));
- ?>
- <a href="<?php echo htmlspecialchars($toggle_link); ?>" class="btn-theme" title="Switch to <?php echo $opposite_theme; ?> Mode">
- <?php if ($current_theme === 'light'): ?>
- πŸŒ™ Dark
- <?php else: ?>
- β˜€οΈLight
- <?php endif; ?>
- </a>
- </div>
- </div>
- <div class="container">
views/index.html
views/list.php
-<?php $repos = getRepositories(); ?>
-<?php if (empty($repos)): ?>
- <div class="card">
- <div class="empty-state">
- <div class="empty-state-icon">πŸ“‚</div>
- <p>No repositories found in <?php echo htmlspecialchars(REPOS_PATH); ?></p>
- </div>
- </div>
-<?php else: ?>
- <ul class="repo-list">
- <?php foreach ($repos as $r): ?>
- <?php $info = getRepoInfo($r); ?>
- <li class="repo-item">
- <div class="repo-name">
- <a href="?action=repo&repo=<?php echo urlencode($r); ?>&theme=<?php echo $current_theme; ?>"><?php echo htmlspecialchars($r); ?></a>
- </div>
- <div class="repo-desc"><?php echo htmlspecialchars($info['description']); ?></div>
- <div class="repo-meta">
- <?php if (isset($info['last_commit'])): ?>
- <span>πŸ•’ <?php echo timeAgo($info['last_commit']['date']); ?></span>
- <?php endif; ?>
- </div>
- </li>
- <?php endforeach; ?>
- </ul>
-<?php endif; ?>
-
views/repo.php
-<?php
-$current_theme = $current_theme ?? ($_GET['theme'] ?? 'dark');
-$repo = $repo ?? ($_GET['repo'] ?? '');
-$ref = $ref ?? ($_GET['ref'] ?? 'HEAD');
-$path = $path ?? ($_GET['path'] ?? '');
-?>
-<div class="breadcrumb">
- <a href="?action=list&theme=<?php echo $current_theme; ?>">Repositories</a>
-</div>
-
-<?php
- $base_repo_link = "?action=repo&repo=" . urlencode($repo) . "&theme=" . $current_theme;
- $view = $_GET['view'] ?? '';
-?>
-<div class="nav-tabs">
- <a href="<?php echo $base_repo_link; ?>" class="nav-tab <?php echo empty($view) ? 'active' : ''; ?>">πŸ“ Commits</a>
- <a href="<?php echo $base_repo_link; ?>&view=tree" class="nav-tab <?php echo $view === 'tree' ? 'active' : ''; ?>">πŸ“ Files</a>
- <a href="<?php echo $base_repo_link; ?>&view=branches" class="nav-tab <?php echo $view === 'branches' ? 'active' : ''; ?>">🌿 Branches</a>
-</div>
-
-<?php
- if ($view === 'tree') {
- include __DIR__ . '/repo_tree.php';
- } elseif ($view === 'branches') {
- include __DIR__ . '/repo_branches.php';
- } else {
- include __DIR__ . '/repo_commits.php';
- }
-?>
-
views/repo_branches.php
-<?php $branches = getBranches($repo); ?>
-<div class="card">
- <ul class="commit-list">
- <?php foreach ($branches as $branch): ?>
- <li class="commit-item">
- <div class="commit-message">
- <a href="?action=repo&repo=<?php echo urlencode($repo); ?>&ref=<?php echo urlencode($branch['name']); ?>&theme=<?php echo $current_theme; ?>">
- 🌿 <?php echo htmlspecialchars($branch['name']); ?>
- </a>
- <div class="commit-meta">
- <?php echo htmlspecialchars($branch['message']); ?> β€’
- <?php echo timeAgo($branch['date']); ?>
- </div>
- </div>
- </li>
- <?php endforeach; ?>
- </ul>
-</div>
-
views/repo_commits.php
-<?php $commits = getCommits($repo, $ref); ?>
-<div class="card">
- <ul class="commit-list">
- <?php foreach ($commits as $commit): ?>
- <li class="commit-item">
- <div class="commit-message">
- <a href="?action=commit&repo=<?php echo urlencode($repo); ?>&hash=<?php echo urlencode($commit['hash']); ?>&theme=<?php echo $current_theme; ?>">
- <?php echo htmlspecialchars($commit['message']); ?>
- </a>
- <div class="commit-meta">
- <?php echo htmlspecialchars($commit['author']); ?> committed <?php echo timeAgo($commit['date']); ?>
- </div>
- </div>
- <div class="commit-hash">
- <a href="?action=commit&repo=<?php echo urlencode($repo); ?>&hash=<?php echo urlencode($commit['hash']); ?>&theme=<?php echo $current_theme; ?>">
- <?php echo substr($commit['hash'], 0, 7); ?>
- </a>
- </div>
- </li>
- <?php endforeach; ?>
- </ul>
-</div>
-
views/repo_tree.php
-<?php $items = getTree($repo, $ref, $path); ?>
-<div class="card">
- <div class="card-header">
- <?php if (empty($path)): ?>
- Root directory
- <?php else: ?>
- <?php echo htmlspecialchars($path); ?>
- <?php endif; ?>
- </div>
- <ul class="file-tree">
- <?php if (!empty($path)): ?>
- <li class="file-item">
- <span class="file-icon">πŸ“‚</span>
- <div class="file-name">
- <?php
- $parentPath = dirname($path);
- if ($parentPath === '.' || $parentPath === '') {
- $parentPath = '';
- }
- ?>
- <a href="?action=repo&repo=<?php echo urlencode($repo); ?>&view=tree&ref=<?php echo urlencode($ref); ?>&path=<?php echo urlencode($parentPath); ?>&theme=<?php echo $current_theme; ?>">../</a>
- </div>
- <div class="file-meta">
- <span class="file-size">-</span>
- <span class="file-date">-</span>
- </div>
- </li>
- <?php endif; ?>
- <?php foreach ($items as $item): ?>
- <li class="file-item">
- <span class="file-icon"><?php echo $item['type'] === 'tree' ? 'πŸ“' : 'πŸ“„'; ?></span>
- <div class="file-name">
- <?php if ($item['type'] === 'tree'): ?>
- <a href="?action=repo&repo=<?php echo urlencode($repo); ?>&view=tree&ref=<?php echo urlencode($ref); ?>&path=<?php echo urlencode($path . ($path ? '/' : '') . $item['name']); ?>&theme=<?php echo $current_theme; ?>">
- <?php echo htmlspecialchars($item['name']); ?>/
- </a>
- <?php else: ?>
- <a href="?action=blob&repo=<?php echo urlencode($repo); ?>&hash=<?php echo urlencode($item['hash']); ?>&name=<?php echo urlencode($item['name']); ?>&theme=<?php echo $current_theme; ?>">
- <?php echo htmlspecialchars($item['name']); ?>
- </a>
- <?php endif; ?>
- </div>
- <div class="file-meta">
- <span class="file-size">
- <?php
- if ($item['type'] === 'blob' && isset($item['size'])) {
- $size = $item['size'];
- if ($size < 1024) {
- echo $size . ' B';
- } elseif ($size < 1024 * 1024) {
- echo round($size / 1024, 1) . ' KB';
- } else {
- echo round($size / (1024 * 1024), 1) . ' MB';
- }
- } else {
- echo '-';
- }
- ?>
- </span>
- <span class="file-date">
- <?php
- if (isset($item['mtime'])) {
- echo date('Y-m-d H:i', $item['mtime']);
- } else {
- echo '-';
- }
- ?>
- </span>
- </div>
- </li>
- <?php endforeach; ?>
- </ul>
-</div>
-