Skip to content

Commit 0bbf609

Browse files
authored
Add support for verbose flag (#15)
Fixes #14.
1 parent 030b928 commit 0bbf609

8 files changed

Lines changed: 98 additions & 28 deletions

File tree

Sources/Zero/CLI.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public enum Zero {
1616
RunScriptsCommand(),
1717
]
1818
)
19+
cli.globalOptions.append(verboseFlag)
1920
cli.helpMessageGenerator = ZeroHelpMessageGenerator()
2021
return cli
2122
}()
@@ -26,3 +27,15 @@ struct ZeroHelpMessageGenerator: HelpMessageGenerator {
2627
out <<< TTY.errorMessage(message)
2728
}
2829
}
30+
31+
extension Command {
32+
var verbose: Bool {
33+
verboseFlag.value
34+
}
35+
}
36+
37+
private let verboseFlag = Flag(
38+
"-v",
39+
"--verbose",
40+
description: "Enable verbose output for zero and subcommands."
41+
)

Sources/Zero/Commands/ApplyDefaults.swift

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ final class ApplyDefaultsCommand: Command {
99
@Key("-d", "--directory") var configDirectory: Path?
1010

1111
func execute() throws {
12-
let runner = try ZeroRunner(configDirectory: configDirectory, workspace: workspace ?? [])
12+
let runner = try ZeroRunner(
13+
configDirectory: self.configDirectory,
14+
workspace: self.workspace ?? [],
15+
verbose: self.verbose
16+
)
1317
try runner.workspaceDirectories.forEach(runner.applyDefaults)
1418
}
1519
}
@@ -25,8 +29,13 @@ extension ZeroRunner {
2529

2630
// Close any open System Preferences panes, to prevent them from
2731
// overriding settings we’re about to change.
28-
try runTask("osascript", "-e", "quit app \"System Preferences\"")
32+
try Self.runTask("osascript", "-e", "quit app \"System Preferences\"")
2933

30-
try runTask("apply-user-defaults", "./defaults.yaml", at: directory)
34+
let verboseFlags: [String] = self.verbose ? ["--verbose"] : []
35+
try Self.runTask(
36+
"apply-user-defaults",
37+
arguments: ["./defaults.yaml"] + verboseFlags,
38+
at: directory
39+
)
3140
}
3241
}

