From cfa8ff7c256e20f3240aed5f98d155c019788e3b Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 20 Jan 2019 20:56:22 +0000 Subject: config: each_inbox iteration preserves config order 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 | 34 +++++++++++++++++++++++++--------- t/config.t | 19 +++++++++++++++++++ 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/lib/PublicInbox/Config.pm b/lib/PublicInbox/Config.pm index cead7fc2..ccfc114f 100644 --- a/lib/PublicInbox/Config.pm +++ b/lib/PublicInbox/Config.pm @@ -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; } diff --git a/t/config.t b/t/config.t index 5f0a95ba..7531fd75 100644 --- a/t/config.t +++ b/t/config.t @@ -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(); -- cgit v1.2.3-24-ge0c7