From a0100c994f6b2d1bae37a809f0d8bc52b634a4e5 Mon Sep 17 00:00:00 2001 From: Serhiy Mytrovtsiy Date: Thu, 9 Jul 2020 22:34:19 +0200 Subject: [PATCH] - another fix of update mechanism (hdiutil block dmg mounting when call it from bash, moved a mostly all logic to swift) --- Stats.xcodeproj/project.pbxproj | 4 +-- Stats/AppDelegate.swift | 14 ++++++--- Stats/Supporting Files/Info.plist | 2 +- StatsKit/extensions.swift | 16 ++++++++++ StatsKit/updater.sh | 49 +++++-------------------------- StatsKit/updater.swift | 14 +++++++-- 6 files changed, 48 insertions(+), 51 deletions(-) diff --git a/Stats.xcodeproj/project.pbxproj b/Stats.xcodeproj/project.pbxproj index c9654bb4..9708e3d9 100644 --- a/Stats.xcodeproj/project.pbxproj +++ b/Stats.xcodeproj/project.pbxproj @@ -1695,7 +1695,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 2.1.9; + MARKETING_VERSION = 2.1.10; PRODUCT_BUNDLE_IDENTIFIER = eu.exelban.Stats; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1727,7 +1727,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 2.1.9; + MARKETING_VERSION = 2.1.10; PRODUCT_BUNDLE_IDENTIFIER = eu.exelban.Stats; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/Stats/AppDelegate.swift b/Stats/AppDelegate.swift index cea20280..3b5e90bf 100755 --- a/Stats/AppDelegate.swift +++ b/Stats/AppDelegate.swift @@ -137,11 +137,17 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele } } - if let dmgIndex = args.firstIndex(of: "--dmg") { + if let mountIndex = args.firstIndex(of: "--mount-path") { + if args.indices.contains(mountIndex+1) { + let mountPath = args[mountIndex+1] + asyncShell("/usr/bin/hdiutil detach \(mountPath)") + asyncShell("/bin/rm -rf \(mountPath)") + } + } + + if let dmgIndex = args.firstIndex(of: "--dmg-path") { if args.indices.contains(dmgIndex+1) { - let dmgPath = args[dmgIndex+1] - let pwd = Bundle.main.bundleURL.absoluteString.replacingOccurrences(of: "file://", with: "").replacingOccurrences(of: "Stats.app/", with: "") - asyncShell("sh \(pwd)/Stats.app/Contents/Resources/Scripts/updater.sh --step 3 --dmg \(dmgPath)") + asyncShell("/bin/rm -rf \(args[dmgIndex+1])") } } } diff --git a/Stats/Supporting Files/Info.plist b/Stats/Supporting Files/Info.plist index abef6918..17eb06db 100755 --- a/Stats/Supporting Files/Info.plist +++ b/Stats/Supporting Files/Info.plist @@ -17,7 +17,7 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - 14 + 16 Description Simple macOS system monitor in your menu bar LSApplicationCategoryType diff --git a/StatsKit/extensions.swift b/StatsKit/extensions.swift index 7916bc64..5925800b 100644 --- a/StatsKit/extensions.swift +++ b/StatsKit/extensions.swift @@ -651,6 +651,22 @@ public func asyncShell(_ args: String) { task.launch() } +public func syncShell(_ args: String) -> String { + let task = Process() + task.launchPath = "/bin/sh" + task.arguments = ["-c", args] + let pipe = Pipe() + + task.standardOutput = pipe + task.launch() + task.waitUntilExit() + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + let output = String(data: data, encoding: .utf8)! + + return output +} + public func colorFromString(_ colorString: String) -> NSColor { switch colorString { case "black": diff --git a/StatsKit/updater.sh b/StatsKit/updater.sh index 845b2fee..6e5aba68 100644 --- a/StatsKit/updater.sh +++ b/StatsKit/updater.sh @@ -1,54 +1,19 @@ #!/bin/bash -STEP=1 - -CURRENT_PATH="" DMG_PATH="$HOME/Download/Stats.dmg" MOUNT_PATH="/tmp/Stats" -APP_PATH="" -PID="" +APPLICATION_PATH="/Applications/" while [[ "$#" > 0 ]]; do case $1 in -d|--dmg) DMG_PATH="$2"; shift;; - -s|--step) STEP="$2"; shift;; - -a|--app) APP_PATH="$2"; shift;; - -p|--pid) PID="$2"; shift;; - -c|--current) CURRENT_PATH="$2"; shift;; + -a|--app) APPLICATION_PATH="$2"; shift;; + -m|--mount) MOUNT_PATH="$2"; shift;; *) echo "Unknown parameter passed: $1"; exit 1;; esac; shift; done -echo "Starting step #$STEP" +rm -rf $APPLICATION_PATH/Stats.app +cp -rf $MOUNT_PATH/Stats.app $APPLICATION_PATH/Stats.app -if [[ "$STEP" == "1" ]]; then - if [ -d "$MOUNT_PATH" ]; then - /usr/bin/hdiutil detach "$MOUNT_PATH" - if [ -d "$MOUNT_PATH" ]; then - /bin/rm -rf "$MOUNT_PATH" - fi - fi +$APPLICATION_PATH/Stats.app/Contents/MacOS/Stats --dmg-path "$DMG_PATH" --mount-path "$MOUNT_PATH" - /usr/bin/mktemp -d $MOUNT_PATH - /usr/bin/hdiutil attach "$DMG_PATH" -mountpoint "$MOUNT_PATH" -noverify -nobrowse -noautoopen - - cp $MOUNT_PATH/Stats.app/Contents/Resources/Scripts/updater.sh $TMPDIR/updater.sh - sh $TMPDIR/updater.sh --step 2 --app "$CURRENT_PATH" --dmg "$DMG_PATH" >/dev/null & - - kill -9 $PID - - echo "DMG is mounted under $MOUNT_PATH. Starting step #2" -elif [[ "$STEP" == "2" ]]; then - rm -rf $APP_PATH/Stats.app - cp -rf $MOUNT_PATH/Stats.app $APP_PATH/Stats.app - - $APP_PATH/Stats.app/Contents/MacOS/Stats --dmg "$DMG_PATH" - - echo "New version started" -elif [[ "$STEP" == "3" ]]; then - /usr/bin/hdiutil detach "$MOUNT_PATH" - /bin/rm -rf "$MOUNT_PATH" - /bin/rm -rf "$DMG_PATH" - - echo "Done" -else - echo "Step not defined" -fi +echo "New version started" diff --git a/StatsKit/updater.swift b/StatsKit/updater.swift index c49cdb65..1a07c1b1 100644 --- a/StatsKit/updater.swift +++ b/StatsKit/updater.swift @@ -111,9 +111,19 @@ public class macAppUpdater { return } + _ = syncShell("mkdir /tmp/Stats") // make sure that directory exist + let res = syncShell("/usr/bin/hdiutil attach \(path) -mountpoint /tmp/Stats -noverify -nobrowse -noautoopen") // mount the dmg + + if res.contains("is busy") { // dmg can be busy, if yes, unmount it and mount again + _ = syncShell("/usr/bin/hdiutil detach $TMPDIR/Stats") + _ = syncShell("/usr/bin/hdiutil attach \(path) -mountpoint /tmp/Stats -noverify -nobrowse -noautoopen") + } + + _ = syncShell("cp $TMPDIR/Stats/app/Stats.app/Contents/Resources/Scripts/updater.sh $TMPDIR/Stats/updater.sh") // copy updater script to tmp folder + let pwd = Bundle.main.bundleURL.absoluteString.replacingOccurrences(of: "file://", with: "").replacingOccurrences(of: "Stats.app/", with: "") - let pid: Int32 = ProcessInfo.processInfo.processIdentifier - asyncShell("sh \(pwd)/Stats.app/Contents/Resources/Scripts/updater.sh --current \(pwd) --dmg \(url) --pid \(pid)") + asyncShell("sh $TMPDIR/updater.sh --step 2 --app \(pwd) --dmg \(path) >/dev/null &") // run updater script in in background + exit(0) } } catch { print ("file error: \(error)")