/**
  * Note this code is somewhat similar to the buildPatch method in
  * @{class:DifferentialReviewRequestMail}.
  *
  * @return @{class:AphrontRedirectResponse}
  */
 private function buildRawDiffResponse(array $changesets, array $vs_changesets, array $vs_map, PhabricatorRepository $repository = null)
 {
     assert_instances_of($changesets, 'DifferentialChangeset');
     assert_instances_of($vs_changesets, 'DifferentialChangeset');
     $engine = new PhabricatorDifferenceEngine();
     $generated_changesets = array();
     foreach ($changesets as $changeset) {
         $changeset->attachHunks($changeset->loadHunks());
         $right = $changeset->makeNewFile();
         $choice = $changeset;
         $vs = idx($vs_map, $changeset->getID());
         if ($vs == -1) {
             $left = $right;
             $right = $changeset->makeOldFile();
         } else {
             if ($vs) {
                 $choice = $vs_changeset = $vs_changesets[$vs];
                 $vs_changeset->attachHunks($vs_changeset->loadHunks());
                 $left = $vs_changeset->makeNewFile();
             } else {
                 $left = $changeset->makeOldFile();
             }
         }
         $synthetic = $engine->generateChangesetFromFileContent($left, $right);
         if (!$synthetic->getAffectedLineCount()) {
             $filetype = $choice->getFileType();
             if ($filetype == DifferentialChangeType::FILE_TEXT || $filetype == DifferentialChangeType::FILE_SYMLINK) {
                 continue;
             }
         }
         $choice->attachHunks($synthetic->getHunks());
         $generated_changesets[] = $choice;
     }
     $diff = new DifferentialDiff();
     $diff->attachChangesets($generated_changesets);
     $diff_dict = $diff->getDiffDict();
     $changes = array();
     foreach ($diff_dict['changes'] as $changedict) {
         $changes[] = ArcanistDiffChange::newFromDictionary($changedict);
     }
     $bundle = ArcanistBundle::newFromChanges($changes);
     $bundle->setLoadFileDataCallback(array($this, 'loadFileByPHID'));
     $vcs = $repository ? $repository->getVersionControlSystem() : null;
     switch ($vcs) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
         case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
             $raw_diff = $bundle->toGitPatch();
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
         default:
             $raw_diff = $bundle->toUnifiedDiff();
             break;
     }
     $request_uri = $this->getRequest()->getRequestURI();
     // this ends up being something like
     //   D123.diff
     // or the verbose
     //   D123.vs123.id123.whitespaceignore-all.diff
     // lame but nice to include these options
     $file_name = ltrim($request_uri->getPath(), '/') . '.';
     foreach ($request_uri->getQueryParams() as $key => $value) {
         if ($key == 'download') {
             continue;
         }
         $file_name .= $key . $value . '.';
     }
     $file_name .= 'diff';
     $file = PhabricatorFile::buildFromFileDataOrHash($raw_diff, array('name' => $file_name));
     return id(new AphrontRedirectResponse())->setURI($file->getBestURI());
 }
 private function buildPatch()
 {
     $diff = new DifferentialDiff();
     $diff->attachChangesets($this->getChangesets());
     // 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);
     $bundle->setLoadFileDataCallback(array($this, 'loadFileByPHID'));
     $format = PhabricatorEnv::getEnvConfig('metamta.differential.patch-format');
     switch ($format) {
         case 'git':
             return $bundle->toGitPatch();
             break;
         case 'unified':
         default:
             return $bundle->toUnifiedDiff();
             break;
     }
 }