]> Sergey Matveev's repositories - public-inbox.git/commitdiff
v2: mirrors don't clobber msgs w/ reused Message-IDs
authorEric Wong <e@80x24.org>
Mon, 18 Oct 2021 05:09:05 +0000 (05:09 +0000)
committerEric Wong <e@80x24.org>
Mon, 18 Oct 2021 05:15:15 +0000 (05:15 +0000)
For odd messages with reused Message-IDs, the second message
showing up in a mirror (via git-fetch + -index) should never
clobber an entry with a different blob in over.

This is noticeable only if the messages arrive in-between
indexing runs.

Fixes: 4441a38481ed ("v2: index forwards (via `git log --reverse')")
MANIFEST
lib/PublicInbox/V2Writable.pm
t/v2index-late-dupe.t [new file with mode: 0644]

index b5aae77747dde457f8f7647b102ccada791ddf86..af1522d71bd124457d6a640ca794c2820df39c76 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -552,6 +552,7 @@ t/v1-add-remove-add.t
 t/v1reindex.t
 t/v2-add-remove-add.t
 t/v2dupindex.t
+t/v2index-late-dupe.t
 t/v2mda.t
 t/v2mirror.t
 t/v2reindex.t
index 3914383cc9d3deb239d3c88e3f19475439514576..ed5182ae846029a5af0837060335c7d7d8a45066 100644 (file)
@@ -813,8 +813,8 @@ sub index_oid { # cat_async callback
                        }
                }
        }
+       my $oidx = $self->{oidx};
        if (!defined($num)) { # reuse if reindexing (or duplicates)
-               my $oidx = $self->{oidx};
                for my $mid (@$mids) {
                        ($num, $mid0) = $oidx->num_mid0_for_oid($oid, $mid);
                        last if defined $num;
@@ -822,6 +822,11 @@ sub index_oid { # cat_async callback
        }
        $mid0 //= do { # is this a number we got before?
                $num = $arg->{mm_tmp}->num_for($mids->[0]);
+
+               # don't clobber existing if Message-ID is reused:
+               if (my $x = defined($num) ? $oidx->get_art($num) : undef) {
+                       undef($num) if $x->{blob} ne $oid;
+               }
                defined($num) ? $mids->[0] : undef;
        };
        if (!defined($num)) {
diff --git a/t/v2index-late-dupe.t b/t/v2index-late-dupe.t
new file mode 100644 (file)
index 0000000..c83e340
--- /dev/null
@@ -0,0 +1,37 @@
+# Copyright (C) all contributors <meta@public-inbox.org>
+# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
+#
+# this simulates a mirror path: git fetch && -index
+use strict; use v5.10.1; use PublicInbox::TestCommon;
+use Test::More; # redundant, used for bisect
+require_mods 'v2';
+require PublicInbox::Import;
+require PublicInbox::Inbox;
+require PublicInbox::Git;
+my ($tmpdir, $for_destroy) = tmpdir();
+my $inboxdir = "$tmpdir/i";
+PublicInbox::Import::init_bare(my $e0 = "$inboxdir/git/0.git");
+open my $fh, '>', "$inboxdir/inbox.lock" or xbail $!;
+my $git = PublicInbox::Git->new($e0);
+my $im = PublicInbox::Import->new($git, qw(i i@example.com));
+$im->{lock_path} = undef;
+$im->{path_type} = 'v2';
+my $eml = eml_load('t/plack-qp.eml');
+ok($im->add($eml), 'add original');
+$im->done;
+run_script([qw(-index -Lbasic), $inboxdir]);
+is($?, 0, 'basic index');
+my $ibx = PublicInbox::Inbox->new({ inboxdir => $inboxdir });
+my $orig = $ibx->over->get_art(1);
+
+my @mid = $eml->header_raw('Message-ID');
+$eml->header_set('Message-ID', @mid, '<extra@z>');
+ok($im->add($eml), 'add another');
+$im->done;
+run_script([qw(-index -Lbasic), $inboxdir]);
+is($?, 0, 'basic index again');
+
+my $after = $ibx->over->get_art(1);
+is_deeply($after, $orig, 'original unchanged') or note explain([$orig,$after]);
+
+done_testing;