diff --git a/Xcodes.xcodeproj/project.pbxproj b/Xcodes.xcodeproj/project.pbxproj index 7aeb76cf..cfb1672b 100644 --- a/Xcodes.xcodeproj/project.pbxproj +++ b/Xcodes.xcodeproj/project.pbxproj @@ -114,6 +114,8 @@ CAFE4AB425B7D3AF0064FE51 /* AdvancedPreferencePane.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFE4AB325B7D3AF0064FE51 /* AdvancedPreferencePane.swift */; }; CAFE4ABC25B7D54B0064FE51 /* UpdatesPreferencePane.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFE4ABB25B7D54B0064FE51 /* UpdatesPreferencePane.swift */; }; CAFFFED8259CDA5000903F81 /* XcodeListViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFFFED7259CDA5000903F81 /* XcodeListViewRow.swift */; }; + D0B0642B2EB65B0C003CBB98 /* unxip in Resources */ = {isa = PBXBuildFile; fileRef = D0B0642A2EB65B0C003CBB98 /* unxip */; }; + D0B0642C2EB65BCF003CBB98 /* unxip in Copy aria2c */ = {isa = PBXBuildFile; fileRef = D0B0642A2EB65B0C003CBB98 /* unxip */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; D93F95C12E0C8C1A00238FB5 /* TagView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93F95C02E0C8C1A00238FB5 /* TagView.swift */; }; E689540325BE8C64000EBCEA /* DockProgress in Frameworks */ = {isa = PBXBuildFile; productRef = E689540225BE8C64000EBCEA /* DockProgress */; }; E81D7EA02805250100A205FC /* Collection+.swift in Sources */ = {isa = PBXBuildFile; fileRef = E81D7E9F2805250100A205FC /* Collection+.swift */; }; @@ -132,7 +134,6 @@ E8B20CBF2A2EDEC20057D816 /* SDKs+Xcode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8B20CBE2A2EDEC20057D816 /* SDKs+Xcode.swift */; }; E8C0EB1A291EF43E0081528A /* XcodesKit in Frameworks */ = {isa = PBXBuildFile; productRef = E8C0EB19291EF43E0081528A /* XcodesKit */; }; E8C0EB1C291EF9A10081528A /* AppState+Runtimes.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8C0EB1B291EF9A10081528A /* AppState+Runtimes.swift */; }; - E8CBDB8927ADE32300B22292 /* unxip in Copy aria2c */ = {isa = PBXBuildFile; fileRef = E8CBDB8627ADD92000B22292 /* unxip */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; E8CBDB8B27AE02FF00B22292 /* ExperiementsPreferencePane.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8CBDB8A27AE02FF00B22292 /* ExperiementsPreferencePane.swift */; }; E8D0296F284B029800647641 /* BottomStatusBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8D0296E284B029800647641 /* BottomStatusBar.swift */; }; E8D655C0288DD04700A139C2 /* SelectedActionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8D655BF288DD04700A139C2 /* SelectedActionType.swift */; }; @@ -189,7 +190,7 @@ dstPath = ""; dstSubfolderSpec = 6; files = ( - E8CBDB8927ADE32300B22292 /* unxip in Copy aria2c */, + D0B0642C2EB65BCF003CBB98 /* unxip in Copy aria2c */, CAA8589325A2B77E00ACF8C0 /* aria2c in Copy aria2c */, ); name = "Copy aria2c"; @@ -322,6 +323,7 @@ CAFE4ABB25B7D54B0064FE51 /* UpdatesPreferencePane.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatesPreferencePane.swift; sourceTree = ""; }; CAFFFED7259CDA5000903F81 /* XcodeListViewRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcodeListViewRow.swift; sourceTree = ""; }; CAFFFEEE259CEAC400903F81 /* RingProgressViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RingProgressViewStyle.swift; sourceTree = ""; }; + D0B0642A2EB65B0C003CBB98 /* unxip */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = unxip; sourceTree = ""; }; D93F95C02E0C8C1A00238FB5 /* TagView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagView.swift; sourceTree = ""; }; E81D7E9F2805250100A205FC /* Collection+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Collection+.swift"; sourceTree = ""; }; E832EAF72B0FBCF4001B570D /* RuntimeInstallationStepDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuntimeInstallationStepDetailView.swift; sourceTree = ""; }; @@ -336,7 +338,6 @@ E8977EA225C11E1500835F80 /* PreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesView.swift; sourceTree = ""; }; E8B20CBE2A2EDEC20057D816 /* SDKs+Xcode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SDKs+Xcode.swift"; sourceTree = ""; }; E8C0EB1B291EF9A10081528A /* AppState+Runtimes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppState+Runtimes.swift"; sourceTree = ""; }; - E8CBDB8627ADD92000B22292 /* unxip */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = unxip; sourceTree = ""; }; E8CBDB8A27AE02FF00B22292 /* ExperiementsPreferencePane.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExperiementsPreferencePane.swift; sourceTree = ""; }; E8D0296E284B029800647641 /* BottomStatusBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomStatusBar.swift; sourceTree = ""; }; E8D655BF288DD04700A139C2 /* SelectedActionType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectedActionType.swift; sourceTree = ""; }; @@ -562,6 +563,7 @@ CABFAA1D2592F7F200380FEE /* Resources */ = { isa = PBXGroup; children = ( + D0B0642A2EB65B0C003CBB98 /* unxip */, E8EEAD1C2E79174F00BE67E8 /* XcodesIcon.icon */, CAA858DA25A3E11F00ACF8C0 /* aria2-release-1.35.0.tar.gz */, CAA8588025A2B63A00ACF8C0 /* aria2c */, @@ -571,7 +573,6 @@ CA9FF83E2594FBC000E47BAF /* Licenses.rtf */, CAD2E7AE2449575000113D76 /* Xcodes.entitlements */, CA8FB64D256E17B100469DA5 /* XcodesTest.entitlements */, - E8CBDB8627ADD92000B22292 /* unxip */, 9DD4FFCA2B13EC1800C974F1 /* Localizable.xcstrings */, ); path = Resources; @@ -844,6 +845,7 @@ E8EEAD1D2E79174F00BE67E8 /* XcodesIcon.icon in Resources */, CA9FF83F2594FBC000E47BAF /* Licenses.rtf in Resources */, CAA858DB25A3E11F00ACF8C0 /* aria2-release-1.35.0.tar.gz in Resources */, + D0B0642B2EB65B0C003CBB98 /* unxip in Resources */, CAD2E7A62449575000113D76 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1155,7 +1157,7 @@ CODE_SIGNING_SUBJECT_ORGANIZATIONAL_UNIT = ZU6GR6B2FY; CODE_SIGN_STYLE = Automatic; CREATE_INFOPLIST_SECTION_IN_BINARY = YES; - DEVELOPMENT_TEAM = ZU6GR6B2FY; + DEVELOPMENT_TEAM = Q23JLSJCCV; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = "$(SRCROOT)/$(TARGET_NAME)/Info.plist"; MARKETING_VERSION = 2.0.0; @@ -1208,7 +1210,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; CREATE_INFOPLIST_SECTION_IN_BINARY = YES; - DEVELOPMENT_TEAM = ZU6GR6B2FY; + DEVELOPMENT_TEAM = Q23JLSJCCV; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = "$(SRCROOT)/$(TARGET_NAME)/Info.plist"; MARKETING_VERSION = 2.0.0; @@ -1359,7 +1361,7 @@ COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 34; DEVELOPMENT_ASSET_PATHS = "\"Xcodes/Preview Content\""; - DEVELOPMENT_TEAM = ZU6GR6B2FY; + DEVELOPMENT_TEAM = Q23JLSJCCV; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; INFOPLIST_FILE = Xcodes/Resources/Info.plist; @@ -1388,7 +1390,7 @@ COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 34; DEVELOPMENT_ASSET_PATHS = "\"Xcodes/Preview Content\""; - DEVELOPMENT_TEAM = ZU6GR6B2FY; + DEVELOPMENT_TEAM = Q23JLSJCCV; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; INFOPLIST_FILE = Xcodes/Resources/Info.plist; diff --git a/Xcodes/Resources/unxip b/Xcodes/Resources/unxip index 46a7f314..4f2b5d60 100755 Binary files a/Xcodes/Resources/unxip and b/Xcodes/Resources/unxip differ diff --git a/Xcodes/XcodesKit/Sources/XcodesKit/Shell/Process.swift b/Xcodes/XcodesKit/Sources/XcodesKit/Shell/Process.swift index daf28e97..43edcb72 100644 --- a/Xcodes/XcodesKit/Sources/XcodesKit/Shell/Process.swift +++ b/Xcodes/XcodesKit/Sources/XcodesKit/Shell/Process.swift @@ -14,45 +14,76 @@ extension Process { } static func run(_ executable: URL, workingDirectory: URL? = nil, input: String? = nil, _ arguments: [String]) throws -> ProcessOutput { - let process = Process() process.currentDirectoryURL = workingDirectory ?? executable.deletingLastPathComponent() process.executableURL = executable process.arguments = arguments - let (stdout, stderr) = (Pipe(), Pipe()) - process.standardOutput = stdout - process.standardError = stderr + let outPipe = Pipe() + let errPipe = Pipe() + process.standardOutput = outPipe + process.standardError = errPipe + var output = Data() + var error = Data() + + let outputLock = NSLock() + let errorLock = NSLock() + outPipe.fileHandleForReading.readabilityHandler = { handle in + let data = handle.availableData + if !data.isEmpty { + outputLock.lock() + output.append(data) + outputLock.unlock() + } + } + errPipe.fileHandleForReading.readabilityHandler = { handle in + let data = handle.availableData + if !data.isEmpty { + errorLock.lock() + error.append(data) + errorLock.unlock() + } + } + if let input = input { let inputPipe = Pipe() - process.standardInput = inputPipe.fileHandleForReading - inputPipe.fileHandleForWriting.write(Data(input.utf8)) + process.standardInput = inputPipe + if let inputData = input.data(using: .utf8) { + inputPipe.fileHandleForWriting.write(inputData) + } inputPipe.fileHandleForWriting.closeFile() } - + do { Logger.subprocess.info("Process.run executable: \(executable), input: \(input ?? ""), arguments: \(arguments.joined(separator: ", "))") - try process.run() process.waitUntilExit() - - let output = String(data: stdout.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) ?? "" - let error = String(data: stderr.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) ?? "" - - Logger.subprocess.info("Process.run output: \(output)") - if !error.isEmpty { - Logger.subprocess.error("Process.run error: \(error)") - } - - guard process.terminationReason == .exit, process.terminationStatus == 0 else { - throw ProcessExecutionError(process: process, standardOutput: output, standardError: error) - } - - return (process.terminationStatus, output, error) } catch { + outPipe.fileHandleForReading.readabilityHandler = nil + errPipe.fileHandleForReading.readabilityHandler = nil throw error } + outPipe.fileHandleForReading.readabilityHandler = nil + errPipe.fileHandleForReading.readabilityHandler = nil + + outputLock.lock() + let outputString = String(data: output, encoding: .utf8) ?? "" + outputLock.unlock() + errorLock.lock() + let errorString = String(data: error, encoding: .utf8) ?? "" + errorLock.unlock() + + Logger.subprocess.info("Process.run output: \(outputString)") + if !errorString.isEmpty { + Logger.subprocess.error("Process.run error: \(errorString)") + } + + guard process.terminationReason == .exit, process.terminationStatus == 0 else { + throw ProcessExecutionError(process: process, standardOutput: outputString, standardError: errorString) + } + + return (process.terminationStatus, outputString, errorString) } }