Skip to content

Commit 45ea417

Browse files
authored
Merge branch 'main' into main
2 parents beca9b4 + 0b6ae5d commit 45ea417

33 files changed

Lines changed: 927 additions & 198 deletions

.github/workflows/appcast.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
persist-credentials: false
1616

1717
- name: Cache 📦
18-
uses: actions/cache@v3.0.8
18+
uses: actions/cache@v3.0.11
1919
with:
2020
path: AppCast/vendor/bundle
2121
key: ${{ runner.os }}-gems-v1.0-${{ hashFiles('AppCast/Gemfile') }}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ Product/*
3636
timeline.xctimeline
3737
playground.xcworkspace
3838

39+
# Jetbrains IDEA
40+
.idea
41+
3942
# Swift Package Manager
4043
#
4144
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.

CONTRIBUTING.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Contributing to Xcodes
2+
We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's:
3+
4+
- Reporting a bug
5+
- Discussing the current state of the code
6+
- Submitting a fix
7+
- Proposing new features
8+
- Becoming a maintainer
9+
10+
## We Develop with Github
11+
We use github to host code, to track issues and feature requests, as well as accept pull requests.
12+
13+
## All Code Changes Happen Through Pull Requests
14+
Pull requests are the best way to propose changes to the codebase We actively welcome your pull requests:
15+
16+
1. Fork the repo and create your branch from `main`.
17+
2. If you've added code that should be tested, add tests.
18+
3. If you've added new functionality, add documentation
19+
4. Ensure the test suite passes.
20+
5. Make sure your code lints.
21+
6. Issue that pull request!
22+
23+
## Any contributions you make will be under the MIT Software License
24+
In short, when you submit code changes, your submissions are understood to be under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the project. Feel free to contact the maintainers if that's a concern.
25+
26+
## Report bugs using Github's [issues](https://github.com/robotsandpencils/xcodesapp/issues)
27+
We use GitHub issues to track public bugs. Report a bug by [opening a new issue](); it's that easy!
28+
29+
## Write bug reports with detail, background, and sample code
30+
31+
**Great Bug Reports** tend to have:
32+
33+
- A quick summary and/or background
34+
- Steps to reproduce
35+
- Be specific!
36+
- What you expected would happen
37+
- What actually happens
38+
- Notes (possibly including why you think this might be happening, or stuff you tried that didn't work)
39+
40+
People *love* thorough bug reports.
41+
42+
## License
43+
By contributing, you agree that your contributions will be licensed under its MIT License.

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ The following languages are supported because of the following community users!
4040
|Hindi 🇮🇳 |[@KGurpreet](https://github.com/KGurpreet)|Chinese-Simplified 🇨🇳|[@megabitsenmzq](https://github.com/megabitsenmzq)|
4141
|Finnish 🇫🇮 |[@marcusziade](https://github.com/marcusziade)|Chinese-Traditional 🇹🇼|[@itszero](https://github.com/itszero)|
4242
|Ukranian 🇺🇦 |[@gelosi](https://github.com/gelosi)|Japanese 🇯🇵|[@tatsuz0u](https://github.com/tatsuz0u)|
43-
|German 🇩🇪|[@drct](https://github.com/drct)|Catalan|[@ferranabello](https://github.com/ferranabello)||
43+
|German 🇩🇪|[@drct](https://github.com/drct)|Dutch 🇳🇱|[@jfversluis](https://github/com/jfversluis)|
44+
|Brazilian Portuguese 🇧🇷|[@brunomunizaf](https://github.com/brunomunizaf)|Catalan|[@ferranabello](https://github.com/ferranabello)||
4445

4546
Want to add more languages? Simply create a PR with the updated strings file.
4647
## Installation

Xcodes.xcodeproj/project.pbxproj

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
36741BFD291E4FDB00A85AAE /* DownloadPreferencePane.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36741BFC291E4FDB00A85AAE /* DownloadPreferencePane.swift */; };
11+
36741BFF291E50F500A85AAE /* FileError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36741BFE291E50F500A85AAE /* FileError.swift */; };
1012
536CFDD2263C94DE00026CE0 /* SignedInView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536CFDD1263C94DE00026CE0 /* SignedInView.swift */; };
1113
536CFDD4263C9A8000026CE0 /* XcodesSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536CFDD3263C9A8000026CE0 /* XcodesSheet.swift */; };
1214
53CBAB2C263DCC9100410495 /* XcodesAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53CBAB2B263DCC9100410495 /* XcodesAlert.swift */; };
@@ -102,6 +104,7 @@
102104
CAFFFED8259CDA5000903F81 /* XcodeListViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFFFED7259CDA5000903F81 /* XcodeListViewRow.swift */; };
103105
E81D7EA02805250100A205FC /* Collection+.swift in Sources */ = {isa = PBXBuildFile; fileRef = E81D7E9F2805250100A205FC /* Collection+.swift */; };
104106
E872EE4E2808D4F100D3DD8B /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E872EE502808D4F100D3DD8B /* Localizable.strings */; };
107+
E87AB3C52939B65E00D72F43 /* Hardware.swift in Sources */ = {isa = PBXBuildFile; fileRef = E87AB3C42939B65E00D72F43 /* Hardware.swift */; };
105108
E87DD6EB25D053FA00D86808 /* Progress+.swift in Sources */ = {isa = PBXBuildFile; fileRef = E87DD6EA25D053FA00D86808 /* Progress+.swift */; };
106109
E89342FA25EDCC17007CF557 /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E89342F925EDCC17007CF557 /* NotificationManager.swift */; };
107110
E8977EA325C11E1500835F80 /* PreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8977EA225C11E1500835F80 /* PreferencesView.swift */; };
@@ -170,6 +173,9 @@
170173
/* Begin PBXFileReference section */
171174
15FAD1652811D15600B63259 /* hi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hi; path = hi.lproj/Localizable.strings; sourceTree = "<group>"; };
172175
25E2FA26284769A00014A318 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = "<group>"; };
176+
327DF109286ABE6B00D694D5 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = "<group>"; };
177+
36741BFC291E4FDB00A85AAE /* DownloadPreferencePane.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownloadPreferencePane.swift; sourceTree = "<group>"; };
178+
36741BFE291E50F500A85AAE /* FileError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileError.swift; sourceTree = "<group>"; };
173179
4A5AAA1D28118FAD00528958 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
174180
536CFDD1263C94DE00026CE0 /* SignedInView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignedInView.swift; sourceTree = "<group>"; };
175181
536CFDD3263C9A8000026CE0 /* XcodesSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcodesSheet.swift; sourceTree = "<group>"; };
@@ -290,8 +296,10 @@
290296
CAFE4ABB25B7D54B0064FE51 /* UpdatesPreferencePane.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatesPreferencePane.swift; sourceTree = "<group>"; };
291297
CAFFFED7259CDA5000903F81 /* XcodeListViewRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcodeListViewRow.swift; sourceTree = "<group>"; };
292298
CAFFFEEE259CEAC400903F81 /* RingProgressViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RingProgressViewStyle.swift; sourceTree = "<group>"; };
299+
E2AFDCCA28F024D000864ADD /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
293300
E81D7E9F2805250100A205FC /* Collection+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Collection+.swift"; sourceTree = "<group>"; };
294301
E872EE4F2808D4F100D3DD8B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
302+
E87AB3C42939B65E00D72F43 /* Hardware.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Hardware.swift; sourceTree = "<group>"; };
295303
E87DD6EA25D053FA00D86808 /* Progress+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Progress+.swift"; sourceTree = "<group>"; };
296304
E89342F925EDCC17007CF557 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = "<group>"; };
297305
E8977EA225C11E1500835F80 /* PreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesView.swift; sourceTree = "<group>"; };
@@ -457,6 +465,7 @@
457465
CAA858C325A2BE4E00ACF8C0 /* Downloader.swift */,
458466
CABFA9B22592EEEA00380FEE /* Entry+.swift */,
459467
CABFA9A92592EEE900380FEE /* Environment.swift */,
468+
36741BFE291E50F500A85AAE /* FileError.swift */,
460469
CABFA9B82592EEEA00380FEE /* FileManager+.swift */,
461470
CAFBDB942598FE96003DCC5A /* FocusedValues.swift */,
462471
CABFA9AC2592EEE900380FEE /* Foundation.swift */,
@@ -483,6 +492,7 @@
483492
E87DD6EA25D053FA00D86808 /* Progress+.swift */,
484493
E81D7E9F2805250100A205FC /* Collection+.swift */,
485494
E8D655BF288DD04700A139C2 /* SelectedActionType.swift */,
495+
E87AB3C42939B65E00D72F43 /* Hardware.swift */,
486496
);
487497
path = Backend;
488498
sourceTree = "<group>";
@@ -589,6 +599,7 @@
589599
isa = PBXGroup;
590600
children = (
591601
CAFE4AB325B7D3AF0064FE51 /* AdvancedPreferencePane.swift */,
602+
36741BFC291E4FDB00A85AAE /* DownloadPreferencePane.swift */,
592603
CAFE4AAB25B7D2C70064FE51 /* GeneralPreferencePane.swift */,
593604
CAFE4ABB25B7D54B0064FE51 /* UpdatesPreferencePane.swift */,
594605
E8977EA225C11E1500835F80 /* PreferencesView.swift */,
@@ -723,6 +734,8 @@
723734
uk,
724735
fi,
725736
ca,
737+
"pt-BR",
738+
nl,
726739
);
727740
mainGroup = CAD2E7952449574E00113D76;
728741
packageReferences = (
@@ -840,6 +853,7 @@
840853
CAA1CB45255A5B60003FD669 /* SignIn2FAView.swift in Sources */,
841854
CABFA9C52592EEEA00380FEE /* FileManager+.swift in Sources */,
842855
CABFA9CD2592EEEA00380FEE /* Foundation.swift in Sources */,
856+
36741BFF291E50F500A85AAE /* FileError.swift in Sources */,
843857
CA9FF8872595607900E47BAF /* InstalledXcode.swift in Sources */,
844858
53CBAB2C263DCC9100410495 /* XcodesAlert.swift in Sources */,
845859
CA42DD6E25AEA8B200BC0B0C /* Logger.swift in Sources */,
@@ -850,6 +864,7 @@
850864
CA9FF84E2595079F00E47BAF /* ScrollingTextView.swift in Sources */,
851865
CABFA9C12592EEEA00380FEE /* Version+.swift in Sources */,
852866
E8D655C0288DD04700A139C2 /* SelectedActionType.swift in Sources */,
867+
36741BFD291E4FDB00A85AAE /* DownloadPreferencePane.swift in Sources */,
853868
CA9FF8522595080100E47BAF /* AcknowledgementsView.swift in Sources */,
854869
CABFA9CE2592EEEA00380FEE /* Version+Xcode.swift in Sources */,
855870
CAFBDB912598FE80003DCC5A /* SelectedXcode.swift in Sources */,
@@ -867,6 +882,7 @@
867882
CAC281CD259F97FA00B8AB0B /* ObservingProgressIndicator.swift in Sources */,
868883
CABFA9C22592EEEA00380FEE /* Publisher+Resumable.swift in Sources */,
869884
CAFBDC68259A308B003DCC5A /* InfoPane.swift in Sources */,
885+
E87AB3C52939B65E00D72F43 /* Hardware.swift in Sources */,
870886
CAA1CB4D255A5CFD003FD669 /* SignInPhoneListView.swift in Sources */,
871887
CAFBDC6C259A3098003DCC5A /* View+Conditional.swift in Sources */,
872888
CABFA9CF2592EEEA00380FEE /* Process.swift in Sources */,
@@ -937,6 +953,8 @@
937953
7CBF284E28606D2C001AA66B /* uk */,
938954
5AA8A6102877EDAD009ECDB0 /* fi */,
939955
5C3927ED28E4B486007B5119 /* ca */,
956+
327DF109286ABE6B00D694D5 /* pt-BR */,
957+
E2AFDCCA28F024D000864ADD /* nl */,
940958
);
941959
name = Localizable.strings;
942960
sourceTree = "<group>";
@@ -1015,7 +1033,7 @@
10151033
CODE_SIGN_IDENTITY = "-";
10161034
CODE_SIGN_STYLE = Manual;
10171035
COMBINE_HIDPI_IMAGES = YES;
1018-
CURRENT_PROJECT_VERSION = 16;
1036+
CURRENT_PROJECT_VERSION = 17;
10191037
DEVELOPMENT_ASSET_PATHS = "\"Xcodes/Preview Content\"";
10201038
DEVELOPMENT_TEAM = "";
10211039
ENABLE_HARDENED_RUNTIME = NO;
@@ -1025,7 +1043,7 @@
10251043
"$(inherited)",
10261044
"@executable_path/../Frameworks",
10271045
);
1028-
MARKETING_VERSION = 1.8.0;
1046+
MARKETING_VERSION = 1.9.0;
10291047
PRODUCT_BUNDLE_IDENTIFIER = com.robotsandpencils.XcodesApp;
10301048
PRODUCT_NAME = Xcodes;
10311049
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1256,7 +1274,7 @@
12561274
CODE_SIGN_ENTITLEMENTS = Xcodes/Resources/Xcodes.entitlements;
12571275
CODE_SIGN_STYLE = Automatic;
12581276
COMBINE_HIDPI_IMAGES = YES;
1259-
CURRENT_PROJECT_VERSION = 16;
1277+
CURRENT_PROJECT_VERSION = 17;
12601278
DEVELOPMENT_ASSET_PATHS = "\"Xcodes/Preview Content\"";
12611279
DEVELOPMENT_TEAM = PBH8V487HB;
12621280
ENABLE_HARDENED_RUNTIME = YES;
@@ -1266,7 +1284,7 @@
12661284
"$(inherited)",
12671285
"@executable_path/../Frameworks",
12681286
);
1269-
MARKETING_VERSION = 1.8.0;
1287+
MARKETING_VERSION = 1.9.0;
12701288
PRODUCT_BUNDLE_IDENTIFIER = com.robotsandpencils.XcodesApp;
12711289
PRODUCT_NAME = Xcodes;
12721290
SWIFT_VERSION = 5.0;
@@ -1280,7 +1298,7 @@
12801298
CODE_SIGN_ENTITLEMENTS = Xcodes/Resources/Xcodes.entitlements;
12811299
CODE_SIGN_STYLE = Automatic;
12821300
COMBINE_HIDPI_IMAGES = YES;
1283-
CURRENT_PROJECT_VERSION = 16;
1301+
CURRENT_PROJECT_VERSION = 17;
12841302
DEVELOPMENT_ASSET_PATHS = "\"Xcodes/Preview Content\"";
12851303
DEVELOPMENT_TEAM = PBH8V487HB;
12861304
ENABLE_HARDENED_RUNTIME = YES;
@@ -1290,7 +1308,7 @@
12901308
"$(inherited)",
12911309
"@executable_path/../Frameworks",
12921310
);
1293-
MARKETING_VERSION = 1.8.0;
1311+
MARKETING_VERSION = 1.9.0;
12941312
PRODUCT_BUNDLE_IDENTIFIER = com.robotsandpencils.XcodesApp;
12951313
PRODUCT_NAME = Xcodes;
12961314
SWIFT_VERSION = 5.0;

