1 # Copyright (C) 2015-2018 all contributors <meta@public-inbox.org>
2 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
6 use File::Temp qw/tempdir/;
7 my $dir = tempdir('pi-git-XXXXXX', TMPDIR => 1, CLEANUP => 1);
9 use PublicInbox::Spawn qw(popen_rd);
11 use_ok 'PublicInbox::Git';
13 is(system(qw(git init -q --bare), $dir), 0, 'created git directory');
14 my @cmd = ('git', "--git-dir=$dir", 'fast-import', '--quiet');
16 my $fi_data = getcwd().'/t/git.fast-import-data';
17 ok(-r $fi_data, "fast-import data readable (or run test at top level)");
19 defined $pid or die "fork failed: $!\n";
21 open STDIN, '<', $fi_data or die "open $fi_data: $!\n";
23 die "failed exec: ",join(' ', @cmd),": $!\n";
26 is($?, 0, 'fast-import succeeded');
30 my $gcf = PublicInbox::Git->new($dir);
31 my $f = 'HEAD:foo.txt';
32 my @x = $gcf->check($f);
33 is(scalar @x, 3, 'returned 3 element array for existing file');
34 like($x[0], qr/\A[a-f0-9]{40}\z/, 'returns obj ID in 1st element');
35 is('blob', $x[1], 'returns obj type in 2nd element');
36 like($x[2], qr/\A\d+\z/, 'returns obj size in 3rd element');
38 my $raw = $gcf->cat_file($f);
39 is($x[2], length($$raw), 'length matches');
43 my $rv = $gcf->cat_file($f, sub {
48 is($rv, 'nothing', 'returned from callback without reading');
49 is($size, $x[2], 'set size for callback correctly');
52 eval { $gcf->cat_file($f, sub { die 'OMG' }) };
53 like($@, qr/\bOMG\b/, 'died in callback propagated');
54 is(${$gcf->cat_file($f)}, $$raw, 'not broken after failures');
58 my $rv = $gcf->cat_file($f, sub {
60 $r = read($in, $buf, 2);
64 is($r, 2, 'only read 2 bytes');
65 is($buf, '--', 'partial read succeeded');
66 is($rv, 'blah', 'return value propagated');
68 is(${$gcf->cat_file($f)}, $$raw, 'not broken after partial read');
73 my @cmd = ('git', "--git-dir=$dir", qw(hash-object -w --stdin));
75 # need a big file, use the AGPL-3.0 :p
76 my $big_data = getcwd().'/COPYING';
77 ok(-r $big_data, 'COPYING readable');
78 my $size = -s $big_data;
79 ok($size > 8192, 'file is big enough');
82 ok(pipe($r, $w), 'created pipe');
85 defined $pid or die "fork failed: $!\n";
88 open STDIN, '<', $big_data or die "open $big_data: $!\n";
91 die "failed exec: ",join(' ', @cmd),": $!\n";
94 my $n = read $r, my $buf, 41;
96 is(0, $?, 'hashed object successfully');
99 my $gcf = PublicInbox::Git->new($dir);
101 is($gcf->cat_file($buf, sub {
104 }), 'x', 'checked input');
105 is($rsize, $size, 'got correct size on big file');
107 my $x = $gcf->cat_file($buf, \$rsize);
108 is($rsize, $size, 'got correct size ref on big file');
109 is(length($$x), $size, 'read correct number of bytes');
112 $gcf->cat_file($buf, sub {
113 my ($in, $left) = @_;
115 $$left -= length($rline);
118 open my $fh, '<', $big_data or die "open failed: $!\n";
119 is($rline, <$fh>, 'first line matches');
123 $gcf->cat_file($buf, sub {
124 my ($in, $left) = @_;
125 my $x = read($in, $all, $$left);
129 open my $fh, '<', $big_data or die "open failed: $!\n";
131 is($all, <$fh>, 'entire read matches');
134 my $ref = $gcf->qx(qw(cat-file blob), $buf);
135 is($all, $ref, 'qx read giant single string');
137 my @ref = $gcf->qx(qw(cat-file blob), $buf);
138 is($all, join('', @ref), 'qx returned array when wanted');
139 my $nl = scalar @ref;
140 ok($nl > 1, "qx returned array length of $nl");
142 $gcf->qx(qw(repack -adbq));
143 ok($gcf->packed_bytes > 0, 'packed size is positive');
146 if ('alternates reloaded') {
147 my $alt = tempdir('pi-git-XXXXXX', TMPDIR => 1, CLEANUP => 1);
148 my @cmd = ('git', "--git-dir=$alt", qw(hash-object -w --stdin));
149 is(system(qw(git init -q --bare), $alt), 0, 'create alt directory');
150 open my $fh, '<', "$alt/config" or die "open failed: $!\n";
151 my $rd = popen_rd(\@cmd, {}, { 0 => fileno($fh) } );
152 close $fh or die "close failed: $!";
153 chomp(my $remote = <$rd>);
154 my $gcf = PublicInbox::Git->new($dir);
155 is($gcf->cat_file($remote), undef, "remote file not found");
156 open $fh, '>>', "$dir/objects/info/alternates" or
157 die "open failed: $!\n";
158 print $fh "$alt/objects" or die "print failed: $!\n";
159 close $fh or die "close failed: $!";
160 my $found = $gcf->cat_file($remote);
161 open $fh, '<', "$alt/config" or die "open failed: $!\n";
162 my $config = eval { local $/; <$fh> };
163 is($$found, $config, 'alternates reloaded');