<?php
namespace Gitonomy\Git;
use Gitonomy\Git\Diff\Diff;
use Gitonomy\Git\Exception\ProcessException;
use Gitonomy\Git\Exception\ReferenceNotFoundException;
use Gitonomy\Git\Util\StringHelper;
class Log implements \Countable, \IteratorAggregate
{
protected $repository;
protected $revisions;
protected $paths;
protected $offset;
protected $limit;
public function __construct(Repository $repository, $revisions = null, $paths = null, $offset = null, $limit = null)
{
if (null !== $revisions && !$revisions instanceof RevisionList) {
$revisions = new RevisionList($repository, $revisions);
}
if (null === $paths) {
$paths = [];
} elseif (is_string($paths)) {
$paths = [$paths];
} elseif (!is_array($paths)) {
throw new \InvalidArgumentException(sprintf('Expected a string or an array, got a "%s".', is_object($paths) ? get_class($paths) : gettype($paths)));
}
$this->repository = $repository;
$this->revisions = $revisions;
$this->paths = $paths;
$this->offset = $offset;
$this->limit = $limit;
}
public function getDiff()
{
return $this->repository->getDiff($this->revisions);
}
public function getRevisions()
{
return $this->revisions;
}
public function getPaths()
{
return $this->paths;
}
public function getOffset()
{
return $this->offset;
}
public function setOffset($offset)
{
$this->offset = $offset;
return $this;
}
public function getLimit()
{
return $this->limit;
}
public function setLimit($limit)
{
$this->limit = $limit;
return $this;
}
public function getSingleCommit()
{
$limit = $this->limit;
$this->limit = 1;
$commits = $this->getCommits();
$this->setLimit($limit);
if (count($commits) === 0) {
throw new ReferenceNotFoundException('The log is empty');
}
return array_pop($commits);
}
public function getCommits()
{
$args = ['--encoding='.StringHelper::getEncoding(), '--format=raw'];
if (null !== $this->offset) {
$args[] = '--skip='.((int) $this->offset);
}
if (null !== $this->limit) {
$args[] = '-n';
$args[] = (int) $this->limit;
}
if (null !== $this->revisions) {
$args = array_merge($args, $this->revisions->getAsTextArray());
} else {
$args[] = '--all';
}
$args[] = '--';
$args = array_merge($args, $this->paths);
try {
$output = $this->repository->run('log', $args);
} catch (ProcessException $e) {
throw new ReferenceNotFoundException(sprintf('Can not find revision "%s"', implode(' ', $this->revisions->getAsTextArray())), null, $e);
}
$parser = new Parser\LogParser();
$parser->parse($output);
$result = [];
foreach ($parser->log as $commitData) {
$hash = $commitData['id'];
unset($commitData['id']);
$commit = $this->repository->getCommit($hash);
$commit->setData($commitData);
$result[] = $commit;
}
return $result;
}
public function count()
{
return $this->countCommits();
}
public function getIterator()
{
return new \ArrayIterator($this->getCommits());
}
public function countCommits()
{
if (null !== $this->revisions && count($this->revisions)) {
$output = $this->repository->run('rev-list', array_merge(['--count'], $this->revisions->getAsTextArray(), ['--'], $this->paths));
} else {
$output = $this->repository->run('rev-list', array_merge(['--count', '--all', '--'], $this->paths));
}
return (int) $output;
}
}