forked from vieter-v/vieter
				
			Switched to cli module; merged cli & vieter into single binary
							parent
							
								
									09d0a40aae
								
							
						
					
					
						commit
						5b919ceeae
					
				|  | @ -1,4 +1,4 @@ | |||
| module main | ||||
| module build | ||||
| 
 | ||||
| import docker | ||||
| import encoding.base64 | ||||
|  | @ -7,6 +7,8 @@ import json | |||
| import server | ||||
| import env | ||||
| import net.http | ||||
| import cli | ||||
| import git | ||||
| 
 | ||||
| const container_build_dir = '/build' | ||||
| 
 | ||||
|  | @ -62,15 +64,13 @@ fn create_build_image() ?string { | |||
| 	return image.id | ||||
| } | ||||
| 
 | ||||
| fn build() ? { | ||||
| 	conf := env.load<env.BuildConfig>() ? | ||||
| 
 | ||||
| fn build(conf env.BuildConfig) ? { | ||||
| 	// We get the repos list from the Vieter instance | ||||
| 	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() ? | ||||
| 	repos := json.decode([]server.GitRepo, res.text) ? | ||||
| 	repos := json.decode([]git.GitRepo, res.text) ? | ||||
| 
 | ||||
| 	// No point in doing work if there's no repos present | ||||
| 	if repos.len == 0 { | ||||
|  | @ -0,0 +1,17 @@ | |||
| module build | ||||
| 
 | ||||
| import cli | ||||
| import env | ||||
| 
 | ||||
| pub fn cmd() cli.Command { | ||||
| 	return cli.Command{ | ||||
| 		name: 'build' | ||||
| 		description: 'Run the build process.' | ||||
| 		execute: fn (cmd cli.Command) ? { | ||||
| 			conf := env.load<env.BuildConfig>() ? | ||||
| 
 | ||||
| 			build(conf) ? | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										25
									
								
								src/env.v
								
								
								
								
							
							
						
						
									
										25
									
								
								src/env.v
								
								
								
								
							|  | @ -56,15 +56,9 @@ fn get_env_var(field_name string) ?string { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| // 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 { | ||||
| 	res := T{} | ||||
| 
 | ||||
| fn load_in_place<T>(mut o T) ? { | ||||
| 	$for field in T.fields { | ||||
| 		res.$(field.name) = get_env_var(field.name) or { | ||||
| 		o.$(field.name) = get_env_var(field.name) or { | ||||
| 			// We use the default instead, if it's present | ||||
| 			mut default := '' | ||||
| 
 | ||||
|  | @ -82,5 +76,20 @@ pub fn load<T>() ?T { | |||
| 			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 { | ||||
| 	mut res := T{} | ||||
| 
 | ||||
| 	load_in_place<T>(mut res) ? | ||||
| 
 | ||||
| 	return res | ||||
| } | ||||
| 
 | ||||
| pub fn load_with_file<T>(path string) ?T { | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,37 @@ | |||
| module git | ||||
| 
 | ||||
| import cli | ||||
| import env | ||||
| import net.http | ||||
| 
 | ||||
| struct Config { | ||||
| 	address string [required] | ||||
| 	api_key string [required] | ||||
| } | ||||
| 
 | ||||
| pub fn cmd() cli.Command { | ||||
| 	return cli.Command{ | ||||
| 		name: 'repos' | ||||
| 		description: 'Interact with the repos API.' | ||||
| 		commands: [ | ||||
| 		cli.Command{ | ||||
| 			name: 'list' | ||||
| 			description: 'List the current repos.' | ||||
| 			execute: fn (cmd cli.Command) ? { | ||||
| 				conf := env.load<Config>() ? | ||||
| 
 | ||||
| 				list(conf) ? | ||||
| 			} | ||||
| 		} | ||||
| 		] | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| } | ||||
|  | @ -0,0 +1,40 @@ | |||
| module git | ||||
| 
 | ||||
| import os | ||||
| import json | ||||
| 
 | ||||
| pub struct GitRepo { | ||||
| pub: | ||||
| 	url    string [required] | ||||
| 	branch string [required] | ||||
| } | ||||
| 
 | ||||
| pub fn read_repos(path string) ?[]GitRepo { | ||||
| 	if !os.exists(path) { | ||||
| 		mut f := os.create(path) ? | ||||
| 
 | ||||
| 		defer { | ||||
| 			f.close() | ||||
| 		} | ||||
| 
 | ||||
| 		f.write_string('[]') ? | ||||
| 
 | ||||
| 		return [] | ||||
| 	} | ||||
| 
 | ||||
| 	content := os.read_file(path) ? | ||||
| 	res := json.decode([]GitRepo, content) ? | ||||
| 	return res | ||||
| } | ||||
| 
 | ||||
| pub fn write_repos(path string, repos []GitRepo) ? { | ||||
| 	mut f := os.create(path) ? | ||||
| 
 | ||||
| 	defer { | ||||
| 		f.close() | ||||
| 	} | ||||
| 
 | ||||
| 	value := json.encode(repos) | ||||
| 	f.write_string(value) ? | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										32
									
								
								src/main.v
								
								
								
								
							
							
						
						
									
										32
									
								
								src/main.v
								
								
								
								
							|  | @ -3,15 +3,33 @@ module main | |||
| import os | ||||
| import server | ||||
| import util | ||||
| import cli | ||||
| import env | ||||
| import build | ||||
| import git | ||||
| 
 | ||||
| fn main() { | ||||
| 	if os.args.len == 1 { | ||||
| 		util.exit_with_message(1, 'No action provided.') | ||||
| 	mut app := cli.Command{ | ||||
| 		name: 'vieter' | ||||
| 		description: 'Arch repository server' | ||||
| 		version: '0.1.0' | ||||
| 		flags: [ | ||||
| 			cli.Flag{ | ||||
| 				flag: cli.FlagType.string | ||||
| 				name: 'config-file' | ||||
| 				abbrev: 'f' | ||||
| 				description: 'Location of Vieter config file; defaults to ~/.vieterrc.' | ||||
| 				global: true | ||||
| 				default_value: [os.expand_tilde_to_home('~/.vieterrc')] | ||||
| 			} | ||||
| 		] | ||||
| 		commands: [ | ||||
| 			server.cmd(), | ||||
| 			build.cmd(), | ||||
| 			git.cmd() | ||||
| 		] | ||||
| 	} | ||||
| 
 | ||||
| 	match os.args[1] { | ||||
| 		'server' { server.server() ? } | ||||
| 		'build' { build() ? } | ||||
| 		else { util.exit_with_message(1, 'Unknown action: ${os.args[1]}') } | ||||
| 	} | ||||
| 	app.setup() | ||||
| 	app.parse(os.args) | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,16 @@ | |||
| module server | ||||
| 
 | ||||
| import cli | ||||
| import env | ||||
| 
 | ||||
| pub fn cmd() cli.Command { | ||||
| 	return cli.Command{ | ||||
| 		name: 'server' | ||||
| 		description: 'Start the Vieter server' | ||||
| 		execute: fn (cmd cli.Command) ? { | ||||
| 			conf := env.load<env.ServerConfig>() ? | ||||
| 
 | ||||
| 			server.server(conf) ? | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -3,44 +3,10 @@ module server | |||
| import web | ||||
| import os | ||||
| import json | ||||
| import git | ||||
| 
 | ||||
| const repos_file = 'repos.json' | ||||
| 
 | ||||
| pub struct GitRepo { | ||||
| pub: | ||||
| 	url    string [required] | ||||
| 	branch string [required] | ||||
| } | ||||
| 
 | ||||
| fn read_repos(path string) ?[]GitRepo { | ||||
| 	if !os.exists(path) { | ||||
| 		mut f := os.create(path) ? | ||||
| 
 | ||||
| 		defer { | ||||
| 			f.close() | ||||
| 		} | ||||
| 
 | ||||
| 		f.write_string('[]') ? | ||||
| 
 | ||||
| 		return [] | ||||
| 	} | ||||
| 
 | ||||
| 	content := os.read_file(path) ? | ||||
| 	res := json.decode([]GitRepo, content) ? | ||||
| 	return res | ||||
| } | ||||
| 
 | ||||
| fn write_repos(path string, repos []GitRepo) ? { | ||||
| 	mut f := os.create(path) ? | ||||
| 
 | ||||
| 	defer { | ||||
| 		f.close() | ||||
| 	} | ||||
| 
 | ||||
| 	value := json.encode(repos) | ||||
| 	f.write_string(value) ? | ||||
| } | ||||
| 
 | ||||
| ['/api/repos'; get] | ||||
| fn (mut app App) get_repos() web.Result { | ||||
| 	if !app.is_authorized() { | ||||
|  | @ -48,7 +14,7 @@ fn (mut app App) get_repos() web.Result { | |||
| 	} | ||||
| 
 | ||||
| 	repos := rlock app.git_mutex { | ||||
| 		read_repos(app.conf.repos_file) or { | ||||
| 		git.read_repos(app.conf.repos_file) or { | ||||
| 			app.lerror('Failed to read repos file.') | ||||
| 
 | ||||
| 			return app.server_error(500) | ||||
|  | @ -68,13 +34,13 @@ fn (mut app App) post_repo() web.Result { | |||
| 		return app.server_error(400) | ||||
| 	} | ||||
| 
 | ||||
| 	new_repo := GitRepo{ | ||||
| 	new_repo := git.GitRepo{ | ||||
| 		url: app.query['url'] | ||||
| 		branch: app.query['branch'] | ||||
| 	} | ||||
| 
 | ||||
| 	mut repos := rlock app.git_mutex { | ||||
| 		read_repos(app.conf.repos_file) or { | ||||
| 		git.read_repos(app.conf.repos_file) or { | ||||
| 			app.lerror('Failed to read repos file.') | ||||
| 
 | ||||
| 			return app.server_error(500) | ||||
|  | @ -91,7 +57,7 @@ fn (mut app App) post_repo() web.Result { | |||
| 	repos << new_repo | ||||
| 
 | ||||
| 	lock app.git_mutex { | ||||
| 		write_repos(app.conf.repos_file, repos) or { return app.server_error(500) } | ||||
| 		git.write_repos(app.conf.repos_file, repos) or { return app.server_error(500) } | ||||
| 	} | ||||
| 
 | ||||
| 	return app.ok('Repo added successfully.') | ||||
|  | @ -107,13 +73,13 @@ fn (mut app App) delete_repo() web.Result { | |||
| 		return app.server_error(400) | ||||
| 	} | ||||
| 
 | ||||
| 	repo_to_remove := GitRepo{ | ||||
| 	repo_to_remove := git.GitRepo{ | ||||
| 		url: app.query['url'] | ||||
| 		branch: app.query['branch'] | ||||
| 	} | ||||
| 
 | ||||
| 	mut repos := rlock app.git_mutex { | ||||
| 		read_repos(app.conf.repos_file) or { | ||||
| 		git.read_repos(app.conf.repos_file) or { | ||||
| 			app.lerror('Failed to read repos file.') | ||||
| 
 | ||||
| 			return app.server_error(500) | ||||
|  | @ -122,7 +88,7 @@ fn (mut app App) delete_repo() web.Result { | |||
| 	filtered := repos.filter(it != repo_to_remove) | ||||
| 
 | ||||
| 	lock app.git_mutex { | ||||
| 		write_repos(app.conf.repos_file, filtered) or { return app.server_error(500) } | ||||
| 		git.write_repos(app.conf.repos_file, filtered) or { return app.server_error(500) } | ||||
| 	} | ||||
| 
 | ||||
| 	return app.ok('Repo removed successfully.') | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ import log | |||
| import repo | ||||
| import env | ||||
| import util | ||||
| import cli | ||||
| 
 | ||||
| const port = 8000 | ||||
| 
 | ||||
|  | @ -20,9 +21,7 @@ pub mut: | |||
| } | ||||
| 
 | ||||
| // server starts the web server & starts listening for requests | ||||
| pub fn server() ? { | ||||
| 	conf := env.load<env.ServerConfig>() ? | ||||
| 
 | ||||
| pub fn server(conf env.ServerConfig) ? { | ||||
| 	// Configure logger | ||||
| 	log_level := log.level_from_tag(conf.log_level) or { | ||||
| 		util.exit_with_message(1, 'Invalid log level. The allowed values are FATAL, ERROR, WARN, INFO & DEBUG.') | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue