2016-09-14 18:17:27 +00:00
|
|
|
//
|
|
|
|
// Reset.swift
|
|
|
|
// mas-cli
|
|
|
|
//
|
|
|
|
// Created by Andrew Naylor on 14/09/2016.
|
|
|
|
// Copyright © 2016 Andrew Naylor. All rights reserved.
|
|
|
|
//
|
|
|
|
|
2018-07-04 20:56:10 +00:00
|
|
|
import Commandant
|
|
|
|
import Result
|
2018-10-14 19:41:19 +00:00
|
|
|
import CommerceKit
|
2018-07-04 20:56:10 +00:00
|
|
|
|
2019-01-12 01:28:03 +00:00
|
|
|
/// Kills several macOS processes as a means to reset the app store.
|
2018-10-14 21:35:48 +00:00
|
|
|
public struct ResetCommand: CommandProtocol {
|
|
|
|
public typealias Options = ResetOptions
|
|
|
|
public let verb = "reset"
|
|
|
|
public let function = "Resets the Mac App Store"
|
|
|
|
|
|
|
|
public init() {}
|
2018-12-27 21:02:14 +00:00
|
|
|
|
2019-01-12 01:28:03 +00:00
|
|
|
/// Runs the command.
|
2018-10-14 21:35:48 +00:00
|
|
|
public func run(_ options: Options) -> Result<(), MASError> {
|
2016-09-14 18:17:27 +00:00
|
|
|
/*
|
|
|
|
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)
|
2018-12-27 21:02:14 +00:00
|
|
|
|
2016-09-14 18:17:27 +00:00
|
|
|
As storeagent no longer exists we will implement a slight variant and kill all
|
|
|
|
App Store-associated processes
|
|
|
|
- storeaccountd
|
|
|
|
- storeassetd
|
|
|
|
- storedownloadd
|
|
|
|
- storeinstalld
|
|
|
|
- storelegacy
|
|
|
|
*/
|
2018-12-27 21:02:14 +00:00
|
|
|
|
2016-09-14 18:17:27 +00:00
|
|
|
// Kill processes
|
|
|
|
let killProcs = [
|
|
|
|
"Dock",
|
|
|
|
"storeaccountd",
|
|
|
|
"storeassetd",
|
|
|
|
"storedownloadd",
|
|
|
|
"storeinstalld",
|
2019-01-12 01:06:02 +00:00
|
|
|
"storelegacy"
|
2016-09-14 18:17:27 +00:00
|
|
|
]
|
2018-12-27 21:02:14 +00:00
|
|
|
|
2016-09-17 12:58:38 +00:00
|
|
|
let kill = Process()
|
|
|
|
let stdout = Pipe()
|
|
|
|
let stderr = Pipe()
|
2018-12-27 21:02:14 +00:00
|
|
|
|
2016-09-14 18:17:27 +00:00
|
|
|
kill.launchPath = "/usr/bin/killall"
|
|
|
|
kill.arguments = killProcs
|
|
|
|
kill.standardOutput = stdout
|
|
|
|
kill.standardError = stderr
|
2018-12-27 21:02:14 +00:00
|
|
|
|
2016-09-14 18:17:27 +00:00
|
|
|
kill.launch()
|
|
|
|
kill.waitUntilExit()
|
2018-12-27 21:02:14 +00:00
|
|
|
|
2016-09-14 18:17:27 +00:00
|
|
|
if kill.terminationStatus != 0 && options.debug {
|
|
|
|
let output = stderr.fileHandleForReading.readDataToEndOfFile()
|
2016-09-25 21:57:11 +00:00
|
|
|
printInfo("killall failed:\r\n\(String(data: output, encoding: String.Encoding.utf8)!)")
|
2016-09-14 18:17:27 +00:00
|
|
|
}
|
2018-12-27 21:02:14 +00:00
|
|
|
|
2016-09-14 18:17:27 +00:00
|
|
|
// Wipe Download Directory
|
2018-01-26 23:32:28 +00:00
|
|
|
if let directory = CKDownloadDirectory(nil) {
|
|
|
|
do {
|
|
|
|
try FileManager.default.removeItem(atPath: directory)
|
|
|
|
} catch {
|
|
|
|
if options.debug {
|
|
|
|
printError("removeItemAtPath:\"\(directory)\" failed, \(error)")
|
|
|
|
}
|
2016-09-14 18:17:27 +00:00
|
|
|
}
|
|
|
|
}
|
2018-10-14 21:35:48 +00:00
|
|
|
|
2016-09-17 12:58:38 +00:00
|
|
|
return .success(())
|
2016-09-14 18:17:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-14 21:35:48 +00:00
|
|
|
public struct ResetOptions: OptionsProtocol {
|
2016-09-14 18:17:27 +00:00
|
|
|
let debug: Bool
|
2018-10-14 21:35:48 +00:00
|
|
|
|
|
|
|
public static func create(debug: Bool) -> ResetOptions {
|
2016-09-17 12:58:38 +00:00
|
|
|
return ResetOptions(debug: debug)
|
|
|
|
}
|
2018-10-14 21:35:48 +00:00
|
|
|
|
2019-01-12 01:06:02 +00:00
|
|
|
public static func evaluate(_ mode: CommandMode) -> Result<ResetOptions, CommandantError<MASError>> {
|
2016-09-17 12:58:38 +00:00
|
|
|
return create
|
2019-01-12 01:06:02 +00:00
|
|
|
<*> mode <| Switch(flag: nil, key: "debug", usage: "Enable debug mode")
|
2016-09-14 18:17:27 +00:00
|
|
|
}
|
|
|
|
}
|