-use parent 'PublicInbox::Git';
-use PublicInbox::Spawn qw(popen_rd);
-use IO::Handle ();
-
-sub new {
- my $self = shift->SUPER::new('/nonexistent');
- my ($out_r, $out_w);
- pipe($out_r, $out_w) or $self->fail("pipe failed: $!");
- my $cmd = [ 'public-inbox-gcf2' ];
- @$self{qw(in pid)} = popen_rd($cmd, undef, { 0 => $out_r });
+use parent qw(PublicInbox::DS);
+use PublicInbox::Git;
+use PublicInbox::Gcf2; # fails if Inline::C or libgit2-dev isn't available
+use PublicInbox::Spawn qw(spawn);
+use Socket qw(AF_UNIX SOCK_STREAM);
+use PublicInbox::Syscall qw(EPOLLIN EPOLLET);
+# fields:
+# sock => socket to Gcf2::loop
+# The rest of these fields are compatible with what PublicInbox::Git
+# uses code-sharing
+# pid => PID of Gcf2::loop process
+# pid.owner => process which spawned {pid}
+# in => same as {sock}, for compatibility with PublicInbox::Git
+# inflight => array (see PublicInbox::Git)
+# rbuf => scalarref, may be non-existent or empty
+sub new {
+ my ($rdr) = @_;
+ my $self = bless {}, __PACKAGE__;
+ # ensure the child process has the same @INC we do:
+ my $env = { PERL5LIB => join(':', @INC) };
+ my ($s1, $s2);
+ socketpair($s1, $s2, AF_UNIX, SOCK_STREAM, 0) or die "socketpair $!";
+ $rdr //= {};
+ $rdr->{0} = $rdr->{1} = $s2;
+ my $cmd = [$^X, qw[-MPublicInbox::Gcf2 -e PublicInbox::Gcf2::loop]];
+ $self->{'pid.owner'} = $$;
+ $self->{pid} = spawn($cmd, $env, $rdr);
+ $s1->blocking(0);