Skip to content

Commit

Permalink
Merge pull request #108 from mbuchetics/spm
Browse files Browse the repository at this point in the history
Support for Swift Package Manager (Package.swift) dependencies
  • Loading branch information
mono0926 authored Sep 24, 2019
2 parents 51ec2ea + f0c4370 commit fb50cca
Show file tree
Hide file tree
Showing 10 changed files with 243 additions and 1 deletion.
4 changes: 3 additions & 1 deletion Sources/LicensePlist/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ private func loadConfig(configPath: URL) -> Config {

let main = command(Option("cartfile-path", default: Consts.cartfileName),
Option("pods-path", default: Consts.podsDirectoryName),
Option("package-path", default: Consts.packageName),
Option("output-path", default: Consts.outputPath),
Option("github-token", default: ""),
Option("config-path", default: Consts.configPath),
Expand All @@ -20,7 +21,7 @@ let main = command(Option("cartfile-path", default: Consts.cartfileName),
Option("markdown-path", default: ""),
Flag("force"),
Flag("add-version-numbers"),
Flag("suppress-opening-directory")) { cartfile, podsPath, output, gitHubToken, configPath, prefix, htmlPath, markdownPath, force, version, suppressOpen in
Flag("suppress-opening-directory")) { cartfile, podsPath, packagePath, output, gitHubToken, configPath, prefix, htmlPath, markdownPath, force, version, suppressOpen in

Logger.configure()
var config = loadConfig(configPath: URL(fileURLWithPath: configPath))
Expand All @@ -30,6 +31,7 @@ let main = command(Option("cartfile-path", default: Consts.cartfileName),
let options = Options(outputPath: URL(fileURLWithPath: output),
cartfilePath: URL(fileURLWithPath: cartfile),
podsPath: URL(fileURLWithPath: podsPath),
packagePath: URL(fileURLWithPath: packagePath),
prefix: prefix,
gitHubToken: gitHubToken.isEmpty ? nil : gitHubToken,
htmlPath: htmlPath.isEmpty ? nil : URL(fileURLWithPath: htmlPath),
Expand Down
1 change: 1 addition & 0 deletions Sources/LicensePlistCore/Consts.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Foundation
public struct Consts {
public static let cartfileName = "Cartfile"
public static let podsDirectoryName = "Pods"
public static let packageName = "Package.swift"
public static let prefix = "com.mono0926.LicensePlist"
public static let outputPath = "\(prefix).Output"
public static let configPath = "license_plist.yml"
Expand Down
2 changes: 2 additions & 0 deletions Sources/LicensePlistCore/Entity/GitHub.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ extension GitHub {
public static func load(_ content: String, renames: [String: String] = [:]) -> [GitHub] {
return load(content, renames: renames, mark: "github ")
}

public static func load(_ content: String, renames: [String: String], mark: String, quotes: String = "\"") -> [GitHub] {
let r = load(content, renames: renames, mark: mark, quotes: quotes, version: true)
if !r.isEmpty {
return r
}
return load(content, renames: renames, mark: mark, quotes: quotes, version: false)
}

public static func load(_ content: String,
renames: [String: String],
mark: String,
Expand Down
4 changes: 4 additions & 0 deletions Sources/LicensePlistCore/Entity/Options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public struct Options {
public let outputPath: URL
public let cartfilePath: URL
public let podsPath: URL
public let packagePath: URL
public let prefix: String
public let gitHubToken: String?
public let htmlPath: URL?
Expand All @@ -13,6 +14,7 @@ public struct Options {
public static let empty = Options(outputPath: URL(fileURLWithPath: ""),
cartfilePath: URL(fileURLWithPath: ""),
podsPath: URL(fileURLWithPath: ""),
packagePath: URL(fileURLWithPath: ""),
prefix: Consts.prefix,
gitHubToken: nil,
htmlPath: nil,
Expand All @@ -22,6 +24,7 @@ public struct Options {
public init(outputPath: URL,
cartfilePath: URL,
podsPath: URL,
packagePath: URL,
prefix: String,
gitHubToken: String?,
htmlPath: URL?,
Expand All @@ -30,6 +33,7 @@ public struct Options {
self.outputPath = outputPath
self.cartfilePath = cartfilePath
self.podsPath = podsPath
self.packagePath = packagePath
self.prefix = prefix
self.gitHubToken = gitHubToken
self.htmlPath = htmlPath
Expand Down
9 changes: 9 additions & 0 deletions Sources/LicensePlistCore/Entity/PlistInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ struct PlistInfo {
Log.info("Carthage License collect start")
githubLibraries = options.config.apply(githubs: GitHub.load(cartfile ?? "", renames: options.config.renames)).sorted()
}

mutating func loadSwiftPackageLibraries(packageFile: String?) {
Log.info("Swift Package Manager License collect start")

let packages = SwiftPackage.loadPackages(packageFile ?? "")
let packagesAsGithubLibraries = packages.compactMap { $0.toGitHub(renames: options.config.renames) }.sorted()

githubLibraries = (githubLibraries ?? []) + packagesAsGithubLibraries
}

mutating func loadManualLibraries() {
Log.info("Manual License start")
Expand Down
58 changes: 58 additions & 0 deletions Sources/LicensePlistCore/Entity/SwiftPackage.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//
// SwiftPackage.swift
// LicensePlistCore
//
// Created by Matthias Buchetics on 20.09.19.
//

import Foundation

public struct SwiftPackage: Decodable, Equatable {
struct State: Decodable, Equatable {
let branch: String?
let revision: String?
let version: String
}

let package: String
let repositoryURL: String
let state: State
}

fileprivate struct ResolvedPackages: Decodable {
struct Pins: Decodable {
let pins: [SwiftPackage]
}

let object: Pins
let version: Int
}

extension SwiftPackage {

static func loadPackages(_ content: String) -> [SwiftPackage] {
guard let data = content.data(using: .utf8) else { return [] }
guard let resolvedPackages = try? JSONDecoder().decode(ResolvedPackages.self, from: data) else { return [] }

return resolvedPackages.object.pins
}

func toGitHub(renames: [String: String]) -> GitHub? {
guard repositoryURL.contains("github.com") else { return nil }

let urlParts = repositoryURL
.replacingOccurrences(of: "https://", with: "")
.replacingOccurrences(of: "http://", with: "")
.components(separatedBy: "/")

guard urlParts.count >= 3 else { return nil }

let name = urlParts.last?.components(separatedBy: ".").first ?? ""
let owner = urlParts[urlParts.count - 2]

return GitHub(name: name,
nameSpecified: renames[name],
owner: owner,
version: state.version)
}
}
11 changes: 11 additions & 0 deletions Sources/LicensePlistCore/LicensePlist.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public final class LicensePlist {
var info = PlistInfo(options: options)
info.loadCocoaPodsLicense(acknowledgements: readPodsAcknowledgements(path: options.podsPath))
info.loadGitHubLibraries(cartfile: readCartfile(path: options.cartfilePath))
info.loadSwiftPackageLibraries(packageFile: readSwiftPackages(path: options.packagePath))
info.loadManualLibraries()
info.compareWithLatestSummary()
info.downloadGitHubLicenses()
Expand All @@ -35,6 +36,16 @@ private func readCartfile(path: URL) -> String? {
return path.lp.read()
}

private func readSwiftPackages(path: URL) -> String? {
if path.lastPathComponent != Consts.packageName {
fatalError("Invalid Package.swift name: \(path.lastPathComponent)")
}
if let content = path.deletingPathExtension().appendingPathExtension("resolved").lp.read() {
return content
}
return path.lp.read()
}

private func readPodsAcknowledgements(path: URL) -> [String] {
if path.lastPathComponent != Consts.podsDirectoryName {
fatalError("Invalid Pods name: \(path.lastPathComponent)")
Expand Down
1 change: 1 addition & 0 deletions Tests/LicensePlistTests/Entity/PlistInfoTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class PlistInfoTests: XCTestCase {
private let options = Options(outputPath: URL(fileURLWithPath: "test_result_dir"),
cartfilePath: URL(fileURLWithPath: "test_result_dir"),
podsPath: URL(fileURLWithPath: "test_result_dir"),
packagePath: URL(fileURLWithPath: "test_result_dir"),
prefix: Consts.prefix,
gitHubToken: nil,
htmlPath: nil,
Expand Down
75 changes: 75 additions & 0 deletions Tests/LicensePlistTests/Entity/SwiftPackageManagerTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//
// SwiftPackageManagerTests.swift
// APIKit
//
// Created by Matthias Buchetics on 20.09.19.
//

import Foundation
import XCTest
@testable import LicensePlistCore

class SwiftPackageManagerTests: XCTestCase {

func testDecoding() {
let jsonString = """
{
"package": "APIKit",
"repositoryURL": "https://github.com/ishkawa/APIKit.git",
"state": {
"branch": null,
"revision": "86d51ecee0bc0ebdb53fb69b11a24169a69097ba",
"version": "4.1.0"
}
}
"""

let data = jsonString.data(using: .utf8)!
let package = try! JSONDecoder().decode(SwiftPackage.self, from: data)

XCTAssertEqual(package.package, "APIKit")
XCTAssertEqual(package.repositoryURL, "https://github.com/ishkawa/APIKit.git")
XCTAssertEqual(package.state.revision, "86d51ecee0bc0ebdb53fb69b11a24169a69097ba")
XCTAssertEqual(package.state.version, "4.1.0")
}

func testConvertToGithub() {
let package = SwiftPackage(package: "Commander", repositoryURL: "https://github.com/kylef/Commander.git", state: SwiftPackage.State(branch: nil, revision: "e5b50ad7b2e91eeb828393e89b03577b16be7db9", version: "0.8.0"))
let result = package.toGitHub(renames: [:])
XCTAssertEqual(result, GitHub(name: "Commander", nameSpecified: nil, owner: "kylef", version: "0.8.0"))
}

func testRename() {
let package = SwiftPackage(package: "Commander", repositoryURL: "https://github.com/kylef/Commander.git", state: SwiftPackage.State(branch: nil, revision: "e5b50ad7b2e91eeb828393e89b03577b16be7db9", version: "0.8.0"))
let result = package.toGitHub(renames: ["Commander": "RenamedCommander"])
XCTAssertEqual(result, GitHub(name: "Commander", nameSpecified: "RenamedCommander", owner: "kylef", version: "0.8.0"))
}

func testInvalidURL() {
let package = SwiftPackage(package: "Google", repositoryURL: "http://www.google.com", state: SwiftPackage.State(branch: nil, revision: "", version: "0.0.0"))
let result = package.toGitHub(renames: [:])
XCTAssertNil(result)
}

func testNonGithub() {
let package = SwiftPackage(package: "Bitbucket", repositoryURL: "https://[email protected]/mbuchetics/adventofcode2018.git", state: SwiftPackage.State(branch: nil, revision: "", version: "0.0.0"))
let result = package.toGitHub(renames: [:])
XCTAssertNil(result)
}

func testParse() {
let path = "https://raw.githubusercontent.com/mono0926/LicensePlist/master/Package.resolved"
//let path = "https://raw.githubusercontent.com/mono0926/LicensePlist/master/Tests/LicensePlistTests/Resources/Package.resolved"
let content = try! String(contentsOf: URL(string: path)!)
let packages = SwiftPackage.loadPackages(content)

XCTAssertFalse(packages.isEmpty)
XCTAssertEqual(packages.count, 8)

let packageFirst = packages.first!
XCTAssertEqual(packageFirst, SwiftPackage(package: "APIKit", repositoryURL: "https://github.com/ishkawa/APIKit.git", state: SwiftPackage.State(branch: nil, revision: "86d51ecee0bc0ebdb53fb69b11a24169a69097ba", version: "4.1.0")))
let packageLast = packages.last!
XCTAssertEqual(packageLast, SwiftPackage(package: "Yaml", repositoryURL: "https://github.com/behrang/YamlSwift.git", state: SwiftPackage.State(branch: nil, revision: "287f5cab7da0d92eb947b5fd8151b203ae04a9a3", version: "3.4.4")))

}
}
79 changes: 79 additions & 0 deletions Tests/LicensePlistTests/Resources/Package.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
"object": {
"pins": [
{
"package": "APIKit",
"repositoryURL": "https://github.com/ishkawa/APIKit.git",
"state": {
"branch": null,
"revision": "86d51ecee0bc0ebdb53fb69b11a24169a69097ba",
"version": "4.1.0"
}
},
{
"package": "Commander",
"repositoryURL": "https://github.com/kylef/Commander.git",
"state": {
"branch": null,
"revision": "e5b50ad7b2e91eeb828393e89b03577b16be7db9",
"version": "0.8.0"
}
},
{
"package": "HeliumLogger",
"repositoryURL": "https://github.com/IBM-Swift/HeliumLogger.git",
"state": {
"branch": null,
"revision": "779865e83149a59894b14950aa83f70b7e81bc27",
"version": "1.8.1"
}
},
{
"package": "LoggerAPI",
"repositoryURL": "https://github.com/IBM-Swift/LoggerAPI.git",
"state": {
"branch": null,
"revision": "e29073bb7cecf3673e56bcb16180e8fd0cb091f6",
"version": "1.8.1"
}
},
{
"package": "Result",
"repositoryURL": "https://github.com/antitypical/Result.git",
"state": {
"branch": null,
"revision": "2ca499ba456795616fbc471561ff1d963e6ae160",
"version": "4.1.0"
}
},
{
"package": "Spectre",
"repositoryURL": "https://github.com/kylef/Spectre.git",
"state": {
"branch": null,
"revision": "f14ff47f45642aa5703900980b014c2e9394b6e5",
"version": "0.9.0"
}
},
{
"package": "HTMLEntities",
"repositoryURL": "https://github.com/IBM-Swift/swift-html-entities.git",
"state": {
"branch": null,
"revision": "3b778b3ab061684db024eaf38c576887b42918aa",
"version": "3.0.13"
}
},
{
"package": "Yaml",
"repositoryURL": "https://github.com/behrang/YamlSwift.git",
"state": {
"branch": null,
"revision": "287f5cab7da0d92eb947b5fd8151b203ae04a9a3",
"version": "3.4.4"
}
}
]
},
"version": 1
}

0 comments on commit fb50cca

Please sign in to comment.