Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
050a076
refactor(picker): migrate from SwiftPicker to SwiftPickerKit package
nikolainobadi Nov 20, 2025
61fe0a5
refactor(core): replace existential types with `any` keyword for prot…
nikolainobadi Nov 20, 2025
29014d8
refactor(core): replace SwiftPicker with SwiftPickerKit package
nikolainobadi Nov 20, 2025
782ec35
minor reformatting
nikolainobadi Nov 20, 2025
ab845c6
update ReleaseVersionHandlerIntegrationTests to use MockSwiftPicker
nikolainobadi Nov 20, 2025
1ade521
update ReleaseVersionHandlerTests to use MockSwiftPicker
nikolainobadi Nov 20, 2025
709fce2
updated ReleaseNotesHandlerTests to use MockSwiftPicker
nikolainobadi Nov 20, 2025
9d9ab17
update BuildExecutionManagerTests to use MockSwiftPicker
nikolainobadi Nov 20, 2025
23f2404
update ReleaseNotesFileUtilityTests to work with MockSwiftPicker
nikolainobadi Nov 20, 2025
9f78fab
replace MockPicker with SwiftPicker in MockContext and fix CreateTapT…
nikolainobadi Nov 20, 2025
02f454e
update tests to use MockSwiftPicker
nikolainobadi Nov 20, 2025
6e2b5ec
remove old MockPicker
nikolainobadi Nov 20, 2025
71ae1b7
Add browseFolders method to NnexPicker protocol -> still need to impl…
nikolainobadi Nov 20, 2025
aeb742b
add folder browsing to ImportTap
nikolainobadi Nov 20, 2025
17985db
add folder browsing to CreateTap
nikolainobadi Nov 20, 2025
36848ef
refactor NnexPicker to use FileSystemNode when browsing
nikolainobadi Nov 20, 2025
4ab9253
add file selection for release notes
nikolainobadi Nov 20, 2025
1c51abb
updated to latest swift packages
nikolainobadi Nov 20, 2025
65c5b66
fix references to singleSelection based on SwiftPickerKit changes
nikolainobadi Nov 20, 2025
71f7c7a
update readme
nikolainobadi Nov 20, 2025
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
14 changes: 7 additions & 7 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ let package = Package(
.package(url: "https://github.com/nikolainobadi/NnGitKit.git", from: "0.6.0"),
.package(url: "https://github.com/nikolainobadi/NnShellKit.git", from: "2.0.0"),
.package(url: "https://github.com/nikolainobadi/NnSwiftDataKit", from: "0.5.0"),
.package(url: "https://github.com/nikolainobadi/SwiftPicker.git", from: "1.0.0"),
.package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.5.0"),
.package(url: "https://github.com/nikolainobadi/SwiftPickerKit.git", from: "0.5.0")
],
targets: [
.executableTarget(
name: "nnex",
dependencies: [
"NnexKit",
"SwiftPicker",
.product(name: "SwiftPickerKit", package: "SwiftPickerKit"),
.product(name: "ArgumentParser", package: "swift-argument-parser")
],
linkerSettings: [
Expand Down Expand Up @@ -66,7 +66,8 @@ let package = Package(
name: "nnexTests",
dependencies: [
"nnex",
"NnexSharedTestHelpers"
"NnexSharedTestHelpers",
.product(name: "SwiftPickerTesting", package: "SwiftPickerKit")
]
),
.testTarget(
Expand Down
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,11 @@ brew install nikolainobadi/tap/nnex
```

## Commands
**nnex** utilizes four subcommands: `Brew`, `Build`, `Config`, and `Archive`.
**nnex** utilizes four subcommands: `Brew`, `Build`, and `Config`.

- **Brew commands** are used to interact with Homebrew and GitHub
- **Build commands** handle local binary building
- **Config commands** are used to set preferences
- **Archive commands** provide archiving and packaging functionality

The tool follows a clean architecture with separation of concerns between command parsing, business logic, and infrastructure.

Expand Down Expand Up @@ -120,7 +119,7 @@ Issues and suggestions are also welcome via [GitHub Issues](https://github.com/n
### Third-Party Libraries

#### My Libraries
- [SwiftPicker](https://github.com/nikolainobadi/SwiftPicker) - Interactive command-line selection interfaces
- [SwiftPickerKit](https://github.com/nikolainobadi/SwiftPickerKit) - Interactive command-line selection interfaces
- [NnGitKit](https://github.com/nikolainobadi/NnGitKit) - Git operations wrapper (GitShellKit)
- [NnShellKit](https://github.com/nikolainobadi/NnShellKit) - Shell command execution utilities
- [NnSwiftDataKit](https://github.com/nikolainobadi/NnSwiftDataKit) - SwiftData utilities and extensions
Expand Down
4 changes: 2 additions & 2 deletions Sources/NnexKit/Building/ProjectBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import Foundation
public struct ProjectBuilder {
private let shell: any Shell
private let config: BuildConfig
private let progressDelegate: BuildProgressDelegate?
private let progressDelegate: (any BuildProgressDelegate)?

public init(shell: any Shell, config: BuildConfig, progressDelegate: BuildProgressDelegate? = nil) {
public init(shell: any Shell, config: BuildConfig, progressDelegate: (any BuildProgressDelegate)? = nil) {
self.shell = shell
self.config = config
self.progressDelegate = progressDelegate
Expand Down
4 changes: 2 additions & 2 deletions Sources/NnexKit/Formula/FormulaPublisher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import Files

/// Handles publishing Homebrew formulas to a specified tap.
public struct FormulaPublisher {
private let gitHandler: GitHandler
private let gitHandler: any GitHandler

/// Initializes a new instance of FormulaPublisher.
/// - Parameter gitHandler: The Git handler used to commit and push formula files.
public init(gitHandler: GitHandler) {
public init(gitHandler: any GitHandler) {
self.gitHandler = gitHandler
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/NnexKit/Git/DefaultGitHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import NnShellKit
/// Default implementation of the GitHandler protocol, providing Git-related operations.
public struct DefaultGitHandler {
private let shell: any Shell
private let gitShell: GitShell
private let gitShell: any GitShell

/// Initializes a new instance of DefaultGitHandler with the specified shell.
/// - Parameter shell: The shell used to execute commands.
Expand Down
4 changes: 2 additions & 2 deletions Sources/NnexKit/Releasing/ReleaseStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

/// Manages the process of uploading a release to a remote repository.
public struct ReleaseStore {
private let gitHandler: GitHandler
private let gitHandler: any GitHandler

/// Initializes a new instance of ReleaseStore with a Git handler.
/// - Parameter gitHandler: The Git handler used for managing releases.
public init(gitHandler: GitHandler) {
public init(gitHandler: any GitHandler) {
self.gitHandler = gitHandler
}
}
Expand Down
1 change: 1 addition & 0 deletions Sources/NnexKit/Shared/NnexError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ public enum NnexError: Error {
case noPreviousVersionToIncrement

case missingExecutable
case selectionRequired
}
4 changes: 2 additions & 2 deletions Sources/nnex/Commands/Archive/ArchiveMacOS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

import Files
import NnexKit
import Foundation
import NnShellKit
import SwiftPickerKit
import ArgumentParser
import Foundation
import SwiftPicker

extension Nnex.Archive {
struct MacOS: ParsableCommand {
Expand Down
11 changes: 9 additions & 2 deletions Sources/nnex/Commands/Brew/ImportTap.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ extension Nnex.Brew {
var path: String?

func run() throws {
let picker = Nnex.makePicker()
let context = try Nnex.makeContext()
let path = try path ?? Nnex.makePicker().getRequiredInput(prompt: "Enter the local path to your Homebrew tap folder.")
let folder = try Folder(path: path)
let folder = try selectHomebrewFolder(path: path, picker: picker)
let tapName = folder.name.removingHomebrewPrefix
let remotePath = try Nnex.makeGitHandler().getRemoteURL(path: folder.path)

Expand Down Expand Up @@ -53,6 +53,13 @@ extension Nnex.Brew {

// MARK: - Private Methods
private extension Nnex.Brew.ImportTap {
func selectHomebrewFolder(path: String?, picker: any NnexPicker) throws -> Folder {
if let path {
return try Folder(path: path)
}

return try picker.requiredFolderSelection(prompt: "Select the Homebrew Tap folder you would like to import.")
}
/// Decodes a Homebrew formula from a file.
/// - Parameter file: The file containing the formula.
/// - Returns: A BrewFormula instance if decoding is successful, or nil otherwise.
Expand Down
6 changes: 3 additions & 3 deletions Sources/nnex/Commands/Export/ExportMacOS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
import Files
import NnexKit
import NnShellKit
import ArgumentParser
import Foundation
import SwiftPicker
import ArgumentParser
import SwiftPickerKit

extension Nnex.Export {
struct MacOS: ParsableCommand {
Expand Down Expand Up @@ -194,4 +194,4 @@ private extension Nnex.Export.MacOS {
let desktopPath = NSString(string: "~/Desktop").expandingTildeInPath
return "\(desktopPath)/\(appName)_\(readableDate).app"
}
}
}
7 changes: 3 additions & 4 deletions Sources/nnex/Commands/Export/NotarizeHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import Files
import NnexKit
import NnShellKit
import Foundation
import SwiftPicker

protocol NotarizeHandler {
func isArchiveNotarized(_ archivePath: String) throws -> Bool
Expand All @@ -18,9 +17,9 @@ protocol NotarizeHandler {

struct DefaultNotarizeHandler: NotarizeHandler {
private let shell: any Shell
private let picker: NnexPicker
private let picker: any NnexPicker

init(shell: any Shell, picker: NnexPicker) {
init(shell: any Shell, picker: any NnexPicker) {
self.shell = shell
self.picker = picker
}
Expand Down Expand Up @@ -252,4 +251,4 @@ private extension DefaultNotarizeHandler {
return "Notarization failed: \(errorMessage)"
}
}
}
}
14 changes: 7 additions & 7 deletions Sources/nnex/Core/Context/ContextFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ protocol ContextFactory {

/// Creates a new picker instance.
/// - Returns: A NnexPicker instance.
func makePicker() -> NnexPicker
func makePicker() -> any NnexPicker

/// Creates a new Git handler instance.
/// - Returns: A GitHandler instance.
func makeGitHandler() -> GitHandler
func makeGitHandler() -> any GitHandler

/// Creates a new Nnex context.
/// - Returns: An NnexContext instance.
Expand All @@ -29,21 +29,21 @@ protocol ContextFactory {

/// Creates a new project detector instance.
/// - Returns: A ProjectDetector instance.
func makeProjectDetector() -> ProjectDetector
func makeProjectDetector() -> any ProjectDetector

/// Creates a new macOS archive builder instance.
/// - Returns: An ArchiveBuilder instance.
func makeMacOSArchiveBuilder() -> ArchiveBuilder
func makeMacOSArchiveBuilder() -> any ArchiveBuilder

/// Creates a new notarize handler instance.
/// - Returns: A NotarizeHandler instance.
func makeNotarizeHandler() -> NotarizeHandler
func makeNotarizeHandler() -> any NotarizeHandler

/// Creates a new export handler instance.
/// - Returns: An ExportHandler instance.
func makeExportHandler() -> ExportHandler
func makeExportHandler() -> any ExportHandler

/// Creates a new trash handler instance.
/// - Returns: A TrashHandler instance.
func makeTrashHandler() -> TrashHandler
func makeTrashHandler() -> any TrashHandler
}
10 changes: 5 additions & 5 deletions Sources/nnex/Core/Context/DefaultContextFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,31 +40,31 @@ struct DefaultContextFactory: ContextFactory {

/// Creates a default project detector instance.
/// - Returns: A DefaultProjectDetector instance.
func makeProjectDetector() -> ProjectDetector {
func makeProjectDetector() -> any ProjectDetector {
return DefaultProjectDetector(shell: makeShell())
}

/// Creates a default macOS archive builder instance.
/// - Returns: A DefaultMacOSArchiveBuilder instance.
func makeMacOSArchiveBuilder() -> ArchiveBuilder {
func makeMacOSArchiveBuilder() -> any ArchiveBuilder {
return DefaultMacOSArchiveBuilder(shell: makeShell())
}

/// Creates a default notarize handler instance.
/// - Returns: A DefaultNotarizeHandler instance.
func makeNotarizeHandler() -> NotarizeHandler {
func makeNotarizeHandler() -> any NotarizeHandler {
return DefaultNotarizeHandler(shell: makeShell(), picker: makePicker())
}

/// Creates a default export handler instance.
/// - Returns: A DefaultExportHandler instance.
func makeExportHandler() -> ExportHandler {
func makeExportHandler() -> any ExportHandler {
return DefaultExportHandler(shell: makeShell())
}

/// Creates a default trash handler instance.
/// - Returns: A DefaultTrashHandler instance.
func makeTrashHandler() -> TrashHandler {
func makeTrashHandler() -> any TrashHandler {
return DefaultTrashHandler()
}
}
22 changes: 0 additions & 22 deletions Sources/nnex/Core/Extensions/BuildOutputLocation+Extensions.swift

This file was deleted.

4 changes: 2 additions & 2 deletions Sources/nnex/Domain/Execution/BuildExecutionManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import Foundation

struct BuildExecutionManager {
private let shell: any Shell
private let picker: NnexPicker
private let picker: any NnexPicker
private let copyUtility: BinaryCopyUtility

init(shell: any Shell, picker: NnexPicker) {
init(shell: any Shell, picker: any NnexPicker) {
self.shell = shell
self.picker = picker
self.copyUtility = BinaryCopyUtility(shell: shell)
Expand Down
11 changes: 6 additions & 5 deletions Sources/nnex/Domain/Execution/CreateTapManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ import Foundation

struct CreateTapManager {
private let shell: any Shell
private let picker: NnexPicker
private let gitHandler: GitHandler
private let picker: any NnexPicker
private let gitHandler: any GitHandler
private let context: NnexContext

init(shell: any Shell, picker: NnexPicker, gitHandler: GitHandler, context: NnexContext) {
init(shell: any Shell, picker: any NnexPicker, gitHandler: any GitHandler, context: NnexContext) {
self.shell = shell
self.picker = picker
self.gitHandler = gitHandler
Expand Down Expand Up @@ -113,8 +113,7 @@ private extension CreateTapManager {

var tapListFolder: Folder
if selection == addNewPath {
let newPath = try picker.getRequiredInput(prompt: "Enter the path where your Homebrew Taps should be created.")
tapListFolder = try Folder(path: newPath)
tapListFolder = try picker.requiredFolderSelection(prompt: "Select the folder where your Homebrew Taps should be created")
} else {
tapListFolder = try homeFolder.createSubfolder(named: defaultTapFolderName)
}
Expand All @@ -126,3 +125,5 @@ private extension CreateTapManager {
return tapListFolder
}
}


8 changes: 4 additions & 4 deletions Sources/nnex/Domain/Execution/PublishExecutionManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ import Foundation

struct PublishExecutionManager {
private let shell: any Shell
private let picker: NnexPicker
private let gitHandler: GitHandler
private let picker: any NnexPicker
private let gitHandler: any GitHandler
private let publishInfoLoader: PublishInfoLoader
private let trashHandler: TrashHandler
private let trashHandler: any TrashHandler

init(shell: any Shell, picker: NnexPicker, gitHandler: GitHandler, publishInfoLoader: PublishInfoLoader, trashHandler: TrashHandler) {
init(shell: any Shell, picker: any NnexPicker, gitHandler: any GitHandler, publishInfoLoader: PublishInfoLoader, trashHandler: any TrashHandler) {
self.shell = shell
self.picker = picker
self.gitHandler = gitHandler
Expand Down
Loading