Changeset View
Changeset View
Standalone View
Standalone View
src/infrastructure/diff/PhabricatorDifferenceEngine.php
<?php | <?php | ||||
/** | /** | ||||
* Utility class which encapsulates some shared behavior between different | * Utility class which encapsulates some shared behavior between different | ||||
* applications which render diffs. | * applications which render diffs. | ||||
* | * | ||||
* @task config Configuring the Engine | * @task config Configuring the Engine | ||||
* @task diff Generating Diffs | * @task diff Generating Diffs | ||||
*/ | */ | ||||
final class PhabricatorDifferenceEngine extends Phobject { | final class PhabricatorDifferenceEngine extends Phobject { | ||||
private $oldName; | private $oldName; | ||||
private $newName; | private $newName; | ||||
private $normalize; | |||||
/* -( Configuring the Engine )--------------------------------------------- */ | /* -( Configuring the Engine )--------------------------------------------- */ | ||||
/** | /** | ||||
* Set the name to identify the old file with. Primarily cosmetic. | * Set the name to identify the old file with. Primarily cosmetic. | ||||
* | * | ||||
Show All 15 Lines | /* -( Configuring the Engine )--------------------------------------------- */ | ||||
* @task config | * @task config | ||||
*/ | */ | ||||
public function setNewName($new_name) { | public function setNewName($new_name) { | ||||
$this->newName = $new_name; | $this->newName = $new_name; | ||||
return $this; | return $this; | ||||
} | } | ||||
public function setNormalize($normalize) { | |||||
$this->normalize = $normalize; | |||||
return $this; | |||||
} | |||||
public function getNormalize() { | |||||
return $this->normalize; | |||||
} | |||||
/* -( Generating Diffs )--------------------------------------------------- */ | /* -( Generating Diffs )--------------------------------------------------- */ | ||||
/** | /** | ||||
* Generate a raw diff from two raw files. This is a lower-level API than | * Generate a raw diff from two raw files. This is a lower-level API than | ||||
* @{method:generateChangesetFromFileContent}, but may be useful if you need | * @{method:generateChangesetFromFileContent}, but may be useful if you need | ||||
* to use a custom parser configuration, as with Diffusion. | * to use a custom parser configuration, as with Diffusion. | ||||
* | * | ||||
Show All 12 Lines | public function generateRawDiffFromFileContent($old, $new) { | ||||
$old_name = nonempty($this->oldName, '/dev/universe').' 9999-99-99'; | $old_name = nonempty($this->oldName, '/dev/universe').' 9999-99-99'; | ||||
$new_name = nonempty($this->newName, '/dev/universe').' 9999-99-99'; | $new_name = nonempty($this->newName, '/dev/universe').' 9999-99-99'; | ||||
$options[] = '-L'; | $options[] = '-L'; | ||||
$options[] = $old_name; | $options[] = $old_name; | ||||
$options[] = '-L'; | $options[] = '-L'; | ||||
$options[] = $new_name; | $options[] = $new_name; | ||||
$normalize = $this->getNormalize(); | |||||
if ($normalize) { | |||||
$old = $this->normalizeFile($old); | |||||
$new = $this->normalizeFile($new); | |||||
} | |||||
$old_tmp = new TempFile(); | $old_tmp = new TempFile(); | ||||
$new_tmp = new TempFile(); | $new_tmp = new TempFile(); | ||||
Filesystem::writeFile($old_tmp, $old); | Filesystem::writeFile($old_tmp, $old); | ||||
Filesystem::writeFile($new_tmp, $new); | Filesystem::writeFile($new_tmp, $new); | ||||
list($err, $diff) = exec_manual( | list($err, $diff) = exec_manual( | ||||
'diff %Ls %s %s', | 'diff %Ls %s %s', | ||||
$options, | $options, | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | public function generateChangesetFromFileContent($old, $new) { | ||||
$diff = $this->generateRawDiffFromFileContent($old, $new); | $diff = $this->generateRawDiffFromFileContent($old, $new); | ||||
$changes = id(new ArcanistDiffParser())->parseDiff($diff); | $changes = id(new ArcanistDiffParser())->parseDiff($diff); | ||||
$diff = DifferentialDiff::newEphemeralFromRawChanges( | $diff = DifferentialDiff::newEphemeralFromRawChanges( | ||||
$changes); | $changes); | ||||
return head($diff->getChangesets()); | return head($diff->getChangesets()); | ||||
} | } | ||||
private function normalizeFile($corpus) { | |||||
// We can freely apply any other transformations we want to here: we have | |||||
// no constraints on what we need to preserve. If we normalize every line | |||||
// to "cat", the diff will still work, the alignment of the "-" / "+" | |||||
// lines will just be very hard to read. | |||||
// In general, we'll make the diff better if we normalize two lines that | |||||
// humans think are the same. | |||||
// We'll make the diff worse if we normalize two lines that humans think | |||||
// are different. | |||||
// Strip all whitespace present anywhere in the diff, since humans never | |||||
// consider whitespace changes to alter the line into a "different line" | |||||
// even when they're semantic (e.g., in a string constant). This covers | |||||
// indentation changes, trailing whitepspace, and formatting changes | |||||
// like "+/-". | |||||
$corpus = preg_replace('/[ \t]/', '', $corpus); | |||||
return $corpus; | |||||
} | |||||
} | } |