1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import Foundation
enum Paths {
static var packageDir: URL {
URL(fileURLWithPath: #filePath)
.deletingLastPathComponent()
.deletingLastPathComponent()
.deletingLastPathComponent()
.deletingLastPathComponent()
.deletingLastPathComponent()
}
static var sourcesDir: URL {
packageDir
.appendingPathComponent("Sources")
}
static var examplesDir: URL {
packageDir
.appendingPathComponent("Examples")
}
static var swiftParserCliDir: URL {
packageDir
.appendingPathComponent("SwiftParserCLI")
}
static var codeGenerationDir: URL {
packageDir
.appendingPathComponent("CodeGeneration")
}
static var editorExtensionProjectPath: URL {
packageDir
.appendingPathComponent("EditorExtension")
.appendingPathComponent("SwiftRefactorExtension.xcodeproj")
}
static var diffExec: URL {
get throws {
return try lookupExecutable(for: "diff")
}
}
static var gitExec: URL {
get throws {
try lookupExecutable(for: "git")
}
}
static var swiftExec: URL {
get throws {
try lookupExecutable(for: "swift")
}
}
/// The directory in which swift-format should be built.
static var swiftFormatBuildDir: URL {
packageDir
.appendingPathComponent(".swift-format-build")
}
static var xcodebuildExec: URL {
get throws {
return try lookupExecutable(for: "xcodebuild")
}
}
static var xcrunExec: URL {
get throws {
return try lookupExecutable(for: "xcrun")
}
}
private static var envSearchPaths: [URL] {
// Compute search paths from PATH variable.
#if os(Windows)
let pathSeparator: Character = ";"
#else
let pathSeparator: Character = ":"
#endif
return (paths ?? "")
.split(separator: pathSeparator)
.map(String.init)
.compactMap { pathString in
return URL(fileURLWithPath: pathString)
}
}
private static var paths: String? {
#if os(Windows)
let pathArg = "Path"
#else
let pathArg = "PATH"
#endif
return ProcessInfo.processInfo.environment[pathArg]
}
enum ExecutableLookupError: Error, CustomStringConvertible {
case notFound(executableName: String)
var description: String {
switch self {
case .notFound(executableName: let executableName):
return "Executable \(executableName) not found in PATH"
}
}
}
private static func lookupExecutable(for filename: String) throws -> URL {
let executable = envSearchPaths.map { $0.appendingPathComponent(filename) }
.first(where: { $0.isExecutableFile })
guard let executable else {
throw ExecutableLookupError.notFound(executableName: filename)
}
return executable
}
}
extension URL {
var isExecutableFile: Bool {
return (self.isFile(path) || self.isSymlink(path)) && FileManager.default.isExecutableFile(atPath: path)
}
private func isFile(_ path: String) -> Bool {
let attrs = try? FileManager.default.attributesOfItem(atPath: path)
return attrs?[.type] as? FileAttributeType == .typeRegular
}
private func isSymlink(_ path: String) -> Bool {
let attrs = try? FileManager.default.attributesOfItem(atPath: path)
return attrs?[.type] as? FileAttributeType == .typeSymbolicLink
}
}
|