Skip to content

Commit

Permalink
Merge pull request #7 from Ether-CLI/develop
Browse files Browse the repository at this point in the history
Codable Types
  • Loading branch information
calebkleveter authored May 4, 2018
2 parents a47655d + 3f1cf3d commit da15f03
Show file tree
Hide file tree
Showing 64 changed files with 4,973 additions and 373 deletions.
30 changes: 29 additions & 1 deletion Sources/Manifest/Dependency/Dependency.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import Utilities

/// An external package that the current project relies on.
/// These are stored in the manifest's `dependencies` array.
public final class Dependency: CustomStringConvertible {
public final class Dependency: CustomStringConvertible, Codable {

/// Keys used to encode/decode a `Target` object.
public typealias CodingKeys = DependencyCodingKeys

/// The URI or path to the dependency.
public let url: String
Expand All @@ -22,6 +25,14 @@ public final class Dependency: CustomStringConvertible {
self.manifest = Manifest.current
}

///
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: DependencyCodingKeys.self)
self.url = try container.decode(String.self, forKey: .url)
self.version = try DependencyVersionType(from: container.decode(String.self, forKey: .version))
self.manifest = Manifest.current
}

///
internal init(manifest: Manifest, url: String, version: String)throws {
self.url = url
Expand All @@ -33,4 +44,21 @@ public final class Dependency: CustomStringConvertible {
public var description: String {
return ".package(url: \"\(self.url)\", \(self.version.description))"
}

///
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: DependencyCodingKeys.self)
try container.encode(url, forKey: .url)
try container.encode(version.description, forKey: .version)
}
}

/// Keys used to encode/decode a `Target` object.
public enum DependencyCodingKeys: CodingKey {

///
case url

///
case version
}
6 changes: 3 additions & 3 deletions Sources/Manifest/Error.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import Foundation

public struct ManifestError: Error {
public let identifier: String
public let reason: String
struct ManifestError: Error {
let identifier: String
let reason: String
}

extension ManifestError {
Expand Down
20 changes: 19 additions & 1 deletion Sources/Manifest/Manifest.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Foundation

/// An interface for a package's manifest.
public class Manifest {
public class Manifest: Codable {

/// The current environment that the `Manifest` is being used in.
public static var environment: Environment = .commandline
Expand Down Expand Up @@ -36,6 +36,24 @@ public class Manifest {
self.path = nil
}

///
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: ManifestDecodingKeys.self)
self.data = try Data(container.decode(String.self, forKey: .manifest).utf8)
self.path = nil
}

///
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: ManifestCodingKeys.self)
try container.encode(self.name(), forKey: .name)
try container.encodeIfPresent(self.packageConfig(), forKey: .pkgConfig)
try container.encode(self.providers(), forKey: .providers)
try container.encode(self.products(), forKey: .products)
try container.encode(self.dependencies(), forKey: .dependencies)
try container.encode(self.targets(), forKey: .targets)
}

/// Gets the contents of the project's manifest as `Data`.
///
/// - Returns: The manifest's contents.
Expand Down
31 changes: 31 additions & 0 deletions Sources/Manifest/ManifestCodingKeys.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
extension Manifest {

/// Keys for encoding a `Manifest` instance.
public typealias CodingKeys = ManifestCodingKeys
}

/// Keys for encoding a `Manifest` instance.
public enum ManifestCodingKeys: String, CodingKey {

///
case name

///
case pkgConfig

///
case providers

///
case products

///
case dependencies

///
case targets
}

