#!/usr/bin/perl

use File::Find;
use File::Fetch;
use POSIX;
use File::Basename;
use File::Copy;
use Cwd qw(abs_path getcwd);
use File::Path qw(make_path remove_tree);

###
### avoid: "Fetch failed! HTTP response: 500 Internal Server Error [500 Can’t verify SSL peers without knowing which Certificate Authorities to trust]"
###
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
###
### avoid: TLSv1.0 backends...
###
$File::Fetch::BLACKLIST = [qw|lwp httptiny httplite|];

$exe = abs_path($0);
$path = abs_path(dirname($exe));
$java = '/usr/bin/java';
$jarfile_name = "xml-casa-assembly-1.52.jar";
$sakura_release = "libsakura-4.0.2065-01.tar.gz";
@java_version = ( );
open(JAVAVER, "$java -version 2>&1 |");
foreach ( <JAVAVER> ) {
    if ( m|version "?(\d+)\.(\d+)|i ) {
        @java_version = ($1,$2);
        print "found java version ", join('.',@java_version), "\n";
    }
}
close(JAVAVER);
die "cannot run $java" unless scalar(@java_version) > 0;
die "java version 1.8 or greater is required\n"
    unless $java_version[0] > 7 || ($java_version[0] == 1 && $java_version[1] >= 8);

### install path
$distro_jarfile = $jarfile = "$path/java/$jarfile_name";
if ( ! -e $jarfile ) {
    ### development path
    $jarfile = "$path/../target/scala-2.12/$jarfile_name";
    if ( ! -e $jarfile ) {
        $jarfile = $distro_jarfile;
        ### pull from download url
        my $jardir = dirname($jarfile);
        make_path($jardir);
        my $ff = File::Fetch->new(uri => "http://casa.nrao.edu/download/devel/xml-casa/java/$jarfile_name");
        my $where = $ff->fetch( to => $jardir );
    }
}
die "configuration error, cannot find jar file ($jarfile_name)" unless -e $jarfile;

if ( ! -d 'sakura-source/src' ) {
    if ( ! -d '.sakura' || ! -f ".sakura/$sakura_release" ) {
        make_path('.sakura');
        ### pull from download url
        ### download from jp times out...
        #my $ff = File::Fetch->new(uri => "http://alma-dl.mtk.nao.ac.jp/ftp/sakura/releases/latest_src/$sakura_release");
        my $ff = File::Fetch->new(uri => "http://casa.nrao.edu/download/devel/libsakura/$sakura_release");
        my $where = $ff->fetch( to => '.sakura' );
        unlink(".sakura/$sakura_release") unless -f ".sakura/$sakura_release" && -s ".sakura/$sakura_release" > 354000;
    }
    die "could not download libsakura" unless -f ".sakura/$sakura_release";
    make_path('sakura-source');
    my @args = ("tar", "-C", "sakura-source", "-zxf", ".sakura/$sakura_release", '--strip-components', '1');
    system(@args) == 0 or die "failed to extract libsakura: $?";
}

$path = getcwd( );

die "expected ./casa-source/ directory" unless -d "./casa-source/";
unless ( -d "./xml/tools/" ) { make_path("xml/tools") or die "could not create 'xml/tools': $!" }
unless ( -d "./lib/" ) { make_path("lib") or die "could not create 'lib': $!" }

$xml_dir = "xml/tools";
$tool_dir = "binding/tools";
$src_dir = "binding/source";
$hdr_dir = "binding/include";

