Merge remote-tracking branch 'kocsismate/feature-bin-compat'
commit
c9b51a5751
|
@ -102,6 +102,15 @@ downloads. When the garbage collection is periodically ran, this is the maximum
|
||||||
size the cache will be able to use. Older (less used) files will be removed
|
size the cache will be able to use. Older (less used) files will be removed
|
||||||
first until the cache fits.
|
first until the cache fits.
|
||||||
|
|
||||||
|
## bin-compat
|
||||||
|
|
||||||
|
Defaults to `auto`. Determines the compatibility of the binaries to be installed.
|
||||||
|
If it is `auto` then Composer tries to automatically guess which compatibility mode
|
||||||
|
to use. If it is `nosymlink` then the binaries will be compatible with Unix-based
|
||||||
|
operating systems (useful for cases when symlinks are not available).
|
||||||
|
If its value is `full` then both .bat files for Windows and scripts for Unix-based
|
||||||
|
operating systems will be installed for each binary.
|
||||||
|
|
||||||
## prepend-autoloader
|
## prepend-autoloader
|
||||||
|
|
||||||
Defaults to `true`. If `false`, the Composer autoloader will not be prepended to
|
Defaults to `true`. If `false`, the Composer autoloader will not be prepended to
|
||||||
|
|
|
@ -186,6 +186,10 @@
|
||||||
"type": ["string", "integer"],
|
"type": ["string", "integer"],
|
||||||
"description": "The cache max size for the files cache, defaults to \"300MiB\"."
|
"description": "The cache max size for the files cache, defaults to \"300MiB\"."
|
||||||
},
|
},
|
||||||
|
"bin-compat": {
|
||||||
|
"enum": ["auto", "nosymlink", "full"],
|
||||||
|
"description": "The compatibility of the binaries, defaults to \"auto\" (automatically guessed) and can be \"nosymlink\" (compatible with Unix-based systems) or \"full\" (compatible with both Windows and Unix-based systems)."
|
||||||
|
},
|
||||||
"discard-changes": {
|
"discard-changes": {
|
||||||
"type": ["string", "boolean"],
|
"type": ["string", "boolean"],
|
||||||
"description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"."
|
"description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"."
|
||||||
|
|
|
@ -307,6 +307,10 @@ EOT
|
||||||
function ($val) { return preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $val) > 0; },
|
function ($val) { return preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $val) > 0; },
|
||||||
function ($val) { return $val; },
|
function ($val) { return $val; },
|
||||||
),
|
),
|
||||||
|
'bin-compat' => array(
|
||||||
|
function ($val) { return in_array($val, array('auto', 'nosymlink', 'full')); },
|
||||||
|
function ($val) { return $val; }
|
||||||
|
),
|
||||||
'discard-changes' => array(
|
'discard-changes' => array(
|
||||||
function ($val) { return in_array($val, array('stash', 'true', 'false', '1', '0'), true); },
|
function ($val) { return in_array($val, array('stash', 'true', 'false', '1', '0'), true); },
|
||||||
function ($val) {
|
function ($val) {
|
||||||
|
|
|
@ -36,6 +36,7 @@ class Config
|
||||||
'cache-ttl' => 15552000, // 6 months
|
'cache-ttl' => 15552000, // 6 months
|
||||||
'cache-files-ttl' => null, // fallback to cache-ttl
|
'cache-files-ttl' => null, // fallback to cache-ttl
|
||||||
'cache-files-maxsize' => '300MiB',
|
'cache-files-maxsize' => '300MiB',
|
||||||
|
'bin-compat' => 'auto',
|
||||||
'discard-changes' => false,
|
'discard-changes' => false,
|
||||||
'autoloader-suffix' => null,
|
'autoloader-suffix' => null,
|
||||||
'optimize-autoloader' => false,
|
'optimize-autoloader' => false,
|
||||||
|
@ -218,6 +219,17 @@ class Config
|
||||||
case 'home':
|
case 'home':
|
||||||
return rtrim($this->process($this->config[$key], $flags), '/\\');
|
return rtrim($this->process($this->config[$key], $flags), '/\\');
|
||||||
|
|
||||||
|
case 'bin-compat':
|
||||||
|
$value = $this->getComposerEnv('COMPOSER_BIN_COMPAT') ?: $this->config[$key];
|
||||||
|
|
||||||
|
if (!in_array($value, array('auto', 'nosymlink', 'full'))) {
|
||||||
|
throw new \RuntimeException(
|
||||||
|
"Invalid value for 'bin-compat': {$value}. Expected auto, nosymlink, full"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
|
||||||
case 'discard-changes':
|
case 'discard-changes':
|
||||||
if ($env = $this->getComposerEnv('COMPOSER_DISCARD_CHANGES')) {
|
if ($env = $this->getComposerEnv('COMPOSER_DISCARD_CHANGES')) {
|
||||||
if (!in_array($env, array('stash', 'true', 'false', '1', '0'), true)) {
|
if (!in_array($env, array('stash', 'true', 'false', '1', '0'), true)) {
|
||||||
|
|
|
@ -18,6 +18,7 @@ use Composer\Repository\InstalledRepositoryInterface;
|
||||||
use Composer\Package\PackageInterface;
|
use Composer\Package\PackageInterface;
|
||||||
use Composer\Util\Filesystem;
|
use Composer\Util\Filesystem;
|
||||||
use Composer\Util\ProcessExecutor;
|
use Composer\Util\ProcessExecutor;
|
||||||
|
use Composer\Util\Symlink;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Package installation manager.
|
* Package installation manager.
|
||||||
|
@ -34,6 +35,7 @@ class LibraryInstaller implements InstallerInterface
|
||||||
protected $io;
|
protected $io;
|
||||||
protected $type;
|
protected $type;
|
||||||
protected $filesystem;
|
protected $filesystem;
|
||||||
|
protected $binCompat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes library installer.
|
* Initializes library installer.
|
||||||
|
@ -53,6 +55,7 @@ class LibraryInstaller implements InstallerInterface
|
||||||
$this->filesystem = $filesystem ?: new Filesystem();
|
$this->filesystem = $filesystem ?: new Filesystem();
|
||||||
$this->vendorDir = rtrim($composer->getConfig()->get('vendor-dir'), '/');
|
$this->vendorDir = rtrim($composer->getConfig()->get('vendor-dir'), '/');
|
||||||
$this->binDir = rtrim($composer->getConfig()->get('bin-dir'), '/');
|
$this->binDir = rtrim($composer->getConfig()->get('bin-dir'), '/');
|
||||||
|
$this->binCompat = $composer->getConfig()->get('bin-compat');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -219,38 +222,53 @@ class LibraryInstaller implements InstallerInterface
|
||||||
$this->io->writeError(' Skipped installation of bin '.$bin.' for package '.$package->getName().': name conflicts with an existing file');
|
$this->io->writeError(' Skipped installation of bin '.$bin.' for package '.$package->getName().': name conflicts with an existing file');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
|
||||||
// add unixy support for cygwin and similar environments
|
if ($this->binCompat === "auto") {
|
||||||
if ('.bat' !== substr($binPath, -4)) {
|
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
||||||
file_put_contents($link, $this->generateUnixyProxyCode($binPath, $link));
|
$this->installFullBinaries($binPath, $link, $bin, $package);
|
||||||
@chmod($link, 0777 & ~umask());
|
} else {
|
||||||
$link .= '.bat';
|
$this->installSymlinkBinaries($binPath, $link);
|
||||||
if (file_exists($link)) {
|
|
||||||
$this->io->writeError(' Skipped installation of bin '.$bin.'.bat proxy for package '.$package->getName().': a .bat proxy was already installed');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!file_exists($link)) {
|
} elseif ($this->binCompat === "nosymlink") {
|
||||||
file_put_contents($link, $this->generateWindowsProxyCode($binPath, $link));
|
$this->installUnixyProxyBinaries($binPath, $link);
|
||||||
}
|
} elseif ($this->binCompat === "full") {
|
||||||
} else {
|
$this->installFullBinaries($binPath, $link, $bin, $package);
|
||||||
$cwd = getcwd();
|
|
||||||
try {
|
|
||||||
// under linux symlinks are not always supported for example
|
|
||||||
// when using it in smbfs mounted folder
|
|
||||||
$relativeBin = $this->filesystem->findShortestPath($link, $binPath);
|
|
||||||
chdir(dirname($link));
|
|
||||||
if (false === @symlink($relativeBin, $link)) {
|
|
||||||
throw new \ErrorException();
|
|
||||||
}
|
|
||||||
} catch (\ErrorException $e) {
|
|
||||||
file_put_contents($link, $this->generateUnixyProxyCode($binPath, $link));
|
|
||||||
}
|
|
||||||
chdir($cwd);
|
|
||||||
}
|
}
|
||||||
@chmod($link, 0777 & ~umask());
|
@chmod($link, 0777 & ~umask());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function installFullBinaries($binPath, $link, $bin, PackageInterface $package)
|
||||||
|
{
|
||||||
|
// add unixy support for cygwin and similar environments
|
||||||
|
if ('.bat' !== substr($binPath, -4)) {
|
||||||
|
$this->installUnixyProxyBinaries($binPath, $link);
|
||||||
|
@chmod($link, 0777 & ~umask());
|
||||||
|
$link .= '.bat';
|
||||||
|
if (file_exists($link)) {
|
||||||
|
$this->io->writeError(' Skipped installation of bin '.$bin.'.bat proxy for package '.$package->getName().': a .bat proxy was already installed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!file_exists($link)) {
|
||||||
|
file_put_contents($link, $this->generateWindowsProxyCode($binPath, $link));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function installSymlinkBinaries($binPath, $link)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$symlink = new Symlink($this->filesystem);
|
||||||
|
$symlink->symlinkBin($binPath, $link);
|
||||||
|
} catch (\ErrorException $e) {
|
||||||
|
$this->installUnixyProxyBinaries($binPath, $link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function installUnixyProxyBinaries($binPath, $link)
|
||||||
|
{
|
||||||
|
file_put_contents($link, $this->generateUnixyProxyCode($binPath, $link));
|
||||||
|
}
|
||||||
|
|
||||||
protected function removeBinaries(PackageInterface $package)
|
protected function removeBinaries(PackageInterface $package)
|
||||||
{
|
{
|
||||||
$binaries = $this->getBinaries($package);
|
$binaries = $this->getBinaries($package);
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer\Util;
|
||||||
|
|
||||||
|
use Composer\Config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Kocsis Máté <kocsismate@woohoolabs.com>
|
||||||
|
*/
|
||||||
|
class Symlink
|
||||||
|
{
|
||||||
|
protected $filesystem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the symlinking utility.
|
||||||
|
*
|
||||||
|
* @param Filesystem $filesystem
|
||||||
|
*/
|
||||||
|
public function __construct(Filesystem $filesystem = null)
|
||||||
|
{
|
||||||
|
$this->filesystem = $filesystem ?: new Filesystem();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a symlink for a binary file at a given path.
|
||||||
|
*
|
||||||
|
* @param string $binPath The path of the binary file to be symlinked
|
||||||
|
* @param string $link The path where the symlink should be created
|
||||||
|
* @throws \ErrorException
|
||||||
|
*/
|
||||||
|
public function symlinkBin($binPath, $link)
|
||||||
|
{
|
||||||
|
$cwd = getcwd();
|
||||||
|
|
||||||
|
$relativeBin = $this->filesystem->findShortestPath($link, $binPath);
|
||||||
|
chdir(dirname($link));
|
||||||
|
$result = @symlink($relativeBin, $link);
|
||||||
|
|
||||||
|
chdir($cwd);
|
||||||
|
if ($result === false) {
|
||||||
|
throw new \ErrorException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue