<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">#!/usr/bin/perl -w
# This file was preprocessed, do not edit!


package Debconf::DbDriver::Stack;
use strict;
use Debconf::Log qw{:all};
use Debconf::Iterator;
use base 'Debconf::DbDriver::Copy';



use fields qw(stack stack_change_errors);


sub init {
	my $this=shift;

	if (! ref $this-&gt;{stack}) {
		my @stack;
		foreach my $name (split(/\s*,\s/, $this-&gt;{stack})) {
			my $driver=$this-&gt;driver($name);
			unless (defined $driver) {
				$this-&gt;error("could not find a db named \"$name\" to use in the stack (it should be defined before the stack in the config file)");
				next;
			}
			push @stack, $driver;
		}
		$this-&gt;{stack}=[@stack];
	}

	$this-&gt;error("no stack set") if ! ref $this-&gt;{stack};
	$this-&gt;error("stack is empty") if ! @{$this-&gt;{stack}};
}


sub iterator {
	my $this=shift;

	my %seen;
	my @iterators = map { $_-&gt;iterator } @{$this-&gt;{stack}};
	my $i = pop @iterators;
	my $iterator=Debconf::Iterator-&gt;new(callback =&gt; sub {
		for (;;) {
			while (my $ret = $i-&gt;iterate) {
				next if $seen{$ret};
				$seen{$ret}=1;
				return $ret;
			}
			$i = pop @iterators;
			return undef unless defined $i;
		}
	});
}


sub shutdown {
	my $this=shift;

	my $ret=1;
	foreach my $driver (@{$this-&gt;{stack}}) {
		$ret=undef if not defined $driver-&gt;shutdown(@_);
	}

	if ($this-&gt;{stack_change_errors}) {
		$this-&gt;error("unable to save changes to: ".
			join(" ", @{$this-&gt;{stack_change_errors}}));
		$ret=undef;
	}

	return $ret;
}


sub exists {
	my $this=shift;

	foreach my $driver (@{$this-&gt;{stack}}) {
		return 1 if $driver-&gt;exists(@_);
	}
	return 0;
}

sub _query {
	my $this=shift;
	my $command=shift;
	shift; # this again
	
	debug "db $this-&gt;{name}" =&gt; "trying to $command(@_) ..";
	foreach my $driver (@{$this-&gt;{stack}}) {
		if (wantarray) {
			my @ret=$driver-&gt;$command(@_);
			debug "db $this-&gt;{name}" =&gt; "$command done by $driver-&gt;{name}" if @ret;
			return @ret if @ret;
		}
		else {
			my $ret=$driver-&gt;$command(@_);
			debug "db $this-&gt;{name}" =&gt; "$command done by $driver-&gt;{name}" if defined $ret;
			return $ret if defined $ret;
		}
	}
	return; # failure
}

sub _change {
	my $this=shift;
	my $command=shift;
	shift; # this again
	my $item=shift;

	debug "db $this-&gt;{name}" =&gt; "trying to $command($item @_) ..";

	foreach my $driver (@{$this-&gt;{stack}}) {
		if ($driver-&gt;exists($item)) {
			last if $driver-&gt;{readonly}; # nope, hit a readonly one
			debug "db $this-&gt;{name}" =&gt; "passing to $driver-&gt;{name} ..";
			return $driver-&gt;$command($item, @_);
		}
	}

	my $src=0;

	foreach my $driver (@{$this-&gt;{stack}}) {
		if ($driver-&gt;exists($item)) {
			my $ret=$this-&gt;_nochange($driver, $command, $item, @_);
			if (defined $ret) {
				debug "db $this-&gt;{name}" =&gt; "skipped $command($item) as it would have no effect";
				return $ret;
			}

			$src=$driver;
			last
		}
	}

	my $writer;
	foreach my $driver (@{$this-&gt;{stack}}) {
		if ($driver == $src) {
			push @{$this-&gt;{stack_change_errors}}, $item;
			return;
		}
		if (! $driver-&gt;{readonly}) {
			if ($command eq 'addowner') {
				if ($driver-&gt;accept($item, $_[1])) {
					$writer=$driver;
					last;
				}
			}
			elsif ($driver-&gt;accept($item)) {
				$writer=$driver;
				last;
			}
		}
	}
	
	unless ($writer) {
		debug "db $this-&gt;{name}" =&gt; "FAILED $command";
		return;
	}

	if ($src) {		
		$this-&gt;copy($item, $src, $writer);
	}

	debug "db $this-&gt;{name}" =&gt; "passing to $writer-&gt;{name} ..";
	return $writer-&gt;$command($item, @_);
}

sub _nochange {
	my $this=shift;
	my $driver=shift;
	my $command=shift;
	my $item=shift;

	if ($command eq 'addowner') {
		my $value=shift;
		foreach my $owner ($driver-&gt;owners($item)) {
			return $value if $owner eq $value;
		}
		return;
	}
	elsif ($command eq 'removeowner') {
		my $value=shift;
		
		foreach my $owner ($driver-&gt;owners($item)) {
			return if $owner eq $value;
		}
		return $value; # no change
	}
	elsif ($command eq 'removefield') {
		my $value=shift;
		
		foreach my $field ($driver-&gt;fields($item)) {
			return if $field eq $value;
		}
		return $value; # no change
	}

	my @list;
	my $get;
	if ($command eq 'setfield') {
		@list=$driver-&gt;fields($item);
		$get='getfield';
	}
	elsif ($command eq 'setflag') {
		@list=$driver-&gt;flags($item);
		$get='getflag';
	}
	elsif ($command eq 'setvariable') {
		@list=$driver-&gt;variables($item);
		$get='getvariable';
	}
	else {
		$this-&gt;error("internal error; bad command: $command");
	}

	my $thing=shift;
	my $value=shift;
	my $currentvalue=$driver-&gt;$get($item, $thing);
	
	my $exists=0;
	foreach my $i (@list) {
		$exists=1, last if $thing eq $i;
	}
	return $currentvalue unless $exists;

	return $currentvalue if $currentvalue eq $value;
	return undef;
}

sub addowner	{ $_[0]-&gt;_change('addowner', @_)	}
sub removeowner { $_[0]-&gt;_change('removeowner', @_)	}
sub owners	{ $_[0]-&gt;_query('owners', @_)		}
sub getfield	{ $_[0]-&gt;_query('getfield', @_)		}
sub setfield	{ $_[0]-&gt;_change('setfield', @_)	}
sub removefield { $_[0]-&gt;_change('removefield', @_)	}
sub fields	{ $_[0]-&gt;_query('fields', @_)		}
sub getflag	{ $_[0]-&gt;_query('getflag', @_)		}
sub setflag	{ $_[0]-&gt;_change('setflag', @_)		}
sub flags	{ $_[0]-&gt;_query('flags', @_)		}
sub getvariable { $_[0]-&gt;_query('getvariable', @_)	}
sub setvariable { $_[0]-&gt;_change('setvariable', @_)	}
sub variables	{ $_[0]-&gt;_query('variables', @_)	}


1
</pre></body></html>