Skip to content

Commit

Permalink
Improved phar activator for windows (make the phar available in the p…
Browse files Browse the repository at this point in the history
…roject directory)
  • Loading branch information
ThomasWeinert committed Oct 15, 2017
1 parent d5474e3 commit a19bf71
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 1 deletion.
8 changes: 8 additions & 0 deletions src/shared/file/PharActivatorFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,12 @@ public function getSymlinkPharActivator() {
return new SymlinkPharActivator();
}


/**
* @return WindowsPharActivator
*/
public function getWindowsPharActivator() {
return new WindowsPharActivator(file_get_contents(__DIR__ . '/../../../conf/pharBat.template'));
}

}
2 changes: 1 addition & 1 deletion src/shared/file/PharActivatorLocator.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public function __construct(PharActivatorFactory $factory) {
*/
public function getPharActivator(Environment $environment) {
if ($environment instanceof WindowsEnvironment) {
return $this->factory->getBatPharActivator();
return $this->factory->getWindowsPharActivator();
}

return $this->factory->getSymlinkPharActivator();
Expand Down
73 changes: 73 additions & 0 deletions src/shared/file/WindowsPharActivator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

namespace PharIo\Phive;

use PharIo\FileSystem\Filename;

/**
* The WindowsPharActivator tries to set a hardlink for the phar file.
* If that works it will add a bat file for the link, for
* the original phar file, otherwise.
*/
class WindowsPharActivator implements PharActivator {

const PHAR_PLACEHOLDER = '##PHAR_FILENAME##';

private $template;

/**
* @param string $template
*/
public function __construct($template) {
$this->template = $template;
}

/**
* @param Filename $pharLocation
* @param Filename $linkDestination
*
* @return Filename
*/
public function activate(Filename $pharLocation, Filename $linkDestination) {
$this->ensureDestinationIsWritable($linkDestination);

$destination = new Filename($linkDestination->asString().'.phar');
if ($this->addFileLink($pharLocation, $destination)) {
$template = str_replace(self::PHAR_PLACEHOLDER, $destination->asString(), $this->template);
} else {
$template = str_replace(self::PHAR_PLACEHOLDER, $pharLocation->asString(), $this->template);
}
$linkFilename = new Filename($linkDestination->asString().'.bat');
file_put_contents($linkFilename, $template);
return $destination;
}

/**
* Set a windows hardlink
*
* @param Filename $source
* @param Filename $target
* @return bool
*/
private function addFileLink(Filename $source, Filename $target) {
$output = [];
$returnValue = 0;
exec(
'mklink /H '.escapeshellarg($source).' '.escapeshellarg($target),
$output,
$returnValue
);
return $returnValue === 0;
}

/**
* @param Filename $destination
*
* @throws FileNotWritableException
*/
private function ensureDestinationIsWritable(Filename $destination) {
if (!$destination->getDirectory()->isWritable()) {
throw new FileNotWritableException(sprintf('File %s is not writable.', $destination->asString()));
}
}
}

0 comments on commit a19bf71

Please sign in to comment.