#!/usr/bin/perl
# 
# Copyright (C) 2010 Sébastien Granjoux  <seb.sfo@free.fr>
# 
# This program 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.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

#
# This program reads all libtool library files (*.la) in the directory used as
# argument. Then copy and update all needed libtool library files to make sure
# that the libraries in the directory are used.

use strict;
use File::Basename;
use File::Copy;
use Getopt::Long;

# Get command line argument
my $dry_run = 0;
my $help = 0;

GetOptions ("n|dry-run" => \$dry_run, "h|help" => \$help);

my $LibraryDirectory = $ARGV[0];

if (!defined($LibraryDirectory))
{
	print "updatela V0.1\n";
	print "\nUsage: updatela [-n|--dry-run] local_library_directory";
	print "\nUpdate all libtool .la file in local directory to use local libraries\n";
	print "\n\t-n, --dry-run\t\tDo not change anything on disk\n";
	exit 0;
}

print "\nSearching Local libraries...\n";
my %LocalLibraries = GetLibraries($LibraryDirectory);
my %LocalDependencies = %LocalLibraries;
my $lib;
foreach $lib (keys(%LocalLibraries))
{
	print "\t$lib\n";
}

print "\nSearching Local Dependencies...\n";
my %Dependencies = %LocalLibraries;
my @NewDependencies = ();
my $new_local = 1;
while ($new_local || @NewDependencies)
{
	my @CheckDependencies;

	if ($new_local)
	{
		@CheckDependencies = values(%Dependencies);
		$new_local = 0;
	}
	else
	{
		@CheckDependencies = @NewDependencies;
	}

	@NewDependencies = ();	
	foreach $lib (@CheckDependencies)
	{
		my $dep;
		my @LibraryDependencies = GetDependencies ($lib);

		foreach $dep (@LibraryDependencies)
		{
			if (!exists $Dependencies{basename($dep)})
			{
				push (@NewDependencies, $dep);
				$Dependencies{basename($dep)} = $dep;
			}
		}

		if (!exists $LocalDependencies{basename($lib)})
		{
			foreach $dep (@LibraryDependencies)
			{
				if (exists $LocalDependencies{basename($dep)})
				{
					my $basename = basename($dep);
					print "\t$lib\n\t\t$basename\n";
					$LocalDependencies{basename($lib)} = $lib;
					$new_local = 1;
					last;
				}
			}
		}
	}
}

print "\nCopying Local Dependencies...\n";
foreach $lib (values(%LocalDependencies))
{
	if (!exists $LocalLibraries{basename($lib)})
	{
		print "\t$lib\n";
		if (!$dry_run)
		{
			copy($lib, $LibraryDirectory . "/" . basename($lib));
		}
	}
}

print "\nUpdating Local Libraries...\n";
foreach $lib (keys(%LocalDependencies))
{
	UpdateLibrary ($LibraryDirectory . "/" . $lib, \%LocalDependencies, $LibraryDirectory, $dry_run);	
}


exit;

# Get all dependencies from a .la file
sub GetDependencies
{
	my $filename = shift;
	my @depend = ();
	my $LA;
	my $line;

	open (LA, $filename) || die "unable to read $filename";
	for $line (<LA>)
	{
		if ($line =~ /^\s*dependency_libs\s*=\s*['"]?(.*?)['"]?\s*$/)
		{
			my $lib;

			for $lib (split(/\s/, $1))
			{
				if ($lib =~ /^[-A-Za-z0-9_\/\.]+\.la$/)
				{
					push @depend, $lib;
				}
			}
		}
	}
	close (LA);

	return @depend;
}

# Get all la file in a directory indexed by the basename
sub GetLibraries
{
	my $directory = shift;
	my %libs =();
	my $lib;

	for $lib (glob($directory . "/*.la"))
	{
		$libs{basename ($lib)} = $lib;
	}

	return %libs;
}

# Replace local dependencies in la file
sub UpdateLibrary
{
	my $filename = shift;
	my $dependencies = shift;
	my $local_path = shift;
	my $dry_run = shift;
	my $line;
	my @new_la = ();
	my $updated = 0;


	open (LA, $filename) || die "unable to read $filename";
	for $line (<LA>)
	{
		if ($line =~ /^(\s*dependency_libs\s*=\s*['"]?)(.*?)(['"]?\s*$)/)
		{
			my $prefix = $1;
			my $list = $2;
			my $suffix = $3;
			my $new_list = "";

			while ($list)
			{
				if ($list =~ s/^(\s+)//)
				{
					$new_list = $new_list . $1;
				}
				elsif ($list =~ s/^([^\s]+)//)
				{
					my $lib = $1;
					if ($lib =~ /^[-A-Za-z0-9_\/\.]+\.la$/)
					{
						if ((exists $dependencies->{basename($lib)}) && ($local_path . "/" . basename($lib) ne $lib))
						{
							if (!$updated)
							{
								print "\t$filename\n";
							}
							print "\t\t$lib\n";	
							$new_list = $new_list . $local_path . "/". basename($lib);
							$updated = 1;
						}
						else
						{
							$new_list = $new_list . $lib;
						}
					}
					else
					{
						$new_list = $new_list . $lib;
					}
				}
			}
			$line = $prefix . $new_list . $suffix;
		}
		push @new_la, $line;
	}
	close (LA);

	if ($updated)
	{
		my $line;

		if (!$dry_run)
		{
			copy ($filename, $filename . ".bak");

			open (LA, ">" . $filename) || die "unable to create $filename";
			foreach $line (@new_la)
			{
				print LA $line;
			}
			close LA;
		}
	}
}	

