diff --git a/src/repository/api/subversion/ArcanistSubversionAPI.php b/src/repository/api/subversion/ArcanistSubversionAPI.php index 481aecd5..7d4cef26 100644 --- a/src/repository/api/subversion/ArcanistSubversionAPI.php +++ b/src/repository/api/subversion/ArcanistSubversionAPI.php @@ -29,6 +29,8 @@ class ArcanistSubversionAPI extends ArcanistRepositoryAPI { protected $svnInfoRaw = array(); protected $svnDiffRaw = array(); + + private $svnBaseRevisionNumber; public function getSourceControlSystemName() { return 'svn'; @@ -161,7 +163,20 @@ class ArcanistSubversionAPI extends ArcanistRepositoryAPI { public function getSourceControlBaseRevision() { $info = $this->getSVNInfo('/'); - return $info['URL'].'@'.$info['Revision']; + return $info['URL'].'@'.$this->getSVNBaseRevisionNumber(); + } + + public function getSVNBaseRevisionNumber() { + if ($this->svnBaseRevisionNumber) { + return $this->svnBaseRevisionNumber; + } + $info = $this->getSVNInfo('/'); + return $info['Revision']; + } + + public function overrideSVNBaseRevisionNumber($effective_base_revision) { + $this->svnBaseRevisionNumber = $effective_base_revision; + return $this; } public function getBranchName() { diff --git a/src/workflow/diff/ArcanistDiffWorkflow.php b/src/workflow/diff/ArcanistDiffWorkflow.php index f31d6279..a1d75ef5 100644 --- a/src/workflow/diff/ArcanistDiffWorkflow.php +++ b/src/workflow/diff/ArcanistDiffWorkflow.php @@ -201,21 +201,6 @@ EOTEXT $parent = null; - $base_revision = $repository_api->getSourceControlBaseRevision(); - $base_path = $repository_api->getSourceControlPath(); - if ($repository_api instanceof ArcanistGitAPI) { - $info = $this->getGitParentLogInfo(); - if ($info['parent']) { - $parent = $info['parent']; - } - if ($info['base_revision']) { - $base_revision = $info['base_revision']; - } - if ($info['base_path']) { - $base_path = $info['base_path']; - } - } - $paths = $this->generateAffectedPaths(); $lint_result = $this->runLint($paths); @@ -256,6 +241,23 @@ EOTEXT $unit = 'none'; } + // NOTE: This has to happen after generateChanges(), since it may overwrite + // the SVN effective base revision. + $base_revision = $repository_api->getSourceControlBaseRevision(); + $base_path = $repository_api->getSourceControlPath(); + if ($repository_api instanceof ArcanistGitAPI) { + $info = $this->getGitParentLogInfo(); + if ($info['parent']) { + $parent = $info['parent']; + } + if ($info['base_revision']) { + $base_revision = $info['base_revision']; + } + if ($info['base_path']) { + $base_path = $info['base_path']; + } + } + $diff = array( 'changes' => $change_list, 'sourceMachine' => php_uname('n'), @@ -505,26 +507,31 @@ EOTEXT } if ($bases) { - // We have at least one path which isn't new. - $repository_info = $repository_api->getSVNInfo('/'); - $bases['.'] = $repository_info['Revision']; - if ($bases['.']) { - $rev = $bases['.']; - foreach ($bases as $path => $baserev) { - if ($baserev !== $rev) { - $revlist = array(); - foreach ($bases as $path => $baserev) { - $revlist[] = " Revision {$baserev}, {$path}"; - } - $revlist = implode("\n", $revlist); - throw new ArcanistUsageException( - "Base revisions of changed paths are mismatched. Update all ". - "paths to the same base revision before creating a diff: ". - "\n\n". - $revlist); + $rev = reset($bases); + foreach ($bases as $path => $baserev) { + if ($baserev !== $rev) { + $revlist = array(); + foreach ($bases as $path => $baserev) { + $revlist[] = " Revision {$baserev}, {$path}"; } + $revlist = implode("\n", $revlist); + throw new ArcanistUsageException( + "Base revisions of changed paths are mismatched. Update all ". + "paths to the same base revision before creating a diff: ". + "\n\n". + $revlist); } } + + // If you have a change which affects several files, all of which are + // at a consistent base revision, treat that revision as the effective + // base revision. The use case here is that you made a change to some + // file, which updates it to HEAD, but want to be able to change it + // again without updating the entire working copy. This is a little + // sketchy but it arises in Facebook Ops workflows with config files and + // doesn't have any real material tradeoffs (e.g., these patches are + // perfectly applyable). + $repository_api->overrideSVNBaseRevisionNumber($rev); } $changes = $parser->parseSubversionDiff(