Repository navigation
Conversation
`xcode-select -p` exits with status 2 when no developer directory is selected, e.g. on a new Mac without Xcode or the Command Line Tools. `list`, `update`, `installed` and `select` (also used by `install --select`) all ran it and aborted on that error. Treat that failure as "no selected Xcode" instead: the lists are printed without a selected marker, `select -p` prints "No selected Xcode", and `select` goes on to select the requested Xcode.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #210.
On a Mac with no developer directory selected (no Xcode and no Command Line Tools, which is what a new Mac looks like),
xcode-select -pexits with status 2.xcodes list,update,installedandselect(with or without-p) all run it, so they abort with that error.xcodes install --selectinstalls Xcode and then fails at the select step for the same reason.With this change, a failing
xcode-select -pmeans "no selected Xcode":list,updateandinstalledprint the list without a selected markerselect -pprints the existingNo selected Xcodemessageselectselects the requested Xcode, or shows the interactive list when no version or path is givenNothing changes when
xcode-select -psucceeds.Root cause
printAvailableXcodes,printInstalledXcodesandselectXcodeAsyncstart withtry await Current.shell.xcodeSelectPrintPath().XcodesProcess.runthrowsProcessExecutionErrorfor a non-zero exit status, and nothing caught it. The selected path is only used to mark the selected Xcode (and, inselect, to detect "already selected"), but its absence failed the whole command.The fix
Environment.swift: newShell.selectedXcodePath(), which callsxcodeSelectPrintPathand returnsnilwhen it throwsProcessExecutionError. Other errors still propagate. It follows the same pattern asauthenticateSudoerIfNecessaryAsync, so tests keep mockingxcodeSelectPrintPath.XcodeInstaller.swift:printAvailableXcodesandprintInstalledXcodespass the optional path toXcodeListPresentationService, which already treatsnilas "nothing selected".XcodeSelect.swift:selectXcodeAsyncuses the helper and passes""toXcodeSelectionServicewhen nothing is selected.XcodeSelectionService.requestcompares the trimmed request with the trimmed selected path, so with nothing selected,xcodes selectwithout arguments would come back as.alreadySelectedPathand printXcode at path is already selected. That case is now only honoured when a path is actually selected. Otherwise it is handled like.selectPath, which falls back to the interactive list as it does today. Another option would be an optional selected path in XcodesKit'sXcodeSelectionService.request. I kept the change in this repo so it works with the current XcodesKit 1.1.x.Testing
Added four tests to
XcodesKitTeststhat stubxcodeSelectPrintPathto throwProcessExecutionErrorwith status 2, which is whatXcodesProcess.runthrows for that exit:test_PrintAvailableXcodes_WithNoSelectedXcode_PrintsXcodestest_Installed_WithNoSelectedXcodetest_SelectPrint_WithNoSelectedXcodetest_SelectInteractively_WithNoSelectedXcodeOn
mainall four fail with the thrownProcessExecutionError. With this change they pass. Before I added the.alreadySelectedPathhandling, the interactive test failed withXcode at path is already selected.Ran
swift testlocally with Swift 6.4 (Xcode 27.0): 90 tests, 85 pass. The 5 failures aretest_InstallLogging_*, and they fail the same way onmain(86 tests, same 5 failures). My Mac's region setting formats the download percentage as1 %with a non-breaking space, while the fixtures expect1%. Those tests don't go through the code changed here, and CI onmainis green.The new code builds without warnings (
swift build --build-tests -Xswiftc -warnings-as-errors).Ran the built
xcodes select -pandxcodes installedon a Mac that has Xcode selected. The output is the same as before, and the selected Xcode is still marked.I didn't test on a Mac with no developer directory. That needs a machine without
/Applications/Xcode.app, without the Command Line Tools and without anxcode-select -spath.DEVELOPER_DIRdoesn't simulate it, becausexcode-select -pjust prints whatever it is set to.