Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37563993
en ru br
Репозитории ALT
S:0.3-alt1
5.1: 0.2-alt3
4.1: 0.2-alt3
4.0: 0.2-alt3
3.0: 0.2-alt3
www.altlinux.org/Changes

Группа :: Разработка/Прочее
Пакет: srpmcmp

 Главная   Изменения   Спек   Патчи   Исходники   Загрузить   Gear   Bugs and FR  Repocop 

#!/usr/bin/perl

=head1 NAME

srpmcmp - compare source RPM packages

=head1 SYNOPSIS

srpmcmp [options] package-v1.src.rpm package-v2.src.rpm

=head1 DESCRIPTION

This perl script compares the contents of two source RPM packages in unified
diff format.

=head1 OPTIONS

=over

=item --verbose

Explain autocrap and RCS removal (see below).

=item --deep

Compare also source trees (by default, only top-level files like spec-files and
patches are compared).

=item --autocrap

Compare also files automatically generated with GNU autotools.
Files with the following names are examnied:

aclocal.m4
configure
config.guess
config.h.in
config.rpath
config.sub
depcomp
install-sh
ltmain.sh
Makefile.in
Makefile
missing
mkinstalldirs
texinfo.tex

=item --rcs

Keep RCS tags intact. Those are unexpanded by default.
Here is a list of RCS keywords (according to C<cvs.info>):

Author
Date
Header
Id
Name
Locker
Log
RCSfile
Revision
Source
State

=back

=head1 COPYING

Copyright (c) 2003, 2004. Alexey Tourbin <at@altlinux.org>. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

=cut

use strict;

use Getopt::Long qw(GetOptions);
GetOptions verbose => \my $opt_verbose,
deep => \my $opt_deep, autocrap => \my $opt_autocrap, rcs => \my $opt_rcs;

use Cwd qw(getcwd realpath);
my $saved_cwd = getcwd();
use sigtrap qw(die normal-signals);

sub fatal {
chdir $saved_cwd;
die "$0: @_\n";
}

sub verbose {
print STDERR "@_\n" if $opt_verbose;
}

sub tmp_unpack ($) {
use File::Temp qw(tempdir);

my $rpm = shift;
my $dir = tempdir("srpmcmp.XXXXXXXXXX", TMPDIR => 1, CLEANUP => 1);
chdir $dir;
my $rv = system qq(rpm2cpio '$rpm' | cpio -idmu --quiet --no-absolute-filenames);
fatal "`rpm2cpio $rpm' failed" if $rv;
return $dir;
}

sub uncompress ($) {
my $dir = shift;
chdir $dir;

if (my @gz = (<*.gz>, <*.tgz>)) {
my $rv = system qw(gzip -df) => @gz;
fatal "`gzip -df @gz' failed" if $rv;
}
if (my @bz2 = <*.bz2>) {
my $rv = system qw(bzip2 -df) => @bz2;
fatal "`bzip2 -df @bz2' failed" if $rv;
}
if (my @xz = <*.xz>) {
my $rv = system qw(xz -df) => @xz;
fatal "`xz -df @xz' failed" if $rv;
}
foreach (<*.tar>) {
my $rv = system qw(tar -xf) => $_;
fatal "`tar -xf $_' failed" if $rv;
unlink;
}
}