%xml_files = ( 'utils' => 'src/cmpt/utils/utils.xml',
               'quanta' => 'casa-source/gcwrap/tools/casa/quanta.xml',
               'image' => 'casa-source/gcwrap/tools/images/image.xml',
               'coordsys' => 'casa-source/gcwrap/tools/images/coordsys.xml',
               'imagepol' => 'casa-source/gcwrap/tools/images/imagepol.xml',
               'synthesisimstore' => 'casa-source/gcwrap/tools/synthesis/synthesisimstore.xml',
               'synthesisnormalizer' => 'casa-source/gcwrap/tools/synthesis/synthesisnormalizer.xml',
               'synthesisimager' => 'casa-source/gcwrap/tools/synthesis/synthesisimager.xml',
               'synthesisdeconvolver' => 'casa-source/gcwrap/tools/synthesis/synthesisdeconvolver.xml',
               'imager' => 'casa-source/gcwrap/tools/synthesis/imager.xml',
               'synthesisutils' => 'casa-source/gcwrap/tools/synthesis/synthesisutils.xml',
               'atmosphere' => 'casa-source/gcwrap/tools/atmosphere/atmosphere.xml',
               'table' => 'casa-source/gcwrap/tools/tables/table.xml',
               'componentlist' => './casa-source/gcwrap/tools/components/componentlist.xml',
               'measures' => 'casa-source/gcwrap/tools/measures/measures.xml',
               'regionmanager' => 'casa-source/gcwrap/tools/images/regionmanager.xml',
               'functional' => 'casa-source/gcwrap/tools/scimath/functional.xml',
               'calanalysis' => 'casa-source/gcwrap/tools/calanalysis/calanalysis.xml',
               'ms' => 'casa-source/gcwrap/tools/ms/ms.xml',
               'msmetadata' => 'casa-source/gcwrap/tools/ms/msmetadata.xml',
               'calibrater' => 'casa-source/gcwrap/tools/synthesis/calibrater.xml',
               'vpmanager' => 'casa-source/gcwrap/tools/synthesis/vpmanager.xml',
               'imagemetadata' => 'casa-source/gcwrap/tools/images/imagemetadata.xml',
               'logsink' => 'casa-source/gcwrap/tools/casa/logsink.xml',
               'agentflagger' => 'casa-source/gcwrap/tools/flagging/agentflagger.xml',
               'mstransformer' => 'casa-source/gcwrap/tools/mstransformer/mstransformer.xml',
               'spectralline' => 'casa-source/gcwrap/tools/spectralline/spectralline.xml',
               'singledishms' => 'casa-source/gcwrap/tools/singledish/singledishms.xml',
               'atcafiller' => 'casa-source/gcwrap/tools/atnf/atcafiller.xml',
               'vlafiller' => 'src/cmpt/vlafiller/vlafiller.xml',
               'iterbotsink' => 'src/cmpt/iterbot/iterbotsink.xml',
               'sdm' => 'src/cmpt/sdm/sdm.xml',
               'sakura' => 'casa-source/gcwrap/tools/singledish/sakura.xml',
               'simulator' => 'casa-source/gcwrap/tools/synthesis/simulator.xml',
               'miriadfiller' => 'casa-source/gcwrap/tools/miriad/miriadfiller.xml',
               'synthesismaskhandler' => 'casa-source/gcwrap/tools/synthesis/synthesismaskhandler.xml',
               'sidebandseparator' => 'casa-source/gcwrap/tools/synthesis/sidebandseparator.xml',
             );
