#!/usr/bin/perl -w # Rebuild an RPM .spec file from a package # Waider July 25 2000 # # 03/11/2004 Add changelog # Check for other packages built from the same source file # Clean up file listing a little use POSIX; use Data::Dumper; # Get the basics $rpm = "/bin/rpm"; $file = shift; die unless $file; # Find out if this is an installed package or something on disk open( INFO, "$rpm -q $file|" ); @info = ; close( INFO ); if ( grep /^package $file is not installed$/, @info ) { $pkg = "p"; } else { $pkg = ""; } # Handy variable to have around $thispkg = `$rpm -q$pkg --queryformat '[%{NAME}-%{VERSION}]' $file`; # see if there's anything else built from the same src.rpm as this my @allpkgs = ( $thispkg ); my $srcrpm = `$rpm -q$pkg --queryformat '[%{SOURCERPM}]' $file`; print STDERR "Source came from $srcrpm, looking for other packages built from that...\n"; for my $line ( split( /\n/, `$rpm -qa --queryformat '%{SOURCERPM} %{NAME}-%{VERSION}\n'` )) { my ( $s, $p ) = split( ' ', $line ); if ( $s eq $srcrpm ) { push @allpkgs, $p unless grep /^$p$/, @allpkgs; } } # Some of this is bloody EVIL. $format =<<"EOF"; Summary: %{SUMMARY} Name: %{NAME} Version: %{VERSION} Release: %{RELEASE} Copyright: %{COPYRIGHT}%|COPYRIGHT?{}:{ DELETEME}| Group: %{GROUP} Source: %{SOURCE}%|SOURCE?{}:{ DELETEME}| %|SOURCE?{ DELETEME}:{Source: $thispkg.tar.gz}| Url: %{URL}%|URL?{}:{ DELETEME}| Packager: %{PACKAGER}%|PACKAGER?{}:{ DELETEME}| Vendor: %{VENDOR}%|VENDOR?{}:{ DELETEME}| Requires: [%{REQUIRENAME} %{REQUIREFLAGS} %{REQUIREVERSION} ]%|REQUIRENAME?{}:{ DELETEME}| Provides: [%{PROVIDES} ] %%description %{DESCRIPTION} %%prep %%setup %%build %%install %%clean %%pre%|PREIN?{}:{ DELETEME}| %{PREIN}%|PREIN?{\n}:{ DELETEME}| %%post%|POSTIN?{}:{ DELETEME}| %{POSTIN}%|POSTIN?{\n}:{ DELETEME}| %%preun%|PREUN?{}:{ DELETEME}| %{PREUN}%|PREUN?{\n}:{ DELETEME}| %%postun%|POSTUN?{}:{ DELETEME}| %{POSTUN}%|POSTUN?{\n}:{ DELETEME}| %%files EOF print "Recovering huge lumpy chunks\n"; @lines = grep !/ DELETEME$/, `$rpm -q$pkg --queryformat '$format' $file`; # MAGIC! @lines = map { if ( /^Requires\: / ) { s/\s+0\s+/ /g; s/12/>=/g; s/16396/>=/g; s/ (16384|64|1344|4416) //g; # no version specified s/(16777290|74)/<=/g; } $_; } @lines; # Ideally, we could slim down the above by figuring out what provides # each requirement, and sorting and uniquing that. # Now figure out the %files section print STDERR "recovering files list...\n"; @lines2 = `$rpm -q$pkg --queryformat '[%{FILEFLAGS} %{FILENAMES}\n]' $file`; # Fix the flags for each file @lines2 = map { s|^2 (/usr/(share/)?doc/$thispkg/)?|\%doc |; s|^1 |\%config |; s|^0 ||; s|/usr/doc/$thispkg\n||; # throw away $_ } @lines2; # clean up the files list a bit my @docs = grep /^\%doc/, @lines2; my @files = grep !/^\%doc/, @lines2; my @man = grep /\/man\d/, @docs; @docs = grep !/\/man\d/, @docs; @man = map { s|\%doc ||; $_ } @man; push @lines, join( " ", "\%doc", map { s|^\%doc (.*)\n|$1|; $_ } @docs ) . "\n"; push @lines, ( @files, @man ); # add in the changelog push @lines, "\n"; push @lines, "\%changelog\n"; for my $cl ( split( '\n', `$rpm -q$pkg --queryformat '[* %{CHANGELOGTIME} %{CHANGELOGNAME}\n%{CHANGELOGTEXT}\n\n]' $file` )) { if ( $cl =~ /^\* (\d+) (.*)$/ ) { $cl = strftime( "* %a %b %e %Y $2", gmtime( $1 )); } push @lines, $cl . "\n"; } open( SPEC, ">$thispkg-rebuilt.spec" ); print SPEC @lines; close( SPEC );