Major refactoring of the codebase, specially in the directory scanning parts.

I have removed the directory management features from Gitter and ported them to GitList,
since they are application-specific logic. I was unhappy with the way directories and multiple
directories were handled, so i altered almost everything.

The tests are OK, but the coverage is not good. This means that i'll need som help from all
GitList users that are actively testing the development version with multiple directories.

I have removed the directory caching feature for now, it will be re-implemented soon.
This commit is contained in:
Klaus Silveira
2013-06-01 12:51:25 -03:00
parent 5ed21119f6
commit 5122e91b49
17 changed files with 193 additions and 130 deletions

1
.gitignore vendored
View File

@@ -31,3 +31,4 @@ node_modules
config.ini config.ini
cache.properties cache.properties
composer.phar composer.phar
phpunit.xml

View File

@@ -1,13 +1,5 @@
<?php <?php
if (!isset($config)) {
die("No configuration object provided.");
}
if (!is_writable(__DIR__ . DIRECTORY_SEPARATOR . 'cache')) {
die(sprintf('The "%s" folder must be writable for GitList to run.', __DIR__ . DIRECTORY_SEPARATOR . 'cache'));
}
// Startup and configure Silex application // Startup and configure Silex application
$app = new GitList\Application($config, __DIR__); $app = new GitList\Application($config, __DIR__);

View File

