Subversion Repositories oidplus

Rev

Rev 1191 | Rev 1193 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1191 Rev 1192
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
                                        return $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 140... Line 149...
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
                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);
145
                $crc32 = unpack('N', fread($fp,4))[1];
154
                $crc32 = unpack('H8', fread($fp,4))[1];
146
                if ($debug) echo "CRC32 = ".sprintf('0x%08x',$crc32)."\n";
155
                if ($debug) echo "CRC32 = ".$crc32."\n";
147
 
156
 
148
                // Get offset (32 bit)
157
                // Get offset (32 bit)
149
                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);
150
                $offset_info = unpack('N', fread($fp,4))[1];
159
                $offset_info = unpack('N', fread($fp,4))[1];
151
                if ($offset_info >= 0x80000000) {
160
                if ($offset_info >= 0x80000000) {
Line 169... Line 178...
169
 
178
 
170
        // Open pack file
179
        // Open pack file
171
        $fp = fopen($pack_file, 'rb');
180
        $fp = fopen($pack_file, 'rb');
172
        if (!$fp) throw new Exception("Cannot open pack file $pack_file");
181
        if (!$fp) throw new Exception("Cannot open pack file $pack_file");
173
 
182
 
174
        // Find out type
183
        // Read type and first part of the size
175
        fseek($fp, $pack_offset);
184
        fseek($fp, $pack_offset);
176
        $size_info = unpack('C', fread($fp,1))[1];
185
        $size_info = unpack('C', fread($fp,1))[1];
177
 
186
 
-
 
187
        // Detect type
178
        $type = ($size_info & 0xE0) >> 5; /*0b11100000*/
188
        $type = ($size_info & 0x70) >> 4; /*0b01110000*/
179
        switch ($type) {
189
        switch ($type) {
180
                case 1:
190
                case 1:
181
                        if ($debug) echo "Type = OBJ_COMMIT ($type)\n";
191
                        if ($debug) echo "Type = OBJ_COMMIT ($type)\n";
182
                        break;
192
                        break;
183
                case 2:
193
                case 2:
Line 198... Line 208...
198
                default:
208
                default:
199
                        if ($debug) echo "Type = Invalid ($type)\n";
209
                        if ($debug) echo "Type = Invalid ($type)\n";
200
                        break;
210
                        break;
201
        }
211
        }
202
 
212
 
203
        // Find out size
213
        // Find out the expected unpacked size
204
        $size = $size_info & 0x1F /*0x00011111*/;
214
        $size = $size_info & 0xF /*0x00001111*/;
205
        $shift_info = 5;
215
        $shift_info = 4;
206
        do {
216
        while ($size_info >= 0x80) {
207
                $size_info = unpack('C', fread($fp,1))[1];
217
                $size_info = unpack('C', fread($fp,1))[1];
208
                $size = (($size_info & 0x7F) << $shift_info) + $size;
218
                $size = (($size_info & 0x7F) << $shift_info) + $size;
209
                $shift_info += 8;
219
                $shift_info += 7;
210
        } while ($size_info >= 0x80);
-
 
211
 
220
        }
212
        if ($debug) echo "Packed size = ".sprintf('0x%x',$size)."\n";
221
        if ($debug) echo "Expected unpacked size = $size\n";
213
 
222
 
214
        // Read delta base type
223
        // Read delta base type
-
 
224
        // Example implementation: https://github.com/AlexFBP/glip/blob/master/lib/git.class.php#L240
215
        if ($type == 6/*OBJ_OFS_DELTA*/) {
225
        if ($type == 6/*OBJ_OFS_DELTA*/) {
216
                // "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"
-
 
227
 
-
 
228
                // Offset encoding
-
 
229
                $offset = 0;
-
 
230
                $shift_info = 0;
-
 
231
                do {
217
                $delta_info = unpack('C*', fread($fp,4))[1];
232
                        $offset_info = unpack('C', fread($fp,1))[1];
-
 
233
                        $offset = (($offset_info & 0x7F) << $shift_info) + $offset;
-
 
234
                        $shift_info += 7;
-
 
235
                } while ($offset_info >= 0x80);
-
 
236
 
218
                if ($debug) echo "Delta negative offset: $delta_info\n";
237
                if ($debug) echo "Delta negative offset: $offset\n";
219
                throw new Exception("OBJ_OFS_DELTA is currently not implemented"); // TODO! Implement OBJ_OFS_DELTA!
238
                throw new Exception("OBJ_OFS_DELTA is currently not implemented"); // TODO! Implement OBJ_OFS_DELTA!
220
        }
239
        }
221
        if ($type == 7/*OBJ_REF_DELTA*/) {
240
        if ($type == 7/*OBJ_REF_DELTA*/) {
222
                // "base object name if OBJ_REF_DELTA"
241
                // "base object name if OBJ_REF_DELTA"
223
                $delta_info = bin2hex(fread($fp,20));
242
                $delta_info = bin2hex(fread($fp,20));
224
                if ($debug) echo "Delta base object name: $delta_info\n";
243
                if ($debug) echo "Delta base object name: $delta_info\n";
225
                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!
226
        }
245
        }
227
 
246
 
228
        // Read compressed data
247
        // Read and uncompress the compressed data
229
        $compressed = fread($fp,$size);
248
        $compressed = '';
230
 
-
 
231
        // 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);
232
        $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
        }
233
        if ($uncompressed === false) throw new Exception("Decompression failed");
260
        if ($uncompressed === false) throw new Exception("Decompression failed");
234
        if ($debug) echo "$uncompressed\n";
261
        if ($debug) echo "$uncompressed\n";
235
 
262
 
236
        // Close pack file
263
        // Close pack file
237
        fclose($fp);
264
        fclose($fp);
238
 
265
 
-
 
266
        if ($version == 2) {
239
        // Check CRC32
267
                // Check CRC32
240
        // TODO: Does not fit; neither crc32, nor crc32b...
268
                // TODO: Hash does not match. What are we doing wrong?!
241
        // if ($debug) echo "CRC32 found = 0x".hash('crc32',$compressed)."\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
        }
242
 
272
 
243
        return $uncompressed;
273
        return $uncompressed;
244
}
274
}