%src_files = ( 'utils' => [ 'casa-source/gcwrap/tools/utils/utils_cmpt.cc',
                            'casa-source/gcwrap/tools/utils/utils_private.h',
                            'casa-source/gcwrap/tools/utils/utils_forward.h',
                            'casa-source/gcwrap/tools/utils/stdBaseInterface.h',
                            'casa-source/gcwrap/tools/utils/stdBaseInterface.cc',
                            'casa-source/gcwrap/tools/utils/BaseInterface.h',
                            'casa-source/gcwrap/tools/utils/BaseInterface.cc',
                            'casa-source/gcwrap/tools/xerces/stdcasaXMLUtil.h',
                            'casa-source/gcwrap/tools/xerces/stdcasaXMLUtil.cc' ],
               'quanta' => [ 'casa-source/gcwrap/tools/casa/quanta_cmpt.cc',
                             'casa-source/gcwrap/tools/casa/quanta_private.h',
                             'casa-source/gcwrap/tools/casa/quanta_forward.h' ],
               'image' =>  [ 'casa-source/gcwrap/tools/images/image_cmpt.cc',
                             'casa-source/gcwrap/tools/images/image_forward.h',
                             'casa-source/gcwrap/tools/images/image_private.h' ],
               'coordsys' =>  [ 'casa-source/gcwrap/tools/images/coordsys_cmpt.cc',
                                'casa-source/gcwrap/tools/images/coordsys_forward.h',
                                'casa-source/gcwrap/tools/images/coordsys_private.h' ],
               'imagepol' =>  [ 'casa-source/gcwrap/tools/images/imagepol_cmpt.cc',
                                'casa-source/gcwrap/tools/images/imagepol_forward.h',
                                'casa-source/gcwrap/tools/images/imagepol_private.h' ],
               'synthesisimstore' =>  [ 'casa-source/gcwrap/tools/synthesis/synthesisimstore_cmpt.cc',
                                        'casa-source/gcwrap/tools/synthesis/synthesisimstore_forward.h',
                                        'casa-source/gcwrap/tools/synthesis/synthesisimstore_private.h' ],
               'synthesisnormalizer' =>  [ 'casa-source/gcwrap/tools/synthesis/synthesisnormalizer_cmpt.cc',
                                           'casa-source/gcwrap/tools/synthesis/synthesisnormalizer_forward.h',
                                           'casa-source/gcwrap/tools/synthesis/synthesisnormalizer_private.h' ],
               'synthesisimager' =>  [ 'casa-source/gcwrap/tools/synthesis/synthesisimager_cmpt.cc',
                                       'casa-source/gcwrap/tools/synthesis/synthesisimager_forward.h',
                                       'casa-source/gcwrap/tools/synthesis/synthesisimager_private.h' ],
               'synthesisdeconvolver' =>  [ 'casa-source/gcwrap/tools/synthesis/synthesisdeconvolver_cmpt.cc',
                                            'casa-source/gcwrap/tools/synthesis/synthesisdeconvolver_forward.h',
                                            'casa-source/gcwrap/tools/synthesis/synthesisdeconvolver_private.h' ],
               'imager' =>  [ 'casa-source/gcwrap/tools/synthesis/imager_cmpt.cc',
                                       'casa-source/gcwrap/tools/synthesis/imager_forward.h',
                                       'casa-source/gcwrap/tools/synthesis/imager_private.h' ],
               'synthesisutils' =>  [ 'casa-source/gcwrap/tools/synthesis/synthesisutils_cmpt.cc',
                                      'casa-source/gcwrap/tools/synthesis/synthesisutils_forward.h',
                                      'casa-source/gcwrap/tools/synthesis/synthesisutils_private.h' ],
               'atmosphere' => [ 'casa-source/gcwrap/tools/atmosphere/atmosphere_forward.h',
                                 'casa-source/gcwrap/tools/atmosphere/atmosphere_private.h',
                                 'casa-source/gcwrap/tools/atmosphere/atmosphere_cmpt.cc' ],
               'table' => [ 'casa-source/gcwrap/tools/tables/table_forward.h',
                            'casa-source/gcwrap/tools/tables/table_private.h',
                            'casa-source/gcwrap/tools/xerces/asdmCasaSaxHandler.h',
                            'casa-source/gcwrap/tools/xerces/asdmCasaSaxHandler.cc',
                            'casa-source/gcwrap/tools/xerces/asdmCasaXMLUtil.h',
                            'casa-source/gcwrap/tools/xerces/asdmCasaXMLUtil.cc',
                            'casa-source/gcwrap/tools/ms/Statistics.h',
                            'casa-source/gcwrap/tools/ms/Statistics.cc',
                            'casa-source/gcwrap/tools/ms/Statistics.tcc',
                            'casa-source/gcwrap/tools/tables/table_cmpt.cc' ],
               'componentlist' => [ 'casa-source/gcwrap/tools/components/componentlist_forward.h',
                                    'casa-source/gcwrap/tools/components/componentlist_private.h',
                                    'casa-source/gcwrap/tools/components/componentlist_cmpt.cc' ],
               'measures' => [ 'casa-source/gcwrap/tools/measures/measures_forward.h',
                               'casa-source/gcwrap/tools/measures/measures_private.h',
                               'casa-source/gcwrap/tools/measures/measures_cmpt.cc' ],
               'regionmanager' => [ 'casa-source/gcwrap/tools/images/regionmanager_forward.h',
                                    'casa-source/gcwrap/tools/images/regionmanager_private.h',
                                    'casa-source/gcwrap/tools/images/regionmanager_cmpt.cc' ],
               'functional' => [ 'casa-source/gcwrap/tools/scimath/functional_forward.h',
                                 'casa-source/gcwrap/tools/scimath/functional_private.h',
                                 'casa-source/gcwrap/tools/scimath/functional_cmpt.cc' ],
               'calanalysis' => [ 'casa-source/gcwrap/tools/calanalysis/calanalysis_forward.h',
                                  'casa-source/gcwrap/tools/calanalysis/calanalysis_private.h',
                                  'casa-source/gcwrap/tools/calanalysis/calanalysis_template.h',
                                  'casa-source/gcwrap/tools/calanalysis/calanalysis_cmpt.cc' ],
               'ms' => [ 'casa-source/gcwrap/tools/ms/ms_private.h',
                         'casa-source/gcwrap/tools/ms/ms_forward.h',
                         'casa-source/gcwrap/tools/ms/ms_cmpt.cc' ],
               'msmetadata' => [ 'casa-source/gcwrap/tools/ms/msmetadata_private.h',
                                 'casa-source/gcwrap/tools/ms/msmetadata_forward.h',
                                 'casa-source/gcwrap/tools/ms/msmetadata_cmpt.cc' ],
               'calibrater' => [ 'casa-source/gcwrap/tools/synthesis/calibrater_private.h',
                                 'casa-source/gcwrap/tools/synthesis/calibrater_forward.h',
                                 'casa-source/gcwrap/tools/synthesis/calibrater_cmpt.cc' ],
               'vpmanager' => [ 'casa-source/gcwrap/tools/synthesis/vpmanager_private.h',
                                'casa-source/gcwrap/tools/synthesis/vpmanager_forward.h',
                                'casa-source/gcwrap/tools/synthesis/vpmanager_cmpt.cc' ],
               'imagemetadata' =>  [ 'casa-source/gcwrap/tools/images/imagemetadata_cmpt.cc',
                                'casa-source/gcwrap/tools/images/imagemetadata_forward.h',
                                'casa-source/gcwrap/tools/images/imagemetadata_private.h' ],
               'logsink' =>  [ 'casa-source/gcwrap/tools/casa/logsink_cmpt.cc',
                               'casa-source/gcwrap/tools/casa/logsink_forward.h',
                               'casa-source/gcwrap/tools/casa/logsink_private.h',
                               'casa-source/gcwrap/tools/casa/TSLogSink.h',
                               'casa-source/gcwrap/tools/casa/TSLogSink.cc',
                               'casa-source/gcwrap/tools/utils/CasapyWatcher.h',
                               'casa-source/gcwrap/tools/utils/CasapyWatcher.cc', ],
               'agentflagger' => [ 'casa-source/gcwrap/tools/flagging/agentflagger_cmpt.cc',
                                   'casa-source/gcwrap/tools/flagging/agentflagger_forward.h',
                                   'casa-source/gcwrap/tools/flagging/agentflagger_private.h', ],
               'mstransformer' => [ 'casa-source/gcwrap/tools/mstransformer/mstransformer_cmpt.cc',
                                    'casa-source/gcwrap/tools/mstransformer/mstransformer_forward.h',
                                    'casa-source/gcwrap/tools/mstransformer/mstransformer_private.h', ],
               'spectralline' => [ 'casa-source/gcwrap/tools/spectralline/spectralline_cmpt.cc',
                                    'casa-source/gcwrap/tools/spectralline/spectralline_forward.h',
                                    'casa-source/gcwrap/tools/spectralline/spectralline_private.h', ],
               'singledishms' => [ 'casa-source/gcwrap/tools/singledish/singledishms_cmpt.cc',
                                    'casa-source/gcwrap/tools/singledish/singledishms_forward.h',
                                    'casa-source/gcwrap/tools/singledish/singledishms_private.h', ],
               'atcafiller' => [ 'casa-source/gcwrap/tools/atnf/atcafiller_cmpt.cc',
                                 'casa-source/gcwrap/tools/atnf/atcafiller_forward.h',
                                 'casa-source/gcwrap/tools/atnf/atcafiller_private.h', ],
               'vlafiller' => [ 'src/cmpt/vlafiller/vlafiller_cmpt.cc' ],
               'iterbotsink' => [ 'src/cmpt/iterbot/iterbotsink_cmpt.cc',
                                  'src/cmpt/iterbot/iterbotsink_forward.h',
                                  'src/cmpt/iterbot/iterbotsink_private.h', ],
               'sdm' => [ 'src/cmpt/sdm/sdm_cmpt.cc',
                          'src/cmpt/sdm/sdm_forward.h',
                          'src/cmpt/sdm/sdm_private.h',
                          'src/cmpt/sdm/asdm2MSGeneric.h',
                          'src/cmpt/sdm/ScansParser.h',
                          'src/cmpt/sdm/ScansParser.cc',
                          'src/cmpt/sdm/ASDM2MSException.h',
                          'src/cmpt/sdm/ASDM2MSFiller.h',
                          'src/cmpt/sdm/ASDM2MSFiller.cc',
                          'src/cmpt/sdm/ASDMVerbatimFiller.h',
                          'src/cmpt/sdm/ASDMVerbatimFiller.cc',
                          'src/cmpt/sdm/UvwCoords.h',
                          'src/cmpt/sdm/UvwCoords.cc',
                          'src/cmpt/sdm/ASDMTableBase.h',
                          'src/cmpt/sdm/ASDMTableBase.cc',
                          'src/cmpt/sdm/ASDMTables.h',
                          'src/cmpt/sdm/ASDMTables.cc',
                          'src/cmpt/sdm/Name2Table.h',
                          'src/cmpt/sdm/Name2Table.cc',
                          'src/cmpt/sdm/BDF2AsdmStManIndex.h',
                          'src/cmpt/sdm/BDF2AsdmStManIndex.cc',
                          'src/cmpt/sdm/SubscanIntent.h',
                          'src/cmpt/sdm/SubscanIntent.cc',
                          'src/cmpt/sdm/SDMBinData.h',
                          'src/cmpt/sdm/SDMBinData.cc',
                          'src/cmpt/sdm/BdFlagger.cc', ],
               'sakura' => [ 'casa-source/gcwrap/tools/singledish/sakura_cmpt.cc',
                             'casa-source/gcwrap/tools/singledish/sakura_forward.h',
                             'casa-source/gcwrap/tools/singledish/sakura_private.h', ],
               'simulator' => [ 'casa-source/gcwrap/tools/synthesis/simulator_cmpt.cc',
                                'casa-source/gcwrap/tools/synthesis/simulator_forward.h',
                                'casa-source/gcwrap/tools/synthesis/simulator_private.h', ],
               'miriadfiller' => [ 'casa-source/gcwrap/tools/miriad/miriadfiller_cmpt.cc',
                                   'casa-source/code/miriad/Filling/Importmiriad.cc' ],
               'synthesismaskhandler' => [ 'casa-source/gcwrap/tools/synthesis/synthesismaskhandler_cmpt.cc',
                                           'casa-source/gcwrap/tools/synthesis/synthesismaskhandler_forward.h',
                                           'casa-source/gcwrap/tools/synthesis/synthesismaskhandler_private.h', ],
               'sidebandseparator' => [ 'casa-source/gcwrap/tools/synthesis/sidebandseparator_cmpt.cc',
                                        'casa-source/gcwrap/tools/synthesis/sidebandseparator_forward.h',
                                        'casa-source/gcwrap/tools/synthesis/sidebandseparator_private.h'],
             );

print "configuring CASAtools... this may take a little while...\n";
unless ( -d $xml_dir ) { make_path($xml_dir) or die "failed to create xml dir: $!" }

#fix_asdm_source("casa-source/code/alma");
#fix_vlafillertask("casa-source/gcwrap");

foreach $k ( keys %xml_files ) { install($xml_files{$k},"$xml_dir/$k.xml") }
foreach $k ( keys %xml_files ) {                                 ### always using the xml_files keys ensures consistency
    my $src = $src_files{$k};
    unless ( -d "$tool_dir/$k" ) { make_path("$tool_dir/$k") }
    foreach my $f ( @$src ) {
        my $base = basename($f);
        open( my $in, "< $f" );
        open( my $out, "> $tool_dir/$k/$base" );
        while ( my $line = <$in> ) {
            $line =~ s|tools/xerces/stdcasaXMLUtil.h|stdcasaXMLUtil.h|g;
            $line =~ s|tools/casa/TSLogSink.h|TSLogSink.h|g;
            $line =~ s|tools/utils/CasapyWatcher.h|CasapyWatcher.h|g;
            print $out $line;
        }
        close($out);
        close($in);
    }
}

@headers = ( 'casa-source/gcwrap/tools/casaswig_types.h',
             'casa-source/gcwrap/tools/swigconvert_python.h',
             'src/swig/casa_typemaps.i',
             'src/swig/swigconvert_python3.h' );
