Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix spm licenses gen #150

Merged
merged 19 commits into from
Apr 9, 2021
Merged
Show file tree
Hide file tree
Changes from all 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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ Pods
!Pods*.swift
test_result_dir
/.history
Tests/LicensePlistTests/XcodeProjects/**/xcuserdata
3 changes: 3 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ disabled_rules:
included:
- Sources
- Tests

excluded:
- Tests/LicensePlistTests/XcodeProjects

line_length: 250
nesting:
Expand Down
8 changes: 7 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ let package = Package(
"Yaml"
]
),
.testTarget(name: "LicensePlistTests", dependencies: ["LicensePlistCore"])
.testTarget(
name: "LicensePlistTests",
dependencies: ["LicensePlistCore"],
exclude: [
"XcodeProjects"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could exclude the test xcode-projects directory by specifying it in Package.swift.

]
)
]
)
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ You can see options by `license-plist --help`.
#### `--package-path`

- Default: `Package.swift`
- If you are using Swift Package Manager inside Xcode, you can use `--package-path $PROJECT_FILE_PATH/project.xcworkspace/xcshareddata/swiftpm/Package.swift` inside your `Run script`.
- `LicensePlist` tries to find `YourProjectName.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved` and `YourProjectName.xcworkspace/xcshareddata/swiftpm/Package.resolved`, then uses new one. If you make anothor workspace in custom directory, you can use `--package-path PathToYourCustomWorkspace/CustomWorkspaceName.xcworkspace/xcshareddata/swiftpm/Package.swift` inside your `Run script`.

#### `--output-path`

Expand Down
22 changes: 22 additions & 0 deletions Sources/LicensePlistCore/Entity/FileReader/FileReader.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// FileReader.swift
// LicensePlistCore
//
// Created by yosshi4486 on 2021/04/06.
//

import Foundation

