public function loadPage() { $table = new DifferentialChangeset(); $conn_r = $table->establishConnection('r'); $data = queryfx_all($conn_r, 'SELECT * FROM %T %Q %Q %Q', $table->getTableName(), $this->buildWhereClause($conn_r), $this->buildOrderClause($conn_r), $this->buildLimitClause($conn_r)); return $table->loadAllFromArray($data); }
protected function collectGarbage() { $table = new DifferentialChangeset(); $conn_w = $table->establishConnection('w'); queryfx($conn_w, 'DELETE FROM %T WHERE dateCreated < %d LIMIT 100', DifferentialChangeset::TABLE_CACHE, $this->getGarbageEpoch()); return $conn_w->getAffectedRows() == 100; }
protected function getAbsoluteRepositoryPathForChangeset(DifferentialChangeset $changeset) { $repository = $this->loadRepository(); if (!$repository) { return '/' . ltrim($changeset->getFilename(), '/'); } $diff = $this->getDiff(); return $changeset->getAbsoluteRepositoryPath($repository, $diff); }
protected function buildInlineInfoDictionary(DifferentialInlineComment $inline, DifferentialChangeset $changeset = null) { $file_path = null; $diff_id = null; if ($changeset) { $file_path = $inline->getIsNewFile() ? $changeset->getFilename() : $changeset->getOldFile(); $diff_id = $changeset->getDiffID(); } return array('id' => $inline->getID(), 'authorPHID' => $inline->getAuthorPHID(), 'filePath' => $file_path, 'isNewFile' => $inline->getIsNewFile(), 'lineNumber' => $inline->getLineNumber(), 'lineLength' => $inline->getLineLength(), 'diffID' => $diff_id, 'content' => $inline->getContent()); }
public function collectGarbage() { $key = 'gcdaemon.ttl.differential-parse-cache'; $ttl = PhabricatorEnv::getEnvConfig($key); if ($ttl <= 0) { return false; } $table = new DifferentialChangeset(); $conn_w = $table->establishConnection('w'); queryfx($conn_w, 'DELETE FROM %T WHERE dateCreated < %d LIMIT 100', DifferentialChangeset::TABLE_CACHE, time() - $ttl); return $conn_w->getAffectedRows() == 100; }
public function testDiffChangesets() { $hunk = new DifferentialHunkModern(); $hunk->setChanges("+a\n b\n-c"); $hunk->setNewOffset(1); $hunk->setNewLen(2); $left = new DifferentialChangeset(); $left->attachHunks(array($hunk)); $tests = array("+a\n b\n-c" => array(array(), array()), "+a\n x\n-c" => array(array(), array()), "+aa\n b\n-c" => array(array(1), array(11)), " b\n-c" => array(array(1), array()), "+a\n b\n c" => array(array(), array(13)), "+a\n x\n c" => array(array(), array(13))); foreach ($tests as $changes => $expected) { $hunk = new DifferentialHunkModern(); $hunk->setChanges($changes); $hunk->setNewOffset(11); $hunk->setNewLen(3); $right = new DifferentialChangeset(); $right->attachHunks(array($hunk)); $parser = new DifferentialChangesetParser(); $parser->setOriginals($left, $right); $this->assertEqual($expected, $parser->diffOriginals(), $changes); } }
private static function buildChangesetsFromRawChanges(DifferentialDiff $diff, array $changes) { // There may not be any changes; initialize the changesets list so that // we don't throw later when accessing it. $diff->attachChangesets(array()); $lines = 0; foreach ($changes as $change) { if ($change->getType() == ArcanistDiffChangeType::TYPE_MESSAGE) { // If a user pastes a diff into Differential which includes a commit // message (e.g., they ran `git show` to generate it), discard that // change when constructing a DifferentialDiff. continue; } $changeset = new DifferentialChangeset(); $add_lines = 0; $del_lines = 0; $first_line = PHP_INT_MAX; $hunks = $change->getHunks(); if ($hunks) { foreach ($hunks as $hunk) { $dhunk = new DifferentialModernHunk(); $dhunk->setOldOffset($hunk->getOldOffset()); $dhunk->setOldLen($hunk->getOldLength()); $dhunk->setNewOffset($hunk->getNewOffset()); $dhunk->setNewLen($hunk->getNewLength()); $dhunk->setChanges($hunk->getCorpus()); $changeset->addUnsavedHunk($dhunk); $add_lines += $hunk->getAddLines(); $del_lines += $hunk->getDelLines(); $added_lines = $hunk->getChangedLines('new'); if ($added_lines) { $first_line = min($first_line, head_key($added_lines)); } } $lines += $add_lines + $del_lines; } else { // This happens when you add empty files. $changeset->attachHunks(array()); } $metadata = $change->getAllMetadata(); if ($first_line != PHP_INT_MAX) { $metadata['line:first'] = $first_line; } $changeset->setOldFile($change->getOldPath()); $changeset->setFilename($change->getCurrentPath()); $changeset->setChangeType($change->getType()); $changeset->setFileType($change->getFileType()); $changeset->setMetadata($metadata); $changeset->setOldProperties($change->getOldProperties()); $changeset->setNewProperties($change->getNewProperties()); $changeset->setAwayPaths($change->getAwayPaths()); $changeset->setAddLines($add_lines); $changeset->setDelLines($del_lines); $diff->addUnsavedChangeset($changeset); } $diff->setLineCount($lines); $parser = new DifferentialChangesetParser(); $changesets = $parser->detectCopiedCode($diff->getChangesets(), $min_width = 30, $min_lines = 3); $diff->attachChangesets($changesets); return $diff; }
public static function newFromRawChanges(array $changes) { $diff = new DifferentialDiff(); $lines = 0; foreach ($changes as $change) { $changeset = new DifferentialChangeset(); $add_lines = 0; $del_lines = 0; $hunks = $change->getHunks(); if ($hunks) { foreach ($hunks as $hunk) { $dhunk = new DifferentialHunk(); $dhunk->setOldOffset($hunk->getOldOffset()); $dhunk->setOldLen($hunk->getOldLength()); $dhunk->setNewOffset($hunk->getNewOffset()); $dhunk->setNewLen($hunk->getNewLength()); $dhunk->setChanges($hunk->getCorpus()); $changeset->addUnsavedHunk($dhunk); $add_lines += $hunk->getAddLines(); $del_lines += $hunk->getDelLines(); $lines += $add_lines + $del_lines; } } else { // This happens when you add empty files. $changeset->attachHunks(array()); } $changeset->setOldFile($change->getOldPath()); $changeset->setFilename($change->getCurrentPath()); $changeset->setChangeType($change->getType()); $changeset->setFileType($change->getFileType()); $changeset->setMetadata($change->getAllMetadata()); $changeset->setOldProperties($change->getOldProperties()); $changeset->setNewProperties($change->getNewProperties()); $changeset->setAwayPaths($change->getAwayPaths()); $changeset->setAddLines($add_lines); $changeset->setDelLines($del_lines); $diff->addUnsavedChangeset($changeset); } $diff->setLineCount($lines); return $diff; }
private function renderChangesetLink(DifferentialChangeset $changeset, $ref, $display_file) { return javelin_tag('a', array('href' => '#' . $changeset->getAnchorName(), 'sigil' => 'differential-load', 'meta' => array('id' => 'diff-' . $changeset->getAnchorName())), $display_file); }
private function renderViewOptionsDropdown(DifferentialChangesetDetailView $detail, $ref, DifferentialChangeset $changeset) { $viewer = $this->getViewer(); $meta = array(); $qparams = array('ref' => $ref, 'whitespace' => $this->whitespace); if ($this->standaloneURI) { $uri = new PhutilURI($this->standaloneURI); $uri->setQueryParams($uri->getQueryParams() + $qparams); $meta['standaloneURI'] = (string) $uri; } $repository = $this->repository; if ($repository) { try { $meta['diffusionURI'] = (string) $repository->getDiffusionBrowseURIForPath($viewer, $changeset->getAbsoluteRepositoryPath($repository, $this->diff), idx($changeset->getMetadata(), 'line:first'), $this->getBranch()); } catch (DiffusionSetupException $e) { // Ignore } } $change = $changeset->getChangeType(); if ($this->leftRawFileURI) { if ($change != DifferentialChangeType::TYPE_ADD) { $uri = new PhutilURI($this->leftRawFileURI); $uri->setQueryParams($uri->getQueryParams() + $qparams); $meta['leftURI'] = (string) $uri; } } if ($this->rightRawFileURI) { if ($change != DifferentialChangeType::TYPE_DELETE && $change != DifferentialChangeType::TYPE_MULTICOPY) { $uri = new PhutilURI($this->rightRawFileURI); $uri->setQueryParams($uri->getQueryParams() + $qparams); $meta['rightURI'] = (string) $uri; } } if ($viewer && $repository) { $path = ltrim($changeset->getAbsoluteRepositoryPath($repository, $this->diff), '/'); $line = idx($changeset->getMetadata(), 'line:first', 1); $editor_link = $viewer->loadEditorLink($path, $line, $repository); if ($editor_link) { $meta['editor'] = $editor_link; } else { $meta['editorConfigure'] = '/settings/panel/display/'; } } $meta['containerID'] = $detail->getID(); return id(new PHUIButtonView())->setTag('a')->setText(pht('View Options'))->setIcon('fa-bars')->setColor(PHUIButtonView::GREY)->setHref(idx($meta, 'detailURI', '#'))->setMetadata($meta)->addSigil('differential-view-options'); }
private function renderChangesetLink(DifferentialChangeset $changeset) { $display_file = $changeset->getDisplayFilename(); if ($this->standaloneViewLink) { $id = $changeset->getID(); $vs_id = idx($this->vsMap, $id); $ref = $vs_id ? $id . '/' . $vs_id : $id; $detail_uri = new PhutilURI($this->renderURI); $detail_uri->setQueryParams(array('ref' => $ref, 'whitespace' => $this->whitespace, 'revision_id' => $this->revisionID)); return phutil_render_tag('a', array('href' => $detail_uri, 'target' => '_blank'), phutil_escape_html($display_file)); } return phutil_render_tag('a', array('href' => '#' . $changeset->getAnchorName()), phutil_escape_html($display_file)); }
private function renderChangesetLink(DifferentialChangeset $changeset, $ref) { $display_file = $changeset->getDisplayFilename(); return javelin_render_tag('a', array('href' => '#' . $changeset->getAnchorName(), 'meta' => array('id' => 'diff-' . $changeset->getAnchorName(), 'ref' => $ref), 'sigil' => 'differential-load'), phutil_escape_html($display_file)); }
public function saveCache() { $render_cache_key = $this->getRenderCacheKey(); if (!$render_cache_key) { return false; } $cache = array(); foreach (self::getCacheableProperties() as $cache_key) { switch ($cache_key) { case 'cacheVersion': $cache[$cache_key] = self::CACHE_VERSION; break; case 'cacheHost': $cache[$cache_key] = php_uname('n'); break; default: $cache[$cache_key] = $this->{$cache_key}; break; } } $cache = json_encode($cache); try { $changeset = new DifferentialChangeset(); $conn_w = $changeset->establishConnection('w'); queryfx($conn_w, 'INSERT INTO %T (id, cache, dateCreated) VALUES (%d, %s, %d) ON DUPLICATE KEY UPDATE cache = VALUES(cache)', DifferentialChangeset::TABLE_CACHE, $render_cache_key, $cache, time()); } catch (AphrontQueryException $ex) { // TODO: uhoh } }
private function buildRawFileResponse(DifferentialChangeset $changeset, $is_new) { if ($is_new) { $key = 'raw:new:phid'; } else { $key = 'raw:old:phid'; } $metadata = $changeset->getMetadata(); $file = null; $phid = idx($metadata, $key); if ($phid) { $file = id(new PhabricatorFile())->loadOneWhere('phid = %s', $phid); } if (!$file) { // This is just building a cache of the changeset content in the file // tool, and is safe to run on a read pathway. $unguard = AphrontWriteGuard::beginScopedUnguardedWrites(); if ($is_new) { $data = $changeset->makeNewFile(); } else { $data = $changeset->makeOldFile(); } $file = PhabricatorFile::newFromFileData($data, array('name' => $changeset->getFilename(), 'mime-type' => 'text/plain')); $metadata[$key] = $file->getPHID(); $changeset->setMetadata($metadata); $changeset->save(); unset($unguard); } return id(new AphrontRedirectResponse())->setURI($file->getBestURI()); }
private function renderViewOptionsDropdown(DifferentialChangesetDetailView $detail, $ref, DifferentialChangeset $changeset) { $meta = array(); $qparams = array('ref' => $ref, 'whitespace' => $this->whitespace); if ($this->standaloneURI) { $uri = new PhutilURI($this->standaloneURI); $uri->setQueryParams($uri->getQueryParams() + $qparams); $meta['standaloneURI'] = (string) $uri; } $repository = $this->repository; if ($repository) { $meta['diffusionURI'] = (string) $repository->getDiffusionBrowseURIForPath($changeset->getAbsoluteRepositoryPath($repository, $this->diff)); } $change = $changeset->getChangeType(); if ($this->leftRawFileURI) { if ($change != DifferentialChangeType::TYPE_ADD) { $uri = new PhutilURI($this->leftRawFileURI); $uri->setQueryParams($uri->getQueryParams() + $qparams); $meta['leftURI'] = (string) $uri; } } if ($this->rightRawFileURI) { if ($change != DifferentialChangeType::TYPE_DELETE && $change != DifferentialChangeType::TYPE_MULTICOPY) { $uri = new PhutilURI($this->rightRawFileURI); $uri->setQueryParams($uri->getQueryParams() + $qparams); $meta['rightURI'] = (string) $uri; } } $user = $this->user; if ($user && $repository) { $path = ltrim($changeset->getAbsoluteRepositoryPath($repository, $this->diff), '/'); $line = 1; // TODO: get first changed line $callsign = $repository->getCallsign(); $editor_link = $user->loadEditorLink($path, $line, $callsign); if ($editor_link) { $meta['editor'] = $editor_link; } else { $meta['editorConfigure'] = '/settings/page/preferences/'; } } $meta['containerID'] = $detail->getID(); Javelin::initBehavior('differential-dropdown-menus', array()); return javelin_render_tag('a', array('class' => 'button small grey', 'meta' => $meta, 'href' => idx($meta, 'detailURI', '#'), 'target' => '_blank', 'sigil' => 'differential-view-options'), "View Options ▼"); }
public function saveCache() { if ($this->highlightErrors) { return false; } $render_cache_key = $this->getRenderCacheKey(); if (!$render_cache_key) { return false; } $cache = array(); foreach (self::getCacheableProperties() as $cache_key) { switch ($cache_key) { case 'cacheVersion': $cache[$cache_key] = self::CACHE_VERSION; break; case 'cacheHost': $cache[$cache_key] = php_uname('n'); break; default: $cache[$cache_key] = $this->{$cache_key}; break; } } $cache = json_encode($cache); // We don't want to waste too much space by a single changeset. if (strlen($cache) > self::CACHE_MAX_SIZE) { return; } try { $changeset = new DifferentialChangeset(); $conn_w = $changeset->establishConnection('w'); $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); queryfx($conn_w, 'INSERT INTO %T (id, cache, dateCreated) VALUES (%d, %s, %d) ON DUPLICATE KEY UPDATE cache = VALUES(cache)', DifferentialChangeset::TABLE_CACHE, $render_cache_key, $cache, time()); } catch (AphrontQueryException $ex) { // TODO: uhoh } }
private function renderViewOptionsDropdown(DifferentialChangesetDetailView $detail, $ref, DifferentialChangeset $changeset) { $meta = array(); $qparams = array('ref' => $ref, 'whitespace' => $this->whitespace); if ($this->standaloneURI) { $uri = new PhutilURI($this->standaloneURI); $uri->setQueryParams($uri->getQueryParams() + $qparams); $meta['standaloneURI'] = (string) $uri; } $repository = $this->repository; if ($repository) { try { $meta['diffusionURI'] = (string) $repository->getDiffusionBrowseURIForPath($this->user, $changeset->getAbsoluteRepositoryPath($repository, $this->diff), idx($changeset->getMetadata(), 'line:first'), $this->getBranch()); } catch (DiffusionSetupException $e) { // Ignore } } $change = $changeset->getChangeType(); if ($this->leftRawFileURI) { if ($change != DifferentialChangeType::TYPE_ADD) { $uri = new PhutilURI($this->leftRawFileURI); $uri->setQueryParams($uri->getQueryParams() + $qparams); $meta['leftURI'] = (string) $uri; } } if ($this->rightRawFileURI) { if ($change != DifferentialChangeType::TYPE_DELETE && $change != DifferentialChangeType::TYPE_MULTICOPY) { $uri = new PhutilURI($this->rightRawFileURI); $uri->setQueryParams($uri->getQueryParams() + $qparams); $meta['rightURI'] = (string) $uri; } } $user = $this->user; if ($user && $repository) { $path = ltrim($changeset->getAbsoluteRepositoryPath($repository, $this->diff), '/'); $line = idx($changeset->getMetadata(), 'line:first', 1); $callsign = $repository->getCallsign(); $editor_link = $user->loadEditorLink($path, $line, $callsign); if ($editor_link) { $meta['editor'] = $editor_link; } else { $meta['editorConfigure'] = '/settings/panel/display/'; } } $meta['containerID'] = $detail->getID(); $caret = phutil_tag('span', array('class' => 'caret'), ''); return javelin_tag('a', array('class' => 'button grey small dropdown', 'meta' => $meta, 'href' => idx($meta, 'detailURI', '#'), 'target' => '_blank', 'sigil' => 'differential-view-options'), array(pht('View Options'), $caret)); }
public static function newFromRawChanges(array $changes) { assert_instances_of($changes, 'ArcanistDiffChange'); $diff = new DifferentialDiff(); $lines = 0; foreach ($changes as $change) { $changeset = new DifferentialChangeset(); $add_lines = 0; $del_lines = 0; $first_line = PHP_INT_MAX; $hunks = $change->getHunks(); if ($hunks) { foreach ($hunks as $hunk) { $dhunk = new DifferentialHunk(); $dhunk->setOldOffset($hunk->getOldOffset()); $dhunk->setOldLen($hunk->getOldLength()); $dhunk->setNewOffset($hunk->getNewOffset()); $dhunk->setNewLen($hunk->getNewLength()); $dhunk->setChanges($hunk->getCorpus()); $changeset->addUnsavedHunk($dhunk); $add_lines += $hunk->getAddLines(); $del_lines += $hunk->getDelLines(); $added_lines = $hunk->getChangedLines('new'); if ($added_lines) { $first_line = min($first_line, head_key($added_lines)); } } $lines += $add_lines + $del_lines; } else { // This happens when you add empty files. $changeset->attachHunks(array()); } $metadata = $change->getAllMetadata(); if ($first_line != PHP_INT_MAX) { $metadata['line:first'] = $first_line; } $changeset->setOldFile($change->getOldPath()); $changeset->setFilename($change->getCurrentPath()); $changeset->setChangeType($change->getType()); $changeset->setFileType($change->getFileType()); $changeset->setMetadata($metadata); $changeset->setOldProperties($change->getOldProperties()); $changeset->setNewProperties($change->getNewProperties()); $changeset->setAwayPaths($change->getAwayPaths()); $changeset->setAddLines($add_lines); $changeset->setDelLines($del_lines); $diff->addUnsavedChangeset($changeset); } $diff->setLineCount($lines); $diff->detectCopiedCode(); return $diff; }
private function createChange($hunks) { $change = new DifferentialChangeset(); $change->attachHunks($hunks); return $change; }
public function saveCache() { if (PhabricatorEnv::isReadOnly()) { return false; } if ($this->highlightErrors) { return false; } $render_cache_key = $this->getRenderCacheKey(); if (!$render_cache_key) { return false; } $cache = array(); foreach (self::getCacheableProperties() as $cache_key) { switch ($cache_key) { case 'cacheVersion': $cache[$cache_key] = self::CACHE_VERSION; break; case 'cacheHost': $cache[$cache_key] = php_uname('n'); break; default: $cache[$cache_key] = $this->{$cache_key}; break; } } $cache = serialize($cache); // We don't want to waste too much space by a single changeset. if (strlen($cache) > self::CACHE_MAX_SIZE) { return; } $changeset = new DifferentialChangeset(); $conn_w = $changeset->establishConnection('w'); $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); try { queryfx($conn_w, 'INSERT INTO %T (id, cache, dateCreated) VALUES (%d, %B, %d) ON DUPLICATE KEY UPDATE cache = VALUES(cache)', DifferentialChangeset::TABLE_CACHE, $render_cache_key, $cache, time()); } catch (AphrontQueryException $ex) { // Ignore these exceptions. A common cause is that the cache is // larger than 'max_allowed_packet', in which case we're better off // not writing it. // TODO: It would be nice to tailor this more narrowly. } unset($unguarded); }
} break; case '--differential': $purge_differential = true; break; case '--maniphest': $purge_maniphest = true; break; case '--help': return help(); default: return usage("Unrecognized argument '{$args[$ii]}'."); } } if ($purge_changesets) { $table = new DifferentialChangeset(); if ($changesets) { echo "Purging changeset cache for changesets " . implode($changesets, ",") . "\n"; queryfx($table->establishConnection('w'), 'DELETE FROM %T WHERE id IN (%Ld)', DifferentialChangeset::TABLE_CACHE, $changesets); } else { echo "Purging changeset cache...\n"; queryfx($table->establishConnection('w'), 'TRUNCATE TABLE %T', DifferentialChangeset::TABLE_CACHE); } echo "Done.\n"; } if ($purge_differential) { echo "Purging Differential comment cache...\n"; $table = new DifferentialComment(); queryfx($table->establishConnection('w'), 'UPDATE %T SET cache = NULL', $table->getTableName()); echo "Purging Differential inline comment cache...\n"; $table = new DifferentialInlineComment();
private function loadCoverage(DifferentialChangeset $changeset) { $target_phids = $changeset->getDiff()->getBuildTargetPHIDs(); if (!$target_phids) { return null; } $unit = id(new HarbormasterBuildUnitMessage())->loadAllWhere('buildTargetPHID IN (%Ls)', $target_phids); if (!$unit) { return null; } $coverage = array(); foreach ($unit as $message) { $test_coverage = $message->getProperty('coverage'); if ($test_coverage === null) { continue; } $coverage_data = idx($test_coverage, $changeset->getFileName()); if (!strlen($coverage_data)) { continue; } $coverage[] = $coverage_data; } if (!$coverage) { return null; } return ArcanistUnitTestResult::mergeCoverage($coverage); }
break; case '--differential': $purge_differential = true; break; case '--maniphest': $purge_maniphest = true; break; case '--help': return help(); default: return usage("Unrecognized argument '{$arg}'."); } } if ($purge_changesets) { echo "Purging changeset cache...\n"; $table = new DifferentialChangeset(); queryfx($table->establishConnection('w'), 'TRUNCATE TABLE %T', DifferentialChangeset::TABLE_CACHE); echo "Done.\n"; } if ($purge_differential) { echo "Purging Differential comment cache...\n"; $table = new DifferentialComment(); queryfx($table->establishConnection('w'), 'UPDATE %T SET cache = NULL', $table->getTableName()); echo "Done.\n"; } if ($purge_maniphest) { echo "Purging Maniphest comment cache...\n"; $table = new ManiphestTransaction(); queryfx($table->establishConnection('w'), 'UPDATE %T SET cache = NULL', $table->getTableName()); echo "Done.\n"; }