#! /usr/bin/perl
#
#    LCAEnv.pl - Creates and syncs a complete LCA environment.
#
#    @(#)LCAEnv     2003-02-18
#
#    U. Jansen, SAP AG
#
#    ========== licence begin LGPL
#    Copyright (C) 2002 SAP AG
#
#    This library is free software; you can redistribute it and/or
#    modify it under the terms of the GNU Lesser General Public
#    License as published by the Free Software Foundation; either
#    version 2.1 of the License, or (at your option) any later version.
#
#    This library 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
#    Lesser General Public License for more details.
#
#    You should have received a copy of the GNU Lesser General Public
#    License along with this library; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#    ========== licence end
#

##############################################################################
# Static includes:

use strict;
use Getopt::Long;
use File::Path;
use File::Copy;
use APOSettings;

##############################################################################
# Console Preparation (redirect STDERR to STDOUT and disable buffering):

close   STDERR;
open    STDERR, ">&STDOUT";
$| = 1;

##############################################################################
# Global variables:

my $ProgramName         = "LCAEnv";
my $Version             = "1";
my $Revision            = "00";
my $Date                = "2003-03-13";

my %Opts                = ();
my $Glob                = {};
$Glob->{'P4Port'}       = "perforce3011.wdf.sap.corp:3011";
$Glob->{'PathSep'}      = ($^O =~ /MSWin32/i) ? "\\" : "/";
$ENV{'P4PORT'}          = $Glob->{'P4Port'};

my $DoCreate            = 0;
my $DoMake              = 0;
my $DoClear             = 0;

##############################################################################
# Main routine:
##############################################################################

unless ($ENV{'TOOL'})
{
    print "%TOOL% is not set in the environment!\n";
    exit (10);
}

$ProgramName = $2 if ($0 =~ /^(.*[\/\\])?([^\/\\]+)$/);
$ProgramName =~ s/\.pl//g;

print "\n$ProgramName v$Version.$Revision ($Date), (c)2003 SAP AG\n";

if ($ProgramName eq "LCAMakeEnv")
{
    $DoCreate   = 1;

    if (!GetOptions( \%Opts, 'h|help|?', 'own=s', 'rel=s', 'cl=i', 'lc=s', 'p4u=s', 'p4c=s', 'p4r=s', 'fr', 'v', 'y', 'm=i', 'M=s', 'cfg=s', 'po', 'prod', '_dosbatch') || $Opts{'h'} || @ARGV)
    {
        Usage();
    }
}
elsif ($ProgramName eq "LCAClearEnv")
{
    $DoClear    = 1;

    if (!GetOptions( \%Opts, 'h|help|?', 'own=s', 'cfg=s', 'v', 'y') || $Opts{'h'} || @ARGV)
    {
        Usage();
    }
}
else
{
    $DoCreate   = 1;

    if (!GetOptions( \%Opts, 'h|help|?', 'own=s', 'rel=s', 'cl=i', 'lc=s', 'p4u=s', 'p4c=s', 'p4r=s', 'fr', 'v', 'y', 'm=i', 'M=s', 'c', 'cfg=s', 'po', 'prod', '_dosbatch') || $Opts{'h'} || @ARGV)
    {
        Usage();
    }
}

if ($Opts{'cfg'})
{
    $Glob = LoadCfg($Opts{'cfg'});
}

if ($DoCreate)
{
    $Glob->{'APORel'}   = (defined $Opts{'rel'}  ? $Opts{'rel'}  : ( defined $Glob->{'APORel'}   ? $Glob->{'APORel'}   : AskAPORel() ));
    $Glob->{'ChList'}   = (defined $Opts{'lc'}   ? $Opts{'lc'}   : ( defined $Glob->{'ChList'}   ? $Glob->{'ChList'}   : AskChList() ));
    $Glob->{'LCVer'}    = (defined $Opts{'lc'}   ? $Opts{'lc'}   : ( defined $Glob->{'LCVer'}    ? $Glob->{'LCVer'}    : AskLCVer() ));
    $Glob->{'P4User'}   = (defined $Opts{'p4u'}  ? $Opts{'p4u'}  : ( defined $Glob->{'P4User'}   ? $Glob->{'P4User'}   : AskP4User() ));
    $Glob->{'P4Client'} = (defined $Opts{'p4c'}  ? $Opts{'p4c'}  : ( defined $Glob->{'P4Client'} ? $Glob->{'P4Client'} : AskP4Client() ));
    $Glob->{'P4Root'}   = (defined $Opts{'p4r'}  ? $Opts{'p4r'}  : ( defined $Glob->{'P4Root'}   ? $Glob->{'P4Root'}   : AskP4Root() ));
    $Glob->{'Own'}      = (defined $Opts{'own'}  ? $Opts{'own'}  : ( defined $Glob->{'Own'}      ? $Glob->{'Own'}      : AskOwn() ));
    $Glob->{'Make'}     = (defined $Opts{'M'}    ? $Opts{'M'}    : ( defined $Opts{'m'}          ? $Opts{'m'}          : ( defined $Glob->{'Make'} ? $Glob->{'Make'} : AskMake() )));
    $Glob->{'RELSTAT'}  = (defined $Opts{'prod'} ? 1 : 0);

    $DoClear = (defined $Opts{'c'} ? 1 : 0);

    print "\n\nThe following settings will be used:\n\n";
    print "APO release          : $Glob->{'APORel'}\n";
    print "Change list          : " . ($Glob->{'ChList'} > 0 ? $Glob->{'ChList'} : "<latest>") . "\n";
    print "LC version           : ". ($Glob->{'LCVer'} ? $Glob->{'LCVer'} : "<default>") . "\n";
    print "\$Own directory       : $Glob->{'Own'}\n";
    print "Perforce server      : $Glob->{'P4Port'}\n";
    print "Perforce user        : $Glob->{'P4User'}\n";
    print "Perforce client      : $Glob->{'P4Client'}\n";
    print "Perforce client root : $Glob->{'P4Root'}\n";
    print "Make                 : " . ($Glob->{'Make'} eq "0" ? "Nothing" : ($Glob->{'Make'} eq "1" ? "Default" : $Glob->{'Make'})) . "\n";
    print "RELSTAT              : PROD\n" if ($Glob->{'RELSTAT'} == 1);

    unless($Opts{'y'} or (RequestInput("\nIs this correct? [Y/n] : ", "y", "[yYnN]", "Input incorrect! Please, use only [y or n].\n") =~ /^[1jy]/i))
    {
        print "\nAbort!\n";
        exit(5);
    }

    SetOwn();
    SaveCfg("$Glob->{'Own'}$Glob->{'PathSep'}LCAEnv.cfg", $Glob);

    if (defined $Opts{'po'})
    {
        print "\nPreparation finished. Exiting...\n";
        exit(0);
    }

    SetAPORel();
    SetP4User();
    SetP4Client();
    SetP4Root();
    SetP4ClientView();
    SetChList();
    P4Sync();
    MakeEnv();

    if ($Glob->{'Make'} ne "0")
    {
        DoMake();
    }
}

