From 692d2a8b6f3626bbc2b471f96e6d05ec29f1f1d1 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 7 Mar 2011 21:33:36 -0800 Subject: [PATCH] Arcanist: Apply symlink patches correctly Summary: When an arcbundle includes a symlink, we fail to apply it correctly when applying to a subversion working copy. Test Plan: created a diff which added a symlink, removed it locally, bundled and applied the patch, got a good symlink out Reviewed By: aran Reviewers: aran CC: epriestley, aran Differential Revision: 63 --- src/parser/diff/change/ArcanistDiffChange.php | 13 +++++++++ src/workflow/patch/ArcanistPatchWorkflow.php | 27 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/parser/diff/change/ArcanistDiffChange.php b/src/parser/diff/change/ArcanistDiffChange.php index ff7ced1d..2a2a3a7f 100644 --- a/src/parser/diff/change/ArcanistDiffChange.php +++ b/src/parser/diff/change/ArcanistDiffChange.php @@ -225,5 +225,18 @@ class ArcanistDiffChange { return implode("\n", $summary); } + public function getSymlinkTarget() { + if ($this->getFileType() != ArcanistDiffChangeType::FILE_SYMLINK) { + throw new Exception("Not a symlink!"); + } + $hunks = $this->getHunks(); + $hunk = reset($hunks); + $corpus = $hunk->getCorpus(); + $match = null; + if (!preg_match('/^\+(?:link )?(.*)$/m', $corpus, $match)) { + throw new Exception("Failed to extract link target!"); + } + return trim($match[1]); + } } diff --git a/src/workflow/patch/ArcanistPatchWorkflow.php b/src/workflow/patch/ArcanistPatchWorkflow.php index 71ec07e7..963f50cb 100644 --- a/src/workflow/patch/ArcanistPatchWorkflow.php +++ b/src/workflow/patch/ArcanistPatchWorkflow.php @@ -177,11 +177,21 @@ EOTEXT $patches = array(); $propset = array(); $adds = array(); + $symlinks = array(); $changes = $bundle->getChanges(); foreach ($changes as $change) { $type = $change->getType(); $should_patch = true; + + $filetype = $change->getFileType(); + switch ($filetype) { + case ArcanistDiffChangeType::FILE_SYMLINK: + $should_patch = false; + $symlinks[] = $change; + break; + } + switch ($type) { case ArcanistDiffChangeType::TYPE_MOVE_AWAY: case ArcanistDiffChangeType::TYPE_MULTICOPY: @@ -270,6 +280,23 @@ EOTEXT $delete)); } + foreach ($symlinks as $symlink) { + $link_target = $symlink->getSymlinkTarget(); + $link_path = $symlink->getCurrentPath(); + switch ($symlink->getType()) { + case ArcanistDiffChangeType::TYPE_ADD: + case ArcanistDiffChangeType::TYPE_MODIFY: + case ArcanistDiffChangeType::TYPE_MOVE_HERE: + case ArcanistDiffChangeType::TYPE_COPY_HERE: + execx( + '(cd %s && ln -sf %s %s)', + $repository_api->getPath(), + $link_target, + $link_path); + break; + } + } + foreach ($patches as $path => $patch) { $tmp = new TempFile(); Filesystem::writeFile($tmp, $patch);