#!/usr/bin/perl -w

# Copyright 2002, Ximian, Inc.
#
#    This app makes it easy to link a live build
# set into an install set. Then your devel iteration
# is: 'build', execute.
#

# ends up in program/env
$env_script = '
ulimit -c unlimited
export PATH=".:$PATH"
export LD_LIBRARY_PATH=".:$LD_LIBRARY_PATH"
export GNOME_DISABLE_CRASH_DIALOG=1
';

$resources = {
	'dbu%%01.res' => 'dbaccess',
	'sfx%%01.res' => 'sfx2',
#	'oem%%01.res' => 'offmgr',
#	'for%%01.res' => 'offmgr',
	'dkt%%01.res' => 'desktop',
	'sd%%01.res' => 'sd',
	'sch%%01.res' => 'sch',
	'eme%%01.res' => 'goodies',
	'epb%%01.res' => 'goodies',
	'epn%%01.res' => 'goodies',
	'epp%%01.res' => 'goodies',
	'egi%%01.res' => 'goodies',
	'ept%%01.res' => 'goodies',
	'eps%%01.res' => 'goodies',
	'epg%%01.res' => 'goodies',
	'gal%%01.res' => 'svx',
	'svx%%01.res' => 'svx',
	'vcl%%01.res' => 'vcl',
	'frm%%01.res' => 'forms',
	'set%%01.res' => 'setup2',
#	'set_pp1%%01.res' => 'setup2',
	'tplx%%01.res' => 'setup2',
	'dbw%%01.res' => 'wizards',
	'cal%%01.res' => 'wizards',
	'eur%%01.res' => 'wizards',
	'imp%%01.res' => 'wizards',
	'tpl%%01.res' => 'wizards',
	'wwz%%01.res' => 'wizards',
	'sc%%01.res' => 'sc',
	'analysis%%01.res' => 'scaddins',
	'date%%01.res' => 'scaddins',
#	'stt%%01.res' => 'basic',
	'basctl%%01.res' => 'basctl',
	'sw%%01.res' => 'sw',
	'sm%%01.res' => 'starmath',
	'uui%%01.res' => 'uui',
	'svt%%01.res' => 'svtools',
	'svs%%01.res' => 'svtools',
	'abp%%01.res' => 'extensions',
	'san%%01.res' => 'extensions',
	'pcr%%01.res' => 'extensions',
	'dbp%%01.res' => 'extensions',
	'bib%%01.res' => 'extensions',
	'dbi%%01.res' => 'extensions',
	'preload%%01.res' => 'extensions',
	'lgd%%01.res' => 'framework',
#	'spa%%01.res' => 'padmin'
};

$opt_resources = {
	'ooo%%01.res' => 'offmgr',
	'iso%%01.res' => 'offmgr',
	'ofa%%01.res' => 'offmgr',
	'cnt%%01.res' => 'chaos',
	'oic%%01.res' => 'extensions',
	'jvm%%01.res' => 'setup2'
};

$libraries = {
    'libfwe%%.so' => 'framework',
    'libfwi%%.so' => 'framework',
    'libfwk%%.so' => 'framework',
    'libfwl%%.so' => 'framework',
    'libfrm%%.so' => 'forms',
    'libpsp%%.so' => 'psprint',
    'libsfx%%.so' => 'sfx2',
    'libsvl%%.so' => 'svtools',
    'libsvt%%.so' => 'svtools',
    'libsvx%%.so' => 'svx',
    'libtl%%.so' => 'tools',
    'libdtransX11%%.so' => 'dtrans',
    'libpackage2.so' => 'package',
    'libucpfile1.so' => 'ucb',
    'libucpdav1.so' => 'ucb',
    'libcached1.so' => 'ucb',
    'libucphier1.so' => 'ucb',
    'libucb1.so' => 'ucb',
    'libutl%%.so' => 'unotools',
    'libvcl%%.so' => 'vcl',
    'libxo%%.so' => 'xmloff',
    'libsb%%.so' => 'basic',
    'libso%%.so' => 'so3',
    'libgo%%.so' => 'goodies',
    'libsc%%.so' => 'sc',
    'libsw%%.so' => 'sw',
    'libsd%%.so' => 'sd',
    'libsm%%.so' => 'starmath',
    'libodbc2.so'  => 'connectivity',
    'libodbcbase2.so' => 'connectivity',
    'libtk%%.so' => 'toolkit',
    'libsch%%.so' => 'sch',
    'libscn%%.so' => 'extensions',
    'libhyphen%%.so' => 'lingucomponent',
    'libspell%%.so' => 'lingucomponent',
    'libtvhlp1.so' => 'xmlhelp',
    'libucpchelp1.so' => 'xmlhelp',
    'libsot%%.so' => 'sot',
    'libbasctl%%.so' => 'basctl',
    'liblng%%.so' => 'linguistic',
    'libanalysis%%.so' => 'scaddins',
    'libdate%%.so' => 'scaddins',
    'liboffacc%%.so' => 'desktop',
    'libres%%.so' => 'extensions',
    'libbib%%.so' => 'extensions'
};

$opt_libraries = {
    'libi18npool%%.so' => 'i18npool',
    'liblth%%.so' => 'lingucomponent',
    'libofa%%.so' => 'offmgr',
    'libulingu%%.so' => 'lingucomponent',
    'libwrp%%.so' => 'desktop',
    'libi18n%%.so' => 'i18n_simple',
    'libucpgvfs1.so' => 'ucb',
    'libucpfpx%%.so' => 'ucb',
    'libucbhelper1gcc3.so' => 'ucbhelper',
    'libucbhelper2gcc3.so' => 'ucbhelper',
    'libcppu.so.3.0.1' => 'cppu',
    'libcppu.so.3.1.0' => 'cppu',
    'libsal.so.3.0.1' => 'sal',
    'libsal.so.3.1.0' => 'sal',
    'libmozab2.so' => 'connectivity',
    'libmozabdrv2.so' => 'connectivity',
    'libmysql2.so' => 'connectivity',
    'libodbc2.so' => 'connectivity',
    'libodbcbase2.so' => 'connectivity',
    'libsdbc2.so' => 'connectivity',
    'libdbase%%.so' => 'connectivity',
    'libdbpool2.so' => 'connectivity',
    'libdbtools2.so' => 'connectivity',
    'libadabas2.so' => 'connectivity',
    'libcalc%%2.so' => 'connectivity',
    'libevoab1.so' => 'connectivity',
    'libfile%%.so' => 'connectivity',
    'libflat%%.so' => 'connectivity',
    'libcalc%%.so' => 'connectivity',
    'libspl%%.so' => 'desktop',
    'libvclplug_dummy%%.so' => 'vcl',
    'libvclplug_gen%%.so' => 'vcl',
    'libvclplug_gtk%%.so' => 'vcl',
    'libcomphelp3gcc3' => 'comphelper',
    'libset%%.so' => 'setup2',
    'libtplx%%.so' => 'setup2',
    'libgcc3_uno.so' => 'bridges'
};

$filter_libraries = {
    'libemp%%.so' => 'sd',
    'libeme%%.so' => 'goodies',
    'libegi%%.so' => 'goodies',
    'libepb%%.so' => 'goodies',
    'libepg%%.so' => 'goodies',
    'libepn%%.so' => 'goodies',
    'libepp%%.so' => 'goodies',
    'libeps%%.so' => 'goodies',
    'libept%%.so' => 'goodies',
    'libera%%.so' => 'goodies',
    'libeti%%.so' => 'goodies',
    'libexp%%.so' => 'goodies',
    'libicd%%.so' => 'goodies',
    'libicg%%.so' => 'goodies',
    'libidx%%.so' => 'goodies',
    'libime%%.so' => 'goodies',
    'libipd%%.so' => 'goodies',
    'libipb%%.so' => 'goodies',
    'libips%%.so' => 'goodies',
    'libipt%%.so' => 'goodies',
    'libipx%%.so' => 'goodies',
    'libira%%.so' => 'goodies',
    'libitg%%.so' => 'goodies',
    'libiti%%.so' => 'goodies',
};

$other_bin_files = {
	'getstyle-gnome' => 'vcl',
	'msgbox-gnome' => 'vcl'
};

sub sniff_target($)
{
    my $build_dir = shift;
    my ($dirhandle, $fname);
    my ($target, $libver, $dllsuffix) = ( 'unxlngi4.pro', '641', 'li' ); # defaults
    
    opendir ($dirhandle, $build_dir) || die "Can't open $build_dir";
    while ($fname = readdir ($dirhandle)) {
	$fname =~ /Set.sh$/ || next;
	
	my $file;
	open ($file, "$build_dir/$fname") || die "Can't open $build_dir/$fname";
	while (<$file>) {
	    /\s*(\S+)\s*=\s*\"(\S+)\"/ || next;
	    if ($1 eq 'INPATH') {
		$target = $2;
	    }
	    if ($1 eq 'UPD') {
		$libver = $2;
	    }
	    if ($1 eq 'DLLSUFFIX') {
		$dllsuffix = $2;
	    }
	}
	close ($file);
    }

    closedir ($dirhandle);

    print "Sniffed target: $target, $libver, $dllsuffix\n";

    return ($target, $libver, $dllsuffix);
}

