Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #55 and code refactoring #58

Merged
merged 4 commits into from
Dec 11, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Model/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* Repository containing files.
*
* Extends stdClass so that properties can be added by processors at will.
* TODO should not extend stdClass anymore! It has been replaced by the metadata property...
*
* @author Matthieu Napoli <matthieu@mnapoli.fr>
*/
Expand Down
86 changes: 86 additions & 0 deletions src/Step/Template/FetchRemoteTemplate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

namespace Couscous\Step\Template;

use Couscous\CommandRunner;
use Couscous\Model\Repository;
use Couscous\Step\StepInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Filesystem\Filesystem;

/**
* Fetch a remote template.
*
* @author Matthieu Napoli <matthieu@mnapoli.fr>
*/
class FetchRemoteTemplate implements StepInterface
{
/**
* @var Filesystem
*/
private $filesystem;

/**
* @var CommandRunner
*/
private $commandRunner;

/**
* Temporarily save the template directory if we are in preview
* to avoid cloning the repository every time.
*
* In theory we shouldn't store state in this object because it's a service
* but we need extensive change to avoid that.
*
* @var string
*/
private $templateDirectory;

public function __construct(Filesystem $filesystem, CommandRunner $commandRunner)
{
$this->filesystem = $filesystem;
$this->commandRunner = $commandRunner;
}

public function __invoke(Repository $repository, OutputInterface $output)
{
// In preview we avoid cloning the repository every time
if ($repository->regenerate && $this->templateDirectory) {
$repository->metadata['template.directory'] = $this->templateDirectory;

return;
}

$templateUrl = $repository->metadata['template.url'];

if ($templateUrl === null) {
return;
}

$directory = $this->fetchGitTemplate($templateUrl, $output);

$this->templateDirectory = $directory;
$repository->metadata['template.directory'] = $directory;
}

private function fetchGitTemplate($gitUrl, OutputInterface $output)
{
$output->writeln("Fetching template from <info>$gitUrl</info>");

$directory = $this->createTempDirectory('couscous_template_');

$this->commandRunner->run("git clone $gitUrl $directory");

return $directory;
}

private function createTempDirectory($prefix)
{
$tempFile = tempnam(sys_get_temp_dir(), $prefix);
// Turn the temp file into a temp directory
$this->filesystem->remove($tempFile);
$this->filesystem->mkdir($tempFile);

return $tempFile;
}
}
95 changes: 0 additions & 95 deletions src/Step/Template/InitTemplate.php

This file was deleted.

2 changes: 1 addition & 1 deletion src/Step/Template/UseDefaultTemplate.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ private function hasCustomTemplateDirectory(Repository $repository)

private function hasTemplateDirectory(Repository $repository)
{
$templateDirectory = $repository->sourceDirectory . '/' . InitTemplate::DEFAULT_TEMPLATE_DIRECTORY;
$templateDirectory = $repository->sourceDirectory . '/' . ValidateTemplateDirectory::DEFAULT_TEMPLATE_DIRECTORY;

return $this->filesystem->exists($templateDirectory);
}
Expand Down
57 changes: 57 additions & 0 deletions src/Step/Template/ValidateTemplateDirectory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace Couscous\Step\Template;

use Couscous\Model\Repository;
use Couscous\Step\StepInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Filesystem\Filesystem;

/**
* Initializes the template directory.
*
* @author Matthieu Napoli <matthieu@mnapoli.fr>
*/
class ValidateTemplateDirectory implements StepInterface
{
const DEFAULT_TEMPLATE_DIRECTORY = 'website';

/**
* @var Filesystem
*/
private $filesystem;

public function __construct(Filesystem $filesystem)
{
$this->filesystem = $filesystem;
}

public function __invoke(Repository $repository, OutputInterface $output)
{
$directory = $repository->metadata['template.directory'];

if ($directory === null) {
$directory = $repository->sourceDirectory . '/' . self::DEFAULT_TEMPLATE_DIRECTORY;
}

if (! $this->filesystem->isAbsolutePath($directory)) {
$directory = $repository->sourceDirectory . '/' . $directory;
}

$this->assertDirectoryExist($directory);

$repository->watchlist->watchDirectory($directory);

$repository->metadata['template.directory'] = $directory;
}

private function assertDirectoryExist($directory)
{
if (! $this->filesystem->exists($directory)) {
throw new \RuntimeException(sprintf(
"The template directory '%s' doesn't exist",
$directory
));
}
}
}
3 changes: 2 additions & 1 deletion src/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
'Couscous\Step\Config\OverrideBaseUrlForPreview',
'Couscous\Step\Scripts\ExecuteBeforeScripts',
'Couscous\Step\Template\UseDefaultTemplate',
'Couscous\Step\Template\InitTemplate',
'Couscous\Step\Template\FetchRemoteTemplate',
'Couscous\Step\Template\ValidateTemplateDirectory',
'Couscous\Step\Assets\RunBowerInstall',
'Couscous\Step\Template\LoadAssets',
'Couscous\Step\Markdown\LoadMarkdownFiles',
Expand Down
83 changes: 83 additions & 0 deletions tests/UnitTest/Step/Template/FetchRemoteTemplateTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

namespace Couscous\Tests\UnitTest\Step\Template;

use Couscous\Step\Template\FetchRemoteTemplate;
use Couscous\Tests\UnitTest\Mock\MockRepository;
use Symfony\Component\Console\Output\NullOutput;

/**
* @covers \Couscous\Step\Template\FetchRemoteTemplate
*/
class FetchRemoteTemplateTest extends \PHPUnit_Framework_TestCase
{
/**
* @test
*/
public function it_should_skip_if_no_template_url()
{
$filesystem = $this->getMock('Symfony\Component\Filesystem\Filesystem');
$commandRunner = $this->getMock('Couscous\CommandRunner');

$step = new FetchRemoteTemplate($filesystem, $commandRunner);

$repository = new MockRepository();

$commandRunner->expects($this->never())
->method('run');

$step->__invoke($repository, new NullOutput());

$this->assertNull($repository->metadata['template.directory']);
}

/**
* @test
*/
public function it_should_clone_and_set_the_template_directory()
{
$filesystem = $this->getMock('Symfony\Component\Filesystem\Filesystem');
$commandRunner = $this->getMock('Couscous\CommandRunner');

$step = new FetchRemoteTemplate($filesystem, $commandRunner);

$repository = new MockRepository();
$repository->metadata['template.url'] = 'git://foo';

$commandRunner->expects($this->once())
->method('run')
->with($this->matches('git clone git://foo %s'));

$step->__invoke($repository, new NullOutput());

$this->assertNotNull($repository->metadata['template.directory']);
}

/**
* @test
*/
public function it_should_not_clone_twice_if_regenerating()
{
$filesystem = $this->getMock('Symfony\Component\Filesystem\Filesystem');
$commandRunner = $this->getMock('Couscous\CommandRunner');

$step = new FetchRemoteTemplate($filesystem, $commandRunner);

$commandRunner->expects($this->once())
->method('run')
->with($this->matches('git clone git://foo %s'));

// Calling once
$repository = new MockRepository();
$repository->metadata['template.url'] = 'git://foo';
$step->__invoke($repository, new NullOutput());
$this->assertNotNull($repository->metadata['template.directory']);

// Calling twice
$repository = new MockRepository();
$repository->regenerate = true;
$repository->metadata['template.url'] = 'git://foo';
$step->__invoke($repository, new NullOutput());
$this->assertNotNull($repository->metadata['template.directory']);
}
}
Loading