summaryrefslogtreecommitdiffstats
path: root/read_object.pl
blob: 8360882660ae7830e44c571c4070f8cd64eb26c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/usr/bin/env perl

use Compress::Zlib;
use Digest::SHA qw(sha1_hex);
use File::Basename;
use Data::Dumper;

use strict;
use warnings;

my @filedata = <>;
my ($signature, $type, $size, $data) = read_object(join('', @filedata));
my $out = format_object($type, $data);

print "signature: $signature\ntype: $type\nsize: $size\n"
    . ("-" x 40) . "\n$out\n";

sub read_object {
    my ($zlib_data) = @_;

    my $raw_data = uncompress($zlib_data)
        || die "Couldn't uncompress zlib data.";
    my $sig = sha1_hex($raw_data);
    $raw_data =~ /(.*?) (.*?)\0(.*)/s || die "Invalid object format.";

    my ($type, $size, $data) = ($1, $2, $3);
    warn "Size mismatch: got $size, but was actually " . length($data)
        unless length($data) == $size;

    ($sig, $type, $size, $data);
}

sub format_object {
    my ($type, $obj) = @_;

    if ($type eq 'commit') {
        $obj;
    } elsif ($type eq 'tag') {
        warn 'TODO - unimplemented';
        join '', map { sprintf('%02x ', $_) } unpack('C*', $obj);
    } elsif ($type eq 'tree') {
        warn 'TODO - unimplemented';
        join '', map { sprintf('%02x ', $_) } unpack('C*', $obj);
    } elsif ($type eq 'blob') {
        warn 'TODO - unimplemented';
        join '', map { sprintf('%02x ', $_) } unpack('C*', $obj);
    } else {
        warn "Unknown object type, showing hex representation: $type.\n";
        join '', map { sprintf('%02x', $_) } unpack('C*', $obj);
    }
}

1;