1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-15 01:50:55 +01:00

(stable) Promote 2017 Week 42

This commit is contained in:
epriestley 2017-10-21 05:57:58 -07:00
commit 24ff632612
10 changed files with 288 additions and 87 deletions

View file

@ -444,6 +444,7 @@ phutil_register_library_map(array(
'DifferentialDiffTransactionQuery' => 'applications/differential/query/DifferentialDiffTransactionQuery.php',
'DifferentialDiffViewController' => 'applications/differential/controller/DifferentialDiffViewController.php',
'DifferentialDoorkeeperRevisionFeedStoryPublisher' => 'applications/differential/doorkeeper/DifferentialDoorkeeperRevisionFeedStoryPublisher.php',
'DifferentialDraftField' => 'applications/differential/customfield/DifferentialDraftField.php',
'DifferentialExactUserFunctionDatasource' => 'applications/differential/typeahead/DifferentialExactUserFunctionDatasource.php',
'DifferentialFieldParseException' => 'applications/differential/exception/DifferentialFieldParseException.php',
'DifferentialFieldValidationException' => 'applications/differential/exception/DifferentialFieldValidationException.php',
@ -5451,6 +5452,7 @@ phutil_register_library_map(array(
'DifferentialDiffTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'DifferentialDiffViewController' => 'DifferentialController',
'DifferentialDoorkeeperRevisionFeedStoryPublisher' => 'DoorkeeperFeedStoryPublisher',
'DifferentialDraftField' => 'DifferentialCoreCustomField',
'DifferentialExactUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'DifferentialFieldParseException' => 'Exception',
'DifferentialFieldValidationException' => 'Exception',

View file

@ -0,0 +1,90 @@
<?php
final class DifferentialDraftField
extends DifferentialCoreCustomField {
public function getFieldKey() {
return 'differential:draft';
}
public function getFieldName() {
return pht('Draft');
}
public function getFieldDescription() {
return pht('Show a warning about draft revisions.');
}
protected function readValueFromRevision(
DifferentialRevision $revision) {
return null;
}
public function shouldAppearInPropertyView() {
return true;
}
public function renderPropertyViewValue() {
return null;
}
public function getWarningsForRevisionHeader(array $handles) {
$viewer = $this->getViewer();
$revision = $this->getObject();
if (!$revision->isDraft()) {
return array();
}
$warnings = array();
$blocking_map = array(
HarbormasterBuildStatus::STATUS_FAILED,
HarbormasterBuildStatus::STATUS_ABORTED,
HarbormasterBuildStatus::STATUS_ERROR,
HarbormasterBuildStatus::STATUS_PAUSED,
HarbormasterBuildStatus::STATUS_DEADLOCKED,
);
$blocking_map = array_fuse($blocking_map);
$builds = $revision->loadActiveBuilds($viewer);
$waiting = array();
$blocking = array();
foreach ($builds as $build) {
if (isset($blocking_map[$build->getBuildStatus()])) {
$blocking[] = $build;
} else {
$waiting[] = $build;
}
}
$blocking_list = $viewer->renderHandleList(mpull($blocking, 'getPHID'))
->setAsInline(true);
$waiting_list = $viewer->renderHandleList(mpull($waiting, 'getPHID'))
->setAsInline(true);
if ($blocking) {
$warnings[] = pht(
'This draft revision will not be submitted for review because %s '.
'build(s) failed: %s.',
phutil_count($blocking),
$blocking_list);
$warnings[] = pht(
'Fix build failures and update the revision.');
} else if ($waiting) {
$warnings[] = pht(
'This draft revision will be sent for review once %s '.
'build(s) pass: %s.',
phutil_count($waiting),
$waiting_list);
} else {
$warnings[] = pht(
'This is a draft revision that has not yet been submitted for '.
'review.');
}
return $warnings;
}
}

View file

@ -1570,58 +1570,12 @@ final class DifferentialTransactionEditor
private function hasActiveBuilds($object) {
$viewer = $this->requireActor();
$diff = $object->getActiveDiff();
$buildables = id(new HarbormasterBuildableQuery())
->setViewer($viewer)
->withContainerPHIDs(array($object->getPHID()))
->withBuildablePHIDs(array($diff->getPHID()))
->withManualBuildables(false)
->execute();
if (!$buildables) {
return false;
}
$builds = id(new HarbormasterBuildQuery())
->setViewer($viewer)
->withBuildablePHIDs(mpull($buildables, 'getPHID'))
->withBuildStatuses(
array(
HarbormasterBuildStatus::STATUS_INACTIVE,
HarbormasterBuildStatus::STATUS_PENDING,
HarbormasterBuildStatus::STATUS_BUILDING,
HarbormasterBuildStatus::STATUS_FAILED,
HarbormasterBuildStatus::STATUS_ABORTED,
HarbormasterBuildStatus::STATUS_ERROR,
HarbormasterBuildStatus::STATUS_PAUSED,
HarbormasterBuildStatus::STATUS_DEADLOCKED,
))
->needBuildTargets(true)
->execute();
$builds = $object->loadActiveBuilds($viewer);
if (!$builds) {
return false;
}
$active = array();
foreach ($builds as $key => $build) {
foreach ($build->getBuildTargets() as $target) {
if ($target->isAutotarget()) {
// Ignore autotargets when looking for active of failed builds. If
// local tests fail and you continue anyway, you don't need to
// double-confirm them.
continue;
}
// This build has at least one real target that's doing something.
$active[$key] = $build;
break;
}
}
if (!$active) {
return false;
}
return true;
}

View file

@ -41,6 +41,20 @@ final class DifferentialChangesetOneUpRenderer
$column_width = 4;
$aural_minus = javelin_tag(
'span',
array(
'aural' => true,
),
'- ');
$aural_plus = javelin_tag(
'span',
array(
'aural' => true,
),
'+ ');
$out = array();
foreach ($primitives as $k => $p) {
$type = $p['type'];
@ -55,8 +69,10 @@ final class DifferentialChangesetOneUpRenderer
if ($is_old) {
if ($p['htype']) {
$class = 'left old';
$aural = $aural_minus;
} else {
$class = 'left';
$aural = null;
}
if ($type == 'old-file') {
@ -79,14 +95,20 @@ final class DifferentialChangesetOneUpRenderer
),
$line);
$render = $p['render'];
if ($aural !== null) {
$render = array($aural, $render);
}
$cells[] = phutil_tag('th', array('class' => $class));
$cells[] = $no_copy;
$cells[] = phutil_tag('td', array('class' => $class), $p['render']);
$cells[] = phutil_tag('td', array('class' => $class), $render);
$cells[] = $no_coverage;
} else {
if ($p['htype']) {
$class = 'right new';
$cells[] = phutil_tag('th', array('class' => $class));
$aural = $aural_plus;
} else {
$class = 'right';
if ($left_prefix) {
@ -98,6 +120,7 @@ final class DifferentialChangesetOneUpRenderer
$oline = $p['oline'];
$cells[] = phutil_tag('th', array('id' => $left_id), $oline);
$aural = null;
}
if ($type == 'new-file') {
@ -120,8 +143,13 @@ final class DifferentialChangesetOneUpRenderer
),
$line);
$render = $p['render'];
if ($aural !== null) {
$render = array($aural, $render);
}
$cells[] = $no_copy;
$cells[] = phutil_tag('td', array('class' => $class), $p['render']);
$cells[] = phutil_tag('td', array('class' => $class), $render);
$cells[] = $no_coverage;
}

View file

@ -67,13 +67,19 @@ final class DifferentialRevision extends DifferentialDAO
$view_policy = $app->getPolicy(
DifferentialDefaultViewCapability::CAPABILITY);
if (PhabricatorEnv::getEnvConfig('phabricator.show-prototypes')) {
$initial_state = DifferentialRevisionStatus::DRAFT;
} else {
$initial_state = DifferentialRevisionStatus::NEEDS_REVIEW;
}
return id(new DifferentialRevision())
->setViewPolicy($view_policy)
->setAuthorPHID($actor->getPHID())
->attachRepository(null)
->attachActiveDiff(null)
->attachReviewers(array())
->setModernRevisionStatus(DifferentialRevisionStatus::NEEDS_REVIEW);
->setModernRevisionStatus($initial_state);
}
protected function getConfiguration() {
@ -702,6 +708,58 @@ final class DifferentialRevision extends DifferentialDAO
return false;
}
public function loadActiveBuilds(PhabricatorUser $viewer) {
$diff = $this->getActiveDiff();
$buildables = id(new HarbormasterBuildableQuery())
->setViewer($viewer)
->withContainerPHIDs(array($this->getPHID()))
->withBuildablePHIDs(array($diff->getPHID()))
->withManualBuildables(false)
->execute();
if (!$buildables) {
return array();
}
$builds = id(new HarbormasterBuildQuery())
->setViewer($viewer)
->withBuildablePHIDs(mpull($buildables, 'getPHID'))
->withBuildStatuses(
array(
HarbormasterBuildStatus::STATUS_INACTIVE,
HarbormasterBuildStatus::STATUS_PENDING,
HarbormasterBuildStatus::STATUS_BUILDING,
HarbormasterBuildStatus::STATUS_FAILED,
HarbormasterBuildStatus::STATUS_ABORTED,
HarbormasterBuildStatus::STATUS_ERROR,
HarbormasterBuildStatus::STATUS_PAUSED,
HarbormasterBuildStatus::STATUS_DEADLOCKED,
))
->needBuildTargets(true)
->execute();
if (!$builds) {
return array();
}
$active = array();
foreach ($builds as $key => $build) {
foreach ($build->getBuildTargets() as $target) {
if ($target->isAutotarget()) {
// Ignore autotargets when looking for active of failed builds. If
// local tests fail and you continue anyway, you don't need to
// double-confirm them.
continue;
}
// This build has at least one real target that's doing something.
$active[$key] = $build;
break;
}
}
return $active;
}
/* -( HarbormasterBuildableInterface )------------------------------------- */

View file

@ -256,6 +256,66 @@ final class DiffusionLowLevelResolveRefsQuery
return $results;
}
// If some of the refs look like hashes, try to bulk resolve them. This
// workflow happens via RefEngine and bulk resolution is dramatically
// faster than individual resolution. See PHI158.
$hashlike = array();
foreach ($unresolved as $key => $ref) {
if (preg_match('/^[a-f0-9]{40}\z/', $ref)) {
$hashlike[$key] = $ref;
}
}
if (count($hashlike) > 1) {
$hashlike_map = array();
$hashlike_groups = array_chunk($hashlike, 64, true);
foreach ($hashlike_groups as $hashlike_group) {
$hashlike_arg = array();
foreach ($hashlike_group as $hashlike_ref) {
$hashlike_arg[] = hgsprintf('%s', $hashlike_ref);
}
$hashlike_arg = '('.implode(' or ', $hashlike_arg).')';
list($err, $refs) = $repository->execLocalCommand(
'log --template=%s --rev %s',
'{node}\n',
$hashlike_arg);
if ($err) {
// NOTE: If any ref fails to resolve, Mercurial will exit with an
// error. We just give up on the whole group and resolve it
// individually below. In theory, we could split it into subgroups
// but the pathway where this bulk resolution matters rarely tries
// to resolve missing refs (see PHI158).
continue;
}
$refs = phutil_split_lines($refs, false);
foreach ($refs as $ref) {
$hashlike_map[$ref] = true;
}
}
foreach ($unresolved as $key => $ref) {
if (!isset($hashlike_map[$ref])) {
continue;
}
$results[$ref][] = array(
'type' => 'commit',
'identifier' => $ref,
);
unset($unresolved[$key]);
}
}
if (!$unresolved) {
return $results;
}
// If we still have unresolved refs (which might be things like "tip"),
// try to resolve them individually.

View file

@ -15,4 +15,8 @@ final class PhabricatorOwnersPackageTransaction
return 'PhabricatorOwnersPackageTransactionType';
}
public function getApplicationTransactionCommentObject() {
return null;
}
}

View file

@ -16,19 +16,49 @@ final class PhabricatorSearchManagementNgramsWorkflow
'name' => 'reset',
'help' => pht('Reset all common ngram records.'),
),
array(
'name' => 'threshold',
'param' => 'threshold',
'help' => pht(
'Prune ngrams present in more than this fraction of '.
'documents. Provide a value between 0.0 and 1.0.'),
),
));
}
public function execute(PhutilArgumentParser $args) {
$min_documents = 4096;
$is_reset = $args->getArg('reset');
$threshold = $args->getArg('threshold');
if ($is_reset && $threshold !== null) {
throw new PhutilArgumentUsageException(
pht('Specify either --reset or --threshold, not both.'));
}
if (!$is_reset && $threshold === null) {
throw new PhutilArgumentUsageException(
pht('Specify either --reset or --threshold.'));
}
if (!$is_reset) {
if (!is_numeric($threshold)) {
throw new PhutilArgumentUsageException(
pht('Specify a numeric threshold between 0 and 1.'));
}
$threshold = (double)$threshold;
if ($threshold <= 0 || $threshold >= 1) {
throw new PhutilArgumentUsageException(
pht('Threshold must be greater than 0.0 and less than 1.0.'));
}
}
$all_objects = id(new PhutilClassMapQuery())
->setAncestorClass('PhabricatorFerretInterface')
->execute();
$min_documents = 4096;
$threshold = 0.15;
foreach ($all_objects as $object) {
$engine = $object->newFerretEngine();
$conn = $object->establishConnection('w');

View file

@ -9,8 +9,6 @@ Overview
Phabricator includes //prototype applications//, which are applications in an
early stage of development.
IMPORTANT: The upstream does not offer support for these applications.
When we begin working on a new application, we usually implement it as a
prototype first. This allows us to get a better sense of how the application
might work and integrate with other applications, and what technical and product
@ -32,34 +30,3 @@ on hold indefinitely if we're less excited about it after we begin building it.
If you're interested in previewing upcoming applications, you can use the
`phabricator.show-prototypes` configuration setting to enable prototypes.
Feedback on Prototypes
======================
We're usually interested in this sort of feedback on prototypes:
- {icon check, color=green} **Use Cases**: If we're building something that
you think you'd use, we'd love to hear about your use cases for it. This can
help us figure out what features to add and how users may think about, use,
and integrate the application.
- {icon check, color=green} **General Interest**: Is an application something
you're looking forward to? Knowing which applications users are interested
in can help us set priorities.
We're usually **not** interested in this sort of feedback on prototypes:
- {icon times, color=red} **Support Requests**: We do not support these
applications. Use them at your own risk, or wait for them to leave the
prototype phase.
- {icon times, color=red} **Bug Reports**: We know these applications don't
work well yet, and usually know about most of the open bugs. Even if we
don't, whatever isn't working yet may change completely before the
application leaves the prototype phase.
- {icon times, color=red} **Contributions / Pull Requests**: These
applications are usually in too early a state to accept contributions. Let
us know about your use case, but wait for release to send code.
Overall, using prototypes makes it easier for us to explore and develop
application ideas, and to share a preview of what's coming in the future with
users, but prototypes are not yet full applications and we do not provide
support until applications leave the prototype phase.

View file

@ -35,7 +35,15 @@ final class PhabricatorClientRateLimit
// If the user was logged in, let them make more requests.
if (isset($request_state['viewer'])) {
$viewer = $request_state['viewer'];
if ($viewer->isLoggedIn()) {
if ($viewer->isOmnipotent()) {
// If the viewer was omnipotent, this was an intracluster request or
// some other kind of special request, so don't give it any points
// toward rate limiting.
$score = 0;
} else if ($viewer->isLoggedIn()) {
// If the viewer was logged in, give them fewer points than if they
// were logged out, since this traffic is much more likely to be
// legitimate.
$score = 0.25;
}
}