Skip to content

Commit bd865b2

Browse files
authored
xcode-select prefers non-RC over RC (#108)
* Adds PlistBuddyReader * Updates ICommandRunner to take array of args * Logs build number of selected Xcode version * Prefers non-RC * Checks for RC when comparing versions
1 parent 0107f3c commit bd865b2

File tree

9 files changed

+63
-7
lines changed

9 files changed

+63
-7
lines changed

xcode-select/__test__/FileSystemXcodeVersionRepository.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,17 @@ test("It omits build number when plist value is missing", async () => {
163163
const xcodeVersions = await repository.getXcodeVersions()
164164
expect(xcodeVersions[0].name).toBe("Xcode 14.3.0")
165165
})
166+
167+
test("It includes RC in the Xcode version name", async () => {
168+
const fileSystem = new MockFileSystem()
169+
fileSystem.dirContents = ["/Users/runner/Applications/Xcode_26.2-RC.app"]
170+
const semanticVersionParser = new SemanticVersionParser()
171+
const xcodeVersionParser = new XcodeVersionParser({ semanticVersionParser })
172+
const repository = new FileSystemXcodeVersionRepository({
173+
fileSystem,
174+
xcodeVersionParser,
175+
plistReader: new MockPlistReader()
176+
})
177+
const xcodeVersions = await repository.getXcodeVersions()
178+
expect(xcodeVersions[0].name).toContain("RC")
179+
})

xcode-select/__test__/XcodeVersionMatcher.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,13 @@ test("It prefers release version of beta version", async () => {
130130
expect(xcodeVersion?.isBeta).toEqual(false)
131131
expect(xcodeVersion?.betaNumber).toBeNull()
132132
})
133+
134+
test("It prefers release version over release candidate", async () => {
135+
const repository = new MockXcodeVersionRepository()
136+
repository.addXcodeVersion(26, 2, 0, false, false)
137+
repository.addXcodeVersion(26, 2, 0, false, true)
138+
const needle = new SemanticVersionTemplate(26, 2, 0)
139+
const matcher = new XcodeVersionMatcher({ xcodeVersionRepository: repository })
140+
const xcodeVersion = await matcher.findXcodeVersion(needle)
141+
expect(xcodeVersion?.isReleaseCandidate).toBe(false)
142+
})

xcode-select/__test__/XcodeVersionParser.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,13 @@ test("It parses XcodeVersion for release candidate", () => {
6363
semanticVersionParser: new SemanticVersionParser()
6464
})
6565
const xcodeVersion = parser.parseFilePath(filePath)
66-
expect(xcodeVersion?.name).toEqual("Xcode 15.0.0")
66+
expect(xcodeVersion?.name).toEqual("Xcode 15.0.0 RC")
6767
expect(xcodeVersion?.version.major).toEqual(15)
6868
expect(xcodeVersion?.version.minor).toEqual(0)
6969
expect(xcodeVersion?.version.patch).toEqual(0)
7070
expect(xcodeVersion?.isBeta).toBeFalsy()
7171
expect(xcodeVersion?.betaNumber).toBeNull()
72+
expect(xcodeVersion?.isReleaseCandidate).toBeTruthy()
7273
})
7374

7475
test("It parses XcodeVersion for abbreviated release candidate", () => {
@@ -77,12 +78,13 @@ test("It parses XcodeVersion for abbreviated release candidate", () => {
7778
semanticVersionParser: new SemanticVersionParser()
7879
})
7980
const xcodeVersion = parser.parseFilePath(filePath)
80-
expect(xcodeVersion?.name).toEqual("Xcode 15.0.0")
81+
expect(xcodeVersion?.name).toEqual("Xcode 15.0.0 RC")
8182
expect(xcodeVersion?.version.major).toEqual(15)
8283
expect(xcodeVersion?.version.minor).toEqual(0)
8384
expect(xcodeVersion?.version.patch).toEqual(0)
8485
expect(xcodeVersion?.isBeta).toBeFalsy()
8586
expect(xcodeVersion?.betaNumber).toBeNull()
87+
expect(xcodeVersion?.isReleaseCandidate).toBeTruthy()
8688
})
8789

