1
0
Fork 0

Merge callback method of FileDownloader and VcsDriver

Required corrections added
pull/293/head
François Pluchino 2012-02-15 13:11:29 +01:00
parent 9638247e44
commit 953f0992f7
3 changed files with 92 additions and 107 deletions

View File

@ -11,10 +11,10 @@
namespace Composer\Downloader; namespace Composer\Downloader;
use Composer\Util\RemoteFilesystem;
use Composer\IO\IOInterface; use Composer\IO\IOInterface;
use Composer\Package\PackageInterface; use Composer\Package\PackageInterface;
use Composer\Util\Filesystem; use Composer\Util\Filesystem;
use Composer\Util\RemoteFilesystem;
/** /**
* Base downloader for file packages * Base downloader for file packages
@ -76,7 +76,7 @@ abstract class FileDownloader implements DownloaderInterface
} }
$rfs = new RemoteFilesystem($this->io); $rfs = new RemoteFilesystem($this->io);
$rfs->copy($package->getSourceUrl(), $fileName, $url); $rfs->copy($package->getSourceUrl(), $url, $fileName);
$this->io->write(''); $this->io->write('');
if (!file_exists($fileName)) { if (!file_exists($fileName)) {

View File

@ -14,6 +14,7 @@ namespace Composer\Repository\Vcs;
use Composer\IO\IOInterface; use Composer\IO\IOInterface;
use Composer\Util\ProcessExecutor; use Composer\Util\ProcessExecutor;
use Composer\Util\RemoteFilesystem;
/** /**
* A driver implementation for driver with authorization interaction. * A driver implementation for driver with authorization interaction.
@ -25,9 +26,6 @@ abstract class VcsDriver
protected $url; protected $url;
protected $io; protected $io;
protected $process; protected $process;
private $firstCall;
private $contentUrl;
private $content;
/** /**
* Constructor. * Constructor.
@ -41,7 +39,6 @@ abstract class VcsDriver
$this->url = $url; $this->url = $url;
$this->io = $io; $this->io = $io;
$this->process = $process ?: new ProcessExecutor; $this->process = $process ?: new ProcessExecutor;
$this->firstCall = true;
} }
/** /**
@ -68,85 +65,7 @@ abstract class VcsDriver
*/ */
protected function getContents($url) protected function getContents($url)
{ {
$this->contentUrl = $url; $rfs = new RemoteFilesystem($this->io);
$auth = $this->io->getAuthorization($this->url); return $rfs->getContents($this->url, $url, false);
$params = array();
// add authorization to curl options
if ($this->io->hasAuthorization($this->url)) {
$authStr = base64_encode($auth['username'] . ':' . $auth['password']);
$params['http'] = array('header' => "Authorization: Basic $authStr\r\n");
} else if (null !== $this->io->getLastUsername()) {
$authStr = base64_encode($this->io->getLastUsername() . ':' . $this->io->getLastPassword());
$params['http'] = array('header' => "Authorization: Basic $authStr\r\n");
$this->io->setAuthorization($this->url, $this->io->getLastUsername(), $this->io->getLastPassword());
}
$ctx = stream_context_create($params);
stream_context_set_params($ctx, array("notification" => array($this, 'callbackGet')));
$content = @file_get_contents($url, false, $ctx);
// content get after authorization
if (false === $content) {
$content = $this->content;
$this->content = null;
$this->contentUrl = null;
}
return $content;
}
/**
* Get notification action.
*
* @param integer $notificationCode The notification code
* @param integer $severity The severity level
* @param string $message The message
* @param integer $messageCode The message code
* @param integer $bytesTransferred The loaded size
* @param integer $bytesMax The total size
*/
protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax)
{
switch ($notificationCode) {
case STREAM_NOTIFY_AUTH_REQUIRED:
case STREAM_NOTIFY_FAILURE:
// for private repository returning 404 error when the authorization is incorrect
$auth = $this->io->getAuthorization($this->url);
$ps = $this->firstCall && 404 === $messageCode
&& null === $this->io->getLastUsername()
&& null === $auth['username'];
if (404 === $messageCode && !$this->firstCall) {
throw new \RuntimeException("The '" . $this->contentUrl . "' URL not found");
}
$this->firstCall = false;
// get authorization informations
if (401 === $messageCode || $ps) {
if (!$this->io->isInteractive()) {
$mess = "The '" . $this->contentUrl . "' URL not found";
if (401 === $code || $ps) {
$mess = "The '" . $this->contentUrl . "' URL required the authorization.\nYou must be used the interactive console";
}
throw new \RuntimeException($mess);
}
$this->io->write(array('', "Authorization for <info>" . $this->contentUrl . "</info>:"));
$username = $this->io->ask(' Username: ');
$password = $this->io->askAndHideAnswer(' Password: ');
$this->io->setAuthorization($this->url, $username, $password);
$this->content = $this->getContents($this->contentUrl);
}
break;
default:
break;
}
} }
} }

