From ab5f5895477a2d98f62781373d51f5f4c3fce310 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Wed, 19 Feb 2025 00:14:00 +0000 Subject: [PATCH] Implemented the Update subcommand (#7) This PR contains the work done to implement the `Update` subcommand that update the package dependencies in a *Hummingbird* project. Reviewed-on: https://repo.rock-n-code.com/rock-n-code/colibri/pulls/7 Co-authored-by: Javier Cicchelli Co-committed-by: Javier Cicchelli --- Executable/Sources/Colibri.swift | 3 +- .../Sources/Commands/OutdatedCommand.swift | 4 +-- .../Sources/Commands/UpdateCommand.swift | 29 +++++++++++++++++++ .../Sources/Options/UpdateOptions.swift | 13 +++++++++ ...ask.swift => UpdateDependenciesTask.swift} | 10 ++++--- ...wift => UpdateDependenciesTaskTests.swift} | 25 +++++++++------- 6 files changed, 67 insertions(+), 17 deletions(-) create mode 100644 Executable/Sources/Commands/UpdateCommand.swift create mode 100644 Executable/Sources/Options/UpdateOptions.swift rename Library/Sources/Public/Tasks/{OutdatedDependenciesTask.swift => UpdateDependenciesTask.swift} (71%) rename Test/Sources/Cases/Public/Tasks/{OutdatedDependenciesTaskTests.swift => UpdateDependenciesTaskTests.swift} (57%) diff --git a/Executable/Sources/Colibri.swift b/Executable/Sources/Colibri.swift index 288e88b..0aee64c 100644 --- a/Executable/Sources/Colibri.swift +++ b/Executable/Sources/Colibri.swift @@ -10,7 +10,8 @@ struct Colibri: AsyncParsableCommand { subcommands: [ Build.self, Create.self, - Outdated.self + Outdated.self, + Update.self ], defaultSubcommand: Create.self ) diff --git a/Executable/Sources/Commands/OutdatedCommand.swift b/Executable/Sources/Commands/OutdatedCommand.swift index 686da2b..2027bb6 100644 --- a/Executable/Sources/Commands/OutdatedCommand.swift +++ b/Executable/Sources/Commands/OutdatedCommand.swift @@ -20,9 +20,9 @@ extension Colibri { mutating func run() async throws { let terminalService = TerminalService() - let outdatedDependencies = OutdatedDependenciesTask(terminalService: terminalService) + let updateDependencies = UpdateDependenciesTask(terminalService: terminalService) - try await outdatedDependencies(at: options.locationURL) + try await updateDependencies(at: options.locationURL, checkOutdated: true) } } diff --git a/Executable/Sources/Commands/UpdateCommand.swift b/Executable/Sources/Commands/UpdateCommand.swift new file mode 100644 index 0000000..eaf869a --- /dev/null +++ b/Executable/Sources/Commands/UpdateCommand.swift @@ -0,0 +1,29 @@ +import ArgumentParser +import ColibriLibrary + +extension Colibri { + struct Update: AsyncParsableCommand { + + // MARK: Properties + + static let configuration = CommandConfiguration( + commandName: "update-dependencies", + abstract: "Update package dependencies in a Hummingbird app", + helpNames: .shortAndLong, + aliases: ["update"] + ) + + @OptionGroup var options: Options + + // MARK: Functions + + mutating func run() async throws { + let terminalService = TerminalService() + + let updateDependencies = UpdateDependenciesTask(terminalService: terminalService) + + try await updateDependencies(at: options.locationURL) + } + + } +} diff --git a/Executable/Sources/Options/UpdateOptions.swift b/Executable/Sources/Options/UpdateOptions.swift new file mode 100644 index 0000000..8dcb812 --- /dev/null +++ b/Executable/Sources/Options/UpdateOptions.swift @@ -0,0 +1,13 @@ +import ArgumentParser +import ColibriLibrary + +extension Colibri.Update { + struct Options: ParsableArguments, Locationable { + + // MARK: Properties + + @Option(name: .shortAndLong) + var location: String? + + } +} diff --git a/Library/Sources/Public/Tasks/OutdatedDependenciesTask.swift b/Library/Sources/Public/Tasks/UpdateDependenciesTask.swift similarity index 71% rename from Library/Sources/Public/Tasks/OutdatedDependenciesTask.swift rename to Library/Sources/Public/Tasks/UpdateDependenciesTask.swift index 38a33de..e404b6b 100644 --- a/Library/Sources/Public/Tasks/OutdatedDependenciesTask.swift +++ b/Library/Sources/Public/Tasks/UpdateDependenciesTask.swift @@ -1,6 +1,6 @@ import Foundation -public struct OutdatedDependenciesTask { +public struct UpdateDependenciesTask { // MARK: Properties @@ -14,7 +14,7 @@ public struct OutdatedDependenciesTask { // MARK: Functions - public func callAsFunction(at location: URL? = nil) async throws (TerminalServiceError) { + public func callAsFunction(at location: URL? = nil, checkOutdated: Bool = false) async throws (TerminalServiceError) { let executableURL = URL(at: "/usr/bin/swift") var arguments: [String] = ["package", "update"] @@ -23,8 +23,10 @@ public struct OutdatedDependenciesTask { arguments.append(contentsOf: ["--package-path", location.pathString]) } - arguments.append("--dry-run") - + if checkOutdated { + arguments.append("--dry-run") + } + try await terminalService.run(executableURL, arguments: arguments) } diff --git a/Test/Sources/Cases/Public/Tasks/OutdatedDependenciesTaskTests.swift b/Test/Sources/Cases/Public/Tasks/UpdateDependenciesTaskTests.swift similarity index 57% rename from Test/Sources/Cases/Public/Tasks/OutdatedDependenciesTaskTests.swift rename to Test/Sources/Cases/Public/Tasks/UpdateDependenciesTaskTests.swift index b79a211..6208277 100644 --- a/Test/Sources/Cases/Public/Tasks/OutdatedDependenciesTaskTests.swift +++ b/Test/Sources/Cases/Public/Tasks/UpdateDependenciesTaskTests.swift @@ -3,23 +3,28 @@ import Testing @testable import ColibriLibrary -struct OutdatedDependenciesTaskTests { +struct UpdateDependenciesTaskTests { - @Test(arguments: [nil, URL.someCurrentFolder]) - func task(at location: URL?) async throws { + @Test(arguments: [nil, URL.someCurrentFolder], [false, true]) + func task(at location: URL?, checkOutdated: Bool) async throws { // GIVEN let terminalService = TerminalServiceSpy() - let task = OutdatedDependenciesTask(terminalService: terminalService) + let task = UpdateDependenciesTask(terminalService: terminalService) // WHEN - try await task(at: location) + try await task(at: location, checkOutdated: checkOutdated) // THEN let executableURL = URL(at: "/usr/bin/swift") - let arguments = if let location { - ["package", "update", "--package-path", location.pathString, "--dry-run"] + + var arguments = if let location { + ["package", "update", "--package-path", location.pathString] } else { - ["package", "update", "--dry-run"] + ["package", "update"] + } + + if checkOutdated { + arguments.append("--dry-run") } #expect(terminalService.actions.count == 1) @@ -30,12 +35,12 @@ struct OutdatedDependenciesTaskTests { func task(at location: URL?, throws error: TerminalServiceError) async throws { // GIVEN let terminalService = TerminalServiceMock(action: .error(error)) - let task = BuildProjectTask(terminalService: terminalService) + let task = UpdateDependenciesTask(terminalService: terminalService) // WHEN // THEN await #expect(throws: error) { - try await task(at: location) + try await task(at: location, checkOutdated: .random()) } }