Skip to content

Commit

Permalink
Add force_unwrapping rule to SwiftLint (PlayCover#753)
Browse files Browse the repository at this point in the history
* Remove force unwraps

* Remove UIF

* Fixes

* Merge fixes

* SwiftLint

* Fixes

* Fix errors

* Fix typo

* Remove unnecessary function

* Cleanup shell

Still got a couple things to fix up

* Fix lldb

* Fix put IPA back
  • Loading branch information
IsaacMarovitz committed Mar 11, 2023
1 parent c42cc67 commit df96821
Show file tree
Hide file tree
Showing 26 changed files with 219 additions and 284 deletions.
4 changes: 2 additions & 2 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
disabled_rules:
- inclusive_language
opt_in_rules:
- force_unwrapping

excluded:
- Carthage
Expand Down
12 changes: 0 additions & 12 deletions PlayCover.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
532644DE26E79E56002EA34D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 532644E026E79E56002EA34D /* Localizable.strings */; };
53D9DAF326C1849D0071959E /* PlayCoverError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53D9DAF226C1849D0071959E /* PlayCoverError.swift */; };
53F3802826EB6F6B00D6B525 /* NotifyService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53F3802726EB6F6B00D6B525 /* NotifyService.swift */; };
53F4D29E26C43C040020167C /* UserIntentFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53F4D29D26C43C040020167C /* UserIntentFlow.swift */; };
53F4D2A026C43C690020167C /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53F4D29F26C43C690020167C /* Log.swift */; };
53F50C4926E3CA42007AD2D3 /* AppLibraryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53F50C4826E3CA42007AD2D3 /* AppLibraryView.swift */; };
68E48B952957046D00C39879 /* DownloadManager in Frameworks */ = {isa = PBXBuildFile; productRef = 68E48B942957046D00C39879 /* DownloadManager */; };
Expand Down Expand Up @@ -107,7 +106,6 @@
53E3311126F574B600217197 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = "<group>"; };
53F3802526EB6CEA00D6B525 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = "<group>"; };
53F3802726EB6F6B00D6B525 /* NotifyService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotifyService.swift; sourceTree = "<group>"; };
53F4D29D26C43C040020167C /* UserIntentFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIntentFlow.swift; sourceTree = "<group>"; };
53F4D29F26C43C690020167C /* Log.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Log.swift; sourceTree = "<group>"; };
53F50C4826E3CA42007AD2D3 /* AppLibraryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLibraryView.swift; sourceTree = "<group>"; };
6854C5E528D53C9500CE28A0 /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = fa.lproj/Localizable.strings; sourceTree = "<group>"; };
Expand Down Expand Up @@ -273,14 +271,6 @@
path = Model;
sourceTree = "<group>";
};
53F4D29C26C43BED0020167C /* IntentFlow */ = {
isa = PBXGroup;
children = (
53F4D29D26C43C040020167C /* UserIntentFlow.swift */,
);
path = IntentFlow;
sourceTree = "<group>";
};
53F5E73B26C1C566005AED1D /* AppInstaller */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -400,7 +390,6 @@
AA970FD228793A310099A5D0 /* PlayCoverRelease.entitlements */,
53D9DAF226C1849D0071959E /* PlayCoverError.swift */,
53F3802626EB6F5600D6B525 /* Services */,
53F4D29C26C43BED0020167C /* IntentFlow */,
53F4D29926C43A390020167C /* Model */,
53F5E74126C1D369005AED1D /* Utils */,
53F5E73E26C1C654005AED1D /* ViewModel */,
Expand Down Expand Up @@ -655,7 +644,6 @@
6E5C68BA289865C8008EC11B /* MainView.swift in Sources */,
28361D6028927CAC00B35EDB /* SaveGenshinUserData.swift in Sources */,
B1419FB628BA82EE000CB69F /* DiscordActivity.swift in Sources */,
53F4D29E26C43C040020167C /* UserIntentFlow.swift in Sources */,
6E66B0BF289DE6240099B907 /* StoreVM.swift in Sources */,
B6603E1328E2257800DEFA3F /* Uninstaller.swift in Sources */,
B6ABDA2A2971EEF700A46E80 /* ProgressVM.swift in Sources */,
Expand Down
50 changes: 26 additions & 24 deletions PlayCover/AppInstaller/Downloader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ class DownloadApp {
if installVM.inProgress {
Log.shared.error(PlayCoverError.waitInstallation)
} else {
if let warningMessage = warning {
if let warningMessage = warning, let app = app {
let alert = NSAlert()
alert.messageText = NSLocalizedString(warningMessage, comment: "")
alert.informativeText = String(
format: NSLocalizedString("ipaLibrary.alert.download", comment: ""),
arguments: [app!.name]
arguments: [app.name]
)
alert.alertStyle = .warning
alert.addButton(withTitle: NSLocalizedString("button.Yes", comment: ""))
Expand Down Expand Up @@ -109,29 +109,32 @@ class DownloadApp {
in: .userDomainMask,
appropriateFor: URL(fileURLWithPath: "/Users"),
create: true)
downloader.addDownload(url: url!,
destinationURL: tmpDir!,
onProgress: { progress in
// progress is a Float
self.downloadVM.progress = Double(progress)
}, onCompletion: { error, fileURL in
self.downloadVM.next(.integrity, 0.7, 0.95)

guard error == nil else {
self.downloadVM.next(.failed, 0.95, 1.0)
self.downloadVM.storeAppData = nil
return Log.shared.error(error!)
}

self.verifyChecksum(checksum: self.downloadVM.storeAppData?.checksum, file: fileURL) { completing in
self.downloadVM.next(completing ? .finish : .failed, 0.95, 1.0)
if completing {
Task { @MainActor in
self.proceedInstall(fileURL)
if let tmpDir = tmpDir, let url = url {
downloader.addDownload(url: url,
destinationURL: tmpDir,
onProgress: { progress in
// progress is a Float
self.downloadVM.progress = Double(progress)
}, onCompletion: { error, fileURL in
self.downloadVM.next(.integrity, 0.7, 0.95)

if let error = error {
self.downloadVM.next(.failed, 0.95, 1.0)
self.downloadVM.storeAppData = nil
return Log.shared.error(error)
}

self.verifyChecksum(checksum: self.downloadVM.storeAppData?.checksum, file: fileURL) { completing in
self.downloadVM.next(completing ? .finish : .failed, 0.95, 1.0)
if completing {
Task { @MainActor in
self.proceedInstall(fileURL)
}
}
}
}
})
})
}
} catch {
self.downloadVM.next(.failed, 0.95, 1.0)

Expand All @@ -144,8 +147,7 @@ class DownloadApp {

private func proceedInstall(_ url: URL?, deleteIPA: Bool = true) {
if let url = url {
uif.ipaUrl = url
Installer.install(ipaUrl: uif.ipaUrl!, export: false, returnCompletion: { _ in
Installer.install(ipaUrl: url, export: false, returnCompletion: { _ in
Task { @MainActor in
if deleteIPA {
FileManager.default.delete(at: url)
Expand Down
7 changes: 1 addition & 6 deletions PlayCover/AppInstaller/Installer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class Installer {

if !export {
try PlayTools.convertMacho(macho)
try fakesign(macho)
try Shell.signMacho(macho)
}
}

Expand Down Expand Up @@ -215,11 +215,6 @@ class Installer {
return location
}

/// Regular codesign, does not accept entitlements. Used to re-seal an app after you've modified it.
static func fakesign(_ url: URL) throws {
try shell.shello("/usr/bin/codesign", "-fs-", url.path)
}

static var isOptionKeyHeld: Bool {
NSEvent.modifierFlags.contains(.option)
}
Expand Down
15 changes: 0 additions & 15 deletions PlayCover/IntentFlow/UserIntentFlow.swift

This file was deleted.

31 changes: 12 additions & 19 deletions PlayCover/Model/AppInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public class AppInfo {

var minimumOSVersion: String {
get {
self[string: "MinimumOSVersion"]!
self[string: "MinimumOSVersion"] ?? ""
}
set {
self[string: "MinimumOSVersion"] = newValue
Expand All @@ -133,30 +133,30 @@ public class AppInfo {

var bundleName: String {
if self[string: "CFBundleName"] == nil || self[string: "CFBundleName"] == "" {
return self[string: "CFBundleDisplayName"]!
return self[string: "CFBundleDisplayName"] ?? ""
} else {
return self[string: "CFBundleName"]!
return self[string: "CFBundleName"] ?? ""
}
}

var displayName: String {
if self[string: "CFBundleDisplayName"] == nil || self[string: "CFBundleDisplayName"] == "" {
return self[string: "CFBundleName"]!
return self[string: "CFBundleName"] ?? ""
} else {
return self[string: "CFBundleDisplayName"]!
return self[string: "CFBundleDisplayName"] ?? ""
}
}

var bundleIdentifier: String {
self[string: "CFBundleIdentifier"]!
self[string: "CFBundleIdentifier"] ?? ""
}

var executableName: String {
self[string: "CFBundleExecutable"]!
self[string: "CFBundleExecutable"] ?? ""
}

var bundleVersion: String {
self[string: "CFBundleShortVersionString"]!
self[string: "CFBundleShortVersionString"] ?? ""
}

var primaryIconName: String {
Expand Down Expand Up @@ -186,18 +186,11 @@ public class AppInfo {
return "AppIcon"
}

var supportsTrueScreenSizeOnMac: Bool {
get {
self[bool: "UISupportsTrueScreenSizeOnMac"]!
}
set {
self[bool: "UISupportsTrueScreenSizeOnMac"] = newValue
}
}

func assert(minimumVersion: Double) {
if Double(minimumOSVersion)! > 11.0 {
minimumOSVersion = Int(minimumVersion).description
if let double = Double(minimumOSVersion) {
if double > 11.0 {
minimumOSVersion = Int(minimumVersion).description
}
}
}
}
13 changes: 3 additions & 10 deletions PlayCover/Model/PlayApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class PlayApp: BaseApp {
Log.shared.error("The app is not codesigned! Please open Xcode and accept license agreement.")
} else {
if settings.openWithLLDB {
Shell.lldb(executable, withTerminalWindow: settings.openLLDBWithTerminal)
try Shell.lldb(executable, withTerminalWindow: settings.openLLDBWithTerminal)
} else {
runAppExec() // Splitting to reduce complexity
}
Expand Down Expand Up @@ -137,7 +137,7 @@ class PlayApp: BaseApp {
}

func isCodesigned() throws -> Bool {
try shell.shello("/usr/bin/codesign", "-dv", executable.path).contains("adhoc")
try Shell.run("/usr/bin/codesign", "-dv", executable.path).contains("adhoc")
}

func showInFinder() {
Expand Down Expand Up @@ -189,21 +189,14 @@ class PlayApp: BaseApp {
.appendingPathExtension("plist")
let conf = try Entitlements.composeEntitlements(self)
try conf.store(tmpEnts)
shell.signAppWith(executable, entitlements: tmpEnts)
try Shell.signAppWith(executable, entitlements: tmpEnts)
try FileManager.default.removeItem(at: tmpDir)
} catch {
print(error)
Log.shared.error(error)
}
}

func largerImage(image imageA: NSImage, compareTo imageB: NSImage?) -> NSImage {
if imageA.size.height > imageB?.size.height ?? -1 {
return imageA
}
return imageB!
}

var prohibitedToPlay: Bool {
PlayApp.PROHIBITED_APPS.contains(info.bundleIdentifier)
}
Expand Down
4 changes: 2 additions & 2 deletions PlayCover/Model/PlayRules.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import Foundation

struct PlayRules: Decodable {
var blacklist: [String]?
var whitelist: [String]?
var blocklist: [String]?
var greenlist: [String]?
var allow: [String]?
var bypass: [String]?

Expand Down
16 changes: 9 additions & 7 deletions PlayCover/Utils/AppIntegrity.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ class AppIntegrity: ObservableObject {

func moveToApps() {
do {
FileManager.default.delete(at: AppIntegrity.expectedUrl)
try FileManager.default.copyItem(at: AppIntegrity.appUrl!, to: AppIntegrity.expectedUrl)
URL(fileURLWithPath: AppIntegrity.expectedUrl.path).openInFinder()
FileManager.default.delete(at: AppIntegrity.appUrl!)
exit(0)
} catch {
Log.shared.error(error)
if let url = AppIntegrity.appUrl {
FileManager.default.delete(at: AppIntegrity.expectedUrl)
try FileManager.default.copyItem(at: url, to: AppIntegrity.expectedUrl)
URL(fileURLWithPath: AppIntegrity.expectedUrl.path).openInFinder()
FileManager.default.delete(at: url)
exit(0)
}
} catch {
Log.shared.error(error)
}
}

Expand Down
4 changes: 2 additions & 2 deletions PlayCover/Utils/Entitlements.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,14 @@ class Entitlements {
sandboxProfile.append(contentsOf: PlayRules.buildRules(rules: rules.allow ?? [], bundleID: bundleID))

if app.settings.settings.bypass {
for file in PlayRules.buildRules(rules: rules.blacklist ?? [], bundleID: bundleID) {
for file in PlayRules.buildRules(rules: rules.blocklist ?? [], bundleID: bundleID) {
sandboxProfile.append(
"""
(deny file* file-read* file-read-metadata file-ioctl (literal "\(file)"))
""")
}

for file in PlayRules.buildRules(rules: rules.whitelist ?? [], bundleID: bundleID) {
for file in PlayRules.buildRules(rules: rules.greenlist ?? [], bundleID: bundleID) {
sandboxProfile.append(
"""
(allow file* file-read* file-read-metadata file-ioctl (literal "\(file)"))
Expand Down
2 changes: 2 additions & 0 deletions PlayCover/Utils/Extensions/DataExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// PlayCover
//

// swiftlint:disable force_unwrapping

import Foundation

extension String {
Expand Down
5 changes: 3 additions & 2 deletions PlayCover/Utils/Extensions/FileExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ extension NSOpenPanel {
panel.canChooseFiles = true
panel.begin { result in
if result == .OK {
let url = panel.urls.first
completion(.success(url!))
if let url = panel.urls.first {
completion(.success(url))
}
}
}
}
Expand Down
18 changes: 11 additions & 7 deletions PlayCover/Utils/IPA.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ public class IPA {
}

func removeQuarantine(_ execUrl: URL) throws {
try shell.shello("/usr/bin/xattr", "-r", "-d", "com.apple.quarantine", execUrl.relativePath)
try Shell.run("/usr/bin/xattr", "-r", "-d", "com.apple.quarantine", execUrl.relativePath)
}

public func unzip() throws -> BaseApp {
if let workDir = tmpDir {
if Shell.quietUnzip(url, toUrl: workDir) == "" {
if try Shell.run("/usr/bin/unzip",
"-oq", url.path, "-d", workDir.path) == "" {
try removeQuarantine(workDir)
return try Installer.fromIPA(detectingAppNameInFolder: workDir.appendingPathComponent("Payload"))
} else {
Expand All @@ -48,12 +49,15 @@ public class IPA {
}

func packIPABack(app: URL) throws -> URL {
let payload = app.deletingPathExtension().deletingLastPathComponent()
let name = app.deletingPathExtension().lastPathComponent

let newIpa = getDocumentsDirectory()
.appendingEscapedPathComponent(app.deletingPathExtension().lastPathComponent).appendingPathExtension("ipa")
try Shell.zip(
ipa: newIpa,
name: app.deletingPathExtension().lastPathComponent,
payload: app.deletingLastPathComponent().deletingLastPathComponent())
.appendingEscapedPathComponent(name)
.appendingPathExtension("ipa")

try Shell.run("usr/bin/zip", "-r", newIpa.path, payload.path)

return newIpa
}

Expand Down
Loading

0 comments on commit df96821

Please sign in to comment.