<?php require_once __DIR__ . '/RepositoryList.php'; require_once __DIR__ . '/git/Git.php'; require_once __DIR__ . '/pages/CommitsPage.php'; require_once __DIR__ . '/pages/DiffPage.php'; require_once __DIR__ . '/pages/HomePage.php'; require_once __DIR__ . '/pages/FilePage.php'; require_once __DIR__ . '/pages/RawPage.php'; require_once __DIR__ . '/pages/TagsPage.php'; require_once __DIR__ . '/pages/ClonePage.php'; require_once __DIR__ . '/pages/ComparePage.php'; class Router { private $repos = []; private $git; public function __construct( string $reposPath ) { $this->git = new Git( $reposPath ); $list = new RepositoryList( $reposPath ); $list->eachRepository( function( $repo ) { $this->repos[$repo['safe_name']] = $repo; } ); } public function route(): Page { if( empty( $_GET ) && !empty( $_SERVER['QUERY_STRING'] ) ) { parse_str( $_SERVER['QUERY_STRING'], $_GET ); } $uri = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH ); $scriptName = dirname( $_SERVER['SCRIPT_NAME'] ); if( $scriptName !== '/' && strpos( $uri, $scriptName ) === 0 ) { $uri = substr( $uri, strlen( $scriptName ) ); } $uri = trim( $uri, '/' ); $parts = explode( '/', $uri ); if( !empty( $parts ) && $parts[0] === 'repo' ) { array_shift( $parts ); } if( empty( $parts ) || empty( $parts[0] ) ) { return new HomePage( $this->repos, $this->git ); } $repoName = array_shift( $parts ); if( str_ends_with( $repoName, '.git' ) ) { $realName = substr( $repoName, 0, -4 ); $repoPath = $this->repos[$realName]['path'] ?? $this->repos[$repoName]['path'] ?? null; if( !$repoPath ) { http_response_code( 404 ); echo "Repository not found"; exit; } $this->git->setRepository( $repoPath ); return new ClonePage( $this->git, implode( '/', $parts ) ); } if( !isset( $this->repos[$repoName] ) ) { return new HomePage( $this->repos, $this->git ); } $currRepo = $this->repos[$repoName]; $this->git->setRepository( $currRepo['path'] ); $action = array_shift( $parts ) ?: 'tree'; $hash = ''; $path = ''; $baseHash = ''; if( in_array( $action, ['tree', 'blob', 'raw', 'commits'] ) ) { $hash = array_shift( $parts ) ?: 'HEAD'; $path = implode( '/', $parts ); } elseif( $action === 'commit' ) { $hash = array_shift( $parts ); } elseif( $action === 'compare' ) { $hash = array_shift( $parts ); $baseHash = array_shift( $parts ); } $_GET['repo'] = $repoName; $_GET['action'] = $action; $_GET['hash'] = $hash; $_GET['name'] = $path; return match( $action ) { 'tree', 'blob' => new FilePage( $this->repos, $currRepo, $this->git, $hash, $path ), 'raw' => new RawPage( $this->git, $hash ), 'commits' => new CommitsPage( $this->repos, $currRepo, $this->git, $hash ), 'commit' => new DiffPage( $this->repos, $currRepo, $this->git, $hash ), 'tags' => new TagsPage( $this->repos, $currRepo, $this->git ), 'compare' => new ComparePage( $this->repos, $currRepo, $this->git, $hash, $baseHash ), default => new FilePage( $this->repos, $currRepo, $this->git, 'HEAD', '' ) }; } }