protected function executeQuery() { $raw_diff = $this->executeRawDiffCommand(); // the only legitimate case here is if we are looking at the first commit // in the repository. no parents means first commit. if (!$raw_diff) { $drequest = $this->getRequest(); $parent_query = DiffusionCommitParentsQuery::newFromDiffusionRequest($drequest); $parents = $parent_query->loadParents(); if ($parents === array()) { // mercurial likes the string null here $this->setAgainstCommit('null'); $raw_diff = $this->executeRawDiffCommand(); } } return $raw_diff; }
private function attachToRevision(DifferentialRevision $revision, $actor_phid) { $drequest = DiffusionRequest::newFromDictionary(array('repository' => $this->repository, 'commit' => $this->commit->getCommitIdentifier())); $raw_diff = DiffusionRawDiffQuery::newFromDiffusionRequest($drequest)->loadRawDiff(); $changes = id(new ArcanistDiffParser())->parseDiff($raw_diff); $diff = DifferentialDiff::newFromRawChanges($changes)->setRevisionID($revision->getID())->setAuthorPHID($actor_phid)->setCreationMethod('commit')->setSourceControlSystem($this->repository->getVersionControlSystem())->setLintStatus(DifferentialLintStatus::LINT_SKIP)->setUnitStatus(DifferentialUnitStatus::UNIT_SKIP)->setDateCreated($this->commit->getEpoch())->setDescription('Commit r' . $this->repository->getCallsign() . $this->commit->getCommitIdentifier()); // TODO: This is not correct in SVN where one repository can have multiple // Arcanist projects. $arcanist_project = id(new PhabricatorRepositoryArcanistProject())->loadOneWhere('repositoryID = %d LIMIT 1', $this->repository->getID()); if ($arcanist_project) { $diff->setArcanistProjectPHID($arcanist_project->getPHID()); } $parents = DiffusionCommitParentsQuery::newFromDiffusionRequest($drequest)->loadParents(); if ($parents) { $diff->setSourceControlBaseRevision(head_key($parents)); } // TODO: Attach binary files. $revision->setLineCount($diff->getLineCount()); return $diff->save(); }
public function processRequest() { $drequest = $this->getDiffusionRequest(); $request = $this->getRequest(); $user = $request->getUser(); $callsign = $drequest->getRepository()->getCallsign(); $content = array(); $content[] = $this->buildCrumbs(array('commit' => true)); $repository = $drequest->getRepository(); $commit = $drequest->loadCommit(); if (!$commit) { // TODO: Make more user-friendly. throw new Exception('This commit has not parsed yet.'); } $commit_data = $drequest->loadCommitData(); $commit->attachCommitData($commit_data); $is_foreign = $commit_data->getCommitDetail('foreign-svn-stub'); if ($is_foreign) { $subpath = $commit_data->getCommitDetail('svn-subpath'); $error_panel = new AphrontErrorView(); $error_panel->setWidth(AphrontErrorView::WIDTH_WIDE); $error_panel->setTitle('Commit Not Tracked'); $error_panel->setSeverity(AphrontErrorView::SEVERITY_WARNING); $error_panel->appendChild("This Diffusion repository is configured to track only one " . "subdirectory of the entire Subversion repository, and this commit " . "didn't affect the tracked subdirectory ('" . phutil_escape_html($subpath) . "'), so no information is available."); $content[] = $error_panel; } else { $engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine(); require_celerity_resource('diffusion-commit-view-css'); require_celerity_resource('phabricator-remarkup-css'); $parent_query = DiffusionCommitParentsQuery::newFromDiffusionRequest($drequest); $headsup_panel = new AphrontHeadsupView(); $headsup_panel->setHeader('Commit Detail'); $headsup_panel->setActionList($this->renderHeadsupActionList($commit)); $headsup_panel->setProperties($this->getCommitProperties($commit, $commit_data, $parent_query->loadParents())); $headsup_panel->appendChild('<div class="diffusion-commit-message phabricator-remarkup">' . $engine->markupText($commit_data->getCommitMessage()) . '</div>'); $content[] = $headsup_panel; } $query = new PhabricatorAuditQuery(); $query->withCommitPHIDs(array($commit->getPHID())); $audit_requests = $query->execute(); $this->auditAuthorityPHIDs = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($user); $content[] = $this->buildAuditTable($commit, $audit_requests); $content[] = $this->buildComments($commit); $change_query = DiffusionPathChangeQuery::newFromDiffusionRequest($drequest); $changes = $change_query->loadChanges(); $content[] = $this->buildMergesTable($commit); $original_changes_count = count($changes); if ($request->getStr('show_all') !== 'true' && $original_changes_count > self::CHANGES_LIMIT) { $changes = array_slice($changes, 0, self::CHANGES_LIMIT); } $change_table = new DiffusionCommitChangeTableView(); $change_table->setDiffusionRequest($drequest); $change_table->setPathChanges($changes); $count = count($changes); $bad_commit = null; if ($count == 0) { $bad_commit = queryfx_one(id(new PhabricatorRepository())->establishConnection('r'), 'SELECT * FROM %T WHERE fullCommitName = %s', PhabricatorRepository::TABLE_BADCOMMIT, 'r' . $callsign . $commit->getCommitIdentifier()); } if ($bad_commit) { $error_panel = new AphrontErrorView(); $error_panel->setWidth(AphrontErrorView::WIDTH_WIDE); $error_panel->setTitle('Bad Commit'); $error_panel->appendChild(phutil_escape_html($bad_commit['description'])); $content[] = $error_panel; } else { if ($is_foreign) { // Don't render anything else. } else { if (!count($changes)) { $no_changes = new AphrontErrorView(); $no_changes->setWidth(AphrontErrorView::WIDTH_WIDE); $no_changes->setSeverity(AphrontErrorView::SEVERITY_WARNING); $no_changes->setTitle('Not Yet Parsed'); // TODO: This can also happen with weird SVN changes that don't do // anything (or only alter properties?), although the real no-changes case // is extremely rare and might be impossible to produce organically. We // should probably write some kind of "Nothing Happened!" change into the // DB once we parse these changes so we can distinguish between // "not parsed yet" and "no changes". $no_changes->appendChild("This commit hasn't been fully parsed yet (or doesn't affect any " . "paths)."); $content[] = $no_changes; } else { $change_panel = new AphrontPanelView(); $change_panel->setHeader("Changes (" . number_format($count) . ")"); if ($count !== $original_changes_count) { $show_all_button = phutil_render_tag('a', array('class' => 'button green', 'href' => '?show_all=true'), phutil_escape_html('Show All Changes')); $warning_view = id(new AphrontErrorView())->setSeverity(AphrontErrorView::SEVERITY_WARNING)->setTitle(sprintf("Showing only the first %d changes out of %s!", self::CHANGES_LIMIT, number_format($original_changes_count))); $change_panel->appendChild($warning_view); $change_panel->addButton($show_all_button); } $change_panel->appendChild($change_table); $content[] = $change_panel; $changesets = DiffusionPathChange::convertToDifferentialChangesets($changes); $vcs = $repository->getVersionControlSystem(); switch ($vcs) { case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $vcs_supports_directory_changes = true; break; case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: $vcs_supports_directory_changes = false; break; default: throw new Exception("Unknown VCS."); } $references = array(); foreach ($changesets as $key => $changeset) { $file_type = $changeset->getFileType(); if ($file_type == DifferentialChangeType::FILE_DIRECTORY) { if (!$vcs_supports_directory_changes) { unset($changesets[$key]); continue; } } $references[$key] = $drequest->generateURI(array('action' => 'rendering-ref', 'path' => $changeset->getFilename())); } // TODO: Some parts of the views still rely on properties of the // DifferentialChangeset. Make the objects ephemeral to make sure we don't // accidentally save them, and then set their ID to the appropriate ID for // this application (the path IDs). $pquery = new DiffusionPathIDQuery(mpull($changesets, 'getFilename')); $path_ids = $pquery->loadPathIDs(); foreach ($changesets as $changeset) { $changeset->makeEphemeral(); $changeset->setID($path_ids[$changeset->getFilename()]); } $change_list = new DifferentialChangesetListView(); $change_list->setChangesets($changesets); $change_list->setRenderingReferences($references); $change_list->setRenderURI('/diffusion/' . $callsign . '/diff/'); $change_list->setRepository($repository); $change_list->setUser($user); $change_list->setStandaloneURI('/diffusion/' . $callsign . '/diff/'); $change_list->setRawFileURIs(null, '/diffusion/' . $callsign . '/diff/?view=r'); $change_list->setInlineCommentControllerURI('/diffusion/inline/' . phutil_escape_uri($commit->getPHID()) . '/'); // TODO: This is pretty awkward, unify the CSS between Diffusion and // Differential better. require_celerity_resource('differential-core-view-css'); $change_list = '<div class="differential-primary-pane">' . $change_list->render() . '</div>'; $content[] = $change_list; } } } $content[] = $this->buildAddCommentView($commit, $audit_requests); return $this->buildStandardPageResponse($content, array('title' => 'r' . $callsign . $commit->getCommitIdentifier())); }
private function loadParentRevisionOf($commit) { $drequest = $this->getDiffusionRequest(); $before_req = DiffusionRequest::newFromDictionary(array('repository' => $drequest->getRepository(), 'commit' => $commit)); $query = DiffusionCommitParentsQuery::newFromDiffusionRequest($before_req); $parents = $query->loadParents(); return head($parents); }
private function buildBeforeResponse($before) { $request = $this->getRequest(); $drequest = $this->getDiffusionRequest(); $before_req = DiffusionRequest::newFromDictionary(array('repository' => $drequest->getRepository(), 'commit' => $before)); $query = DiffusionCommitParentsQuery::newFromDiffusionRequest($before_req); $parents = $query->loadParents(); $parent = head($parents); // NOTE: If they get back to the very first commit, we just keep them there. // We could maybe show a message or something. $before_uri = $drequest->generateURI(array('action' => 'browse', 'commit' => $parent ? $parent->getCommitIdentifier() : $before, 'line' => $drequest->getLine())); $before_uri->setQueryParams($request->getRequestURI()->getQueryParams()); $before_uri = $before_uri->alter('before', null); return id(new AphrontRedirectResponse())->setURI($before_uri); }