@@ -4,7 +4,7 @@
"twig/twig": "1.12.*", "twig/twig": "1.12.*",
"symfony/twig-bridge": "2.2.*", "symfony/twig-bridge": "2.2.*",
"symfony/filesystem": "2.2.*", "symfony/filesystem": "2.2.*",
"klaussilveira/gitter": "dev-master" "klaussilveira/gitter": "0.2.*"
}, },
"require-dev": { "require-dev": {
"symfony/browser-kit": "2.2.*", "symfony/browser-kit": "2.2.*",

31
composer.lock generated
View File

@@ -1,18 +1,22 @@
{ {
"hash": "e1fd62caf104a8cbb216cdb0aa2fe317", "_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
],
"hash": "3b87a5ccc4819475fffa9f49284e65a6",
"packages": [ "packages": [
{ {
"name": "klaussilveira/gitter", "name": "klaussilveira/gitter",
"version": "dev-master", "version": "0.2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/klaussilveira/gitter.git", "url": "https://github.com/klaussilveira/gitter.git",
"reference": "47c7aba9465c22595e7424ba989631aa80ccbea0" "reference": "0.2.0"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/klaussilveira/gitter/zipball/47c7aba9465c22595e7424ba989631aa80ccbea0", "url": "https://api.github.com/repos/klaussilveira/gitter/zipball/0.2.0",
"reference": "47c7aba9465c22595e7424ba989631aa80ccbea0", "reference": "0.2.0",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -47,7 +51,7 @@
"git", "git",
"vcs" "vcs"
], ],
"time": "2013-04-03 13:16:26" "time": "2013-06-01 13:32:37"
}, },
{ {
"name": "pimple/pimple", "name": "pimple/pimple",
@@ -1217,12 +1221,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/DomCrawler.git", "url": "https://github.com/symfony/DomCrawler.git",
"reference": "4639cf28884df5595703153802d74d7384b70296" "reference": "09f0cd5980511ee77c2e8142405ccd5c867506b9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/DomCrawler/zipball/4639cf28884df5595703153802d74d7384b70296", "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/09f0cd5980511ee77c2e8142405ccd5c867506b9",
"reference": "4639cf28884df5595703153802d74d7384b70296", "reference": "09f0cd5980511ee77c2e8142405ccd5c867506b9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1232,12 +1236,12 @@
"symfony/css-selector": ">=2.0,<3.0" "symfony/css-selector": ">=2.0,<3.0"
}, },
"suggest": { "suggest": {
"symfony/css-selector": "2.2.*" "symfony/css-selector": ""
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "2.3-dev" "dev-master": "2.4-dev"
} }
}, },
"autoload": { "autoload": {
@@ -1261,7 +1265,7 @@
], ],
"description": "Symfony DomCrawler Component", "description": "Symfony DomCrawler Component",
"homepage": "http://symfony.com", "homepage": "http://symfony.com",
"time": "2013-04-01 08:07:30" "time": "2013-05-27 14:49:42"
}, },
{ {
"name": "symfony/finder", "name": "symfony/finder",
@@ -1487,8 +1491,7 @@
], ],
"minimum-stability": "dev", "minimum-stability": "dev",
"stability-flags": { "stability-flags": {
"silex/silex": 20, "silex/silex": 20
"klaussilveira/gitter": 20
}, },
"platform": [ "platform": [

View File

@@ -1,26 +1,19 @@
[git] [git]
client = '/usr/bin/git' ; Your git executable path client = '/usr/bin/git' ; Your git executable path
repositories = '/var/www/projects/' ; Path to your repositories
default_branch = 'master' ; Default branch when HEAD is detached default_branch = 'master' ; Default branch when HEAD is detached
repositories[] = '/home/git/repositories/' ; Path to your repositories
; If you wish to add more repositories, just add a new line
; WINDOWS USERS
;Windows Users
;client = '"C:\Program Files (x86)\Git\bin\git.exe"' ; Your git executable path ;client = '"C:\Program Files (x86)\Git\bin\git.exe"' ; Your git executable path
;repositories = 'C:\Path\to\Repos\' ; Path to your repositories ;repositories[] = 'C:\Path\to\Repos\' ; Path to your repositories
; If you want to specify multiple paths, use the array syntax instead:
;
;repositories[] = '/var/www/projects/'
;repositories[] = '/var/www/subdir/more_projects/'
;repositories[] = '/home/user/even_more_projects/'
; You can hide repositories from GitList, just copy this for each repository you want to hide ; You can hide repositories from GitList, just copy this for each repository you want to hide
; hidden[] = '/var/www/projects/BetaTest' ; hidden[] = '/home/git/repositories/BetaTest'
[app] [app]
debug = false debug = false
cache = true
; If you need to specify custom filetypes for certain extensions, do this here ; If you need to specify custom filetypes for certain extensions, do this here
[filetypes] [filetypes]

View File

@@ -14,12 +14,13 @@ if (php_sapi_name() == 'cli-server' && file_exists(substr($_SERVER['REQUEST_URI'
return false; return false;
} }
if (!is_writable(__DIR__ . DIRECTORY_SEPARATOR . 'cache')) {
die(sprintf('The "%s" folder must be writable for GitList to run.', __DIR__ . DIRECTORY_SEPARATOR . 'cache'));
}
require 'vendor/autoload.php'; require 'vendor/autoload.php';
// Load configuration
$config = GitList\Config::fromFile('config.ini'); $config = GitList\Config::fromFile('config.ini');
$app = require 'boot.php'; $app = require 'boot.php';
$app->run(); $app->run();

View File

@@ -36,23 +36,20 @@ class Application extends SilexApplication
// Register services // Register services
$this->register(new TwigServiceProvider(), array( $this->register(new TwigServiceProvider(), array(
'twig.path' => $this->getViewPath(), 'twig.path' => $this->getViewPath(),
'twig.options' => array('cache' => $this->getCachePath() . 'views'), 'twig.options' => $config->get('app', 'cache') ?
array('cache' => $this->getCachePath() . 'views') : array(),
)); ));
$repositories = $config->get('git', 'repositories'); $repositories = $config->get('git', 'repositories');
$repositoryCache = $config->get('app', 'cached_repos');
if (false === $repositoryCache || empty($repositoryCache)) {
$repositoryCache = $this->getCachePath() . 'repos.json';
}
$this->register(new GitServiceProvider(), array( $this->register(new GitServiceProvider(), array(
'git.client' => $config->get('git', 'client'), 'git.client' => $config->get('git', 'client'),
'git.repos' => $repositories, 'git.repos' => $repositories,
'cache.repos' => $repositoryCache, 'ini.file' => "config.ini",
'ini.file' => "config.ini", 'git.hidden' => $config->get('git', 'hidden') ?
'git.hidden' => $config->get('git', 'hidden') ? $config->get('git', 'hidden') : array(),
$config->get('git', 'hidden') : array(), 'git.default_branch' => $config->get('git', 'default_branch') ?
'git.default_branch' => $config->get('git', 'default_branch') ? $config->get('git', 'default_branch') : 'master', $config->get('git', 'default_branch') : 'master',
)); ));
$this->register(new ViewUtilServiceProvider()); $this->register(new ViewUtilServiceProvider());
@@ -100,4 +97,3 @@ class Application extends SilexApplication
return $this->path . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR; return $this->path . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR;
} }
} }

View File

