composer update
This commit is contained in:
173
vendor/gitonomy/gitlib/src/Gitonomy/Git/Admin.php
vendored
Normal file
173
vendor/gitonomy/gitlib/src/Gitonomy/Git/Admin.php
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git;
|
||||
|
||||
use Gitonomy\Git\Exception\RuntimeException;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
/**
|
||||
* Administration class for Git repositories.
|
||||
*
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*/
|
||||
class Admin
|
||||
{
|
||||
/**
|
||||
* Initializes a repository and returns the instance.
|
||||
*
|
||||
* @param string $path path to the repository
|
||||
* @param bool $bare indicate to create a bare repository
|
||||
* @param array $options options for Repository creation
|
||||
*
|
||||
* @return Repository
|
||||
*
|
||||
* @throws RuntimeException Directory exists or not writable (only if debug=true)
|
||||
*/
|
||||
public static function init($path, $bare = true, array $options = array())
|
||||
{
|
||||
$process = static::getProcess('init', array_merge(array('-q'), $bare ? array('--bare') : array(), array($path)), $options);
|
||||
|
||||
$process->run();
|
||||
|
||||
if (!$process->isSuccessFul()) {
|
||||
throw new RuntimeException(sprintf("Error on repository initialization, command wasn't successful (%s). Error output:\n%s", $process->getCommandLine(), $process->getErrorOutput()));
|
||||
}
|
||||
|
||||
return new Repository($path, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the validity of a git repository url without cloning it.
|
||||
*
|
||||
* This will use the `ls-remote` command of git against the given url.
|
||||
* Usually, this command returns 0 when successful, and 128 when the
|
||||
* repository is not found.
|
||||
*
|
||||
* @param string $url url of repository to check
|
||||
* @param array $options options for Repository creation
|
||||
*
|
||||
* @return bool true if url is valid
|
||||
*/
|
||||
public static function isValidRepository($url, array $options = array())
|
||||
{
|
||||
$process = static::getProcess('ls-remote', array($url), $options);
|
||||
|
||||
$process->run();
|
||||
|
||||
return $process->isSuccessFul();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone a repository to a local path.
|
||||
*
|
||||
* @param string $path indicates where to clone repository
|
||||
* @param string $url url of repository to clone
|
||||
* @param bool $bare indicates if repository should be bare or have a working copy
|
||||
* @param array $options options for Repository creation
|
||||
*
|
||||
* @return Repository
|
||||
*/
|
||||
public static function cloneTo($path, $url, $bare = true, array $options = array())
|
||||
{
|
||||
$args = $bare ? array('--bare') : array();
|
||||
|
||||
return static::cloneRepository($path, $url, $args, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone a repository branch to a local path.
|
||||
*
|
||||
* @param string $path indicates where to clone repository
|
||||
* @param string $url url of repository to clone
|
||||
* @param string $branch branch to clone
|
||||
* @param bool $bare indicates if repository should be bare or have a working copy
|
||||
* @param array $options options for Repository creation
|
||||
*
|
||||
* @return Repository
|
||||
*/
|
||||
public static function cloneBranchTo($path, $url, $branch, $bare = true, $options = array())
|
||||
{
|
||||
$args = array('--branch', $branch);
|
||||
if ($bare) {
|
||||
$args[] = '--bare';
|
||||
}
|
||||
|
||||
return static::cloneRepository($path, $url, $args, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirrors a repository (fetch all revisions, not only branches).
|
||||
*
|
||||
* @param string $path indicates where to clone repository
|
||||
* @param string $url url of repository to clone
|
||||
* @param array $options options for Repository creation
|
||||
*
|
||||
* @return Repository
|
||||
*/
|
||||
public static function mirrorTo($path, $url, array $options = array())
|
||||
{
|
||||
return static::cloneRepository($path, $url, array('--mirror'), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method to launch effective ``git clone`` command.
|
||||
*
|
||||
* @param string $path indicates where to clone repository
|
||||
* @param string $url url of repository to clone
|
||||
* @param array $args arguments to be added to the command-line
|
||||
* @param array $options options for Repository creation
|
||||
*
|
||||
* @return Repository
|
||||
*/
|
||||
public static function cloneRepository($path, $url, array $args = array(), array $options = array())
|
||||
{
|
||||
$process = static::getProcess('clone', array_merge(array('-q'), $args, array($url, $path)), $options);
|
||||
|
||||
$process->run();
|
||||
|
||||
if (!$process->isSuccessFul()) {
|
||||
throw new RuntimeException(sprintf('Error while initializing repository: %s', $process->getErrorOutput()));
|
||||
}
|
||||
|
||||
return new Repository($path, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal method is used to create a process object.
|
||||
*/
|
||||
private static function getProcess($command, array $args = array(), array $options = array())
|
||||
{
|
||||
$is_windows = defined('PHP_WINDOWS_VERSION_BUILD');
|
||||
$options = array_merge(array(
|
||||
'environment_variables' => $is_windows ? array('PATH' => getenv('PATH')) : array(),
|
||||
'command' => 'git',
|
||||
'process_timeout' => 3600,
|
||||
), $options);
|
||||
|
||||
$commandline = array_merge(array($options['command'], $command), $args);
|
||||
|
||||
// Backward compatible layer for Symfony Process < 4.0.
|
||||
if (class_exists('Symfony\Component\Process\ProcessBuilder')) {
|
||||
$commandline = implode(' ', array_map(
|
||||
'Symfony\Component\Process\ProcessUtils::escapeArgument',
|
||||
$commandline
|
||||
));
|
||||
}
|
||||
|
||||
$process = new Process($commandline);
|
||||
$process->setEnv($options['environment_variables']);
|
||||
$process->setTimeout($options['process_timeout']);
|
||||
$process->setIdleTimeout($options['process_timeout']);
|
||||
|
||||
return $process;
|
||||
}
|
||||
}
|
145
vendor/gitonomy/gitlib/src/Gitonomy/Git/Blame.php
vendored
Normal file
145
vendor/gitonomy/gitlib/src/Gitonomy/Git/Blame.php
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git;
|
||||
|
||||
use Gitonomy\Git\Blame\Line;
|
||||
use Gitonomy\Git\Exception\InvalidArgumentException;
|
||||
use Gitonomy\Git\Parser\BlameParser;
|
||||
|
||||
/**
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*/
|
||||
class Blame implements \Countable
|
||||
{
|
||||
/**
|
||||
* @var Repository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* @var Revision
|
||||
*/
|
||||
protected $revision;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $file;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
protected $lineRange;
|
||||
|
||||
/**
|
||||
* @var array|null
|
||||
*/
|
||||
protected $lines;
|
||||
|
||||
/**
|
||||
* @param string $lineRange Argument to pass to git blame (-L).
|
||||
* Can be a line range (40,60 or 40,+21)
|
||||
* or a regexp ('/^function$/')
|
||||
*/
|
||||
public function __construct(Repository $repository, Revision $revision, $file, $lineRange = null)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
$this->revision = $revision;
|
||||
$this->lineRange = $lineRange;
|
||||
$this->file = $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Line
|
||||
*/
|
||||
public function getLine($number)
|
||||
{
|
||||
if ($number < 1) {
|
||||
throw new InvalidArgumentException('Line number should be at least 1');
|
||||
}
|
||||
|
||||
$lines = $this->getLines();
|
||||
|
||||
if (!isset($lines[$number])) {
|
||||
throw new InvalidArgumentException('Line does not exist');
|
||||
}
|
||||
|
||||
return $lines[$number];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns lines grouped by commit.
|
||||
*
|
||||
* @return array a list of two-elements array (commit, lines)
|
||||
*/
|
||||
public function getGroupedLines()
|
||||
{
|
||||
$result = array();
|
||||
$commit = null;
|
||||
$current = array();
|
||||
|
||||
foreach ($this->getLines() as $lineNumber => $line) {
|
||||
if ($commit !== $line->getCommit()) {
|
||||
if (count($current)) {
|
||||
$result[] = array($commit, $current);
|
||||
}
|
||||
$commit = $line->getCommit();
|
||||
$current = array();
|
||||
}
|
||||
|
||||
$current[$lineNumber] = $line;
|
||||
}
|
||||
|
||||
if (count($current)) {
|
||||
$result[] = array($commit, $current);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all lines of the blame.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLines()
|
||||
{
|
||||
if (null !== $this->lines) {
|
||||
return $this->lines;
|
||||
}
|
||||
|
||||
$args = array('-p');
|
||||
|
||||
if (null !== $this->lineRange) {
|
||||
$args[] = '-L';
|
||||
$args[] = $this->lineRange;
|
||||
}
|
||||
|
||||
$args[] = $this->revision->getRevision();
|
||||
$args[] = '--';
|
||||
$args[] = $this->file;
|
||||
|
||||
$parser = new BlameParser($this->repository);
|
||||
$parser->parse($this->repository->run('blame', $args));
|
||||
$this->lines = $parser->lines;
|
||||
|
||||
return $this->lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->getLines());
|
||||
}
|
||||
}
|
56
vendor/gitonomy/gitlib/src/Gitonomy/Git/Blame/Line.php
vendored
Normal file
56
vendor/gitonomy/gitlib/src/Gitonomy/Git/Blame/Line.php
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git\Blame;
|
||||
|
||||
use Gitonomy\Git\Commit;
|
||||
|
||||
/**
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*/
|
||||
class Line
|
||||
{
|
||||
/**
|
||||
* @var Commit
|
||||
*/
|
||||
protected $commit;
|
||||
protected $sourceLine;
|
||||
protected $targetLine;
|
||||
protected $blockLine;
|
||||
protected $content;
|
||||
|
||||
/**
|
||||
* Instanciates a new Line object.
|
||||
*/
|
||||
public function __construct(Commit $commit, $sourceLine, $targetLine, $blockLine, $content)
|
||||
{
|
||||
$this->commit = $commit;
|
||||
$this->sourceLine = $sourceLine;
|
||||
$this->targetLine = $targetLine;
|
||||
$this->blockLine = $blockLine;
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
public function getContent()
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
public function getLine()
|
||||
{
|
||||
return $this->sourceLine;
|
||||
}
|
||||
|
||||
public function getCommit()
|
||||
{
|
||||
return $this->commit;
|
||||
}
|
||||
}
|
107
vendor/gitonomy/gitlib/src/Gitonomy/Git/Blob.php
vendored
Normal file
107
vendor/gitonomy/gitlib/src/Gitonomy/Git/Blob.php
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git;
|
||||
|
||||
/**
|
||||
* Representation of a Blob commit.
|
||||
*
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*/
|
||||
class Blob
|
||||
{
|
||||
/**
|
||||
* @var Repository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $hash;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $content;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $mimetype;
|
||||
|
||||
/**
|
||||
* @param Repository $repository Repository where the blob is located
|
||||
* @param string $hash Hash of the blob
|
||||
*/
|
||||
public function __construct(Repository $repository, $hash)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
$this->hash = $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getHash()
|
||||
{
|
||||
return $this->hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns content of the blob.
|
||||
*
|
||||
* @throws ProcessException Error occurred while getting content of blob
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
if (null === $this->content) {
|
||||
$this->content = $this->repository->run('cat-file', array('-p', $this->hash));
|
||||
}
|
||||
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the mimetype of the blob.
|
||||
*
|
||||
* @return string A mimetype
|
||||
*/
|
||||
public function getMimetype()
|
||||
{
|
||||
if (null === $this->mimetype) {
|
||||
$finfo = new \finfo(FILEINFO_MIME);
|
||||
$this->mimetype = $finfo->buffer($this->getContent());
|
||||
}
|
||||
|
||||
return $this->mimetype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if file is binary.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isBinary()
|
||||
{
|
||||
return !$this->isText();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if file is text.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isText()
|
||||
{
|
||||
return (bool) preg_match('#^text/|^application/xml#', $this->getMimetype());
|
||||
}
|
||||
}
|
404
vendor/gitonomy/gitlib/src/Gitonomy/Git/Commit.php
vendored
Normal file
404
vendor/gitonomy/gitlib/src/Gitonomy/Git/Commit.php
vendored
Normal file
@@ -0,0 +1,404 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git;
|
||||
|
||||
use Gitonomy\Git\Diff\Diff;
|
||||
use Gitonomy\Git\Exception\InvalidArgumentException;
|
||||
use Gitonomy\Git\Exception\ProcessException;
|
||||
use Gitonomy\Git\Exception\ReferenceNotFoundException;
|
||||
use Gitonomy\Git\Util\StringHelper;
|
||||
|
||||
/**
|
||||
* Representation of a Git commit.
|
||||
*
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*/
|
||||
class Commit extends Revision
|
||||
{
|
||||
/**
|
||||
* Associative array of commit data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $data = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Gitonomy\Git\Repository $repository Repository of the commit
|
||||
* @param string $hash Hash of the commit
|
||||
*/
|
||||
public function __construct(Repository $repository, $hash, array $data = array())
|
||||
{
|
||||
if (!preg_match('/^[a-f0-9]{40}$/', $hash)) {
|
||||
throw new ReferenceNotFoundException($hash);
|
||||
}
|
||||
|
||||
parent::__construct($repository, $hash);
|
||||
|
||||
$this->setData($data);
|
||||
}
|
||||
|
||||
public function setData(array $data)
|
||||
{
|
||||
foreach ($data as $name => $value) {
|
||||
$this->data[$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Diff
|
||||
*/
|
||||
public function getDiff()
|
||||
{
|
||||
$args = array('-r', '-p', '-m', '-M', '--no-commit-id', '--full-index', $this->revision);
|
||||
|
||||
$diff = Diff::parse($this->repository->run('diff-tree', $args));
|
||||
$diff->setRepository($this->repository);
|
||||
|
||||
return $diff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the commit hash.
|
||||
*
|
||||
* @return string A SHA1 hash
|
||||
*/
|
||||
public function getHash()
|
||||
{
|
||||
return $this->revision;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the short commit hash.
|
||||
*
|
||||
* @return string A SHA1 hash
|
||||
*/
|
||||
public function getShortHash()
|
||||
{
|
||||
return $this->getData('shortHash');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a fixed-with short hash.
|
||||
*/
|
||||
public function getFixedShortHash($length = 6)
|
||||
{
|
||||
return StringHelper::substr($this->revision, 0, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns parent hashes.
|
||||
*
|
||||
* @return array An array of SHA1 hashes
|
||||
*/
|
||||
public function getParentHashes()
|
||||
{
|
||||
return $this->getData('parentHashes');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent commits.
|
||||
*
|
||||
* @return array An array of Commit objects
|
||||
*/
|
||||
public function getParents()
|
||||
{
|
||||
$result = array();
|
||||
foreach ($this->getData('parentHashes') as $parentHash) {
|
||||
$result[] = $this->repository->getCommit($parentHash);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tree hash.
|
||||
*
|
||||
* @return string A SHA1 hash
|
||||
*/
|
||||
public function getTreeHash()
|
||||
{
|
||||
return $this->getData('treeHash');
|
||||
}
|
||||
|
||||
public function getTree()
|
||||
{
|
||||
return $this->getData('tree');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Commit
|
||||
*/
|
||||
public function getLastModification($path = null)
|
||||
{
|
||||
if (0 === strpos($path, '/')) {
|
||||
$path = StringHelper::substr($path, 1);
|
||||
}
|
||||
|
||||
if ($getWorkingDir = $this->repository->getWorkingDir()) {
|
||||
$path = $getWorkingDir.'/'.$path;
|
||||
}
|
||||
|
||||
$result = $this->repository->run('log', array('--format=%H', '-n', 1, $this->revision, '--', $path));
|
||||
|
||||
return $this->repository->getCommit(trim($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first line of the commit, and the first 50 characters.
|
||||
*
|
||||
* Ported from https://github.com/fabpot/Twig-extensions/blob/d67bc7e69788795d7905b52d31188bbc1d390e01/lib/Twig/Extensions/Extension/Text.php#L52-L109
|
||||
*
|
||||
* @param int $length
|
||||
* @param bool $preserve
|
||||
* @param string $separator
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getShortMessage($length = 50, $preserve = false, $separator = '...')
|
||||
{
|
||||
$message = $this->getData('subjectMessage');
|
||||
|
||||
if (StringHelper::strlen($message) > $length) {
|
||||
if ($preserve && false !== ($breakpoint = StringHelper::strpos($message, ' ', $length))) {
|
||||
$length = $breakpoint;
|
||||
}
|
||||
|
||||
return rtrim(StringHelper::substr($message, 0, $length)).$separator;
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves all references associated to this commit.
|
||||
*
|
||||
* @return array An array of references (Branch, Tag, Squash)
|
||||
*/
|
||||
public function resolveReferences()
|
||||
{
|
||||
return $this->repository->getReferences()->resolve($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find branch containing the commit.
|
||||
*
|
||||
* @param bool $local set true to try to locate a commit on local repository
|
||||
* @param bool $remote set true to try to locate a commit on remote repository
|
||||
*
|
||||
* @return array An array of Reference\Branch
|
||||
*/
|
||||
public function getIncludingBranches($local = true, $remote = true)
|
||||
{
|
||||
$arguments = array('--contains', $this->revision);
|
||||
|
||||
if ($local && $remote) {
|
||||
$arguments[] = '-a';
|
||||
} elseif (!$local && $remote) {
|
||||
$arguments[] = '-r';
|
||||
} elseif (!$local && !$remote) {
|
||||
throw new InvalidArgumentException('You should a least set one argument to true');
|
||||
}
|
||||
|
||||
try {
|
||||
$result = $this->repository->run('branch', $arguments);
|
||||
} catch (ProcessException $e) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if (!$result) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$branchesName = explode("\n", trim(str_replace('*', '', $result)));
|
||||
$branchesName = array_filter($branchesName, function ($v) { return false === StringHelper::strpos($v, '->');});
|
||||
$branchesName = array_map('trim', $branchesName);
|
||||
|
||||
$references = $this->repository->getReferences();
|
||||
|
||||
$branches = array();
|
||||
foreach ($branchesName as $branchName) {
|
||||
if (false === $local) {
|
||||
$branches[] = $references->getRemoteBranch($branchName);
|
||||
} elseif (0 === StringHelper::strrpos($branchName, 'remotes/')) {
|
||||
$branches[] = $references->getRemoteBranch(str_replace('remotes/', '', $branchName));
|
||||
} else {
|
||||
$branches[] = $references->getBranch($branchName);
|
||||
}
|
||||
}
|
||||
|
||||
return $branches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the author name.
|
||||
*
|
||||
* @return string A name
|
||||
*/
|
||||
public function getAuthorName()
|
||||
{
|
||||
return $this->getData('authorName');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the author email.
|
||||
*
|
||||
* @return string An email
|
||||
*/
|
||||
public function getAuthorEmail()
|
||||
{
|
||||
return $this->getData('authorEmail');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the authoring date.
|
||||
*
|
||||
* @return DateTime A time object
|
||||
*/
|
||||
public function getAuthorDate()
|
||||
{
|
||||
return $this->getData('authorDate');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the committer name.
|
||||
*
|
||||
* @return string A name
|
||||
*/
|
||||
public function getCommitterName()
|
||||
{
|
||||
return $this->getData('committerName');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the comitter email.
|
||||
*
|
||||
* @return string An email
|
||||
*/
|
||||
public function getCommitterEmail()
|
||||
{
|
||||
return $this->getData('committerEmail');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the authoring date.
|
||||
*
|
||||
* @return DateTime A time object
|
||||
*/
|
||||
public function getCommitterDate()
|
||||
{
|
||||
return $this->getData('committerDate');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message of the commit.
|
||||
*
|
||||
* @return string A commit message
|
||||
*/
|
||||
public function getMessage()
|
||||
{
|
||||
return $this->getData('message');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the subject message (the first line).
|
||||
*
|
||||
* @return string The subject message
|
||||
*/
|
||||
public function getSubjectMessage()
|
||||
{
|
||||
return $this->getData('subjectMessage');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the body message.
|
||||
*
|
||||
* @return string The body message
|
||||
*/
|
||||
public function getBodyMessage()
|
||||
{
|
||||
return $this->getData('bodyMessage');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getCommit()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function getData($name)
|
||||
{
|
||||
if (isset($this->data[$name])) {
|
||||
return $this->data[$name];
|
||||
}
|
||||
|
||||
if ($name === 'shortHash') {
|
||||
$this->data['shortHash'] = trim($this->repository->run('log', array('--abbrev-commit', '--format=%h', '-n', 1, $this->revision)));
|
||||
|
||||
return $this->data['shortHash'];
|
||||
}
|
||||
|
||||
if ($name === 'tree') {
|
||||
$this->data['tree'] = $this->repository->getTree($this->getData('treeHash'));
|
||||
|
||||
return $this->data['tree'];
|
||||
}
|
||||
|
||||
if ($name === 'subjectMessage') {
|
||||
$lines = explode("\n", $this->getData('message'));
|
||||
$this->data['subjectMessage'] = reset($lines);
|
||||
|
||||
return $this->data['subjectMessage'];
|
||||
}
|
||||
|
||||
if ($name === 'bodyMessage') {
|
||||
$message = $this->getData('message');
|
||||
|
||||
$lines = explode("\n", $message);
|
||||
|
||||
array_shift($lines);
|
||||
array_shift($lines);
|
||||
|
||||
$data['bodyMessage'] = implode("\n", $lines);
|
||||
|
||||
return $data['bodyMessage'];
|
||||
}
|
||||
|
||||
$parser = new Parser\CommitParser();
|
||||
try {
|
||||
$result = $this->repository->run('cat-file', array('commit', $this->revision));
|
||||
} catch (ProcessException $e) {
|
||||
throw new ReferenceNotFoundException(sprintf('Can not find reference "%s"', $this->revision));
|
||||
}
|
||||
|
||||
$parser->parse($result);
|
||||
|
||||
$this->data['treeHash'] = $parser->tree;
|
||||
$this->data['parentHashes'] = $parser->parents;
|
||||
$this->data['authorName'] = $parser->authorName;
|
||||
$this->data['authorEmail'] = $parser->authorEmail;
|
||||
$this->data['authorDate'] = $parser->authorDate;
|
||||
$this->data['committerName'] = $parser->committerName;
|
||||
$this->data['committerEmail'] = $parser->committerEmail;
|
||||
$this->data['committerDate'] = $parser->committerDate;
|
||||
$this->data['message'] = $parser->message;
|
||||
|
||||
if (!isset($this->data[$name])) {
|
||||
throw new \InvalidArgumentException(sprintf('No data named "%s" in Commit.', $name));
|
||||
}
|
||||
|
||||
return $this->data[$name];
|
||||
}
|
||||
}
|
22
vendor/gitonomy/gitlib/src/Gitonomy/Git/CommitReference.php
vendored
Normal file
22
vendor/gitonomy/gitlib/src/Gitonomy/Git/CommitReference.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git;
|
||||
|
||||
class CommitReference
|
||||
{
|
||||
private $hash;
|
||||
|
||||
public function __construct($hash)
|
||||
{
|
||||
$this->hash = $hash;
|
||||
}
|
||||
}
|
127
vendor/gitonomy/gitlib/src/Gitonomy/Git/Diff/Diff.php
vendored
Normal file
127
vendor/gitonomy/gitlib/src/Gitonomy/Git/Diff/Diff.php
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git\Diff;
|
||||
|
||||
use Gitonomy\Git\Parser\DiffParser;
|
||||
use Gitonomy\Git\Repository;
|
||||
|
||||
/**
|
||||
* Representation of a diff.
|
||||
*
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*/
|
||||
class Diff
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $files;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $rawDiff;
|
||||
|
||||
/**
|
||||
* Constructs a new diff for a given revision.
|
||||
*
|
||||
* @param array $files The files
|
||||
* @param string $rawDiff The raw diff
|
||||
*/
|
||||
public function __construct(array $files, $rawDiff)
|
||||
{
|
||||
$this->files = $files;
|
||||
$this->rawDiff = $rawDiff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Diff
|
||||
*/
|
||||
public static function parse($rawDiff)
|
||||
{
|
||||
$parser = new DiffParser();
|
||||
$parser->parse($rawDiff);
|
||||
|
||||
return new self($parser->files, $rawDiff);
|
||||
}
|
||||
|
||||
public function setRepository(Repository $repository)
|
||||
{
|
||||
foreach ($this->files as $file) {
|
||||
$file->setRepository($repository);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getRevisions()
|
||||
{
|
||||
return $this->revisions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of files modified in the diff's revision.
|
||||
*
|
||||
* @return array An array of Diff\File objects
|
||||
*/
|
||||
public function getFiles()
|
||||
{
|
||||
return $this->files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw diff.
|
||||
*
|
||||
* @return string The raw diff
|
||||
*/
|
||||
public function getRawDiff()
|
||||
{
|
||||
return $this->rawDiff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a diff as array.
|
||||
*
|
||||
* @return array The array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return array(
|
||||
'rawDiff' => $this->rawDiff,
|
||||
'files' => array_map(
|
||||
function (File $file) {
|
||||
return $file->toArray();
|
||||
}, $this->files
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of Diff from an array.
|
||||
*
|
||||
* @param array $array The array
|
||||
*
|
||||
* @return Diff The new instance
|
||||
*/
|
||||
public static function fromArray(array $array)
|
||||
{
|
||||
return new static(
|
||||
array_map(
|
||||
function ($array) {
|
||||
return File::fromArray($array);
|
||||
}, $array['files']
|
||||
),
|
||||
$array['rawDiff']
|
||||
);
|
||||
}
|
||||
}
|
289
vendor/gitonomy/gitlib/src/Gitonomy/Git/Diff/File.php
vendored
Normal file
289
vendor/gitonomy/gitlib/src/Gitonomy/Git/Diff/File.php
vendored
Normal file
@@ -0,0 +1,289 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git\Diff;
|
||||
|
||||
use Gitonomy\Git\Repository;
|
||||
|
||||
/**
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*/
|
||||
class File
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $oldName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $newName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $oldMode;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $newMode;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $oldIndex;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $newIndex;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $isBinary;
|
||||
|
||||
/**
|
||||
* @var array An array of FileChange objects
|
||||
*/
|
||||
protected $changes;
|
||||
|
||||
/**
|
||||
* @var Repository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* Instanciates a new File object.
|
||||
*/
|
||||
public function __construct($oldName, $newName, $oldMode, $newMode, $oldIndex, $newIndex, $isBinary)
|
||||
{
|
||||
$this->oldName = $oldName;
|
||||
$this->newName = $newName;
|
||||
$this->oldMode = $oldMode;
|
||||
$this->newMode = $newMode;
|
||||
$this->oldIndex = $oldIndex;
|
||||
$this->newIndex = $newIndex;
|
||||
$this->isBinary = $isBinary;
|
||||
|
||||
$this->changes = array();
|
||||
}
|
||||
|
||||
public function addChange(FileChange $change)
|
||||
{
|
||||
$this->changes[] = $change;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this diff file is a creation.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isCreation()
|
||||
{
|
||||
return null === $this->oldName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this diff file is a modification.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isModification()
|
||||
{
|
||||
return null !== $this->oldName && null !== $this->newName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if it's a rename.
|
||||
*
|
||||
* A rename can only occurs if it's a modification (not a creation or a deletion).
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isRename()
|
||||
{
|
||||
return $this->isModification() && $this->oldName !== $this->newName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the file mode has changed.
|
||||
*/
|
||||
public function isChangeMode()
|
||||
{
|
||||
return $this->isModification() && $this->oldMode !== $this->newMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this diff file is a deletion.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isDeletion()
|
||||
{
|
||||
return null === $this->newName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this diff file is a deletion.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isDelete()
|
||||
{
|
||||
return null === $this->newName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int Number of added lines
|
||||
*/
|
||||
public function getAdditions()
|
||||
{
|
||||
$result = 0;
|
||||
foreach ($this->changes as $change) {
|
||||
$result += $change->getCount(FileChange::LINE_ADD);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int Number of deleted lines
|
||||
*/
|
||||
public function getDeletions()
|
||||
{
|
||||
$result = 0;
|
||||
foreach ($this->changes as $change) {
|
||||
$result += $change->getCount(FileChange::LINE_REMOVE);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getOldName()
|
||||
{
|
||||
return $this->oldName;
|
||||
}
|
||||
|
||||
public function getNewName()
|
||||
{
|
||||
return $this->newName;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
if (null === $this->newName) {
|
||||
return $this->oldName;
|
||||
}
|
||||
|
||||
return $this->newName;
|
||||
}
|
||||
|
||||
public function getOldMode()
|
||||
{
|
||||
return $this->oldMode;
|
||||
}
|
||||
|
||||
public function getNewMode()
|
||||
{
|
||||
return $this->newMode;
|
||||
}
|
||||
|
||||
public function getOldIndex()
|
||||
{
|
||||
return $this->oldIndex;
|
||||
}
|
||||
|
||||
public function getNewIndex()
|
||||
{
|
||||
return $this->newIndex;
|
||||
}
|
||||
|
||||
public function isBinary()
|
||||
{
|
||||
return $this->isBinary;
|
||||
}
|
||||
|
||||
public function getChanges()
|
||||
{
|
||||
return $this->changes;
|
||||
}
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
return array(
|
||||
'old_name' => $this->oldName,
|
||||
'new_name' => $this->newName,
|
||||
'old_mode' => $this->oldMode,
|
||||
'new_mode' => $this->newMode,
|
||||
'old_index' => $this->oldIndex,
|
||||
'new_index' => $this->newIndex,
|
||||
'is_binary' => $this->isBinary,
|
||||
'changes' => array_map(function (FileChange $change) {
|
||||
return $change->toArray();
|
||||
}, $this->changes),
|
||||
);
|
||||
}
|
||||
|
||||
public static function fromArray(array $array)
|
||||
{
|
||||
$file = new self($array['old_name'], $array['new_name'], $array['old_mode'], $array['new_mode'], $array['old_index'], $array['new_index'], $array['is_binary']);
|
||||
|
||||
foreach ($array['changes'] as $change) {
|
||||
$file->addChange(FileChange::fromArray($change));
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
public function getAnchor()
|
||||
{
|
||||
return substr($this->newIndex, 0, 12);
|
||||
}
|
||||
|
||||
public function getRepository()
|
||||
{
|
||||
return $this->repository;
|
||||
}
|
||||
|
||||
public function setRepository(Repository $repository)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
public function getOldBlob()
|
||||
{
|
||||
if (null === $this->repository) {
|
||||
throw new \RuntimeException('Repository is missing to return Blob object.');
|
||||
}
|
||||
|
||||
if ($this->isCreation()) {
|
||||
throw new \LogicException('Can\'t return old Blob on a creation');
|
||||
}
|
||||
|
||||
return $this->repository->getBlob($this->oldIndex);
|
||||
}
|
||||
|
||||
public function getNewBlob()
|
||||
{
|
||||
if (null === $this->repository) {
|
||||
throw new \RuntimeException('Repository is missing to return Blob object.');
|
||||
}
|
||||
|
||||
if ($this->isDeletion()) {
|
||||
throw new \LogicException('Can\'t return new Blob on a deletion');
|
||||
}
|
||||
|
||||
return $this->repository->getBlob($this->newIndex);
|
||||
}
|
||||
}
|
87
vendor/gitonomy/gitlib/src/Gitonomy/Git/Diff/FileChange.php
vendored
Normal file
87
vendor/gitonomy/gitlib/src/Gitonomy/Git/Diff/FileChange.php
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git\Diff;
|
||||
|
||||
class FileChange
|
||||
{
|
||||
const LINE_CONTEXT = 0;
|
||||
const LINE_REMOVE = -1;
|
||||
const LINE_ADD = 1;
|
||||
|
||||
protected $rangeOldStart;
|
||||
protected $rangeOldCount;
|
||||
protected $rangeNewStart;
|
||||
protected $rangeNewCount;
|
||||
protected $lines;
|
||||
|
||||
public function __construct($rangeOldStart, $rangeOldCount, $rangeNewStart, $rangeNewCount, $lines)
|
||||
{
|
||||
$this->rangeOldStart = $rangeOldStart;
|
||||
$this->rangeOldCount = $rangeOldCount;
|
||||
$this->rangeNewStart = $rangeNewStart;
|
||||
$this->rangeNewCount = $rangeNewCount;
|
||||
$this->lines = $lines;
|
||||
}
|
||||
|
||||
public function getCount($type)
|
||||
{
|
||||
$result = 0;
|
||||
foreach ($this->lines as $line) {
|
||||
if ($line[0] === $type) {
|
||||
++$result;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getRangeOldStart()
|
||||
{
|
||||
return $this->rangeOldStart;
|
||||
}
|
||||
|
||||
public function getRangeOldCount()
|
||||
{
|
||||
return $this->rangeOldCount;
|
||||
}
|
||||
|
||||
public function getRangeNewStart()
|
||||
{
|
||||
return $this->rangeNewStart;
|
||||
}
|
||||
|
||||
public function getRangeNewCount()
|
||||
{
|
||||
return $this->rangeNewCount;
|
||||
}
|
||||
|
||||
public function getLines()
|
||||
{
|
||||
return $this->lines;
|
||||
}
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
return array(
|
||||
'range_old_start' => $this->rangeOldStart,
|
||||
'range_old_count' => $this->rangeOldCount,
|
||||
'range_new_start' => $this->rangeNewStart,
|
||||
'range_new_count' => $this->rangeNewCount,
|
||||
'lines' => $this->lines,
|
||||
);
|
||||
}
|
||||
|
||||
public static function fromArray(array $array)
|
||||
{
|
||||
return new self($array['range_old_start'], $array['range_old_count'], $array['range_new_start'], $array['range_new_count'], $array['lines']);
|
||||
}
|
||||
}
|
16
vendor/gitonomy/gitlib/src/Gitonomy/Git/Exception/GitExceptionInterface.php
vendored
Normal file
16
vendor/gitonomy/gitlib/src/Gitonomy/Git/Exception/GitExceptionInterface.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git\Exception;
|
||||
|
||||
interface GitExceptionInterface
|
||||
{
|
||||
}
|
7
vendor/gitonomy/gitlib/src/Gitonomy/Git/Exception/InvalidArgumentException.php
vendored
Normal file
7
vendor/gitonomy/gitlib/src/Gitonomy/Git/Exception/InvalidArgumentException.php
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Gitonomy\Git\Exception;
|
||||
|
||||
class InvalidArgumentException extends \InvalidArgumentException implements GitExceptionInterface
|
||||
{
|
||||
}
|
7
vendor/gitonomy/gitlib/src/Gitonomy/Git/Exception/LogicException.php
vendored
Normal file
7
vendor/gitonomy/gitlib/src/Gitonomy/Git/Exception/LogicException.php
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Gitonomy\Git\Exception;
|
||||
|
||||
class LogicException extends \LogicException implements GitExceptionInterface
|
||||
{
|
||||
}
|
33
vendor/gitonomy/gitlib/src/Gitonomy/Git/Exception/ProcessException.php
vendored
Normal file
33
vendor/gitonomy/gitlib/src/Gitonomy/Git/Exception/ProcessException.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Gitonomy\Git\Exception;
|
||||
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
class ProcessException extends RuntimeException implements GitExceptionInterface
|
||||
{
|
||||
protected $process;
|
||||
|
||||
public function __construct(Process $process)
|
||||
{
|
||||
parent::__construct("Error while running git command:\n".
|
||||
$process->getCommandLine()."\n".
|
||||
"\n".
|
||||
$process->getErrorOutput()."\n".
|
||||
"\n".
|
||||
$process->getOutput()
|
||||
);
|
||||
|
||||
$this->process = $process;
|
||||
}
|
||||
|
||||
public function getErrorOutput()
|
||||
{
|
||||
return $this->process->getErrorOutput();
|
||||
}
|
||||
|
||||
public function getOutput()
|
||||
{
|
||||
return $this->process->getOutput();
|
||||
}
|
||||
}
|
20
vendor/gitonomy/gitlib/src/Gitonomy/Git/Exception/ReferenceNotFoundException.php
vendored
Normal file
20
vendor/gitonomy/gitlib/src/Gitonomy/Git/Exception/ReferenceNotFoundException.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git\Exception;
|
||||
|
||||
class ReferenceNotFoundException extends \InvalidArgumentException implements GitExceptionInterface
|
||||
{
|
||||
public function __construct($reference)
|
||||
{
|
||||
parent::__construct(sprintf('Reference not found: "%s"', $reference));
|
||||
}
|
||||
}
|
7
vendor/gitonomy/gitlib/src/Gitonomy/Git/Exception/RuntimeException.php
vendored
Normal file
7
vendor/gitonomy/gitlib/src/Gitonomy/Git/Exception/RuntimeException.php
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Gitonomy\Git\Exception;
|
||||
|
||||
class RuntimeException extends \RuntimeException implements GitExceptionInterface
|
||||
{
|
||||
}
|
7
vendor/gitonomy/gitlib/src/Gitonomy/Git/Exception/UnexpectedValueException.php
vendored
Normal file
7
vendor/gitonomy/gitlib/src/Gitonomy/Git/Exception/UnexpectedValueException.php
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Gitonomy\Git\Exception;
|
||||
|
||||
class UnexpectedValueException extends \UnexpectedValueException implements GitExceptionInterface
|
||||
{
|
||||
}
|
127
vendor/gitonomy/gitlib/src/Gitonomy/Git/Hooks.php
vendored
Normal file
127
vendor/gitonomy/gitlib/src/Gitonomy/Git/Hooks.php
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git;
|
||||
|
||||
use Gitonomy\Git\Exception\InvalidArgumentException;
|
||||
use Gitonomy\Git\Exception\LogicException;
|
||||
|
||||
/**
|
||||
* Hooks collection, aggregated by repository.
|
||||
*
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*/
|
||||
class Hooks
|
||||
{
|
||||
/**
|
||||
* @var Gitonomy\Git\Repository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* @var Repository
|
||||
*/
|
||||
public function __construct(Repository $repository)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if repository has a given hook.
|
||||
*
|
||||
* @param string $name Name of the hook
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has($name)
|
||||
{
|
||||
return file_exists($this->getPath($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches content of a hook.
|
||||
*
|
||||
* @param string $name Name of the hook
|
||||
*
|
||||
* @return string Content of the hook
|
||||
*
|
||||
* @throws InvalidArgumentException Hook does not exist
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
if (!$this->has($name)) {
|
||||
throw new InvalidArgumentException(sprintf('Hook named "%s" is not present', $name));
|
||||
}
|
||||
|
||||
return file_get_contents($this->getPath($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a hook in repository using a symlink.
|
||||
*
|
||||
* @param string $name Name of the hook to insert
|
||||
* @param string $file Target of symlink
|
||||
*
|
||||
* @throws LogicException Hook is already present
|
||||
* @throws RuntimeException Error on symlink creation
|
||||
*/
|
||||
public function setSymlink($name, $file)
|
||||
{
|
||||
if ($this->has($name)) {
|
||||
throw new LogicException(sprintf('A hook "%s" is already defined', $name));
|
||||
}
|
||||
|
||||
$path = $this->getPath($name);
|
||||
if (false === symlink($file, $path)) {
|
||||
throw new RuntimeException(sprintf('Unable to create hook "%s"', $name, $path));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a hook in repository.
|
||||
*
|
||||
* @param string $name Name of the hook
|
||||
* @param string $content Content of the hook
|
||||
*
|
||||
* @throws LogicException The hook is already defined
|
||||
*/
|
||||
public function set($name, $content)
|
||||
{
|
||||
if ($this->has($name)) {
|
||||
throw new LogicException(sprintf('A hook "%s" is already defined', $name));
|
||||
}
|
||||
|
||||
$path = $this->getPath($name);
|
||||
file_put_contents($path, $content);
|
||||
chmod($path, 0777);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a hook from repository.
|
||||
*
|
||||
* @param string $name Name of the hook
|
||||
*
|
||||
* @throws LogicException The hook is not present
|
||||
*/
|
||||
public function remove($name)
|
||||
{
|
||||
if (!$this->has($name)) {
|
||||
throw new LogicException(sprintf('The hook "%s" was not found', $name));
|
||||
}
|
||||
|
||||
unlink($this->getPath($name));
|
||||
}
|
||||
|
||||
protected function getPath($name)
|
||||
{
|
||||
return $this->repository->getGitDir().'/hooks/'.$name;
|
||||
}
|
||||
}
|
232
vendor/gitonomy/gitlib/src/Gitonomy/Git/Log.php
vendored
Normal file
232
vendor/gitonomy/gitlib/src/Gitonomy/Git/Log.php
vendored
Normal file
@@ -0,0 +1,232 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git;
|
||||
|
||||
use Gitonomy\Git\Exception\ProcessException;
|
||||
use Gitonomy\Git\Exception\ReferenceNotFoundException;
|
||||
use Gitonomy\Git\Util\StringHelper;
|
||||
|
||||
/**
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*/
|
||||
class Log implements \Countable, \IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* @var Repository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* @var null|RevisionList
|
||||
*/
|
||||
protected $revisions;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $paths;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $offset;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $limit;
|
||||
|
||||
/**
|
||||
* Instanciates a git log object.
|
||||
*
|
||||
* @param Repository $repository the repository where log occurs
|
||||
* @param RevisionList|Revision|array|null $revisions a list of revisions or null if you want all history
|
||||
* @param array $paths paths to filter on
|
||||
* @param int|null $offset start list from a given position
|
||||
* @param int|null $limit limit number of fetched elements
|
||||
*/
|
||||
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 = array();
|
||||
} elseif (is_string($paths)) {
|
||||
$paths = array($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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Diff
|
||||
*/
|
||||
public function getDiff()
|
||||
{
|
||||
return $this->repository->getDiff($this->revisions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RevisionList
|
||||
*/
|
||||
public function getRevisions()
|
||||
{
|
||||
return $this->revisions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getPaths()
|
||||
{
|
||||
return $this->paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getOffset()
|
||||
{
|
||||
return $this->offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $offset
|
||||
*/
|
||||
public function setOffset($offset)
|
||||
{
|
||||
$this->offset = $offset;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLimit()
|
||||
{
|
||||
return $this->limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getCommits()
|
||||
{
|
||||
$args = array('--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 = array();
|
||||
foreach ($parser->log as $commitData) {
|
||||
$hash = $commitData['id'];
|
||||
unset($commitData['id']);
|
||||
|
||||
$commit = $this->repository->getCommit($hash);
|
||||
$commit->setData($commitData);
|
||||
|
||||
$result[] = $commit;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Countable
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return $this->countCommits();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IteratorAggregate
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->getCommits());
|
||||
}
|
||||
|
||||
/**
|
||||
* Count commits, without offset or limit.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countCommits()
|
||||
{
|
||||
if (null !== $this->revisions && count($this->revisions)) {
|
||||
$output = $this->repository->run('rev-list', array_merge(array('--count'), $this->revisions->getAsTextArray(), array('--'), $this->paths));
|
||||
} else {
|
||||
$output = $this->repository->run('rev-list', array_merge(array('--count', '--all', '--'), $this->paths));
|
||||
}
|
||||
|
||||
return (int) $output;
|
||||
}
|
||||
}
|
74
vendor/gitonomy/gitlib/src/Gitonomy/Git/Parser/BlameParser.php
vendored
Normal file
74
vendor/gitonomy/gitlib/src/Gitonomy/Git/Parser/BlameParser.php
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git\Parser;
|
||||
|
||||
use Gitonomy\Git\Blame\Line;
|
||||
use Gitonomy\Git\Repository;
|
||||
|
||||
class BlameParser extends ParserBase
|
||||
{
|
||||
public $lines;
|
||||
|
||||
protected $repository;
|
||||
|
||||
public function __construct(Repository $repository)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
protected function doParse()
|
||||
{
|
||||
$this->lines = array();
|
||||
|
||||
$memory = array();
|
||||
|
||||
$line = 1;
|
||||
while (!$this->isFinished()) {
|
||||
$hash = $this->consumeHash();
|
||||
$this->consume(' ');
|
||||
$vars = $this->consumeRegexp('/(\d+) (\d+)( (\d+))?/A');
|
||||
$sourceLine = $vars[1];
|
||||
$targetLine = $vars[2];
|
||||
$blockLine = isset($vars[4]) ? $vars[4] : null;
|
||||
$this->consumeTo("\n");
|
||||
$this->consumeNewLine();
|
||||
|
||||
if (!isset($memory[$hash])) {
|
||||
foreach (array('author', 'author-mail', 'author-time', 'author-tz',
|
||||
'committer', 'committer-mail', 'committer-time', 'committer-tz',
|
||||
'summary', ) as $key) {
|
||||
$this->consume($key);
|
||||
$this->consumeTo("\n");
|
||||
$this->consumeNewLine();
|
||||
}
|
||||
|
||||
if ($this->expects('previous ')) {
|
||||
$this->consumeTo("\n");
|
||||
$this->consumeNewLine();
|
||||
}
|
||||
|
||||
if ($this->expects('boundary')) {
|
||||
$this->consumeNewLine();
|
||||
}
|
||||
$this->consume('filename');
|
||||
$this->consumeTo("\n"); // filename
|
||||
$this->consumeNewLine();
|
||||
$memory[$hash] = $this->repository->getCommit($hash);
|
||||
}
|
||||
$content = $this->consumeTo("\n"); // content of line
|
||||
$this->consumeNewLine();
|
||||
|
||||
$this->lines[$line] = new Line($memory[$hash], $sourceLine, $targetLine, $blockLine, $content);
|
||||
++$line;
|
||||
}
|
||||
}
|
||||
}
|
79
vendor/gitonomy/gitlib/src/Gitonomy/Git/Parser/CommitParser.php
vendored
Normal file
79
vendor/gitonomy/gitlib/src/Gitonomy/Git/Parser/CommitParser.php
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git\Parser;
|
||||
|
||||
use Gitonomy\Git\Exception\RuntimeException;
|
||||
|
||||
class CommitParser extends ParserBase
|
||||
{
|
||||
public $tree;
|
||||
public $parents;
|
||||
public $authorName;
|
||||
public $authorEmail;
|
||||
public $authorDate;
|
||||
public $committerName;
|
||||
public $committerEmail;
|
||||
public $committerDate;
|
||||
public $message;
|
||||
|
||||
protected function doParse()
|
||||
{
|
||||
$this->consume('tree ');
|
||||
$this->tree = $this->consumeHash();
|
||||
$this->consumeNewLine();
|
||||
|
||||
$this->parents = array();
|
||||
while ($this->expects('parent ')) {
|
||||
$this->parents[] = $this->consumeHash();
|
||||
$this->consumeNewLine();
|
||||
}
|
||||
|
||||
$this->consume('author ');
|
||||
list($this->authorName, $this->authorEmail, $this->authorDate) = $this->consumeNameEmailDate();
|
||||
$this->authorDate = $this->parseDate($this->authorDate);
|
||||
$this->consumeNewLine();
|
||||
|
||||
$this->consume('committer ');
|
||||
list($this->committerName, $this->committerEmail, $this->committerDate) = $this->consumeNameEmailDate();
|
||||
$this->committerDate = $this->parseDate($this->committerDate);
|
||||
|
||||
// will consume an GPG signed commit if there is one
|
||||
$this->consumeGPGSignature();
|
||||
|
||||
$this->consumeNewLine();
|
||||
|
||||
$this->consumeNewLine();
|
||||
$this->message = $this->consumeAll();
|
||||
}
|
||||
|
||||
protected function consumeNameEmailDate()
|
||||
{
|
||||
if (!preg_match('/(([^\n]*) <([^\n]*)> (\d+ [+-]\d{4}))/A', $this->content, $vars, 0, $this->cursor)) {
|
||||
throw new RuntimeException('Unable to parse name, email and date');
|
||||
}
|
||||
|
||||
$this->cursor += strlen($vars[1]);
|
||||
|
||||
return array($vars[2], $vars[3], $vars[4]);
|
||||
}
|
||||
|
||||
protected function parseDate($text)
|
||||
{
|
||||
$date = \DateTime::createFromFormat('U e O', $text.' UTC');
|
||||
|
||||
if (!$date instanceof \DateTime) {
|
||||
throw new RuntimeException(sprintf('Unable to convert "%s" to datetime', $text));
|
||||
}
|
||||
|
||||
return $date;
|
||||
}
|
||||
}
|
133
vendor/gitonomy/gitlib/src/Gitonomy/Git/Parser/DiffParser.php
vendored
Normal file
133
vendor/gitonomy/gitlib/src/Gitonomy/Git/Parser/DiffParser.php
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git\Parser;
|
||||
|
||||
use Gitonomy\Git\Diff\File;
|
||||
use Gitonomy\Git\Diff\FileChange;
|
||||
|
||||
class DiffParser extends ParserBase
|
||||
{
|
||||
public $files;
|
||||
|
||||
protected function doParse()
|
||||
{
|
||||
$this->files = array();
|
||||
|
||||
while (!$this->isFinished()) {
|
||||
// 1. title
|
||||
$vars = $this->consumeRegexp('/diff --git (a\/.*) (b\/.*)\n/');
|
||||
$oldName = $vars[1];
|
||||
$newName = $vars[2];
|
||||
$oldIndex = null;
|
||||
$newIndex = null;
|
||||
$oldMode = null;
|
||||
$newMode = null;
|
||||
|
||||
// 2. mode
|
||||
if ($this->expects('new file mode ')) {
|
||||
$newMode = $this->consumeTo("\n");
|
||||
$this->consumeNewLine();
|
||||
$oldMode = null;
|
||||
}
|
||||
if ($this->expects('old mode ')) {
|
||||
$oldMode = $this->consumeTo("\n");
|
||||
$this->consumeNewLine();
|
||||
$this->consume('new mode ');
|
||||
$newMode = $this->consumeTo("\n");
|
||||
$this->consumeNewLine();
|
||||
}
|
||||
if ($this->expects('deleted file mode ')) {
|
||||
$oldMode = $this->consumeTo("\n");
|
||||
$newMode = null;
|
||||
$this->consumeNewLine();
|
||||
}
|
||||
|
||||
if ($this->expects('similarity index ')) {
|
||||
$this->consumeRegexp('/\d{1,3}%\n/');
|
||||
$this->consume('rename from ');
|
||||
$this->consumeTo("\n");
|
||||
$this->consumeNewLine();
|
||||
$this->consume('rename to ');
|
||||
$this->consumeTo("\n");
|
||||
$this->consumeNewLine();
|
||||
}
|
||||
|
||||
// 4. File informations
|
||||
$isBinary = false;
|
||||
if ($this->expects('index ')) {
|
||||
$oldIndex = $this->consumeShortHash();
|
||||
$this->consume('..');
|
||||
$newIndex = $this->consumeShortHash();
|
||||
if ($this->expects(' ')) {
|
||||
$vars = $this->consumeRegexp('/\d{6}/');
|
||||
$newMode = $oldMode = $vars[0];
|
||||
}
|
||||
$this->consumeNewLine();
|
||||
|
||||
if ($this->expects('--- ')) {
|
||||
$oldName = $this->consumeTo("\n");
|
||||
$this->consumeNewLine();
|
||||
$this->consume('+++ ');
|
||||
$newName = $this->consumeTo("\n");
|
||||
$this->consumeNewLine();
|
||||
} elseif ($this->expects('Binary files ')) {
|
||||
$vars = $this->consumeRegexp('/(.*) and (.*) differ\n/');
|
||||
$isBinary = true;
|
||||
$oldName = $vars[1];
|
||||
$newName = $vars[2];
|
||||
}
|
||||
}
|
||||
|
||||
$oldName = $oldName === '/dev/null' ? null : substr($oldName, 2);
|
||||
$newName = $newName === '/dev/null' ? null : substr($newName, 2);
|
||||
$oldIndex = preg_match('/^0+$/', $oldIndex) ? null : $oldIndex;
|
||||
$newIndex = preg_match('/^0+$/', $newIndex) ? null : $newIndex;
|
||||
$file = new File($oldName, $newName, $oldMode, $newMode, $oldIndex, $newIndex, $isBinary);
|
||||
|
||||
// 5. Diff
|
||||
while ($this->expects('@@ ')) {
|
||||
$vars = $this->consumeRegexp('/-(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))?/');
|
||||
$rangeOldStart = $vars[1];
|
||||
$rangeOldCount = $vars[2];
|
||||
$rangeNewStart = $vars[3];
|
||||
$rangeNewCount = isset($vars[4]) ? $vars[4] : $vars[2]; // @todo Ici, t'as pris un gros raccourci mon loulou
|
||||
$this->consume(' @@');
|
||||
$this->consumeTo("\n");
|
||||
$this->consumeNewLine();
|
||||
|
||||
// 6. Lines
|
||||
$lines = array();
|
||||
while (true) {
|
||||
if ($this->expects(' ')) {
|
||||
$lines[] = array(FileChange::LINE_CONTEXT, $this->consumeTo("\n"));
|
||||
} elseif ($this->expects('+')) {
|
||||
$lines[] = array(FileChange::LINE_ADD, $this->consumeTo("\n"));
|
||||
} elseif ($this->expects('-')) {
|
||||
$lines[] = array(FileChange::LINE_REMOVE, $this->consumeTo("\n"));
|
||||
} elseif ($this->expects("\ No newline at end of file")) {
|
||||
// Ignore this case...
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
$this->consumeNewLine();
|
||||
}
|
||||
|
||||
$change = new FileChange($rangeOldStart, $rangeOldCount, $rangeNewStart, $rangeNewCount, $lines);
|
||||
|
||||
$file->addChange($change);
|
||||
}
|
||||
|
||||
$this->files[] = $file;
|
||||
}
|
||||
}
|
||||
}
|
75
vendor/gitonomy/gitlib/src/Gitonomy/Git/Parser/LogParser.php
vendored
Normal file
75
vendor/gitonomy/gitlib/src/Gitonomy/Git/Parser/LogParser.php
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git\Parser;
|
||||
|
||||
class LogParser extends CommitParser
|
||||
{
|
||||
public $log = array();
|
||||
|
||||
protected function doParse()
|
||||
{
|
||||
$this->log = array();
|
||||
|
||||
while (!$this->isFinished()) {
|
||||
$commit = array();
|
||||
$this->consume('commit ');
|
||||
$commit['id'] = $this->consumeHash();
|
||||
$this->consumeNewLine();
|
||||
|
||||
$this->consume('tree ');
|
||||
$commit['treeHash'] = $this->consumeHash();
|
||||
$this->consumeNewLine();
|
||||
|
||||
$commit['parentHashes'] = array();
|
||||
while ($this->expects('parent ')) {
|
||||
$commit['parentHashes'][] = $this->consumeHash();
|
||||
$this->consumeNewLine();
|
||||
}
|
||||
|
||||
$this->consume('author ');
|
||||
list($commit['authorName'], $commit['authorEmail'], $commit['authorDate']) = $this->consumeNameEmailDate();
|
||||
$commit['authorDate'] = $this->parseDate($commit['authorDate']);
|
||||
$this->consumeNewLine();
|
||||
|
||||
$this->consume('committer ');
|
||||
list($commit['committerName'], $commit['committerEmail'], $commit['committerDate']) = $this->consumeNameEmailDate();
|
||||
$commit['committerDate'] = $this->parseDate($commit['committerDate']);
|
||||
|
||||
// will consume an GPG signed commit if there is one
|
||||
$this->consumeGPGSignature();
|
||||
|
||||
$this->consumeNewLine();
|
||||
$this->consumeNewLine();
|
||||
|
||||
$message = '';
|
||||
if ($this->expects(' ')) {
|
||||
$this->cursor -= strlen(' ');
|
||||
|
||||
while ($this->expects(' ')) {
|
||||
$message .= $this->consumeTo("\n")."\n";
|
||||
$this->consumeNewLine();
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->cursor--;
|
||||
}
|
||||
|
||||
if (!$this->isFinished()) {
|
||||
$this->consumeNewLine();
|
||||
}
|
||||
|
||||
$commit['message'] = $message;
|
||||
|
||||
$this->log[] = $commit;
|
||||
}
|
||||
}
|
||||
}
|
137
vendor/gitonomy/gitlib/src/Gitonomy/Git/Parser/ParserBase.php
vendored
Normal file
137
vendor/gitonomy/gitlib/src/Gitonomy/Git/Parser/ParserBase.php
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git\Parser;
|
||||
|
||||
use Gitonomy\Git\Exception\RuntimeException;
|
||||
|
||||
abstract class ParserBase
|
||||
{
|
||||
protected $cursor;
|
||||
protected $content;
|
||||
protected $length;
|
||||
|
||||
abstract protected function doParse();
|
||||
|
||||
public function parse($content)
|
||||
{
|
||||
$this->cursor = 0;
|
||||
$this->content = $content;
|
||||
$this->length = strlen($this->content);
|
||||
|
||||
$this->doParse();
|
||||
}
|
||||
|
||||
protected function isFinished()
|
||||
{
|
||||
return $this->cursor === $this->length;
|
||||
}
|
||||
|
||||
protected function consumeAll()
|
||||
{
|
||||
$rest = substr($this->content, $this->cursor);
|
||||
$this->cursor += strlen($rest);
|
||||
|
||||
return $rest;
|
||||
}
|
||||
|
||||
protected function expects($expected)
|
||||
{
|
||||
$length = strlen($expected);
|
||||
$actual = substr($this->content, $this->cursor, $length);
|
||||
if ($actual !== $expected) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->cursor += $length;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function consumeShortHash()
|
||||
{
|
||||
if (!preg_match('/([A-Za-z0-9]{7,40})/A', $this->content, $vars, null, $this->cursor)) {
|
||||
throw new RuntimeException('No short hash found: '.substr($this->content, $this->cursor, 7));
|
||||
}
|
||||
|
||||
$this->cursor += strlen($vars[1]);
|
||||
|
||||
return $vars[1];
|
||||
}
|
||||
|
||||
protected function consumeHash()
|
||||
{
|
||||
if (!preg_match('/([A-Za-z0-9]{40})/A', $this->content, $vars, null, $this->cursor)) {
|
||||
throw new RuntimeException('No hash found: '.substr($this->content, $this->cursor, 40));
|
||||
}
|
||||
|
||||
$this->cursor += 40;
|
||||
|
||||
return $vars[1];
|
||||
}
|
||||
|
||||
protected function consumeRegexp($regexp)
|
||||
{
|
||||
if (!preg_match($regexp.'A', $this->content, $vars, null, $this->cursor)) {
|
||||
throw new RuntimeException('No match for regexp '.$regexp.' Upcoming: '.substr($this->content, $this->cursor, 30));
|
||||
}
|
||||
|
||||
$this->cursor += strlen($vars[0]);
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
protected function consumeTo($text)
|
||||
{
|
||||
$pos = strpos($this->content, $text, $this->cursor);
|
||||
|
||||
if (false === $pos) {
|
||||
throw new RuntimeException(sprintf('Unable to find "%s"', $text));
|
||||
}
|
||||
|
||||
$result = substr($this->content, $this->cursor, $pos - $this->cursor);
|
||||
$this->cursor = $pos;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function consume($expected)
|
||||
{
|
||||
$length = strlen($expected);
|
||||
$actual = substr($this->content, $this->cursor, $length);
|
||||
if ($actual !== $expected) {
|
||||
throw new RuntimeException(sprintf('Expected "%s", but got "%s" (%s)', $expected, $actual, substr($this->content, $this->cursor, 10)));
|
||||
}
|
||||
$this->cursor += $length;
|
||||
|
||||
return $expected;
|
||||
}
|
||||
|
||||
protected function consumeNewLine()
|
||||
{
|
||||
return $this->consume("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function consumeGPGSignature() {
|
||||
$expected = "\ngpgsig ";
|
||||
$length = strlen($expected);
|
||||
$actual = substr($this->content, $this->cursor, $length);
|
||||
if($actual != $expected) {
|
||||
return '';
|
||||
}
|
||||
$this->cursor += $length;
|
||||
|
||||
return $this->consumeTo("\n\n");
|
||||
}
|
||||
}
|
30
vendor/gitonomy/gitlib/src/Gitonomy/Git/Parser/ReferenceParser.php
vendored
Normal file
30
vendor/gitonomy/gitlib/src/Gitonomy/Git/Parser/ReferenceParser.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git\Parser;
|
||||
|
||||
class ReferenceParser extends ParserBase
|
||||
{
|
||||
public $references;
|
||||
|
||||
protected function doParse()
|
||||
{
|
||||
$this->references = array();
|
||||
|
||||
while (!$this->isFinished()) {
|
||||
$hash = $this->consumeHash();
|
||||
$this->consume(' ');
|
||||
$name = $this->consumeTo("\n");
|
||||
$this->consumeNewLine();
|
||||
$this->references[] = array($hash, $name);
|
||||
}
|
||||
}
|
||||
}
|
38
vendor/gitonomy/gitlib/src/Gitonomy/Git/Parser/TreeParser.php
vendored
Normal file
38
vendor/gitonomy/gitlib/src/Gitonomy/Git/Parser/TreeParser.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git\Parser;
|
||||
|
||||
class TreeParser extends ParserBase
|
||||
{
|
||||
public $entries = array();
|
||||
|
||||
protected function doParse()
|
||||
{
|
||||
while (!$this->isFinished()) {
|
||||
$vars = $this->consumeRegexp('/\d{6}/A');
|
||||
$mode = $vars[0];
|
||||
$this->consume(' ');
|
||||
|
||||
$vars = $this->consumeRegexp('/(blob|tree|commit)/A');
|
||||
$type = $vars[0];
|
||||
$this->consume(' ');
|
||||
|
||||
$hash = $this->consumeHash();
|
||||
$this->consume("\t");
|
||||
|
||||
$name = $this->consumeTo("\n");
|
||||
$this->consumeNewLine();
|
||||
|
||||
$this->entries[] = array($mode, $type, $hash, $name);
|
||||
}
|
||||
}
|
||||
}
|
169
vendor/gitonomy/gitlib/src/Gitonomy/Git/PushReference.php
vendored
Normal file
169
vendor/gitonomy/gitlib/src/Gitonomy/Git/PushReference.php
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git;
|
||||
|
||||
use Gitonomy\Git\Exception\LogicException;
|
||||
|
||||
/**
|
||||
* Push reference contains a commit interval. This object aggregates methods
|
||||
* for this interval.
|
||||
*
|
||||
* @author Julien DIDIER <genzo.wm@gmail.com>
|
||||
*/
|
||||
class PushReference
|
||||
{
|
||||
const ZERO = '0000000000000000000000000000000000000000';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $reference;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $before;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $after;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $isForce;
|
||||
|
||||
public function __construct(Repository $repository, $reference, $before, $after)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
$this->reference = $reference;
|
||||
$this->before = $before;
|
||||
$this->after = $after;
|
||||
$this->isForce = $this->getForce();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Repository
|
||||
*/
|
||||
public function getRepository()
|
||||
{
|
||||
return $this->repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getReference()
|
||||
{
|
||||
return $this->reference;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBefore()
|
||||
{
|
||||
return $this->before;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAfter()
|
||||
{
|
||||
return $this->after;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getLog($excludes = array())
|
||||
{
|
||||
return $this->repository->getLog(array_merge(
|
||||
array($this->getRevision()),
|
||||
array_map(function ($e) {
|
||||
return '^'.$e;
|
||||
}, $excludes)
|
||||
));
|
||||
}
|
||||
|
||||
public function getRevision()
|
||||
{
|
||||
if ($this->isDelete()) {
|
||||
throw new LogicException('No revision for deletion');
|
||||
}
|
||||
|
||||
if ($this->isCreate()) {
|
||||
return $this->getAfter();
|
||||
}
|
||||
|
||||
return $this->getBefore().'..'.$this->getAfter();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isCreate()
|
||||
{
|
||||
return $this->isZero($this->before);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isDelete()
|
||||
{
|
||||
return $this->isZero($this->after);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isForce()
|
||||
{
|
||||
return $this->isForce;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isFastForward()
|
||||
{
|
||||
return !$this->isDelete() && !$this->isCreate() && !$this->isForce();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function isZero($reference)
|
||||
{
|
||||
return self::ZERO === $reference;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function getForce()
|
||||
{
|
||||
if ($this->isDelete() || $this->isCreate()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = $this->repository->run('merge-base', array(
|
||||
$this->before,
|
||||
$this->after,
|
||||
));
|
||||
|
||||
return $this->before !== trim($result);
|
||||
}
|
||||
}
|
70
vendor/gitonomy/gitlib/src/Gitonomy/Git/Reference.php
vendored
Normal file
70
vendor/gitonomy/gitlib/src/Gitonomy/Git/Reference.php
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git;
|
||||
|
||||
/**
|
||||
* Reference in a Git repository.
|
||||
*
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* @author Julien DIDIER <genzo.wm@gmail.com>
|
||||
*/
|
||||
abstract class Reference extends Revision
|
||||
{
|
||||
protected $commitHash;
|
||||
|
||||
public function __construct(Repository $repository, $revision, $commitHash = null)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
$this->revision = $revision;
|
||||
$this->commitHash = $commitHash;
|
||||
}
|
||||
|
||||
public function getFullname()
|
||||
{
|
||||
return $this->revision;
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$this->repository->getReferences()->delete($this->getFullname());
|
||||
}
|
||||
|
||||
public function getCommitHash()
|
||||
{
|
||||
if (null !== $this->commitHash) {
|
||||
return $this->commitHash;
|
||||
}
|
||||
|
||||
try {
|
||||
$result = $this->repository->run('rev-parse', array('--verify', $this->revision));
|
||||
} catch (ProcessException $e) {
|
||||
throw new ReferenceNotFoundException(sprintf('Can not find revision "%s"', $this->revision));
|
||||
}
|
||||
|
||||
return $this->commitHash = trim($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the commit associated to the reference.
|
||||
*
|
||||
* @return Commit
|
||||
*/
|
||||
public function getCommit()
|
||||
{
|
||||
return $this->repository->getCommit($this->getCommitHash());
|
||||
}
|
||||
|
||||
public function getLastModification($path = null)
|
||||
{
|
||||
return $this->getCommit()->getLastModification($path);
|
||||
}
|
||||
}
|
61
vendor/gitonomy/gitlib/src/Gitonomy/Git/Reference/Branch.php
vendored
Normal file
61
vendor/gitonomy/gitlib/src/Gitonomy/Git/Reference/Branch.php
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git\Reference;
|
||||
|
||||
use Gitonomy\Git\Exception\RuntimeException;
|
||||
use Gitonomy\Git\Reference;
|
||||
|
||||
/**
|
||||
* Representation of a branch reference.
|
||||
*
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*/
|
||||
class Branch extends Reference
|
||||
{
|
||||
private $local = null;
|
||||
|
||||
public function getName()
|
||||
{
|
||||
$fullname = $this->getFullname();
|
||||
|
||||
if (preg_match('#^refs/heads/(?<name>.*)$#', $fullname, $vars)) {
|
||||
return $vars['name'];
|
||||
}
|
||||
|
||||
if (preg_match('#^refs/remotes/(?<remote>[^/]*)/(?<name>.*)$#', $fullname, $vars)) {
|
||||
return $vars['remote'].'/'.$vars['name'];
|
||||
}
|
||||
|
||||
throw new RuntimeException(sprintf('Cannot extract branch name from "%s"', $fullname));
|
||||
}
|
||||
|
||||
public function isRemote()
|
||||
{
|
||||
$this->detectBranchType();
|
||||
|
||||
return !$this->local;
|
||||
}
|
||||
|
||||
public function isLocal()
|
||||
{
|
||||
$this->detectBranchType();
|
||||
|
||||
return $this->local;
|
||||
}
|
||||
|
||||
private function detectBranchType()
|
||||
{
|
||||
if (null === $this->local) {
|
||||
$this->local = !preg_match('#^refs/remotes/(?<remote>[^/]*)/(?<name>.*)$#', $this->getFullname());
|
||||
}
|
||||
}
|
||||
}
|
25
vendor/gitonomy/gitlib/src/Gitonomy/Git/Reference/Stash.php
vendored
Normal file
25
vendor/gitonomy/gitlib/src/Gitonomy/Git/Reference/Stash.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git\Reference;
|
||||
|
||||
use Gitonomy\Git\Reference;
|
||||
|
||||
/**
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*/
|
||||
class Stash extends Reference
|
||||
{
|
||||
public function getName()
|
||||
{
|
||||
return 'stash';
|
||||
}
|
||||
}
|
32
vendor/gitonomy/gitlib/src/Gitonomy/Git/Reference/Tag.php
vendored
Normal file
32
vendor/gitonomy/gitlib/src/Gitonomy/Git/Reference/Tag.php
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git\Reference;
|
||||
|
||||
use Gitonomy\Git\Exception\RuntimeException;
|
||||
use Gitonomy\Git\Reference;
|
||||
|
||||
/**
|
||||
* Representation of a tag reference.
|
||||
*
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*/
|
||||
class Tag extends Reference
|
||||
{
|
||||
public function getName()
|
||||
{
|
||||
if (!preg_match('#^refs/tags/(.*)$#', $this->revision, $vars)) {
|
||||
throw new RuntimeException(sprintf('Cannot extract tag name from "%s"', $this->revision));
|
||||
}
|
||||
|
||||
return $vars[1];
|
||||
}
|
||||
}
|
399
vendor/gitonomy/gitlib/src/Gitonomy/Git/ReferenceBag.php
vendored
Normal file
399
vendor/gitonomy/gitlib/src/Gitonomy/Git/ReferenceBag.php
vendored
Normal file
@@ -0,0 +1,399 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git;
|
||||
|
||||
use Gitonomy\Git\Exception\ReferenceNotFoundException;
|
||||
use Gitonomy\Git\Exception\RuntimeException;
|
||||
use Gitonomy\Git\Reference\Branch;
|
||||
use Gitonomy\Git\Reference\Stash;
|
||||
use Gitonomy\Git\Reference\Tag;
|
||||
|
||||
/**
|
||||
* Reference set associated to a repository.
|
||||
*
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* @author Julien DIDIER <genzo.wm@gmail.com>
|
||||
*/
|
||||
class ReferenceBag implements \Countable, \IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* Repository object.
|
||||
*
|
||||
* @var Gitonomy\Git\Repository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* Associative array of fullname references.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $references;
|
||||
|
||||
/**
|
||||
* List with all tags.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $tags;
|
||||
|
||||
/**
|
||||
* List with all branches.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $branches;
|
||||
|
||||
/**
|
||||
* A boolean indicating if the bag is already initialized.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $initialized = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Gitonomy\Git\Repository $repository The repository
|
||||
*/
|
||||
public function __construct($repository)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
$this->references = array();
|
||||
$this->tags = array();
|
||||
$this->branches = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference, by name.
|
||||
*
|
||||
* @param string $fullname Fullname of the reference (refs/heads/master, for example).
|
||||
*
|
||||
* @return Reference A reference object.
|
||||
*/
|
||||
public function get($fullname)
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
if (!isset($this->references[$fullname])) {
|
||||
throw new ReferenceNotFoundException($fullname);
|
||||
}
|
||||
|
||||
return $this->references[$fullname];
|
||||
}
|
||||
|
||||
public function has($fullname)
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
return isset($this->references[$fullname]);
|
||||
}
|
||||
|
||||
public function update(Reference $reference)
|
||||
{
|
||||
$fullname = $reference->getFullname();
|
||||
|
||||
$this->initialize();
|
||||
$this->repository->run('update-ref', array($fullname, $reference->getCommitHash()));
|
||||
|
||||
$this->references[$fullname] = $reference;
|
||||
|
||||
return $reference;
|
||||
}
|
||||
|
||||
public function createBranch($name, $commitHash)
|
||||
{
|
||||
$branch = new Branch($this->repository, 'refs/heads/'.$name, $commitHash);
|
||||
|
||||
return $this->update($branch);
|
||||
}
|
||||
|
||||
public function createTag($name, $commitHash)
|
||||
{
|
||||
$tag = new Tag($this->repository, 'refs/tags/'.$name, $commitHash);
|
||||
|
||||
return $this->update($tag);
|
||||
}
|
||||
|
||||
public function delete($fullname)
|
||||
{
|
||||
$this->repository->run('update-ref', array('-d', $fullname));
|
||||
|
||||
unset($this->references[$fullname]);
|
||||
}
|
||||
|
||||
public function hasBranches()
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
return count($this->branches) > 0;
|
||||
}
|
||||
|
||||
public function hasBranch($name)
|
||||
{
|
||||
return $this->has('refs/heads/'.$name);
|
||||
}
|
||||
|
||||
public function hasRemoteBranch($name)
|
||||
{
|
||||
return $this->has('refs/remotes/'.$name);
|
||||
}
|
||||
|
||||
public function hasTag($name)
|
||||
{
|
||||
return $this->has('refs/tags/'.$name);
|
||||
}
|
||||
|
||||
public function getFirstBranch()
|
||||
{
|
||||
$this->initialize();
|
||||
reset($this->branches);
|
||||
|
||||
return current($this->references);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array An array of Tag objects
|
||||
*/
|
||||
public function resolveTags($hash)
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
if ($hash instanceof Commit) {
|
||||
$hash = $hash->getHash();
|
||||
}
|
||||
|
||||
$tags = array();
|
||||
foreach ($this->references as $reference) {
|
||||
if ($reference instanceof Reference\Tag && $reference->getCommitHash() === $hash) {
|
||||
$tags[] = $reference;
|
||||
}
|
||||
}
|
||||
|
||||
return $tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array An array of Branch objects
|
||||
*/
|
||||
public function resolveBranches($hash)
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
if ($hash instanceof Commit) {
|
||||
$hash = $hash->getHash();
|
||||
}
|
||||
|
||||
$branches = array();
|
||||
foreach ($this->references as $reference) {
|
||||
if ($reference instanceof Reference\Branch && $reference->getCommitHash() === $hash) {
|
||||
$branches[] = $reference;
|
||||
}
|
||||
}
|
||||
|
||||
return $branches;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array An array of references
|
||||
*/
|
||||
public function resolve($hash)
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
if ($hash instanceof Commit) {
|
||||
$hash = $hash->getHash();
|
||||
}
|
||||
|
||||
$result = array();
|
||||
foreach ($this->references as $k => $reference) {
|
||||
if ($reference->getCommitHash() === $hash) {
|
||||
$result[] = $reference;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all tags.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTags()
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
return $this->tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all branches.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getBranches()
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
$result = array();
|
||||
foreach ($this->references as $reference) {
|
||||
if ($reference instanceof Reference\Branch) {
|
||||
$result[] = $reference;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all locales branches.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLocalBranches()
|
||||
{
|
||||
$result = array();
|
||||
foreach ($this->getBranches() as $branch) {
|
||||
if ($branch->isLocal()) {
|
||||
$result[] = $branch;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all remote branches.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRemoteBranches()
|
||||
{
|
||||
$result = array();
|
||||
foreach ($this->getBranches() as $branch) {
|
||||
if ($branch->isRemote()) {
|
||||
$result[] = $branch;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array An associative array with fullname as key (refs/heads/master, refs/tags/0.1)
|
||||
*/
|
||||
public function getAll()
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
return $this->references;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Tag
|
||||
*/
|
||||
public function getTag($name)
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
return $this->get('refs/tags/'.$name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Branch
|
||||
*/
|
||||
public function getBranch($name)
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
return $this->get('refs/heads/'.$name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Branch
|
||||
*/
|
||||
public function getRemoteBranch($name)
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
return $this->get('refs/remotes/'.$name);
|
||||
}
|
||||
|
||||
protected function initialize()
|
||||
{
|
||||
if (true === $this->initialized) {
|
||||
return;
|
||||
}
|
||||
$this->initialized = true;
|
||||
|
||||
try {
|
||||
$parser = new Parser\ReferenceParser();
|
||||
$output = $this->repository->run('show-ref');
|
||||
} catch (RuntimeException $e) {
|
||||
$output = $e->getOutput();
|
||||
$error = $e->getErrorOutput();
|
||||
if ($error) {
|
||||
throw new RuntimeException('Error while getting list of references: '.$error);
|
||||
}
|
||||
}
|
||||
$parser->parse($output);
|
||||
|
||||
foreach ($parser->references as $row) {
|
||||
list($commitHash, $fullname) = $row;
|
||||
|
||||
if (preg_match('#^refs/(heads|remotes)/(.*)$#', $fullname)) {
|
||||
if (preg_match('#.*HEAD$#', $fullname)) {
|
||||
continue;
|
||||
}
|
||||
$reference = new Branch($this->repository, $fullname, $commitHash);
|
||||
$this->references[$fullname] = $reference;
|
||||
$this->branches[] = $reference;
|
||||
} elseif (preg_match('#^refs/tags/(.*)$#', $fullname)) {
|
||||
$reference = new Tag($this->repository, $fullname, $commitHash);
|
||||
$this->references[$fullname] = $reference;
|
||||
$this->tags[] = $reference;
|
||||
} elseif ($fullname === 'refs/stash') {
|
||||
$reference = new Stash($this->repository, $fullname, $commitHash);
|
||||
$this->references[$fullname] = $reference;
|
||||
} elseif (preg_match('#^refs/pull/(.*)$#', $fullname)) {
|
||||
// Do nothing here
|
||||
} elseif ($fullname === 'refs/notes/gtm-data') {
|
||||
// Do nothing here
|
||||
} else {
|
||||
throw new RuntimeException(sprintf('Unable to parse "%s"', $fullname));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*
|
||||
* @see Countable
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
return count($this->references);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IteratorAggregate
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
return new \ArrayIterator($this->references);
|
||||
}
|
||||
}
|
667
vendor/gitonomy/gitlib/src/Gitonomy/Git/Repository.php
vendored
Normal file
667
vendor/gitonomy/gitlib/src/Gitonomy/Git/Repository.php
vendored
Normal file
@@ -0,0 +1,667 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git;
|
||||
|
||||
use Gitonomy\Git\Diff\Diff;
|
||||
use Gitonomy\Git\Exception\InvalidArgumentException;
|
||||
use Gitonomy\Git\Exception\ProcessException;
|
||||
use Gitonomy\Git\Exception\RuntimeException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Symfony\Component\Process\ProcessUtils;
|
||||
|
||||
/**
|
||||
* Git repository object.
|
||||
*
|
||||
* Main entry point for browsing a Git repository.
|
||||
*
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*/
|
||||
class Repository
|
||||
{
|
||||
const DEFAULT_DESCRIPTION = "Unnamed repository; edit this file 'description' to name the repository.\n";
|
||||
|
||||
/**
|
||||
* Directory containing git files.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $gitDir;
|
||||
|
||||
/**
|
||||
* Working directory.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $workingDir;
|
||||
|
||||
/**
|
||||
* Cache containing all objects of the repository.
|
||||
*
|
||||
* Associative array, indexed by object hash
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $objects;
|
||||
|
||||
/**
|
||||
* Reference bag associated to this repository.
|
||||
*
|
||||
* @var ReferenceBag
|
||||
*/
|
||||
protected $referenceBag;
|
||||
|
||||
/**
|
||||
* Logger (can be null).
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* Path to git command.
|
||||
*/
|
||||
protected $command;
|
||||
|
||||
/**
|
||||
* Debug flag, indicating if errors should be thrown.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $debug;
|
||||
|
||||
/**
|
||||
* Environment variables that should be set for every running process.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $environmentVariables;
|
||||
|
||||
/**
|
||||
* Timeout that should be set for every running process.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $processTimeout;
|
||||
|
||||
/**
|
||||
* Constructs a new repository.
|
||||
*
|
||||
* Available options are:
|
||||
*
|
||||
* * working_dir : specify where working copy is located (option --work-tree)
|
||||
*
|
||||
* * debug : (default: true) enable/disable minimize errors and reduce log level
|
||||
*
|
||||
* * logger : a logger to use for logging actions (Psr\Log\LoggerInterface)
|
||||
*
|
||||
* * environment_variables : define environment variables for every ran process
|
||||
*
|
||||
* @param string $dir path to git repository
|
||||
* @param array $options array of options values
|
||||
*
|
||||
* @throws InvalidArgumentException The folder does not exists
|
||||
*/
|
||||
public function __construct($dir, $options = array())
|
||||
{
|
||||
$is_windows = defined('PHP_WINDOWS_VERSION_BUILD');
|
||||
$options = array_merge(array(
|
||||
'working_dir' => null,
|
||||
'debug' => true,
|
||||
'logger' => null,
|
||||
'environment_variables' => $is_windows ? array('PATH' => getenv('path')) : array(),
|
||||
'command' => 'git',
|
||||
'process_timeout' => 3600,
|
||||
), $options);
|
||||
|
||||
if (null !== $options['logger'] && !$options['logger'] instanceof LoggerInterface) {
|
||||
throw new InvalidArgumentException(sprintf('Argument "logger" passed to Repository should be a Psr\Log\LoggerInterface. A %s was provided', is_object($options['logger']) ? get_class($options['logger']) : gettype($options['logger'])));
|
||||
}
|
||||
|
||||
$this->logger = $options['logger'];
|
||||
$this->initDir($dir, $options['working_dir']);
|
||||
|
||||
$this->objects = array();
|
||||
$this->debug = (bool) $options['debug'];
|
||||
$this->environmentVariables = $options['environment_variables'];
|
||||
$this->processTimeout = $options['process_timeout'];
|
||||
$this->command = $options['command'];
|
||||
|
||||
if (true === $this->debug && null !== $this->logger) {
|
||||
$this->logger->debug(sprintf('Repository created (git dir: "%s", working dir: "%s")', $this->gitDir, $this->workingDir ?: 'none'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes directory attributes on repository:.
|
||||
*
|
||||
* @param string $gitDir directory of a working copy with files checked out
|
||||
* @param string $workingDir directory containing git files (objects, config...)
|
||||
*/
|
||||
private function initDir($gitDir, $workingDir = null)
|
||||
{
|
||||
$realGitDir = realpath($gitDir);
|
||||
|
||||
if (false === $realGitDir) {
|
||||
throw new InvalidArgumentException(sprintf('Directory "%s" does not exist or is not a directory', $gitDir));
|
||||
} else if (!is_dir($realGitDir)) {
|
||||
throw new InvalidArgumentException(sprintf('Directory "%s" does not exist or is not a directory', $realGitDir));
|
||||
} elseif (null === $workingDir && is_dir($realGitDir.'/.git')) {
|
||||
$workingDir = $realGitDir;
|
||||
$realGitDir = $realGitDir.'/.git';
|
||||
}
|
||||
|
||||
$this->gitDir = $realGitDir;
|
||||
$this->workingDir = $workingDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if repository is a bare repository.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isBare()
|
||||
{
|
||||
return null === $this->workingDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HEAD resolved as a commit.
|
||||
*
|
||||
* @return Commit|null returns a Commit or ``null`` if repository is empty
|
||||
*/
|
||||
public function getHeadCommit()
|
||||
{
|
||||
$head = $this->getHead();
|
||||
|
||||
if ($head instanceof Reference) {
|
||||
return $head->getCommit();
|
||||
}
|
||||
|
||||
return $head;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RuntimeException Unable to find file HEAD (debug-mode only)
|
||||
*
|
||||
* @return Reference|Commit|null current HEAD object or null if error occurs
|
||||
*/
|
||||
public function getHead()
|
||||
{
|
||||
$file = $this->gitDir.'/HEAD';
|
||||
|
||||
if (!file_exists($file)) {
|
||||
$message = sprintf('Unable to find HEAD file ("%s")', $file);
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->error($message);
|
||||
}
|
||||
|
||||
if (true === $this->debug) {
|
||||
throw new RuntimeException($message);
|
||||
}
|
||||
}
|
||||
|
||||
$content = trim(file_get_contents($file));
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('HEAD file read: '.$content);
|
||||
}
|
||||
|
||||
if (preg_match('/^ref: (.+)$/', $content, $vars)) {
|
||||
return $this->getReferences()->get($vars[1]);
|
||||
} elseif (preg_match('/^[0-9a-f]{40}$/', $content)) {
|
||||
return $this->getCommit($content);
|
||||
}
|
||||
|
||||
$message = sprintf('Unexpected HEAD file content (file: %s). Content of file: %s', $file, $content);
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->error($message);
|
||||
}
|
||||
|
||||
if (true === $this->debug) {
|
||||
throw new RuntimeException($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isHeadDetached()
|
||||
{
|
||||
return !$this->isHeadAttached();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isHeadAttached()
|
||||
{
|
||||
return $this->getHead() instanceof Reference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the git repository.
|
||||
*
|
||||
* @return string A directory path
|
||||
*/
|
||||
public function getPath()
|
||||
{
|
||||
return $this->workingDir === null ? $this->gitDir : $this->workingDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the directory containing git files (git-dir).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGitDir()
|
||||
{
|
||||
return $this->gitDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the work-tree directory. This may be null if repository is
|
||||
* bare.
|
||||
*
|
||||
* @return string path to repository or null if repository is bare
|
||||
*/
|
||||
public function getWorkingDir()
|
||||
{
|
||||
return $this->workingDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instanciates a revision.
|
||||
*
|
||||
* @param string $name Name of the revision
|
||||
*
|
||||
* @return Revision
|
||||
*/
|
||||
public function getRevision($name)
|
||||
{
|
||||
return new Revision($this, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WorkingCopy
|
||||
*/
|
||||
public function getWorkingCopy()
|
||||
{
|
||||
return new WorkingCopy($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reference list associated to the repository.
|
||||
*
|
||||
* @return ReferenceBag
|
||||
*/
|
||||
public function getReferences()
|
||||
{
|
||||
if (null === $this->referenceBag) {
|
||||
$this->referenceBag = new ReferenceBag($this);
|
||||
}
|
||||
|
||||
return $this->referenceBag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instanciates a commit object or fetches one from the cache.
|
||||
*
|
||||
* @param string $hash A commit hash, with a length of 40
|
||||
*
|
||||
* @return Commit
|
||||
*/
|
||||
public function getCommit($hash)
|
||||
{
|
||||
if (!isset($this->objects[$hash])) {
|
||||
$this->objects[$hash] = new Commit($this, $hash);
|
||||
}
|
||||
|
||||
return $this->objects[$hash];
|
||||
}
|
||||
|
||||
/**
|
||||
* Instanciates a tree object or fetches one from the cache.
|
||||
*
|
||||
* @param string $hash A tree hash, with a length of 40
|
||||
*
|
||||
* @return Tree
|
||||
*/
|
||||
public function getTree($hash)
|
||||
{
|
||||
if (!isset($this->objects[$hash])) {
|
||||
$this->objects[$hash] = new Tree($this, $hash);
|
||||
}
|
||||
|
||||
return $this->objects[$hash];
|
||||
}
|
||||
|
||||
/**
|
||||
* Instanciates a blob object or fetches one from the cache.
|
||||
*
|
||||
* @param string $hash A blob hash, with a length of 40
|
||||
*
|
||||
* @return Blob
|
||||
*/
|
||||
public function getBlob($hash)
|
||||
{
|
||||
if (!isset($this->objects[$hash])) {
|
||||
$this->objects[$hash] = new Blob($this, $hash);
|
||||
}
|
||||
|
||||
return $this->objects[$hash];
|
||||
}
|
||||
|
||||
public function getBlame($revision, $file, $lineRange = null)
|
||||
{
|
||||
if (is_string($revision)) {
|
||||
$revision = $this->getRevision($revision);
|
||||
}
|
||||
|
||||
return new Blame($this, $revision, $file, $lineRange);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns log for a given set of revisions and paths.
|
||||
*
|
||||
* All those values can be null, meaning everything.
|
||||
*
|
||||
* @param array $revisions An array of revisions to show logs from. Can be
|
||||
* any text value type
|
||||
* @param array $paths Restrict log to modifications occurring on given
|
||||
* paths.
|
||||
* @param int $offset Start from a given offset in results.
|
||||
* @param int $limit Limit number of total results.
|
||||
*
|
||||
* @return Log
|
||||
*/
|
||||
public function getLog($revisions = null, $paths = null, $offset = null, $limit = null)
|
||||
{
|
||||
return new Log($this, $revisions, $paths, $offset, $limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Diff
|
||||
*/
|
||||
public function getDiff($revisions)
|
||||
{
|
||||
if (null !== $revisions && !$revisions instanceof RevisionList) {
|
||||
$revisions = new RevisionList($this, $revisions);
|
||||
}
|
||||
|
||||
$args = array_merge(array('-r', '-p', '-m', '-M', '--no-commit-id', '--full-index'), $revisions->getAsTextArray());
|
||||
|
||||
$diff = Diff::parse($this->run('diff', $args));
|
||||
$diff->setRepository($this);
|
||||
|
||||
return $diff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of repository, in kilobytes.
|
||||
*
|
||||
* @return int A sum, in kilobytes
|
||||
*
|
||||
* @throws RuntimeException An error occurred while computing size
|
||||
*/
|
||||
public function getSize()
|
||||
{
|
||||
$commandlineArguments = array('du', '-skc', $this->gitDir);
|
||||
$commandline = $this->normalizeCommandlineArguments($commandlineArguments);
|
||||
$process = new Process($commandline);
|
||||
$process->run();
|
||||
|
||||
if (!preg_match('/(\d+)\s+total$/', trim($process->getOutput()), $vars)) {
|
||||
$message = sprintf("Unable to parse process output\ncommand: %s\noutput: %s", $process->getCommandLine(), $process->getOutput());
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->error($message);
|
||||
}
|
||||
|
||||
if (true === $this->debug) {
|
||||
throw new RuntimeException('unable to parse repository size output');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return $vars[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a shell command on the repository, using PHP pipes.
|
||||
*
|
||||
* @param string $command The command to execute
|
||||
*/
|
||||
public function shell($command, array $env = array())
|
||||
{
|
||||
$argument = sprintf('%s \'%s\'', $command, $this->gitDir);
|
||||
|
||||
$prefix = '';
|
||||
foreach ($env as $name => $value) {
|
||||
$prefix .= sprintf('export %s=%s;', escapeshellarg($name), escapeshellarg($value));
|
||||
}
|
||||
|
||||
proc_open($prefix.'git shell -c '.escapeshellarg($argument), array(STDIN, STDOUT, STDERR), $pipes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hooks object.
|
||||
*
|
||||
* @return Hooks
|
||||
*/
|
||||
public function getHooks()
|
||||
{
|
||||
return new Hooks($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of repository from description file in git directory.
|
||||
*
|
||||
* @return string The description
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
$file = $this->gitDir.'/description';
|
||||
$exists = is_file($file);
|
||||
|
||||
if (null !== $this->logger && true === $this->debug) {
|
||||
if (false === $exists) {
|
||||
$this->logger->debug(sprintf('no description file in repository ("%s")', $file));
|
||||
} else {
|
||||
$this->logger->debug(sprintf('reading description file in repository ("%s")', $file));
|
||||
}
|
||||
}
|
||||
|
||||
if (false === $exists) {
|
||||
return static::DEFAULT_DESCRIPTION;
|
||||
}
|
||||
|
||||
return file_get_contents($this->gitDir.'/description');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if repository has a custom set description.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasDescription()
|
||||
{
|
||||
return static::DEFAULT_DESCRIPTION !== $this->getDescription();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the repository description (file description in git-directory).
|
||||
*
|
||||
* @return Repository the current repository
|
||||
*/
|
||||
public function setDescription($description)
|
||||
{
|
||||
$file = $this->gitDir.'/description';
|
||||
|
||||
if (null !== $this->logger && true === $this->debug) {
|
||||
$this->logger->debug(sprintf('change description file content to "%s" (file: %s)', $description, $file));
|
||||
}
|
||||
file_put_contents($file, $description);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This command is a facility command. You can run any command
|
||||
* directly on git repository.
|
||||
*
|
||||
* @param string $command Git command to run (checkout, branch, tag)
|
||||
* @param array $args Arguments of git command
|
||||
*
|
||||
* @return string Output of a successful process or null if execution failed and debug-mode is disabled.
|
||||
*
|
||||
* @throws RuntimeException Error while executing git command (debug-mode only)
|
||||
*/
|
||||
public function run($command, $args = array())
|
||||
{
|
||||
$process = $this->getProcess($command, $args);
|
||||
|
||||
if ($this->logger) {
|
||||
$this->logger->info(sprintf('run command: %s "%s" ', $command, implode(' ', $args)));
|
||||
$before = microtime(true);
|
||||
}
|
||||
|
||||
$process->run();
|
||||
|
||||
$output = $process->getOutput();
|
||||
|
||||
if ($this->logger && $this->debug) {
|
||||
$duration = microtime(true) - $before;
|
||||
$this->logger->debug(sprintf('last command (%s) duration: %sms', $command, sprintf('%.2f', $duration * 1000)));
|
||||
$this->logger->debug(sprintf('last command (%s) return code: %s', $command, $process->getExitCode()));
|
||||
$this->logger->debug(sprintf('last command (%s) output: %s', $command, $output));
|
||||
}
|
||||
|
||||
if (!$process->isSuccessful()) {
|
||||
$error = sprintf("error while running %s\n output: \"%s\"", $command, $process->getErrorOutput());
|
||||
|
||||
if ($this->logger) {
|
||||
$this->logger->error($error);
|
||||
}
|
||||
|
||||
if ($this->debug) {
|
||||
throw new ProcessException($process);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set repository logger.
|
||||
*
|
||||
* @param LoggerInterface $logger A logger
|
||||
*
|
||||
* @return Repository The current repository
|
||||
*/
|
||||
public function setLogger(LoggerInterface $logger)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns repository logger.
|
||||
*
|
||||
* @return LoggerInterface the logger or null
|
||||
*/
|
||||
public function getLogger()
|
||||
{
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones the current repository to a new directory and return instance of new repository.
|
||||
*
|
||||
* @param string $path path to the new repository in which current repository will be cloned
|
||||
* @param bool $bare flag indicating if repository is bare or has a working-copy
|
||||
*
|
||||
* @return Repository the newly created repository
|
||||
*/
|
||||
public function cloneTo($path, $bare = true, array $options = array())
|
||||
{
|
||||
return Admin::cloneTo($path, $this->gitDir, $bare, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal method is used to create a process object.
|
||||
*
|
||||
* Made private to be sure that process creation is handled through the run method.
|
||||
* run method ensures logging and debug.
|
||||
*
|
||||
* @see self::run
|
||||
*/
|
||||
private function getProcess($command, $args = array())
|
||||
{
|
||||
$base = array($this->command, '--git-dir', $this->gitDir);
|
||||
|
||||
if ($this->workingDir) {
|
||||
$base = array_merge($base, array('--work-tree', $this->workingDir));
|
||||
}
|
||||
|
||||
$base[] = $command;
|
||||
|
||||
$commandlineArguments = array_merge($base, $args);
|
||||
$commandline = $this->normalizeCommandlineArguments($commandlineArguments);
|
||||
|
||||
$process = new Process($commandline);
|
||||
$process->setEnv($this->environmentVariables);
|
||||
$process->setTimeout($this->processTimeout);
|
||||
$process->setIdleTimeout($this->processTimeout);
|
||||
|
||||
return $process;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal helper method is used to convert an array of commandline
|
||||
* arguments to an escaped commandline string for older versions of the
|
||||
* Symfony Process component.
|
||||
*
|
||||
* It acts as a backward compatible layer for Symfony Process < 3.3.
|
||||
*
|
||||
* @param array $arguments a list of command line arguments
|
||||
*
|
||||
* @return string|array a single escaped string (< 4.0) or a raw array of
|
||||
* the arguments passed in (4.0+)
|
||||
*
|
||||
* @see Process::escapeArgument()
|
||||
* @see ProcessUtils::escapeArgument()
|
||||
*/
|
||||
private function normalizeCommandlineArguments(array $arguments)
|
||||
{
|
||||
// From version 4.0 and onwards, the Process accepts an array of
|
||||
// arguments, and escaping is taken care of automatically.
|
||||
if (!class_exists('Symfony\Component\Process\ProcessBuilder')) {
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
// For version < 3.3, the Process only accepts a simple string
|
||||
// as commandline, and escaping has to happen manually.
|
||||
$commandline = implode(' ', array_map(
|
||||
'Symfony\Component\Process\ProcessUtils::escapeArgument',
|
||||
$arguments
|
||||
));
|
||||
|
||||
return $commandline;
|
||||
}
|
||||
}
|
68
vendor/gitonomy/gitlib/src/Gitonomy/Git/Revision.php
vendored
Normal file
68
vendor/gitonomy/gitlib/src/Gitonomy/Git/Revision.php
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git;
|
||||
|
||||
/**
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*/
|
||||
class Revision
|
||||
{
|
||||
/**
|
||||
* @var Repository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $revision;
|
||||
|
||||
public function __construct(Repository $repository, $revision)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
$this->revision = $revision;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Log
|
||||
*/
|
||||
public function getLog($paths = null, $offset = null, $limit = null)
|
||||
{
|
||||
return $this->repository->getLog($this, $paths, $offset, $limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last modification date of the reference.
|
||||
*
|
||||
* @return Commit
|
||||
*/
|
||||
public function getCommit()
|
||||
{
|
||||
return $this->getLog()->getSingleCommit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRevision()
|
||||
{
|
||||
return $this->revision;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Repository
|
||||
*/
|
||||
public function getRepository()
|
||||
{
|
||||
return $this->repository;
|
||||
}
|
||||
}
|
72
vendor/gitonomy/gitlib/src/Gitonomy/Git/RevisionList.php
vendored
Normal file
72
vendor/gitonomy/gitlib/src/Gitonomy/Git/RevisionList.php
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git;
|
||||
|
||||
/**
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*/
|
||||
class RevisionList implements \IteratorAggregate, \Countable
|
||||
{
|
||||
protected $revisions;
|
||||
|
||||
/**
|
||||
* Constructs a revision list from a variety of types.
|
||||
*
|
||||
* @param mixed $revisions can be a string, an array of strings or an array of Revision, Branch, Tag, Commit
|
||||
*/
|
||||
public function __construct(Repository $repository, $revisions)
|
||||
{
|
||||
if (is_string($revisions)) {
|
||||
$revisions = array($repository->getRevision($revisions));
|
||||
} elseif ($revisions instanceof Revision) {
|
||||
$revisions = array($revisions);
|
||||
} elseif (!is_array($revisions)) {
|
||||
throw new \InvalidArgumentException(sprintf('Expected a string, a Revision or an array, got a "%s".', is_object($revisions) ? get_class($revisions) : gettype($revisions)));
|
||||
}
|
||||
|
||||
if (count($revisions) == 0) {
|
||||
throw new \InvalidArgumentException(sprintf('Empty revision list not allowed'));
|
||||
}
|
||||
|
||||
foreach ($revisions as $i => $revision) {
|
||||
if (is_string($revision)) {
|
||||
$revisions[$i] = new Revision($repository, $revision);
|
||||
} elseif (!$revision instanceof Revision) {
|
||||
throw new \InvalidArgumentException(sprintf('Expected a "Revision", got a "%s".', is_object($revision) ? get_class($revision) : gettype($revision)));
|
||||
}
|
||||
}
|
||||
|
||||
$this->revisions = $revisions;
|
||||
}
|
||||
|
||||
public function getAll()
|
||||
{
|
||||
return $this->revisions;
|
||||
}
|
||||
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->revisions);
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
return count($this->revisions);
|
||||
}
|
||||
|
||||
public function getAsTextArray()
|
||||
{
|
||||
return array_map(function ($revision) {
|
||||
return $revision->getRevision();
|
||||
}, $this->revisions);
|
||||
}
|
||||
}
|
107
vendor/gitonomy/gitlib/src/Gitonomy/Git/Tree.php
vendored
Normal file
107
vendor/gitonomy/gitlib/src/Gitonomy/Git/Tree.php
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git;
|
||||
|
||||
use Gitonomy\Git\Exception\InvalidArgumentException;
|
||||
use Gitonomy\Git\Exception\UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*/
|
||||
class Tree
|
||||
{
|
||||
protected $repository;
|
||||
protected $hash;
|
||||
protected $isInitialized = false;
|
||||
protected $entries;
|
||||
|
||||
public function __construct(Repository $repository, $hash)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
$this->hash = $hash;
|
||||
}
|
||||
|
||||
public function getHash()
|
||||
{
|
||||
return $this->hash;
|
||||
}
|
||||
|
||||
protected function initialize()
|
||||
{
|
||||
if (true === $this->isInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
$output = $this->repository->run('cat-file', array('-p', $this->hash));
|
||||
$parser = new Parser\TreeParser();
|
||||
$parser->parse($output);
|
||||
|
||||
$this->entries = array();
|
||||
|
||||
foreach ($parser->entries as $entry) {
|
||||
list($mode, $type, $hash, $name) = $entry;
|
||||
if ($type == 'blob') {
|
||||
$this->entries[$name] = array($mode, $this->repository->getBlob($hash));
|
||||
} elseif ($type == 'tree') {
|
||||
$this->entries[$name] = array($mode, $this->repository->getTree($hash));
|
||||
} else {
|
||||
$this->entries[$name] = array($mode, new CommitReference($hash));
|
||||
}
|
||||
}
|
||||
|
||||
$this->isInitialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array An associative array name => $object
|
||||
*/
|
||||
public function getEntries()
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
return $this->entries;
|
||||
}
|
||||
|
||||
public function getEntry($name)
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
if (!isset($this->entries[$name])) {
|
||||
throw new InvalidArgumentException('No entry '.$name);
|
||||
}
|
||||
|
||||
return $this->entries[$name][1];
|
||||
}
|
||||
|
||||
public function resolvePath($path)
|
||||
{
|
||||
if ($path == '') {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$path = preg_replace('#^/#', '', $path);
|
||||
|
||||
$segments = explode('/', $path);
|
||||
$element = $this;
|
||||
foreach ($segments as $segment) {
|
||||
if ($element instanceof self) {
|
||||
$element = $element->getEntry($segment);
|
||||
} elseif ($entry instanceof Blob) {
|
||||
throw new InvalidArgumentException('Unresolvable path');
|
||||
} else {
|
||||
throw new UnexpectedValueException('Unknow type of element');
|
||||
}
|
||||
}
|
||||
|
||||
return $element;
|
||||
}
|
||||
}
|
56
vendor/gitonomy/gitlib/src/Gitonomy/Git/Util/StringHelper.php
vendored
Normal file
56
vendor/gitonomy/gitlib/src/Gitonomy/Git/Util/StringHelper.php
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git\Util;
|
||||
|
||||
/**
|
||||
* Helper class to support language particularity.
|
||||
*
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*/
|
||||
class StringHelper
|
||||
{
|
||||
private static $encoding = 'utf-8';
|
||||
|
||||
public static function getEncoding()
|
||||
{
|
||||
return self::$encoding;
|
||||
}
|
||||
|
||||
public static function setEncoding($encoding)
|
||||
{
|
||||
self::$encoding = $encoding;
|
||||
}
|
||||
|
||||
public static function strlen($string)
|
||||
{
|
||||
return function_exists('mb_strlen') ? mb_strlen($string, self::$encoding) : strlen($string);
|
||||
}
|
||||
|
||||
public static function substr($string, $start, $length = false)
|
||||
{
|
||||
if (false === $length) {
|
||||
$length = self::strlen($string);
|
||||
}
|
||||
|
||||
return function_exists('mb_substr') ? mb_substr($string, $start, $length, self::$encoding) : substr($string, $start, $length);
|
||||
}
|
||||
|
||||
public static function strpos($haystack, $needle, $offset = 0)
|
||||
{
|
||||
return function_exists('mb_strpos') ? mb_strpos($haystack, $needle, $offset, self::$encoding) : strpos($haystack, $needle, $offset);
|
||||
}
|
||||
|
||||
public static function strrpos($haystack, $needle, $offset = 0)
|
||||
{
|
||||
return function_exists('mb_strrpos') ? mb_strrpos($haystack, $needle, $offset, self::$encoding) : strrpos($haystack, $needle, $offset);
|
||||
}
|
||||
}
|
96
vendor/gitonomy/gitlib/src/Gitonomy/Git/WorkingCopy.php
vendored
Normal file
96
vendor/gitonomy/gitlib/src/Gitonomy/Git/WorkingCopy.php
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Gitonomy.
|
||||
*
|
||||
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
* (c) Julien DIDIER <genzo.wm@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
namespace Gitonomy\Git;
|
||||
|
||||
use Gitonomy\Git\Diff\Diff;
|
||||
use Gitonomy\Git\Exception\InvalidArgumentException;
|
||||
use Gitonomy\Git\Exception\LogicException;
|
||||
|
||||
/**
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*/
|
||||
class WorkingCopy
|
||||
{
|
||||
/**
|
||||
* @var Repository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
public function __construct(Repository $repository)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
|
||||
if ($this->repository->isBare()) {
|
||||
throw new LogicException('Can\'t create a working copy on a bare repository');
|
||||
}
|
||||
}
|
||||
|
||||
public function getStatus()
|
||||
{
|
||||
return WorkingStatus::parseOutput();
|
||||
}
|
||||
|
||||
public function getUntrackedFiles()
|
||||
{
|
||||
$lines = explode("\0", $this->run('status', array('--porcelain', '--untracked-files=all', '-z')));
|
||||
$lines = array_filter($lines, function ($l) { return substr($l, 0, 3) === '?? '; });
|
||||
$lines = array_map(function ($l) { return substr($l, 3); }, $lines);
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
public function getDiffPending()
|
||||
{
|
||||
$diff = Diff::parse($this->run('diff', array('-r', '-p', '-m', '-M', '--full-index')));
|
||||
$diff->setRepository($this->repository);
|
||||
|
||||
return $diff;
|
||||
}
|
||||
|
||||
public function getDiffStaged()
|
||||
{
|
||||
$diff = Diff::parse($this->run('diff', array('-r', '-p', '-m', '-M', '--full-index', '--staged')));
|
||||
$diff->setRepository($this->repository);
|
||||
|
||||
return $diff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WorkingCopy
|
||||
*/
|
||||
public function checkout($revision, $branch = null)
|
||||
{
|
||||
$args = array();
|
||||
if ($revision instanceof Commit) {
|
||||
$args[] = $revision->getHash();
|
||||
} elseif ($revision instanceof Reference) {
|
||||
$args[] = $revision->getFullname();
|
||||
} elseif (is_string($revision)) {
|
||||
$args[] = $revision;
|
||||
} else {
|
||||
throw new InvalidArgumentException(sprintf('Unknown type "%s"', gettype($revision)));
|
||||
}
|
||||
|
||||
if (null !== $branch) {
|
||||
$args = array_merge($args, array('-b', $branch));
|
||||
}
|
||||
|
||||
$this->run('checkout', $args);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function run($command, array $args = array())
|
||||
{
|
||||
return $this->repository->run($command, $args);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user