#@source = ( 'casa-source/gcwrap/tools/StdCasa/conversions.cc',
#            'casa-source/gcwrap/tools/StdCasa/conversions_python.cc',
#            'casa-source/gcwrap/tools/StdCasa/interrupt.cc',
#            'casa-source/gcwrap/tools/StdCasa/type_record.cc',
#            'casa-source/gcwrap/tools/StdCasa/type_variant.cc',
#            'casa-source/gcwrap/tools/StdCasa/value_record.cc',
#            'casa-source/gcwrap/tools/StdCasa/value_variant.cc' );
@source = ( 'casa-source/gcwrap/tools/StdCasa/conversions_python.cc',
            'src/swig/swigconvert_python3.cc' );

unless ( -d "$hdr_dir" ) { make_path("$hdr_dir") }
foreach ( @headers ) {
    my $base = basename($_);
    open(my $in,"< $_");
    open(my $out,"> $hdr_dir/$base");
    while ( my $line = <$in> ) {
        $line =~ s|tools/swigconvert_python.h|swigconvert_python.h|g;
        $line =~ s|tools/casaswig_types.h|casaswig_types.h|g;
        print $out $line;
    }
    close($out);
    close($in);
}
unless ( -d "$src_dir" ) { make_path("$src_dir") }
foreach ( @source ) {
    my $base = basename($_);
    open(my $in,"< $_");
    open(my $out, "> $src_dir/$base");
    while (my $line = <$in> ) {
        $line =~ s|tools/swigconvert_python.h|swigconvert_python.h|g;
        $line =~ s|tools/casaswig_types.h|casaswig_types.h|;
        print $out $line;
    }
    close($out);
    close($in);
}