Xcodes/Backend/AppState+Install.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ extension AppState {
4343

4444
Logger.appState.info("Using \(downloader) downloader")
4545

46-
return self.getXcodeArchive(installationType, downloader: downloader)
46+
return validateSession()
47+
.flatMap { _ in
48+
self.getXcodeArchive(installationType, downloader: downloader)
49+
}
4750
.flatMap { xcode, url -> AnyPublisher<InstalledXcode, Swift.Error> in
4851
self.installArchivedXcode(xcode, at: url)
4952
}
@@ -93,15 +96,12 @@ extension AppState {
9396
}
9497

9598
private func downloadXcode(availableXcode: AvailableXcode, downloader: Downloader) -> AnyPublisher<(AvailableXcode, URL), Error> {
96-
return validateADCSession(path: availableXcode.downloadPath)
97-
.flatMap { _ in
98-
return self.downloadOrUseExistingArchive(for: availableXcode, downloader: downloader, progressChanged: { [unowned self] progress in
99-
DispatchQueue.main.async {
100-
self.setInstallationStep(of: availableXcode.version, to: .downloading(progress: progress))
101-
}
102-
})
103-
.map { return (availableXcode, $0) }
104-
}
99+
self.downloadOrUseExistingArchive(for: availableXcode, downloader: downloader, progressChanged: { [unowned self] progress in
100+
DispatchQueue.main.async {
101+
self.setInstallationStep(of: availableXcode.version, to: .downloading(progress: progress))
102+
}
103+
})
104+
.map { return (availableXcode, $0) }
105105
.eraseToAnyPublisher()
106106
}
107107

@@ -513,7 +513,7 @@ public enum InstallationError: LocalizedError, Equatable {
513513
case .unexpectedCodeSigningIdentity(let identity, let certificateAuthority):
514514
return String(format: localizeString("InstallationError.UnexpectedCodeSigningIdentity"), identity, certificateAuthority, XcodeTeamIdentifier, XcodeCertificateAuthority)
515515
case .unsupportedFileFormat(let fileExtension):
516-
return String(format: localizeString("InstallationError.UnsuppoawwrtedFileFormat"), fileExtension)
516+
return String(format: localizeString("InstallationError.UnsupportedFileFormat"), fileExtension)
517517
case .missingSudoerPassword:
518518
return localizeString("InstallationError.MissingSudoerPassword")
519519
case let .unavailableVersion(version):

Xcodes/Backend/AppState.swift

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,12 @@ class AppState: ObservableObject {
9393
}
9494
}
9595
}
96-
96+
97+
@Published var showOpenInRosettaOption = false {
98+
didSet {
99+
Current.defaults.set(showOpenInRosettaOption, forKey: "showOpenInRosettaOption")
100+
}
101+
}
97102
// MARK: - Publisher Cancellables
98103

