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

Fetaure/skip asset update 2 #289

Merged
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
57 changes: 57 additions & 0 deletions Repository/Vcs/GitDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
namespace Fxp\Composer\AssetPlugin\Repository\Vcs;

use Composer\Cache;
use Composer\IO\IOInterface;
use Composer\Repository\Vcs\GitDriver as BaseGitDriver;
use Composer\Util\Filesystem;
use Composer\Util\Git as GitUtil;

/**
* Git vcs driver.
Expand All @@ -35,4 +38,58 @@ public function getComposerInformation($identifier)

return ProcessUtil::getComposerInformation($this->cache, $this->infoCache, $this->repoConfig['asset-type'], $this->process, $identifier, $resource, sprintf('git show %s', $resource), sprintf('git log -1 --format=%%at %s', escapeshellarg($identifier)), $this->repoDir, '@');
}

/**
* {@inheritDoc}
*/
public function initialize()
{
/* @var AssetRepositoryManager $arm */
$arm = $this->repoConfig['asset-repository-manager'];

$skipSync = false;
if (null !== ($skip = $arm->getConfig()->get('git-skip-update'))) {
$localUrl = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/';
// check if local copy exists and if it is a git repository and that modification time is within threshold
if (is_dir($localUrl) && is_file($localUrl.'/config') && filemtime($localUrl) > strtotime('-'.$skip)) {
$skipSync = true;
$this->io->write('(<comment>skip update</comment>) ', false, IOInterface::VERBOSE);
}
}

// copied from parent::initialize()
if (Filesystem::isLocalPath($this->url)) {
$this->url = preg_replace('{[\\/]\.git/?$}', '', $this->url);
$this->repoDir = $this->url;
$cacheUrl = realpath($this->url);
} else {
$this->repoDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/';

GitUtil::cleanEnv();

$fs = new Filesystem();
$fs->ensureDirectoryExists(dirname($this->repoDir));

if (!is_writable(dirname($this->repoDir))) {
throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.dirname($this->repoDir).'" directory is not writable by the current user.');
}

if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $this->url)) {
throw new \InvalidArgumentException('The source URL '.$this->url.' is invalid, ssh URLs should have a port number after ":".'."\n".'Use ssh://git@example.com:22/path or just git@example.com:path if you do not want to provide a password or custom port.');
}

$gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs);
// patched line, sync from local dir without modifying url
if (!$skipSync && !$gitUtil->syncMirror($this->url, $this->repoDir)) {
$this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated</error>');
}

$cacheUrl = $this->url;
}

$this->getTags();
$this->getBranches();

$this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $cacheUrl));
}
}
10 changes: 10 additions & 0 deletions Resources/doc/schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ The plugin can override the main file definitions of the Bower packages. To over
definitions specify the packages and their main file array as name/value pairs. For an example
see the [usage informations](index.md#override-the-main-files-for-bower).

##### config.fxp-asset.git-skip-update (root-only)

The plugin can skip updating meta-data in git repositories for given amount of time, i.e. `6 hours`, `3 days` or `1 week`.

"config": {
"fxp-asset": {
"git-skip-update": "2 days"
}
}

### Mapping asset file to composer package

##### NPM mapping
Expand Down
82 changes: 82 additions & 0 deletions Tests/Repository/Vcs/GitDriverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Composer\IO\IOInterface;
use Composer\Util\Filesystem;
use Composer\Util\ProcessExecutor;
use Fxp\Composer\AssetPlugin\Repository\AssetRepositoryManager;
use Fxp\Composer\AssetPlugin\Repository\Vcs\GitDriver;

/**
Expand All @@ -29,15 +30,34 @@ class GitDriverTest extends \PHPUnit_Framework_TestCase
*/
private $config;

/**
* @var AssetRepositoryManager|\PHPUnit_Framework_MockObject_MockObject
*/
private $assetRepositoryManager;

public function setUp()
{
$assetConfig = new \Fxp\Composer\AssetPlugin\Config\Config(array('git-skip-update' => '1 hour'));

/* @var AssetRepositoryManager|\PHPUnit_Framework_MockObject_MockObject $arm */
$this->assetRepositoryManager = $this->getMockBuilder(AssetRepositoryManager::class)->disableOriginalConstructor()->getMock();
$this->assetRepositoryManager->expects($this->any())
->method('getConfig')
->willReturn($assetConfig);

$this->config = new Config();
$this->config->merge(array(
'config' => array(
'home' => sys_get_temp_dir().'/composer-test',
'cache-repo-dir' => sys_get_temp_dir().'/composer-test-cache',
'cache-vcs-dir' => sys_get_temp_dir().'/composer-test-cache',
),
));

// Mock for skip asset
$fs = new Filesystem();
$fs->ensureDirectoryExists(sys_get_temp_dir().'/composer-test-cache/https---git.luolix.top-fxpio-composer-asset-plugin.git');
file_put_contents(sys_get_temp_dir().'/composer-test-cache/https---git.luolix.top-fxpio-composer-asset-plugin.git/config', '');
}

public function tearDown()
Expand Down Expand Up @@ -71,6 +91,7 @@ public function testPublicRepositoryWithEmptyComposer($type, $filename)
'url' => $repoUrl,
'asset-type' => $type,
'filename' => $filename,
'asset-repository-manager' => $this->assetRepositoryManager,
);

