Diff for /loncom/build/make_rpm.pl between versions 1.12 and 1.17

version 1.12, 2002/01/05 00:48:05 version 1.17, 2002/04/07 20:35:41
Line 1 Line 1
 #!/usr/bin/perl  #!/usr/bin/perl
   
   # -------------------------------------------------------- Documentation notice
   # Run "perldoc ./make_rpm.pl" in order to best view the software documentation
   # internalized in this program.
   
   # --------------------------------------------------------- License Information
 # The LearningOnline Network with CAPA  # The LearningOnline Network with CAPA
 # make_rpm.pl - make RedHat package manager file  # make_rpm.pl - make RedHat package manager file (A CLEAN AND CONFIGURABLE WAY)
 #  #
 # $Id$  # $Id$
 #  #
Line 25 Line 30
 # along with LON-CAPA; if not, write to the Free Software  # along with LON-CAPA; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #  #
 # /home/httpd/html/adm/gpl.txt  
 #  
 # http://www.lon-capa.org/  # http://www.lon-capa.org/
 #  #
 # YEAR=2000  # YEAR=2000
Line 34 Line 37
 # YEAR=2001  # YEAR=2001
 # 1/8,1/10,1/13,1/23,5/16 - Scott Harrison  # 1/8,1/10,1/13,1/23,5/16 - Scott Harrison
 # YEAR=2002  # YEAR=2002
 # 1/4 - Scott Harrison  # 1/4,1/8,1/9,2/13,4/7 - Scott Harrison
 #  #
 ###  ###
   
 # Automatically generate RPM files  # make_rpm.pl automatically generate RPM software packages
 # from file listing.  # from a target image directory and file listing.  POD
   # documentation is at the end of this file.
 # This script does actually "build" the RPM.  
   ###############################################################################
 # This script also generates and then deletes temporary  ##                                                                           ##
 # files (and binary root directory tree) to build an RPM with.  ## ORGANIZATION OF THIS PERL SCRIPT                                          ##
   ##                                                                           ##
 # I still need to implement the CONFIGURATION_FILES and  ## 1. Check to see if RPM builder application is available                   ##
 # DOCUMENTATION_FILES portion of the command line interface to this  ## 2. Read in command-line arguments                                         ##
 # script.  ## 3. Generate temporary directories (subdirs of first command-line argument)##
   ## 4. Initialize some variables                                              ##
 # Take in a file list (from standard input),   ## 5. Create a stand-alone rpm building environment                          ##
 # a description tag and version tag from command line argument  ## 6. Perform variable initializations and customizations                    ##
 # and temporarily generate a:  ## 7. Print header information for .spec file                                ##
 #      RPM .spec file  ## 8. Process file list and generate information                             ##
 #      RPM Makefile  ## 9. Generate SRPM and BinaryRoot Makefiles                                 ##
 #      SourceRoot  ## 10. mirror copy (BinaryRoot) files under a temporary directory            ##
   ## 11. roll everything into an rpm                                           ##
 # A resulting .rpm file is generated.  ## 12. clean everything up                                                   ##
   ## 13. subroutines                                                           ##
 unless (-e "/usr/lib/rpm/rpmrc") {  ## 13a. find_info - recursively gather information from a directory          ##
     print <<END;  ## 13b. grabtag - grab a tag from an XML string                              ##
 ERROR: This script only works with a properly installed RPM builder  ## 14. Plain Old Documentation                                               ##
   ##                                                                           ##
   ###############################################################################
   
   use strict;
   
   # ------------------------ Check to see if RPM builder application is available
   
   unless (-e '/usr/lib/rpm/rpmrc') { # part of the expected rpm software package
       print(<<END);
   **** ERROR **** This script only works with a properly installed RPM builder
 application.    application.  
 Cannot find /usr/lib/rpm/rpmrc, so cannot generate customized rpmrc file.  Cannot find /usr/lib/rpm/rpmrc, so cannot generate customized rpmrc file.
 Script aborting.  Script aborting.
 END  END
       exit(1);
 }  }
   
 my ($tag,$version,$configuration_files,$documentation_files,$pathprefix)=@ARGV;  # ---------------------------------------------- Read in command-line arguments
 @ARGV=();  
   
 if (!$version) {  my ($tag,$version,$configuration_files,$documentation_files,
     print "Usage: <TAG> <VERSION> [CONFIGURATION_FILES] [DOCUMENTATION] ".      $pathprefix,$customize)=@ARGV;
  "[PATHPREFIX]\n";  @ARGV=(); # read standard input based on a pipe, not a command-line argument
     print "Standard input provides the list of files to work with.\n";  
     print "TAG, required descriptive tag.  For example, a kerberos software ".  if (!$version) {# version should be defined and string length greater than zero
  "package might be tagged as \"krb4\".\n";      print(<<END);
     print "VERSION, required version.  Needed to generate version information".  See "perldoc make_rpm.pl" for more information.
  " for the RPM.  This should be in the format N.M where N and M are ".  
  "integers.\n";  Usage: 
     print "CONFIGURATION_FILES, optional comma-separated listing of files to ".             <STDIN> | perl make_rpm.pl <TAG> <VERSION> [CONFIGURATION_FILES]
  "be treated as configuration files by RPM (and thus subject to saving".             [DOCUMENTATION_FILES] [PATHPREFIX] [CUSTOMIZATION_XML]
  " during RPM upgrades).\n";  
     print "DOCUMENTATION, optional comma-separated listing of files to be ".  Standard input provides the list of files to work with.
  "treated as documentation files by RPM (and thus subject to being ".  TAG, required descriptive tag.  For example, a kerberos software
  "placed in the /usr/doc/RPM-NAME directory during RPM installation).".  package might be tagged as "krb4". (This value is also used in
  "\n";  the generation of a temporary directory; you cannot have
     print "PATHPREFIX, optional path to be removed from file listing.  This ".  a pre-existing directory named ./TAG.)
  "is in case you are building an RPM from files elsewhere than ".  VERSION, required version.  Needed to generate version information
  "root-level.  Note, this still depends on a root directory hierarchy ".  for the RPM.  It is recommended that this be in the format N.M where N and
  "after PATHPREFIX.\n";  M are integers.
     exit;  CONFIGURATION_FILES, optional comma-separated listing of files to
 }  be treated as configuration files by RPM (and thus subject to saving
   during RPM upgrades).
 mkdir $tag,0755;  DOCUMENTATION_FILES, optional comma-separated listing of files to be
 mkdir "$tag/BuildRoot",0755;  treated as documentation files by RPM (and thus subject to being
 mkdir "$tag/SOURCES",0755;  placed in the /usr/doc/RPM-NAME directory during RPM installation).
 mkdir "$tag/SOURCES/LON-CAPA-$tag-$version",0755;  PATHPREFIX, optional path to be removed from file listing.  This
 mkdir "$tag/SPECS",0755;  is in case you are building an RPM from files elsewhere than
 mkdir "$tag/BUILD",0755;  root-level.  Note, this still depends on a root directory hierarchy
 mkdir "$tag/SRPMS",0755;  after PATHPREFIX.
 mkdir "$tag/RPMS",0755;  CUSTOMIZATION_XML, allows for customizing various pieces of information such
 mkdir "$tag/RPMS/i386",0755;  as vendor, summary, name, copyright, group, autoreqprov, requires, prereq,
   description, and pre-installation scripts (see more in the POD,
   "perldoc make_rpm.pl").
   END
       exit(1);
   }
   
   # ----- Generate temporary directories (subdirs of first command-line argument)
   
   # Do some error-checking related to important first command-line argument.
   if ($tag=~/\W/) { # non-alphanumeric characters cause problems
       print(<<END);
   **** ERROR **** Invalid tag name "$tag"
   (The first command-line argument must be alphanumeric characters without
   spaces.)
   END
       exit(1);
   }
   if (-e $tag) { # do not overwrite or conflict with existing data
       print(<<END);
   **** ERROR **** a file or directory "./$tag" already exists
   (This program needs to generate a temporary directory named "$tag".)
   END
       exit(1);
   }
   
   print('Generating temporary directory ./'.$tag."\n");
   mkdir($tag,0755) or die("**** ERROR **** cannot generate $tag directory\n");
   mkdir("$tag/BuildRoot",0755);
   mkdir("$tag/SOURCES",0755);
   mkdir("$tag/SPECS",0755);
   mkdir("$tag/BUILD",0755);
   mkdir("$tag/SRPMS",0755);
   mkdir("$tag/RPMS",0755);
   mkdir("$tag/RPMS/i386",0755);
   
   # -------------------------------------------------------- Initialize variables
   
 my $file;  my $file;
 my $binaryroot="$tag/BinaryRoot";  my $binaryroot=$tag.'/BinaryRoot';
 my ($type,$size,$octalmode,$user,$group);  my ($type,$size,$octalmode,$user,$group);
   
 $currentdir=`pwd`; chop $currentdir; $invokingdir=$currentdir;  my $currentdir=`pwd`; chomp($currentdir); my $invokingdir=$currentdir;
 $currentdir.="/$tag";  $currentdir.='/'.$tag;
   
   # ------------------------------- Create a stand-alone rpm building environment
   
 open (IN,"</usr/lib/rpm/rpmrc") or die("Can't open /usr/lib/rpm/rpmrc");  print('Creating stand-alone rpm build environment.'."\n");
 @lines=<IN>;  open(IN,'</usr/lib/rpm/rpmrc') or die('Cannot open /usr/lib/rpm/rpmrc'."\n");
 close IN;  my @lines=<IN>;
   close(IN);
   
 open (RPMRC,">$tag/SPECS/rpmrc");  open(RPMRC,">$tag/SPECS/rpmrc");
 foreach $line (@lines) {  foreach my $line (@lines) {
     if ($line=~/^macrofiles/) {      if ($line=~/^macrofiles/) {
  chop $line;   chomp($line);
  $line.=":$currentdir/SPECS/rpmmacros\n";   $line.=":$currentdir/SPECS/rpmmacros\n";
     }      }
     print RPMRC $line;      print(RPMRC $line);
 }  }
 close RPMRC;  close(RPMRC);
   
 open (RPMMACROS,">$tag/SPECS/rpmmacros");  open(RPMMACROS,">$tag/SPECS/rpmmacros");
 print RPMMACROS <<END;  print(RPMMACROS <<END);
 \%_topdir $currentdir  \%_topdir $currentdir
 \%__spec_install_post    \\  \%__spec_install_post    \\
     /usr/lib/rpm/brp-strip \\      /usr/lib/rpm/brp-strip \\
     /usr/lib/rpm/brp-strip-comment-note \\      /usr/lib/rpm/brp-strip-comment-note \\
 \%{nil}  \%{nil}
 END  END
 close RPMMACROS;  close(RPMMACROS);
   
 # This needs to be dynamically based upon doc/otherfiles/rpm_list.txt  # ------------------------- Perform variable initializations and customizations
 # at some point.  
 my $requires="";  my $cu=''; # string that holds customization XML file contents
 if ($tag eq "setup") {  if (length($customize)>0) {
     $requires=<<END;      print('Reading in XML-formatted customizations from '.$customize."\n");
 PreReq: setup      open(IN,"<$customize") or
 PreReq: passwd      (
 PreReq: util-linux       print(`cd $invokingdir; rm -Rf $tag`) and
 END       die('Cannot open customization file "'.$customize.'"'."\n")
 }      );
 elsif ($tag eq "base") {      my @clines=(<IN>);
     $requires=<<END;      $cu=join('',@clines);
 PreReq: LON-CAPA-setup      close(IN);
 PreReq: apache  
 PreReq: /etc/httpd/conf/access.conf  
 END  
     $requires2=<<END;  
 Requires: LON-CAPA-setup  
 Requires: raidtools  
 Requires: ncurses  
 Requires: popt  
 Requires: tcsh  
 Requires: redhat-release  
 Requires: diffutils  
 Requires: ed  
 Requires: dialog  
 Requires: rmt  
 Requires: sed  
 Requires: which  
 Requires: gawk  
 Requires: mingetty  
 Requires: info  
 Requires: portmap  
 Requires: openssh-clients  
 Requires: openssh  
 Requires: openssh-server  
 Requires: openssl  
 Requires: basesystem  
 Requires: ldconfig  
 Requires: filesystem  
 Requires: mktemp  
 Requires: termcap  
 Requires: shadow-utils  
 Requires: libtermcap  
 Requires: MAKEDEV  
 Requires: utempter  
 Requires: bash  
 Requires: logrotate  
 Requires: SysVinit  
 Requires: chkconfig  
 Requires: textutils  
 Requires: pwdb  
 Requires: vixie-cron  
 Requires: procps  
 Requires: modutils  
 Requires: psmisc  
 Requires: sysklogd  
 Requires: authconfig  
 Requires: zlib  
 Requires: sh-utils  
 Requires: mailcap  
 Requires: anacron  
 Requires: bc  
 Requires: bdflush  
 Requires: bind-utils  
 Requires: cpio  
 Requires: crontabs  
 Requires: etcskel  
 Requires: e2fsprogs  
 Requires: samba-client  
 Requires: apache-devel  
 Requires: autofs  
 Requires: findutils  
 Requires: gdbm  
 Requires: getty_ps  
 Requires: readline  
 Requires: glib10  
 Requires: inetd  
 Requires: losetup  
 Requires: gnupg  
 Requires: gpgp  
 Requires: urw-fonts  
 Requires: mailx  
 Requires: gzip  
 Requires: ld.so  
 Requires: less  
 Requires: passwd  
 Requires: sysreport  
 Requires: ncompress  
 Requires: mount  
 Requires: lilo  
 Requires: bzip2  
 Requires: grep  
 Requires: memprof  
 Requires: mars-nwe  
 Requires: pidentd  
 Requires: procinfo  
 Requires: units  
 Requires: routed  
 Requires: quota  
 Requires: pam  
 Requires: stat  
 Requires: setserial  
 Requires: mod_perl  
 Requires: rootfiles  
 Requires: nfs-utils  
 Requires: sendmail  
 Requires: sharutils  
 Requires: tmpwatch  
 Requires: shapecfg  
 Requires: tcp_wrappers  
 Requires: unzip  
 Requires: tetex-dvips  
 Requires: tetex-afm  
 Requires: tetex-latex  
 Requires: xntp3  
 Requires: rpm  
 Requires: wu-ftpd  
 Requires: setup  
 Requires: glibc  
 Requires: fileutils  
 Requires: initscripts  
 Requires: netatalk  
 Requires: apache  
 Requires: bash2  
 Requires: dev  
 Requires: samba  
 Requires: ghostscript  
 Requires: kernel-headers  
 Requires: kernel  
 Requires: linuxconf  
 Requires: tetex  
 Requires: tetex-fonts  
 Requires: util-linux  
 Requires: vim-common  
 Requires: perl  
 Requires: cracklib  
 Requires: cracklib-dicts  
 Requires: cdrecord  
 Requires: ghostscript-fonts  
 Requires: libgr  
 Requires: libjpeg  
 Requires: libpng  
 Requires: libungif-progs  
 Requires: libtiff  
 Requires: libungif  
 Requires: samba-common  
 Requires: ImageMagick  
 Requires: libgr-progs  
 Requires: man-pages  
 Requires: tar  
 Requires: vim-minimal  
 END  
 }  
 else {  
     $requires=<<END;  
 Requires: LON-CAPA-base  
 END  
 }  }
 open (SPEC,">$tag/SPECS/LON-CAPA-$tag-$version.spec");  
   
 my $vendor='Laboratory for Instructional Technology Education, Division of '.  # tv - temporary variable (if it exists inside the XML document) then use it,
     'Science and Mathematics Education, Michigan State University.';  # otherwise don't overwrite existing values of variables
   my $tv='';
   
   # (Sure. We could use HTML::TokeParser here... but that wouldn't be fun now,
   # would it?)
   my $name=$tag;
   # read in name from customization if available
   $tv=grabtag('name',$cu,1); $name=$tv if $tv;
   $name=~s/\<tag \/\>/$tag/g;
   
   # (When in doubt, be paranoid about overwriting things.)
   if (-e "$name-$version-1.i386.rpm") {
       print(`cd $invokingdir; rm -Rf $tag`); # clean temporary filespace in use
       die("**** ERROR **** $name-$version-1.i386.rpm already exists.\n");
   }
   
 print SPEC <<END;  my $requires='';
 Summary: Files for the $tag component of LON-CAPA.  # read in relevant requires info from customization file (if applicable)
 Name: LON-CAPA-$tag  # note that "PreReq: item" controls order of CD-ROM installation (if you
   # are making a customized CD-ROM)
   # "Requires: item" just enforces dependencies from the command-line invocation
   $tv=grabtag('requires',$cu,1); $requires=$tv if $tv;
   # do more require processing here
   $requires=~s/\s*\<\/item\>\s*//g;
   $requires=~s/\s*\<item\>\s*/\n/g;
   $requires=~s/^\s+//s;
   
   my $summary='Files for the '.$name.' software package.';
   # read in summary from customization if available
   $tv=grabtag('summary',$cu,1); $summary=$tv if $tv;
   $summary=~s/\<tag \/\>/$tag/g;
   
   my $autoreqprov='no';
   # read in autoreqprov from customization if available
   $tv=grabtag('autoreqprov',$cu,1); $autoreqprov=$tv if $tv;
   
   my $copyright="not specified here";
   # read in copyright from customization if available
   $tv=grabtag('copyright',$cu,1); $copyright=$tv if $tv;
   $copyright=~s/\<tag \/\>/$tag/g;
   
   open(SPEC,">$tag/SPECS/$name-$version.spec");
   
   my $vendor='Me';
   # read in vendor from customization if available
   $tv=grabtag('vendor',$cu,1); $vendor=$tv if $tv;
   $vendor=~s/\<tag \/\>/$tag/g;
   
   my $description="$name software package";
   # read in description from customization if available
   $tv=grabtag('description',$cu,0); $description=$tv if $tv;
   $description=~s/\<tag \/\>/$tag/g;
   
   my $pre='';
   # read in pre-installation script if available
   $tv=grabtag('pre',$cu,0); $pre=$tv if $tv;
   $pre=~s/\<tag \/\>/$tag/g;
   
   # ------------------------------------- Print header information for .spec file
   
   print(SPEC <<END);
   Summary: $summary
   Name: $name
 Version: $version  Version: $version
 Release: 1  Release: 1
 Vendor: $vendor  Vendor: $vendor
 BuildRoot: $currentdir/BuildRoot  BuildRoot: $currentdir/BuildRoot
 Copyright: Michigan State University patents may apply.  Copyright: $copyright
 Group: Utilities/System  Group: Utilities/System
 Source: LON-CAPA-$tag-$version.tar.gz  Source: $name-$version.tar.gz
 AutoReqProv: no  AutoReqProv: $autoreqprov
 $requires  $requires
 # requires: filesystem  # requires: filesystem
 \%description  \%description
 This package is automatically generated by the make_rpm.pl perl  $description
 script (written by the LON-CAPA development team, www.lon-capa.org,  
 Scott Harrison). This implements the $tag component for LON-CAPA.  
 For more on the LON-CAPA project, visit http://www.lon-capa.org/.  
   
 \%prep  \%prep
 \%setup  \%setup
