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

Felix/packageresolved version system #21

Merged
merged 2 commits into from
Mar 15, 2022
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
57 changes: 42 additions & 15 deletions Sources/SwiftPackageListCommand/Models.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,39 +22,66 @@ struct RuntimeError: Error, CustomStringConvertible {

// MARK: - PackageResolved

struct PackageResolved: Decodable {
let object: Object
enum PackageResolvedVersion: Int {
case v1 = 1
case v2
}

extension PackageResolved {
struct PackageResolved_V1: Decodable {

struct Object: Decodable {

struct Pin: Decodable {

struct State: Decodable {
let branch: String?
let revision: String
let version: String?
}

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

let pins: [Pin]
}

let object: Object
let version: Int
}

extension PackageResolved.Object {
extension PackageResolved_V1.Object.Pin {

struct Pin: Decodable {
let package: String
let repositoryURL: String
let state: State
var checkoutURL: URL? {
URL(string: repositoryURL.replacingOccurrences(of: ".git", with: ""))
}
}

extension PackageResolved.Object.Pin {
struct PackageResolved_V2: Decodable {

struct State: Decodable {
let branch: String?
let revision: String
let version: String?
struct Pin: Decodable {

struct State: Decodable {
let revision: String
let version: String?
let branch: String?
}

let identity: String
let kind: String
let location: String
let state: State
}

let pins: [Pin]
let version: Int
}

extension PackageResolved.Object.Pin {
extension PackageResolved_V2.Pin {

var checkoutURL: URL? {
URL(string: repositoryURL.replacingOccurrences(of: ".git", with: ""))
URL(string: location.replacingOccurrences(of: ".git", with: ""))
}
}

Expand Down
52 changes: 40 additions & 12 deletions Sources/SwiftPackageListCommand/SwiftPackageListCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,49 @@ struct SwiftPackageListCommand: ParsableCommand {
guard FileManager.default.fileExists(atPath: project.packageDotResolvedFileURL.path) else {
throw CleanExit.message("This project has no Swift-Package dependencies")
}
let packageDotResolved = try String(contentsOfFile: project.packageDotResolvedFileURL.path)
let packageResolved = try JSONDecoder().decode(PackageResolved.self, from: Data(packageDotResolved.utf8))
let packageDotResolved = try Data(contentsOf: project.packageDotResolvedFileURL)

let packages = try packageResolved.object.pins.compactMap { pin -> Package? in
guard let checkoutURL = pin.checkoutURL else { return nil }
if let licensePath = try locateLicensePath(for: checkoutURL, in: checkoutsPath) {
let license = try String(contentsOf: licensePath, encoding: .utf8)
return Package(name: pin.package, version: pin.state.version, branch: pin.state.branch, revision: pin.state.revision, repositoryURL: checkoutURL, license: license)
} else if !requiresLicense {
return Package(name: pin.package, version: pin.state.version, branch: pin.state.branch, revision: pin.state.revision, repositoryURL: checkoutURL, license: nil)
let packages = try createPackages(from: packageDotResolved, checkoutsPath: checkoutsPath)
try writeOutputFile(for: packages)
}

func createPackages(from packageDotResolved: Data, checkoutsPath: URL) throws -> [Package] {
let packageDotResolvedJSON = try JSONSerialization.jsonObject(with: packageDotResolved) as? [String: Any]
let version = packageDotResolvedJSON?["version"] as? Int
let packageResolvedVersion = PackageResolvedVersion(rawValue: version ?? 0)

switch packageResolvedVersion {
case .v1:
let packageResolved = try JSONDecoder().decode(PackageResolved_V1.self, from: packageDotResolved)
let packages = try packageResolved.object.pins.compactMap { pin -> Package? in
guard let checkoutURL = pin.checkoutURL else { return nil }
let name = checkoutURL.lastPathComponent
if let licensePath = try locateLicensePath(for: checkoutURL, in: checkoutsPath) {
let license = try String(contentsOf: licensePath, encoding: .utf8)
return Package(name: name, version: pin.state.version, branch: pin.state.branch, revision: pin.state.revision, repositoryURL: checkoutURL, license: license)
} else if !requiresLicense {
return Package(name: name, version: pin.state.version, branch: pin.state.branch, revision: pin.state.revision, repositoryURL: checkoutURL, license: nil)
}
return nil
}
return nil
return packages
case .v2:
let packageResolved = try JSONDecoder().decode(PackageResolved_V2.self, from: packageDotResolved)
let packages = try packageResolved.pins.compactMap { pin -> Package? in
guard let checkoutURL = pin.checkoutURL else { return nil }
let name = checkoutURL.lastPathComponent
if let licensePath = try locateLicensePath(for: checkoutURL, in: checkoutsPath) {
let license = try String(contentsOf: licensePath, encoding: .utf8)
return Package(name: name, version: pin.state.version, branch: pin.state.branch, revision: pin.state.revision, repositoryURL: checkoutURL, license: license)
} else if !requiresLicense {
return Package(name: name, version: pin.state.version, branch: pin.state.branch, revision: pin.state.revision, repositoryURL: checkoutURL, license: nil)
}
return nil
}
return packages
case .none:
throw RuntimeError("The version of the Package.resolved is not supported")
}

try writeOutputFile(for: packages)
}

func writeOutputFile(for packages: [Package]) throws {
Expand Down