From 056459aedaa95bab059f00d80faf27c9ec866c3e Mon Sep 17 00:00:00 2001 From: Sitaram Chamarty Date: Wed, 17 Aug 2011 19:46:07 +0530 Subject: [PATCH] fix sequencing for repo config statements Without this, complex mirroring scenarios will be unpredictable. For example (abbreviating "gitolite.mirror." to "gimo.") something as simple as this will not give "foo" his different mirror setup repo @all config gimo.master = "frodo" config gimo.slaves = "sam" repo foo config gimo.master = "sam" config gimo.slaves = "frodo gollum" repo foo bar RW = u1 Even worse things happen when you have wild cards. Now, however, they all come in the right sequence and the most recent one takes effect (unlike ACL rules, where the first match wins, because there you're trying to just find a match and get out, while here you're just mindlessly applying config lines in the right order). --- src/gitolite.pm | 24 ++++++++++++++++++------ src/gitolite_rc.pm | 2 +- src/gl-compile-conf | 5 +++-- t/out/t01-repo-groups.1 | 2 +- t/out/t01-repo-groups.1b | 2 +- t/out/t01-repo-groups.1bs | 2 +- t/out/t01-repo-groups.2 | 2 +- t/out/t02-user-groups.1 | 2 +- t/out/t02-user-groups.1b | 2 +- t/out/t02-user-groups.1bs | 2 +- t/out/t02-user-groups.2 | 2 +- t/out/t02-user-groups.2bs | 2 +- 12 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/gitolite.pm b/src/gitolite.pm index 79d329c..3c6e65d 100644 --- a/src/gitolite.pm +++ b/src/gitolite.pm @@ -426,12 +426,24 @@ sub setup_git_configs { my ($repo, $git_configs_p) = @_; - while ( my ($key, $value) = each(%{ $git_configs_p->{$repo} }) ) { - if ($value ne "") { - $value =~ s/^"(.*)"$/$1/; - system("git", "config", $key, $value); - } else { - system("git", "config", "--unset-all", $key); + # new_wild calls us without checking! + return unless $git_configs_p->{$repo}; + + # git_configs_p is a ref to a hash whose elements look like + # {"reponame"}{sequence_number}{"key"} = "value"; + + my %rch = %{ $git_configs_p->{$repo} }; + # %rch has elements that look like {sequence_number}{"key"} = "value" + for my $seq (sort { $a <=> $b } keys %rch) { + # and the final step is the repo config: {"key"} = "value" + my $rc = $rch{$seq}; + while ( my ($key, $value) = each(%{ $rc }) ) { + if ($value ne "") { + $value =~ s/^"(.*)"$/$1/; + system("git", "config", $key, $value); + } else { + system("git", "config", "--unset-all", $key); + } } } } diff --git a/src/gitolite_rc.pm b/src/gitolite_rc.pm index 4316215..03934c1 100644 --- a/src/gitolite_rc.pm +++ b/src/gitolite_rc.pm @@ -32,7 +32,7 @@ use Exporter 'import'; # real constants # ------------------------------------------------------------------------------ -$current_data_version = '1.7'; +$current_data_version = '2.0'; $ABRT = "\n\t\t***** ABORTING *****\n "; $WARN = "\n\t\t***** WARNING *****\n "; diff --git a/src/gl-compile-conf b/src/gl-compile-conf index 56d023c..8a57a17 100755 --- a/src/gl-compile-conf +++ b/src/gl-compile-conf @@ -49,8 +49,9 @@ open STDOUT, ">", "/dev/null" if (@ARGV and shift eq '-q'); # names of repos whose ACLs don't make it into the main compiled config file # copy above desc to lite.pm -- my %split_conf = (); -# rule sequence number +# rule and config sequence numbers my $rule_seq = 0; +my $config_seq = 0; # ... having been forced to use a list as described above, we lose some # efficiency due to the possibility of the same {ref, perms} pair showing up @@ -244,7 +245,7 @@ sub parse_conf_line die "$ABRT git config $key not allowed\ncheck GL_GITCONFIG_KEYS in the rc file for how to allow it\n" if (@matched < 1); for my $repo (@{ $repos_p }) # each repo in the current stanza { - $git_configs{$repo}{$key} = $value; + $git_configs{$repo}{$config_seq++}{$key} = $value; # force entry in %repos. Without this, a repo para with just a # config line and no ACLs gets ignored in the output diff --git a/t/out/t01-repo-groups.1 b/t/out/t01-repo-groups.1 index 2124ba6..cce7523 100644 --- a/t/out/t01-repo-groups.1 +++ b/t/out/t01-repo-groups.1 @@ -1,4 +1,4 @@ -$data_version = '1.7'; +$data_version = '2.0'; %repos = ( 'aa' => { 'R' => { diff --git a/t/out/t01-repo-groups.1b b/t/out/t01-repo-groups.1b index 3275bcf..3710cd3 100644 --- a/t/out/t01-repo-groups.1b +++ b/t/out/t01-repo-groups.1b @@ -1,4 +1,4 @@ -$data_version = '1.7'; +$data_version = '2.0'; %repos = ( 'aa' => { 'R' => { diff --git a/t/out/t01-repo-groups.1bs b/t/out/t01-repo-groups.1bs index a606c7a..3600f81 100644 --- a/t/out/t01-repo-groups.1bs +++ b/t/out/t01-repo-groups.1bs @@ -1,4 +1,4 @@ -$data_version = '1.7'; +$data_version = '2.0'; %repos = (); %split_conf = ( 'aa' => 1, diff --git a/t/out/t01-repo-groups.2 b/t/out/t01-repo-groups.2 index 25131c9..f8b6140 100644 --- a/t/out/t01-repo-groups.2 +++ b/t/out/t01-repo-groups.2 @@ -1,4 +1,4 @@ -$data_version = '1.7'; +$data_version = '2.0'; %repos = ( '@g1' => { '@g1' => [ diff --git a/t/out/t02-user-groups.1 b/t/out/t02-user-groups.1 index 05ba1fb..de27571 100644 --- a/t/out/t02-user-groups.1 +++ b/t/out/t02-user-groups.1 @@ -1,4 +1,4 @@ -$data_version = '1.7'; +$data_version = '2.0'; %repos = ( 'aa' => { 'R' => { diff --git a/t/out/t02-user-groups.1b b/t/out/t02-user-groups.1b index 16d4f1b..1f0ba5d 100644 --- a/t/out/t02-user-groups.1b +++ b/t/out/t02-user-groups.1b @@ -1,4 +1,4 @@ -$data_version = '1.7'; +$data_version = '2.0'; %repos = ( 'aa' => { 'R' => { diff --git a/t/out/t02-user-groups.1bs b/t/out/t02-user-groups.1bs index 9a36428..2c8af39 100644 --- a/t/out/t02-user-groups.1bs +++ b/t/out/t02-user-groups.1bs @@ -1,4 +1,4 @@ -$data_version = '1.7'; +$data_version = '2.0'; %repos = (); %split_conf = ( 'aa' => 1, diff --git a/t/out/t02-user-groups.2 b/t/out/t02-user-groups.2 index b4d5fd1..5e9a3c3 100644 --- a/t/out/t02-user-groups.2 +++ b/t/out/t02-user-groups.2 @@ -1,4 +1,4 @@ -$data_version = '1.7'; +$data_version = '2.0'; %repos = ( 'aa' => { '@g1' => [ diff --git a/t/out/t02-user-groups.2bs b/t/out/t02-user-groups.2bs index 09e1a33..7264595 100644 --- a/t/out/t02-user-groups.2bs +++ b/t/out/t02-user-groups.2bs @@ -1,4 +1,4 @@ -$data_version = '1.7'; +$data_version = '2.0'; %repos = (); %groups = ( '@g1' => {