Skip to content

Commit

Permalink
Merge pull request #75 from leetal/manual_license_capability
Browse files Browse the repository at this point in the history
Added capablility to supply manual license information
  • Loading branch information
mono0926 authored Oct 5, 2017
2 parents efe6660 + 9c05449 commit ccf5d5b
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 18 deletions.
16 changes: 13 additions & 3 deletions Sources/LicensePlistCore/Entity/Config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import Yaml

public struct Config {
let githubs: [GitHub]
let manuals: [Manual]
let excludes: [String]
let renames: [String: String]
public var force = false
public var addVersionNumbers = false
public var suppressOpeningDirectory = false

public static let empty = Config(githubs: [], excludes: [], renames: [:])
public static let empty = Config(githubs: [], manuals: [], excludes: [], renames: [:])

public init(yaml: String) {
let value = try! Yaml.load(yaml)
Expand All @@ -21,6 +22,8 @@ public struct Config {
sum[from] = to
return sum
} ?? [:]
let manuals = value["manual"].array ?? []
let manualList = Manual.load(manuals, renames: renames)
let githubs = value["github"].array?.map { $0.string }.flatMap { $0 } ?? []
let gitHubList = githubs.map { GitHub.load($0, renames: renames, mark: "", quotes: "") }.flatMap { $0 }
gitHubList.forEach {
Expand All @@ -39,11 +42,12 @@ public struct Config {
owner: owner,
version: dictionary["version"]?.string)
}.flatMap { $0 } ?? []
self = Config(githubs: githubsVersion + gitHubList, excludes: excludes, renames: renames)
self = Config(githubs: githubsVersion + gitHubList, manuals: manualList, excludes: excludes, renames: renames)
}

init(githubs: [GitHub], excludes: [String], renames: [String: String]) {
init(githubs: [GitHub], manuals: [Manual], excludes: [String], renames: [String: String]) {
self.githubs = githubs
self.manuals = manuals
self.excludes = excludes
self.renames = renames
}
Expand Down Expand Up @@ -93,15 +97,21 @@ public struct Config {
return result
}
}

func apply(githubs: [GitHub]) -> [GitHub] {
self.githubs.forEach { Log.warning("\($0.name) was loaded from config YAML.") }
return filterExcluded((self.githubs + githubs))
}

func applyManual(manuals: [Manual]) -> [Manual] {
return filterExcluded((self.manuals + manuals))
}
}

