mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-26 14:38:19 +01:00
(stable) Promote 2018 Week 30
This commit is contained in:
commit
79c15e936c
20 changed files with 298 additions and 72 deletions
|
@ -143,7 +143,7 @@ final class PhabricatorOpcodeCacheSpec extends PhabricatorCacheSpec {
|
||||||
$this
|
$this
|
||||||
->newIssue('extension.opcache.devmode')
|
->newIssue('extension.opcache.devmode')
|
||||||
->setShortName(pht('OPcache Config'))
|
->setShortName(pht('OPcache Config'))
|
||||||
->setName(pht('OPCache Not Configured for Development'))
|
->setName(pht('OPcache Not Configured for Development'))
|
||||||
->setSummary($summary)
|
->setSummary($summary)
|
||||||
->setMessage($message)
|
->setMessage($message)
|
||||||
->addPHPConfig('opcache.validate_timestamps')
|
->addPHPConfig('opcache.validate_timestamps')
|
||||||
|
|
|
@ -15,7 +15,7 @@ final class PhabricatorConfigApplication extends PhabricatorApplication {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTitleGlyph() {
|
public function getTitleGlyph() {
|
||||||
return "\xE2\x98\xBA";
|
return "\xE2\x9C\xA8";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getApplicationGroup() {
|
public function getApplicationGroup() {
|
||||||
|
|
|
@ -445,7 +445,7 @@ final class PhabricatorSetupIssueView extends AphrontView {
|
||||||
'p',
|
'p',
|
||||||
array(),
|
array(),
|
||||||
pht(
|
pht(
|
||||||
'You can find more information about configuring OPCache in '.
|
'You can find more information about configuring OPcache in '.
|
||||||
'the %s.',
|
'the %s.',
|
||||||
phutil_tag(
|
phutil_tag(
|
||||||
'a',
|
'a',
|
||||||
|
@ -453,7 +453,7 @@ final class PhabricatorSetupIssueView extends AphrontView {
|
||||||
'href' => 'http://php.net/manual/opcache.configuration.php',
|
'href' => 'http://php.net/manual/opcache.configuration.php',
|
||||||
'target' => '_blank',
|
'target' => '_blank',
|
||||||
),
|
),
|
||||||
pht('PHP OPCache Documentation'))));
|
pht('PHP OPcache Documentation'))));
|
||||||
}
|
}
|
||||||
|
|
||||||
$info[] = phutil_tag(
|
$info[] = phutil_tag(
|
||||||
|
|
|
@ -43,7 +43,10 @@ final class PhabricatorDifferentialApplication extends PhabricatorApplication {
|
||||||
|
|
||||||
public function getRoutes() {
|
public function getRoutes() {
|
||||||
return array(
|
return array(
|
||||||
'/D(?P<id>[1-9]\d*)' => 'DifferentialRevisionViewController',
|
'/D(?P<id>[1-9]\d*)' => array(
|
||||||
|
'' => 'DifferentialRevisionViewController',
|
||||||
|
'/(?P<filter>new)/' => 'DifferentialRevisionViewController',
|
||||||
|
),
|
||||||
'/differential/' => array(
|
'/differential/' => array(
|
||||||
'(?:query/(?P<queryKey>[^/]+)/)?'
|
'(?:query/(?P<queryKey>[^/]+)/)?'
|
||||||
=> 'DifferentialRevisionListController',
|
=> 'DifferentialRevisionListController',
|
||||||
|
|
|
@ -6,6 +6,7 @@ final class DifferentialRevisionViewController
|
||||||
private $revisionID;
|
private $revisionID;
|
||||||
private $changesetCount;
|
private $changesetCount;
|
||||||
private $hiddenChangesets;
|
private $hiddenChangesets;
|
||||||
|
private $warnings = array();
|
||||||
|
|
||||||
public function shouldAllowPublic() {
|
public function shouldAllowPublic() {
|
||||||
return true;
|
return true;
|
||||||
|
@ -68,9 +69,17 @@ final class DifferentialRevisionViewController
|
||||||
|
|
||||||
$revision->attachActiveDiff(last($diffs));
|
$revision->attachActiveDiff(last($diffs));
|
||||||
|
|
||||||
$diff_vs = $request->getInt('vs');
|
$diff_vs = $this->getOldDiffID($revision, $diffs);
|
||||||
$target_id = $request->getInt('id');
|
if ($diff_vs instanceof AphrontResponse) {
|
||||||
$target = idx($diffs, $target_id, end($diffs));
|
return $diff_vs;
|
||||||
|
}
|
||||||
|
|
||||||
|
$target_id = $this->getNewDiffID($revision, $diffs);
|
||||||
|
if ($target_id instanceof AphrontResponse) {
|
||||||
|
return $target_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
$target = $diffs[$target_id];
|
||||||
|
|
||||||
$target_manual = $target;
|
$target_manual = $target;
|
||||||
if (!$target_id) {
|
if (!$target_id) {
|
||||||
|
@ -81,10 +90,6 @@ final class DifferentialRevisionViewController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($diffs[$diff_vs])) {
|
|
||||||
$diff_vs = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$repository = null;
|
$repository = null;
|
||||||
$repository_phid = $target->getRepositoryPHID();
|
$repository_phid = $target->getRepositoryPHID();
|
||||||
if ($repository_phid) {
|
if ($repository_phid) {
|
||||||
|
@ -170,7 +175,7 @@ final class DifferentialRevisionViewController
|
||||||
}
|
}
|
||||||
|
|
||||||
$handles = $this->loadViewerHandles($object_phids);
|
$handles = $this->loadViewerHandles($object_phids);
|
||||||
$warnings = array();
|
$warnings = $this->warnings;
|
||||||
|
|
||||||
$request_uri = $request->getRequestURI();
|
$request_uri = $request->getRequestURI();
|
||||||
|
|
||||||
|
@ -1312,4 +1317,133 @@ final class DifferentialRevisionViewController
|
||||||
->setShowViewAll(true);
|
->setShowViewAll(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getOldDiffID(DifferentialRevision $revision, array $diffs) {
|
||||||
|
assert_instances_of($diffs, 'DifferentialDiff');
|
||||||
|
$request = $this->getRequest();
|
||||||
|
|
||||||
|
$diffs = mpull($diffs, null, 'getID');
|
||||||
|
|
||||||
|
$is_new = ($request->getURIData('filter') === 'new');
|
||||||
|
$old_id = $request->getInt('vs');
|
||||||
|
|
||||||
|
// This is ambiguous, so just 404 rather than trying to figure out what
|
||||||
|
// the user expects.
|
||||||
|
if ($is_new && $old_id) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($is_new) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$xactions = id(new DifferentialTransactionQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withObjectPHIDs(array($revision->getPHID()))
|
||||||
|
->withAuthorPHIDs(array($viewer->getPHID()))
|
||||||
|
->setOrder('newest')
|
||||||
|
->setLimit(1)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
if (!$xactions) {
|
||||||
|
$this->warnings[] = id(new PHUIInfoView())
|
||||||
|
->setTitle(pht('No Actions'))
|
||||||
|
->setSeverity(PHUIInfoView::SEVERITY_WARNING)
|
||||||
|
->appendChild(
|
||||||
|
pht(
|
||||||
|
'Showing all changes because you have never taken an '.
|
||||||
|
'action on this revision.'));
|
||||||
|
} else {
|
||||||
|
$xaction = head($xactions);
|
||||||
|
|
||||||
|
// Find the transactions which updated this revision. We want to
|
||||||
|
// figure out which diff was active when you last took an action.
|
||||||
|
$updates = id(new DifferentialTransactionQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withObjectPHIDs(array($revision->getPHID()))
|
||||||
|
->withTransactionTypes(
|
||||||
|
array(
|
||||||
|
DifferentialRevisionUpdateTransaction::TRANSACTIONTYPE,
|
||||||
|
))
|
||||||
|
->setOrder('oldest')
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
// Sort the diffs into two buckets: those older than your last action
|
||||||
|
// and those newer than your last action.
|
||||||
|
$older = array();
|
||||||
|
$newer = array();
|
||||||
|
foreach ($updates as $update) {
|
||||||
|
// If you updated the revision with "arc diff", try to count that
|
||||||
|
// update as "before your last action".
|
||||||
|
if ($update->getDateCreated() <= $xaction->getDateCreated()) {
|
||||||
|
$older[] = $update->getNewValue();
|
||||||
|
} else {
|
||||||
|
$newer[] = $update->getNewValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$newer) {
|
||||||
|
$this->warnings[] = id(new PHUIInfoView())
|
||||||
|
->setTitle(pht('No Recent Updates'))
|
||||||
|
->setSeverity(PHUIInfoView::SEVERITY_WARNING)
|
||||||
|
->appendChild(
|
||||||
|
pht(
|
||||||
|
'Showing all changes because the diff for this revision '.
|
||||||
|
'has not been updated since your last action.'));
|
||||||
|
} else {
|
||||||
|
$older = array_fuse($older);
|
||||||
|
|
||||||
|
// Find the most recent diff from before the last action.
|
||||||
|
$old = null;
|
||||||
|
foreach ($diffs as $diff) {
|
||||||
|
if (!isset($older[$diff->getPHID()])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$old = $diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's possible we may not find such a diff: transactions may have
|
||||||
|
// been removed from the database, for example. If we miss, just
|
||||||
|
// fail into some reasonable state since 404'ing would be perplexing.
|
||||||
|
if ($old) {
|
||||||
|
$this->warnings[] = id(new PHUIInfoView())
|
||||||
|
->setTitle(pht('New Changes Shown'))
|
||||||
|
->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
|
||||||
|
->appendChild(
|
||||||
|
pht(
|
||||||
|
'Showing changes since the last action you took on this '.
|
||||||
|
'revision.'));
|
||||||
|
|
||||||
|
$old_id = $old->getID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($diffs[$old_id])) {
|
||||||
|
return $old_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getNewDiffID(DifferentialRevision $revision, array $diffs) {
|
||||||
|
assert_instances_of($diffs, 'DifferentialDiff');
|
||||||
|
$request = $this->getRequest();
|
||||||
|
|
||||||
|
$diffs = mpull($diffs, null, 'getID');
|
||||||
|
|
||||||
|
$is_new = ($request->getURIData('filter') === 'new');
|
||||||
|
$new_id = $request->getInt('id');
|
||||||
|
|
||||||
|
if ($is_new && $new_id) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($diffs[$new_id])) {
|
||||||
|
return $new_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)last_key($diffs);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -624,7 +624,9 @@ final class DifferentialTransactionEditor
|
||||||
$body = new PhabricatorMetaMTAMailBody();
|
$body = new PhabricatorMetaMTAMailBody();
|
||||||
$body->setViewer($this->requireActor());
|
$body->setViewer($this->requireActor());
|
||||||
|
|
||||||
$revision_uri = PhabricatorEnv::getProductionURI('/D'.$object->getID());
|
$revision_uri = $object->getURI();
|
||||||
|
$revision_uri = PhabricatorEnv::getProductionURI($revision_uri);
|
||||||
|
$new_uri = $revision_uri.'/new/';
|
||||||
|
|
||||||
$this->addHeadersAndCommentsToMailBody(
|
$this->addHeadersAndCommentsToMailBody(
|
||||||
$body,
|
$body,
|
||||||
|
@ -645,19 +647,6 @@ final class DifferentialTransactionEditor
|
||||||
$this->appendInlineCommentsForMail($object, $inlines, $body);
|
$this->appendInlineCommentsForMail($object, $inlines, $body);
|
||||||
}
|
}
|
||||||
|
|
||||||
$changed_uri = $this->getChangedPriorToCommitURI();
|
|
||||||
if ($changed_uri) {
|
|
||||||
$body->addLinkSection(
|
|
||||||
pht('CHANGED PRIOR TO COMMIT'),
|
|
||||||
$changed_uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->addCustomFieldsToMailBody($body, $object, $xactions);
|
|
||||||
|
|
||||||
$body->addLinkSection(
|
|
||||||
pht('REVISION DETAIL'),
|
|
||||||
$revision_uri);
|
|
||||||
|
|
||||||
$update_xaction = null;
|
$update_xaction = null;
|
||||||
foreach ($xactions as $xaction) {
|
foreach ($xactions as $xaction) {
|
||||||
switch ($xaction->getTransactionType()) {
|
switch ($xaction->getTransactionType()) {
|
||||||
|
@ -669,7 +658,28 @@ final class DifferentialTransactionEditor
|
||||||
|
|
||||||
if ($update_xaction) {
|
if ($update_xaction) {
|
||||||
$diff = $this->requireDiff($update_xaction->getNewValue(), true);
|
$diff = $this->requireDiff($update_xaction->getNewValue(), true);
|
||||||
|
} else {
|
||||||
|
$diff = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$changed_uri = $this->getChangedPriorToCommitURI();
|
||||||
|
if ($changed_uri) {
|
||||||
|
$body->addLinkSection(
|
||||||
|
pht('CHANGED PRIOR TO COMMIT'),
|
||||||
|
$changed_uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->addCustomFieldsToMailBody($body, $object, $xactions);
|
||||||
|
|
||||||
|
if (!$this->getIsNewObject()) {
|
||||||
|
$body->addLinkSection(pht('CHANGES SINCE LAST ACTION'), $new_uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
$body->addLinkSection(
|
||||||
|
pht('REVISION DETAIL'),
|
||||||
|
$revision_uri);
|
||||||
|
|
||||||
|
if ($update_xaction) {
|
||||||
$body->addTextSection(
|
$body->addTextSection(
|
||||||
pht('AFFECTED FILES'),
|
pht('AFFECTED FILES'),
|
||||||
$this->renderAffectedFilesForMail($diff));
|
$this->renderAffectedFilesForMail($diff));
|
||||||
|
|
|
@ -48,10 +48,12 @@ final class PhabricatorDifferentialRevisionTestDataGenerator
|
||||||
|
|
||||||
public function generateDiff($author) {
|
public function generateDiff($author) {
|
||||||
$paste_generator = new PhabricatorPasteTestDataGenerator();
|
$paste_generator = new PhabricatorPasteTestDataGenerator();
|
||||||
$languages = $paste_generator->supportedLanguages;
|
$languages = $paste_generator->getSupportedLanguages();
|
||||||
$lang = array_rand($languages);
|
$language = array_rand($languages);
|
||||||
$code = $paste_generator->generateContent($lang);
|
$spec = $languages[$language];
|
||||||
$altcode = $paste_generator->generateContent($lang);
|
|
||||||
|
$code = $paste_generator->generateContent($spec);
|
||||||
|
$altcode = $paste_generator->generateContent($spec);
|
||||||
$newcode = $this->randomlyModify($code, $altcode);
|
$newcode = $this->randomlyModify($code, $altcode);
|
||||||
$diff = id(new PhabricatorDifferenceEngine())
|
$diff = id(new PhabricatorDifferenceEngine())
|
||||||
->generateRawDiffFromFileContent($code, $newcode);
|
->generateRawDiffFromFileContent($code, $newcode);
|
||||||
|
|
|
@ -307,7 +307,7 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView {
|
||||||
$content = phabricator_form(
|
$content = phabricator_form(
|
||||||
$this->getUser(),
|
$this->getUser(),
|
||||||
array(
|
array(
|
||||||
'action' => '#toc',
|
'action' => '/D'.$revision_id.'#toc',
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
$table,
|
$table,
|
||||||
|
|
|
@ -119,11 +119,23 @@ final class PhabricatorDocumentRef
|
||||||
}
|
}
|
||||||
|
|
||||||
$snippet = $this->getSnippet();
|
$snippet = $this->getSnippet();
|
||||||
if (!preg_match('/^\s*[{[]/', $snippet)) {
|
|
||||||
|
// If the file is longer than the snippet, we don't detect the content
|
||||||
|
// as JSON. We could use some kind of heuristic here if we wanted, but
|
||||||
|
// see PHI749 for a false positive.
|
||||||
|
if (strlen($snippet) < $this->getByteLength()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return phutil_is_utf8($snippet);
|
// If the snippet is the whole file, just check if the snippet is valid
|
||||||
|
// JSON. Note that `phutil_json_decode()` only accepts arrays and objects
|
||||||
|
// as JSON, so this won't misfire on files with content like "3".
|
||||||
|
try {
|
||||||
|
phutil_json_decode($snippet);
|
||||||
|
return true;
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSnippet() {
|
public function getSnippet() {
|
||||||
|
|
|
@ -492,12 +492,13 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
||||||
$this->setStorageFormat($format->getStorageFormatKey());
|
$this->setStorageFormat($format->getStorageFormatKey());
|
||||||
$this->setStorageProperties($properties);
|
$this->setStorageProperties($properties);
|
||||||
|
|
||||||
list($identifier, $new_handle) = $this->writeToEngine(
|
list($identifier, $new_handle, $integrity_hash) = $this->writeToEngine(
|
||||||
$engine,
|
$engine,
|
||||||
$data,
|
$data,
|
||||||
$params);
|
$params);
|
||||||
|
|
||||||
$this->setStorageHandle($new_handle);
|
$this->setStorageHandle($new_handle);
|
||||||
|
$this->setIntegrityHash($integrity_hash);
|
||||||
$this->save();
|
$this->save();
|
||||||
|
|
||||||
$this->deleteFileDataIfUnused(
|
$this->deleteFileDataIfUnused(
|
||||||
|
|
|
@ -104,8 +104,8 @@ final class PhabricatorMemeEngine extends Phobject {
|
||||||
private function newTransformHash() {
|
private function newTransformHash() {
|
||||||
$properties = array(
|
$properties = array(
|
||||||
'kind' => 'meme',
|
'kind' => 'meme',
|
||||||
'above' => phutil_utf8_strtoupper($this->getAboveText()),
|
'above' => $this->getAboveText(),
|
||||||
'below' => phutil_utf8_strtoupper($this->getBelowText()),
|
'below' => $this->getBelowText(),
|
||||||
);
|
);
|
||||||
|
|
||||||
$properties = phutil_json_encode($properties);
|
$properties = phutil_json_encode($properties);
|
||||||
|
|
|
@ -22,9 +22,11 @@ final class PhabricatorPasteTestDataGenerator
|
||||||
PhabricatorPasteTitleTransaction::TRANSACTIONTYPE,
|
PhabricatorPasteTitleTransaction::TRANSACTIONTYPE,
|
||||||
$name);
|
$name);
|
||||||
|
|
||||||
$xactions[] = $this->newTransaction(
|
if (strlen($language) > 0) {
|
||||||
PhabricatorPasteLanguageTransaction::TRANSACTIONTYPE,
|
$xactions[] = $this->newTransaction(
|
||||||
$language);
|
PhabricatorPasteLanguageTransaction::TRANSACTIONTYPE,
|
||||||
|
$language);
|
||||||
|
}
|
||||||
|
|
||||||
$xactions[] = $this->newTransaction(
|
$xactions[] = $this->newTransaction(
|
||||||
PhabricatorPasteContentTransaction::TRANSACTIONTYPE,
|
PhabricatorPasteContentTransaction::TRANSACTIONTYPE,
|
||||||
|
@ -43,17 +45,29 @@ final class PhabricatorPasteTestDataGenerator
|
||||||
return new PhabricatorPasteTransaction();
|
return new PhabricatorPasteTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function newPasteContent() {
|
public function getSupportedLanguages() {
|
||||||
$languages = array(
|
return array(
|
||||||
'txt' => array(),
|
'php' => array(
|
||||||
'php' => array(
|
'content' => 'PhutilPHPCodeSnippetContextFreeGrammar',
|
||||||
'content' => 'PhutilPHPCodeSnippetContextFreeGrammar',
|
),
|
||||||
),
|
'java' => array(
|
||||||
'java' => array(
|
'content' => 'PhutilJavaCodeSnippetContextFreeGrammar',
|
||||||
'content' => 'PhutilJavaCodeSnippetContextFreeGrammar',
|
),
|
||||||
),
|
);
|
||||||
);
|
}
|
||||||
|
|
||||||
|
public function generateContent($spec) {
|
||||||
|
$content_generator = idx($spec, 'content');
|
||||||
|
if (!$content_generator) {
|
||||||
|
$content_generator = 'PhutilLipsumContextFreeGrammar';
|
||||||
|
}
|
||||||
|
|
||||||
|
return newv($content_generator, array())
|
||||||
|
->generateSeveral($this->roll(4, 12, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function newPasteContent() {
|
||||||
|
$languages = $this->getSupportedLanguages();
|
||||||
$language = array_rand($languages);
|
$language = array_rand($languages);
|
||||||
$spec = $languages[$language];
|
$spec = $languages[$language];
|
||||||
|
|
||||||
|
@ -62,16 +76,10 @@ final class PhabricatorPasteTestDataGenerator
|
||||||
$title_generator = 'PhabricatorPasteFilenameContextFreeGrammar';
|
$title_generator = 'PhabricatorPasteFilenameContextFreeGrammar';
|
||||||
}
|
}
|
||||||
|
|
||||||
$content_generator = idx($spec, 'content');
|
|
||||||
if (!$content_generator) {
|
|
||||||
$content_generator = 'PhutilLipsumContextFreeGrammar';
|
|
||||||
}
|
|
||||||
|
|
||||||
$title = newv($title_generator, array())
|
$title = newv($title_generator, array())
|
||||||
->generate();
|
->generate();
|
||||||
|
|
||||||
$content = newv($content_generator, array())
|
$content = $this->generateContent($spec);
|
||||||
->generateSeveral($this->roll(4, 12, 10));
|
|
||||||
|
|
||||||
// Usually add the language as a suffix.
|
// Usually add the language as a suffix.
|
||||||
if ($this->roll(1, 20) > 2) {
|
if ($this->roll(1, 20) > 2) {
|
||||||
|
|
|
@ -22,7 +22,13 @@ final class PhabricatorProjectSearchEngine
|
||||||
return array(
|
return array(
|
||||||
id(new PhabricatorSearchTextField())
|
id(new PhabricatorSearchTextField())
|
||||||
->setLabel(pht('Name'))
|
->setLabel(pht('Name'))
|
||||||
->setKey('name'),
|
->setKey('name')
|
||||||
|
->setDescription(
|
||||||
|
pht(
|
||||||
|
'(Deprecated.) Search for projects with a given name or '.
|
||||||
|
'hashtag using tokenizer/datasource query matching rules. This '.
|
||||||
|
'is deprecated in favor of the more powerful "query" '.
|
||||||
|
'constraint.')),
|
||||||
id(new PhabricatorSearchStringListField())
|
id(new PhabricatorSearchStringListField())
|
||||||
->setLabel(pht('Slugs'))
|
->setLabel(pht('Slugs'))
|
||||||
->setIsHidden(true)
|
->setIsHidden(true)
|
||||||
|
|
|
@ -57,7 +57,10 @@ final class PhabricatorFerretSearchEngineExtension
|
||||||
$fields[] = id(new PhabricatorSearchTextField())
|
$fields[] = id(new PhabricatorSearchTextField())
|
||||||
->setKey('query')
|
->setKey('query')
|
||||||
->setLabel(pht('Query'))
|
->setLabel(pht('Query'))
|
||||||
->setDescription(pht('Fulltext search.'));
|
->setDescription(
|
||||||
|
pht(
|
||||||
|
'Find objects matching a fulltext search query. See '.
|
||||||
|
'"Search User Guide" in the documentation for details.'));
|
||||||
|
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,10 @@ final class PhabricatorFulltextToken extends Phobject {
|
||||||
$tip = pht('Substring Search');
|
$tip = pht('Substring Search');
|
||||||
$shade = PHUITagView::COLOR_VIOLET;
|
$shade = PHUITagView::COLOR_VIOLET;
|
||||||
break;
|
break;
|
||||||
|
case PhutilSearchQueryCompiler::OPERATOR_EXACT:
|
||||||
|
$tip = pht('Exact Search');
|
||||||
|
$shade = PHUITagView::COLOR_GREEN;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
$shade = PHUITagView::COLOR_BLUE;
|
$shade = PHUITagView::COLOR_BLUE;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -84,6 +84,7 @@ final class PhabricatorSearchResultView extends AphrontView {
|
||||||
|
|
||||||
switch ($operator) {
|
switch ($operator) {
|
||||||
case PhutilSearchQueryCompiler::OPERATOR_SUBSTRING:
|
case PhutilSearchQueryCompiler::OPERATOR_SUBSTRING:
|
||||||
|
case PhutilSearchQueryCompiler::OPERATOR_EXACT:
|
||||||
$patterns[] = '(('.preg_quote($value).'))ui';
|
$patterns[] = '(('.preg_quote($value).'))ui';
|
||||||
break;
|
break;
|
||||||
case PhutilSearchQueryCompiler::OPERATOR_AND:
|
case PhutilSearchQueryCompiler::OPERATOR_AND:
|
||||||
|
|
|
@ -3599,6 +3599,7 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
->setContinueOnMissingFields(true)
|
->setContinueOnMissingFields(true)
|
||||||
->setParentMessageID($this->getParentMessageID())
|
->setParentMessageID($this->getParentMessageID())
|
||||||
->setIsInverseEdgeEditor(true)
|
->setIsInverseEdgeEditor(true)
|
||||||
|
->setIsSilent($this->getIsSilent())
|
||||||
->setActor($this->requireActor())
|
->setActor($this->requireActor())
|
||||||
->setActingAsPHID($this->getActingAsPHID())
|
->setActingAsPHID($this->getActingAsPHID())
|
||||||
->setContentSource($this->getContentSource());
|
->setContentSource($this->getContentSource());
|
||||||
|
|
|
@ -138,6 +138,7 @@ some special syntax. These features are supported:
|
||||||
- Field search with `title:platypus`.
|
- Field search with `title:platypus`.
|
||||||
- Filtering out matches with `-platypus`.
|
- Filtering out matches with `-platypus`.
|
||||||
- Quoted terms with `"platypus attorney"`.
|
- Quoted terms with `"platypus attorney"`.
|
||||||
|
- Matching entire fields with `=platypus`.
|
||||||
- Combining features with `title:~"platypus attorney"`.
|
- Combining features with `title:~"platypus attorney"`.
|
||||||
|
|
||||||
See below for more detail.
|
See below for more detail.
|
||||||
|
@ -173,3 +174,11 @@ or `title:"platypus attorney"`. These scopes are also supported:
|
||||||
**Filtering Matches**: You can remove documents which match certain terms from
|
**Filtering Matches**: You can remove documents which match certain terms from
|
||||||
the result set with `-`. For example: `platypus -mammal`. Documents which match
|
the result set with `-`. For example: `platypus -mammal`. Documents which match
|
||||||
negated terms will be filtered out of the result set.
|
negated terms will be filtered out of the result set.
|
||||||
|
|
||||||
|
**Matching Entire Fields**: If you know the exact name of an object and want
|
||||||
|
to find only that object, you can use the `=` operator. A query like
|
||||||
|
`title:"warp drive"` will find a document titled "Warp Drive", but will also
|
||||||
|
find documents with longer titles, like "Not a Warp Drive". The `=` operator
|
||||||
|
requires that the entire field match the query exactly, so //only// documents
|
||||||
|
exactly titled "Warp Drive" will be matched by the query (but note that the
|
||||||
|
query is still case insensitive).
|
||||||
|
|
|
@ -1918,6 +1918,7 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery
|
||||||
|
|
||||||
$op_sub = PhutilSearchQueryCompiler::OPERATOR_SUBSTRING;
|
$op_sub = PhutilSearchQueryCompiler::OPERATOR_SUBSTRING;
|
||||||
$op_not = PhutilSearchQueryCompiler::OPERATOR_NOT;
|
$op_not = PhutilSearchQueryCompiler::OPERATOR_NOT;
|
||||||
|
$op_exact = PhutilSearchQueryCompiler::OPERATOR_EXACT;
|
||||||
|
|
||||||
$where = array();
|
$where = array();
|
||||||
$current_function = 'all';
|
$current_function = 'all';
|
||||||
|
@ -1941,6 +1942,25 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery
|
||||||
$is_substring = false;
|
$is_substring = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we're doing exact search, just test the raw corpus.
|
||||||
|
$is_exact = ($raw_token->getOperator() == $op_exact);
|
||||||
|
if ($is_exact) {
|
||||||
|
if ($is_not) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'(%T.rawCorpus != %s)',
|
||||||
|
$table_alias,
|
||||||
|
$value);
|
||||||
|
} else {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'(%T.rawCorpus = %s)',
|
||||||
|
$table_alias,
|
||||||
|
$value);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// If we're doing substring search, we just match against the raw corpus
|
// If we're doing substring search, we just match against the raw corpus
|
||||||
// and we're done.
|
// and we're done.
|
||||||
if ($is_substring) {
|
if ($is_substring) {
|
||||||
|
|
|
@ -24,21 +24,33 @@ final class PhabricatorStorageManagementDestroyWorkflow
|
||||||
$console = PhutilConsole::getConsole();
|
$console = PhutilConsole::getConsole();
|
||||||
|
|
||||||
if (!$this->isDryRun() && !$this->isForce()) {
|
if (!$this->isDryRun() && !$this->isForce()) {
|
||||||
$console->writeOut(
|
if ($args->getArg('unittest-fixtures')) {
|
||||||
phutil_console_wrap(
|
$console->writeOut(
|
||||||
pht(
|
phutil_console_wrap(
|
||||||
'Are you completely sure you really want to permanently destroy '.
|
pht(
|
||||||
'all storage for Phabricator data? This operation can not be '.
|
'Are you completely sure you really want to destroy all unit '.
|
||||||
'undone and your data will not be recoverable if you proceed.')));
|
'test fixure data? This operation can not be undone.')));
|
||||||
|
if (!phutil_console_confirm(pht('Destroy all unit test data?'))) {
|
||||||
|
$console->writeOut("%s\n", pht('Cancelled.'));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$console->writeOut(
|
||||||
|
phutil_console_wrap(
|
||||||
|
pht(
|
||||||
|
'Are you completely sure you really want to permanently destroy '.
|
||||||
|
'all storage for Phabricator data? This operation can not be '.
|
||||||
|
'undone and your data will not be recoverable if you proceed.')));
|
||||||
|
|
||||||
if (!phutil_console_confirm(pht('Permanently destroy all data?'))) {
|
if (!phutil_console_confirm(pht('Permanently destroy all data?'))) {
|
||||||
$console->writeOut("%s\n", pht('Cancelled.'));
|
$console->writeOut("%s\n", pht('Cancelled.'));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!phutil_console_confirm(pht('Really destroy all data forever?'))) {
|
if (!phutil_console_confirm(pht('Really destroy all data forever?'))) {
|
||||||
$console->writeOut("%s\n", pht('Cancelled.'));
|
$console->writeOut("%s\n", pht('Cancelled.'));
|
||||||
exit(1);
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue