#!/usr/bin/perl -w

use strict;
use warnings;

use Getopt::Long;
use RPM::Header;
use File::Path qw(make_path remove_tree);
use Pod::Usage;
use Gear::Rules 0.11;
use RPM::Source::Transformation::GenericTransformationSet;
use RPM::Source::Transformation::Factory::RaiseRelease;
use RPM::Source::Transformation::RPMEditorProvider;
our @ISA=qw/Source::Shared::CLI/;

$RPM::Source::Transformation::Factory::RaiseRelease::nextrel='nmu';
$RPM::Source::Transformation::Factory::RaiseRelease::defaultchangelog='- rebuild (with the help of girar-nmu utility)';

my $srpmdir;
# TODO: move code shared with girar-backport-prepare to common  writer (girar-writer)
my $outsrpmdir='OUT.SRPMS';
my $outgeardir='OUT.gits';
my $repo='sisyphus';
my $gitbranch='nmu';
my $version_check=1;

sub cli_container_ref {['RPM::Source::TransformContainer']};
our @LONGOPT=(
	"b|branch=s"   => \$repo,
	"d|localbranch=s"   => \$gitbranch,
	"exact-version!"   => \$version_check,
	"G|outgear=s"   => \$outgeardir,
	"S|outsrpm=s"   => \$outsrpmdir,
	"srpmdir=s"   => \$srpmdir,
    );

our @LONGOPT_POD2USAGE;
__PACKAGE__->get_and_process_cli_options();

if (not @ARGV) {
    __PACKAGE__->usage();
    exit 0;
}

RPM::Source::TransformContainer->init_transformations();

my $curdir=`pwd`;
chomp $curdir;

my @srpms;

if (!$srpmdir) {
    @srpms=@ARGV;
} else {
    unless (-d $srpmdir) {
	die "not a directory: $srpmdir\n";
    }
    $srpmdir=~s!^\./!!;
    $srpmdir="$curdir/$srpmdir" if $srpmdir!~m!^/!;

    my %name2path;
    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;
    foreach my $name (@ARGV) {
	my $path=$name2path{$name};
	unless ($path) {
	    die "source rpm file is not found in $srpmdir for the name $name.\n";
	}
	push @srpms, $path;
    }
}

foreach my $item (@srpms) {
    unless (-e $item) {
	die "source rpm file $item does not exist. You should use real src.rpms even if they will be uploaded as .gits. If $item is a package name, then please, use --srpmdir /path/to/srpms/ option.\n";
    }
    my $rhref;
    eval {
	$rhref=new RPM::Header $item;
    };
    die "$item is not an rpm file!: $@" if $@;
    die "not a source rpm!" if ! $rhref->is_source();
    my $rpmname=$rhref->{NAME};
    my $converter_opt=RPM::Source::TransformContainer->mk_opt();
    my $method=`girar-get-upload-method -b $repo '$rpmname'`;
    chomp $method;
    if ($method eq 'git') {
	-d $outgeardir || make_path($outgeardir);
	chdir $outgeardir;
	system('girar-clone-build-commit','-f','-b',$repo,'-d',$gitbranch,$rpmname);
	my $gearname=$rpmname;
	chdir $gearname.'.git';
	my $rules=Gear::Rules->new();
	my $specfile=$rules->get_spec();
	if ($version_check) {
	    my ($described_name,$described_version,$described_release)=$rules->get_nvr();
	    if ($rpmname ne $described_name and $described_name!~/\%/) {
		warn "$rpmname: name mismatch (--no-exact-version will disable this check):\n";
		warn "Expected: $rpmname\n";
		warn "gear --describe reported: $described_name\n";
		die "ERROR: name mismatch\n";
	    }
	    my $expected_desc=$rhref->{VERSION}.' '.$rhref->{RELEASE};
	    my $description=$described_version.' '.$described_release;
	    if ($expected_desc ne $description  and $description!~/\%/) {
		warn "$rpmname: version mismatch (--no-exact-version will disable this check):\n";
		warn "Expected: $expected_desc\n";
		warn "gear --describe reported: $description\n";
		die "ERROR: version mismatch\n";
	    }
	}
	my $spec=$RPM::Source::TransformContainer::RPMEditorProvider->rpmeditoropts2spec([SPECFILE=>$specfile]);
	$converter_opt->{-inplace}=1;
	RPM::Source::TransformContainer->transform_once($spec,undef,$converter_opt);
	&system_or_die('git', 'add', $specfile);
	&system_or_die('gear-commit','--no-edit');
	chdir $curdir;
    } elsif ($method eq 'srpm') {
	my $spec=$RPM::Source::TransformContainer::RPMEditorProvider->rpmeditoropts2spec([SOURCERPM=>$item]);
	$converter_opt->{-outputdir}=$outsrpmdir.'/'.$rpmname;

	RPM::Source::TransformContainer->transform_once($spec,undef,$converter_opt);
	# TODO: test if " failed.
#--------------------------------------------------------------------------------
#Perhaps you should install missing required rpm-build-* or rpm-macros-* packages
#or use --hashertar option.\n";
    } else {
	die "internal error: $method in girar-get-upload-method $rpmname. Please, report.";
    }
}

