From af25b0da322d59082eadcadb09d5c658f3dc7d4e Mon Sep 17 00:00:00 2001 From: Sergey Khruschak Date: Sun, 6 Jul 2025 08:35:51 +0000 Subject: [PATCH 1/6] Swift 6 --- .devcontainer/devcontainer.json | 2 +- .vscode/launch.json | 22 ++++++++++++++++++++++ Package.swift | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 5655a49..d0a85dd 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,6 @@ { "name": "Swift", - "image": "swift:5.9", + "image": "swift:6.1", "features": { "ghcr.io/devcontainers/features/common-utils:2": { "installZsh": "false", diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..d0b3b2a --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,22 @@ +{ + "configurations": [ + { + "type": "swift", + "request": "launch", + "args": [], + "cwd": "${workspaceFolder:table-cli}", + "name": "Debug table", + "program": "${workspaceFolder:table-cli}/.build/debug/table", + "preLaunchTask": "swift: Build Debug table" + }, + { + "type": "swift", + "request": "launch", + "args": [], + "cwd": "${workspaceFolder:table-cli}", + "name": "Release table", + "program": "${workspaceFolder:table-cli}/.build/release/table", + "preLaunchTask": "swift: Build Release table" + } + ] +} \ No newline at end of file diff --git a/Package.swift b/Package.swift index b0188bd..ab06251 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 5.8 +// swift-tools-version: 6.1 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription From 564ee7f10f5f43a83153132f194f9c9873d209ca Mon Sep 17 00:00:00 2001 From: Sergey Khruschak Date: Sun, 13 Jul 2025 19:58:18 +0000 Subject: [PATCH 2/6] dev container update --- .devcontainer/devcontainer.json | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index d0a85dd..bf78d14 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,18 +2,8 @@ "name": "Swift", "image": "swift:6.1", "features": { - "ghcr.io/devcontainers/features/common-utils:2": { - "installZsh": "false", - "username": "vscode", - "userUid": "1000", - "userGid": "1000", - "upgradePackages": "false" - }, - "ghcr.io/devcontainers/features/git:1": { - "version": "os-provided", - "ppa": "false" - }, - "ghcr.io/swift-server-community/swift-devcontainer-features/swift-format:0": {} + "ghcr.io/devcontainers/features/common-utils:2": {}, + "ghcr.io/devcontainers/features/git:1": {} }, "runArgs": [ "--cap-add=SYS_PTRACE", @@ -30,16 +20,13 @@ }, // Add the IDs of extensions you want installed when the container is created. "extensions": [ - "sswg.swift-lang" + "swiftlang.swift-vscode" ] } }, // Use 'forwardPorts' to make a list of ports inside the container available locally. // "forwardPorts": [], - // Use 'postCreateCommand' to run commands after the container is created. - "postCreateCommand": "swift --version", - // Set `remoteUser` to `root` to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. - "remoteUser": "vscode" + "remoteUser": "root" } From b6e1ed5fb69129bcfe57d1a0fb22068f00646d15 Mon Sep 17 00:00:00 2001 From: Sergey Khruschak Date: Wed, 16 Jul 2025 17:26:53 +0300 Subject: [PATCH 3/6] swift 6 changes --- Package.resolved | 7 ++++--- Package.swift | 7 +++---- Sources/table/Extensions.swift | 4 +--- Sources/table/MainApp.swift | 29 ++++++++++++++++++++++------- Sources/table/Shell.swift | 1 - test-data/mixed_quotes_sql.out | 13 +++++++++++++ 6 files changed, 43 insertions(+), 18 deletions(-) create mode 100644 test-data/mixed_quotes_sql.out diff --git a/Package.resolved b/Package.resolved index aceaff7..947204d 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,14 +1,15 @@ { + "originHash" : "84a9b1698a9c385c559d9f7dafb10494b6e8006ab6e2051965b29e02f3f15759", "pins" : [ { "identity" : "swift-argument-parser", "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-argument-parser.git", "state" : { - "revision" : "011f0c765fb46d9cac61bca19be0527e99c98c8b", - "version" : "1.5.1" + "revision" : "309a47b2b1d9b5e991f36961c983ecec72275be3", + "version" : "1.6.1" } } ], - "version" : 2 + "version" : 3 } diff --git a/Package.swift b/Package.swift index ab06251..b0b30f2 100644 --- a/Package.swift +++ b/Package.swift @@ -6,8 +6,7 @@ import PackageDescription let package = Package( name: "table", dependencies: [ - .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.5.1"), - // .package(url: "https://github.com/groue/GRMustache.swift", from: "4.0.0") + .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.6.1") ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. @@ -16,8 +15,8 @@ let package = Package( name: "table", dependencies: [ .product(name: "ArgumentParser", package: "swift-argument-parser"), - // .product(name: "Mustache", package: "GRMustache.swift") - ]), + ] + ), .testTarget( name: "table-Tests", dependencies: ["table"]), diff --git a/Sources/table/Extensions.swift b/Sources/table/Extensions.swift index 556d19b..caa55ca 100644 --- a/Sources/table/Extensions.swift +++ b/Sources/table/Extensions.swift @@ -56,7 +56,5 @@ extension Table { } func debug(_ message: String) { - if Global.debug { - print(message) - } + Debug.debug(message) } \ No newline at end of file diff --git a/Sources/table/MainApp.swift b/Sources/table/MainApp.swift index 4655411..9b4a1a6 100644 --- a/Sources/table/MainApp.swift +++ b/Sources/table/MainApp.swift @@ -1,8 +1,24 @@ import ArgumentParser import Foundation -struct Global { - static var debug: Bool = false +struct Debug { + // this one is set on start, so we don't care about concurrency checks + nonisolated(unsafe) private static var debug: Bool = false + + static func enableDebug() { + debug = true + print("Debug mode enabled") + } + + static func debug(_ message: String) { + if debug { + print(message) + } + } + + static func isDebugEnabled() -> Bool { + return debug + } } func buildPrinter(formatOpt: Format?, outFileFmt: FileType, outputFile: String?) throws -> TablePrinter { @@ -31,7 +47,7 @@ func buildPrinter(formatOpt: Format?, outFileFmt: FileType, outputFile: String?) } @main -struct MainApp: ParsableCommand { +struct MainApp: ParsableCommand { static let configuration = CommandConfiguration( commandName: "table", abstract: "A utility for transforming CSV files of SQL output.", @@ -109,11 +125,10 @@ struct MainApp: ParsableCommand { @Option(name: .customLong("generate"), help: "Generates a sample empty table with the specified number of rows. Example: '--generate 1000 --add id=%{uuid}' will generate a table of UUIDs with 1000 rows.") var generate: Int? - mutating func run() throws { + mutating func run() async throws { if debugEnabled { - Global.debug = true - print("Debug enabled") + Debug.enableDebug() } let userTypes = try columnTypes.map { try CellType.fromStringList($0) } @@ -165,7 +180,7 @@ struct MainApp: ParsableCommand { let formatOpt = try printFormat.map { try Format(format: $0).validated(header: table.header) } if let sortColumns { - let expression = try Sort(sortColumns).validated(header: table.header) + let expression = try Sort(sortColumns).validated(header: table.header) debug("Sorting by columns: \(expression.columns.map { (name, order) in "\(name) \(order)" }.joined(separator: ","))") table = try InMemoryTableView(table: table).sort(expr: expression) } diff --git a/Sources/table/Shell.swift b/Sources/table/Shell.swift index ea9129a..9cde5fa 100644 --- a/Sources/table/Shell.swift +++ b/Sources/table/Shell.swift @@ -12,7 +12,6 @@ func shell(_ command: String, env: Dictionary = [:]) throws -> S task.launchPath = "/bin/bash" task.standardInput = nil - try task.run() task.waitUntilExit() diff --git a/test-data/mixed_quotes_sql.out b/test-data/mixed_quotes_sql.out new file mode 100644 index 0000000..c5e72a3 --- /dev/null +++ b/test-data/mixed_quotes_sql.out @@ -0,0 +1,13 @@ ++-----------------------------------+---------+--------------------+ +| ref | count | id | ++-----------------------------------+---------+--------------------+ +| 45af1d3287f11111 | 5 | 50403400 | +| 68ce1086965bd401 | 2 | 3A | +| 546b1729e5ae8401 | 14 | 241.39564439115765 | +| 0407549437d54cb5b1dbea45c03e2a1c | 10 | 1A01 | +| 0864c5bdf9604a8ebf1c5816aff5087f | 8 | 1811 | +| 0ffd3d159c724129932d90ed315fb5d6 | 3 | 900 | +| 165b6f71e80348d49c3dc236c3ffe373 | 5 | 1500 | +| 1a4bf1fb1ebb46818a41e0e208a14730 | 2 | 80 | +| 2a2e17c3d1004ad5b0489ec85b28396a | 5 | 1500 | ++-----------------------------------+---------+--------------------+ \ No newline at end of file From 7a2b3b4a80719964c3158c23dfeb0487ff7c01ce Mon Sep 17 00:00:00 2001 From: Sergey Khruschak Date: Wed, 16 Jul 2025 17:44:29 +0300 Subject: [PATCH 4/6] using sync --- Sources/table/MainApp.swift | 2 +- Sources/table/Shell.swift | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Sources/table/MainApp.swift b/Sources/table/MainApp.swift index 9b4a1a6..8c81e7d 100644 --- a/Sources/table/MainApp.swift +++ b/Sources/table/MainApp.swift @@ -125,7 +125,7 @@ struct MainApp: ParsableCommand { @Option(name: .customLong("generate"), help: "Generates a sample empty table with the specified number of rows. Example: '--generate 1000 --add id=%{uuid}' will generate a table of UUIDs with 1000 rows.") var generate: Int? - mutating func run() async throws { + mutating func run() throws { if debugEnabled { Debug.enableDebug() diff --git a/Sources/table/Shell.swift b/Sources/table/Shell.swift index 9cde5fa..fdc68e8 100644 --- a/Sources/table/Shell.swift +++ b/Sources/table/Shell.swift @@ -11,8 +11,7 @@ func shell(_ command: String, env: Dictionary = [:]) throws -> S task.arguments = ["-c", command] task.launchPath = "/bin/bash" task.standardInput = nil - - try task.run() + task.launch() task.waitUntilExit() let data = pipe.fileHandleForReading.readDataToEndOfFile() From f46f9be10f62434e55dbbcb53597806796b95590 Mon Sep 17 00:00:00 2001 From: Sergey Khruschak Date: Wed, 16 Jul 2025 21:25:30 +0300 Subject: [PATCH 5/6] GH actions updated --- .github/workflows/build-test.yaml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-test.yaml b/.github/workflows/build-test.yaml index e355357..d4db5ef 100644 --- a/.github/workflows/build-test.yaml +++ b/.github/workflows/build-test.yaml @@ -9,7 +9,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest] - swift: ["5.10"] + swift: ["6.1"] steps: - uses: actions/checkout@v4 - uses: swift-actions/setup-swift@v2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 96f7c8f..101d7e0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest ] - swift: ["5.10"] + swift: ["6.1"] steps: - uses: actions/checkout@v4 - uses: swift-actions/setup-swift@v2 From 3b03c42a20f8198b3f309203ecbf5fd0a02d1a7f Mon Sep 17 00:00:00 2001 From: Sergey Khruschak Date: Fri, 18 Jul 2025 23:15:13 +0300 Subject: [PATCH 6/6] updated fileno --- Sources/table/Table.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/table/Table.swift b/Sources/table/Table.swift index f3529d2..4487948 100644 --- a/Sources/table/Table.swift +++ b/Sources/table/Table.swift @@ -96,7 +96,7 @@ class ParsedTable: Table { file = try FileHandle(forReadingAtPath: path).orThrow(RuntimeError("File \(path) is not found")) } else { - if (isatty(fileno(stdin)) != 0) { + if (isatty(STDIN_FILENO) != 0) { throw RuntimeError("No input file provided and standard input is not a terminal. Use --input to specify a file or --generate to generate rows.") }