extension Config: Equatable {
public static func==(lhs: Config, rhs: Config) -> Bool {
return lhs.githubs == rhs.githubs &&
lhs.manuals == rhs.manuals &&
lhs.excludes == rhs.excludes &&
lhs.renames == rhs.renames
}
Expand Down
68 changes: 68 additions & 0 deletions Sources/LicensePlistCore/Entity/Manual.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import Foundation
import APIKit
import LoggerAPI
import Yaml

public class Manual: Library {
public let name: String
public var body: String? // Used as a container between YAML and ManualLicence
public var source: String?
public var nameSpecified: String?
public var version: String?

init(name n: String, source: String?, nameSpecified: String?, version: String?) {
self.name = n
self.source = source
self.nameSpecified = nameSpecified
self.version = version
}
}

extension Manual {
public static func==(lhs: Manual, rhs: Manual) -> Bool {
return lhs.name == rhs.name &&
lhs.nameSpecified == rhs.nameSpecified &&
lhs.version == rhs.version
}
}

extension Manual: CustomStringConvertible {
public var description: String {
return "name: \(name), source: \(source ?? ""), nameSpecified: \(nameSpecified ?? ""), version: \(version ?? "")"
}
}

extension Manual {
public static func load(_ raw: [Yaml],
renames: [String: String]) -> [Manual] {
return raw.map { (manualEntry) -> Manual in
var name = ""
var body = ""
var source = ""
var rename = ""
var version = ""
for valuePair in manualEntry.dictionary ?? [:] {
switch valuePair.key.string ?? "" {
case "source":
source = valuePair.value.string ?? ""
break
case "name":
name = valuePair.value.string ?? ""
break
case "version":
version = valuePair.value.string ?? ""
break
case "body":
body = valuePair.value.string ?? ""
break
default:
Log.warning("Tried to parse an unknown YAML key")
}
}
rename = renames[name] ?? ""
let manual = Manual(name: name, source: source, nameSpecified: rename, version: version)
manual.body = body // This is so that we do not have to store a body at all ( for testing purposes mostly )
return manual
}
}
}
25 changes: 25 additions & 0 deletions Sources/LicensePlistCore/Entity/ManualLicense.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Foundation
import LoggerAPI

public struct ManualLicense: License, Equatable {
public let library: Manual
public let body: String

public static func==(lhs: ManualLicense, rhs: ManualLicense) -> Bool {
return lhs.library == rhs.library
}
}

extension ManualLicense: CustomStringConvertible {
public var description: String {
return "name: \(library.name), nameSpecified: \(library.nameSpecified ?? ""), version: \(library.version ?? "")\nbody: \(String(body.characters.prefix(20)))"
}
}

extension ManualLicense {
public static func load(_ manuals: [Manual]) -> [ManualLicense] {
return manuals.map {
return ManualLicense(library: $0, body: $0.body ?? "")
}
}
}
19 changes: 15 additions & 4 deletions Sources/LicensePlistCore/Entity/PlistInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import LoggerAPI
struct PlistInfo {
let options: Options
var cocoaPodsLicenses: [CocoaPodsLicense]?
var manualLicenses: [ManualLicense]?
var githubLibraries: [GitHub]?
var githubLicenses: [GitHubLicense]?
var summary: String?
Expand Down Expand Up @@ -32,13 +33,21 @@ struct PlistInfo {
githubLibraries = options.config.apply(githubs: GitHub.load(cartfile ?? "", renames: options.config.renames))
}

mutating func loadManualLibraries() {
Log.info("Manual License start")
manualLicenses = ManualLicense.load(options.config.manuals)
}

mutating func compareWithLatestSummary() {
guard let cocoaPodsLicenses = cocoaPodsLicenses, let githubLibraries = githubLibraries else { preconditionFailure() }
guard let cocoaPodsLicenses = cocoaPodsLicenses,
let githubLibraries = githubLibraries,
let manualLicenses = manualLicenses else { preconditionFailure() }

let config = options.config

let contents = (cocoaPodsLicenses.map { String(describing: $0) } +
githubLibraries.map { String(describing: $0) } +
manualLicenses.map { String(describing: $0) } +
["add-version-numbers: \(options.config.addVersionNumbers)", "LicensePlist Version: \(Consts.version)"])
.joined(separator: "\n\n")
let savePath = options.outputPath.appendingPathComponent("\(Consts.prefix).latest_result.txt")
Expand All @@ -60,9 +69,11 @@ struct PlistInfo {
}

mutating func collectLicenseInfos() {
guard let cocoaPodsLicenses = cocoaPodsLicenses, let githubLicenses = githubLicenses else { preconditionFailure() }
guard let cocoaPodsLicenses = cocoaPodsLicenses,
let githubLicenses = githubLicenses,
let manualLicenses = manualLicenses else { preconditionFailure() }

licenses = ((cocoaPodsLicenses as [LicenseInfo]) + (githubLicenses as [LicenseInfo]))
licenses = ((cocoaPodsLicenses as [LicenseInfo]) + (githubLicenses as [LicenseInfo]) + (manualLicenses as [LicenseInfo]))
.reduce([String: LicenseInfo]()) { sum, e in
var sum = sum
sum[e.name] = e
Expand Down Expand Up @@ -92,7 +103,7 @@ struct PlistInfo {
Log.info("# Missing license:")
let missing = Set(githubLibraries.map { $0.name }).subtracting(Set(licenses.map { $0.name }))
if missing.isEmpty {
Log.info("None🎉")
Log.info("None 🎉")
} else {
Array(missing).sorted { $0 < $1 }.forEach { Log.warning($0) }
}
Expand Down
1 change: 1 addition & 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.loadManualLibraries()
info.compareWithLatestSummary()
info.downloadGitHubLicenses()
info.collectLicenseInfos()
Expand Down
2 changes: 1 addition & 1 deletion Tests/LicensePlistTests/Entity/CocoaPodsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class CocoaPodsTests: XCTestCase {
let content = try! String(contentsOf: URL(string: path)!)
let results = CocoaPodsLicense.load(content,
versionInfo: VersionInfo(dictionary: ["Firebase": "1.2.3"]),
config: Config(githubs: [], excludes: [], renames: ["Firebase": "Firebase2"]))
config: Config(githubs: [], manuals: [], excludes: [], renames: ["Firebase": "Firebase2"]))
XCTAssertFalse(results.isEmpty)
XCTAssertEqual(results.count, 11)
let licenseFirst = results.first!
Expand Down
15 changes: 8 additions & 7 deletions Tests/LicensePlistTests/Entity/ConfigTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@ import XCTest
class ConfigTests: XCTestCase {

func testInit_empty_yaml() {
XCTAssertEqual(Config(yaml: ""), Config(githubs: [], excludes: [], renames: [:]))
XCTAssertEqual(Config(yaml: ""), Config(githubs: [], manuals: [], excludes: [], renames: [:]))
}
func testInit_sample() {
let path = "https://raw.githubusercontent.com/mono0926/LicensePlist/master/Tests/LicensePlistTests/Resources/license_plist.yml"
XCTAssertEqual(Config(yaml: URL(string: path)!.lp.download().resultSync().value!),
Config(githubs: [GitHub(name: "LicensePlist", nameSpecified: "License Plist", owner: "mono0926", version: "1.2.0"),
GitHub(name: "NativePopup", nameSpecified: nil, owner: "mono0926", version: nil)],
manuals: [Manual(name: "WebRTC", source: "https://webrtc.googlesource.com/src", nameSpecified: "Web RTC", version: "M61")],
excludes: ["RxSwift", "ios-license-generator", "/^Core.*$/"],
renames: ["LicensePlist": "License Plist"]))
renames: ["LicensePlist": "License Plist", "WebRTC": "Web RTC"]))
}

func testExcluded() {
let target = Config(githubs: [], excludes: ["lib1"], renames: [:])
let target = Config(githubs: [], manuals: [], excludes: ["lib1"], renames: [:])
XCTAssertTrue(target.excluded(name: "lib1"))
XCTAssertFalse(target.excluded(name: "lib2"))
}
Expand All @@ -28,22 +29,22 @@ class ConfigTests: XCTestCase {
}

func testExcluded_regex() {
let target = Config(githubs: [], excludes: ["/^lib.*$/"], renames: [:])
let target = Config(githubs: [], manuals: [], excludes: ["/^lib.*$/"], renames: [:])
XCTAssertTrue(target.excluded(name: "lib1"))
XCTAssertTrue(target.excluded(name: "lib2"))
XCTAssertFalse(target.excluded(name: "hello"))
}

func testApply_filterExcluded() {
let config = Config(githubs: [], excludes: ["lib2"], renames: [:])
let config = Config(githubs: [], manuals: [], excludes: ["lib2"], renames: [:])
let shouldBeIncluded = GitHub(name: "lib1", nameSpecified: nil, owner: "o1", version: nil)
let result = config.filterExcluded([shouldBeIncluded, GitHub(name: "lib2", nameSpecified: nil, owner: "o2", version: nil)])
XCTAssertEqual(result, [shouldBeIncluded])
}

func testApply_githubs() {
let github1 = GitHub(name: "github1", nameSpecified: nil, owner: "g1", version: nil)
let config = Config(githubs: [github1], excludes: ["lib2"], renames: [:])
let github1 = GitHub(name: "github1", nameSpecified: nil, owner: "g1", version: nil)
let config = Config(githubs: [github1], manuals: [], excludes: ["lib2"], renames: [:])
let shouldBeIncluded = GitHub(name: "lib1", nameSpecified: nil, owner: "o1", version: nil)
let result = config.apply(githubs: [shouldBeIncluded, GitHub(name: "lib2", nameSpecified: nil, owner: "o2", version: nil)])
XCTAssertEqual(result, [github1, shouldBeIncluded])
Expand Down
12 changes: 10 additions & 2 deletions Tests/LicensePlistTests/Entity/PlistInfoTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class PlistInfoTests: XCTestCase {
nameSpecified: nil,
owner: "owner",
version: nil)],
manuals: [],
excludes: ["exclude"],
renames: ["Himotoki": "Himotoki2"]))

Expand Down Expand Up @@ -69,6 +70,7 @@ class PlistInfoTests: XCTestCase {
func testCompareWithLatestSummary() {
var target = PlistInfo(options: options)
target.cocoaPodsLicenses = []
target.manualLicenses = []
target.githubLibraries = []

XCTAssertNil(target.summary)
Expand Down Expand Up @@ -106,13 +108,17 @@ class PlistInfoTests: XCTestCase {
kind: LicenseKindResponse(name: "name",
spdxId: nil)))
target.cocoaPodsLicenses = []
let manual = Manual(name: "FooBar", source: "https://foo.bar", nameSpecified: nil, version: nil)
let manualLicense = ManualLicense(library: manual,
body: "body")
target.manualLicenses = [manualLicense]
target.githubLicenses = [githubLicense]

XCTAssertNil(target.licenses)
target.collectLicenseInfos()
let licenses = target.licenses!
XCTAssertEqual(licenses.count, 1)
let license = licenses.first!
XCTAssertEqual(licenses.count, 2)
let license = licenses.last!
XCTAssertEqual(license.name, "LicensePlist")
}

Expand Down Expand Up @@ -160,6 +166,8 @@ class PlistInfoTests: XCTestCase {
target.githubLicenses = [githubLicense]
let podsLicense = CocoaPodsLicense(library: CocoaPods(name: "", nameSpecified: nil, version: nil), body: "body")
target.cocoaPodsLicenses = [podsLicense]
let manualLicense = ManualLicense(library: Manual(name: "", source: nil, nameSpecified: nil, version: nil), body: "body")
target.manualLicenses = [manualLicense]
target.licenses = [githubLicense, podsLicense]
target.summary = ""
target.summaryPath = URL(fileURLWithPath: "")
Expand Down
35 changes: 34 additions & 1 deletion Tests/LicensePlistTests/Resources/license_plist.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,38 @@ github:
# Depricated(Will be removed at Version 2. Use above.)
- mono0926/NativePopup

# Specify libraries manually
manual:
- source: https://webrtc.googlesource.com/src
name: WebRTC
version: M61
body: '
Copyright (c) 2011, The WebRTC project authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Google nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'

# Specify libraries to be excluded.
exclude:
- RxSwift
Expand All @@ -16,4 +48,5 @@ exclude:

# Specify libraries' names to be renamed.
rename:
LicensePlist: License Plist # Rename LicensePlist to "License Plist"
LicensePlist: License Plist # Rename LicensePlist to "License Plist"
WebRTC: Web RTC # Rename WebRTC to "Web RTC" (which is faulty, but used for test)

0 comments on commit ccf5d5b

Please sign in to comment.