commit eb87aeb261301f19d6a250b696dc9b7444673181
parent 6f4cbf33e55785d9b282f5f6910e8dff9251ba98
Author: Alexey Yerin <yyp@disroot.org>
Date: Tue, 22 Feb 2022 19:06:33 +0300
cmd/hare: clear the indicator if a build error happens
Also refactor it a little bit while here.
Signed-off-by: Alexey Yerin <yyp@disroot.org>
Diffstat:
3 files changed, 105 insertions(+), 40 deletions(-)
diff --git a/Makefile b/Makefile
@@ -25,6 +25,7 @@ include stdlib.mk
hare_srcs=\
./cmd/hare/main.ha \
./cmd/hare/plan.ha \
+ ./cmd/hare/progress.ha \
./cmd/hare/release.ha \
./cmd/hare/schedule.ha \
./cmd/hare/subcmds.ha
diff --git a/cmd/hare/plan.ha b/cmd/hare/plan.ha
@@ -7,7 +7,6 @@ use fs;
use hare::ast;
use hare::module;
use io;
-use math;
use os::exec;
use os;
use path;
@@ -58,6 +57,14 @@ type plan = struct {
libs: []str,
environ: [](str, str),
modmap: [64][]modcache,
+ progress: plan_progress,
+};
+
+type plan_progress = struct {
+ tty: (io::file | void),
+ complete: size,
+ total: size,
+ current_module: str,
};
fn mkplan(ctx: *module::context, libs: []str) plan = {
@@ -95,6 +102,10 @@ fn mkplan(ctx: *module::context, libs: []str) plan = {
(strings::dup("HARECACHE"), strings::dup(ctx.cache)),
]),
libs = libs,
+ progress = plan_progress {
+ tty = if (tty::isatty(os::stderr)) os::stderr else void,
+ ...
+ },
...
};
};
@@ -128,10 +139,19 @@ fn plan_finish(plan: *plan) void = {
for (let i = 0z; i < len(plan.modmap); i += 1) {
free(plan.modmap[i]);
};
+
+ match (plan.progress.tty) {
+ case let f: io::file =>
+ io::close(f);
+ case => void;
+ };
};
fn plan_execute(plan: *plan, verbose: bool) (void | !exec::exit_status) = {
+ plan.progress.total = len(plan.scheduled);
+
if (verbose) {
+ plan.progress.tty = void;
for (let i = 0z; i < len(plan.environ); i += 1) {
// TODO: Uncomment this with shlex::quote
let item = plan.environ[i];
@@ -139,16 +159,6 @@ fn plan_execute(plan: *plan, verbose: bool) (void | !exec::exit_status) = {
};
};
- let current_module = "";
- let current = 0z;
- const total = len(plan.scheduled);
- // Disable progress when used with -v
- const term = if (!verbose && tty::isatty(os::stderr)) {
- yield os::stderr;
- } else {
- yield;
- };
-
for (len(plan.scheduled) != 0) {
let next: nullable *task = null;
let i = 0z;
@@ -176,37 +186,19 @@ fn plan_execute(plan: *plan, verbose: bool) (void | !exec::exit_status) = {
match (task.module) {
case let s: str =>
- current_module = s;
+ plan.progress.current_module = s;
case => void;
};
- match (term) {
- case let term: io::file =>
- current += 1;
- fmt::fprintf(term, "\r\x1b[K[{%}/{}] [",
- current, &fmt::modifiers {
- width = math::ceilf64(math::log10f64(
- total: f64)): uint,
- ...
- },
- total)!;
- const stop = (current: f64 / total: f64 * 50.0): size;
- for (let i = 0z; i < 50; i += 1) {
- if (i > stop) {
- fmt::fprint(term, ".")!;
- } else {
- fmt::fprint(term, "#")!;
- };
- };
- fmt::fprintf(term, "] {}", current_module)!;
- case => void;
- };
+ progress_increment(plan);
match (execute(plan, task, verbose)) {
case let err: exec::error =>
+ progress_clear(plan);
fmt::fatal("Error: {}: {}", task.cmd[0],
exec::strerror(err));
case let err: !exec::exit_status =>
+ progress_clear(plan);
fmt::errorfln("Error: {}: {}", task.cmd[0],
exec::exitstr(err))!;
return err;
@@ -219,12 +211,7 @@ fn plan_execute(plan: *plan, verbose: bool) (void | !exec::exit_status) = {
append(plan.complete, task);
};
- match (term) {
- case let term: io::file =>
- fmt::fprint(term, "\r\x1b[K")!;
- case => void;
- };
-
+ progress_clear(plan);
update_modcache(plan);
};
@@ -268,13 +255,39 @@ fn execute(
fmt::errorln()!;
};
- let cmd = exec::cmd(task.cmd[0], task.cmd[1..]...)?;
+ let cmd = exec::cmd(task.cmd[0], task.cmd[1..]...)!;
for (let i = 0z; i < len(plan.environ); i += 1) {
let e = plan.environ[i];
exec::setenv(&cmd, e.0, e.1);
};
+ const pipe = if (plan.progress.tty is io::file) {
+ const pipe = exec::pipe();
+ exec::addfile(&cmd, os::stderr, pipe.1);
+ yield pipe;
+ } else (0: io::file, 0: io::file);
+
let proc = exec::start(&cmd)?;
+ if (pipe.0 != 0) {
+ io::close(pipe.1);
+ };
+
+ let cleared = false;
+ if (pipe.0 != 0) {
+ for (true) {
+ let buf: [os::BUFSIZ]u8 = [0...];
+ match (io::read(pipe.0, buf)!) {
+ case let n: size =>
+ if (!cleared) {
+ progress_clear(plan);
+ cleared = true;
+ };
+ io::write(os::stderr, buf[..n])!;
+ case io::EOF =>
+ break;
+ };
+ };
+ };
let st = exec::wait(&proc)?;
return exec::check(&st);
};
diff --git a/cmd/hare/progress.ha b/cmd/hare/progress.ha
@@ -0,0 +1,51 @@
+use fmt;
+use io;
+use math;
+
+fn progress_update(plan: *plan) void = {
+ const tty = match (plan.progress.tty) {
+ case let f: io::file =>
+ yield f;
+ case =>
+ return;
+ };
+ const complete = plan.progress.complete,
+ total = plan.progress.total,
+ current_module = plan.progress.current_module;
+
+ fmt::fprintf(tty, "\r\x1b[K[{%}/{}] [",
+ complete, &fmt::modifiers {
+ width = math::ceilf64(math::log10f64(total: f64)): uint,
+ ...
+ },
+ total)!;
+ const stop = (complete: f64 / total: f64 * 50.0): size;
+ for (let i = 0z; i < 50; i += 1) {
+ if (i > stop) {
+ fmt::fprint(tty, ".")!;
+ } else {
+ fmt::fprint(tty, "#")!;
+ };
+ };
+ if (len(current_module) > 0) {
+ fmt::fprintf(tty, "] {}", current_module)!;
+ } else {
+ // Don't print a leading space
+ fmt::fprint(tty, "]")!;
+ };
+};
+
+fn progress_clear(plan: *plan) void = {
+ const tty = match (plan.progress.tty) {
+ case let f: io::file =>
+ yield f;
+ case =>
+ return;
+ };
+ fmt::fprint(tty, "\r\x1b[K")!;
+};
+
+fn progress_increment(plan: *plan) void = {
+ plan.progress.complete += 1;
+ progress_update(plan);
+};