Page MenuHomePhabricator

D21182.id50444.diff
No OneTemporary

D21182.id50444.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -154,6 +154,8 @@
'ArcanistDiffParserTestCase' => 'parser/__tests__/ArcanistDiffParserTestCase.php',
'ArcanistDiffUtils' => 'difference/ArcanistDiffUtils.php',
'ArcanistDiffUtilsTestCase' => 'difference/__tests__/ArcanistDiffUtilsTestCase.php',
+ 'ArcanistDiffVectorNode' => 'difference/ArcanistDiffVectorNode.php',
+ 'ArcanistDiffVectorTree' => 'difference/ArcanistDiffVectorTree.php',
'ArcanistDiffWorkflow' => 'workflow/ArcanistDiffWorkflow.php',
'ArcanistDifferentialCommitMessage' => 'differential/ArcanistDifferentialCommitMessage.php',
'ArcanistDifferentialCommitMessageParserException' => 'differential/ArcanistDifferentialCommitMessageParserException.php',
@@ -691,7 +693,6 @@
'PhutilExecutionEnvironment' => 'utils/PhutilExecutionEnvironment.php',
'PhutilFileLock' => 'filesystem/PhutilFileLock.php',
'PhutilFileLockTestCase' => 'filesystem/__tests__/PhutilFileLockTestCase.php',
- 'PhutilFileTree' => 'filesystem/PhutilFileTree.php',
'PhutilFrenchLocale' => 'internationalization/locales/PhutilFrenchLocale.php',
'PhutilGermanLocale' => 'internationalization/locales/PhutilGermanLocale.php',
'PhutilGitBinaryAnalyzer' => 'filesystem/binary/PhutilGitBinaryAnalyzer.php',
@@ -1134,6 +1135,8 @@
'ArcanistDiffParserTestCase' => 'PhutilTestCase',
'ArcanistDiffUtils' => 'Phobject',
'ArcanistDiffUtilsTestCase' => 'PhutilTestCase',
+ 'ArcanistDiffVectorNode' => 'Phobject',
+ 'ArcanistDiffVectorTree' => 'Phobject',
'ArcanistDiffWorkflow' => 'ArcanistWorkflow',
'ArcanistDifferentialCommitMessage' => 'Phobject',
'ArcanistDifferentialCommitMessageParserException' => 'Exception',
@@ -1702,7 +1705,6 @@
'PhutilExecutionEnvironment' => 'Phobject',
'PhutilFileLock' => 'PhutilLock',
'PhutilFileLockTestCase' => 'PhutilTestCase',
- 'PhutilFileTree' => 'Phobject',
'PhutilFrenchLocale' => 'PhutilLocale',
'PhutilGermanLocale' => 'PhutilLocale',
'PhutilGitBinaryAnalyzer' => 'PhutilBinaryAnalyzer',
diff --git a/src/difference/ArcanistDiffVectorNode.php b/src/difference/ArcanistDiffVectorNode.php
new file mode 100644
--- /dev/null
+++ b/src/difference/ArcanistDiffVectorNode.php
@@ -0,0 +1,113 @@
+<?php
+
+final class ArcanistDiffVectorNode
+ extends Phobject {
+
+ private $vector;
+ private $children = array();
+ private $parentNode;
+ private $displayNode;
+ private $displayVector;
+ private $displayDepth;
+ private $valueNode;
+ private $attributes = array();
+
+ public function setVector(array $vector) {
+ $this->vector = $vector;
+ return $this;
+ }
+
+ public function getVector() {
+ return $this->vector;
+ }
+
+ public function getChildren() {
+ return $this->children;
+ }
+
+ public function setParentNode(ArcanistDiffVectorNode $parent) {
+ $this->parentNode = $parent;
+ return $this;
+ }
+
+ public function getParentNode() {
+ return $this->parentNode;
+ }
+
+ public function addChild(array $vector, $length, $idx) {
+ $is_node = ($idx === ($length - 1));
+ $element = $vector[$idx];
+
+ if (!isset($this->children[$element])) {
+ $this->children[$element] = id(new self())
+ ->setParentNode($this)
+ ->setVector(array_slice($vector, 0, $idx + 1));
+ }
+
+ $child = $this->children[$element];
+
+ if ($is_node) {
+ $child->setValueNode($child);
+ return;
+ }
+
+ $child->addChild($vector, $length, $idx + 1);
+ }
+
+ public function getDisplayVector() {
+ return $this->displayVector;
+ }
+
+ public function appendDisplayElement($element) {
+ if ($this->displayVector === null) {
+ $this->displayVector = array();
+ }
+
+ $this->displayVector[] = $element;
+
+ return $this;
+ }
+
+ public function setDisplayNode(ArcanistDiffVectorNode $display_node) {
+ $this->displayNode = $display_node;
+ return $this;
+ }
+
+ public function getDisplayNode() {
+ return $this->displayNode;
+ }
+
+ public function setDisplayDepth($display_depth) {
+ $this->displayDepth = $display_depth;
+ return $this;
+ }
+
+ public function getDisplayDepth() {
+ return $this->displayDepth;
+ }
+
+ public function setValueNode($value_node) {
+ $this->valueNode = $value_node;
+ return $this;
+ }
+
+ public function getValueNode() {
+ return $this->valueNode;
+ }
+
+ public function setAncestralAttribute($key, $value) {
+ $this->attributes[$key] = $value;
+
+ $parent = $this->getParentNode();
+ if ($parent) {
+ $parent->setAncestralAttribute($key, $value);
+ }
+
+ return $this;
+ }
+
+ public function getAttribute($key, $default = null) {
+ return idx($this->attributes, $key, $default);
+ }
+
+}
diff --git a/src/difference/ArcanistDiffVectorTree.php b/src/difference/ArcanistDiffVectorTree.php
new file mode 100644
--- /dev/null
+++ b/src/difference/ArcanistDiffVectorTree.php
@@ -0,0 +1,95 @@
+<?php
+
+final class ArcanistDiffVectorTree
+ extends Phobject {
+
+ private $vectors;
+
+ public function addVector(array $vector) {
+ $this->vectors[] = $vector;
+ return $this;
+ }
+
+ public function newDisplayList() {
+ $root = new ArcanistDiffVectorNode();
+
+ foreach ($this->vectors as $vector) {
+ $root->addChild($vector, count($vector), 0);
+ }
+
+ foreach ($root->getChildren() as $child) {
+ $this->compressTree($child);
+ }
+
+ $root->setDisplayDepth(-1);
+ foreach ($root->getChildren() as $child) {
+ $this->updateDisplayDepth($child);
+ }
+
+ return $this->getDisplayList($root);
+ }
+
+ private function compressTree(ArcanistDiffVectorNode $node) {
+ $display_node = $node;
+
+ $children = $node->getChildren();
+ if ($children) {
+ $parent = $node->getParentNode();
+ if ($parent) {
+ $siblings = $parent->getChildren();
+ if (count($siblings) === 1) {
+ if (!$parent->getValueNode()) {
+ $parent_display = $parent->getDisplayNode();
+ if ($parent_display) {
+ $display_node = $parent_display;
+ if ($node->getValueNode()) {
+ $parent->setValueNode($node->getValueNode());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ $node->setDisplayNode($display_node);
+
+ $display_element = last($node->getVector());
+ $display_node->appendDisplayElement($display_element);
+
+ foreach ($children as $child) {
+ $this->compressTree($child);
+ }
+ }
+
+ private function updateDisplayDepth(ArcanistDiffVectorNode $node) {
+ $parent_depth = $node->getParentNode()->getDisplayDepth();
+
+ if ($node->getDisplayVector() === null) {
+ $display_depth = $parent_depth;
+ } else {
+ $display_depth = $parent_depth + 1;
+ }
+
+ $node->setDisplayDepth($display_depth);
+
+ foreach ($node->getChildren() as $child) {
+ $this->updateDisplayDepth($child);
+ }
+ }
+
+ private function getDisplayList(ArcanistDiffVectorNode $node) {
+ $result = array();
+
+ foreach ($node->getChildren() as $child) {
+ if ($child->getDisplayVector() !== null) {
+ $result[] = $child;
+ }
+ foreach ($this->getDisplayList($child) as $item) {
+ $result[] = $item;
+ }
+ }
+
+ return $result;
+ }
+
+}
diff --git a/src/filesystem/PhutilFileTree.php b/src/filesystem/PhutilFileTree.php
deleted file mode 100644
--- a/src/filesystem/PhutilFileTree.php
+++ /dev/null
@@ -1,112 +0,0 @@
-<?php
-
-/**
- * Data structure for representing filesystem directory trees.
- */
-final class PhutilFileTree extends Phobject {
-
- private $name;
- private $fullPath;
- private $data;
- private $depth = 0;
- private $parentNode;
- private $children = array();
-
- public function addPath($path, $data) {
- $parts = $this->splitPath($path);
- $parts = array_reverse($parts);
- $this->insertPath($parts, $data);
- return $this;
- }
-
- public function destroy() {
- $this->parentNode = null;
- foreach ($this->children as $child) {
- $child->destroy();
- }
- $this->children = array();
- return $this;
- }
-
- /**
- * Get the next node, iterating in depth-first order.
- */
- public function getNextNode() {
- if ($this->children) {
- return head($this->children);
- }
- $cursor = $this;
- while ($cursor) {
- if ($cursor->getNextSibling()) {
- return $cursor->getNextSibling();
- }
- $cursor = $cursor->parentNode;
- }
- return null;
- }
-
- public function getName() {
- return $this->name;
- }
-
- public function getFullPath() {
- return $this->fullPath;
- }
-
- public function getDepth() {
- return $this->depth;
- }
-
- public function getData() {
- return $this->data;
- }
-
- protected function insertPath(array $parts, $data) {
- $part = array_pop($parts);
- if ($part === null) {
- if ($this->data) {
- $full_path = $this->getFullPath();
- throw new Exception(
- pht("Duplicate insertion for path '%s'.", $full_path));
- }
- $this->data = $data;
- return;
- }
-
- if (empty($this->children[$part])) {
- $node = new PhutilFileTree();
- $node->parentNode = $this;
- $node->depth = $this->depth + 1;
- $node->name = $part;
- $node->fullPath = $this->parentNode ? ($this->fullPath.'/'.$part) : $part;
- $this->children[$part] = $node;
- }
-
- $this->children[$part]->insertPath($parts, $data);
- }
-
- protected function splitPath($path) {
- $path = trim($path, '/');
- $parts = preg_split('@/+@', $path);
- return $parts;
- }
-
- protected function getNextSibling() {
- if (!$this->parentNode) {
- return null;
- }
-
- $found = false;
- foreach ($this->parentNode->children as $node) {
- if ($found) {
- return $node;
- }
- if ($this->name === $node->name) {
- $found = true;
- }
- }
-
- return null;
- }
-
-}

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 5, 11:28 PM (9 h, 40 m ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7227900
Default Alt Text
D21182.id50444.diff (9 KB)

Event Timeline