if ($DoClear)
{
    $Glob->{'Own'} = (defined $Opts{'own'}  ? $Opts{'own'}  : ($Glob->{'Own'} ? $Glob->{'Own'} : $ENV{'OWN'}));

    unless (defined $Glob->{'Own'})
    {
        print "\nError! \$Own is not set! Exiting...\n";
        exit(10);
    }

    unless ($Opts{'y'} or (RequestInput("\nDeleting all entries for '$Glob->{'Own'}'.\nIs this correct? [y/N] : ", "n", "[yYnN]", "Input incorrect. Please, just use [y or n].\n") =~ /^[1jy]/i))
    {
        print "\nClean-up cancelled. Use '-own' or '-cfg' to specify the release to delete.\n\n";
        exit(5);
    }
    $Glob = LoadCfg("$Glob->{'Own'}/LCAEnv.cfg");

    ClearAll();
}

exit(0);

##############################################################################
# AskAPORel() - Asks for the APO release to use
##############################################################################

sub AskAPORel
{
    my $count = 1;
    my @apokeys;
    my $erg;
    print "\nAvailable APO releases:\n\n";
    foreach (reverse sort keys %APOSettings::Depots)
    {
        my $outstr = sprintf("[%2u] = %s\n", $count, $_);
        print "$outstr";
        $apokeys[$count++] = $_;
    }

    print "\nPlease enter the APO release [1 - " . ($count - 1 ). "] : ";
    $erg = <STDIN>;
    chomp $erg;
    while (($erg <= 0) or ($erg >= $count))
    {
        print "Input incorrect. Please use numbers between 1 - " . ($count - 1) . ".\n";
        print "\nPlease enter the APO release [1 - " . ($count - 1 ). "] : ";
        $erg = <STDIN>;
        chomp $erg;
    }

    return $apokeys[$erg];
}

##############################################################################
# SetAPORel() - Sets the APO release to use
##############################################################################

sub SetAPORel
{
    unless ($APOSettings::Depots{$Glob->{'APORel'}})
    {
        print "\nError! The APO Release you entered ($Glob->{'APORel'}) is unknown!\nExiting...\n";
        exit (15);
    }
    return;
}

##############################################################################
# AskChList() - Asks for the ChangeList which will be used to sync the sources
##############################################################################

sub AskChList
{
    if ($Opts{'y'})
    {
        return 0;
    }

    my $res;
    print "\nPlease enter the change list you want to use.\n\nChangeList ['0' or <Enter> = latest] : ";
    $res = <STDIN>;
    chomp $res;
    if ($res =~ /^$/)
    {
        return 0;
    }
    while ($res !~ /^\d+$/)
    {
        print "\nInput incorrect. Please, use only numbers or <Enter>.\n\nChangeList ['0' or <Enter> = latest] : ";
        $res = <STDIN>;
        chomp $res;
    }

    return $res;
}

##############################################################################
# AskLCVer() - Asks for the LC-Version which will be used
##############################################################################

sub AskLCVer
{
    if ($Opts{'y'})
    {
        return 0;
    }

    my $res;
    print "\nPlease enter the LC Version you want to use.\n\nLC Version ['0' or <Enter> = default version] : ";
    $res = <STDIN>;
    chomp $res;
    if ($res =~ /^$/)
    {
        return 0;
    }
    while ($res !~ /^\S+$/)
    {
        print "\nInput incorrect. Please, type in a single word or <Enter>.\n\nChangeList ['0' or <Enter> = default version] : ";
        $res = <STDIN>;
        chomp $res;
    }

    return $res;
}

##############################################################################
# AskOwn() - Determines the "Own" directory to use.
##############################################################################

sub AskOwn
{
    my $curdir      = GetCurrentDir();
    my $reldef      = $Glob->{'P4Root'} . $Glob->{'PathSep'} . $Glob->{'APORel'};

    print "\nPlease select which \$Own directory you want to use:\n\n";

    print "[c] = use the current directory ($curdir)\n";
    print "[p] = use P4 client root ($Glob->{'P4Root'})\n";
    print "[r] = use releases default directory ($reldef), default\n";
    print "[s] = select a different client name manually\n\n";

    my $sel = RequestInput("Please select: ", "r", "[cCpPrRsS]", "Input incorrect. Please, just use [c, p, r or s].\n");

    if ($sel =~ /^c$/i)
    {

        return $curdir;
    }
    elsif ($sel =~ /^p$/i)
    {
        return $Glob->{'P4Root'};
    }
    elsif ($sel =~ /^r$/i)
    {
        return $reldef;
    }
    else
    {
        return ($Glob->{'P4Root'} . $Glob->{'PathSep'} . RequestInput("\$Glob->{'Own'} directory: $Glob->{'P4Root'}$Glob->{'PathSep'}", "", ".+", "Input incorrect. Please, just use normal characters.\n"));
    }
}

##############################################################################
# SetOwn() - Sets the "Own" directory to use.
##############################################################################

sub SetOwn
{
    unless ($Glob->{'Own'} =~ /^\Q$Glob->{'P4Root'}\E/i)
    {
        print "\nError! The \$Glob->{'Own'} directory ($Glob->{'Own'}) has to be\na sub directory of the Perforce client root you want to use!\nExiting...\n";
        exit (15);
    }

    unless(-d $Glob->{'Own'})
    {
        if($Opts{'y'} or (RequestInput("\nDirectory '$Glob->{'Own'}' does not exist. Create ? [Y/n] : ", "y", "[yYnN]", "Input incorrect. Please use [y or n].\n") =~ /^[1jy]/i))
        {
            print "\nCreating directory '$Glob->{'Own'}'...\n";
            File::Path::mkpath(($Glob->{'Own'}), 0, 0777) or die "Can't create directory '$Glob->{'Own'}'!\n$!\n";
            $ENV{'OWN'} = $Glob->{'Own'};
        }
        else
        {
            print "Can't continue without \$Glob->{'Own'}. Exiting...\n";
            exit (10);
        }
    }
}

##############################################################################
# AskMake() - Asks wether to make (and what) or not
##############################################################################

sub AskMake
{
    my $target;
    my $sel;

    print "\nPlease select a make action you want to perform:\n\n";
    print "[n] = no make, default\n";
    print "[d] = default make (lcapps.mac)\n";
    print "[s] = enter a different target to make, manually\n\n";

    if ($Opts{'y'})
    {
        $sel = "n";
    }
    else
    {
        $sel = RequestInput("Please select: ", "n", "[nNdDsS]", "Input incorrect. Please, just use [n, d or s].\n");
    }

    if ($sel =~ /^n$/i)
    {
        $target = "0";
    }
    elsif ($sel =~ /^d$/i)
    {
        $target = "1";
    }
    elsif ($sel =~ /^s$/i)
    {
        $target = RequestInput("Make target: ", "", ".+", "Input incorrect. Please, enter a single target name.\n");
    }

    return $target;
}

