Rev 78 | Rev 80 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 78 | Rev 79 | ||
---|---|---|---|
Line 72... | Line 72... | ||
72 | $pack_files = @glob($objects_dir.'/pack/pack-*.pack'); |
72 | $pack_files = @glob($objects_dir.'/pack/pack-*.pack'); |
73 | $last_exception = 'No pack files found'; |
73 | $last_exception = 'No pack files found'; |
74 | if ($pack_files) foreach ($pack_files as $basename) { |
74 | if ($pack_files) foreach ($pack_files as $basename) { |
75 | $basename = substr(basename($basename),0,strlen(basename($basename))-5); |
75 | $basename = substr(basename($basename),0,strlen(basename($basename))-5); |
76 | try { |
76 | try { |
- | 77 | if (class_exists('ViaThinkSoft\Glip\Git')) { |
|
- | 78 | // https://github.com/danielmarschall/glip |
|
- | 79 | // composer require danielmarschall/glip |
|
- | 80 | $git = new Git($git_dir); |
|
- | 81 | $obj = $git->getObject(hex2bin($commit_object)); |
|
- | 82 | echo $obj->detail; |
|
- | 83 | } else { |
|
- | 84 | // Own implementation (cannot read delta objects yet) |
|
77 | return git_read_object($commit_object, |
85 | return git_read_object($commit_object, |
78 | $objects_dir.'/pack/'.$basename.'.idx', |
86 | $objects_dir.'/pack/'.$basename.'.idx', |
79 | $objects_dir.'/pack/'.$basename.'.pack' |
87 | $objects_dir.'/pack/'.$basename.'.pack' |
80 | ); |
88 | ); |
- | 89 | } |
|
81 | } catch (Exception $e) { |
90 | } catch (Exception $e) { |
82 | $last_exception = $e; |
91 | $last_exception = $e; |
83 | } |
92 | } |
84 | } |
93 | } |
85 | throw new Exception($last_exception); |
94 | throw new Exception($last_exception); |
Line 139... | Line 148... | ||
139 | } while (bin2hex($binary) != strtolower($object_wanted)); |
148 | } while (bin2hex($binary) != strtolower($object_wanted)); |
140 | if ($debug) echo "Exact object no = $object_no\n"; |
149 | if ($debug) echo "Exact object no = $object_no\n"; |
141 | 150 | ||
142 | if ($version == 2) { |
151 | if ($version == 2) { |
143 | // Get CRC32 |
152 | // Get CRC32 |
144 | // TODO: is this correct? or do we need to read 'H8' ? |
- | |
145 | fseek($fp, $fanout_offset + 4*256 + 20*$num_objects + 4*$object_no); |
153 | fseek($fp, $fanout_offset + 4*256 + 20*$num_objects + 4*$object_no); |
146 | $crc32 = unpack('N', fread($fp,4))[1]; |
154 | $crc32 = unpack('H8', fread($fp,4))[1]; |
147 | if ($debug) echo "CRC32 = ".sprintf('0x%08x',$crc32)."\n"; |
155 | if ($debug) echo "CRC32 = ".$crc32."\n"; |
148 | 156 | ||
149 | // Get offset (32 bit) |
157 | // Get offset (32 bit) |
150 | fseek($fp, $fanout_offset + 4*256 + 20*$num_objects + 4*$num_objects + 4*$object_no); |
158 | fseek($fp, $fanout_offset + 4*256 + 20*$num_objects + 4*$num_objects + 4*$object_no); |
151 | $offset_info = unpack('N', fread($fp,4))[1]; |
159 | $offset_info = unpack('N', fread($fp,4))[1]; |
152 | if ($offset_info >= 0x80000000) { |
160 | if ($offset_info >= 0x80000000) { |
Line 170... | Line 178... | ||
170 | 178 | ||
171 | // Open pack file |
179 | // Open pack file |
172 | $fp = fopen($pack_file, 'rb'); |
180 | $fp = fopen($pack_file, 'rb'); |
173 | if (!$fp) throw new Exception("Cannot open pack file $pack_file"); |
181 | if (!$fp) throw new Exception("Cannot open pack file $pack_file"); |
174 | 182 | ||
175 | // Find out type |
183 | // Read type and first part of the size |
176 | fseek($fp, $pack_offset); |
184 | fseek($fp, $pack_offset); |
177 | $size_info = unpack('C', fread($fp,1))[1]; |
185 | $size_info = unpack('C', fread($fp,1))[1]; |
178 | 186 | ||
- | 187 | // Detect type |
|
179 | $type = ($size_info & 0x70) >> 4; /*0b01110000*/ |
188 | $type = ($size_info & 0x70) >> 4; /*0b01110000*/ |
180 | switch ($type) { |
189 | switch ($type) { |
181 | case 1: |
190 | case 1: |
182 | if ($debug) echo "Type = OBJ_COMMIT ($type)\n"; |
191 | if ($debug) echo "Type = OBJ_COMMIT ($type)\n"; |
183 | break; |
192 | break; |
Line 199... | Line 208... | ||
199 | default: |
208 | default: |
200 | if ($debug) echo "Type = Invalid ($type)\n"; |
209 | if ($debug) echo "Type = Invalid ($type)\n"; |
201 | break; |
210 | break; |
202 | } |
211 | } |
203 | 212 | ||
204 | // Find out size |
213 | // Find out the expected unpacked size |
205 | $size = $size_info & 0xF /*0x00001111*/; |
214 | $size = $size_info & 0xF /*0x00001111*/; |
206 | $shift_info = 4; |
215 | $shift_info = 4; |
207 | while ($size_info >= 0x80) { |
216 | while ($size_info >= 0x80) { |
208 | $size_info = unpack('C', fread($fp,1))[1]; |
217 | $size_info = unpack('C', fread($fp,1))[1]; |
209 | $size = (($size_info & 0x7F) << $shift_info) + $size; |
218 | $size = (($size_info & 0x7F) << $shift_info) + $size; |
210 | $shift_info += 7; |
219 | $shift_info += 7; |
211 | } |
220 | } |
212 | - | ||
213 | // TODO: Is this the packed or unpacked size? http://driusan.github.io/git-pack.html |
- | |
214 | if ($debug) echo "Packed size = ".sprintf('0x%x',$size)."\n"; |
221 | if ($debug) echo "Expected unpacked size = $size\n"; |
215 | 222 | ||
216 | // Read delta base type |
223 | // Read delta base type |
- | 224 | // Example implementation: https://github.com/AlexFBP/glip/blob/master/lib/git.class.php#L240 |
|
217 | if ($type == 6/*OBJ_OFS_DELTA*/) { |
225 | if ($type == 6/*OBJ_OFS_DELTA*/) { |
218 | // "a negative relative offset from the delta object's position in the pack if this is an OBJ_OFS_DELTA object" |
226 | // "a negative relative offset from the delta object's position in the pack if this is an OBJ_OFS_DELTA object" |
219 | 227 | ||
220 | // Offset encoding |
228 | // Offset encoding |
221 | $offset = 0; |
229 | $offset = 0; |
Line 234... | Line 242... | ||
234 | $delta_info = bin2hex(fread($fp,20)); |
242 | $delta_info = bin2hex(fread($fp,20)); |
235 | if ($debug) echo "Delta base object name: $delta_info\n"; |
243 | if ($debug) echo "Delta base object name: $delta_info\n"; |
236 | throw new Exception("OBJ_REF_DELTA is currently not implemented"); // TODO! Implement OBJ_REF_DELTA! |
244 | throw new Exception("OBJ_REF_DELTA is currently not implemented"); // TODO! Implement OBJ_REF_DELTA! |
237 | } |
245 | } |
238 | 246 | ||
239 | // Read compressed data |
247 | // Read and uncompress the compressed data |
240 | $compressed = fread($fp,$size); |
248 | $compressed = ''; |
241 | - | ||
242 | // Uncompress |
249 | $uncompressed = false; |
- | 250 | for ($compressed_size=1; $compressed_size<=32768*$size; $compressed_size++) { |
|
- | 251 | // Since we don't know the compressed size, we need to do trial and error |
|
- | 252 | // TODO: this is a super stupid algorithm! Is there a better way??? |
|
- | 253 | $compressed .= fread($fp,1); |
|
243 | $uncompressed = @gzuncompress($compressed); |
254 | $uncompressed = @gzuncompress($compressed); |
- | 255 | if (strlen($uncompressed) === $size) { |
|
- | 256 | if ($debug) echo "Detected compressed size = $compressed_size\n"; |
|
- | 257 | break; |
|
- | 258 | } |
|
- | 259 | } |
|
244 | if ($uncompressed === false) throw new Exception("Decompression failed"); |
260 | if ($uncompressed === false) throw new Exception("Decompression failed"); |
245 | if ($debug) echo "$uncompressed\n"; |
261 | if ($debug) echo "$uncompressed\n"; |
246 | 262 | ||
247 | // Close pack file |
263 | // Close pack file |
248 | fclose($fp); |
264 | fclose($fp); |
249 | 265 | ||
- | 266 | if ($version == 2) { |
|
250 | // Check CRC32 |
267 | // Check CRC32 |
251 | // TODO: Does not fit; neither crc32, nor crc32b... |
268 | // TODO: Hash does not match. What are we doing wrong?! |
252 | // if ($debug) echo "CRC32 found = 0x".hash('crc32',$compressed)." vs $crc32\n"; |
269 | // if ($debug) echo "CRC32 found = ".hash('crc32',$compressed)." vs $crc32\n"; |
- | 270 | // if ($debug) echo "CRC32 found = ".hash('crc32b',$compressed)." vs $crc32\n"; |
|
- | 271 | } |
|
253 | 272 | ||
254 | return $uncompressed; |
273 | return $uncompressed; |
255 | } |
274 | } |