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

Commit 0dd2e0d

Browse files
author
fieg
committed
optimized git how cloning and checking out is handled
1 parent 56f1a5a commit 0dd2e0d

File tree

6 files changed

+201
-92
lines changed

6 files changed

+201
-92
lines changed

src/Webcreate/Vcs/Common/AbstractClient.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ abstract class AbstractClient
2626
/**
2727
* Adapter for VCS backend
2828
*
29-
* @var Webcreate\Vcs\Common\Adapter\AdapterInterface
29+
* @var \Webcreate\Vcs\Common\Adapter\AdapterInterface
3030
*/
3131
protected $adapter;
3232

3333
/**
3434
* Reference to current branch or tag
3535
*
36-
* @var Webcreate\Vcs\Common\Reference
36+
* @var \Webcreate\Vcs\Common\Reference
3737
*/
3838
protected $head;
3939

src/Webcreate/Vcs/Common/Adapter/CliAdapter.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,21 @@ class CliAdapter implements AdapterInterface
3030
/**
3131
* Commandline interface utility
3232
*
33-
* @var Webcreate\Util\Cli
33+
* @var \Webcreate\Util\Cli
3434
*/
3535
protected $cli;
3636

3737
/**
3838
* VCS client
3939
*
40-
* @var Webcreate\Vcs\Common\AbstractClient
40+
* @var \Webcreate\Vcs\Common\AbstractClient
4141
*/
4242
protected $client;
4343

4444
/**
4545
* Output parser
4646
*
47-
* @var Webcreate\Vcs\Common\Parser\ParserInterface
47+
* @var \Webcreate\Vcs\Common\Parser\ParserInterface
4848
*/
4949
protected $parser;
5050

src/Webcreate/Vcs/Common/Pointer.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public function getType()
5252
public function setType($type)
5353
{
5454
$this->type = $type;
55+
5556
return $this;
5657
}
5758

@@ -74,6 +75,7 @@ public function getName()
7475
public function setName($name)
7576
{
7677
$this->name = $name;
78+
7779
return $this;
7880
}
7981

@@ -84,4 +86,4 @@ public function __toString()
8486
{
8587
return $this->getName();
8688
}
87-
}
89+
}

src/Webcreate/Vcs/Git.php

