Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Sources/Commands/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ add_library(Commands
PackageCommands/Resolve.swift
PackageCommands/ShowDependencies.swift
PackageCommands/ShowExecutables.swift
PackageCommands/ShowTraits.swift
PackageCommands/SwiftPackageCommand.swift
PackageCommands/ToolsVersionCommand.swift
PackageCommands/Update.swift
Expand Down
85 changes: 85 additions & 0 deletions Sources/Commands/PackageCommands/ShowTraits.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2014-2025 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 the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import ArgumentParser
import Basics
import CoreCommands
import Foundation
import PackageModel
import PackageGraph
import Workspace

struct ShowTraits: AsyncSwiftCommand {
static let configuration = CommandConfiguration(
abstract: "List the available traits for a package.")

@OptionGroup(visibility: .hidden)
var globalOptions: GlobalOptions

@Option(help: "Show traits for the package id")
var packageId: String?

@Option(help: "Set the output format.")
var format: ShowTraitsMode = .flatlist

func run(_ swiftCommandState: SwiftCommandState) async throws {
let packageGraph = try await swiftCommandState.loadPackageGraph()

let traits = if let packageId {
packageGraph.packages.filter({ $0.identity.description == packageId }).flatMap( { $0.manifest.traits } ).sorted(by: {$0.name < $1.name} )
} else {
packageGraph.rootPackages.flatMap( { $0.manifest.traits } ).sorted(by: {$0.name < $1.name} )
}

switch self.format {
case .flatlist:
let defaultTraits = traits.filter( { $0.isDefault } ).flatMap( { $0.enabledTraits })

for trait in traits {
guard !trait.isDefault else {
continue
}

print("\(trait.name)\(trait.description ?? "" != "" ? " - " + trait.description! : "")\(defaultTraits.contains(trait.name) ? " (default)" : "")")
}

case .json:
let encoder = JSONEncoder()
let data = try encoder.encode(traits)
if let output = String(data: data, encoding: .utf8) {
print(output)
}
}
}

enum ShowTraitsMode: String, RawRepresentable, CustomStringConvertible, ExpressibleByArgument, CaseIterable {
case flatlist, json

public init?(rawValue: String) {
switch rawValue.lowercased() {
case "flatlist":
self = .flatlist
case "json":
self = .json
default:
return nil
}
}

public var description: String {
switch self {
case .flatlist: return "flatlist"
case .json: return "json"
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public struct SwiftPackageCommand: AsyncParsableCommand {

ShowDependencies.self,
ShowExecutables.self,
ShowTraits.self,
ToolsVersionCommand.self,
ComputeChecksum.self,
ArchiveSource.self,
Expand Down
Loading