From e7660d9ccd5330bca286989f12a62638a3e09155 Mon Sep 17 00:00:00 2001 From: "Lucas C. Villa Real" Date: Mon, 2 Jan 2017 19:24:01 -0200 Subject: Rename main script. --- bin/InstallPackage-RPM | 508 ------------------------------------------------- 1 file changed, 508 deletions(-) delete mode 100755 bin/InstallPackage-RPM (limited to 'bin/InstallPackage-RPM') diff --git a/bin/InstallPackage-RPM b/bin/InstallPackage-RPM deleted file mode 100755 index 099f670..0000000 --- a/bin/InstallPackage-RPM +++ /dev/null @@ -1,508 +0,0 @@ -#!/bin/bash - -source ScriptFunctions -Import File -Import GoboLinux -Import Log -Import OptionParser - -### Options ################################################################### - -scriptDescription="Install RPM and DEB packages on GoboLinux." -scriptCredits="Copyright (C) Lucas C. Villa Real, 2016,2017 - Released under the GNU GPL." -helpOnNoArguments=yes -scriptUsage=" [file.rpm]" -scriptExample="xispita-2.0.3-1.x86_64.rpm" - -Add_Option_Entry "n" "app-name" "Override program name" -Add_Option_Entry "e" "version-number" "Override program version number" -Add_Option_Entry "l" "symlink" "If symlinks should be created and wether they should be forced on conflicts." "yes" "yes no force" -Add_Option_Boolean "W" "no-web" "Do not search the web to resolve dependencies." -Parse_Options "$@" - -### Functions ################################################################# - -function fetch_package() { - local inputfile="$1" - local filename=$(basename "$inputfile") - if Is_URL "$inputfile" - then - if wget --help | grep -q "no-check-certificate" - then wget_cmd="wget --no-check-certificate" - else wget_cmd="wget" - fi - Quiet ${wget_cmd} -c "${inputfile}" -O "${goboTemp}/${filename}" || Die "Error downloading package." - echo "${goboTemp}/${filename}" - else - echo "$inputfile" - fi -} - -function uncompress_package() { - local inputfile="$1" - thirdparty_uncompress "$inputfile" -} - -function determine_flattening_level() { - local rootdirs="bin$\|sbin$\|lib$\|lib64$\|libexec$\|include$\|share$" - local filenames=$(for i in "${inputfiles[@]}"; do thirdparty_filenames $i; done) - - Log_Verbose "$filenames" - if echo "$filenames" | grep -q "/opt/$rootdirs" - then - # 1-level /opt hierarchy - echo "1" - elif echo "$filenames" | grep -q "/opt/[^/]*/$rootdirs" - then - # 2-level /opt hierarchy - echo "2" - elif echo "$filenames" | grep -q "/opt" - then - # Get the longest common prefix among the $filenames list that starts - # with "/opt" and then determine how many path levels we have there. - local commonprefix=$(echo "$filenames" | grep "/opt" | sed -e 'N;s/^\(.*\).*\n\1.*$/\1\n\1/;D') - local numslashes=$(echo "$commonprefix" | grep -o "/" | wc -l) - let numslashes=numslashes-1 - if [ "$numslashes" = 1 ] - then - Log_Verbose "Package seems to have a 1-level /opt structure" - echo "1" - elif [ "$numslashes" = 2 ] - then - Log_Verbose "Package seems to have a 2-level /opt structure" - echo "2" - else - Log_Error "Could not determine this package's /opt structure, assuming 2-level" - echo "2" - fi - fi -} - -function flatten_package() { - local inputfile="$1" - - Log_Normal "Flattening directory structure." - - function create_opt_links() { - local vendordir="$1" - local unmanagedopt="Resources/Unmanaged/opt" - for pkgdir in $(basename --multiple ./opt/$vendordir/*) - do - mkdir ${verbose} -p "${unmanagedopt}/$vendordir/$pkgdir" - if [ -h "/opt/$vendordir/$pkgdir" ] - then - Log_Error "Too many programs are attempting to populate /opt/$vendordir/$pkgdir" - Log_Error "This feature is not supported by InstallPackage-RPM at this time." - continue - fi - for optfile in $(basename --multiple ./opt/$vendordir/$pkgdir/*) - do - if [ ! -e "${unmanagedopt}/$vendordir/$pkgdir/$optfile" ] - then - ln ${verbose} -fs $target/$optfile "${unmanagedopt}/$vendordir/$pkgdir/$optfile" - fi - done - done - } - - function flatten_opt_1_level() { - # Flatten 1-level dir: opt/pkgname/{bin,sbin,...} - cp ${verbose} -a ./opt/*/* . - create_opt_links "" - realpath ./opt/* | sed "s,$(realpath $PWD),,g" >> Resources/UnmanagedFiles - } - - function flatten_opt_2_levels() { - # Flatten 2-levels dir: opt/vendorname/pkgname/{bin,sbin,...} - cp ${verbose} -a ./opt/*/*/* . - for vendordir in $(basename --multiple ./opt/*) - do - create_opt_links "$vendordir" - done - realpath ./opt/*/* | sed "s,$(realpath $PWD),,g" >> Resources/UnmanagedFiles - } - - if [ -d "./usr" ] - then - cp ${verbose} -a ./usr/* . - rm -rf -- ./usr - fi - if [ -d "./etc" ] - then - mkdir -p Resources/Defaults/Settings - mv ${verbose} ./etc/* Resources/Defaults/Settings - rm -rf -- ./etc - fi - if [ -d "./lib64" ] - then - Quiet rmdir lib - if [ ! -d "./lib" ] - then mv ./lib64 lib - else cp -a ./lib64/* ./lib/ - fi - rm -rf ./lib64 - fi - if [ -d "./var" ] - then - mkdir -p Resources/Unmanaged/$goboVariable - find ./var | sed "s,./var,$goboVariable,g" >> Resources/UnmanagedFiles - mv ${verbose} ./var/* Resources/Unmanaged/$goboVariable - rm -rf -- ./var - fi - if [ -d "./opt" ] - then - # Prevent the creation of backlinks to directories that would be pruned later on - find share -type d | xargs rmdir -p --ignore-fail-on-non-empty - rmdir * 2> /dev/null - mkdir -p Resources/Unmanaged/opt - if [ "$flatteninglevel" = "1" ] - then - Log_Verbose "Flattening 1-level /opt directory" - flatten_opt_1_level - elif [ "$flatteninglevel" = "2" ] - then - Log_Verbose "Flattening 2-level /opt directory" - flatten_opt_2_levels - fi - rm -rf -- ./opt - fi - if [ -e Resources/UnmanagedFiles ] - then - # If multiple RPM files are being merged, then ensure we have no dups - cat Resources/UnmanagedFiles | sort -n | uniq > x && mv x Resources/UnmanagedFiles - fi - rmdir * 2> /dev/null -} - -function is_inputfile() { - local dependency="$1" - local pkgname=$(echo "$dependency" | cut -d'(' -f1 | awk {'print $1'}) - printf "%s\n" "${inputnames[@]}" | grep -q "^${pkgname}$" && return 0 - return 1 -} - -function populate_dependencies() { - local inputfile="$1" - thirdparty_dependencies "$inputfile" | while read dependency - do - if echo "$dependency" | grep -q "^/" - then - depinfo=$(take_dependency_from_path "$inputfile" "$dependency" "") - if [ "$depinfo" ] - then echo "$depinfo" - else echo "# Unresolved path-based dependency: $dependency" - fi - elif echo "$dependency" | grep -q "^lib.*\.so*\|.*\.so\.*" - then - libname=$(echo "$dependency" | cut -d'(' -f1) - wantedsymbol=$(echo "$dependency" | cut -d'(' -f2 | cut -d')' -f1) - depinfo=$(take_dependency_from_path "$inputfile" "$goboLibraries/$libname" "$wantedsymbol") - if [ "$depinfo" ] - then echo "$depinfo" - else echo "# Unresolved path-based library dependency: $dependency" - fi - elif is_basic_symbol "$dependency" - then - Log_Verbose "Skipping basic symbol: $dependency" - elif is_inputfile "$dependency" - then - Log_Verbose "Skipping dependency passed as input file: $dependency" - else - depinfo=$(lookup_pkgname "$dependency") - if [ "$depinfo" ] - then echo "$depinfo" - else echo "# Unresolved dependency: $dependency" - fi - fi - done -} - -function populate_resources() { - local inputfile="$1" - local arch=$(thirdparty_arch "$inputfile") - local description=$(thirdparty_description "$inputfile") - local release=$(thirdparty_release "$inputfile") - local distro=$(thirdparty_distribution "$inputfile") - - Log_Normal "Populating Resources." - mkdir -p Resources - - if [ "$arch" ] - then echo "$arch" > Resources/Architecture - else echo "$(uname -m)" > Resources/Architecture - fi - echo "$release" > Resources/Revision - - # Note that we never truncate neither Resources/PackageSource nor - # Resources/Description or Resources/Dependencies. This is to - # enable the installation of multiple RPM/DEB files under the same - # /Programs entry while keeing metadata of all the original files - # around. - - [ -e Resources/PackageSource ] && echo >> Resources/PackageSource - echo "[File] $(basename $inputfile)" >> Resources/PackageSource - echo "[Distribution] $distro" >> Resources/PackageSource - - if [ "$description" ] - then - [ -e Resources/Description ] && echo "" >> Resources/Description - echo "[Name] $(thirdparty_name $inputfile)" >> Resources/Description - echo "[Summary] $(thirdparty_summary $inputfile)" >> Resources/Description - echo "[License] $(thirdparty_license $inputfile)" >> Resources/Description - echo "[Description] $(thirdparty_description $inputfile)" >> Resources/Description - echo "[Homepage] $(thirdparty_url $inputfile)" >> Resources/Description - fi - - Log_Normal "Processing dependencies." - alldeps=$(mktemp ThirdPartyInstaller.XXXXXXXXXX) - populate_dependencies "$inputfile" >> Resources/Dependencies - cat Resources/Dependencies | sort -n | uniq > "$alldeps" - cat "$alldeps" > Resources/Dependencies - rm -f -- "$alldeps" -} - -function lookup_symbol() { - local depname="$1" - local testversion="$2" - local arch="$3" - local symbol="$4" - local testarch=$(cat "$goboPrograms/$depname/$testversion/Resources/Architecture" 2> /dev/null) - - if [ "$testarch" ] && [ "$testarch" = "$arch" ] - then - Log_Verbose "Looking for symbol $symbol on $goboPrograms/$depname/$testversion/$path" - if nm "$goboPrograms/$depname/$testversion/$path" 2> /dev/null | grep --max-count=1 -q "$symbol" - then - Log_Verbose "Match: $depname $testversion" - echo "$depname $testversion" - return 0 - fi - fi - return 1 -} - -function take_dependency_from_path() { - # TODO since $2 may come in the form '/usr/lib/libfoo >= version', we have to pick the - # path from the first part of the string. Right now we're using awk to get it, but that - # will not work if the dependency path contains spaces. - - local inputfile="$1" - local originalpath=$(echo "$2" | awk '{print $1}') - local path=$(echo "$originalpath" | sed 's,/usr,,g') - local symbol="$3" - local fullpath="$(readlink -f $path)" - local arch=$(thirdparty_arch "$inputfile") - local distro=$(thirdparty_distribution "$inputfile") - - local depname= - local depversion= - - if echo "$fullpath" | grep -q "^${goboPrograms}" - then - # If given, we search for the presence of @symbol on the given target file. - # We iterate over different installations of the same program looking for - # that symbol. If none of the installations have it, we fallback to printing - # the dependency currently linked on /System/Index. - # - # Note that when iterating over installed programs we skip those entries whose - # Resources/Architecture do not match the output of $(rpminfo --arch). - - depname=$(echo "$fullpath" | cut -d/ -f3) - depversion=$(echo "$fullpath" | cut -d/ -f4) - if [ "$symbol" ] - then - for testversion in $(ls $goboPrograms/$depname/ | grep -v "Settings\|Variable\|Current") - do - lookup_symbol "$depname" "$testversion" "$arch" "$symbol" && return 0 - done - fi - - Log_Verbose "Fallback: $depname $depversion" - echo "$depname $depversion" - else - # We have a path, but we don't have a link to that file under /System/Index. - # Our first attempt is to search over the list of installed programs anyhow, - # because some programs may not be currently activated. - - for fullpath in $(ls $goboPrograms/*/*/$path 2> /dev/null | grep -v "Current") - do - depname=$(echo "$fullpath" | cut -d/ -f3) - testversion=$(echo "$fullpath" | cut -d/ -f4) - [ -z "$depversion" ] && depversion="$testversion" - Log_Verbose "Looking for symbol on candidate file $candidate ($depname, $testversion)" - lookup_symbol "$depname" "$testversion" "$arch" "$symbol" && return 0 - done - - # We don't have a match. If we have a file name that satisfies the path but - # that doesn't contain the requested symbol, we simply return that path. - - if [ "$depname" ] && [ "$depversion" ] - then - echo "$depname $depversion" - return 0 - fi - - # We don't have a matching filename under /System/Index nor under /Programs/*/*. - # What we do now is to query remote RPM/DEB databases to find which package hosts the - # dependency file. - - if ! Boolean "no-web" - then - Log_Normal "Searching the remote $(thirdparty_backend) database for the package hosting $originalpath" - depname=$(third_party_search_remotedb "$originalpath" "$arch" "$distro") - if [ "$depname" ] - then - # TODO: we could now lookup the GoboLinux recipe store to find whether we - # have it or not - echo "$(GuessProgramCase $depname)" - return 0 - fi - fi - fi -} - -function lookup_pkgname() { - local dependency="$1" - local pkgname=$(echo "$dependency" | cut -d'(' -f1) - - # GoboLinux doesn't have "devel" packages like most mainstream distros do - local goboname=$(echo "$pkgname" | sed 's,-devel$,,g') - - # Do we have a GoboLinux package installed with a matching name? - for testname in $(ls $goboPrograms/) - do - # Case-insensitive comparison (requires Bash 4) - if [ "${testname,,}" = "${pkgname,,}" ] || [ "${testname,,}" = "${goboname,,}" ] - then - echo "$testname" && return 0 - fi - done - - # Query the GoboLinux recipe store. - if ! Boolean "no-web" - then - - local recipeurl=$(FindPackage -t recipe "${pkgname}" || FindPackage -t recipe "${goboname}") - if [ "$recipeurl" ] - then - # TODO we're potentially discarding the wanted version(s) of the given dep - echo "$(basename $recipeurl | sed 's,\(.*\)--.*--.*,\1,g')" && return 0 - fi - fi - - # TODO Query the remote RPM database for $pkgname - - # TODO Query the remote DEB database for $pkgname - - return 1 -} - -function is_basic_symbol() { - local dependency="$1" - echo "$dependency" | grep -q "^rtld(" && return 0 - return 1 -} - -function deduce_program_name() { - local inputfile="$1" - local name=$(thirdparty_name "$inputfile") - echo $name -} - -function prepare_program_entry() { - local inputfile="$1" - - if [ ${#inputfiles[@]} -gt 1 ] && Is_Entry "app-name" && [ ! -z "$programname" ] - then - # We have already prepared this program's entry on /Programs - return - fi - if Is_Entry "app-name" - then programname=$(Entry "app-name") - else programname="$(deduce_program_name $inputfile)" - fi - if Is_Entry "version-number" - then programversion=$(Entry "version-number") - else programversion=$(printf "%s_%s" $(thirdparty_version "$inputfile") $(thirdparty_release "$inputfile")) - fi - - # Prepare /Programs tree and update program name (PrepareProgram may have changed its case) - PrepareProgram -t "$programname" "$programversion" - programname=$(ls $goboPrograms/ | grep -i "^${programname}$") - target="$goboPrograms/$programname/$programversion" -} - -### Operation ################################################################# - -Is_Writable "${goboPrograms}" || Verify_Superuser - -if Boolean "verbose" -then verbose="--verbose" -else verbose= -fi - -# The inputfiles array holds the full path of all RPM/DEB input files -# The inputnames array holds the package name of all RPM/DEB input files -inputfiles=() -inputnames=() -rpmcount=0 -debcount=0 -eval `Args_To_Array inputfiles_` -for entry in "${inputfiles_[@]}" -do - inputfiles+=( "$(readlink -f ${entry} || echo ${entry})" ) - inputnames+=( "$(rpminfo --name $entry)" ) - echo "$entry" | grep -qi "\.deb" && let debcount=debcount+1 - echo "$entry" | grep -qi "\.rpm" && let rpmcount=rpmcount+1 -done - -# Sanity checks, then import the backend to handle the package format -if [ $rpmcount -gt 0 ] && [ $debcount -gt 0 ] -then - Die "Error: cannot handle both RPM and DEB files in a single shot." -elif [ $rpmcount -gt 0 ] -then - Import RPM -elif [ $debcount -gt 0 ] -then - Import DEB -fi - -# These will be set by prepare_program_entry() -unset programname -unset programversion -unset target - -# Determine the flattening level of /opt. In other words, whether -# we have something like: -# /opt/pkgname/{bin,sbin...} (1-level), or -# /opt/vendorname/pkgname/{bin,sbin...} (2-level) - -flatteninglevel=$(determine_flattening_level) - -# Installation pipeline -for entry in "${inputfiles[@]}" -do - Log_Normal "Processing $(basename $entry)" - inputfile=$(fetch_package "$entry") - prepare_program_entry "$inputfile" - Quiet pushd "$target" || Die "Could not enter $target" - - uncompress_package "$inputfile" - flatten_package "$inputfile" - populate_resources "$inputfile" - - Quiet popd - Is_URL "$entry" && rm -f -- "$inputfile" -done - -# Symlinking -if [ $(Entry "symlink") = "no" ] -then - Log_Normal "Done." - exit 0 -fi - -[ -d "$target/Resources/Defaults/Settings" ] && UpdateSettings "$programname" "$programversion" -SymlinkProgram "$programname" "$programversion" -Log_Normal "Done." -- cgit v1.1