Page MenuHomePhabricator

D19444.diff
No OneTemporary

D19444.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -106,6 +106,7 @@
'ArcanistDefaultParametersXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistDefaultParametersXHPASTLinterRuleTestCase.php',
'ArcanistDeprecationXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistDeprecationXHPASTLinterRule.php',
'ArcanistDeprecationXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistDeprecationXHPASTLinterRuleTestCase.php',
+ 'ArcanistDiffByteSizeException' => 'exception/ArcanistDiffByteSizeException.php',
'ArcanistDiffChange' => 'parser/diff/ArcanistDiffChange.php',
'ArcanistDiffChangeType' => 'parser/diff/ArcanistDiffChangeType.php',
'ArcanistDiffHunk' => 'parser/diff/ArcanistDiffHunk.php',
@@ -525,6 +526,7 @@
'ArcanistDefaultParametersXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistDeprecationXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistDeprecationXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
+ 'ArcanistDiffByteSizeException' => 'Exception',
'ArcanistDiffChange' => 'Phobject',
'ArcanistDiffChangeType' => 'Phobject',
'ArcanistDiffHunk' => 'Phobject',
diff --git a/src/exception/ArcanistDiffByteSizeException.php b/src/exception/ArcanistDiffByteSizeException.php
new file mode 100644
--- /dev/null
+++ b/src/exception/ArcanistDiffByteSizeException.php
@@ -0,0 +1,3 @@
+<?php
+
+final class ArcanistDiffByteSizeException extends Exception {}
diff --git a/src/parser/ArcanistBundle.php b/src/parser/ArcanistBundle.php
--- a/src/parser/ArcanistBundle.php
+++ b/src/parser/ArcanistBundle.php
@@ -15,6 +15,8 @@
private $loadFileDataCallback;
private $authorName;
private $authorEmail;
+ private $byteLimit;
+ private $reservedBytes;
public function setAuthorEmail($author_email) {
$this->authorEmail = $author_email;
@@ -76,6 +78,15 @@
return $this->encoding;
}
+ public function setByteLimit($byte_limit) {
+ $this->byteLimit = $byte_limit;
+ return $this;
+ }
+
+ public function getByteLimit() {
+ return $this->byteLimit;
+ }
+
public function getBaseRevision() {
return $this->baseRevision;
}
@@ -241,12 +252,13 @@
}
public function toUnifiedDiff() {
+ $this->reservedBytes = 0;
+
$eol = $this->getEOL('unified');
$result = array();
$changes = $this->getChanges();
foreach ($changes as $change) {
-
$hunk_changes = $this->buildHunkChanges($change->getHunks(), $eol);
if (!$hunk_changes) {
continue;
@@ -299,6 +311,8 @@
}
public function toGitPatch() {
+ $this->reservedBytes = 0;
+
$eol = $this->getEOL('git');
$result = array();
@@ -649,6 +663,8 @@
$n_len = $small_hunk->getNewLength();
$corpus = $small_hunk->getCorpus();
+ $this->reserveBytes(strlen($corpus));
+
// NOTE: If the length is 1 it can be omitted. Since git does this,
// we also do it so that "arc export --git" diffs are as similar to
// real git diffs as possible, which helps debug issues.
@@ -740,6 +756,20 @@
$old_length = strlen($old_data);
+ // Here, and below, the binary will be emitted with base85 encoding. This
+ // encoding encodes each 4 bytes of input in 5 bytes of output, so we may
+ // need up to 5/4ths as many bytes to represent it.
+
+ // We reserve space up front because base85 encoding isn't super cheap. If
+ // the blob is enormous, we'd rather just bail out now before doing a ton
+ // of work and then throwing it away anyway.
+
+ // However, the data is compressed before it is emitted so we may actually
+ // end up using fewer bytes. For now, the allocator just assumes the worst
+ // case since it isn't important to be precise, but we could do a more
+ // exact job of this.
+ $this->reserveBytes($old_length * 5 / 4);
+
if ($old_data === null) {
$old_data = '';
$old_sha1 = str_repeat('0', 40);
@@ -758,6 +788,7 @@
}
$new_length = strlen($new_data);
+ $this->reserveBytes($new_length * 5 / 4);
if ($new_data === null) {
$new_data = '';
@@ -1003,4 +1034,21 @@
return $buf;
}
+ private function reserveBytes($bytes) {
+ $this->reservedBytes += $bytes;
+
+ if ($this->byteLimit) {
+ if ($this->reservedBytes > $this->byteLimit) {
+ throw new ArcanistDiffByteSizeException(
+ pht(
+ 'This large diff requires more space than it is allowed to '.
+ 'use (limited to %s bytes; needs more than %s bytes).',
+ new PhutilNumber($this->byteLimit),
+ new PhutilNumber($this->reservedBytes)));
+ }
+ }
+
+ return $this;
+ }
+
}

File Metadata

Mime Type
text/plain
Expires
Fri, Jan 10, 3:06 AM (4 h, 39 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6981367
Default Alt Text
D19444.diff (4 KB)

Event Timeline