internal enum ManifestDecodingKeys: String, CodingKey {
case manifest
}
43 changes: 42 additions & 1 deletion Sources/Manifest/Product/Product.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import Utilities
/// A product that is vended by the parent package.
///
/// For more information, visit the [SPM docs](https://github.com/apple/swift-package-manager/blob/master/Documentation/PackageDescriptionV4.md#products).
public final class Product: CustomStringConvertible {
public final class Product: CustomStringConvertible, Codable {

/// Keys used of encoding a `Product` object.
public typealias CodingKeys = ProductCodingKeys

/// Denotes wheather the product is a library or an executable.
public let type: ProductType
Expand Down Expand Up @@ -33,6 +36,17 @@ public final class Product: CustomStringConvertible {
self.manifest = Manifest.current
}

///
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: ProductCodingKeys.self)
self.type = try ProductType(rawValue: container.decodeIfPresent(String.self, forKey: .type) ?? "library") ?? .library
self.name = try container.decode(String.self, forKey: .name)
self.linking = try LibraryLinkingType(rawValue: container.decodeIfPresent(String.self, forKey: .linking) ?? "none")
self.targets = try container.decode([String].self, forKey: .targets)

self.manifest = Manifest.current
}

/// Used to create `Product` objects that who's data is fecthed from the project manifest.
internal init(from manifest: Manifest, withType type: ProductType, name: String, linking: LibraryLinkingType?, targets: [String]) {
self.type = type
Expand All @@ -52,4 +66,31 @@ public final class Product: CustomStringConvertible {
"targets: \(self.targets.description)" +
")"
}

/// Encodes the objects public properties to an encoder
///
/// - Parameter encoder: The encoder the properties get encoded to.
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: ProductCodingKeys.self)
try container.encode(self.type.rawValue, forKey: .type)
try container.encode(self.name, forKey: .name)
try container.encode(self.targets, forKey: .targets)
try container.encodeIfPresent(self.linking?.rawValue, forKey: .linking)
}
}

/// Keys used of encoding a `Product` object.
public enum ProductCodingKeys: String, CodingKey {

///
case type

///
case name

///
case linking

///
case targets
}
28 changes: 28 additions & 0 deletions Sources/Manifest/Providers/Manifest+Providers.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Foundation
import Utilities

extension Manifest {

/// Get all the elements in `Package.providers` from the project's manifest.
///
/// - Returns: `Package.providers`
/// - Throws: Errors that occur when creating a RegEx pattern
/// or reading or writing the manifest.
public func providers()throws -> [Provider] {
let brew = try NSRegularExpression(pattern: "\\.brew\\((\\[.*?\\])\\)", options: [])
let apt = try NSRegularExpression(pattern: "\\.apt\\((\\[.*?\\])\\)", options: [])
let contents: String = try self.contents()

let brewProviders: [Provider] = brew.matches(in: contents, options: [], range: contents.range).map { (match) in
let packages = contents.parseArray(at: match.range(at: 1))
return Provider(type: .brew, packages: packages, manifest: self)
}
let aptProviders: [Provider] = apt.matches(in: contents, options: [], range: contents.range).map { (match) in
let packages = contents.parseArray(at: match.range(at: 1))
return Provider(type: .apt, packages: packages, manifest: self)
}

return brewProviders + aptProviders
}
}

53 changes: 29 additions & 24 deletions Sources/Manifest/Providers/Providers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import Utilities
/// Respresents a system package manager and the packages that should be installed through that given package manager.
///
/// More information [here](https://github.com/apple/swift-package-manager/blob/master/Documentation/PackageDescriptionV4.md#providers)
public class Provider: CustomStringConvertible {
public class Provider: CustomStringConvertible, Codable {

/// Keys used for encoding/decoding a `Provider` object.
public typealias CodingKeys = ProviderCodingKeys

/// The package manager that the provider represents
public let type: ProviderType
Expand All @@ -23,6 +26,20 @@ public class Provider: CustomStringConvertible {
self.manifest = manifest ?? Manifest.current
}

///
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: ProviderCodingKeys.self)

let rawType = try container.decode(String.self, forKey: .type)
guard let type = ProviderType(rawValue: rawType) else {
throw ManifestError(identifier: "missingDecodingValue", reason: "No value found for key 'type' of type 'String'. Valid values are 'brew' and 'apt'")
}
self.type = type
self.packages = try container.decode([String].self, forKey: .packages)

self.manifest = Manifest.current
}

