diff --git a/Stats.xcodeproj/project.pbxproj b/Stats.xcodeproj/project.pbxproj index a522f54a..80f1bc30 100644 --- a/Stats.xcodeproj/project.pbxproj +++ b/Stats.xcodeproj/project.pbxproj @@ -111,6 +111,8 @@ 9AE29AFB249A53DC0071B02D /* readers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AE29AF9249A53780071B02D /* readers.swift */; }; 9AE29AFC249A53DC0071B02D /* values.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AE29AF7249A53420071B02D /* values.swift */; }; 9AE29AFE249A82B70071B02D /* Sensors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AE29AFD249A82B70071B02D /* Sensors.swift */; }; + 9AECEF3B24ACF7BA00DB95D4 /* updater.sh in Resources */ = {isa = PBXBuildFile; fileRef = 9AECEF3A24ACF7BA00DB95D4 /* updater.sh */; }; + 9AECEF3E24ACF9A500DB95D4 /* updater.sh in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9AECEF3A24ACF7BA00DB95D4 /* updater.sh */; }; 9AF9EE0924648751005D2270 /* Disk.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AF9EE0224648751005D2270 /* Disk.framework */; }; 9AF9EE0A24648751005D2270 /* Disk.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9AF9EE0224648751005D2270 /* Disk.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 9AF9EE0F2464875F005D2270 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AF9EE0E2464875F005D2270 /* main.swift */; }; @@ -372,6 +374,16 @@ name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; + 9AECEF3D24ACF98800DB95D4 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = Scripts; + dstSubfolderSpec = 7; + files = ( + 9AECEF3E24ACF9A500DB95D4 /* updater.sh in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 9AF9EE1824649BAD005D2270 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -462,6 +474,7 @@ 9AE29AF7249A53420071B02D /* values.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = values.swift; path = Modules/Sensors/values.swift; sourceTree = SOURCE_ROOT; }; 9AE29AF9249A53780071B02D /* readers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = readers.swift; path = Modules/Sensors/readers.swift; sourceTree = SOURCE_ROOT; }; 9AE29AFD249A82B70071B02D /* Sensors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sensors.swift; sourceTree = ""; }; + 9AECEF3A24ACF7BA00DB95D4 /* updater.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = updater.sh; sourceTree = ""; }; 9AF9EE0224648751005D2270 /* Disk.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Disk.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9AF9EE0524648751005D2270 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9AF9EE0E2464875F005D2270 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; @@ -580,6 +593,7 @@ 9A0C82DD24460F7200FAE3D4 /* Info.plist */, 9A9D728924471FAE005CF997 /* SMC.swift */, 9A81C76F2449B8D500825D92 /* Charts.swift */, + 9AECEF3A24ACF7BA00DB95D4 /* updater.sh */, ); path = StatsKit; sourceTree = ""; @@ -746,9 +760,9 @@ 9AABEB65243FCE8A00668CB0 /* CPU */, 9A81C7572449A41400825D92 /* Memory */, 9AF9EE0324648751005D2270 /* Disk */, + 9AE29AD6249A50350071B02D /* Sensors */, 9A3E17CD247A94AF00449CD1 /* Net */, 9ABFF8F7248BEBCB00C9041A /* Battery */, - 9AE29AD6249A50350071B02D /* Sensors */, ); path = Modules; sourceTree = ""; @@ -883,6 +897,7 @@ 9A1410F3229E721100D29793 /* Resources */, 9AB54DAE22A19F96006192E0 /* Copy Files */, 9A6698E72326AB16001D00E1 /* Embed Frameworks */, + 9AECEF3D24ACF98800DB95D4 /* CopyFiles */, ); buildRules = ( ); @@ -1157,6 +1172,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 9AECEF3B24ACF7BA00DB95D4 /* updater.sh in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1667,7 +1683,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = ""; - CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; @@ -1699,7 +1715,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = ""; - CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; diff --git a/Stats/AppDelegate.swift b/Stats/AppDelegate.swift index 84808617..aa7607e8 100755 --- a/Stats/AppDelegate.swift +++ b/Stats/AppDelegate.swift @@ -127,6 +127,14 @@ class AppDelegate: NSObject, NSApplicationDelegate { } } } + + if let dmgIndex = args.firstIndex(of: "--dmg") { + 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)") + } + } } private func defaultValues() { diff --git a/StatsKit/extensions.swift b/StatsKit/extensions.swift index 02f9b7c5..6d9836c6 100644 --- a/StatsKit/extensions.swift +++ b/StatsKit/extensions.swift @@ -602,3 +602,12 @@ public func dialogOKCancel(question: String, text: String) { alert.addButton(withTitle: "Cancel") alert.runModal() } + +public func asyncShell(_ args: String) { + let task = Process() + task.launchPath = "/bin/sh" + task.arguments = ["-c", args] + let pipe = Pipe() + task.standardOutput = pipe + task.launch() +} diff --git a/StatsKit/updater.sh b/StatsKit/updater.sh new file mode 100644 index 00000000..0701c9b5 --- /dev/null +++ b/StatsKit/updater.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +STEP=1 + +CURRENT_PATH="" +DMG_PATH="$HOME/Download/Stats.dmg" +MOUNT_PATH="/tmp/Stats" +APP_PATH="" +PID="" + +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;; + *) echo "Unknown parameter passed: $1"; exit 1;; +esac; shift; done + +echo "Starting step #$STEP" + +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 + + /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 $MOUNT_PATH/updater.sh + sh $MOUNT_PATH/updater.sh --step 2 --app "$CURRENT_PATH" --dmg "$DMG_PATH" & + + 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 diff --git a/StatsKit/updater.swift b/StatsKit/updater.swift index a80fcaa4..b0ba5328 100644 --- a/StatsKit/updater.swift +++ b/StatsKit/updater.swift @@ -136,7 +136,9 @@ public class macAppUpdater { return } - self.openDMG(url: path) + 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)") } } catch { print ("file error: \(error)") @@ -171,19 +173,6 @@ public class macAppUpdater { } } - private func openDMG(url: String) { - let task = Process() - task.launchPath = "/usr/bin/hdiutil" - task.arguments = ["attach", url] - - let pipe = Pipe() - task.standardOutput = pipe - task.launch() - task.waitUntilExit() - - exit(0) - } - // https://stackoverflow.com/questions/30743408/check-for-internet-connection-with-swift private func isConnectedToNetwork() -> Bool { var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))