diff --git a/3rdparty/granite/git/blob.php b/3rdparty/granite/git/blob.php deleted file mode 100644 index 781a697d56..0000000000 --- a/3rdparty/granite/git/blob.php +++ /dev/null @@ -1,162 +0,0 @@ - - * @license http://www.opensource.org/licenses/mit-license.php MIT Expat License - * @link http://craig0990.github.com/Granite/ - */ - -namespace Granite\Git; -use \Granite\Git\Object\Raw as Raw; -use \InvalidArgumentException as InvalidArgumentException; -use \finfo as finfo; -/** - * **Granite\Git\Blob** represents the raw content of an object in a Git repository, - * typically a **file**. This class provides methods related to the handling of - * blob content, mimetypes, sizes and write support. - * - * @category Git - * @package Granite - * @author Craig Roberts - * @license http://www.opensource.org/licenses/mit-license.php MIT Expat License - * @link http://craig0990.github.com/Granite/ - */ -class Blob -{ - - /** - * Stores the SHA-1 id of the object requested; accessed through the `sha()` - * method where it is recalculated based on the blob content. - */ - private $sha = null; - /** - * The raw binary string of the file contents. - */ - private $content = ""; - /** - * The path to the repository location. - */ - private $path; - - /** - * Fetches a raw Git object and parses the result. Throws an - * InvalidArgumentException if the object is not of the correct type, - * or cannot be found. - * - * @param string $path The path to the repository root. - * @param string $sha The SHA-1 id of the requested object, or `null` if - * creating a new blob object. - * - * @throws InvalidArgumentException If the SHA-1 id provided is not a blob. - */ - public function __construct($path, $sha = NULL) - { - $this->path = $path; - if ($sha !== NULL) { - $this->sha = $sha; - $object = Raw::factory($path, $sha); - - if ($object->type() !== Raw::OBJ_BLOB) { - throw new InvalidArgumentException( - "The object $sha is not a blob, type is {$object->type()}" - ); - } - - $this->content = $object->content(); - unset($object); - } - } - - /** - * Sets or returns the raw file content, depending whether the parameter is - * provided. - * - * @param string $content The object content to set, or `null` if requesting the - * current content. - * - * @return string The raw binary string of the file contents. - */ - public function content($content = NULL) - { - if ($content == NULL) { - return $this->content; - } - $this->content = $content; - } - - /** - * Returns the size of the file content in bytes, equivalent to - * `strlen($blob->content())`. - * - * @return int The size of the object in bytes. - */ - public function size() - { - return strlen($this->content); - } - - /** - * Updates and returns the SHA-1 id of the object, based on it's contents. - * - * @return int The SHA-1 id of the object. - */ - public function sha() - { - $sha = hash_init('sha1'); - $header = 'blob ' . strlen($this->content) . "\0"; - hash_update($sha, $header); - hash_update($sha, $this->content); - $this->sha = hash_final($sha); - return $this->sha; - } - - /** - * Returns the mimetype of the object, using `finfo()` to determine the mimetype - * of the string. - * - * @return string The object mimetype. - * @see http://php.net/manual/en/function.finfo-open.php - */ - public function mimetype() - { - $finfo = new finfo(FILEINFO_MIME); - return $finfo->buffer($this->content); - } - - /** - * Encode and compress the object content, saving it to a 'loose' file. - * - * @return boolean True on success, false on failure. - */ - public function write() - { - $sha = $this->sha(TRUE); - $path = $this->path - . 'objects' - . DIRECTORY_SEPARATOR - . substr($sha, 0, 2) - . DIRECTORY_SEPARATOR - . substr($sha, 2); - // FIXME: currently writes loose objects only - if (file_exists($path)) { - return FALSE; - } - - if (!is_dir(dirname($path))) { - mkdir(dirname($path), 0777, TRUE); - } - - $loose = fopen($path, 'wb'); - $data = 'blob ' . strlen($this->content) . "\0" . $this->content; - $write = fwrite($loose, gzcompress($data)); - fclose($loose); - - return ($write !== FALSE); - } - -} diff --git a/3rdparty/granite/git/commit.php b/3rdparty/granite/git/commit.php deleted file mode 100644 index 51077e89f3..0000000000 --- a/3rdparty/granite/git/commit.php +++ /dev/null @@ -1,232 +0,0 @@ - - * @license http://www.opensource.org/licenses/mit-license.php MIT Expat License - * @link http://craig0990.github.com/Granite/ - */ - -namespace Granite\Git; -use \Granite\Git\Object\Raw as Raw; -use \InvalidArgumentException as InvalidArgumentException; - -/** - * Commit represents a full commit object - * - * @category Git - * @package Granite - * @author Craig Roberts - * @license http://www.opensource.org/licenses/mit-license.php MIT Expat License - * @link http://craig0990.github.com/Granite/ - */ -class Commit -{ - - /** - * The path to the repository root - */ - private $path; - /** - * The SHA-1 id of the requested commit - */ - private $sha; - /** - * The size of the commit in bytes - */ - private $size; - /** - * The commit message - */ - private $message; - /** - * The full committer string - */ - private $committer; - /** - * The full author string - */ - private $author; - /** - * The SHA-1 ids of the parent commits - */ - private $parents = array(); - - /** - * Fetches a raw Git object and parses the result. Throws an - * InvalidArgumentException if the object is not of the correct type, - * or cannot be found. - * - * @param string $path The path to the repository root - * @param string $sha The SHA-1 id of the requested object - * - * @throws InvalidArgumentException - */ - public function __construct($path, $sha = NULL) - { - $this->path = $path; - if ($sha !== NULL) { - $this->sha = $sha; - $object = Raw::factory($path, $sha); - $this->size = $object->size(); - - if ($object->type() !== Raw::OBJ_COMMIT) { - throw new InvalidArgumentException( - "The object $sha is not a commit, type is " . $object->type() - ); - } - - // Parse headers and commit message (delimited with "\n\n") - list($headers, $this->message) = explode("\n\n", $object->content(), 2); - $headers = explode("\n", $headers); - - foreach ($headers as $header) { - list($header, $value) = explode(' ', $header, 2); - if ($header == 'parent') { - $this->parents[] = $value; - } else { - $this->$header = $value; - } - } - - $this->tree = new Tree($this->path, $this->tree); - } - } - - /** - * Returns the message stored in the commit - * - * @return string The commit message - */ - public function message($message = NULL) - { - if ($message !== NULL) { - $this->message = $message; - return $this; - } - return $this->message; - } - - /** - * Returns the commiter string - * - * @return string The committer string - */ - public function committer($committer = NULL) - { - if ($committer !== NULL) { - $this->committer = $committer; - return $this; - } - return $this->committer; - } - - /** - * Returns the author string - * - * @return string The author string - */ - public function author($author = NULL) - { - if ($author !== NULL) { - $this->author = $author; - return $this; - } - return $this->author; - } - - /** - * Returns the parents of the commit, or an empty array if none - * - * @return array The parents of the commit - */ - public function parents($parents = NULL) - { - if ($parents !== NULL) { - $this->parents = $parents; - return $this; - } - return $this->parents; - } - - /** - * Returns a tree object associated with the commit - * - * @return Tree - */ - public function tree(Tree $tree = NULL) - { - if ($tree !== NULL) { - $this->tree = $tree; - return $this; - } - return $this->tree; - } - - /** - * Returns the size of the commit in bytes (Git header + data) - * - * @return int - */ - public function size() - { - return $this->size; - } - - /** - * Returns the size of the commit in bytes (Git header + data) - * - * @return int - */ - public function sha() - { - $this->sha = hash('sha1', $this->_raw()); - return $this->sha; - } - - public function write() - { - $sha = $this->sha(); - $path = $this->path - . 'objects' - . DIRECTORY_SEPARATOR - . substr($sha, 0, 2) - . DIRECTORY_SEPARATOR - . substr($sha, 2); - // FIXME: currently writes loose objects only - if (file_exists($path)) { - return FALSE; - } - - if (!is_dir(dirname($path))) { - mkdir(dirname($path), 0777, TRUE); - } - - $loose = fopen($path, 'wb'); - $data = $this->_raw(); - $write = fwrite($loose, gzcompress($data)); - fclose($loose); - - return ($write !== FALSE); - } - - public function _raw() - { - $data = 'tree ' . $this->tree->sha() . "\n"; - foreach ($this->parents as $parent) - { - $data .= "parent $parent\n"; - } - $data .= 'author ' . $this->author . "\n"; - $data .= 'committer ' . $this->committer . "\n\n"; - $data .= $this->message; - - $data = 'commit ' . strlen($data) . "\0" . $data; - return $data; - } - -} diff --git a/3rdparty/granite/git/object/index.php b/3rdparty/granite/git/object/index.php deleted file mode 100644 index 239706d4ef..0000000000 --- a/3rdparty/granite/git/object/index.php +++ /dev/null @@ -1,210 +0,0 @@ - - * @license http://www.opensource.org/licenses/mit-license.php MIT License - * @link http://craig0990.github.com/Granite/ - */ - -namespace Granite\Git\Object; -use \UnexpectedValueException as UnexpectedValueException; - -/** - * Index represents a packfile index - * - * @category Git - * @package Granite - * @author Craig Roberts - * @license http://www.opensource.org/licenses/mit-license.php MIT License - * @link http://craig0990.github.com/Granite/ - */ -class Index -{ - const INDEX_MAGIC = "\377tOc"; - - /** - * The full path to the packfile index - */ - private $path; - /** - * The offset at which the fanout begins, version 2+ indexes have a 2-byte header - */ - private $offset = 8; - /** - * The size of the SHA-1 entries, version 1 stores 4-byte offsets alongside to - * total 24 bytes, version 2+ stores offsets separately - */ - private $size = 20; - /** - * The version of the index file format, versions 1 and 2 are in use and - * currently supported - */ - private $version; - - /** - * Fetches a raw Git object and parses the result - * - * @param string $path The path to the repository root - * @param string $packname The name of the packfile index to read - */ - public function __construct($path, $packname) - { - $this->path = $path - . 'objects' - . DIRECTORY_SEPARATOR - . 'pack' - . DIRECTORY_SEPARATOR - . 'pack-' . $packname . '.idx'; - - $this->version = $this->_readVersion(); - if ($this->version !== 1 && $this->version !== 2) { - throw new UnexpectedValueException( - "Unsupported index version (version $version)" - ); - } - - if ($this->version == 1) { - $this->offset = 0; // Version 1 index has no header/version - $this->size = 24; // Offsets + SHA-1 ids are stored together - } - } - - /** - * Returns the offset of the object stored in the index - * - * @param string $sha The SHA-1 id of the object being requested - * - * @return int The offset of the object in the packfile - */ - public function find($sha) - { - $index = fopen($this->path, 'rb'); - $offset = false; // Offset for object in packfile not found by default - - // Read the fanout to skip to the start char in the sorted SHA-1 list - list($start, $after) = $this->_readFanout($index, $sha); - - if ($start == $after) { - fclose($index); - return false; // Object is apparently located in a 0-length section - } - - // Seek $offset + 255 4-byte fanout entries and read 256th entry - fseek($index, $this->offset + 4 * 255); - $totalObjects = $this->_uint32($index); - - // Look up the SHA-1 id of the object - // TODO: Binary search - fseek($index, $this->offset + 1024 + $this->size * $start); - for ($i = $start; $i < $after; $i++) { - if ($this->version == 1) { - $offset = $this->_uint32($index); - } - - $name = fread($index, 20); - if ($name == pack('H40', $sha)) { - break; // Found it - } - } - - if ($i == $after) { - fclose($index); - return false; // Scanned entire section, couldn't find it - } - - if ($this->version == 2) { - // Jump to the offset location and read it - fseek($index, 1032 + 24 * $totalObjects + 4 * $i); - $offset = $this->_uint32($index); - if ($offset & 0x80000000) { - // Offset is a 64-bit integer; packfile is larger than 2GB - fclose($index); - throw new UnexpectedValueException( - "Packfile larger than 2GB, currently unsupported" - ); - } - } - - fclose($index); - return $offset; - } - - /** - * Converts a binary string into a 32-bit unsigned integer - * - * @param handle $file Binary string to convert - * - * @return int Integer value - */ - private function _uint32($file) - { - $val = unpack('Nx', fread($file, 4)); - return $val['x']; - } - - /** - * Reads the fanout for a particular SHA-1 id - * - * Largely modified from Glip, with some reference to Grit - largely because I - * can't see how to re-implement this in PHP - * - * @param handle $file File handle to the index file - * @param string $sha The SHA-1 id to search for - * @param int $offset The offset at which the fanout begins - * - * @return array Array containing integer 'start' and - * 'past-the-end' locations - */ - private function _readFanout($file, $sha) - { - $sha = pack('H40', $sha); - fseek($file, $this->offset); - if ($sha{0} == "\00") { - /** - * First character is 0, read first fanout entry to provide - * 'past-the-end' location (since first fanout entry provides start - * point for '1'-prefixed SHA-1 ids) - */ - $start = 0; - fseek($file, $this->offset); // Jump to start of fanout, $offset bytes in - $after = $this->_uint32($file); - } else { - /** - * Take ASCII value of first character, minus one to get the fanout - * position of the offset (minus one because the fanout does not - * contain an entry for "\00"), multiplied by four bytes per entry - */ - fseek($file, $this->offset + (ord($sha{0}) - 1) * 4); - $start = $this->_uint32($file); - $after = $this->_uint32($file); - } - - return array($start, $after); - } - - /** - * Returns the version number of the index file, or 1 if there is no version - * information - * - * @return int - */ - private function _readVersion() - { - $file = fopen($this->path, 'rb'); - $magic = fread($file, 4); - $version = $this->_uint32($file); - - if ($magic !== self::INDEX_MAGIC) { - $version = 1; - } - - fclose($file); - return $version; - } - -} diff --git a/3rdparty/granite/git/object/loose.php b/3rdparty/granite/git/object/loose.php deleted file mode 100644 index 32f894845b..0000000000 --- a/3rdparty/granite/git/object/loose.php +++ /dev/null @@ -1,81 +0,0 @@ - - * @license http://www.opensource.org/licenses/mit-license.php MIT Expat License - * @link http://craig0990.github.com/Granite/ - */ - -namespace Granite\Git\Object; -use \UnexpectedValueException as UnexpectedValueException; - -/** - * Loose represents a loose object in the Git repository - * - * @category Git - * @package Granite - * @author Craig Roberts - * @license http://www.opensource.org/licenses/mit-license.php MIT Expat License - * @link http://craig0990.github.com/Granite/ - */ -class Loose extends Raw -{ - - /** - * Reads an object from a loose object file based on the SHA-1 id - * - * @param string $path The path to the repository root - * @param string $sha The SHA-1 id of the requested object - * - * @throws UnexpectedValueException If the type is not 'commit', 'tree', - * 'tag' or 'blob' - */ - public function __construct($path, $sha) - { - $this->sha = $sha; - - $loose_path = $path - . 'objects/' - . substr($sha, 0, 2) - . '/' - . substr($sha, 2); - - if (!file_exists($loose_path)) { - throw new InvalidArgumentException("Cannot open loose object file for $sha"); - } - - $raw = gzuncompress(file_get_contents($loose_path)); - $data = explode("\0", $raw, 2); - - $header = $data[0]; - $this->content = $data[1]; - - list($this->type, $this->size) = explode(' ', $header); - - switch ($this->type) { - case 'commit': - $this->type = Raw::OBJ_COMMIT; - break; - case 'tree': - $this->type = Raw::OBJ_TREE; - break; - case 'blob': - $this->type = Raw::OBJ_BLOB; - break; - case 'tag': - $this->type = Raw::OBJ_TAG; - break; - default: - throw new UnexpectedValueException( - "Unexpected type '{$this->type}'" - ); - break; - } - } - -} diff --git a/3rdparty/granite/git/object/packed.php b/3rdparty/granite/git/object/packed.php deleted file mode 100644 index 7e8d663b32..0000000000 --- a/3rdparty/granite/git/object/packed.php +++ /dev/null @@ -1,304 +0,0 @@ - - * @license http://www.opensource.org/licenses/mit-license.php MIT Expat License - * @link http://craig0990.github.com/Granite/ - */ - -namespace Granite\Git\Object; -use \UnexpectedValueException as UnexpectedValueException; - -/** - * Packed represents a packed object in the Git repository - * - * @category Git - * @package Granite - * @author Craig Roberts - * @license http://www.opensource.org/licenses/mit-license.php MIT Expat License - * @link http://craig0990.github.com/Granite/ - */ -class Packed extends Raw -{ - - /** - * The name of the packfile being read - */ - private $_packfile; - - /** - * Added to the object size to make a 'best-guess' effort at how much compressed - * data to read - should be reimplemented, ideally with streams. - */ - const OBJ_PADDING = 512; - - /** - * Reads the object data from the compressed data at $offset in $packfile - * - * @param string $packfile The path to the packfile - * @param int $offset The offset of the object data - */ - public function __construct($packfile, $offset) - { - $this->_packfile = $packfile; - - list($this->type, $this->size, $this->content) - = $this->_readPackedObject($offset); - } - - /** - * Reads the object data at $this->_offset - * - * @param int $offset Offset of the object header - * - * @return array Containing the type, size and object data - */ - private function _readPackedObject($offset) - { - $file = fopen($this->_packfile, 'rb'); - fseek($file, $offset); - // Read the type and uncompressed size from the object header - list($type, $size) = $this->_readHeader($file, $offset); - $object_offset = ftell($file); - - if ($type == self::OBJ_OFS_DELTA || $type == self::OBJ_REF_DELTA) { - return $this->_unpackDeltified( - $file, $offset, $object_offset, $type, $size - ); - } - - $content = gzuncompress(fread($file, $size + self::OBJ_PADDING), $size); - - return array($type, $size, $content); - } - - /** - * Reads a packed object header, returning the type and the size. For more - * detailed information, refer to the @see tag. - * - * From the @see tag: "Each byte is really 7 bits of data, with the first bit - * being used to say if that hunk is the last one or not before the data starts. - * If the first bit is a 1, you will read another byte, otherwise the data starts - * next. The first 3 bits in the first byte specifies the type of data..." - * - * @param handle $file File handle to read - * @param int $offset Offset of the object header - * - * @return array Containing the type and the size - * @see http://book.git-scm.com/7_the_packfile.html - */ - private function _readHeader($file, $offset) - { - // Read the object header byte-by-byte - fseek($file, $offset); - $byte = ord(fgetc($file)); - /** - * Bit-shift right by four, then ignore the first bit with a bitwise AND - * This gives us the object type in binary: - * 001 commit self::OBJ_COMMIT - * 010 tree self::OBJ_TREE - * 011 blob self::OBJ_BLOB - * 100 tag self::OBJ_TAG - * 110 offset delta self::OBJ_OFS_DELTA - * 111 ref delta self::OBJ_REF_DELTA - * - * (000 is undefined, 101 is not currently in use) - * See http://book.git-scm.com/7_the_packfile.html for details - */ - $type = ($byte >> 4) & 0x07; - - // Read the last four bits of the first byte, used to find the size - $size = $byte & 0x0F; - - /** - * $shift initially set to four, since we use the last four bits of the first - * byte - * - * $byte & 0x80 checks the initial bit is set to 1 (i.e. keep reading data) - * - * Finally, $shift is incremented by seven for each consecutive byte (because - * we ignore the initial bit) - */ - for ($shift = 4; $byte & 0x80; $shift += 7) { - $byte = ord(fgetc($file)); - /** - * The size is ANDed against 0x7F to strip the initial bit, then - * bitshifted by left $shift (4 or 7, depending on whether it's the - * initial byte) and ORed against the existing binary $size. This - * continuously increments the $size variable. - */ - $size |= (($byte & 0x7F) << $shift); - } - - return array($type, $size); - } - - /** - * Unpacks a deltified object located at $offset in $file - * - * @param handle $file File handle to read - * @param int $offset Offset of the object data - * @param int $object_offset Offset of the object data, past the header - * @param int $type The object type, either OBJ_REF_DELTA - or OBJ_OFS_DELTA - * @param int $size The expected size of the uncompressed data - * - * @return array Containing the type, size and object data - */ - private function _unpackDeltified($file, $offset, $object_offset, $type, $size) - { - fseek($file, $object_offset); - - if ($type == self::OBJ_REF_DELTA) { - - $base_sha = bin2hex(fread($file, 20)); - - $path = substr($this->_packfile, 0, strpos($this->_packfile, '.git')+5); - $base = Raw::factory($path, $base_sha); - $type = $base->type(); - $base = $base->content(); - - $delta = gzuncompress( - fread($file, $size + self::OBJ_PADDING), $size - ); - - $content = $this->_applyDelta($base, $delta); - - } elseif ($type == self::OBJ_OFS_DELTA) { - - // 20 = maximum varint size according to Glip - $data = fread($file, $size + self::OBJ_PADDING + 20); - - list($base_offset, $length) = $this->_bigEndianNumber($data); - - $delta = gzuncompress(substr($data, $length), $size); - unset($data); - - $base_offset = $offset - $base_offset; - list($type, $size, $base) = $this->_readPackedObject($base_offset); - - $content = $this->_applyDelta($base, $delta); - - } else { - throw new UnexpectedValueException( - "Unknown type $type for deltified object" - ); - } - - return array($type, strlen($content), $content); - } - - /** - * Applies the $delta byte-sequence to $base and returns the - * resultant binary string. - * - * This code is modified from Grit (see below), the Ruby - * implementation used for GitHub under an MIT license. - * - * @param string $base The base string for the delta to be applied to - * @param string $delta The delta string to apply - * - * @return string The patched binary string - * @see - * https://github.com/mojombo/grit/blob/master/lib/grit/git-ruby/internal/pack.rb - */ - private function _applyDelta($base, $delta) - { - $pos = 0; - $src_size = $this->_varint($delta, $pos); - $dst_size = $this->_varint($delta, $pos); - - if ($src_size !== strlen($base)) { - throw new UnexpectedValueException( - 'Expected base delta size ' . strlen($base) . ' does not match the expected ' - . "value $src_size" - ); - } - - $dest = ""; - while ($pos < strlen($delta)) { - $byte = ord($delta{$pos++}); - - if ($byte & 0x80) { - /* copy a part of $base */ - $offset = 0; - if ($byte & 0x01) $offset = ord($delta{$pos++}); - if ($byte & 0x02) $offset |= ord($delta{$pos++}) << 8; - if ($byte & 0x04) $offset |= ord($delta{$pos++}) << 16; - if ($byte & 0x08) $offset |= ord($delta{$pos++}) << 24; - $length = 0; - if ($byte & 0x10) $length = ord($delta{$pos++}); - if ($byte & 0x20) $length |= ord($delta{$pos++}) << 8; - if ($byte & 0x40) $length |= ord($delta{$pos++}) << 16; - if ($length == 0) $length = 0x10000; - $dest .= substr($base, $offset, $length); - } else { - /* take the next $byte bytes as they are */ - $dest .= substr($delta, $pos, $byte); - $pos += $byte; - } - } - - if (strlen($dest) !== $dst_size) { - throw new UnexpectedValueException( - "Deltified string expected to be $dst_size bytes, but actually " - . strlen($dest) . ' bytes' - ); - } - - return $dest; - } - - /** - * Parse a Git varint (variable-length integer). Used in the `_applyDelta()` - * method to read the delta header. - * - * @param string $string The string to parse - * @param int &$pos The position in the string to read from - * - * @return int The integer value - */ - private function _varint($string, &$pos = 0) - { - $varint = 0; - $bitmask = 0x80; - for ($i = 0; $bitmask & 0x80; $i += 7) { - $bitmask = ord($string{$pos++}); - $varint |= (($bitmask & 0x7F) << $i); - } - return $varint; - } - - /** - * Decodes a big endian modified base 128 number (refer to @see tag); this only - * appears to be used in one place, the offset delta in packfiles. The offset - * is the number of bytes to seek back from the start of the delta object to find - * the base object. - * - * This code has been implemented using the C code given in the @see tag below. - * - * @param string &$data The data to read from and decode the number - * - * @return Array Containing the base offset (number of bytes to seek back) and - * the length to use when reading the delta - * @see http://git.rsbx.net/Documents/Git_Data_Formats.txt - */ - private function _bigEndianNumber(&$data) - { - $i = 0; - $byte = ord($data{$i++}); - $number = $byte & 0x7F; - while ($byte & 0x80) { - $byte = ord($data{$i++}); - $number = (($number + 1) << 7) | ($byte & 0x7F); - } - - return array($number, $i); - } - -} diff --git a/3rdparty/granite/git/object/raw.php b/3rdparty/granite/git/object/raw.php deleted file mode 100644 index 56f363c37b..0000000000 --- a/3rdparty/granite/git/object/raw.php +++ /dev/null @@ -1,153 +0,0 @@ - - * @license http://www.opensource.org/licenses/mit-license.php MIT Expat License - * @link http://craig0990.github.com/Granite/ - */ - -namespace Granite\Git\Object; -use \InvalidArgumentException as InvalidArgumentException; - -/** - * Raw represents a raw Git object, using Index to locate - * packed objects. - * - * @category Git - * @package Granite - * @author Craig Roberts - * @license http://www.opensource.org/licenses/mit-license.php MIT Expat License - * @link http://craig0990.github.com/Granite/ - */ -class Raw -{ - /** - * Integer values for Git objects - * @see http://book.git-scm.com/7_the_packfile.html - */ - const OBJ_COMMIT = 1; - const OBJ_TREE = 2; - const OBJ_BLOB = 3; - const OBJ_TAG = 4; - const OBJ_OFS_DELTA = 6; - const OBJ_REF_DELTA = 7; - - /** - * The SHA-1 id of the requested object - */ - protected $sha; - /** - * The type of the requested object (see class constants) - */ - protected $type; - /** - * The binary string content of the requested object - */ - protected $content; - - /** - * Returns an instance of a raw Git object - * - * @param string $path The path to the repository root - * @param string $sha The SHA-1 id of the requested object - * - * @return Packed|Loose - */ - public static function factory($path, $sha) - { - $loose_path = $path - . 'objects/' - . substr($sha, 0, 2) - . '/' - . substr($sha, 2); - if (file_exists($loose_path)) { - return new Loose($path, $sha); - } else { - return self::_findPackedObject($path, $sha); - } - } - - /** - * Returns the raw content of the Git object requested - * - * @return string Raw object content - */ - public function content() - { - return $this->content; - } - - /** - * Returns the size of the Git object - * - * @return int The size of the object in bytes - */ - public function size() - { - return strlen($this->content); - } - - /** - * Returns the type of the object as either commit, tag, blob or tree - * - * @return string The object type - */ - public function type() - { - return $this->type; - } - - /** - * Searches a packfile for the SHA id and reads the object from the packfile - * - * @param string $path The path to the repository - * @param string $sha The SHA-1 id of the object being requested - * - * @throws \InvalidArgumentException - * @return array An array containing the type, size and object data - */ - private static function _findPackedObject($path, $sha) - { - $packfiles = glob( - $path - . 'objects' - . DIRECTORY_SEPARATOR - . 'pack' - . DIRECTORY_SEPARATOR - . 'pack-*.pack' - ); - - $offset = false; - foreach ($packfiles as $packfile) { - $packname = substr(basename($packfile, '.pack'), 5); - $idx = new Index($path, $packname); - $offset = $idx->find($sha); - - if ($offset !== false) { - break; // Found it - } - } - - if ($offset == false) { - throw new InvalidArgumentException("Could not find packed object $sha"); - } - - $packname = $path - . 'objects' - . DIRECTORY_SEPARATOR - . 'pack' - . DIRECTORY_SEPARATOR - . 'pack-' . $packname . '.pack'; - $object = new Packed($packname, $offset); - - return $object; - } - -} - -?> diff --git a/3rdparty/granite/git/repository.php b/3rdparty/granite/git/repository.php deleted file mode 100644 index 30b58a39f5..0000000000 --- a/3rdparty/granite/git/repository.php +++ /dev/null @@ -1,293 +0,0 @@ - - * @license http://www.opensource.org/licenses/mit-license.php MIT Expat License - * @link http://craig0990.github.com/Granite/ - */ - -namespace Granite\Git; -use \InvalidArgumentException as InvalidArgumentException; -use \UnexpectedValueException as UnexpectedValueException; - -/** - * Repository represents a Git repository, providing a variety of methods for - * fetching objects from SHA-1 ids or the tip of a branch with `head()` - * - * @category Git - * @package Granite - * @author Craig Roberts - * @license http://www.opensource.org/licenses/mit-license.php MIT Expat License - * @link http://craig0990.github.com/Granite/ - */ -class Repository -{ - - /** - * The path to the repository root - */ - private $_path; - /** - * The indexed version of a commit, ready to write with `commit()` - */ - private $idx_commit; - /** - * The indexed version of a tree, modified to with `add()` and `remove()` - */ - private $idx_tree; - - /** - * Sets the repository path - * - * @param string $path The path to the repository root (i.e. /repo/.git/) - */ - public function __construct($path) - { - if (!is_dir($path)) { - throw new InvalidArgumentException("Unable to find directory $path"); - } elseif (!is_readable($path)) { - throw new InvalidArgumentException("Unable to read directory $path"); - } elseif (!is_dir($path . DIRECTORY_SEPARATOR . 'objects') - || !is_dir($path . DIRECTORY_SEPARATOR . 'refs') - ) { - throw new UnexpectedValueException( - "Invalid directory, could not find 'objects' or 'refs' in $path" - ); - } - - $this->_path = $path; - $this->idx_commit = $this->factory('commit'); - $this->idx_tree = $this->factory('tree'); - } - - /** - * Returns an object from the Repository of the given type, with the given - * SHA-1 id, or false if it cannot be found - * - * @param string $type The type (blob, commit, tag or tree) of object being - * requested - * @param string $sha The SHA-1 id of the object (or the name of a tag) - * - * @return Blob|Commit|Tag|Tree - */ - public function factory($type, $sha = null) - { - if (!in_array($type, array('blob', 'commit', 'tag', 'tree'))) { - throw new InvalidArgumentException("Invalid type: $type"); - } - - if ($type == 'tag') { - $sha = $this->_ref('tags' . DIRECTORY_SEPARATOR . $sha); - } - $type = 'Granite\\Git\\' . ucwords($type); - - return new $type($this->_path, $sha); - } - - /** - * Returns a Commit object representing the HEAD commit - * - * @param string $branch The branch name to lookup, defaults to 'master' - * - * @return Commit An object representing the HEAD commit - */ - public function head($branch = 'master', $value = NULL) - { - if ($value == NULL) - return $this->factory( - 'commit', $this->_ref('heads' . DIRECTORY_SEPARATOR . $branch) - ); - - file_put_contents( - $this->_path . DIRECTORY_SEPARATOR - . 'refs' . DIRECTORY_SEPARATOR - . 'heads' . DIRECTORY_SEPARATOR . 'master', - $value - ); - } - - /** - * Returns a string representing the repository's location, which may or may - * not be initialised - * - * @return string A string representing the repository's location - */ - public function path() - { - return $this->_path; - } - - /** - * Returns an array of the local branches under `refs/heads` - * - * @return array - */ - public function tags() - { - return $this->_refs('tags'); - } - - /** - * Returns an array of the local tags under `refs/tags` - * - * @return array - */ - public function branches() - { - return $this->_refs('heads'); - } - - private function _refs($type) - { - $dir = $this->_path . 'refs' . DIRECTORY_SEPARATOR . $type; - $refs = glob($dir . DIRECTORY_SEPARATOR . '*'); - foreach ($refs as &$ref) { - $ref = basename($ref); - } - return $refs; - } - - /** - * Initialises a Git repository - * - * @return boolean Returns true on success, false on error - */ - public static function init($path) - { - $path .= '/'; - if (!is_dir($path)) { - mkdir($path); - } elseif (is_dir($path . 'objects')) { - return false; - } - - mkdir($path . 'objects'); - mkdir($path . 'objects/info'); - mkdir($path . 'objects/pack'); - mkdir($path . 'refs'); - mkdir($path . 'refs/heads'); - mkdir($path . 'refs/tags'); - - file_put_contents($path . 'HEAD', 'ref: refs/heads/master'); - - return true; - } - - /** - * Writes the indexed commit to disk, with blobs added/removed via `add()` and - * `rm()` - * - * @param string $message The commit message - * @param string $author The author name - * - * @return boolean True on success, or false on failure - */ - public function commit($message, $author) - { - $user_string = $username . ' ' . time() . ' +0000'; - - try { - $parents = array($this->repo->head()->sha()); - } catch (InvalidArgumentException $e) { - $parents = array(); - } - - $this->idx_commit->message($message); - $this->idx_commit->author($user_string); - $this->idx_commit->committer($user_string); - $this->idx_commit->tree($this->idx_tree); - $commit->parents($parents); - - $this->idx_tree->write(); - $this->idx_commit->write(); - - $this->repo->head('master', $this->idx_commit->sha()); - - $this->idx_commit = $this->factory('commit'); - $this->idx_tree = $this->factory('tree'); - } - - /** - * Adds a file to the indexed commit, to be written to disk with `commit()` - * - * @param string $filename The filename to save it under - * @param Granite\Git\Blob $blob The raw blob object to add to the tree - */ - public function add($filename, Granite\Git\Blob $blob) - { - $blob->write(); - $nodes = $this->idx_tree->nodes(); - $nodes[$filename] = new Granite\Git\Tree\Node($filename, '100644', $blob->sha()); - $this->idx_tree->nodes($nodes); - } - - /** - * Removes a file from the indexed commit - */ - public function rm($filename) - { - $nodes = $this->idx_tree->nodes(); - unset($nodes[$filename]); - $this->idx_tree->nodes($nodes); - } - - /** - * Returns an SHA-1 id of the ref resource - * - * @param string $ref The ref name to lookup - * - * @return string An SHA-1 id of the ref resource - */ - private function _ref($ref) - { - // All refs are stored in `.git/refs` - $file = $this->_path . 'refs' . DIRECTORY_SEPARATOR . $ref; - - if (file_exists($file)) { - return trim(file_get_contents($file)); - } - - $sha = $this->_packedRef($ref); - - if ($sha == false) { - throw new InvalidArgumentException("The ref $ref could not be found"); - } - - return $sha; - } - - /** - * Returns an SHA-1 id of the ref resource, or false if it cannot be found - * - * @param string $ref The ref name to lookup - * - * @return string An SHA-1 id of the ref resource - */ - private function _packedRef($ref) - { - $sha = false; - if (file_exists($this->_path . 'packed-refs')) { - $file = fopen($this->_path . 'packed-refs', 'r'); - - while (($line = fgets($file)) !== false) { - $info = explode(' ', $line); - if (count($info) == 2 - && trim($info[1]) == 'refs' . DIRECTORY_SEPARATOR . $ref - ) { - $sha = trim($info[0]); - break; - } - } - - fclose($file); - } - - return $sha; - } - -} diff --git a/3rdparty/granite/git/tag.php b/3rdparty/granite/git/tag.php deleted file mode 100644 index e26ddaffa6..0000000000 --- a/3rdparty/granite/git/tag.php +++ /dev/null @@ -1,38 +0,0 @@ - - * @license http://www.opensource.org/licenses/mit-license.php MIT Expat License - * @link http://craig0990.github.com/Granite/ - */ - -namespace Granite\Git; - -/** - * Tag represents a full tag object - * - * @category Git - * @package Granite - * @author Craig Roberts - * @license http://www.opensource.org/licenses/mit-license.php MIT Expat License - * @link http://craig0990.github.com/Granite/ - */ -class Tag -{ - - public function __construct($path, $sha) - { - $this->sha = $sha; - } - - public function sha() - { - return $this->sha; - } - -} diff --git a/3rdparty/granite/git/tree.php b/3rdparty/granite/git/tree.php deleted file mode 100644 index 2de7227453..0000000000 --- a/3rdparty/granite/git/tree.php +++ /dev/null @@ -1,198 +0,0 @@ - - * @license http://www.opensource.org/licenses/mit-license.php MIT Expat License - * @link http://craig0990.github.com/Granite/ - */ - -namespace Granite\Git; -use \Granite\Git\Tree\Node as Node; - -/** - * Tree represents a full tree object, with nodes pointing to other tree objects - * and file blobs - * - * @category Git - * @package Granite - * @author Craig Roberts - * @license http://www.opensource.org/licenses/mit-license.php MIT Expat License - * @link http://craig0990.github.com/Granite/ - */ -class Tree -{ - - /** - * The SHA-1 id of the requested tree - */ - private $sha; - /** - * The nodes/entries for the requested tree - */ - private $nodes = array(); - /** - * The path to the repository - */ - private $path; - - /** - * Reads a tree object by fetching the raw object - * - * @param string $path The path to the repository root - * @param string $sha The SHA-1 id of the requested object - */ - public function __construct($path, $sha = NULL, $dbg = FALSE) - { - $this->path = $path; - if ($sha !== NULL) { - $object = Object\Raw::factory($path, $sha); - $this->sha = $sha; - - if ($object->type() !== Object\Raw::OBJ_TREE) { - throw new \InvalidArgumentException( - "The object $sha is not a tree, type is " . $object->type() - ); - } - - $content = $object->content(); - file_put_contents('/tmp/tree_from_real_repo'.time(), $content); - $nodes = array(); - - for ($i = 0; $i < strlen($content); $i = $data_start + 21) { - $data_start = strpos($content, "\0", $i); - $info = substr($content, $i, $data_start-$i); - list($mode, $name) = explode(' ', $info, 2); - // Read the object SHA-1 id - $sha = bin2hex(substr($content, $data_start + 1, 20)); - - $this->nodes[$name] = new Node($name, $mode, $sha); - } - } - } - - /** - * Returns an array of Tree and Granite\Git\Blob objects, - * representing subdirectories and files - * - * @return array Array of Tree and Granite\Git\Blob objects - */ - public function nodes($nodes = null) - { - if ($nodes == null) { - return $this->nodes; - } - $this->nodes = $nodes; - } - - /** - * Adds a blob or a tree to the list of nodes - * - * @param string $name The basename (filename) of the blob or tree - * @param string $mode The mode of the blob or tree (see above) - * @param string $sha The SHA-1 id of the blob or tree to add - */ - public function add($name, $mode, $sha) - { - $this->nodes[$name] = new Node($name, $mode, $sha); - uasort($this->nodes, array($this, '_sort')); - } - - public function write() - { - $sha = $this->sha(); - $path = $this->path - . 'objects' - . DIRECTORY_SEPARATOR - . substr($sha, 0, 2) - . DIRECTORY_SEPARATOR - . substr($sha, 2); - // FIXME: currently writes loose objects only - if (file_exists($path)) { - return FALSE; - } - - if (!is_dir(dirname($path))) { - mkdir(dirname($path), 0777, TRUE); - } - - $loose = fopen($path, 'wb'); - $data = $this->_raw(); - $data = 'tree ' . strlen($data) . "\0" . $data; - $write = fwrite($loose, gzcompress($data)); - fclose($loose); - - return ($write !== FALSE); - } - - /** - * Returns the SHA-1 id of the Tree - * - * @return string SHA-1 id of the Tree - */ - public function sha() - { - $data = $this->_raw(); - $raw = 'tree ' . strlen($data) . "\0" . $data; - $this->sha = hash('sha1', $raw); - return $this->sha; - } - - /** - * Generates the raw object content to be saved to disk - */ - public function _raw() - { - uasort($this->nodes, array($this, '_sort')); - $data = ''; - foreach ($this->nodes as $node) - { - $data .= base_convert($node->mode(), 10, 8) . ' ' . $node->name() . "\0"; - $data .= pack('H40', $node->sha()); - } - file_put_contents('/tmp/tree_made'.time(), $data); - return $data; - } - - /** - * Sorts the node entries in a tree, general sort method adapted from original - * Git C code (see @see tag below). - * - * @return 1, 0 or -1 if the first entry is greater than, the same as, or less - * than the second, respectively. - * @see https://github.com/gitster/git/blob/master/read-cache.c Around line 352, - * the `base_name_compare` function - */ - public function _sort(&$a, &$b) - { - $length = strlen($a->name()) < strlen($b->name()) ? strlen($a->name()) : strlen($b->name()); - - $cmp = strncmp($a->name(), $b->name(), $length); - if ($cmp) { - return $cmp; - } - - $suffix1 = $a->name(); - $suffix1 = (strlen($suffix1) > $length) ? $suffix1{$length} : FALSE; - $suffix2 = $b->name(); - $suffix2 = (strlen($suffix2) > $length) ? $suffix2{$length} : FALSE; - if (!$suffix1 && $a->isDirectory()) { - $suffix1 = '/'; - } - if (!$suffix2 && $b->isDirectory()) { - $suffix2 = '/'; - } - if ($suffix1 < $suffix2) { - return -1; - } elseif ($suffix1 > $suffix2) { - return 1; - } - - return 0; - } - -} diff --git a/3rdparty/granite/git/tree/node.php b/3rdparty/granite/git/tree/node.php deleted file mode 100644 index f99eb1ae28..0000000000 --- a/3rdparty/granite/git/tree/node.php +++ /dev/null @@ -1,126 +0,0 @@ - - * @license http://www.opensource.org/licenses/mit-license.php MIT Expat License - * @link http://craig0990.github.com/Granite/ - */ - -namespace Granite\Git\Tree; - -/** - * Node represents an entry in a Tree - * - * @category Git - * @package Granite - * @author Craig Roberts - * @license http://www.opensource.org/licenses/mit-license.php MIT Expat License - * @link http://craig0990.github.com/Granite/ - */ -class Node -{ - - /** - * Name of the file, directory or submodule - */ - private $_name; - /** - * Mode of the object, in octal - */ - private $_mode; - /** - * SHA-1 id of the tree - */ - private $_sha; - /** - * Boolean value for whether the entry represents a directory - */ - private $_is_dir; - /** - * Boolean value for whether the entry represents a submodule - */ - private $_is_submodule; - - /** - * Sets up a Node class with properties corresponding to the $mode parameter - * - * @param string $name The name of the object (file, directory or submodule name) - * @param int $mode The mode of the object, retrieved from the repository - * @param string $sha The SHA-1 id of the object - */ - public function __construct($name, $mode, $sha) - { - $this->_name = $name; - $this->_mode = intval($mode, 8); - $this->_sha = $sha; - - $this->_is_dir = (bool) ($this->_mode & 0x4000); - $this->_is_submodule = ($this->_mode == 0xE000); - } - - /** - * Returns a boolean value indicating whether the node is a directory - * - * @return boolean - */ - public function isDirectory() - { - return $this->_is_dir; - } - - /** - * Returns a boolean value indicating whether the node is a submodule - * - * @return boolean - */ - public function isSubmodule() - { - return $this->_is_submodule; - } - - /** - * Returns the object name - * - * @return string - */ - public function name() - { - return $this->_name; - } - - /** - * Returns the object's SHA-1 id - * - * @return string - */ - public function sha() - { - return $this->_sha; - } - - /** - * Returns the octal value of the file mode - * - * @return int - */ - public function mode() - { - return $this->_mode; - } - - public function type() - { - if ($this->isDirectory()) { - return 'tree'; - } elseif ($this->isSubmodule()) { - return 'commit'; - } else { - return 'blob'; - } - } -}