From 1006eba2fc0068134bde079956dc835f488918da Mon Sep 17 00:00:00 2001 From: Sitaram Chamarty Date: Fri, 1 Apr 2011 06:39:04 +0530 Subject: [PATCH] allow the include statement to use globs (bonus: we now have a test case for "include" itself, should it ever decide to take an unplanned vacation!) --- doc/gitolite.conf.mkd | 9 +++++++ src/gl-compile-conf | 23 ++++++++++++---- t/t68-include | 62 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 t/t68-include diff --git a/doc/gitolite.conf.mkd b/doc/gitolite.conf.mkd index ce2efba..e7ac5c7 100644 --- a/doc/gitolite.conf.mkd +++ b/doc/gitolite.conf.mkd @@ -71,6 +71,15 @@ will include the contents of the file "foo.conf" from the same directory as the main config file. You can also use an absolute path if you like, although in the interests of cloning the admin-repo sanely you should avoid doing this! +You can also use a glob, as in: + + include "*.conf" + +which will include all the ".conf" files from the directory in which the main +config file exists. + +Files that have been already processed once are skipped, with a warning. + [Advanced users: the include statement cannot be used inside a delegated config file, for security reasons]. diff --git a/src/gl-compile-conf b/src/gl-compile-conf index f0bfdf1..9799841 100755 --- a/src/gl-compile-conf +++ b/src/gl-compile-conf @@ -93,10 +93,19 @@ sub expand_list return @new_list; } +sub device_inode { + my $file = shift; + return join("/", (stat $file)[0,1]); +} + # ---------------------------------------------------------------------------- # "compile" GL conf # ---------------------------------------------------------------------------- +# detect recursion in include files; see processing of "include" statement later +our %included; +$included{device_inode("conf/gitolite.conf")}++; + sub check_fragment_repo_disallowed { # trying to set access for $repo (='foo')... @@ -250,12 +259,16 @@ sub parse_conf_line # include elsif ($line =~ /^include "(.+)"/) { - my $file = $1; - $file = "$GL_ADMINDIR/conf/$file" unless $file =~ /^\//; - die "$ABRT $fragment attempting to include configuration\n" if $fragment ne 'master'; - die "$ABRT included file not found: '$file'\n" unless -f $file; + my $include_glob = $1; + for my $file (glob($include_glob =~ m(^/) ? $include_glob : "conf/$include_glob")) { + die "$ABRT $fragment attempting to include configuration\n" if $fragment ne 'master'; + die "$ABRT included file not found: '$file'\n" unless -f $file; - parse_conf_file( $file, $fragment ); + my $file_id = device_inode($file); + warn("$WARN $file already included\n"), next if ($included{$file_id}++); + + parse_conf_file( $file, $fragment ); + } } # very simple syntax for the gitweb description of repo; one of: # reponame = "some description string" diff --git a/t/t68-include b/t/t68-include new file mode 100644 index 0000000..f1be71d --- /dev/null +++ b/t/t68-include @@ -0,0 +1,62 @@ +cd $TESTDIR +$TESTDIR/rollback || die "rollback failed" +# ---------- + +name "setup" +echo " + repo foo + RW = u1 u2 +" | ugc +notexpect ABORT +expect "remote: creating foo..." +expect "remote: Initialized empty Git repository in $TEST_BASE_FULL/foo.git/" +expect "remote: u3(u3.pub),u4(u4.pub),u5(u5.pub),u6(u6.pub)" + +name "add i1.conf, i2.conf, and i3" +cd ~/gitolite-admin +echo " + repo bar + RW = u3 u4 +" > conf/i1.conf +echo " + repo baz + RW = u5 +" > conf/i2.conf +echo " + repo frob + RW = u6 +" > conf/i3 +ugc < /dev/null +notexpect "remote: creating bar..." +notexpect "remote: Initialized empty Git repository in $TEST_BASE_FULL/bar.git/" +notexpect "remote: creating baz..." +notexpect "remote: Initialized empty Git repository in $TEST_BASE_FULL/baz.git/" + +name "add include statement" +echo " + include \"*.conf\" +" | ugc + +expect "remote: conf/gitolite.conf already included" +notexpect "remote: conf/i1.conf already included" +notexpect "remote: conf/i2.conf already included" +expect "remote: creating bar..." +expect "remote: Initialized empty Git repository in $TEST_BASE_FULL/bar.git/" +expect "remote: creating baz..." +expect "remote: Initialized empty Git repository in $TEST_BASE_FULL/baz.git/" +expect "remote: u6(u6.pub)" +notexpect frob +notexpect "u3(u3.pub)" +notexpect "u4(u4.pub)" +notexpect "u5(u5.pub)" + +name "append again to conf" +echo " + include \"i*.conf\" +" | ugc + +expect "remote: conf/gitolite.conf already included" +expect "remote: conf/i1.conf already included" +expect "remote: conf/i2.conf already included" + +name INTERNAL