diff --git a/CommonResources b/CommonResources index 6fca193..ab45060 100755 --- a/CommonResources +++ b/CommonResources @@ -195,8 +195,8 @@ updateActiveFile () logMessage "ERROR: specified soure file $sourceFile does not exist - can't continue with install" scriptAction='UNINSTALL' installFailed=true + return fi - return destinationFile="$2" # use active file for both source and destination else diff --git a/blindInstall/SetupHelperVersion b/blindInstall/SetupHelperVersion index 95cd864..0b880fd 100644 --- a/blindInstall/SetupHelperVersion +++ b/blindInstall/SetupHelperVersion @@ -1 +1 @@ -v5.14 +v5.15 diff --git a/changes b/changes index b0696cc..3c505ef 100644 --- a/changes +++ b/changes @@ -1,3 +1,7 @@ +v5.15: + fixed: PackageManager isn't in menus after v5.14 install + updateFileSets: fixed: NO_REPLACEMENT in existing file sets that should link to other sets + v5.14: v5.13 did not include blind install diff --git a/updateFileSets b/updateFileSets index 37ffec9..54c9ebd 100755 --- a/updateFileSets +++ b/updateFileSets @@ -526,7 +526,7 @@ for package in $packageList; do previousLink="../$version2/$baseName" checkLinks=true fi - elif $useOrigFlag2 ; then #################### is not working + elif $useOrigFlag2 ; then if $replacement1exists ; then logMessage "ERROR $package $basename file in $version1 conflicts with USE_ORIGINAL in $version2" touch "$fileSet1/$baseName.CHECK_REPLACEMENT" @@ -534,6 +534,7 @@ for package in $packageList; do else touch "$replacement1.USE_ORIGINAL" rm -f "$replacement1" + touch "$replacement2.USE_ORIGINAL" checkLinks=true fi fi @@ -556,7 +557,6 @@ for package in $packageList; do elif ! $useOrigFlag2 ; then touch "$replacement2.USE_ORIGINAL" rm -f "$replacement2" -logMessage "#### $baseName setting USE_ORIGINAL v2 $version2" fi if $replacement2isRealFile ; then logMessage "ERROR $package $baseName $verson1 has file but matches $version1 with USE_ORIGINAL set" @@ -573,7 +573,7 @@ logMessage "#### $baseName setting USE_ORIGINAL v2 $version2" replacement1="$fileSet1/$baseName" replacement1isRealFile=false useOrigFlag1=false - if [ -f "$replacement1" ] && [ -L "$replacement1" ]; then + if [ -f "$replacement1" ] && [ ! -L "$replacement1" ]; then replacement1isRealFile=true elif [ -f "$replacement1.USE_ORIGINAL" ]; then useOrigFlag1=true diff --git a/updateFileSets (original) b/updateFileSets (original) new file mode 100755 index 0000000..bf027e2 --- /dev/null +++ b/updateFileSets (original) @@ -0,0 +1,912 @@ +#!/bin/bash + +# this script updates file sets for all packages in the list below +# it scans all Venus OS versions in the stockFiles directory +# +# This is a unix bash script and should be run on a host computer, not a GX device +# Windows will not run this script natively. +# However Windows 10 apparently supports bash: +# https://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/ +# +# packages to be evaulated may be specified on the command line +# use 'all' to process all packages in the allPackages list below +# +# file sets which contain real files (not just links and flags) +# for a version NOT contained in StockFiles will be flagged with UNUSED_FILE_SET +# this can occur if you remove versions from StockFiles. +# For example, you may wish to remove beta versions after a beta test cycle. +# file sets which do not contain any real files (just symbolic links or flag files) are removed + +# stockFiles contains excerpts from Venus OS file systems +# and must be stored on the host +# within a directory with name of the exact Venus OS version +# and within the stockFiles directory defined below. +# +# 1) missing file set directories are created +# 2) if any files in fileList don't exist (eg, a new file was added to file list), +# the original file in stockFiles is copied to the version directory +# 3) if the original file does not exist, the file is so marked with .NO_STOCK_FILE +# this situation must be corrected: +# version-dependent files without an original MUST use an "alternate original" +# specified in FileSets. This permits version checks for these files too +# replacement files that do not replace a stock file should be placed in version-indpendent file storage +# (FileSets/). +# If these replacement files vary with Venus OS versions, they MUST include an "alternate original". +# This permits version checks for these files too +# +# when a stock file set does not exist, this script will check files from existing file sets +# for a matching original file. +# If a match is found, the replacement file is automatically placed in the new file set +# If no match is found, the missing replacement is flagged and a suitable replacement must be created manually. +# +# existing file sets not in the stockFiles are checked. If empty, they are removed. +# If not empty they are marked UNUSED_FILE_SET and flagged for manual removal. +# +# file sets will include all files listed in fileList. +# this allows the setup script to always have a replacement for known versions +# without searching other file sets for a matching original file +# (there have been cases where installation fails because the search for a matching original could not be found) +# if the stock file matches a previous version, a symbolic link for the replacement is created +# rather than duplicating the file +# this also makes maintanence easier since matching replacement can be identified +# +# original files in the file set are not normally used when installing the package +# however, they are retained so that the setup script can attempt to create a file set for an unknown Venus OS version +# this of course may fail if a matching original file can not be found +# +# if no end action is specified on the command line, the user is prompted for how to proceed for each package processed +# end actions specified will bypass this prompt and proceed with the next package +# end actions: +# -p do not update the package but preserve the working copy +# -d do not update the package and deete the working copy +# -u update the package with changes in the working copy's file sets +# +# -r restore package from backup if present - no processing is performed on the packge, backup or working copy +# backups are automatically created when updating a package +# Note: the restore option is not offered at the end prompt since the update has not been applied yet. +# +# if errors occur, the needed corrections may be more obvious by comparing the package and the working copy +# for this reason, preserving the working copy is recommended if errors are expected + +# set allPackages to all packages this script should evalueate if no options are included +allPackages="SetupHelper GuiMods ExtTransferSwitch ShutdownMonitor VeCanSetup RpiDisplaySetup RpiGpioSetup" +## GeneratorConnector TankRepeater are obsolete and file sets should not be updated. + +# set these as appropriate to your system +packageRoot="/Users/Kevin/GitHub" +stockFiles="$packageRoot/StockVenusOsFiles" + +totalErrors=0 +totalWarnings=0 +packageErrors=0 +packageWarnings=0 + +outputtingProgress=false + +function logMessage () +{ + if $outputtingProgress ; then + clearProgress + fi + echo "$*" + if [[ "$*" == "ERROR"* ]]; then + ((totalErrors++)) + ((packageErrors++)) + elif [[ "$*" == "WARNING"* ]]; then + ((totalWarnings++)) + ((packageWarnings++)) + fi +} + +function outputProgressTick () +{ + if ! $outputtingProgress ; then + echo -en "$beginProgressString" + fi + echo -en "$1" + outputtingProgress=true +} + +function clearProgress () +{ + echo -ne "\r\033[2K" + outputtingProgress=false +} + +beginProgressString="" + +function beginProgress () +{ + # erase the line but stay on it + if $outputtingProgress ; then + echo -ne "\r\033[2K" + fi + if [ ! -z "$1" ]; then + beginProgressString="$1 " + echo -en "$beginProgressString" + + outputtingProgress=true + fi +} + + +function versionStringToNumber () +{ + local local p4="" ; local p5="" ; local p6="" + local major=""; local minor="" + + # first character should be 'v' so first awk parameter will be empty and is not prited into the read command + # + # version number formats: v2.40, v2.40~6, v2.40-large-7, v2.40~6-large-7 + # so we must adjust how we use paramters read from the version string + # and parsed by awk + # if no beta make sure release is greater than any beta (i.e., a beta portion of 999) + + read major minor p4 p5 p6 <<< $(echo $1 | awk -v FS='[v.~-]' '{print $2, $3, $4, $5, $6}') + ((versionNumber = major * 1000000 + minor * 1000)) + if [ -z $p4 ] || [ $p4 = "large" ]; then + ((versionNumber += 999)) + else + ((versionNumber += p4)) + fi + if [ ! -z $p4 ] && [ $p4 = "large" ]; then + ((versionNumber += p5 * 1000)) + large=$p5 + elif [ ! -z $p6 ]; then + ((versionNumber += p6 * 1000)) + fi +} + +# removing a nested set of directories sometimes results in permission denied the first time + # so try several times to be sure + +function deleteNestedDirectories () +{ + rm -rf "$1" &> /dev/null + if [ -d "$1" ] ; then + rm -rf "$1" &> /dev/null + if [ -d "$1" ] ; then + rm -rf "$1" + fi + fi +} + + +yesNoPrompt () +{ + response='' + while true; do + /bin/echo -n "$*" + read response + case $response in + [yY]*) + yesResponse=true + break + ;; + [nN]*) + yesResponse=false + break + ;; + *) + esac + done +} + + +#### script code begins here +packageList="" +doAllPackages=false +globalEndAction='' +for param in $* ; do + case $param in + -[pP]*) + logMessage "working copies will be preserved - packages will not be updated" + globalEndAction='preserve' + ;; + -[dD]*) + logMessage "working copies will be deleted - packages will not be updated" + globalEndAction='delete' + ;; + -[uU]*) + logMessage "packages will be updated without prompting" + globalEndAction='update' + ;; + -[rR]*) + logMessage "packages will be restored from backups" + globalEndAction='restore' + ;; + all) + doAllPackages=true + ;; + *) + packageList+=" "$1 + esac + shift +done +if $doAllPackages ; then + packageList=$allPackages +elif [ -z "$packageList" ]; then + logMessage "ERROR no packages specified - use 'all' for all packages" + exit +fi + +if [ "$globalEndAction" == "restore" ]; then + for package in $packageList; do + sourceDirectory="$packageRoot/$package" + sourceFiles="$sourceDirectory/FileSets" + backupDirectory="$packageRoot/$package.backup" + backupFiles="$backupDirectory/FileSets" + if [ ! -d "$backupDirectory" ]; then + logMessage "WARNING $package: no backup found - package NOT restored" + continue + fi + logMessage "WARNING $package: restored from backup" + deleteNestedDirectories "$sourceFiles" + mv "$backupFiles" "$sourceFiles" + if [ -f "$backupFiles/obsoleteVersion" ]; then + mv -f "$backupFiles/obsoleteVersion" "$sourceDirectory" + fi + if [ -f "$backupFiles/firstCompatibleVersion" ]; then + mv -f "$backupFiles/firstCompatibleVersion" "$sourceDirectory" + fi + deleteNestedDirectories $backupDirectory + done + exit +fi + +# make the version list from the directories in stock files +# version lists are sorted so the most recent version is first +tempList=() +stockVersionList=($(ls -d "$stockFiles"/v* 2> /dev/null)) +for entry in ${stockVersionList[@]} ; do + version=$(basename $entry) + versionFile="$stockFiles/$version/opt/victronenergy/version" + realVersion=$(cat "$versionFile" | head -n 1) + + if [ $version != $realVersion ]; then + directoryName=$(basename $stockFiles)/$version + logMessage "ERROR $directoryName name does not mactch Venus $realVersion - can't continue" + exit + fi + versionStringToNumber $version + tempList+=("$version:$versionNumber") +done +stockVersionList=( $(echo ${tempList[@]} | tr ' ' '\n' | sort -t ':' -r -n -k 2 | uniq ) ) + +for package in $packageList; do + packageErrors=0 + packageWarnings=0 + sourceDirectory="$packageRoot/$package" + sourceFiles="$sourceDirectory/FileSets" + workingDirectory="$packageRoot/$package.copy" + workingFiles="$workingDirectory/FileSets" + + if [ ! -d "$sourceDirectory" ] || [ ! -f "$sourceDirectory/version" ]; then + logMessage "$sourceDirectory - not a package directory" + continue + fi + if [ ! -d "$sourceFiles" ]; then + logMessage "$package: no file sets" + continue + fi + if [ ! -f "$sourceFiles/fileList" ]; then + logMessage "$package: no version-dependent files" + continue + fi + fileList=$(cat "$sourceFiles/fileList") + if [ -z "$fileList" ]; then + logMessage "WARNING $package: empty file list" + continue + fi + + # make copy of source package FileSets + beginProgress "$package: making working copy" + deleteNestedDirectories "$workingDirectory" + mkdir -p "$workingDirectory" + cp -pR "$sourceFiles" "$workingFiles" + if [ -f "$sourceDirectory/obsoleteVersion" ]; then + cp -p "$sourceDirectory/obsoleteVersion" "$workingDirectory" + fi + if [ -f "$sourceDirectory/firstCompatibleVersion" ]; then + cp -p "$sourceDirectory/firstCompatibleVersion" "$workingDirectory" + fi + # compute compatible version range + if [ -f "$workingDirectory/obsoleteVersion" ]; then + versionStringToNumber $(cat "$workingDirectory/obsoleteVersion") + obsoleteVersion=$versionNumber + else + obsoleteVersion=999999999 + fi + if [ -f "$workingDirectory/firstCompatibleVersion" ]; then + versionStringToNumber $(cat "$workingDirectory/firstCompatibleVersion") + firstVersion=$versionNumber + else + firstVersion=0 + fi + + # append the package's existing file sets NOT in the stock versions + # to the END of the stock files list + # this insures these file sets contain only files used by that or other unused versions + sourceFileSets=($(ls -d "$sourceFiles"/v* 2> /dev/null)) + tempList=() + for entry in ${sourceFileSets[@]} ; do + version=$(basename $entry) + if [ ! -d "$stockFiles/$version" ]; then + versionStringToNumber $version + tempList+=($version:$versionNumber) + fi + done + existingFileSets=( $(echo ${tempList[@]} | tr ' ' '\n' | sort -t ':' -r -n -k 2 | uniq ) ) + allFileSets=(${stockVersionList[@]}) + allFileSets+=(${existingFileSets[@]}) + + # move incompatible versions to the end of the list + # so that real files end up in a supported file set + obsoleteFileSets=() + tempList=() + for entry in ${allFileSets[@]} ; do + IFS=':' read version versionNumber <<< "$entry" + if (( $versionNumber >= $obsoleteVersion )) || (( $versionNumber < $firstVersion )); then + obsoleteFileSets+=($version:$versionNumber) + else + tempList+=($version:$versionNumber) + fi + done + allFileSets=(${tempList[@]}) + allFileSets+=(${obsoleteFileSets[@]}) + allFileSetsLength=${#allFileSets[@]} + + # clean up flag files from a previous run + rm -f "$workingFiles"/*/INCOMPATIBLE_VERSION + rm -f "$workingFiles"/*/UNUSED_FILE_SET + rm -f "$workingFiles"/*/INCOMPLETE + rm -f "$workingFiles"/*/COMPLETE + rm -f "$workingFiles"/*/LINKS_ONLY + rm -f "$workingFiles"/*/*.NO_ORIG + rm -f "$workingFiles"/*/*.NO_REPLACEMENT + rm -f "$workingFiles"/*/*.NO_REPLACEMENT_LINK + rm -f "$workingFiles"/*/*.CHECK_REPLACEMENT + rm -f "$workingFiles"/*/NEW_FILE_SET + rm -f "$workingFiles"/*/*.MATCHES_PREVIOUS + + for (( i1 = 0; i1 < $allFileSetsLength; i1++ )); do + IFS=':' read version versionNumber <<< "${allFileSets[$i1]}" + + fileSet1="$workingFiles/$version" + if [ ! -d "$fileSet1" ]; then + mkdir "$fileSet1" + touch "$fileSet1/NEW_FILE_SET" + fi + # check to see if package is compatible with this Venus version + if (( $versionNumber >= $obsoleteVersion )) || (( $versionNumber < $firstVersion )); then + touch "$fileSet1/INCOMPATIBLE_VERSION" + fi + + done + + beginProgress "$package: updating file sets" + for file in $fileList ; do + baseName=$(basename "$file") + outputProgressTick "." + # use alternate original if present + if [ -f "$workingFiles/$baseName.ALT_ORIG" ]; then + useAltOrig=true + altOrigFile=$(cat "$workingFiles/$baseName.ALT_ORIG") + else + useAltOrig=false + altOrigFile="" + fi + + # move real files to newest file set + for (( i1 = 0; i1 < $allFileSetsLength; i1++ )); do + IFS=':' read version1 version1number <<< "${allFileSets[$i1]}" + fileSet1="$workingFiles/$version1" + stockFileSet1="$stockFiles/$version1" + # if stock file set does not exist, or this is an incompatible version + # don't move files here + # this will allow file sets for versions no longer supported to be removed + # an error result if a replacement in this version is needed for other file sets + if [ ! -d "$stockFileSet1" ] || [ -f "$fileSet1/INCOMPATIBLE_VERSION" ]; then + continue + fi + + replacement1="$fileSet1/$baseName" + if [ -f "$replacement1" ] && [ ! -L "$replacement1" ]; then + replacement1exists=true + else + replacement1exists=false + fi + orig1="$fileSet1/$baseName.orig" + # select appropirate stock file + if $useAltOrig ; then + stockFile1="$stockFileSet1$altOrigFile" + else + stockFile1="$stockFileSet1$file" + fi + + if [ ! -f "$stockFile1" ]; then + if $useAltOrig ; then + logMessage "ERROR $package: $version1 $baseName stock file missing (move) - check ALT_ORIG" + touch "$fileSet1/$baseName.CHECK_ALT_ORIG" + else + logMessage "ERROR $package: $version1 $baseName stock file missing (move) - consider using an ALT_ORIG" + fi + touch "$fileSet1/$baseName.NO_STOCK_FILE" + touch "$fileSet1/INCOMPLETE" + logMessage "can't continue" + exit + fi + + # look for a match (stock files) in older file sets + # and relocate if found + checkLinks=false + for (( i2 = $i1 + 1; i2 < $allFileSetsLength; i2++ )); do + IFS=':' read version2 version2number <<< "${allFileSets[$i2]}" + fileSet2="$workingFiles/$version2" + replacement2="$fileSet2/$baseName" + orig2="$fileSet2/$baseName.orig" + + if [ -L "$replacement2" ] ; then + replacement2isLink=true + replacement2isRealFile=false + elif [ -f "$replacement2" ] ; then + replacement2isRealFile=true + replacement2isLink=false + else + replacement2isRealFile=false + replacement2isLink=false + fi + # USE_ORIGINAL is valid only if the original file also exists (and is not a sym link) + if [ -f "$replacement2.USE_ORIGINAL" ] && [ -f $orig2 ] && [ ! -L $orig2 ]; then + useOrigFlag2=true + else + useOrigFlag2=false + fi + if $replacement2isRealFile || $useOrigFlag2 || [ -f "$fileSet2/NEW_FILE_SET" ]; then + doStockCheck=true + else + doStockCheck=false + fi + + stockMatch=false + if $doStockCheck ; then + if [ -d "$stockFiles/$version2" ]; then + # select appropirate original file + if $useAltOrig ; then + stockFile2="$stockFiles/$version2$altOrigFile" + else + stockFile2="$stockFiles/$version2$file" + fi + if [ ! -f "$stockFile2" ]; then + if $useAltOrig ; then + logMessage "ERROR $package: $version2 $baseName stock file missing - check ALT_ORIG" + touch "$fileSet2/$baseName.CHECK_ALT_ORIG" + else + logMessage "ERROR $package: $version2 $baseName stock file missing - consider using an ALT_ORIG" + fi + touch "$fileSet2/$baseName.NO_STOCK_FILE" + touch "$fileSet2/INCOMPLETE" + logMessage "can't continue" + exit + fi + + # stock files match + cmp -s "$stockFile2" "$stockFile1" > /dev/null + if [ $? -eq 0 ]; then + stockMatch=true + fi + # no stock files but existing file set + elif $replacement2isRealFile && [ -f "$orig2" ] ; then + # existing orig matches stock + cmp -s "$orig2" "$stockFile1" + if [ $? -eq 0 ] ;then + stockMatch=true + fi + fi + fi + if $stockMatch ; then + moveReplacement=true + if $replacement2isRealFile ; then + if $replacement1exists ; then + cmp -s "$replacement1" "$replacement2" /dev/null + if [ $? -ne 0 ]; then + logMessage "ERROR $package: $baseName $version1 and $version2 replacements differ but same stock files" + touch "$fileSet1/$baseName.CHECK_REPLACEMENT" + touch "$fileSet2/$baseName.CHECK_REPLACEMENT" + moveReplacement=false + fi + fi + if $moveReplacement ; then + mv -f "$replacement2" "$replacement1" + rm -f "$fileSet1/$baseName.USE_ORIGINAL" + ln -sf "../$version1/$baseName" "$replacement2" + cp -f "$stockFile1" "$orig1" + previousLink="../$version2/$baseName" + checkLinks=true + fi + elif $useOrigFlag2 ; then + touch "$replacement1.USE_ORIGINAL" + touch "$replacement2.USE_ORIGINAL" + fi + + if [ -f "$orig2" ]; then + mv -f "$orig2" "$orig1" + fi + fi + + # relink replacement to new location + if $checkLinks && $replacement2isLink ; then + if [ "$(readlink "$replacement2")" == "$previousLink" ]; then + ln -sf "../$version1/$baseName" "$replacement2" + fi + fi + done # for i2 + done # for i1 (update) + + # make another pass and fill in links that were missed in the first past + for (( i1 = 0; i1 < $allFileSetsLength; i1++ )); do + IFS=':' read version1 version1number <<< "${allFileSets[$i1]}" + fileSet1="$workingFiles/$version1" + replacement1="$fileSet1/$baseName" + # must be a real replacement (not link) + if [ ! -f "$replacement1" ] || [ -L "$replacement1" ]; then + continue + fi + + stockFileSet1="$stockFiles/$version1" + if [ ! -d "$stockFileSet1" ]; then + continue + fi + + # if no replacement, search for one that we can link to + for (( i2 = $i1 + 1; i2 < $allFileSetsLength; i2++ )); do + IFS=':' read version2 version2number <<< "${allFileSets[$i2]}" + fileSet2="$workingFiles/$version2" + replacement2="$fileSet2/$baseName" + # skip if replacement already exists + if [ -e "$replacement2" ] ; then + continue + fi + + # select appropirate stock files + if $useAltOrig ; then + stockFile1="$stockFileSet1$altOrigFile" + stockFile2="$stockFiles/$version2$altOrigFile" + else + stockFile1="$stockFileSet1$file" + stockFile2="$stockFiles/$version2$file" + fi + # stock files match - create link + cmp -s "$stockFile2" "$stockFile1" > /dev/null + if [ $? -eq 0 ]; then + ln -sf "../$version1/$baseName" "$replacement2" + fi + done # for i2 + done # for i1 (missing sym links) + done # for file + + # check to see if a non-versioned file is appropriate -- but only if no errors were found + reloadFileList=false + if (( $packageErrors == 0 )) ; then + for file in $fileList ; do + realFileCount=0 + baseName=$(basename "$file") + + # file must be be using an alternate stock file + if [ ! -f "$workingFiles/$baseName.ALT_ORIG" ]; then + continue + fi + for (( i1 = 0; i1 < $allFileSetsLength; i1++ )); do + IFS=':' read version1 version1number <<< "${allFileSets[$i1]}" + fileSet1="$workingFiles/$version1" + replacement1="$fileSet1/$baseName" + if [ -f "$replacement1" ] && [ ! -L "$replacement1" ]; then + (( realFileCount += 1 )) + + fi + done + + if (( realFileCount == 1 )); then + yesNoPrompt "$package: $baseName - make version-independent (y / n)?: " + if $yesResponse ; then + logMessage "$baseName.ALT_ORIG.UNUSED and $(basename $fileListFile.old) can be removed" + mv -f "$workingFiles/$baseName.ALT_ORIG" "$workingFiles/$baseName.ALT_ORIG.UNUSED" + fileListFile="$workingFiles/fileList" + grep -v "$file" "$fileListFile" > "$fileListFile.tmp" + mv -f "$fileListFile" "$fileListFile.old" + mv -f "$fileListFile.tmp" "$fileListFile" + reloadFileList=true + for (( i1 = 0; i1 < $allFileSetsLength; i1++ )); do + IFS=':' read version1 version1number <<< "${allFileSets[$i1]}" + fileSet1="$workingFiles/$version1" + if [ ! -d "$fileSet1" ]; then + continue + fi + replacementFile="$fileSet1/$baseName" + if [ -L "$replacementFile" ]; then + rm -f "$replacementFile" + elif [ -f "$replacementFile" ]; then + mv "$replacementFile" "$workingFiles" + rm -f "$replacementFile.orig" + fi + done + else + logMessage "$baseName remains in version-dependent file sets" + fi + fi + done # for file (version independent check) + fi + + # reload fileList if changed above + if $reloadFileList ; then + fileList=$(cat "$workingFiles/fileList") + if [ -z "$fileList" ]; then + logMessage "WARNING $package: empty file list" + continue + fi + fi + + linksOnlyVersions=() + realFileVersions=() + linksOnlyVersionCount=0 + realFilesVersionCount=0 + beginProgress "$package: final checks" + for (( i1 = 0; i1 < $allFileSetsLength; i1++ )); do + IFS=':' read version1 version1number <<< "${allFileSets[$i1]}" + fileSet1="$workingFiles/$version1" + if [ ! -d "$fileSet1" ]; then + continue + fi + outputProgressTick "." + + replacementFilesExist=false + replacmentSymLinksExist=false + for file in $fileList ; do + baseName=$(basename "$file") + + if [ -f "$workingFiles/$baseName.ALT_ORIG" ]; then + useAltOrig=true + altOrigFile=$(cat "$workingFiles/$baseName.ALT_ORIG") + else + useAltOrig=false + altOrigFile="" + fi + + replacement1="$fileSet1/$baseName" + orig1="$fileSet1/$baseName.orig" + + # do final checks for -- must be file, link or USE_ORIG but not more than one + if [ -L "$replacement1" ]; then + symLinkReplacement=true + realReplacement=false + anyReplacement=true + elif [ -f "$replacement1" ]; then + realReplacement=true + symLinkReplacement=false + anyReplacement=true + else + realReplacement=false + symLinkReplacement=false + anyReplacement=false + fi + if [ -f "$orig1" ]; then + origExists=true + else + origExists=false + fi + if [ -f "$replacement1.USE_ORIGINAL" ]; then + useOrigFlag=true + else + useOrigFlag=false + fi + + if ! $anyReplacement && ! $useOrigFlag; then + logMessage "ERROR $package: $baseName $version1 no replacement" + touch "$replacement1.NO_REPLACEMENT" + stockFileSet1="$stockFiles/$version1" + if $useAltOrig ; then + stockFile1="$stockFileSet1$altOrigFile" + else + stockFile1="$stockFileSet1$file" + fi + # fill in missing original file if it exists + if [ ! -f "$orig1" ] && [ -f "$stockFile1" ]; then + cp "$stockFile1" "$orig1" + fi + elif $anyReplacement && $useOrigFlag; then + logMessage "WARNING $package $version1 $baseName replacement exists - removing USE_ORIGINAL flag" + rm "$replacement1.USE_ORIGINAL" + fi + if $symLinkReplacement && $origExists ; then + logMessage "WARNING $package: $baseName $version1 should NOT contain link AND orig file" + elif $realReplacement && ! $origExists ; then + logMessage "ERROR $package: $baseName $version1 must contain real file AND orig file" + touch "$replacement1.NO_ORIG" + fi + + if [ -f "$replacement1.NO_REPLACEMENT" ] \ + || [ -f "$replacement1.CHECK_REPLACEMENT" ] \ + || [ -f "$replacement1.NO_ORIG" ] ; then + touch "$fileSet1/INCOMPLETE" + fi + + # identify real file & symlink in file set for later + if $symLinkReplacement ; then + replacmentSymLinksExist=true + fi + if $realReplacement || ( $useOrigFlag && $origExists ) ; then + replacementFilesExist=true + fi + done # for file + + # if all replacement files are in place, mark the file set COMPLETE + # so _checkFileSets can skip all checks + # COMPLETE tells _checkFileSets to skip all checks and accept the file set as is + if [ -f "$fileSet1/INCOMPLETE" ]; then + rm -f "$fileSet1/COMPLETE" + else + touch "$fileSet1/COMPLETE" + fi + + if ! $replacementFilesExist && $replacmentSymLinksExist ; then + touch "$fileSet1/LINKS_ONLY" + linksOnlyVersions+=" $version1" + ((linksOnlyVersionCount++)) + elif $replacementFilesExist ; then + realFileVersions+=" $version1" + ((realFilesVersionCount++)) + fi + + # remove file sets for incompatible Venus OS versions + if [ -e "$fileSet1/INCOMPATIBLE_VERSION" ]; then + if $replacementFilesExist ; then + logMessage "WARNING $package: not compatible with Venus $version1 but not empty - consider manual removal" + else + if [ ! -f "$fileSet1/NEW_FILE_SET" ]; then + logMessage "WARNING $package: not compatible with Venus $version1 - file set will not be included in update" + fi + rm -Rf "$fileSet1" + + fi + # not in stock files list + elif [ ! -d "$stockFiles/$version1" ]; then + if $replacementFilesExist ; then + logMessage "WARNING $package: $version1 no longer used but not empty - manual remove is OK" + touch "$fileSet1/UNUSED_FILE_SET" + # no files (empty file set) + else + # log removal of a previous file set if not created with this run + # if it was created with this run, delete it silently + if [ ! -f "$fileSet1/NEW_FILE_SET" ]; then + logMessage "WARNING $package: $version1 no longer used and contains only links - removing file set" + fi + rm -rf "$fileSet1" + fi + fi + + if [ -f "$fileSet1/NEW_FILE_SET" ]; then + logMessage "$package: new file set $version1" + fi + + # remove temporary files + done # for i1 (final checks) + rm -f "$workingFiles/v"*/*tmp + rm -f "$workingFiles/v"*/NEW_FILE_SET + + if [ ! -z "$realFileVersions" ]; then + logMessage "$package: $realFilesVersionCount file sets containing real files:$realFileVersions" + fi + if [ ! -z "$linksOnlyVersions" ]; then + logMessage "$package: $linksOnlyVersionCount file sets containing only links:$linksOnlyVersions" + fi + + if [ "$packageErrors" == 0 ]; then + errorText="no errors " + else + errorText="$totalErrors ERRORS " + fi + if [ "$packageWarnings" == 0 ]; then + warningText="no warnings" + else + warningText="$totalWarnings WARNINGS" + fi + + logMessage "$package complete $errorText $warningText" + + baseName=$(basename $workingDirectory) + + if [ -z "$globalEndAction" ]; then + echo + echo "select to finish:" + echo " update $package (u)" + echo " preserve working copy for inspection (p)" + echo " discard working copy (d)" + while true ; do + read -p "choose action from list above (u / p / d): " response + case $response in + [uU]*) + endAction='update' + break + ;; + [pP]*) + endAction='preserve' + break + ;; + [dD]*) + endAction='delete' + break + ;; + *) + esac + done + else + endAction=$globalEndAction + fi + + case $endAction in + preserve) + logMessage "$package unchanged - changes preserved as $baseName" + ;; + delete) + logMessage "$package unchanged - $baseName removed" + deleteNestedDirectories "$workingDirectory" + ;; + update) + logMessage "$package: updating file sets - backup in $package.backup" + deleteNestedDirectories "$package.backup" + mkdir "$package.backup" + mv "$sourceFiles" "$package.backup" + if [ -f "$sourceDirectory/obsoleteVersion" ]; then + mv -f "$sourceDirectory/obsoleteVersion" "$package.backup" + fi + if [ -f "$sourceDirectory/firstCompatibleVersion" ]; then + mv -f "$sourceDirectory/firstCompatibleVersion" "$package.backup" + fi + + deleteNestedDirectories "$sourceFiles" + mv "$workingFiles" "$sourceFiles" + if [ -f "$workingDirectory/obsoleteVersion" ]; then + mv -f "$workingDirectory/obsoleteVersion" "$sourceDirectory" + fi + if [ -f "$workingDirectory/firstCompatibleVersion" ]; then + mv -f "$workingDirectory/firstCompatibleVersion" "$sourceDirectory" + fi + deleteNestedDirectories $workingDirectory + ;; + *) + logMessage "ERROR: invalid end action $endAction" + esac +done # for package + +# review all file sets and report any that only contain sym links across all packages +# it would be possile to remove those verions from stock files without loosing any data +# this check is only done if updating all file sets and there are no errors +if $doAllPackages && [ "$totalErrors" == 0 ]; then + for entry in ${stockVersionList[@]} ; do + IFS=':' read version versionNumber <<< "$entry" + linksOnly=true + for package in $packageList; do + fileSet="$packageRoot/$package/FileSets/$version" + if [ ! -e "$fileSet/LINKS_ONLY" ]; then + linksOnly=false + break + fi + done + if $linksOnly ; then + logMessage "$version: only links in all packages - stock version could be removed" + fi + done +fi + +if [ "$totalErrors" == 0 ]; then + errorText="no errors " +else + errorText="$totalErrors ERRORS " +fi +if [ "$totalWarnings" == 0 ]; then + warningText="no warnings" +else + warningText="$totalWarnings WARNINGS" +fi + +logMessage "updateFileSets complete $errorText $warningText" diff --git a/updateFileSets-partilaFileSets b/updateFileSets-partilaFileSets new file mode 100755 index 0000000..3194df8 --- /dev/null +++ b/updateFileSets-partilaFileSets @@ -0,0 +1,827 @@ +#!/bin/bash + +# this script updates file sets for all packages in the list below +# it scans all Venus OS versions in the stockFiles directory +# +# This is a unix bash script and should be run on a host computer, not a GX device +# Windows will not run this script natively. +# However Windows 10 apparently supports bash: +# https://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/ +# +# packages to be evaulated may be specified on the command line +# use 'all' to process all packages in the allPackages list below +# +# file sets which contain real files (not just links and flags) +# for a version NOT contained in StockFiles will be flagged with UNUSED_FILE_SET +# this can occur if you remove versions from StockFiles. +# For example, you may wish to remove beta versions after a beta test cycle. +# file sets which do not contain any real files (just symbolic links or flag files) are removed + +# stockFiles contains excerpts from Venus OS file systems +# and must be stored on the host +# within a directory with name of the exact Venus OS version +# and within the stockFiles directory defined below. +# +# 1) missing file set directories are created +# 2) if any files in fileList don't exist (eg, a new file was added to file list), +# the original file in stockFiles is copied to the version directory +# 3) if the original file does not exist, the file is so marked with .NO_STOCK_FILE +# this situation must be corrected: +# version-dependent files without an original MUST use an "alternate original" +# specified in FileSets. This permits version checks for these files too +# replacement files that do not replace a stock file should be placed in version-indpendent file storage +# (FileSets/). +# If these replacement files vary with Venus OS versions, they MUST include an "alternate original". +# This permits version checks for these files too +# +# when a stock file set does not exist, this script will check files from existing file sets +# for a matching original file. +# If a match is found, the replacement file is automatically placed in the new file set +# If no match is found, the missing replacement is flagged and a suitable replacement must be created manually. +# +# existing file sets not in the stockFiles are checked. If empty, they are removed. +# If not empty they are marked UNUSED_FILE_SET and flagged for manual removal. +# +# file sets will include all files listed in fileList. +# this allows the setup script to always have a replacement for known versions +# without searching other file sets for a matching original file +# (there have been cases where installation fails because the search for a matching original could not be found) +# if the stock file matches a previous version, a symbolic link for the replacement is created +# rather than duplicating the file +# this also makes maintanence easier since matching replacement can be identified +# +# original files in the file set are not normally used when installing the package +# however, they are retained so that the setup script can attempt to create a file set for an unknown Venus OS version +# this of course may fail if a matching original file can not be found +# +# if no end action is specified on the command line, the user is prompted for how to proceed for each package processed +# end actions specified will bypass this prompt and proceed with the next package +# end actions: +# -p do not update the package but preserve the working copy +# -d do not update the package and deete the working copy +# -u update the package with changes in the working copy's file sets +# +# -r restore package from backup if present - no processing is performed on the packge, backup or working copy +# backups are automatically created when updating a package +# Note: the restore option is not offered at the end prompt since the update has not been applied yet. +# +# if errors occur, the needed corrections may be more obvious by comparing the package and the working copy +# for this reason, preserving the working copy is recommended if errors are expected + +# set allPackages to all packages this script should evalueate if no options are included +allPackages="SetupHelper GuiMods ExtTransferSwitch ShutdownMonitor VeCanSetup RpiDisplaySetup RpiGpioSetup" +## GeneratorConnector TankRepeater are obsolete and file sets should not be updated. + +# set these as appropriate to your system +packageRoot="/Users/Kevin/GitHub" +stockFiles="$packageRoot/StockVenusOsFiles" + +totalErrors=0 +totalWarnings=0 +packageErrors=0 +packageWarnings=0 + +outputtingProgress=false + +function logMessage () +{ + if $outputtingProgress ; then + clearProgress + fi + echo "$*" + if [[ "$*" == "ERROR"* ]]; then + ((totalErrors++)) + ((packageErrors++)) + elif [[ "$*" == "WARNING"* ]]; then + ((totalWarnings++)) + ((packageWarnings++)) + fi +} + +function outputProgressTick () +{ + if ! $outputtingProgress ; then + echo -en "$beginProgressString" + fi + echo -en "$1" + outputtingProgress=true +} + +function clearProgress () +{ + echo -ne "\r\033[2K" + outputtingProgress=false +} + +beginProgressString="" + +function beginProgress () +{ + # erase the line but stay on it + if $outputtingProgress ; then + echo -ne "\r\033[2K" + fi + if [ ! -z "$1" ]; then + beginProgressString="$1 " + echo -en "$beginProgressString" + + outputtingProgress=true + fi +} + + +function versionStringToNumber () +{ + local local p4="" ; local p5="" ; local p6="" + local major=""; local minor="" + + # first character should be 'v' so first awk parameter will be empty and is not prited into the read command + # + # version number formats: v2.40, v2.40~6, v2.40-large-7, v2.40~6-large-7 + # so we must adjust how we use paramters read from the version string + # and parsed by awk + # if no beta make sure release is greater than any beta (i.e., a beta portion of 999) + + read major minor p4 p5 p6 <<< $(echo $1 | awk -v FS='[v.~-]' '{print $2, $3, $4, $5, $6}') + ((versionNumber = major * 1000000 + minor * 1000)) + if [ -z $p4 ] || [ $p4 = "large" ]; then + ((versionNumber += 999)) + else + ((versionNumber += p4)) + fi + if [ ! -z $p4 ] && [ $p4 = "large" ]; then + ((versionNumber += p5 * 1000)) + large=$p5 + elif [ ! -z $p6 ]; then + ((versionNumber += p6 * 1000)) + fi +} + +# removing a nested set of directories sometimes results in permission denied the first time + # so try several times to be sure + +function deleteNestedDirectories () +{ + rm -rf "$1" &> /dev/null + if [ -d "$1" ] ; then + rm -rf "$1" &> /dev/null + if [ -d "$1" ] ; then + rm -rf "$1" + fi + fi +} + + +yesNoPrompt () +{ + response='' + while true; do + /bin/echo -n "$*" + read response + case $response in + [yY]*) + yesResponse=true + break + ;; + [nN]*) + yesResponse=false + break + ;; + *) + esac + done +} + + +#### script code begins here +packageList="" +doAllPackages=false +globalEndAction='' +for param in $* ; do + case $param in + -[pP]*) + logMessage "working copies will be preserved - packages will not be updated" + globalEndAction='preserve' + ;; + -[dD]*) + logMessage "working copies will be deleted - packages will not be updated" + globalEndAction='delete' + ;; + -[uU]*) + logMessage "packages will be updated without prompting" + globalEndAction='update' + ;; + -[rR]*) + logMessage "packages will be restored from backups" + globalEndAction='restore' + ;; + all) + doAllPackages=true + ;; + *) + packageList+=" "$1 + esac + shift +done +if $doAllPackages ; then + packageList=$allPackages +elif [ -z "$packageList" ]; then + logMessage "ERROR no packages specified - use 'all' for all packages" + exit +fi + +if [ "$globalEndAction" == "restore" ]; then + for package in $packageList; do + sourceDirectory="$packageRoot/$package" + sourceFiles="$sourceDirectory/FileSets" + backupDirectory="$packageRoot/$package.backup" + backupFiles="$backupDirectory/FileSets" + if [ ! -d "$backupDirectory" ]; then + logMessage "WARNING $package: no backup found - package NOT restored" + continue + fi + logMessage "WARNING $package: restored from backup" + deleteNestedDirectories "$sourceFiles" + mv "$backupFiles" "$sourceFiles" + if [ -f "$backupFiles/obsoleteVersion" ]; then + mv -f "$backupFiles/obsoleteVersion" "$sourceDirectory" + fi + if [ -f "$backupFiles/firstCompatibleVersion" ]; then + mv -f "$backupFiles/firstCompatibleVersion" "$sourceDirectory" + fi + deleteNestedDirectories $backupDirectory + done + exit +fi + +# make the version list from the directories in stock files +# version lists are sorted so the most recent version is first +tempList=() +stockVersionList=($(ls -d "$stockFiles"/v* 2> /dev/null)) +for entry in ${stockVersionList[@]} ; do + version=$(basename $entry) + versionFile="$stockFiles/$version/opt/victronenergy/version" + realVersion=$(cat "$versionFile" | head -n 1) + + if [ $version != $realVersion ]; then + directoryName=$(basename $stockFiles)/$version + logMessage "ERROR $directoryName name does not mactch Venus $realVersion - can't continue" + exit + fi + versionStringToNumber $version + tempList+=("$version:$versionNumber") +done +stockVersionList=( $(echo ${tempList[@]} | tr ' ' '\n' | sort -t ':' -r -n -k 2 | uniq ) ) + +for package in $packageList; do + packageErrors=0 + packageWarnings=0 + sourceDirectory="$packageRoot/$package" + sourceFiles="$sourceDirectory/FileSets" + workingDirectory="$packageRoot/$package.copy" + workingFiles="$workingDirectory/FileSets" + + if [ ! -d "$sourceDirectory" ] || [ ! -f "$sourceDirectory/version" ]; then + logMessage "$sourceDirectory - not a package directory" + continue + fi + if [ ! -d "$sourceFiles" ]; then + logMessage "$package: no file sets" + continue + fi + if [ ! -f "$sourceFiles/fileList" ]; then + logMessage "$package: no version-dependent files" + continue + fi + fileList=$(cat "$sourceFiles/fileList") + if [ -z "$fileList" ]; then + logMessage "WARNING $package: empty file list" + continue + fi + + # make copy of source package FileSets + beginProgress "$package: making working copy" + deleteNestedDirectories "$workingDirectory" + mkdir -p "$workingDirectory" + cp -pR "$sourceFiles" "$workingFiles" + if [ -f "$sourceDirectory/obsoleteVersion" ]; then + cp -p "$sourceDirectory/obsoleteVersion" "$workingDirectory" + fi + if [ -f "$sourceDirectory/firstCompatibleVersion" ]; then + cp -p "$sourceDirectory/firstCompatibleVersion" "$workingDirectory" + fi + # compute compatible version range + if [ -f "$workingDirectory/obsoleteVersion" ]; then + versionStringToNumber $(cat "$workingDirectory/obsoleteVersion") + obsoleteVersion=$versionNumber + else + obsoleteVersion=999999999 + fi + if [ -f "$workingDirectory/firstCompatibleVersion" ]; then + versionStringToNumber $(cat "$workingDirectory/firstCompatibleVersion") + firstVersion=$versionNumber + else + firstVersion=0 + fi + + # append the package's existing file sets NOT in the stock versions + # to the END of the stock files list + # this insures these file sets contain only files used by that or other unused versions + sourceFileSets=($(ls -d "$sourceFiles"/v* 2> /dev/null)) + tempList=() + for entry in ${sourceFileSets[@]} ; do + version=$(basename $entry) + if [ ! -d "$stockFiles/$version" ]; then + versionStringToNumber $version + tempList+=($version:$versionNumber) + fi + done + existingFileSets=( $(echo ${tempList[@]} | tr ' ' '\n' | sort -t ':' -r -n -k 2 | uniq ) ) + allFileSets=(${stockVersionList[@]}) + allFileSets+=(${existingFileSets[@]}) + + # move incompatible versions to the end of the list + # so that real files end up in a supported file set + obsoleteFileSets=() + tempList=() + for entry in ${allFileSets[@]} ; do + IFS=':' read version versionNumber <<< "$entry" + if (( $versionNumber >= $obsoleteVersion )) || (( $versionNumber < $firstVersion )); then + obsoleteFileSets+=($version:$versionNumber) + else + tempList+=($version:$versionNumber) + fi + done + allFileSets=(${tempList[@]}) + allFileSets+=(${obsoleteFileSets[@]}) + allFileSetsLength=${#allFileSets[@]} + + # clean up flag files from a previous run + rm -f "$workingFiles"/*/INCOMPATIBLE_VERSION + rm -f "$workingFiles"/*/UNUSED_FILE_SET + rm -f "$workingFiles"/*/INCOMPLETE + rm -f "$workingFiles"/*/COMPLETE + rm -f "$workingFiles"/*/LINKS_ONLY + rm -f "$workingFiles"/*/*.NO_ORIG + rm -f "$workingFiles"/*/*.NO_REPLACEMENT + rm -f "$workingFiles"/*/*.NO_REPLACEMENT_LINK + rm -f "$workingFiles"/*/*.CHECK_REPLACEMENT + rm -f "$workingFiles"/*/NEW_FILE_SET + rm -f "$workingFiles"/*/*.MATCHES_PREVIOUS + + for (( i1 = 0; i1 < $allFileSetsLength; i1++ )); do + IFS=':' read version versionNumber <<< "${allFileSets[$i1]}" + + fileSet1="$workingFiles/$version" + if [ ! -d "$fileSet1" ]; then + mkdir "$fileSet1" + touch "$fileSet1/NEW_FILE_SET" + fi + # check to see if package is compatible with this Venus version + if (( $versionNumber >= $obsoleteVersion )) || (( $versionNumber < $firstVersion )); then + touch "$fileSet1/INCOMPATIBLE_VERSION" + fi + + done + + beginProgress "$package: updating file sets" + for file in $fileList ; do + baseName=$(basename "$file") + outputProgressTick "." + # use alternate original if present + if [ -f "$workingFiles/$baseName.ALT_ORIG" ]; then + useAltOrig=true + altOrigFile=$(cat "$workingFiles/$baseName.ALT_ORIG") + else + useAltOrig=false + altOrigFile="" + fi + + # move real files to newest file set + for (( i1 = 0; i1 < $allFileSetsLength; i1++ )); do + IFS=':' read version1 version1number <<< "${allFileSets[$i1]}" + fileSet1="$workingFiles/$version1" + stockFileSet1="$stockFiles/$version1" + # if stock file set does not exist, or this is an incompatible version + # don't move files here + # this will allow file sets for versions no longer supported to be removed + # an error result if a replacement in this version is needed for other file sets + if [ ! -d "$stockFileSet1" ] || [ -f "$fileSet1/INCOMPATIBLE_VERSION" ]; then + continue + fi + + replacement1="$fileSet1/$baseName" + replacement1exists=false + useOrigFlag1=false + if [ -f "$replacement1" ] && [ ! -L "$replacement1" ]; then + replacement1exists=true + elif [ -f "$replacement1.USE_ORIGINAL" ]; then + useOrigFlag1=true + fi + orig1="$fileSet1/$baseName.orig" + # select appropirate stock file + if $useAltOrig ; then + stockFile1="$stockFileSet1$altOrigFile" + else + stockFile1="$stockFileSet1$file" + fi + + if [ ! -f "$stockFile1" ]; then + if $useAltOrig ; then + logMessage "ERROR $package: $version1 $baseName stock file missing (move) - check ALT_ORIG" + touch "$fileSet1/$baseName.CHECK_ALT_ORIG" + else + logMessage "ERROR $package: $version1 $baseName stock file missing (move) - consider using an ALT_ORIG" + fi + touch "$fileSet1/$baseName.NO_STOCK_FILE" + touch "$fileSet1/INCOMPLETE" + logMessage "can't continue" + exit + fi + + # look for a match (stock files) in older file sets + # and relocate if found + checkLinks=false + for (( i2 = $i1 + 1; i2 < $allFileSetsLength; i2++ )); do + IFS=':' read version2 version2number <<< "${allFileSets[$i2]}" + fileSet2="$workingFiles/$version2" + replacement2="$fileSet2/$baseName" + orig2="$fileSet2/$baseName.orig" + + if [ -L "$replacement2" ] ; then + replacement2isLink=true + replacement2isRealFile=false + elif [ -f "$replacement2" ] ; then + replacement2isRealFile=true + replacement2isLink=false + else + replacement2isRealFile=false + replacement2isLink=false + fi + # USE_ORIGINAL is valid only if the original file also exists (and is not a sym link) + if [ -f "$replacement2.USE_ORIGINAL" ] && [ -f $orig2 ] && [ ! -L $orig2 ]; then + useOrigFlag2=true + else + useOrigFlag2=false + fi + if $replacement2isRealFile || $useOrigFlag2 || [ -f "$fileSet2/NEW_FILE_SET" ]; then + doStockCheck=true + else + doStockCheck=false + fi + + stockMatch=false + if $doStockCheck ; then + if [ -d "$stockFiles/$version2" ]; then + # select appropirate original file + if $useAltOrig ; then + stockFile2="$stockFiles/$version2$altOrigFile" + else + stockFile2="$stockFiles/$version2$file" + fi + if [ ! -f "$stockFile2" ]; then + if $useAltOrig ; then + logMessage "ERROR $package: $version2 $baseName stock file missing - check ALT_ORIG" + touch "$fileSet2/$baseName.CHECK_ALT_ORIG" + else + logMessage "ERROR $package: $version2 $baseName stock file missing - consider using an ALT_ORIG" + fi + touch "$fileSet2/$baseName.NO_STOCK_FILE" + touch "$fileSet2/INCOMPLETE" + logMessage "can't continue" + exit + fi + + # stock files match + cmp -s "$stockFile2" "$stockFile1" > /dev/null + if [ $? -eq 0 ]; then + stockMatch=true + fi + # no stock files but existing file set + elif ( $replacement2isRealFile || $useOrigFlag2 ) && [ -f "$orig2" ] ; then + # existing orig matches stock + cmp -s "$orig2" "$stockFile1" + if [ $? -eq 0 ] ;then + stockMatch=true + fi + fi + fi + if $stockMatch ; then + moveReplacement=true + if $replacement2isRealFile ; then + if $replacement1exists ; then + cmp -s "$replacement1" "$replacement2" /dev/null + if [ $? -ne 0 ]; then + logMessage "ERROR $package: $baseName $version1 and $version2 replacements differ but same stock files" + touch "$fileSet1/$baseName.CHECK_REPLACEMENT" + touch "$fileSet2/$baseName.CHECK_REPLACEMENT" + moveReplacement=false + fi + fi + if $moveReplacement ; then + mv -f "$replacement2" "$replacement1" + rm -f "$fileSet1/$baseName.USE_ORIGINAL" + cp -f "$stockFile1" "$orig1" + checkLinks=true + fi + elif $useOrigFlag2 ; then + if $replacement1exists ; then + logMessage "ERROR $package $basename file in $version1 conflicts with USE_ORIGINAL in $version2" + touch "$fileSet1/$baseName.CHECK_REPLACEMENT" + touch "$fileSet2/$baseName.CHECK_REPLACEMENT" + else + mv "$replacement2.USE_ORIGINAL" "$replacement1.USE_ORIGINAL" + rm -f "$replacement1" + checkLinks=true + fi + fi + + if [ -f "$orig2" ]; then + mv -f "$orig2" "$orig1" + fi + fi + done # for i2 + done # for i1 (update) + done # for file + + # check to see if a non-versioned file is appropriate -- but only if no errors were found + reloadFileList=false + if (( $packageErrors == 0 )) ; then + for file in $fileList ; do + realFileCount=0 + baseName=$(basename "$file") + + # file must be be using an alternate stock file + if [ ! -f "$workingFiles/$baseName.ALT_ORIG" ]; then + continue + fi + for (( i1 = 0; i1 < $allFileSetsLength; i1++ )); do + IFS=':' read version1 version1number <<< "${allFileSets[$i1]}" + fileSet1="$workingFiles/$version1" + replacement1="$fileSet1/$baseName" + if [ -f "$replacement1" ] && [ ! -L "$replacement1" ]; then + (( realFileCount += 1 )) + + fi + done + + if (( realFileCount == 1 )); then + yesNoPrompt "$package: $baseName - make version-independent (y / n)?: " + if $yesResponse ; then + logMessage "$baseName.ALT_ORIG.UNUSED and $(basename $fileListFile.old) can be removed" + mv -f "$workingFiles/$baseName.ALT_ORIG" "$workingFiles/$baseName.ALT_ORIG.UNUSED" + fileListFile="$workingFiles/fileList" + grep -v "$file" "$fileListFile" > "$fileListFile.tmp" + mv -f "$fileListFile" "$fileListFile.old" + mv -f "$fileListFile.tmp" "$fileListFile" + reloadFileList=true + for (( i1 = 0; i1 < $allFileSetsLength; i1++ )); do + IFS=':' read version1 version1number <<< "${allFileSets[$i1]}" + fileSet1="$workingFiles/$version1" + if [ ! -d "$fileSet1" ]; then + continue + fi + replacementFile="$fileSet1/$baseName" + if [ -L "$replacementFile" ]; then + rm -f "$replacementFile" + elif [ -f "$replacementFile" ]; then + mv "$replacementFile" "$workingFiles" + rm -f "$replacementFile.orig" + fi + done + else + logMessage "$baseName remains in version-dependent file sets" + fi + fi + done # for file (version independent check) + fi + + # reload fileList if changed above + if $reloadFileList ; then + fileList=$(cat "$workingFiles/fileList") + if [ -z "$fileList" ]; then + logMessage "WARNING $package: empty file list" + continue + fi + fi + + beginProgress "$package: final checks" + for (( i1 = 0; i1 < $allFileSetsLength; i1++ )); do + IFS=':' read version1 version1number <<< "${allFileSets[$i1]}" + fileSet1="$workingFiles/$version1" + if [ ! -d "$fileSet1" ]; then + continue + fi + outputProgressTick "." + + emptyFileSet=true + completeFileSet=true + for file in $fileList ; do + baseName=$(basename "$file") + + if [ -f "$workingFiles/$baseName.ALT_ORIG" ]; then + useAltOrig=true + altOrigFile=$(cat "$workingFiles/$baseName.ALT_ORIG") + else + useAltOrig=false + altOrigFile="" + fi + + replacement1="$fileSet1/$baseName" + orig1="$fileSet1/$baseName.orig" + + # remove a symlink if it exists - no longer used + if [ -L "$replacement1" ]; then + rm "$replacement1" + fi + if [ -f "$replacement1" ]; then + realReplacement=true + else + realReplacement=false + fi + if [ -f "$orig1" ]; then + origExists=true + else + origExists=false + fi + useOrigFlag=false + if [ -f "$replacement1.USE_ORIGINAL" ]; then + if ! $realReplacement ; then + useOrigFlag=true + else + logMessage "WARNING $package $version1 $baseName replacement exists - removing USE_ORIGINAL flag" + rm "$replacement1.USE_ORIGINAL" + fi + fi + + if $realReplacement || $useOrigFlag ; then + emptyFileSet=false + # if original is missing, fill it in from stock if it exists + if [ ! -f "$orig1" ] ; then + stockFileSet1="$stockFiles/$version1" + if $useAltOrig ; then + stockFile1="$stockFileSet1$altOrigFile" + else + stockFile1="$stockFileSet1$file" + fi + if [ -f "$stockFile1" ]; then + cp "$stockFile1" "$orig1" + else + logMessage "ERROR $package: $baseName $version1 no original available" + touch "$replacement1.NO_ORIG" + completeFileSet=false + fi + fi + else + completeFileSet=false + fi + + if [ -f "$replacement1.NO_REPLACEMENT" ] \ + || [ -f "$replacement1.CHECK_REPLACEMENT" ] \ + || [ -f "$replacement1.NO_ORIG" ] ; then + touch "$fileSet1/INCOMPLETE" + completeFileSet=false + fi + done # for file + + # if all replacement files are in place, mark the file set COMPLETE + # COMPLETE tells _checkFileSets to skip all checks and accept the file set as is + if $completeFileSet ; then + touch "$fileSet1/COMPLETE" + else + rm -f "$fileSet1/COMPLETE" + fi + + if $emptyFileSet ; then + if [ ! -f "$fileSet1/NEW_FILE_SET" ]; then + logMessage "WARNING $package: $version1 - removing empty file set" + fi + rm -Rf "$fileSet1" + + # remove file sets for incompatible Venus OS versions + elif [ -e "$fileSet1/INCOMPATIBLE_VERSION" ]; then + logMessage "WARNING $package: not compatible with Venus $version1 but not empty - consider manual removal" + # not in stock files list + elif [ ! -d "$stockFiles/$version1" ]; then + logMessage "WARNING $package: $version1 no longer used but not empty - manual remove is OK" + touch "$fileSet1/UNUSED_FILE_SET" + fi + + if [ -f "$fileSet1/NEW_FILE_SET" ]; then + logMessage "$package: new file set $version1" + rm -f "$fileSet1/NEW_FILE_SET" + fi + done # for i1 (final checks) + # remove temporary files + rm -f "$workingFiles/v"*/*tmp + + if [ "$packageErrors" == 0 ]; then + errorText="no errors " + else + errorText="$totalErrors ERRORS " + fi + if [ "$packageWarnings" == 0 ]; then + warningText="no warnings" + else + warningText="$totalWarnings WARNINGS" + fi + + logMessage "$package complete $errorText $warningText" + + baseName=$(basename $workingDirectory) + + if [ -z "$globalEndAction" ]; then + echo + echo "select to finish:" + echo " update $package (u)" + echo " preserve working copy for inspection (p)" + echo " discard working copy (d)" + while true ; do + read -p "choose action from list above (u / p / d): " response + case $response in + [uU]*) + endAction='update' + break + ;; + [pP]*) + endAction='preserve' + break + ;; + [dD]*) + endAction='delete' + break + ;; + *) + esac + done + else + endAction=$globalEndAction + fi + + case $endAction in + preserve) + logMessage "$package unchanged - changes preserved as $baseName" + ;; + delete) + logMessage "$package unchanged - $baseName removed" + deleteNestedDirectories "$workingDirectory" + ;; + update) + logMessage "$package: updating file sets - backup in $package.backup" + deleteNestedDirectories "$package.backup" + mkdir "$package.backup" + mv "$sourceFiles" "$package.backup" + if [ -f "$sourceDirectory/obsoleteVersion" ]; then + mv -f "$sourceDirectory/obsoleteVersion" "$package.backup" + fi + if [ -f "$sourceDirectory/firstCompatibleVersion" ]; then + mv -f "$sourceDirectory/firstCompatibleVersion" "$package.backup" + fi + + deleteNestedDirectories "$sourceFiles" + mv "$workingFiles" "$sourceFiles" + if [ -f "$workingDirectory/obsoleteVersion" ]; then + mv -f "$workingDirectory/obsoleteVersion" "$sourceDirectory" + fi + if [ -f "$workingDirectory/firstCompatibleVersion" ]; then + mv -f "$workingDirectory/firstCompatibleVersion" "$sourceDirectory" + fi + deleteNestedDirectories $workingDirectory + ;; + *) + logMessage "ERROR: invalid end action $endAction" + esac +done # for package + +# review all file sets and report any that only contain sym links across all packages +# it would be possile to remove those verions from stock files without loosing any data +# this check is only done if updating all file sets and there are no errors +if $doAllPackages && [ "$totalErrors" == 0 ]; then + for entry in ${stockVersionList[@]} ; do + IFS=':' read version versionNumber <<< "$entry" + linksOnly=true + for package in $packageList; do + fileSet="$packageRoot/$package/FileSets/$version" + if [ ! -e "$fileSet/LINKS_ONLY" ]; then + linksOnly=false + break + fi + done + if $linksOnly ; then + logMessage "$version: only links in all packages - stock version could be removed" + fi + done +fi + +if [ "$totalErrors" == 0 ]; then + errorText="no errors " +else + errorText="$totalErrors ERRORS " +fi +if [ "$totalWarnings" == 0 ]; then + warningText="no warnings" +else + warningText="$totalWarnings WARNINGS" +fi + +logMessage "updateFileSets complete $errorText $warningText" diff --git a/venus-data.UninstallPackages.tgz b/venus-data.UninstallPackages.tgz index 08b23c1..f82b966 100644 Binary files a/venus-data.UninstallPackages.tgz and b/venus-data.UninstallPackages.tgz differ diff --git a/venus-data.tgz b/venus-data.tgz index 85d3a40..1f3a550 100644 Binary files a/venus-data.tgz and b/venus-data.tgz differ diff --git a/version b/version index 95cd864..0b880fd 100644 --- a/version +++ b/version @@ -1 +1 @@ -v5.14 +v5.15