99104
var cancellables = Set<AnyCancellable>()
@@ -142,6 +147,7 @@ class AppState: ObservableObject {
142147
createSymLinkOnSelect = Current.defaults.bool(forKey: "createSymLinkOnSelect") ?? false
143148
onSelectActionType = SelectedActionType(rawValue: Current.defaults.string(forKey: "onSelectActionType") ?? "none") ?? .none
144149
installPath = Current.defaults.string(forKey: "installPath") ?? Path.defaultInstallDirectory.string
150+
showOpenInRosettaOption = Current.defaults.bool(forKey: "showOpenInRosettaOption") ?? false
145151
}
146152

147153
// MARK: Timer
@@ -381,7 +387,7 @@ class AppState: ObservableObject {
381387
case .apple:
382388
install(id: id)
383389
case .xcodeReleases:
384-
installWithoutLogin(id: id)
390+
install(id: id)
385391
}
386392
}
387393

@@ -454,6 +460,7 @@ class AppState: ObservableObject {
454460
}
455461

456462
/// Skips using the username/password to log in to Apple, and simply gets a Auth Cookie used in downloading
463+
/// As of Nov 2022 this was returning a 403 forbidden
457464
func installWithoutLogin(id: Xcode.ID) {
458465
guard let availableXcode = availableXcodes.first(where: { $0.version == id }) else { return }
459466

@@ -584,13 +591,18 @@ class AppState: ObservableObject {
584591
)
585592
}
586593

587-
func open(xcode: Xcode) {
594+
func open(xcode: Xcode, openInRosetta: Bool? = false) {
588595
switch xcode.installState {
589-
case let .installed(path):
590-
NSWorkspace.shared.openApplication(at: path.url, configuration: .init())
591-
default:
592-
Logger.appState.error("\(xcode.id) is not installed")
593-
return
596+
case let .installed(path):
597+
let config = NSWorkspace.OpenConfiguration.init()
598+
if (openInRosetta ?? false) {
599+
config.architecture = CPU_TYPE_X86_64
600+
}
601+
config.allowsRunningApplicationSubstitution = false
602+
NSWorkspace.shared.openApplication(at: path.url, configuration: config)
603+
default:
604+
Logger.appState.error("\(xcode.id) is not installed")
605+
return
594606
}
595607
}
596608

@@ -609,10 +621,10 @@ class AppState: ObservableObject {
609621
NSPasteboard.general.setString(url.absoluteString, forType: .string)
610622
}
611623

612-
func createSymbolicLink(xcode: Xcode) {
624+
func createSymbolicLink(xcode: Xcode, isBeta: Bool = false) {
613625
guard let installedXcodePath = xcode.installedPath else { return }
614626

615-
let destinationPath: Path = Path.installDirectory/"Xcode.app"
627+
let destinationPath: Path = Path.installDirectory/"Xcode\(isBeta ? "-Beta" : "").app"
616628

617629
// does an Xcode.app file exist?
618630
if FileManager.default.fileExists(atPath: destinationPath.string) {
@@ -634,7 +646,7 @@ class AppState: ObservableObject {
634646

635647
do {
636648
try FileManager.default.createSymbolicLink(atPath: destinationPath.string, withDestinationPath: installedXcodePath.string)
637-
Logger.appState.info("Successfully created symbolic link with Xcode.app")
649+
Logger.appState.info("Successfully created symbolic link with Xcode\(isBeta ? "-Beta": "").app")
638650
} catch {
639651
Logger.appState.error("Unable to create symbolic Link")
640652
self.error = error

Xcodes/Backend/FileError.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//
2+
// FileError.swift
3+
// Xcodes
4+
//
5+
// Created by Leon Wolf on 06.10.22.
6+
// Copyright © 2022 Robots and Pencils. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import LegibleError
11+
12+
enum FileError: LocalizedError{
13+
case fileNotFound(_ fileName: String)
14+
}
15+
16+
extension FileError {
17+
var errorDescription: String? {
18+
switch self {
19+
case .fileNotFound(let fileName):
20+
return String(format: localizeString("Alert.Uninstall.Error.Message.FileNotFound"), fileName)
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)