Merge branch 'master' of https://github.com/Block8/PHPCI into unit-test-fixes

This commit is contained in:
meadsteve 2013-11-03 13:40:17 +00:00
commit 010b5ebe6d
18 changed files with 402 additions and 133 deletions

View file

@ -22,7 +22,7 @@ class BuildFactory
{
/**
* Takes a generic build and returns a type-specific build model.
* @return PHPCI\Model\Build\LocalBuild|PHPCI\Model\Build\GithubBuild|PHPCI\Model\Build\BitbucketBuild
* @return \PHPCI\Model\Build\LocalBuild|\PHPCI\Model\Build\GithubBuild|\PHPCI\Model\Build\BitbucketBuild
*/
public static function getBuild(Build $base)
{

View file

@ -1,72 +1,70 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2013, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link http://www.phptesting.org/
*/
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2013, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link http://www.phptesting.org/
*/
namespace PHPCI;
use PHPCI\Model\Build;
use b8\Store;
use b8\Config;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
/**
* PHPCI Build Runner
* @author Dan Cryer <dan@block8.co.uk>
*/
class Builder
* PHPCI Build Runner
* @author Dan Cryer <dan@block8.co.uk>
*/
class Builder implements LoggerAwareInterface
{
/**
* @var string
*/
* @var string
*/
public $buildPath;
/**
* @var string[]
*/
public $ignore = array();
* @var string[]
*/
public $ignore = array();
/**
* @var string
*/
* @var string
*/
protected $ciDir;
/**
* @var string
*/
* @var string
*/
protected $directory;
/**
* @var bool
*/
protected $success = true;
* @var bool
*/
protected $success = true;
/**
* @var string
*/
protected $log = '';
* @var bool
*/
protected $verbose = true;
/**
* @var bool
*/
protected $verbose = true;
/**
* @var \PHPCI\Model\Build
*/
* @var \PHPCI\Model\Build
*/
protected $build;
/**
* @var callable
*/
protected $logCallback;
* @var LoggerInterface
*/
protected $logger;
/**
* @var array
*/
* @var array
*/
protected $config;
/**
@ -75,7 +73,7 @@ class Builder
protected $lastOutput;
/**
* An array of key => value pairs that will be used for
* An array of key => value pairs that will be used for
* interpolation and environment variables
* @var array
* @see setInterpolationVars()
@ -93,30 +91,32 @@ class Builder
public $quiet = false;
/**
* Set up the builder.
* @param \PHPCI\Model\Build
* @param callable
*/
public function __construct(Build $build, \Closure $logCallback)
* Set up the builder.
* @param \PHPCI\Model\Build $build
* @param LoggerInterface $logger
*/
public function __construct(Build $build, $logger = null)
{
if ($logger) {
$this->setLogger($logger);
}
$this->build = $build;
$this->store = Store\Factory::getStore('Build');
$this->logCallback = $logCallback;
}
/**
* Set the config array, as read from phpci.yml
* @param array
*/
* Set the config array, as read from phpci.yml
* @param array
*/
public function setConfigArray(array $config)
{
$this->config = $config;
}
/**
* Access a variable from the phpci.yml file.
* @param string
*/
* Access a variable from the phpci.yml file.
* @param string
*/
public function getConfig($key)
{
$rtn = null;
@ -147,8 +147,8 @@ class Builder
}
/**
* Run the active build.
*/
* Run the active build.
*/
public function execute()
{
// Update the build in the database, ping any external services.
@ -164,7 +164,6 @@ class Builder
// Run the core plugin stages:
foreach (array('setup', 'test', 'complete') as $stage) {
$this->executePlugins($stage);
$this->log('');
}
// Failed build? Execute failure plugins and then mark the build as failed.
@ -181,10 +180,10 @@ class Builder
}
} catch (\Exception $ex) {
$this->logFailure($ex->getMessage());
$this->logFailure($ex->getMessage(), $ex);
$this->build->setStatus(3);
}
// Clean up:
$this->log('Removing build.');
shell_exec(sprintf('rm -Rf "%s"', $this->buildPath));
@ -192,26 +191,25 @@ class Builder
// Update the build in the database, ping any external services, etc.
$this->build->sendStatusPostback();
$this->build->setFinished(new \DateTime());
$this->build->setLog($this->log);
$this->store->save($this->build);
}
/**
* Used by this class, and plugins, to execute shell commands.
*/
* Used by this class, and plugins, to execute shell commands.
*/
public function executeCommand()
{
$command = call_user_func_array('sprintf', func_get_args());
if (!$this->quiet) {
$this->log('Executing: ' . $command, ' ');
$this->log('Executing: ' . $command);
}
$status = 0;
exec($command, $this->lastOutput, $status);
if (!empty($this->lastOutput) && ($this->verbose || $status != 0)) {
$this->log($this->lastOutput, ' ');
$this->log($this->lastOutput);
}
@ -233,43 +231,62 @@ class Builder
}
/**
* Add an entry to the build log.
* @param string|string[]
* @param string
*/
public function log($message, $prefix = '')
* Add an entry to the build log.
* @param string|string[] $message
* @param string $level
* @param mixed[] $context
*/
public function log($message, $level = LogLevel::INFO, $context = array())
{
// Skip if no logger has been loaded.
if (!$this->logger) {
return;
}
if (!is_array($message)) {
$message = array($message);
}
foreach ($message as $item) {
call_user_func_array($this->logCallback, array($prefix . $item));
$this->log .= $prefix . $item . PHP_EOL;
}
// The build is added to the context so the logger can use
// details from it if required.
$context['build'] = $this;
$this->build->setLog($this->log);
$this->store->save($this->build);
foreach ($message as $item) {
$this->logger->log($level, $item, $context);
}
}
/**
* Add a success-coloured message to the log.
* @param string
*/
* Add a success-coloured message to the log.
* @param string
*/
public function logSuccess($message)
{
$this->log("\033[0;32m" . $message . "\033[0m");
}
/**
* Add a failure-coloured message to the log.
* @param string
*/
public function logFailure($message)
* Add a failure-coloured message to the log.
* @param string $message
* @param \Exception $exception The exception that caused the error.
*/
public function logFailure($message, \Exception $exception = null)
{
$this->log("\033[0;31m" . $message . "\033[0m");
$context = array();
// The psr3 log interface stipulates that exceptions should be passed
// as the exception key in the context array.
if ($exception) {
$context['exception'] = $exception;
}
$this->log(
"\033[0;31m" . $message . "\033[0m",
LogLevel::ERROR,
$context
);
}
/**
* Replace every occurance of the interpolation vars in the given string
* Example: "This is build %PHPCI_BUILD%" => "This is build 182"
@ -284,7 +301,7 @@ class Builder
}
/**
* Sets the variables that will be used for interpolation. This must be run
* Sets the variables that will be used for interpolation. This must be run
* from setupBuild() because prior to that, we don't know the buildPath
*/
protected function setInterpolationVars()
@ -294,9 +311,11 @@ class Builder
$this->interpolation_vars['%COMMIT%'] = $this->build->getCommitId();
$this->interpolation_vars['%PROJECT%'] = $this->build->getProjectId();
$this->interpolation_vars['%BUILD%'] = $this->build->getId();
$this->interpolation_vars['%PROJECT_TITLE%'] = $this->getBuildProjectTitle();
$this->interpolation_vars['%PROJECT_TITLE%'] = $this->getBuildProjectTitle(
);
$this->interpolation_vars['%BUILD_PATH%'] = $this->buildPath;
$this->interpolation_vars['%BUILD_URI%'] = PHPCI_URL . "build/view/" . $this->build->getId();
$this->interpolation_vars['%BUILD_URI%'] = PHPCI_URL . "build/view/" . $this->build->getId(
);
$this->interpolation_vars['%PHPCI_COMMIT%'] = $this->interpolation_vars['%COMMIT%'];
$this->interpolation_vars['%PHPCI_PROJECT%'] = $this->interpolation_vars['%PROJECT%'];
$this->interpolation_vars['%PHPCI_BUILD%'] = $this->interpolation_vars['%BUILD%'];
@ -305,25 +324,28 @@ class Builder
$this->interpolation_vars['%PHPCI_BUILD_URI%'] = $this->interpolation_vars['%BUILD_URI%'];
putenv('PHPCI=1');
putenv('PHPCI_COMMIT='.$this->interpolation_vars['%COMMIT%']);
putenv('PHPCI_PROJECT='.$this->interpolation_vars['%PROJECT%']);
putenv('PHPCI_BUILD='.$this->interpolation_vars['%BUILD%']);
putenv('PHPCI_PROJECT_TITLE='.$this->interpolation_vars['%PROJECT_TITLE%']);
putenv('PHPCI_BUILD_PATH='.$this->interpolation_vars['%BUILD_PATH%']);
putenv('PHPCI_BUILD_URI='.$this->interpolation_vars['%BUILD_URI%']);
putenv('PHPCI_COMMIT=' . $this->interpolation_vars['%COMMIT%']);
putenv('PHPCI_PROJECT=' . $this->interpolation_vars['%PROJECT%']);
putenv('PHPCI_BUILD=' . $this->interpolation_vars['%BUILD%']);
putenv(
'PHPCI_PROJECT_TITLE=' . $this->interpolation_vars['%PROJECT_TITLE%']
);
putenv('PHPCI_BUILD_PATH=' . $this->interpolation_vars['%BUILD_PATH%']);
putenv('PHPCI_BUILD_URI=' . $this->interpolation_vars['%BUILD_URI%']);
}
/**
* Set up a working copy of the project for building.
*/
* Set up a working copy of the project for building.
*/
protected function setupBuild()
{
$buildId = 'project' . $this->build->getProject()->getId() . '-build' . $this->build->getId();
$this->ciDir = dirname(__FILE__) . '/../';
$this->buildPath = $this->ciDir . 'build/' . $buildId . '/';
$buildId = 'project' . $this->build->getProject()->getId(
) . '-build' . $this->build->getId();
$this->ciDir = dirname(__FILE__) . '/../';
$this->buildPath = $this->ciDir . 'build/' . $buildId . '/';
$this->setInterpolationVars();
// Create a working copy of the project:
if (!$this->build->createWorkingCopy($this, $this->buildPath)) {
throw new \Exception('Could not create a working copy.');
@ -344,17 +366,20 @@ class Builder
}
/**
* Execute a the appropriate set of plugins for a given build stage.
*/
* Execute a the appropriate set of plugins for a given build stage.
*/
protected function executePlugins($stage)
{
// Ignore any stages for which we don't have plugins set:
if (!array_key_exists($stage, $this->config) || !is_array($this->config[$stage])) {
if (!array_key_exists(
$stage,
$this->config
) || !is_array($this->config[$stage])
) {
return;
}
foreach ($this->config[$stage] as $plugin => $options) {
$this->log('');
$this->log('RUNNING PLUGIN: ' . $plugin);
// Is this plugin allowed to fail?
@ -392,7 +417,7 @@ class Builder
$class = 'PHPCI\\Plugin\\' . str_replace(' ', '', $class);
if (!class_exists($class)) {
$this->logFailure('Plugin does not exist: ' . $plugin);
$this->logFailure('Plugin does not exist: ' . $plugin, $ex);
return false;
}
@ -406,7 +431,7 @@ class Builder
$rtn = false;
}
} catch (\Exception $ex) {
$this->logFailure('EXCEPTION: ' . $ex->getMessage());
$this->logFailure('EXCEPTION: ' . $ex->getMessage(), $ex);
$rtn = false;
}
@ -445,4 +470,25 @@ class Builder
return null;
}
/**
* Sets a logger instance on the object
*
* @param LoggerInterface $logger
* @return null
*/
public function setLogger(LoggerInterface $logger)
{
$this->logger = $logger;
}
/**
* returns the logger attached to this builder.
*
* @return LoggerInterface
*/
public function getLogger()
{
return $this->logger;
}
}