sub cleanup ($) {
my $dir = shift;
chdir $dir;

sub kill_autocrap {
my %crap = (
"aclocal.m4" => [
"# generated automatically by aclocal",
"dnl aclocal.m4 generated automatically by aclocal",
],
"configure" => [
"# Generated by GNU Autoconf",
"# Generated automatically using autoconf",
],
"config.guess" => [
"# Attempt to guess a canonical system name",
],
"config.h.in" => [
"/* config.h.in. Generated automatically from configure.in by autoheader",
"/* config.h.in. Generated from configure.in by autoheader",
],
"config.rpath" => [
"# Output a system dependent set of variables",
],
"config.sub" => [
"# Configuration validation subroutine script",
],
"depcomp" => [
"# depcomp - compile a program generating dependencies",
],
"install-sh" => [
"# install - install a program, script, or datafile",
],
"ltmain.sh" => [
"# ltmain.sh - Provide generalized library-building support services",
],
"Makefile.in" => [
"# Makefile.in generated by automake",
"# Makefile.in generated automatically by automake",
],
"Makefile" => [
"# Generated automatically from Makefile.in",
],
"missing" => [
"# Common stub for a few missing GNU programs while installing",
],
"mkinstalldirs" => [
"# mkinstalldirs --- make directory hierarchy",
],
"texinfo.tex" => [
"% texinfo.tex -- TeX macros to handle Texinfo files"
],
);

my $fname = $_;
return unless $crap{$fname};
return unless open my $fh, $fname;
while (my $line = <$fh>) {
last if $. > 9;
if (grep { index($line, $_) == 0 } @{$crap{$fname}}) {
unlink $fname;
verbose "removed $File::Find::name (autocrap)";
}
}
}
sub kill_rcs {
my $fname = $_;
my $keywords = qr(Author|Date|Header|Id|Name|Locker|Log|RCSfile|Revision|Source|State);

open my $fh, "+<", $fname
or return;
my ($atime, $mtime) = (stat $fh)[7,9];
local $/ = undef;
local $_ = <$fh>;
if (s/\$($keywords):.*?\$/\$$1\$/go) {
verbose "unexpanded RCS tags in $File::Find::name";
seek $fh, 0, 0;
print $fh $_;
truncate $fh, tell $fh;
utime $atime, $mtime => $fname;
}
}
sub wanted {
-f || return;
&kill_autocrap unless $opt_autocrap;
&kill_rcs unless $opt_rcs;
}

use File::Find qw(find);
find \&wanted => ".";
}

sub cmp_rm ($$) {
my ($f1, $f2) = @_;
my $rv;
if (-e $f1 && -e $f2) {
local $ENV{LC_ALL} = "C";
local $ENV{TZ} = "UTC0";
$rv = `diff -abBpruw $f1 $f2`;
system qw(rm -rf) => $f1, $f2;
}
return $rv;
}

sub _cmp_eq ($$) {
return $_[0] eq $_[1];
}

sub _cmp_ver ($$) {
my ($ver1, $ver2) = @_;
foreach ($ver1, $ver2) {
s/rc\d//ig;
s/pre\d//ig;
s/[^a-z]//g;
}
return $ver1 eq $ver2;
}

sub same_type ($$) {
my ($f1, $f2) = @_;
return "f" if -f $f1 && -f $f2;
return "d" if -d $f1 && -d $f2 && $opt_deep;
return;
}

sub supercmp ($$$) {
my ($dir1, $dir2, $glob) = @_;
my $diff;
try: while (1) {
foreach my $cmp_func (\&_cmp_eq, \&_cmp_ver) {
chdir $dir1; my @f1 = glob($glob);
foreach my $f1 (@f1) {
chdir $dir2; my @f2 = glob($glob);
foreach my $f2 (@f2) {
if ($cmp_func->($f1, $f2) && same_type("$dir1/$f1", "$dir2/$f2")) {
$diff .= cmp_rm "$dir1/$f1", "$dir2/$f2";
next try;
}
}
}
}
last;
}
return $diff;
}

sub srpmcmp ($$) {
my ($rpm1, $rpm2) = map { realpath($_) } @_;

my $dir1 = tmp_unpack $rpm1; uncompress $dir1; cleanup $dir1;
my $dir2 = tmp_unpack $rpm2; uncompress $dir2; cleanup $dir2;

my $diff = supercmp($dir1, $dir2, "*.spec")
. supercmp($dir1, $dir2, "*.patch")
. supercmp($dir1, $dir2, "*.diff")
. supercmp($dir1, $dir2, "*.init")
. supercmp($dir1, $dir2, "*.menu")
. supercmp($dir1, $dir2, "*")
. "End of diff\n\n";

# see the rest
my $rest1 = `/bin/ls -AF $dir1`;
$diff .= "Files not compared in $dir1:\n$rest1\n" if $rest1 =~ /\S/;
my $rest2 = `/bin/ls -AF $dir2`;
$diff .= "Files not compared in $dir2:\n$rest2\n" if $rest2 =~ /\S/;

# filter out temporary directories
for ($rpm1, $rpm2) {
s/.*\///;
s/\.src\.rpm$//;
}
$diff =~ s/\Q$dir1/$rpm1/g;
$diff =~ s/\Q$dir2/$rpm2/g;
return $diff;
}

@ARGV == 2 and -f $ARGV[0] and -f $ARGV[1] or print <<EOF and exit 1;
usage:
$0 [--deep] [--autocrap] [--rcs] package1.src.rpm package2.src.rpm
See srpmcmp(1) for details.
EOF

print srpmcmp $ARGV[0], $ARGV[1];
chdir $saved_cwd;
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin