Git pack parsing

master
Sven Slootweg 12 years ago
parent a4d11ef490
commit 77f563f95f

@ -23,11 +23,20 @@ function sha1_from_bin($bin)
return bin2hex($bin);
}
function number_from_bin($bin)
{
$c = unpack("N", $bin);
return $c[1];
}
class GitBranchNotFoundException extends Exception {}
class GitTagNotFoundException extends Exception {}
class GitInvalidOriginException extends Exception {}
class GitInvalidElementException extends Exception {}
class GitInvalidFormatException extends Exception {}
class GitUnsupportedVersionException extends Exception {}
class GitPathNotFoundException extends Exception {}
class GitCorruptIndexException extends Exception {}
require(dirname(__FILE__) . "/class.repository.php");
require(dirname(__FILE__) . "/class.branch.php");
@ -38,4 +47,6 @@ require(dirname(__FILE__) . "/class.tree.php");
require(dirname(__FILE__) . "/class.tree.element.php");
require(dirname(__FILE__) . "/class.commit.php");
require(dirname(__FILE__) . "/class.actor.php");
require(dirname(__FILE__) . "/class.pack.php");
require(dirname(__FILE__) . "/class.pack.index.php");
?>

@ -0,0 +1,74 @@
<?php
define("PACK_IDX_SIGNATURE", "\377tOc");
class GitPackIndex
{
public $rawdata = "";
public $version = 0;
public $index = array();
function __construct($data)
{
$this->rawdata = $data;
if(substr($data, 0, 4) == PACK_IDX_SIGNATURE)
{
$version = number_from_bin(substr($data, 4, 4));
if($version == 2)
{
$this->version = $version;
$offset = 8;
$indexes = unpack("N*", substr($data, $offset, 256*4));
$highest = 0;
for($i = 0; $i < 256; $i++)
{
if(!isset($indexes[$i + 1]))
{
continue;
}
$n = $indexes[$i + 1];
if($n < $highest)
{
throw new GitCorruptIndexException("The pack index file is corrupt.");
}
$highest = $n;
}
$offset = $offset + (256 * 4);
$keys = array();
$values = array();
for($i = 0; $i < $highest; $i++)
{
$keys[] = sha1_from_bin(substr($data, $offset, 20));
$offset += 20;
}
$offset += ($highest * 4);
for($i = 0; $i < $highest; $i++)
{
$values[] = number_from_bin(substr($data, $offset, 4));
$offset += 4;
}
$this->index = array_combine($keys, $values);
}
else
{
throw new GitUnsupportedVersionException("Version {$version} pack indexes are not supported by this version of the library.");
}
}
else
{
throw new GitInvalidFormatException("The provided data does not look like a pack index file.");
}
}
}

@ -0,0 +1,16 @@
<?php
class GitPack
{
public $repo = null;
public $index = array();
function __construct($repo, $name)
{
$this->repo = $repo;
$index_filename = "{$repo->path}/objects/pack/{$name}.idx";
$pack_filename = "{$repo->path}/objects/pack/{$name}.pack";
$this->index = new GitPackIndex(file_get_contents($index_filename));
}
}

@ -2,4 +2,5 @@
require("libgit/base.php");
$repo = new GitRepository("/home/occupy/testrepo.git");
pretty_dump($repo->GetObjectForPath($repo->GetBranch("master")->GetTree(), "public_html/css/images/derp"));
pretty_dump(new GitPack($repo, "pack-8503a2b8cf6e60831dd012afd4d486eb1eddfef8"));
//pretty_dump($repo->GetObjectForPath($repo->GetBranch("master")->GetTree(), "public_html/css/images/derp"));

Loading…
Cancel
Save