8890
test("It parses XcodeVersion for 2nd beta version", () => {

xcode-select/__test__/mock/MockXcodeVersionRepository.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@ import IXcodeVersionRepository from "../../src/XcodeVersion/IXcodeVersionReposit
55
export default class MockXcodeVersionRepository implements IXcodeVersionRepository {
66
private xcodeVersions: XcodeVersion[] = []
77

8-
addXcodeVersion(major: number, minor: number = 0, patch: number = 0, isBeta: boolean = false) {
8+
addXcodeVersion(
9+
major: number,
10+
minor: number = 0,
11+
patch: number = 0,
12+
isBeta: boolean = false,
13+
isReleaseCandidate: boolean = false
14+
) {
915
const name = "Xcode " + [major, minor, patch].filter(e => e != null).join(".")
1016
const filePath = "/Users/runner/Applications/" + name + ".app"
1117
const version = new SemanticVersion(major, minor, patch)
12-
const xcodeVersion = new XcodeVersion(filePath, version, isBeta)
18+
const xcodeVersion = new XcodeVersion(filePath, version, isBeta, null, isReleaseCandidate)
1319
this.xcodeVersions.push(xcodeVersion)
1420
}
1521

xcode-select/dist/index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

xcode-select/src/XcodeVersion/FileSystemXcodeVersionRepository.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export default class FileSystemXcodeVersionRepository implements IXcodeVersionRe
5454
&& e.version.patch === xcodeVersion.version.patch
5555
&& e.isBeta === xcodeVersion.isBeta
5656
&& e.betaNumber === xcodeVersion.betaNumber
57+
&& e.isReleaseCandidate === xcodeVersion.isReleaseCandidate
5758
})
5859
if (existing.length == 0) {
5960
result.push(xcodeVersion)

xcode-select/src/XcodeVersion/XcodeVersion.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,22 @@ export default class XcodeVersion {
55
private _version: SemanticVersion
66
private _isBeta: boolean
77
private _betaNumber: number | null
8+
private _isReleaseCandidate: boolean
89
private _buildNumber: string | null
910

1011
constructor(
1112
filePath: string,
1213
version: SemanticVersion,
1314
isBeta: boolean = false,
1415
betaNumber: number | null = null,
16+
isReleaseCandidate: boolean = false,
1517
buildNumber: string | null = null
1618
) {
1719
this._filePath = filePath
1820
this._version = version
1921
this._isBeta = isBeta
2022
this._betaNumber = betaNumber
23+
this._isReleaseCandidate = isReleaseCandidate
2124
this._buildNumber = buildNumber
2225
}
2326

@@ -37,6 +40,10 @@ export default class XcodeVersion {
3740
return this._betaNumber
3841
}
3942

43+
get isReleaseCandidate(): boolean {
44+
return this._isReleaseCandidate
45+
}
46+
4047
get buildNumber(): string | null {
4148
return this._buildNumber
4249
}
@@ -47,6 +54,7 @@ export default class XcodeVersion {
4754
this.version,
4855
this.isBeta,
4956
this.betaNumber,
57+
this.isReleaseCandidate,
5058
buildNumber
5159
)
5260
}
@@ -59,6 +67,9 @@ export default class XcodeVersion {
5967
str += " " + this.betaNumber
6068
}
6169
}
70+
if (this.isReleaseCandidate) {
71+
str += " RC"
72+
}
6273
if (this.buildNumber != null) {
6374
str += " (" + this.buildNumber + ")"
6475
}
@@ -75,6 +86,10 @@ export function xcodeVersionSort(lhs: XcodeVersion, rhs: XcodeVersion): number {
7586
return -1
7687
} else if (!lhs.isBeta && rhs.isBeta) {
7788
return 1
89+
} else if (lhs.isReleaseCandidate && !rhs.isReleaseCandidate) {
90+
return -1
91+
} else if (!lhs.isReleaseCandidate && rhs.isReleaseCandidate) {
92+
return 1
7893
} else if (lhs.isBeta && rhs.isBeta && lhs.betaNumber != null && rhs.betaNumber != null) {
7994
if (lhs.betaNumber < rhs.betaNumber) {
8095
return -1

xcode-select/src/XcodeVersion/XcodeVersionMatcher.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ export default class XcodeVersionMatcher {
2323
if (lhs.isBeta !== rhs.isBeta) {
2424
return lhs.isBeta ? -1 : 1
2525
}
26+
if (lhs.isReleaseCandidate !== rhs.isReleaseCandidate) {
27+
return lhs.isReleaseCandidate ? -1 : 1
28+
}
2629
return 0
2730
})
2831
.reverse()

xcode-select/src/XcodeVersion/XcodeVersionParser.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,13 @@ export default class XcodeVersionParser implements IXcodeVersionParser {
2727
.replace(/beta.*$/i, "")
2828
// Remove anything after the version number.
2929
.replace(/[^0-9]+$/, "")
30+
const lowerName = name.toLowerCase()
3031
// Check if it is a beta version.
31-
const isBeta = name.toLowerCase().includes("beta")
32+
const isBeta = lowerName.includes("beta")
33+
const isReleaseCandidate = lowerName.includes("rc")
34+
|| lowerName.includes("release candidate")
35+
|| lowerName.includes("release.candidate")
36+
|| lowerName.includes("releasecandidate")
3237
// Extract the b eta number if available.
3338
let betaNumber: number | null = null
3439
if (isBeta) {
@@ -44,6 +49,6 @@ export default class XcodeVersionParser implements IXcodeVersionParser {
4449
if (version == null) {
4550
return null
4651
}
47-
return new XcodeVersion(filePath, version, isBeta, betaNumber)
52+
return new XcodeVersion(filePath, version, isBeta, betaNumber, isReleaseCandidate)
4853
}
4954
}

0 commit comments

Comments
 (0)