Lines changed: 118 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,46 @@ class Git extends AbstractGit implements VcsInterface
2929
{
3030
const PRETTY_FORMAT = '<logentry><commit>%H</commit>%n<date>%aD</date>%n<author>%an</author>%n<msg><![CDATA[%B]]></msg></logentry>';
3131

32+
/**
33+
* @var array remote tags cache
34+
*/
35+
private $tags;
36+
37+
/**
38+
* @var array remote branches cache
39+
*/
40+
private $branches;
41+
42+
/** @var bool ensures that we only fetch once */
43+
private $isFetched = false;
44+
45+
public function cloneRepository($dest = null)
46+
{
47+
$temporary = $this->isTemporary;
48+
49+
$realdest = (true === is_null($dest) ? $this->cwd : $dest);
50+
$branch = $this->getHead()->getName();
51+
52+
$result = $this->execute('clone', array('-b' => (string) $branch, $this->url, $realdest));
53+
54+
$this->setCwd($realdest);
55+
56+
// the setCwd resets the isTemporary flag, this keeps it correct
57+
$this->isTemporary = $temporary;
58+
59+
// a clone implies a fetch
60+
$this->isFetched = true;
61+
}
62+
3263
/**
3364
* Perform a clone operation
3465
*
3566
* @param string|null $dest
3667
*/
3768
public function checkout($dest = null)
3869
{
70+
$temporary = $this->isTemporary;
71+
3972
if (true === is_null($dest)) {
4073
$realdest = $this->cwd;
4174
} else {
@@ -45,13 +78,15 @@ public function checkout($dest = null)
4578
$head = $this->getHead();
4679
$branch = $head->getName();
4780

48-
$result = $this->execute('clone', array('-b' => (string) $branch, $this->url, $realdest));
81+
if (false === $this->hasClone || false === is_null($dest)) {
82+
$this->cloneRepository($dest);
83+
} else {
84+
$result = $this->execute('checkout', array((string) $branch));
85+
}
4986

50-
$this->setCwd($realdest);
87+
$this->hasCheckout = true;
5188

52-
if (true === is_null($dest)) {
53-
$this->isTemporary = true;
54-
}
89+
$result = $this->pull();
5590
}
5691

5792
/**
@@ -130,11 +165,23 @@ public function export($path, $dest)
130165
$head = $this->getHead();
131166
$branch = $head->getName();
132167

133-
$result = $this->execute('clone', array('-b' => (string) $branch, '--depth=1', $this->url, $dest));
168+
if (!$this->hasCheckout) {
169+
// if ($this->isTemporary) {
170+
// // create a shallow checkout
171+
// $result = $this->execute('clone', array('-b' => (string) $branch, '--depth=1', $this->url, $dest));
172+
// } else {
173+
// $this->checkout();
174+
// }
175+
176+
$this->checkout();
177+
}
178+
179+
// we already have cloned the repository, use that instead
180+
$result = $this->execute('clone', array('-b' => (string) $branch, '--depth=1', 'file://' . $this->cwd, $dest), getcwd());
134181

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

137-
$this->isTemporary = false;
184+
//$this->isTemporary = false;
138185

139186
$filesystem = new Filesystem();
140187
$filesystem->remove($dest . '/.git');
@@ -184,9 +231,7 @@ public function ls($path)
184231
*/
185232
public function log($path, $revision = null, $limit = null)
186233
{
187-
if (!$this->hasCheckout) {
188-
$this->checkout();
189-
}
234+
$this->fetch();
190235

191236
if ('' === $path) {
192237
$path = '.';
@@ -206,9 +251,7 @@ public function log($path, $revision = null, $limit = null)
206251
*/
207252
public function changelog($revision1, $revision2)
208253
{
209-
if (!$this->hasCheckout) {
210-
$this->checkout();
211-
}
254+
$this->fetch();
212255

213256
return $this->execute('log', array(
214257
'--pretty=' => self::PRETTY_FORMAT,
@@ -245,6 +288,8 @@ public function cat($path)
245288
public function diff($oldPath, $newPath, $oldRevision = 'HEAD',
246289
$newRevision = 'HEAD', $summary = true)
247290
{
291+
$this->fetch();
292+
248293
$arguments = array(
249294
'--name-status' => $summary,
250295
$oldRevision,
@@ -267,17 +312,21 @@ public function diff($oldPath, $newPath, $oldRevision = 'HEAD',
267312
*/
268313
public function branches()
269314
{
270-
$retval = $this->execute('ls-remote', array('--heads' => true, $this->getUrl()));
315+
if (null === $this->branches) {
316+
$retval = $this->execute('ls-remote', array('--heads' => true, $this->getUrl()));
317+
318+
$list = explode("\n", rtrim($retval));
271319

272-
$list = explode("\n", rtrim($retval));
320+
$branches = array();
321+
foreach ($list as $line) {
322+
list ($hash, $ref) = explode("\t", $line);
323+
$branches[] = new Reference(basename($ref), Reference::BRANCH, $hash);
324+
}
273325

274-
$branches = array();
275-
foreach ($list as $line) {
276-
list ($hash, $ref) = explode("\t", $line);
277-
$branches[] = new Reference(basename($ref), Reference::BRANCH, $hash);
326+
$this->branches = $branches;
278327
}
279328

280-
return $branches;
329+
return $this->branches;
281330
}
282331

283332
/**
@@ -286,29 +335,33 @@ public function branches()
286335
*/
287336
public function tags()
288337
{
289-
$retval = $this->execute('ls-remote', array('--tags' => true, $this->getUrl()));
338+
if (null === $this->tags) {
339+
$retval = $this->execute('ls-remote', array('--tags' => true, $this->getUrl()));
290340

291-
if ('' === $retval) {
292-
return array();
293-
}
341+
if ('' === $retval) {
342+
return $this->tags = array();
343+
}
344+
345+
$list = explode("\n", rtrim($retval));
294346

295-
$list = explode("\n", rtrim($retval));
347+
$tags = array();
348+
foreach ($list as $line) {
349+
list ($hash, $ref) = explode("\t", $line);
350+
$tags[] = new Reference(basename($ref), Reference::TAG, $hash);
351+
}
296352

297-
$tags = array();
298-
foreach ($list as $line) {
299-
list ($hash, $ref) = explode("\t", $line);
300-
$tags[] = new Reference(basename($ref), Reference::TAG, $hash);
353+
$this->tags = $tags;
301354
}
302355

303-
return $tags;
356+
return $this->tags;
304357
}
305358

306359
/**
307360
* Git push
308361
*
309362
* @param string $remote
310363
* @throws \RuntimeException
311-
* @return string
364+
* @return null|string
312365
*/
313366
public function push($remote = 'origin')
314367
{
@@ -322,6 +375,8 @@ public function push($remote = 'origin')
322375
// ignore output on stderr: it contains
323376
// progress information, for example about hooks
324377
}
378+
379+
return null;
325380
}
326381

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

343398
/**
344-
* (non-PHPdoc)
345-
* @see Webcreate\Vcs.VcsInterface::revisionCompare()
399+
* Git fetch
400+
*
401+
* @param string $remote
402+
* @throws \RuntimeException
403+
* @return bool
404+
*/
405+
public function fetch($remote = null)
406+
{
407+
if ($this->isFetched) {
408+
return false;
409+
}
410+
411+
if (!$this->hasClone) {
412+
$this->cloneRepository();
413+
}
414+
415+
$args = array();
416+
if (null !== $remote) {
417+
$args[] = $remote;
418+
}
419+
420+
$this->execute('fetch', $args);
421+
422+
$this->isFetched = true;
423+
424+
return true;
425+
}
426+
427+
/**
428+
* {@inheritdoc}
346429
*/
347430
public function revisionCompare($revision1, $revision2)
348431
{
432+
$this->fetch();
433+
349434
if ($revision1 == $revision2) {
350435
return 0;
351436
} else {

src/Webcreate/Vcs/Git/AbstractGit.php

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ abstract class AbstractGit extends AbstractClient
4141
*/
4242
protected $hasCheckout = false;
4343

44+
/**
45+
* @var bool
46+
*/
47+
protected $hasClone = false;
48+
4449
/**
4550
* @var bool
4651
*/
@@ -56,7 +61,9 @@ abstract class AbstractGit extends AbstractClient
5661
public function __construct($url, AdapterInterface $adapter = null, $cwd = null)
5762
{
5863
if (null === $adapter) {
59-
$adapter = new CliAdapter('/usr/bin/git', new Cli(), new CliParser());
64+
$cli = new Cli();
65+
$cli->setTimeout(600);
66+
$adapter = new CliAdapter('/usr/bin/git', $cli, new CliParser());
6067
}
6168

6269
parent::__construct($url, $adapter);
@@ -74,6 +81,7 @@ public function __construct($url, AdapterInterface $adapter = null, $cwd = null)
7481
public function setCwd($cwd)
7582
{
7683
$this->hasCheckout = false;
84+
$this->hasClone = false;
7785
$this->isTemporary = false;
7886

7987
if (is_null($cwd)) {
@@ -82,7 +90,7 @@ public function setCwd($cwd)
8290
} else {
8391
if (is_dir($cwd)) {
8492
if (is_dir($cwd . '/.git')) {
85-
$this->hasCheckout = true;
93+
$this->hasClone = true;
8694
}
8795
}
8896
$this->cwd = $cwd;
@@ -91,16 +99,30 @@ public function setCwd($cwd)
9199
return $this;
92100
}
93101

102+
public function setHead($reference)
103+
{
104+
parent::setHead($reference);
105+
106+
// branch might have changed, so if we had a checkout it could be out of sync
107+
// setting this to false will get it back in sync
108+
$this->hasCheckout = false;
109+
}
110+
94111
/**
95112
* Execute GIT command
96113
*
97114
* @param string $command
98-
* @param array $arguments
115+
* @param array $arguments
116+
* @param string|null $cwd
99117
* @return string
100118
*/
101-
protected function execute($command, array $arguments = array())
119+
protected function execute($command, array $arguments = array(), $cwd = null)
102120
{
103-
return $this->adapter->execute($command, $arguments, $this->cwd);
121+
if (null === $cwd) {
122+
$cwd = $this->cwd;
123+
}
124+
125+
return $this->adapter->execute($command, $arguments, $cwd);
104126
}
105127

106128
/**

0 commit comments

Comments
 (0)