Teknik is a suite of services with attractive and functional interfaces. https://www.teknik.io/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Routing.php 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <?php
  2. namespace GitList\Util;
  3. use Silex\Application;
  4. use GitList\Exception\EmptyRepositoryException;
  5. class Routing
  6. {
  7. protected $app;
  8. public function __construct(Application $app)
  9. {
  10. $this->app = $app;
  11. }
  12. /* @brief Return $commitish, $path parsed from $commitishPath, based on
  13. * what's in $repo. Raise a 404 if $branchpath does not represent a
  14. * valid branch and path.
  15. *
  16. * A helper for parsing routes that use commit-ish names and paths
  17. * separated by /, since route regexes are not enough to get that right.
  18. */
  19. public function parseCommitishPathParam($commitishPath, $repo)
  20. {
  21. $app = $this->app;
  22. $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
  23. $commitish = null;
  24. $path = null;
  25. $slashPosition = strpos($commitishPath, '/');
  26. if (strlen($commitishPath) >= 40 &&
  27. ($slashPosition === false ||
  28. $slashPosition === 40)) {
  29. // We may have a commit hash as our commitish.
  30. $hash = substr($commitishPath, 0, 40);
  31. if ($repository->hasCommit($hash)) {
  32. $commitish = $hash;
  33. }
  34. }
  35. if ($commitish === null) {
  36. $branches = $repository->getBranches();
  37. $tags = $repository->getTags();
  38. if ($tags !== null && count($tags) > 0) {
  39. $branches = array_merge($branches, $tags);
  40. }
  41. $matchedBranch = null;
  42. $matchedBranchLength = 0;
  43. foreach ($branches as $branch) {
  44. if (strpos($commitishPath, $branch) === 0 &&
  45. strlen($branch) > $matchedBranchLength) {
  46. $matchedBranch = $branch;
  47. $matchedBranchLength = strlen($matchedBranch);
  48. }
  49. }
  50. if ($matchedBranch !== null) {
  51. $commitish = $matchedBranch;
  52. } else {
  53. // We may have partial commit hash as our commitish.
  54. $hash = $slashPosition === false ? $commitishPath : substr($commitishPath, 0, $slashPosition);
  55. if ($repository->hasCommit($hash)) {
  56. $commit = $repository->getCommit($hash);
  57. $commitish = $commit->getHash();
  58. } else {
  59. throw new EmptyRepositoryException('This repository is currently empty. There are no commits.');
  60. }
  61. }
  62. }
  63. $commitishLength = strlen($commitish);
  64. $path = substr($commitishPath, $commitishLength);
  65. if (strpos($path, '/') === 0) {
  66. $path = substr($path, 1);
  67. }
  68. return array($commitish, $path);
  69. }
  70. public function getBranchRegex()
  71. {
  72. static $branchRegex = null;
  73. if ($branchRegex === null) {
  74. $branchRegex = '(?!/|.*([/.]\.|//|@\{|\\\\))[^\040\177 ~^:?*\[]+(?<!\.lock|[/.])';
  75. }
  76. return $branchRegex;
  77. }
  78. public function getCommitishPathRegex()
  79. {
  80. static $commitishPathRegex = null;
  81. if ($commitishPathRegex === null) {
  82. $commitishPathRegex = '.+';
  83. }
  84. return $commitishPathRegex;
  85. }
  86. public function getRepositoryRegex()
  87. {
  88. static $regex = null;
  89. if ($regex === null) {
  90. $isWindows = $this->isWindows();
  91. $quotedPaths = array_map(
  92. function ($repo) use ($isWindows) {
  93. $repoName = preg_quote($repo['name']);
  94. if ($isWindows) {
  95. $repoName = str_replace('\\', '\\\\', $repoName);
  96. }
  97. return $repoName;
  98. },
  99. $this->app['git']->getRepositories($this->app['git.repos'])
  100. );
  101. usort(
  102. $quotedPaths,
  103. function ($a, $b) {
  104. return strlen($b) - strlen($a);
  105. }
  106. );
  107. $regex = implode('|', $quotedPaths);
  108. }
  109. return $regex;
  110. }
  111. public function isWindows()
  112. {
  113. switch (PHP_OS) {
  114. case 'WIN32':
  115. case 'WINNT':
  116. case 'Windows':
  117. return true;
  118. default:
  119. return false;
  120. }
  121. }
  122. /**
  123. * Strips the base path from a full repository path
  124. *
  125. * @param string $repoPath Full path to the repository
  126. * @return string Relative path to the repository from git.repositories
  127. */
  128. public function getRelativePath($repoPath)
  129. {
  130. if (strpos($repoPath, $this->app['git.repos']) === 0) {
  131. $relativePath = substr($repoPath, strlen($this->app['git.repos']));
  132. return ltrim(strtr($relativePath, '\\', '/'), '/');
  133. } else {
  134. throw new \InvalidArgumentException(
  135. sprintf("Path '%s' does not match configured repository directory", $repoPath)
  136. );
  137. }
  138. }
  139. }