Changeset View
Changeset View
Standalone View
Standalone View
src/parser/ArcanistBundle.php
| Show First 20 Lines • Show All 775 Lines • ▼ Show 20 Lines | private function buildBinaryChange(ArcanistDiffChange $change, $old_binary) { | ||||
| $content[] = "literal {$old_length}".$eol; | $content[] = "literal {$old_length}".$eol; | ||||
| $content[] = $this->emitBinaryDiffBody($old_data).$eol; | $content[] = $this->emitBinaryDiffBody($old_data).$eol; | ||||
| return implode('', $content); | return implode('', $content); | ||||
| } | } | ||||
| private function emitBinaryDiffBody($data) { | private function emitBinaryDiffBody($data) { | ||||
| $eol = $this->getEOL('git'); | $eol = $this->getEOL('git'); | ||||
| return self::newBase85Data($data, $eol); | |||||
| } | |||||
| public static function newBase85Data($data, $eol, $mode = null) { | |||||
| // The "32bit" and "64bit" modes are used by unit tests to verify that all | |||||
| // of the encoding pathways here work identically. In these modes, we skip | |||||
| // compression because `gzcompress()` may not be stable and we just want | |||||
| // to test that the output matches some expected result. | |||||
| if ($mode === null) { | |||||
| if (!function_exists('gzcompress')) { | if (!function_exists('gzcompress')) { | ||||
| throw new Exception( | throw new Exception( | ||||
| pht( | pht( | ||||
| 'This patch has binary data. The PHP zlib extension is required to '. | 'This patch has binary data. The PHP zlib extension is required '. | ||||
| 'apply patches with binary data to git. Install the PHP zlib '. | 'to apply patches with binary data to git. Install the PHP zlib '. | ||||
| 'extension to continue.')); | 'extension to continue.')); | ||||
| } | } | ||||
| $input = gzcompress($data); | |||||
| } else { | |||||
| switch ($mode) { | |||||
| case '32bit': | |||||
| $input = $data; | |||||
| break; | |||||
| case '64bit': | |||||
| $input = $data; | |||||
| break; | |||||
| default: | |||||
| throw new Exception( | |||||
| pht( | |||||
| 'Unsupported base85 encoding mode "%s".', | |||||
| $mode)); | |||||
| } | |||||
| } | |||||
| // See emit_binary_diff_body() in diff.c for git's implementation. | // See emit_binary_diff_body() in diff.c for git's implementation. | ||||
| $buf = ''; | $buf = ''; | ||||
| $deflated = gzcompress($data); | $lines = str_split($input, 52); | ||||
| $lines = str_split($deflated, 52); | |||||
| foreach ($lines as $line) { | foreach ($lines as $line) { | ||||
| $len = strlen($line); | $len = strlen($line); | ||||
| // The first character encodes the line length. | // The first character encodes the line length. | ||||
| if ($len <= 26) { | if ($len <= 26) { | ||||
| $buf .= chr($len + ord('A') - 1); | $buf .= chr($len + ord('A') - 1); | ||||
| } else { | } else { | ||||
| $buf .= chr($len - 26 + ord('a') - 1); | $buf .= chr($len - 26 + ord('a') - 1); | ||||
| } | } | ||||
| $buf .= self::encodeBase85($line); | $buf .= self::encodeBase85($line); | ||||
| $buf .= $eol; | $buf .= $eol; | ||||
| } | } | ||||
| return $buf; | return $buf; | ||||
| } | } | ||||
| public static function encodeBase85($data) { | private static function encodeBase85($data) { | ||||
| // This is implemented awkwardly in order to closely mirror git's | // This is implemented awkwardly in order to closely mirror git's | ||||
| // implementation in base85.c | // implementation in base85.c | ||||
| // It is also implemented awkwardly to work correctly on 32-bit machines. | // It is also implemented awkwardly to work correctly on 32-bit machines. | ||||
| // Broadly, this algorithm converts the binary input to printable output | // Broadly, this algorithm converts the binary input to printable output | ||||
| // by transforming each 4 binary bytes of input to 5 printable bytes of | // by transforming each 4 binary bytes of input to 5 printable bytes of | ||||
| // output, one piece at a time. | // output, one piece at a time. | ||||
| // | // | ||||
| ▲ Show 20 Lines • Show All 134 Lines • Show Last 20 Lines | |||||