Line 330  make ROOT="\$RPM_BUILD_ROOT" SOURCE="$cu Line 291  make ROOT="\$RPM_BUILD_ROOT" SOURCE="$cu
 make ROOT="\$RPM_BUILD_ROOT" SOURCE="$currentdir/BinaryRoot" links  make ROOT="\$RPM_BUILD_ROOT" SOURCE="$currentdir/BinaryRoot" links
   
 \%pre  \%pre
 echo "***********************************************************************"  $pre
 echo "LON-CAPA  LearningOnline with CAPA"  
 echo "http://www.lon-capa.org/"  
 echo "Gerd Kortemeyer, et al"  
 echo "Laboratory for Instructional Technology Education"  
 echo "Michigan State University"  
 echo " "  
 echo "** Michigan State University patents may apply **"  
 echo " "  
 echo "This installation assumes an installation of Redhat 6.2"  
 echo " "  
 echo "The server computer should be currently connected to the ethernet"  
 echo " "  
 echo "The files in this package are only those for the $tag component."  
 echo "Configuration files are sometimes part of the LON-CAPA-base RPM."  
 echo "***********************************************************************"  
   
 \%post  \%post
 \%postun  \%postun
Line 353  echo "********************************** Line 299  echo "**********************************
 \%files  \%files
 END  END
   
 foreach $file (<>) {  # ------------------------------------ Process file list and gather information
     chop $file;  
   my %BinaryRootMakefile;
   my %Makefile;
   my %dotspecfile;
   
   foreach my $file (<>) {
       chomp($file);
     my $comment="";      my $comment="";
     if ($file=~/\s+\#(.*)$/) {      if ($file=~/\s+\#(.*)$/) {
  $file=~s/\s+\#(.*)$//;   $file=~s/\s+\#(.*)$//;
  $comment=$1;   $comment=$1;
     }      }
     my $config="";      my $directive="";
     if ($comment=~/config/i) {      if ($comment=~/config\(noreplace\)/) {
  $config="\%config ";   $directive="\%config(noreplace) ";
       }
       elsif ($comment=~/config/) {
    $directive="\%config ";
       }
       elsif ($comment=~/doc/) {
    $directive="\%doc";
     }      }
     if (($type,$size,$octalmode,$user,$group)=find_info($file)) {      if (($type,$size,$octalmode,$user,$group)=find_info($file)) {
  $octalmode="0" . $octalmode if length($octalmode)<4;   $octalmode="0" . $octalmode if length($octalmode)<4;
Line 370  foreach $file (<>) { Line 328  foreach $file (<>) {
     $file=~s/^$pathprefix//;      $file=~s/^$pathprefix//;
  }   }
  if ($type eq "files") {   if ($type eq "files") {
     push @{$BinaryRootMakefile{$type}},"\tinstall -D -m $octalmode ".      push(@{$BinaryRootMakefile{$type}},"\tinstall -D -m $octalmode ".
  "$pathprefix$file $binaryroot$file\n";   "$pathprefix$file $binaryroot$file\n");
     push @{$Makefile{$type}},"\tinstall -D -m $octalmode ".      push(@{$Makefile{$type}},"\tinstall -D -m $octalmode ".
  "\$(SOURCE)$file \$(ROOT)$file\n";   "\$(SOURCE)$file \$(ROOT)$file\n");
     push @{$dotspecfile{$type}},"$config\%attr($octalmode,$user,".      push(@{$dotspecfile{$type}},"$directive\%attr($octalmode,$user,".
  "$group) $file\n";   "$group) $file\n");
  }   }
  elsif ($type eq "directories") {   elsif ($type eq "directories") {
     push @{$BinaryRootMakefile{$type}},"\tinstall -m $octalmode -d ".      push(@{$BinaryRootMakefile{$type}},"\tinstall -m $octalmode -d ".
  "$binaryroot$file\n";   "$binaryroot$file\n");
     push @{$Makefile{$type}},"\tinstall -m $octalmode -d ".      push(@{$Makefile{$type}},"\tinstall -m $octalmode -d ".
  "\$(SOURCE)$file \$(ROOT)$file\n";   "\$(SOURCE)$file \$(ROOT)$file\n");
     push @{$dotspecfile{$type}},"\%dir \%attr($octalmode,$user,".      push(@{$dotspecfile{$type}},"\%dir \%attr($octalmode,$user,".
  "$group) $file\n";   "$group) $file\n");
  }   }
  elsif ($type eq "links") {   elsif ($type eq "links") {
     my $link=$size; # I use the size variable to pass the link value      my $link=$size; # I use the size variable to pass the link value
                             # from the subroutine find_info                              # from the subroutine find_info
     $link=~s/^$pathprefix//;      $link=~s/^$pathprefix//;
     push @{$BinaryRootMakefile{$type}},      push(@{$BinaryRootMakefile{$type}},
          "\tln -s $link $binaryroot$file\n";           "\tln -s $link $binaryroot$file\n");
     push @{$Makefile{$type}},"\tln -s $link \$(ROOT)$file\n";      push(@{$Makefile{$type}},"\tln -s $link \$(ROOT)$file\n");
     push @{$dotspecfile{$type}},"\%attr(-,$user,$group) $file\n";      push(@{$dotspecfile{$type}},"\%attr(-,$user,$group) $file\n");
  }   }
     }      }
 }  }
   
 open OUT, ">$tag/SOURCES/LON-CAPA-$tag-$version/Makefile";  # -------------------------------------- Generate SRPM and BinaryRoot Makefiles
 open OUT2, ">$tag/BinaryRootMakefile";  
   # Generate a much needed directory.
   # This directory is meant to hold all source code information
   # necessary for converting .src.rpm files into .i386.rpm files.
   mkdir("$tag/SOURCES/$name-$version",0755);
   
   open(OUTS,">$tag/SOURCES/$name-$version/Makefile");
   open(OUTB, ">$tag/BinaryRootMakefile");
 foreach $type ("directories","files","links") {  foreach $type ("directories","files","links") {
     print OUT "$type\:\n";      print(OUTS "$type\:\n");
     print OUT join("",@{$Makefile{$type}});      print(OUTS join("",@{$Makefile{$type}})) if $Makefile{$type};
     print OUT "\n";      print(OUTS "\n");
     print OUT2 "$type\:\n";      print(OUTB "$type\:\n");
     print OUT2 join("",@{$BinaryRootMakefile{$type}});      print(OUTB join("",@{$BinaryRootMakefile{$type}}))
     print OUT2 "\n";   if $BinaryRootMakefile{$type};
     print SPEC join("",@{$dotspecfile{$type}});      print(OUTB "\n");
       print(SPEC join("",@{$dotspecfile{$type}})) if $dotspecfile{$type};
 }  }
 close OUT2;  close(OUTB);
 close OUT;  close(OUTS);
   
   close(SPEC);
   
 close SPEC;  # ------------------ mirror copy (BinaryRoot) files under a temporary directory
   
 `make -f $tag/BinaryRootMakefile directories`;  `make -f $tag/BinaryRootMakefile directories`;
 `make -f $tag/BinaryRootMakefile files`;  `make -f $tag/BinaryRootMakefile files`;
 `make -f $tag/BinaryRootMakefile links`;  `make -f $tag/BinaryRootMakefile links`;
   
 my $command="cd $currentdir/SOURCES; tar czvf LON-CAPA-$tag-$version.tar.gz ".  # ------------------------------------------------- roll everything into an RPM
     "LON-CAPA-$tag-$version";  print('Build a tarball and then run the rpm -ba command.'."\n");
 print `$command`;  my $command="cd $currentdir/SOURCES; tar czvf $name-$version.tar.gz ".
       "$name-$version";
   print(`$command`);
 $command="cd $currentdir/SPECS; rpm --rcfile=./rpmrc -ba ".  $command="cd $currentdir/SPECS; rpm --rcfile=./rpmrc -ba ".
     "LON-CAPA-$tag-$version.spec; cd ../RPMS/i386; cp ".      "$name-$version.spec; cd ../RPMS/i386; cp -v ".
     "LON-CAPA-$tag-$version-1.i386.rpm $invokingdir/.";      "$name-$version-1.i386.rpm $invokingdir/.";
 print `$command`;  print(`$command`);
 print `cd $invokingdir; rm -Rf $tag`;  
   # --------------------------------------------------------- clean everything up
   print('Removing temporary ./'.$tag.' directory'."\n");
   print(`cd $invokingdir; rm -Rf $tag`);
   
   # -------------------------------------------------------- Yeah! We're all done
   print('Success. Script complete.'."\n");
   
   # ----------------------------------------------------------------- SUBROUTINES
   # ----- Subroutine: find_info - recursively gather information from a directory
 sub find_info {  sub find_info {
     # only look for  
     my ($file)=@_;      my ($file)=@_;
     my $line;      my $line='';
     if (($line=`find $file -type f -prune`)=~/^$file\n/) {      if (($line=`find $file -type f -prune`)=~/^$file\n/) {
  $line=`find $file -type f -prune -printf "\%s\t\%m\t\%u\t\%g"`;   $line=`find $file -type f -prune -printf "\%s\t\%m\t\%u\t\%g"`;
  return ("files",split(/\t/,$line));   return("files",split(/\t/,$line));
     }      }
     elsif (($line=`find $file -type d -prune`)=~/^$file\n/) {      elsif (($line=`find $file -type d -prune`)=~/^$file\n/) {
  $line=`find $file -type d -prune -printf "\%s\t\%m\t\%u\t\%g"`;   $line=`find $file -type d -prune -printf "\%s\t\%m\t\%u\t\%g"`;
  return ("directories",split(/\t/,$line));   return("directories",split(/\t/,$line));
     }      }
     elsif (($line=`find $file -type l -prune`)=~/^$file\n/) {      elsif (($line=`find $file -type l -prune`)=~/^$file\n/) {
  $line=`find $file -type l -prune -printf "\%l\t\%m\t\%u\t\%g"`;   $line=`find $file -type l -prune -printf "\%l\t\%m\t\%u\t\%g"`;
  return ("links",split(/\t/,$line));   return("links",split(/\t/,$line));
     }      }
       die("**** ERROR **** $file is neither a directory, soft link, or file.\n");
   }
   
   # ------------------------- Subroutine: grabtag - grab a tag from an xml string
   sub grabtag {
       my ($tag,$text,$clean)=@_;
       # meant to be quick and dirty as opposed to a formal state machine parser
       my $value='';
       $cu=~/\<$tag\>(.*?)\<\/$tag\>/s; 
       $value=$1; $value=~s/^\s+//;
       if ($clean==1) {
    $value=~s/\n\s/ /g;
    $value=~s/\s\n/ /g;
    $value=~s/\n/ /g;
    $value=~s/\s+$//;
       }
       return($value);
 }  }
   
   # ----------------------------------------------------- Plain Old Documentation
   
   =head1 NAME
   
   make_rpm.pl - cleanly generate an rpm in a simple one-line command
   
   =head1 SYNOPSIS
   
   Usage: <STDIN> | make_rpm.pl <TAG> <VERSION>
          [CONFIGURATION_FILES] [DOCUMENTATION_FILES]
          [PATHPREFIX] [CUSTOMIZATION_XML]
   
   =head2 The standard input stream
   
   I<STDIN>, the standard input stream, provides the list of files to work
   with.  This list of file names must give the complete filesystem
   path starting from '/'.
   
   =over 4
   
   =item * For instance, the following is invalid:
   
    romeodir/file1.txt # ** INVALID! ** missing leading filesystem path
    romeodir/file2.txt
    romeodir/file3.txt
   
   =item * Whereas, the following is valid:
   
    /home/joe/romeodir/file1.txt
    /home/joe/romeodir/file2.txt
    /home/joe/romeodir/file3.txt
   
   =item * In terms of the B<find> command,
   
    "find romeodir | perl make_rpm.pl [COMMAND-LINE ARGUMENTS]"
   
   is incorrect, whereas
   
    "find /home/joe/romeodir |perl make_rpm.pl [COMMAND-LINE ARGUMENTS]"
   
   or
   
    "find `pwd`/romeodir |perl make_rpm.pl [COMMAND-LINE ARGUMENTS]"
   
   is correct.
   
   =back
   
   The standard input stream can also
   specify configuration files and documentation files through
   '#'-style commenting.
   
   For example, the following file listing encodes some of these directives:
   
    /home/joe/romeodir/buildloc/etc/romeo/user.conf # config(noreplace)
    /home/joe/romeodir/buildloc/etc/romeo/juliet.conf # config
    /home/joe/romeodir/buildloc/doc/man/man.1/romeo.1 # doc
    /home/joe/romeodir/buildloc/doc/man/man.1/romeo_talks.1 # doc
    /home/joe/romeodir/buildloc/usr/local/bin/where_art_thou
    /home/joe/romeodir/buildloc/usr/local/bin/romeo_talks
   
   The I<config> directive controls how files are replaced
   and/or backed up when a user attempts to install (B<rpm -i>) the F<.rpm>
   file generated by B<make_rpm.pl>.  The I<doc> directive controls how a
   given file is placed inside special documentation directories
   on the filesystem during rpm installation (B<rpm -i>).
   (If you want to learn more on how the B<rpm> tool gives configuration and
   documentation files special treatment, you should read about "Directives"
   in Edward Bailey's well-known "Maximum RPM" book available online
   at http://www.rpm.org/max-rpm/s1-rpm-inside-files-list-directives.html.)
   
   =head2 Description of command-line arguments
   
   I<TAG> ($tag), B<required> descriptive tag.  For example, a kerberos software
   package might be tagged as "krb4".
   
   I<VERSION> ($version), B<required> version.  Needed to generate version
   information for the RPM.  This should be in the format N.M where N and M are
   integers.
   
   I<CONFIGURATION_FILES>, B<optional> comma-separated listing of files to
   be treated as configuration files by RPM (and thus subject to saving
   during RPM upgrades).  Configuration files can also be specified in
   the standard input stream (as described in L<"The standard input stream">).
   
   I<DOCUMENTATION_FILES>, B<optional> comma-separated listing of files to be
   treated as documentation files by RPM (and thus subject to being
   placed in the F</usr/doc/RPM-NAME> directory during RPM installation).
   Documentation files can also be specified in
   the standard input stream (as described in L<"The standard input stream">).
   
   I<PATHPREFIX>, B<optional> path to be removed from file listing.  This
   is in case you are building an RPM from files elsewhere than
   root-level.  Note, this still depends on a root directory hierarchy
   after PATHPREFIX.
   
   I<CUSTOMIZATION_XML>, B<optional> filename where XML-ish information exists.
   Allows for customizing various pieces of information such
   as vendor, summary, name, copyright, group, autoreqprov, requires, prereq,
   description, and pre-installation scripts
   (see L<"Customizing descriptive data of your RPM software package">).
   
   =head2 Examples
   
    bash$ find /notreallyrootdir | perl make_rpm.pl \
          makemoney 3.1 '' \
          '/usr/doc/man/man3/makemoney.3' \
          /notreallyrootdir
    would generate makemoney-3.1-1.i386.rpm
   
    bash$ find /usr/local/bin | \
          perl make_rpm.pl mybinfiles 1.0
    would generate mybinfiles-1.0-1.i386.rpm
   
    bash$ find /home/joe/romeodir/buildloc | \
          perl make_rpm.pl romeo \
          1.0 '' '' '/home/joe/romeodir/buildloc' customize.xml
    would generate romeo with customizations from customize.xml.
   
   The I<CUSTOMIZATION_XML> argument represents a way to customize the
   numerous variables associated with RPMs.  This argument represents
   a file name.  (Parsing is done in an unsophisticated fashion using
   regular expressions.)  See
   L<"Customizing descriptive data of your RPM software package">.
   
   =head1 Customizing descriptive data of your RPM software package
   
   RPMS can be (and often are) packaged with descriptive data 
   describing authorship, dependencies, descriptions, etc.
   
   The following values can be tagged inside an XML file
   (specified by the 6th command-line argument)
   and made part of the RPM package information
   (B<rpm -qi E<lt>package-nameE<gt>>).
   
   =over 4
   
   =item * vendor
   
   =item * summary
   
   =item * name
   
   (overrides the <TAG> argument value; see 
   L<"Description of command-line arguments>)
   
   =item * copyright
   
   =item * group
   
   (the software package group;
   e.g. Applications/System, User Interface/X, Development/Libraries,
   etc.)
   
   =item * requires
   
   Contains all the dependency information (see the example below).
   
   =item * description
   
   =item * pre
   
   Commands to be executed prior to software package installation.
   
   =back
   
   Here is an example (note that B<make_rpm.pl> automatically substitutes
   any "<tag />" string with the first command-line argument described
   in L<"Description of command-line arguments">):
   
    <vendor>
    Laboratory for Instructional Technology Education, Division of
    Science and Mathematics Education, Michigan State University.
    </vendor>
    <summary>Files for the <tag /> component of LON-CAPA</summary>
    <name>LON-CAPA-<tag /></name>
    <copyright>Michigan State University patents may apply.</copyright>
    <group>Utilities/System</group>
    <AutoReqProv>no</AutoReqProv>
    <requires tag='setup'>
    <item>PreReq: setup</item>
    <item>PreReq: passwd</item>
    <item>PreReq: util-linux</item>
    </requires>
    <requires tag='base'>
    <item>PreReq: LON-CAPA-setup</item>
    <item>PreReq: apache</item>
    <item>PreReq: /etc/httpd/conf/access.conf</item>
    </requires>
    <requires>
    <item>Requires: LON-CAPA-base</item>
    </requires>
    <description>
    This package is automatically generated by the make_rpm.pl perl
    script (written by the LON-CAPA development team, www.lon-capa.org,
    Scott Harrison). This implements the <tag /> component for LON-CAPA.
    For more on the LON-CAPA project, visit http://www.lon-capa.org/.
    </description>
    <pre>
    echo "************************************************************"
    echo "LON-CAPA  LearningOnline with CAPA"
    echo "http://www.lon-capa.org/"
    echo " "
    echo "Laboratory for Instructional Technology Education"
    echo "Michigan State University"
    echo " "
    echo "** Michigan State University patents may apply **"
    echo " "
    echo "This installation assumes an installation of Redhat 6.2"
    echo " "
    echo "The files in this package are for the <tag /> component."
    echo "***********************************************************"
    </pre>
   
   =head1 DESCRIPTION
   
   Automatically generate an RPM software package from a list of files.
   
   B<make_rpm.pl> builds the RPM in a very clean and configurable fashion.
   (Finally!  Making RPMs outside of F</usr/src/redhat> without a zillion
   file intermediates left over!)
   
   B<make_rpm.pl> generates and then deletes temporary
   files needed to build an RPM with.
   It works cleanly and independently from pre-existing
   directory trees such as F</usr/src/redhat/*>.
   
   Input to the script is simple.  B<make_rpm.pl> accepts five kinds of
   information, three of which are mandatory:
   
   =over 4
   
   =item *
   
   (required) a list of files that are to be part of the software package;
   
   =item *
   
   (required) the absolute filesystem location of these files
   (see L<"The standard input stream">);
   
   =item *
   
   (required) a descriptive tag and a version tag for the naming of the
   RPM software package;
   
   =item *
   
   (optional) documentation and configuration files;
   
   =item *
   
   and (optional) an XML file that defines the additional metadata
   associated with the RPM software package.
   
   =back
   
   A temporary directory named $tag (first argument described in
   L<"Description of command-line arguments">) is
   
   =over 4
   
   =item *
   
   generated under the directory from which you run B<make_rpm.pl>.
   
   For example, user "joe" running
   
    cat file_list.txt | make_rpm.pl krb4 1.0
   
   would temporarily generate F</home/joe/krb4/>.
   
   =item *
   
   F</home/joe/krb4/> is deleted after the *.rpm
   file is generated.
   
   =back
   
   The RPM will typically be named $name-$version.i386.rpm
   where $name=$tag.  (The $name can be overridden in the customization
   XML file; see
   L<"Customizing descriptive data of your RPM software package">.)
   
   Here are some of the items are generated inside
   the $tag directory during the construction of an RPM:
   
   =over 4
   
   =item *
   
   RPM .spec file (F<./$tag/SPECS/$name-$version.spec>)
   
   =item *
   
   RPM Makefile (F<./$tag/SOURCES/$name-$version/Makefile>)
   
   This is the Makefile that is called by the rpm
   command in building the .i386.rpm from the .src.rpm.
   The following directories are generated and/or used:
   
   =over 4
   
   =item *
   
   SOURCE directory: F<./$tag/BinaryRoot/>
   
   =item *
   
   TARGET directory: F<./$tag/BuildRoot/>
   
   =back
   
   =item *
   
   BinaryRootMakefile (F<./$tag/BinaryRootMakefile>)
   
   This is the Makefile that this script creates and calls
   to build the F<$tag/BinaryRoot/> directory from the existing
   filesystem.
   The following directories are generated and/or used:
   
   =over 4
   
   =item *
   
   SOURCE directory: / (your entire filesystem)
   
   =item *
   
   TARGET directory: F<./$tag/BinaryRoot/>
   
   =back
   
   =back
   
   The final output of B<make_rpm.pl> is a binary F<.rpm> file.
   The F<./tag> directory is deleted (along with the F<.src.rpm>
   file).  The typical file name generated by B<make_rpm.pl> is
   F<$tag-$version.i386.rpm>.
   
   B<make_rpm.pl> is compatible with either rpm version 3.* or rpm version 4.*.
   
   =head1 README
   
   Automatically generate an RPM software package from a list of files.
   
   B<make_rpm.pl> builds the RPM in a very clean and configurable fashion.
   (Making RPMs "the simple way" in a one-line command.)
   
   B<make_rpm.pl> generates and then deletes temporary
   files (and binary root directory tree) to build an RPM with.
   It is designed to work cleanly and independently from pre-existing
   directory trees such as /usr/src/redhat/*.
   
   =head1 PREREQUISITES
   
   This script requires the C<strict> module.
   
   =head1 AUTHOR
   
    Scott Harrison
    harris41@msu.edu
   
   Please let me know how/if you are finding this script useful and
   any/all suggestions.  -Scott
   
   =head1 LICENSE
   
   Written by Scott Harrison, harris41@msu.edu
   
   Copyright Michigan State University Board of Trustees
   
   This file is part of the LearningOnline Network with CAPA (LON-CAPA).
   
   This is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   
   This file is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   The GNU Public License is available for review at
   http://www.gnu.org/copyleft/gpl.html.
   
   For information on the LON-CAPA project, please visit
   http://www.lon-capa.org/.
   
   =head1 OSNAMES
   
   Linux
   
   =head1 SCRIPT CATEGORIES
   
   UNIX/System_administration
   
   =cut
   

Removed from v.1.12  
changed lines
  Added in v.1.17


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>