diff --git a/Sources/mas/Commands/Uninstall.swift b/Sources/mas/Commands/Uninstall.swift index 25f8a6f..4e1e591 100644 --- a/Sources/mas/Commands/Uninstall.swift +++ b/Sources/mas/Commands/Uninstall.swift @@ -35,7 +35,7 @@ extension Mas { if dryRun { for installedApp in installedApps { - printInfo("\(installedApp.appName) \(installedApp.bundlePath)") + printInfo("'\(installedApp.appName)' '\(installedApp.bundlePath)'") } printInfo("(not removed, dry run)") } else { diff --git a/Sources/mas/Controllers/MasAppLibrary.swift b/Sources/mas/Controllers/MasAppLibrary.swift index 9325af4..cb3b45f 100644 --- a/Sources/mas/Controllers/MasAppLibrary.swift +++ b/Sources/mas/Controllers/MasAppLibrary.swift @@ -38,8 +38,8 @@ class MasAppLibrary: AppLibrary { /// - Parameter app: App to be removed. /// - Throws: Error if there is a problem. func uninstallApp(app: SoftwareProduct) throws { - if !userIsRoot() { - printWarning("Apps installed from the Mac App Store require root permission to remove.") + if NSUserName() != "root" { + throw MASError.macOSUserMustBeRoot } let appUrl = URL(fileURLWithPath: app.bundlePath) @@ -55,11 +55,4 @@ class MasAppLibrary: AppLibrary { throw MASError.uninstallFailed } } - - /// Detects whether the current user is root. - /// - /// - Returns: true if the current user is root; false otherwise - private func userIsRoot() -> Bool { - NSUserName() == "root" - } } diff --git a/Sources/mas/Errors/MASError.swift b/Sources/mas/Errors/MASError.swift index 7065673..4eba734 100644 --- a/Sources/mas/Errors/MASError.swift +++ b/Sources/mas/Errors/MASError.swift @@ -29,6 +29,7 @@ enum MASError: Error, Equatable { case notInstalled(appID: AppID) case uninstallFailed + case macOSUserMustBeRoot case noData case jsonParsing(data: Data?) @@ -84,6 +85,8 @@ extension MASError: CustomStringConvertible { return "No apps installed with app ID \(appID)" case .uninstallFailed: return "Uninstall failed" + case .macOSUserMustBeRoot: + return "Apps installed from the Mac App Store require root permission to remove." case .noData: return "Service did not return data" case .jsonParsing(let data): diff --git a/Tests/masTests/Commands/UninstallSpec.swift b/Tests/masTests/Commands/UninstallSpec.swift index 2d171cf..c2587fc 100644 --- a/Tests/masTests/Commands/UninstallSpec.swift +++ b/Tests/masTests/Commands/UninstallSpec.swift @@ -43,9 +43,11 @@ public class UninstallSpec: QuickSpec { it("finds an app") { mockLibrary.installedApps.append(app) expect { - try uninstall.run(appLibrary: mockLibrary) + try captureStream(stdout) { + try uninstall.run(appLibrary: mockLibrary) + } } - .toNot(throwError()) + == "==> 'Some App' '/tmp/Some.app'\n==> (not removed, dry run)\n" } } context("wet run") { @@ -67,12 +69,12 @@ public class UninstallSpec: QuickSpec { try uninstall.run(appLibrary: mockLibrary) } } - == "==> Some App /tmp/Some.app\n==> (not removed, dry run)\n" + .toNot(throwError()) } it("fails if there is a problem with the trash command") { - var brokenUninstall = app - brokenUninstall.bundlePath = "/dev/null" - mockLibrary.installedApps.append(brokenUninstall) + var brokenApp = app + brokenApp.bundlePath = "/dev/null" + mockLibrary.installedApps.append(brokenApp) expect { try uninstall.run(appLibrary: mockLibrary) }