Skip to content

Commit

Permalink
Get rid of CartonHelpers dependency from carton driver (#502)
Browse files Browse the repository at this point in the history
  • Loading branch information
kateinoigakukun authored Nov 17, 2024
1 parent c44dda0 commit 2fdf063
Show file tree
Hide file tree
Showing 41 changed files with 399 additions and 470 deletions.
6 changes: 2 additions & 4 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ let package = Package(
name: "CartonDriver",
dependencies: [
"SwiftToolchain",
"CartonHelpers"
]
),
.executableTarget(
Expand Down Expand Up @@ -125,7 +124,7 @@ let package = Package(
.target(
name: "SwiftToolchain",
dependencies: [
"CartonHelpers",
"CartonCore",
],
exclude: ["Utilities/README.md"]
),
Expand Down Expand Up @@ -166,8 +165,7 @@ let package = Package(
name: "carton-release",
dependencies: [
.product(name: "ArgumentParser", package: "swift-argument-parser"),
"CartonHelpers",
"WasmTransformer",
"CartonCore",
]
),
.testTarget(
Expand Down
6 changes: 0 additions & 6 deletions Sources/CartonCore/CartonCoreError.swift

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ extension String {
public var isAbsolutePath: Bool { first == "/" }
}

extension FileSystem {
public func traverseRecursively(_ traversalRoot: AbsolutePath) throws -> [AbsolutePath] {
extension FileManager {
public func traverseRecursively(_ traversalRoot: URL) throws -> [URL] {
var isDirectory: ObjCBool = false
guard
FileManager.default.fileExists(atPath: traversalRoot.pathString, isDirectory: &isDirectory)
FileManager.default.fileExists(atPath: traversalRoot.path, isDirectory: &isDirectory)
else {
return []
}
Expand All @@ -33,18 +33,18 @@ extension FileSystem {
return result
}

let enumerator = FileManager.default.enumerator(atPath: traversalRoot.pathString)
let enumerator = FileManager.default.enumerator(atPath: traversalRoot.path)

while let element = enumerator?.nextObject() as? String {
let path = try traversalRoot.appending(RelativePath(validating: element))
let path = traversalRoot.appendingPathComponent(element)
result.append(path)
}

return result
}

public func resourcesDirectoryNames(relativeTo buildDirectory: AbsolutePath) throws -> [String] {
try FileManager.default.contentsOfDirectory(atPath: buildDirectory.pathString).filter {
public func resourcesDirectoryNames(relativeTo buildDirectory: URL) throws -> [String] {
try FileManager.default.contentsOfDirectory(atPath: buildDirectory.path).filter {
$0.hasSuffix(".resources")
}
}
Expand Down
17 changes: 17 additions & 0 deletions Sources/CartonCore/FoundationProcessEx.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,21 @@ extension Foundation.Process {
forwardExit: forwardExit
)
}

public static func which(_ executable: String) throws -> URL {
let pathSeparator: Character
#if os(Windows)
pathSeparator = ";"
#else
pathSeparator = ":"
#endif
let paths = ProcessInfo.processInfo.environment["PATH"]!.split(separator: pathSeparator)
for path in paths {
let url = URL(fileURLWithPath: String(path)).appendingPathComponent(executable)
if FileManager.default.isExecutableFile(atPath: url.path) {
return url
}
}
throw CartonCoreError("Executable \(executable) not found in PATH")
}
}
113 changes: 113 additions & 0 deletions Sources/CartonCore/InteractiveWriter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
This source file is part of the Swift.org open source project
Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception
See http://swift.org/LICENSE.txt for license information
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
*/

import Foundation

#if os(Android) || canImport(Musl)
public typealias FILEPointer = OpaquePointer
#else
public typealias FILEPointer = UnsafeMutablePointer<FILE>
#endif

/// Implements file output stream for local file system.
public final class _LocalFileOutputByteStream {

/// The pointer to the file.
let filePointer: FILEPointer

public static let stdout = _LocalFileOutputByteStream(filePointer: Foundation.stdout)
public static let stderr = _LocalFileOutputByteStream(filePointer: Foundation.stderr)

/// Instantiate using the file pointer.
public init(filePointer: FILEPointer) {
self.filePointer = filePointer
}

@discardableResult
public func send(_ value: CustomStringConvertible) -> _LocalFileOutputByteStream {
var contents = [UInt8](value.description.utf8)
while true {
let n = fwrite(&contents, 1, contents.count, filePointer)
if n < 0 {
if errno == EINTR { continue }
} else if n != contents.count {
continue
}
break
}
return self
}

public func flush() {
fflush(filePointer)
}
}

/// This class is used to write on the underlying stream.
///
/// If underlying stream is a not tty, the string will be written in without any
/// formatting.
public final class InteractiveWriter {
/// The standard error writer.
public static let stderr = InteractiveWriter(stream: .stderr)

/// The standard output writer.
public static let stdout = InteractiveWriter(stream: .stdout)

/// The terminal controller, if present.
private let term: TerminalController?

/// The output byte stream reference.
private let stream: _LocalFileOutputByteStream

/// Create an instance with the given stream.
public init(stream: _LocalFileOutputByteStream) {
term = TerminalController(stream: stream)
self.stream = stream
}

/// Write the string to the contained terminal or stream.
public func write(
_ string: String,
inColor color: TerminalController.Color = .noColor,
bold: Bool = false
) {
if let term = term {
term.write(string, inColor: color, bold: bold)
} else {
stream.send(string)
stream.flush()
}
}

public func clearLine() {
if let term = term {
term.clearLine()
} else {
stream.send("\n")
stream.flush()
}
}

public func saveCursor() {
term?.write("\u{001B}[s")
}

public func revertCursorAndClear() {
term?.write("\u{001B}[u\u{001B}[2J\u{001B}H")
}

public func logLookup<T>(_ description: String, _ target: T, newline: Bool = false)
where T: CustomStringConvertible {
write(description)
write("\(target)\n", inColor: .cyan, bold: true)
if newline {
write("\n")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.

public struct CartonCoreError: Error & CustomStringConvertible {
public init(_ description: String) {
self.description = description
}
public var description: String
}

public let cartonVersion = "1.1.2"

#if compiler(>=6.0)
public let defaultToolchainVersion = "wasm-6.0.2-RELEASE"
#elseif compiler(>=5.10)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public final class TerminalController {
}

/// Pointer to output stream to operate on.
private var stream: WritableByteStream
private var stream: _LocalFileOutputByteStream

/// Width of the terminal.
public var width: Int {
Expand All @@ -84,13 +84,9 @@ public final class TerminalController {
private let boldString = "\u{001B}[1m"

/// Constructs the instance if the stream is a tty.
public init?(stream: WritableByteStream) {
let realStream = (stream as? ThreadSafeOutputByteStream)?.stream ?? stream

public init?(stream: _LocalFileOutputByteStream) {
// Make sure it is a file stream and it is tty.
guard let fileStream = realStream as? LocalFileOutputByteStream,
TerminalController.isTTY(fileStream)
else {
guard TerminalController.isTTY(stream) else {
return nil
}

Expand All @@ -109,14 +105,14 @@ public final class TerminalController {
}

/// Checks if passed file stream is tty.
public static func isTTY(_ stream: LocalFileOutputByteStream) -> Bool {
public static func isTTY(_ stream: _LocalFileOutputByteStream) -> Bool {
return terminalType(stream) == .tty
}

/// Computes the terminal type of the stream.
public static func terminalType(_ stream: LocalFileOutputByteStream) -> TerminalType {
public static func terminalType(_ stream: _LocalFileOutputByteStream) -> TerminalType {
#if !os(Windows)
if ProcessEnv.block["TERM"] == "dumb" {
if ProcessInfo.processInfo.environment["TERM"] == "dumb" {
return .dumb
}
#endif
Expand All @@ -138,7 +134,7 @@ public final class TerminalController {
return Int(csbi.srWindow.Right - csbi.srWindow.Left) + 1
#else
// Try to get from environment.
if let columns = ProcessEnv.block["COLUMNS"], let width = Int(columns) {
if let columns = ProcessInfo.processInfo.environment["COLUMNS"], let width = Int(columns) {
return width
}

Expand Down Expand Up @@ -181,7 +177,7 @@ public final class TerminalController {

/// Writes a string to the stream.
public func write(_ string: String, inColor color: Color = .noColor, bold: Bool = false) {
writeWrapped(string, inColor: color, bold: bold, stream: stream)
stream.send(writeWrapped(string, inColor: color, bold: bold))
flush()
}

Expand All @@ -193,19 +189,16 @@ public final class TerminalController {

/// Wraps the string into the color mentioned.
public func wrap(_ string: String, inColor color: Color, bold: Bool = false) -> String {
let stream = BufferedOutputByteStream()
writeWrapped(string, inColor: color, bold: bold, stream: stream)
return stream.bytes.description
return writeWrapped(string, inColor: color, bold: bold)
}

private func writeWrapped(
_ string: String, inColor color: Color, bold: Bool = false, stream: WritableByteStream
) {
_ string: String, inColor color: Color, bold: Bool = false
) -> String {
// Don't wrap if string is empty or color is no color.
guard !string.isEmpty && color != .noColor else {
stream.send(string)
return
return string
}
stream.send(color.string).send(bold ? boldString : "").send(string).send(resetString)
return color.string + (bold ? boldString : "") + string + resetString
}
}
24 changes: 12 additions & 12 deletions Sources/CartonDriver/CartonDriverCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
// This executable should be eventually removed once SwiftPM provides a way to express those requirements.

import CartonCore
import CartonHelpers
import Foundation
import SwiftToolchain

Expand Down Expand Up @@ -134,31 +133,32 @@ func pluginSubcommand(subcommand: String, argv0: String, arguments: [String]) as
}

let terminal = InteractiveWriter.stdout
let toolchainSystem = try ToolchainSystem(fileSystem: localFileSystem)
let toolchainSystem = try ToolchainSystem(fileSystem: .default)
let swiftPath = try await toolchainSystem.inferSwiftPath(terminal)
let extraArguments = arguments

let swiftExec = URL(fileURLWithPath: swiftPath.swift.pathString)
let pluginArguments = try derivePackageCommandArguments(
swiftExec: swiftExec,
swiftExec: swiftPath.swift,
subcommand: subcommand,
scratchPath: scratchPath.path,
extraArguments: extraArguments
)

var env: [String: String] = ProcessInfo.processInfo.environment
if ToolchainSystem.isSnapshotVersion(swiftPath.version),
swiftPath.toolchain.extension == "xctoolchain"
swiftPath.toolchain.pathExtension == "xctoolchain"
{
env["DYLD_LIBRARY_PATH"] = swiftPath.toolchain.appending(
components: ["usr", "lib", "swift", "macosx"]
).pathString
env["DYLD_LIBRARY_PATH"] = swiftPath.toolchain
.appendingPathComponent("usr")
.appendingPathComponent("lib")
.appendingPathComponent("swift")
.appendingPathComponent("macosx")
.path
}

try Foundation.Process.checkRun(
swiftExec,
swiftPath.swift,
arguments: pluginArguments,
environment: env,
forwardExit: true
)
}
Expand All @@ -185,11 +185,11 @@ public func main(arguments: [String]) async throws {
subcommand: subcommand, argv0: argv0, arguments: Array(arguments.dropFirst()))
case "package":
let terminal = InteractiveWriter.stdout
let toolchainSystem = try ToolchainSystem(fileSystem: localFileSystem)
let toolchainSystem = try ToolchainSystem(fileSystem: .default)
let swiftPath = try await toolchainSystem.inferSwiftPath(terminal)

try Foundation.Process.checkRun(
URL(fileURLWithPath: swiftPath.swift.pathString),
swiftPath.swift,
arguments: ["package"] + arguments.dropFirst(),
forwardExit: true
)
Expand Down
2 changes: 1 addition & 1 deletion Sources/CartonFrontend/CartonFrontendCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// limitations under the License.

import ArgumentParser
import CartonHelpers
import CartonCore

public struct CartonFrontendCommand: AsyncParsableCommand {
public static let configuration = CommandConfiguration(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import ArgumentParser
import CartonHelpers
import CartonCore
import CartonKit
import Foundation

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

import CartonHelpers
import CartonCore
import CartonKit
import Foundation
import NIOCore
Expand Down
Loading

0 comments on commit 2fdf063

Please sign in to comment.