@@ -13,19 +13,15 @@ class Config
} }
$data = parse_ini_file($file, true); $data = parse_ini_file($file, true);
$config = new static($data);
# Ensure that repositories item is an array $config->validateOptions();
if (!is_array($data['git']['repositories'])) {
$data['git']['repositories'] = array($data['git']['repositories']);
}
return new static($data); return $config;
} }
public function __construct($data) public function __construct($data = array())
{ {
$this->data = $data; $this->data = $data;
$this->validateOptions();
} }
public function get($section, $option) public function get($section, $option)
@@ -59,10 +55,6 @@ class Config
{ {
$repositories = $this->get('git', 'repositories'); $repositories = $this->get('git', 'repositories');
if (!is_array($repositories)) {
return;
}
$atLeastOneOk = false; $atLeastOneOk = false;
$atLeastOneWrong = false; $atLeastOneWrong = false;

View File

@@ -13,7 +13,7 @@ class BlobController implements ControllerProviderInterface
$route = $app['controllers_factory']; $route = $app['controllers_factory'];
$route->get('{repo}/blob/{commitishPath}', function ($repo, $commitishPath) use ($app) { $route->get('{repo}/blob/{commitishPath}', function ($repo, $commitishPath) use ($app) {
$repository = $app['git']->getRepository($app['git.repos'], $repo); $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
list($branch, $file) = $app['util.routing'] list($branch, $file) = $app['util.routing']
->parseCommitishPathParam($commitishPath, $repo); ->parseCommitishPathParam($commitishPath, $repo);
@@ -46,7 +46,7 @@ class BlobController implements ControllerProviderInterface
->bind('blob'); ->bind('blob');
$route->get('{repo}/raw/{commitishPath}', function ($repo, $commitishPath) use ($app) { $route->get('{repo}/raw/{commitishPath}', function ($repo, $commitishPath) use ($app) {
$repository = $app['git']->getRepository($app['git.repos'], $repo); $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
list($branch, $file) = $app['util.routing'] list($branch, $file) = $app['util.routing']
->parseCommitishPathParam($commitishPath, $repo); ->parseCommitishPathParam($commitishPath, $repo);

View File

@@ -13,7 +13,7 @@ class CommitController implements ControllerProviderInterface
$route = $app['controllers_factory']; $route = $app['controllers_factory'];
$route->get('{repo}/commits/{commitishPath}', function ($repo, $commitishPath) use ($app) { $route->get('{repo}/commits/{commitishPath}', function ($repo, $commitishPath) use ($app) {
$repository = $app['git']->getRepository($app['git.repos'], $repo); $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
if ($commitishPath === null) { if ($commitishPath === null) {
$commitishPath = $repository->getHead(); $commitishPath = $repository->getHead();
@@ -53,7 +53,7 @@ class CommitController implements ControllerProviderInterface
->bind('commits'); ->bind('commits');
$route->post('{repo}/commits/{branch}/search', function (Request $request, $repo, $branch = '') use ($app) { $route->post('{repo}/commits/{branch}/search', function (Request $request, $repo, $branch = '') use ($app) {
$repository = $app['git']->getRepository($app['git.repos'], $repo); $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
$query = $request->get('query'); $query = $request->get('query');
$commits = $repository->searchCommitLog($request->get('query')); $commits = $repository->searchCommitLog($request->get('query'));
@@ -79,7 +79,7 @@ class CommitController implements ControllerProviderInterface
->bind('searchcommits'); ->bind('searchcommits');
$route->get('{repo}/commit/{commit}', function ($repo, $commit) use ($app) { $route->get('{repo}/commit/{commit}', function ($repo, $commit) use ($app) {
$repository = $app['git']->getRepository($app['git.repos'], $repo); $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
$commit = $repository->getCommit($commit); $commit = $repository->getCommit($commit);
$branch = $repository->getHead(); $branch = $repository->getHead();
@@ -93,7 +93,7 @@ class CommitController implements ControllerProviderInterface
->bind('commit'); ->bind('commit');
$route->get('{repo}/blame/{commitishPath}', function ($repo, $commitishPath) use ($app) { $route->get('{repo}/blame/{commitishPath}', function ($repo, $commitishPath) use ($app) {
$repository = $app['git']->getRepository($app['git.repos'], $repo); $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
list($branch, $file) = $app['util.routing'] list($branch, $file) = $app['util.routing']
->parseCommitishPathParam($commitishPath, $repo); ->parseCommitishPathParam($commitishPath, $repo);

View File

@@ -23,15 +23,12 @@ class MainController implements ControllerProviderInterface
$route->get('/refresh', function(Request $request) use ($app ) { $route->get('/refresh', function(Request $request) use ($app ) {
$app['git']->deleteCached();
# Go back to calling page # Go back to calling page
return $app->redirect($request->headers->get('Referer')); return $app->redirect($request->headers->get('Referer'));
})->bind('refresh'); })->bind('refresh');
$route->get('{repo}/stats/{branch}', function($repo, $branch) use ($app) { $route->get('{repo}/stats/{branch}', function($repo, $branch) use ($app) {
$repository = $app['git']->getRepository($app['git.repos'], $repo); $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
if ($branch === null) { if ($branch === null) {
$branch = $repository->getHead(); $branch = $repository->getHead();
@@ -54,7 +51,7 @@ class MainController implements ControllerProviderInterface
->bind('stats'); ->bind('stats');
$route->get('{repo}/{branch}/rss/', function($repo, $branch) use ($app) { $route->get('{repo}/{branch}/rss/', function($repo, $branch) use ($app) {
$repository = $app['git']->getRepository($app['git.repos'], $repo); $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
if ($branch === null) { if ($branch === null) {
$branch = $repository->getHead(); $branch = $repository->getHead();
@@ -77,4 +74,3 @@ class MainController implements ControllerProviderInterface
return $route; return $route;
} }
} }

View File

@@ -14,7 +14,7 @@ class TreeController implements ControllerProviderInterface
$route = $app['controllers_factory']; $route = $app['controllers_factory'];
$route->get('{repo}/tree/{commitishPath}/', $treeController = function ($repo, $commitishPath = '') use ($app) { $route->get('{repo}/tree/{commitishPath}/', $treeController = function ($repo, $commitishPath = '') use ($app) {
$repository = $app['git']->getRepository($app['git.repos'], $repo); $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
if (!$commitishPath) { if (!$commitishPath) {
$commitishPath = $repository->getHead(); $commitishPath = $repository->getHead();
} }
@@ -48,7 +48,7 @@ class TreeController implements ControllerProviderInterface
->bind('tree'); ->bind('tree');
$route->post('{repo}/tree/{branch}/search', function (Request $request, $repo, $branch = '', $tree = '') use ($app) { $route->post('{repo}/tree/{branch}/search', function (Request $request, $repo, $branch = '', $tree = '') use ($app) {
$repository = $app['git']->getRepository($app['git.repos'], $repo); $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
if (!$branch) { if (!$branch) {
$branch = $repository->getHead(); $branch = $repository->getHead();
} }
@@ -74,7 +74,7 @@ class TreeController implements ControllerProviderInterface
# Intentionally before next statement, because order appears # Intentionally before next statement, because order appears
# to be important, and the other statement got precedence previously. # to be important, and the other statement got precedence previously.
$route->get('{repo}/{format}ball/{branch}', function($repo, $format, $branch) use ($app) { $route->get('{repo}/{format}ball/{branch}', function($repo, $format, $branch) use ($app) {
$repository = $app['git']->getRepository($app['git.repos'], $repo); $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
$tree = $repository->getBranchTree($branch); $tree = $repository->getBranchTree($branch);

View File

@@ -6,17 +6,95 @@ use Gitter\Client as BaseClient;
class Client extends BaseClient class Client extends BaseClient
{ {
protected $default_branch; protected $defaultBranch;
protected $hidden;
public function __construct($options = null) public function __construct($options = null)
{ {
parent::__construct($options); parent::__construct($options['path']);
$this->setDefaultBranch($options['default_branch']);
$this->setHidden($options['hidden']);
}
if (!isset($options['default_branch'])) { public function getRepositoryFromName($paths, $repo)
$options['default_branch'] = 'master'; {
$repositories = $this->getRepositories($paths);
$path = $repositories[$repo]['path'];
return $this->getRepository($path);
}
/**
* Searches for valid repositories on the specified path
*
* @param array $paths Array of paths where repositories will be searched
* @return array Found repositories, containing their name, path and description
*/
public function getRepositories($paths)
{
$allRepositories = array();
foreach ($paths as $path) {
$repositories = $this->recurseDirectory($path);
if (empty($repositories)) {
throw new \RuntimeException('There are no GIT repositories in ' . $path);
}
$allRepositories = array_merge($allRepositories, $repositories);
} }
$this->setDefaultBranch($options['default_branch']); $allRepositories = array_unique($allRepositories, SORT_REGULAR);
asort($allRepositories);
return $allRepositories;
}
private function recurseDirectory($path)
{
$dir = new \DirectoryIterator($path);
$repositories = array();
foreach ($dir as $file) {
if ($file->isDot()) {
continue;
}
if (strrpos($file->getFilename(), '.') === 0) {
continue;
}
if ($file->isDir()) {
$isBare = file_exists($file->getPathname() . '/HEAD');
$isRepository = file_exists($file->getPathname() . '/.git/HEAD');
if ($isRepository || $isBare) {
if (in_array($file->getPathname(), $this->getHidden())) {
continue;
}
if ($isBare) {
$description = $file->getPathname() . '/description';
} else {
$description = $file->getPathname() . '/.git/description';
}
if (file_exists($description)) {
$description = file_get_contents($description);
} else {
$description = null;
}
$repositories[$file->getFilename()] = array('name' => $file->getFilename(), 'path' => $file->getPathname(), 'description' => $description);
continue;
} else {
$repositories = array_merge($repositories, $this->recurseDirectory($file->getPathname()));
}
}
}
return $repositories;
} }
/** /**
@@ -26,7 +104,7 @@ class Client extends BaseClient
*/ */
protected function setDefaultBranch($branch) protected function setDefaultBranch($branch)
{ {
$this->default_branch = $branch; $this->defaultBranch = $branch;
return $this; return $this;
} }
@@ -36,14 +114,35 @@ class Client extends BaseClient
*/ */
public function getDefaultBranch() public function getDefaultBranch()
{ {
return $this->default_branch; return $this->defaultBranch;
} }
/** /**
* Creates a new repository on the specified path * Get hidden repository list
* *
* @param string $path Path where the new repository will be created * @return array List of repositories to hide
* @return Repository Instance of Repository */
protected function getHidden()
{
return $this->hidden;
}
/**
* Set the hidden repository list
*
* @param array $hidden List of repositories to hide
*/
protected function setHidden($hidden)
{
$this->hidden = $hidden;
return $this;
}
/**
* Overloads the parent::createRepository method for the correct Repository class instance
*
* {@inheritdoc}
*/ */
public function createRepository($path, $bare = null) public function createRepository($path, $bare = null)
{ {
@@ -57,25 +156,16 @@ class Client extends BaseClient
} }
/** /**
* Opens a specified repository * Overloads the parent::getRepository method for the correct Repository class instance
* *
* @param array $repos Array of items describing configured repositories * {@inheritdoc}
* @param string $repo Name of repository we are currently handling
* @return Repository Instance of Repository
*/ */
public function getRepository($repos, $repo) public function getRepository($path)
{ {
$repotmp = $this->getRepositoryCached($repos, $repo);
$path = $repotmp->getPath();
if (!file_exists($path) || !file_exists($path . '/.git/HEAD') && !file_exists($path . '/HEAD')) { if (!file_exists($path) || !file_exists($path . '/.git/HEAD') && !file_exists($path . '/HEAD')) {
throw new \RuntimeException('There is no GIT repository at ' . $path); throw new \RuntimeException('There is no GIT repository at ' . $path);
} }
if (in_array($path, $this->getHidden())) {
throw new \RuntimeException('You don\'t have access to this repository');
}
return new Repository($path, $this); return new Repository($path, $this);
} }
} }

View File

@@ -21,7 +21,6 @@ class GitServiceProvider implements ServiceProviderInterface
$options['path'] = $app['git.client']; $options['path'] = $app['git.client'];
$options['hidden'] = $app['git.hidden']; $options['hidden'] = $app['git.hidden'];
$options['ini.file'] = $app['ini.file']; $options['ini.file'] = $app['ini.file'];
$options['cache.repos'] = $app['cache.repos'];
$options['default_branch'] = $app['git.default_branch']; $options['default_branch'] = $app['git.default_branch'];
return new Client($options); return new Client($options);
@@ -32,4 +31,3 @@ class GitServiceProvider implements ServiceProviderInterface
{ {
} }
} }

View File

@@ -24,7 +24,7 @@ class Routing
public function parseCommitishPathParam($commitishPath, $repo) public function parseCommitishPathParam($commitishPath, $repo)
{ {
$app = $this->app; $app = $this->app;
$repository = $app['git']->getRepository($app['git.repos'], $repo); $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
$commitish = null; $commitish = null;
$path = null; $path = null;
@@ -105,7 +105,7 @@ class Routing
$self = $this; $self = $this;
$quotedPaths = array_map( $quotedPaths = array_map(
function ($repo) use ($app, $self) { function ($repo) use ($app, $self) {
$repoName = $repo['name'] ; $repoName = $repo['name'];
//Windows //Windows
if ($self->isWindows()){ if ($self->isWindows()){
$repoName = str_replace('\\', '\\\\',$repoName); $repoName = str_replace('\\', '\\\\',$repoName);
@@ -131,12 +131,14 @@ class Routing
public function isWindows() public function isWindows()
{ {
switch(PHP_OS){ switch (PHP_OS) {
case 'WIN32': case 'WIN32':
case 'WINNT': case 'WINNT':
case 'Windows': return true; case 'Windows':
default : return false; return true;
} default:
return false;
}
} }
/** /**

View File

@@ -2,13 +2,12 @@
use Silex\WebTestCase; use Silex\WebTestCase;
use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Filesystem;
use Gitter\Client; use GitList\Git\Client;
class InterfaceTest extends WebTestCase class InterfaceTest extends WebTestCase
{ {
protected static $tmpdir; protected static $tmpdir;
protected static $gitPath; protected static $gitPath;
protected static $cached_repos;
public static function setUpBeforeClass() public static function setUpBeforeClass()
{ {
@@ -31,13 +30,11 @@ class InterfaceTest extends WebTestCase
$options['path'] = getenv('GIT_CLIENT') ?: '/usr/bin/git'; $options['path'] = getenv('GIT_CLIENT') ?: '/usr/bin/git';
$options['hidden'] = array(self::$tmpdir . '/hiddenrepo'); $options['hidden'] = array(self::$tmpdir . '/hiddenrepo');
$options['default_branch'] = 'master';
$options['ini.file'] = "config.ini"; $options['ini.file'] = "config.ini";
$cached_dir = self::$tmpdir . DIRECTORY_SEPARATOR . 'cache'; $cacheDir = self::$tmpdir . DIRECTORY_SEPARATOR . 'cache';
$fs->mkdir($cached_dir); $fs->mkdir($cacheDir);
self::$cached_repos = $cached_dir . DIRECTORY_SEPARATOR . 'repos.json';
$options['cache.repos'] = self::$cached_repos;
$git = new Client($options); $git = new Client($options);
@@ -45,7 +42,7 @@ class InterfaceTest extends WebTestCase
// GitTest repository fixture // GitTest repository fixture
$git->createRepository(self::$tmpdir . 'GitTest'); $git->createRepository(self::$tmpdir . 'GitTest');
$repository = $git->getRepositoryCached(self::$tmpdir, 'GitTest'); $repository = $git->getRepository(self::$tmpdir . 'GitTest');
file_put_contents(self::$tmpdir . 'GitTest/README.md', "## GitTest\nGitTest is a *test* repository!"); file_put_contents(self::$tmpdir . 'GitTest/README.md', "## GitTest\nGitTest is a *test* repository!");
file_put_contents(self::$tmpdir . 'GitTest/test.php', "<?php\necho 'Hello World'; // This is a test"); file_put_contents(self::$tmpdir . 'GitTest/test.php', "<?php\necho 'Hello World'; // This is a test");
$repository->setConfig('user.name', 'Luke Skywalker'); $repository->setConfig('user.name', 'Luke Skywalker');
@@ -58,7 +55,7 @@ class InterfaceTest extends WebTestCase
// foobar repository fixture // foobar repository fixture
$git->createRepository(self::$tmpdir . 'foobar'); $git->createRepository(self::$tmpdir . 'foobar');
$repository = $git->getRepositoryCached(self::$tmpdir, 'foobar'); $repository = $git->getRepository(self::$tmpdir . 'foobar');
file_put_contents(self::$tmpdir . 'foobar/bar.json', "{\n\"name\": \"foobar\"\n}"); file_put_contents(self::$tmpdir . 'foobar/bar.json', "{\n\"name\": \"foobar\"\n}");
file_put_contents(self::$tmpdir . 'foobar/.git/description', 'This is a test repo!'); file_put_contents(self::$tmpdir . 'foobar/.git/description', 'This is a test repo!');
@@ -77,7 +74,7 @@ class InterfaceTest extends WebTestCase
$nested_dir = self::$tmpdir . 'nested/'; $nested_dir = self::$tmpdir . 'nested/';
$fs->mkdir($nested_dir); $fs->mkdir($nested_dir);
$git->createRepository($nested_dir . 'NestedRepo'); $git->createRepository($nested_dir . 'NestedRepo');
$repository = $git->getRepositoryCached($nested_dir, 'NestedRepo'); $repository = $git->getRepository($nested_dir . 'NestedRepo');
file_put_contents($nested_dir . 'NestedRepo/.git/description', 'This is a NESTED test repo!'); file_put_contents($nested_dir . 'NestedRepo/.git/description', 'This is a NESTED test repo!');
file_put_contents($nested_dir . 'NestedRepo/README.txt', 'NESTED TEST REPO README'); file_put_contents($nested_dir . 'NestedRepo/README.txt', 'NESTED TEST REPO README');
$repository->setConfig('user.name', 'Luke Skywalker'); $repository->setConfig('user.name', 'Luke Skywalker');
@@ -93,7 +90,7 @@ class InterfaceTest extends WebTestCase
// master-less repository fixture // master-less repository fixture
$git->createRepository(self::$tmpdir . 'develop'); $git->createRepository(self::$tmpdir . 'develop');
$repository = $git->getRepositoryCached(self::$tmpdir, 'develop'); $repository = $git->getRepository(self::$tmpdir . 'develop');
$repository->setConfig('user.name', 'Luke Skywalker'); $repository->setConfig('user.name', 'Luke Skywalker');
$repository->setConfig('user.email', 'luke@rebel.org'); $repository->setConfig('user.email', 'luke@rebel.org');
file_put_contents(self::$tmpdir . 'develop/README.md', "## develop\ndevelop is a *test* repository!"); file_put_contents(self::$tmpdir . 'develop/README.md', "## develop\ndevelop is a *test* repository!");
@@ -110,25 +107,23 @@ class InterfaceTest extends WebTestCase
// Detached HEAD repository fixture // Detached HEAD repository fixture
$git->createRepository(self::$tmpdir . 'detached-head'); $git->createRepository(self::$tmpdir . 'detached-head');
$repository = $git->getRepositoryCached(self::$tmpdir, 'detached-head'); $repository = $git->getRepository(self::$tmpdir . 'detached-head');
# $repository = $git->getRepository(self::$tmpdir . '/detached-head');
$repository->setConfig('user.name', 'Luke Skywalker'); $repository->setConfig('user.name', 'Luke Skywalker');
$repository->setConfig('user.email', 'luke@rebel.org'); $repository->setConfig('user.email', 'luke@rebel.org');
file_put_contents(self::$tmpdir . 'detached-head/README.md', "## detached head\ndetached-head is a *test* repository!"); file_put_contents(self::$tmpdir . 'detached-head/README.md', "## detached head\ndetached-head is a *test* repository!");
$repository->addAll(); $repository->addAll();
$repository->commit("First commit"); $repository->commit("First commit");
$repository->checkout('HEAD'); $repository->checkout('HEAD');
$git->deleteCached();
} }
public function createApplication() public function createApplication()
{ {
$config = GitList\Config::fromFile('config.ini'); $config = new GitList\Config;
$config->set('app', 'cached_repos', self::$cached_repos);
$config->set('git', 'repositories', self::$tmpdir);
$config->set('app', 'debug', true); $config->set('app', 'debug', true);
$config->set('app', 'debug', false);
$config->set('git', 'client', self::$gitPath); $config->set('git', 'client', self::$gitPath);
$config->set('git', 'default_branch', 'master');
$config->set('git', 'repositories', array(self::$tmpdir));
$app = require 'boot.php'; $app = require 'boot.php';
return $app; return $app;

View File

@@ -13,7 +13,11 @@
<a href="{{ path('rss', {repo: repository.name, branch: 'master'}) }}"><i class="rss pull-right"></i></a> <a href="{{ path('rss', {repo: repository.name, branch: 'master'}) }}"><i class="rss pull-right"></i></a>
</div> </div>
<div class="repository-body"> <div class="repository-body">
{% if repository.description %}
<p>{{ repository.description }}</p> <p>{{ repository.description }}</p>
{% else %}
<p>There is no repository description file. Please, create one to remove this message.</p>
{% endif %}
</div> </div>
</div> </div>
{% endfor %} {% endfor %}