Changeset View
Changeset View
Standalone View
Standalone View
src/parser/ArcanistBundle.php
Show All 9 Lines | final class ArcanistBundle extends Phobject { | ||||
private $blobs = array(); | private $blobs = array(); | ||||
private $diskPath; | private $diskPath; | ||||
private $baseRevision; | private $baseRevision; | ||||
private $revisionID; | private $revisionID; | ||||
private $encoding; | private $encoding; | ||||
private $loadFileDataCallback; | private $loadFileDataCallback; | ||||
private $authorName; | private $authorName; | ||||
private $authorEmail; | private $authorEmail; | ||||
private $subject; | |||||
private $dateString; | |||||
private $byteLimit; | private $byteLimit; | ||||
private $reservedBytes; | private $reservedBytes; | ||||
public function setAuthorEmail($author_email) { | public function setAuthorEmail($author_email) { | ||||
$this->authorEmail = $author_email; | $this->authorEmail = $author_email; | ||||
return $this; | return $this; | ||||
} | } | ||||
Show All 28 Lines | public function getFullAuthor() { | ||||
$address = new PhutilEmailAddress($full_author); | $address = new PhutilEmailAddress($full_author); | ||||
if (!$address->getDisplayName() || !$address->getAddress()) { | if (!$address->getDisplayName() || !$address->getAddress()) { | ||||
return null; | return null; | ||||
} | } | ||||
return $full_author; | return $full_author; | ||||
} | } | ||||
public function setSubject($subject) { | |||||
$this->subject = $subject; | |||||
return $this; | |||||
} | |||||
public function getSubject() { | |||||
return $this->subject; | |||||
} | |||||
public function setDateString($date_string) { | |||||
$this->dateString = $date_string; | |||||
return $this; | |||||
} | |||||
public function getDateString() { | |||||
return $this->dateString; | |||||
} | |||||
public function setConduit(ConduitClient $conduit) { | public function setConduit(ConduitClient $conduit) { | ||||
$this->conduit = $conduit; | $this->conduit = $conduit; | ||||
return $this; | return $this; | ||||
} | } | ||||
public function setBaseRevision($base_revision) { | public function setBaseRevision($base_revision) { | ||||
$this->baseRevision = $base_revision; | $this->baseRevision = $base_revision; | ||||
return $this; | return $this; | ||||
▲ Show 20 Lines • Show All 243 Lines • ▼ Show 20 Lines | final class ArcanistBundle extends Phobject { | ||||
public function toGitPatch() { | public function toGitPatch() { | ||||
$this->reservedBytes = 0; | $this->reservedBytes = 0; | ||||
$eol = $this->getEOL('git'); | $eol = $this->getEOL('git'); | ||||
$result = array(); | $result = array(); | ||||
$changes = $this->getChanges(); | $changes = $this->getChanges(); | ||||
$result[] = $this->buildGitPatchHeader(); | |||||
$binary_sources = array(); | $binary_sources = array(); | ||||
foreach ($changes as $change) { | foreach ($changes as $change) { | ||||
if (!$this->isGitBinaryChange($change)) { | if (!$this->isGitBinaryChange($change)) { | ||||
continue; | continue; | ||||
} | } | ||||
$type = $change->getType(); | $type = $change->getType(); | ||||
if ($type == ArcanistDiffChangeType::TYPE_MOVE_AWAY || | if ($type == ArcanistDiffChangeType::TYPE_MOVE_AWAY || | ||||
▲ Show 20 Lines • Show All 150 Lines • ▼ Show 20 Lines | foreach ($changes as $change) { | ||||
$result[] = $change_body; | $result[] = $change_body; | ||||
} | } | ||||
} | } | ||||
$diff = implode('', $result).$eol; | $diff = implode('', $result).$eol; | ||||
return $this->convertNonUTF8Diff($diff); | return $this->convertNonUTF8Diff($diff); | ||||
} | } | ||||
private function buildGitPatchHeader() { | |||||
$header = array(); | |||||
// Not using pht() here, because this is is read by a machine (git am). | |||||
if ($this->getFullAuthor() !== null) { | |||||
$header[] = 'From: '.$this->getFullAuthor(); | |||||
} | |||||
if (phutil_nonempty_string($this->getDateString())) { | |||||
$header[] = 'Date: '.$this->getDateString(); | |||||
} | |||||
if (phutil_nonempty_string($this->getSubject())) { | |||||
$header[] = 'Subject: '.$this->getSubject(); | |||||
} | |||||
if (!$header) { | |||||
return null; | |||||
} | |||||
$eol = $this->getEOL('git'); | |||||
foreach ($header as $i => $value) { | |||||
// minimal sanitation | |||||
$header[$i] = str_replace($eol, ' ', $value); | |||||
} | |||||
$header[] = $eol; | |||||
return implode($eol, $header); | |||||
} | |||||
private function isGitBinaryChange(ArcanistDiffChange $change) { | private function isGitBinaryChange(ArcanistDiffChange $change) { | ||||
$file_type = $change->getFileType(); | $file_type = $change->getFileType(); | ||||
return ($file_type == ArcanistDiffChangeType::FILE_BINARY || | return ($file_type == ArcanistDiffChangeType::FILE_BINARY || | ||||
$file_type == ArcanistDiffChangeType::FILE_IMAGE); | $file_type == ArcanistDiffChangeType::FILE_IMAGE); | ||||
} | } | ||||
private function convertNonUTF8Diff($diff) { | private function convertNonUTF8Diff($diff) { | ||||
if ($this->encoding) { | if ($this->encoding) { | ||||
▲ Show 20 Lines • Show All 262 Lines • ▼ Show 20 Lines | if ($old_binary) { | ||||
$old_phid = $change->getMetadata('old:binary-phid'); | $old_phid = $change->getMetadata('old:binary-phid'); | ||||
} | } | ||||
if ($old_data === null && $old_phid) { | if ($old_data === null && $old_phid) { | ||||
$name = basename($change->getOldPath()); | $name = basename($change->getOldPath()); | ||||
$old_data = $this->getBlob($old_phid, $name); | $old_data = $this->getBlob($old_phid, $name); | ||||
} | } | ||||
if ($old_data === null) { | |||||
$old_length = 0; | |||||
$old_data = ''; | |||||
$old_sha1 = str_repeat('0', 40); | |||||
} else { | |||||
$old_length = strlen($old_data); | $old_length = strlen($old_data); | ||||
// Here, and below, the binary will be emitted with base85 encoding. This | // 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 | // 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. | // need up to 5/4ths as many bytes to represent it. | ||||
// We reserve space up front because base85 encoding isn't super cheap. If | // 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 | // the blob is enormous, we'd rather just bail out now before doing a ton | ||||
// of work and then throwing it away anyway. | // of work and then throwing it away anyway. | ||||
// However, the data is compressed before it is emitted so we may actually | // 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 | // 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 | // case since it isn't important to be precise, but we could do a more | ||||
// exact job of this. | // exact job of this. | ||||
$this->reserveBytes($old_length * 5 / 4); | $this->reserveBytes($old_length * 5 / 4); | ||||
if ($old_data === null) { | |||||
$old_data = ''; | |||||
$old_sha1 = str_repeat('0', 40); | |||||
} else { | |||||
$old_sha1 = sha1("blob {$old_length}\0{$old_data}"); | $old_sha1 = sha1("blob {$old_length}\0{$old_data}"); | ||||
} | } | ||||
$new_phid = $change->getMetadata('new:binary-phid'); | $new_phid = $change->getMetadata('new:binary-phid'); | ||||
$new_data = null; | $new_data = null; | ||||
if ($change->getCurrentFileData() !== null) { | if ($change->getCurrentFileData() !== null) { | ||||
$new_data = $change->getCurrentFileData(); | $new_data = $change->getCurrentFileData(); | ||||
} else if ($new_phid) { | } else if ($new_phid) { | ||||
$name = basename($change->getCurrentPath()); | $name = basename($change->getCurrentPath()); | ||||
$new_data = $this->getBlob($new_phid, $name); | $new_data = $this->getBlob($new_phid, $name); | ||||
} | } | ||||
$new_length = strlen($new_data); | |||||
$this->reserveBytes($new_length * 5 / 4); | |||||
if ($new_data === null) { | if ($new_data === null) { | ||||
$new_length = 0; | |||||
$new_data = ''; | $new_data = ''; | ||||
$new_sha1 = str_repeat('0', 40); | $new_sha1 = str_repeat('0', 40); | ||||
} else { | } else { | ||||
$new_length = strlen($new_data); | |||||
$this->reserveBytes($new_length * 5 / 4); | |||||
$new_sha1 = sha1("blob {$new_length}\0{$new_data}"); | $new_sha1 = sha1("blob {$new_length}\0{$new_data}"); | ||||
} | } | ||||
$content = array(); | $content = array(); | ||||
$content[] = "index {$old_sha1}..{$new_sha1}".$eol; | $content[] = "index {$old_sha1}..{$new_sha1}".$eol; | ||||
$content[] = 'GIT binary patch'.$eol; | $content[] = 'GIT binary patch'.$eol; | ||||
$content[] = "literal {$new_length}".$eol; | $content[] = "literal {$new_length}".$eol; | ||||
▲ Show 20 Lines • Show All 250 Lines • Show Last 20 Lines |
Content licensed under Creative Commons Attribution-ShareAlike 4.0 (CC-BY-SA) unless otherwise noted; code licensed under Apache 2.0 or other open source licenses. · CC BY-SA 4.0 · Apache 2.0