@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Improve "Land Revision" errors for issues related to staging areas

Summary: Ref T10093. Changes must be pushed to staging before they can be landed from the web.

Test Plan:
Changes must be pushed to staging before they can be landed from the web.

{F1161909}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T10093

Differential Revision: https://secure.phabricator.com/D15427

+140 -18
+34 -18
src/applications/differential/query/DifferentialDiffQuery.php
··· 6 6 private $ids; 7 7 private $phids; 8 8 private $revisionIDs; 9 + 9 10 private $needChangesets = false; 11 + private $needProperties; 10 12 11 13 public function withIDs(array $ids) { 12 14 $this->ids = $ids; ··· 28 30 return $this; 29 31 } 30 32 31 - protected function loadPage() { 32 - $table = new DifferentialDiff(); 33 - $conn_r = $table->establishConnection('r'); 33 + public function needProperties($need_properties) { 34 + $this->needProperties = $need_properties; 35 + return $this; 36 + } 34 37 35 - $data = queryfx_all( 36 - $conn_r, 37 - 'SELECT * FROM %T %Q %Q %Q', 38 - $table->getTableName(), 39 - $this->buildWhereClause($conn_r), 40 - $this->buildOrderClause($conn_r), 41 - $this->buildLimitClause($conn_r)); 38 + public function newResultObject() { 39 + return new DifferentialDiff(); 40 + } 42 41 43 - return $table->loadAllFromArray($data); 42 + protected function loadPage() { 43 + return $this->loadStandardPage($this->newResultObject()); 44 44 } 45 45 46 46 protected function willFilterPage(array $diffs) { ··· 76 76 return $diffs; 77 77 } 78 78 79 + protected function didFilterPage(array $diffs) { 80 + if ($this->needProperties) { 81 + $properties = id(new DifferentialDiffProperty())->loadAllWhere( 82 + 'diffID IN (%Ld)', 83 + mpull($diffs, 'getID')); 84 + 85 + $properties = mgroup($properties, 'getDiffID'); 86 + foreach ($diffs as $diff) { 87 + $map = idx($properties, $diff->getID(), array()); 88 + $map = mpull($map, 'getData', 'getName'); 89 + $diff->attachDiffProperties($map); 90 + } 91 + } 92 + 93 + return $diffs; 94 + } 95 + 79 96 private function loadChangesets(array $diffs) { 80 97 id(new DifferentialChangesetQuery()) 81 98 ->setViewer($this->getViewer()) ··· 88 105 return $diffs; 89 106 } 90 107 91 - protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { 92 - $where = array(); 108 + protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { 109 + $where = parent::buildWhereClauseParts($conn); 93 110 94 111 if ($this->ids) { 95 112 $where[] = qsprintf( 96 - $conn_r, 113 + $conn, 97 114 'id IN (%Ld)', 98 115 $this->ids); 99 116 } 100 117 101 118 if ($this->phids) { 102 119 $where[] = qsprintf( 103 - $conn_r, 120 + $conn, 104 121 'phid IN (%Ls)', 105 122 $this->phids); 106 123 } 107 124 108 125 if ($this->revisionIDs) { 109 126 $where[] = qsprintf( 110 - $conn_r, 127 + $conn, 111 128 'revisionID IN (%Ld)', 112 129 $this->revisionIDs); 113 130 } 114 131 115 - $where[] = $this->buildPagingClause($conn_r); 116 - return $this->formatWhereClause($where); 132 + return $where; 117 133 } 118 134 119 135 public function getQueryApplicationClass() {
+104
src/applications/drydock/operation/DrydockLandRepositoryOperation.php
··· 248 248 ); 249 249 } 250 250 251 + // Check if this diff was pushed to a staging area. 252 + $diff = id(new DifferentialDiffQuery()) 253 + ->setViewer($viewer) 254 + ->withIDs(array($revision->getActiveDiff()->getID())) 255 + ->needProperties(true) 256 + ->executeOne(); 257 + 258 + // Older diffs won't have this property. They may still have been pushed. 259 + // At least for now, assume staging changes are present if the property 260 + // is missing. This should smooth the transition to the more formal 261 + // approach. 262 + $has_staging = $diff->hasDiffProperty('arc.staging'); 263 + if ($has_staging) { 264 + $staging = $diff->getProperty('arc.staging'); 265 + if (!is_array($staging)) { 266 + $staging = array(); 267 + } 268 + $status = idx($staging, 'status'); 269 + if ($status != ArcanistDiffWorkflow::STAGING_PUSHED) { 270 + return $this->getBarrierToLandingFromStagingStatus($status); 271 + } 272 + } 273 + 251 274 // TODO: At some point we should allow installs to give "land reviewed 252 275 // code" permission to more users than "push any commit", because it is 253 276 // a much less powerful operation. For now, just require push so this ··· 334 357 } 335 358 336 359 return null; 360 + } 361 + 362 + private function getBarrierToLandingFromStagingStatus($status) { 363 + switch ($status) { 364 + case ArcanistDiffWorkflow::STAGING_USER_SKIP: 365 + return array( 366 + 'title' => pht('Staging Area Skipped'), 367 + 'body' => pht( 368 + 'The diff author used the %s flag to skip pushing this change to '. 369 + 'staging. Changes must be pushed to staging before they can be '. 370 + 'landed from the web.', 371 + phutil_tag('tt', array(), '--skip-staging')), 372 + ); 373 + case ArcanistDiffWorkflow::STAGING_DIFF_RAW: 374 + return array( 375 + 'title' => pht('Raw Diff Source'), 376 + 'body' => pht( 377 + 'The diff was generated from a raw input source, so the change '. 378 + 'could not be pushed to staging. Changes must be pushed to '. 379 + 'staging before they can be landed from the web.'), 380 + ); 381 + case ArcanistDiffWorkflow::STAGING_REPOSITORY_UNKNOWN: 382 + return array( 383 + 'title' => pht('Unknown Repository'), 384 + 'body' => pht( 385 + 'When the diff was generated, the client was not able to '. 386 + 'determine which repository it belonged to, so the change '. 387 + 'was not pushed to staging. Changes must be pushed to staging '. 388 + 'before they can be landed from the web.'), 389 + ); 390 + case ArcanistDiffWorkflow::STAGING_REPOSITORY_UNAVAILABLE: 391 + return array( 392 + 'title' => pht('Staging Unavailable'), 393 + 'body' => pht( 394 + 'When this diff was generated, the server was running an older '. 395 + 'version of Phabricator which did not support staging areas, so '. 396 + 'the change was not pushed to staging. Changes must be pushed '. 397 + 'to staging before they can be landed from the web.'), 398 + ); 399 + case ArcanistDiffWorkflow::STAGING_REPOSITORY_UNSUPPORTED: 400 + return array( 401 + 'title' => pht('Repository Unsupported'), 402 + 'body' => pht( 403 + 'When this diff was generated, the server was running an older '. 404 + 'version of Phabricator which did not support staging areas for '. 405 + 'this version control system, so the chagne was not pushed to '. 406 + 'staging. Changes must be pushed to staging before they can be '. 407 + 'landed from the web.'), 408 + ); 409 + 410 + case ArcanistDiffWorkflow::STAGING_REPOSITORY_UNCONFIGURED: 411 + return array( 412 + 'title' => pht('Repository Unconfigured'), 413 + 'body' => pht( 414 + 'When this diff was generated, the repository was not configured '. 415 + 'with a staging area, so the change was not pushed to staging. '. 416 + 'Changes must be pushed to staging before they can be landed '. 417 + 'from the web.'), 418 + ); 419 + case ArcanistDiffWorkflow::STAGING_CLIENT_UNSUPPORTED: 420 + return array( 421 + 'title' => pht('Client Support Unavailable'), 422 + 'body' => pht( 423 + 'When this diff was generated, the client did not support '. 424 + 'staging areas for this version control system, so the change '. 425 + 'was not pushed to staging. Changes must be pushed to staging '. 426 + 'before they can be landed from the web. Updating the client '. 427 + 'may resolve this issue.'), 428 + ); 429 + default: 430 + return array( 431 + 'title' => pht('Unknown Error'), 432 + 'body' => pht( 433 + 'When this diff was generated, it was not pushed to staging for '. 434 + 'an unknown reason (the status code was "%s"). Changes must be '. 435 + 'pushed to staging before they can be landed from the web. '. 436 + 'The server may be running an out-of-date version of Phabricator, '. 437 + 'and updating may provide more information about this error.', 438 + $status), 439 + ); 440 + } 337 441 } 338 442 339 443 }
+2
src/applications/harbormaster/storage/build/HarbormasterBuildLog.php
··· 114 114 115 115 $this->rope->append($content); 116 116 $this->flush(); 117 + 118 + return $this; 117 119 } 118 120 119 121 private function flush() {