mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-15 10:00:55 +01:00
(stable) Promote 2017 Week 42
This commit is contained in:
commit
24ff632612
10 changed files with 288 additions and 87 deletions
|
@ -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',
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 )------------------------------------- */
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -15,4 +15,8 @@ final class PhabricatorOwnersPackageTransaction
|
|||
return 'PhabricatorOwnersPackageTransactionType';
|
||||
}
|
||||
|
||||
public function getApplicationTransactionCommentObject() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue