haiku/data/bin/installoptionalpackage

963 lines
22 KiB
Bash
Executable File

#!/bin/bash
#
# Copyright (c) 2009-2010 Haiku, Inc.
# Distributed under the terms of the MIT License.
#
# Authors:
# Matt Madia, mattmadia@gmail.com
#
# Synopsis:
# Provides a controlled mechanism for end-users to install certain pre-built
# OptionalPackages. The script will determine the host information: the
# default GCC, availability of secondary GCC libs, and revision. Using this
# information, the user will be limited to the appropriate OptionalPackages
# that were available for that specific revision.
#
DISCLAIMER="\
Disclaimer:\n\
This is a temporary solution for installing OptionalPackages.\n\
In time, there will be an official package manager.\n\
See these URL's for information on the in-development package manager.\n\
http://dev.haiku-os.org/wiki/PackageManagerIdeas\n\
http://dev.haiku-os.org/wiki/PackageFormat\n\
"
USAGE="\
Usage: ./installoptionalpackage [<pkg> [<pkg> ...]]\n\
or ./installoptionalpackage [-a|-s <pkg> [<pkg> ...]]\n\
or ./installoptionalpackage [-f|-h|-l]\n\
\n\
Options:\n\
-a Add one or more packages and all dependencies\n\
-s Show the final list of packages that would be installed\n\
-f Remove cached data and list installable packages\n\
-h Print this help.\n\
-l List installable packages\n\
"
declare -A availablePackages
declare availablePackagesKeys=""
declare wantsToInstall=""
declare alreadyInstalled=""
# Some Packages cannot be installed,
# as they require either the source code or compiled binaries
declare packageIgnoreList="Bluetooth Development DevelopmentMin \
DevelopmentBase ICU-devel ICU MandatoryPackages UserlandFS \
WebPositive Welcome WifiFirmwareScriptData "
function CreateInstallerScript()
{
# This function will create a secondary script, containing all of the
# information needed to install the optional package and its dependencies
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cat << EOF > ${tmpDir}/install-optpkg.sh
#!/bin/bash
tmpDir=${tmpDir}
HAIKU_GCC_VERSION[1]=${HAIKU_GCC_VERSION[1]}
isHybridBuild=${isHybridBuild}
TARGET_ARCH=${TARGET_ARCH}
HAIKU_IMAGE_HOST_NAME=`uname -n`
#TODO: possibly add a CLI option to execute InstallSourceArchive
HAIKU_INCLUDE_SOURCES=0
$urlLine
$sslPkgLine
$sslUrlLine
$webkitFileLine
declare -a functionArgs
expanderRulesFile=`finddir B_COMMON_DATA_DIRECTORY`/expander.rules
if [ -f \${expanderRulesFile} ] ; then
expanderRulesFileExists=1
fi
function ParseFunctionArguments()
{
# ParseFunctionArguments <args>
# Parse arguments for Jam wrapper functions into an array.
IN="\$@"
OIFS=\$IFS
IFS=":"
local count=0
functionArgs=( )
for x in \$IN
do
functionArgs[\${count}]="\${x}"
((count++))
done
IFS=\$OIFS
}
function TrimLeadingSpace()
{
# TrimLeadingSpace <variable name>
eval local text='\$'"\$1"
local _outvar="\$1"
local length=\${#text}
((length--))
if [ "\${text:0:1}" == ' ' ] ; then
text=\${text#' '}
fi
eval \$_outvar="'\$text'"
}
function TrimEndingSpace()
{
# TrimEndingSpace <variable name>
eval local text='\$'"\$1"
local _outvar="\$1"
local length=\${#text}
((length--))
if [ "\${text:\$length}" == ' ' ] ; then
text=\${text%' '}
fi
eval \$_outvar="'\$text'"
}
function Exit()
{
# Exit <message>
# Wrapper for Jam rule
echo "\$@"
exit 1
}
function InstallOptionalHaikuImagePackage()
{
# InstallOptionalHaikuImagePackage package : url : dirTokens : isCDPackage
# Wrapper for Jam rule
echo "Installing \$1 ..."
cd \$tmpDir
archiveFile=\`echo \$3 | sed -s "s/http.*\///"\`
if ! [ -f \$archiveFile ] ; then
echo "Downloading \$3 ..."
# TODO : add some error handling for downloads
local attempt=1
while [ \`wget -nv \$3 ; echo \$? \` -ne 0 ]; do
if [ \$attempt -eq 5 ]; then
break
fi
(( attempt++ ))
echo "Download attempt #\$attempt failed. Retrying ..."
if [ -e \$archiveFile ]; then
rm \$archiveFile
fi
done
if [ \$attempt -ge 5 ]; then
if [ -e \$archiveFile ]; then
rm \$archiveFile
fi
Exit "Max download retries exceeded. Halting installation."
fi
fi
local dirTokens='/boot'
local count=4
local i=0
for possibleToken in "\$@" ; do
if [ \$i -lt \$count ] ; then
((i++))
else
((i++))
if [ "\$possibleToken" != ':' ] ; then
dirTokens=\${dirTokens}/\$possibleToken
else
break
fi
fi
done
echo "Extracting \$archiveFile ..."
extractDir="\${dirTokens}"
local errorMessage="
...Failed while extracting \$archiveFile
You may need to manually clean up the partially extracted files.
"
case "\$archiveFile" in
*.zip)
unzip -q -o -d "\$extractDir" "\$archiveFile" \
|| Exit "\$errorMessage"
;;
*.tgz|*.tar.gz)
tar -C "\$extractDir" -xf "\$archiveFile" \
|| Exit "\$errorMessage"
;;
*)
echo "Unhandled archive extension in InstallOptionalHaikuImagePackage()"
exit 1
;;
esac
if [ -f '/boot/.OptionalPackageDescription' ] ; then
rm '/boot/.OptionalPackageDescription'
fi
rm "\$archiveFile"
}
function InstallSourceArchive()
{
if [ \$HAIKU_INCLUDE_SOURCES -gt 0 ]; then
echo "InstallSourceArchive is not implemented."
fi
}
function AddDirectoryToHaikuImage()
{
# AddDirectoryToHaikuImage directoryTokens : attributeFiles
# Wrapper for Jam rule
ParseFunctionArguments "\$@"
local dirTokens="/boot/\${functionArgs[0]}"
TrimLeadingSpace dirTokens
TrimEndingSpace dirTokens
dirTokens=\${dirTokens//' '/\/}
mkdir -p "\${dirTokens}"
}
function AddSymlinkToHaikuImage()
{
# AddSymlinkToHaikuImage <dir tokens> : <link target> [ : <link name> ]
# Wrapper for Jam rule
ParseFunctionArguments "\$@"
local dirTokens="/boot/\${functionArgs[0]}"
TrimLeadingSpace dirTokens
TrimEndingSpace dirTokens
dirTokens=\${dirTokens//' '/\/}
local linkTarget="\${functionArgs[1]}"
TrimLeadingSpace linkTarget
TrimEndingSpace linkTarget
local linkName="\${functionArgs[2]}"
TrimLeadingSpace linkName
TrimEndingSpace linkName
mkdir -p "\${dirTokens}"
if [ "\${linkName}" == '' ] ; then
ln -sf "\${linkTarget}" -t "\${dirTokens}"
else
ln -sf "\${linkTarget}" "\${dirTokens}/\${linkName}"
fi
}
function AddUserToHaikuImage()
{
# AddUserToHaikuImage user : uid : gid : home : shell : realName
# Wrapper for Jam rule
ParseFunctionArguments "\$@"
local user=\${functionArgs[0]}
local uid=\${functionArgs[1]}
local gid=\${functionArgs[2]}
local home=\${functionArgs[3]}
local shell=\${functionArgs[4]}
local realName=\${functionArgs[5]}
passwdLine="\${user}:x:\${uid}:\${gid}:\${realName}:\${home}:\${shell}"
passwdLine=\${passwdLine//' :'/':'}
passwdLine=\${passwdLine//': '/':'}
local length=\${#passwdLine}
((length--))
if [ "\${passwdLine:\$length}" == ' ' ] ; then
passwdLine=\${passwdLine%' '}
fi
passwdFile="\`finddir B_COMMON_ETC_DIRECTORY\`/passwd"
touch \${passwdFile}
local userExists=1
while read line ; do
if [ "\${passwdLine}" == "\${line}" ] ; then
userExists=0
fi
done < \${passwdFile}
if [ \$userExists -ge 1 ] ; then
echo "\${passwdLine}" >> \${passwdFile}
fi
}
function AddExpanderRuleToHaikuImage()
{
# AddExpanderRuleToHaikuImage <mimetype> : <extension> : <list> : <extract>
# Wrapper for Jam rule
ParseFunctionArguments "\$@"
local mimetype=\${functionArgs[0]}
local extension=\${functionArgs[1]}
local list=\${functionArgs[2]}
local extract=\${functionArgs[3]}
# clean up the variables
TrimLeadingSpace mimetype
TrimEndingSpace mimetype
TrimLeadingSpace extension
TrimEndingSpace extension
TrimLeadingSpace list
TrimEndingSpace list
TrimLeadingSpace extract
TrimEndingSpace extract
local rule_raw="\${mimetype}\\t\${extension}\\t\${list}\\t\${extract}"
# reset this at every invocation
ruleFound=
if [ \${expanderRulesFileExists} ] ; then
# Check if a rule for the mimetype & extension exists.
while read line ; do
existing_rule=`echo \$line | awk '{ print \$1\$2 }'`
if [ "\${mimetype}\${extension}" == "\${existing_rule}" ] ; then
ruleFound=1
break
fi
done < "\${expanderRulesFile}"
fi
if ! [ \${expanderRulesFileExists} ] || ! [ \${ruleFound} ] ; then
# Either expander.rules does not exist or a rule for mimetype &
# extension does not exist. Output the new rule directly to it.
echo -e \${rule_raw} >> \${expanderRulesFile}
fi
}
EOF
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cat ${tmpDir}/optpkg.stage2 >> ${tmpDir}/install-optpkg.sh
rm ${tmpDir}/optpkg.stage2
}
function ContainsSubstring()
{
# ContainsSubstring <stringToLookIn> <stringToLookFor>
local string="$1"
local substring="$2"
local newString=${string/${substring}/''}
if [ ${#string} -eq $((${#newString} + ${#substring})) ] ; then
return 0
fi
return 1
}
function ErrorExit()
{
echo $1
exit 1
}
function Init()
{
# Set up some directory paths
baseDir=`finddir B_COMMON_DATA_DIRECTORY`/optional-packages
tmpDir=`finddir B_COMMON_TEMP_DIRECTORY`
libDir=`finddir B_SYSTEM_LIB_DIRECTORY`
installedPackagesFile="${baseDir}/InstalledPackages"
# Make sure these files are empty.
echo "" > ${tmpDir}/optpkg.jam
echo "" > ${tmpDir}/optpkg.stage1
if ! [ -d ${baseDir} ] ; then
mkdir -p ${baseDir}
fi
DetectSystemConfiguration
DownloadAllBuildFiles
ReadInstalledPackagesIntoMemory
ReadPackageNamesIntoMemory
}
function DownloadAllBuildFiles()
{
# DownloadAllBuildFiles
# Retreive the necessary jam files from svn.
local buildFiles="BuildFeatures OptionalPackageDependencies \
OptionalPackages OptionalLibPackages"
for file in ${buildFiles} ; do
GetBuildFile ${file}
done
}
function GetBuildFile()
{
# GetBuildFile <file>
# Downloads files from Haiku's svn
local buildfile="$1"
if ! [ -f ${baseDir}/${buildfile} ] ; then
echo "Fetching ${buildfile} ..."
cd ${baseDir}
local baseURL=http://cgit.haiku-os.org/haiku/plain
local revisionTag=`uname -v | awk '{print $1}' | sed -e 's/-.*//'`
# the sed invocation above drops potential dirty markers off the
# revision tag
local url="${baseURL}/build/jam/${buildfile}?id=${revisionTag}"
wget -q ${url} -O ${buildfile} \
|| ErrorExit "...failed to download $buildfile"
fi
}
function DetectSystemConfiguration()
{
# Determine which GCC we're running
if [ -f "$libDir"/libsupc++.so ] ; then
HAIKU_GCC_VERSION[1]=4
else
HAIKU_GCC_VERSION[1]=2
fi
# Test for hybrid
if [ -d "$libDir"/gcc4 -a -d "$libDir"/gcc2 ]; then
echo "Sorry, but your build appears to be broken ..."
echo "Both gcc2 and gcc4 subdirs exist."
exit 1
elif [ -d "$libDir"/gcc4 -o -d "$libDir"/gcc2 ]; then
isHybridBuild=1
else
isHybridBuild=""
fi
# Determine the Architecture.
if [ `uname -m` == "BePC" ] ; then
TARGET_ARCH='x86'
elif [ `uname -m` == "x86_64" ] ; then
TARGET_ARCH='x86_64'
else
echo "Sorry, x86 only for now."
exit 1
fi
}
function ReadInstalledPackagesIntoMemory()
{
while read line ; do
alreadyInstalled="${alreadyInstalled} $line"
packageIgnoreList=${packageIgnoreList/"${line} "/' '}
done < ${installedPackagesFile}
}
function ReadPackageNamesIntoMemory()
{
local file="${baseDir}/OptionalPackageNames"
if ! [ -f ${file} ] ; then
GeneratePackageNames
fi
# read list into associative array
while read line ; do
local pkg=`echo ${line} | awk '{print $1}'`
local pkgDeps=${line/"${pkg} :"/}
availablePackages[${pkg}]="${pkgDeps}"
availablePackagesKeys="${availablePackagesKeys} ${pkg}"
done < ${file}
}
function GeneratePackageNames()
{
# GeneratePackageNames
# Creates a file containing available package names
# Each line shows a pakage and all of its recrusive dependencies
# "<pkg> : <dep1> <dep2> ..."
echo "Generating a list of Package Names ..."
local file="${baseDir}/OptionalPackageNames"
if [ -e "${file}" ]; then
rm "${file}"
fi
local regExp='/^if\ \[\ IsOptionalHaikuImagePackageAdded/p'
sed -n -e "$regExp" ${baseDir}/OptionalPackages > ${file}.temp
sed -n -e "$regExp" ${baseDir}/OptionalLibPackages >> ${file}.temp
while read line ; do
# in each non-filtered line, the 4th word is the optional package
local pkg=`echo ${line} | awk '{print $4}'`
nonRepeatingDeps=""
GetPackageDependencies "$pkg"
local lowerCasePkg=`echo ${pkg} | tr '[A-Z]' '[a-z]'`
if ! ContainsSubstring "${alreadyInstalled} " "${pkg} " ; then
if IsPackageAndDepsOkToInstall ${pkg} ; then
echo "${lowerCasePkg} : ${pkg} ${nonRepeatingDeps}" >> ${file}
fi
fi
done < ${file}.temp
rm ${file}.temp
}
function GetPackageDependencies()
{
# GetPackageDependencies <pkg>
# parse OptionalPackageDependencies for the single line that defines
# this optional package's dependencies.
local regExp="^OptionalPackageDependencies\ ${1}\ \:"
local inputFile="${baseDir}/OptionalPackageDependencies"
# print that single line
sed -n -e "/${regExp}\ /p" ${inputFile} > ${tmpDir}/optpkg.temp
# strip out "OptionalPackageDependencies PackageName :"
# this leaves "<dep1> .... ;"
tempDeps=`sed -e "s/${regExp}\ //" ${tmpDir}/optpkg.temp`
for foo in ${tempDeps%' ;'} ; do
# Prevent duplicate entries of the same dependency package.
if ! ContainsSubstring "${nonRepeatingDeps} " "${foo} " ; then
nonRepeatingDeps="$foo $nonRepeatingDeps "
nonRepeatingDeps="${nonRepeatingDeps// / }"
fi
done
# Recursively get the dependencies of these dependencies.
for dep in ${tempDeps%' ;'} ; do
GetPackageDependencies "$dep"
done
}
function IsPackageAndDepsOkToInstall()
{
# IsPackageAndDepsOkToInstall <pkg>
if ContainsSubstring "${packageIgnoreList}" "${1}"; then
#echo "...warning: ${1} cannot be installed"
return 1
fi
for foo in ${nonRepeatingDeps} ; do
if ContainsSubstring "${packageIgnoreList}" "${foo}"; then
#echo "...warning: ${1} cannot be installed because of ${foo}"
return 1
fi
done
return 0
}
function BuildListOfRequestedPackages()
{
if [ "$1" = '-a' ] || [ "$1" = '-s' ]; then
shift
fi
while [ $# -gt 0 ]; do
local lowerCase=`echo $1 | tr '[A-Z]' '[a-z]'`
wantsToInstall="${wantsToInstall} $lowerCase"
shift
done
}
function AddPackages()
{
# AddPackages
# If one or more packages can be installed, do it.
if BuildFinalListOfPackagesToInstall ; then
for package in ${packagesToInstall} ; do
# output the "if [ IsOptionalHaikuImagePackageAdded..." code block
local regExp="if\ \[\ IsOptionalHaikuImagePackageAdded\ ${package}\ "
for inputFile in OptionalPackages OptionalLibPackages ; do
sed -n "/^$regExp/,/^\}/p" "${baseDir}/${inputFile}" >> ${tmpDir}/optpkg.jam
done
done
ConvertJamToBash "${tmpDir}/optpkg.jam"
rm "${tmpDir}/optpkg.jam"
CreateInstallerScript
sh ${tmpDir}/install-optpkg.sh
exitcode=$?
if [ $exitcode -gt 0 ]; then
ErrorExit "... something went wrong when installing packages."
fi
rm ${tmpDir}/install-optpkg.sh
# update files to account for the newly installed packages
alreadyInstalled="${alreadyInstalled} ${packagesToInstall} "
RecordInstalledPackages
GeneratePackageNames
echo "... done."
fi
}
function BuildFinalListOfPackagesToInstall()
{
# BuildFinalListOfPackagesToInstall
packagesToInstall=""
proceedWithInstallation=false
for desiredPackage in ${wantsToInstall}; do
if IsPackageNameValid $desiredPackage ; then
for item in ${availablePackages[${desiredPackage}]} ; do
if ! ContainsSubstring "${packagesToInstall}" "${item}" ; then
packagesToInstall="${packagesToInstall} ${item}"
fi
done
proceedWithInstallation=true
fi
done
# pad the variable
packagesToInstall="${packagesToInstall} "
# remove entries that are already installed
for skip in ${alreadyInstalled}; do
packagesToInstall=${packagesToInstall/"${skip} "/}
done
# strip double spaces
packagesToInstall=${packagesToInstall/" "/" "}
if ! [ ${#packagesToInstall} -gt 1 ]; then
echo "... no packages need to be installed."
echo ""
echo "If you wish to re-install a package, run these two commands"
echo " rm ${baseDir}/OptionalPackageNames"
echo " open $installedPackagesFile"
echo "and delete the line containing the package name(s)."
echo ""
proceedWithInstallation=false
fi
if ! $proceedWithInstallation ; then
echo 'Not proceeding with installation.'
return 1
fi
echo "To be installed: ${packagesToInstall}"
return 0
}
function IsPackageNameValid()
{
# IsPackageNameValid <name>
for name in ${availablePackagesKeys} ; do
if [ "$1" == "$name" ] ; then
return 0
fi
done
return 1
}
function RecordInstalledPackages()
{
echo -e ${alreadyInstalled} | tr '\ ' '\n' | sort > ${installedPackagesFile}
}
function ConvertJamToBash()
{
# ConvertJamToBash <input file>
# The main Jam-to-Bash conversion function.
local inputFile=$1
declare -a generatedBash
countGenBashLine=0
# Parse out some variable declarations
# TODO : add these following variables to the CreateInstallerScript
# TODO : parse HAIKU_ICU_GCC_2_PACKAGE
#local regExp='/^HAIKU_ICU_GCC_2_PACKAGE/p'
#icuGcc2PkgLine=`sed -n -e "$regExp" ${baseDir}/BuildFeatures`
#ConvertVariableDeclarationLines "$regExp" 'icuGcc2PkgLine'
# TODO : parse HAIKU_ICU_GCC_4_PACKAGE
#local regExp='/^HAIKU_ICU_GCC_4_PACKAGE/p'
#icuGcc4PkgLine=`sed -n -e "$regExp" ${baseDir}/BuildFeatures`
#ConvertVariableDeclarationLines "$regExp" 'icuGcc4PkgLine'
# TODO : parse HAIKU_ICU_DEVEL_PACKAGE
#local regExp='/^HAIKU_ICU_DEVEL_PACKAGE/p'
#icuDevelPkgLine=`sed -n -e "$regExp" ${baseDir}/BuildFeatures`
#ConvertVariableDeclarationLines "$regExp" 'icuDevelPkgLine'
# TODO : fix the regex
local regExp="/^\s*HAIKU_OPENSSL_PACKAGE = .*-gcc${HAIKU_GCC_VERSION[1]}-/p"
sslPkgLine=`sed -n -e "$regExp" ${baseDir}/BuildFeatures`
ConvertVariableDeclarationLines "$regExp" 'sslPkgLine'
# TODO : fix the regex
local regExp='/^HAIKU_OPENSSL_URL/p'
sslUrlLine=`sed -n -e "$regExp" ${baseDir}/BuildFeatures`
ConvertVariableDeclarationLines "$regExp" 'sslUrlLine'
# TODO : fix the regex
local regExp='/^HAIKU_WEBKIT_FILE/p'
webkitFileLine=`sed -n -e "$regExp" ${baseDir}/BuildFeatures`
ConvertVariableDeclarationLines "$regExp" 'webkitFileLine'
local regExp='/^local\ baseURL/p'
urlLine=`sed -n -e "$regExp" ${baseDir}/OptionalPackages`
urlLine=${urlLine/local\ /''}
ConvertVariableDeclarationLines "$regExp" 'urlLine'
# Convert the easy bits.
while read line ; do
line=${line/'Echo'/'echo'}
# TODO: add support for converting for loops.
# will need to introduce curly brace counting
ConvertIfStatements "$line"
ConvertVariables "$line"
#ReplaceComparators "$line"
line=${line/"IsOptionalHaikuImagePackageAdded"/'"SomeText" !='}
generatedBash[$countGenBashLine]=${line}
((countGenBashLine++))
done < ${tmpDir}/optpkg.jam
# output stage 1 generated code
local i=0
while [ $i -lt $countGenBashLine ] ; do
echo ${generatedBash[$i]} >> ${tmpDir}/optpkg.stage1
((i++))
done
# This converts multi-line jam statements into a single line.
# --- Start awk ---
awk '
/InstallOptionalHaikuImagePackage/,/\;/{
isRule=1;
if($0~/\;/) ORS="\n";
else ORS=" "; print
}
/AddSymlinkToHaikuImage/,/\;/{
isRule=1;
if($0~/\;/) ORS="\n";
else ORS=" "; print
}
/AddUserToHaikuImage/,/\;/{
isRule=1;
if($0~/\;/) ORS="\n";
else ORS=" "; print
}
/AddExpanderRuleToHaikuImage/,/\;/{
isRule=1;
if($0~/\;/) ORS="\n";
else ORS=" "; print
}
/Exit/,/\;/{
isRule=1;
if($0~/\;/) ORS="\n";
else ORS=" "; print
}
{
if($1!='InstallOptionalHaikuImagePackage' && isRule!=1 && $1!="\;")
print $0
}
{ isRule=0; }
' ${tmpDir}/optpkg.stage1 > ${tmpDir}/optpkg.stage2 2>/dev/null
# --- End awk ---
rm ${tmpDir}/optpkg.stage1
}
function ConvertVariableDeclarationLines()
{
# ConvertVariableDeclarationLines <regex> <variable>
# One of the Jam-to-Bash conversion functions.
# Jam lines that define variables need to be parsed differently.
eval local input='$'"$2"
local regex="$1"
local _outvar="$2"
input=${input/\ =\ /=}
input=${input/\;/''}
input=${input//\(/'{'}
input=${input//\)/'}'}
eval $_outvar="'$input'"
}
function ConvertIfStatements()
{
# ConvertIfStatements <line>
# One of the Jam-to-Bash conversion functions.
line=${line//'} else {'/'else '}
line=${line//'} else if '/'elif '}
if ContainsSubstring "$line" "if " ; then
if ! ContainsSubstring "$line" "if [" ; then
line=${line/'if '/'if [ '}
fi
if ContainsSubstring "$line" '] {' ; then
line=${line/'{'/' ; then'}
elif ContainsSubstring "$line" '{' ; then
line=${line/'{'/' ] ; then'}
fi
for compound in '&&' '||' ; do
if ContainsSubstring "$line" "$compound" ; then
line=${line/"$compound"/"] $compound ["}
fi
done
ReplaceComparators "$line"
fi
# Assume all remaining closing braces are part of if statements
line=${line/'}'/'fi'}
}
function ConvertVariables()
{
# ConvertVariables
# One of the Jam-to-Bash conversion functions.
# NOTE: jam's variables are normally '$(VARIABLE)'. \n
# The issue is with '(' and ')', so let's replace them globally.
if ContainsSubstring "$line" '$(' ; then
line=${line//'('/'{'}
line=${line//')'/'}'}
fi
}
function ReplaceComparators()
{
# ReplaceComparators <line>
# One of the Jam-to-Bash conversion functions.
# Preserve string comparators for TARGET_ARCH.
if ! ContainsSubstring "$line" 'TARGET_ARCH' ; then
line=${line//'>='/'-ge'}
line=${line//'<='/'-le'}
line=${line//'>'/'-gt'}
line=${line//'<'/'-lt'}
line=${line//'!='/'-ne'}
line=${line//'='/'-eq'}
fi
}
function DisplayUsage()
{
echo -e "$DISCLAIMER"
echo -e "$USAGE"
}
function RemoveCachedFiles()
{
# RemoveCachedFiles
echo "Removing cached files ..."
if [ -e ${baseDir}/OptionalPackageNames ]; then
rm ${baseDir}/OptionalPackageNames
fi
# Unset variables, which prevents duplicate entries.
declare -A availablePackages
declare availablePackagesKeys=""
# Reinitialize
Init
}
function ListPackages()
{
# ListPackages
echo ""
echo "Optional Packages that have been installed:"
echo ${alreadyInstalled}
echo ""
echo ""
echo "Installable Optional Packages:"
# single line:
echo ${availablePackagesKeys}
# one per line:
#for package in ${availablePackagesKeys} ; do
# echo ${package}
#done
}
# If no arguments were passed to the script, display its usage and exit.
if [ "$#" -lt 1 ] ; then
DisplayUsage
exit 0
else
Init
fi
# Support `installoptionalpackage <pkg> <pkg> ...`
if [ "$1" != '-f' ] && [ "$1" != '-l' ] && [ "$1" != '-h' ] \
&& [ "$1" != '-s' ]; then
BuildListOfRequestedPackages $@
AddPackages
exit 0
fi
# Parse the arguments given to the script.
while getopts "as:fhl" opt; do
case $opt in
a)
BuildListOfRequestedPackages $@
AddPackages
exit 0
;;
f)
RemoveCachedFiles
ListPackages
exit 0
;;
h)
DisplayUsage
exit 0
;;
l)
ListPackages
exit 0
;;
s)
BuildListOfRequestedPackages $@
BuildFinalListOfPackagesToInstall
exit 0
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done