From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id E6B36211B4 for ; Fri, 11 Jan 2019 04:10:09 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 1/7] hoist out resolve_repo_dir from -index Date: Fri, 11 Jan 2019 04:10:02 +0000 Message-Id: <20190111041008.24361-2-e@80x24.org> In-Reply-To: <20190111041008.24361-1-e@80x24.org> References: <20190111041008.24361-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: We'll be using it in future admin tools, and making this easier-to-test. --- MANIFEST | 2 + lib/PublicInbox/Admin.pm | 44 +++++++++++++++++++++ script/public-inbox-index | 32 +--------------- t/admin.t | 81 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+), 30 deletions(-) create mode 100644 lib/PublicInbox/Admin.pm create mode 100644 t/admin.t diff --git a/MANIFEST b/MANIFEST index e4f3df8..5ac85c3 100644 --- a/MANIFEST +++ b/MANIFEST @@ -51,6 +51,7 @@ examples/unsubscribe.milter examples/unsubscribe.psgi examples/varnish-4.vcl lib/PublicInbox/Address.pm +lib/PublicInbox/Admin.pm lib/PublicInbox/AltId.pm lib/PublicInbox/Config.pm lib/PublicInbox/ContentId.pm @@ -141,6 +142,7 @@ scripts/slrnspool2maildir scripts/ssoma-replay scripts/xhdr-num2mid t/address.t +t/admin.t t/altid.t t/altid_v2.t t/cgi.t diff --git a/lib/PublicInbox/Admin.pm b/lib/PublicInbox/Admin.pm new file mode 100644 index 0000000..d0a8dd0 --- /dev/null +++ b/lib/PublicInbox/Admin.pm @@ -0,0 +1,44 @@ +# Copyright (C) 2019 all contributors +# License: AGPL-3.0+ + +# common stuff for administrative command-line tools +# Unstable internal API +package PublicInbox::Admin; +use strict; +use warnings; +use Cwd 'abs_path'; +use base qw(Exporter); +our @EXPORT_OK = qw(resolve_repo_dir); + +sub resolve_repo_dir { + my ($cd, $ver) = @_; + my $prefix = defined $cd ? $cd : './'; + if (-d $prefix && -f "$prefix/inbox.lock") { # v2 + $$ver = 2 if $ver; + return abs_path($prefix); + } + + my @cmd = qw(git rev-parse --git-dir); + my $cmd = join(' ', @cmd); + my $pid = open my $fh, '-|'; + defined $pid or die "forking $cmd failed: $!\n"; + if ($pid == 0) { + if (defined $cd) { + chdir $cd or die "chdir $cd failed: $!\n"; + } + exec @cmd; + die "Failed to exec $cmd: $!\n"; + } else { + my $dir = eval { + local $/; + <$fh>; + }; + close $fh or die "error in $cmd: $!\n"; + chomp $dir; + $$ver = 1 if $ver; + return abs_path($cd) if ($dir eq '.' && defined $cd); + abs_path($dir); + } +} + +1; diff --git a/script/public-inbox-index b/script/public-inbox-index index 73ad9bc..32121f6 100755 --- a/script/public-inbox-index +++ b/script/public-inbox-index @@ -9,9 +9,10 @@ use strict; use warnings; use Getopt::Long qw(:config gnu_getopt no_ignore_case auto_abbrev); -use Cwd 'abs_path'; my $usage = "public-inbox-index REPO_DIR"; use PublicInbox::Config; +use PublicInbox::Admin qw(resolve_repo_dir); + my $config = eval { PublicInbox::Config->new } || eval { warn "public-inbox unconfigured for serving, indexing anyways...\n"; {} @@ -35,35 +36,6 @@ die "--jobs must be positive\n" if defined $jobs && $jobs < 0; my @dirs; -sub resolve_repo_dir { - my ($cd) = @_; - my $prefix = defined $cd ? $cd : './'; - if (-d $prefix && -f "$prefix/inbox.lock") { # v2 - return abs_path($prefix); - } - - my @cmd = qw(git rev-parse --git-dir); - my $cmd = join(' ', @cmd); - my $pid = open my $fh, '-|'; - defined $pid or die "forking $cmd failed: $!\n"; - if ($pid == 0) { - if (defined $cd) { - chdir $cd or die "chdir $cd failed: $!\n"; - } - exec @cmd; - die "Failed to exec $cmd: $!\n"; - } else { - my $dir = eval { - local $/; - <$fh>; - }; - close $fh or die "error in $cmd: $!\n"; - chomp $dir; - return abs_path($cd) if ($dir eq '.' && defined $cd); - abs_path($dir); - } -} - if (@ARGV) { @dirs = map { resolve_repo_dir($_) } @ARGV; } else { diff --git a/t/admin.t b/t/admin.t new file mode 100644 index 0000000..cc1e65d --- /dev/null +++ b/t/admin.t @@ -0,0 +1,81 @@ +# Copyright (C) 2019 all contributors +# License: AGPL-3.0+ +use strict; +use warnings; +use Test::More; +use File::Temp qw(tempdir); +# use Cwd qw(getcwd); +use_ok 'PublicInbox::Admin', qw(resolve_repo_dir); +my $tmpdir = tempdir('pi-admin.XXXXXX', TMPDIR => 1, CLEANUP => 1); +my $git_dir = "$tmpdir/v1"; +my $v2_dir = "$tmpdir/v2"; +my ($res, $err, $v); + +is(0, system(qw(git init -q --bare), $git_dir), 'git init v1'); + +# v1 +is(resolve_repo_dir($git_dir), $git_dir, 'top-level GIT_DIR resolved'); +is(resolve_repo_dir("$git_dir/objects"), $git_dir, 'GIT_DIR/objects resolved'); + +ok(chdir($git_dir), 'chdir GIT_DIR works'); +is(resolve_repo_dir(), $git_dir, 'resolve_repo_dir works in GIT_DIR'); + +ok(chdir("$git_dir/objects"), 'chdir GIT_DIR/objects works'); +is(resolve_repo_dir(), $git_dir, 'resolve_repo_dir works in GIT_DIR'); +$res = resolve_repo_dir(undef, \$v); +is($v, 1, 'version 1 detected'); +is($res, $git_dir, 'detects directory along with version'); + +# $tmpdir could be inside a git working, directory, so we test '/' +SKIP: { + my $no_vcs_dir = '/'; + # do people version-control "/"? + skip "$no_vcs_dir is version controlled by git", 4 if -d '/.git'; + open my $null, '>', '/dev/null' or die "open /dev/null: $!"; + open my $olderr, '>&', \*STDERR or die "dup stderr: $!"; + + ok(chdir($no_vcs_dir), 'chdir to a non-inbox'); + open STDERR, '>&', $null or die "redirect stderr to /dev/null: $!"; + $res = eval { resolve_repo_dir() }; + open STDERR, '>&', $olderr or die "restore stderr: $!"; + is($res, undef, 'fails inside non-version-controlled dir'); + + ok(chdir($tmpdir), 'back to test-specific $tmpdir'); + open STDERR, '>&', $null or die "redirect stderr to /dev/null: $!"; + $res = eval { resolve_repo_dir($no_vcs_dir) }; + $err = $@; + open STDERR, '>&', $olderr or die "restore stderr: $!"; + is($res, undef, 'fails on non-version-controlled dir'); + ok($err, '$@ set on failure'); +} + +# v2 +SKIP: { + for my $m (qw(DBD::SQLite Search::Xapian)) { + skip "$m missing", 5 unless eval "require $m"; + } + use_ok 'PublicInbox::V2Writable'; + use_ok 'PublicInbox::Inbox'; + my $ibx = PublicInbox::Inbox->new({ + mainrepo => $v2_dir, + name => 'test-v2writable', + version => 2, + -primary_address => 'test@example.com', + indexlevel => 'basic', + }); + PublicInbox::V2Writable->new($ibx, 1)->idx_init; + + ok(-e "$v2_dir/inbox.lock", 'exists'); + is(resolve_repo_dir($v2_dir), $v2_dir, + 'resolve_repo_dir works on v2_dir'); + ok(chdir($v2_dir), 'chdir v2_dir OK'); + is(resolve_repo_dir(), $v2_dir, 'resolve_repo_dir works inside v2_dir'); + $res = resolve_repo_dir(undef, \$v); + is($v, 2, 'version 2 detected'); + is($res, $v2_dir, 'detects directory along with version'); + + # TODO: should work from inside Xapian dirs, and git dirs, here... +} + +chdir '/'; +done_testing(); -- EW