@@ -169,44 +169,14 @@ extension Platform {
169169
170170 // Install ourselves in the final location
171171 public func installSwiftlyBin( _ ctx: SwiftlyCoreContext ) async throws {
172- // First, let's find out where we are.
173- let cmd = CommandLine . arguments [ 0 ]
174-
175- var cmdAbsolute : FilePath ?
176-
177- if cmd. hasPrefix ( " / " ) {
178- cmdAbsolute = FilePath ( cmd)
179- } else {
180- let pathEntries = ( [ fs. cwd. string] + ( ProcessInfo . processInfo. environment [ " PATH " ] ? . components ( separatedBy: " : " ) ?? [ ] ) ) . map
181- {
182- FilePath ( $0) / cmd
183- }
184-
185- for pathEntry in pathEntries {
186- if try await fs. exists ( atPath: pathEntry) {
187- cmdAbsolute = pathEntry
188- break
189- }
190- }
191- }
192-
193172 // We couldn't find ourselves in the usual places. Assume that no installation is necessary
194173 // since we were most likely invoked at SWIFTLY_BIN_DIR already.
195- guard let cmdAbsolute else {
196- return
197- }
198-
199- // If swiftly is symlinked then we leave it where it is, such as in a homebrew installation.
200- if let _ = try ? FileManager . default. destinationOfSymbolicLink ( atPath: cmdAbsolute) {
174+ guard let cmdAbsolute = try await self . absoluteCommandPath ( ) else {
201175 return
202176 }
203177
204- // Proceed to installation only if we're in the user home directory, or a non-system location.
205- let userHome = fs. home
206-
207- let systemRoots : [ FilePath ] = [ " /usr " , " /opt " , " /bin " ]
208-
209- guard cmdAbsolute. starts ( with: userHome) || systemRoots. filter ( { cmdAbsolute. starts ( with: $0) } ) . first == nil else {
178+ // Make sure swiftly is not system managed.
179+ if try await self . isSystemManaged ( cmdAbsolute) {
210180 return
211181 }
212182
@@ -242,55 +212,24 @@ extension Platform {
242212 // Find the location where swiftly should be executed.
243213 public func findSwiftlyBin( _ ctx: SwiftlyCoreContext ) async throws -> FilePath ? {
244214 let swiftlyHomeBin = self . swiftlyBinDir ( ctx) / " swiftly "
245-
246- // First, let's find out where we are.
247- let cmd = CommandLine . arguments [ 0 ]
248- var cmdAbsolute : FilePath ?
249- if cmd. hasPrefix ( " / " ) {
250- cmdAbsolute = FilePath ( cmd)
251- } else {
252- let pathEntries = ( [ fs. cwd. string] + ( ProcessInfo . processInfo. environment [ " PATH " ] ? . components ( separatedBy: " : " ) ?? [ ] ) ) . map
253- {
254- FilePath ( $0) / cmd
255- }
256-
257- for pathEntry in pathEntries {
258- if try await fs. exists ( atPath: pathEntry) {
259- cmdAbsolute = pathEntry
260- break
261- }
262- }
263- }
264-
265- // We couldn't find ourselves in the usual places, so if we're not going to be installing
266- // swiftly then we can assume that we are running from the final location.
267- let homeBinExists = try await fs. exists ( atPath: swiftlyHomeBin)
268- if cmdAbsolute == nil && homeBinExists {
269- return swiftlyHomeBin
270- }
271-
272- // If swiftly is a symlink then something else, such as homebrew, is managing it.
273- if cmdAbsolute != nil {
274- if let _ = try ? FileManager . default. destinationOfSymbolicLink ( atPath: cmdAbsolute!) {
275- return cmdAbsolute
215+ guard let cmdAbsolute = try await self . absoluteCommandPath ( ) else {
216+ if try await fs. exists ( atPath: swiftlyHomeBin) {
217+ // We couldn't find ourselves in the usual places, so if we're not going to be installing
218+ // swiftly then we can assume that we are running from the final location.
219+ return swiftlyHomeBin
276220 }
221+ return nil
277222 }
278223
279- let systemRoots : [ FilePath ] = [ " /usr " , " /opt " , " /bin " ]
280-
281- // If we are system managed then we know where swiftly should be.
282- let userHome = fs. home
283-
284- if let cmdAbsolute, !cmdAbsolute. starts ( with: userHome) && systemRoots. filter ( { cmdAbsolute. starts ( with: $0) } ) . first != nil {
224+ if try await self. isSystemManaged ( cmdAbsolute) {
285225 return cmdAbsolute
286226 }
287227
288228 // If we're running inside an xctest then we don't have a location for this swiftly.
289- guard let cmdAbsolute,
290- !(
291- ( cmdAbsolute. string. hasSuffix ( " xctest " ) || cmdAbsolute. string. hasSuffix ( " swiftpm-testing-helper " ) )
292- && CommandLine . arguments. contains { $0. contains ( " InstallTests " ) }
293- )
229+ guard !(
230+ ( cmdAbsolute. string. hasSuffix ( " xctest " ) || cmdAbsolute. string. hasSuffix ( " swiftpm-testing-helper " ) )
231+ && CommandLine . arguments. contains { $0. contains ( " InstallTests " ) }
232+ )
294233 else {
295234 return nil
296235 }
@@ -303,5 +242,37 @@ extension Platform {
303242 ( try await self . findToolchainLocation ( ctx, toolchain) ) / " usr/bin "
304243 }
305244
245+ private func absoluteCommandPath( ) async throws -> FilePath ? {
246+ let cmd = CommandLine . arguments [ 0 ]
247+ if cmd. hasPrefix ( " / " ) {
248+ return FilePath ( cmd)
249+ }
250+ let localCmd = FilePath ( fs. cwd. string) / cmd
251+ if try await fs. exists ( atPath: localCmd) {
252+ return localCmd
253+ }
254+ guard let path = ProcessInfo . processInfo. environment [ " PATH " ] else {
255+ return nil
256+ }
257+ let pathEntries = path. components ( separatedBy: " : " ) . map { FilePath ( $0) / cmd }
258+ for pathEntry in pathEntries where try await fs. exists ( atPath: pathEntry) {
259+ return pathEntry
260+ }
261+ return nil
262+ }
263+
264+ private func isSystemManaged( _ path: FilePath) async throws -> Bool {
265+ // If swiftly is symlinked then we leave it where it is, such as in a Homebrew installation.
266+ if try await fs. isSymLink ( atPath: path) {
267+ return true
268+ }
269+ if path. starts ( with: fs. home) {
270+ // In user's home directory, so not system managed.
271+ return false
272+ }
273+ // With a system prefix?
274+ return [ " /usr " , " /opt " , " /bin " ] . contains { path. starts ( with: $0) }
275+ }
276+
306277#endif
307278}
0 commit comments