Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
| 1 | <?php |
||
| 19 | class RepositoryController extends Controller |
||
| 20 | { |
||
| 21 | protected $client; |
||
| 22 | protected $hidden; |
||
| 23 | |||
| 24 | public function __construct() |
||
| 25 | { |
||
| 26 | $this->hidden = []; |
||
| 27 | $this->client = new Client(Setting::get('git_client_path')); |
||
| 28 | } |
||
| 29 | |||
| 30 | /** |
||
| 31 | * Display a listing of the resource. |
||
| 32 | * |
||
| 33 | * @return \Illuminate\Http\Response |
||
| 34 | */ |
||
| 35 | public function index($project = null) |
||
| 40 | |||
| 41 | public function showRepo($team, $project) |
||
| 42 | { |
||
| 43 | return $this->showTree($team.'/'.$project, ''); |
||
| 44 | } |
||
| 45 | |||
| 46 | public function showTree($repo, $path) |
||
| 47 | { |
||
| 48 | $repository = $this->getRepositoryFromName([Setting::get('git_repositories_path')], $repo); |
||
| 49 | |||
| 50 | if (! $path) { |
||
| 51 | $path = $repository->getHead(); |
||
| 52 | } |
||
| 53 | |||
| 54 | if (strpos($path, '/') !== false) { |
||
| 55 | $branch = strstr($path, '/', true); |
||
| 56 | $tree = str_replace($branch.'/', '', $path); |
||
| 57 | } else { |
||
| 58 | $branch = $path; |
||
| 59 | $tree = ''; |
||
| 60 | } |
||
| 61 | |||
| 62 | $parent = null; |
||
| 63 | if (($slash = strrpos($tree, '/')) !== false) { |
||
| 64 | $parent = substr($tree, 0, $slash); |
||
| 65 | } elseif (! empty($tree)) { |
||
| 66 | $parent = ''; |
||
| 67 | } |
||
| 68 | |||
| 69 | $files = $repository->getTree($tree ? "$branch:\"$tree\"/" : $branch); |
||
| 70 | |||
| 71 | $pageTitle = sprintf('"%s" - %s - %s', 'project title', trans('dashboard.projects.edit.title'), trans('dashboard.dashboard')); |
||
| 72 | |||
| 73 | return View::make('dashboard.repositories.tree') |
||
| 74 | ->withPageTitle($pageTitle) |
||
| 75 | ->withRepository($repository) |
||
| 76 | ->withRepo($repo) |
||
| 77 | ->withCurrentBranch($branch) |
||
| 78 | ->withBranches($repository->getBranches()) |
||
| 79 | ->withPath($tree ? $tree.'/' : $tree) |
||
| 80 | ->withParentPath($parent) |
||
| 81 | ->withFiles($files->output()); |
||
| 82 | } |
||
| 83 | |||
| 84 | View Code Duplication | public function showBlob($repo, $path) |
|
| 85 | { |
||
| 86 | $pageTitle = sprintf('"%s" - %s - %s', 'project title', trans('dashboard.projects.edit.title'), trans('dashboard.dashboard')); |
||
| 87 | |||
| 88 | return View::make('dashboard.repositories.blob') |
||
| 89 | ->withPageTitle($pageTitle) |
||
| 90 | ->withProject([]) |
||
| 91 | ->withGroups([]); |
||
| 92 | } |
||
| 93 | |||
| 94 | View Code Duplication | public function showCommits($repo, $path) |
|
| 95 | { |
||
| 96 | $pageTitle = sprintf('"%s" - %s - %s', 'project title', trans('dashboard.projects.edit.title'), trans('dashboard.dashboard')); |
||
| 97 | |||
| 98 | return View::make('dashboard.repositories.commits') |
||
| 99 | ->withPageTitle($pageTitle) |
||
| 100 | ->withProject([]) |
||
| 101 | ->withGroups([]); |
||
| 102 | } |
||
| 103 | |||
| 104 | View Code Duplication | public function showRaw($repo, $path) |
|
| 105 | { |
||
| 106 | $pageTitle = sprintf('"%s" - %s - %s', 'project title', trans('dashboard.projects.edit.title'), trans('dashboard.dashboard')); |
||
| 107 | |||
| 108 | return View::make('dashboard.repositories.raw') |
||
| 109 | ->withPageTitle($pageTitle) |
||
| 110 | ->withProject([]) |
||
| 111 | ->withGroups([]); |
||
| 112 | } |
||
| 113 | |||
| 114 | View Code Duplication | public function showBlame($repo, $path) |
|
| 123 | |||
| 124 | public function getRepositoryFromName($paths, $repo) |
||
| 125 | { |
||
| 126 | $repositories = $this->getRepositories($paths); |
||
| 127 | $path = $repositories[$repo]['path']; |
||
| 128 | |||
| 129 | return $this->client->getRepository($path); |
||
| 130 | } |
||
| 131 | |||
| 132 | /** |
||
| 133 | * Searches for valid repositories on the specified path. |
||
| 134 | * |
||
| 135 | * @param array $paths Array of paths where repositories will be searched |
||
| 136 | * |
||
| 137 | * @return array Found repositories, containing their name, path and description sorted |
||
| 138 | * by repository name |
||
| 139 | */ |
||
| 140 | public function getRepositories($paths) |
||
| 141 | { |
||
| 142 | $allRepositories = []; |
||
| 143 | |||
| 144 | foreach ($paths as $path) { |
||
| 145 | $repositories = $this->recurseDirectory($path); |
||
| 146 | |||
| 147 | if (empty($repositories)) { |
||
| 148 | throw new \RuntimeException('There are no GIT repositories in '.$path); |
||
| 149 | } |
||
| 150 | |||
| 151 | $allRepositories = $allRepositories + $repositories; |
||
| 152 | } |
||
| 153 | |||
| 154 | $allRepositories = array_unique($allRepositories, SORT_REGULAR); |
||
| 155 | uksort($allRepositories, function ($k1, $k2) { |
||
| 156 | return strtolower($k2) < strtolower($k1); |
||
| 157 | }); |
||
| 158 | |||
| 159 | return $allRepositories; |
||
| 160 | } |
||
| 161 | |||
| 162 | private function recurseDirectory($path, $topLevel = true) |
||
| 163 | { |
||
| 164 | $dir = new \DirectoryIterator($path); |
||
| 165 | |||
| 166 | $repositories = []; |
||
| 167 | |||
| 168 | foreach ($dir as $file) { |
||
| 169 | if ($file->isDot()) { |
||
| 170 | continue; |
||
| 171 | } |
||
| 172 | |||
| 173 | if (strrpos($file->getFilename(), '.') === 0) { |
||
| 174 | continue; |
||
| 175 | } |
||
| 176 | |||
| 177 | if (! $file->isReadable()) { |
||
| 178 | continue; |
||
| 179 | } |
||
| 180 | |||
| 181 | if ($file->isDir()) { |
||
| 182 | $isBare = file_exists($file->getPathname().'/HEAD'); |
||
| 183 | $isRepository = file_exists($file->getPathname().'/.git/HEAD'); |
||
| 184 | |||
| 185 | if ($isRepository || $isBare) { |
||
| 186 | if (in_array($file->getPathname(), $this->getHidden(), true)) { |
||
| 187 | continue; |
||
| 188 | } |
||
| 189 | |||
| 190 | if ($isBare) { |
||
| 191 | $description = $file->getPathname().'/description'; |
||
| 192 | } else { |
||
| 193 | $description = $file->getPathname().'/.git/description'; |
||
| 194 | } |
||
| 195 | |||
| 196 | if (file_exists($description)) { |
||
| 197 | $description = file_get_contents($description); |
||
| 198 | } else { |
||
| 199 | $description = null; |
||
| 200 | } |
||
| 201 | |||
| 202 | if (! $topLevel) { |
||
| 203 | $repoName = $file->getPathInfo()->getFilename().'/'.$file->getFilename(); |
||
| 204 | } else { |
||
| 205 | $repoName = $file->getFilename(); |
||
| 206 | } |
||
| 207 | |||
| 208 | $repositories[$repoName] = [ |
||
| 209 | 'name' => $repoName, |
||
| 210 | 'path' => $file->getPathname(), |
||
| 211 | 'description' => $description, |
||
| 212 | ]; |
||
| 213 | |||
| 214 | continue; |
||
| 215 | } else { |
||
| 216 | $repositories = array_merge($repositories, $this->recurseDirectory($file->getPathname(), false)); |
||
| 217 | } |
||
| 218 | } |
||
| 219 | } |
||
| 220 | |||
| 221 | return $repositories; |
||
| 222 | } |
||
| 223 | |||
| 224 | /** |
||
| 225 | * Get hidden repository list. |
||
| 226 | * |
||
| 227 | * @return array List of repositories to hide |
||
| 228 | */ |
||
| 229 | protected function getHidden() |
||
| 233 | } |
||
| 234 |