Page MenuHomePhorge

No OneTemporary

diff --git a/src/infrastructure/diff/view/PHUIDiffGraphView.php b/src/infrastructure/diff/view/PHUIDiffGraphView.php
index ed4b0acf57..76ae0b2045 100644
--- a/src/infrastructure/diff/view/PHUIDiffGraphView.php
+++ b/src/infrastructure/diff/view/PHUIDiffGraphView.php
@@ -1,213 +1,213 @@
<?php
final class PHUIDiffGraphView extends Phobject {
private $isHead = true;
private $isTail = true;
public function setIsHead($is_head) {
$this->isHead = $is_head;
return $this;
}
public function getIsHead() {
return $this->isHead;
}
public function setIsTail($is_tail) {
$this->isTail = $is_tail;
return $this;
}
public function getIsTail() {
return $this->isTail;
}
public function renderRawGraph(array $parents) {
// This keeps our accumulated information about each line of the
// merge/branch graph.
$graph = array();
// This holds the next commit we're looking for in each column of the
// graph.
$threads = array();
// This is the largest number of columns any row has, i.e. the width of
// the graph.
$count = 0;
foreach ($parents as $cursor => $parent_list) {
$joins = array();
$splits = array();
// Look for some thread which has this commit as the next commit. If
// we find one, this commit goes on that thread. Otherwise, this commit
// goes on a new thread.
$line = '';
$found = false;
$pos = count($threads);
$thread_count = $pos;
for ($n = 0; $n < $thread_count; $n++) {
-
if (empty($threads[$n])) {
$line .= ' ';
continue;
}
if ($threads[$n] == $cursor) {
if ($found) {
$line .= ' ';
$joins[] = $n;
- unset($threads[$n]);
+ $threads[$n] = false;
} else {
$line .= 'o';
$found = true;
$pos = $n;
}
} else {
// We render a "|" for any threads which have a commit that we haven't
// seen yet, this is later drawn as a vertical line.
$line .= '|';
}
}
// If we didn't find the thread this commit goes on, start a new thread.
// We use "o" to mark the commit for the rendering engine, or "^" to
// indicate that there's nothing after it so the line from the commit
// upward should not be drawn.
if (!$found) {
if ($this->getIsHead()) {
$line .= '^';
} else {
$line .= 'o';
foreach ($graph as $k => $meta) {
// Go back across all the lines we've already drawn and add a
// "|" to the end, since this is connected to some future commit
// we don't know about.
for ($jj = strlen($meta['line']); $jj <= $count; $jj++) {
$graph[$k]['line'] .= '|';
}
}
}
}
// Update the next commit on this thread to the commit's first parent.
// This might have the effect of making a new thread.
$threads[$pos] = head($parent_list);
// If we made a new thread, increase the thread count.
$count = max($pos + 1, $count);
// Now, deal with splits (merges). I picked this terms opposite to the
// underlying repository term to confuse you.
foreach (array_slice($parent_list, 1) as $parent) {
$found = false;
// Try to find the other parent(s) in our existing threads. If we find
// them, split to that thread.
foreach ($threads as $idx => $thread_commit) {
if ($thread_commit == $parent) {
$found = true;
$splits[] = $idx;
+ break;
}
}
// If we didn't find the parent, we don't know about it yet. Find the
// first free thread and add it as the "next" commit in that thread.
// This might create a new thread.
if (!$found) {
for ($n = 0; $n < $count; $n++) {
if (empty($threads[$n])) {
break;
}
}
$threads[$n] = $parent;
$splits[] = $n;
$count = max($n + 1, $count);
}
}
$graph[] = array(
'line' => $line,
'split' => $splits,
'join' => $joins,
);
}
// If this is the last page in history, replace any "o" characters at the
// bottom of columns with "x" characters so we do not draw a connecting
// line downward, and replace "^" with an "X" for repositories with
// exactly one commit.
if ($this->getIsTail() && $graph) {
$terminated = array();
foreach (array_reverse(array_keys($graph)) as $key) {
$line = $graph[$key]['line'];
$len = strlen($line);
for ($ii = 0; $ii < $len; $ii++) {
$c = $line[$ii];
if ($c == 'o') {
// If we've already terminated this thread, we don't need to add
// a terminator.
if (isset($terminated[$ii])) {
continue;
}
$terminated[$ii] = true;
// If this thread is joinining some other node here, we don't want
// to terminate it.
if (isset($graph[$key + 1])) {
$joins = $graph[$key + 1]['join'];
if (in_array($ii, $joins)) {
continue;
}
}
$graph[$key]['line'][$ii] = 'x';
} else if ($c != ' ') {
$terminated[$ii] = true;
} else {
unset($terminated[$ii]);
}
}
}
$last = array_pop($graph);
$last['line'] = str_replace('^', 'X', $last['line']);
$graph[] = $last;
}
return array($graph, $count);
}
public function renderGraph(array $parents) {
list($graph, $count) = $this->renderRawGraph($parents);
// Render into tags for the behavior.
foreach ($graph as $k => $meta) {
$graph[$k] = javelin_tag(
'div',
array(
'sigil' => 'commit-graph',
'meta' => $meta,
),
'');
}
Javelin::initBehavior(
'diffusion-commit-graph',
array(
'count' => $count,
));
return $graph;
}
}
diff --git a/src/infrastructure/diff/view/__tests__/PHUIDiffGraphViewTestCase.php b/src/infrastructure/diff/view/__tests__/PHUIDiffGraphViewTestCase.php
index 9bcf9645a3..2b9e4f8097 100644
--- a/src/infrastructure/diff/view/__tests__/PHUIDiffGraphViewTestCase.php
+++ b/src/infrastructure/diff/view/__tests__/PHUIDiffGraphViewTestCase.php
@@ -1,94 +1,117 @@
<?php
final class PHUIDiffGraphViewTestCase extends PhabricatorTestCase {
public function testTailTermination() {
$nodes = array(
'A' => array('B'),
'B' => array('C', 'D', 'E'),
'E' => array(),
'D' => array(),
'C' => array('F', 'G'),
'G' => array(),
'F' => array(),
);
$graph = $this->newGraph($nodes);
$picture = array(
'^',
'o',
'||x',
'|x ',
'o ',
'|x ',
'x ',
);
$this->assertGraph($picture, $graph, pht('Terminating Tree'));
}
public function testReverseTree() {
$nodes = array(
'A' => array('B'),
'C' => array('B'),
'B' => array('D'),
'E' => array('D'),
'F' => array('D'),
'D' => array('G'),
'G' => array(),
);
$graph = $this->newGraph($nodes);
$picture = array(
'^',
'|^',
'o ',
- '|^',
- '||^',
- 'o ',
- 'x',
+ '| ^',
+ '| |^',
+ 'o ',
+ 'x ',
);
$this->assertGraph($picture, $graph, pht('Reverse Tree'));
}
public function testJoinTerminateTree() {
$nodes = array(
'A' => array('D'),
'B' => array('C'),
'C' => array('D'),
'D' => array(),
);
$graph = $this->newGraph($nodes);
$picture = array(
'^',
'|^',
'|o',
'x ',
);
- $this->assertGraph($picture, $graph, pht('Reverse Tree'));
+ $this->assertGraph($picture, $graph, pht('Terminated Tree'));
+ }
+
+ public function testThreeWayGraphJoin() {
+ $nodes = array(
+ 'A' => array('D', 'C', 'B'),
+ 'B' => array('D'),
+ 'C' => array('B', 'E', 'F'),
+ 'D' => array(),
+ 'E' => array(),
+ 'F' => array(),
+ );
+
+ $graph = $this->newGraph($nodes);
+ $picture = array(
+ '^',
+ '||o',
+ '|o|',
+ 'x| ||',
+ ' | x|',
+ ' | x',
+ );
+
+ $this->assertGraph($picture, $graph, pht('Three-Way Tree'));
}
private function newGraph(array $nodes) {
return id(new PHUIDiffGraphView())
->setIsHead(true)
->setIsTail(true)
->renderRawGraph($nodes);
}
private function assertGraph($picture, $graph, $label) {
list($data, $count) = $graph;
$lines = ipull($data, 'line');
$picture = implode("\n", $picture);
$lines = implode("\n", $lines);
$this->assertEqual($picture, $lines, $label);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 19, 17:00 (2 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1126738
Default Alt Text
(9 KB)

Event Timeline