Category: System Packaging
Author/Contact Info DRAUONER <jmrenouard@gmail.com>
Description: myrpm2 is a simple rpm packaging tool.

How to install it ?

  • yum -y install cpan2rpm
  • cpan2rpm —no-sign Text ::Template
  • cpan2rpm —no-sign IO ::Zlib
  • cpan2rpm —no-sign Archive ::Tar
  • cpan2rpm —no-sign Getopt ::Long
  • cp myrpm2.pl /usr/bin

How to use it ?

General Options :

  • -h, —help : Print this help.
  • -V, —verbose : Print debug information, verbose mode.
  • -b, —build : Build the package automattically at the end.
  • -d, —directory= : Root directory ( / by default ).

Package Options :

  • -n, —name= : Package name.
  • -v, —version= : Package version.
  • -r, —release= : Package release.
  • -D, —description= : Package Description.
  • -S, —summary= : Package Summary.
  • -p, —packager= : Packager identity.

Examples

Package a sub directory as the root filesystem

cd /home/jmrenouard/myrpmBuildDir && find `pwd` -iname ’*’ -print | myrpm.pl -V -d /home/jmrenouard/myrpmBuildDir -n toto -b
  • Find build the list of all the files in /home/jmrenouard/myrpmBuildDir.
  • myrpm.pl packages all the files /home/jmrenouard/myrpmBuildDir in a package with toto as name.
  • myrpm.pl consider /home/jmrenouard/myrpmBuildDir as the root of all the files so all this files will be installed from the root file system by the rpm program.

Re package a installed rpm

rpm -ql yum |  myrpm.pl -V -n yum -r 1_jmr -b
  • Rpm gives the list of the files in the yum package installed on the system.
  • myrpm.pl packages all the files in a package with yum as name and 1_jmr as release.
  • This is a new way to package modification on a installed system.

#!/usr/bin/perl 

use warnings;
use strict;
use Text::Template;
use Archive::Tar;
use File::stat;
use Getopt::Long;

my $tmpDir=$ENV{'HOME'}."/tmp";
my $srcDir=$ENV{'HOME'}."/fedora/SOURCES";
my $specDir=$ENV{'HOME'}."/fedora/SPECS";

my $line="";
my @files=();
my @defFiles=();
my @instFiles=();


Getopt::Long::Configure('bundling');

my ($on, $ov, $or, $op, $oI, $oE, $oh, $ob, $od, $oV, $oD, $oS);
GetOptions
    ("h"   => \$oh, "help"       => \$oh,
     "n=s" => \$on, "name=s"       => \$on,
     "b" => \$ob, "build"       => \$ob,
     "V" => \$oV, "verbose"       => \$oV,
     "v=s" => \$ov, "version=s"  => \$ov,
     "d=s" => \$od, "directory=s"=> \$od,
     "D=s" => \$oD, "description=s"=> \$oD,
     "S=s" => \$oS, "summary=s"=> \$oS,
     "r=s" => \$or, "release=s"  => \$or,
     "p=s" => \$op, "packager=s" => \$op);

print_usage() if ($oh); 
($on) || ($on = shift) || ($on = "TailTail");
($ov) || ($ov = shift) || ($ov = "0.1");
($or) || ($or = shift) || ($or = "1");
($op) || ($op = shift) || ($op = 'Jean-Marie Renouard<jean-marie.renou
+ard@alcove.fr>');
($od) || ($od = shift) || ($od = "");
($oD) || ($oD = shift) || ($oD = "A standard description for this pack
+age ;)");
($oS) || ($oS = shift) || ($oS = "A standard summary for this package 
+;)");

my %lusers;
my %lgroups;

while (defined($line = <>)) {
    chop($line);
    last if ($line eq "");
    my $line_chrooted=$line;
    $line_chrooted =~ s/^$od\///;
#    print " * Traitement de '$line'\n" if defined $oV;
     die (" $line does nt exists") unless ( -e $line);
    my $mode=stat($line)->mode;
    my $uid =stat($line)->uid;
    my $gid =stat($line)->gid;
    my $cmd="cat /etc/passwd | cut -d ':' -f 1,3 | grep $uid";
    my @nameu=split (':', `$cmd`);
    
    $cmd="cat /etc/group | cut -d ':' -f 1,3 | grep $gid";
    my @nameg=split (':', `$cmd`);

#    print "\n* util=".$nameu[0];
#    print "\n* group=".$nameg[0];
    $lusers{$nameu[0]}++;
    $lgroups{$nameg[0]}++;

    my $trueMode=sprintf( "%04o", $mode & 07777);
    push @files, "./$line_chrooted";
#    print "\t * $line into Tar ball....\n" if  defined $oV; 
#    print "\t * $line and $line_chrooted into Spec file....\n" if  de
+fined $oV; 
    
#    $line =~ s/^\///;
    push @instFiles, "mkdir -p `dirname %{buildroot}$line` || 1" if (-
+f "$line");
    push @instFiles, "%{__install} -m $trueMode $line_chrooted %{build
+root}/$line_chrooted" if ( -f "$line");
    push @instFiles, "%{__install} -d -m $trueMode $line_chrooted %{bu
+ildroot}/$line_chrooted" if ( -d "$line");
    push @defFiles, "%defattr(-, $nameu[0], $nameg[0], $trueMode)", "/
+$line_chrooted";
}

my $pre_code = "echo -e 'PRE'";
foreach my $g (keys(%lgroups)) { $pre_code.="\ngroupadd $g || 1";}
foreach my $u (keys(%lusers) ) { $pre_code.="\nadduser $u || 1"; }


