Skip to content
This repository has been archived by the owner on Mar 26, 2018. It is now read-only.

Commit

Permalink
compiled to phar
Browse files Browse the repository at this point in the history
  • Loading branch information
khepin committed Jul 23, 2012
1 parent 2e9a14d commit 8ba5116
Show file tree
Hide file tree
Showing 7 changed files with 291 additions and 13 deletions.
9 changes: 9 additions & 0 deletions bin/compile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env php
<?php

include __DIR__.'/../vendor/autoload.php';

use Khepin\Medusa\Compiler;

$compiler = new Compiler();
$compiler->compile();
6 changes: 4 additions & 2 deletions bin/medusa
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ include __DIR__.'/../vendor/autoload.php';

use Symfony\Component\Console\Application;
use Khepin\Medusa\Command\AddRepoCommand;
use Khepin\Medusa\Command\ResolveDependenciesCommand;
use Khepin\Medusa\Command\UpdateReposCommand;
use Khepin\Medusa\Command\MirrorCommand;

$application = new Application();
$application->add(new AddRepoCommand);
$application->add(new ResolveDependenciesCommand);
$application->add(new UpdateReposCommand);
$application->add(new MirrorCommand);
$application->run();
29 changes: 19 additions & 10 deletions src/Khepin/Medusa/Command/AddRepoCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Symfony\Component\Process\Process;
use Guzzle\Service\Client;
use Composer\Json\JsonFile;
use Khepin\Medusa\DependencyResolver;

class AddRepoCommand extends Command
{
Expand All @@ -29,6 +30,7 @@ protected function configure()
new InputArgument('package', InputArgument::REQUIRED, 'The name of a composer package', null),
new InputArgument('repos-dir', InputArgument::OPTIONAL, 'Location where to output built files', null),
new InputOption('config-file', null, InputOption::VALUE_NONE, 'The config file to update with the new info'),
new InputOption('with-deps', null, InputOption::VALUE_NONE, 'If set, the package dependencies will be downloaded too'),
))
->setHelp(<<<EOT
The <info>mirror</info> command reads the given composer.lock file and mirrors
Expand All @@ -48,17 +50,24 @@ protected function execute(InputInterface $input, OutputInterface $output)
$dir = $input->getArgument('repos-dir');
$package = $input->getArgument('package');

$output->writeln(' - Fetching <info>'.$package.'</info>');
$this->getGitRepo($package, $dir);
$output->writeln('');
$deps = [$package];
if($input->getOption('with-deps')){
$resolver = new DependencyResolver($package);
$deps = $resolver->resolve();
}
foreach($deps as $package){
$output->writeln(' - Mirroring <info>'.$package.'</info>');
$this->getGitRepo($package, $dir);
$output->writeln('');

if($input->getOption('config-file')){
$file = new JsonFile($input->getOption('config-file'));
$config = $file->read();
$url = realpath($dir.'/'.str_replace('/', '-', $package).'.git');
$repo = array('type' => 'git', 'url' => 'file:///'.$url);
$config['repositories'][] = $repo;
$file->write($config);
if($input->getOption('config-file')){
$file = new JsonFile($input->getOption('config-file'));
$config = $file->read();
$url = realpath($dir.'/'.str_replace('/', '-', $package).'.git');
$repo = array('type' => 'git', 'url' => 'file:///'.$url);
$config['repositories'][] = $repo;
$file->write($config);
}
}
}

Expand Down
62 changes: 62 additions & 0 deletions src/Khepin/Medusa/Command/MirrorCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php
namespace Khepin\Medusa\Command;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Command\Command;
use Khepin\Medusa\DependencyResolver;
use Guzzle\Service\Client;
use Khepin\Medusa\Downloader;
use Symfony\Component\Console\Input\ArrayInput;

class MirrorCommand extends Command
{
protected $guzzle;

protected function configure()
{
$this
->setName('mirror')
->setDescription('Mirrors all repositories given a config file')
->setDefinition(array(
new InputArgument('config', InputArgument::OPTIONAL, 'A config file', null),
))
;
}

/**
* @param InputInterface $input The input instance
* @param OutputInterface $output The output instance
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln('<info>First getting all dependencies</info>');
$this->guzzle = new Client('http://packagist.org');
$config = json_decode(file_get_contents($input->getArgument('config')));
$repos = [];
foreach($config->require as $dependency){
$output->writeln(' - Getting dependencies for <info>'.$dependency.'</info>');
$resolver = new DependencyResolver($dependency);
$deps = $resolver->resolve();
$repos = array_merge($repos, $deps);
}

foreach($repos as $repo){
$command = $this->getApplication()->find('add');

$arguments = array(
'command' => 'add',
'package' => $repo,
'repos-dir' => $config->repodir,
);
if(!is_null($config->satisconfig)){
$arguments['--config-file'] = $config->satisconfig;
}

$input = new ArrayInput($arguments);
$returnCode = $command->run($input, $output);
}
}
}
50 changes: 50 additions & 0 deletions src/Khepin/Medusa/Command/UpdateReposCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
namespace Khepin\Medusa\Command;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Process\Process;

class UpdateReposCommand extends Command
{

protected function configure()
{
$this
->setName('update')
->setDescription('Fetch last updates from each package')
->setDefinition(array(
new InputArgument('repos-dir', InputArgument::OPTIONAL, 'Location where to output built files', null),
))
->setHelp(<<<EOT
The <info>mirror</info> command reads the given composer.lock file and mirrors
each git repository so they can be used locally.
<warning>This will only work for repos hosted on github.</warning>
EOT
)
;
}

/**
* @param InputInterface $input The input instance
* @param OutputInterface $output The output instance
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$dir = $input->getArgument('repos-dir');
$repos = glob($dir.'/*/*.git');
$cmd = 'cd %s && git fetch';
foreach($repos as $repo){
$output->writeln(' - Fetching latest changes in <info>'.$repo.'</info>');
$process = new Process(sprintf($cmd, $repo));
$process->run();
if (!$process->isSuccessful()) {
throw new \Exception($process->getErrorOutput());
}
$output->writeln($process->getOutput());
}
}
}
146 changes: 146 additions & 0 deletions src/Khepin/Medusa/Compiler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
<?php
namespace Khepin\Medusa;

