mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-27 07:50:57 +01:00
Differential mail
Test Plan: EMPTY Reviewers: aran, epriestley Reviewed By: epriestley CC: aran, epriestley, mareksapota Differential Revision: 1004
This commit is contained in:
parent
fee7184350
commit
87a2987ad6
10 changed files with 126 additions and 61 deletions
|
@ -232,6 +232,11 @@ return array(
|
|||
// Prefix prepended to mail sent by Differential.
|
||||
'metamta.differential.subject-prefix' => '[Differential]',
|
||||
|
||||
// Set this to true if you want patches to be attached to mail from
|
||||
// Differential. This won't work if you are using SendGrid as your mail
|
||||
// adapter.
|
||||
'metamta.differential.attach-patches' => false,
|
||||
|
||||
// By default, Phabricator generates unique reply-to addresses and sends a
|
||||
// separate email to each recipient when you enable reply handling. This is
|
||||
// more secure than using "From" to establish user identity, but can mean
|
||||
|
|
|
@ -72,60 +72,7 @@ class ConduitAPI_differential_getdiff_Method extends ConduitAPIMethod {
|
|||
$changeset->attachHunks($changeset->loadHunks());
|
||||
}
|
||||
|
||||
return $this->createDiffDict($diff);
|
||||
}
|
||||
|
||||
public static function createDiffDict(DifferentialDiff $diff) {
|
||||
$dict = array(
|
||||
'id' => $diff->getID(),
|
||||
'parent' => $diff->getParentRevisionID(),
|
||||
'revisionID' => $diff->getRevisionID(),
|
||||
'sourceControlBaseRevision' => $diff->getSourceControlBaseRevision(),
|
||||
'sourceControlPath' => $diff->getSourceControlPath(),
|
||||
'unitStatus' => $diff->getUnitStatus(),
|
||||
'lintStatus' => $diff->getLintStatus(),
|
||||
'changes' => array(),
|
||||
'properties' => array(),
|
||||
);
|
||||
|
||||
foreach ($diff->getChangesets() as $changeset) {
|
||||
$hunks = array();
|
||||
foreach ($changeset->getHunks() as $hunk) {
|
||||
$hunks[] = array(
|
||||
'oldOffset' => $hunk->getOldOffset(),
|
||||
'newOffset' => $hunk->getNewOffset(),
|
||||
'oldLength' => $hunk->getOldLen(),
|
||||
'newLength' => $hunk->getNewLen(),
|
||||
'addLines' => null,
|
||||
'delLines' => null,
|
||||
'isMissingOldNewline' => null,
|
||||
'isMissingNewNewline' => null,
|
||||
'corpus' => $hunk->getChanges(),
|
||||
);
|
||||
}
|
||||
$change = array(
|
||||
'metadata' => $changeset->getMetadata(),
|
||||
'oldPath' => $changeset->getOldFile(),
|
||||
'currentPath' => $changeset->getFileName(),
|
||||
'awayPaths' => $changeset->getAwayPaths(),
|
||||
'oldProperties' => $changeset->getOldProperties(),
|
||||
'newProperties' => $changeset->getNewProperties(),
|
||||
'type' => $changeset->getChangeType(),
|
||||
'fileType' => $changeset->getFileType(),
|
||||
'commitHash' => null,
|
||||
'hunks' => $hunks,
|
||||
);
|
||||
$dict['changes'][] = $change;
|
||||
}
|
||||
|
||||
$properties = id(new DifferentialDiffProperty())->loadAllWhere(
|
||||
'diffID = %d',
|
||||
$diff->getID());
|
||||
foreach ($properties as $property) {
|
||||
$dict['properties'][$property->getName()] = $property->getData();
|
||||
}
|
||||
|
||||
return $dict;
|
||||
return $diff->getDiffDict();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
phutil_require_module('phabricator', 'applications/conduit/method/base');
|
||||
phutil_require_module('phabricator', 'applications/conduit/protocol/exception');
|
||||
phutil_require_module('phabricator', 'applications/differential/storage/diff');
|
||||
phutil_require_module('phabricator', 'applications/differential/storage/diffproperty');
|
||||
phutil_require_module('phabricator', 'applications/differential/storage/revision');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
|
|
@ -62,8 +62,7 @@ class ConduitAPI_differential_getrevision_Method extends ConduitAPIMethod {
|
|||
foreach ($diff->getChangesets() as $changeset) {
|
||||
$changeset->attachHunks($changeset->loadHunks());
|
||||
}
|
||||
$diff_dicts[] =
|
||||
ConduitAPI_differential_getdiff_Method::createDiffDict($diff);
|
||||
$diff_dicts[] = $diff->getDiffDict();
|
||||
}
|
||||
|
||||
$commit_dicts = array();
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/conduit/method/base');
|
||||
phutil_require_module('phabricator', 'applications/conduit/method/differential/getdiff');
|
||||
phutil_require_module('phabricator', 'applications/conduit/protocol/exception');
|
||||
phutil_require_module('phabricator', 'applications/differential/constants/revisionstatus');
|
||||
phutil_require_module('phabricator', 'applications/differential/field/selector/base');
|
||||
|
|
|
@ -73,6 +73,7 @@ abstract class DifferentialMail {
|
|||
$cc_phids = $this->getCCPHIDs();
|
||||
$subject = $this->buildSubject();
|
||||
$body = $this->buildBody();
|
||||
$attachments = $this->buildAttachments();
|
||||
|
||||
$template = new PhabricatorMetaMTAMail();
|
||||
$actor_handle = $this->getActorHandle();
|
||||
|
@ -89,6 +90,14 @@ abstract class DifferentialMail {
|
|||
->setParentMessageID($this->parentMessageID)
|
||||
->addHeader('Thread-Topic', $this->getRevision()->getTitle());
|
||||
|
||||
foreach ($attachments as $attachment) {
|
||||
$template->addAttachment(
|
||||
$attachment['data'],
|
||||
$attachment['filename'],
|
||||
$attachment['mimetype']
|
||||
);
|
||||
}
|
||||
|
||||
$template->setThreadID(
|
||||
$this->getThreadID(),
|
||||
$this->isFirstMailAboutRevision());
|
||||
|
@ -165,6 +174,21 @@ EOTEXT;
|
|||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* You can override this method in a subclass and return array of attachments
|
||||
* to be sent with the email. Each attachment is a dictionary with 'data',
|
||||
* 'filename' and 'mimetype' keys. For example:
|
||||
*
|
||||
* array(
|
||||
* 'data' => 'some text',
|
||||
* 'filename' => 'example.txt',
|
||||
* 'mimetype' => 'text/plain'
|
||||
* );
|
||||
*/
|
||||
protected function buildAttachments() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getReplyHandler() {
|
||||
if ($this->replyHandler) {
|
||||
return $this->replyHandler;
|
||||
|
|
|
@ -77,4 +77,39 @@ abstract class DifferentialReviewRequestMail extends DifferentialMail {
|
|||
|
||||
return implode("\n", $body);
|
||||
}
|
||||
|
||||
protected function buildAttachments() {
|
||||
$attachments = array();
|
||||
if (PhabricatorEnv::getEnvConfig('metamta.differential.attach-patches')) {
|
||||
$revision = $this->getRevision();
|
||||
$revision_id = $revision->getID();
|
||||
|
||||
$diffs = $revision->loadDiffs();
|
||||
$diff_number = count($diffs);
|
||||
$diff = array_pop($diffs);
|
||||
|
||||
$filename = "D{$revision_id}.{$diff_number}.diff";
|
||||
|
||||
$diff->attachChangesets($diff->loadChangesets());
|
||||
// TODO: We could batch this to improve performance.
|
||||
foreach ($diff->getChangesets() as $changeset) {
|
||||
$changeset->attachHunks($changeset->loadHunks());
|
||||
}
|
||||
$diff_dict = $diff->getDiffDict();
|
||||
|
||||
$changes = array();
|
||||
foreach ($diff_dict['changes'] as $changedict) {
|
||||
$changes[] = ArcanistDiffChange::newFromDictionary($changedict);
|
||||
}
|
||||
$bundle = ArcanistBundle::newFromChanges($changes);
|
||||
$unified_diff = $bundle->toUnifiedDiff();
|
||||
|
||||
$attachments[] = array(
|
||||
'data' => $unified_diff,
|
||||
'filename' => $filename,
|
||||
'mimetype' => 'text/x-diff; charset=utf-8'
|
||||
);
|
||||
}
|
||||
return $attachments;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,12 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('arcanist', 'parser/bundle');
|
||||
phutil_require_module('arcanist', 'parser/diff/change');
|
||||
|
||||
phutil_require_module('phabricator', 'applications/differential/mail/base');
|
||||
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||
phutil_require_module('phabricator', 'infrastructure/env');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
|
|
@ -146,4 +146,56 @@ class DifferentialDiff extends DifferentialDAO {
|
|||
return $diff;
|
||||
}
|
||||
|
||||
public function getDiffDict() {
|
||||
$dict = array(
|
||||
'id' => $this->getID(),
|
||||
'parent' => $this->getParentRevisionID(),
|
||||
'revisionID' => $this->getRevisionID(),
|
||||
'sourceControlBaseRevision' => $this->getSourceControlBaseRevision(),
|
||||
'sourceControlPath' => $this->getSourceControlPath(),
|
||||
'unitStatus' => $this->getUnitStatus(),
|
||||
'lintStatus' => $this->getLintStatus(),
|
||||
'changes' => array(),
|
||||
'properties' => array(),
|
||||
);
|
||||
|
||||
foreach ($this->getChangesets() as $changeset) {
|
||||
$hunks = array();
|
||||
foreach ($changeset->getHunks() as $hunk) {
|
||||
$hunks[] = array(
|
||||
'oldOffset' => $hunk->getOldOffset(),
|
||||
'newOffset' => $hunk->getNewOffset(),
|
||||
'oldLength' => $hunk->getOldLen(),
|
||||
'newLength' => $hunk->getNewLen(),
|
||||
'addLines' => null,
|
||||
'delLines' => null,
|
||||
'isMissingOldNewline' => null,
|
||||
'isMissingNewNewline' => null,
|
||||
'corpus' => $hunk->getChanges(),
|
||||
);
|
||||
}
|
||||
$change = array(
|
||||
'metadata' => $changeset->getMetadata(),
|
||||
'oldPath' => $changeset->getOldFile(),
|
||||
'currentPath' => $changeset->getFileName(),
|
||||
'awayPaths' => $changeset->getAwayPaths(),
|
||||
'oldProperties' => $changeset->getOldProperties(),
|
||||
'newProperties' => $changeset->getNewProperties(),
|
||||
'type' => $changeset->getChangeType(),
|
||||
'fileType' => $changeset->getFileType(),
|
||||
'commitHash' => null,
|
||||
'hunks' => $hunks,
|
||||
);
|
||||
$dict['changes'][] = $change;
|
||||
}
|
||||
|
||||
$properties = id(new DifferentialDiffProperty())->loadAllWhere(
|
||||
'diffID = %d',
|
||||
$this->getID());
|
||||
foreach ($properties as $property) {
|
||||
$dict['properties'][$property->getName()] = $property->getData();
|
||||
}
|
||||
|
||||
return $dict;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
phutil_require_module('phabricator', 'applications/differential/storage/base');
|
||||
phutil_require_module('phabricator', 'applications/differential/storage/changeset');
|
||||
phutil_require_module('phabricator', 'applications/differential/storage/diffproperty');
|
||||
phutil_require_module('phabricator', 'applications/differential/storage/hunk');
|
||||
phutil_require_module('phabricator', 'applications/repository/storage/arcanistproject');
|
||||
|
||||
|
|
Loading…
Reference in a new issue