1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-28 00:10: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:
Marek Sapota 2011-10-14 12:08:31 -07:00
parent fee7184350
commit 87a2987ad6
10 changed files with 126 additions and 61 deletions

View file

@ -232,6 +232,11 @@ return array(
// Prefix prepended to mail sent by Differential. // Prefix prepended to mail sent by Differential.
'metamta.differential.subject-prefix' => '[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 // By default, Phabricator generates unique reply-to addresses and sends a
// separate email to each recipient when you enable reply handling. This is // separate email to each recipient when you enable reply handling. This is
// more secure than using "From" to establish user identity, but can mean // more secure than using "From" to establish user identity, but can mean

View file

@ -72,60 +72,7 @@ class ConduitAPI_differential_getdiff_Method extends ConduitAPIMethod {
$changeset->attachHunks($changeset->loadHunks()); $changeset->attachHunks($changeset->loadHunks());
} }
return $this->createDiffDict($diff); return $diff->getDiffDict();
}
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;
} }
} }

View file

@ -9,7 +9,6 @@
phutil_require_module('phabricator', 'applications/conduit/method/base'); phutil_require_module('phabricator', 'applications/conduit/method/base');
phutil_require_module('phabricator', 'applications/conduit/protocol/exception'); phutil_require_module('phabricator', 'applications/conduit/protocol/exception');
phutil_require_module('phabricator', 'applications/differential/storage/diff'); 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('phabricator', 'applications/differential/storage/revision');
phutil_require_module('phutil', 'utils'); phutil_require_module('phutil', 'utils');

View file

@ -62,8 +62,7 @@ class ConduitAPI_differential_getrevision_Method extends ConduitAPIMethod {
foreach ($diff->getChangesets() as $changeset) { foreach ($diff->getChangesets() as $changeset) {
$changeset->attachHunks($changeset->loadHunks()); $changeset->attachHunks($changeset->loadHunks());
} }
$diff_dicts[] = $diff_dicts[] = $diff->getDiffDict();
ConduitAPI_differential_getdiff_Method::createDiffDict($diff);
} }
$commit_dicts = array(); $commit_dicts = array();

View file

@ -7,7 +7,6 @@
phutil_require_module('phabricator', 'applications/conduit/method/base'); 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/conduit/protocol/exception');
phutil_require_module('phabricator', 'applications/differential/constants/revisionstatus'); phutil_require_module('phabricator', 'applications/differential/constants/revisionstatus');
phutil_require_module('phabricator', 'applications/differential/field/selector/base'); phutil_require_module('phabricator', 'applications/differential/field/selector/base');

View file

@ -73,6 +73,7 @@ abstract class DifferentialMail {
$cc_phids = $this->getCCPHIDs(); $cc_phids = $this->getCCPHIDs();
$subject = $this->buildSubject(); $subject = $this->buildSubject();
$body = $this->buildBody(); $body = $this->buildBody();
$attachments = $this->buildAttachments();
$template = new PhabricatorMetaMTAMail(); $template = new PhabricatorMetaMTAMail();
$actor_handle = $this->getActorHandle(); $actor_handle = $this->getActorHandle();
@ -89,6 +90,14 @@ abstract class DifferentialMail {
->setParentMessageID($this->parentMessageID) ->setParentMessageID($this->parentMessageID)
->addHeader('Thread-Topic', $this->getRevision()->getTitle()); ->addHeader('Thread-Topic', $this->getRevision()->getTitle());
foreach ($attachments as $attachment) {
$template->addAttachment(
$attachment['data'],
$attachment['filename'],
$attachment['mimetype']
);
}
$template->setThreadID( $template->setThreadID(
$this->getThreadID(), $this->getThreadID(),
$this->isFirstMailAboutRevision()); $this->isFirstMailAboutRevision());
@ -165,6 +174,21 @@ EOTEXT;
return $body; 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() { public function getReplyHandler() {
if ($this->replyHandler) { if ($this->replyHandler) {
return $this->replyHandler; return $this->replyHandler;

View file

@ -77,4 +77,39 @@ abstract class DifferentialReviewRequestMail extends DifferentialMail {
return implode("\n", $body); 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;
}
} }

View file

@ -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/differential/mail/base');
phutil_require_module('phabricator', 'applications/phid/handle/data'); phutil_require_module('phabricator', 'applications/phid/handle/data');
phutil_require_module('phabricator', 'infrastructure/env');
phutil_require_module('phutil', 'utils'); phutil_require_module('phutil', 'utils');

View file

@ -146,4 +146,56 @@ class DifferentialDiff extends DifferentialDAO {
return $diff; 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;
}
} }

View file

@ -8,6 +8,7 @@
phutil_require_module('phabricator', 'applications/differential/storage/base'); phutil_require_module('phabricator', 'applications/differential/storage/base');
phutil_require_module('phabricator', 'applications/differential/storage/changeset'); 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/differential/storage/hunk');
phutil_require_module('phabricator', 'applications/repository/storage/arcanistproject'); phutil_require_module('phabricator', 'applications/repository/storage/arcanistproject');