#!/usr/bin/perl

## Modules

use strict;
use warnings;

use Getopt::Std;

## Globals

use vars qw/%opt/;
my $PN = "ecl";
my $PV = "20070131";
my @log;
my $lines;
my $pkg;
my $rpkg;
my $PortDir;
my $PortDirFrom;

## Functions

# Show help/usage and exit
sub Help($) {
	print STDERR << "EOF";
$PN $PV by David Watzke <david\@watzke.cz> http://www.watzke.cz/perl
Usage: $PN [options] [category/]package
Options:
	-f	show changelog file
	-h	show this help
	-l	set number of lines to be shown from the changelog
		(default = whole file)
	-v	dump version
EOF
	exit shift;
}

Help(1) if ($#ARGV == -1);

# Show message and exit
sub End($) {
	my $msg = shift;
	print "$msg\n";
	exit 0;
}

# Get options
sub GetOpts {
	getopts('fhl:v', \%opt) or Help(0);
	Help(0) if $opt{h};
}

# Check a package name
sub CheckPkgName($) {
	my $pkg2check = shift;
	$pkg2check =~ /^\w(?:[-\w]*\w)?(?:\/\w(?:[-\w]*\w)?)?$/
	? $pkg = $pkg2check
	: die "Not a valid package name: '$pkg2check'!\n";
}

# Load a file and return array with it's contents
sub LoadFile($) {
	my $file = shift;
	open('myfd', $file) if (-r $file) or die "Cannot open file '$file'!\n";
	my @arr = <myfd>;
	close('myfd');
	return @arr;
}

sub StripPortDir($) {
	my $var = shift;
	$var =~ s/^(?:export| +)?PORTDIR=//;
	$var =~ s/["\n]//g;
	return $var;
}

sub GetPortDirFrom($) {
	$PortDirFrom = shift;
	my @tmp;
	$PortDir = StripPortDir($tmp[0]) if (-r $PortDirFrom && (@tmp = grep(/PORTDIR=/, LoadFile($PortDirFrom))));
}

sub GetPortDir {
	GetPortDirFrom('/etc/make.conf');
	if (!defined($PortDir)) {
		GetPortDirFrom('/etc/make.globals');
		die "Could not determine Portage directory!\n" if !defined($PortDir);
	}
}

sub CheckLogs {
	my @checkedLog;
	while (@log) {
		my $tmplog = shift @log;
		push(@checkedLog, $tmplog) if (-r $tmplog);
	}
	@log = @checkedLog;
}

# Simpler 'head' command
sub Head($) {
	my @arr = LoadFile(shift);
	if ($lines =~ /^all$/) {
		print @arr;
	} else {
		for (my $i=0; ($i<$lines && $i<$#arr); $i++) {
			print $arr[$i];
		}
	}
}

## Let's begin

&GetOpts;
die "$PV\n" if $opt{v};
if ( $opt{l} ) {
	$opt{l} =~ /^(?:\d+|all)?$/
	? $lines = $opt{l}
	: die "Option -l must have a decimal argument!\n";
} else {
	$lines = "all";
}

&GetPortDir;
die "Your PORTDIR (\"$PortDir\", declared in $PortDirFrom) is not a directory!\n" if (!-d "$PortDir/");

$ARGV[0] # if some pkgname given
? CheckPkgName($ARGV[0])
: Help(1);

$rpkg = $pkg; # we need to keep original pkgname for case that package does not exist
$pkg = "*/$pkg" if !($pkg =~ /\//); # if we don't know the category
@log = <$PortDir/$pkg/ChangeLog>; # shell expansion rocks
&CheckLogs;

if ($#log == 0) {
	$opt{f}
	? End($log[0])
	: Head($log[0]);
} elsif ($#log > 0) {
	warn << "EOF";
Short package name (without category) is ambiguous in this case.
Please try one of the following ones instead:
EOF
	while (@log) {
		my $tmp = shift @log;
		$tmp =~ s/(?:^$PortDir\/|\/ChangeLog$)?//g;
		warn "\t$tmp\n";
	}
	exit 1;
} else {
	die "Package '$rpkg' does not exist!\n";
}

exit 0; # we're happy :)

