]> Sergey Matveev's repositories - public-inbox.git/commitdiff
config: each_inbox iteration preserves config order
authorEric Wong <e@80x24.org>
Sun, 20 Jan 2019 20:56:22 +0000 (20:56 +0000)
committerEric Wong <e@80x24.org>
Sun, 20 Jan 2019 20:59:30 +0000 (20:59 +0000)
For cross-inbox Message-ID resolution; having some sort of
stable ordering makes the most sense.  Relying on the
order of the config file seems most natural and allows us
to avoid introducing yet another configuration knob.

lib/PublicInbox/Config.pm
t/config.t

index cead7fc287c1220b7af6905f2d04132d2c2a0a1f..ccfc114f9888a7da1711ab9a582c825470afc913 100644 (file)
@@ -90,13 +90,22 @@ sub lookup_name ($$) {
 
 sub each_inbox {
        my ($self, $cb) = @_;
-       my %seen;
-       foreach my $k (keys %$self) {
-               $k =~ m!\Apublicinbox\.([^/]+)\.mainrepo\z! or next;
-               next if $seen{$1};
-               $seen{$1} = 1;
-               my $ibx = lookup_name($self, $1) or next;
-               $cb->($ibx);
+       if (my $section_order = $self->{-section_order}) {
+               foreach my $section (@$section_order) {
+                       next if $section !~ m!\Apublicinbox\.([^/]+)\z!;
+                       $self->{"publicinbox.$1.mainrepo"} or next;
+                       my $ibx = lookup_name($self, $1) or next;
+                       $cb->($ibx);
+               }
+       } else {
+               my %seen;
+               foreach my $k (keys %$self) {
+                       $k =~ m!\Apublicinbox\.([^/]+)\.mainrepo\z! or next;
+                       next if $seen{$1};
+                       $seen{$1} = 1;
+                       my $ibx = lookup_name($self, $1) or next;
+                       $cb->($ibx);
+               }
        }
 }
 
@@ -137,7 +146,7 @@ sub default_file {
 
 sub git_config_dump {
        my ($file) = @_;
-       my ($in, $out);
+       my (%section_seen, @section_order);
        my @cmd = (qw/git config/, "--file=$file", '-l');
        my $cmd = join(' ', @cmd);
        my $fh = popen_rd(\@cmd) or die "popen_rd failed for $file: $!\n";
@@ -146,8 +155,14 @@ sub git_config_dump {
        while (defined(my $line = <$fh>)) {
                chomp $line;
                my ($k, $v) = split(/=/, $line, 2);
-               my $cur = $rv{$k};
 
+               my ($section) = ($k =~ /\A(\S+)\.[^\.]+\z/);
+               unless (defined $section_seen{$section}) {
+                       $section_seen{$section} = 1;
+                       push @section_order, $section;
+               }
+
+               my $cur = $rv{$k};
                if (defined $cur) {
                        if (ref($cur) eq "ARRAY") {
                                push @$cur, $v;
@@ -159,6 +174,7 @@ sub git_config_dump {
                }
        }
        close $fh or die "failed to close ($cmd) pipe: $?";
+       $rv{-section_order} = \@section_order;
 
        \%rv;
 }
index 5f0a95ba746bf80b8a0c6ac4c57d006f422e1180..7531fd7552aac14d88855e3f163e12d564264ecb 100644 (file)
@@ -150,4 +150,23 @@ for my $s (@valid) {
        ok(PublicInbox::Config::valid_inbox_name($s), "$d name accepted");
 }
 
+{
+       my $f = "$tmpdir/ordered";
+       open my $fh, '>', $f or die "open: $!";
+       my @expect;
+       foreach my $i (0..3) {
+               push @expect, "$i";
+               print $fh <<"" or die "print: $!";
+[publicinbox "$i"]
+       mainrepo = /path/to/$i.git
+       address = $i\@example.com
+
+       }
+       close $fh or die "close: $!";
+       my $cfg = PublicInbox::Config->new($f);
+       my @result;
+       $cfg->each_inbox(sub { push @result, $_[0]->{name} });
+       is_deeply(\@result, \@expect);
+}
+
 done_testing();