hare

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

commit a34403b365af8c13f0868901ebfe31f3edbcf250
parent e7479d15649ad6693c5e33fbe6ee03b57e776b6f
Author: Sebastian <sebastian@sebsite.pw>
Date:   Sat,  9 Dec 2023 21:06:29 -0500

hare build: only overwrite executable files

Fixes: https://todo.sr.ht/~sircmpwn/hare/659
Signed-off-by: Sebastian <sebastian@sebsite.pw>

Diffstat:
Mcmd/hare/build.ha | 19+++++++++++++++++--
Mcmd/hare/error.ha | 3+++
Mcmd/hare/main.ha | 3+++
3 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/cmd/hare/build.ha b/cmd/hare/build.ha @@ -216,10 +216,25 @@ fn get_output(goal: build::stage, input: str) (str | error) = { if (goal != build::stage::BIN) { path::push_ext(&buf, build::stage_ext[goal])?; }; - match (path::peek(&buf)) { + + const output = match (path::peek(&buf)) { case let s: str => - return s; + yield s; case void => return unknown_output; }; + stat = match (os::stat(output)) { + case let s: fs::filestat => + yield s; + case errors::noentry => + return output; + case fs::error => + // XXX: double cast here (and below) shouldn't be necessary + return output: output_exists: error; + }; + if (!fs::isfile(stat.mode) + || fs::mode_perm(stat.mode) & fs::mode::USER_X == 0) { + return output: output_exists: error; + }; + return output; }; diff --git a/cmd/hare/error.ha b/cmd/hare/error.ha @@ -21,6 +21,7 @@ type error = !( unknown_arch | unknown_output | unknown_type | + output_exists | output_failed | invalid_namespace | build::unknown_platform | @@ -32,6 +33,8 @@ type unknown_output = !void; type unknown_type = !str; +type output_exists = !str; + type output_failed = !(str, fs::error); type invalid_namespace = !str; diff --git a/cmd/hare/main.ha b/cmd/hare/main.ha @@ -122,6 +122,9 @@ export fn main() void = { fmt::fatal("Error: Can't guess output in root directory"); case let e: unknown_type => fmt::fatalf("Error: Unknown build type: {}", e); + case let e: output_exists => + fmt::fatalf("Error: Output path '{}' already exists, but isn't an executable file", + e); case let e: output_failed => fmt::fatalf("Error: Could not open output '{}': {}", e.0, fs::strerror(e.1));