Sources/Zero/Commands/ApplySymlinks.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ final class ApplySymlinksCommand: Command {
99
@Key("-d", "--directory") var configDirectory: Path?
1010

1111
final func execute() throws {
12-
let runner = try ZeroRunner(configDirectory: configDirectory, workspace: workspace ?? [])
12+
let runner = try ZeroRunner(
13+
configDirectory: self.configDirectory,
14+
workspace: self.workspace ?? [],
15+
verbose: self.verbose
16+
)
1317
try runner.workspaceDirectories.forEach(runner.applySymlinks)
1418
}
1519
}
@@ -25,7 +29,7 @@ extension ZeroRunner {
2529

2630
Term.stdout <<< TTY.progressMessage("Applying symlinks...")
2731
for link in symlinks {
28-
try runTask(
32+
try Self.runTask(
2933
"stow",
3034
link.basename(),
3135
"--target",

Sources/Zero/Commands/Bundle.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ final class BundleCommand: Command {
99
@Key("-d", "--directory") var configDirectory: Path?
1010

1111
func execute() throws {
12-
let runner = try ZeroRunner(configDirectory: configDirectory, workspace: workspace ?? [])
12+
let runner = try ZeroRunner(
13+
configDirectory: self.configDirectory,
14+
workspace: self.workspace ?? [],
15+
verbose: self.verbose
16+
)
1317
try runner.workspaceDirectories.forEach(runner.bundle)
1418
}
1519
}
@@ -20,7 +24,8 @@ extension ZeroRunner {
2024
if !directory.join("Brewfile").exists {
2125
Term.stdout <<< "No Brewfile found."
2226
} else {
23-
try runTask("brew", "bundle", at: directory)
27+
let verboseFlags: [String] = self.verbose ? ["--verbose"] : []
28+
try Self.runTask("brew", arguments: ["bundle"] + verboseFlags, at: directory)
2429
}
2530
}
2631
}

Sources/Zero/Commands/RunScripts.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ final class RunScriptsCommand: Command {
99
@Key("-d", "--directory") var configDirectory: Path?
1010

1111
func execute() throws {
12-
let runner = try ZeroRunner(configDirectory: configDirectory, workspace: workspace ?? [])
12+
let runner = try ZeroRunner(
13+
configDirectory: self.configDirectory,
14+
workspace: self.workspace ?? [],
15+
verbose: self.verbose
16+
)
1317
try runner.workspaceDirectories.forEach { directory in
1418
try runner.runScripts(directory: directory, suffix: .before)
1519
try runner.runScripts(directory: directory, suffix: .after)
@@ -34,7 +38,7 @@ extension ZeroRunner {
3438
}
3539

3640
for script in scripts {
37-
try spawnTask("./\(script.basename())", at: scriptDirectory)
41+
try Self.spawnTask("./\(script.basename())", at: scriptDirectory)
3842
}
3943
}
4044
}

Sources/Zero/Commands/Setup.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,16 @@ final class SetupCommand: Command {
88
@Param var workspace: Workspace?
99
@Key("-d", "--directory") var configDirectory: Path?
1010

11+
@Flag("-v", "--verbose", description: "Enable verbose output for zero and subcommands.")
12+
var verbose: Bool
13+
1114
func execute() throws {
12-
let runner = try ZeroRunner(configDirectory: configDirectory, workspace: workspace ?? [])
13-
try ZeroRunner.update()
15+
let runner = try ZeroRunner(
16+
configDirectory: self.configDirectory,
17+
workspace: self.workspace ?? [],
18+
verbose: self.verbose
19+
)
20+
try ZeroRunner.update(verbose: self.verbose)
1421
try runner.workspaceDirectories.forEach(runner.setup)
1522
}
1623
}

Sources/Zero/Commands/Update.swift

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,29 @@ final class UpdateCommand: Command {
66
let shortDescription: String = "Check for system and application updates"
77

88
func execute() throws {
9-
try ZeroRunner.update()
9+
try ZeroRunner.update(verbose: self.verbose)
1010
}
1111
}
1212

1313
extension ZeroRunner {
1414
/// Check and apply all system and application updates via
1515
/// `softwareupdate`, `brew` and `mas`.
16-
static func update() throws {
17-
try systemUpdate()
18-
try brewUpdate()
16+
static func update(verbose: Bool) throws {
17+
try systemUpdate(verbose: verbose)
18+
try brewUpdate(verbose: verbose)
1919
try appStoreUpdate()
2020
}
2121
}
2222

2323
private extension ZeroRunner {
2424
/// Check and apply system updates via `softwareupdate` CLI.
25-
static func systemUpdate() throws {
25+
static func systemUpdate(verbose: Bool) throws {
2626
Term.stdout <<< TTY.progressMessage("Checking for system updates...")
2727

28+
let verboseFlags: [String] = verbose ? ["--verbose"] : []
2829
let result = try Task.capture(
2930
"/usr/sbin/softwareupdate",
30-
arguments: ["--list"],
31+
arguments: ["--list"] + verboseFlags,
3132
tee: Term.stdout,
3233

3334
// `NSUnbufferedIO` forces output of `softwareupdate` to be
@@ -54,7 +55,7 @@ private extension ZeroRunner {
5455
"--install",
5556
"--all",
5657
"--restart",
57-
])
58+
] + verboseFlags)
5859
guard exitStatus == 0 else {
5960
throw SpawnError(exitStatus: exitStatus)
6061
}
@@ -66,10 +67,11 @@ private extension ZeroRunner {
6667
}
6768

6869
/// Check and apply brew and brew cask updates.
69-
static func brewUpdate() throws {
70-
try Task.run("brew", "update")
71-
try Task.run("brew", "upgrade")
72-
try Task.run("brew", "cask", "upgrade")
70+
static func brewUpdate(verbose: Bool) throws {
71+
let verboseFlags: [String] = verbose ? ["--verbose"] : []
72+
try Task.run("brew", arguments: ["update"] + verboseFlags)
73+
try Task.run("brew", arguments: ["upgrade"] + verboseFlags)
74+
try Task.run("brew", arguments: ["cask", "upgrade"] + verboseFlags)
7375
}
7476

7577
/// Check and apply app store updates.

Sources/Zero/Runner.swift

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,22 +32,28 @@ enum ZeroValidationError: LocalizedError {
3232
struct ZeroRunner {
3333
let configDirectory: Path
3434
let workspace: Workspace
35+
let verbose: Bool
3536

36-
init(configDirectory: Path? = nil, workspace: Workspace) throws {
37+
init(configDirectory: Path? = nil, workspace: Workspace, verbose: Bool) throws {
3738
let fallbackDirectories: [Path] = [
3839
Path.XDG.configHome.join("zero").join("dotfiles"),
3940
Path.home.join(".dotfiles"),
4041
]
4142
self.configDirectory = configDirectory ?? fallbackDirectories.first { $0.isDirectory } ??
4243
fallbackDirectories.last!
44+
self.verbose = verbose
4345
self.workspace = workspace
4446
try validate()
4547
}
4648

4749
/// Run an executable with the given arguments, printing the command before
4850
/// running.
49-
func runTask(_ executable: String, _ arguments: String..., at directory: Path? = nil) throws {
50-
printCommand(executable, arguments)
51+
static func runTask(
52+
_ executable: String,
53+
arguments: [String],
54+
at directory: Path? = nil
55+
) throws {
56+
self.printCommand(executable, arguments)
5157

5258
if let directory = directory, executable.hasPrefix(".") {
5359
// Process.launchPath doesn't seem to honor currentDirectoryPath
@@ -64,8 +70,12 @@ struct ZeroRunner {
6470

6571
/// Run an executable using `Task.spawn` with the given arguments, printing
6672
/// the command before running.
67-
func spawnTask(_ executable: String, _ arguments: String..., at directory: Path? = nil) throws {
68-
printCommand(executable, arguments)
73+
static func spawnTask(
74+
_ executable: String,
75+
arguments: [String],
76+
at directory: Path? = nil
77+
) throws {
78+
self.printCommand(executable, arguments)
6979

7080
let fileManager = FileManager.default
7181
let previousWorkingDirectory = fileManager.currentDirectoryPath
@@ -86,6 +96,22 @@ struct ZeroRunner {
8696
throw SpawnError(exitStatus: exitStatus)
8797
}
8898
}
99+
100+
static func runTask(
101+
_ executable: String,
102+
_ arguments: String...,
103+
at directory: Path? = nil
104+
) throws {
105+
try self.runTask(executable, arguments: arguments, at: directory)
106+
}
107+
108+
static func spawnTask(
109+
_ executable: String,
110+
_ arguments: String...,
111+
at directory: Path? = nil
112+
) throws {
113+
try self.spawnTask(executable, arguments: arguments, at: directory)
114+
}
89115
}
90116

91117
private extension ZeroRunner {
@@ -117,7 +143,7 @@ private extension ZeroRunner {
117143
}
118144
}
119145

120-
func printCommand(_ executable: String, _ arguments: [String]) {
146+
static func printCommand(_ executable: String, _ arguments: [String]) {
121147
let escapedCommand: [String] = [executable] + arguments.map(Task.escapeArgument)
122148
Term.stdout <<< TTY.commandMessage(escapedCommand.joined(separator: " "))
123149
}

0 commit comments

Comments
 (0)