diff --git a/.woodpecker/arch-rel.yml b/.woodpecker/arch-rel.yml index f727486..f5f228e 100644 --- a/.woodpecker/arch-rel.yml +++ b/.woodpecker/arch-rel.yml @@ -9,7 +9,7 @@ skip_clone: true pipeline: build: - image: 'git.rustybever.be/vieter-v/vieter-builder' + image: 'menci/archlinuxarm:base-devel' commands: # Add the vieter repository so we can use the compiler - echo -e '[vieter]\nServer = https://arch.r8r.be/$repo/$arch\nSigLevel = Optional' >> /etc/pacman.conf diff --git a/.woodpecker/arch.yml b/.woodpecker/arch.yml index f5f8432..8f1a6ff 100644 --- a/.woodpecker/arch.yml +++ b/.woodpecker/arch.yml @@ -9,7 +9,7 @@ skip_clone: true pipeline: build: - image: 'git.rustybever.be/vieter-v/vieter-builder' + image: 'menci/archlinuxarm:base-devel' commands: # Add the vieter repository so we can use the compiler - echo -e '[vieter]\nServer = https://arch.r8r.be/$repo/$arch\nSigLevel = Optional' >> /etc/pacman.conf diff --git a/.woodpecker/build.yml b/.woodpecker/build.yml index f10e2a5..9ee8085 100644 --- a/.woodpecker/build.yml +++ b/.woodpecker/build.yml @@ -1,5 +1,5 @@ variables: - - &vlang_image 'git.rustybever.be/chewing_bever/vlang:0.3.2' + - &vlang_image 'chewingbever/vlang:0.3' matrix: PLATFORM: diff --git a/.woodpecker/docs.yml b/.woodpecker/docs.yml index cf4874e..048b1ad 100644 --- a/.woodpecker/docs.yml +++ b/.woodpecker/docs.yml @@ -1,5 +1,5 @@ variables: - - &vlang_image 'git.rustybever.be/chewing_bever/vlang:0.3.2' + - &vlang_image 'chewingbever/vlang:0.3' platform: 'linux/amd64' branches: diff --git a/.woodpecker/gitea.yml b/.woodpecker/gitea.yml index 9034f33..8e3b9d4 100644 --- a/.woodpecker/gitea.yml +++ b/.woodpecker/gitea.yml @@ -1,5 +1,5 @@ variables: - - &vlang_image 'git.rustybever.be/chewing_bever/vlang:0.3.2' + - &vlang_image 'chewingbever/vlang:0.3' platform: 'linux/amd64' branches: [ 'main' ] diff --git a/.woodpecker/lint.yml b/.woodpecker/lint.yml index f87c06f..c80ce33 100644 --- a/.woodpecker/lint.yml +++ b/.woodpecker/lint.yml @@ -1,5 +1,5 @@ variables: - - &vlang_image 'git.rustybever.be/chewing_bever/vlang:0.3.2' + - &vlang_image 'chewingbever/vlang:0.3' # These checks already get performed on the feature branches branches: diff --git a/.woodpecker/man.yml b/.woodpecker/man.yml index 8c6ca06..86a1bd8 100644 --- a/.woodpecker/man.yml +++ b/.woodpecker/man.yml @@ -1,5 +1,5 @@ variables: - - &vlang_image 'git.rustybever.be/chewing_bever/vlang:0.3.2' + - &vlang_image 'chewingbever/vlang:0.3' platform: 'linux/amd64' branches: diff --git a/.woodpecker/test.yml b/.woodpecker/test.yml index 39cb9f9..08b7534 100644 --- a/.woodpecker/test.yml +++ b/.woodpecker/test.yml @@ -1,5 +1,5 @@ variables: - - &vlang_image 'git.rustybever.be/chewing_bever/vlang:0.3.2' + - &vlang_image 'chewingbever/vlang:0.3' matrix: PLATFORM: diff --git a/Makefile b/Makefile index 895d3fd..69bd795 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ SRC_DIR := src SOURCES != find '$(SRC_DIR)' -iname '*.v' V_PATH ?= v -V := $(V_PATH) -showcc -gc boehm -W +V := $(V_PATH) -showcc -gc boehm all: vieter diff --git a/src/build/build.v b/src/build/build.v index 734427d..2ad70a6 100644 --- a/src/build/build.v +++ b/src/build/build.v @@ -21,8 +21,8 @@ const ( // system, install some necessary packages & creates a non-root user to run // makepkg with. The base image should be some Linux distribution that uses // Pacman as its package manager. -pub fn create_build_image(base_image string) !string { - mut dd := docker.new_conn()! +pub fn create_build_image(base_image string) ?string { + mut dd := docker.new_conn()? defer { dd.close() or {} @@ -57,15 +57,15 @@ pub fn create_build_image(base_image string) !string { image_tag := if image_parts.len > 1 { image_parts[1] } else { 'latest' } // We pull the provided image - dd.pull_image(image_name, image_tag)! + dd.pull_image(image_name, image_tag)? - id := dd.container_create(c)!.id - // id := docker.create_container(c)! - dd.container_start(id)! + id := dd.container_create(c)?.id + // id := docker.create_container(c)? + dd.container_start(id)? // This loop waits until the container has stopped, so we can remove it after for { - data := dd.container_inspect(id)! + data := dd.container_inspect(id)? if !data.state.running { break @@ -79,8 +79,8 @@ pub fn create_build_image(base_image string) !string { // TODO also add the base image's name into the image name to prevent // conflicts. tag := time.sys_mono_now().str() - image := dd.create_image_from_container(id, 'vieter-build', tag)! - dd.container_remove(id)! + image := dd.create_image_from_container(id, 'vieter-build', tag)? + dd.container_remove(id)? return image.id } @@ -96,8 +96,8 @@ pub: // build_target builds, packages & publishes a given Arch package based on the // provided target. The base image ID should be of an image previously created // by create_build_image. It returns the logs of the container. -pub fn build_target(address string, api_key string, base_image_id string, target &Target) !BuildResult { - mut dd := docker.new_conn()! +pub fn build_target(address string, api_key string, base_image_id string, target &Target) ?BuildResult { + mut dd := docker.new_conn()? defer { dd.close() or {} @@ -125,25 +125,25 @@ pub fn build_target(address string, api_key string, base_image_id string, target user: '0:0' } - id := dd.container_create(c)!.id - dd.container_start(id)! + id := dd.container_create(c)?.id + dd.container_start(id)? - mut data := dd.container_inspect(id)! + mut data := dd.container_inspect(id)? // This loop waits until the container has stopped, so we can remove it after for data.state.running { time.sleep(1 * time.second) - data = dd.container_inspect(id)! + data = dd.container_inspect(id)? } - mut logs_stream := dd.container_get_logs(id)! + mut logs_stream := dd.container_get_logs(id)? // Read in the entire stream mut logs_builder := strings.new_builder(10 * 1024) - util.reader_to_writer(mut logs_stream, mut logs_builder)! + util.reader_to_writer(mut logs_stream, mut logs_builder)? - dd.container_remove(id)! + dd.container_remove(id)? return BuildResult{ start_time: data.state.start_time diff --git a/src/client/client.v b/src/client/client.v index aa6094a..d68ff18 100644 --- a/src/client/client.v +++ b/src/client/client.v @@ -21,7 +21,7 @@ pub fn new(address string, api_key string) Client { // send_request_raw sends an HTTP request, returning the http.Response object. // It encodes the params so that they're safe to pass as HTTP query parameters. -fn (c &Client) send_request_raw(method Method, url string, params map[string]string, body string) !http.Response { +fn (c &Client) send_request_raw(method Method, url string, params map[string]string, body string) ?http.Response { mut full_url := '$c.address$url' if params.len > 0 { @@ -38,33 +38,31 @@ fn (c &Client) send_request_raw(method Method, url string, params map[string]str full_url = '$full_url?$params_str' } - // Looking at the source code, this function doesn't actually fail, so I'm - // not sure why it returns an optional - mut req := http.new_request(method, full_url, body) or { return error('') } - req.add_custom_header('X-Api-Key', c.api_key)! + mut req := http.new_request(method, full_url, body)? + req.add_custom_header('X-Api-Key', c.api_key)? - res := req.do()! + res := req.do()? return res } // send_request just calls send_request_with_body with an empty body. -fn (c &Client) send_request(method Method, url string, params map[string]string) !Response { +fn (c &Client) send_request(method Method, url string, params map[string]string) ?Response { return c.send_request_with_body(method, url, params, '') } // send_request_with_body calls send_request_raw_response & parses its // output as a Response object. -fn (c &Client) send_request_with_body(method Method, url string, params map[string]string, body string) !Response { - res_text := c.send_request_raw_response(method, url, params, body)! - data := json.decode(Response, res_text)! +fn (c &Client) send_request_with_body(method Method, url string, params map[string]string, body string) ?Response { + res_text := c.send_request_raw_response(method, url, params, body)? + data := json.decode(Response, res_text)? return data } // send_request_raw_response returns the raw text response for an HTTP request. -fn (c &Client) send_request_raw_response(method Method, url string, params map[string]string, body string) !string { - res := c.send_request_raw(method, url, params, body)! +fn (c &Client) send_request_raw_response(method Method, url string, params map[string]string, body string) ?string { + res := c.send_request_raw(method, url, params, body)? return res.body } diff --git a/src/client/logs.v b/src/client/logs.v index eaddc8c..b414245 100644 --- a/src/client/logs.v +++ b/src/client/logs.v @@ -6,40 +6,40 @@ import web.response { Response } import time // get_build_logs returns all build logs. -pub fn (c &Client) get_build_logs(filter BuildLogFilter) !Response<[]BuildLog> { +pub fn (c &Client) get_build_logs(filter BuildLogFilter) ?Response<[]BuildLog> { params := models.params_from(filter) - data := c.send_request<[]BuildLog>(Method.get, '/api/v1/logs', params)! + data := c.send_request<[]BuildLog>(Method.get, '/api/v1/logs', params)? return data } // get_build_logs_for_target returns all build logs for a given target. -pub fn (c &Client) get_build_logs_for_target(target_id int) !Response<[]BuildLog> { +pub fn (c &Client) get_build_logs_for_target(target_id int) ?Response<[]BuildLog> { params := { 'repo': target_id.str() } - data := c.send_request<[]BuildLog>(Method.get, '/api/v1/logs', params)! + data := c.send_request<[]BuildLog>(Method.get, '/api/v1/logs', params)? return data } // get_build_log returns a specific build log. -pub fn (c &Client) get_build_log(id int) !Response { - data := c.send_request(Method.get, '/api/v1/logs/$id', {})! +pub fn (c &Client) get_build_log(id int) ?Response { + data := c.send_request(Method.get, '/api/v1/logs/$id', {})? return data } // get_build_log_content returns the contents of the build log file. -pub fn (c &Client) get_build_log_content(id int) !string { - data := c.send_request_raw_response(Method.get, '/api/v1/logs/$id/content', {}, '')! +pub fn (c &Client) get_build_log_content(id int) ?string { + data := c.send_request_raw_response(Method.get, '/api/v1/logs/$id/content', {}, '')? return data } // add_build_log adds a new build log to the server. -pub fn (c &Client) add_build_log(target_id int, start_time time.Time, end_time time.Time, arch string, exit_code int, content string) !Response { +pub fn (c &Client) add_build_log(target_id int, start_time time.Time, end_time time.Time, arch string, exit_code int, content string) ?Response { params := { 'target': target_id.str() 'startTime': start_time.unix_time().str() @@ -48,7 +48,7 @@ pub fn (c &Client) add_build_log(target_id int, start_time time.Time, end_time t 'exitCode': exit_code.str() } - data := c.send_request_with_body(Method.post, '/api/v1/logs', params, content)! + data := c.send_request_with_body(Method.post, '/api/v1/logs', params, content)? return data } diff --git a/src/client/targets.v b/src/client/targets.v index fd4254c..c5e44fe 100644 --- a/src/client/targets.v +++ b/src/client/targets.v @@ -5,21 +5,21 @@ import net.http { Method } import web.response { Response } // get_targets returns a list of targets, given a filter object. -pub fn (c &Client) get_targets(filter TargetFilter) ![]Target { +pub fn (c &Client) get_targets(filter TargetFilter) ?[]Target { params := models.params_from(filter) - data := c.send_request<[]Target>(Method.get, '/api/v1/targets', params)! + data := c.send_request<[]Target>(Method.get, '/api/v1/targets', params)? return data.data } // get_all_targets retrieves *all* targs from the API using the default // limit. -pub fn (c &Client) get_all_targets() ![]Target { +pub fn (c &Client) get_all_targets() ?[]Target { mut targets := []Target{} mut offset := u64(0) for { - sub_targets := c.get_targets(offset: offset)! + sub_targets := c.get_targets(offset: offset)? if sub_targets.len == 0 { break @@ -34,8 +34,8 @@ pub fn (c &Client) get_all_targets() ![]Target { } // get_target returns the target for a specific id. -pub fn (c &Client) get_target(id int) !Target { - data := c.send_request(Method.get, '/api/v1/targets/$id', {})! +pub fn (c &Client) get_target(id int) ?Target { + data := c.send_request(Method.get, '/api/v1/targets/$id', {})? return data.data } @@ -49,24 +49,24 @@ pub struct NewTarget { } // add_target adds a new target to the server. -pub fn (c &Client) add_target(t NewTarget) !Response { +pub fn (c &Client) add_target(t NewTarget) ?Response { params := models.params_from(t) - data := c.send_request(Method.post, '/api/v1/targets', params)! + data := c.send_request(Method.post, '/api/v1/targets', params)? return data } // remove_target removes the target with the given id from the server. -pub fn (c &Client) remove_target(id int) !Response { - data := c.send_request(Method.delete, '/api/v1/targets/$id', {})! +pub fn (c &Client) remove_target(id int) ?Response { + data := c.send_request(Method.delete, '/api/v1/targets/$id', {})? return data } // patch_target sends a PATCH request to the given target with the params as // payload. -pub fn (c &Client) patch_target(id int, params map[string]string) !Response { - data := c.send_request(Method.patch, '/api/v1/targets/$id', params)! +pub fn (c &Client) patch_target(id int, params map[string]string) ?Response { + data := c.send_request(Method.patch, '/api/v1/targets/$id', params)? return data } diff --git a/src/console/aur/aur.v b/src/console/aur/aur.v index 6a061dd..c98f8e6 100644 --- a/src/console/aur/aur.v +++ b/src/console/aur/aur.v @@ -21,12 +21,12 @@ pub fn cmd() cli.Command { name: 'search' description: 'Search for packages.' required_args: 1 - execute: fn (cmd cli.Command) ! { + execute: fn (cmd cli.Command) ? { c := aur.new() - pkgs := c.search(cmd.args[0])! + pkgs := c.search(cmd.args[0])? data := pkgs.map([it.name, it.description]) - println(console.pretty_table(['name', 'description'], data)!) + println(console.pretty_table(['name', 'description'], data)?) } }, cli.Command{ @@ -34,12 +34,12 @@ pub fn cmd() cli.Command { usage: 'repo pkg-name [pkg-name...]' description: 'Add the given AUR package(s) to Vieter. Non-existent packages will be silently ignored.' required_args: 2 - execute: fn (cmd cli.Command) ! { - config_file := cmd.flags.get_string('config-file')! - conf := vconf.load(prefix: 'VIETER_', default_path: config_file)! + execute: fn (cmd cli.Command) ? { + config_file := cmd.flags.get_string('config-file')? + conf := vconf.load(prefix: 'VIETER_', default_path: config_file)? c := aur.new() - pkgs := c.info(cmd.args[1..])! + pkgs := c.info(cmd.args[1..])? vc := client.new(conf.address, conf.api_key) diff --git a/src/console/console.v b/src/console/console.v index 5c40de8..caf4cca 100644 --- a/src/console/console.v +++ b/src/console/console.v @@ -13,7 +13,7 @@ pub fn tabbed_table(data [][]string) string { // pretty_table converts a list of string data into a pretty table. Many thanks // to @hungrybluedev in the Vlang Discord for providing this code! // https://ptb.discord.com/channels/592103645835821068/592106336838352923/970278787143045192 -pub fn pretty_table(header []string, data [][]string) !string { +pub fn pretty_table(header []string, data [][]string) ?string { column_count := header.len mut column_widths := []int{len: column_count, init: header[it].len} @@ -26,7 +26,7 @@ pub fn pretty_table(header []string, data [][]string) !string { } } - single_line_length := arrays.sum(column_widths)! + (column_count + 1) * 3 - 4 + single_line_length := arrays.sum(column_widths)? + (column_count + 1) * 3 - 4 horizontal_line := '+' + strings.repeat(`-`, single_line_length) + '+' mut buffer := strings.new_builder(data.len * single_line_length) @@ -64,12 +64,12 @@ pub fn pretty_table(header []string, data [][]string) !string { // export_man_pages recursively generates all man pages for the given // cli.Command & writes them to the given directory. -pub fn export_man_pages(cmd cli.Command, path string) ! { +pub fn export_man_pages(cmd cli.Command, path string) ? { man := cmd.manpage() os.write_file(os.join_path_single(path, cmd.full_name().replace(' ', '-') + '.1'), - man)! + man)? for sub_cmd in cmd.commands { - export_man_pages(sub_cmd, path)! + export_man_pages(sub_cmd, path)? } } diff --git a/src/console/logs/logs.v b/src/console/logs/logs.v index 6d5ffad..41830c2 100644 --- a/src/console/logs/logs.v +++ b/src/console/logs/logs.v @@ -63,30 +63,30 @@ pub fn cmd() cli.Command { flag: cli.FlagType.string }, ] - execute: fn (cmd cli.Command) ! { - config_file := cmd.flags.get_string('config-file')! - conf := vconf.load(prefix: 'VIETER_', default_path: config_file)! + execute: fn (cmd cli.Command) ? { + config_file := cmd.flags.get_string('config-file')? + conf := vconf.load(prefix: 'VIETER_', default_path: config_file)? mut filter := BuildLogFilter{} - limit := cmd.flags.get_int('limit')! + limit := cmd.flags.get_int('limit')? if limit != 0 { filter.limit = u64(limit) } - offset := cmd.flags.get_int('offset')! + offset := cmd.flags.get_int('offset')? if offset != 0 { filter.offset = u64(offset) } - target_id := cmd.flags.get_int('target')! + target_id := cmd.flags.get_int('target')? if target_id != 0 { filter.target = target_id } tz_offset := time.offset() - if cmd.flags.get_bool('today')! { + if cmd.flags.get_bool('today')? { today := time.now() filter.after = time.new_time(time.Time{ @@ -98,12 +98,12 @@ pub fn cmd() cli.Command { } // The -today flag overwrites any of the other date flags. else { - day_str := cmd.flags.get_string('day')! - before_str := cmd.flags.get_string('before')! - after_str := cmd.flags.get_string('after')! + day_str := cmd.flags.get_string('day')? + before_str := cmd.flags.get_string('before')? + after_str := cmd.flags.get_string('after')? if day_str != '' { - day := time.parse_rfc3339(day_str)! + day := time.parse_rfc3339(day_str)? day_utc := time.new_time(time.Time{ year: day.year month: day.month @@ -118,24 +118,24 @@ pub fn cmd() cli.Command { filter.before = day_utc.add_days(1) } else { if before_str != '' { - filter.before = time.parse(before_str)!.add_seconds(-tz_offset) + filter.before = time.parse(before_str)?.add_seconds(-tz_offset) } if after_str != '' { - filter.after = time.parse(after_str)!.add_seconds(-tz_offset) + filter.after = time.parse(after_str)?.add_seconds(-tz_offset) } } } - if cmd.flags.get_bool('failed')! { + if cmd.flags.get_bool('failed')? { filter.exit_codes = [ '!0', ] } - raw := cmd.flags.get_bool('raw')! + raw := cmd.flags.get_bool('raw')? - list(conf, filter, raw)! + list(conf, filter, raw)? } }, cli.Command{ @@ -143,12 +143,12 @@ pub fn cmd() cli.Command { required_args: 1 usage: 'id' description: 'Show all info for a specific build log.' - execute: fn (cmd cli.Command) ! { - config_file := cmd.flags.get_string('config-file')! - conf := vconf.load(prefix: 'VIETER_', default_path: config_file)! + execute: fn (cmd cli.Command) ? { + config_file := cmd.flags.get_string('config-file')? + conf := vconf.load(prefix: 'VIETER_', default_path: config_file)? id := cmd.args[0].int() - info(conf, id)! + info(conf, id)? } }, cli.Command{ @@ -156,12 +156,12 @@ pub fn cmd() cli.Command { required_args: 1 usage: 'id' description: 'Output the content of a build log to stdout.' - execute: fn (cmd cli.Command) ! { - config_file := cmd.flags.get_string('config-file')! - conf := vconf.load(prefix: 'VIETER_', default_path: config_file)! + execute: fn (cmd cli.Command) ? { + config_file := cmd.flags.get_string('config-file')? + conf := vconf.load(prefix: 'VIETER_', default_path: config_file)? id := cmd.args[0].int() - content(conf, id)! + content(conf, id)? } }, ] @@ -169,46 +169,46 @@ pub fn cmd() cli.Command { } // print_log_list prints a list of logs. -fn print_log_list(logs []BuildLog, raw bool) ! { +fn print_log_list(logs []BuildLog, raw bool) ? { data := logs.map([it.id.str(), it.target_id.str(), it.start_time.local().str(), it.exit_code.str()]) if raw { println(console.tabbed_table(data)) } else { - println(console.pretty_table(['id', 'target', 'start time', 'exit code'], data)!) + println(console.pretty_table(['id', 'target', 'start time', 'exit code'], data)?) } } // list prints a list of all build logs. -fn list(conf Config, filter BuildLogFilter, raw bool) ! { +fn list(conf Config, filter BuildLogFilter, raw bool) ? { c := client.new(conf.address, conf.api_key) - logs := c.get_build_logs(filter)!.data + logs := c.get_build_logs(filter)?.data - print_log_list(logs, raw)! + print_log_list(logs, raw)? } // list prints a list of all build logs for a given target. -fn list_for_target(conf Config, target_id int, raw bool) ! { +fn list_for_target(conf Config, target_id int, raw bool) ? { c := client.new(conf.address, conf.api_key) - logs := c.get_build_logs_for_target(target_id)!.data + logs := c.get_build_logs_for_target(target_id)?.data - print_log_list(logs, raw)! + print_log_list(logs, raw)? } // info print the detailed info for a given build log. -fn info(conf Config, id int) ! { +fn info(conf Config, id int) ? { c := client.new(conf.address, conf.api_key) - log := c.get_build_log(id)!.data + log := c.get_build_log(id)?.data print(log) } // content outputs the contents of the log file for a given build log to // stdout. -fn content(conf Config, id int) ! { +fn content(conf Config, id int) ? { c := client.new(conf.address, conf.api_key) - content := c.get_build_log_content(id)! + content := c.get_build_log_content(id)? println(content) } diff --git a/src/console/man/man.v b/src/console/man/man.v index 22cb5f7..d91a140 100644 --- a/src/console/man/man.v +++ b/src/console/man/man.v @@ -11,11 +11,11 @@ pub fn cmd() cli.Command { description: 'Generate all man pages & save them in the given directory.' usage: 'dir' required_args: 1 - execute: fn (cmd cli.Command) ! { + execute: fn (cmd cli.Command) ? { root := cmd.root() - os.mkdir_all(cmd.args[0])! + os.mkdir_all(cmd.args[0])? - console.export_man_pages(root, cmd.args[0])! + console.export_man_pages(root, cmd.args[0])? } } } diff --git a/src/console/schedule/schedule.v b/src/console/schedule/schedule.v index 7ce0516..8fceddd 100644 --- a/src/console/schedule/schedule.v +++ b/src/console/schedule/schedule.v @@ -18,11 +18,11 @@ pub fn cmd() cli.Command { default_value: ['5'] }, ] - execute: fn (cmd cli.Command) ! { - ce := parse_expression(cmd.args.join(' '))! - count := cmd.flags.get_int('count')! + execute: fn (cmd cli.Command) ? { + ce := parse_expression(cmd.args.join(' '))? + count := cmd.flags.get_int('count')? - for t in ce.next_n(time.now(), count)! { + for t in ce.next_n(time.now(), count)? { println(t) } } diff --git a/src/console/targets/build.v b/src/console/targets/build.v index 83ebde2..6337aa3 100644 --- a/src/console/targets/build.v +++ b/src/console/targets/build.v @@ -6,29 +6,29 @@ import os import build // build locally builds the target with the given id. -fn build(conf Config, target_id int) ! { +fn build(conf Config, target_id int) ? { c := client.new(conf.address, conf.api_key) - target := c.get_target(target_id)! + target := c.get_target(target_id)? build_arch := os.uname().machine println('Creating base image...') - image_id := build.create_build_image(conf.base_image)! + image_id := build.create_build_image(conf.base_image)? println('Running build...') - res := build.build_target(conf.address, conf.api_key, image_id, target)! + res := build.build_target(conf.address, conf.api_key, image_id, target)? println('Removing build image...') - mut dd := docker.new_conn()! + mut dd := docker.new_conn()? defer { dd.close() or {} } - dd.remove_image(image_id)! + dd.remove_image(image_id)? println('Uploading logs to Vieter...') c.add_build_log(target.id, res.start_time, res.end_time, build_arch, res.exit_code, - res.logs)! + res.logs)? } diff --git a/src/console/targets/targets.v b/src/console/targets/targets.v index 774a129..5640011 100644 --- a/src/console/targets/targets.v +++ b/src/console/targets/targets.v @@ -39,30 +39,30 @@ pub fn cmd() cli.Command { flag: cli.FlagType.string }, ] - execute: fn (cmd cli.Command) ! { - config_file := cmd.flags.get_string('config-file')! - conf := vconf.load(prefix: 'VIETER_', default_path: config_file)! + execute: fn (cmd cli.Command) ? { + config_file := cmd.flags.get_string('config-file')? + conf := vconf.load(prefix: 'VIETER_', default_path: config_file)? mut filter := TargetFilter{} - limit := cmd.flags.get_int('limit')! + limit := cmd.flags.get_int('limit')? if limit != 0 { filter.limit = u64(limit) } - offset := cmd.flags.get_int('offset')! + offset := cmd.flags.get_int('offset')? if offset != 0 { filter.offset = u64(offset) } - repo := cmd.flags.get_string('repo')! + repo := cmd.flags.get_string('repo')? if repo != '' { filter.repo = repo } - raw := cmd.flags.get_bool('raw')! + raw := cmd.flags.get_bool('raw')? - list(conf, filter, raw)! + list(conf, filter, raw)? } }, cli.Command{ @@ -83,20 +83,20 @@ pub fn cmd() cli.Command { flag: cli.FlagType.string }, ] - execute: fn (cmd cli.Command) ! { - config_file := cmd.flags.get_string('config-file')! - conf := vconf.load(prefix: 'VIETER_', default_path: config_file)! + execute: fn (cmd cli.Command) ? { + config_file := cmd.flags.get_string('config-file')? + conf := vconf.load(prefix: 'VIETER_', default_path: config_file)? t := NewTarget{ - kind: cmd.flags.get_string('kind')! + kind: cmd.flags.get_string('kind')? url: cmd.args[0] repo: cmd.args[1] branch: cmd.flags.get_string('branch') or { '' } } - raw := cmd.flags.get_bool('raw')! + raw := cmd.flags.get_bool('raw')? - add(conf, t, raw)! + add(conf, t, raw)? } }, cli.Command{ @@ -104,11 +104,11 @@ pub fn cmd() cli.Command { required_args: 1 usage: 'id' description: 'Remove a target that matches the given id.' - execute: fn (cmd cli.Command) ! { - config_file := cmd.flags.get_string('config-file')! - conf := vconf.load(prefix: 'VIETER_', default_path: config_file)! + execute: fn (cmd cli.Command) ? { + config_file := cmd.flags.get_string('config-file')? + conf := vconf.load(prefix: 'VIETER_', default_path: config_file)? - remove(conf, cmd.args[0])! + remove(conf, cmd.args[0])? } }, cli.Command{ @@ -116,11 +116,11 @@ pub fn cmd() cli.Command { required_args: 1 usage: 'id' description: 'Show detailed information for the target matching the id.' - execute: fn (cmd cli.Command) ! { - config_file := cmd.flags.get_string('config-file')! - conf := vconf.load(prefix: 'VIETER_', default_path: config_file)! + execute: fn (cmd cli.Command) ? { + config_file := cmd.flags.get_string('config-file')? + conf := vconf.load(prefix: 'VIETER_', default_path: config_file)? - info(conf, cmd.args[0])! + info(conf, cmd.args[0])? } }, cli.Command{ @@ -160,9 +160,9 @@ pub fn cmd() cli.Command { flag: cli.FlagType.string }, ] - execute: fn (cmd cli.Command) ! { - config_file := cmd.flags.get_string('config-file')! - conf := vconf.load(prefix: 'VIETER_', default_path: config_file)! + execute: fn (cmd cli.Command) ? { + config_file := cmd.flags.get_string('config-file')? + conf := vconf.load(prefix: 'VIETER_', default_path: config_file)? found := cmd.flags.get_all_found() @@ -170,11 +170,11 @@ pub fn cmd() cli.Command { for f in found { if f.name != 'config-file' { - params[f.name] = f.get_string()! + params[f.name] = f.get_string()? } } - patch(conf, cmd.args[0], params)! + patch(conf, cmd.args[0], params)? } }, cli.Command{ @@ -182,11 +182,11 @@ pub fn cmd() cli.Command { required_args: 1 usage: 'id' description: 'Build the target with the given id & publish it.' - execute: fn (cmd cli.Command) ! { - config_file := cmd.flags.get_string('config-file')! - conf := vconf.load(prefix: 'VIETER_', default_path: config_file)! + execute: fn (cmd cli.Command) ? { + config_file := cmd.flags.get_string('config-file')? + conf := vconf.load(prefix: 'VIETER_', default_path: config_file)? - build(conf, cmd.args[0].int())! + build(conf, cmd.args[0].int())? } }, ] @@ -197,22 +197,22 @@ pub fn cmd() cli.Command { // ID. If multiple or none are found, an error is raised. // list prints out a list of all repositories. -fn list(conf Config, filter TargetFilter, raw bool) ! { +fn list(conf Config, filter TargetFilter, raw bool) ? { c := client.new(conf.address, conf.api_key) - repos := c.get_targets(filter)! + repos := c.get_targets(filter)? data := repos.map([it.id.str(), it.kind, it.url, it.repo]) if raw { println(console.tabbed_table(data)) } else { - println(console.pretty_table(['id', 'kind', 'url', 'repo'], data)!) + println(console.pretty_table(['id', 'kind', 'url', 'repo'], data)?) } } // add adds a new repository to the server's list. -fn add(conf Config, t &NewTarget, raw bool) ! { +fn add(conf Config, t &NewTarget, raw bool) ? { c := client.new(conf.address, conf.api_key) - res := c.add_target(t)! + res := c.add_target(t)? if raw { println(res.data) @@ -222,18 +222,18 @@ fn add(conf Config, t &NewTarget, raw bool) ! { } // remove removes a repository from the server's list. -fn remove(conf Config, id string) ! { +fn remove(conf Config, id string) ? { id_int := id.int() if id_int != 0 { c := client.new(conf.address, conf.api_key) - res := c.remove_target(id_int)! + res := c.remove_target(id_int)? println(res.message) } } // patch patches a given repository with the provided params. -fn patch(conf Config, id string, params map[string]string) ! { +fn patch(conf Config, id string, params map[string]string) ? { // We check the cron expression first because it's useless to send an // invalid one to the server. if 'schedule' in params && params['schedule'] != '' { @@ -245,14 +245,14 @@ fn patch(conf Config, id string, params map[string]string) ! { id_int := id.int() if id_int != 0 { c := client.new(conf.address, conf.api_key) - res := c.patch_target(id_int, params)! + res := c.patch_target(id_int, params)? println(res.message) } } // info shows detailed information for a given repo. -fn info(conf Config, id string) ! { +fn info(conf Config, id string) ? { id_int := id.int() if id_int == 0 { @@ -260,6 +260,6 @@ fn info(conf Config, id string) ! { } c := client.new(conf.address, conf.api_key) - repo := c.get_target(id_int)! + repo := c.get_target(id_int)? println(repo) } diff --git a/src/cron/cli.v b/src/cron/cli.v index 0d7a042..4d95833 100644 --- a/src/cron/cli.v +++ b/src/cron/cli.v @@ -22,11 +22,11 @@ pub fn cmd() cli.Command { return cli.Command{ name: 'cron' description: 'Start the cron service that periodically runs builds.' - execute: fn (cmd cli.Command) ! { - config_file := cmd.flags.get_string('config-file')! - conf := vconf.load(prefix: 'VIETER_', default_path: config_file)! + execute: fn (cmd cli.Command) ? { + config_file := cmd.flags.get_string('config-file')? + conf := vconf.load(prefix: 'VIETER_', default_path: config_file)? - cron(conf)! + cron(conf)? } } } diff --git a/src/cron/cron.v b/src/cron/cron.v index f1d6b7b..5f128cf 100644 --- a/src/cron/cron.v +++ b/src/cron/cron.v @@ -8,7 +8,7 @@ import os const log_file_name = 'vieter.cron.log' // cron starts a cron daemon & starts periodically scheduling builds. -pub fn cron(conf Config) ! { +pub fn cron(conf Config) ? { // Configure logger log_level := log.level_from_tag(conf.log_level) or { return error('Invalid log level. The allowed values are FATAL, ERROR, WARN, INFO & DEBUG.') @@ -27,7 +27,7 @@ pub fn cron(conf Config) ! { } mut d := daemon.init_daemon(logger, conf.address, conf.api_key, conf.base_image, ce, - conf.max_concurrent_builds, conf.api_update_frequency, conf.image_rebuild_frequency)! + conf.max_concurrent_builds, conf.api_update_frequency, conf.image_rebuild_frequency)? d.run() } diff --git a/src/cron/daemon/daemon.v b/src/cron/daemon/daemon.v index 8c6516c..934d35a 100644 --- a/src/cron/daemon/daemon.v +++ b/src/cron/daemon/daemon.v @@ -53,7 +53,7 @@ mut: // init_daemon initializes a new Daemon object. It renews the targets & // populates the build queue for the first time. -pub fn init_daemon(logger log.Log, address string, api_key string, base_image string, global_schedule CronExpression, max_concurrent_builds int, api_update_frequency int, image_rebuild_frequency int) !Daemon { +pub fn init_daemon(logger log.Log, address string, api_key string, base_image string, global_schedule CronExpression, max_concurrent_builds int, api_update_frequency int, image_rebuild_frequency int) ?Daemon { mut d := Daemon{ client: client.new(address, api_key) base_image: base_image @@ -207,7 +207,7 @@ fn (mut d Daemon) renew_queue() { // For some reason, using // ```v - // for d.queue.len() > 0 && d.queue.peek() !.timestamp < now { + // for d.queue.len() > 0 && d.queue.peek() ?.timestamp < now { //``` // here causes the function to prematurely just exit, without any errors or anything, very weird // https://github.com/vlang/v/issues/14042 diff --git a/src/cron/daemon/log.v b/src/cron/daemon/log.v index 95a50e7..003898b 100644 --- a/src/cron/daemon/log.v +++ b/src/cron/daemon/log.v @@ -3,33 +3,33 @@ module daemon import log // log reate a log message with the given level -pub fn (mut d Daemon) log(msg string, level log.Level) { +pub fn (mut d Daemon) log(msg &string, level log.Level) { lock d.logger { d.logger.send_output(msg, level) } } // lfatal create a log message with the fatal level -pub fn (mut d Daemon) lfatal(msg string) { +pub fn (mut d Daemon) lfatal(msg &string) { d.log(msg, log.Level.fatal) } // lerror create a log message with the error level -pub fn (mut d Daemon) lerror(msg string) { +pub fn (mut d Daemon) lerror(msg &string) { d.log(msg, log.Level.error) } // lwarn create a log message with the warn level -pub fn (mut d Daemon) lwarn(msg string) { +pub fn (mut d Daemon) lwarn(msg &string) { d.log(msg, log.Level.warn) } // linfo create a log message with the info level -pub fn (mut d Daemon) linfo(msg string) { +pub fn (mut d Daemon) linfo(msg &string) { d.log(msg, log.Level.info) } // ldebug create a log message with the debug level -pub fn (mut d Daemon) ldebug(msg string) { +pub fn (mut d Daemon) ldebug(msg &string) { d.log(msg, log.Level.debug) } diff --git a/src/cron/expression/expression.v b/src/cron/expression/expression.v index 438805d..17d2dde 100644 --- a/src/cron/expression/expression.v +++ b/src/cron/expression/expression.v @@ -12,7 +12,7 @@ pub struct CronExpression { // next calculates the earliest time this cron expression is valid. It will // always pick a moment in the future, even if ref matches completely up to the // minute. This function conciously does not take gap years into account. -pub fn (ce &CronExpression) next(ref time.Time) !time.Time { +pub fn (ce &CronExpression) next(ref time.Time) ?time.Time { // If the given ref matches the next cron occurence up to the minute, it // will return that value. Because we always want to return a value in the // future, we artifically shift the ref 60 seconds to make sure we always @@ -117,19 +117,19 @@ pub fn (ce &CronExpression) next(ref time.Time) !time.Time { // next_from_now returns the result of ce.next(ref) where ref is the result of // time.now(). -pub fn (ce &CronExpression) next_from_now() !time.Time { +pub fn (ce &CronExpression) next_from_now() ?time.Time { return ce.next(time.now()) } // next_n returns the n next occurences of the expression, given a starting // time. -pub fn (ce &CronExpression) next_n(ref time.Time, n int) ![]time.Time { +pub fn (ce &CronExpression) next_n(ref time.Time, n int) ?[]time.Time { mut times := []time.Time{cap: n} - times << ce.next(ref)! + times << ce.next(ref)? for i in 1 .. n { - times << ce.next(times[i - 1])! + times << ce.next(times[i - 1])? } return times @@ -137,7 +137,7 @@ pub fn (ce &CronExpression) next_n(ref time.Time, n int) ![]time.Time { // parse_range parses a given string into a range of sorted integers, if // possible. -fn parse_range(s string, min int, max int, mut bitv []bool) ! { +fn parse_range(s string, min int, max int, mut bitv []bool) ? { mut start := min mut end := max mut interval := 1 @@ -228,11 +228,11 @@ fn bitv_to_ints(bitv []bool, min int) []int { // parse_part parses a given part of a cron expression & returns the // corresponding array of ints. -fn parse_part(s string, min int, max int) ![]int { +fn parse_part(s string, min int, max int) ?[]int { mut bitv := []bool{len: max - min + 1, init: false} for range in s.split(',') { - parse_range(range, min, max, mut bitv)! + parse_range(range, min, max, mut bitv)? } return bitv_to_ints(bitv, min) @@ -240,7 +240,7 @@ fn parse_part(s string, min int, max int) ![]int { // parse_expression parses an entire cron expression string into a // CronExpression object, if possible. -pub fn parse_expression(exp string) !CronExpression { +pub fn parse_expression(exp string) ?CronExpression { // The filter allows for multiple spaces between parts mut parts := exp.split(' ').filter(it != '') diff --git a/src/package/package.v b/src/package/package.v index aadf6f2..9eaf5a2 100644 --- a/src/package/package.v +++ b/src/package/package.v @@ -43,12 +43,12 @@ pub mut: } // checksum calculates the sha256 hash of the package -pub fn (p &Pkg) checksum() !string { +pub fn (p &Pkg) checksum() ?string { return util.hash_file(p.path) } // parse_pkg_info_string parses a PkgInfo object from a string -fn parse_pkg_info_string(pkg_info_str &string) !PkgInfo { +fn parse_pkg_info_string(pkg_info_str &string) ?PkgInfo { mut pkg_info := PkgInfo{} // Iterate over the entire string @@ -101,7 +101,7 @@ fn parse_pkg_info_string(pkg_info_str &string) !PkgInfo { // read_pkg_archive extracts the file list & .PKGINFO contents from an archive // NOTE: this command only supports zstd-, xz- & gzip-compressed tarballs. -pub fn read_pkg_archive(pkg_path string) !Pkg { +pub fn read_pkg_archive(pkg_path string) ?Pkg { if !os.is_file(pkg_path) { return error("'$pkg_path' doesn't exist or isn't a file.") } @@ -159,7 +159,7 @@ pub fn read_pkg_archive(pkg_path string) !Pkg { pkg_text := unsafe { buf.vstring_with_len(size).clone() } - pkg_info = parse_pkg_info_string(pkg_text)! + pkg_info = parse_pkg_info_string(pkg_text)? } else { C.archive_read_data_skip(a) } @@ -201,7 +201,7 @@ pub fn (pkg &Pkg) filename() string { } // to_desc returns a desc file valid string representation -pub fn (pkg &Pkg) to_desc() !string { +pub fn (pkg &Pkg) to_desc() ?string { p := pkg.info // filename @@ -222,7 +222,7 @@ pub fn (pkg &Pkg) to_desc() !string { desc += format_entry('CSIZE', p.csize.str()) desc += format_entry('ISIZE', p.size.str()) - sha256sum := pkg.checksum()! + sha256sum := pkg.checksum()? desc += format_entry('SHA256SUM', sha256sum) diff --git a/src/server/cli.v b/src/server/cli.v index 26ee0f1..6fd09c5 100644 --- a/src/server/cli.v +++ b/src/server/cli.v @@ -18,11 +18,11 @@ pub fn cmd() cli.Command { return cli.Command{ name: 'server' description: 'Start the Vieter server.' - execute: fn (cmd cli.Command) ! { - config_file := cmd.flags.get_string('config-file')! - conf := vconf.load(prefix: 'VIETER_', default_path: config_file)! + execute: fn (cmd cli.Command) ? { + config_file := cmd.flags.get_string('config-file')? + conf := vconf.load(prefix: 'VIETER_', default_path: config_file)? - server(conf)! + server(conf)? } } } diff --git a/src/server/server.v b/src/server/server.v index d5f6135..9903cea 100644 --- a/src/server/server.v +++ b/src/server/server.v @@ -24,7 +24,7 @@ pub mut: } // server starts the web server & starts listening for requests -pub fn server(conf Config) ! { +pub fn server(conf Config) ? { // Prevent using 'any' as the default arch if conf.default_arch == 'any' { util.exit_with_message(1, "'any' is not allowed as the value for default_arch.") diff --git a/src/util/stream.v b/src/util/stream.v index 15cc618..06397aa 100644 --- a/src/util/stream.v +++ b/src/util/stream.v @@ -5,7 +5,7 @@ import io import os // reader_to_writer tries to consume the entire reader & write it to the writer. -pub fn reader_to_writer(mut reader io.Reader, mut writer io.Writer) ! { +pub fn reader_to_writer(mut reader io.Reader, mut writer io.Writer) ? { mut buf := []u8{len: 10 * 1024} for { @@ -21,8 +21,8 @@ pub fn reader_to_writer(mut reader io.Reader, mut writer io.Writer) ! { } // reader_to_file writes the contents of a BufferedReader to a file -pub fn reader_to_file(mut reader io.BufferedReader, length int, path string) ! { - mut file := os.create(path)! +pub fn reader_to_file(mut reader io.BufferedReader, length int, path string) ? { + mut file := os.create(path)? defer { file.close() } @@ -69,11 +69,11 @@ pub fn match_array_in_array(a1 []T, a2 []T) int { // read_until_separator consumes an io.Reader until it encounters some // separator array. The data read is stored inside the provided res array. -pub fn read_until_separator(mut reader io.Reader, mut res []u8, sep []u8) ! { +pub fn read_until_separator(mut reader io.Reader, mut res []u8, sep []u8) ? { mut buf := []u8{len: sep.len} for { - c := reader.read(mut buf)! + c := reader.read(mut buf)? res << buf[..c] match_len := match_array_in_array(buf[..c], sep) @@ -84,7 +84,7 @@ pub fn read_until_separator(mut reader io.Reader, mut res []u8, sep []u8) ! { if match_len > 0 { match_left := sep.len - match_len - c2 := reader.read(mut buf[..match_left])! + c2 := reader.read(mut buf[..match_left])? res << buf[..c2] if buf[..c2] == sep[match_len..] { diff --git a/src/util/util.v b/src/util/util.v index 213104c..4cd374e 100644 --- a/src/util/util.v +++ b/src/util/util.v @@ -23,7 +23,7 @@ pub fn exit_with_message(code int, msg string) { } // hash_file returns the sha256 hash of a given file -pub fn hash_file(path &string) !string { +pub fn hash_file(path &string) ?string { file := os.open(path) or { return error('Failed to open file.') } mut sha256sum := sha256.new() @@ -39,7 +39,7 @@ pub fn hash_file(path &string) !string { // This function never actually fails, but returns an option to follow // the Writer interface. - sha256sum.write(buf[..bytes_read])! + sha256sum.write(buf[..bytes_read])? } return sha256sum.checksum().hex() diff --git a/src/web/logging.v b/src/web/logging.v index 12b07d7..fc697ff 100644 --- a/src/web/logging.v +++ b/src/web/logging.v @@ -3,33 +3,33 @@ module web import log // log reate a log message with the given level -pub fn (mut ctx Context) log(msg string, level log.Level) { +pub fn (mut ctx Context) log(msg &string, level log.Level) { lock ctx.logger { ctx.logger.send_output(msg, level) } } // lfatal create a log message with the fatal level -pub fn (mut ctx Context) lfatal(msg string) { +pub fn (mut ctx Context) lfatal(msg &string) { ctx.log(msg, log.Level.fatal) } // lerror create a log message with the error level -pub fn (mut ctx Context) lerror(msg string) { +pub fn (mut ctx Context) lerror(msg &string) { ctx.log(msg, log.Level.error) } // lwarn create a log message with the warn level -pub fn (mut ctx Context) lwarn(msg string) { +pub fn (mut ctx Context) lwarn(msg &string) { ctx.log(msg, log.Level.warn) } // linfo create a log message with the info level -pub fn (mut ctx Context) linfo(msg string) { +pub fn (mut ctx Context) linfo(msg &string) { ctx.log(msg, log.Level.info) } // ldebug create a log message with the debug level -pub fn (mut ctx Context) ldebug(msg string) { +pub fn (mut ctx Context) ldebug(msg &string) { ctx.log(msg, log.Level.debug) }