Explorar el Código

Dpkg::Conf: Switch implementation to be hash based

Store the options in a hash instead of a list so that we can more easily
retrieve them. And add two accessors and an option to the filter method
to control its behavior.
Guillem Jover hace 10 años
padre
commit
94e241761c
Se han modificado 3 ficheros con 103 adiciones y 41 borrados
  1. 2 0
      debian/changelog
  2. 70 18
      scripts/Dpkg/Conf.pm
  3. 31 23
      scripts/t/Dpkg_Conf.t

+ 2 - 0
debian/changelog

@@ -79,6 +79,8 @@ dpkg (1.18.5) UNRELEASED; urgency=medium
     - Error out on source packages without any strong digests in
     - Error out on source packages without any strong digests in
       Dpkg::Source::Package, used by dpkg-source --extract, which can still
       Dpkg::Source::Package, used by dpkg-source --extract, which can still
       be disabled with --no-check.
       be disabled with --no-check.
+    - Switch Dpkg::Conf implementation to be hash based, add two new accessors
+      and a new option to the filter method to use the old behavior.
   * Build system:
   * Build system:
     - Fix building development documentation.
     - Fix building development documentation.
     - Remove unused UA_LIBS variable.
     - Remove unused UA_LIBS variable.

+ 70 - 18
scripts/Dpkg/Conf.pm

@@ -18,7 +18,7 @@ package Dpkg::Conf;
 use strict;
 use strict;
 use warnings;
 use warnings;
 
 
-our $VERSION = '1.01';
+our $VERSION = '1.02';
 
 
 use Dpkg::Gettext;
 use Dpkg::Gettext;
 use Dpkg::ErrorHandling;
 use Dpkg::ErrorHandling;
@@ -58,7 +58,7 @@ sub new {
     my $class = ref($this) || $this;
     my $class = ref($this) || $this;
 
 
     my $self = {
     my $self = {
-	options => [],
+	options => {},
 	allow_short => 0,
 	allow_short => 0,
     };
     };
     foreach my $opt (keys %opts) {
     foreach my $opt (keys %opts) {
@@ -79,7 +79,46 @@ Returns the list of options that can be parsed like @ARGV.
 
 
 sub get_options {
 sub get_options {
     my $self = shift;
     my $self = shift;
-    return @{$self->{options}};
+    my @options;
+
+    foreach my $name (sort keys %{$self->{options}}) {
+        my $value = $self->{options}->{$name};
+
+        $name = "--$name" unless $name =~ /^-/;
+        if (defined $value) {
+            push @options, "$name=$value";
+        } else {
+            push @options, $name;
+        }
+    }
+
+    return @options;
+}
+
+=item $value = $conf->get($name)
+
+Returns the value of option $name, where the option name should not have "--"
+prefixed. If the option is not present the function will return undef.
+
+=cut
+
+sub get {
+    my ($self, $name) = @_;
+
+    return $self->{options}->{$name};
+}
+
+=item $conf->set($name, $value)
+
+Set the $value of option $name, where the option name should not have "--"
+prefixed.
+
+=cut
+
+sub set {
+    my ($self, $name, $value) = @_;
+
+    $self->{options}->{$name} = $value;
 }
 }
 
 
 =item $conf->load($file)
 =item $conf->load($file)
@@ -111,13 +150,11 @@ sub parse {
 	}
 	}
 	if (/^([^=]+)(?:=(.*))?$/) {
 	if (/^([^=]+)(?:=(.*))?$/) {
 	    my ($name, $value) = ($1, $2);
 	    my ($name, $value) = ($1, $2);
-	    $name = "--$name" unless $name =~ /^-/;
 	    if (defined $value) {
 	    if (defined $value) {
 		$value =~ s/^"(.*)"$/$1/ or $value =~ s/^'(.*)'$/$1/;
 		$value =~ s/^"(.*)"$/$1/ or $value =~ s/^'(.*)'$/$1/;
-		push @{$self->{options}}, "$name=$value";
-	    } else {
-		push @{$self->{options}}, $name;
 	    }
 	    }
+	    $name =~ s/^--//;
+	    $self->{options}->{$name} = $value;
 	    $count++;
 	    $count++;
 	} else {
 	} else {
 	    warning(g_('invalid syntax for option in %s, line %d'), $desc, $.);
 	    warning(g_('invalid syntax for option in %s, line %d'), $desc, $.);
@@ -126,12 +163,12 @@ sub parse {
     return $count;
     return $count;
 }
 }
 
 
-=item $conf->filter(remove => $rmfunc)
-
-=item $conf->filter(keep => $keepfunc)
+=item $conf->filter(%opts)
 
 
 Filter the list of options, either removing or keeping all those that
 Filter the list of options, either removing or keeping all those that
-return true when &$rmfunc($option) or &keepfunc($option) is called.
+return true when &$opts{remove}($option) or &opts{keep}($option) is called.
+If $opts{format_argv} is true the long options passed to the filter
+functions will have "--" prefixed.
 
 
 =cut
 =cut
 
 
@@ -140,8 +177,16 @@ sub filter {
     my $remove = $opts{remove} // sub { 0 };
     my $remove = $opts{remove} // sub { 0 };
     my $keep = $opts{keep} // sub { 1 };
     my $keep = $opts{keep} // sub { 1 };
 
 
-    @{$self->{options}} = grep { not &$remove($_) and &$keep($_) }
-                               @{$self->{options}};
+    foreach my $name (keys %{$self->{options}}) {
+        my $option = $name;
+
+        if ($opts{format_argv}) {
+            $option = "--$name" unless $name =~ /^-/;
+        }
+        if (&$remove($option) or not &$keep($option)) {
+            delete $self->{options}->{$name};
+        }
+    }
 }
 }
 
 
 =item $string = $conf->output($fh)
 =item $string = $conf->output($fh)
@@ -162,11 +207,12 @@ Save the options in a file.
 sub output {
 sub output {
     my ($self, $fh) = @_;
     my ($self, $fh) = @_;
     my $ret = '';
     my $ret = '';
-    foreach my $opt ($self->get_options()) {
-	$opt =~ s/^--//;
-	if ($opt =~ s/^([^=]+)=/$1 = "/) {
-	    $opt .= '"';
-	}
+
+    foreach my $name (sort keys %{$self->{options}}) {
+	my $value = $self->{options}->{$name};
+
+	my $opt = $name;
+	$opt .= " = \"$value\"" if defined $value;
 	$opt .= "\n";
 	$opt .= "\n";
 	print { $fh } $opt if defined $fh;
 	print { $fh } $opt if defined $fh;
 	$ret .= $opt;
 	$ret .= $opt;
@@ -178,6 +224,12 @@ sub output {
 
 
 =head1 CHANGES
 =head1 CHANGES
 
 
+=head2 Version 1.02 (dpkg 1.18.5)
+
+New option: Accept new option 'format_argv' in $conf->filter().
+
+New methods: $conf->get(), $conf->set().
+
 =head2 Version 1.01 (dpkg 1.15.8)
 =head2 Version 1.01 (dpkg 1.15.8)
 
 
 New method: $conf->filter()
 New method: $conf->filter()

+ 31 - 23
scripts/t/Dpkg_Conf.t

@@ -16,7 +16,7 @@
 use strict;
 use strict;
 use warnings;
 use warnings;
 
 
-use Test::More tests => 9;
+use Test::More tests => 14;
 
 
 BEGIN {
 BEGIN {
     use_ok('Dpkg::Conf');
     use_ok('Dpkg::Conf');
@@ -28,18 +28,17 @@ my $datadir = $srcdir . '/t/Dpkg_Conf';
 my ($conf, $count, @opts);
 my ($conf, $count, @opts);
 
 
 my @expected_long_opts = (
 my @expected_long_opts = (
+'--l=v',
+'--option-dash=value-dash',
 '--option-double-quotes=value double quotes',
 '--option-double-quotes=value double quotes',
+'--option-equal=value-equal=subvalue-equal',
+'--option-indent=value-indent',
+'--option-name=value-name',
+'--option-noequal=value-noequal',
+'--option-simple',
 '--option-single-quotes=value single quotes',
 '--option-single-quotes=value single quotes',
 '--option-space=value words space',
 '--option-space=value words space',
-qw(
---option-name=value-name
---option-indent=value-indent
---option-equal=value-equal=subvalue-equal
---option-noequal=value-noequal
---option-simple
---option-dash=value-dash
---l=v
-));
+);
 my @expected_short_opts = qw(
 my @expected_short_opts = qw(
 -o=vd
 -o=vd
 -s
 -s
@@ -59,37 +58,45 @@ $count = $conf->load("$datadir/config-mixed");
 is($count, 12, 'Load a config file, mixed options');
 is($count, 12, 'Load a config file, mixed options');
 
 
 @opts = $conf->get_options();
 @opts = $conf->get_options();
-my @expected_mixed_opts = ( @expected_long_opts, @expected_short_opts );
+my @expected_mixed_opts = ( @expected_short_opts, @expected_long_opts );
 is_deeply(\@opts, \@expected_mixed_opts, 'Parse mixed options');
 is_deeply(\@opts, \@expected_mixed_opts, 'Parse mixed options');
 
 
 my $expected_mixed_output = <<'MIXED';
 my $expected_mixed_output = <<'MIXED';
+-o = "vd"
+-s
+l = "v"
+option-dash = "value-dash"
 option-double-quotes = "value double quotes"
 option-double-quotes = "value double quotes"
-option-single-quotes = "value single quotes"
-option-space = "value words space"
-option-name = "value-name"
-option-indent = "value-indent"
 option-equal = "value-equal=subvalue-equal"
 option-equal = "value-equal=subvalue-equal"
+option-indent = "value-indent"
+option-name = "value-name"
 option-noequal = "value-noequal"
 option-noequal = "value-noequal"
 option-simple
 option-simple
-option-dash = "value-dash"
-l = "v"
--o = "vd"
--s
+option-single-quotes = "value single quotes"
+option-space = "value words space"
 MIXED
 MIXED
 
 
 is($conf->output, $expected_mixed_output, 'Output mixed options');
 is($conf->output, $expected_mixed_output, 'Output mixed options');
 
 
+is($conf->get('-o'), 'vd', 'Get option -o');
+is($conf->get('option-dash'), 'value-dash', 'Get option-dash');
+is($conf->get('option-space'), 'value words space', 'Get option-space');
+
+is($conf->get('manual-option'), undef, 'Get non-existent option');
+$conf->set('manual-option', 'manual value');
+is($conf->get('manual-option'), 'manual value', 'Get manual option');
+
 my $expected_filter;
 my $expected_filter;
 
 
 $expected_filter = <<'FILTER';
 $expected_filter = <<'FILTER';
-l = "v"
 -o = "vd"
 -o = "vd"
 -s
 -s
+l = "v"
 FILTER
 FILTER
 
 
 $conf = Dpkg::Conf->new(allow_short => 1);
 $conf = Dpkg::Conf->new(allow_short => 1);
 $conf->load("$datadir/config-mixed");
 $conf->load("$datadir/config-mixed");
-$conf->filter(remove => sub { $_[0] =~ m/^--option/ });
+$conf->filter(format_argv => 1, remove => sub { $_[0] =~ m/^--option/ });
 is($conf->output, $expected_filter, 'Filter remove');
 is($conf->output, $expected_filter, 'Filter remove');
 
 
 $expected_filter = <<'FILTER';
 $expected_filter = <<'FILTER';
@@ -99,7 +106,7 @@ FILTER
 
 
 $conf = Dpkg::Conf->new(allow_short => 1);
 $conf = Dpkg::Conf->new(allow_short => 1);
 $conf->load("$datadir/config-mixed");
 $conf->load("$datadir/config-mixed");
-$conf->filter(keep => sub { $_[0] =~ m/^--option-[a-z]+-quotes/ });
+$conf->filter(keep => sub { $_[0] =~ m/^option-[a-z]+-quotes/ });
 is($conf->output, $expected_filter, 'Filter keep');
 is($conf->output, $expected_filter, 'Filter keep');
 
 
 $expected_filter = <<'FILTER';
 $expected_filter = <<'FILTER';
@@ -108,7 +115,8 @@ FILTER
 
 
 $conf = Dpkg::Conf->new(allow_short => 1);
 $conf = Dpkg::Conf->new(allow_short => 1);
 $conf->load("$datadir/config-mixed");
 $conf->load("$datadir/config-mixed");
-$conf->filter(remove => sub { $_[0] =~ m/^--option/ },
+$conf->filter(format_argv => 1,
+              remove => sub { $_[0] =~ m/^--option/ },
               keep => sub { $_[0] =~ m/^--/ });
               keep => sub { $_[0] =~ m/^--/ });
 is($conf->output, $expected_filter, 'Filter keep and remove');
 is($conf->output, $expected_filter, 'Filter keep and remove');