############################
# THE TEMPLATE
############################
my $templDef= 'Summary:         <$summary> 
Name:            <$name>
Version:         <$version>
Release:           <$release>    
License:         GPL
URL:             http://www.alcove.fr
Source0:         %{name}-%{version}.tar.gz
Group:             System/Administration
Vendor:            AlcĂ´ve
Packager:        <$packager>
Buildarch:         i486
BuildRoot:         %{_tmppath}/%{name}-%{version}-root

%description 
<$description>

%prep
#%setup -q 
#-n %{name}-%{version}
%setup -c -q

%pre
<$pre_code>

%build
echo -e \'BUILD\'

%install
mkdir -p %{buildroot}
< foreach $i (@instFiles) { $OUT.= "$i\n"; }>

%post
<$post_code>

%preun
<$preun_code>

%postun
<$postun_code>

%clean
rm -rf %{buildroot}

%files
< foreach $i (@listOfFiles) { $OUT.= "$i\n"; }>
 
%changelog
* <$date> <$packager> <$name>-<$version>-<$release>
- <$ChangeLog>
-  Generated version.';

    
my $template = Text::Template->new(SOURCE => "$templDef", TYPE => 'STR
+ING', DELIMITERS => ["<", ">"])
          or die "Couldn't construct template: $Text::Template::ERROR"
+;

      my @monthname = qw(January February March April May June
                           July August September October November Dece
+mber);
      my %vars = (name => "$on",
          summary => "$oS",
          version => "$ov",
          release => "$or", 
          packager => "$op",
          pre_code => "$pre_code",
          post_code => "echo -e 'POST'",
          preun_code => "echo -e 'PREUN'",
          postun_code => "echo -e 'POSTUN'",
          listOfFiles =>\@defFiles,      
          instFiles =>\@instFiles,      
          ChangeLog    => 'Test release at the starting point',
          date => 'Wed May 04 2005',#`date +"%a %b %d %Y"` ,
          description => "$oD",
);

my $result = $template->fill_in(HASH => \%vars);
die "Couldn't fill in template: $Text::Template::ERROR" unless (define
+d $result); 

#die ("erreur Path : $od") unless defined $od;

if ( $od eq "") { chdir ("/") } else {    chdir($od); }
#generate Tarball
my $tar = Archive::Tar->new;
foreach my $file (@files) {

    $file =~ s/^\//\.\//;
#    print "\n$file to Archive...\n";
    $tar->add_files( $file);
}

$tar->write("$srcDir/$vars{'name'}-$vars{'version'}.tar.gz", 1);
#Writing spec file
open F, "> $specDir/$vars{'name'}-$vars{'version'}.spec";
    print F $result if (defined($result));
    print $result if (defined($result) && $oV);
close F;

#my $editor=$ENV{'EDITOR'};
#$editor="/bin/sh /usr/bin/vim" unless (defined($editor));
#`$editor $specDir/$vars{'name'}-$vars{'version'}.spec` if ($oe);

#Compiling pakage
my $cmd="rpmbuild -ba $specDir/$vars{'name'}-$vars{'version'}.spec";

print "\n#Executing to build package : $cmd\n" if ($oV);
print `$cmd` if ($ob);
exit 0;

sub print_usage {
print " Usage: myrpm.pl [OPTION]... \n";
print "myrpm.pl is a automatic spec file generator and builder.\n";
print "Allow you to install freely software on a rpm compliant system 
+and realize a binary package.\n";
print "from a list of file. This program manages rigths and users.\n";
print "It s a simple tool that simplify packaging in chroot mode.\n";

print "\nGeneral Options :";
print "\n -h, --help\t\t\t: Print this help.";
print "\n -V, --verbose\t\t\t: Print debug information, verbose mode."
+;
print "\n -b, --build\t\t\t: Build the package automattically at the e
+nd.";
print "\n -d, --directory=<directory>\t: Root directory ( / by default
+ ).";

print "\n\nPackage Options :";
print "\n -n, --name=<name>\t\t: Package name";
print "\n -v, --version=<version>\t: Package version.";
print "\n -r, --release=<release>\t: Package release.";
print "\n -D, --description=<description>: Package Description.";
print "\n -S, --summary=<summary>\t: Package Summary.";
print "\n -p, --packager=<packager>\t: Packager identity.";

print "\n\nExamples :";
print "\ncd /home/jmrenouard/myrpmBuildDir && find `pwd` -iname '*' -p
+rint | myrpm.pl -V -d /home/jmrenouard/myrpmBuildDir -n toto -b";
print "\n\t\t * Find build the list of all the files in /home/jmrenoua
+rd/myrpmBuildDir.";
print "\n\t\t * myrpm.pl packages all the files /home/jmrenouard/myrpm
+BuildDir  in a package with toto as name.";
print "\n\t\t * myrpm.pl consider /home/jmrenouard/myrpmBuildDir as th
+e root of all the files so all this files will be installed from the 
+root file system by the rpm program.";

print "\n\nrpm -ql yum |  myrpm.pl -V -n yum -r 1_jmr -b";
print "\n\t\t * Rpm gives the list of the files in the yum package ins
+talled on the system.";
print "\n\t\t * myrpm.pl packages all the files in a package with yum 
+as name and 1_jmr as release.";
print "\n\t\t * This is a new way to package modification on a install
+ed system.";

print "\n\nSubmit bugs at Jean-Marie Renouard <jmrenouard at gmail.com
+>\n";      
exit;
}