mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-26 00:32:42 +01:00
For changesets that affect binaries, use the new binary file content hash as an effect hash
Summary: Ref T13522. When changesets update an image, we currently compute no effect hash. A content hash of the image (or other binary file) is a reasonable effect hash, and enalbes effect-hash-based behavior, including hiding files in intradiffs. Test Plan: - Created a revision affecting `cat.png` and `quack.txt` (currently, there must be 2+ changesets to trigger the hide logic). - Updated it with the exact same changes. - Viewed revision: - Saw the image renderered in the interdiff. - Applied patch. - Ran `bin/differential rebuild-changesets ...`. - Viewed revision: - Saw both changesets collapse as unchanged. Maniphest Tasks: T13522 Differential Revision: https://secure.phabricator.com/D21174
This commit is contained in:
parent
b0c295e545
commit
c12db28251
5 changed files with 103 additions and 2 deletions
|
@ -2,9 +2,22 @@
|
||||||
|
|
||||||
final class DifferentialChangesetEngine extends Phobject {
|
final class DifferentialChangesetEngine extends Phobject {
|
||||||
|
|
||||||
|
private $viewer;
|
||||||
|
|
||||||
|
public function setViewer(PhabricatorUser $viewer) {
|
||||||
|
$this->viewer = $viewer;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getViewer() {
|
||||||
|
return $this->viewer;
|
||||||
|
}
|
||||||
|
|
||||||
public function rebuildChangesets(array $changesets) {
|
public function rebuildChangesets(array $changesets) {
|
||||||
assert_instances_of($changesets, 'DifferentialChangeset');
|
assert_instances_of($changesets, 'DifferentialChangeset');
|
||||||
|
|
||||||
|
$changesets = $this->loadChangesetFiles($changesets);
|
||||||
|
|
||||||
foreach ($changesets as $changeset) {
|
foreach ($changesets as $changeset) {
|
||||||
$this->detectGeneratedCode($changeset);
|
$this->detectGeneratedCode($changeset);
|
||||||
$this->computeHashes($changeset);
|
$this->computeHashes($changeset);
|
||||||
|
@ -13,6 +26,45 @@ final class DifferentialChangesetEngine extends Phobject {
|
||||||
$this->detectCopiedCode($changesets);
|
$this->detectCopiedCode($changesets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function loadChangesetFiles(array $changesets) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$file_phids = array();
|
||||||
|
foreach ($changesets as $changeset) {
|
||||||
|
$file_phid = $changeset->getNewFileObjectPHID();
|
||||||
|
if ($file_phid !== null) {
|
||||||
|
$file_phids[] = $file_phid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($file_phids) {
|
||||||
|
$files = id(new PhabricatorFileQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withPHIDs($file_phids)
|
||||||
|
->execute();
|
||||||
|
$files = mpull($files, null, 'getPHID');
|
||||||
|
} else {
|
||||||
|
$files = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($changesets as $changeset_key => $changeset) {
|
||||||
|
$file_phid = $changeset->getNewFileObjectPHID();
|
||||||
|
if ($file_phid === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = idx($files, $file_phid);
|
||||||
|
if (!$file) {
|
||||||
|
unset($changesets[$changeset_key]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$changeset->attachNewFileObject($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $changesets;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( Generated Code )----------------------------------------------------- */
|
/* -( Generated Code )----------------------------------------------------- */
|
||||||
|
|
||||||
|
@ -86,6 +138,20 @@ final class DifferentialChangesetEngine extends Phobject {
|
||||||
return PhabricatorHash::digestForIndex($new_data);
|
return PhabricatorHash::digestForIndex($new_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($changeset->getNewFileObjectPHID()) {
|
||||||
|
$file = $changeset->getNewFileObject();
|
||||||
|
|
||||||
|
// See T13522. For now, the "contentHash" is not really a content hash
|
||||||
|
// for files >4MB. This is okay: we will just always detect them as
|
||||||
|
// changed, which is the safer behavior.
|
||||||
|
|
||||||
|
$hash = $file->getContentHash();
|
||||||
|
if ($hash !== null) {
|
||||||
|
$hash = sprintf('file-hash:%s', $hash);
|
||||||
|
return PhabricatorHash::digestForIndex($hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,7 @@ final class PhabricatorDifferentialRebuildChangesetsWorkflow
|
||||||
}
|
}
|
||||||
|
|
||||||
id(new DifferentialChangesetEngine())
|
id(new DifferentialChangesetEngine())
|
||||||
|
->setViewer($viewer)
|
||||||
->rebuildChangesets($changesets);
|
->rebuildChangesets($changesets);
|
||||||
|
|
||||||
foreach ($changesets as $changeset) {
|
foreach ($changesets as $changeset) {
|
||||||
|
|
|
@ -1827,8 +1827,6 @@ final class DifferentialChangesetParser extends Phobject {
|
||||||
|
|
||||||
if (!$vs) {
|
if (!$vs) {
|
||||||
$metadata = $this->changeset->getMetadata();
|
$metadata = $this->changeset->getMetadata();
|
||||||
$data = idx($metadata, 'attachment-data');
|
|
||||||
|
|
||||||
$old_phid = idx($metadata, 'old:binary-phid');
|
$old_phid = idx($metadata, 'old:binary-phid');
|
||||||
$new_phid = idx($metadata, 'new:binary-phid');
|
$new_phid = idx($metadata, 'new:binary-phid');
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -25,6 +25,9 @@ final class DifferentialChangeset
|
||||||
private $authorityPackages;
|
private $authorityPackages;
|
||||||
private $changesetPackages;
|
private $changesetPackages;
|
||||||
|
|
||||||
|
private $newFileObject = self::ATTACHABLE;
|
||||||
|
private $oldFileObject = self::ATTACHABLE;
|
||||||
|
|
||||||
const TABLE_CACHE = 'differential_changeset_parse_cache';
|
const TABLE_CACHE = 'differential_changeset_parse_cache';
|
||||||
|
|
||||||
const METADATA_TRUSTED_ATTRIBUTES = 'attributes.trusted';
|
const METADATA_TRUSTED_ATTRIBUTES = 'attributes.trusted';
|
||||||
|
@ -459,6 +462,34 @@ final class DifferentialChangeset
|
||||||
return $this->getChangesetAttribute(self::ATTRIBUTE_GENERATED);
|
return $this->getChangesetAttribute(self::ATTRIBUTE_GENERATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getNewFileObjectPHID() {
|
||||||
|
$metadata = $this->getMetadata();
|
||||||
|
return idx($metadata, 'new:binary-phid');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOldFileObjectPHID() {
|
||||||
|
$metadata = $this->getMetadata();
|
||||||
|
return idx($metadata, 'old:binary-phid');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function attachNewFileObject(PhabricatorFile $file) {
|
||||||
|
$this->newFileObject = $file;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNewFileObject() {
|
||||||
|
return $this->assertAttached($this->newFileObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function attachOldFileObject(PhabricatorFile $file) {
|
||||||
|
$this->oldFileObject = $file;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOldFileObject() {
|
||||||
|
return $this->assertAttached($this->oldFileObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||||
|
|
||||||
|
|
|
@ -232,7 +232,12 @@ final class DifferentialDiff
|
||||||
|
|
||||||
$changesets = $diff->getChangesets();
|
$changesets = $diff->getChangesets();
|
||||||
|
|
||||||
|
// TODO: This is "safe", but it would be better to propagate a real user
|
||||||
|
// down the stack.
|
||||||
|
$viewer = PhabricatorUser::getOmnipotentUser();
|
||||||
|
|
||||||
id(new DifferentialChangesetEngine())
|
id(new DifferentialChangesetEngine())
|
||||||
|
->setViewer($viewer)
|
||||||
->rebuildChangesets($changesets);
|
->rebuildChangesets($changesets);
|
||||||
|
|
||||||
return $diff;
|
return $diff;
|
||||||
|
|
Loading…
Reference in a new issue