/// The provider formatted for the manifest.
public var description: String {
return ".\(self.type.rawValue)(\(self.packages.description))"
Expand Down Expand Up @@ -67,6 +84,13 @@ public class Provider: CustomStringConvertible {
let packages = String(contents).parseArray(at: provider.range(at: 1))
return Provider(type: .apt, packages: packages, manifest: manifest)
}

///
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: ProviderCodingKeys.self)
try container.encode(self.type.rawValue, forKey: .type)
try container.encode(self.packages, forKey: .packages)
}
}

/// Designates which package manager the provider is for.
Expand All @@ -79,27 +103,8 @@ public enum ProviderType: String {
case apt
}

extension Manifest {

/// Get all the elements in `Package.providers` from the project's manifest.
///
/// - Returns: `Package.providers`
/// - Throws: Errors that occur when creating a RegEx pattern
/// or reading or writing the manifest.
public func providers()throws -> [Provider] {
let brew = try NSRegularExpression(pattern: "\\.brew\\((\\[.*?\\])\\)", options: [])
let apt = try NSRegularExpression(pattern: "\\.apt\\((\\[.*?\\])\\)", options: [])
let contents: String = try self.contents()

let brewProviders: [Provider] = brew.matches(in: contents, options: [], range: contents.range).map { (match) in
let packages = contents.parseArray(at: match.range(at: 1))
return Provider(type: .brew, packages: packages, manifest: self)
}
let aptProviders: [Provider] = apt.matches(in: contents, options: [], range: contents.range).map { (match) in
let packages = contents.parseArray(at: match.range(at: 1))
return Provider(type: .apt, packages: packages, manifest: self)
}

return brewProviders + aptProviders
}
/// Keys used for encoding/decoding a `Provider` object.
public enum ProviderCodingKeys: String, CodingKey {
case type
case packages
}
60 changes: 59 additions & 1 deletion Sources/Manifest/Target/Target.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import Foundation
import Utilities

/// Represents a target declaration in a project's manifest.
public class Target: CustomStringConvertible {
public class Target: CustomStringConvertible, Codable {

/// Keys for encoding/decoding a `Target` object.
public typealias CodingKeys = TargetCodingKeys

/// Wheather the target is for testing or not.
public let isTest: Bool
Expand Down Expand Up @@ -85,6 +88,20 @@ public class Target: CustomStringConvertible {
")"
}

///
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: TargetCodingKeys.self)
self.isTest = try container.decode(Bool.self, forKey: .isTest)
self.name = try container.decode(String.self, forKey: .name)
self.path = try container.decodeIfPresent(String.self, forKey: .path)
self.publicHeadersPath = try container.decodeIfPresent(String.self, forKey: .publicHeadersPath)
self.dependencies = try container.decode([String].self, forKey: .dependencies)
self.exclude = try container.decode([String].self, forKey: .exclude)
self.source = try container.decode([String].self, forKey: .source)
self.raw = try container.decode(String.self, forKey: .raw)
self.manifest = Manifest.current
}

/// The target formatted for the manifest.
public var description: String {
return (self.isTest ? ".testTarget" : ".target") +
Expand All @@ -95,4 +112,45 @@ public class Target: CustomStringConvertible {
(self.publicHeadersPath == nil ? "" : ", publicHeadersPath: \"\(self.publicHeadersPath!)\"") +
")"
}

///
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: TargetCodingKeys.self)
try container.encode(isTest, forKey: .isTest)
try container.encode(name, forKey: .name)
try container.encodeIfPresent(path, forKey: .path)
try container.encodeIfPresent(publicHeadersPath, forKey: .publicHeadersPath)
try container.encode(dependencies, forKey: .dependencies)
try container.encode(exclude, forKey: .exclude)
try container.encode(source, forKey: .source)
try container.encode(raw, forKey: .raw)
}
}

/// Keys for encoding/decoding a `Target` object.
public enum TargetCodingKeys: String, CodingKey {

///
case isTest

///
case name

///
case path

///
case publicHeadersPath

///
case dependencies

///
case exclude

///
case source

///
case raw
}
Loading

0 comments on commit da15f03

Please sign in to comment.