##############################################################################
# AskP4User() - Asks for the perforce user
##############################################################################

sub AskP4User
{
    my $login = getlogin;
    my $p4user;

    print "\nPlease select which Perforce user you want to use:\n\n";
    print "[l] = use your login name ($login), default\n";

    if ($ENV{'P4USER'})
    {
        print "[p] = use current Perforce user ($ENV{'P4USER'})\n";
    }

    print "[s] = select a different user name manually\n\n";

    my $sel = RequestInput("Please select: ", "l", $ENV{'P4USER'} ? "[lLpPsS]" : "[lLsS]", "Input incorrect. Please, just use " . ($ENV{'P4USER'} ? "[l, p or s].\n" : "[l or s].\n"));

    if ($sel =~ /^l$/i)
    {
        $p4user = $login;
    }
    elsif ($sel =~ /^p$/i)
    {
        $p4user = $ENV{'P4USER'};
    }
    else
    {
        $p4user = RequestInput("Perforce user: ", "", "[a-zA-Z0-9_]+", "Input incorrect. Please, just use [a-z, A-Z, 0-9 or _].\n");
    }

    $ENV{'P4USER'} = $p4user;

    return $p4user;
}


##############################################################################
# SetP4User() - Sets the Perforce user
##############################################################################

sub SetP4User
{
    my $found = 0;

    open USER_OUT, "p4 -p $Glob->{'P4Port'} user -o $Glob->{'P4User'} |" or die "Can't open 'p4 user -o $Glob->{'P4User'}'!\n$!\n";
    while (<USER_OUT>)
    {
        $found = 1 if (/^Access:/);
    }
    close USER_OUT or die "Can't close 'p4 user -i $Glob->{'P4User'}'!\n$!\n";

    if ($found)
    {
        print "\nUsing existing Perforce user '$Glob->{'P4User'}'...\n";
    }
    else
    {
        print "\nPerforce user '$Glob->{'P4User'}' doesn't exist. Create? [y/N] : ";
        my $res = <STDIN>;
        unless ($res =~ /^[yY]/)
        {
            print "\nUser not created! Aborting...";
            exit(5);
        }

        my ($fullname, $email) = ($1, $2) if (qx($ENV{TOOL}/bin/tel.pl $Glob->{'P4User'}) =~ /^\"([\w|\s]+)\".*,\s(\S+@\S+),/);

        unless ($fullname)
        {
            print "\nCan't determine the full name for user $Glob->{'P4User'}.\n";
            $fullname = RequestInput("Full name: ", "", "[a-zA-Z0-9_]+", "Input incorrect. Please, just use [a-z, A-Z, 0-9 or _].\n");
        }

        unless ($email)
        {
            print "\nCan't determine email address for user $Glob->{'P4User'}.\n";
            $email = RequestInput("Email address: ", "", "[a-zA-Z0-9_@]+", "Input incorrect. Please, just use [a-z, A-Z, 0-9, @ or _].\n");
        }

        print "Creating Perforce user:\n\nUser     = $Glob->{'P4User'}\nFullname = $fullname\nEmail    = $email\n\n";

        open USER_IN, "| p4 -p $Glob->{'P4Port'} user -i" or die "Can't open 'p4 user -i'!\n$!\n";
        print USER_IN "User: $Glob->{'P4User'}\n";
        print USER_IN "Email: $email\n";
        print USER_IN "FullName: $fullname\n";
        close USER_IN or die "Can't 'close p4 user -i'!\n$!\n";

    }
}

##############################################################################
# AskP4Client() - Asks for the Perforce client
##############################################################################

sub AskP4Client
{
    my $hostname = qx(hostname);
    my $p4client;

    chomp $hostname;

    print "\nPlease select which Perforce client you want to use:\n\n";
    print "[h] = use the local host name ($hostname), default\n";

    if ($ENV{'P4CLIENT'})
    {
        print "[p] = use current Perforce client ($ENV{'P4CLIENT'})\n";
    }

    print "[s] = select a different client name manually\n\n";

    my $sel = RequestInput("Please select: ", "h", $ENV{'P4CLIENT'} ? "[hHpPsS]" : "[hHsS]", "Input incorrect. Please, just use " . ($ENV{'P4CLIENT'} ? "[h, p or s].\n" : "[h or s].\n"));

    if ($sel =~ /^h$/i)
    {
        $p4client = $hostname;
    }
    elsif ($sel =~ /^p$/i)
    {
        $p4client = $ENV{'P4CLIENT'};
    }
    else
    {
        $p4client = RequestInput("Perforce client: ", "", "[a-zA-Z0-9_]+", "Input incorrect. Please, just use [a-z, A-Z, 0-9 or _].\n");
    }

    $ENV{'P4CLIENT'} = $p4client;

    return $p4client;
}


##############################################################################
# SetP4Client() - Sets the Perforce client
##############################################################################

sub SetP4Client
{
    my $found = 0;
    my $hostname = qx(hostname);

    chomp $hostname;

    open CLIENT_OUT, "p4 clients |" or die "Can't open 'p4 clients'!\n$!\n";
    while (<CLIENT_OUT>)
    {
        $found = 1 if (/^Client\s$Glob->{'P4Client'}\s.*/);
    }
    close CLIENT_OUT or die "Can't close 'p4 clients'!\n$!\n";

    if ($found)
    {
        print "\nUsing existing Perforce client '$Glob->{'P4Client'}'...\n";
    }
    else
    {
        unless ($Opts{'y'} or (RequestInput("\nPerforce client '$Glob->{'P4Client'}' doesn't exist. Create? [Y/N] : ", "y", "[yYnN]", "Input incorrect. Please, use [y or n].\n") =~ /^[1jy]/i))
        {
            print "\nClient not created! Aborting...";
            exit(5);
        }

        print "\nCreating client '$Glob->{'P4Client'}'...\n";
        open( CLIENT_IN, "| p4 -p $Glob->{'P4Port'} -u $Glob->{'P4User'} client -i") or die "open p4 client -i failed! \n$!\n";
        print CLIENT_IN "Client: $Glob->{'P4Client'}\n";
        print CLIENT_IN "Owner: $Glob->{'P4User'}\n";
        print CLIENT_IN "Host: $hostname\n";
        print CLIENT_IN "Description:\n\tCreated by LCAEnv.\n";
        print CLIENT_IN "Root:\t$Glob->{'P4Root'}\n";
        print CLIENT_IN "Options:\tnoallwrite noclobber nocompress crlf unlocked nomodtime normdir\n";
        print CLIENT_IN "View:\n";
        close CLIENT_IN or die "Can't save the p4 client! \n$!\n";
    }
}

##############################################################################
# AskP4Root() - Asks for the Perforce client root to use
##############################################################################

sub AskP4Root
{
    my $clientroot  = GetP4ClientRoot();
    my $curdir      = GetCurrentDir();
    my $p4root;

    print "\nPlease select which client root you want to use for your P4 client:\n\n";

    print "[c] = use the current directory ($curdir)\n";

    if ($clientroot)
    {
        print "[p] = use current P4 client root ($clientroot)\n";
    }

    print "[s] = select a different client name manually\n\n";

    my $sel = RequestInput("Please select: ", "", $clientroot ? "[cCpPsS]" : "[cCsS]", "Input incorrect. Please, just use " . ($clientroot ? "[c, p or s].\n" : "[o or s].\n"));

    if ($sel =~ /^c$/i)
    {

        $p4root = $curdir;
    }
    elsif ($sel =~ /^p$/i)
    {
        $p4root = $clientroot;
    }
    else
    {
        $p4root = RequestInput("Perforce client root: ", "", ".+", "Input incorrect. Please, just use normal characters.\n");
    }

    return $p4root;

}

##############################################################################
# SetP4Root() - Sets the new P4Client Root
##############################################################################

sub SetP4Root
{
    my $clientroot = GetP4ClientRoot();

    if (lc($clientroot) ne lc($Glob->{'P4Root'}))
    {
        unless ($Opts{'y'} or (RequestInput("\nThe Perforce client root you entered differs from actual value:\nOld root = $clientroot\nNew root = $Glob->{'P4Root'}\n\nDo you want to change it to the new value ? [y/N] : ", "n", "[yYnN]", "Input incorrect. Please, use only [y or n].\n") =~ /^[1jy]/i))
        {
            print "\nPerforce client root not changed. Aborting...\n";
            exit(5);
        }

        open CLIENT_IN, "| p4 -p $Glob->{'P4Port'} -u $Glob->{'P4User'} client -i"            or die "Can't open p4 client -i!\n$!\n";
        open CLIENT_OUT, "p4 -p $Glob->{'P4Port'} -u $Glob->{'P4User'} client -o $Glob->{'P4Client'} |" or die "Can't open p4 client -o $Glob->{'P4Client'}!\n$!\n";
        while (<CLIENT_OUT>)
        {
            if (/^Root:\s+/)
            {
                print CLIENT_IN "Root:\t$Glob->{'P4Root'}\n";
            }
            else
            {
                print CLIENT_IN $_;
            }
        }
        close CLIENT_OUT or die "Can't close p4 client -o $Glob->{'P4Client'}!\n$!\n";
        close CLIENT_IN  or die "Can't close p4 client -i!\n$!\n";
        print "\nPerforce client root set to $Glob->{'P4Root'}...\n";
    }
    else
    {
        print "\nPerforce client root is up-to-date...\n";
    }
}

##############################################################################
# SetP4ClientView() - Adds a new client to Perforce
##############################################################################

sub SetP4ClientView
{
    my %Views;
    my $actview = $APOSettings::Depots{$Glob->{'APORel'}} . "/" . $Glob->{'APORel'};
    my $actpath = $Glob->{'Own'} . "/sys/src";
    my $newwritten = 0;
    my $viewfound = 0;

    $actpath =~ s/\Q$Glob->{'P4Root'}\E//i;
    $actpath =~ tr/\\/\//;
    $actpath = "//$Glob->{'P4Client'}" . $actpath;

    open CLIENT_OUT, "p4 -p $Glob->{'P4Port'} -u $Glob->{'P4User'} client -o $Glob->{'P4Client'} |" or die "Can't open p4 client -o $Glob->{'P4Client'}!\n$!\n";
    while (<CLIENT_OUT>) { $Views{$1} = $2 if (/^\s+(\S+)\/\.\.\.\s+(\S+)\/\.\.\..*/) }
    close CLIENT_OUT or die "Can't close p4 client -o $Glob->{'P4Client'}!\n$!\n";

    if (defined $Views{$actview})
    {
        if (lc($Views{$actview}) eq lc($actpath))
        {
            print "\nPerforce client view path is up-to-date...\n";
            return;
        }
        unless ($Opts{'y'} or (RequestInput("\nThe Perforce client view path you entered differs from actual value:\nOld view path = $Views{$actview}\nNew view path = $actpath\n\nDo you want to change it to the new value ? [y/N] : ", "n", "[yYnN]", "Input incorrect. Please, use only [y or n].\n") =~ /^[1jy]/i))
        {
            print "\nPerforce client view for Rel $Glob->{'APORel'} has not been changed.\nAborting...\n";
            exit(5);
        }
    }

    print "\nUpdating Perforce client view path...\n";

    open CLIENT_IN, "| p4 -p $Glob->{'P4Port'} -u $Glob->{'P4User'} client -i"            or die "Can't open p4 client -i!\n$!\n";
    open CLIENT_OUT, "p4 -p $Glob->{'P4Port'} -u $Glob->{'P4User'} client -o $Glob->{'P4Client'} |" or die "Can't open p4 client -o $Glob->{'P4Client'}!\n$!\n";
    while (<CLIENT_OUT>)
    {
        print CLIENT_IN $_;
        if (/^View:.*/)
        {
            $viewfound = 1;
            last;
        }
    }

    unless ($viewfound)
    {
        print CLIENT_IN "View:\n";
    }

    foreach my $key (keys %Views)
    {
        if ($key eq $actview)
        {
            print CLIENT_IN "\t$actview/... $actpath/...\n";
            $newwritten = 1;
        }
        else
        {
            print CLIENT_IN "\t$key/... $Views{$key}/...\n";
        }
    }

    unless ($newwritten)
    {
        print CLIENT_IN "\t$actview/... $actpath/...\n";
    }

    close CLIENT_OUT or die "Can't close p4 client -o $Glob->{'P4Client'}!\n$!\n";
    close CLIENT_IN  or die "Can't close p4 client -i!\n$!\n";
}

##############################################################################
# RemP4ClientView () - Removes a specific client view and ev. the whole client
##############################################################################

sub RemP4ClientView
{
    my $actview = $APOSettings::Depots{$Glob->{'APORel'}} . "/" . $Glob->{'APORel'};
    my $views = 0;

    print "\nRemoving client entries...\n";

    open CLIENT_IN, "| p4 -p $Glob->{'P4Port'} -u $Glob->{'P4User'} client -i"            or die "Can't open p4 client -i!\n$!\n";
    open CLIENT_OUT, "p4 -p $Glob->{'P4Port'} -u $Glob->{'P4User'} client -o $Glob->{'P4Client'} |" or die "Can't open p4 client -o $Glob->{'P4Client'}!\n$!\n";
    while (<CLIENT_OUT>)
    {
        $views ++ if (/^\s+(\S+)\/\.\.\.\s+(\S+)\/\.\.\./);
        print CLIENT_IN $_ unless (/^\s+$actview\/\.\.\..*/);
    }

    close CLIENT_OUT or die "Can't close p4 client -o $Glob->{'P4Client'}!\n$!\n";
    close CLIENT_IN  or die "Can't close p4 client -i!\n$!\n";

    if ($views == 1)
    {
        if ($Opts{'y'} or (RequestInput("\nThe actual client ($Glob->{'P4Client'}) has no more views.\nRemove the client? [y/N] : ", "n", "[yYnN]", "Input incorrect. Please, use just [y or n].\n") =~ /^[1jy]/i))
        {
            my $rc = system("p4 -p $Glob->{'P4Port'} client -d $Glob->{'P4Client'}");

            if ($rc)
            {
                print "\nError! Client '$Glob->{'P4Client'}' could not be deleted! Continuing...\n";
            }
        }
        else
        {
            print "\nClient '$Glob->{'P4Client'}' has not been deleted...\n";
        }
    }

}

##############################################################################
# SetChList() - Determines the correct changelist number
##############################################################################

sub SetChList
{
    my $branch = $APOSettings::Depots{$Glob->{'APORel'}} . "/" . $Glob->{'APORel'} . "/...";

    unless ($Glob->{'ChList'})
    {
        open CHLIST_OUT, "p4 -p $Glob->{'P4Port'} -u $Glob->{'P4User'} changes -m 1 -s submitted $branch |" or die "Can't open p4 changes -m 1 -s submitted $branch\n$!\n";
        while(<CHLIST_OUT>)
        {
            if (/^Change\s*(\d+)\s/)
            {
                $Glob->{'ChList'} = $1;
            }
        }
        close CHLIST_OUT or die "Can't close p4 changes -m 1 -s submitted $branch!\n$!\n";
    }

    unless ($Glob->{'ChList'})
    {
        print "\nCouldn't determine change list! Please make sure that the Perforce user\nyou entered has access rights for this release ($Glob->{'APORel'}).\nExiting...\n";
        exit (15);
    }

    # Additionally, log the changelist number into a file in $Own for the make progcess:
    open CHLIST_OUT, ">$Glob->{'Own'}$Glob->{'PathSep'}changelist.log" or die "Can't open '$Glob->{'Own'}$Glob->{'PathSep'}changelist.log' for writing!\n$!\n";
    print CHLIST_OUT "$Glob->{'ChList'}\n";
    close CHLIST_OUT or die "Can't close '$Glob->{'Own'}$Glob->{'PathSep'}changelist.log'!\n$!\n";

    print "\nRelease change list is $Glob->{'ChList'}...\n";
}

##############################################################################
# P4Sync() - Sync the actual source tree
##############################################################################

sub P4Sync
{
    my $branch      = $APOSettings::Depots{$Glob->{'APORel'}} . "/" . $Glob->{'APORel'} . "/...";
    my $cmdparam    = ($Glob->{'ChList'} ne "none" ? "$branch\@$Glob->{'ChList'}" : "$branch/...#none");
    my $rc          = 0;

    if ($Opts{'fr'})
    {
        $cmdparam = "-f " . $cmdparam;
        print "\nDoing a complete re-sync of [$Glob->{'APORel'} \@ $Glob->{'ChList'}]" . ($Opts{'v'} ? " :\n\n" : "...\n");
    }
    else
    {
        if ($Glob->{'ChList'} ne "none")
        {
            print "\nSynchronizing files [$Glob->{'APORel'} \@ $Glob->{'ChList'}]" . ($Opts{'v'} ? " :\n\n" : "...\n");
        }
        else
        {
            print "\nRemoving all files from [$Glob->{'APORel'}]" . ($Opts{'v'} ? " :\n\n" : "...\n");
        }
    }

    $| = 1;

    open CMD_OUT, "p4 -s -p $Glob->{'P4Port'} -u $Glob->{'P4User'} -c $Glob->{'P4Client'} sync $cmdparam |" or die "Can't open p4 sync $cmdparam!\n$!\n";
    while (<CMD_OUT>)
    {
        if    (/^(.*):\s(.*)\s-\sadded/)       { print "Add     : $2\n" if ($Opts{'v'}) }
        elsif (/^(.*):\s(.*)\s-\srefreshing/)  { print "Refresh : $2\n" if ($Opts{'v'}) }
        elsif (/^(.*):\s(.*)\s-\supdating/)    { print "Update  : $2\n" if ($Opts{'v'}) }
        elsif (/^(.*):\s(.*)\s-\sdeleted/)     { print "Deleted : $2\n" if ($Opts{'v'}) }
        elsif (/^(.*):.*up-to-date/)           { print "Info    : All files are up-to-date.\n"    }
        elsif (/^error:\s(.*)/)                { print "Error   : $1\n"    }
        elsif (/^info:\s(.*)/)                 { print "Info    : $1\n" if ($Opts{'v'}) }
        elsif (/^exit:\s(\d+)/)                { $rc = $1;                 }
        else                                   { print "$_" if ($Opts{'v'}) }
    }
    close CMD_OUT or $rc = 40;

    if ($Glob->{'ChList'} ne "none")
    {
        print ($rc ? "\nSync failed.\n" : "\nSync OK.\n");
    }
    else
    {
        print ($rc ? "\nFile removal failed.\n" : "\nFile removal OK.\n");
    }
}

##############################################################################
# GetP4ClientRoot() - Retrieves the root directory for a P4 client
##############################################################################

sub GetP4ClientRoot
{
    my $rootpath;
    my $found = 0;

    open CLIENT_OUT, "p4 -p $Glob->{'P4Port'} -u $Glob->{'P4User'} clients |" or die "Can't open 'p4 clients'!\n$!\n";
    while (<CLIENT_OUT>)
    {
        $found = 1 if (/^Client\s$Glob->{'P4Client'}\s.*/);
    }
    close CLIENT_OUT or die "Can't close 'p4 clients'!\n$!\n";

    return "" unless ($found);

    open CLIENT_OUT, "p4 -p $Glob->{'P4Port'} -u $Glob->{'P4User'} client -o $Glob->{'P4Client'} |" or die "Can't open p4 client -o $Glob->{'P4Client'}! \n$!\n";
    while (<CLIENT_OUT>)
    {
        $rootpath = $1 if (/^Root:\s+(\S+)/);
    }
    close CLIENT_OUT or die "Can't close p4 client -o $Glob->{'P4Client'}! \n$!\n";

    return $rootpath;
}

##############################################################################
# MakeEnv() - Sets the current environment.
##############################################################################

sub MakeEnv
{
    print "\nGenerating environment:\n\n";

    local @ARGV = $Glob->{'LCVer'}==0 ? ("-release", uc($Glob->{'APORel'}), "-own", $Glob->{'Own'}) : ("-release", uc($Glob->{'APORel'}), "-own", $Glob->{'Own'}, "-lcversion", "$Glob->{'LCVer'}");
    do "$ENV{TOOL}/bin/vmakeEnv.pl";
    if ( $@ )
    {
        print "\nInitial vmakeEnv failed.\n$@\n";
        exit (10);
    }

    if ($^O =~ /MSWin32/i)
    {
        open ENV_OUT, ">$Glob->{'Own'}\\LCAEnv.bat" or die "Can't open $Glob->{'Own'}\\LCAEnv.bat\n$!\n";
        print ENV_OUT "\@echo off\n";
        print ENV_OUT "set OWN=$Glob->{'Own'}\n";
        print ENV_OUT "set P4USER=$Glob->{'P4User'}\n";
        print ENV_OUT "set P4CLIENT=$Glob->{'P4Client'}\n";
        print ENV_OUT "set P4PORT=$Glob->{'P4Port'}\n";
        print ENV_OUT "set BRANCH_INFO=$Glob->{'APORel'}\n";
        print ENV_OUT "set DEPOT=$APOSettings::Depots{$Glob->{'APORel'}}/$Glob->{'APORel'}\n";
        print ENV_OUT "set FORCED_LCVERSION=$Glob->{'LCVer'}\n" if ($Glob->{'LCVer'} != 0);
        print ENV_OUT "set RELSTAT=PROD\n" if ($Glob->{'RELSTAT'} == 1);
        print ENV_OUT "call %OWN%\\sys\\src\\iprofile.bat\n";
        close ENV_OUT or die "Can't close $Glob->{'Own'}\\LCAEnv.bat\n$!\n";

        open ENV_IN, "<$Glob->{'Own'}\\LCAEnv.bat" or die "Can't open $Glob->{'Own'}\\LCAEnv.bat for reading!\n$!\n";
        while (<ENV_IN>) { print "$_"; }
        close ENV_IN or die "Can't close $Glob->{'Own'}\\LCAEnv.bat!\n$!\n";
        if ($Opts{_dosbatch})
        {
            copy("$Glob->{'Own'}\\LCAEnv.bat", "$ENV{'LCAENV_TMP'}\\LCAEnv_TMP.bat");
        }
        else
        {
            print "\nOK!\n\n$Glob->{'Own'}\\LCAEnv.bat has been generated. To generate the correct\nenvironment, please execute this script.\n\n";
        }
    }
    else
    {
        {
            open ENV_OUT, ">tmpout.dat" or die "Can't open 'tmpout.dat' for writing!\n$!\n";
            print ENV_OUT "P4USER=$Glob->{'P4User'} export P4USER\n";
            print ENV_OUT "P4CLIENT=$Glob->{'P4Client'} export P4CLIENT\n";
            print ENV_OUT "P4PORT=$Glob->{'P4Port'} export P4PORT\n";
            print ENV_OUT "RELSTAT=PROD export RELSTAT\n" if ($Glob->{'RELSTAT'} == 1);
            close ENV_OUT or die "Can't close tmpout.dat!\n$!\n";

            my $platform = vmakeEnv::getPlatform();

            vmakeEnv::printInfo("-platform", $platform, "-apo_src", $Glob->{'Own'});
            vmakeEnv::createProfile ("-all", "-append", "$ENV{TOOL}/profiles/APODev/iprofile.$platform", "-append", "tmpout.dat");

            unlink ("tmpout.dat");

            print "\nOK!\n\n$Glob->{'Own'}/.iprofile has been generated. To generate the correct\nenvironment, please execute this script.\n\n";
        }
    }

}

##############################################################################
# DoMake() - Executes the make
##############################################################################

sub DoMake
{
    my $target = $Glob->{'Make'} eq "1" ? "lcapps.mac" : $Glob->{'Make'};

    if ($^O =~ /MSWin32/i)
    {
        open FILE_OUT, ">LCAMake.bat" or die "Can't create LCAMake.bat!\n$!\n";
        print FILE_OUT "\@echo off\n";
        print FILE_OUT "call $Glob->{'Own'}\\LCAEnv.bat\n";
        print FILE_OUT "echo Running 'python $ENV{'TOOL'}/bin/dsp2vmake.py'...\n";
        if ($Opts{'v'})
        {
            print FILE_OUT "python $ENV{'TOOL'}/bin/dsp2vmake.py -v\n";
        }
        else
        {
            print FILE_OUT "python $ENV{'TOOL'}/bin/dsp2vmake.py\n";
        }
        print FILE_OUT "echo Running 'lcmake -i $target'...\n";
        print FILE_OUT "lcmake -i $target\n";
        close FILE_OUT or die "Can't close LCAMake.bat!\n$!\n";

        print "Executing Make script:\n\n";

        open CMD_OUT, "call LCAMake.bat |" or die "Can't execute 'call LCAMake.bat'!\n$!\n";
        while (<CMD_OUT>) { print "$_" }
        close CMD_OUT or die "Can't close 'call LCAMake.bat'!\n$!\n";

        unlink("LCAMake.bat");
    }
    else
    {
        open FILE_OUT, ">LCAMake.sh" or die "Can't create LCAMake.sh!\n$!\n";
        print FILE_OUT ". $Glob->{'Own'}$Glob->{'PathSep'}.iprofile\n";
        print FILE_OUT "echo Running 'python $ENV{'TOOL'}/bin/dsp2vmake.py'...\n";
        if ($Opts{'v'})
        {
            print FILE_OUT "python $ENV{'TOOL'}/bin/dsp2vmake.py -v\n";
        }
        else
        {
            print FILE_OUT "python $ENV{'TOOL'}/bin/dsp2vmake.py\n";
        }
        print FILE_OUT "echo Running 'lcmake -i $target'...\n";
        print FILE_OUT "lcmake -i $target\n";
        close FILE_OUT or die "Can't close LCAMake.sh!\n$!\n";

        print "Executing Make script:\n\n";

        open CMD_OUT, ". LCAMake.sh |" or die "Can't execute '. LCAMake.sh'!\n$!\n";
        while (<CMD_OUT>) { print "$_" }
        close CMD_OUT or die "Can't close '. LCAMake.sh'!\n$!\n";

        unlink ("LCAMake.sh");
    }

    print "\nMake done.\n";
}

##############################################################################
# ClearAll() - Cleans the working dir again.
##############################################################################

sub ClearAll
{
    $ENV{'P4USER'}      = $Glob->{'P4User'};
    $ENV{'P4CLIENT'}    = $Glob->{'P4Client'};
    $ENV{'P4PORT'}      = $Glob->{'P4Port'};

    $Glob->{'ChList'}   = "none";

    P4Sync();

    RemP4ClientView();

    print "\nRemoving directory structure". ($Opts{'v'} ? ":\n\n" : "...\n");

    DelTree($Glob->{'Own'});

    print "\n\$Own tree has been removed.\n";
}

##############################################################################
# DelTree() - Removes a complete tree
##############################################################################

sub DelTree
{
    my ($dir) = @_;
    my @dirlist;

    opendir (DIR, $dir) or die "Can't open $dir for reading!\n$!\n";
    @dirlist = readdir(DIR);
    closedir DIR or die "Can't close $dir!\n$!\n";

    foreach my $entry (@dirlist)
    {
        next if (($entry eq ".") or ($entry eq "..") or (! -d $dir.$Glob->{'PathSep'}.$entry));
        DelTree($dir.$Glob->{'PathSep'}.$entry);
    }


    print "Removing: $dir\n" if $Opts{'v'};
    system("rm -f -R $dir");

}

##############################################################################
# Usage() - Shows the program usage and exits the script.
##############################################################################

sub Usage
{
    if ($DoCreate)
    {
        print "\n";
        print "Usage:  $ProgramName.pl [-own <OWN_DIR>] [-rel <RELEASE>] [-cl <CHANGELIST>]\n";
        print "                      [-lc <LC_VERSION>] [-p4u <P4USER>] [-p4c <P4CLIENT>]\n";
        print "                      [-p4r <P4CLIENT_ROOT>] [-v] [-y] [-h]\n";
        print "                      [-cfg <Config-File>]\n";
        if ($DoMake)
        {
            print "                      [-m] [-M <MAKE-TARGET>]\n";
        }
        if ($DoClear)
        {
            print "                      [-c]\n";
        }
        print "\nWhere:\n";
        print "        -own <OWN_DIR>\n";
        print "             sets the root directory for the new environment\n";
        print "        -rel <RELEASE>\n";
        print "             sets the APO-Release\n";
        print "        -cl  <CHANGELIST>\n";
        print "             sets the changelist to be used for the release\n";
        print "        -lc  <LC_VERSION>\n";
        print "             sets the liveCache Version to be used\n";
        print "        -p4u <P4USER>\n";
        print "             sets the Perforce user to be used (If this user doesn't\n";
        print "             exist, it will be created.)\n";
        print "        -p4c <P4CLIENT>\n";
        print "             sets the Perforce client to be used (If the client\n";
        print "             doesn't exist, it will be created.)\n";
        print "        -p4r <P4CLIENT_ROOT>\n";
        print "             sets the client root to be used for the Perforce client.\n";
        print "        -fr\n";
        print "             Force a re-sync of all files, even if they already exist.\n";
        print "        -v\n";
        print "             Verbose mode. Use this option to see more detailed outputs.\n";
        print "        -y\n";
        print "             Answer all questions with (y)es\n";
        print "        -h\n";
        print "             shows this help\n";
        print "        -cfg <Config-File>\n";
        print "             Instead of setting all parameters manually, you can give\n";
        print "             config file which contains all needed data. Such a config\n";
        print "             file is created under '\$Own/LCAEnv.env' each time you\n";
        print "             create an environment with this tool. You may copy this file\n";
        print "             for later use.\n";
        print "        -po\n";
        print "             Prepare only. With this option, you can only create a cfg file\n";
        print "             without actually do something. The file can be found under:\n";
        print "             \$Own/LCAEnv.cfg.\n";
        print "        -prod\n";
        print "             Set RELSTAT = PROD\n";
        if ($DoMake)
        {
            print "        -m\n";
            print "             does a default make\n";
            print "        -M   <MAKE-TARGET>\n";
            print "             does a make on the given make target\n";
        }
        if ($DoClear)
        {
            print "        -c\n";
            print "             Clears the complete enviroment again at the end\n";
        }

        print "\n        You can also start this program without parameters. Any missing\n";
        print "        option/information will be asked for.\n";
        print "\nAvailable APO releases:\n\n";
        foreach (reverse sort keys %APOSettings::Depots)
        {
            print "        $_\n";
        }
        print "\n";
    }
    else
    {
        print "\n";
        print "Usage:  $ProgramName.pl [-own <OWN_DIR>] [-cfg <Config-File>] [-v] [-y]\n";
        print "\nWhere:\n";
        print "        -own <OWN_DIR>\n";
        print "             sets the root directory for the environment to be cleared\n";
        print "        -cfg <Config-File>\n";
        print "             Instead of setting all parameters manually, you can give\n";
        print "             config file which contains all needed data.\n";
        print "        -v\n";
        print "             Verbose mode. Use this option to see more detailed outputs.\n";
        print "        -y\n";
        print "             Answer all questions with (y)es\n";
        print "\n        You can also start this program without parameters. Any missing\n";
        print "        option/information will be asked for.\n";
        print "\n        NOTE: If you give neither -own nor -cfg, the program tries to use\n";
        print "              the environment variable \$OWN!\n\n";
    }

    print "        For more detailed information, use 'perldoc LCAEnv.pl'.\n\n";

    exit(1);
}

##############################################################################
# RequestInput() - Asks for a user input
##############################################################################

sub RequestInput
{
    my ($outstr,$defval,$inpmask,$errstr) = @_;
    my $tempval;

    if ($outstr)
    {
        print $outstr;
    }

    unless ((!$defval) || ($defval =~ /^$inpmask$/))
    {
        print "\nThe input mask doesn't seem to be appropriate! Exiting...".$inpmask;
        exit(20);
    }

    $tempval = <STDIN>;
    chomp $tempval;

    until (($tempval =~ /^$inpmask$/) or ($defval and ($tempval =~ /^$/)))
    {
        print $errstr.$outstr;
        $tempval = <STDIN>;
        chomp $tempval;
    }

    if ($tempval =~ /^$/)
    {
        $tempval = $defval;
    }

    return $tempval;
}

##############################################################################
# GetCurrentDir() - Returns the actual working dir
##############################################################################

sub GetCurrentDir
{
    my $dir;

    if ($^O =~ /MSWin32/i)
    {
        $dir = qx(cd);
    }
    else
    {
        $dir = qx(pwd);
    }
    chomp $dir;
    return $dir;
}

##############################################################################
# LoadEnv() - Loads the current Settings
##############################################################################

sub LoadCfg
{
    my ($fname) = @_;
    my $temp = {};

    open FILE_IN, "<$fname" or die "Can't open $fname for reading!\n$!\n";
    while (<FILE_IN>)
    {
        chomp $_;
        $temp->{$1} = $2 if (/^\[(.*)]=(.*)$/);
    }
    close FILE_IN or die "Can't close $fname!\n$!\n";

    return $temp;
}

##############################################################################
# SaveEnv() - Saves the current Settings
##############################################################################

sub SaveCfg
{
    my ($fname, $env) = @_;

    open FILE_OUT, ">$fname" or die "Can't open $fname for writing!\n$!\n";
    foreach my $key (keys %{$env})
    {
        print FILE_OUT "[$key]=$env->{$key}\n";
    }
    close FILE_OUT or die "Can't close $fname!\n$!\n";
}

__END__

=head1 NAME

LCAEnv - LCApps environment creation / deletion tool.

Version: v1.00 (2003-03-13)

=head1 NOTE

This tool is for internal use, only.
In order to work correctly, this tool needs a pre-installed development
environment. Since it also copies data from internal servers, it is very
likely not working outside SAP.

=head1 SYNOPSIS

There are three different ways to call this tool. Actually, they all start
the same tool. The different names just enable/disable various command line
options:

=over 4

=item LCAMakeEnv

[-own <$OWN directory>] [-rel <release>] [-cl <change list>] [-lc <LC version>]
[-p4u <perforce user>] [-p4c <perforce client>] [-p4r <perforce client root>]
[-v] [-y] [-h] [-cfg <config file>] [-m] [-M <make target>] [-prod]

=item LCAClearEnv

[-own <$OWN directory>] [-cfg <config file>] [-v] [-y]

=item LCAEnv

[-own <$OWN directory>] [-rel <release>] [-cl <change list>] [-lc <LC version>]
[-p4u <perforce user>] [-p4c <perforce client>] [-p4r <perforce client root>]
[-v] [-y] [-h] [-cfg <config file>] [-m] [-M <make target>] [-prod] [-c]

=back

=head1 DESCRIPTION

With this tool you are able to create a complete LCApps development tree in
one single step. It will set the correct environment, sync all sources into
the target directory and even start the make process, if you want it to.
Additionally, you can specify a liveCache version other than the default
version to be installed together with the APO environment. Finally, you
can automatically clean-up all directories LCAEnv created.

=head2 COMMAND LINE OPTIONS

The following command line options can be used with this tool. Any needed
option (marked by a '*') you didn't give will be asked for.

NOTE: The available command line options depend on which command name you
      used. (See synopsis above.)

=over 4

=item -own <$OWN directory> *

Sets the OWN directory for the release to be installed. This is typically
something like: <my sub tree>/<APORel>/develop. NOTE: This path has to be
a sub-directory of the Perforce root (see below).


=item -rel <release> *

The APO release you want to use. This can be either "dev" or a format like
this: "4.0_HOT", "3.0A_COR" or "3.10"

=item -cl <change list>

The change list you want to sync to. If you enter "0", a sync to head revision
will be performed.

=item -lc <LC version>

Here you can set the liveCache version you want to use with this APO release.
Again, if you enter "0" here, the default LC version will be taken.
The version number you enter here must be a complete version including the
build number, eg. "740317" or "730031".

=item -p4u <Perforce user> *

This will set the Perforce user you want to use. The user you enter here
should already exist on the Perforce server since you are not able to access
the source files otherwise. Normally, you would take your DUser.

=item -p4c <Perforce client> *

The Perforce client to be used. Here you can either use your default client or
any other you like. Please, be aware that if you use an existing client and if
there's already a branch entry for the APO release you use, this entry will be
*OVERWRITTEN* by the new settings. Please, be also aware that each new client
cost a license...

=item -p4r <Perforce client root> *

This is the (Perforce) client root path you want to use. Note, that the $Own
directory has to be a sub-directory of this path.

EXAMPLE: -own c:\APODev\4.0_HOT -p4r c:\APODev

=item -v

Switch verbose mode on. With this option turned on you get a more detailed
output of what really happens in background.

=item -y

Assume 'yes' on all 'yes/no' questions. With this option, the program should
only bother you if it's really neccessary. Using the 'y' option in conjuction
with either all needed parameters or a configuration file (see below), you
can do unattended installations.

=item -h

Shows the short command line help.

=item -cfg <config file>

A configuration file you want to use. Each time you use 'LCAEnv', a
configuration file is created under '$Own/LCAEnv.cfg'. If you don't want to
enter all data again each time you use this program, you can copy this file
and use it as config file next time you start the program. Since this is a
plain text file, you can also edit it and use it as template later.

For more information on the config file format, see below.

=item -m

Automatically make default target (lcapps.mac). Having this wsitch turned
on, a default make will automatically be performed after finishing the
installation procedure.

=item -M <make target>

This option will start a make of a specific target after the install routine
has been finished. Please note, that this option overrides the '-m' option.

=item -prod

This option creates an environment for productive makes by setting the env
variable $RELSTAT to "PROD".

=item -c

This option is only available in "full mode", ie. when you start the program
as "LCAEnv". It will automatically clear the environment again after finishing
all tasks. This option is only useful, if you eg. want to create an
environment, make a target and clean-up the whole thing again in one single
step (having the outputs piped into a file).

=back

=head2 CONFIG FILE FORMAT

The format of the config files is quite simple. The following rules apply:

=over 4

=item 1. Each valid line contains exactly one setting.

=item 2. Each valid line has the following format: [<KEY>]=<VALUE>

=item 3. Each line NOT having the format given above is NOT valid and will therefore
be treated as comment.

=back

=head3 KNOWN KEYS

=over 4

=item [APORel]

Sets the APO release. Equals the '-rel' option.

=item [ChList]

Sets the actual change list to use. Equals the '-cl' option.

=item [LCVer]

Set the liveCache version you want to use. Equals the '-lc' option.

=item [Make]

Sets the make target. Here you can set either "0" for no make, "1" for the
default make target or directly a target, like "lcapps.mac".

=item [Own]

Sets the $Own directory to be used. Equals the '-own' option.

=item [P4Client]

Sets the Perforce client you want to use. Equals the '-p4c' option.

=item [P4Port]

Sets the Perforce client port to use. This option cannot be set as command
line parameter and is high likely not to be changed. Default value is:
"perforce3011.wdf.sap.corp:3011".

=item [P4Root]

Set the Perforce root path for the given client. Equals the '-p4r' option.

=item [P4User]

Sets the Perforce user to be used. Equals the '-p4u' option.

=item [PathSep]

Sets the path separator to be used on this platform. This option must be '/'
for all UNIX platforms or '\' for Windows platorms.

=item [RELSTAT]

Set the RELSTAT value in the environment. This key can be either '0' or '1'.
Having set this key to '1', the environment variable $RELSTAT will be set to
'PROD'.

=back

=head1 EXAMPLES

Here are some examples to make things even a bit more clear.

=head2 EXAMPLE CALLS

=over 4

=item LCAMakeEnv

Creates an APO environment asking you for all options.

=item LCAMakeEnv -y

Creates an APO environment asking you just for all NEEDED options.

=item LCAMakeEnv -v -y

Same as above, but gives you a lot mor information on whats happening.

=item LCAMakeEnv -own c:\apomake\dev -rel dev -p4u d101010 -p4c P10101 -p4r c:\apomake -lc 0 -cl 0 -y -v -m

Creates a complete environment for APO (dev) in c:\apomake\dev using the latest
changes and the default liveCache version not asking any questions and giving a
lot of information. Finally, also the default make will be performed.

=item LCAEnv -own c:\apomake\dev -rel dev -p4u d101010 -p4c P10101 -p4r c:\apomake -lc 0 -cl 0 -y -v -m -c > c:\temp\out.log

This call is weired. It creates a complete environment as explained above,
makes the default target and clears everything afterwards again. All outputs
will be written to c:\temp\out.log.

=item LCAClearEnv -own c:\apomake\dev

Deletes the whole environment again. Any made changes in Perforce will also be
reverted.

=back

=head2 EXAMPLE CONFIG FILE (for Windows)

File "c:\apomake\dev\LCAEnv.cfg":

=over 4

=item [ChList]=0

=item [Own]=c:\apomake\dev

=item [PathSep]=\

=item [LCVer]=740317

=item [P4Client]=P10101

=item [RELSTAT]=0

=item [P4Port]=perforce3011.wdf.sap.corp:3011

=item [P4Root]=c:\apomake

=item [Make]=1

=item [APORel]=dev

=item [P4User]=d010101

=back

=head1 COPYRIGHT

Copyright SAP AG 2003