#!/usr/bin/perl -w use DBI; use Getopt::Long; use File::Path qw(make_path); use File::Basename; use File::Spec::Functions qw(catfile); use Data::Dumper; use File::Temp qw(tempfile); use strict; my @sections; my $print_sections = 0; my $usage_help = "usage: ".basename($0)." db1 [db2] [out_dir] [--print-sections] [--use-alignment] [--section=section{1,..N}]\n"; my $opts1 = {}; my $opts2 = {}; my $use_alignment = 0; GetOptions ("section=s" => \@sections, "print-sections" => \$print_sections, "use-alignment" => \$use_alignment) or die "$usage_help"; my ($db1, $db2, $out_dir) = @ARGV; die "$usage_help" unless (defined $db1 && -f $db1); die "$usage_help" unless ($print_sections || ((defined $db2 && -f $db2) && (defined $out_dir))); sub connect_db { my ($database) = @_; my $driver = "SQLite"; my $dsn = "DBI:$driver:dbname=$database"; my $userid = ""; my $password = ""; my $dbh = DBI->connect($dsn, $userid, $password, { RaiseError => 1 }) or die $DBI::errstr; return $dbh; } sub read_db { my ($db, $opts) = @_; my $dbh = connect_db($db); my $stmt = qq(SELECT PATH,NAME,VALUE,HELP from OPTIONS;); my $sth = $dbh->prepare($stmt); my $rv = $sth->execute() or die $DBI::errstr; if ($rv < 0){ print $DBI::errstr; } while (my @row = $sth->fetchrow_array()) { my ($path, $opt, $value, $help) = @row; $opts->{$path}->{$opt} = { 'value' => $value, 'help' => $help } } $dbh->disconnect(); } sub format_option { my ($opt, $opt_name) = @_; my $v = $opt->{'value'}; my $h = ''; $h = "|:::|".$opt->{'help'} if ($v =~ /#{10}/); return " $opt_name=$v$h\n"; } sub section2txt_view { my ($opts_s1, $opts_s2) = @_; my ($sview_1, $sview_2) = ('',''); my @handled_opts; foreach my $opt (sort keys %$opts_s1) { if (exists $opts_s2->{$opt}) { my $fo = format_option($opts_s1->{$opt}, $opt); $sview_1 .= "$fo"; $fo = format_option($opts_s2->{$opt}, $opt); $sview_2 .= "$fo"; push (@handled_opts, $opt); } } foreach (@handled_opts) { delete $opts_s1->{$_}; delete $opts_s2->{$_}; } foreach my $opt (sort keys %$opts_s1) { my $fo = format_option($opts_s1->{$opt}, $opt); $sview_1 .= "$fo"; $sview_2 .= "\n" if ($use_alignment); } foreach my $opt (sort keys %$opts_s2) { my $fo = format_option($opts_s2->{$opt}, $opt); $sview_2 .= "$fo"; $sview_1 .= "\n" if ($use_alignment); } return ($sview_1, $sview_2); } read_db($db1, $opts1); read_db($db2, $opts2) if (defined $db2); if ($print_sections) { print "$db1 sections:\n"; print "\t$_\n" for (sort keys %$opts1); if (defined $db2) { print "\n\n$db2 sections:\n"; print "\t$_\n" for (sort keys %$opts2); } exit 0; } my ($view_1, $view_2) = ('',''); unless (@sections) { my %unique_sects; my @keys1 = (sort keys %$opts1); my @keys2 = (sort keys %$opts2); $unique_sects{$_} = 1 for (keys %$opts1); $unique_sects{$_} = 1 for (keys %$opts2); @sections = (sort keys %unique_sects); } foreach my $sect (@sections) { my ($sview_1, $sview_2) = ('',''); $view_1 .= "$sect\n"; $view_2 .= "$sect\n"; print "process section: $sect\n"; if ((exists $opts1->{$sect}) && (exists $opts2->{$sect})) { ($sview_1, $sview_2) = section2txt_view($opts1->{$sect}, $opts2->{$sect}); } elsif (exists $opts1->{$sect}) { ($sview_1, $sview_2) = section2txt_view($opts1->{$sect}, {}); } elsif (exists $opts2->{$sect}) { ($sview_1, $sview_2) = section2txt_view({}, $opts2->{$sect}); } $view_1 .= $sview_1; $view_2 .= $sview_2; } unless (-d $out_dir) { make_path($out_dir) or die "Couldn't create dir $!"; } my $db1_name = basename($db1); my $db2_name = basename($db2); if ($db1_name eq $db2_name) { $db1_name .= '.1'; $db2_name .= '.2'; } $db1_name .= '.txt'; $db2_name .= '.txt'; my $fname_1 = catfile($out_dir, $db1_name); open (my $fh1, '>', $fname_1) or die "Couldn't open $fname_1: $!"; print $fh1 $view_1 or die "$!"; my $fname_2 = catfile($out_dir, $db2_name); open (my $fh2, '>', $fname_2) or die "Couldn't open $fname_2: $!"; print $fh2 $view_2 or die "$!"; if ($use_alignment) { system("vim -O $fname_1 $fname_2"); } else { system("vimdiff $fname_1 $fname_2"); } close $fh1; close $fh2;