[PATCH] cvsserver: Complete rewrite of the configuration parser

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Move the configuration parsing to a separate GITCVS::config
module. Simplifies using the configuration in the rest of
the code.

Restrict parsed configuration variables to
^gitcvs\.((ext|pserver)\.)?
since we don't use anything else anyway. This also
reduces the risk of getting confused with arbitrary
variables (especially arbitrary subsection names).

Also fixes a bug where the config parser got confused
if a section had a subsection and a variable with the
same name.

Signed-off-by: Frank Lichtenheld <frank@xxxxxxxxxxxxxx>
---
 git-cvsserver.perl |  187 ++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 158 insertions(+), 29 deletions(-)

 Maybe a bit overkill if one only wants to solve the problem Junio discovered
 but I believe it's still worthwile.

 Has a lot of overlap with perl/Git.pm though...

 Not extensively tested but it at least passes the test cases and creates a useful
 log which should take care of the two main code paths (get_gitcvs and
 get_gitcvs_bool).

diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index 3e7bf5b..e51ffd0 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -174,27 +174,17 @@ sub req_Root
        return 0;
     }
 
-    my @gitvars = `git-config -l`;
-    if ($?) {
-       print "E problems executing git-config on the server -- this is not a git repository or the PATH is not set correctly.\n";
-        print "E \n";
-        print "error 1 - problem executing git-config\n";
-       return 0;
-    }
-    foreach my $line ( @gitvars )
-    {
-        next unless ( $line =~ /^(.*?)\.(.*?)(?:\.(.*?))?=(.*)$/ );
-        unless ($3) {
-            $cfg->{$1}{$2} = $4;
-        } else {
-            $cfg->{$1}{$2}{$3} = $4;
-        }
+    $cfg = GITCVS::config->new();
+
+    unless ($cfg) {
+	print "E problems executing git-config on the server -- ".
+	    "this is not a git repository or the PATH is not set correctly.\n";
+	print "E \n";
+	print "error 1 - problem executing git-config\n";
+	return 0;
     }
 
-    unless ( ($cfg->{gitcvs}{$state->{method}}{enabled}
-	      and $cfg->{gitcvs}{$state->{method}}{enabled} =~ /^\s*(1|true|yes)\s*$/i)
-	     or ($cfg->{gitcvs}{enabled}
-	      and $cfg->{gitcvs}{enabled} =~ /^\s*(1|true|yes)\s*$/i) )
+    unless ( $cfg->get_gitcvs_bool($state->{method},'enabled') )
     {
         print "E GITCVS emulation needs to be enabled on this repo\n";
         print "E the repo config file needs a [gitcvs] section added, and the parameter 'enabled' set to 1\n";
@@ -203,7 +193,7 @@ sub req_Root
         return 0;
     }
 
-    my $logfile = $cfg->{gitcvs}{$state->{method}}{logfile} || $cfg->{gitcvs}{logfile};
+    my $logfile = $cfg->get_gitcvs($state->{method},'logfile');
     if ( $logfile )
     {
         $log->setfile($logfile);
@@ -1967,7 +1957,7 @@ sub kopts_from_path
 	# what attributes apply to this path.
 
 	# Until then, take the setting from the config file
-    unless ( defined ( $cfg->{gitcvs}{allbinary} ) and $cfg->{gitcvs}{allbinary} =~ /^\s*(1|true|yes)\s*$/i )
+    unless ( $cfg->get_gitcvs_bool('allbinary') )
     {
 		# Return "" to give no special treatment to any path
 		return "";
@@ -1978,6 +1968,147 @@ sub kopts_from_path
     }
 }
 
+package GITCVS::config;
+
+####
+#### Copyright 2007 Frank Lichtenheld <frank@xxxxxxxxxxxxxx>.
+####
+
+use strict;
+use warnings;
+
+=head1 NAME
+
+GITCVS::config -- interface to the git configuration files
+
+=head1 DESCRIPTION
+
+Parses the output of "git-config -l" once and then allows to access that
+information
+
+=head1 METHODS
+
+=cut
+
+=head2 new
+
+Creates a new object and retrieves the config information.
+If retrieving the configuration fails, returns undef.
+
+=cut
+sub new
+{
+    my $class = shift;
+
+    my $self = {};
+
+    bless $self, $class;
+
+    $self->update() or return;
+
+    return $self;
+}
+
+=head2 update
+
+Update the config information. Is called by new on creation.
+Currently limits itself to the variables actually used by
+git-cvsserver since the output of git-config -l is not actually
+completly maschine-parsable. Multi-valued variables are not
+supported, the last value found is used.
+
+=cut
+sub update
+{
+    my $self = shift;
+
+    my @gitvars = `git-config -l`;
+    return if $?;
+    foreach my $line ( @gitvars )
+    {
+	next unless ( $line =~ /^((gitcvs)\.(?:(ext|pserver)\.)?([\w-]+))=(.*)$/ );
+	$self->{cfg}{$1} = $5;
+    }
+
+    return $self;
+}
+
+=head2 get
+
+Retrieve a configuration value. Give the key as array.
+
+=cut
+sub get {
+    my $self = shift;
+    my @key = @_;
+
+    unless (($#key == 1)
+	    || ($#key == 2)) {
+	return;
+    }
+
+    $key[0] = lc $key[0];
+    $key[-1] = lc $key[-1];
+
+    my $key = join('.',@key);
+    if (exists $self->{cfg}{$key}) {
+	return $self->{cfg}{$key};
+    }
+    return;
+}
+
+=head2 get_bool
+
+Retrieve a configuration value. Give the key as array.
+Normalizes the value to either undef, 0, or 1.
+
+=cut
+sub get_bool {
+    my $self = shift;
+    my $value = $self->get(@_);
+
+    return unless defined($value);
+    return 1 if $value =~ /^\s*(1|true|yes)\s*$/i;
+    return 0;
+}
+
+=head2 get_gitcvs
+
+Like get(), but automatically assumes gitcvs as section.
+If given two paramters, tries with second one alone
+if the first query gave no result.
+
+=cut
+sub get_gitcvs {
+    my $self = shift;
+    my @key = @_;
+
+    my $value = $self->get('gitcvs',@key);
+    if (!defined($value) && ($#key == 1)) {
+	$value = $self->get('gitcvs',$key[1]);
+    }
+
+    return $value;
+}
+
+=head2 get_gitcvs_bool
+
+What get_bool is to get that
+is get_gitcvs_bool to get_gitcvs.
+
+=cut
+sub get_gitcvs_bool {
+    my $self = shift;
+    my @key = @_;
+
+    my $value = $self->get_bool('gitcvs',@key);
+    if (!defined($value) && ($#key == 1)) {
+	$value = $self->get_bool('gitcvs',$key[1]);
+    }
+
+    return $value;
+}
+
 package GITCVS::log;
 
 ####
@@ -2189,14 +2320,12 @@ sub new
 
     die "Git repo '$self->{git_path}' doesn't exist" unless ( -d $self->{git_path} );
 
-    $self->{dbdriver} = $cfg->{gitcvs}{$state->{method}}{dbdriver} ||
-        $cfg->{gitcvs}{dbdriver} || "SQLite";
-    $self->{dbname} = $cfg->{gitcvs}{$state->{method}}{dbname} ||
-        $cfg->{gitcvs}{dbname} || "%Ggitcvs.%m.sqlite";
-    $self->{dbuser} = $cfg->{gitcvs}{$state->{method}}{dbuser} ||
-        $cfg->{gitcvs}{dbuser} || "";
-    $self->{dbpass} = $cfg->{gitcvs}{$state->{method}}{dbpass} ||
-        $cfg->{gitcvs}{dbpass} || "";
+    $self->{dbdriver} = $cfg->get_gitcvs($state->{method},'dbdriver') ||
+	"SQLite";
+    $self->{dbname} = $cfg->get_gitcvs($state->{method},'dbname') ||
+	"%Ggitcvs.%m.sqlite";
+    $self->{dbuser} = $cfg->get_gitcvs($state->{method},'dbuser') || "";
+    $self->{dbpass} = $cfg->get_gitcvs($state->{method},'dbpass') || "";
     my %mapping = ( m => $module,
                     a => $state->{method},
                     u => getlogin || getpwuid($<) || $<,
-- 
1.5.1.4

-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux