Subversion Repositories php_utils

Rev

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
}