use Symfony\Component\Finder\Finder;

class Compiler
{
public function compile($pharFile = 'medusa.phar')
{
if (file_exists($pharFile)) {
unlink($pharFile);
}

$phar = new \Phar($pharFile, 0, 'medusa.phar');
$phar->setSignatureAlgorithm(\Phar::SHA1);

$phar->startBuffering();

$finders = array();

$finder = new Finder();
$finder->files()
->ignoreVCS(true)
->name('*.php')
->notName('Compiler.php')
->in(__DIR__.'/../../')
;
$finders[] = $finder;

$finder = new Finder();
$finder->files()
->ignoreVCS(true)
->name('*.php')
->in([
__DIR__.'/../../../vendor/symfony/symfony/src/Symfony/Component/Console',
__DIR__.'/../../../vendor/symfony/symfony/src/Symfony/Component/EventDispatcher',
__DIR__.'/../../../vendor/symfony/symfony/src/Symfony/Component/Process',
])
;
$finders[] = $finder;

$finder = new Finder();
$finder->files()
->ignoreVCS(true)
->name('autoload.php')
->in(__DIR__.'/../../../vendor')
;
$finders[] = $finder;

$finder = new Finder();
$finder->files()
->ignoreVCS(true)
->name('*.php')
->in(__DIR__.'/../../../vendor/composer')
->depth(0)
;
$finders[] = $finder;

$finder = new Finder();
$finder->files()
->ignoreVCS(true)
->name('*.php')
->in(__DIR__.'/../../../vendor/guzzle')
;
$finders[] = $finder;

foreach ($finders as $finder) {
foreach ($finder as $file) {
$this->addFile($phar, $file);
}
}

$this->addBin($phar);

// Stubs
$phar->setStub($this->getStub());

$phar->stopBuffering();

$phar->compressFiles(\Phar::GZ);

unset($phar);
}

private function addFile($phar, $file, $strip = true)
{
$path = str_replace(dirname(dirname(dirname(__DIR__))).DIRECTORY_SEPARATOR, '', $file->getRealPath());

$content = file_get_contents($file);
if ($strip) {
$content = $this->stripWhitespace($content);
} elseif ('LICENSE' === basename($file)) {
$content = "\n".$content."\n";
}

$phar->addFromString($path, $content);
}

private function addBin($phar)
{
$content = file_get_contents(__DIR__.'/../../../bin/medusa');
$content = preg_replace('{^#!/usr/bin/env php\s*}', '', $content);
$phar->addFromString('bin/medusa', $content);
}

private function stripWhitespace($source)
{
if (!function_exists('token_get_all')) {
return $source;
}

$output = '';
foreach (token_get_all($source) as $token) {
if (is_string($token)) {
$output .= $token;
} elseif (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
$output .= str_repeat("\n", substr_count($token[1], "\n"));
} elseif (T_WHITESPACE === $token[0]) {
// reduce wide spaces
$whitespace = preg_replace('{[ \t]+}', ' ', $token[1]);
// normalize newlines to \n
$whitespace = preg_replace('{(?:\r\n|\r|\n)}', "\n", $whitespace);
// trim leading spaces
$whitespace = preg_replace('{\n +}', "\n", $whitespace);
$output .= $whitespace;
} else {
$output .= $token[1];
}
}

return $output;
}

private function getStub()
{
return <<<'EOF'
#!/usr/bin/env php
<?php
Phar::mapPhar('medusa.phar');
require 'phar://medusa.phar/bin/medusa';
__HALT_COMPILER();
EOF;
}
}
2 changes: 1 addition & 1 deletion src/Khepin/Medusa/Downloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public function __construct($package, $url)
public function download($in_dir)
{
$cmd = 'git clone --mirror %s %s';
$dir = $in_dir.'/'.str_replace('/', '-', $this->package).'.git';
$dir = $in_dir.'/'.$this->package.'.git';
if(is_dir($dir)){
return;
}
Expand Down

0 comments on commit 8ba5116

Please sign in to comment.