Skip to content

Commit

Permalink
Merge pull request #23 from xing/support_products
Browse files Browse the repository at this point in the history
Support to use Product as target in SPM
  • Loading branch information
Juantri94 authored Aug 20, 2023
2 parents f178a39 + 41751ec commit fe61816
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 23 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ ARGUMENTS:
OPTIONS:
--since <since> Equivalent to git-log --since: Eg: '6 months ago' (default: 6 months ago)
--module <module> The Module to compare. If you specify something, target parameter will be ommited
--target <target> The target in your Podfile file to be used
--target <target> The target in your Podfile or Package.swift file to be used (this can be a Product name in SPM)
--output-format <output-format>
csv or json (default: csv)
--version Show the version.
Expand Down Expand Up @@ -90,7 +90,7 @@ ARGUMENTS:
OPTIONS:
--to <git-object> The git objects to compare the current graph to. Eg: - 'main', 'my_branch', 'some_commit_hash'. (default: HEAD, main, master)
--module <module> The Module to compare. If you specify something, target parameter will be ommited
--target <target> The target in your Podfile or Package.swift file to be used
--target <target> The target in your Podfile or Package.swift file to be used (this can be a Product name in SPM)
--version Show the version.
-h, --help Show help information.
```
Expand Down Expand Up @@ -127,7 +127,7 @@ ARGUMENTS:
<directory-path> Path to the directory where Podfile.lock or Package.swift is located (default: .)

OPTIONS:
--target <target> The target in your Podfile or Package.swift file to be used
--target <target> The target in your Podfile or Package.swift file to be used (this can be a Product name in SPM)
--version Show the version.
-h, --help Show help information.

Expand Down Expand Up @@ -157,7 +157,7 @@ ARGUMENTS:
<directory-path> Path to the directory where Podfile.lock or Package.swift is located (default: .)

OPTIONS:
--target <target> The target in your Podfile or Package.swift file to be used
--target <target> The target in your Podfile or Package.swift file to be used (this can be a Product name in SPM)
--show-only-tests Show only Test targets
--version Show the version.
-h, --help Show help information.
Expand Down Expand Up @@ -185,7 +185,7 @@ ARGUMENTS:
OPTIONS:
--of <git-object> A git object representing the version to draw the graph for. Eg: - 'main', 'my_branch', 'some_commit_hash'.
--module <module> The Module to compare. If you specify something, target parameter will be ommited
--target <target> The target in your Podfile or Package.swift file to be used
--target <target> The target in your Podfile or Package.swift file to be used (this can be a Product name in SPM)
--use-multiedge Use multi-edge or unique-edge configuration
--show-externals Show Externals modules dependencies
--version Show the version.
Expand Down
24 changes: 16 additions & 8 deletions Sources/SPMExtractor/Module+Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import Shell

public struct Package: Decodable {
public let targets: [Target]
public let products: [Product]

public struct Product: Decodable {
let name: String
let targets: [String]
}
public struct Target: Decodable {
let name: String
let targetDependencies: [String]?
Expand Down Expand Up @@ -48,7 +53,7 @@ extension TargetError: CustomStringConvertible {
}
}

public func extracPackageModules(from packageRaw: String, target: String) throws -> ([Module], [String]) {
public func extracPackageModules(from packageRaw: String, target: String, isRootTarget: Bool = true) throws -> ([Module], [String]) {

guard
let data = packageRaw.data(using: .utf8)
Expand All @@ -58,15 +63,18 @@ public func extracPackageModules(from packageRaw: String, target: String) throws

let package = try JSONDecoder().decode(Package.self, from: data)

guard let targetModules = package.targets.filter({ $0.name == target }).first else {
if let targetModules = package.targets.filter({ $0.name == target }).first {
let dependencies = extractDependencies(from: package, on: target)
let external = targetModules.productDependencies?.compactMap { Module(name: $0, dependencies: []) } ?? []
let targetDependencies = targetModules.dependencies
return (dependencies + external, targetDependencies)
} else if let product = package.products.filter({ $0.name == target }).first, isRootTarget == true {
let result = try product.targets.compactMap { try extracPackageModules(from: packageRaw, target: $0, isRootTarget: false)}
let modules = Set(result.flatMap(\.0))
return (Array(modules), product.targets)
} else {
throw TargetError.targetNotFound(target: target)
}

let dependencies = extractDependencies(from: package, on: target)
let external = targetModules.productDependencies?.compactMap { Module(name: $0, dependencies: []) } ?? []

let targetDependencies = targetModules.dependencies
return (dependencies + external, targetDependencies)
}

public func extractDependantTargets(from packageRaw: String, target: String) throws -> [Module] {
Expand Down
2 changes: 1 addition & 1 deletion Sources/jungle/Commands/CompareCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ struct CompareCommand: ParsableCommand {
@Option(help: "The Module to compare. If you specify something, target parameter will be ommited")
var module: String?

@Option(help: "The target in your Podfile or Package.swift file to be used")
@Option(help: "The target in your Podfile or Package.swift file to be used (this can be a Product name in SPM)")
var target: String

@Flag(help: "Use multi-edge or unique-edge configuration")
Expand Down
2 changes: 1 addition & 1 deletion Sources/jungle/Commands/DependantCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ struct DependantCommand: ParsableCommand {
abstract: "Outputs a sorted list of targets that depends on the specified one in target"
)

@Option(help: "The target in your Podfile or Package.swift file to be used")
@Option(help: "The target in your Podfile or Package.swift file to be used (this can be a Product name in SPM)")
var target: String

@Flag(help: "Show only Test targets")
Expand Down
2 changes: 1 addition & 1 deletion Sources/jungle/Commands/GraphCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ struct GraphCommand: ParsableCommand {
@Option(help: "The Module to compare. If you specify something, target parameter will be ommited")
var module: String?

@Option(help: "The target in your Podfile or Package.swift file to be used")
@Option(help: "The target in your Podfile or Package.swift file to be used (this can be a Product name in SPM)")
var target: String

@Flag(help: "Use multi-edge or unique-edge configuration")
Expand Down
10 changes: 5 additions & 5 deletions Sources/jungle/Commands/HistoryCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct HistoryCommand: AsyncParsableCommand {
@Option(help: "The Module to compare. If you specify something, target parameter will be ommited")
var module: String?

@Option(help: "The target in your Podfile file to be used")
@Option(help: "The target in your Podfile or Package.swift file to be used (this can be a Product name in SPM)")
var target: String

@Flag(help: "Use multi-edge or unique-edge configuration")
Expand Down Expand Up @@ -84,10 +84,10 @@ struct HistoryCommand: AsyncParsableCommand {
}

public func process(entry: GitLogEntry, target: String, directoryURL: URL) async throws -> HistoryStatsOutput? {
guard let package = try? shell("git show \(entry.revision):Package.swift", at: directoryURL), !package.isEmpty else {
guard let package = try? shell("git show \(entry.revision):./Package.swift", at: directoryURL), !package.isEmpty else {
return nil
}
try shell("git show \(entry.revision):Package.swift > Package.swift.new", at: directoryURL)
try shell("git show \(entry.revision):./Package.swift > Package.swift.new", at: directoryURL)
try shell("mv Package.swift Package.swift.current", at: directoryURL)
try shell("mv Package.swift.new Package.swift", at: directoryURL)
guard
Expand Down Expand Up @@ -132,15 +132,15 @@ struct HistoryCommand: AsyncParsableCommand {
group.addTask {

guard
let podfile = try? shell("git show \(entry.revision):Podfile", at: directoryURL),
let podfile = try? shell("git show \(entry.revision):./Podfile", at: directoryURL),
let entryTargetDependencies = try? moduleFromPodfile(podfile, on: target) ?? .init(name: target, dependencies: [])
else {
return nil
}

return try? await entry.process(
pod: module,
podfile: shell("git show \(entry.revision):Podfile.lock", at: directoryURL),
podfile: shell("git show \(entry.revision):./Podfile.lock", at: directoryURL),
target: entryTargetDependencies,
usingMultiEdge: useMultiedge
)
Expand Down
2 changes: 1 addition & 1 deletion Sources/jungle/Commands/Main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ struct Jungle: AsyncParsableCommand {
static var configuration = CommandConfiguration(
commandName: "jungle",
abstract: "SwiftPM and Cocoapods based projects complexity analyzer.",
version: "2.2.2",
version: "2.3.2",
subcommands: [HistoryCommand.self, CompareCommand.self, GraphCommand.self, ModulesCommand.self, DependantCommand.self],
defaultSubcommand: CompareCommand.self
)
Expand Down
2 changes: 1 addition & 1 deletion Sources/jungle/Commands/ModulesCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ struct ModulesCommand: ParsableCommand {
abstract: "Outputs a sorted list of modules dependencies count of your project"
)

@Option(help: "The target in your Podfile or Package.swift file to be used")
@Option(help: "The target in your Podfile or Package.swift file to be used (this can be a Product name in SPM)")
var target: String

@Argument(help: "Path to the directory where Podfile.lock or Package.swift is located")
Expand Down
90 changes: 90 additions & 0 deletions Tests/SPMExtractorTests/SPMExtractorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -452,4 +452,94 @@ final class SPMExtractorTests: XCTestCase {
let dependant = try extractDependantTargets(from: rawPackage, target: "SamplePackage")
XCTAssertEqual(dependant.map(\.name).sorted(), ["Library", "LibraryTests", "SamplePackageTests"])
}

func testProductModulesFromPackage() throws {
let rawPackage = """
{
"dependencies" : [
{
"identity" : "swift-algorithms",
"requirement" : {
"range" : [
{
"lower_bound" : "1.0.0",
"upper_bound" : "2.0.0"
}
]
},
"type" : "sourceControl",
"url" : "https://github.com/apple/swift-algorithms"
}
],
"manifest_display_name" : "MyPackage",
"name" : "MyPackage",
"path" : "/Users/oswaldo.rubio/Desktop/MyPackage",
"platforms" : [
],
"products" : [
{
"name" : "MyPackage",
"targets" : [
"MyPackage"
],
"type" : {
"library" : [
"automatic"
]
}
},
{
"name" : "FeaturesContainer",
"targets" : [
"MyPackage"
],
"type" : {
"library" : [
"automatic"
]
}
}
],
"targets" : [
{
"c99name" : "MyPackageTests",
"module_type" : "SwiftTarget",
"name" : "MyPackageTests",
"path" : "Tests/MyPackageTests",
"sources" : [
"MyPackageTests.swift"
],
"target_dependencies" : [
"MyPackage"
],
"type" : "test"
},
{
"c99name" : "MyPackage",
"module_type" : "SwiftTarget",
"name" : "MyPackage",
"path" : "Sources/MyPackage",
"product_dependencies" : [
"Algorithms"
],
"product_memberships" : [
"MyPackage",
"FeaturesContainer"
],
"sources" : [
"MyPackage.swift"
],
"type" : "library"
}
],
"tools_version" : "5.8"
}
"""

let (dependencies, targetDependencies) = try extracPackageModules(from: rawPackage, target: "FeaturesContainer")

XCTAssertEqual(dependencies.map(\.name).sorted(), ["Algorithms", "MyPackage"])
XCTAssertEqual(targetDependencies.sorted(), ["MyPackage"])
}
}

0 comments on commit fe61816

Please sign in to comment.