#!/usr/bin/perl -w

use strict;
use warnings;
use File::Find;
use RPM::Header;
use Getopt::Long;
use Pod::Usage;
use Date::Parse;
use File::Basename;
use Date::Format;

my $user;
my ($datamin,$datamax);
my ($timemin,$timemax);
my $verbose=1;
my $help=0;
my ($this_month, $ignore_mtime);
my $check_mtime;
my %CHECK_MTIME=map {$_=>1} qw/strict month ignore no/;

my $result = GetOptions (
    'check-mtime!'=> \$check_mtime,
    'min=s'=> \$datamin,
    'max=s'=> \$datamax,
    'month' => \$this_month,
    'user=s'=> \$user,
    'quiet'=> sub {$verbose=0},
    "verbose+"  => \$verbose,
    "help"  => \$help,
);

if ($check_mtime and not $CHECK_MTIME{$check_mtime}) {
    warn "--check-mtime: invlid value $check_mtime.
Expected one of ",join(' ',sort(keys(%CHECK_MTIME))),"\n";
    exit(1);
}
$check_mtime//='month';

if ($this_month) {
#    %L      month number, starting with 1
#    %m      month number, starting with 01
#    %b      month abbr
#    %y      year (2 digits)
#    %Y      year (4 digits)
    $datamax=time2str("1 %b %Y", time+3600*24*3);
    $datamin=time2str("1 %b %Y", time-3600*24*27);
}

print STDERR defined ($datamin)? $datamin: 'oldest', ' - ', defined($datamax) ?$datamax: 'latest',"\n" if $verbose;

$timemin = str2time($datamin) if defined $datamin;
$timemax = str2time($datamax) if defined $datamax;

my @directories = @ARGV;

if ($help or ! @directories) {
    pod2usage();
}

map {-d $_ or die "argument is not a directory: $_\n"} @directories;

# first step is just a usual find; to find dup names
find(\&wanted,  @directories);
sub wanted {
# $File::Find::dir  = /some/path/
# $_                = foo.ext
# $File::Find::name = /some/path/foo.ext
    my $name=$_;
    return unless /\.src\.rpm$/ and not -l $_;
    my @stat=stat $name;
#  0 dev      device number of filesystem
#  1 ino      inode number
#  2 mode     file mode  (type and permissions)
#  3 nlink    number of (hard) links to the file
#  4 uid      numeric user ID of file's owner
#  5 gid      numeric group ID of file's owner
#  6 rdev     the device identifier (special files only)
#  7 size     total size of file, in bytes
#  8 atime    last access time in seconds since the epoch
#  9 mtime    last modify time in seconds since the epoch
# 10 ctime    inode change time in seconds since the epoch (*)
# 11 blksize  preferred block size for file system I/O
# 12 blocks   actual number of blocks allocated
    my $rpmpath=$name;
    my $rpmmtime = $stat[9];
    if ($check_mtime eq 'strict') {
	return if defined ($timemin) and $rpmmtime < $timemin;
	return if defined ($timemax) and $rpmmtime > $timemax;
    } elsif ($check_mtime eq 'month') {
	# 3600*24*31 = 2678400 - seconds in a month
	return if defined ($timemin) and $rpmmtime < $timemin - 2678400;
	return if defined ($timemax) and $rpmmtime > $timemax + 2678400;
    }
    #print "eval $rpmpath\n";
    my $header;
    eval {
	$header=new RPM::Header $rpmpath;
    };
    if ($@) {
	warn "$rpmpath skipped: $@\n" if $verbose;
	return;
    }
    my $changelogname=$header->{CHANGELOGNAME};
    my $changelogtime=$header->{CHANGELOGTIME};
    #my $changelogtext=$header->{CHANGELOGTEXT};
    unless ($changelogtime and $changelogname) { # and $changelogtext
	print STDERR 'ERROR: bad changelog time for ', basename($rpmpath),"\n";
    } else {
	#print basename($rpmpath),"\n";
	for (my $i=0;$i<@$changelogtime;$i++) {
	    next if defined ($timemin) and $changelogtime->[$i]<= $timemin;
	    next if defined ($timemax) and $changelogtime->[$i]> $timemax;
	    next if defined($user) && $changelogname->[$i]!~/\b$user\@/;
	    #print "name i=$i: ", $changelogname->[$i],"\n";
	    #print "time i=$i: ", ctime($changelogtime->[$i]);#,"\n";
	    #print "text i=$i: ", $changelogtext->[$i],"\n";
	    print basename($rpmpath), ' ', $changelogname->[$i], ' ',ctime($changelogtime->[$i]);#,"\n";
	}
    }
    #exit;
}


=head1	NAME

srpmlschangelog - .

=head1	SYNOPSIS

B<srpmlschangelog>
[B<-h|--help>]
[B<-v|--verbose>]
[B<-q|--quiet>]
[B<--min> I<date>]
[B<--max> I<date>]
[B<--month>]
[B<-u|--user> I<userid>]
[I<DIR>...] 

=head1	DESCRIPTION

B<srpmlschangelog> 

=head1	OPTIONS

=over

=item	B<-h, --help>

Display this help and exit.

=item	B<-v, --verbose>, B<-q, --quiet>

Verbosity level. Multiple -v increase the verbosity level, -q sets it to 0.

=item	B<--min> I<date>

List changelogs starting from I<date>.

=item	B<--max> I<date>

List changelogs up to I<date>.

=item	B<--month>

List changelogs for the current month.

=item	B<-u|--user> I<userid>

List changelogs that belong to specified user.

=item	B<--check-mtime>=I<strict|month|no>

Checking all changelogs can take too long. srpmlschangelog
can optimize it by first checking mtime of src.rpm.
strict - ignore mtime outside the time interval
month - ignore mtime outside the time interval plus/minus a month (default)
no - do not optimize search for changelogs using mtime.

=back

=head1	AUTHOR

Written by Igor Vlasenko <viy@altlinux.org>.

=head1	COPYING

Copyright (c) 2009-2021 Igor Vlasenko, ALT Linux Team.

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.

=cut

