From 4bb58cbe2fd3ba10531dd0453cbfd7750dd1fe52 Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Fri, 4 Oct 2013 14:05:14 +0200 Subject: [PATCH 01/19] Added guardfile to ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index aaa7bfb..00a9c31 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,4 @@ phpunit.xml composer.lock !.gitkeep config.php +Guardfile From e7a0d97f33cf66ef933b9f706addb5e1dfc6ac72 Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Fri, 4 Oct 2013 14:05:14 +0200 Subject: [PATCH 02/19] Added guardfile to ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index aaa7bfb..00a9c31 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,4 @@ phpunit.xml composer.lock !.gitkeep config.php +Guardfile From 627abdf1457e7f2e65653b1f11c45ace1fb45155 Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Thu, 28 Nov 2013 07:15:59 +0100 Subject: [PATCH 03/19] DRY repository loading --- index.php | 21 ++++---- src/GitPrettyStats/RepositoryList.php | 70 +++++++++++++++++---------- 2 files changed, 56 insertions(+), 35 deletions(-) diff --git a/index.php b/index.php index ad9a34e..ddc7d84 100644 --- a/index.php +++ b/index.php @@ -32,8 +32,9 @@ $app['config'] = $config; - $repositoryList = new RepositoryList($repositoriesPath); - $app['repositories'] = $repositoryList->getRepositories(); + $repositoryList = new RepositoryList($repositoriesPath); + $app['repositories'] = $repositoryList->getRepositories(); + $app['repositoryList'] = new RepositoryList; if (count($app['repositories']) == 0) { throw new RuntimeException("No repositories found in path: $repositoriesPath", 0); @@ -42,21 +43,23 @@ function loadRepository ($app, $path) { - $repositoryPath = $app['config']['repositoriesPath'][$path]; - //trying the old-fashioned way for compatibility - if( !realpath($repositoryPath) ){ + if (isset($app['config']['repositoriesPath'][$path])) { + $repositoryPath = $app['config']['repositoriesPath'][$path]; + } elseif (!realpath($path)) { $repositoryPath = $app['config']['repositoriesPath'] . '/' . $path; } + + if (!$repository = $app['repositoryList']->loadRepository($repositoryPath)) { + throw new RuntimeException('The repository path does not contain a valid git repository', 0, $e); + } + try { - $gitWrapper = new \PHPGit_Repository(__DIR__ . '/' . $repositoryPath); - $repository = new Repository($gitWrapper); $repository->loadCommits(); - $app['repository'] = $repository; } catch (Exception $e) { // Catch all possible errors while loading the repository, re-wrap it with a friendlier // message and re-throw so it's caught by the error handler: // (the original exception is chained to the new one): - throw new RuntimeException('The repository path does not contain a valid git repository', 0, $e); + throw new RuntimeException('Could not load commits from repository', 0, $e); } return $repository; diff --git a/src/GitPrettyStats/RepositoryList.php b/src/GitPrettyStats/RepositoryList.php index 99384b3..9d8b949 100644 --- a/src/GitPrettyStats/RepositoryList.php +++ b/src/GitPrettyStats/RepositoryList.php @@ -17,7 +17,7 @@ class RepositoryList * @param string $path Path to repositories * @return void */ - public function __construct($path) + public function __construct($path = null) { $this->path = $path; } @@ -29,40 +29,58 @@ public function __construct($path) */ public function getRepositories () { - $repositories = array(); - if ( is_array($this->path) ){ - foreach ($this->path as $key => $repo) { - try { - $gitWrapper = new \PHPGit_Repository(__DIR__ . '/../../' . $repo . '/'); - $repository = new Repository($gitWrapper); - $repositories[] = array( - 'name' => $repository->getName(), - 'commits' => $repository->countCommitsFromGit(), - 'branch' => $repository->getGitWrapper()->getCurrentBranch() - ); - } catch (Exception $e) { - // Not a valid repository - } + $repositories = array(); + $loadRepositoryPaths = array(); + + // Config with array of paths to repositories + if (is_array($this->path)) { + foreach ($this->path as $repo) { + $loadRepositoryPaths[] = realpath(__DIR__ . '/../../' . $repo . '/'); } } + // Config with path to directory of repositories elseif ($handle = opendir($this->path)) { while (false !== ($entry = readdir($handle))) { if ($entry == '.' || $entry == '..') { continue; } - try { - $gitWrapper = new \PHPGit_Repository(__DIR__ . '/../../' . $this->path . '/' . $entry); - $repository = new Repository($gitWrapper); - $repositories[] = array( - 'name' => $repository->getName(), - 'commits' => $repository->countCommitsFromGit(), - 'branch' => $repository->getGitWrapper()->getCurrentBranch() - ); - } catch (Exception $e) { - // Not a valid repository - } + + $loadRepositoryPaths[] = realpath(__DIR__ . '/../../' . $this->path . '/' . $entry); } } + + // Load repositories + foreach ($loadRepositoryPaths as $loadRepositoryPath) { + if ($repository = $this->loadRepository($loadRepositoryPath)) { + $repositories[] = array( + 'name' => $repository->getName(), + 'commits' => $repository->countCommitsFromGit(), + 'branch' => $repository->getGitWrapper()->getCurrentBranch() + ); + } + } + return $repositories; } + + /** + * Load a repository for given path + * + * @param string $path Location of reposittory + * @return mixed + */ + public function loadRepository ($path) + { + if ( !is_dir($path)) { + return false; + } + + try { + $gitWrapper = new \PHPGit_Repository($path); + $repository = new Repository($gitWrapper); + return $repository; + } catch (Exception $e) { + return false; + } + } } From a294a446234e073687244eb50c318fdae6d2e1ca Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Thu, 28 Nov 2013 07:23:07 +0100 Subject: [PATCH 04/19] Added klaussilveira/gitter to composer --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index be945bc..6a9a958 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,8 @@ "silex/silex": "1.0.*@dev", "twig/twig": "1.*", "ornicar/php-git-repo": "dev-master", - "nesbot/carbon": "dev-master" + "nesbot/carbon": "dev-master", + "klaussilveira/gitter": "0.2.0" }, "require-dev": { "phpunit/phpunit": "3.7.*@dev", From 61165603e7ee9a41da50a2611907e2d758ddc7eb Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Thu, 28 Nov 2013 20:44:34 +0100 Subject: [PATCH 05/19] Specified version of Carbon --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 6a9a958..63d3d4d 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "silex/silex": "1.0.*@dev", "twig/twig": "1.*", "ornicar/php-git-repo": "dev-master", - "nesbot/carbon": "dev-master", + "nesbot/carbon": "1.6.0", "klaussilveira/gitter": "0.2.0" }, "require-dev": { From 3ff2eb982878f44aa2500e02080fff7d5733da31 Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Thu, 28 Nov 2013 20:44:57 +0100 Subject: [PATCH 06/19] Started converting to Gitter as git wrapper --- index.php | 2 +- src/GitPrettyStats/Repository.php | 96 +++++++++++++-------------- src/GitPrettyStats/RepositoryList.php | 5 +- 3 files changed, 48 insertions(+), 55 deletions(-) diff --git a/index.php b/index.php index ddc7d84..df3edc4 100644 --- a/index.php +++ b/index.php @@ -81,7 +81,7 @@ function loadRepository ($app, $path) { array( 'repositories' => $app['repositories'], 'name' => $repository->getName(), - 'branch' => $repository->getGitWrapper()->getCurrentBranch(), + 'branch' => $repository->gitter->getCurrentBranch(), 'statsEndpoint' => $app["request"]->getBaseUrl() . "/stats/" . $path, ) ); diff --git a/src/GitPrettyStats/Repository.php b/src/GitPrettyStats/Repository.php index f996504..5ae0bcb 100644 --- a/src/GitPrettyStats/Repository.php +++ b/src/GitPrettyStats/Repository.php @@ -2,6 +2,7 @@ namespace GitPrettyStats; use Carbon\Carbon; +use Gitter\Client; /** * Class Repository @@ -9,8 +10,11 @@ */ class Repository { - /** @var \PHPGit_Repository */ - public $gitWrapper; + /** @var \Gitter\Repository */ + public $gitter; + + /** @var \Gitter\Client */ + public $client; /** @var array Storage for "raw" commits */ public $commits = array(); @@ -43,21 +47,22 @@ class Repository /** * Constructor * - * @param \PHPGit_Repository $gitwrapper Wrapper for git commands + * @param \Gitter\Client $client Git client * @return void */ - public function __construct(\PHPGit_Repository $gitWrapper) + public function __construct($path) { - $this->gitWrapper = $gitWrapper; + $this->client = new Client; + $this->gitter = $this->client->getRepository($path); $this->statistics = new Statistics($this); } /** * @return \PHPGit_Repository */ - public function getGitWrapper() + public function getClient() { - return $this->gitWrapper; + return $this->client; } /** @@ -67,7 +72,8 @@ public function getGitWrapper() */ public function getName () { - $path = $this->getGitWrapper()->git('rev-parse --show-toplevel'); + return 'Asdf'; + $path = $this->getClient()->run('rev-parse --show-toplevel'); $name = substr($path, strrpos($path, '/') + 1); return $name; } @@ -79,7 +85,8 @@ public function getName () */ public function countCommitsFromGit () { - return $this->getGitWrapper()->git('git rev-list --count HEAD'); + return 12; + return $this->getClient()->git('git rev-list --count HEAD'); } /** @@ -89,8 +96,9 @@ public function countCommitsFromGit () */ public function loadCommits() { - $rawCommits = $this->getCommits(-1); - $this->commits = $this->parseLogsIntoArray(trim($rawCommits)); + $this->commits = $this->gitter->getCommits(); + + $this->parseCommits(); } /** @@ -118,52 +126,37 @@ public function getNumberOfContributors() * * @return array list of commits and their properties **/ - public function getCommits($numberOfCommits = 10) - { - $output = $this->getGitWrapper()->git( - sprintf( - '--no-pager log -n %d --date=%s --format=format:"%s" --reverse', - $numberOfCommits, - $this->dateFormat, - implode('|', $this->logFormat) - ) - ); - return $output; - } + // public function getCommits($numberOfCommits = 10) + // { + // $output = $this->getClient()->git( + // sprintf( + // '--no-pager log -n %d --date=%s --format=format:"%s" --reverse', + // $numberOfCommits, + // $this->dateFormat, + // implode('|', $this->logFormat) + // ) + // ); + // return $output; + // } /** - * Convert a formatted log string into an array + * Parses commits and adds them to stats * - * @param string $logOutput The output from a `git log` command formated using $this->logFormat * @return array */ - public function parseLogsIntoArray($logOutput) + public function parseCommits() { - $commits = array(); + foreach ($this->commits as $commit) { + $date = $commit->getCommiterDate()->format('Y-m-d'); + $hour = $commit->getCommiterDate()->format('H'); + $day = $commit->getCommiterDate()->format('N'); - foreach (explode("\n", $logOutput) as $line) { - $commitInfo = explode('|', $line); - $commit = array(); - - $i = 0; - foreach (array_keys($this->logFormat) as $key) { - $commit[$key] = $commitInfo[$i]; - $i++; - } - - $commits[] = $commit; - - $commitDate = date('Y-m-d', strtotime($commit['commitDate'])); - $commitHour = date('H', strtotime($commit['commitDate'])); - $commitDay = date('N', strtotime($commit['commitDate'])); - $this->addCommitToStats($this->commitsByDate, $commitDate); - $this->addCommitToStats($this->commitsByHour, $commitHour); - $this->addCommitToStats($this->commitsByDay, $commitDay); + $this->addCommitToStats($this->commitsByDate, $date); + $this->addCommitToStats($this->commitsByHour, $hour); + $this->addCommitToStats($this->commitsByDay, $day); $this->addCommitToContributor($commit); } - - return $commits; } /** @@ -189,17 +182,18 @@ public function addCommitToStats(&$stats, $key) */ public function addCommitToContributor($commit) { - $email = trim($commit['commiterEmail']); + $email = $commit->getAuthor()->getEmail(); + $name = $commit->getAuthor()->getName(); if (!isset($this->commitsByContributor[$email])) { $this->commitsByContributor[$email] = array( - 'name' => trim($commit['commiter']), + 'name' => $name, 'commits' => array() ); } - $commitDate = date('Y-m-d', strtotime($commit['commitDate'])); - $this->commitsByContributor[$email]['commits'][$commitDate][] = $commit; + $date = $commit->getCommiterDate()->format('Y-m-d'); + $this->commitsByContributor[$email]['commits'][$date][] = $commit; } public function getDaysRepositoryBeenActive () diff --git a/src/GitPrettyStats/RepositoryList.php b/src/GitPrettyStats/RepositoryList.php index 9d8b949..3b66990 100644 --- a/src/GitPrettyStats/RepositoryList.php +++ b/src/GitPrettyStats/RepositoryList.php @@ -55,7 +55,7 @@ public function getRepositories () $repositories[] = array( 'name' => $repository->getName(), 'commits' => $repository->countCommitsFromGit(), - 'branch' => $repository->getGitWrapper()->getCurrentBranch() + 'branch' => $repository->gitter->getCurrentBranch() ); } } @@ -76,8 +76,7 @@ public function loadRepository ($path) } try { - $gitWrapper = new \PHPGit_Repository($path); - $repository = new Repository($gitWrapper); + $repository = new Repository($path); return $repository; } catch (Exception $e) { return false; From a04987e1fb06bd07725e67871213ad737324bd93 Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Thu, 28 Nov 2013 20:45:33 +0100 Subject: [PATCH 07/19] Removed unused function --- src/GitPrettyStats/Repository.php | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/GitPrettyStats/Repository.php b/src/GitPrettyStats/Repository.php index 5ae0bcb..51c6e47 100644 --- a/src/GitPrettyStats/Repository.php +++ b/src/GitPrettyStats/Repository.php @@ -121,24 +121,6 @@ public function getNumberOfContributors() return count($this->commitsByContributor); } - /** - * Return the result of `git log` formatted in a PHP array - * - * @return array list of commits and their properties - **/ - // public function getCommits($numberOfCommits = 10) - // { - // $output = $this->getClient()->git( - // sprintf( - // '--no-pager log -n %d --date=%s --format=format:"%s" --reverse', - // $numberOfCommits, - // $this->dateFormat, - // implode('|', $this->logFormat) - // ) - // ); - // return $output; - // } - /** * Parses commits and adds them to stats * From 6a3d15db0d563ffcf4f251088993b7cc3405c4a6 Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Thu, 28 Nov 2013 20:47:18 +0100 Subject: [PATCH 08/19] Use gitter for running commit count --- src/GitPrettyStats/Repository.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/GitPrettyStats/Repository.php b/src/GitPrettyStats/Repository.php index 51c6e47..5055643 100644 --- a/src/GitPrettyStats/Repository.php +++ b/src/GitPrettyStats/Repository.php @@ -85,8 +85,7 @@ public function getName () */ public function countCommitsFromGit () { - return 12; - return $this->getClient()->git('git rev-list --count HEAD'); + return $this->getClient()->run($this->gitter, 'rev-list --count HEAD'); } /** From 32e6bfaa39e002b3bbd999120aaf34b78b9ade8e Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Thu, 28 Nov 2013 20:48:05 +0100 Subject: [PATCH 09/19] Use gitter for getting repository name --- src/GitPrettyStats/Repository.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GitPrettyStats/Repository.php b/src/GitPrettyStats/Repository.php index 5055643..63041c7 100644 --- a/src/GitPrettyStats/Repository.php +++ b/src/GitPrettyStats/Repository.php @@ -72,9 +72,9 @@ public function getClient() */ public function getName () { - return 'Asdf'; - $path = $this->getClient()->run('rev-parse --show-toplevel'); + $path = $this->getClient()->run($this->gitter, 'rev-parse --show-toplevel'); $name = substr($path, strrpos($path, '/') + 1); + return $name; } From 2a045d1b2b64b14a16cd42fe33a25adaaa451e05 Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Thu, 28 Nov 2013 20:48:45 +0100 Subject: [PATCH 10/19] Removed unused properties --- src/GitPrettyStats/Repository.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/GitPrettyStats/Repository.php b/src/GitPrettyStats/Repository.php index 63041c7..90176b7 100644 --- a/src/GitPrettyStats/Repository.php +++ b/src/GitPrettyStats/Repository.php @@ -19,16 +19,6 @@ class Repository /** @var array Storage for "raw" commits */ public $commits = array(); - /** @var string Date format */ - public $dateFormat = 'iso'; - - /** @var array Mapper for fetching information about commits */ - public $logFormat = array( - 'commiter' => '%cn', - 'commiterEmail' => '%ce', - 'commitDate' => '%cd', - ); - /** @var array Storage for commits by date */ public $commitsByDate = array(); From 6c509189ac4fff6b8b1362f47885139413edb5a5 Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Thu, 28 Nov 2013 20:57:28 +0100 Subject: [PATCH 11/19] General code formatting --- src/GitPrettyStats/Repository.php | 48 +++++++++++++++++---------- src/GitPrettyStats/RepositoryList.php | 1 + 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/GitPrettyStats/Repository.php b/src/GitPrettyStats/Repository.php index 90176b7..1f7e78b 100644 --- a/src/GitPrettyStats/Repository.php +++ b/src/GitPrettyStats/Repository.php @@ -142,6 +142,7 @@ public function addCommitToStats(&$stats, $key) if (!isset($stats[$key])) { $stats[$key] = 0; } + $stats[$key]++; } @@ -158,12 +159,13 @@ public function addCommitToContributor($commit) if (!isset($this->commitsByContributor[$email])) { $this->commitsByContributor[$email] = array( - 'name' => $name, + 'name' => $name, 'commits' => array() ); } $date = $commit->getCommiterDate()->format('Y-m-d'); + $this->commitsByContributor[$email]['commits'][$date][] = $commit; } @@ -190,9 +192,9 @@ public function getStatistics() $this->statistics->averageCommitsPerDay(), ), 'charts' => array( - 'date' => $this->getCommitsByDate(), - 'hour' => $this->getCommitsByHour(), - 'day' => $this->getCommitsByDay(), + 'date' => $this->getCommitsByDate(), + 'hour' => $this->getCommitsByHour(), + 'day' => $this->getCommitsByDay(), 'contributor' => $this->getCommitsByContributor(), ) ); @@ -206,6 +208,7 @@ public function getStatistics() public function getFirstCommitDate() { $firstDate = array_slice($this->commitsByDate, 0, 1); + return new Carbon(key($firstDate)); } @@ -215,6 +218,7 @@ public function getFirstCommitDate() public function getLastCommitDate() { $lastDate = key(array_slice($this->commitsByDate, count($this->commitsByDate) - 1, 1)); + return new Carbon(date("Y-m-d", strtotime($lastDate . ' +1 day'))); } @@ -225,18 +229,19 @@ public function getLastCommitDate() */ public function getCommitsByDate() { - $begin = $this->getFirstCommitDate(); - $end = $this->getLastCommitDate(); + $begin = $this->getFirstCommitDate(); + $end = $this->getLastCommitDate(); $interval = \DateInterval::createFromDateString('1 day'); - $period = new \DatePeriod($begin, $interval, $end); + $period = new \DatePeriod($begin, $interval, $end); $data = array(); foreach ($period as $date) { $dayFormatted = $date->format("Y-m-d"); - $value = isset($this->commitsByDate[$dayFormatted]) ? $this->commitsByDate[$dayFormatted] : 0; - $data['x'][] = $dayFormatted; - $data['y'][] = $value; + $value = isset($this->commitsByDate[$dayFormatted]) ? $this->commitsByDate[$dayFormatted] : 0; + $data['x'][] = $dayFormatted; + $data['y'][] = $value; } + return $data; } @@ -248,11 +253,14 @@ public function getCommitsByDate() public function getCommitsByHour() { $data = array(); + ksort($this->commitsByHour); + foreach ($this->commitsByHour as $hour => $numberOfCommits) { $data['x'][] = $hour; $data['y'][] = $numberOfCommits; } + return $data; } @@ -267,9 +275,11 @@ public function getCommitsByDay() $days = array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'); ksort($this->commitsByDay); + foreach ($this->commitsByDay as $weekday => $numberOfCommits) { $data[] = array($days[$weekday - 1], $numberOfCommits); } + return $data; } @@ -283,17 +293,20 @@ public function getCommitsByContributor() $data = array(); foreach ($this->commitsByContributor as $email => $contributor) { - $begin = $this->getFirstCommitDate(); - $end = $this->getLastCommitDate(); + $begin = $this->getFirstCommitDate(); + $end = $this->getLastCommitDate(); $interval = \DateInterval::createFromDateString('1 day'); - $period = new \DatePeriod($begin, $interval, $end); + $period = new \DatePeriod($begin, $interval, $end); - $commitsData = array(); + $commitsData = array(); $totalCommits = 0; + foreach ($period as $date) { $dayFormatted = $date->format("Y-m-d"); + $value = isset($contributor['commits'][$dayFormatted]) ? count($contributor['commits'][$dayFormatted]) : 0; + $totalCommits += $value; $commitsData['x'][] = $dayFormatted; @@ -301,10 +314,10 @@ public function getCommitsByContributor() } $data[] = array( - 'name' => $contributor['name'], - 'email' => $email, + 'name' => $contributor['name'], + 'email' => $email, 'commits' => $totalCommits, - 'data' => $commitsData, + 'data' => $commitsData, ); } @@ -325,6 +338,7 @@ public function sortContributorsByCommits($sortA, $sortB) if ($sortA['commits'] == $sortB['commits']) { return 0; } + return ($sortA['commits'] > $sortB['commits']) ? -1 : 1; } } diff --git a/src/GitPrettyStats/RepositoryList.php b/src/GitPrettyStats/RepositoryList.php index 3b66990..172419d 100644 --- a/src/GitPrettyStats/RepositoryList.php +++ b/src/GitPrettyStats/RepositoryList.php @@ -38,6 +38,7 @@ public function getRepositories () $loadRepositoryPaths[] = realpath(__DIR__ . '/../../' . $repo . '/'); } } + // Config with path to directory of repositories elseif ($handle = opendir($this->path)) { while (false !== ($entry = readdir($handle))) { From 7379c6dbfd9c7f7e17d18757744ac21d3dccb063 Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Thu, 28 Nov 2013 21:05:14 +0100 Subject: [PATCH 12/19] Sort commits by date array before getting first and last date --- src/GitPrettyStats/Repository.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/GitPrettyStats/Repository.php b/src/GitPrettyStats/Repository.php index 1f7e78b..7174a09 100644 --- a/src/GitPrettyStats/Repository.php +++ b/src/GitPrettyStats/Repository.php @@ -207,6 +207,8 @@ public function getStatistics() */ public function getFirstCommitDate() { + ksort($this->commitsByDate); + $firstDate = array_slice($this->commitsByDate, 0, 1); return new Carbon(key($firstDate)); @@ -217,6 +219,8 @@ public function getFirstCommitDate() */ public function getLastCommitDate() { + ksort($this->commitsByDate); + $lastDate = key(array_slice($this->commitsByDate, count($this->commitsByDate) - 1, 1)); return new Carbon(date("Y-m-d", strtotime($lastDate . ' +1 day'))); From d9545410117b09b070e1080b55fa6ec32f183424 Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Thu, 28 Nov 2013 21:10:22 +0100 Subject: [PATCH 13/19] Removed php-git-repo dependency --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index 63d3d4d..b4ab191 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,6 @@ "require": { "silex/silex": "1.0.*@dev", "twig/twig": "1.*", - "ornicar/php-git-repo": "dev-master", "nesbot/carbon": "1.6.0", "klaussilveira/gitter": "0.2.0" }, From bcb771797409ec681753a6330c07a6db3abffce8 Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Thu, 28 Nov 2013 21:48:01 +0100 Subject: [PATCH 14/19] Trim repository name --- src/GitPrettyStats/Repository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitPrettyStats/Repository.php b/src/GitPrettyStats/Repository.php index 7174a09..d17c6c5 100644 --- a/src/GitPrettyStats/Repository.php +++ b/src/GitPrettyStats/Repository.php @@ -65,7 +65,7 @@ public function getName () $path = $this->getClient()->run($this->gitter, 'rev-parse --show-toplevel'); $name = substr($path, strrpos($path, '/') + 1); - return $name; + return trim($name); } /** From 6940eabdc9fb63fe359f0bae6a142f9d651eb6a1 Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Thu, 28 Nov 2013 21:51:07 +0100 Subject: [PATCH 15/19] Changed stats endpoint This could cause some issues before with hosting providers that used the stats route for web statistics --- index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.php b/index.php index df3edc4..74cec9e 100644 --- a/index.php +++ b/index.php @@ -82,12 +82,12 @@ function loadRepository ($app, $path) { 'repositories' => $app['repositories'], 'name' => $repository->getName(), 'branch' => $repository->gitter->getCurrentBranch(), - 'statsEndpoint' => $app["request"]->getBaseUrl() . "/stats/" . $path, + 'statsEndpoint' => $app["request"]->getBaseUrl() . "/git-stats/" . $path, ) ); }); -$app->get('/stats/{path}', function($path) use($app) { +$app->get('/git-stats/{path}', function($path) use($app) { $repository = loadRepository($app, $path); return $app->json( From 2dc8eb8bf0450bfdf2fec3e165c02565cd911609 Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Thu, 28 Nov 2013 21:54:06 +0100 Subject: [PATCH 16/19] =?UTF-8?q?Get=20repository=20name=20from=20top=20le?= =?UTF-8?q?vel=20dir=20and=20clean=20=E2=80=98.git=E2=80=99=20away=20from?= =?UTF-8?q?=20the=20end?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/GitPrettyStats/Repository.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/GitPrettyStats/Repository.php b/src/GitPrettyStats/Repository.php index d17c6c5..82b193c 100644 --- a/src/GitPrettyStats/Repository.php +++ b/src/GitPrettyStats/Repository.php @@ -62,9 +62,13 @@ public function getClient() */ public function getName () { - $path = $this->getClient()->run($this->gitter, 'rev-parse --show-toplevel'); + $path = $this->gitter->getPath(); $name = substr($path, strrpos($path, '/') + 1); + if (substr($name, -4) == '.git') { + $name = substr($name, 0, strlen($name) - 4); + } + return trim($name); } From 80f5d71fd88ad42536309bab84951456799a4f4d Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Fri, 29 Nov 2013 15:42:37 +0100 Subject: [PATCH 17/19] Phpdoc for client return type --- src/GitPrettyStats/Repository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitPrettyStats/Repository.php b/src/GitPrettyStats/Repository.php index 82b193c..5a34535 100644 --- a/src/GitPrettyStats/Repository.php +++ b/src/GitPrettyStats/Repository.php @@ -48,7 +48,7 @@ public function __construct($path) } /** - * @return \PHPGit_Repository + * @return \Gitter\Client */ public function getClient() { From 65f609a57dbf1ea212b142026ff95b7394e5271b Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Fri, 29 Nov 2013 15:54:10 +0100 Subject: [PATCH 18/19] Test and testability for new implementation with Gitter --- src/GitPrettyStats/Repository.php | 14 +- tests/GitPrettyStats/RepositoryTest.php | 185 +++++++++++++++--------- 2 files changed, 126 insertions(+), 73 deletions(-) diff --git a/src/GitPrettyStats/Repository.php b/src/GitPrettyStats/Repository.php index 5a34535..39f5e31 100644 --- a/src/GitPrettyStats/Repository.php +++ b/src/GitPrettyStats/Repository.php @@ -40,11 +40,12 @@ class Repository * @param \Gitter\Client $client Git client * @return void */ - public function __construct($path) + public function __construct($path, $client = null, $statistics = null) { - $this->client = new Client; + $this->client = ($client) ? $client : new Client; + $this->statistics = ($statistics) ? $statistics : new Statistics($this); + $this->gitter = $this->client->getRepository($path); - $this->statistics = new Statistics($this); } /** @@ -62,8 +63,11 @@ public function getClient() */ public function getName () { - $path = $this->gitter->getPath(); - $name = substr($path, strrpos($path, '/') + 1); + $name = $this->gitter->getPath(); + + if (strstr($name, '/')) { + $name = substr($name, strrpos($name, '/') + 1); + } if (substr($name, -4) == '.git') { $name = substr($name, 0, strlen($name) - 4); diff --git a/tests/GitPrettyStats/RepositoryTest.php b/tests/GitPrettyStats/RepositoryTest.php index ad952da..22436e7 100644 --- a/tests/GitPrettyStats/RepositoryTest.php +++ b/tests/GitPrettyStats/RepositoryTest.php @@ -2,55 +2,68 @@ namespace GitPrettyStats; use Mockery as m; +use Carbon\Carbon; /** * @covers GitPrettyStats\Repository */ class RepositoryTest extends \PHPUnit_Framework_TestCase { - protected $repository; - protected $gitWrapper; + public $repository; + public $client; + public $gitter; public $commits = array( - array('Author 1', 'author_1@email.com', '2013-03-01 14:55:47 +0200'), - array('Author 1', 'author_1@email.com', '2013-03-02 12:13:54 +0200'), - array('Author 2', 'author_2@email.com', '2013-03-02 14:55:47 +0200'), - array('Author 3', 'author_3@email.com', '2013-03-03 09:13:47 +0200'), - array('Author 2', 'author_2@email.com', '2013-03-03 19:55:47 +0200'), - array('Author alias 1', 'author_1@email.com', '2013-03-03 22:32:19 +0200'), - array('Author 4', 'author_4@email.com', '2013-03-04 10:32:00 +0200'), - array('Author 4', 'author_4@email.com', '2013-03-04 14:55:47 +0200'), - array('Author 5', 'author_5@email.com', '2013-03-05 09:55:47 +0200'), - array('Author 1', 'author_1@email.com', '2013-03-05 18:14:30 +0200'), + array('Author 1', 'author_1@email.com', '2013-03-01 14:55:47'), + array('Author 1', 'author_1@email.com', '2013-03-02 12:13:54'), + array('Author 2', 'author_2@email.com', '2013-03-02 14:55:47'), + array('Author 3', 'author_3@email.com', '2013-03-03 09:13:47'), + array('Author 2', 'author_2@email.com', '2013-03-03 19:55:47'), + array('Author alias 1', 'author_1@email.com', '2013-03-03 22:32:19'), + array('Author 4', 'author_4@email.com', '2013-03-04 10:32:00'), + array('Author 4', 'author_4@email.com', '2013-03-04 14:55:47'), + array('Author 5', 'author_5@email.com', '2013-03-05 09:55:47'), + array('Author 1', 'author_1@email.com', '2013-03-05 18:14:30'), ); public function setUp() { - $this->gitWrapper = m::mock('\PHPGit_Repository'); + $this->client = m::mock('\Gitter\Client'); + $this->gitter = m::mock('\Gitter\Repository'); - $logFormat = array( - 'commiter' => '%cn', - 'commiterEmail' => '%ce', - 'commitDate' => '%cd', - ); - - $logArg = sprintf( - '--no-pager log -n %d --date=%s --format=format:"%s" --reverse', - -1, - 'iso', - implode('|', $logFormat) - ); + $this->client + ->shouldReceive('getRepository') + ->andReturn($this->gitter); - $rawCommits = ""; + $commits = array(); foreach ($this->commits as $commit) { - $rawCommits .= "{$commit[0]}|{$commit[1]}|{$commit[2]}\n"; + $commits[] = $this->createCommit($commit[0], $commit[1], $commit[2]); } - $this->gitWrapper - ->shouldReceive('git') + $this->commits = $commits; + } + + public function createCommit($name, $email, $date) + { + $author = m::mock('stdClass'); + $author + ->shouldReceive('getName') + ->zeroOrMoreTimes() + ->andReturn($name) + ->shouldReceive('getEmail') + ->zeroOrMoreTimes() + ->andReturn($email); + + $commit = m::mock('stdClass'); + $commit + ->shouldReceive('getCommiterDate') + ->zeroOrMoreTimes() + ->andReturn(new Carbon($date)) + ->shouldReceive('getAuthor') ->zeroOrMoreTimes() - ->with($logArg) - ->andReturn($rawCommits); + ->andReturn($author); + + return $commit; } public function tearDown() @@ -60,44 +73,59 @@ public function tearDown() public function createInstance() { - $repo = new Repository($this->gitWrapper); + $repo = new Repository('.', $this->client); + $repo->commits = $this->commits; + return $repo; } - public function testGetName() + public function repositoryNames () + { + return array( + array('./some/git/repository', 'repository'), + array('sample.git', 'sample'), + array('../../yet-another-repository', 'yet-another-repository'), + ); + } + + /** + * @dataProvider repositoryNames + */ + public function testGetName($path, $expected) { - $this->gitWrapper - ->shouldReceive('git') - ->with('rev-parse --show-toplevel') - ->andReturn('some/path/to/git-repo'); + $this->gitter + ->shouldReceive('getPath') + ->andReturn($path); $repo = $this->createInstance(); + $this->assertEquals( - 'git-repo', + $expected, $repo->getName(), - 'Name not correct' + 'Returned incorrect repository name' ); } - public function testNumberOfCommitsFromGitAreCorrect() + public function testLoadCommits () { - $this->gitWrapper - ->shouldReceive('git') - ->with('git rev-list --count HEAD') - ->andReturn(5); + $this->gitter->shouldReceive('getCommits')->once(); + + $repo = m::mock('GitPrettyStats\Repository[parseCommits]', ['.', $this->client]); + + $repo->shouldReceive('parseCommits')->once(); + + $repo->loadCommits(); - $repo = $this->createInstance(); - $this->assertEquals( - 5, - $repo->countCommitsFromGit(), - 'Number of commits are incorrect from git' - ); } public function testNumberOfCommitsAreCorrect() { + $this->client + ->shouldReceive('getRepository') + ->andReturn($this->gitter); + $repo = $this->createInstance(); - $repo->loadCommits(); + $this->assertEquals( 10, $repo->getNumberOfCommits(), @@ -107,8 +135,13 @@ public function testNumberOfCommitsAreCorrect() public function testNumberOfContributorsAreCorrect() { + $this->client + ->shouldReceive('getRepository') + ->andReturn($this->gitter); + $repo = $this->createInstance(); - $repo->loadCommits(); + $repo->parseCommits(); + $this->assertEquals( 5, count($repo->commitsByContributor), @@ -142,16 +175,16 @@ public function testgetStatistics($expectedKey) public function testFirstAndLastCommitDate() { $repo = $this->createInstance(); - $repo->loadCommits(); + $repo->parseCommits(); - $firstCommitDate = $this->commits[0][2]; + $firstCommitDate = $this->commits[0]->getCommiterDate(); $this->assertEquals( date('Y-m-d', strtotime($firstCommitDate)), $repo->getFirstCommitDate()->format('Y-m-d'), 'First commit date not correct' ); - $lastCommitDate = $this->commits[count($this->commits) - 1][2]; + $lastCommitDate = $this->commits[count($this->commits) - 1]->getCommiterDate(); $this->assertEquals( date('Y-m-d', strtotime($lastCommitDate . ' +1 day')), $repo->getLastCommitDate()->format('Y-m-d'), @@ -159,9 +192,28 @@ public function testFirstAndLastCommitDate() ); } + public function testGetClient () + { + $repo = $this->createInstance(); + + $this->assertEquals($this->client, $repo->getClient(), 'Invalid client returned'); + } + + public function testCountCommitsFromGit () + { + $this->client + ->shouldReceive('run') + ->with($this->gitter, 'rev-list --count HEAD') + ->andReturn(5); + + $repo = $this->createInstance(); + $this->assertEquals(5, $repo->countCommitsFromGit(), 'Invalid commit count from git'); + } + public function testAddingCommitToStats() { $repo = $this->createInstance(); + $repo->parseCommits(); $commits = array(); $key = 'commit'; @@ -175,11 +227,7 @@ public function testAddingCommitToStats() public function testAddingCommitToContributor() { - $commit = array( - 'commiter' => 'Jane Doe', - 'commiterEmail' => 'jane@doe.com', - 'commitDate' => '2013-04-01' - ); + $commit = $this->createCommit('Jane Doe', 'jane@doe.com', '2013-04-01'); $repo = $this->createInstance(); $repo->addCommitToContributor($commit); @@ -196,15 +244,16 @@ public function testAddingCommitToContributor() ); $this->assertEquals( $expected, - $repo->commitsByContributor[$commit['commiterEmail']], + $repo->commitsByContributor['jane@doe.com'], 'Contributor formatted incorrectly' ); - $commit['commitDate'] = '2013-05-01'; + $commit = $this->createCommit('Jane Doe', 'jane@doe.com', '2013-05-01'); + $repo->addCommitToContributor($commit); $this->assertEquals( 2, - count($repo->commitsByContributor[$commit['commiterEmail']]['commits']), + count($repo->commitsByContributor['jane@doe.com']['commits']), 'Incorrect number of commits for contributor' ); } @@ -212,7 +261,7 @@ public function testAddingCommitToContributor() public function testGetCommitsByDate() { $repo = $this->createInstance(); - $repo->loadCommits(); + $repo->parseCommits(); $expected = array( 'x' => array('2013-03-01','2013-03-02','2013-03-03','2013-03-04', '2013-03-05'), @@ -229,10 +278,10 @@ public function testGetCommitsByDate() public function testGetCommitsByHour() { $repo = $this->createInstance(); - $repo->loadCommits(); + $repo->parseCommits(); $expected = array( - 'x' => array('08', '09', 11, 13, 17, 18, 21), + 'x' => array('09', 10, 12, 14, 18, 19, 22), 'y' => array(2, 1, 1, 3, 1, 1, 1) ); @@ -246,7 +295,7 @@ public function testGetCommitsByHour() public function testGetCommitsByDay() { $repo = $this->createInstance(); - $repo->loadCommits(); + $repo->parseCommits(); $expected = array( array("Monday", 2), @@ -266,7 +315,7 @@ public function testGetCommitsByDay() public function testGetCommitsByContributor() { $repo = $this->createInstance(); - $repo->loadCommits(); + $repo->parseCommits(); $expected = array( array( From 0d49ca5c2c283d00bd853501d4407fac4bd9653c Mon Sep 17 00:00:00 2001 From: Niklas Modess Date: Fri, 29 Nov 2013 15:54:43 +0100 Subject: [PATCH 19/19] Updated readme for v0.2.1 --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 542304b..fa4e8f2 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,10 @@ You know those cool graphs and statistics you can get for a repository on github? The things is that (unfortunately) not all git repositories are hosted on github for various reasons. This is the tool for rendering graphs for your repository that can be hosted anywhere, and it looks great. -## Features (v0.2.0) +## Features (v0.2.1) * Handles multiple repositories +* Handles bare repositories * Statistics - Total commits - Total contributors @@ -30,11 +31,11 @@ Start by clone this repository and setup your web server Install dependencies using [Composer](http://getcomposer.org/), e.g. `php composer.phar install` -Clone the repositories you want to statistics and graphs for in to the **repositories** folder. +Clone the repositories you want to statistics and graphs for in to the **repositories** folder. cd repositories git clone - + You can clone as many as you want to in to this folder. > To manually set the repositories path, copy `config.example.php` to `config.php`. Then change the value of `repositoriesPath` in the config file relative to the folder where your desired git repositories are located. @@ -62,8 +63,9 @@ For more screenshots visit the [project homepage](http://www.codingswag.com/git- ## Powered by -* [php-git-repo](https://github.com/ornicar/php-git-repo) +* [Gitter](https://github.com/klaussilveira/gitter) * [Silex](https://github.com/fabpot/Silex) +* [Carbon](https://github.com/briannesbitt/Carbon) * [Twig](https://github.com/fabpot/Twig) * [Flat UI](https://github.com/designmodo/Flat-UI) * [Highcharts JS](https://github.com/highslide-software/highcharts.com)