Skip to content

Commit

Permalink
Relative symlinking (#695)
Browse files Browse the repository at this point in the history
  • Loading branch information
verbruggenalex authored and mrook committed Feb 14, 2018
1 parent 7a128c6 commit 1adb2ad
Showing 1 changed file with 46 additions and 5 deletions.
51 changes: 46 additions & 5 deletions classes/phing/tasks/ext/SymlinkTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,46 @@ public function isRelative()
return $this->relative;
}

/**
* Given an existing path, convert it to a path relative to a given starting path.
*
* @param string $endPath Absolute path of target
* @param string $startPath Absolute path where traversal begins
*
* @return string Path of target relative to starting path
*/
public function makePathRelative($endPath, $startPath)
{
// Normalize separators on Windows
if ('\\' === DIRECTORY_SEPARATOR) {
$endPath = str_replace('\\', '/', $endPath);
$startPath = str_replace('\\', '/', $startPath);
}

// Split the paths into arrays
$startPathArr = explode('/', trim($startPath, '/'));
$endPathArr = explode('/', trim($endPath, '/'));

// Find for which directory the common path stops
$index = 0;
while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
++$index;
}

// Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels)
$depth = count($startPathArr) - $index;

// Repeated "../" for each level need to reach the common path
$traverser = str_repeat('../', $depth);

$endPathRemainder = implode('/', array_slice($endPathArr, $index));

// Construct $endPath from traversing to the common path, then to the remaining $endPath
$relativePath = $traverser.('' !== $endPathRemainder ? $endPathRemainder.'/' : '');

return '' === $relativePath ? './' : $relativePath;
}

/**
* Generates an array of directories / files to be linked
* If _filesets is empty, returns getTarget()
Expand Down Expand Up @@ -234,11 +274,7 @@ protected function getMap()
throw new BuildException('Link must be an existing directory when using fileset');
}

if ($this->isRelative()) {
$fromDir = $fs->getDir($this->getProject())->getPath();
} else {
$fromDir = $fs->getDir($this->getProject())->getAbsolutePath();
}
$fromDir = $fs->getDir($this->getProject())->getAbsolutePath();

if (!is_dir($fromDir)) {
$this->log('Directory doesn\'t exist: ' . $fromDir, Project::MSG_WARN);
Expand Down Expand Up @@ -299,6 +335,11 @@ protected function symlink($target, $link)
{
$fs = FileSystem::getFileSystem();

if ($this->isRelative()) {
$link =(new PhingFile($link))->getAbsolutePath();
$target = rtrim($this->makePathRelative($target, dirname($link)), '/');
}

if (is_link($link) && @readlink($link) == $target) {
$this->log('Link exists: ' . $link, Project::MSG_INFO);

Expand Down

0 comments on commit 1adb2ad

Please sign in to comment.