public static function indexRevision(DifferentialRevision $rev)
 {
     $doc = new PhabricatorSearchAbstractDocument();
     $doc->setPHID($rev->getPHID());
     $doc->setDocumentType(PhabricatorPHIDConstants::PHID_TYPE_DREV);
     $doc->setDocumentTitle($rev->getTitle());
     $doc->setDocumentCreated($rev->getDateCreated());
     $doc->setDocumentModified($rev->getDateModified());
     $doc->addField(PhabricatorSearchField::FIELD_BODY, $rev->getSummary());
     $doc->addField(PhabricatorSearchField::FIELD_TEST_PLAN, $rev->getTestPlan());
     $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_AUTHOR, $rev->getAuthorPHID(), PhabricatorPHIDConstants::PHID_TYPE_USER, $rev->getDateCreated());
     if ($rev->getStatus() != ArcanistDifferentialRevisionStatus::CLOSED && $rev->getStatus() != ArcanistDifferentialRevisionStatus::ABANDONED) {
         $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_OPEN, $rev->getPHID(), PhabricatorPHIDConstants::PHID_TYPE_DREV, time());
     }
     $comments = id(new DifferentialComment())->loadAllWhere('revisionID = %d', $rev->getID());
     $inlines = id(new DifferentialInlineComment())->loadAllWhere('revisionID = %d AND commentID IS NOT NULL', $rev->getID());
     $touches = array();
     foreach (array_merge($comments, $inlines) as $comment) {
         if (strlen($comment->getContent())) {
             $doc->addField(PhabricatorSearchField::FIELD_COMMENT, $comment->getContent());
         }
         $author = $comment->getAuthorPHID();
         $touches[$author] = $comment->getDateCreated();
     }
     foreach ($touches as $touch => $time) {
         $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_TOUCH, $touch, PhabricatorPHIDConstants::PHID_TYPE_USER, $time);
     }
     $rev->loadRelationships();
     // If a revision needs review, the owners are the reviewers. Otherwise, the
     // owner is the author (e.g., accepted, rejected, closed).
     if ($rev->getStatus() == ArcanistDifferentialRevisionStatus::NEEDS_REVIEW) {
         foreach ($rev->getReviewers() as $phid) {
             $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_OWNER, $phid, PhabricatorPHIDConstants::PHID_TYPE_USER, $rev->getDateModified());
             // Bogus timestamp.
         }
     } else {
         $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_OWNER, $rev->getAuthorPHID(), PhabricatorPHIDConstants::PHID_TYPE_USER, $rev->getDateCreated());
     }
     $ccphids = $rev->getCCPHIDs();
     $handles = id(new PhabricatorObjectHandleData($ccphids))->loadHandles();
     foreach ($handles as $phid => $handle) {
         $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_SUBSCRIBER, $phid, $handle->getType(), $rev->getDateModified());
         // Bogus timestamp.
     }
     self::reindexAbstractDocument($doc);
 }
 public function commitRevisionToWorkspace(DifferentialRevision $revision, ArcanistRepositoryAPI $workspace, PhabricatorUser $user)
 {
     $diff_id = $revision->loadActiveDiff()->getID();
     $call = new ConduitCall('differential.getrawdiff', array('diffID' => $diff_id));
     $call->setUser($user);
     $raw_diff = $call->execute();
     $future = $workspace->execFutureLocal('patch --no-commit -');
     $future->write($raw_diff);
     $future->resolvex();
     $workspace->reloadWorkingCopy();
     $call = new ConduitCall('differential.getcommitmessage', array('revision_id' => $revision->getID()));
     $call->setUser($user);
     $message = $call->execute();
     $author = id(new PhabricatorUser())->loadOneWhere('phid = %s', $revision->getAuthorPHID());
     $author_string = sprintf('%s <%s>', $author->getRealName(), $author->loadPrimaryEmailAddress());
     $author_date = $revision->getDateCreated();
     $workspace->execxLocal('commit --date=%s --user=%s ' . '--message=%s', $author_date . ' 0', $author_string, $message);
 }
 public function commitRevisionToWorkspace(DifferentialRevision $revision, ArcanistRepositoryAPI $workspace, PhabricatorUser $user)
 {
     $diff_id = $revision->loadActiveDiff()->getID();
     $call = new ConduitCall('differential.getrawdiff', array('diffID' => $diff_id));
     $call->setUser($user);
     $raw_diff = $call->execute();
     $missing_binary = "\nindex " . "0000000000000000000000000000000000000000.." . "0000000000000000000000000000000000000000\n";
     if (strpos($raw_diff, $missing_binary) !== false) {
         throw new Exception(pht('Patch is missing content for a binary file'));
     }
     $future = $workspace->execFutureLocal('apply --index -');
     $future->write($raw_diff);
     $future->resolvex();
     $workspace->reloadWorkingCopy();
     $call = new ConduitCall('differential.getcommitmessage', array('revision_id' => $revision->getID()));
     $call->setUser($user);
     $message = $call->execute();
     $author = id(new PhabricatorUser())->loadOneWhere('phid = %s', $revision->getAuthorPHID());
     $author_string = sprintf('%s <%s>', $author->getRealName(), $author->loadPrimaryEmailAddress());
     $author_date = $revision->getDateCreated();
     $workspace->execxLocal('-c user.name=%s -c user.email=%s ' . 'commit --date=%s --author=%s ' . '--message=%s', $user->getRealName(), $user->loadPrimaryEmailAddress(), $author_date, $author_string, $message);
 }
 private function getImplicitComments(DifferentialRevision $revision, DifferentialDiff $diff)
 {
     $author_phid = nonempty($diff->getAuthorPHID(), $revision->getAuthorPHID());
     $template = new DifferentialComment();
     $template->setAuthorPHID($author_phid);
     $template->setRevisionID($revision->getID());
     $template->setDateCreated($revision->getDateCreated());
     $comments = array();
     if (strlen($revision->getSummary())) {
         $summary_comment = clone $template;
         $summary_comment->setContent($revision->getSummary());
         $summary_comment->setAction(DifferentialAction::ACTION_SUMMARIZE);
         $comments[] = $summary_comment;
     }
     if (strlen($revision->getTestPlan())) {
         $testplan_comment = clone $template;
         $testplan_comment->setContent($revision->getTestPlan());
         $testplan_comment->setAction(DifferentialAction::ACTION_TESTPLAN);
         $comments[] = $testplan_comment;
     }
     return $comments;
 }
 private function buildSubheaderView(DifferentialRevision $revision)
 {
     $viewer = $this->getViewer();
     $author_phid = $revision->getAuthorPHID();
     $author = $viewer->renderHandle($author_phid)->render();
     $date = phabricator_datetime($revision->getDateCreated(), $viewer);
     $author = phutil_tag('strong', array(), $author);
     $handles = $viewer->loadHandles(array($author_phid));
     $image_uri = $handles[$author_phid]->getImageURI();
     $image_href = $handles[$author_phid]->getURI();
     $content = pht('Authored by %s on %s.', $author, $date);
     return id(new PHUIHeadThingView())->setImage($image_uri)->setImageHref($image_href)->setContent($content);
 }
 /**
  * @return array($reviewed, $not_reviewed)
  */
 public function computeTimes(DifferentialRevision $revision, array $comments)
 {
     assert_instances_of($comments, 'DifferentialComment');
     $add_rev = DifferentialComment::METADATA_ADDED_REVIEWERS;
     $rem_rev = DifferentialComment::METADATA_REMOVED_REVIEWERS;
     $date = $revision->getDateCreated();
     // Find out original reviewers.
     $reviewers = array_fill_keys($revision->getReviewers(), $date);
     foreach (array_reverse($comments) as $comment) {
         $metadata = $comment->getMetadata();
         foreach (idx($metadata, $add_rev, array()) as $phid) {
             unset($reviewers[$phid]);
         }
         foreach (idx($metadata, $rem_rev, array()) as $phid) {
             $reviewers[$phid] = $date;
         }
     }
     $reviewed = array();
     $not_reviewed = array();
     $status = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW;
     foreach ($comments as $comment) {
         $date = $comment->getDateCreated();
         $old_status = $status;
         switch ($comment->getAction()) {
             case DifferentialAction::ACTION_UPDATE:
                 if ($status != ArcanistDifferentialRevisionStatus::CLOSED && $status != ArcanistDifferentialRevisionStatus::ACCEPTED) {
                     $status = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW;
                 }
                 break;
             case DifferentialAction::ACTION_REQUEST:
             case DifferentialAction::ACTION_RECLAIM:
                 $status = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW;
                 break;
             case DifferentialAction::ACTION_REJECT:
             case DifferentialAction::ACTION_RETHINK:
                 $status = ArcanistDifferentialRevisionStatus::NEEDS_REVISION;
                 break;
             case DifferentialAction::ACTION_ACCEPT:
                 $status = ArcanistDifferentialRevisionStatus::ACCEPTED;
                 break;
             case DifferentialAction::ACTION_CLOSE:
                 $status = ArcanistDifferentialRevisionStatus::CLOSED;
                 break;
             case DifferentialAction::ACTION_ABANDON:
                 $status = ArcanistDifferentialRevisionStatus::ABANDONED;
                 break;
         }
         // Update current reviewers.
         $metadata = $comment->getMetadata();
         foreach (idx($metadata, $add_rev, array()) as $phid) {
             // If someone reviewed a revision without being its reviewer then give
             // him zero response time.
             $reviewers[$phid] = $date;
         }
         foreach (idx($metadata, $rem_rev, array()) as $phid) {
             $start = idx($reviewers, $phid);
             if ($start !== null) {
                 if ($date >= $this->since) {
                     $reviewed[$phid][] = $date - $start;
                 }
                 unset($reviewers[$phid]);
             }
         }
         // TODO: Respect workdays and status away.
         if ($old_status != $status) {
             if ($status == ArcanistDifferentialRevisionStatus::NEEDS_REVIEW) {
                 $reviewers = array_fill_keys(array_keys($reviewers), $date);
             } else {
                 if ($date >= $this->since) {
                     if ($old_status == ArcanistDifferentialRevisionStatus::NEEDS_REVIEW) {
                         foreach ($reviewers as $phid => $start) {
                             if ($phid == $comment->getAuthorPHID()) {
                                 $reviewed[$phid][] = $date - $start;
                             } else {
                                 $not_reviewed[$phid][] = $date - $start;
                             }
                         }
                     }
                 }
             }
         }
     }
     if ($status == ArcanistDifferentialRevisionStatus::NEEDS_REVIEW) {
         $date = $this->until !== null ? $this->until : time();
         if ($date >= $this->since) {
             foreach ($reviewers as $phid => $start) {
                 $not_reviewed[$phid][] = $date - $start;
             }
         }
     }
     return array($reviewed, $not_reviewed);
 }
 public function renderValueForRevisionList(DifferentialRevision $revision)
 {
     return phabricator_date($revision->getDateCreated(), $this->getUser());
 }