diff --git a/composer.json b/composer.json index 22c3e02d..c3aa7bfe 100644 --- a/composer.json +++ b/composer.json @@ -12,9 +12,10 @@ "bin/the-build-installer" ], "require": { - "palantirnet/phing-drush-task": "^1.1", + "cweagans/composer-patches": "^1.7", "drupal/coder": "^8.3.6", "drush/drush": "^9 || ^10", + "palantirnet/phing-drush-task": "^1.1", "pear/http_request2": "^2.3", "pear/versioncontrol_git": "@dev", "phing/phing": "^2.14", @@ -27,5 +28,12 @@ }, "config": { "sort-packages": true + }, + "extra": { + "patches": { + "phing/phing": { + "Support relative symliks in Phing": "https://raw.githubusercontent.com/palantirnet/the-build/7cdc28b6019fb88a0604261366f9ea35f1e21d96/patches/phing-relative-symlinks.patch" + } + } } } diff --git a/defaults/install/build.xml b/defaults/install/build.xml index 209c358c..c5267f3c 100644 --- a/defaults/install/build.xml +++ b/defaults/install/build.xml @@ -45,7 +45,7 @@ - + diff --git a/patches/README.md b/patches/README.md new file mode 100644 index 00000000..cad5547e --- /dev/null +++ b/patches/README.md @@ -0,0 +1,9 @@ +### phing-relative-symlinks.patch + +Source: [https://github.com/phingofficial/phing/pull/695](https://github.com/phingofficial/phing/pull/695) + +This patch updates Phing's SymlinkTask to allow creating relative symlinks, using the syntax: + +``` + +``` diff --git a/patches/phing-relative-symlinks.patch b/patches/phing-relative-symlinks.patch new file mode 100644 index 00000000..1733b4ff --- /dev/null +++ b/patches/phing-relative-symlinks.patch @@ -0,0 +1,76 @@ +diff --git a/classes/phing/tasks/ext/SymlinkTask.php b/classes/phing/tasks/ext/SymlinkTask.php +index f132b4f747..87844a0d09 100644 +--- a/classes/phing/tasks/ext/SymlinkTask.php ++++ b/classes/phing/tasks/ext/SymlinkTask.php +@@ -206,6 +206,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() +@@ -235,11 +275,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); +@@ -300,6 +336,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); + diff --git a/src/TheBuild/IncludeResourceTask.php b/src/TheBuild/IncludeResourceTask.php index 43d43feb..a3a75215 100644 --- a/src/TheBuild/IncludeResourceTask.php +++ b/src/TheBuild/IncludeResourceTask.php @@ -32,6 +32,12 @@ class IncludeResourceTask extends \Task { */ protected $dest = NULL; + /** + * Whether to create relative symlinks + * + * @var boolean + */ + protected $relative = true; /** * Init tasks. @@ -44,6 +50,10 @@ public function init() { if (!is_null($mode)) { $this->setMode($mode); } + $relative = $this->getProject()->getProperty('includeresource.relative'); + if (!is_null($relative)) { + $this->setRelative($relative); + } } @@ -70,7 +80,11 @@ public function main() { } else { $this->log(sprintf("Linking '%s' to '%s'", $this->source->getPath(), $this->dest->getPath())); - FileSystem::getFileSystem()->symlink($this->source->getPath(), $this->dest->getPath()); + $symlink_task = $this->project->createTask("symlink"); + $symlink_task->setTarget($this->source->getPath()); + $symlink_task->setLink($this->dest->getPath()); + $symlink_task->setRelative($this->relative); + $symlink_task->main(); } } @@ -122,4 +136,12 @@ public function setDest(PhingFile $dest) { $this->dest = $dest; } + /** + * @param boolean $relative + */ + public function setRelative($relative) + { + $this->relative = $relative; + } + } diff --git a/targets/drupal.xml b/targets/drupal.xml index 7821f614..19161f98 100644 --- a/targets/drupal.xml +++ b/targets/drupal.xml @@ -183,10 +183,25 @@ Or, you can specify the export file directly: the permissions, the database will be created. -->