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();
 }
 private function loadBundleFromConduit(ConduitClient $conduit, $params)
 {
     $future = $conduit->callMethod('differential.getdiff', $params);
     $diff = $future->resolve();
     $changes = array();
     foreach ($diff['changes'] as $changedict) {
         $changes[] = ArcanistDiffChange::newFromDictionary($changedict);
     }
     $bundle = ArcanistBundle::newFromChanges($changes);
     $bundle->setConduit($conduit);
     // since the conduit method has changes, assume that these fields
     // could be unset
     $bundle->setProjectID(idx($diff, 'projectName'));
     $bundle->setBaseRevision(idx($diff, 'sourceControlBaseRevision'));
     $bundle->setRevisionID(idx($diff, 'revisionID'));
     $bundle->setAuthorName(idx($diff, 'authorName'));
     $bundle->setAuthorEmail(idx($diff, 'authorEmail'));
     return $bundle;
 }
 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());
 }
 private function loadBundleFromConduit(ConduitClient $conduit, $params)
 {
     $future = $conduit->callMethod('differential.getdiff', $params);
     $diff = $future->resolve();
     $changes = array();
     foreach ($diff['changes'] as $changedict) {
         $changes[] = ArcanistDiffChange::newFromDictionary($changedict);
     }
     $bundle = ArcanistBundle::newFromChanges($changes);
     $bundle->setConduit($conduit);
     $bundle->setProjectID($diff['projectName']);
     $bundle->setBaseRevision($diff['sourceControlBaseRevision']);
     $bundle->setRevisionID($diff['revisionID']);
     return $bundle;
 }
 public static function newFromArcBundle($path)
 {
     $path = Filesystem::resolvePath($path);
     $future = new ExecFuture('tar tfO %s', $path);
     list($stdout, $file_list) = $future->resolvex();
     $file_list = explode("\n", trim($file_list));
     if (in_array('meta.json', $file_list)) {
         $future = new ExecFuture('tar xfO %s meta.json', $path);
         $meta_info = $future->resolveJSON();
         $version = idx($meta_info, 'version', 0);
         $project_name = idx($meta_info, 'projectName');
         $base_revision = idx($meta_info, 'baseRevision');
         $revision_id = idx($meta_info, 'revisionID');
         $encoding = idx($meta_info, 'encoding');
         $author_name = idx($meta_info, 'authorName');
         $author_email = idx($meta_info, 'authorEmail');
     } else {
         // this arc bundle was probably made before we started storing meta info
         $version = 0;
         $project_name = null;
         $base_revision = null;
         $revision_id = null;
         $encoding = null;
         $author = null;
     }
     $future = new ExecFuture('tar xfO %s changes.json', $path);
     $changes = $future->resolveJSON();
     foreach ($changes as $change_key => $change) {
         foreach ($change['hunks'] as $key => $hunk) {
             list($hunk_data) = execx('tar xfO %s hunks/%s', $path, $hunk['corpus']);
             $changes[$change_key]['hunks'][$key]['corpus'] = $hunk_data;
         }
     }
     foreach ($changes as $change_key => $change) {
         $changes[$change_key] = ArcanistDiffChange::newFromDictionary($change);
     }
     $obj = new ArcanistBundle();
     $obj->changes = $changes;
     $obj->diskPath = $path;
     $obj->setProjectID($project_name);
     $obj->setBaseRevision($base_revision);
     $obj->setRevisionID($revision_id);
     $obj->setEncoding($encoding);
     return $obj;
 }
 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);
 }
 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);
 }
 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;
     }
 }