Ticket #5315: installoptionalpackage-Improvements.patch
File installoptionalpackage-Improvements.patch, 17.3 KB (added by , 14 years ago) |
---|
-
data/bin/installoptionalpackage
1 #!/bin/ sh1 #!/bin/bash 2 2 # 3 # Copyright (c) 2009 Haiku Inc. All rights reserved.3 # Copyright (c) 2009-2010 Haiku Inc. All rights reserved. 4 4 # Distributed under the terms of the MIT License. 5 5 # 6 6 # Authors: … … 20 20 # http://dev.haiku-os.org/wiki/PackageManagerIdeas 21 21 # http://dev.haiku-os.org/wiki/PackageFormat 22 22 # 23 # Usage: ./installoptionalpackage [-l] [-a ]23 # Usage: ./installoptionalpackage [-l] [-a "<pkg> [<pkg> ...]"] 24 24 # -l List installable packages 25 # -a Add a package and all of itsdependencies25 # -a Add one or more packages and all dependencies 26 26 27 27 28 declare - a packagesToInstall29 declare -a availablePackages28 declare -A availablePackages 29 declare availablePackagesKeys="" 30 30 # Some Packages cannot be installed, 31 31 # as they require either the source code or compiled binaries 32 declare -a packageIgnoreList=( 'Bluetooth' 'Development' 'DevelopmentMin'\33 'DevelopmentBase' 'NetFS' 'P7zip' 'UserlandFS' 'Welcome') 32 declare packageIgnoreList='Bluetooth Development DevelopmentMin \ 33 DevelopmentBase P7zip UserlandFS Welcome Wifi-ipw2100+fw Wifi-iprowifi2200+fw' 34 34 35 35 36 36 function CreateInstallerScript() … … 40 40 41 41 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 42 42 cat << EOF > ${tmpDir}/install-optpkg.sh 43 #!/bin/ sh43 #!/bin/bash 44 44 45 45 tmpDir=${tmpDir} 46 46 HAIKU_GCC_VERSION[1]=${HAIKU_GCC_VERSION[1]} … … 143 143 done 144 144 echo "Unzipping \$zipFile ..." 145 145 unzipDir="\${dirTokens}" 146 unzip -q - d "\$unzipDir" "\$zipFile"147 # TODO should .OptionalPackageDescription be added to AboutSystem?146 unzip -q -o -d "\$unzipDir" "\$zipFile" 147 148 148 if [ -f '/boot/.OptionalPackageDescription' ] ; then 149 149 rm '/boot/.OptionalPackageDescription' 150 150 fi … … 170 170 local linkName="\${functionArgs[2]}" 171 171 TrimLeadingSpace linkName 172 172 TrimEndingSpace linkName 173 173 174 mkdir -p "${dirTokens}" 175 174 176 if [ "\${linkName}" == '' ] ; then 175 177 ln -sf "\${linkTarget}" -t "\${dirTokens}" 176 178 else … … 225 227 } 226 228 227 229 230 function ContainsSubstring() 231 { 232 # ContainsSubstring <stringToLookIn> <stringToLookFor> 233 local string="$1" 234 local substring="$2" 235 local newString=${string/${substring}/''} 236 if [ ${#string} -eq `expr ${#newString} + ${#substring}` ] ; then 237 return 0 238 fi 239 return 1 240 } 241 242 243 function Init() 244 { 245 246 # Set up some directory paths 247 baseDir=`finddir B_COMMON_DATA_DIRECTORY`/optional-packages 248 tmpDir=`finddir B_COMMON_TEMP_DIRECTORY` 249 libDir=`finddir B_SYSTEM_LIB_DIRECTORY` 250 251 # Make sure these files are empty. 252 echo "" > ${tmpDir}/optpkg.jam 253 echo "" > ${tmpDir}/optpkg.stage1 254 255 if ! [ -d ${baseDir} ] ; then 256 mkdir -p ${baseDir} 257 fi 258 259 # Retreive the necessary jam files from svn. 260 local buildFiles="OptionalPackages OptionalPackageDependencies \ 261 OptionalBuildFeatures" 262 for file in ${buildFiles} ; do 263 GetBuildFile ${file} 264 done 265 266 DetectSystemConfiguration 267 ReadPackageNamesIntoMemory 268 } 269 270 228 271 function GetBuildFile() 229 272 { 230 273 # GetBuildFile <file> 231 # Downloads files from Haiku's svn 232 if ! [ -f ${baseDir}/${1} ] ; then 233 echo "Fetching ${1} ..." 274 # Downloads files from Haiku's svn 275 local buildfile="$1" 276 if ! [ -f ${baseDir}/${buildfile} ] ; then 277 echo "Fetching ${buildfile} ..." 234 278 cd ${baseDir} 235 279 local baseURL=http://dev.haiku-os.org/export/ 236 280 local revision=`uname -v | awk '{print $1}' | sed -e 's/r//'` 237 wget ${baseURL}${revision}/haiku/trunk/build/jam/${file} 2>&1 > /dev/null 281 local url="${baseURL}${revision}/haiku/trunk/build/jam/${buildfile}" 282 wget -nv ${url} 2>&1 > /dev/null 238 283 fi 239 284 } 240 285 241 286 242 function GeneratePackageNames()287 function DetectSystemConfiguration() 243 288 { 244 # GeneratePackageNames 245 # Creates a file containing available package names 246 local outfile="${baseDir}/OptionalPackageNames" 247 248 if ! [ -f ${outfile} ] ; then 249 echo "Generating a list of Package Names ..." 250 251 touch ${outfile} 252 local regExp='/^if\ \[\ IsOptionalHaikuImagePackageAdded/p' 253 sed -n -e "$regExp" ${baseDir}/OptionalPackages > ${outfile}.temp 254 while read line ; do 255 local pkg=`echo ${line} | awk '{print $4}'` 256 257 if ! IspackageIgnoreListed ${pkg} ; then 258 echo ${pkg} >> ${outfile} 259 fi 260 261 done < ${outfile}.temp 262 rm ${outfile}.temp 263 fi 264 265 # read list into array 266 local count=0 267 while read line ; do 268 availablePackages[$count]=$line 269 ((count++)) 270 done < ${outfile} 289 # Determine which GCC we're running and if we're a hybrid 290 if [ -d "$libDir"/gcc4 ] ; then 291 HAIKU_GCC_VERSION[1]=2 292 isHybridBuild=1 293 elif [ -d "$libDir"/gcc2 ] ; then 294 HAIKU_GCC_VERSION[1]=4 295 isHybridBuild=1 296 elif [ -f "$libDir"/libsupc++.so ] ; then 297 HAIKU_GCC_VERSION[1]=4 298 isHybridBuild=0 299 else 300 HAIKU_GCC_VERSION[1]=2 301 isHybridBuild=0 302 fi 303 304 # Determine the Architecture. 305 if [ `uname -m` == "BePC" ] ; then 306 TARGET_ARCH='x86' 307 fi 271 308 } 272 309 273 310 274 function IspackageIgnoreListed()311 function ReadPackageNamesIntoMemory() 275 312 { 276 # IspackageIgnoreListed <pkg> 277 # Check if this package or any of its deps cannot be installed 313 local file="${baseDir}/OptionalPackageNames" 314 if ! [ -f ${file} ] ; then 315 GeneratePackageNames 316 fi 278 317 279 GetPackageDependencies ${1} 280 281 local mustIgnore=1 282 for ignoreThisPackage in ${packageIgnoreList[*]} ; do 283 if [ ${1} == ${ignoreThisPackage} ] ; then 284 mustIgnore=0 285 break 286 else 287 for dep in ${tempDeps} ; do 288 if [ ${dep} == ${ignoreThisPackage} ] ; then 289 mustIgnore=0 290 break 291 fi 292 done 293 fi 294 done 295 return $mustIgnore 318 # read list into associative array 319 while read line ; do 320 local pkg=`echo ${line} | awk '{print $1}'` 321 local pkgDeps=${line/':'/} 322 availablePackages[${pkg}]="${pkgDeps}" 323 availablePackagesKeys="${availablePackagesKeys} ${pkg}" 324 done < ${file} 296 325 } 297 326 298 327 299 function IsPackageNameValid()328 function GeneratePackageNames() 300 329 { 301 # IsPackageNameValid <name>302 if IspackageIgnoreListed "$1" ; then303 echo "Due to limitations, the package \"$1\" cannot be installed."304 exit 1305 fi330 # GeneratePackageNames 331 # Creates a file containing available package names 332 # Each line shows a pakage and all of its recrusive dependencies 333 # "<pkg> : <dep1> <dep2> ..." 334 echo "Generating a list of Package Names ..." 306 335 307 local packageExists=1 308 for name in ${availablePackages[*]} ; do 309 if [ "$1" == "$name" ] ; then 310 packageExists=0 311 packagesToInstall[0]=${1} 312 GetPackageDependencies "$1" 313 314 # move deps into packagesToInstall 315 if [ ${#tempDeps} -gt 0 ] ; then 316 for dep in ${tempDeps} ; do 317 if [ ';' == "$dep" ] ; then 318 break 319 fi 320 gPDi=${#packagesToInstall[@]} 321 ((gPDi++)) 322 packagesToInstall[$gPDi]=${dep} 323 GetPackageDependencies ${dep} 324 done 325 fi 326 echo "Packages to be installed:" 327 echo " ${packagesToInstall[*]}" 328 return 0 336 local file="${baseDir}/OptionalPackageNames" 337 touch ${file} 338 339 local regExp='/^if\ \[\ IsOptionalHaikuImagePackageAdded/p' 340 sed -n -e "$regExp" ${baseDir}/OptionalPackages > ${file}.temp 341 while read line ; do 342 # in each non-filtered line, the 4th word is the optional package 343 local pkg=`echo ${line} | awk '{print $4}'` 344 345 nonRepeatingDeps="" 346 GetPackageDependencies "$pkg" 347 if IsPackageAndDepsOkToInstall ${pkg} ; then 348 echo "${pkg} : ${nonRepeatingDeps}" >> ${file} 329 349 fi 330 done 331 332 if [ $packageExists -gt 0 ] ; then 333 echo "Package \"$1\" does not exist." 334 echo '' 335 exit 1 336 fi 337 return 1 350 351 done < ${file}.temp 352 rm ${file}.temp 338 353 } 339 354 340 355 341 356 function GetPackageDependencies() 342 357 { 343 # getPackageDependecies <pkg> 344 # parse OptionalPackageDependencies for <pkg>'s dependencies 345 local regExp="^OptionalPackageDependencies\ ${1}" 358 # GetPackageDependencies <pkg> 359 360 # parse OptionalPackageDependencies for the single line that defines 361 # this optional package's dependencies. 362 local regExp="^OptionalPackageDependencies\ ${1}\ \:" 346 363 local inputFile="${baseDir}/OptionalPackageDependencies" 364 365 # print that single line 347 366 sed -n -e "/${regExp}\ /p" ${inputFile} > ${tmpDir}/optpkg.temp 348 tempDeps=`sed -e "s/${regExp}\ :\ //" ${tmpDir}/optpkg.temp`349 rm ${tmpDir}/optpkg.temp350 }351 352 353 function ContainsSubstring()354 {355 # ContainsSubstring <stringToLookIn> <stringToLookFor>356 local newString=${1/${2}/''}357 if [ ${#1} -eq `expr ${#newString} + ${#2}` ] ; then358 return 0359 fi360 return 1361 }362 363 function ReplaceComparators()364 {365 # ReplaceComparators <line>366 # One of the Jam-to-Bash conversion functions.367 367 368 # Preserve string comparators for TARGET_ARCH. 369 if ! ContainsSubstring "$line" 'TARGET_ARCH' ; then 370 line=${line//'>='/'-ge'} 371 line=${line//'<='/'-le'} 372 line=${line//'>'/'-gt'} 373 line=${line//'<'/'-lt'} 374 line=${line//'!='/'-ne'} 375 fi 368 # strip out "OptionalPackageDependencies PackageName :" 369 # this leaves "<dep1> .... ;" 370 tempDeps=`sed -e "s/${regExp}\ //" ${tmpDir}/optpkg.temp` 371 372 for foo in ${tempDeps%' ;'} ; do 373 # Prevent duplicate entries of the same dependency package. 374 if ! ContainsSubstring "${nonRepeatingDeps} " "${foo} " ; then 375 nonRepeatingDeps="$foo $nonRepeatingDeps " 376 nonRepeatingDeps="${nonRepeatingDeps// / }" 377 fi 378 done 379 380 # Recursively get the dependencies of these dependencies. 381 for dep in ${tempDeps%' ;'} ; do 382 GetPackageDependencies "$dep" 383 done 384 376 385 } 377 386 378 387 379 function ConvertVariables()388 function IsPackageAndDepsOkToInstall() 380 389 { 381 # ConvertVariables 382 # One of the Jam-to-Bash conversion functions. 383 # NOTE: jam's variables are normally '$(VARIABLE)'. \n 384 # The issue is with '(' and ')', so let's replace them globally. 385 386 if ContainsSubstring "$line" '$(' ; then 387 line=${line//'('/'{'} 388 line=${line//')'/'}'} 390 # IsPackageAndDepsOkToInstall <pkg> 391 if ContainsSubstring "${packageIgnoreList}" "${1}"; then 392 echo "...warning: ${1} cannot be installed" 393 return 1 389 394 fi 395 for foo in ${nonRepeatingDeps} ; do 396 if ContainsSubstring "${packageIgnoreList}" "${foo}"; then 397 echo "...warning: ${1} cannot be installed because of ${foo}" 398 return 1 399 fi 400 done 401 return 0 390 402 } 391 403 392 404 393 function ConvertVariableDeclarationLines()405 function AddPackage() 394 406 { 395 # ConvertVariableDeclarationLines <regex> <variable> 396 # One of the Jam-to-Bash conversion functions. 397 # Jam lines that define variables need to be parsed differently. 398 eval local input='$'"$2" 399 local regex="$1" 400 local _outvar="$2" 407 # AddPackage <name> 408 packagesToInstall="" 409 proceedWithInstallation=false 401 410 402 input=${input/\ =\ /=} 403 input=${input/\;/''} 404 input=${input//\(/'{'} 405 input=${input//\)/'}'} 411 for desiredPackage in ${1}; do 412 if IsPackageNameValid $desiredPackage ; then 413 for item in ${availablePackages[${desiredPackage}]} ; do 414 if ! ContainsSubstring "${packagesToInstall}" "${item}" ; then 415 packagesToInstall="${packagesToInstall} ${item}" 416 fi 417 done 418 proceedWithInstallation=true 419 fi 420 done 406 421 407 eval $_outvar="'$input'" 422 # If one or more packages can be installed, do it. 423 if $proceedWithInstallation ; then 424 echo "To be installed: ${packagesToInstall}" 425 426 for package in ${packagesToInstall} ; do 427 # output the "if [ IsOptionalHaikuImagePackageAdded..." code block 428 local regExp="if\ \[\ IsOptionalHaikuImagePackageAdded\ ${package}" 429 local inputFile="${baseDir}/OptionalPackages" 430 sed -n "/^$regExp/,/^\}/p" ${inputFile} >> ${tmpDir}/optpkg.jam 431 done 432 433 ConvertJamToBash "${tmpDir}/optpkg.jam" 434 rm "${tmpDir}/optpkg.jam" 435 CreateInstallerScript 436 sh ${tmpDir}/install-optpkg.sh 437 rm ${tmpDir}/install-optpkg.sh 438 fi 408 439 } 409 440 410 441 411 412 function ConvertIfStatements() 442 function IsPackageNameValid() 413 443 { 414 # ConvertIfStatements <line> 415 # One of the Jam-to-Bash conversion functions. 416 line=${line//'} else {'/'else '} 417 line=${line//'} else if '/'elif '} 418 if ContainsSubstring "$line" "if " ; then 419 if ! ContainsSubstring "$line" "if [" ; then 420 line=${line/'if '/'if [ '} 444 # IsPackageNameValid <name> 445 for name in ${availablePackagesKeys} ; do 446 if [ "$1" == "$name" ] ; then 447 return 0 421 448 fi 422 423 if ContainsSubstring "$line" '] {' ; then 424 line=${line/'{'/' ; then'} 425 elif ContainsSubstring "$line" '{' ; then 426 line=${line/'{'/' ] ; then'} 427 fi 428 429 for compound in '&&' '||' ; do 430 if ContainsSubstring "$line" "$compound" ; then 431 line=${line/"$compound"/"] $compound ["} 432 fi 433 done 434 fi 435 # Assume all remaining closing braces are part of if statements 436 line=${line/'}'/'fi'} 449 done 450 return 1 437 451 } 438 452 439 453 … … 513 527 } 514 528 515 529 516 function ListPackages()530 function ConvertVariableDeclarationLines() 517 531 { 518 # ListPackages 519 echo "Available Optional Packages:" 520 for package in ${availablePackages[*]} ; do 521 echo ${package} 522 done 532 # ConvertVariableDeclarationLines <regex> <variable> 533 # One of the Jam-to-Bash conversion functions. 534 # Jam lines that define variables need to be parsed differently. 535 eval local input='$'"$2" 536 local regex="$1" 537 local _outvar="$2" 538 539 input=${input/\ =\ /=} 540 input=${input/\;/''} 541 input=${input//\(/'{'} 542 input=${input//\)/'}'} 543 544 eval $_outvar="'$input'" 523 545 } 524 546 525 547 526 function AddPackage()548 function ConvertIfStatements() 527 549 { 528 # AddPackage <name> 529 if IsPackageNameValid $1 ; then 530 for package in ${packagesToInstall[*]} ; do 531 local regExp="if\ \[\ IsOptionalHaikuImagePackageAdded\ ${package}" 532 local inputFile="${baseDir}/OptionalPackages" 533 sed -n "/^$regExp/,/^\}/p" ${inputFile} >> ${tmpDir}/optpkg.jam 550 # ConvertIfStatements <line> 551 # One of the Jam-to-Bash conversion functions. 552 line=${line//'} else {'/'else '} 553 line=${line//'} else if '/'elif '} 554 if ContainsSubstring "$line" "if " ; then 555 if ! ContainsSubstring "$line" "if [" ; then 556 line=${line/'if '/'if [ '} 557 fi 558 559 if ContainsSubstring "$line" '] {' ; then 560 line=${line/'{'/' ; then'} 561 elif ContainsSubstring "$line" '{' ; then 562 line=${line/'{'/' ] ; then'} 563 fi 564 565 for compound in '&&' '||' ; do 566 if ContainsSubstring "$line" "$compound" ; then 567 line=${line/"$compound"/"] $compound ["} 568 fi 534 569 done 535 ConvertJamToBash "${tmpDir}/optpkg.jam"536 rm "${tmpDir}/optpkg.jam"537 CreateInstallerScript538 sh ${tmpDir}/install-optpkg.sh539 rm ${tmpDir}/install-optpkg.sh540 570 fi 571 # Assume all remaining closing braces are part of if statements 572 line=${line/'}'/'fi'} 541 573 } 542 574 543 575 544 function DisplayUsage()576 function ConvertVariables() 545 577 { 546 echo '' 547 echo 'Disclaimer:' 548 echo ' This is a temporary solution for installing OptionalPackages.' 549 echo ' In time, there will be an official package manager.' 550 echo " See these URL's for info on the in-development package manager." 551 echo ' http://dev.haiku-os.org/wiki/PackageManagerIdeas' 552 echo ' http://dev.haiku-os.org/wiki/PackageFormat' 553 echo '' 554 echo "Usage: $0 [-l] [-a]" 555 echo "-l List installable packages" 556 echo "-a Add a package and all of its dependencies" 557 echo '' 578 # ConvertVariables 579 # One of the Jam-to-Bash conversion functions. 580 581 # NOTE: jam's variables are normally '$(VARIABLE)'. \n 582 # The issue is with '(' and ')', so let's replace them globally. 583 if ContainsSubstring "$line" '$(' ; then 584 line=${line//'('/'{'} 585 line=${line//')'/'}'} 586 fi 558 587 } 559 588 560 589 561 function DetectSystemConfiguration()590 function ReplaceComparators() 562 591 { 563 # Determine which GCC we're running and if we're a hybrid 564 if [ -d "$libDir"/gcc4 ] ; then 565 HAIKU_GCC_VERSION[1]=2 566 isHybridBuild=1 567 elif [ -d "$libDir"/gcc2 ] ; then 568 HAIKU_GCC_VERSION[1]=4 569 isHybridBuild=1 570 elif [ -f "$libDir"/libsupc++.so ] ; then 571 HAIKU_GCC_VERSION[1]=4 572 isHybridBuild=0 573 else 574 HAIKU_GCC_VERSION[1]=2 575 isHybridBuild=0 592 # ReplaceComparators <line> 593 # One of the Jam-to-Bash conversion functions. 594 595 # Preserve string comparators for TARGET_ARCH. 596 if ! ContainsSubstring "$line" 'TARGET_ARCH' ; then 597 line=${line//'>='/'-ge'} 598 line=${line//'<='/'-le'} 599 line=${line//'>'/'-gt'} 600 line=${line//'<'/'-lt'} 601 line=${line//'!='/'-ne'} 576 602 fi 603 } 577 604 578 # Determine the Architecture. 579 if [ `uname -m` == "BePC" ] ; then 580 TARGET_ARCH='x86' 581 fi 605 606 function DisplayUsage() 607 { 608 cat << EOF 609 610 Disclaimer: 611 This is a temporary solution for installing OptionalPackages. 612 In time, there will be an official package manager. 613 See these URL's for information on the in-development package manager. 614 http://dev.haiku-os.org/wiki/PackageManagerIdeas 615 http://dev.haiku-os.org/wiki/PackageFormat 616 617 Usage: ./installoptionalpackage [-l] [-a "<pkg> [<pkg> ...]"] 618 -l List installable packages 619 -a Add one or more packages and all dependencies 620 621 EOF 582 622 } 583 623 584 function Init() 624 625 function ListPackages() 585 626 { 627 # ListPackages 628 echo "" 629 echo "" 630 echo "Available Optional Packages:" 586 631 587 # Set up some directory paths 588 baseDir=`finddir B_COMMON_DATA_DIRECTORY`/optional-packages 589 tmpDir=`finddir B_COMMON_TEMP_DIRECTORY` 590 libDir=`finddir B_SYSTEM_LIB_DIRECTORY` 591 592 # Make sure these files are empty. 593 echo "" > ${tmpDir}/optpkg.jam 594 echo "" > ${tmpDir}/optpkg.stage1 632 # single line: 633 echo ${availablePackagesKeys} 595 634 596 597 if ! [ -d ${baseDir} ] ; then 598 mkdir -p ${baseDir} 599 fi 600 601 # Retreive the necessary jam files from svn. 602 local buildFiles=( 'OptionalPackages' 'OptionalPackageDependencies' \ 603 'OptionalBuildFeatures') 604 for file in ${buildFiles[*]} ; do 605 GetBuildFile ${file} 606 done 607 608 DetectSystemConfiguration 609 GeneratePackageNames 635 # one per line: 636 #for package in ${availablePackagesKeys} ; do 637 # echo ${package} 638 #done 610 639 } 611 640 612 641 … … 622 651 while getopts "a:lh" opt; do 623 652 case $opt in 624 653 a) 625 AddPackage $OPTARG654 AddPackage "$OPTARG" 626 655 exit 0 627 656 ;; 628 657 h)