Skip to content
This repository has been archived by the owner on Jan 29, 2019. It is now read-only.

Commit

Permalink
optimized git how cloning and checking out is handled
Browse files Browse the repository at this point in the history
  • Loading branch information
fieg committed Jul 31, 2013
1 parent 56f1a5a commit 0dd2e0d
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 92 deletions.
4 changes: 2 additions & 2 deletions src/Webcreate/Vcs/Common/AbstractClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ abstract class AbstractClient
/**
* Adapter for VCS backend
*
* @var Webcreate\Vcs\Common\Adapter\AdapterInterface
* @var \Webcreate\Vcs\Common\Adapter\AdapterInterface
*/
protected $adapter;

/**
* Reference to current branch or tag
*
* @var Webcreate\Vcs\Common\Reference
* @var \Webcreate\Vcs\Common\Reference
*/
protected $head;

Expand Down
6 changes: 3 additions & 3 deletions src/Webcreate/Vcs/Common/Adapter/CliAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,21 @@ class CliAdapter implements AdapterInterface
/**
* Commandline interface utility
*
* @var Webcreate\Util\Cli
* @var \Webcreate\Util\Cli
*/
protected $cli;

/**
* VCS client
*
* @var Webcreate\Vcs\Common\AbstractClient
* @var \Webcreate\Vcs\Common\AbstractClient
*/
protected $client;

/**
* Output parser
*
* @var Webcreate\Vcs\Common\Parser\ParserInterface
* @var \Webcreate\Vcs\Common\Parser\ParserInterface
*/
protected $parser;

Expand Down
4 changes: 3 additions & 1 deletion src/Webcreate/Vcs/Common/Pointer.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public function getType()
public function setType($type)
{
$this->type = $type;

return $this;
}

Expand All @@ -74,6 +75,7 @@ public function getName()
public function setName($name)
{
$this->name = $name;

return $this;
}

