forked from garveen/imagist
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0cd5099
Showing
7 changed files
with
361 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
vendor/ | ||
composer.lock | ||
|
||
public/* | ||
!public/index.php |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
## Imagist | ||
|
||
Image the packagist | ||
|
||
### Introduction | ||
|
||
Due to the Internet connection may not so stable, you want to have a cached `packagist` for using `composer`. | ||
|
||
### Installation | ||
|
||
#### Installer | ||
|
||
``` | ||
composer global require acabin/imagist | ||
``` | ||
|
||
You may have put the `~/.composer/vendor/bin` directory in your PATH. If not, do so. | ||
|
||
Once installed, the `imagist new` command can be used for create your own site. | ||
|
||
``` | ||
imagist new my_packagist | ||
``` | ||
|
||
#### Composer | ||
|
||
``` | ||
composer require composer/composer:^1.0@alpha acabin/imagist | ||
``` | ||
|
||
### Usage | ||
|
||
1. Now you have a `public` directory in your site. You can set up a web server as usual, just by using the `public` as root. | ||
|
||
2. Set up a `crontab` job to update the packages.json: | ||
|
||
``` | ||
*/5 * * * * php /path/to/public/index.php packages.json >/dev/null 2>&1 | ||
``` | ||
|
||
3. Configure your `composer` to use this amazing site: | ||
|
||
``` | ||
composer config [--global] repo.packagist composer https://yoursite | ||
``` | ||
|
||
Notice: You should **NOT** use `imagist` globally on the machine which you run it. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"name": "acabin/imagist", | ||
"description": "Image the packagist", | ||
"keywords": ["image", "proxy", "packagist", "composer"], | ||
"config": { | ||
"bin-dir": "public" | ||
}, | ||
"authors": [ | ||
{ | ||
"name": "Gavin", | ||
"email": "acabin@live.com" | ||
} | ||
], | ||
"require": { | ||
"symfony/console": "~2.3|~3.0", | ||
"symfony/process": "~2.3|~3.0", | ||
"symfony/http-foundation": "~2.3|~3.0", | ||
"composer/composer": "^1.0@alpha" | ||
}, | ||
"autoload": { | ||
"psr-4": { | ||
"Acabin\\Imagist\\": "src/" | ||
} | ||
}, | ||
"bin": ["imagist"], | ||
"license": "GPL-2.0" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#!/usr/bin/env php | ||
<?php | ||
if (file_exists(__DIR__.'/../../autoload.php')) { | ||
require __DIR__.'/../../autoload.php'; | ||
} else { | ||
require __DIR__.'/vendor/autoload.php'; | ||
} | ||
define('ROOT_PATH', __DIR__); | ||
$app = new Symfony\Component\Console\Application('imagist'); | ||
$app->add(new Acabin\Imagist\Console\NewCommand); | ||
$app->run(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
|
||
if (file_exists(__DIR__.'/../../autoload.php')) { | ||
require __DIR__.'/../../autoload.php'; | ||
} else { | ||
require __DIR__.'/../vendor/autoload.php'; | ||
} | ||
define('ROOT_PATH', __DIR__); | ||
|
||
use Symfony\Component\HttpFoundation\Request; | ||
use Symfony\Component\HttpFoundation\Response; | ||
|
||
if(PHP_SAPI == 'cli') { | ||
$argv[0] = ''; | ||
$request = Request::create(implode('/', $argv)); | ||
} else { | ||
$request = Request::createFromGlobals(); | ||
} | ||
|
||
$response = new Response; | ||
$imagist = new Acabin\Imagist\Http\Imagist($request, $response); | ||
$imagist->run(); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
<?php | ||
namespace Acabin\Imagist\Console; | ||
|
||
use RuntimeException; | ||
use Symfony\Component\Process\Process; | ||
use Symfony\Component\Console\Command\Command; | ||
use Symfony\Component\Console\Input\InputOption; | ||
use Symfony\Component\Console\Input\InputArgument; | ||
use Symfony\Component\Console\Input\InputInterface; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
class NewCommand extends Command | ||
{ | ||
/** | ||
* Configure the command options. | ||
* | ||
* @return void | ||
*/ | ||
protected function configure() | ||
{ | ||
$this | ||
->setName('new') | ||
->setDescription('Create a new Imagist application.') | ||
->addArgument('name', InputArgument::REQUIRED); | ||
} | ||
/** | ||
* Execute the command. | ||
* | ||
* @param InputInterface $input | ||
* @param OutputInterface $output | ||
* @return void | ||
*/ | ||
protected function execute(InputInterface $input, OutputInterface $output) | ||
{ | ||
$this->verifyApplicationDoesntExist( | ||
$directory = getcwd() . '/' . $input->getArgument('name'), | ||
$output | ||
); | ||
|
||
mkdir($directory, 0755, true); | ||
$composer = $this->findComposer(); | ||
$commands = [ | ||
"$composer require composer/composer:^1.0@alpha acabin/imagist", | ||
]; | ||
if(!empty($commands)) { | ||
$this->process($commands, $directory, $output); | ||
} | ||
mkdir($directory . "/public", 0755, true); | ||
copy(ROOT_PATH . '/index.php', $directory . "/public/index.php"); | ||
|
||
$output->writeln('<comment>Here we are! Now you can have a cached composer!</comment>'); | ||
|
||
} | ||
protected function process($commands, $directory, $output) | ||
{ | ||
$process = new Process(implode(' && ', $commands), $directory, null, null, null); | ||
$process->run(function ($type, $line) use ($output) { | ||
$output->write($line); | ||
}); | ||
} | ||
/** | ||
* Verify that the application does not already exist. | ||
* | ||
* @param string $directory | ||
* @return void | ||
*/ | ||
protected function verifyApplicationDoesntExist($directory, OutputInterface $output) | ||
{ | ||
if (is_dir($directory)) { | ||
throw new RuntimeException('Application already exists!'); | ||
} | ||
} | ||
/** | ||
* Get the composer command for the environment. | ||
* | ||
* @return string | ||
*/ | ||
protected function findComposer() | ||
{ | ||
if (file_exists(getcwd() . '/composer.phar')) { | ||
return '"' . PHP_BINARY . '" composer.phar'; | ||
} | ||
return 'composer'; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
<?php | ||
|
||
namespace Acabin\Imagist\Http; | ||
|
||
use Illuminate\Http\Request; | ||
|
||
use Composer\Console\Application; | ||
use Composer\IO\ConsoleIO; | ||
use Symfony\Component\Console\Helper\HelperSet; | ||
use Composer\Factory; | ||
use Composer\Repository\CompositeRepository; | ||
|
||
use Symfony\Component\Console\Input\StringInput; | ||
use Symfony\Component\Console\Output\BufferedOutput; | ||
use Composer\DependencyResolver\Pool; | ||
|
||
class Imagist | ||
{ | ||
protected $request; | ||
protected $response; | ||
protected $pathinfo; | ||
public function __construct($request, $response) | ||
{ | ||
$this->request = $request; | ||
$this->response = $response; | ||
$this->pathinfo = $request->getPathInfo(); | ||
|
||
} | ||
|
||
public function run() | ||
{ | ||
$pathinfo = rawurldecode($this->pathinfo); | ||
switch (true) { | ||
case preg_match('{^/packages.json$}i', $pathinfo): | ||
$output = $this->generate(); | ||
break; | ||
case preg_match('{^/p/(?<name>.*)\$(?<hash>.*)\.json$}i', $pathinfo, $matches): | ||
$output = $this->package($matches); | ||
break; | ||
default: | ||
echo $pathinfo;exit; | ||
} | ||
if (isset($output)) { | ||
if (is_string($output)) { | ||
echo $output; | ||
return; | ||
} elseif (is_object($output)) { | ||
if (is_callable([$output, '__toString'])) { | ||
echo $output->__toString(); | ||
return; | ||
} | ||
} | ||
echo json_encode($output); | ||
} | ||
} | ||
|
||
protected function generate() | ||
{ | ||
$packages = [ | ||
'packages' => [], | ||
'notify' => 'https://packagist.org/downloads/%package%', | ||
'notify-batch' => 'https://packagist.org/downloads/', | ||
'providers-url' => '/p/%package%$%hash%.json', | ||
'search' => 'https://packagist.org/search.json?q=%query%', | ||
'provider-includes' => [ | ||
], | ||
|
||
'sync-time' => date('c'), | ||
]; | ||
|
||
$repos = $this->getRepos(); | ||
foreach ($repos as $repo) { | ||
$repoName = $repo->name; | ||
if (!is_callable([$repo, 'getProviderNames'])) { | ||
continue; | ||
} | ||
$repo->getProviderNames(); | ||
// do some hack | ||
$ref = new \ReflectionProperty($repo, 'providerListing'); | ||
$ref->setAccessible(true); | ||
$all = $ref->getValue($repo); | ||
|
||
$json = json_encode(['providers' => $all]); | ||
$sha256 = hash('sha256', $json); | ||
$path = "p/{$repoName}"; | ||
$file = "{$path}/all\${$sha256}.json"; | ||
|
||
mkdir($path, 0755, true); | ||
|
||
file_put_contents($file, $json); | ||
|
||
$packages['provider-includes'][$file] = ['sha256' => $sha256]; | ||
} | ||
|
||
file_put_contents("packages.json", json_encode($packages)); | ||
return $packages; | ||
} | ||
|
||
protected function package($matches) | ||
{ | ||
|
||
$hash = $matches['hash']; | ||
$name = $matches['name']; | ||
$filename = 'p/hash/' . substr($hash, 0, 2) . '/' . substr($hash, 2, 2) . '/' . $hash . hash('md5', $hash . $name) . '.json'; | ||
if (!file_exists($filename)) { | ||
$repos = $this->getRepos(); | ||
$pool = new Pool('dev'); | ||
foreach ($repos as $repo) { | ||
try { | ||
$pool->addRepository($repo); | ||
} catch (\RuntimeException $e) {} | ||
|
||
} | ||
$matches = $pool->whatProvides($name, null); | ||
if (!$matches) { | ||
return '{}'; | ||
} else { | ||
$match = $matches[0]; | ||
$repo = $match->getRepository(); | ||
|
||
$ref = new \ReflectionProperty($repo, 'cache'); | ||
$ref->setAccessible(true); | ||
$cache = $ref->getValue($repo); | ||
|
||
$cacheKey = 'provider-' . strtr($name, '/', '$') . '.json'; | ||
$packages = $cache->read($cacheKey); | ||
if (empty($packages)) { | ||
throw new \Exception("Cache should exists, please report this issue on github", 1); | ||
} | ||
mkdir(dirname($filename), 0755, true); | ||
file_put_contents($filename, $packages); | ||
} | ||
|
||
} | ||
return file_get_contents($filename); | ||
} | ||
|
||
protected function getRepos() | ||
{ | ||
$input = new StringInput(''); | ||
$output = new BufferedOutput; | ||
$helperSet = new HelperSet; | ||
|
||
$io = new ConsoleIO($input, $output, $helperSet); | ||
if (!file_exists('composer.json')) { | ||
putenv('COMPOSER=../composer.json'); | ||
} | ||
|
||
$composer = Factory::create($io); | ||
$config = $composer->getConfig(); | ||
$repos = $config->getRepositories(); | ||
|
||
foreach ($repos as &$repo) { | ||
$type = ucfirst($repo['type']); | ||
$type = "Composer\\Repository\\{$type}Repository"; | ||
$repo = new $type($repo, $io, $config); | ||
$ref = new \ReflectionProperty($repo, 'url'); | ||
$ref->setAccessible(true); | ||
$url = $ref->getValue($repo); | ||
$repo->name = preg_replace(['{^https?://}i', '{[^a-z0-9._]}i'], ['', '-'], $url); | ||
} | ||
return $repos; | ||
} | ||
} |