Page MenuHomePhabricator

D7734.id17479.diff
No OneTemporary

D7734.id17479.diff

Index: src/__phutil_library_map__.php
===================================================================
--- src/__phutil_library_map__.php
+++ src/__phutil_library_map__.php
@@ -2185,8 +2185,10 @@
'PhragmentHistoryController' => 'applications/phragment/controller/PhragmentHistoryController.php',
'PhragmentPHIDTypeFragment' => 'applications/phragment/phid/PhragmentPHIDTypeFragment.php',
'PhragmentPHIDTypeFragmentVersion' => 'applications/phragment/phid/PhragmentPHIDTypeFragmentVersion.php',
+ 'PhragmentPatchController' => 'applications/phragment/controller/PhragmentPatchController.php',
'PhragmentPatchUtil' => 'applications/phragment/util/PhragmentPatchUtil.php',
'PhragmentUpdateController' => 'applications/phragment/controller/PhragmentUpdateController.php',
+ 'PhragmentVersionController' => 'applications/phragment/controller/PhragmentVersionController.php',
'PhragmentZIPController' => 'applications/phragment/controller/PhragmentZIPController.php',
'PhrequentController' => 'applications/phrequent/controller/PhrequentController.php',
'PhrequentDAO' => 'applications/phrequent/storage/PhrequentDAO.php',
@@ -4784,8 +4786,10 @@
'PhragmentHistoryController' => 'PhragmentController',
'PhragmentPHIDTypeFragment' => 'PhabricatorPHIDType',
'PhragmentPHIDTypeFragmentVersion' => 'PhabricatorPHIDType',
+ 'PhragmentPatchController' => 'PhragmentController',
'PhragmentPatchUtil' => 'Phobject',
'PhragmentUpdateController' => 'PhragmentController',
+ 'PhragmentVersionController' => 'PhragmentController',
'PhragmentZIPController' => 'PhragmentController',
'PhrequentController' => 'PhabricatorController',
'PhrequentDAO' => 'PhabricatorLiskDAO',
Index: src/applications/phragment/application/PhabricatorApplicationPhragment.php
===================================================================
--- src/applications/phragment/application/PhabricatorApplicationPhragment.php
+++ src/applications/phragment/application/PhabricatorApplicationPhragment.php
@@ -39,6 +39,8 @@
'update/(?P<dblob>.*)' => 'PhragmentUpdateController',
'history/(?P<dblob>.*)' => 'PhragmentHistoryController',
'zip/(?P<dblob>.*)' => 'PhragmentZIPController',
+ 'version/(?P<id>[0-9]*)/' => 'PhragmentVersionController',
+ 'patch/(?P<aid>[0-9x]*)/(?P<bid>[0-9]*)/' => 'PhragmentPatchController',
),
);
}
Index: src/applications/phragment/controller/PhragmentHistoryController.php
===================================================================
--- src/applications/phragment/controller/PhragmentHistoryController.php
+++ src/applications/phragment/controller/PhragmentHistoryController.php
@@ -47,6 +47,7 @@
foreach ($versions as $version) {
$item = id(new PHUIObjectItemView());
$item->setHeader('Version '.$version->getSequence());
+ $item->setHref($version->getURI());
$item->addAttribute(phabricator_datetime(
$version->getDateCreated(),
$viewer));
Index: src/applications/phragment/controller/PhragmentPatchController.php
===================================================================
--- /dev/null
+++ src/applications/phragment/controller/PhragmentPatchController.php
@@ -0,0 +1,88 @@
+<?php
+
+final class PhragmentPatchController extends PhragmentController {
+
+ private $aid;
+ private $bid;
+
+ public function willProcessRequest(array $data) {
+ $this->aid = idx($data, "aid", 0);
+ $this->bid = idx($data, "bid", 0);
+ }
+
+ public function processRequest() {
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ // If "aid" is "x", then it means the user wants to generate
+ // a patch of an empty file to the version specified by "bid".
+
+ $ids = array($this->aid, $this->bid);
+ if ($this->aid === "x") {
+ $ids = array($this->bid);
+ }
+
+ $versions = id(new PhragmentFragmentVersionQuery())
+ ->setViewer($viewer)
+ ->withIDs($ids)
+ ->execute();
+
+ $version_a = null;
+ if ($this->aid !== "x") {
+ $version_a = idx($versions, $this->aid, null);
+ if ($version_a === null) {
+ return new Aphront404Response();
+ }
+ }
+
+ $version_b = idx($versions, $this->bid, null);
+ if ($version_b === null) {
+ return new Aphront404Response();
+ }
+
+ $file_phids = array();
+ if ($version_a !== null) {
+ $file_phids[] = $version_a->getFilePHID();
+ }
+ $file_phids[] = $version_b->getFilePHID();
+
+ $files = id(new PhabricatorFileQuery())
+ ->setViewer($viewer)
+ ->withPHIDs($file_phids)
+ ->execute();
+ $files = mpull($files, null, 'getPHID');
+
+ $file_a = null;
+ if ($version_a != null) {
+ $file_a = idx($files, $version_a->getFilePHID(), null);
+ }
+ $file_b = idx($files, $version_b->getFilePHID(), null);
+
+ $patch = PhragmentPatchUtil::calculatePatch($file_a, $file_b);
+
+ if ($patch === null) {
+ throw new Exception("Unable to compute patch!");
+ }
+
+ $a_sequence = 'x';
+ if ($version_a !== null) {
+ $a_sequence = $version_a->getSequence();
+ }
+
+ $name =
+ $version_b->getFragment()->getName().'.'.
+ $a_sequence.'.'.
+ $version_b->getSequence().'.patch';
+
+ $result = PhabricatorFile::buildFromFileDataOrHash(
+ $patch,
+ array(
+ 'name' => $name,
+ 'mime-type' => 'text/plain',
+ 'ttl' => time() + 60 * 60 * 24,
+ ));
+ return id(new AphrontRedirectResponse())
+ ->setURI($result->getBestURI());
+ }
+
+}
Index: src/applications/phragment/controller/PhragmentVersionController.php
===================================================================
--- /dev/null
+++ src/applications/phragment/controller/PhragmentVersionController.php
@@ -0,0 +1,179 @@
+<?php
+
+final class PhragmentVersionController extends PhragmentController {
+
+ private $id;
+
+ public function willProcessRequest(array $data) {
+ $this->id = idx($data, "id", 0);
+ }
+
+ public function processRequest() {
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ $version = id(new PhragmentFragmentVersionQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($this->id))
+ ->executeOne();
+ if ($version === null) {
+ return new Aphront404Response();
+ }
+
+ $parents = $this->loadParentFragments($version->getFragment()->getPath());
+ if ($parents === null) {
+ return new Aphront404Response();
+ }
+ $current = idx($parents, count($parents) - 1, null);
+
+ $crumbs = $this->buildApplicationCrumbsWithPath($parents);
+ $crumbs->addCrumb(
+ id(new PhabricatorCrumbView())
+ ->setName(pht('View Version %d', $version->getSequence())));
+
+ $phids = array();
+ $phids[] = $version->getFilePHID();
+
+ $this->loadHandles($phids);
+
+ $file = id(new PhabricatorFileQuery())
+ ->setViewer($viewer)
+ ->withPHIDs(array($version->getFilePHID()))
+ ->executeOne();
+ if ($file !== null) {
+ $file_uri = $file->getBestURI();
+ }
+
+ $header = id(new PHUIHeaderView())
+ ->setHeader(pht(
+ "%s at version %d",
+ $version->getFragment()->getName(),
+ $version->getSequence()))
+ ->setPolicyObject($version)
+ ->setUser($viewer);
+
+ $actions = id(new PhabricatorActionListView())
+ ->setUser($viewer)
+ ->setObject($version)
+ ->setObjectURI($version->getURI());
+ $actions->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('Download Version'))
+ ->setHref($file_uri)
+ ->setDisabled($file === null)
+ ->setIcon('download'));
+
+ $properties = id(new PHUIPropertyListView())
+ ->setUser($viewer)
+ ->setObject($version)
+ ->setActionList($actions);
+ $properties->addProperty(
+ pht('File'),
+ $this->renderHandlesForPHIDs(array($version->getFilePHID())));
+
+ $box = id(new PHUIObjectBoxView())
+ ->setHeader($header)
+ ->addPropertyList($properties);
+
+ return $this->buildApplicationPage(
+ array(
+ $crumbs,
+ $box,
+ $this->renderPatchFromPreviousVersion($version, $file),
+ $this->renderPreviousVersionList($version)),
+ array(
+ 'title' => pht('View Version'),
+ 'device' => true));
+ }
+
+ private function renderPatchFromPreviousVersion(
+ PhragmentFragmentVersion $version,
+ PhabricatorFile $file) {
+
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ $previous_file = null;
+ $previous = id(new PhragmentFragmentVersionQuery())
+ ->setViewer($viewer)
+ ->withFragmentPHIDs(array($version->getFragmentPHID()))
+ ->withSequences(array($version->getSequence() - 1))
+ ->executeOne();
+ if ($previous !== null) {
+ $previous_file = id(new PhabricatorFileQuery())
+ ->setViewer($viewer)
+ ->withPHIDs(array($previous->getFilePHID()))
+ ->executeOne();
+ }
+
+ $patch = PhragmentPatchUtil::calculatePatch($previous_file, $file);
+
+ if ($patch === null) {
+ return id(new AphrontErrorView())
+ ->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
+ ->setTitle(pht("Identical Version"))
+ ->appendChild(phutil_tag(
+ 'p',
+ array(),
+ pht("This version is identical to the previous version.")));
+ }
+
+ if (strlen($patch) > 20480) {
+ // Patch is longer than 20480 characters. Trim it and let the user know.
+ $patch = substr($patch, 0, 20480)."\n...\n";
+ $patch .= pht(
+ "This patch is longer than 20480 characters. Use the link ".
+ "in the action list to download the full patch.");
+ }
+
+ return id(new PHUIObjectBoxView())
+ ->setHeader(id(new PHUIHeaderView())
+ ->setHeader(pht('Differences since previous version')))
+ ->appendChild(id(new PhabricatorSourceCodeView())
+ ->setLines(phutil_split_lines($patch)));
+ }
+
+ private function renderPreviousVersionList(
+ PhragmentFragmentVersion $version) {
+
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ $previous_versions = id(new PhragmentFragmentVersionQuery())
+ ->setViewer($viewer)
+ ->withFragmentPHIDs(array($version->getFragmentPHID()))
+ ->withSequenceBefore($version->getSequence())
+ ->execute();
+
+ $list = id(new PHUIObjectItemListView())
+ ->setUser($viewer);
+
+ foreach ($previous_versions as $previous_version) {
+ $item = id(new PHUIObjectItemView());
+ $item->setHeader('Version '.$previous_version->getSequence());
+ $item->setHref($previous_version->getURI());
+ $item->addAttribute(phabricator_datetime(
+ $previous_version->getDateCreated(),
+ $viewer));
+ $item->addAction(id(new PHUIListItemView())
+ ->setIcon('patch')
+ ->setName(pht("Get Patch"))
+ ->setHref($this->getApplicationURI(
+ 'patch/'.$previous_version->getID().'/'.$version->getID())));
+ $list->addItem($item);
+ }
+
+ $item = id(new PHUIObjectItemView());
+ $item->setHeader('Prior to Version 0');
+ $item->addAttribute('Prior to any content (empty file)');
+ $item->addAction(id(new PHUIListItemView())
+ ->setIcon('patch')
+ ->setName(pht("Get Patch"))
+ ->setHref($this->getApplicationURI(
+ 'patch/x/'.$version->getID())));
+ $list->addItem($item);
+
+ return $list;
+ }
+
+}
Index: src/applications/phragment/query/PhragmentFragmentVersionQuery.php
===================================================================
--- src/applications/phragment/query/PhragmentFragmentVersionQuery.php
+++ src/applications/phragment/query/PhragmentFragmentVersionQuery.php
@@ -6,6 +6,8 @@
private $ids;
private $phids;
private $fragmentPHIDs;
+ private $sequences;
+ private $sequenceBefore;
public function withIDs(array $ids) {
$this->ids = $ids;
@@ -22,6 +24,16 @@
return $this;
}
+ public function withSequences(array $sequences) {
+ $this->sequences = $sequences;
+ return $this;
+ }
+
+ public function withSequenceBefore($current) {
+ $this->sequenceBefore = $current;
+ return $this;
+ }
+
public function loadPage() {
$table = new PhragmentFragmentVersion();
$conn_r = $table->establishConnection('r');
@@ -61,6 +73,20 @@
$this->fragmentPHIDs);
}
+ if ($this->sequences) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'sequence IN (%Ld)',
+ $this->sequences);
+ }
+
+ if ($this->sequenceBefore !== null) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'sequence < %d',
+ $this->sequenceBefore);
+ }
+
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
Index: src/applications/phragment/storage/PhragmentFragmentVersion.php
===================================================================
--- src/applications/phragment/storage/PhragmentFragmentVersion.php
+++ src/applications/phragment/storage/PhragmentFragmentVersion.php
@@ -22,7 +22,7 @@
}
public function getURI() {
- return '/phragment/patch/'.$this->getID().'/';
+ return '/phragment/version/'.$this->getID().'/';
}
public function getFragment() {
Index: src/applications/phragment/util/PhragmentPatchUtil.php
===================================================================
--- src/applications/phragment/util/PhragmentPatchUtil.php
+++ src/applications/phragment/util/PhragmentPatchUtil.php
@@ -9,7 +9,7 @@
*
* @phutil-external-symbol class diff_match_patch
*/
- public function calculatePatch(
+ public static function calculatePatch(
PhabricatorFile $old = null,
PhabricatorFile $new = null) {

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 16, 9:09 PM (3 d, 15 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6715541
Default Alt Text
D7734.id17479.diff (13 KB)

Event Timeline