Expand All @@ -84,4 +86,4 @@ public function __toString()
{
return $this->getName();
}
}
}
151 changes: 118 additions & 33 deletions src/Webcreate/Vcs/Git.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,46 @@ class Git extends AbstractGit implements VcsInterface
{
const PRETTY_FORMAT = '<logentry><commit>%H</commit>%n<date>%aD</date>%n<author>%an</author>%n<msg><![CDATA[%B]]></msg></logentry>';

/**
* @var array remote tags cache
*/
private $tags;

/**
* @var array remote branches cache
*/
private $branches;

/** @var bool ensures that we only fetch once */
private $isFetched = false;

public function cloneRepository($dest = null)
{
$temporary = $this->isTemporary;

$realdest = (true === is_null($dest) ? $this->cwd : $dest);
$branch = $this->getHead()->getName();

$result = $this->execute('clone', array('-b' => (string) $branch, $this->url, $realdest));

$this->setCwd($realdest);

// the setCwd resets the isTemporary flag, this keeps it correct
$this->isTemporary = $temporary;

// a clone implies a fetch
$this->isFetched = true;
}

/**
* Perform a clone operation
*
* @param string|null $dest
*/
public function checkout($dest = null)
{
$temporary = $this->isTemporary;

if (true === is_null($dest)) {
$realdest = $this->cwd;
} else {
Expand All @@ -45,13 +78,15 @@ public function checkout($dest = null)
$head = $this->getHead();
$branch = $head->getName();

$result = $this->execute('clone', array('-b' => (string) $branch, $this->url, $realdest));
if (false === $this->hasClone || false === is_null($dest)) {
$this->cloneRepository($dest);
} else {
$result = $this->execute('checkout', array((string) $branch));
}

$this->setCwd($realdest);
$this->hasCheckout = true;

if (true === is_null($dest)) {
$this->isTemporary = true;
}
$result = $this->pull();
}

/**
Expand Down Expand Up @@ -130,11 +165,23 @@ public function export($path, $dest)
$head = $this->getHead();
$branch = $head->getName();

$result = $this->execute('clone', array('-b' => (string) $branch, '--depth=1', $this->url, $dest));
if (!$this->hasCheckout) {
// if ($this->isTemporary) {
// // create a shallow checkout
// $result = $this->execute('clone', array('-b' => (string) $branch, '--depth=1', $this->url, $dest));
// } else {
// $this->checkout();
// }

$this->checkout();
}

// we already have cloned the repository, use that instead
$result = $this->execute('clone', array('-b' => (string) $branch, '--depth=1', 'file://' . $this->cwd, $dest), getcwd());

$result = $this->adapter->execute('submodule', array('update', '--init' => true, '--recursive' => true), $dest);

$this->isTemporary = false;
//$this->isTemporary = false;

$filesystem = new Filesystem();
$filesystem->remove($dest . '/.git');
Expand Down Expand Up @@ -184,9 +231,7 @@ public function ls($path)
*/
public function log($path, $revision = null, $limit = null)
{
if (!$this->hasCheckout) {
$this->checkout();
}
$this->fetch();

if ('' === $path) {
$path = '.';
Expand All @@ -206,9 +251,7 @@ public function log($path, $revision = null, $limit = null)
*/
public function changelog($revision1, $revision2)
{
if (!$this->hasCheckout) {
$this->checkout();
}
$this->fetch();

return $this->execute('log', array(
'--pretty=' => self::PRETTY_FORMAT,
Expand Down Expand Up @@ -245,6 +288,8 @@ public function cat($path)
public function diff($oldPath, $newPath, $oldRevision = 'HEAD',
$newRevision = 'HEAD', $summary = true)
{
$this->fetch();

$arguments = array(
'--name-status' => $summary,
$oldRevision,
Expand All @@ -267,17 +312,21 @@ public function diff($oldPath, $newPath, $oldRevision = 'HEAD',
*/
public function branches()
{
$retval = $this->execute('ls-remote', array('--heads' => true, $this->getUrl()));
if (null === $this->branches) {
$retval = $this->execute('ls-remote', array('--heads' => true, $this->getUrl()));

$list = explode("\n", rtrim($retval));

$list = explode("\n", rtrim($retval));
$branches = array();
foreach ($list as $line) {
list ($hash, $ref) = explode("\t", $line);
$branches[] = new Reference(basename($ref), Reference::BRANCH, $hash);
}

$branches = array();
foreach ($list as $line) {
list ($hash, $ref) = explode("\t", $line);
$branches[] = new Reference(basename($ref), Reference::BRANCH, $hash);
$this->branches = $branches;
}

return $branches;
return $this->branches;
}

/**
Expand All @@ -286,29 +335,33 @@ public function branches()
*/
public function tags()
{
$retval = $this->execute('ls-remote', array('--tags' => true, $this->getUrl()));
if (null === $this->tags) {
$retval = $this->execute('ls-remote', array('--tags' => true, $this->getUrl()));

if ('' === $retval) {
return array();
}
if ('' === $retval) {
return $this->tags = array();
}

$list = explode("\n", rtrim($retval));

$list = explode("\n", rtrim($retval));
$tags = array();
foreach ($list as $line) {
list ($hash, $ref) = explode("\t", $line);
$tags[] = new Reference(basename($ref), Reference::TAG, $hash);
}

$tags = array();
foreach ($list as $line) {
list ($hash, $ref) = explode("\t", $line);
$tags[] = new Reference(basename($ref), Reference::TAG, $hash);
$this->tags = $tags;
}

return $tags;
return $this->tags;
}

/**
* Git push
*
* @param string $remote
* @throws \RuntimeException
* @return string
* @return null|string
*/
public function push($remote = 'origin')
{
Expand All @@ -322,6 +375,8 @@ public function push($remote = 'origin')
// ignore output on stderr: it contains
// progress information, for example about hooks
}

return null;
}

/**
Expand All @@ -341,11 +396,41 @@ public function pull($remote = 'origin')
}

/**
* (non-PHPdoc)
* @see Webcreate\Vcs.VcsInterface::revisionCompare()
* Git fetch
*
* @param string $remote
* @throws \RuntimeException
* @return bool
*/
public function fetch($remote = null)
{
if ($this->isFetched) {
return false;
}

if (!$this->hasClone) {
$this->cloneRepository();
}

$args = array();
if (null !== $remote) {
$args[] = $remote;
}

$this->execute('fetch', $args);

$this->isFetched = true;

return true;
}

/**
* {@inheritdoc}
*/
public function revisionCompare($revision1, $revision2)
{
$this->fetch();

if ($revision1 == $revision2) {
return 0;
} else {
Expand Down
32 changes: 27 additions & 5 deletions src/Webcreate/Vcs/Git/AbstractGit.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ abstract class AbstractGit extends AbstractClient
*/
protected $hasCheckout = false;

/**
* @var bool
*/
protected $hasClone = false;

/**
* @var bool
*/
Expand All @@ -56,7 +61,9 @@ abstract class AbstractGit extends AbstractClient
public function __construct($url, AdapterInterface $adapter = null, $cwd = null)
{
if (null === $adapter) {
$adapter = new CliAdapter('/usr/bin/git', new Cli(), new CliParser());
$cli = new Cli();
$cli->setTimeout(600);
$adapter = new CliAdapter('/usr/bin/git', $cli, new CliParser());
}

parent::__construct($url, $adapter);
Expand All @@ -74,6 +81,7 @@ public function __construct($url, AdapterInterface $adapter = null, $cwd = null)
public function setCwd($cwd)
{
$this->hasCheckout = false;
$this->hasClone = false;
$this->isTemporary = false;

if (is_null($cwd)) {
Expand All @@ -82,7 +90,7 @@ public function setCwd($cwd)
} else {
if (is_dir($cwd)) {
if (is_dir($cwd . '/.git')) {
$this->hasCheckout = true;
$this->hasClone = true;
}
}
$this->cwd = $cwd;
Expand All @@ -91,16 +99,30 @@ public function setCwd($cwd)
return $this;
}

public function setHead($reference)
{
parent::setHead($reference);

// branch might have changed, so if we had a checkout it could be out of sync
// setting this to false will get it back in sync
$this->hasCheckout = false;
}

/**
* Execute GIT command
*
* @param string $command
* @param array $arguments
* @param array $arguments
* @param string|null $cwd
* @return string
*/
protected function execute($command, array $arguments = array())
protected function execute($command, array $arguments = array(), $cwd = null)
{
return $this->adapter->execute($command, $arguments, $this->cwd);
if (null === $cwd) {
$cwd = $this->cwd;
}

return $this->adapter->execute($command, $arguments, $cwd);
}

/**
Expand Down
Loading

0 comments on commit 0dd2e0d

Please sign in to comment.