commit 554a40c042084f92da0d91913466c64c125cd546
parent c8d66f11253d86b2264a19075143cfa5aa4d451e
Author: Drew DeVault <sir@cmpwn.com>
Date: Tue, 6 Sep 2022 11:51:50 +0200
hare::module: incorporate tags into manifest
This makes cross-compilation work more reliably.
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
3 files changed, 55 insertions(+), 9 deletions(-)
diff --git a/hare/module/manifest.ha b/hare/module/manifest.ha
@@ -24,13 +24,14 @@ use temp;
// The manifest file format is a series of line-oriented records. Lines starting
// with # are ignored.
//
-// - "version" indicates the manifest format version, currently 1.
+// - "version" indicates the manifest format version, currently 2.
// - "input" is an input file, and its fields are the file hash, path, inode,
// and mtime as a Unix timestamp.
// - "module" is a version of a module, and includes the module hash and the set
// of input hashes which produce it.
+// - "tags" is a list of tags associated with a module version
-def VERSION: int = 1;
+def VERSION: int = 2;
fn getinput(in: []input, hash: []u8) nullable *input = {
for (let i = 0z; i < len(in); i += 1) {
@@ -226,6 +227,33 @@ export fn manifest_load(ctx: *context, ident: ast::ident) (manifest | error) = {
inputs = minputs,
...
});
+ case "tags" =>
+ let modhash = match (strings::next_token(&tok)) {
+ case void =>
+ return manifest;
+ case let s: str =>
+ yield s;
+ };
+ let modhash = match (hex::decodestr(modhash)) {
+ case let b: []u8 =>
+ yield b;
+ case =>
+ return manifest;
+ };
+
+ const tags = strings::remaining_tokens(&tok);
+ const tags = parsetags(tags) as []tag;
+ let found = false;
+ for (let i = 0z; i < len(versions); i += 1) {
+ if (bytes::equal(versions[i].hash, modhash)) {
+ versions[i].tags = tags;
+ found = true;
+ break;
+ };
+ };
+ // Implementation detail: tags always follows module
+ // directive for a given module version
+ assert(found);
case =>
return manifest;
};
@@ -331,6 +359,20 @@ export fn manifest_write(ctx: *context, man: *manifest) (void | error) = {
};
fmt::fprintln(file)?;
+
+ fmt::fprintf(file, "tags {} ", hash)?;
+ for (let i = 0z; i < len(ver.tags); i += 1) {
+ const tag = &ver.tags[i];
+ fmt::fprintf(file, "{}{}",
+ switch (tag.mode) {
+ case tag_mode::INCLUSIVE =>
+ yield "+";
+ case tag_mode::EXCLUSIVE =>
+ yield "-";
+ },
+ tag.name)?;
+ };
+ fmt::fprintln(file)!;
};
fs::move(ctx.fs, name, mpath)?;
@@ -351,5 +393,6 @@ export fn manifest_finish(m: *manifest) void = {
for (let i = 0z; i < len(m.versions); i += 1) {
free(m.versions[i].inputs);
+ tags_free(m.versions[i].tags);
};
};
diff --git a/hare/module/scan.ha b/hare/module/scan.ha
@@ -25,15 +25,15 @@ def ABI_VERSION: u8 = 4;
export fn scan(ctx: *context, path: str) (version | error) = {
// TODO: Incorporate defines into the hash
let sha = sha256::sha256();
- let found = false;
for (let i = 0z; i < len(ctx.tags); i += 1) {
- if (ctx.tags[i].mode == tag_mode::INCLUSIVE
- && ctx.tags[i].name == "test") {
- found = true;
- break;
- };
+ const tag = &ctx.tags[i];
+ hash::write(&sha, if (tag.mode == tag_mode::INCLUSIVE) {
+ yield [1];
+ } else {
+ yield [0];
+ });
+ hash::write(&sha, strings::toutf8(tag.name));
};
- hash::write(&sha, [if (found) 1 else 0]);
let iter = match (fs::iter(ctx.fs, path)) {
case fs::wrongtype =>
// Single file case
@@ -65,6 +65,7 @@ export fn scan(ctx: *context, path: str) (version | error) = {
basedir = strings::dup(path::dirname(path)),
depends = deps,
inputs = inputs,
+ tags = tags_dup(ctx.tags),
...
};
case let err: fs::error =>
@@ -75,6 +76,7 @@ export fn scan(ctx: *context, path: str) (version | error) = {
defer fs::finish(iter);
let ver = version {
basedir = strings::dup(path),
+ tags = tags_dup(ctx.tags),
...
};
scan_directory(ctx, &ver, &sha, path, iter)?;
diff --git a/hare/module/types.ha b/hare/module/types.ha
@@ -34,6 +34,7 @@ export type version = struct {
depends: []ast::ident,
inputs: []input,
subdirs: []str,
+ tags: []tag,
};
// The filetype of a file within a module.