updated perl scripts (Ken Estes).
authorjbj <devnull@localhost>
Mon, 17 Jan 2000 18:58:36 +0000 (18:58 +0000)
committerjbj <devnull@localhost>
Mon, 17 Jan 2000 18:58:36 +0000 (18:58 +0000)
CVS patchset: 3524
CVS date: 2000/01/17 18:58:36

CHANGES
rpm.spec
scripts/Makefile.am
scripts/Makefile.in
scripts/perl.prov
scripts/perl.req
scripts/rpmdiff
scripts/rpmdiff.cgi [new file with mode: 0644]
tools/javadeps.c

diff --git a/CHANGES b/CHANGES
index 60690a3..37eecc3 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -45,6 +45,7 @@
        - fix: resurrect relative path's in fprint lookup queries.
        - extract spec files from bzip'ped tarballs too on tar builds.
        - add %_rebuilddbpath macro to permit rebuilding db in new location.
+       - updated perl scripts (Ken Estes).
 
 3.0.2 -> 3.0.3
        - add --eval to find result of macro expansion.
index dd8e428..059e291 100644 (file)
--- a/rpm.spec
+++ b/rpm.spec
@@ -2,7 +2,7 @@ Summary: The Red Hat package management system.
 Name: rpm
 %define version 3.0.4
 Version: %{version}
-Release: 0.32
+Release: 0.33
 Group: System Environment/Base
 Source: ftp://ftp.rpm.org/pub/rpm/dist/rpm-3.0.x/rpm-%{version}.tar.gz
 Copyright: GPL
index 2d9600f..5da4602 100644 (file)
@@ -6,7 +6,8 @@ EXTRA_DIST = \
        brp-compress brp-strip brp-strip-comment-note \
        check-prereqs convertrpmrc.sh find-lang.sh find-prov.pl find-req.pl \
        freshen.sh get_magic.pl getpo.sh http.req magic.prov magic.req \
-       perl.prov perl.req rpmdiff u_pkg.sh vpkg-provides.sh vpkg-provides2.sh
+       perl.prov perl.req rpmdiff rpmdiff.cgi u_pkg.sh \
+       vpkg-provides.sh vpkg-provides2.sh
 
 installprefix = $(DESTDIR)
 
@@ -17,4 +18,5 @@ config_SCRIPTS = \
        brp-compress brp-strip brp-strip-comment-note \
        check-prereqs convertrpmrc.sh find-lang.sh find-prov.pl find-req.pl \
        freshen.sh get_magic.pl getpo.sh http.req magic.prov magic.req \
-       perl.prov perl.req rpmdiff u_pkg.sh vpkg-provides.sh vpkg-provides2.sh
+       perl.prov perl.req rpmdiff rpmdiff.cgi u_pkg.sh \
+       vpkg-provides.sh vpkg-provides2.sh
index 5f31d70..df3c1b6 100644 (file)
@@ -152,13 +152,13 @@ varprefix = @varprefix@
 
 AUTOMAKE_OPTIONS = 1.4 foreign
 
-EXTRA_DIST =   brp-compress brp-strip brp-strip-comment-note   check-prereqs convertrpmrc.sh find-lang.sh find-prov.pl find-req.pl     freshen.sh get_magic.pl getpo.sh http.req magic.prov magic.req  perl.prov perl.req rpmdiff u_pkg.sh vpkg-provides.sh vpkg-provides2.sh
+EXTRA_DIST =   brp-compress brp-strip brp-strip-comment-note   check-prereqs convertrpmrc.sh find-lang.sh find-prov.pl find-req.pl     freshen.sh get_magic.pl getpo.sh http.req magic.prov magic.req  perl.prov perl.req rpmdiff rpmdiff.cgi u_pkg.sh         vpkg-provides.sh vpkg-provides2.sh
 
 
 installprefix = $(DESTDIR)
 
 configdir = ${prefix}/lib/rpm
-config_SCRIPTS =       brp-compress brp-strip brp-strip-comment-note   check-prereqs convertrpmrc.sh find-lang.sh find-prov.pl find-req.pl     freshen.sh get_magic.pl getpo.sh http.req magic.prov magic.req  perl.prov perl.req rpmdiff u_pkg.sh vpkg-provides.sh vpkg-provides2.sh
+config_SCRIPTS =       brp-compress brp-strip brp-strip-comment-note   check-prereqs convertrpmrc.sh find-lang.sh find-prov.pl find-req.pl     freshen.sh get_magic.pl getpo.sh http.req magic.prov magic.req  perl.prov perl.req rpmdiff rpmdiff.cgi u_pkg.sh         vpkg-provides.sh vpkg-provides2.sh
 
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
 CONFIG_HEADER = ../config.h
index 6643f6a..c9723f8 100755 (executable)
@@ -1,15 +1,49 @@
 #!/usr/bin/perl
 
-# a simple script to print the proper name for perl libraries.
+# RPM (and it's source code) is covered under two separate licenses.
 
-# I plan to rewrite this in C so that perl is not required by RPM at
-# build time.
+# The entire code base may be distributed under the terms of the GNU
+# General Public License (GPL), which appears immediately below.
+# Alternatively, all of the source code in the lib subdirectory of the
+# RPM source code distribution as well as any code derived from that
+# code may instead be distributed under the GNU Library General Public
+# License (LGPL), at the choice of the distributor. The complete text
+# of the LGPL appears at the bottom of this file.
 
-# by Ken Estes Mail.com kestes@staff.mail.com
+# This alternative is allowed to enable applications to be linked
+# against the RPM library (commonly called librpm) without forcing
+# such applications to be distributed under the GPL.
+
+# Any questions regarding the licensing of RPM should be addressed to
+# Erik Troan <ewt@redhat.com>.
+
+# a simple script to print the proper name for perl libraries.
+
+# To save development time I do not parse the perl grammmar but
+# instead just lex it looking for what I want.  I take special care to
+# ignore comments and pod's.
 
 # it would be much better if perl could tell us the proper name of a
 # given script.
 
+# The filenames to scan are either passed on the command line or if
+# that is empty they are passed via stdin.
+
+# If there are lines in the file which match the pattern
+#      (m/^\s*\$VERSION\s*=\s+/)
+# then these are taken to be the version numbers of the modules.
+# Special care is taken with a few known idioms for specifying version
+# numbers of files under rcs/cvs control.
+
+# If there are strings in the file which match the pattern
+#     m/^\s*\$RPM_Provides\s*=\s*["'](.*)['"]/i
+# then these are treated as additional names which are provided by the
+# file and are printed as well.
+
+# I plan to rewrite this in C so that perl is not required by RPM at
+# build time.
+
+# by Ken Estes Mail.com kestes@staff.mail.com
 
 if ("@ARGV") {
   foreach (@ARGV) {
@@ -30,7 +64,12 @@ foreach $module (sort keys %require) {
   if (length($require{$module}) == 0) {
     print "perl($module)\n";
   } else {
-    print "perl($module)=$require{$module}\n";
+
+    # I am not using rpm3.0 so I do not want spaces arround my
+    # operators. Also I will need to change the processing of the
+    # $RPM_* vairable when I upgrade.
+
+    print "perl($module) = $require{$module}\n";
   }
 }
 
@@ -51,6 +90,11 @@ sub process_file {
   while (<FILE>) {
     
     # skip the documentation
+
+    # we should not need to have item in this if statement (it
+    # properly belongs in the over/back section) but people do not
+    # read the perldoc.
+
     if ( (m/^=(head1|head2|pod|item)/) .. (m/^=(cut)/) ) {
       next;
     }
@@ -80,9 +124,9 @@ sub process_file {
 
     # here are examples of VERSION lines from the perl distribution
 
-    #FindBin.pm:$VERSION = $VERSION = sprintf("%d.%02d", q$Revision: 1.2 $ =~ /(\d+)\.(\d+)/);
-    #ExtUtils/Install.pm:$VERSION = substr q$Revision: 1.2 $, 10;
-    #CGI/Apache.pm:$VERSION = (qw$Revision: 1.2 $)[1];
+    #FindBin.pm:$VERSION = $VERSION = sprintf("%d.%02d", q$Revision: 1.3 $ =~ /(\d+)\.(\d+)/);
+    #ExtUtils/Install.pm:$VERSION = substr q$Revision: 1.3 $, 10;
+    #CGI/Apache.pm:$VERSION = (qw$Revision: 1.3 $)[1];
     #DynaLoader.pm:$VERSION = $VERSION = "1.03";     # avoid typo warning
 
     if ( 
index bec4705..e63235d 100755 (executable)
@@ -1,15 +1,44 @@
 #!/usr/bin/perl
 
+# RPM (and it's source code) is covered under two separate licenses. 
+
+# The entire code base may be distributed under the terms of the GNU
+# General Public License (GPL), which appears immediately below.
+# Alternatively, all of the source code in the lib subdirectory of the
+# RPM source code distribution as well as any code derived from that
+# code may instead be distributed under the GNU Library General Public
+# License (LGPL), at the choice of the distributor. The complete text
+# of the LGPL appears at the bottom of this file.
+
+# This alternatively is allowed to enable applications to be linked
+# against the RPM library (commonly called librpm) without forcing
+# such applications to be distributed under the GPL.
+
+# Any questions regarding the licensing of RPM should be addressed to
+# Erik Troan <ewt@redhat.com>.
+
 # a simple makedepends like script for perl.
+# To save development time I do not parse the perl grammmar but
+# instead just lex it looking for what I want.  I take special care to
+# ignore comments and pod's.
+
+# It would be much better if perl could tell us the dependencies of a
+# given script.
+
+# The filenames to scan are either passed on the command line or if
+# that is empty they are passed via stdin.
+
+# If there are strings in the file which match the pattern
+#     m/^\s*\$RPM_Requires\s*=\s*["'](.*)['"]/i
+# then these are treated as additional names which are required by the
+# file and are printed as well.
 
 # I plan to rewrite this in C so that perl is not required by RPM at
 # build time.
 
 # by Ken Estes Mail.com kestes@staff.mail.com
 
-# it would be much better if perl could tell us the dependencies of a
-# given script.
-
 if ("@ARGV") {
   foreach (@ARGV) {
     process_file($_);
@@ -29,7 +58,12 @@ foreach $module (sort keys %require) {
   if (length($require{$module}) == 0) {
     print "perl($module)\n";
   } else {
-    print "perl($module)>=$require{$module}\n";
+
+    # I am not using rpm3.0 so I do not want spaces arround my
+    # operators. Also I will need to change the processing of the
+    # $RPM_* vairable when I upgrage.
+
+    print "perl($module) >= $require{$module}\n";
   }
 }
 
@@ -48,6 +82,11 @@ sub process_file {
   while (<FILE>) {
     
     # skip the documentation
+
+    # we should not need to have item in this if statement (it
+    # properly belongs in the over/back section) but people do not
+    # read the perldoc.
+
     if ( (m/^=(head1|head2|pod|item)/) .. (m/^=(cut)/) ) {
       next;
     }
@@ -91,19 +130,6 @@ sub process_file {
        ) {
       my ($module, $version) = ($2,$3);
 
-      # trim off trailing parenthesis if any.  Sometimes people pass
-      # the module an empty list.
-
-      $module =~ s/\(\s*\)$//;
-
-      if ( $module =~ m/^[0-9._]+$/ ) {
-      # if module is a number then both require and use interpret that
-      # to mean that a particular version of perl is specified
-
-       print "perl>$module\n";
-       next;
-      };
-
       # if there is some interpolation of variables just skip this
       # dependency, we do not want
       #        do "$ENV{LOGDIR}/$rcfile";
@@ -116,6 +142,34 @@ sub process_file {
 
       ($module  =~ m/[,>]$/) && next;
 
+      # if the module name starts in a dot it is not a module name.
+      # Is this necessary?  Please give me an example if you turn this
+      # back on.
+
+      #      ($module =~ m/^\./) && next;
+
+      # if the module ends with .pm strip it to leave only basename.
+
+      $module =~ s/\.pm$//;
+
+      # some perl programmers write 'require URI/URL;' when 
+      # they mean 'require URI::URL;'
+
+      $module =~ s/\//::/;
+
+      # trim off trailing parenthesis if any.  Sometimes people pass
+      # the module an empty list.
+
+      $module =~ s/\(\s*\)$//;
+
+      if ( $module =~ m/^[0-9._]+$/ ) {
+      # if module is a number then both require and use interpret that
+      # to mean that a particular version of perl is specified
+
+       print "perl > $module\n";
+       next;
+      };
+
       # ph files do not use the package name inside the file.
       # perlmodlib  documentation says:
       
index 4f45998..af8760e 100644 (file)
@@ -1,5 +1,23 @@
 #!/usr/bin/perl
 
+# RPM (and it's source code) is covered under two separate licenses. 
+
+# The entire code base may be distributed under the terms of the GNU
+# General Public License (GPL), which appears immediately below.
+# Alternatively, all of the source code in the lib subdirectory of the
+# RPM source code distribution as well as any code derived from that
+# code may instead be distributed under the GNU Library General Public
+# License (LGPL), at the choice of the distributor. The complete text
+# of the LGPL appears at the bottom of this file.
+
+# This alternatively is allowed to enable applications to be linked
+# against the RPM library (commonly called librpm) without forcing
+# such applications to be distributed under the GPL.
+
+# Any questions regarding the licensing of RPM should be addressed to
+# Erik Troan <ewt@redhat.com>.
+
+
 # rpmdiff - a program for comparing two rpm files for differences.
 # Written by Ken Estes, Mail.com.
 
@@ -128,7 +146,7 @@ order to encode the information:
 
        S is the file size
 
-       M is the files mode
+       M is the file\'s mode
 
        5 is the MD5 checksum of the file
 
@@ -138,8 +156,14 @@ order to encode the information:
 
        U is the owner of the file
 
+       G is the file\'s group
+
        T is the modification time of the file
 
+       added indicates the file was added to the old version
+
+       missing indicates the file was deleted from the old version
+
 Any attributes which match are denoted with a '.'. 
 
 
@@ -147,8 +171,8 @@ Output Example
 
 
 S.5.....   PREIN
-.....U..   /dev/vcsa1
-..5....T   /dev/printer
+.....UG.   /bin/echo
+..5....T   /usr/bin/grep
 S.5....T   /etc/info-dir
 missing    /usr/doc/dhcpcd-0.70/README
 .M......   /usr/lib/libpanel.so.4
@@ -391,7 +415,7 @@ sub set_static_vars {
   
   $NUM_DIFFERENCES = 0;
 
-  $RCS_REVISION = ' $Revision: 1.3 $ ';
+  $RCS_REVISION = ' $Revision: 1.4 $ ';
   
   # set a known path.
  
@@ -456,7 +480,7 @@ sub parse_args{
  }
   
  if($opt_version) {
-   print "Version: $VERSION\n";
+   print "$0: Version: $VERSION\n";
    exit 0;  
  }
  
diff --git a/scripts/rpmdiff.cgi b/scripts/rpmdiff.cgi
new file mode 100644 (file)
index 0000000..c28478b
--- /dev/null
@@ -0,0 +1,590 @@
+#!/usr/bin/perl
+
+# a web interface to 'cvs rdiff'.  This script makes it easy to query
+# the tags which are created by the build script.
+
+
+use CGI ':standard';
+use File::Basename;
+use File::stat;
+use Data::Dumper;
+
+# the big datastructures are:
+
+#    $RPM_FILE_BY_FQN{$fqn} is the full path rpm wich is discribed by the fqn
+
+#    keys %SORTED_RECENT_FQN is the set of all package names
+
+#    $SORTED_RECENT_FQN{$name} is an ordered list of the most recent
+#                                  versions of this package
+
+# for a short time there are these datastrutures but they are large
+# and expensive to save to disk.
+
+
+# An rpm_package is a hash of:
+#     $package{'fqn'}="perl-5.00502-3"
+#     $package{'rpm_file'}="$RPMS_DIR/".
+#                "./sparc/perl-5.00502-3.solaris2.6-sparc.rpm"
+#     $package{'srpm_file'}="$SRPMS_DIR/".
+#                           "./perl-5.00502-3.src.rpm"
+#     $package{'name'}="perl"
+#     $package{'version'}="5.00502"
+#     $package{'release'}="3"
+
+# fqn is "fully qualified name"
+
+# while the $pkg structure exists we find the pkg we want by looking
+# it up in this structure.  This will hold many more packages then the
+# web page ever knows about.
+#      $BY_NAME{$name}{$version}{$release};
+
+
+sub usage {
+
+  # If they are asking for help then they are clueless so reset all
+  # their parameters for them, in case they are in a bad state.
+
+  param(-name=>'Defaults', -value=>'on');
+  my $rpmdiff_version = `rpmdiff --version`;
+
+  $usage =<<EOF;
+
+  $0          version: $VERSION
+  $rpmdiff_version
+
+This is a web interface into the rpmdiff command.
+
+The user is requested to enter two different packages to diff after
+any one of the multiple submit buttons is pressed the difference will
+be the next webpage loaded.  For convenience each package name is
+listed once (in alphabetical order) and below it is checkbox of the
+most recent $MAX_PICK_LIST versions of this package.  Any pick list
+which is not actively picked by the user contains the string '(none)'.
+
+The user should pick one package in the first column (this represents
+the "old package") and one package in the second column (this
+represents the "new package").  When the user wants to run the
+difference any 'submit' button can be pressed.  The multiple submit
+buttons are listed only for convenience to reduce hunting for a button
+on the page.
+
+Error reporting is very minimal and if an incorrect number of packages
+is picked then the main page is displayed again.  It is suggested that
+the user hit the default button if any problems are encountered using
+the program.
+
+Most users are only interested in differences in the contents of files
+and the contents of soft links.  The defaults for the program reflect
+this interest.  However sometimes users are also interested in changes
+in permissions or ownership.  Alternatively it may happen that a user
+is only interested in the set of files whose size changes and changes
+to files which keep the same size should be ignored.  To acomidate all
+possible uses we gave the user great flexibility in determining what
+set of changes are significant.  There is a pick list at the top of
+the main screen which displays the current criterion for a difference
+to be displayed.  A file which has changes made to properties which
+are not picked will not be considered different and will not be
+displayed.  Of special note the options:
+
+help   will display the help screen for rpmdiff which contains an
+       explanation of how to read the diff format.
+
+all    will require that all differences are considered important.
+       This is the same as checking all the boxes of differences
+
+version will display the version of rpmdiff that is being used by
+       this webpage.
+
+The organization of the pick list page keeps the total number of
+packages hidden from the user.  The pick list page takes a long time
+to load because the number of choices is very large.  To save time the
+set of package pick lists is not regenerated each time the page is
+loaded.  There may have been new packages added to the package
+repository since the page was generated and these packages will not be
+displayed until the page is regenerated again.  The page will never be
+more then one day old.  If you need to use the latest contents of the
+package repository check the box at the bottom of the page marked
+"Flush Cache" this will increase the loading time of the page but
+ensure the freshness of the data.
+
+EOF
+    print pre($usage);
+
+  return ;
+}
+
+
+sub set_static_vars {
+
+# This functions sets all the static variables which are often
+# configuration parameters.  Since it only sets variables to static
+# quantites it can not fail at run time. Some of these variables are
+# adjusted by parse_args() but asside from that none of these
+# variables are ever written to. All global variables are defined here
+# so we have a list of them and a comment of what they are for.
+
+
+  $ARCHIVE = "/devel/java_repository";
+  $RCS_REVISION = ' $Revision: 1.1 $ ';
+  
+  @ORIG_ARGV= @ARGV;
+  
+  # The pattern for parsing fqn into ($name, $version, $release).
+  # This is difficult to parse since some hyphens are significant and
+  # others are not, some packages have alphabetic characters in the
+  # version number.
+
+  $PACKAGE_PAT ='(.*)-([^-]+)-([^-]+).solaris2.6-\w*.rpm';
+
+  # packages which will end up in the picklists  match this pattern
+
+  $PICKLIST_PAT = '/((htdocs)|(djava)|(devel))';
+
+  # only show the most recent packages
+  
+  $MAX_PICK_LIST = 20;
+
+  # the list of allowable arguments to rpmdiff
+
+  @RPMDIFF_ARGS= qw(
+                   version help all 
+                   size mode md5 dev link user group mtime 
+                  );
+
+  @RPMDIFF_ARGS_DEFAULT = qw(size md5 link);
+
+  # the list of  directories where rpms are stored
+  @RPM_ARCHIVES = ('/net/master-mm/export/rpms/redhat',);
+
+  $CACHE_DIR = "/tmp/webtools"; 
+
+  # In an effort to make the cache update atomic we write to one file
+  # name and only move it into the gobally known name when the whole
+  # file is ready.
+
+  $TMP_CACHE_FILE= "$CACHE_DIR/rpmfiles.cache.$UID"; 
+  $CACHE_FILE= "$CACHE_DIR/rpmfiles.cache"; 
+  # set a known path.
+  
+  # the correct path has not been finalized yet, but this is close.
+  
+  $ENV{'PATH'}= (
+                '/usr/local/bin'.
+                ':/usr/bin'.
+                ':/bin'.
+                ':/usr/apache/cgibins/cgi-forms'.
+                ':/tmp'.
+                '');
+  
+  # taint perl requires we clean up these bad environmental
+  # variables.
+  
+  delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
+  
+  return 1;
+} #set_static_vars
+
+
+
+
+sub get_env {
+
+# this function sets variables similar to set_static variables.  This
+# function may fail only if the OS is in a very strange state.  after
+# we leave this function we should be all set up to give good error
+# handling, should things fail.
+
+  $| = 1; 
+  $PID = $$; 
+  $PROGRAM = basename($0); 
+  $TIME = time();
+  $LOCALTIME = localtime($main::TIME); 
+  $START_TIME = $TIME;
+
+  {
+    my ($sec,$min,$hour,$mday,$mon,
+       $year,$wday,$yday,$isdst) =
+         localtime(time());
+    
+    # convert confusing perl time vars to what users expect
+    
+    $year += 1900;
+    $mon++;
+    
+    $CVS_DATE_STR = sprintf("%02u/%02u/%02u", $mday, $mon, $year, );
+    $TAG_DATE_STR = sprintf("%02u%02u%02u", $year, $mon, $mday, );
+    $TIME_STR = sprintf("%02u%02u", $hour, $min);
+  }
+  # a unique id for cache file generation
+  $UID = "$TAG_DATE_STR.$TIME_STR.$PID";
+  $VERSION = 'NONE';
+  if ( $RCS_REVISION =~ m/([.0-9]+)/ ) {
+    $VERSION = $1;
+  }
+
+  (-d $CACHE_DIR) ||
+    mkdir($CACHE_DIR, 0664) ||
+      die("Could not mkdir: $CACHE_DIR: $!\n");
+
+  return 1;
+} # get_env
+
+
+
+sub parse_fqn {
+
+  # This is difficult to parse since some hyphens are significant and
+  # others are not, some packages have alphabetic characters in the
+  # version number. 
+
+  # Also remember that the format of the file is dependent on how RPM
+  # is configured so this may not be portable to all RPM users.
+
+  (!("@_" =~ m/^$PACKAGE_PAT$/)) &&
+    die("rpm_package_name: '$@_' is not in a valid format");
+  
+  return ($1, $2, $3);
+}
+
+
+sub new_rpm_package {
+
+# An rpm_package is a hash of:
+#     $package{'fqn'}="perl-5.00502-3"
+#     $package{'rpm_file'}="$RPMS_DIR/".
+#                "./sparc/perl-5.00502-3.solaris2.6-sparc.rpm"
+#     $package{'srpm_file'}="$SRPMS_DIR/".
+#                           "./perl-5.00502-3.src.rpm"
+#     $package{'name'}="perl"
+#     $package{'version'}="5.00502"
+#     $package{'release'}="3"
+
+  my ($rpm_file) = @_;
+  my $error = '';  
+  my($name, $version, $release) = main::parse_fqn(basename($rpm_file));
+
+  my ($package) = ();
+  
+  $package->{'fqn'}="$name-$version-$release";
+  $package->{'name'}=$name;
+  $package->{'version'}=$version;
+  $package->{'release'}=$release;
+  $package->{'rpm_file'}=$rpm_file;
+
+  # these are needed to do proper sorting of major/minor numbers in
+  # the version of the package
+
+  $package->{'version_cmp'}=[split(/\./, $version)];
+  $package->{'release_cmp'}=[split(/\./, $release)]; 
+
+  return $package;
+}
+
+
+sub get_recent_fqn {
+  my ($name) =(@_);
+
+  my @out = ();
+
+  foreach $version ( keys %{ $BY_NAME{$name} }) {
+    foreach $release ( keys %{ $BY_NAME{$name}{$version} }) {
+
+      push @out, $BY_NAME{$name}{$version}{$release};
+
+    }
+  }
+
+  # the $BY_NAME datastructure is fairly good but the list can not be
+  # sorted right. Sort again using the Schwartzian Transform as
+  # discribed in perlfaq4
+
+  my @sorted = sort {
+
+    # compare the versions but make no assumptions
+    # about how many elements there are
+    
+    my $i=0;
+    my @a_version = @{ $a->{'version_cmp'} }; 
+    my @b_version = @{ $b->{'version_cmp'} };
+    while ( 
+          ($#a_version > $i) && 
+          ($#b_version > $i) && 
+          ($a_version[$i] == $b_version[$i]) 
+         ) {
+      $i++;
+    }
+    
+    my $j = 0;
+    my @a_release = @{ $a->{'release_cmp'} }; 
+    my @b_release = @{ $b->{'release_cmp'} };
+    while ( 
+          ($#a_release > $j) && 
+          ($#b_release > $j) &&
+          ($a_release[$j] == $b_release[$j])
+         ) {
+      $j++;
+    }
+    
+    return (
+           ($b_version[$i] <=> $a_version[$i])
+           ||
+           ($b_release[$j] <=> $a_release[$j])
+          );
+  }
+  @out;
+  
+  ($#sorted > $MAX_PICK_LIST) &&
+    (@sorted = @sorted[0 .. $MAX_PICK_LIST]);
+
+  # dumping data to disk is expensive so we only save the data we
+  # need.  Limit RPM_FILE_BY_FQN to only those packages which appear
+  # in the picklist and this explains why we do not store the whole
+  # pkg in a BY_FQN hash.
+
+  foreach $pkg (@sorted) {
+    $RPM_FILE_BY_FQN{$pkg->{'fqn'}}=$pkg->{'rpm_file'}
+  }
+
+  my @fqns = map { $_->{'fqn'} } @sorted;
+
+  return @fqns;  
+}
+
+
+
+sub parse_package_names {
+
+  $flush_cache = param("Flush Cache");
+  if ( (!($flush_cache)) && (-e $CACHE_FILE) && ( -M $CACHE_FILE < 1 ) ) {
+    my $st = stat($CACHE_FILE) ||
+      die ("Could not stat: $CACHE_FILE: $!");
+    $CACHE_LOCALTIME=localtime($st->mtime);
+    require $CACHE_FILE;
+    return ;
+  }
+
+  $CACHE_LOCALTIME=$LOCALTIME;
+
+  foreach $archive (@RPM_ARCHIVES) {
+    
+    open(FILES, "-|") || 
+      exec("find", $archive, "-print") ||
+       die("Could not run find. $!\n");
+
+    while ($filename = <FILES>) { 
+
+      # we want only the binary rpm files of interest
+
+      ($filename =~ m/\.rpm$/) || next;
+      ($filename =~ m/\.src\.rpm$/) && next;
+      ($filename =~ m/$PICKLIST_PAT/) || next;
+      chomp $filename;
+
+      $pkg = new_rpm_package($filename);
+      $BY_NAME{$pkg->{'name'}}{$pkg->{'version'}}{$pkg->{'release'}} = $pkg;
+
+    }
+
+    close(FILES) || 
+      die("Could not close find. $!\n");
+    
+  }
+
+  foreach $group (keys %BY_NAME) {
+    $SORTED_RECENT_FQN{$group} = [get_recent_fqn($group)];
+
+  }
+
+  open(FILE, ">$TMP_CACHE_FILE") ||
+    die("Could not open filename: '$TMP_CACHE_FILE': $!\n");
+
+  print FILE "# cache file created by $0\n";
+  print FILE "# at $LOCALTIME\n\n";
+
+  print FILE Data::Dumper->Dump( [\%RPM_FILE_BY_FQN,  \%SORTED_RECENT_FQN],
+                                ["SAVED_FQN", "SAVED_SORTED",], );
+
+  print FILE "\n\n";
+  print FILE '%RPM_FILE_BY_FQN = %{ $SAVED_FQN };'."\n";
+  print FILE '%SORTED_RECENT_FQN = %{ $SAVED_SORTED };'."\n";
+  print FILE "1;\n";
+
+  close(FILE) ||
+    die("Could not close filename: '$TMP_CACHE_FILE': $!\n");
+
+  # In an effort to make the cache update atomic we write to one file
+  # name and only move it into the gobally known name when the whole
+  # file is ready.
+
+  (!(-e $CACHE_FILE)) ||
+    unlink($CACHE_FILE) ||
+      die("Could not unlink $CACHE_FILE: $!\n");
+
+  rename($TMP_CACHE_FILE, $CACHE_FILE) ||
+    die("Could not rename ($TMP_CACHE_FILE, $CACHE_FILE): $!\n");
+
+  return ;
+}
+
+
+
+
+
+sub print_pkg_picklists {
+
+  print start_form;  
+  # create a set of picklists for the packages based on the package names.
+
+  print h3("Choose the criterion for a difference"),
+  checkbox_group( 
+                -name=>"rpmdiff arguments",
+                -value=>[ @RPMDIFF_ARGS ],
+                -default=>[ @RPMDIFF_ARGS_DEFAULT ],
+               ),p();
+    
+  print h3("Choose one package in each column then hit any submit"),p();
+  
+  my @rows = ();
+  
+  foreach $name (sort keys %SORTED_RECENT_FQN) {
+    
+    push @rows,
+    # column A
+    td(
+       strong("$name "),
+       p(),
+       popup_menu( 
+                 -name=>"old$name",
+                 -value=>[
+                          '(none)', 
+                          @{ $SORTED_RECENT_FQN{$name} },
+                         ],
+                 -default=>'(none)',
+                ),
+      ).
+       # column B
+       td(
+          strong("$name "),
+          p(),
+          popup_menu( 
+                     -name=>"new$name",
+                     -value=>[
+                              '(none)', 
+                              @{ $SORTED_RECENT_FQN{$name} },
+                             ],
+                     -default=>'(none)',
+                    ),
+         ).
+           td(
+              defaults(-name=>'Defaults'),
+              submit(-name=>'Submit'),
+             ).
+               '';
+  }
+  
+  print table(Tr(\@rows));
+
+  my $footer_info=<<EOF;
+
+Try 'rpmdiff --help' for information about what constitues a
+difference.  The output of rpmdiff is exactly the same as the output
+of rpm verify, 'rpm -V'.  The --help option documents the format of
+rpm verify and the format of rpmdiff and is a handy reference for this
+terse table.  rpmdiff is included in the devel-build-tools package.
+
+
+This web interface is for taking differences in the binary code.  To
+take differences of the binaries use <a href="cvs_tag_diff.cgi">'cvs tag diff'</a>.  
+
+EOF
+
+  print pre($footer_info);
+
+  print "This page generated with data cached at: $CACHE_LOCALTIME\n",p(),
+        "The time is now: $LOCALTIME\n",p(),
+        submit(-name=>"Flush Cache"),p(),
+        submit(-name=>"Help Screen"),p();
+
+  print end_form;  
+
+  return ;
+}
+
+
+
+sub print_diff {
+  my($oldpkg_file, $newpkg_file, @args) = @_;
+
+  my $cmd = "rpmdiff @args $oldpkg_file $newpkg_file 2>&1";
+
+  my $result = "\n".qx{$cmd}."\n";
+  print pre($result);
+
+  return ;
+}
+
+
+#       Main        
+{
+
+  set_static_vars();
+  get_env();
+
+  parse_package_names();
+
+  my @picked_rpmdiff_args = param("rpmdiff arguments");
+  @picked_rpmdiff_args = split(/\s+/, 
+                              '--'.(join(" --", @picked_rpmdiff_args)));
+  push @picked_rpmdiff_args, '--';
+  foreach $name (sort keys %SORTED_RECENT_FQN) {
+    
+    if ( (param("old$name")) && (param("old$name") ne "(none)") ) {
+      push @picked_oldpkg, param("old$name");
+    }
+    
+    if ( (param("new$name")) && (param("new$name") ne "(none)") ) {
+      push @picked_newpkg, param("new$name");
+    }
+    
+  }
+
+  print (header.
+        start_html(-title=>'rpmdiff'),
+        h2("rpmdiff"));
+  
+  if (param("Help Screen")) {
+
+    usage();
+
+  } elsif ( grep {/^(\-\-)((help)|(version))$/} @picked_rpmdiff_args ) {
+       
+    print_diff(
+              '/dev/null', 
+              '/dev/null', 
+              @picked_rpmdiff_args, 
+             );
+    
+  } elsif (
+          ($#picked_oldpkg == 0) &&
+          ($#picked_newpkg == 0)
+         ) {
+    
+    print_diff(
+              $RPM_FILE_BY_FQN{$picked_oldpkg[0]}, 
+              $RPM_FILE_BY_FQN{$picked_newpkg[0]}, 
+              @picked_rpmdiff_args, 
+             );
+    
+  } else {
+
+    print_pkg_picklists();
+
+    print end_html;
+    print "\n\n\n";
+  }
+
+}
+
index 0abfc4c..4d6abfb 100644 (file)
@@ -1,3 +1,22 @@
+/*
+RPM and it's source code are covered under two separate licenses. 
+
+The entire code base may be distributed under the terms of the GNU General
+Public License (GPL), which appears immediately below.  Alternatively,
+all of the source code in the lib subdirectory of the RPM source code
+distribution as well as any code derived from that code may instead be
+distributed under the GNU Library General Public License (LGPL), at the
+choice of the distributor. The complete text of the LGPL appears
+at the bottom of this file.
+
+This alternatively is allowed to enable applications to be linked against
+the RPM library (commonly called librpm) without forcing such applications
+to be distributed under the GPL. 
+
+Any questions regarding the licensing of RPM should be addressed to
+marc@redhat.com and ewt@redhat.com.
+*/
+
 /* 
    Simple progam for pullng all the referenced java classes out of a
    class file.  Java files are supposed to be platform independent, so
 
 #include "system.h"
 
+/*
+  these includes are for my use, rpm will use #include "system.h"*
+*/
+
+/*
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+*/
+
 #include <stdarg.h>
 
 /*---------typedefs---------*/
@@ -106,6 +136,7 @@ size_t my_fread(void *ptr, size_t size, size_t nitems, FILE *stream);
 void check_range(short value, short poolSize);
 char *is_lower_equal (char *string, char *pattern);
 int findJavaMagic (FILE *fileHandle);
+int my_strcmp (const void *a, const void *b);
 void print_table_flush(void);
 void print_table_add(char *str);
 char *formatClassName(char *pSomeString, char terminator, char print_star);
@@ -212,7 +243,7 @@ usage (void)
         "assumed to be zero. \n\n"
         "");
   printf("EXAMPLES (Java Keywords): \n\n"
-        "\t public static final String REVISION = \"$Revision: 2.5 $\";\n"
+        "\t public static final String REVISION = \"$Revision: 2.6 $\";\n"
         "\t public static final String EPOCH = \"4\";\n"
         "\t public static final String REQUIRES = \"RPM_Requires: "
         "java(gnu.regexp.RE) java(com.ibm.site.util.Options)>=1.5\";\n"
@@ -228,6 +259,9 @@ usage (void)
         "\tcat filename2.class | javadeps --requires -- filename1.class -\n\n"
         "\tunzip -p filename.jar | javadeps --requires -- - \n\n"
         "");
+  printf("This program is distributed with RPM the Redhat Package \n"
+        "Managment system.  Further information about RPM can be found at \n"
+        "\thttp://www.rpm.org/\n\n");
   printf("\n\n");
   exit(-1);
 }
@@ -418,7 +452,7 @@ int findJavaMagic (FILE *fileHandle)
 #undef mod4
 
 
-static int
+int
 my_strcmp (const void *a, const void *b) {
 char **a1; char **b1;
 int ret;
@@ -487,11 +521,24 @@ print_table_add(char *str) {
 }
 
 
-/* Given a list separated by whitespace, put each element in the print
+void 
+print_list(char *in_string) {
+
+  /* This function is no longer needed due to fixes in RPM's
+     processing of dependencies.  Keep the code until I get a chance
+     to use RPM3.0 personally */
+
+  if (in_string) {
+    printf("%s\n", in_string);
+  }
+
+/* 
+   Old function did:
+
+   Given a list separated by whitespace, put each element in the print
    table with an added "\n" */
 
-static void 
-print_list(char *in_string) {
+ /*
   char *WhiteSpace_Set = "\t\v\n\r\f ";
   char *newEnd, *out_string;
   int copy_len;
@@ -527,7 +574,8 @@ print_list(char *in_string) {
     in_string += strspn(in_string+copy_len, WhiteSpace_Set);
   }
 
-  return ;
+ */
+ return ;
 }
 
 
@@ -628,8 +676,8 @@ char
   if(ARG_RPMFORMAT) {
     strcat(out_string, ")");
   }
-  strcat(out_string, "\n");
 
+  strcat(out_string, "\n");
   free(ClassName_Break_Set);
   return out_string;
 }
@@ -933,11 +981,6 @@ findClassName (FILE *fileHandle, symbolTable_t *symbolTable) {
 
   out_string = formatClassName(symbolTable->stringList[class], '\0', 0);
 
-  newline = strchr(out_string, '\n');
-  if (newline) {
-    *newline ='\0';
-  }
-
   {
     int len = 10;
 
@@ -957,26 +1000,50 @@ findClassName (FILE *fileHandle, symbolTable_t *symbolTable) {
     out_string = realloc(out_string, len );
   }
 
-  if (! out_string ){
+  if (!out_string){
     outofmemory();
   }
   
   if( KEYWORD_VERSION || KEYWORD_REVISION ){
-    strcat(out_string, "=");
+    /* It is easier to remove the extra new line here in one place
+       then to try and add a newline every where that formatClassName
+       is called */
+    char *newline;
+
+    /* I am not using rpm 3.0 yet so I need both the dependencies with
+       and without the version numbers, when I upgrade I will remove
+       this block (with copy_string) and change the "=" to " = " ten
+       lines down.*/
+    {
+      char *copy_string;
+      copy_string = (char*) malloc(strlen(out_string));
+      if (!copy_string){
+       outofmemory();
+      }
+      copy_string = strcpy(copy_string, out_string);
+      print_table_add(copy_string);
+    }
+
+    newline = strrchr(out_string, '\n');
+    if (newline) {
+      newline[0] = '\0';
+    }
+    strcat(out_string, " = ");
     if(KEYWORD_EPOCH){
       strcat(out_string, KEYWORD_EPOCH);
       strcat(out_string, ":");
     }
-    if( KEYWORD_VERSION ){
+    if(KEYWORD_VERSION){
       strcat(out_string, KEYWORD_VERSION);
-      } else {
-       strcat(out_string, KEYWORD_REVISION);
-      }
+    } else {
+      strcat(out_string, KEYWORD_REVISION);
+    }
     strcat(out_string, "\n");
-    print_table_add(out_string);
-    out_string=NULL;
   }
   
+  print_table_add(out_string);
+  out_string=NULL;
+
   /* Provide the star version of this class for jhtml
      dependencies. This option is deprecated since jhtml is
      deprecated. */