public function handleRequest(AphrontRequest $request)
 {
     $response = $this->loadDiffusionContext();
     if ($response) {
         return $response;
     }
     $viewer = $this->getViewer();
     $drequest = $this->getDiffusionRequest();
     $content = array();
     $data = $this->callConduitWithDiffusionRequest('diffusion.diffquery', array('commit' => $drequest->getCommit(), 'path' => $drequest->getPath()));
     $drequest->updateSymbolicCommit($data['effectiveCommit']);
     $raw_changes = ArcanistDiffChange::newFromConduit($data['changes']);
     $diff = DifferentialDiff::newEphemeralFromRawChanges($raw_changes);
     $changesets = $diff->getChangesets();
     $changeset = reset($changesets);
     if (!$changeset) {
         // TODO: Refine this.
         return new Aphront404Response();
     }
     $repository = $drequest->getRepository();
     $changesets = array(0 => $changeset);
     $changeset_view = new DifferentialChangesetListView();
     $changeset_view->setTitle(pht('Change'));
     $changeset_view->setChangesets($changesets);
     $changeset_view->setVisibleChangesets($changesets);
     $changeset_view->setRenderingReferences(array(0 => $drequest->generateURI(array('action' => 'rendering-ref'))));
     $raw_params = array('action' => 'browse', 'params' => array('view' => 'raw'));
     $right_uri = $drequest->generateURI($raw_params);
     $raw_params['params']['before'] = $drequest->getStableCommit();
     $left_uri = $drequest->generateURI($raw_params);
     $changeset_view->setRawFileURIs($left_uri, $right_uri);
     $changeset_view->setRenderURI($repository->getPathURI('diff/'));
     $changeset_view->setWhitespace(DifferentialChangesetParser::WHITESPACE_SHOW_ALL);
     $changeset_view->setUser($viewer);
     // TODO: This is pretty awkward, unify the CSS between Diffusion and
     // Differential better.
     require_celerity_resource('differential-core-view-css');
     $content[] = $changeset_view->render();
     $crumbs = $this->buildCrumbs(array('branch' => true, 'path' => true, 'view' => 'change'));
     $links = $this->renderPathLinks($drequest, $mode = 'browse');
     $header = id(new PHUIHeaderView())->setHeader($links)->setUser($viewer)->setPolicyObject($drequest->getRepository());
     $actions = $this->buildActionView($drequest);
     $properties = $this->buildPropertyView($drequest, $actions);
     $object_box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties);
     return $this->newPage()->setTitle(array(basename($drequest->getPath()), $repository->getDisplayName()))->setCrumbs($crumbs)->appendChild(array($object_box, $content));
 }
 public function buildPatch()
 {
     $diff = new DifferentialDiff();
     $diff->attachChangesets($this->getChangesets());
     $raw_changes = $diff->buildChangesList();
     $changes = array();
     foreach ($raw_changes as $changedict) {
         $changes[] = ArcanistDiffChange::newFromDictionary($changedict);
     }
     $viewer = $this->getViewer();
     $loader = id(new PhabricatorFileBundleLoader())->setViewer($viewer);
     $bundle = ArcanistBundle::newFromChanges($changes);
     $bundle->setLoadFileDataCallback(array($loader, 'loadFileData'));
     $format = $this->getFormat();
     switch ($format) {
         case 'git':
             return $bundle->toGitPatch();
             break;
         case 'unified':
         default:
             return $bundle->toUnifiedDiff();
             break;
     }
 }
 /**
  * Note this code is somewhat similar to the buildPatch method in
  * @{class:DifferentialReviewRequestMail}.
  *
  * @return @{class:AphrontRedirectResponse}
  */
 private function buildRawDiffResponse(DifferentialRevision $revision, array $changesets, array $vs_changesets, array $vs_map, PhabricatorRepository $repository = null)
 {
     assert_instances_of($changesets, 'DifferentialChangeset');
     assert_instances_of($vs_changesets, 'DifferentialChangeset');
     $viewer = $this->getRequest()->getUser();
     id(new DifferentialHunkQuery())->setViewer($viewer)->withChangesets($changesets)->needAttachToChangesets(true)->execute();
     $diff = new DifferentialDiff();
     $diff->attachChangesets($changesets);
     $raw_changes = $diff->buildChangesList();
     $changes = array();
     foreach ($raw_changes as $changedict) {
         $changes[] = ArcanistDiffChange::newFromDictionary($changedict);
     }
     $loader = id(new PhabricatorFileBundleLoader())->setViewer($viewer);
     $bundle = ArcanistBundle::newFromChanges($changes);
     $bundle->setLoadFileDataCallback(array($loader, 'loadFileData'));
     $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, 'ttl' => 60 * 60 * 24, 'viewPolicy' => PhabricatorPolicies::POLICY_NOONE));
     $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
     $file->attachToObject($revision->getPHID());
     unset($unguarded);
     return $file->getRedirectResponse();
 }
 public static final function convertToArcanistChanges(array $changes)
 {
     assert_instances_of($changes, 'DiffusionPathChange');
     $direct = array();
     $result = array();
     foreach ($changes as $path) {
         $change = new ArcanistDiffChange();
         $change->setCurrentPath($path->getPath());
         $direct[] = $path->getPath();
         $change->setType($path->getChangeType());
         $file_type = $path->getFileType();
         if ($file_type == DifferentialChangeType::FILE_NORMAL) {
             $file_type = DifferentialChangeType::FILE_TEXT;
         }
         $change->setFileType($file_type);
         $change->setOldPath($path->getTargetPath());
         foreach ($path->getAwayPaths() as $away_path) {
             $change->addAwayPath($away_path);
         }
         $result[$path->getPath()] = $change;
     }
     return array_select_keys($result, $direct);
 }
 protected function getChange($path)
 {
     $repository_api = $this->getRepositoryAPI();
     // TODO: Very gross
     $is_git = $repository_api instanceof ArcanistGitAPI;
     $is_hg = $repository_api instanceof ArcanistMercurialAPI;
     $is_svn = $repository_api instanceof ArcanistSubversionAPI;
     if ($is_svn) {
         // NOTE: In SVN, we don't currently support a "get all local changes"
         // operation, so special case it.
         if (empty($this->changeCache[$path])) {
             $diff = $repository_api->getRawDiffText($path);
             $parser = $this->newDiffParser();
             $changes = $parser->parseDiff($diff);
             if (count($changes) != 1) {
                 throw new Exception("Expected exactly one change.");
             }
             $this->changeCache[$path] = reset($changes);
         }
     } else {
         if ($is_git || $is_hg) {
             if (empty($this->changeCache)) {
                 $changes = $repository_api->getAllLocalChanges();
                 foreach ($changes as $change) {
                     $this->changeCache[$change->getCurrentPath()] = $change;
                 }
             }
         } else {
             throw new Exception("Missing VCS support.");
         }
     }
     if (empty($this->changeCache[$path])) {
         if ($is_git) {
             // This can legitimately occur under git if you make a change, "git
             // commit" it, and then revert the change in the working copy and run
             // "arc lint".
             $change = new ArcanistDiffChange();
             $change->setCurrentPath($path);
             return $change;
         } else {
             throw new Exception("Trying to get change for unchanged path '{$path}'!");
         }
     }
     return $this->changeCache[$path];
 }
 protected function execute(ConduitAPIRequest $request)
 {
     $viewer = $request->getUser();
     $change_data = $request->getValue('changes');
     $changes = array();
     foreach ($change_data as $dict) {
         $changes[] = ArcanistDiffChange::newFromDictionary($dict);
     }
     $diff = DifferentialDiff::newFromRawChanges($viewer, $changes);
     // TODO: Remove repository UUID eventually; for now continue writing
     // the UUID. Note that we'll overwrite it below if we identify a
     // repository, and `arc` no longer sends it. This stuff is retained for
     // backward compatibility.
     $repository_uuid = $request->getValue('repositoryUUID');
     $repository_phid = $request->getValue('repositoryPHID');
     if ($repository_phid) {
         $repository = id(new PhabricatorRepositoryQuery())->setViewer($viewer)->withPHIDs(array($repository_phid))->executeOne();
         if ($repository) {
             $repository_phid = $repository->getPHID();
             $repository_uuid = $repository->getUUID();
         }
     }
     switch ($request->getValue('lintStatus')) {
         case 'skip':
             $lint_status = DifferentialLintStatus::LINT_SKIP;
             break;
         case 'okay':
             $lint_status = DifferentialLintStatus::LINT_OKAY;
             break;
         case 'warn':
             $lint_status = DifferentialLintStatus::LINT_WARN;
             break;
         case 'fail':
             $lint_status = DifferentialLintStatus::LINT_FAIL;
             break;
         case 'postponed':
             $lint_status = DifferentialLintStatus::LINT_POSTPONED;
             break;
         case 'none':
         default:
             $lint_status = DifferentialLintStatus::LINT_NONE;
             break;
     }
     switch ($request->getValue('unitStatus')) {
         case 'skip':
             $unit_status = DifferentialUnitStatus::UNIT_SKIP;
             break;
         case 'okay':
             $unit_status = DifferentialUnitStatus::UNIT_OKAY;
             break;
         case 'warn':
             $unit_status = DifferentialUnitStatus::UNIT_WARN;
             break;
         case 'fail':
             $unit_status = DifferentialUnitStatus::UNIT_FAIL;
             break;
         case 'postponed':
             $unit_status = DifferentialUnitStatus::UNIT_POSTPONED;
             break;
         case 'none':
         default:
             $unit_status = DifferentialUnitStatus::UNIT_NONE;
             break;
     }
     $diff_data_dict = array('sourcePath' => $request->getValue('sourcePath'), 'sourceMachine' => $request->getValue('sourceMachine'), 'branch' => $request->getValue('branch'), 'creationMethod' => $request->getValue('creationMethod'), 'authorPHID' => $viewer->getPHID(), 'bookmark' => $request->getValue('bookmark'), 'repositoryUUID' => $repository_uuid, 'repositoryPHID' => $repository_phid, 'sourceControlSystem' => $request->getValue('sourceControlSystem'), 'sourceControlPath' => $request->getValue('sourceControlPath'), 'sourceControlBaseRevision' => $request->getValue('sourceControlBaseRevision'), 'lintStatus' => $lint_status, 'unitStatus' => $unit_status);
     $xactions = array(id(new DifferentialTransaction())->setTransactionType(DifferentialDiffTransaction::TYPE_DIFF_CREATE)->setNewValue($diff_data_dict));
     id(new DifferentialDiffEditor())->setActor($viewer)->setContentSourceFromConduitRequest($request)->setContinueOnNoEffect(true)->applyTransactions($diff, $xactions);
     $path = '/differential/diff/' . $diff->getID() . '/';
     $uri = PhabricatorEnv::getURI($path);
     return array('diffid' => $diff->getID(), 'phid' => $diff->getPHID(), 'uri' => $uri);
 }
 /**
  * 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());
 }
 protected function buildChange($path = null)
 {
     $change = null;
     if ($path !== null) {
         if (!empty($this->changes[$path])) {
             return $this->changes[$path];
         }
     }
     if ($this->forcePath) {
         return $this->changes[$this->forcePath];
     }
     $change = new ArcanistDiffChange();
     if ($path !== null) {
         $change->setCurrentPath($path);
         $this->changes[$path] = $change;
     } else {
         $this->changes[] = $change;
     }
     return $change;
 }
 private function buildBinaryChange(ArcanistDiffChange $change, $old_binary)
 {
     $eol = $this->getEOL('git');
     // In Git, when we write out a binary file move or copy, we need the
     // original binary for the source and the current binary for the
     // destination.
     if ($old_binary) {
         if ($old_binary->getOriginalFileData() !== null) {
             $old_data = $old_binary->getOriginalFileData();
             $old_phid = null;
         } else {
             $old_data = null;
             $old_phid = $old_binary->getMetadata('old:binary-phid');
         }
     } else {
         $old_data = $change->getOriginalFileData();
         $old_phid = $change->getMetadata('old:binary-phid');
     }
     if ($old_data === null && $old_phid) {
         $name = basename($change->getOldPath());
         $old_data = $this->getBlob($old_phid, $name);
     }
     $old_length = strlen($old_data);
     if ($old_data === null) {
         $old_data = '';
         $old_sha1 = str_repeat('0', 40);
     } else {
         $old_sha1 = sha1("blob {$old_length}{$old_data}");
     }
     $new_phid = $change->getMetadata('new:binary-phid');
     $new_data = null;
     if ($change->getCurrentFileData() !== null) {
         $new_data = $change->getCurrentFileData();
     } else {
         if ($new_phid) {
             $name = basename($change->getCurrentPath());
             $new_data = $this->getBlob($new_phid, $name);
         }
     }
     $new_length = strlen($new_data);
     if ($new_data === null) {
         $new_data = '';
         $new_sha1 = str_repeat('0', 40);
     } else {
         $new_sha1 = sha1("blob {$new_length}{$new_data}");
     }
     $content = array();
     $content[] = "index {$old_sha1}..{$new_sha1}" . $eol;
     $content[] = "GIT binary patch" . $eol;
     $content[] = "literal {$new_length}" . $eol;
     $content[] = $this->emitBinaryDiffBody($new_data) . $eol;
     $content[] = "literal {$old_length}" . $eol;
     $content[] = $this->emitBinaryDiffBody($old_data) . $eol;
     return implode('', $content);
 }
 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}.patch";
         $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[] = new PhabricatorMetaMTAAttachment($unified_diff, $filename, 'text/x-patch; charset=utf-8');
     }
     return $attachments;
 }
 protected function execute(ConduitAPIRequest $request)
 {
     $change_data = $request->getValue('changes');
     $changes = array();
     foreach ($change_data as $dict) {
         $changes[] = ArcanistDiffChange::newFromDictionary($dict);
     }
     $diff = DifferentialDiff::newFromRawChanges($changes);
     $diff->setSourcePath($request->getValue('sourcePath'));
     $diff->setSourceMachine($request->getValue('sourceMachine'));
     $diff->setBranch($request->getValue('branch'));
     $diff->setCreationMethod($request->getValue('creationMethod'));
     $diff->setAuthorPHID($request->getValue('authorPHID'));
     $parent_id = $request->getValue('parentRevisionID');
     if ($parent_id) {
         $parent_rev = id(new DifferentialRevision())->load($parent_id);
         if ($parent_rev) {
             if ($parent_rev->getStatus() != DifferentialRevisionStatus::COMMITTED) {
                 $diff->setParentRevisionID($parent_id);
             }
         }
     }
     $system = $request->getValue('sourceControlSystem');
     $diff->setSourceControlSystem($system);
     $diff->setSourceControlPath($request->getValue('sourceControlPath'));
     $diff->setSourceControlBaseRevision($request->getValue('sourceControlBaseRevision'));
     $project_name = $request->getValue('arcanistProject');
     $project_phid = null;
     if ($project_name) {
         $arcanist_project = id(new PhabricatorRepositoryArcanistProject())->loadOneWhere('name = %s', $project_name);
         if (!$arcanist_project) {
             $arcanist_project = new PhabricatorRepositoryArcanistProject();
             $arcanist_project->setName($project_name);
             $arcanist_project->save();
         }
         $project_phid = $arcanist_project->getPHID();
     }
     $diff->setArcanistProjectPHID($project_phid);
     $diff->setRepositoryUUID($request->getValue('repositoryUUID'));
     switch ($request->getValue('lintStatus')) {
         case 'skip':
             $diff->setLintStatus(DifferentialLintStatus::LINT_SKIP);
             break;
         case 'okay':
             $diff->setLintStatus(DifferentialLintStatus::LINT_OKAY);
             break;
         case 'warn':
             $diff->setLintStatus(DifferentialLintStatus::LINT_WARN);
             break;
         case 'fail':
             $diff->setLintStatus(DifferentialLintStatus::LINT_FAIL);
             break;
         case 'none':
         default:
             $diff->setLintStatus(DifferentialLintStatus::LINT_NONE);
             break;
     }
     switch ($request->getValue('unitStatus')) {
         case 'skip':
             $diff->setUnitStatus(DifferentialUnitStatus::UNIT_SKIP);
             break;
         case 'okay':
             $diff->setUnitStatus(DifferentialUnitStatus::UNIT_OKAY);
             break;
         case 'warn':
             $diff->setUnitStatus(DifferentialUnitStatus::UNIT_WARN);
             break;
         case 'fail':
             $diff->setUnitStatus(DifferentialUnitStatus::UNIT_FAIL);
             break;
         case 'postponed':
             $diff->setUnitStatus(DifferentialUnitStatus::UNIT_POSTPONED);
             break;
         case 'none':
         default:
             $diff->setUnitStatus(DifferentialUnitStatus::UNIT_NONE);
             break;
     }
     $diff->save();
     $path = '/differential/diff/' . $diff->getID() . '/';
     $uri = PhabricatorEnv::getURI($path);
     return array('diffid' => $diff->getID(), 'uri' => $uri);
 }
Exemple #12
0
 private function buildBinaryChange(ArcanistDiffChange $change)
 {
     $old_phid = $change->getMetadata('old:binary-phid', null);
     $new_phid = $change->getMetadata('new:binary-phid', null);
     $type = $change->getType();
     if ($type == ArcanistDiffChangeType::TYPE_ADD) {
         $old_null = true;
     } else {
         $old_null = false;
     }
     if ($type == ArcanistDiffChangeType::TYPE_DELETE) {
         $new_null = true;
     } else {
         $new_null = false;
     }
     if ($old_null) {
         $old_data = '';
         $old_length = 0;
         $old_sha1 = str_repeat('0', 40);
     } else {
         $old_data = $this->getBlob($old_phid);
         $old_length = strlen($old_data);
         $old_sha1 = sha1("blob {$old_length}{$old_data}");
     }
     if ($new_null) {
         $new_data = '';
         $new_length = 0;
         $new_sha1 = str_repeat('0', 40);
     } else {
         $new_data = $this->getBlob($new_phid);
         $new_length = strlen($new_data);
         $new_sha1 = sha1("blob {$new_length}{$new_data}");
     }
     $content = array();
     $content[] = "index {$old_sha1}..{$new_sha1}";
     $content[] = "GIT binary patch";
     $content[] = "literal {$new_length}";
     $content[] = $this->emitBinaryDiffBody($new_data);
     $content[] = "literal {$old_length}";
     $content[] = $this->emitBinaryDiffBody($old_data);
     return implode("\n", $content);
 }
 protected function execute(ConduitAPIRequest $request)
 {
     $viewer = $request->getUser();
     $change_data = $request->getValue('changes');
     $changes = array();
     foreach ($change_data as $dict) {
         $changes[] = ArcanistDiffChange::newFromDictionary($dict);
     }
     $diff = DifferentialDiff::newFromRawChanges($changes);
     $diff->setSourcePath($request->getValue('sourcePath'));
     $diff->setSourceMachine($request->getValue('sourceMachine'));
     $diff->setBranch($request->getValue('branch'));
     $diff->setCreationMethod($request->getValue('creationMethod'));
     $diff->setAuthorPHID($viewer->getPHID());
     $diff->setBookmark($request->getValue('bookmark'));
     // TODO: Remove this eventually; for now continue writing the UUID. Note
     // that we'll overwrite it below if we identify a repository, and `arc`
     // no longer sends it. This stuff is retained for backward compatibility.
     $diff->setRepositoryUUID($request->getValue('repositoryUUID'));
     $repository_phid = $request->getValue('repositoryPHID');
     if ($repository_phid) {
         $repository = id(new PhabricatorRepositoryQuery())->setViewer($viewer)->withPHIDs(array($repository_phid))->executeOne();
         if ($repository) {
             $diff->setRepositoryPHID($repository->getPHID());
             $diff->setRepositoryUUID($repository->getUUID());
         }
     }
     $system = $request->getValue('sourceControlSystem');
     $diff->setSourceControlSystem($system);
     $diff->setSourceControlPath($request->getValue('sourceControlPath'));
     $diff->setSourceControlBaseRevision($request->getValue('sourceControlBaseRevision'));
     $project_name = $request->getValue('arcanistProject');
     $project_phid = null;
     if ($project_name) {
         $arcanist_project = id(new PhabricatorRepositoryArcanistProject())->loadOneWhere('name = %s', $project_name);
         if (!$arcanist_project) {
             $arcanist_project = new PhabricatorRepositoryArcanistProject();
             $arcanist_project->setName($project_name);
             $arcanist_project->save();
         }
         $project_phid = $arcanist_project->getPHID();
     }
     $diff->setArcanistProjectPHID($project_phid);
     switch ($request->getValue('lintStatus')) {
         case 'skip':
             $diff->setLintStatus(DifferentialLintStatus::LINT_SKIP);
             break;
         case 'okay':
             $diff->setLintStatus(DifferentialLintStatus::LINT_OKAY);
             break;
         case 'warn':
             $diff->setLintStatus(DifferentialLintStatus::LINT_WARN);
             break;
         case 'fail':
             $diff->setLintStatus(DifferentialLintStatus::LINT_FAIL);
             break;
         case 'postponed':
             $diff->setLintStatus(DifferentialLintStatus::LINT_POSTPONED);
             break;
         case 'none':
         default:
             $diff->setLintStatus(DifferentialLintStatus::LINT_NONE);
             break;
     }
     switch ($request->getValue('unitStatus')) {
         case 'skip':
             $diff->setUnitStatus(DifferentialUnitStatus::UNIT_SKIP);
             break;
         case 'okay':
             $diff->setUnitStatus(DifferentialUnitStatus::UNIT_OKAY);
             break;
         case 'warn':
             $diff->setUnitStatus(DifferentialUnitStatus::UNIT_WARN);
             break;
         case 'fail':
             $diff->setUnitStatus(DifferentialUnitStatus::UNIT_FAIL);
             break;
         case 'postponed':
             $diff->setUnitStatus(DifferentialUnitStatus::UNIT_POSTPONED);
             break;
         case 'none':
         default:
             $diff->setUnitStatus(DifferentialUnitStatus::UNIT_NONE);
             break;
     }
     id(new DifferentialDiffEditor())->setActor($viewer)->setContentSource(PhabricatorContentSource::newFromConduitRequest($request))->saveDiff($diff);
     // If we didn't get an explicit `repositoryPHID` (which means the client is
     // old, or couldn't figure out which repository the working copy belongs
     // to), apply heuristics to try to figure it out.
     if (!$repository_phid) {
         $repository = id(new DifferentialRepositoryLookup())->setDiff($diff)->setViewer($viewer)->lookupRepository();
         if ($repository) {
             $diff->setRepositoryPHID($repository->getPHID());
             $diff->setRepositoryUUID($repository->getUUID());
             $diff->save();
         }
     }
     $path = '/differential/diff/' . $diff->getID() . '/';
     $uri = PhabricatorEnv::getURI($path);
     return array('diffid' => $diff->getID(), 'uri' => $uri);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $response = $this->loadDiffusionContext();
     if ($response) {
         return $response;
     }
     $viewer = $this->getViewer();
     $drequest = $this->getDiffusionRequest();
     if (!$request->isAjax()) {
         // This request came out of the dropdown menu, either "View Standalone"
         // or "View Raw File".
         $view = $request->getStr('view');
         if ($view == 'r') {
             $uri = $drequest->generateURI(array('action' => 'browse', 'params' => array('view' => 'raw')));
         } else {
             $uri = $drequest->generateURI(array('action' => 'change'));
         }
         return id(new AphrontRedirectResponse())->setURI($uri);
     }
     $data = $this->callConduitWithDiffusionRequest('diffusion.diffquery', array('commit' => $drequest->getCommit(), 'path' => $drequest->getPath()));
     $drequest->updateSymbolicCommit($data['effectiveCommit']);
     $raw_changes = ArcanistDiffChange::newFromConduit($data['changes']);
     $diff = DifferentialDiff::newEphemeralFromRawChanges($raw_changes);
     $changesets = $diff->getChangesets();
     $changeset = reset($changesets);
     if (!$changeset) {
         return new Aphront404Response();
     }
     $parser = new DifferentialChangesetParser();
     $parser->setUser($viewer);
     $parser->setChangeset($changeset);
     $parser->setRenderingReference($drequest->generateURI(array('action' => 'rendering-ref')));
     $parser->readParametersFromRequest($request);
     $coverage = $drequest->loadCoverage();
     if ($coverage) {
         $parser->setCoverage($coverage);
     }
     $commit = $drequest->loadCommit();
     $pquery = new DiffusionPathIDQuery(array($changeset->getFilename()));
     $ids = $pquery->loadPathIDs();
     $path_id = $ids[$changeset->getFilename()];
     $parser->setLeftSideCommentMapping($path_id, false);
     $parser->setRightSideCommentMapping($path_id, true);
     $parser->setCanMarkDone($commit->getAuthorPHID() && $viewer->getPHID() == $commit->getAuthorPHID());
     $parser->setObjectOwnerPHID($commit->getAuthorPHID());
     $parser->setWhitespaceMode(DifferentialChangesetParser::WHITESPACE_SHOW_ALL);
     $inlines = PhabricatorAuditInlineComment::loadDraftAndPublishedComments($viewer, $commit->getPHID(), $path_id);
     if ($inlines) {
         foreach ($inlines as $inline) {
             $parser->parseInlineComment($inline);
         }
         $phids = mpull($inlines, 'getAuthorPHID');
         $handles = $this->loadViewerHandles($phids);
         $parser->setHandles($handles);
     }
     $engine = new PhabricatorMarkupEngine();
     $engine->setViewer($viewer);
     foreach ($inlines as $inline) {
         $engine->addObject($inline, PhabricatorInlineCommentInterface::MARKUP_FIELD_BODY);
     }
     $engine->process();
     $parser->setMarkupEngine($engine);
     $spec = $request->getStr('range');
     list($range_s, $range_e, $mask) = DifferentialChangesetParser::parseRangeSpecification($spec);
     $parser->setRange($range_s, $range_e);
     $parser->setMask($mask);
     return id(new PhabricatorChangesetResponse())->setRenderedChangeset($parser->renderChangeset())->setUndoTemplates($parser->getRenderer()->renderUndoTemplates());
 }
 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;
     }
 }