@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.

Fix an issue where the last line of block-based diffs could be incorrectly hidden

Summary:
Fixes T13468. See that task for discussion. The older source-rendering code mixes "line number" / "1-based" lists with "block number" / "0-based" lists and then has other bugs which cancel this out.

For block-based diffs, build an explicit block-based mask with only block numbers. This sort of sidesteps the whole issue.

Test Plan: Viewed the diff with the original reproduction case, plus various other block-based diffs, including one-block image diffs, in unified and side-by-side mode. Didn't spot any oddities.

Maniphest Tasks: T13468

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

+66 -9
+64
src/applications/differential/parser/DifferentialHunkParser.php
··· 354 354 return $this; 355 355 } 356 356 357 + public function generateVisibleBlocksMask($lines_context) { 358 + 359 + // See T13468. This is similar to "generateVisibleLinesMask()", but 360 + // attempts to work around a series of bugs which cancel each other 361 + // out but make a mess of the intermediate steps. 362 + 363 + $old = $this->getOldLines(); 364 + $new = $this->getNewLines(); 365 + 366 + $length = max(count($old), count($new)); 367 + 368 + $visible_lines = array(); 369 + for ($ii = 0; $ii < $length; $ii++) { 370 + $old_visible = (isset($old[$ii]) && $old[$ii]['type']); 371 + $new_visible = (isset($new[$ii]) && $new[$ii]['type']); 372 + 373 + $visible_lines[$ii] = ($old_visible || $new_visible); 374 + } 375 + 376 + $mask = array(); 377 + $reveal_cursor = -1; 378 + for ($ii = 0; $ii < $length; $ii++) { 379 + 380 + // If this line isn't visible, it isn't going to reveal anything. 381 + if (!$visible_lines[$ii]) { 382 + 383 + // If it hasn't been revealed by a nearby line, mark it as masked. 384 + if (empty($mask[$ii])) { 385 + $mask[$ii] = false; 386 + } 387 + 388 + continue; 389 + } 390 + 391 + // If this line is visible, reveal all the lines nearby. 392 + 393 + // First, compute the minimum and maximum offsets we want to reveal. 394 + $min_reveal = max($ii - $lines_context, 0); 395 + $max_reveal = min($ii + $lines_context, $length - 1); 396 + 397 + // Naively, we'd do more work than necessary when revealing context for 398 + // several adjacent visible lines: we would mark all the overlapping 399 + // lines as revealed several times. 400 + 401 + // To avoid duplicating work, keep track of the largest line we've 402 + // revealed to. Since we reveal context by marking every consecutive 403 + // line, we don't need to touch any line above it. 404 + $min_reveal = max($min_reveal, $reveal_cursor); 405 + 406 + // Reveal the remaining unrevealed lines. 407 + for ($jj = $min_reveal; $jj <= $max_reveal; $jj++) { 408 + $mask[$jj] = true; 409 + } 410 + 411 + // Move the cursor to the next line which may still need to be revealed. 412 + $reveal_cursor = $max_reveal + 1; 413 + } 414 + 415 + $this->setVisibleLinesMask($mask); 416 + 417 + return $mask; 418 + } 419 + 357 420 public function generateVisibleLinesMask($lines_context) { 358 421 $old = $this->getOldLines(); 359 422 $new = $this->getNewLines(); ··· 361 424 $visible = false; 362 425 $last = 0; 363 426 $mask = array(); 427 + 364 428 for ($cursor = -$lines_context; $cursor < $max_length; $cursor++) { 365 429 $offset = $cursor + $lines_context; 366 430 if ((isset($old[$offset]) && $old[$offset]['type']) ||
+2 -9
src/applications/files/diff/PhabricatorDocumentEngineBlocks.php
··· 59 59 ->parseHunksForLineData($changeset->getHunks()) 60 60 ->reparseHunksForSpecialAttributes(); 61 61 62 - $hunk_parser->generateVisibleLinesMask(2); 62 + $hunk_parser->generateVisibleBlocksMask(2); 63 63 $mask = $hunk_parser->getVisibleLinesMask(); 64 64 65 65 $old_lines = $hunk_parser->getOldLines(); ··· 72 72 $old_line = idx($old_lines, $ii); 73 73 $new_line = idx($new_lines, $ii); 74 74 75 - $is_visible = !empty($mask[$ii + 1]); 76 - 77 - // TODO: There's currently a bug where one-line files get incorrectly 78 - // masked. This causes images to completely fail to render. Just ignore 79 - // the mask if it came back empty. 80 - if (!$mask) { 81 - $is_visible = true; 82 - } 75 + $is_visible = !empty($mask[$ii]); 83 76 84 77 if ($old_line) { 85 78 $old_hash = rtrim($old_line['text'], "\n");