Files
xtool-mirror/Sources/PackLib/PackSchema.swift
Kabir Oberai 836fca8daf Improve tmpdir management (#147)
- We now have a single tmpdir "root" that can be recreated at launch to
clean up old stragglers
- The location of this tmpdir root can be controlled by `XTL_TMPDIR` or
`TMPDIR`. In general the path is `$TMPDIR/sh.xtool`.

With this change it should be possible to `export XTL_TMPDIR=/var/tmp`
if `/tmp` doesn't have enough space, which fixes #23.
2025-08-10 01:43:09 -04:00

93 lines
2.5 KiB
Swift

import Foundation
import Yams
import XUtils
public struct PackSchemaBase: Codable, Sendable {
public enum Version: Int, Codable, Sendable {
case v1 = 1
}
public var version: Version
public var orgID: String?
public var bundleID: String?
public var product: String?
public var infoPath: String?
public var entitlementsPath: String?
public var iconPath: String?
public var resources: [String]?
public var extensions: [Extension]?
public struct Extension: Codable, Sendable {
public var product: String
public var bundleID: String?
public var infoPath: String
public var resources: [String]?
public var entitlementsPath: String?
}
}
@dynamicMemberLookup
public struct PackSchema: Sendable {
public typealias Extension = PackSchemaBase.Extension
public enum IDSpecifier: Sendable {
case orgID(String)
case bundleID(String)
func formBundleID(product: String) -> String {
switch self {
case .orgID(let orgID): "\(orgID).\(product)"
case .bundleID(let bundleID): bundleID
}
}
}
public let base: PackSchemaBase
public let idSpecifier: IDSpecifier
public init(validating base: PackSchemaBase) throws {
self.base = base
if base.version != .v1 {
throw StringError("xtool.yml: Unsupported schema version: \(base.version.rawValue)")
}
switch (base.bundleID, base.orgID) {
case (let bundleID?, _):
idSpecifier = .bundleID(bundleID)
case (nil, let orgID?):
idSpecifier = .orgID(orgID)
case (nil, nil):
throw StringError("xtool.yml: Must specify either orgID or bundleID")
}
if let iconPath = base.iconPath {
let ext = URL(fileURLWithPath: iconPath).pathExtension
guard ext == "png" else {
throw StringError("xtool.yml: iconPath should have a 'png' path extension. Got '\(ext)'.")
}
}
}
// swiftlint:disable:next force_try
public static let `default` = try! PackSchema(validating: .init(
version: .v1,
orgID: "com.example"
))
public init(url: URL) async throws {
let data = try await Data(reading: url)
let base = try YAMLDecoder().decode(PackSchemaBase.self, from: data)
try self.init(validating: base)
}
public subscript<Subject>(dynamicMember keyPath: KeyPath<PackSchemaBase, Subject>) -> Subject {
self.base[keyPath: keyPath]
}
}