$process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock();
Expand All @@ -96,6 +117,65 @@ public function testPublicRepositoryWithEmptyComposer($type, $filename)
$this->assertSame($validEmpty, $gitDriver->getComposerInformation($identifier));
}

/**
* @dataProvider getAssetTypes
*
* @param string $type
* @param string $filename
*/
public function testPublicRepositoryWithSkipUpdate($type, $filename)
{
$repoUrl = 'https://github.com/fxpio/composer-asset-plugin.git';
$identifier = '92bebbfdcde75ef2368317830e54b605bc938123';
$io = $this->getMockBuilder('Composer\IO\IOInterface')->getMock();

$repoConfig = array(
'url' => $repoUrl,
'asset-type' => $type,
'filename' => $filename,
'asset-repository-manager' => $this->assetRepositoryManager,
);

$process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock();
$process->expects($this->any())
->method('splitLines')
->will($this->returnValue(array()));
$process->expects($this->any())
->method('execute')
->will($this->returnCallback(function ($command, &$output = null) use ($identifier, $repoConfig) {
if ($command === sprintf('git show %s', sprintf('%s:%s', escapeshellarg($identifier), $repoConfig['filename']))) {
$output = '{"name": "foo"}';
} elseif (false !== strpos($command, 'git log')) {
$date = new \DateTime(null, new \DateTimeZone('UTC'));
$output = $date->getTimestamp();
}

return 0;
}));

/* @var IOInterface $io */
/* @var ProcessExecutor $process */

$gitDriver1 = new GitDriver($repoConfig, $io, $this->config, $process, null);
$gitDriver1->initialize();

$gitDriver2 = new GitDriver($repoConfig, $io, $this->config, $process, null);
$gitDriver2->initialize();

$validEmpty = array(
'_nonexistent_package' => true,
);

$composer1 = $gitDriver1->getComposerInformation($identifier);
$composer2 = $gitDriver2->getComposerInformation($identifier);

$this->assertNotNull($composer1);
$this->assertNotNull($composer2);
$this->assertSame($composer1, $composer2);
$this->assertNotSame($validEmpty, $composer1);
$this->assertNotSame($validEmpty, $composer2);
}

/**
* @dataProvider getAssetTypes
*
Expand All @@ -110,6 +190,7 @@ public function testPublicRepositoryWithCodeCache($type, $filename)
'url' => $repoUrl,
'asset-type' => $type,
'filename' => $filename,
'asset-repository-manager' => $this->assetRepositoryManager,
);
$io = $this->getMockBuilder('Composer\IO\IOInterface')->getMock();
$process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock();
Expand Down Expand Up @@ -156,6 +237,7 @@ public function testPublicRepositoryWithFilesystemCache($type, $filename)
'url' => $repoUrl,
'asset-type' => $type,
'filename' => $filename,
'asset-repository-manager' => $this->assetRepositoryManager,
);
$io = $this->getMockBuilder('Composer\IO\IOInterface')->getMock();
$process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock();
Expand Down
5 changes: 5 additions & 0 deletions Tests/Repository/Vcs/GitHubDriverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,13 @@ public function setUp()
),
));

$assetConfig = new \Fxp\Composer\AssetPlugin\Config\Config(array());

$this->assetRepositoryManager = $this->getMockBuilder(AssetRepositoryManager::class)
->disableOriginalConstructor()->getMock();
$this->assetRepositoryManager->expects($this->any())
->method('getConfig')
->willReturn($assetConfig);
}

public function tearDown()
Expand Down