my $table_subst = sub {
    if ( -f $_ ) {
        my @lines = ( );
        open( my $in, "< $_" );
        while (my $line = <$in>) {
            $line =~ s|tools/xerces/asdmCasaXMLUtil.h|tools/table/asdmCasaXMLUtil.h|g;
            $line =~ s|tools/xerces/asdmCasaSaxHandler.h|tools/table/asdmCasaSaxHandler.h|g;
            $line =~ s|tools/ms/Statistics.h|tools/table/Statistics.h|g;
            $line =~ s|tools/ms/Statistics.tcc|tools/table/Statistics.tcc|g;
            push(@lines,$line);
        }
        close($in);
        open( my $out, "> $_" );
        print $out @lines;
        close($out);
    }
};
my $ms_subst = sub {
    if ( -f $_ ) {
        my @lines = ( );
        open( my $in, "< $_" );
        while (my $line = <$in>) {
            $line =~ s|tools/ms/msmetadata_forward.h|msmetadata_forward.h|g;
            $line =~ s|tools/ms/Statistics.h|tools/table/Statistics.h|g;
            push(@lines,$line);
        }
        close($in);
        open( my $out, "> $_" );
        print $out @lines;
        close($out);
    }
};
find( { wanted => $table_subst }, 'binding/tools/table' );
find( { wanted => $ms_subst }, 'binding/tools/msmetadata' );
find( { wanted => $ms_subst }, 'binding/tools/ms' );

