hare

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

commit fc8562c4f5a93afaff824988d7cc191e75e450c9
parent b8499183ddef9e9170ba4bb8e5c60b60531b5f3f
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri, 26 Feb 2021 15:11:15 -0500

hare::module: compute hashes on scan

Diffstat:
Mhare/module/scan.ha | 37+++++++++++++++++++++++++++++++------
Mhare/module/types.ha | 2+-
Mhash/hash.ha | 3+++
3 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/hare/module/scan.ha b/hare/module/scan.ha @@ -1,24 +1,44 @@ +use crypto::sha256; +use encoding::hex; use fs; use hare::ast; +use hash; use io; use path; use slice; use strings; +fn hash_file(ctx: *context, path: path::path) (str | error) = { + let sha = sha256::sha256(); + //defer! hash::close(sha); + let f = fs::open(ctx.fs, path, io::mode::READ)?; + io::copy(hash::writer(sha), f)?; + let sum = hash::finish(sha); + defer free(sum); + return hex::encode(sum); +}; + // Scans the files in a directory for eligible build inputs and returns a // [version] which includes all applicable files. export fn scan(ctx: *context, path: path::path) (version | error) = { + let sha = sha256::sha256(); + //defer! hash::close(sha); let inputs: []input = []; let iter = match (fs::iter(ctx.fs, path)) { fs::wrongtype => { let st = fs::stat(ctx.fs, path)?; - append(inputs, input { + let in = input { path = path, stat = st, + hash = hash_file(ctx, path)?, ... - }); + }; + append(inputs, in); + hash::write(sha, strings::to_utf8(in.hash)); + let sum = hash::finish(sha); + defer free(sum); return version { - hash = "", // TODO + hash = hex::encode(sum), inputs = inputs, }; }, @@ -33,17 +53,22 @@ export fn scan(ctx: *context, path: path::path) (version | error) = { fs::mode::REG => if (eligible(ctx, ent.name)) { let p = path::join(path, ent.name); let st = fs::stat(ctx.fs, p)?; - append(inputs, input { + let in = input { path = p, stat = st, + hash = hash_file(ctx, p)?, ... - }); + }; + append(inputs, in); + hash::write(sha, strings::to_utf8(in.hash)); }, * => void, }, }; + let sum = hash::finish(sha); + defer free(sum); return version { - hash = "", // TODO + hash = hex::encode(sum), inputs = inputs, }; }; diff --git a/hare/module/types.ha b/hare/module/types.ha @@ -38,7 +38,7 @@ export type input = struct { export type module_not_found = void!; // All possible error types. -export type error = (fs::error | io::error | module_not_found); +export type error = (fs::error | io::error | module_not_found)!; export fn errstr(err: error) const str = match (err) { err: fs::error => fs::errstr(err), diff --git a/hash/hash.ha b/hash/hash.ha @@ -31,6 +31,9 @@ export fn finish(h: *hash) []u8 = { return sum; }; +// Closes a hash, freeing its resources and discarding the checksum. +export fn close(h: *hash) void = io::close(&h.stream); + // Returns the current sum. The return value is heap allocated, the caller // needs to free it. export fn sum(h: *hash) []u8 = h.sum(h);