Skip to content

Commit

Permalink
Merge pull request #72 from FelixHerrmann/feature/package-name
Browse files Browse the repository at this point in the history
[Feature] Package Name
  • Loading branch information
FelixHerrmann authored Dec 11, 2023
2 parents 412180a + a3a54d7 commit 859f1e9
Show file tree
Hide file tree
Showing 25 changed files with 764 additions and 225 deletions.
14 changes: 13 additions & 1 deletion Sources/SwiftPackageList/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import Foundation
/// A package object in the package-list file.
public struct Package: Hashable, Codable {

/// The package identity based on it's source location.
public let identity: String

/// The name of the package.
public let name: String

Expand All @@ -36,7 +39,16 @@ public struct Package: Hashable, Codable {
/// This is always present if the `--requires-license` flag is parsed on command execution.
public let license: String?

public init(name: String, version: String?, branch: String?, revision: String, repositoryURL: URL, license: String?) {
public init(
identity: String,
name: String,
version: String?,
branch: String?,
revision: String,
repositoryURL: URL,
license: String?
) {
self.identity = identity
self.name = name
self.version = version
self.branch = branch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,31 +42,31 @@ extension PackageResolved {
// MARK: - Packages

extension PackageResolved {
public func packages(in checkoutsDirectory: URL, requiresLicense: Bool) throws -> [Package] {
public func packages(in sourcePackagesDirectory: URL, requiresLicense: Bool) throws -> [Package] {
switch self {
case .v1(let packageResolved):
return try packages(
pins: packageResolved.object.pins,
checkoutsDirectory: checkoutsDirectory,
sourcePackagesDirectory: sourcePackagesDirectory,
requiresLicense: requiresLicense
)
case .v2(let packageResolved):
return try packages(
pins: packageResolved.pins,
checkoutsDirectory: checkoutsDirectory,
sourcePackagesDirectory: sourcePackagesDirectory,
requiresLicense: requiresLicense
)
case .v3(let packageResolved):
return try packages(
pins: packageResolved.pins,
checkoutsDirectory: checkoutsDirectory,
sourcePackagesDirectory: sourcePackagesDirectory,
requiresLicense: requiresLicense
)
}
}

private func licensePath(for checkoutURL: URL, in checkoutsDirectory: URL) throws -> URL? {
let checkoutName = checkoutURL.lastPathComponent
let checkoutName = checkoutURL.deletingPathExtension().lastPathComponent
let checkoutPath = checkoutsDirectory.appendingPathComponent(checkoutName)
let packageFiles = try FileManager.default.contentsOfDirectory(
at: checkoutPath,
Expand All @@ -82,15 +82,18 @@ extension PackageResolved {

private func packages(
pins: [PackageResolved_V1.Object.Pin],
checkoutsDirectory: URL,
sourcePackagesDirectory: URL,
requiresLicense: Bool
) throws -> [Package] {
let checkoutsDirectory = sourcePackagesDirectory.appendingPathComponent("checkouts")

return try pins.compactMap { pin -> Package? in
guard let checkoutURL = pin.checkoutURL else { return nil }
if let licensePath = try licensePath(for: checkoutURL, in: checkoutsDirectory) {
let license = try String(contentsOf: licensePath, encoding: .utf8)
return Package(
name: checkoutURL.lastPathComponent,
identity: pin.identity,
name: pin.package,
version: pin.state.version,
branch: pin.state.branch,
revision: pin.state.revision,
Expand All @@ -99,7 +102,8 @@ extension PackageResolved {
)
} else if !requiresLicense {
return Package(
name: checkoutURL.lastPathComponent,
identity: pin.identity,
name: pin.package,
version: pin.state.version,
branch: pin.state.branch,
revision: pin.state.revision,
Expand All @@ -111,13 +115,24 @@ extension PackageResolved {
}
}

private func packages(pins: [PackageResolved_V2.Pin], checkoutsDirectory: URL, requiresLicense: Bool) throws -> [Package] {
private func packages(
pins: [PackageResolved_V2.Pin],
sourcePackagesDirectory: URL,
requiresLicense: Bool
) throws -> [Package] {
let checkoutsDirectory = sourcePackagesDirectory.appendingPathComponent("checkouts")
let workspaceStateFile = sourcePackagesDirectory.appendingPathComponent("workspace-state.json")
let workspaceState = try WorkspaceState(at: workspaceStateFile)

return try pins.compactMap { pin -> Package? in
guard let checkoutURL = pin.checkoutURL else { return nil }
let name = workspaceState.packageName(for: pin.identity) ?? pin.identity

if let licensePath = try licensePath(for: checkoutURL, in: checkoutsDirectory) {
let license = try String(contentsOf: licensePath, encoding: .utf8)
return Package(
name: checkoutURL.lastPathComponent,
identity: pin.identity,
name: name,
version: pin.state.version,
branch: pin.state.branch,
revision: pin.state.revision,
Expand All @@ -126,7 +141,8 @@ extension PackageResolved {
)
} else if !requiresLicense {
return Package(
name: checkoutURL.lastPathComponent,
identity: pin.identity,
name: name,
version: pin.state.version,
branch: pin.state.branch,
revision: pin.state.revision,
Expand Down Expand Up @@ -172,7 +188,18 @@ public struct PackageResolved_V1: Decodable {

extension PackageResolved_V1.Object.Pin {
var checkoutURL: URL? {
URL(string: repositoryURL.replacingOccurrences(of: ".git", with: ""))
return URL(string: repositoryURL)
}

/// Source: https://github.com/apple/swift-package-manager/blob/d457fa46b396248e46361776faacb9e0020b92d1/Sources/PackageModel/PackageIdentity.swift#L304
var identity: String {
let url: URL
if let remoteURL = URL(string: repositoryURL) {
url = remoteURL
} else {
url = URL(fileURLWithPath: repositoryURL)
}
return url.deletingPathExtension().lastPathComponent.lowercased()
}
}

Expand All @@ -198,7 +225,7 @@ public struct PackageResolved_V2: Decodable {

extension PackageResolved_V2.Pin {
var checkoutURL: URL? {
URL(string: location.replacingOccurrences(of: ".git", with: ""))
return URL(string: location)
}
}

Expand Down
156 changes: 156 additions & 0 deletions Sources/SwiftPackageListCore/File Representations/WorkspaceState.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
//
// WorkspaceState.swift
// SwiftPackageListCore
//
// Created by Felix Herrmann on 09.12.23.
//

import Foundation

/// Source: https://github.com/apple/swift-package-manager/blob/d457fa46b396248e46361776faacb9e0020b92d1/Sources/Workspace/Workspace%2BState.swift
public enum WorkspaceState {
// swiftlint:disable identifier_name
case v4(WorkspaceState_V4)
case v5(WorkspaceState_V5)
case v6(WorkspaceState_V6)
// swiftlint:enable identifier_name
}

extension WorkspaceState {
public init(at url: URL) throws {
let data = try Data(contentsOf: url)
let decoder = JSONDecoder()
let version = try decoder.decode(Version.self, from: data)

switch version.version {
case 1, 2, 3, 4:
let workspaceState = try decoder.decode(WorkspaceState_V4.self, from: data)
self = .v4(workspaceState)
case 5:
let workspaceState = try decoder.decode(WorkspaceState_V5.self, from: data)
self = .v5(workspaceState)
case 6:
let workspaceState = try decoder.decode(WorkspaceState_V6.self, from: data)
self = .v6(workspaceState)
default:
throw RuntimeError("Version \(version.version) of workspace-state.json is not supported")
}
}
}

// MARK: - Package Name

extension WorkspaceState {
func packageName(for identity: String) -> String? {
switch self {
case .v4(let v4): // swiftlint:disable:this identifier_name
for artifact in v4.object.artifacts where artifact.packageRef.identity == identity {
return artifact.packageRef.name
}

for dependency in v4.object.dependencies where dependency.packageRef.identity == identity {
return dependency.packageRef.name
}
case .v5(let v5): // swiftlint:disable:this identifier_name
for artifact in v5.object.artifacts where artifact.packageRef.identity == identity {
return artifact.packageRef.name
}

for dependency in v5.object.dependencies where dependency.packageRef.identity == identity {
return dependency.packageRef.name
}
case .v6(let v6): // swiftlint:disable:this identifier_name
for artifact in v6.object.artifacts where artifact.packageRef.identity == identity {
return artifact.packageRef.name
}

for dependency in v6.object.dependencies where dependency.packageRef.identity == identity {
return dependency.packageRef.name
}
}
return nil
}
}

// MARK: - Version

extension WorkspaceState {
struct Version: Decodable {
let version: Int
}
}

// MARK: - v4

public struct WorkspaceState_V4: Decodable {
struct Object: Decodable {
struct Artifact: Decodable {
let packageRef: PackageRef
}

struct Dependency: Decodable {
let packageRef: PackageRef
}

struct PackageRef: Decodable {
let identity: String
let name: String
}

let artifacts: [Artifact]
let dependencies: [Dependency]
}

let object: Object
let version: Int
}

// MARK: - V5

public struct WorkspaceState_V5: Decodable {
struct Object: Decodable {
struct Artifact: Decodable {
let packageRef: PackageRef
}

struct Dependency: Decodable {
let packageRef: PackageRef
}

struct PackageRef: Decodable {
let identity: String
let name: String
}

let artifacts: [Artifact]
let dependencies: [Dependency]
}

let object: Object
let version: Int
}

// MARK: - V6

public struct WorkspaceState_V6: Decodable {
struct Object: Decodable {
struct Artifact: Decodable {
let packageRef: PackageRef
}

struct Dependency: Decodable {
let packageRef: PackageRef
}

struct PackageRef: Decodable {
let identity: String
let name: String
}

let artifacts: [Artifact]
let dependencies: [Dependency]
}

let object: Object
let version: Int
}
14 changes: 8 additions & 6 deletions Sources/SwiftPackageListObjc/SPLPackage.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@

@implementation SPLPackage

- (instancetype)initWithName:(NSString *)name
version:(NSString *)version
branch:(NSString *)branch
revision:(NSString *)revision
repositoryURL:(NSURL *)repositoryURL
license:(NSString *)license {
- (instancetype)initWithIdentity:(NSString *)identity
name:(NSString *)name
version:(NSString *)version
branch:(NSString *)branch
revision:(NSString *)revision
repositoryURL:(NSURL *)repositoryURL
license:(NSString *)license {
self = [super init];
if (self) {
_identity = identity;
_name = name;
_version = version;
_branch = branch;
Expand Down
13 changes: 7 additions & 6 deletions Sources/SwiftPackageListObjc/SPLPackageList.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
NSArray<SPLPackage *> *SPLTransformArray(NSArray *array) {
NSMutableArray<SPLPackage *> *packages = [[NSMutableArray alloc] init];
for (NSDictionary *packageDict in array) {
SPLPackage *package = [[SPLPackage alloc] initWithName:[packageDict valueForKey:@"name"]
version:[packageDict valueForKey:@"version"]
branch:[packageDict valueForKey:@"branch"]
revision:[packageDict valueForKey:@"revision"]
repositoryURL:[packageDict valueForKey:@"repositoryURL"]
license:[packageDict valueForKey:@"license"]];
SPLPackage *package = [[SPLPackage alloc] initWithIdentity:[packageDict valueForKey:@"identity"]
name:[packageDict valueForKey:@"name"]
version:[packageDict valueForKey:@"version"]
branch:[packageDict valueForKey:@"branch"]
revision:[packageDict valueForKey:@"revision"]
repositoryURL:[packageDict valueForKey:@"repositoryURL"]
license:[packageDict valueForKey:@"license"]];
[packages addObject:package];
}
return packages;
Expand Down
16 changes: 10 additions & 6 deletions Sources/SwiftPackageListObjc/include/SPLPackage.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ NS_ASSUME_NONNULL_BEGIN
/// A package object in the package-list file.
@interface SPLPackage : NSObject

/// The package identity based on it's source location.
@property(nonatomic, readonly) NSString *identity;

/// The name of the package.
@property(nonatomic, readonly) NSString *name;

Expand All @@ -38,12 +41,13 @@ NS_ASSUME_NONNULL_BEGIN
/// This is always present if the --requires-license flag is parsed on command execution.
@property(nonatomic, readonly, nullable) NSString *license;

- (instancetype)initWithName:(NSString *)name
version:(nullable NSString *)version
branch:(nullable NSString *)branch
revision:(NSString *)revision
repositoryURL:(NSURL *)repositoryURL
license:(nullable NSString *)license;
- (instancetype)initWithIdentity:(NSString *)identity
name:(NSString *)name
version:(nullable NSString *)version
branch:(nullable NSString *)branch
revision:(NSString *)revision
repositoryURL:(NSURL *)repositoryURL
license:(nullable NSString *)license;

@end

Expand Down
Loading

0 comments on commit 859f1e9

Please sign in to comment.