foreach ( keys %xml_files ) {
    unless ( -d "binding/generated/tools/$_" ) { make_path("binding/generated/tools/$_") or die "could not create binding/generated/tools/$_: $!" }
}

foreach ( 'libcasatools/generated/source', 'libcasatools/generated/include' ) {
    unless ( -d $_ ) { make_path($_) or die "could not create $_: $!" }
}

sub install {
    my $input = shift(@_);
    my $output = shift(@_);
    open(OUTPUT,"> $output");
    open(UPDATED,"$java -jar $jarfile -upgrade $input |");
    while( <UPDATED> ) { print OUTPUT $_ }
    close(UPDATED);
    close(OUTPUT);
}


sub fix_vlafillertask {
    my $find_path = shift(@_);
    my $find_vlafillertask = sub {
        if ( -f $_ && m|vlafillertask| ) {
            my $file = $_;
            my @lines = ( );
            open( my $fd, "< $file" ) || die "cannot open $File::Find::dir/$file: $!";
            while( my $line = <$fd> ) {
                $line =~ s|vlafillertask|vlafiller|g;
                push(@lines,$line);
            }
            close( $fd );
            open( $fd, "> $file" );
            print $fd @lines;
            close( $fd );
        }
    };

    if ( ! -f "$path/.updated.vlafillertask" ) {
        find( { wanted => $find_vlafillertask }, $find_path );

        my ($sec,$min,$hour,$day,$month,$yr19,@rest) =   localtime(time);
        open( my $fd, "> $path/.updated.vlafillertask" );
        print $fd sprintf("%d %d %d %02d:%02d:%02d\n",$day,$month,$yr19,$hour,$min,$sec);
        close( $fd );
    }
}

sub fix_asdm_source {
    my $find_path = shift(@_);
    my %subst = ( );

    my $asdm_find_headers = sub {
        if ( -f $_ && m|\.h(?:pp)?$| ) {
            my $p = "$File::Find::dir/$_";
            $p =~ s|^.*?/code/alma/(.*)|alma/$1|;
            $subst{$_} = $p;
        }
    };

    my $asdm_substitute = sub {
        if ( -f $_ && m/\.cc$|\.h(?:pp)?$/ ) {
            my $file = $_;
            my @lines = ( );
            open( my $fd, "< $file" ) || die "cannot open $File::Find::dir/$file: $!";
            while( my $line = <$fd> ) {
                foreach my $inc ( keys %subst ) {
                    my $newinc = $subst{$inc};
                    $line =~ s|[<"]$inc[">]|<$newinc>|g;
                }
                push(@lines,$line);
            }
            close( $fd );
            open( $fd, "> $file" );
            print $fd @lines;
            close( $fd );
        }
    };

    if ( ! -f "$path/.updated.alma.includes" ) {
        find( { wanted => $asdm_find_headers }, $find_path );
        find({ wanted => $asdm_substitute }, $find_path );

        my ($sec,$min,$hour,$day,$month,$yr19,@rest) =   localtime(time);
        open( my $fd, "> $path/.updated.alma.includes" );
        print $fd sprintf("%d %d %d %02d:%02d:%02d\n",$day,$month,$yr19,$hour,$min,$sec);
        close( $fd );
    }
}