diff --git a/.gitignore b/.gitignore index a2804fe6..aaec9ef0 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ gdb.txt # Generated docs _docs/ +docs/resources/_gen/ /man/ # VLS logs diff --git a/.woodpecker/arch-rel.yml b/.woodpecker/arch-rel.yml index f5f228ef..f7274866 100644 --- a/.woodpecker/arch-rel.yml +++ b/.woodpecker/arch-rel.yml @@ -9,7 +9,7 @@ skip_clone: true pipeline: build: - image: 'menci/archlinuxarm:base-devel' + image: 'git.rustybever.be/vieter-v/vieter-builder' 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 8f1a6ff0..f5f84323 100644 --- a/.woodpecker/arch.yml +++ b/.woodpecker/arch.yml @@ -9,7 +9,7 @@ skip_clone: true pipeline: build: - image: 'menci/archlinuxarm:base-devel' + image: 'git.rustybever.be/vieter-v/vieter-builder' 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 9ee80853..f10e2a5a 100644 --- a/.woodpecker/build.yml +++ b/.woodpecker/build.yml @@ -1,5 +1,5 @@ variables: - - &vlang_image 'chewingbever/vlang:0.3' + - &vlang_image 'git.rustybever.be/chewing_bever/vlang:0.3.2' matrix: PLATFORM: diff --git a/.woodpecker/docs.yml b/.woodpecker/docs.yml index 048b1ad9..cf4874e9 100644 --- a/.woodpecker/docs.yml +++ b/.woodpecker/docs.yml @@ -1,5 +1,5 @@ variables: - - &vlang_image 'chewingbever/vlang:0.3' + - &vlang_image 'git.rustybever.be/chewing_bever/vlang:0.3.2' platform: 'linux/amd64' branches: diff --git a/.woodpecker/gitea.yml b/.woodpecker/gitea.yml index 8e3b9d44..9034f337 100644 --- a/.woodpecker/gitea.yml +++ b/.woodpecker/gitea.yml @@ -1,5 +1,5 @@ variables: - - &vlang_image 'chewingbever/vlang:0.3' + - &vlang_image 'git.rustybever.be/chewing_bever/vlang:0.3.2' platform: 'linux/amd64' branches: [ 'main' ] diff --git a/.woodpecker/lint.yml b/.woodpecker/lint.yml index c80ce338..ec64d132 100644 --- a/.woodpecker/lint.yml +++ b/.woodpecker/lint.yml @@ -1,5 +1,5 @@ variables: - - &vlang_image 'chewingbever/vlang:0.3' + - &vlang_image 'git.rustybever.be/chewing_bever/vlang:0.3.2' # These checks already get performed on the feature branches branches: @@ -7,10 +7,21 @@ branches: platform: 'linux/amd64' pipeline: + # vfmt seems to get confused if these aren't present + install-modules: + image: *vlang_image + pull: true + commands: + - export VMODULES=$PWD/.vmodules + - 'cd src && v install' + when: + event: [pull_request] + lint: image: *vlang_image pull: true commands: + - export VMODULES=$PWD/.vmodules - make lint when: - event: [ pull_request ] + event: [pull_request] diff --git a/.woodpecker/man.yml b/.woodpecker/man.yml index 86a1bd8c..8c6ca068 100644 --- a/.woodpecker/man.yml +++ b/.woodpecker/man.yml @@ -1,5 +1,5 @@ variables: - - &vlang_image 'chewingbever/vlang:0.3' + - &vlang_image 'git.rustybever.be/chewing_bever/vlang:0.3.2' platform: 'linux/amd64' branches: diff --git a/.woodpecker/test.yml b/.woodpecker/test.yml index 08b7534f..39cb9f9b 100644 --- a/.woodpecker/test.yml +++ b/.woodpecker/test.yml @@ -1,5 +1,5 @@ variables: - - &vlang_image 'chewingbever/vlang:0.3' + - &vlang_image 'git.rustybever.be/chewing_bever/vlang:0.3.2' matrix: PLATFORM: diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cd39c4a..18311d77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased](https://git.rustybever.be/vieter-v/vieter/src/branch/dev) +### Changed + +* Migrated codebase to V 0.3.2 + ## [0.4.0](https://git.rustybever.be/vieter-v/vieter/src/tag/0.4.0) ### Added diff --git a/Dockerfile b/Dockerfile index 7aed9179..210ae66d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM chewingbever/vlang:0.3 AS builder +FROM git.rustybever.be/chewing_bever/vlang:0.3.2 AS builder ARG TARGETPLATFORM ARG CI_COMMIT_SHA diff --git a/Makefile b/Makefile index 69bd7957..e7168076 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 +V := $(V_PATH) -showcc -gc boehm -W -d use_openssl all: vieter @@ -92,9 +92,9 @@ clean: .PHONY: autofree autofree: afvieter afvieter: $(SOURCES) - $(V_PATH) -showcc -autofree -o afvieter $(SRC_DIR) + $(V) -showcc -autofree -o afvieter $(SRC_DIR) .PHONY: skip-unused skip-unused: suvieter suvieter: $(SOURCES) - $(V_PATH) -showcc -skip-unused -o suvieter $(SRC_DIR) + $(V) -skip-unused -o suvieter $(SRC_DIR) diff --git a/src/build/build.v b/src/build/build.v index 2ad70a6f..247df6e9 100644 --- a/src/build/build.v +++ b/src/build/build.v @@ -1,6 +1,6 @@ module build -import vieter_v.docker +import docker import encoding.base64 import time import os @@ -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 d68ff18f..aa6094ae 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,31 +38,33 @@ fn (c &Client) send_request_raw(method Method, url string, params map[string]str full_url = '$full_url?$params_str' } - mut req := http.new_request(method, full_url, body)? - req.add_custom_header('X-Api-Key', c.api_key)? + // 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)! - 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 b4142450..eaddc8cf 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 c5e44fea..fd4254c6 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 c98f8e68..a6a33242 100644 --- a/src/console/aur/aur.v +++ b/src/console/aur/aur.v @@ -3,8 +3,8 @@ module aur import cli import console import client -import vieter_v.aur -import vieter_v.conf as vconf +import aur +import conf as vconf struct Config { address string [required] @@ -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 caf4cca7..5c40de8c 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 41830c25..1330dd06 100644 --- a/src/console/logs/logs.v +++ b/src/console/logs/logs.v @@ -1,7 +1,7 @@ module logs import cli -import vieter_v.conf as vconf +import conf as vconf import client import console import time @@ -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 d91a140f..22cb5f7b 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 8fceddd9..7ce0516e 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 6337aa3e..93685588 100644 --- a/src/console/targets/build.v +++ b/src/console/targets/build.v @@ -1,34 +1,34 @@ module targets import client -import vieter_v.docker +import docker 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 56400117..521ca234 100644 --- a/src/console/targets/targets.v +++ b/src/console/targets/targets.v @@ -1,7 +1,7 @@ module targets import cli -import vieter_v.conf as vconf +import conf as vconf import cron.expression { parse_expression } import client { NewTarget } import console @@ -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 4d958339..16a3537f 100644 --- a/src/cron/cli.v +++ b/src/cron/cli.v @@ -1,7 +1,7 @@ module cron import cli -import vieter_v.conf as vconf +import conf as vconf struct Config { pub: @@ -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 5f128cf0..f1d6b7bd 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 934d35a0..0d30a23b 100644 --- a/src/cron/daemon/daemon.v +++ b/src/cron/daemon/daemon.v @@ -6,7 +6,7 @@ import datatypes { MinHeap } import cron.expression { CronExpression, parse_expression } import math import build -import vieter_v.docker +import docker import os import client import models { Target } @@ -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 003898b5..95a50e74 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 17d2dde2..438805d3 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/cron/expression/expression_parse_test.v b/src/cron/expression/expression_parse_test.v index 4eebc49e..5c12329d 100644 --- a/src/cron/expression/expression_parse_test.v +++ b/src/cron/expression/expression_parse_test.v @@ -11,88 +11,88 @@ fn parse_range_error(s string, min int, max int) string { } // =====parse_range===== -fn test_range_star_range() ? { +fn test_range_star_range() ! { mut bitv := []bool{len: 6, init: false} - parse_range('*', 0, 5, mut bitv)? + parse_range('*', 0, 5, mut bitv)! assert bitv == [true, true, true, true, true, true] } -fn test_range_number() ? { +fn test_range_number() ! { mut bitv := []bool{len: 6, init: false} - parse_range('4', 0, 5, mut bitv)? + parse_range('4', 0, 5, mut bitv)! assert bitv_to_ints(bitv, 0) == [4] } -fn test_range_number_too_large() ? { +fn test_range_number_too_large() ! { assert parse_range_error('10', 0, 6) == 'Out of range.' } -fn test_range_number_too_small() ? { +fn test_range_number_too_small() ! { assert parse_range_error('0', 2, 6) == 'Out of range.' } -fn test_range_number_invalid() ? { +fn test_range_number_invalid() ! { assert parse_range_error('x', 0, 6) == 'Invalid number.' } -fn test_range_step_star_1() ? { +fn test_range_step_star_1() ! { mut bitv := []bool{len: 21, init: false} - parse_range('*/4', 0, 20, mut bitv)? + parse_range('*/4', 0, 20, mut bitv)! assert bitv_to_ints(bitv, 0) == [0, 4, 8, 12, 16, 20] } -fn test_range_step_star_2() ? { +fn test_range_step_star_2() ! { mut bitv := []bool{len: 8, init: false} - parse_range('*/3', 1, 8, mut bitv)? + parse_range('*/3', 1, 8, mut bitv)! assert bitv_to_ints(bitv, 1) == [1, 4, 7] } -fn test_range_step_star_too_large() ? { +fn test_range_step_star_too_large() ! { assert parse_range_error('*/21', 0, 20) == 'Step size too large.' } -fn test_range_step_zero() ? { +fn test_range_step_zero() ! { assert parse_range_error('*/0', 0, 20) == 'Step size zero not allowed.' } -fn test_range_step_number() ? { +fn test_range_step_number() ! { mut bitv := []bool{len: 21, init: false} - parse_range('5/4', 2, 22, mut bitv)? + parse_range('5/4', 2, 22, mut bitv)! assert bitv_to_ints(bitv, 2) == [5, 9, 13, 17, 21] } -fn test_range_step_number_too_large() ? { +fn test_range_step_number_too_large() ! { assert parse_range_error('10/4', 0, 5) == 'Out of range.' } -fn test_range_step_number_too_small() ? { +fn test_range_step_number_too_small() ! { assert parse_range_error('2/4', 5, 10) == 'Out of range.' } -fn test_range_dash() ? { +fn test_range_dash() ! { mut bitv := []bool{len: 10, init: false} - parse_range('4-8', 0, 9, mut bitv)? + parse_range('4-8', 0, 9, mut bitv)! assert bitv_to_ints(bitv, 0) == [4, 5, 6, 7, 8] } -fn test_range_dash_step() ? { +fn test_range_dash_step() ! { mut bitv := []bool{len: 10, init: false} - parse_range('4-8/2', 0, 9, mut bitv)? + parse_range('4-8/2', 0, 9, mut bitv)! assert bitv_to_ints(bitv, 0) == [4, 6, 8] } // =====parse_part===== -fn test_part_single() ? { - assert parse_part('*', 0, 5)? == [0, 1, 2, 3, 4, 5] +fn test_part_single() ! { + assert parse_part('*', 0, 5)! == [0, 1, 2, 3, 4, 5] } -fn test_part_multiple() ? { - assert parse_part('*/2,2/3', 1, 8)? == [1, 2, 3, 5, 7, 8] +fn test_part_multiple() ! { + assert parse_part('*/2,2/3', 1, 8)! == [1, 2, 3, 5, 7, 8] } diff --git a/src/cron/expression/expression_test.v b/src/cron/expression/expression_test.v index 9e25e924..82bf9598 100644 --- a/src/cron/expression/expression_test.v +++ b/src/cron/expression/expression_test.v @@ -2,12 +2,12 @@ module expression import time { parse } -fn util_test_time(exp string, t1_str string, t2_str string) ? { - ce := parse_expression(exp)? - t1 := parse(t1_str)? - t2 := parse(t2_str)? +fn util_test_time(exp string, t1_str string, t2_str string) ! { + ce := parse_expression(exp)! + t1 := parse(t1_str)! + t2 := parse(t2_str)! - t3 := ce.next(t1)? + t3 := ce.next(t1)! assert t2.year == t3.year assert t2.month == t3.month @@ -16,19 +16,19 @@ fn util_test_time(exp string, t1_str string, t2_str string) ? { assert t2.minute == t3.minute } -fn test_next_simple() ? { +fn test_next_simple() ! { // Very simple - util_test_time('0 3', '2002-01-01 00:00:00', '2002-01-01 03:00:00')? + util_test_time('0 3', '2002-01-01 00:00:00', '2002-01-01 03:00:00')! // Overlap to next day - util_test_time('0 3', '2002-01-01 03:00:00', '2002-01-02 03:00:00')? - util_test_time('0 3', '2002-01-01 04:00:00', '2002-01-02 03:00:00')? + util_test_time('0 3', '2002-01-01 03:00:00', '2002-01-02 03:00:00')! + util_test_time('0 3', '2002-01-01 04:00:00', '2002-01-02 03:00:00')! - util_test_time('0 3/4', '2002-01-01 04:00:00', '2002-01-01 07:00:00')? + util_test_time('0 3/4', '2002-01-01 04:00:00', '2002-01-01 07:00:00')! // Overlap to next month - util_test_time('0 3', '2002-11-31 04:00:00', '2002-12-01 03:00:00')? + util_test_time('0 3', '2002-11-31 04:00:00', '2002-12-01 03:00:00')! // Overlap to next year - util_test_time('0 3', '2002-12-31 04:00:00', '2003-01-01 03:00:00')? + util_test_time('0 3', '2002-12-31 04:00:00', '2003-01-01 03:00:00')! } diff --git a/src/db/db.v b/src/db/db.v index 9459c052..b8b861aa 100644 --- a/src/db/db.v +++ b/src/db/db.v @@ -26,8 +26,8 @@ const ( ) // init initializes a database & adds the correct tables. -pub fn init(db_path string) ?VieterDb { - conn := sqlite.connect(db_path)? +pub fn init(db_path string) !VieterDb { + conn := sqlite.connect(db_path)! sql conn { create table MigrationVersion diff --git a/src/package/package.v b/src/package/package.v index 9eaf5a23..aadf6f2b 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/repo/add.v b/src/repo/add.v index 608ca501..8ab3ae1f 100644 --- a/src/repo/add.v +++ b/src/repo/add.v @@ -29,7 +29,7 @@ pub: } // new creates a new RepoGroupManager & creates the directories as needed -pub fn new(repos_dir string, pkg_dir string, default_arch string) ?RepoGroupManager { +pub fn new(repos_dir string, pkg_dir string, default_arch string) !RepoGroupManager { if !os.is_dir(repos_dir) { os.mkdir_all(repos_dir) or { return error('Failed to create repos directory: $err.msg()') } } @@ -49,27 +49,27 @@ pub fn new(repos_dir string, pkg_dir string, default_arch string) ?RepoGroupMana // pkg archive. It's a wrapper around add_pkg_in_repo that parses the archive // file, passes the result to add_pkg_in_repo, and hard links the archive to // the right subdirectories in r.pkg_dir if it was successfully added. -pub fn (r &RepoGroupManager) add_pkg_from_path(repo string, pkg_path string) ?RepoAddResult { +pub fn (r &RepoGroupManager) add_pkg_from_path(repo string, pkg_path string) !RepoAddResult { pkg := package.read_pkg_archive(pkg_path) or { return error('Failed to read package file: $err.msg()') } - archs := r.add_pkg_in_repo(repo, pkg)? + archs := r.add_pkg_in_repo(repo, pkg)! // If the add was successful, we move the file to the packages directory for arch in archs { repo_pkg_path := os.real_path(os.join_path(r.pkg_dir, repo, arch)) dest_path := os.join_path_single(repo_pkg_path, pkg.filename()) - os.mkdir_all(repo_pkg_path)? + os.mkdir_all(repo_pkg_path)! // We create hard links so that "any" arch packages aren't stored // multiple times - os.link(pkg_path, dest_path)? + os.link(pkg_path, dest_path)! } // After linking, we can remove the original file - os.rm(pkg_path)? + os.rm(pkg_path)! return RepoAddResult{ name: pkg.info.name @@ -85,11 +85,11 @@ pub fn (r &RepoGroupManager) add_pkg_from_path(repo string, pkg_path string) ?Re // r.default_arch. If this arch-repo doesn't exist yet, it is created. If the // architecture isn't 'any', the package is only added to the specific // architecture. -fn (r &RepoGroupManager) add_pkg_in_repo(repo string, pkg &package.Pkg) ?[]string { +fn (r &RepoGroupManager) add_pkg_in_repo(repo string, pkg &package.Pkg) ![]string { // A package not of arch 'any' can be handled easily by adding it to the // respective repo if pkg.info.arch != 'any' { - r.add_pkg_in_arch_repo(repo, pkg.info.arch, pkg)? + r.add_pkg_in_arch_repo(repo, pkg.info.arch, pkg)! return [pkg.info.arch] } @@ -104,7 +104,7 @@ fn (r &RepoGroupManager) add_pkg_in_repo(repo string, pkg &package.Pkg) ?[]strin // If this is the first package that's added to the repo, the directory // won't exist yet if os.exists(repo_dir) { - arch_repos = os.ls(repo_dir)? + arch_repos = os.ls(repo_dir)! } // The default_arch should always be updated when a package with arch 'any' @@ -118,7 +118,7 @@ fn (r &RepoGroupManager) add_pkg_in_repo(repo string, pkg &package.Pkg) ?[]strin // not know which arch-repositories did succeed in adding the package, if // any. for arch in arch_repos { - r.add_pkg_in_arch_repo(repo, arch, pkg)? + r.add_pkg_in_arch_repo(repo, arch, pkg)! } return arch_repos @@ -128,24 +128,24 @@ fn (r &RepoGroupManager) add_pkg_in_repo(repo string, pkg &package.Pkg) ?[]strin // arch-repo. It records the package's data in the arch-repo's desc & files // files, and afterwards updates the db & files archives to reflect these // changes. -fn (r &RepoGroupManager) add_pkg_in_arch_repo(repo string, arch string, pkg &package.Pkg) ? { +fn (r &RepoGroupManager) add_pkg_in_arch_repo(repo string, arch string, pkg &package.Pkg) ! { pkg_dir := os.join_path(r.repos_dir, repo, arch, '$pkg.info.name-$pkg.info.version') // Remove the previous version of the package, if present - r.remove_pkg_from_arch_repo(repo, arch, pkg.info.name, false)? + r.remove_pkg_from_arch_repo(repo, arch, pkg.info.name, false)! os.mkdir_all(pkg_dir) or { return error('Failed to create package directory.') } - os.write_file(os.join_path_single(pkg_dir, 'desc'), pkg.to_desc()?) or { - os.rmdir_all(pkg_dir)? + os.write_file(os.join_path_single(pkg_dir, 'desc'), pkg.to_desc()!) or { + os.rmdir_all(pkg_dir)! return error('Failed to write desc file.') } os.write_file(os.join_path_single(pkg_dir, 'files'), pkg.to_files()) or { - os.rmdir_all(pkg_dir)? + os.rmdir_all(pkg_dir)! return error('Failed to write files file.') } - r.sync(repo, arch)? + r.sync(repo, arch)! } diff --git a/src/repo/remove.v b/src/repo/remove.v index add921cb..63866a95 100644 --- a/src/repo/remove.v +++ b/src/repo/remove.v @@ -5,7 +5,7 @@ import os // remove_pkg_from_arch_repo removes a package from an arch-repo's database. It // returns false if the package wasn't present in the database. It also // optionally re-syncs the repo archives. -pub fn (r &RepoGroupManager) remove_pkg_from_arch_repo(repo string, arch string, pkg_name string, sync bool) ?bool { +pub fn (r &RepoGroupManager) remove_pkg_from_arch_repo(repo string, arch string, pkg_name string, sync bool) !bool { repo_dir := os.join_path(r.repos_dir, repo, arch) // If the repository doesn't exist yet, the result is automatically false @@ -15,7 +15,7 @@ pub fn (r &RepoGroupManager) remove_pkg_from_arch_repo(repo string, arch string, // We iterate over every directory in the repo dir // TODO filter so we only check directories - for d in os.ls(repo_dir)? { + for d in os.ls(repo_dir)! { // Because a repository only allows a single version of each package, // we need only compare whether the name of the package is the same, // not the version. @@ -25,22 +25,22 @@ pub fn (r &RepoGroupManager) remove_pkg_from_arch_repo(repo string, arch string, // We lock the mutex here to prevent other routines from creating a // new archive while we remove an entry lock r.mutex { - os.rmdir_all(os.join_path_single(repo_dir, d))? + os.rmdir_all(os.join_path_single(repo_dir, d))! } // Also remove the package archive repo_pkg_dir := os.join_path(r.pkg_dir, repo, arch) - archives := os.ls(repo_pkg_dir)?.filter(it.split('-')#[..-3].join('-') == name) + archives := os.ls(repo_pkg_dir)!.filter(it.split('-')#[..-3].join('-') == name) for archive_name in archives { full_path := os.join_path_single(repo_pkg_dir, archive_name) - os.rm(full_path)? + os.rm(full_path)! } // Sync the db archives if requested if sync { - r.sync(repo, arch)? + r.sync(repo, arch)! } return true @@ -51,7 +51,7 @@ pub fn (r &RepoGroupManager) remove_pkg_from_arch_repo(repo string, arch string, } // remove_arch_repo removes an arch-repo & its packages. -pub fn (r &RepoGroupManager) remove_arch_repo(repo string, arch string) ?bool { +pub fn (r &RepoGroupManager) remove_arch_repo(repo string, arch string) !bool { repo_dir := os.join_path(r.repos_dir, repo, arch) // If the repository doesn't exist yet, the result is automatically false @@ -59,16 +59,16 @@ pub fn (r &RepoGroupManager) remove_arch_repo(repo string, arch string) ?bool { return false } - os.rmdir_all(repo_dir)? + os.rmdir_all(repo_dir)! pkg_dir := os.join_path(r.pkg_dir, repo, arch) - os.rmdir_all(pkg_dir)? + os.rmdir_all(pkg_dir)! return true } // remove_repo removes a repo & its packages. -pub fn (r &RepoGroupManager) remove_repo(repo string) ?bool { +pub fn (r &RepoGroupManager) remove_repo(repo string) !bool { repo_dir := os.join_path_single(r.repos_dir, repo) // If the repository doesn't exist yet, the result is automatically false @@ -76,10 +76,10 @@ pub fn (r &RepoGroupManager) remove_repo(repo string) ?bool { return false } - os.rmdir_all(repo_dir)? + os.rmdir_all(repo_dir)! pkg_dir := os.join_path_single(r.pkg_dir, repo) - os.rmdir_all(pkg_dir)? + os.rmdir_all(pkg_dir)! return true } diff --git a/src/repo/sync.v b/src/repo/sync.v index 73d21c88..95547484 100644 --- a/src/repo/sync.v +++ b/src/repo/sync.v @@ -32,7 +32,7 @@ fn archive_add_entry(archive &C.archive, entry &C.archive_entry, file_path &stri } // sync regenerates the repository archive files. -fn (r &RepoGroupManager) sync(repo string, arch string) ? { +fn (r &RepoGroupManager) sync(repo string, arch string) ! { subrepo_path := os.join_path(r.repos_dir, repo, arch) lock r.mutex { @@ -54,7 +54,7 @@ fn (r &RepoGroupManager) sync(repo string, arch string) ? { C.archive_write_open_filename(a_files, &char(files_path.str)) // Iterate over each directory - for d in os.ls(subrepo_path)?.filter(os.is_dir(os.join_path_single(subrepo_path, + for d in os.ls(subrepo_path)!.filter(os.is_dir(os.join_path_single(subrepo_path, it))) { // desc mut inner_path := os.join_path_single(d, 'desc') diff --git a/src/server/api_logs.v b/src/server/api_logs.v index 287755a9..fcbf0248 100644 --- a/src/server/api_logs.v +++ b/src/server/api_logs.v @@ -43,9 +43,9 @@ fn (mut app App) v1_get_log_content(id int) web.Result { // parse_query_time unescapes an HTTP query parameter & tries to parse it as a // time.Time struct. -fn parse_query_time(query string) ?time.Time { - unescaped := urllib.query_unescape(query)? - t := time.parse(unescaped)? +fn parse_query_time(query string) !time.Time { + unescaped := urllib.query_unescape(query)! + t := time.parse(unescaped)! return t } diff --git a/src/server/cli.v b/src/server/cli.v index 6fd09c54..a9644f35 100644 --- a/src/server/cli.v +++ b/src/server/cli.v @@ -1,7 +1,7 @@ module server import cli -import vieter_v.conf as vconf +import conf as vconf struct Config { pub: @@ -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 9903cea9..d5f61359 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 06397aa8..15cc6186 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 4cd374e7..213104c3 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 fc697ffc..12b07d7a 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) } diff --git a/src/web/parse.v b/src/web/parse.v index ee7a72cc..7af635fb 100644 --- a/src/web/parse.v +++ b/src/web/parse.v @@ -8,7 +8,7 @@ import net.http const attrs_to_ignore = ['auth'] // Parsing function attributes for methods and path. -fn parse_attrs(name string, attrs []string) ?([]http.Method, string) { +fn parse_attrs(name string, attrs []string) !([]http.Method, string) { if attrs.len == 0 { return [http.Method.get], '/$name' } @@ -61,7 +61,7 @@ fn parse_query_from_url(url urllib.URL) map[string]string { } // Extract form data from an HTTP request. -fn parse_form_from_request(request http.Request) ?(map[string]string, map[string][]http.FileData) { +fn parse_form_from_request(request http.Request) !(map[string]string, map[string][]http.FileData) { mut form := map[string]string{} mut files := map[string][]http.FileData{} if request.method in methods_with_form { diff --git a/src/web/web.v b/src/web/web.v index 1d1480fb..1b40e7a3 100644 --- a/src/web/web.v +++ b/src/web/web.v @@ -24,7 +24,7 @@ pub: pub mut: // TCP connection to client. // But beware, do not store it for further use, after request processing web will close connection. - conn &net.TcpConn + conn &net.TcpConn = unsafe { nil } // Gives access to a shared logger object logger shared log.Log // time.ticks() from start of web connection handle. @@ -67,20 +67,20 @@ struct Route { pub fn (ctx Context) before_request() {} // send_string writes the given string to the TCP connection socket. -fn (mut ctx Context) send_string(s string) ? { - ctx.conn.write(s.bytes())? +fn (mut ctx Context) send_string(s string) ! { + ctx.conn.write(s.bytes())! } // send_reader reads at most `size` bytes from the given reader & writes them // to the TCP connection socket. Internally, a 10KB buffer is used, to avoid // having to store all bytes in memory at once. -fn (mut ctx Context) send_reader(mut reader io.Reader, size u64) ? { +fn (mut ctx Context) send_reader(mut reader io.Reader, size u64) ! { mut buf := []u8{len: 10_000} mut bytes_left := size // Repeat as long as the stream still has data for bytes_left > 0 { - bytes_read := reader.read(mut buf)? + bytes_read := reader.read(mut buf)! bytes_left -= u64(bytes_read) mut to_write := bytes_read @@ -96,20 +96,20 @@ fn (mut ctx Context) send_reader(mut reader io.Reader, size u64) ? { // send_custom_response sends the given http.Response to the client. It can be // used to overwrite the Context object & send a completely custom // http.Response instead. -fn (mut ctx Context) send_custom_response(resp &http.Response) ? { - ctx.send_string(resp.bytestr())? +fn (mut ctx Context) send_custom_response(resp &http.Response) ! { + ctx.send_string(resp.bytestr())! } // send_response_header constructs a valid HTTP response with an empty body & // sends it to the client. -pub fn (mut ctx Context) send_response_header() ? { +pub fn (mut ctx Context) send_response_header() ! { mut resp := http.new_response( header: ctx.header.join(headers_close) ) resp.header.add(.content_type, ctx.content_type) resp.set_status(ctx.status) - ctx.send_custom_response(resp)? + ctx.send_custom_response(resp)! } // send is a convenience function for sending the HTTP response with an empty