From 4c2bdcca098792bf1c7fb19d7779d05c436a2f78 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 1 Sep 2020 01:15:07 +0000 Subject: init+convert: create non-existing directory hierarchies Following "git init" as an example, we'll create every parent path up to the one specified, instead of attempting to continue on when Cwd::abs_path returns `undef'. --- script/public-inbox-convert | 7 +++++-- script/public-inbox-init | 10 ++++++++-- t/convert-compact.t | 20 ++++++++++---------- t/init.t | 12 ++++++++++++ 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/script/public-inbox-convert b/script/public-inbox-convert index 017411fb..b61c743f 100755 --- a/script/public-inbox-convert +++ b/script/public-inbox-convert @@ -52,7 +52,9 @@ Cwd->import('abs_path'); require PublicInbox::Config; require PublicInbox::InboxWritable; -$old_dir = abs_path($old_dir); +my $abs = abs_path($old_dir); +die "failed to resolve $old_dir: $!\n" if (!defined($abs)); + my $cfg = PublicInbox::Config->new; my $old; $cfg->each_inbox(sub { @@ -72,6 +74,7 @@ if ($old) { } die "Only conversion from v1 inboxes is supported\n" if $old->version >= 2; +require File::Spec; require PublicInbox::Admin; my $detected = PublicInbox::Admin::detect_indexlevel($old); $old->{indexlevel} //= $detected; @@ -85,7 +88,7 @@ if ($opt->{'index'}) { } local %ENV = (%$env, %ENV) if $env; my $new = { %$old }; -$new->{inboxdir} = abs_path($new_dir); +$new->{inboxdir} = File::Spec->canonpath($new_dir); $new->{version} = 2; $new = PublicInbox::InboxWritable->new($new, { nproc => $opt->{jobs} }); $new->{-no_fsync} = 1 if !$opt->{fsync}; diff --git a/script/public-inbox-init b/script/public-inbox-init index ae4a575c..c775eb31 100755 --- a/script/public-inbox-init +++ b/script/public-inbox-init @@ -138,8 +138,9 @@ close($fh) or die "failed to close $pi_config_tmp: $!\n"; my $pfx = "publicinbox.$name"; my @x = (qw/git config/, "--file=$pi_config_tmp"); -require Cwd; -$inboxdir = Cwd::abs_path($inboxdir); +require File::Spec; +$inboxdir = File::Spec->canonpath($inboxdir); + die "`\\n' not allowed in `$inboxdir'\n" if $inboxdir =~ /\n/s; if (-f "$inboxdir/inbox.lock") { if (!defined $version) { @@ -185,6 +186,11 @@ if ($skip_docdata) { $ibx->{-skip_docdata} = $skip_docdata; } $ibx->init_inbox(0, $skip_epoch, $skip_artnum); +require Cwd; +my $tmp = Cwd::abs_path($inboxdir); +defined($tmp) or die "failed to resolve $inboxdir: $!\n"; +$inboxdir = $tmp; +die "`\\n' not allowed in `$inboxdir'\n" if $inboxdir =~ /\n/s; # needed for git prior to v2.1.0 umask(0077) if defined $perm; diff --git a/t/convert-compact.t b/t/convert-compact.t index 26a8fca0..575262e8 100644 --- a/t/convert-compact.t +++ b/t/convert-compact.t @@ -78,33 +78,33 @@ ok(defined($hwm) && $hwm > 0, "highwater mark set #$hwm"); $cmd = [ '-convert', '--no-index', $ibx->{inboxdir}, "$tmpdir/no-index" ]; ok(run_script($cmd, undef, $rdr), 'convert --no-index works'); -$cmd = [ '-convert', $ibx->{inboxdir}, "$tmpdir/v2" ]; +$cmd = [ '-convert', $ibx->{inboxdir}, "$tmpdir/x/v2" ]; ok(run_script($cmd, undef, $rdr), 'convert works'); -@xdir = glob("$tmpdir/v2/xap*/*"); +@xdir = glob("$tmpdir/x/v2/xap*/*"); foreach (@xdir) { my @st = stat($_); is($st[2] & 07777, -f _ ? 0644 : 0755, 'sharedRepository respected after convert'); } -$cmd = [ '-compact', "$tmpdir/v2" ]; +$cmd = [ '-compact', "$tmpdir/x/v2" ]; my $env = { NPROC => 2 }; ok(run_script($cmd, $env, $rdr), 'v2 compact works'); -$ibx->{inboxdir} = "$tmpdir/v2"; +$ibx->{inboxdir} = "$tmpdir/x/v2"; $ibx->{version} = 2; is($ibx->mm->num_highwater, $hwm, 'highwater mark unchanged in v2 inbox'); -@xdir = glob("$tmpdir/v2/xap*/*"); +@xdir = glob("$tmpdir/x/v2/xap*/*"); foreach (@xdir) { my @st = stat($_); is($st[2] & 07777, -f _ ? 0644 : 0755, 'sharedRepository respected after v2 compact'); } -is(((stat("$tmpdir/v2/msgmap.sqlite3"))[2]) & 07777, 0644, +is(((stat("$tmpdir/x/v2/msgmap.sqlite3"))[2]) & 07777, 0644, 'sharedRepository respected for v2 msgmap'); -@xdir = (glob("$tmpdir/v2/git/*.git/objects/*/*"), - glob("$tmpdir/v2/git/*.git/objects/pack/*")); +@xdir = (glob("$tmpdir/x/v2/git/*.git/objects/*/*"), + glob("$tmpdir/x/v2/git/*.git/objects/pack/*")); foreach (@xdir) { my @st = stat($_); is($st[2] & 07777, -f _ ? 0444 : 0755, @@ -116,12 +116,12 @@ is(scalar @$msgs, 1, 'only one message in history'); $ibx = undef; $err = ''; -$cmd = [ qw(-index -j0 --reindex -c), "$tmpdir/v2" ]; +$cmd = [ qw(-index -j0 --reindex -c), "$tmpdir/x/v2" ]; ok(run_script($cmd, undef, $rdr), '--reindex -c'); like($err, qr/xapian-compact/, 'xapian-compact ran (-c)'); $rdr->{2} = \(my $err2 = ''); -$cmd = [ qw(-index -j0 --reindex -cc), "$tmpdir/v2" ]; +$cmd = [ qw(-index -j0 --reindex -cc), "$tmpdir/x/v2" ]; ok(run_script($cmd, undef, $rdr), '--reindex -c -c'); like($err2, qr/xapian-compact/, 'xapian-compact ran (-c -c)'); ok(($err2 =~ tr/\n/\n/) > ($err =~ tr/\n/\n/), '-compacted twice'); diff --git a/t/init.t b/t/init.t index a5a9debc..dba59231 100644 --- a/t/init.t +++ b/t/init.t @@ -59,6 +59,18 @@ sub quiet_fail { like($err, qr/`\\n' not allowed in `/s, 'reported \\n'); is_deeply([glob("$tmpdir/.public-inbox/pi-init-*")], [], 'no junk files left behind'); + + # "git init" does this, too + $cmd = [ '-init', 'deep-non-existent', "$tmpdir/a/b/c/d", + qw(http://example.com/abcd abcd@example.com) ]; + $err = ''; + ok(run_script($cmd, $env, $rdr), 'initializes non-existent hierarchy'); + ok(-d "$tmpdir/a/b/c/d", 'directory created'); + open my $fh, '>', "$tmpdir/d" or BAIL_OUT "open: $!"; + close $fh; + $cmd = [ '-init', 'd-f-conflict', "$tmpdir/d/f/conflict", + qw(http://example.com/conflict onflict@example.com) ]; + ok(!run_script($cmd, $env, $rdr), 'fails on D/F conflict'); } SKIP: { -- cgit v1.2.3-24-ge0c7