diff --git a/conf/default.conf.php b/conf/default.conf.php index 0cb3f9db72..485c0a4026 100644 --- a/conf/default.conf.php +++ b/conf/default.conf.php @@ -997,6 +997,17 @@ return array( // interact with the revisions. 'differential.anonymous-access' => false, + // If you set this to true, revision author email address information will + // be exposed in Conduit. This is useful for Arcanist. + // + // For example, consider the "arc patch DX" workflow which needs to ask + // Differential for the revision DX. This data often should contain + // the author's email address, eg "George Washington + // " when DX is a git or mercurial revision. If this + // option is false, Differential defaults to the best it can, something like + // "George Washington" or "gwashington". + 'differential.expose-emails-prudently' => false, + // List of file regexps that should be treated as if they are generated by // an automatic process, and thus get hidden by default in differential. 'differential.generated-paths' => array( diff --git a/src/applications/conduit/method/differential/ConduitAPI_differential_getdiff_Method.php b/src/applications/conduit/method/differential/ConduitAPI_differential_getdiff_Method.php index 85b59c72b6..5f2719691d 100644 --- a/src/applications/conduit/method/differential/ConduitAPI_differential_getdiff_Method.php +++ b/src/applications/conduit/method/differential/ConduitAPI_differential_getdiff_Method.php @@ -64,7 +64,7 @@ final class ConduitAPI_differential_getdiff_Method extends ConduitAPIMethod { $basic_dict = $diff->getDiffDict(); // for conduit calls, the basic dict is not enough - // we also need to include the arcanist project + // we also need to include the arcanist project and author information $project = $diff->loadArcanistProject(); if ($project) { $project_name = $project->getName(); @@ -72,6 +72,7 @@ final class ConduitAPI_differential_getdiff_Method extends ConduitAPIMethod { $project_name = null; } $basic_dict['projectName'] = $project_name; + $basic_dict['author'] = $diff->loadAuthorInformation(); return $basic_dict; } diff --git a/src/applications/differential/storage/DifferentialDiff.php b/src/applications/differential/storage/DifferentialDiff.php index c8f09d0463..38f64733c3 100644 --- a/src/applications/differential/storage/DifferentialDiff.php +++ b/src/applications/differential/storage/DifferentialDiff.php @@ -312,4 +312,52 @@ final class DifferentialDiff extends DifferentialDAO { return $dict; } + + /** + * Figures out the right author information for a given diff based on the + * repository and Phabricator configuration settings. + * + * Git is particularly finicky as it requires author information to be in + * the format "George Washington " to + * consistently work. If the Phabricator instance isn't configured to + * expose emails prudently, then we are unable to get any author information + * for git. + */ + public function loadAuthorInformation() { + $author = id(new PhabricatorUser()) + ->loadOneWhere('phid = %s', $this->getAuthorPHID()); + + $use_emails = + PhabricatorEnv::getEnvConfig('differential.expose-emails-prudently', + false); + + switch ($this->getSourceControlSystem()) { + case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: + if (!$use_emails) { + $author_info = ''; + } else { + $author_info = $this->getFullAuthorInfo($author); + } + break; + case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: + if (!$use_emails) { + $author_info = $author->getUsername(); + } else { + $author_info = $this->getFullAuthorInfo($author); + } + break; + case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: + default: + $author_info = $author->getUsername(); + break; + } + + return $author_info; + } + + private function getFullAuthorInfo(PhabricatorUser $author) { + return sprintf('%s <%s>', + $author->getRealName(), + $author->loadPrimaryEmailAddress()); + } }