aboutsummaryrefslogtreecommitdiff
path: root/src/main.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2025-02-24 20:24:52 -0800
committerAndrew Kelley <andrew@ziglang.org>2025-02-26 11:42:03 -0800
commitd6a88ed74db270c14c669ab334f3ab715cfd2b76 (patch)
tree6a82af3d767e00c4682f45ba49e8c8ef48be6a32 /src/main.zig
parent9763dd2901069f80dbdaae7c6b8004fbe1cf1b26 (diff)
downloadzig-d6a88ed74db270c14c669ab334f3ab715cfd2b76.tar.gz
zig-d6a88ed74db270c14c669ab334f3ab715cfd2b76.zip
introduce package id and redo hash format again
Introduces the `id` field to `build.zig.zon`. Together with name, this represents a globally unique package identifier. This field should be initialized with a 16-bit random number when the package is first created, and then *never change*. This allows Zig to unambiguously detect when one package is an updated version of another. When forking a Zig project, this id should be regenerated with a new random number if the upstream project is still maintained. Otherwise, the fork is *hostile*, attempting to take control over the original project's identity. `0x0000` is invalid because it obviously means a random number wasn't used. `0xffff` is reserved to represent "naked" packages. Tracking issue #14288 Additionally: * Fix bad path in error messages regarding build.zig.zon file. * Manifest validates that `name` and `version` field of build.zig.zon are maximum 32 bytes. * Introduce error for root package to not switch to enum literal for name. * Introduce error for root package to omit `id`. * Update init template to generate `id` * Update init template to populate `minimum_zig_version`. * New package hash format changes: - name and version limited to 32 bytes via error rather than truncation - truncate sha256 to 192 bits rather than 40 bits - include the package id This means that, given only the package hashes for a complete dependency tree, it is possible to perform version selection and know the final size on disk, without doing any fetching whatsoever. This prevents wasted bandwidth since package versions not selected do not need to be fetched.
Diffstat (limited to 'src/main.zig')
-rw-r--r--src/main.zig38
1 files changed, 28 insertions, 10 deletions
diff --git a/src/main.zig b/src/main.zig
index d6b20f94f9..b1680dbf8e 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -4751,8 +4751,10 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
};
var ok_count: usize = 0;
+ const id = Package.randomId();
+
for (template_paths) |template_path| {
- if (templates.write(arena, fs.cwd(), cwd_basename, template_path)) |_| {
+ if (templates.write(arena, fs.cwd(), cwd_basename, template_path, id)) |_| {
std.log.info("created {s}", .{template_path});
ok_count += 1;
} else |err| switch (err) {
@@ -7430,10 +7432,10 @@ fn loadManifest(
0,
) catch |err| switch (err) {
error.FileNotFound => {
+ const id = Package.randomId();
var templates = findTemplates(gpa, arena);
defer templates.deinit();
-
- templates.write(arena, options.dir, options.root_name, Package.Manifest.basename) catch |e| {
+ templates.write(arena, options.dir, options.root_name, Package.Manifest.basename, id) catch |e| {
fatal("unable to write {s}: {s}", .{
Package.Manifest.basename, @errorName(e),
});
@@ -7491,6 +7493,7 @@ const Templates = struct {
out_dir: fs.Dir,
root_name: []const u8,
template_path: []const u8,
+ id: u16,
) !void {
if (fs.path.dirname(template_path)) |dirname| {
out_dir.makePath(dirname) catch |err| {
@@ -7504,13 +7507,28 @@ const Templates = struct {
};
templates.buffer.clearRetainingCapacity();
try templates.buffer.ensureUnusedCapacity(contents.len);
- for (contents) |c| {
- if (c == '$') {
- try templates.buffer.appendSlice(root_name);
- } else {
- try templates.buffer.append(c);
- }
- }
+ var state: enum { start, dollar } = .start;
+ for (contents) |c| switch (state) {
+ .start => switch (c) {
+ '$' => state = .dollar,
+ else => try templates.buffer.append(c),
+ },
+ .dollar => switch (c) {
+ 'n' => {
+ try templates.buffer.appendSlice(root_name);
+ state = .start;
+ },
+ 'i' => {
+ try templates.buffer.writer().print("0x{x}", .{id});
+ state = .start;
+ },
+ 'v' => {
+ try templates.buffer.appendSlice(build_options.version);
+ state = .start;
+ },
+ else => fatal("unknown substitution: ${c}", .{c}),
+ },
+ };
return out_dir.writeFile(.{
.sub_path = template_path,