Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/treetrek.git
<?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', '' )
    };
  }
}