sub system_or_die {
    my (@args)=@_;
    system(@args)==0 or die join(' ',@args)." failed";
}

=head1	NAME

girar-nmu-prepare - generate NMU packages according to their upload method.

=head1	SYNOPSIS

B<girar-nmu-prepare>
[B<-h>] 
[B<-b> I<repository>]
[B<-d> I<local branch>]
[B<-e, --exact-version | --no-e, --no-exact-version>]
[B<-G> I<path/to/OUT.gits dir>]
[B<-S> I<path/to/OUT.SRPMS dir>]
[B<-c|--changelog> I<changelog text>]
[B<--hashertar>]
[B<--hook> I<path/to/hook>]
[B<other spec editing options here, see --help>]
B<--srpmdir> I<dir> I<srpmname ...> | I<srpm ...>

=head1	DESCRIPTION

B<girar-nmu-prepare> 
generate NMU packages according to their upload method.
for each package girar-nmu-prepare generate either a git repository with
the NMU commmit or the NMU src.rpm according to the package's upload method.
Each result is stored either as OUT.gits/name.git or OUT.SRPMS/name/*src..rpm.

As an argument girar-nmu-prepare takes either a list of original src.rpms 
or the path to dir with src.rpms in --srpmdir option and a list of names.


=head1	OPTIONS

There are lots of srpm processing options that are inherited from RPM::Source::*
utilities. To view full list of available options, run gurar-nmu-prepare --help.

=head2 gurar-nmu-prepare specific OPTIONS

=over

=item	B<-b> I<repository name>

Name of the repository branch. Values are: sisyphus|5.1|p5|..
Default is sisyphus.

=item	B<--ch, --changelog> I<changelog text>

Changelog text. Default is like '- rebuild (with the help of girar-nmu utility)'

=item	B<-d> I<local branch name>

Git repository option.
Name of the local git branch to build from. Default is nmu.

=item	[B<-e, --exact-version>]

Die if version-release of src.rpm and git repository spec file does not match (Default).
Conversely, B<--no-e, --no-exact-version> allows to skip git repository version check.

=item	B<-G> I<dir>

name of output directory with Git repositories.
Default is "OUT.gits".

=item	B<-S> I<dir>

name of output directory for src.rpms.
Default is "OUT.SRPMS".

=item	B<--hashertar>

Generate hasher-ready .tar file instead of src.rpm file.
Some src.rpm require you to install extra rpm-build-* or rpm-macros-* packages
or else rpmbuild -bs --nodeps will fail. On the other hand, generating hasher-ready .tar
file does not require installing rpm-build-* or rpm-macros-* packages, but
this tar file should be first processed in hasher.
Use --hashertar option to avoid polluting your working environment with
unnecessary rpm-build-* or rpm-macros-* packages.

=item	B<-h, --help>

Display this help and exit.

=back

=head1	AUTHOR

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

=head1	COPYING

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

