private function tryCacheStuff() { $whitespace_mode = $this->whitespaceMode; switch ($whitespace_mode) { case self::WHITESPACE_SHOW_ALL: case self::WHITESPACE_IGNORE_TRAILING: break; default: $whitespace_mode = self::WHITESPACE_IGNORE_ALL; break; } $skip_cache = $whitespace_mode != self::WHITESPACE_IGNORE_ALL; $this->whitespaceMode = $whitespace_mode; $changeset = $this->changeset; if ($changeset->getFileType() == DifferentialChangeType::FILE_TEXT || $changeset->getFileType() == DifferentialChangeType::FILE_SYMLINK) { if ($skip_cache || !$this->loadCache()) { $ignore_all = $this->whitespaceMode == self::WHITESPACE_IGNORE_ALL; if ($ignore_all && $changeset->getWhitespaceMatters()) { $ignore_all = false; } // The "ignore all whitespace" algorithm depends on rediffing the // files, and we currently need complete representations of both // files to do anything reasonable. If we only have parts of the files, // don't use the "ignore all" algorithm. if ($ignore_all) { $hunks = $changeset->getHunks(); if (count($hunks) !== 1) { $ignore_all = false; } else { $first_hunk = reset($hunks); if ($first_hunk->getOldOffset() != 1 || $first_hunk->getNewOffset() != 1) { $ignore_all = false; } } } if ($ignore_all) { $old_file = $changeset->makeOldFile(); $new_file = $changeset->makeNewFile(); if ($old_file == $new_file) { // If the old and new files are exactly identical, the synthetic // diff below will give us nonsense and whitespace modes are // irrelevant anyway. This occurs when you, e.g., copy a file onto // itself in Subversion (see T271). $ignore_all = false; } } if ($ignore_all) { // Huge mess. Generate a "-bw" (ignore all whitespace changes) diff, // parse it out, and then play a shell game with the parsed format // in process() so we highlight only changed lines but render // whitespace differences. If we don't do this, we either fail to // render whitespace changes (which is incredibly confusing, // especially for python) or often produce a much larger set of // differences than necessary. $engine = new PhabricatorDifferenceEngine(); $engine->setIgnoreWhitespace(true); $no_whitespace_changeset = $engine->generateChangesetFromFileContent($old_file, $new_file); // subparser takes over the current non-whitespace-ignoring changeset $subparser = new DifferentialChangesetParser(); $subparser->isSubparser = true; $subparser->setChangeset($changeset); foreach ($changeset->getHunks() as $hunk) { $subparser->parseHunk($hunk); } // We need to call process() so that the subparser's values for // metadata (like 'unchanged') is correct. $subparser->process(); $this->subparser = $subparser; // While we aren't updating $this->changeset (since it has a bunch // of metadata we need to preserve, so that headers like "this file // was moved" render correctly), we're overwriting the local // $changeset so that the block below will choose the synthetic // hunks we've built instead of the original hunks. $changeset = $no_whitespace_changeset; } // This either uses the real hunks, or synthetic hunks we built above. foreach ($changeset->getHunks() as $hunk) { $this->parseHunk($hunk); } $this->process(); if (!$skip_cache) { $this->saveCache(); } } } }