@@ -6,6 +6,9 @@ import std.process : ProcessPipes, Redirect, wait, environment;
66import std.range : drop, front;
77import std.stdio : writeln;
88import std.string : indexOf;
9+ import std.sumtype : SumType, match;
10+
11+ import argparse;
912
1013import mcl.utils.env : optional, parseEnv;
1114import mcl.utils.fetch : fetchJson;
@@ -14,112 +17,166 @@ import mcl.utils.nix : nix, queryStorePath;
1417import mcl.utils.process : execute;
1518import mcl.utils.string : camelCaseToCapitalCase;
1619
17- export void config (string [] args) {
18- if (args.length == 0 ) {
19- errorAndExit(" Usage: mcl config <subcommand> [args]" );
20- }
21- if (! checkRepo()) {
22- errorAndExit(" This command must be run from a repository containing a NixOS machine configuration" );
23- }
20+ @(Command(" config" ).Description(" Manage NixOS machine configurations" ))
21+ export struct config_args
22+ {
23+ @SubCommands SumType! (
24+ sys_args,
25+ home_args,
26+ start_vm_args,
27+ Default! unknown_command_args
28+ ) cmd;
29+ }
30+
31+ @(Command(" sys" ).Description(" Manage system configurations" ))
32+ struct sys_args
33+ {
34+ @SubCommands SumType! (
35+ sys_apply_args,
36+ sys_edit_args,
37+ Default! unknown_command_args
38+ ) cmd;
39+ }
40+
41+ @(Command(" apply" ).Description(" Apply system configuration" ))
42+ struct sys_apply_args
43+ {
44+ @(PositionalArgument(0 ).Placeholder(" machine-name" ).Description(" Name of the machine" ))
45+ string machineName;
46+ }
47+
48+ @(Command(" edit" ).Description(" Edit system configuration" ))
49+ struct sys_edit_args
50+ {
51+ @(PositionalArgument(0 ).Placeholder(" machine-name" ).Description(" Name of the machine" ))
52+ string machineName;
53+ }
54+
55+ @(Command(" home" ).Description(" Manage home configurations" ))
56+ struct home_args
57+ {
58+ @SubCommands SumType! (
59+ home_apply_args,
60+ home_edit_args,
61+ Default! unknown_command_args
62+ ) cmd;
63+ }
64+
65+ @(Command(" apply" ).Description(" Apply user configuration" ))
66+ struct home_apply_args
67+ {
68+ @(PositionalArgument(0 ).Placeholder(" desktop/server" ).Description(" Type of home configuration" ))
69+ string type;
70+ }
71+
72+ @(Command(" edit" ).Description(" Edit user configuration" ))
73+ struct home_edit_args
74+ {
75+ @(PositionalArgument(0 ).Placeholder(" desktop/server" ).Description(" Type of home configuration" ))
76+ string type;
77+ }
78+
79+ @(Command(" start-vm" ).Description(" Start a VM" ))
80+ struct start_vm_args
81+ {
82+ @(PositionalArgument(0 ).Optional().Placeholder(" vm-name" ).Description(" Name of the VM" ))
83+ string vmName = " " ;
84+ }
85+
86+ @(Command(" " ).Description(" " ))
87+ struct unknown_command_args
88+ {
89+ }
90+
91+ int unknown_command (unknown_command_args unused)
92+ {
93+ errorAndExit(" Unknown command. Use --help for a list of available commands." );
94+ return 1 ;
95+ }
2496
25- string subcommand = args.front;
26-
27- switch (subcommand) {
28- case " sys" :
29- sys(args.drop(1 ));
30- break ;
31- case " home" :
32- home(args.drop(1 ));
33- break ;
34- case " start-vm" :
35- startVM(args.drop(1 ));
36- break ;
37- default :
38- errorAndExit(" Unknown config subcommand " ~ subcommand ~ " . Supported subcommands: sys, home, start-vm" );
39- break ;
97+ export int config (config_args args)
98+ {
99+ if (! checkRepo())
100+ {
101+ errorAndExit(
102+ " This command must be run from a repository containing a NixOS machine configuration" );
40103 }
104+
105+ return args.cmd.match! (
106+ (sys_args a) => sys(a),
107+ (home_args a) => home(a),
108+ (start_vm_args a) => startVM(a.vmName),
109+ (unknown_command_args a) => unknown_command(a)
110+ );
41111}
42112
43113bool checkRepo ()
44114{
45115 const string [] validRepos = [" nixos-machine-config" , " infra-lido" ];
46- string remoteOriginUrl = execute([" git" , " config" , " --get" , " remote.origin.url" ], false );
116+ string remoteOriginUrl = execute([
117+ " git" , " config" , " --get" , " remote.origin.url"
118+ ], false );
47119
48- foreach (string repo; validRepos) {
49- if (remoteOriginUrl.indexOf(repo) != - 1 ) {
120+ foreach (string repo; validRepos)
121+ {
122+ if (remoteOriginUrl.indexOf(repo) != - 1 )
123+ {
50124 return true ;
51125 }
52126 }
53127 return false ;
54128}
55129
56- void executeCommand (string command) {
130+ int executeCommand (string command)
131+ {
57132 auto exec = execute! ProcessPipes(command, true , false , Redirect.stderrToStdout);
58- wait(exec.pid);
133+ return wait (exec.pid);
59134}
60135
61- void edit (string type, string path) {
136+ int edit (string type, string path)
137+ {
62138 string editor = environment.get (" EDITOR" , " vim" );
63139 string user = environment.get (" USER" , " root" );
64140 writeln(" Editing " ~ path ~ " configuration from: " , path);
65- final switch (type) {
66- case " system" :
67- executeCommand(editor ~ " machines/*/" ~ path ~ " /*.nix" );
68- break ;
69- case " user" :
70- executeCommand(editor~ " users/" ~ user ~ " /gitconfig " ~ " users/" ~ user ~ " /*.nix " ~ " users/" ~ user ~ " /home-" ~ path~ " /*.nix" );
71- break ;
141+ final switch (type)
142+ {
143+ case " system" :
144+ return executeCommand (editor ~ " machines/*/" ~ path ~ " /*.nix" );
145+ case " user" :
146+ return executeCommand (editor ~ " users/" ~ user ~ " /gitconfig " ~ " users/" ~ user ~ " /*.nix " ~ " users/" ~ user ~ " /home-" ~ path ~ " /*.nix" );
72147 }
73148}
74149
75- void sys (string [] args )
150+ int apply (string type, string value )
76151{
77- if ((args.length < 1 || args.length > 2 ) && ! [" apply" , " edit" ].canFind(args.front))
78- {
79- errorAndExit(" Usage: mcl config sys apply or mcl config sys apply <machine-name>\n " ~
80- " mcl config sys edit or mcl config sys edit <machine-name>" );
81- }
152+ writeln(" Applying " , type, " configuration from: " , value);
153+ return executeCommand (" just switch-" ~ type ~ " " ~ value);
154+ }
82155
83- string machineName = args.length > 1 ? args[1 ] : " " ;
84- final switch (args.front) {
85- case " apply" :
86- writeln(" Applying system configuration from: " , machineName);
87- executeCommand(" just switch-system " ~ machineName);
88- break ;
89- case " edit" :
90- edit(" system" , machineName);
91- break ;
92- }
156+ int sys (sys_args args)
157+ {
158+ return args.cmd.match! (
159+ (sys_apply_args a) => apply(" system" , a.machineName),
160+ (sys_edit_args a) => edit(" system" , a.machineName),
161+ (unknown_command_args a) => unknown_command(a)
162+ );
93163}
94164
95- void home (string [] args)
165+ int home (home_args args)
96166{
97- if ((args.length != 2 ) && args.front != " apply" )
98- {
99- errorAndExit(" Usage: mcl config home apply <desktop/server>\n " ~
100- " mcl config home edit <desktop/server>" );
101- }
102167
103- auto type = args[1 ];
104- final switch (args.front) {
105- case " apply" :
106- writeln(" Applying home configuration from: " , type);
107- executeCommand(" just switch-home " ~ type);
108- break ;
109- case " edit" :
110- edit(" user" , type);
111- break ;
112- }
168+ return args.cmd.match! (
169+ (home_apply_args a) {
170+ writeln(" Applying home configuration from: " , a.type);
171+ return executeCommand (" just switch-home " ~ a.type);
172+ },
173+ (home_edit_args a) => " user" .edit(a.type),
174+ (unknown_command_args a) => unknown_command(a)
175+ );
113176}
114177
115- void startVM (string [] args )
178+ int startVM (string vmName )
116179{
117- if (args.length != 1 )
118- {
119- errorAndExit(" Usage: mcl config start-vm <vm-name>" );
120- }
121-
122- string vmName = args.front;
123180 writeln(" Starting VM: " , vmName);
124- executeCommand(" just start-vm " ~ vmName);
181+ return executeCommand (" just start-vm " ~ vmName);
125182}
0 commit comments