sub do_linkage {
    my $files = shift;
    my $substitute = shift;
    my $dest_subdir = shift;
    my $src_subdir = shift;
    my $optional = shift;
    my $file;

    my $inst = "$OOO_INSTALL$dest_subdir";
    my $linked_dir = "$inst/linked";

    if (!-d $linked_dir) {
	mkdir $linked_dir || die "Can't make $linked_dir: $!";
    }
    
    for $file (keys %$files) {
	my $bres = $files->{$file};
	
	$file =~ s/%%/$substitute/;

	my $build = "$OOO_BUILD/$bres/$src_subdir/$file";
	if (!$product) {
	    # Prefer non .pro paths if we can find them
	    my $tmp = $build;
	    $tmp =~ s/\.pro//;
	    $build = $tmp if -f $tmp;
	}

	$optional || -f "$build" || die "No file '$build' to link to\n";
	
	if (-l "$inst/$file") {
	    # re-write the link
	    unlink ("$inst/$file");
	    symlink ("$build", "$inst/$file") || die "Failed to symlink: $!";
	} elsif (-f "$inst/$file") {
	    # move / write the link
	    rename ("$inst/$file", "$linked_dir/$file") || die "Failed rename of $inst/$file: $!";
	    symlink ("$build", "$inst/$file") || die "Failed to symlink: $!";
	    print " $file";
	} elsif (!$optional) {
	    print "Unexpected / missing file $build -> $inst/$file\n";
	}
    }
}

if (@ARGV < 2) {
    printf "Usage: linkoo </path/to/ooo/install> </path/to/ooo/build/tree> [--product]\n";
    exit (1);
}

$OOO_INSTALL = shift (@ARGV) . "/program";
$OOO_BUILD = shift (@ARGV);

substr ($OOO_INSTALL, 0, 1) eq '/' || die "linkoo requires absolute paths";
substr ($OOO_BUILD, 0, 1)   eq '/' || die "linkoo requires absolute paths";

my $a;
for $a (@ARGV) {
    $product = 1 if $a =~ /--product/;
}

if ($OOO_BUILD !~ m|^/|) {
    printf "second argument must be an absolute path\n";
    exit (1);
}

-d $OOO_INSTALL || die "No such directory $OOO_INSTALL";
-w $OOO_INSTALL || die "You need write access to $OOO_INSTALL";
-d $OOO_BUILD || die "No such directory $OOO_BUILD";
-d "$OOO_INSTALL/resource" || die "$OOO_INSTALL doesn't look like an OO install";

($TARGET, $LIBVER, $DLLSUFFIX) = sniff_target ($OOO_BUILD);

print "Linking resources:";
do_linkage ($resources, $LIBVER, '/resource', "$TARGET/bin", '');
do_linkage ($opt_resources, $LIBVER . $DLLSUFFIX, '', "$TARGET/lib", '1');

print "\n";

print "Linking libraries:";
do_linkage ($libraries,     $LIBVER . $DLLSUFFIX, '', "$TARGET/lib", '');
do_linkage ($opt_libraries, $LIBVER . $DLLSUFFIX, '', "$TARGET/lib", '1');
print "\n";

print "Linking filters:";
do_linkage ($filter_libraries, $LIBVER . $DLLSUFFIX, '/filter', "$TARGET/lib", '');
print "\n";

print "Linking other files:";
do_linkage ($other_bin_files, $LIBVER . $DLLSUFFIX, '', "$TARGET/bin", '1');
print "\n";

print "Special iso.res case:";
$ooo_res="$OOO_INSTALL/resource/ooo".$LIBVER."01.res";
$star_res="$OOO_INSTALL/resource/iso".$LIBVER."01.res";
if (-l $ooo_res && -l $star_res) {
    unlink ($star_res);
    symlink ($ooo_res, $star_res);
    print " clobbered";
}
print "\n";

if (!-f "$OOO_INSTALL/env") {
    print "Creating '$OOO_INSTALL/env'\n";
    open ($env, ">$OOO_INSTALL/env") || die "Can't open $OOO_INSTALL/env: $!";
    print $env $env_script;
    close ($env);
}