/// An object that reads any file from the given path.
protocol FileReader {

/// The result parameter type of reading a file.
associatedtype ResultType

/// The path which an interested file located.
var path: URL { get }

/// Returns a concrete result by reading a file which the given path specifies.
func read() throws -> ResultType

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// SwiftPackageFileReader.swift
// LicensePlistCore
//
// Created by yosshi4486 on 2021/04/06.
//

import Foundation

/// An object that reads a Package.swift or Package.resolved file.
struct SwiftPackageFileReader: FileReader {

struct FileReaderError: Swift.Error {
let path: URL

var localizedDescription: String? {
return "Invalide Package.swift name: \(path.lastPathComponent)"
}

}

typealias ResultType = String?

let path: URL

func read() throws -> String? {
if path.lastPathComponent != Consts.packageName && path.lastPathComponent != "Package.resolved" {
throw FileReaderError(path: path)
}

if let content = path.deletingPathExtension().appendingPathExtension("resolved").lp.read() {
return content
}
return path.lp.read()
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//
// XcodeProjectFileReader.swift
// LicensePlistCore
//
// Created by yosshi4486 on 2021/04/06.
//

import Foundation

/// An object that reads a xcodeproj file.
struct XcodeProjectFileReader: FileReader {

typealias ResultType = String?

let path: URL

/// The path which specifies "xcodeproj" file.
var projectPath: URL? {
if path.lastPathComponent.contains("*") {
// find first "xcodeproj" in directory
return path.deletingLastPathComponent().lp.listDir().first { $0.pathExtension == Consts.xcodeprojExtension }
} else {
// use the specified path
return path
}
}

func read() throws -> String? {
guard let validatedPath = projectPath else { return nil }

if validatedPath.pathExtension != Consts.xcodeprojExtension {
return nil
}

let xcodeprojPackageResolvedPath = validatedPath
.appendingPathComponent("project.xcworkspace")
.appendingPathComponent("xcshareddata")
.appendingPathComponent("swiftpm")
.appendingPathComponent("Package.resolved")

let xcworkspacePackageResolvedPath = validatedPath
.deletingPathExtension()
.appendingPathExtension("xcworkspace")
.appendingPathComponent("xcshareddata")
.appendingPathComponent("swiftpm")
.appendingPathComponent("Package.resolved")

let defaultPath = xcworkspacePackageResolvedPath

/*
Xcode only update one Package.resolved that associated with workspace you work in. so, the files may be inconsistent at any time.
This implementation compare modificationDate and use new one to avoid referring old Package.resolved.
*/
switch (xcodeprojPackageResolvedPath.lp.isExists, xcworkspacePackageResolvedPath.lp.isExists) {
case (true, true):
guard
let xcodeprojPackageResolvedModifiedDate = try xcodeprojPackageResolvedPath
.resourceValues(forKeys: [.attributeModificationDateKey])
.attributeModificationDate,
let xcworkspacePackageResolveModifiedDate = try xcworkspacePackageResolvedPath
.resourceValues(forKeys: [.attributeModificationDateKey])
.attributeModificationDate
else {
return try SwiftPackageFileReader(path: defaultPath).read()
}

if xcworkspacePackageResolveModifiedDate >= xcodeprojPackageResolvedModifiedDate {
return try SwiftPackageFileReader(path: xcworkspacePackageResolvedPath).read()
} else {
return try SwiftPackageFileReader(path: xcodeprojPackageResolvedPath).read()
}

case (true, false):
return try SwiftPackageFileReader(path: xcodeprojPackageResolvedPath).read()

case (false, true):
return try SwiftPackageFileReader(path: xcworkspacePackageResolvedPath).read()

case (false, false):
return try SwiftPackageFileReader(path: defaultPath).read()
}
}

}
3 changes: 3 additions & 0 deletions Sources/LicensePlistCore/Extension/URL.extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ extension LicensePlistExtension where Base == URL {
assertionFailure(message)
Log.error(message)
}
internal var fileURL: URL {
return URL(fileURLWithPath: base.absoluteString)
}
}

protocol HasDefaultValue {
Expand Down
52 changes: 8 additions & 44 deletions Sources/LicensePlistCore/LicensePlist.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,14 @@ public final class LicensePlist {
info.loadCocoaPodsLicense(acknowledgements: readPodsAcknowledgements(path: options.podsPath))
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))

do {
let swiftPackageFileReadResult = try SwiftPackageFileReader(path: options.packagePath).read()
let xcodeProjectFileReadResult = try XcodeProjectFileReader(path: options.xcodeprojPath).read()
info.loadSwiftPackageLibraries(packageFile: swiftPackageFileReadResult ?? xcodeProjectFileReadResult)
} catch {
fatalError(error.localizedDescription)
}
info.loadManualLibraries()
info.compareWithLatestSummary()
info.downloadGitHubLicenses()
Expand Down Expand Up @@ -44,49 +51,6 @@ private func readMintfile(path: URL) -> GitHubLibraryConfigFile {
return .mint(content: path.lp.read())
}

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

private func readXcodeProject(path: URL) -> String? {

var projectPath: URL?
if path.lastPathComponent.contains("*") {
// find first "xcodeproj" in directory
projectPath = path.deletingLastPathComponent().lp.listDir().first { $0.pathExtension == Consts.xcodeprojExtension }
} else {
// use the specified path
projectPath = path
}
guard let validatedPath = projectPath else { return nil }

if validatedPath.pathExtension != Consts.xcodeprojExtension {
return nil
}
let packageResolvedPath = validatedPath
.appendingPathComponent("project.xcworkspace")
.appendingPathComponent("xcshareddata")
.appendingPathComponent("swiftpm")
.appendingPathComponent("Package.resolved")
if packageResolvedPath.lp.isExists {
return readSwiftPackages(path: packageResolvedPath)
} else {
let packageResolvedPath = validatedPath
.deletingPathExtension()
.appendingPathExtension("xcworkspace")
.appendingPathComponent("xcshareddata")
.appendingPathComponent("swiftpm")
.appendingPathComponent("Package.resolved")
return readSwiftPackages(path: packageResolvedPath)
}
}

private func readPodsAcknowledgements(path: URL) -> [String] {
if path.lastPathComponent != Consts.podsDirectoryName {
fatalError("Invalid Pods name: \(path.lastPathComponent)")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
//
// SwiftPackageFileReaderTests.swift
// LicensePlistTests
//
// Created by yosshi4486 on 2021/04/06.
//

import XCTest
@testable import LicensePlistCore

class SwiftPackageFileReaderTests: XCTestCase {

var fileURL: URL!

var packageResolvedText: String {
return #"""
{
"object": {
"pins": [
{
"package": "APIKit",
"repositoryURL": "https://github.com/ishkawa/APIKit.git",
"state": {
"branch": null,
"revision": "86d51ecee0bc0ebdb53fb69b11a24169a69097ba",
"version": "4.1.0"
}
},
{
"package": "HeliumLogger",
"repositoryURL": "https://github.com/IBM-Swift/HeliumLogger.git",
"state": {
"branch": null,
"revision": "146a36c2a91270e4213fa7d7e8192cd2e55d0ace",
"version": "1.9.0"
}
},
{
"package": "LoggerAPI",
"repositoryURL": "https://github.com/IBM-Swift/LoggerAPI.git",
"state": {
"branch": null,
"revision": "3357dd9526cdf9436fa63bb792b669e6efdc43da",
"version": "1.9.0"
}
},
{
"package": "Result",
"repositoryURL": "https://github.com/antitypical/Result.git",
"state": {
"branch": null,
"revision": "2ca499ba456795616fbc471561ff1d963e6ae160",
"version": "4.1.0"
}
},
{
"package": "swift-argument-parser",
"repositoryURL": "https://github.com/apple/swift-argument-parser.git",
"state": {
"branch": null,
"revision": "92646c0cdbaca076c8d3d0207891785b3379cbff",
"version": "0.3.1"
}
},
{
"package": "HTMLEntities",
"repositoryURL": "https://github.com/IBM-Swift/swift-html-entities.git",
"state": {
"branch": null,
"revision": "744c094976355aa96ca61b9b60ef0a38e979feb7",
"version": "3.0.14"
}
},
{
"package": "swift-log",
"repositoryURL": "https://github.com/apple/swift-log.git",
"state": {
"branch": null,
"revision": "eba9b323b5ba542c119ff17382a4ce737bcdc0b8",
"version": "0.0.0"
}
},
{
"package": "Yaml",
"repositoryURL": "https://github.com/behrang/YamlSwift.git",
"state": {
"branch": null,
"revision": "287f5cab7da0d92eb947b5fd8151b203ae04a9a3",
"version": "3.4.4"
}
}
]
},
"version": 1
}
"""#
}

override func setUpWithError() throws {
fileURL = URL(fileURLWithPath: "\(TestUtil.testProjectsPath)/SwiftPackageManagerTestProject/SwiftPackageManagerTestProject.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved")
}

override func tearDownWithError() throws {
fileURL = nil
}

func testInvalidPath() throws {
let invalidFilePath = fileURL.deletingLastPathComponent().appendingPathComponent("Podfile.lock")
let reader = SwiftPackageFileReader(path: invalidFilePath)
XCTAssertThrowsError(try reader.read())
}

func testPackageSwift() throws {
// Path for this package's Package.swift.
let packageSwiftPath = TestUtil.sourceDir.appendingPathComponent("Package.swift").lp.fileURL
let reader = SwiftPackageFileReader(path: packageSwiftPath)
XCTAssertEqual(
try reader.read()?.trimmingCharacters(in: .whitespacesAndNewlines),
packageResolvedText.trimmingCharacters(in: .whitespacesAndNewlines)
)
}

func testPackageResolved() throws {
// Path for this package's Package.resolved.
let packageResolvedPath = TestUtil.sourceDir.appendingPathComponent("Package.resolved").lp.fileURL
let reader = SwiftPackageFileReader(path: packageResolvedPath)
XCTAssertEqual(
try reader.read()?.trimmingCharacters(in: .whitespacesAndNewlines),
packageResolvedText.trimmingCharacters(in: .whitespacesAndNewlines)
)
}

}
Loading