Deprecate yaml and json manifests (#190)
* Deprecate JSON and YAML manifests * Add tests * Deprecate JSON and YAML manifests
This commit is contained in:
parent
9137e48f03
commit
330b7727d9
|
@ -16,6 +16,10 @@ Please, check out guidelines: https://keepachangelog.com/en/1.0.0/
|
|||
|
||||
- Danger https://github.com/tuist/tuist/pull/186 by @pepibumur.
|
||||
|
||||
### Deprecated
|
||||
|
||||
- JSON and YAML manifests https://github.com/tuist/tuist/pull/190 by @pepibumur.
|
||||
|
||||
## 0.10.2
|
||||
|
||||
### Fixed
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
import Foundation
|
||||
|
||||
/// Protocol that defines an interface to notify the user about features being deprecated
|
||||
public protocol Deprecating {
|
||||
/// Notifies the user about deprecations by printing a warning message.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - deprecation: Feature that will be deprecated.
|
||||
/// - suggestion: Suggestions for the user to migrate.
|
||||
func notify(deprecation: String, suggestion: String)
|
||||
}
|
||||
|
||||
public final class Deprecator: Deprecating {
|
||||
/// Printer instance to output the warning to the users.
|
||||
private let printer: Printing
|
||||
|
||||
/// Constructs a deprecator with a printer instance.
|
||||
///
|
||||
/// - Parameter printer: Printer instance to output the warning to the users.
|
||||
public init(printer: Printing = Printer()) {
|
||||
self.printer = printer
|
||||
}
|
||||
|
||||
/// Notifies the user about deprecations by printing a warning message.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - deprecation: Feature that will be deprecated.
|
||||
/// - suggestion: Suggestions for the user to migrate.
|
||||
public func notify(deprecation: String, suggestion: String) {
|
||||
let message = "\(deprecation) will be deprecated in the next major release. Use \(suggestion) instead."
|
||||
printer.print(deprecation: message)
|
||||
}
|
||||
}
|
|
@ -10,6 +10,11 @@ public protocol Printing: AnyObject {
|
|||
func print(error: Error)
|
||||
func print(success: String)
|
||||
func print(errorMessage: String)
|
||||
|
||||
/// Prints a deprecation message (yellow color)
|
||||
///
|
||||
/// - Parameter deprecation: Deprecation message.
|
||||
func print(deprecation: String)
|
||||
}
|
||||
|
||||
public class Printer: Printing {
|
||||
|
@ -45,6 +50,16 @@ public class Printer: Printing {
|
|||
writer.write("\n")
|
||||
}
|
||||
|
||||
/// Prints a deprecation message (yellow color)
|
||||
///
|
||||
/// - Parameter deprecation: Deprecation message.
|
||||
public func print(deprecation: String) {
|
||||
let writer = InteractiveWriter.stdout
|
||||
writer.write("Deprecated: ", inColor: .yellow, bold: true)
|
||||
writer.write(deprecation, inColor: .yellow, bold: false)
|
||||
writer.write("\n")
|
||||
}
|
||||
|
||||
public func print(warning: String) {
|
||||
let writer = InteractiveWriter.stdout
|
||||
writer.write("⚠️ Warning: ", inColor: .yellow, bold: true)
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
import Foundation
|
||||
import TuistCore
|
||||
|
||||
public final class MockDeprecator: Deprecating {
|
||||
public var notifyArgs: [(deprecation: String, suggestion: String)] = []
|
||||
|
||||
public func notify(deprecation: String, suggestion: String) {
|
||||
notifyArgs.append((deprecation: deprecation, suggestion: suggestion))
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ public final class MockPrinter: Printing {
|
|||
public var printErrorMessageArgs: [String] = []
|
||||
public var printSuccessArgs: [String] = []
|
||||
public var printWarningArgs: [String] = []
|
||||
public var printDeprecationArgs: [String] = []
|
||||
|
||||
public func print(_ text: String) {
|
||||
printArgs.append(text)
|
||||
|
@ -35,6 +36,11 @@ public final class MockPrinter: Printing {
|
|||
standardOutput.append("\(warning)\n")
|
||||
}
|
||||
|
||||
public func print(deprecation: String) {
|
||||
printDeprecationArgs.append(deprecation)
|
||||
standardOutput.append("\(deprecation)\n")
|
||||
}
|
||||
|
||||
public func print(errorMessage: String) {
|
||||
printErrorMessageArgs.append(errorMessage)
|
||||
standardError.append("\(errorMessage)\n")
|
||||
|
|
|
@ -78,21 +78,35 @@ protocol GraphManifestLoading {
|
|||
class GraphManifestLoader: GraphManifestLoading {
|
||||
// MARK: - Attributes
|
||||
|
||||
let fileAggregator: FileAggregating
|
||||
/// File handler to interact with the file system.
|
||||
let fileHandler: FileHandling
|
||||
|
||||
/// Instance to run commands in the system.
|
||||
let system: Systeming
|
||||
|
||||
/// Resource locator to look up Tuist-related resources.
|
||||
let resourceLocator: ResourceLocating
|
||||
|
||||
/// Depreactor to notify about deprecations.
|
||||
let deprecator: Deprecating
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
init(fileAggregator: FileAggregating = FileAggregator(),
|
||||
fileHandler: FileHandling = FileHandler(),
|
||||
/// Initializes the manifest loader with its attributes.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - fileHandler: File handler to interact with the file system.
|
||||
/// - system: Instance to run commands in the system.
|
||||
/// - resourceLocator: Resource locator to look up Tuist-related resources.
|
||||
/// - deprecator: Depreactor to notify about deprecations.
|
||||
init(fileHandler: FileHandling = FileHandler(),
|
||||
system: Systeming = System(),
|
||||
resourceLocator: ResourceLocating = ResourceLocator()) {
|
||||
self.fileAggregator = fileAggregator
|
||||
resourceLocator: ResourceLocating = ResourceLocator(),
|
||||
deprecator: Deprecating = Deprecator()) {
|
||||
self.fileHandler = fileHandler
|
||||
self.system = system
|
||||
self.resourceLocator = resourceLocator
|
||||
self.deprecator = deprecator
|
||||
}
|
||||
|
||||
func load(_ manifest: Manifest, path: AbsolutePath) throws -> JSON {
|
||||
|
@ -100,8 +114,10 @@ class GraphManifestLoader: GraphManifestLoading {
|
|||
if manifestPath.extension == "swift" {
|
||||
return try loadSwiftManifest(path: manifestPath)
|
||||
} else if manifestPath.extension == "json" {
|
||||
deprecator.notify(deprecation: "JSON manifests", suggestion: "Swift manifests")
|
||||
return try loadJSONManifest(path: manifestPath)
|
||||
} else if manifestPath.extension == "yaml" || manifestPath.extension == "yml" {
|
||||
deprecator.notify(deprecation: "YAML manifests", suggestion: "Swift manifests")
|
||||
return try loadYamlManifest(path: manifestPath)
|
||||
} else {
|
||||
throw GraphManifestLoaderError.manifestNotFound(manifest, path)
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
import Basic
|
||||
import Foundation
|
||||
|
||||
/// A file aggregator aggregates the content of multiple files.
|
||||
protocol FileAggregating: AnyObject {
|
||||
/// Aggreates the files at the given paths.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - paths: paths whose content will be aggregated.
|
||||
/// - into: path of the file where the contents will be aggregated into.
|
||||
/// - Throws: an error if the aggregation fails.
|
||||
func aggregate(_ paths: [AbsolutePath], into: AbsolutePath) throws
|
||||
}
|
||||
|
||||
/// Default file aggreagtor.
|
||||
final class FileAggregator: FileAggregating {
|
||||
/// Aggreates the files at the given paths.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - paths: paths whose content will be aggregated.
|
||||
/// - into: path of the file where the contents will be aggregated into.
|
||||
/// - Throws: an error if the aggregation fails.
|
||||
func aggregate(_ paths: [AbsolutePath], into: AbsolutePath) throws {
|
||||
var paths = paths
|
||||
if paths.count == 0 { return }
|
||||
let outputStream = OutputStream(toFileAtPath: into.asString, append: true)!
|
||||
outputStream.open()
|
||||
let first = paths.removeFirst()
|
||||
try Data(contentsOf: URL(fileURLWithPath: first.asString)).write(into: outputStream)
|
||||
try paths.forEach { path in
|
||||
"\n".data(using: .utf8)!.write(into: outputStream)
|
||||
try Data(contentsOf: URL(fileURLWithPath: path.asString)).write(into: outputStream)
|
||||
}
|
||||
outputStream.close()
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate extension Data {
|
||||
func write(into: OutputStream) {
|
||||
_ = withUnsafeBytes {
|
||||
into.write($0, maxLength: self.count)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import Foundation
|
||||
import XCTest
|
||||
|
||||
@testable import TuistCore
|
||||
@testable import TuistCoreTesting
|
||||
|
||||
final class DeprecatorTests: XCTestCase {
|
||||
var printer: MockPrinter!
|
||||
var subject: Deprecator!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
printer = MockPrinter()
|
||||
subject = Deprecator(printer: printer)
|
||||
}
|
||||
|
||||
func test_notify() {
|
||||
subject.notify(deprecation: "foo", suggestion: "bar")
|
||||
XCTAssertEqual(printer.printDeprecationArgs, ["foo will be deprecated in the next major release. Use bar instead."])
|
||||
}
|
||||
}
|
|
@ -34,12 +34,15 @@ final class ManifestTests: XCTestCase {
|
|||
|
||||
final class GraphManifestLoaderTests: XCTestCase {
|
||||
var fileHandler: MockFileHandler!
|
||||
var deprecator: MockDeprecator!
|
||||
var subject: GraphManifestLoader!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
fileHandler = try! MockFileHandler()
|
||||
subject = GraphManifestLoader(fileHandler: fileHandler)
|
||||
deprecator = MockDeprecator()
|
||||
subject = GraphManifestLoader(fileHandler: fileHandler,
|
||||
deprecator: deprecator)
|
||||
}
|
||||
|
||||
func test_load_when_swift() throws {
|
||||
|
@ -72,6 +75,9 @@ final class GraphManifestLoaderTests: XCTestCase {
|
|||
let got = try subject.load(.project, path: fileHandler.currentPath)
|
||||
|
||||
XCTAssertEqual(try got.get("name") as String, "tuist")
|
||||
XCTAssertEqual(deprecator.notifyArgs.count, 1)
|
||||
XCTAssertEqual(deprecator.notifyArgs.first?.deprecation, "JSON manifests")
|
||||
XCTAssertEqual(deprecator.notifyArgs.first?.suggestion, "Swift manifests")
|
||||
}
|
||||
|
||||
func test_load_when_yaml() throws {
|
||||
|
@ -87,6 +93,9 @@ final class GraphManifestLoaderTests: XCTestCase {
|
|||
let got = try subject.load(.project, path: fileHandler.currentPath)
|
||||
|
||||
XCTAssertEqual(try got.get("name") as String, "tuist")
|
||||
XCTAssertEqual(deprecator.notifyArgs.count, 1)
|
||||
XCTAssertEqual(deprecator.notifyArgs.first?.deprecation, "YAML manifests")
|
||||
XCTAssertEqual(deprecator.notifyArgs.first?.suggestion, "Swift manifests")
|
||||
}
|
||||
|
||||
func test_load_when_yml() throws {
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
import Basic
|
||||
import Foundation
|
||||
@testable import TuistKit
|
||||
import XCTest
|
||||
|
||||
final class FileAggregatorTests: XCTestCase {
|
||||
var subject: FileAggregator!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
subject = FileAggregator()
|
||||
}
|
||||
|
||||
func test_aggregate() throws {
|
||||
let dir = try TemporaryDirectory(removeTreeOnDeinit: true)
|
||||
let aPath = dir.path.appending(component: "a.swift")
|
||||
let bPath = dir.path.appending(component: "b.swift")
|
||||
try "a".write(toFile: aPath.asString,
|
||||
atomically: true,
|
||||
encoding: .utf8)
|
||||
try "b".write(toFile: bPath.asString,
|
||||
atomically: true,
|
||||
encoding: .utf8)
|
||||
let cPath = dir.path.appending(component: "c.swift")
|
||||
try subject.aggregate([aPath, bPath], into: cPath)
|
||||
let content = try String(contentsOf: URL(fileURLWithPath: cPath.asString))
|
||||
XCTAssertEqual(content, "a\nb")
|
||||
}
|
||||
}
|
|
@ -2,31 +2,31 @@ import ProjectDescription
|
|||
|
||||
let project = Project(name: "App",
|
||||
up: [
|
||||
/* Configures the environment for the project */
|
||||
/* .homebrew(packages: ["swiftlint"]) */
|
||||
/* Configures the environment for the project */
|
||||
/* .homebrew(packages: ["swiftlint"]) */
|
||||
],
|
||||
targets: [
|
||||
Target(name: "App",
|
||||
platform: .iOS,
|
||||
product: .app,
|
||||
bundleId: "io.tuist.App",
|
||||
infoPlist: "Info.plist",
|
||||
sources: "Sources/**",
|
||||
dependencies: [
|
||||
/* Target dependencies can be defined here */
|
||||
/* .framework(path: "framework") */
|
||||
],
|
||||
settings: Settings(base: ["CODE_SIGN_IDENTITY": "",
|
||||
"CODE_SIGNING_REQUIRED": "NO"])),
|
||||
Target(name: "AppTests",
|
||||
platform: .iOS,
|
||||
product: .unitTests,
|
||||
bundleId: "io.tuist.AppTests",
|
||||
infoPlist: "Tests.plist",
|
||||
sources: "Tests/**",
|
||||
dependencies: [
|
||||
.target(name: "App")
|
||||
],
|
||||
settings: Settings(base: ["CODE_SIGN_IDENTITY": "",
|
||||
"CODE_SIGNING_REQUIRED": "NO"]))
|
||||
])
|
||||
Target(name: "App",
|
||||
platform: .iOS,
|
||||
product: .app,
|
||||
bundleId: "io.tuist.App",
|
||||
infoPlist: "Info.plist",
|
||||
sources: "Sources/**",
|
||||
dependencies: [
|
||||
/* Target dependencies can be defined here */
|
||||
/* .framework(path: "framework") */
|
||||
],
|
||||
settings: Settings(base: ["CODE_SIGN_IDENTITY": "",
|
||||
"CODE_SIGNING_REQUIRED": "NO"])),
|
||||
Target(name: "AppTests",
|
||||
platform: .iOS,
|
||||
product: .unitTests,
|
||||
bundleId: "io.tuist.AppTests",
|
||||
infoPlist: "Tests.plist",
|
||||
sources: "Tests/**",
|
||||
dependencies: [
|
||||
.target(name: "App"),
|
||||
],
|
||||
settings: Settings(base: ["CODE_SIGN_IDENTITY": "",
|
||||
"CODE_SIGNING_REQUIRED": "NO"])),
|
||||
])
|
||||
|
|
|
@ -2,10 +2,9 @@ import UIKit
|
|||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
|
||||
func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
|
||||
window = UIWindow(frame: UIScreen.main.bounds)
|
||||
let viewController = UIViewController()
|
||||
viewController.view.backgroundColor = .white
|
||||
|
@ -13,5 +12,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||
window?.makeKeyAndVisible()
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,4 @@ import XCTest
|
|||
|
||||
@testable import App
|
||||
|
||||
final class AppTests: XCTestCase {
|
||||
|
||||
}
|
||||
final class AppTests: XCTestCase {}
|
||||
|
|
Loading…
Reference in New Issue