From 8af169a5335b42fe19449d6442d59ba43da4d318 Mon Sep 17 00:00:00 2001 From: Andrew Naylor Date: Wed, 14 Sep 2016 09:17:42 +0100 Subject: [PATCH 1/2] Preparing release 1.2.2 --- mas-cli/mas-cli-Info.plist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mas-cli/mas-cli-Info.plist b/mas-cli/mas-cli-Info.plist index 5abe54c..e81731c 100644 --- a/mas-cli/mas-cli-Info.plist +++ b/mas-cli/mas-cli-Info.plist @@ -11,6 +11,6 @@ CFBundleName mas-cli CFBundleShortVersionString - 1.2.0 + 1.2.2 From 9c6ae2f311b87737e6ba1f597c88ba779d65a8e9 Mon Sep 17 00:00:00 2001 From: Andrew Naylor Date: Wed, 14 Sep 2016 19:17:27 +0100 Subject: [PATCH 2/2] Implement `mas reset` Replicates the `Reset Application` functionality of the Mac App Store Debug menu --- mas-cli.xcodeproj/project.pbxproj | 4 ++ mas-cli/Commands/Reset.swift | 81 +++++++++++++++++++++++++++++++ mas-cli/main.swift | 1 + mas-cli/mas-cli-Bridging-Header.h | 2 + 4 files changed, 88 insertions(+) create mode 100644 mas-cli/Commands/Reset.swift diff --git a/mas-cli.xcodeproj/project.pbxproj b/mas-cli.xcodeproj/project.pbxproj index aa55b47..a4ea7be 100644 --- a/mas-cli.xcodeproj/project.pbxproj +++ b/mas-cli.xcodeproj/project.pbxproj @@ -32,6 +32,7 @@ EDA3BE521B8B84AF00C18D70 /* SSPurchase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA3BE511B8B84AF00C18D70 /* SSPurchase.swift */; }; EDB6CE8C1BAEC3D400648B4D /* Version.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDB6CE8B1BAEC3D400648B4D /* Version.swift */; }; EDC90B651C70045E0019E396 /* SignIn.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC90B641C70045E0019E396 /* SignIn.swift */; }; + EDCBF9531D89AC6F000039C6 /* Reset.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDCBF9521D89AC6F000039C6 /* Reset.swift */; }; EDD3B3631C34709400B56B88 /* Upgrade.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDD3B3621C34709400B56B88 /* Upgrade.swift */; }; EDE296531C700F4300554778 /* SignOut.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDE296521C700F4300554778 /* SignOut.swift */; }; EDEAA0C01B51CE6200F2FC3F /* StoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDEAA0BF1B51CE6200F2FC3F /* StoreFoundation.framework */; }; @@ -91,6 +92,7 @@ EDB6CE8B1BAEC3D400648B4D /* Version.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Version.swift; sourceTree = ""; }; EDC90B621C6FF50B0019E396 /* ISAccountService-Protocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ISAccountService-Protocol.h"; sourceTree = ""; }; EDC90B641C70045E0019E396 /* SignIn.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignIn.swift; sourceTree = ""; }; + EDCBF9521D89AC6F000039C6 /* Reset.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Reset.swift; sourceTree = ""; }; EDD3B3621C34709400B56B88 /* Upgrade.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Upgrade.swift; sourceTree = ""; }; EDE2964F1C700B0300554778 /* ISAuthenticationContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISAuthenticationContext.h; sourceTree = ""; }; EDE296501C700B0300554778 /* ISServiceRemoteObject-Protocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ISServiceRemoteObject-Protocol.h"; sourceTree = ""; }; @@ -206,6 +208,7 @@ ED0F237E1B87522400AE40CD /* Install.swift */, ED0F23821B87533A00AE40CD /* List.swift */, ED0F23841B87536A00AE40CD /* Outdated.swift */, + EDCBF9521D89AC6F000039C6 /* Reset.swift */, 693A98981CBFFA760004D3B4 /* Search.swift */, EDC90B641C70045E0019E396 /* SignIn.swift */, EDE296521C700F4300554778 /* SignOut.swift */, @@ -369,6 +372,7 @@ 30EA893640B02CCF679F9C57 /* Option.swift in Sources */, ED0F23851B87536A00AE40CD /* Outdated.swift in Sources */, ED0F23891B87543D00AE40CD /* PurchaseDownloadObserver.swift in Sources */, + EDCBF9531D89AC6F000039C6 /* Reset.swift in Sources */, 0EBF5CDD379D7462C3389536 /* Result.swift in Sources */, 319FDBA6ED6443A912B9A65F /* ResultType.swift in Sources */, 693A98991CBFFA760004D3B4 /* Search.swift in Sources */, diff --git a/mas-cli/Commands/Reset.swift b/mas-cli/Commands/Reset.swift new file mode 100644 index 0000000..6bfb9eb --- /dev/null +++ b/mas-cli/Commands/Reset.swift @@ -0,0 +1,81 @@ +// +// Reset.swift +// mas-cli +// +// Created by Andrew Naylor on 14/09/2016. +// Copyright © 2016 Andrew Naylor. All rights reserved. +// + +struct ResetCommand: CommandType { + typealias Options = ResetOptions + let verb = "reset" + let function = "Resets the Mac App Store" + + func run(options: Options) -> Result<(), MASError> { + /* + The "Reset Application" command in the Mac App Store debug menu performs + the following steps + + - killall Dock + - killall storeagent (storeagent no longer exists) + - rm com.apple.appstore download directory + - clear cookies (appears to be a no-op) + + As storeagent no longer exists we will implement a slight variant and kill all + App Store-associated processes + - storeaccountd + - storeassetd + - storedownloadd + - storeinstalld + - storelegacy + */ + + // Kill processes + let killProcs = [ + "Dock", + "storeaccountd", + "storeassetd", + "storedownloadd", + "storeinstalld", + "storelegacy", + ] + + let kill = NSTask() + let stdout = NSPipe() + let stderr = NSPipe() + + kill.launchPath = "/usr/bin/killall" + kill.arguments = killProcs + kill.standardOutput = stdout + kill.standardError = stderr + + kill.launch() + kill.waitUntilExit() + + if kill.terminationStatus != 0 && options.debug { + let output = stderr.fileHandleForReading.readDataToEndOfFile() + print("==> killall failed:\r\n\(String(data: output, encoding: NSUTF8StringEncoding)!)") + } + + // Wipe Download Directory + let directory = CKDownloadDirectory(nil) + do { + try NSFileManager.defaultManager().removeItemAtPath(directory) + } catch { + if options.debug { + print("removeItemAtPath:\"\(directory)\" failed, \(error)") + } + } + + return .Success(()) + } +} + +struct ResetOptions: OptionsType { + let debug: Bool + + static func evaluate(m: CommandMode) -> Result> { + return curry(ResetOptions.init) + <*> m <| Switch(flag: nil, key: "debug", usage: "Enable debug mode") + } +} diff --git a/mas-cli/main.swift b/mas-cli/main.swift index 4663635..0a41904 100644 --- a/mas-cli/main.swift +++ b/mas-cli/main.swift @@ -20,6 +20,7 @@ registry.register(AccountCommand()) registry.register(InstallCommand()) registry.register(ListCommand()) registry.register(OutdatedCommand()) +registry.register(ResetCommand()) registry.register(SearchCommand()) registry.register(SignInCommand()) registry.register(SignOutCommand()) diff --git a/mas-cli/mas-cli-Bridging-Header.h b/mas-cli/mas-cli-Bridging-Header.h index f5e635a..e169f88 100644 --- a/mas-cli/mas-cli-Bridging-Header.h +++ b/mas-cli/mas-cli-Bridging-Header.h @@ -39,4 +39,6 @@ @end +NSString* CKDownloadDirectory(NSString *target); + #endif /* mas_cli_Bridging_Header_h */