1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-26 00:32:42 +01:00

Unify code for parsing "Reverts X" magic, and when something "reverts <hash>", also revert associated revisions

Summary:
Depends on D20468. Ref T13276. See PHI1008.

When a commit or revision "reverts <hash>", and that's the hash of a commit which has a revision, also write a "reverts" edge to the revision.

Test Plan:
Created "reverts X" objects for:

  - a revision;
  - a commit;
  - a commit with a revision (both got marked properly).

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13276

Differential Revision: https://secure.phabricator.com/D20469
This commit is contained in:
epriestley 2019-04-23 10:57:51 -07:00
parent 56f5c2443b
commit a78f141b3f
3 changed files with 81 additions and 36 deletions

View file

@ -390,30 +390,13 @@ final class PhabricatorAuditEditor
->parseCorpus($huge_block); ->parseCorpus($huge_block);
$reverts = array_mergev(ipull($reverts_refs, 'monograms')); $reverts = array_mergev(ipull($reverts_refs, 'monograms'));
if ($reverts) { if ($reverts) {
// Only allow commits to revert other commits in the same repository. $reverted_objects = DiffusionCommitRevisionQuery::loadRevertedObjects(
$reverted_commits = id(new DiffusionCommitQuery()) $actor,
->setViewer($actor) $object,
->withRepository($object->getRepository()) $reverts,
->withIdentifiers($reverts) $object->getRepository());
->execute();
$reverted_revisions = id(new PhabricatorObjectQuery()) $reverted_phids = mpull($reverted_objects, 'getPHID', 'getPHID');
->setViewer($actor)
->withNames($reverts)
->withTypes(
array(
DifferentialRevisionPHIDType::TYPECONST,
))
->execute();
$reverted_phids =
mpull($reverted_commits, 'getPHID', 'getPHID') +
mpull($reverted_revisions, 'getPHID', 'getPHID');
// NOTE: Skip any write attempts if a user cleverly implies a commit
// reverts itself, although this would be exceptionally clever in Git
// or Mercurial.
unset($reverted_phids[$object->getPHID()]);
$reverts_edge = DiffusionCommitRevertsCommitEdgeType::EDGECONST; $reverts_edge = DiffusionCommitRevertsCommitEdgeType::EDGECONST;
$result[] = id(new PhabricatorAuditTransaction()) $result[] = id(new PhabricatorAuditTransaction())

View file

@ -832,22 +832,14 @@ final class DifferentialTransactionEditor
} }
if ($revert_monograms) { if ($revert_monograms) {
$revert_objects = id(new PhabricatorObjectQuery()) $revert_objects = DiffusionCommitRevisionQuery::loadRevertedObjects(
->setViewer($this->getActor()) $this->getActor(),
->withNames($revert_monograms) $object,
->withTypes( $revert_monograms,
array( null);
DifferentialRevisionPHIDType::TYPECONST,
PhabricatorRepositoryCommitPHIDType::TYPECONST,
))
->execute();
$revert_phids = mpull($revert_objects, 'getPHID', 'getPHID'); $revert_phids = mpull($revert_objects, 'getPHID', 'getPHID');
// Don't let an object revert itself, although other silly stuff like
// cycles of objects reverting each other is not prevented.
unset($revert_phids[$object->getPHID()]);
$revert_type = DiffusionCommitRevertsCommitEdgeType::EDGECONST; $revert_type = DiffusionCommitRevertsCommitEdgeType::EDGECONST;
$edges[$revert_type] = $revert_phids; $edges[$revert_type] = $revert_phids;
} else { } else {

View file

@ -64,5 +64,75 @@ final class DiffusionCommitRevisionQuery
->executeOne(); ->executeOne();
} }
public static function loadRevertedObjects(
PhabricatorUser $viewer,
$source_object,
array $object_names,
PhabricatorRepository $repository_scope = null) {
// Fetch commits first, since we need to load data on commits in order
// to identify associated revisions later on.
$commit_query = id(new DiffusionCommitQuery())
->setViewer($viewer)
->withIdentifiers($object_names)
->needCommitData(true);
// If we're acting in a specific repository, only allow commits in that
// repository to be affected: when commit X reverts commit Y by hash, we
// only want to revert commit Y in the same repository, even if other
// repositories have a commit with the same hash.
if ($repository_scope) {
$commit_query->withRepository($repository_scope);
}
$objects = $commit_query->execute();
$more_objects = id(new PhabricatorObjectQuery())
->setViewer($viewer)
->withNames($object_names)
->withTypes(
array(
DifferentialRevisionPHIDType::TYPECONST,
))
->execute();
foreach ($more_objects as $object) {
$objects[] = $object;
}
// See PHI1008 and T13276. If something reverts commit X, we also revert
// any associated revision.
// For now, we don't try to find associated commits if something reverts
// revision Y. This is less common, although we could make more of an
// effort in the future.
foreach ($objects as $object) {
if (!($object instanceof PhabricatorRepositoryCommit)) {
continue;
}
// NOTE: If our object "reverts X", where "X" is a commit hash, it is
// possible that "X" will not have parsed yet, so we'll fail to find
// a revision even though one exists.
// For now, do nothing. It's rare to push a commit which reverts some
// commit "X" before "X" has parsed, so we expect this to be unusual.
$revision = self::loadRevisionForCommit(
$viewer,
$object);
if ($revision) {
$objects[] = $revision;
}
}
$objects = mpull($objects, null, 'getPHID');
// Prevent an object from reverting itself, although this would be very
// clever in Git or Mercurial.
unset($objects[$source_object->getPHID()]);
return $objects;
}
} }