diff --git a/NEWS.mdtext b/NEWS.mdtext index bb50f63..37ae1a7 100644 --- a/NEWS.mdtext +++ b/NEWS.mdtext @@ -8,6 +8,7 @@ or newer to properly run this version of Indefero! - Indefero's issue tracker can now bi-directionally link issues with variable, configurable terms, such as "is related to", "is blocked by" or "is duplicated by" (issue 638) - Mercurial source views now show parent revisions (if any) and detailed change information +- Subversion source views now show detailed change information (issue 622) - File download URLs now contain the file name rather than the upload id; old links still work though (issues 559 and 686) - Display monotone file and directory attributes in the tree and file view (needs a monotone with an interface version of 13.1 or newer) diff --git a/src/IDF/Scm/Svn.php b/src/IDF/Scm/Svn.php index 340fe14..9432843 100644 --- a/src/IDF/Scm/Svn.php +++ b/src/IDF/Scm/Svn.php @@ -479,6 +479,88 @@ class IDF_Scm_Svn extends IDF_Scm return self::shell_exec('IDF_Scm_Svn::getDiff', $cmd); } + /** + * @see IDF_Scm::getChanges() + */ + public function getChanges($commit) + { + if ($this->validateRevision($commit) != IDF_Scm::REVISION_VALID) { + return null; + } + $cmd = sprintf(Pluf::f('svn_path', 'svn').' log --xml -v --no-auth-cache -r %s --username=%s --password=%s %s', + escapeshellarg($commit), + escapeshellarg($this->username), + escapeshellarg($this->password), + escapeshellarg($this->repo)); + $out = array(); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + $out = self::shell_exec('IDF_Scm_Svn::getChanges', $cmd); + $xml = simplexml_load_string($out); + if (count($xml) == 0) { + return null; + } + $entry = current($xml); + + $return = (object) array( + 'additions' => array(), + 'deletions' => array(), + 'patches' => array(), + // while SVN has support for attributes, we cannot see their changes + // in the log's XML unfortunately + 'properties' => array(), + 'copies' => array(), + 'renames' => array(), + ); + + foreach ($entry->paths->path as $p) { + $path = (string) $p; + foreach ($p->attributes() as $k => $v) { + $key = (string) $k; + $val = (string) $v; + if ($key != 'action') + continue; + if ($val == 'M') + $return->patches[] = $path; + else if ($val == 'A') + $return->additions[] = $path; + else if ($val == 'D') + $return->deletions[] = $path; + } + } + + // copies are treated as renames if they have an add _and_ a drop; + // only if they only have an add, but no drop, they're treated as copies + foreach ($xml->paths as $path) { + $trg = (string) $path; + $src = null; + foreach ($path->attributes() as $k => $v) { + if ((string) $k == 'copyfrom-path') { + $src = (string) $v; + break; + } + } + + if ($src == null) + continue; + + $srcidx = array_search($src, $return->deletions); + $trgidx = array_search($trg, $return->additions); + if ($srcidx !== false && $trgidx !== false) { + $return->renames[$src] = $trg; + unset($return->deletions[$srcidx]); + unset($return->additions[$trgidx]); + continue; + } + if ($srcidx === false && $trgidx !== false) { + $return->copies[$src] = $trg; + unset($return->additions[$trgidx]); + continue; + } + // file sutures (counter-operation to copy) not supported + } + + return $return; + } /** * Get latest changes.