]> Sergey Matveev's repositories - public-inbox.git/blob - t/git.t
msgmap: add tmp_clone to create an anonymous copy
[public-inbox.git] / t / git.t
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>
3 use strict;
4 use warnings;
5 use Test::More;
6 use File::Temp qw/tempdir/;
7 my $dir = tempdir('pi-git-XXXXXX', TMPDIR => 1, CLEANUP => 1);
8 use Cwd qw/getcwd/;
9 use PublicInbox::Spawn qw(popen_rd);
10
11 use_ok 'PublicInbox::Git';
12 {
13         is(system(qw(git init -q --bare), $dir), 0, 'created git directory');
14         my @cmd = ('git', "--git-dir=$dir", 'fast-import', '--quiet');
15
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)");
18         my $pid = fork;
19         defined $pid or die "fork failed: $!\n";
20         if ($pid == 0) {
21                 open STDIN, '<', $fi_data or die "open $fi_data: $!\n";
22                 exec @cmd;
23                 die "failed exec: ",join(' ', @cmd),": $!\n";
24         }
25         waitpid $pid, 0;
26         is($?, 0, 'fast-import succeeded');
27 }
28
29 {
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');
37
38         my $raw = $gcf->cat_file($f);
39         is($x[2], length($$raw), 'length matches');
40
41         {
42                 my $size;
43                 my $rv = $gcf->cat_file($f, sub {
44                         my ($in, $left) = @_;
45                         $size = $$left;
46                         'nothing'
47                 });
48                 is($rv, 'nothing', 'returned from callback without reading');
49                 is($size, $x[2], 'set size for callback correctly');
50         }
51
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');
55
56         {
57                 my ($buf, $r);
58                 my $rv = $gcf->cat_file($f, sub {
59                         my ($in, $left) = @_;
60                         $r = read($in, $buf, 2);
61                         $$left -= $r;
62                         'blah'
63                 });
64                 is($r, 2, 'only read 2 bytes');
65                 is($buf, '--', 'partial read succeeded');
66                 is($rv, 'blah', 'return value propagated');
67         }
68         is(${$gcf->cat_file($f)}, $$raw, 'not broken after partial read');
69 }
70
71 if (1) {
72         use POSIX qw(dup2);
73         my @cmd = ('git', "--git-dir=$dir", qw(hash-object -w --stdin));
74
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');
80
81         my ($r, $w);
82         ok(pipe($r, $w), 'created pipe');
83
84         my $pid = fork;
85         defined $pid or die "fork failed: $!\n";
86         if ($pid == 0) {
87                 close $r;
88                 open STDIN, '<', $big_data or die "open $big_data: $!\n";
89                 dup2(fileno($w), 1);
90                 exec @cmd;
91                 die "failed exec: ",join(' ', @cmd),": $!\n";
92         }
93         close $w;
94         my $n = read $r, my $buf, 41;
95         waitpid $pid, 0;
96         is(0, $?, 'hashed object successfully');
97         chomp $buf;
98
99         my $gcf = PublicInbox::Git->new($dir);
100         my $rsize;
101         is($gcf->cat_file($buf, sub {
102                 $rsize = ${$_[1]};
103                 'x';
104         }), 'x', 'checked input');
105         is($rsize, $size, 'got correct size on big file');
106
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');
110
111         my $rline;
112         $gcf->cat_file($buf, sub {
113                 my ($in, $left) = @_;
114                 $rline = <$in>;
115                 $$left -= length($rline);
116         });
117         {
118                 open my $fh, '<', $big_data or die "open failed: $!\n";
119                 is($rline, <$fh>, 'first line matches');
120         };
121
122         my $all;
123         $gcf->cat_file($buf, sub {
124                 my ($in, $left) = @_;
125                 my $x = read($in, $all, $$left);
126                 $$left -= $x;
127         });
128         {
129                 open my $fh, '<', $big_data or die "open failed: $!\n";
130                 local $/;
131                 is($all, <$fh>, 'entire read matches');
132         };
133
134         my $ref = $gcf->qx(qw(cat-file blob), $buf);
135         is($all, $ref, 'qx read giant single string');
136
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");
141
142         $gcf->qx(qw(repack -adbq));
143         ok($gcf->packed_bytes > 0, 'packed size is positive');
144 }
145
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');
164 }
165
166 done_testing();