View File

@ -19,11 +19,14 @@ use Composer\IO\IOInterface;
*/ */
class RemoteFilesystem class RemoteFilesystem
{ {
protected $io; private $io;
private $firstCall;
private $bytesMax; private $bytesMax;
private $originUrl; private $originUrl;
private $fileUrl; private $fileUrl;
private $fileName; private $fileName;
private $content;
private $progess;
/** /**
* Constructor. * Constructor.
@ -38,19 +41,51 @@ class RemoteFilesystem
/** /**
* Copy the remote file in local. * Copy the remote file in local.
* *
* @param string $originUrl The origin URL * @param string $originUrl The orgin URL
* @param string $fileName The local filename
* @param string $fileUrl The file URL * @param string $fileUrl The file URL
* * @param string $fileName the local filename
* @throws \RuntimeException When opensll extension is disabled * @param boolean $progess Display the progression
*/ */
public function copy($originUrl, $fileName, $fileUrl) public function copy($originUrl, $fileUrl, $fileName, $progess = true)
{
$this->get($originUrl, $fileUrl, $fileName, $progess);
}
/**
* Get the content.
*
* @param string $originUrl The orgin URL
* @param string $fileUrl The file URL
* @param boolean $progess Display the progression
*
* @return false|string The content
*/
public function getContents($originUrl, $fileUrl, $progess = true)
{
$this->get($originUrl, $fileUrl, null, $progess);
return $this->content;
}
/**
* Get file content or copy action.
*
* @param string $originUrl The orgin URL
* @param string $fileUrl The file URL
* @param string $fileName the local filename
* @param boolean $progess Display the progression
*
* @throws \RuntimeException When the openssl extension is disabled
*/
protected function get($originUrl, $fileUrl, $fileName = null, $progess = true)
{ {
$this->firstCall = true; $this->firstCall = true;
$this->originUrl = $originUrl;
$this->fileName = $fileName;
$this->fileUrl = $fileUrl;
$this->bytesMax = 0; $this->bytesMax = 0;
$this->content = null;
$this->originUrl = $originUrl;
$this->fileUrl = $fileUrl;
$this->fileName = $fileName;
$this->progress = $progess;
// Handle system proxy // Handle system proxy
$params = array('http' => array()); $params = array('http' => array());
@ -69,19 +104,36 @@ class RemoteFilesystem
); );
} }
// add authorization in context
if ($this->io->hasAuthorization($originUrl)) { if ($this->io->hasAuthorization($originUrl)) {
$auth = $this->io->getAuthorization($originUrl); $auth = $this->io->getAuthorization($originUrl);
$authStr = base64_encode($auth['username'] . ':' . $auth['password']); $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
$params['http'] = array_merge($params['http'], array('header' => "Authorization: Basic $authStr\r\n")); $params['http'] = array_merge($params['http'], array('header' => "Authorization: Basic $authStr\r\n"));
} else if (null !== $this->io->getLastUsername()) {
$authStr = base64_encode($this->io->getLastUsername() . ':' . $this->io->getLastPassword());
$params['http'] = array('header' => "Authorization: Basic $authStr\r\n");
$this->io->setAuthorization($originUrl, $this->io->getLastUsername(), $this->io->getLastPassword());
} }
$ctx = stream_context_create($params); $ctx = stream_context_create($params);
stream_context_set_params($ctx, array("notification" => array($this, 'callbackGet'))); stream_context_set_params($ctx, array("notification" => array($this, 'callbackGet')));
if ($this->progress) {
$this->io->overwrite(" Downloading: <comment>connection...</comment>", false); $this->io->overwrite(" Downloading: <comment>connection...</comment>", false);
}
if (null !== $fileName) {
@copy($fileUrl, $fileName, $ctx); @copy($fileUrl, $fileName, $ctx);
} else {
$this->content = @file_get_contents($fileUrl, false, $ctx);
}
if ($this->progress) {
$this->io->overwrite(" Downloading", false); $this->io->overwrite(" Downloading", false);
} }
}
/** /**
* Get notification action. * Get notification action.
@ -100,8 +152,7 @@ class RemoteFilesystem
case STREAM_NOTIFY_FAILURE: case STREAM_NOTIFY_FAILURE:
// for private repository returning 404 error when the authorization is incorrect // for private repository returning 404 error when the authorization is incorrect
$auth = $this->io->getAuthorization($this->originUrl); $auth = $this->io->getAuthorization($this->originUrl);
$ps = $this->firstCall && 404 === $messageCode $ps = $this->firstCall && 404 === $messageCode && null === $auth['username'];
&& null === $auth['username'];
if (404 === $messageCode && !$this->firstCall) { if (404 === $messageCode && !$this->firstCall) {
throw new \RuntimeException("The '" . $this->fileUrl . "' URL not found"); throw new \RuntimeException("The '" . $this->fileUrl . "' URL not found");
@ -112,21 +163,21 @@ class RemoteFilesystem
// get authorization informations // get authorization informations
if (401 === $messageCode || $ps) { if (401 === $messageCode || $ps) {
if (!$this->io->isInteractive()) { if (!$this->io->isInteractive()) {
$mess = "The '" . $this->fileUrl . "' URL not found"; $mess = "The '" . $this->fileUrl . "' URL was not found";
if (401 === $code || $ps) { if (401 === $code || $ps) {
$mess = "The '" . $this->fileUrl . "' URL required the authorization.\nYou must be used the interactive console"; $mess = "The '" . $this->fileUrl . "' URL required the authorization.\nYou must be using the interactive console";
} }
throw new \RuntimeException($mess); throw new \RuntimeException($mess);
} }
$this->io->overwrite(' Authorization required:'); $this->io->overwrite(' Authorization required (<info>' .$this->getHostname($this->fileUrl).'</info>):');
$username = $this->io->ask(' Username: '); $username = $this->io->ask(' Username: ');
$password = $this->io->askAndHideAnswer(' Password: '); $password = $this->io->askAndHideAnswer(' Password: ');
$this->io->setAuthorization($this->originUrl, $username, $password); $this->io->setAuthorization($this->originUrl, $username, $password);
$this->copy($this->originUrl, $this->fileName, $this->fileUrl); $this->content = $this->get($this->originUrl, $this->fileUrl, $this->fileName, $this->progess);
} }
break; break;
@ -137,7 +188,7 @@ class RemoteFilesystem
break; break;
case STREAM_NOTIFY_PROGRESS: case STREAM_NOTIFY_PROGRESS:
if ($this->bytesMax > 0) { if ($this->bytesMax > 0 && $this->progress) {
$progression = 0; $progression = 0;
if ($this->bytesMax > 0) { if ($this->bytesMax > 0) {
@ -154,4 +205,19 @@ class RemoteFilesystem
break; break;
} }
} }
/**
* Get the hostname.
*
* @param string $url The file URL
*
* @return string The hostname
*/
protected function getHostname($url)
{
$host = substr($url, strpos($url, '://') + 3);
$host = substr($host, 0, strpos($host, '/'));
return $host;
}
} }