/** * Extracts an object from the pack * * @param string $hash hash of object to extract * @param int $type output parameter, returns the type of the object * @return string|boolean object content, or false if not found */ public function GetObject($hash, &$type = 0) { if (!preg_match('/[0-9a-fA-F]{40}/', $hash)) { return false; } if (!$this->packIndex->Valid()) { throw new Exception('Invalid pack index'); } if (!$this->packData->Valid()) { throw new Exception('Unsupported pack file format'); } $offset = $this->packIndex->FindPackedObject($hash); if ($offset === false) { return false; } return $this->packData->GetObject($offset, $type); }
/** * Applies a binary delta to a base object * * @param string $delta delta string * @param string $base base object data * @return string patched content */ private static function ApplyDelta($delta, $base) { /* * algorithm from patch-delta.c */ $pos = 0; GitPHP_PackData::ParseVarInt($delta, $pos); // base size GitPHP_PackData::ParseVarInt($delta, $pos); // result size $data = ''; $deltalen = strlen($delta); while ($pos < $deltalen) { $opcode = ord($delta[$pos++]); if ($opcode & 0x80) { $off = 0; if ($opcode & 0x1) { $off = ord($delta[$pos++]); } if ($opcode & 0x2) { $off |= ord($delta[$pos++]) << 8; } if ($opcode & 0x4) { $off |= ord($delta[$pos++]) << 16; } if ($opcode & 0x8) { $off |= ord($delta[$pos++]) << 24; } $len = 0; if ($opcode & 0x10) { $len = ord($delta[$pos++]); } if ($opcode & 0x20) { $len |= ord($delta[$pos++]) << 8; } if ($opcode & 0x40) { $len |= ord($delta[$pos++]) << 16; } if ($len == 0) { $len = 0x10000; } $data .= mb_orig_substr($base, $off, $len); } else { if ($opcode > 0) { $data .= mb_orig_substr($delta, $pos, $opcode); $pos += $opcode; } } } return $data; }