diff --git a/README.md b/README.md index 39eddc9a..201862fa 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,10 @@ You can see options by `license-plist --help`. - Default: `Cartfile` +#### `--mintfile-path` + +- Default: `Mintfile` + #### `--pods-path` - Default: `Pods` diff --git a/Sources/LicensePlist/main.swift b/Sources/LicensePlist/main.swift index 790b092f..46ec5200 100644 --- a/Sources/LicensePlist/main.swift +++ b/Sources/LicensePlist/main.swift @@ -11,6 +11,7 @@ private func loadConfig(configPath: URL) -> Config { } let main = command(Option("cartfile-path", default: Consts.cartfileName), + Option("mintfile-path", default: Consts.mintfileName), Option("pods-path", default: Consts.podsDirectoryName), Option("package-path", default: Consts.packageName), Option("xcodeproj-path", default: "*.xcodeproj"), @@ -24,7 +25,7 @@ let main = command(Option("cartfile-path", default: Consts.cartfileName), Flag("add-version-numbers"), Flag("suppress-opening-directory"), Flag("single-page"), - Flag("fail-if-missing-license")) { cartfile, podsPath, packagePath, xcodeprojPath, output, gitHubToken, configPath, prefix, htmlPath, markdownPath, force, version, suppressOpen, singlePage, failIfMissingLicense in + Flag("fail-if-missing-license")) { cartfile, mintfile, podsPath, packagePath, xcodeprojPath, output, gitHubToken, configPath, prefix, htmlPath, markdownPath, force, version, suppressOpen, singlePage, failIfMissingLicense in Logger.configure() var config = loadConfig(configPath: URL(fileURLWithPath: configPath)) @@ -35,6 +36,7 @@ let main = command(Option("cartfile-path", default: Consts.cartfileName), config.failIfMissingLicense = failIfMissingLicense let options = Options(outputPath: URL(fileURLWithPath: output), cartfilePath: URL(fileURLWithPath: cartfile), + mintfilePath: URL(fileURLWithPath: mintfile), podsPath: URL(fileURLWithPath: podsPath), packagePath: URL(fileURLWithPath: packagePath), xcodeprojPath: URL(fileURLWithPath: xcodeprojPath), diff --git a/Sources/LicensePlistCore/Consts.swift b/Sources/LicensePlistCore/Consts.swift index da5b378f..16fbd245 100644 --- a/Sources/LicensePlistCore/Consts.swift +++ b/Sources/LicensePlistCore/Consts.swift @@ -2,6 +2,7 @@ import Foundation public struct Consts { public static let cartfileName = "Cartfile" + public static let mintfileName = "Mintfile" public static let podsDirectoryName = "Pods" public static let packageName = "Package.swift" public static let xcodeprojExtension = "xcodeproj" diff --git a/Sources/LicensePlistCore/Entity/Config.swift b/Sources/LicensePlistCore/Entity/Config.swift index 2940659f..7c0ed9e5 100644 --- a/Sources/LicensePlistCore/Entity/Config.swift +++ b/Sources/LicensePlistCore/Entity/Config.swift @@ -27,7 +27,7 @@ public struct Config { let manuals = value["manual"].array ?? [] let manualList = Manual.load(manuals, renames: renames, configBasePath: configBasePath) let githubs = value["github"].array?.map { $0.string }.compactMap { $0 } ?? [] - let gitHubList = githubs.map { GitHub.load($0, renames: renames, mark: "", quotes: "") }.flatMap { $0 } + let gitHubList = githubs.map { GitHub.load(.licensePlist(content: $0), renames: renames) }.flatMap { $0 } gitHubList.forEach { Log.warning("\($0.name) is specified by the depricated format. It will be removed at Version 2." + "See: https://github.com/mono0926/LicensePlist/blob/master/Tests/LicensePlistTests/Resources/license_plist.yml .") diff --git a/Sources/LicensePlistCore/Entity/GitHub.swift b/Sources/LicensePlistCore/Entity/GitHub.swift index 04245498..592c7b01 100644 --- a/Sources/LicensePlistCore/Entity/GitHub.swift +++ b/Sources/LicensePlistCore/Entity/GitHub.swift @@ -25,25 +25,19 @@ extension GitHub: CustomStringConvertible { } 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) + public static func load(_ file: GitHubLibraryConfigFile, renames: [String: String] = [:]) -> [GitHub] { + let r = load(file, renames: renames, version: true) if !r.isEmpty { return r } - return load(content, renames: renames, mark: mark, quotes: quotes, version: false) + return load(file, renames: renames, version: false) } - public static func load(_ content: String, - renames: [String: String], - mark: String, - quotes: String = "\"", - version: Bool = false) -> [GitHub] { - let pattern = "[\\w\\.\\-]+" - let regexString = "\(mark)\(quotes)(\(pattern))/(\(pattern))\(quotes)" + (version ? " \(quotes)([\\w\\.\\-]+)\(quotes)" : "") + private static func load(_ file: GitHubLibraryConfigFile, + renames: [String: String], + version: Bool = false) -> [GitHub] { + guard let content = file.content else { return [] } + let regexString = file.type.regexString(version: version) let regex = try! NSRegularExpression(pattern: regexString, options: []) let nsContent = content as NSString let matches = regex.matches(in: content, options: [], range: NSRange(location: 0, length: nsContent.length)) diff --git a/Sources/LicensePlistCore/Entity/GitHubLibraryConfigFile.swift b/Sources/LicensePlistCore/Entity/GitHubLibraryConfigFile.swift new file mode 100644 index 00000000..1e5888c1 --- /dev/null +++ b/Sources/LicensePlistCore/Entity/GitHubLibraryConfigFile.swift @@ -0,0 +1,31 @@ +public struct GitHubLibraryConfigFile: Equatable { + let type: GitHubLibraryConfigFileType + let content: String? +} + +extension GitHubLibraryConfigFile { + static func carthage(content: String?) -> GitHubLibraryConfigFile { .init(type: .carthage, content: content) } + static func mint(content: String?) -> GitHubLibraryConfigFile { .init(type: .mint, content: content) } + static func licensePlist(content: String?) -> GitHubLibraryConfigFile { .init(type: .licensePlist, content: content) } +} + +public enum GitHubLibraryConfigFileType: Int, CaseIterable { + case carthage + case mint + case licensePlist +} + +extension GitHubLibraryConfigFileType { + func regexString(version: Bool) -> String { + let pattern = "[\\w\\.\\-]+" + switch self { + case .carthage: + let quotes = "\"" + return "github \(quotes)(\(pattern))/(\(pattern))\(quotes)" + (version ? " \(quotes)(\(pattern))\(quotes)" : "") + case .mint: + return "(\(pattern))/(\(pattern))" + (version ? "@(\(pattern))" : "") + case .licensePlist: + return "(\(pattern))/(\(pattern))" + (version ? " (\(pattern))" : "") + } + } +} diff --git a/Sources/LicensePlistCore/Entity/Options.swift b/Sources/LicensePlistCore/Entity/Options.swift index 85b2858b..5852f803 100644 --- a/Sources/LicensePlistCore/Entity/Options.swift +++ b/Sources/LicensePlistCore/Entity/Options.swift @@ -3,6 +3,7 @@ import Foundation public struct Options { public let outputPath: URL public let cartfilePath: URL + public let mintfilePath: URL public let podsPath: URL public let packagePath: URL public let xcodeprojPath: URL @@ -14,6 +15,7 @@ public struct Options { public static let empty = Options(outputPath: URL(fileURLWithPath: ""), cartfilePath: URL(fileURLWithPath: ""), + mintfilePath: URL(fileURLWithPath: ""), podsPath: URL(fileURLWithPath: ""), packagePath: URL(fileURLWithPath: ""), xcodeprojPath: URL(fileURLWithPath: ""), @@ -25,6 +27,7 @@ public struct Options { public init(outputPath: URL, cartfilePath: URL, + mintfilePath: URL, podsPath: URL, packagePath: URL, xcodeprojPath: URL, @@ -35,6 +38,7 @@ public struct Options { config: Config) { self.outputPath = outputPath self.cartfilePath = cartfilePath + self.mintfilePath = mintfilePath self.podsPath = podsPath self.packagePath = packagePath self.xcodeprojPath = xcodeprojPath diff --git a/Sources/LicensePlistCore/Entity/PlistInfo.swift b/Sources/LicensePlistCore/Entity/PlistInfo.swift index b4006529..37eb5781 100644 --- a/Sources/LicensePlistCore/Entity/PlistInfo.swift +++ b/Sources/LicensePlistCore/Entity/PlistInfo.swift @@ -28,9 +28,18 @@ struct PlistInfo { cocoaPodsLicenses = config.filterExcluded(licenses).sorted() } - mutating func loadGitHubLibraries(cartfile: String?) { - Log.info("Carthage License collect start") - githubLibraries = options.config.apply(githubs: GitHub.load(cartfile ?? "", renames: options.config.renames)).sorted() + mutating func loadGitHubLibraries(file: GitHubLibraryConfigFile) { + switch file.type { + case .carthage: + Log.info("Carthage License collect start") + case .mint: + Log.info("Mint License collect start") + case .licensePlist: + // should not reach here + preconditionFailure() + } + let githubs = GitHub.load(file, renames: options.config.renames) + githubLibraries = ((githubLibraries ?? []) + options.config.apply(githubs: githubs)).sorted() } mutating func loadSwiftPackageLibraries(packageFile: String?) { diff --git a/Sources/LicensePlistCore/LicensePlist.swift b/Sources/LicensePlistCore/LicensePlist.swift index ccd009b7..e6b777d8 100644 --- a/Sources/LicensePlistCore/LicensePlist.swift +++ b/Sources/LicensePlistCore/LicensePlist.swift @@ -10,7 +10,8 @@ public final class LicensePlist { GitHubAuthorization.shared.token = options.gitHubToken var info = PlistInfo(options: options) info.loadCocoaPodsLicense(acknowledgements: readPodsAcknowledgements(path: options.podsPath)) - info.loadGitHubLibraries(cartfile: readCartfile(path: options.cartfilePath)) + info.loadGitHubLibraries(file: readCartfile(path: options.cartfilePath)) + info.loadGitHubLibraries(file: readMintfile(path: options.mintfilePath)) info.loadSwiftPackageLibraries(packageFile: readSwiftPackages(path: options.packagePath) ?? readXcodeProject(path: options.xcodeprojPath)) info.loadManualLibraries() info.compareWithLatestSummary() @@ -26,14 +27,21 @@ public final class LicensePlist { } } -private func readCartfile(path: URL) -> String? { +private func readCartfile(path: URL) -> GitHubLibraryConfigFile { if path.lastPathComponent != Consts.cartfileName { fatalError("Invalid Cartfile name: \(path.lastPathComponent)") } if let content = path.appendingPathExtension("resolved").lp.read() { - return content + return GitHubLibraryConfigFile(type: .carthage, content: content) } - return path.lp.read() + return .carthage(content: path.lp.read()) +} + +private func readMintfile(path: URL) -> GitHubLibraryConfigFile { + if path.lastPathComponent != Consts.mintfileName { + fatalError("Invalid MintFile name: \(path.lastPathComponent)") + } + return .mint(content: path.lp.read()) } private func readSwiftPackages(path: URL) -> String? { diff --git a/Tests/LicensePlistTests/Entity/GitHubLibraryConfigFileTests.swift b/Tests/LicensePlistTests/Entity/GitHubLibraryConfigFileTests.swift new file mode 100644 index 00000000..0db7e8b5 --- /dev/null +++ b/Tests/LicensePlistTests/Entity/GitHubLibraryConfigFileTests.swift @@ -0,0 +1,11 @@ +import XCTest +@testable import LicensePlistCore + +class GitHubLibraryConfigFileTests: XCTestCase { + + func testInit() { + XCTAssertEqual(GitHubLibraryConfigFile.carthage(content: "content"), GitHubLibraryConfigFile(type: .carthage, content: "content")) + XCTAssertEqual(GitHubLibraryConfigFile.mint(content: "content"), GitHubLibraryConfigFile(type: .mint, content: "content")) + XCTAssertEqual(GitHubLibraryConfigFile.licensePlist(content: "content"), GitHubLibraryConfigFile(type: .licensePlist, content: "content")) + } +} diff --git a/Tests/LicensePlistTests/Entity/GitHubLibraryConfigFileTypeTests.swift b/Tests/LicensePlistTests/Entity/GitHubLibraryConfigFileTypeTests.swift new file mode 100644 index 00000000..756e8c7f --- /dev/null +++ b/Tests/LicensePlistTests/Entity/GitHubLibraryConfigFileTypeTests.swift @@ -0,0 +1,28 @@ +import XCTest +@testable import LicensePlistCore + +class GitHubLibraryConfigFileTypeTests: XCTestCase { + + func testRegexString() { + // carthage + do { + let type = GitHubLibraryConfigFileType.carthage + XCTAssertEqual(type.regexString(version: false), "github \"([\\w\\.\\-]+)/([\\w\\.\\-]+)\"") + XCTAssertEqual(type.regexString(version: true), "github \"([\\w\\.\\-]+)/([\\w\\.\\-]+)\" \"([\\w\\.\\-]+)\"") + } + + // mint + do { + let type = GitHubLibraryConfigFileType.mint + XCTAssertEqual(type.regexString(version: false), "([\\w\\.\\-]+)/([\\w\\.\\-]+)") + XCTAssertEqual(type.regexString(version: true), "([\\w\\.\\-]+)/([\\w\\.\\-]+)@([\\w\\.\\-]+)") + } + + // licensePlist + do { + let type = GitHubLibraryConfigFileType.licensePlist + XCTAssertEqual(type.regexString(version: false), "([\\w\\.\\-]+)/([\\w\\.\\-]+)") + XCTAssertEqual(type.regexString(version: true), "([\\w\\.\\-]+)/([\\w\\.\\-]+) ([\\w\\.\\-]+)") + } + } +} diff --git a/Tests/LicensePlistTests/Entity/GitHubTests.swift b/Tests/LicensePlistTests/Entity/GitHubTests.swift index 235d34ca..84fc144a 100644 --- a/Tests/LicensePlistTests/Entity/GitHubTests.swift +++ b/Tests/LicensePlistTests/Entity/GitHubTests.swift @@ -5,40 +5,40 @@ import XCTest class GitHubTests: XCTestCase { func testParse_empty() { - let results = GitHub.load("( ´・‿・`)") + let results = GitHub.load(.carthage(content: "( ´・‿・`)")) XCTAssertTrue(results.isEmpty) } func testParse_one() { - let results = GitHub.load("github \"mono0926/NativePopup\"") + let results = GitHub.load(.carthage(content: "github \"mono0926/NativePopup\"")) XCTAssertTrue(results.count == 1) let result = results.first XCTAssertEqual(result, GitHub(name: "NativePopup", nameSpecified: nil, owner: "mono0926", version: nil)) } func testParse_one_rename() { - let results = GitHub.load("github \"mono0926/NativePopup\"", renames: ["NativePopup": "NativePopup2"]) + let results = GitHub.load(.carthage(content: "github \"mono0926/NativePopup\""), renames: ["NativePopup": "NativePopup2"]) XCTAssertTrue(results.count == 1) let result = results.first XCTAssertEqual(result, GitHub(name: "NativePopup", nameSpecified: "NativePopup2", owner: "mono0926", version: nil)) } func testParse_one_dot() { - let results = GitHub.load("github \"tephencelis/SQLite.swift\"") + let results = GitHub.load(.carthage(content: "github \"tephencelis/SQLite.swift\"")) XCTAssertTrue(results.count == 1) let result = results.first XCTAssertEqual(result, GitHub(name: "SQLite.swift", nameSpecified: nil, owner: "tephencelis", version: nil)) } func testParse_one_hyphen() { - let results = GitHub.load("github \"mono0926/ios-license-generator\"") + let results = GitHub.load(.carthage(content: "github \"mono0926/ios-license-generator\"")) XCTAssertTrue(results.count == 1) let result = results.first XCTAssertEqual(result, GitHub(name: "ios-license-generator", nameSpecified: nil, owner: "mono0926", version: nil)) } func testParse_multiple() { - let results = GitHub.load("github \"mono0926/NativePopup\"\ngithub \"ReactiveX/RxSwift\"") + let results = GitHub.load(.carthage(content: "github \"mono0926/NativePopup\"\ngithub \"ReactiveX/RxSwift\"")) XCTAssertTrue(results.count == 2) let result1 = results[0] XCTAssertEqual(result1, GitHub(name: "NativePopup", nameSpecified: nil, owner: "mono0926", version: nil)) @@ -47,21 +47,21 @@ class GitHubTests: XCTestCase { } func testParse_one_versoin() { - let results = GitHub.load("github \"mono0926/NativePopup\" \"1.8.4\"") + let results = GitHub.load(.carthage(content: "github \"mono0926/NativePopup\" \"1.8.4\"")) XCTAssertTrue(results.count == 1) let result = results.first XCTAssertEqual(result, GitHub(name: "NativePopup", nameSpecified: nil, owner: "mono0926", version: "1.8.4")) } func testParse_one_versoin_v() { - let results = GitHub.load("github \"mono0926/NativePopup\" \"v1.8.4\"") + let results = GitHub.load(.carthage(content: "github \"mono0926/NativePopup\" \"v1.8.4\"")) XCTAssertTrue(results.count == 1) let result = results.first XCTAssertEqual(result, GitHub(name: "NativePopup", nameSpecified: nil, owner: "mono0926", version: "v1.8.4")) } func testParse_one_hash() { - let results = GitHub.load("github \"mono0926/NativePopup\" \"e64dcc63d4720f04eec8700b31ecaee188b6483a\"") + let results = GitHub.load(.carthage(content: "github \"mono0926/NativePopup\" \"e64dcc63d4720f04eec8700b31ecaee188b6483a\"")) XCTAssertTrue(results.count == 1) let result = results.first XCTAssertEqual(result, GitHub(name: "NativePopup", nameSpecified: nil, owner: "mono0926", version: "e64dcc6")) diff --git a/Tests/LicensePlistTests/Entity/PlistInfoTests.swift b/Tests/LicensePlistTests/Entity/PlistInfoTests.swift index cebd24cc..3fd8c43d 100644 --- a/Tests/LicensePlistTests/Entity/PlistInfoTests.swift +++ b/Tests/LicensePlistTests/Entity/PlistInfoTests.swift @@ -11,6 +11,7 @@ class PlistInfoTests: XCTestCase { private let options = Options(outputPath: URL(fileURLWithPath: "test_result_dir"), cartfilePath: URL(fileURLWithPath: "test_result_dir"), + mintfilePath: URL(fileURLWithPath: "test_result_dir"), podsPath: URL(fileURLWithPath: "test_result_dir"), packagePath: URL(fileURLWithPath: "test_result_dir"), xcodeprojPath: URL(fileURLWithPath: "test_result_dir"), @@ -53,7 +54,7 @@ class PlistInfoTests: XCTestCase { func testLoadGitHubLibraries() { var target = PlistInfo(options: options) XCTAssertNil(target.githubLibraries) - target.loadGitHubLibraries(cartfile: "github \"ikesyo/Himotoki\" \"3.0.1\"") + target.loadGitHubLibraries(file: .carthage(content: "github \"ikesyo/Himotoki\" \"3.0.1\"")) let libraries = target.githubLibraries! XCTAssertEqual(libraries.count, 2) let lib1 = libraries[0] @@ -65,7 +66,7 @@ class PlistInfoTests: XCTestCase { func testLoadGitHubLibraries_empty() { var target = PlistInfo(options: options) XCTAssertNil(target.githubLibraries) - target.loadGitHubLibraries(cartfile: nil) + target.loadGitHubLibraries(file: .carthage(content: nil)) let libraries = target.githubLibraries! XCTAssertEqual(libraries.count, 1) let lib1 = libraries[0]