hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit a3ce0eca32d2c5570034530fe2f7d5c49b8c1c8f
parent 0cf6503998baa3f68b9d680f2f4d448bf291f7f9
Author: Sebastian <sebastian@sebsite.pw>
Date:   Sun, 29 Jan 2023 01:27:40 -0500

haredoc: get default tags from `hare version`

If hare isn't found in PATH, haredoc falls back to just setting the
platform and architecture as tags, like it already used to.

Signed-off-by: Sebastian <sebastian@sebsite.pw>

Diffstat:
Mcmd/hare/subcmds.ha | 1-
Mcmd/haredoc/env.ha | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Mcmd/haredoc/errors.ha | 6+++++-
Mcmd/haredoc/main.ha | 7++++++-
4 files changed, 64 insertions(+), 13 deletions(-)

diff --git a/cmd/hare/subcmds.ha b/cmd/hare/subcmds.ha @@ -553,7 +553,6 @@ fn version(args: []str) void = { fmt::printfln("Hare {}", VERSION)!; if (verbose) { - fmt::errorln()!; fmt::printf("Build tags\t")!; const build_target = default_target(); const tags = build_target.tags; diff --git a/cmd/haredoc/env.ha b/cmd/haredoc/env.ha @@ -1,23 +1,66 @@ // License: GPL-3.0 // (c) 2021 Drew DeVault <sir@cmpwn.com> // (c) 2022 Haelwenn (lanodan) Monnier <contact@hacktivis.me> +use bufio; +use fmt; use hare::module; +use io; use os::exec; use os; use strings; def PLATFORM: str = "unknown"; -fn default_tags() []module::tag = { - // TODO: Once os::exec can handle pipes, we should read the default tags - // from $(hare version). - return alloc([module::tag { - name = strings::dup(PLATFORM), - mode = module::tag_mode::INCLUSIVE, - }, module::tag { - name = strings::dup(os::machine()), - mode = module::tag_mode::INCLUSIVE, - }]); +fn default_tags() ([]module::tag | error) = { + let cmd = match (exec::cmd("hare", "version", "-v")) { + case let cmd: exec::command => + yield cmd; + case exec::nocmd => + let platform = strings::dup(PLATFORM); + let machine = strings::dup(os::machine()); + fmt::errorln("Couldn't find hare binary in PATH")?; + fmt::errorfln("Build tags defaulting to +{}+{}", + platform, machine)?; + + return alloc([module::tag { + name = platform, + mode = module::tag_mode::INCLUSIVE, + }, module::tag { + name = machine, + mode = module::tag_mode::INCLUSIVE, + }]); + case let err: exec::error => + return err; + }; + + let pipe = exec::pipe(); + exec::addfile(&cmd, os::stdout_file, pipe.1); + let proc = exec::start(&cmd)?; + io::close(pipe.1)?; + + let tags: []module::tag = []; + for (true) match (bufio::scanline(pipe.0)?) { + case let b: []u8 => + defer free(b); + const (k, v) = strings::cut(strings::fromutf8(b)!, "\t"); + if (k == "Build tags") { + tags = module::parsetags(v) as []module::tag; + break; + }; + case io::EOF => + // process exited with failure; handled below + break; + }; + + io::close(pipe.0)?; + let status = exec::wait(&proc)?; + match (exec::check(&status)) { + case void => + assert(len(tags) > 0); + case let status: !exec::exit_status => + fmt::fatal("Error: hare:", exec::exitstr(status)); + }; + return tags; }; fn addtags(tags: []module::tag, in: str) ([]module::tag | void) = { diff --git a/cmd/haredoc/errors.ha b/cmd/haredoc/errors.ha @@ -5,8 +5,10 @@ use hare::lex; use hare::module; use hare::parse; use io; +use os::exec; -type error = !(lex::error | parse::error | io::error | module::error); +type error = !(lex::error | parse::error | io::error | module::error | + exec::error); fn strerror(err: error) str = { match (err) { @@ -18,5 +20,7 @@ fn strerror(err: error) str = { return io::strerror(err); case let err: module::error => return module::strerror(err); + case let err: exec::error => + return exec::strerror(err); }; }; diff --git a/cmd/haredoc/main.ha b/cmd/haredoc/main.ha @@ -48,7 +48,12 @@ export fn main() void = { }; let template = true; let show_undocumented = false; - let tags = default_tags(); + let tags = match (default_tags()) { + case let t: []module::tag => + yield t; + case let err: exec::error => + fmt::fatal(strerror(err)); + }; defer module::tags_free(tags); const help: [_]getopt::help = [