Compare commits

...

2 Commits

Author SHA1 Message Date
Jef Roosens e9d7858380
env module now properly supports config file 2022-04-06 17:51:06 +02:00
Jef Roosens 21ef262ede
Migrated rest of cli commands 2022-04-06 17:16:27 +02:00
5 changed files with 87 additions and 113 deletions

84
cli.v
View File

@ -1,84 +0,0 @@
import os
import toml
import net.http
struct Config {
address string [required]
api_key string [required]
}
fn list(conf Config) ? {
mut req := http.new_request(http.Method.get, '$conf.address/api/repos', '') ?
req.add_custom_header('X-API-Key', conf.api_key) ?
res := req.do() ?
println(res.text)
}
fn add(conf Config, args []string) ? {
if args.len < 2 {
eprintln('Not enough arguments.')
exit(1)
}
if args.len > 2 {
eprintln('Too many arguments.')
exit(1)
}
mut req := http.new_request(http.Method.post, '$conf.address/api/repos?url=${args[0]}&branch=${args[1]}', '') ?
req.add_custom_header('X-API-Key', conf.api_key) ?
res := req.do() ?
println(res.text)
}
fn remove(conf Config, args []string) ? {
if args.len < 2 {
eprintln('Not enough arguments.')
exit(1)
}
if args.len > 2 {
eprintln('Too many arguments.')
exit(1)
}
mut req := http.new_request(http.Method.delete, '$conf.address/api/repos?url=${args[0]}&branch=${args[1]}', '') ?
req.add_custom_header('X-API-Key', conf.api_key) ?
res := req.do() ?
println(res.text)
}
fn main() {
conf_path := os.expand_tilde_to_home('~/.vieterrc')
if !os.is_file(conf_path) {
exit(1)
}
conf := toml.parse_file(conf_path) ?.reflect<Config>()
args := os.args[1..]
if args.len == 0 {
eprintln('No action provided.')
exit(1)
}
action := args[0]
match action {
'list' { list(conf) ? }
'add' { add(conf, args[1..]) ? }
'remove' { remove(conf, args[1..]) ? }
else {
eprintln("Invalid action '$action'.")
exit(1)
}
}
}

View File

@ -8,7 +8,8 @@ pub fn cmd() cli.Command {
name: 'build'
description: 'Run the build process.'
execute: fn (cmd cli.Command) ? {
conf := env.load<env.BuildConfig>() ?
config_file := cmd.flags.get_string('config-file') ?
conf := env.load<env.BuildConfig>(config_file) ?
build(conf) ?
}

View File

@ -1,6 +1,7 @@
module env
import os
import toml
// The prefix that every environment variable should have
const prefix = 'VIETER_'
@ -32,9 +33,9 @@ fn get_env_var(field_name string) ?string {
env_var := os.getenv(env_var_name)
env_file := os.getenv(env_file_name)
// If both aren't set, we report them missing
// If both are missing, we return an empty string
if env_var == '' && env_file == '' {
return error('Either $env_var_name or $env_file_name is required.')
return ''
}
// If they're both set, we report a conflict
@ -56,37 +57,47 @@ fn get_env_var(field_name string) ?string {
}
}
fn load_in_place<T>(mut o T) ? {
$for field in T.fields {
o.$(field.name) = get_env_var(field.name) or {
// We use the default instead, if it's present
mut default := ''
for attr in field.attrs {
if attr.starts_with('default: ') {
default = attr[9..]
break
}
}
if default == '' {
return err
}
default
}
}
}
// load<T> attempts to create the given type from environment variables. For
// each field, the corresponding env var is its name in uppercase prepended
// with the hardcoded prefix. If this one isn't present, it looks for the env
// var with the file_suffix suffix.
pub fn load<T>() ?T {
pub fn load<T>(path string) ?T {
mut res := T{}
load_in_place<T>(mut res) ?
if os.exists(path) {
res = toml.parse_file(path) ?.reflect<T>()
}
$for field in T.fields {
$if field.typ is string {
env_value := get_env_var(field.name) ?
// The value of the env var will always be chosen over the config
// file
if env_value != '' {
res.$(field.name) = env_value
}
// If there's no value from the toml file either, we try to find a
// default value
else if res.$(field.name) == '' {
// We use the default instead, if it's present
mut default := ''
for attr in field.attrs {
if attr.starts_with('default: ') {
default = attr[9..]
break
}
}
if default == '' {
return error("Missing config variable '$field.name' with no provided default. Either add it to the config file or provide it using an environment variable.")
}
res.$(field.name) = default
}
}
}
return res
}

View File

@ -18,11 +18,36 @@ pub fn cmd() cli.Command {
name: 'list'
description: 'List the current repos.'
execute: fn (cmd cli.Command) ? {
conf := env.load<Config>() ?
config_file := cmd.flags.get_string('config-file') ?
conf := env.load<Config>(config_file) ?
list(conf) ?
}
},
cli.Command{
name: 'add'
required_args: 2
usage: 'url branch'
description: 'Add a new repository.'
execute: fn (cmd cli.Command) ? {
config_file := cmd.flags.get_string('config-file') ?
conf := env.load<Config>(config_file) ?
add(conf, cmd.args[0], cmd.args[1]) ?
}
},
cli.Command{
name: 'remove'
required_args: 2
usage: 'url branch'
description: 'Remove a repository.'
execute: fn (cmd cli.Command) ? {
config_file := cmd.flags.get_string('config-file') ?
conf := env.load<Config>(config_file) ?
remove(conf, cmd.args[0], cmd.args[1]) ?
}
},
]
}
}
@ -35,3 +60,23 @@ fn list(conf Config) ? {
println(res.text)
}
fn add(conf Config, url string, branch string) ? {
mut req := http.new_request(http.Method.post, '$conf.address/api/repos?url=$url&branch=$branch',
'') ?
req.add_custom_header('X-API-Key', conf.api_key) ?
res := req.do() ?
println(res.text)
}
fn remove(conf Config, url string, branch string) ? {
mut req := http.new_request(http.Method.delete, '$conf.address/api/repos?url=$url&branch=$branch',
'') ?
req.add_custom_header('X-API-Key', conf.api_key) ?
res := req.do() ?
println(res.text)
}

View File

@ -8,7 +8,8 @@ pub fn cmd() cli.Command {
name: 'server'
description: 'Start the Vieter server'
execute: fn (cmd cli.Command) ? {
conf := env.load<env.ServerConfig>() ?
config_file := cmd.flags.get_string('config-file') ?
conf := env.load<env.ServerConfig>(config_file) ?
server(conf) ?
}