View file

@ -9,6 +9,11 @@
namespace PHPCI\Command;
use Monolog\Logger;
use PHPCI\Helper\BuildDBLogHandler;
use PHPCI\Helper\LoggedBuildContextTidier;
use PHPCI\Helper\OutputLogHandler;
use Psr\Log\LoggerAwareInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@ -26,6 +31,11 @@ use PHPCI\BuildFactory;
*/
class RunCommand extends Command
{
/**
* @var OutputInterface
*/
protected $output;
protected function configure()
{
$this
@ -34,32 +44,44 @@ class RunCommand extends Command
}
/**
* Pulls all pending builds from the database and runs them.
*/
* Pulls all pending builds from the database and runs them.
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->output = $output;
$store = Factory::getStore('Build');
$logger = new Logger("BuildLog");
$store = Factory::getStore('Build');
$result = $store->getByStatus(0);
$builds = 0;
// For verbose mode we want to output all informational and above
// messages to the symphony output interface.
if ($input->getOption('verbose')) {
$logger->pushHandler(
new OutputLogHandler($this->output, Logger::INFO)
);
}
$logger->pushProcessor(new LoggedBuildContextTidier());
foreach ($result['items'] as $build) {
$builds++;
$build = BuildFactory::getBuild($build);
if ($input->getOption('verbose')) {
$builder = new Builder($build, function ($log) {
$this->output->writeln($log);
});
} else {
$builder = new Builder($build, function () {
// Empty stub function.
});
}
// Logging relevant to this build should be stored
// against the build itself.
$buildDbLog = new BuildDBLogHandler($build, Logger::INFO);
$logger->pushHandler($buildDbLog);
$builder = new Builder($build, $logger);
$builder->execute();
// After execution we no longer want to record the information
// back to this specific build so the handler should be removed.
$logger->popHandler($buildDbLog);
}
return $builds;

View file

@ -0,0 +1,35 @@
<?php
namespace PHPCI\Helper;
use b8\Store;
use Monolog\Handler\AbstractProcessingHandler;
use PHPCI\Model\Build;
class BuildDBLogHandler extends AbstractProcessingHandler
{
/**
* @var Build
*/
protected $build;
protected $logValue;
function __construct(
Build $build,
$level = LogLevel::INFO,
$bubble = true
) {
parent::__construct($level, $bubble);
$this->build = $build;
// We want to add to any existing saved log information.
$this->logValue = $build->getLog();
}
protected function write(array $record)
{
$this->logValue .= (string)$record['formatted'];
$this->build->setLog($this->logValue);
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace PHPCI\Helper;
class LoggedBuildContextTidier{
function __invoke()
{
return $this->tidyLoggedBuildContext(func_get_arg(0));
}
/**
* Removes the build object from the logged record and adds the ID as
* this is more useful to display.
*
* @param array $logRecord
* @return array
*/
protected function tidyLoggedBuildContext(array $logRecord)
{
if (isset($logRecord['context']['build'])) {
$build = $logRecord['context']['build'];
if ($build instanceof Build) {
$logRecord['context']['buildID'] = $build->getId();
unset($logRecord['context']['build']);
}
}
return $logRecord;
}
}

View file

@ -0,0 +1,33 @@
<?php
namespace PHPCI\Helper;
use Monolog\Handler\AbstractProcessingHandler;
use Psr\Log\LogLevel;
use Symfony\Component\Console\Output\OutputInterface;
class OutputLogHandler extends AbstractProcessingHandler
{
/**
* @var OutputInterface
*/
protected $output;
function __construct(
OutputInterface $output,
$level = LogLevel::INFO,
$bubble = true
) {
parent::__construct($level, $bubble);
$this->output = $output;
}
protected function write(array $record)
{
$this->output->writeln((string)$record['formatted']);
}
}

View file

@ -49,18 +49,18 @@ class Atoum implements \PHPCI\Plugin
$dirPath = $this->phpci->buildPath . DIRECTORY_SEPARATOR . $this->directory;
$cmd .= " -d '{$dirPath}'";
}
chdir($this->phpci->buildPath);
$output = '';
$status = true;
exec($cmd, $output);
if (count(preg_grep("/Success \(/", $output)) == 0) {
$status = false;
$this->phpci->log($output, ' ');
$this->phpci->log($output);
}
if (count($output) == 0) {
$status = false;
$this->phpci->log("No test have been performed!", ' ');
$this->phpci->log("No test have been performed!");
}
return $status;

2
PHPCI/Plugin/PhpCpd.php Executable file → Normal file
View file

@ -77,7 +77,7 @@ class PhpCpd implements \PHPCI\Plugin
return false;
}
$success = $this->phpci->executeCommand($phpcpd . ' %s "%s"', $ignore, $this->phpci->buildPath.$this->path);
$success = $this->phpci->executeCommand($phpcpd . ' %s "%s"', $ignore, $this->path);
print $this->phpci->getLastOutput();

View file

@ -7,7 +7,7 @@
<div class="col-lg-3">
<ul class="nav nav-pills nav-stacked">
<li><a href="<?= PHPCI_URL ?>"><i class="icon-home"></i> Dashboard</a></li>
<li><a href="<?= PHPCI_URL ?>project/view/<?php print $build->getProject()->getId(); ?>"><i class="icon-folder-open"></i> <?php print $build->getProject()->getTitle(); ?></a></li>
<li><a href="<?= PHPCI_URL ?>project/view/<?php print $build->getProject()->getId(); ?>"><i class="icon-folder-open"></i> <?php print htmlspecialchars($build->getProject()->getTitle()); ?></a></li>
</ul>
<h5>Options</h5>
<ul class="nav nav-pills nav-stacked">

View file

@ -41,7 +41,7 @@ switch($build->getStatus())
<td><a href="<?= PHPCI_URL ?>project/view/<?php print $build->getProjectId(); ?>">
<?php
if (is_object($build->getProject())) {
print $build->getProject()->getTitle();
print htmlspecialchars($build->getProject()->getTitle());
} else {
print ' - ';
}

View file

@ -11,7 +11,7 @@
<h5>Projects</h5>
<ul class="nav nav-pills nav-stacked">
<?php foreach($projects as $project): ?>
<li><a href="<?= PHPCI_URL ?>project/view/<?php print $project->getId(); ?>"><?php print $project->getTitle(); ?></a></li>
<li><a href="<?= PHPCI_URL ?>project/view/<?php print $project->getId(); ?>"><?php print htmlspecialchars($project->getTitle()); ?></a></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>

View file

@ -1,12 +1,12 @@
<div id="title">
<h1>Project: <?php print (is_object($project)) ? $project->getTitle() : ' - '; ?></h1>
<h1>Project: <?php print (is_object($project)) ? htmlspecialchars($project->getTitle()) : ' - '; ?></h1>
</div>
<div class="row">
<div class="col-lg-3">
<ul class="nav nav-pills nav-stacked">
<li><a href="<?= PHPCI_URL ?>"><i class="icon-home"></i> Dashboard</a></li>
<li><a href="<?= PHPCI_URL ?>project/view/<?php print $project->getId(); ?>"><i class="icon-folder-open"></i> <?php print $project->getTitle(); ?></a></li>
<li><a href="<?= PHPCI_URL ?>project/view/<?php print $project->getId(); ?>"><i class="icon-folder-open"></i> <?php print htmlspecialchars($project->getTitle()); ?></a></li>
</ul>
<h5>Options</h5>
<ul class="nav nav-pills nav-stacked">

View file

@ -82,7 +82,7 @@ foreach($projects as $project):
<?= $health ?>
</span>
</td>
<td><a href='<?= PHPCI_URL ?>project/view/<?= $project->getId() ?>'><?= $project->getTitle() ?></a></td>
<td><a href='<?= PHPCI_URL ?>project/view/<?= $project->getId() ?>'><?= htmlspecialchars($project->getTitle()) ?></a></td>
<td><?php print is_null($success) ? 'Never' : $success; ?></td>
<td><?php print is_null($failure) ? 'Never' : $failure; ?></td>
<td>

View file

@ -40,7 +40,7 @@
?>
<tr class="<?php print $cls; ?>">
<td><a href="<?= PHPCI_URL ?>user/edit/<?php print $user->getId(); ?>"><?php print $user->getEmail(); ?></a></td>
<td><?php print $user->getName(); ?></td>
<td><?php print htmlspecialchars($user->getName()); ?></td>
<td><?php print $status; ?></td>
<td>
<?php if($this->User()->getIsAdmin()): ?>

View file

@ -1,5 +1,5 @@
<div id="title">
<h1><?php print $type == 'add' ? 'Add User' : 'Edit ' . $user->getName() ?></h1>
<h1><?php print $type == 'add' ? 'Add User' : 'Edit ' . htmlspecialchars($user->getName()) ?></h1>
</div>
<div class="row">

View file

@ -36,7 +36,7 @@
<div class="nav-collapse collapse navbar-responsive-collapse">
<ul class="nav navbar-nav pull-right">
<li><p class="navbar-text"><strong><?php print $this->User()->getName(); ?></strong></p></li>
<li><p class="navbar-text"><strong><?php print htmlspecialchars($this->User()->getName()); ?></strong></p></li>
<li><a href="<?php print PHPCI_URL ?>session/logout">Log out</a></li>
<?php if ($this->User()->getIsAdmin()): ?>
<li>

View file

@ -27,7 +27,9 @@
"ircmaxell/password-compat": "1.*",
"swiftmailer/swiftmailer" : "5.0.*",
"symfony/yaml" : "2.*",
"symfony/console" : "2.*"
"symfony/console" : "2.*",
"psr/log": "1.0.0",
"monolog/monolog": "1.6.0"
},
"suggest": {

106
composer.lock generated
View file

@ -3,7 +3,7 @@
"This file locks the dependencies of your project to a known state",
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
],
"hash": "04cca0ac809838a65555d04534cc95ae",
"hash": "534baabecc11275d5cc7f375eecf738d",
"packages": [
{
"name": "block8/b8framework",
@ -91,6 +91,106 @@
],
"time": "2013-04-30 19:58:08"
},
{
"name": "monolog/monolog",
"version": "1.6.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
"reference": "f72392d0e6eb855118f5a84e89ac2d257c704abd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/f72392d0e6eb855118f5a84e89ac2d257c704abd",
"reference": "f72392d0e6eb855118f5a84e89ac2d257c704abd",
"shasum": ""
},
"require": {
"php": ">=5.3.0",
"psr/log": "~1.0"
},
"require-dev": {
"doctrine/couchdb": "dev-master",
"mlehner/gelf-php": "1.0.*",
"raven/raven": "0.5.*"
},
"suggest": {
"doctrine/couchdb": "Allow sending log messages to a CouchDB server",
"ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
"ext-mongo": "Allow sending log messages to a MongoDB server",
"mlehner/gelf-php": "Allow sending log messages to a GrayLog2 server",
"raven/raven": "Allow sending log messages to a Sentry server"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.6.x-dev"
}
},
"autoload": {
"psr-0": {
"Monolog": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be",
"role": "Developer"
}
],
"description": "Sends your logs to files, sockets, inboxes, databases and various web services",
"homepage": "http://github.com/Seldaek/monolog",
"keywords": [
"log",
"logging",
"psr-3"
],
"time": "2013-07-28 22:38:30"
},
{
"name": "psr/log",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "fe0936ee26643249e916849d48e3a51d5f5e278b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b",
"reference": "fe0936ee26643249e916849d48e3a51d5f5e278b",
"shasum": ""
},
"type": "library",
"autoload": {
"psr-0": {
"Psr\\Log\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"keywords": [
"log",
"psr",
"psr-3"
],
"time": "2012-12-21 11:40:51"
},
{
"name": "swiftmailer/swiftmailer",
"version": "v5.0.2",
@ -142,7 +242,7 @@
},
{
"name": "symfony/console",
"version": "v2.3.5",
"version": "v2.3.6",
"target-dir": "Symfony/Component/Console",
"source": {
"type": "git",
@ -195,7 +295,7 @@
},
{
"name": "symfony/yaml",
"version": "v2.3.5",
"version": "v2.3.6",
"target-dir": "Symfony/Component/Yaml",
"source": {
"type": "git",