#!/usr/bin/perl

use strict;
use warnings;

use Getopt::Long;
use Pod::Usage;

my ($opt_srclist,$opt_oneline,$help,$srpmdir,$opt_name2path);
my $verbose=0;
my $options_result = 
    GetOptions (
	"h|help"   => \$help,
	"1"	=> \$opt_oneline,
	"name2path"	=> \$opt_name2path,
	"dir|srpmdir=s" => \$srpmdir,
	"list|namelist|namefile=s" => \$opt_srclist,
	"verbose+"  => \$verbose,
);

if ($help or ($opt_name2path and not ($opt_srclist or $srpmdir))) {
    #exec "pod2usage --exit=0 $0";
    pod2usage({ #-message => "the options below are package-specific:" ,
	-exitval => 0  ,
	-verbose => $verbose,
	#-output  => $filehandle
	      } );
}

my @all_names;
my %name2path;

if (not $opt_name2path) {
    &__load_namelist($opt_srclist,0) if defined $opt_srclist;
} else {
    if (not $srpmdir and $opt_srclist=~m!files/list/src.list$!) {
	$srpmdir=$opt_srclist;
	$srpmdir=~s!files/list/src.list$!files/SRPMS!;
    };
    die " --srpmdir /path is required\n" unless defined $srpmdir;
    my $has_path;
    $has_path=&__load_namelist($opt_srclist,1) if $opt_srclist;
    if (not $has_path) {
	&__traditional_load_name2path($srpmdir);
	@all_names=keys(%name2path) unless $opt_srclist;
    }
}

while (my $line=<>) {
    my @list = map {&__expand_glob($_,\@all_names)} &__line2array($line);
    next if scalar @list == 0;
    @list = map {$name2path{$_}} @list if $opt_name2path;
    if ($opt_oneline) {
	map {print "$_\n"} @list;
    } else {
	print join("\t",@list), "\n";
    }
}

sub __load_namelist {
    my ($file,$load_path)=@_;
    my $has_path;
    open (my $fn, '<', $file) or die "can't open file $file\n";
    while (my $line=<$fn>) {
	my @list = &__line2array($line);
	push @all_names, $list[0];
	if ($load_path and $list[2]) {
	    my $path=$srpmdir.'/'.$list[2];
	    $name2path{$list[0]}=$path;
	    $has_path=1;
	}
    }
    close($fn);
    return $has_path;
}

sub __traditional_load_name2path {
    my ($srpmdir)=@_;
    die "$srpmdir is required\n" unless defined $srpmdir;
    die "$srpmdir: not a directory\n" unless -d $srpmdir;
    my $PWD=`pwd`;
    chomp $PWD;
    $srpmdir=~s!^\./!!;
    $srpmdir="$PWD/$srpmdir" if $srpmdir!~m!^/!;
    open (RPMARGS_FILES, "ls -1 $srpmdir |egrep -x '[^.].*[.]src[.]rpm' |") || die $!;
    my $f;
    while ($f=<RPMARGS_FILES>) {
	chomp $f;
	my $path="$srpmdir/$f";
	next unless -e $path;
	my $rhref = new RPM::Header $path;
	$name2path{$rhref->{NAME}}=$path;
    }
    close RPMARGS_FILES;
};


# glob expansion on $opt_srclist
sub __expand_glob {
    my ($pattern, $arrayptr)=@_;
    return $pattern unless $pattern =~/[?*]/;
    my $regexp=&glob2pat($pattern);
    my @names = grep {/$regexp/} @$arrayptr;
    print STDERR "WARNING: pattern $pattern does not match.\n" unless @names;
    return @names;
}

sub __line2array {
    my $line=shift;
    chomp $line;
    $line=~s/^\s*//;
    $line=~s/\s*$//;
    return if $line=~/^\s*#/;
    return if $line eq '';
    return split (/\s+/, $line);
}

sub glob2pat {
    my $globstr = shift;
    my %patmap = (
	'*' => '.*',
	'?' => '.',
	'[' => '[',
	']' => ']',
	'{' => '(?:',
	'}' => ')',
	',' => '|',
	);
    $globstr =~ s{(.)} { $patmap{$1} || "\Q$1" }ge;
    return '^' . $globstr . '$';
}


=head1	NAME

girar-nmu-filter-name-expand-glob - filter that expands pkg names

=head1	SYNOPSIS

B<girar-nmu-filter-name-expand-glob>
[B<-h>]
[B<-1>]
[B<--name2path>]
[B<--srpmdir>=I</path/to/files/SRPMS>]
B<--list>=I</files/list/src.list>
[input file] ...

=head1	DESCRIPTION

B<girar-nmu-filter-name-expand-glob> 
Pipe filter/text file converter.
Expand shell globs in src.rpm names using the list of all possible
src.rpm names in --namelist <namelist file>.

Any file containing available src.rpm names in its first column will do,
such as /ALT/Sisyphus/files/list/src.list.
It takes as an argument either STDIN or [a list of] text files,

=head1	OPTIONS

=over

=item	B<-h, --help>

Display this help and exit.

=item	B<--list,--namefile> I<namefile>

Mandatory option. I<namefile> may be any file containing available src.rpm names 
as its first column, such as /ALT/Sisyphus/files/list/src.list.

=item	B<-1>

Oneline mode: print one name per line.

=item	B<--name2path>

Path mode: replace src.rpm name with full path to file.
--srpmdir is required unless I<namefile> is specified as */files/list/src.list

=item	[B<--srpmdir>=I</path/to/files/SRPMS>]

Path to directory with srpms. Note that if I<namefile> is specified as 
I<$SOME_PATH/files/list/src.list>, than <srpmdir> is guessed to be 
I<$SOME_PATH/files/SRPMS>.

=back

=head1	AUTHOR

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

=head1	COPYING

Copyright (c) 2011 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
