| author | |
| committer | |
| log | de43f5eb6ae4a569efe15e3469b3de76a86d9cd1 |
| tree | dca7d9277507de70c93ec5f7fc95425995231e59 |
| parent | 67904e925d2b33c48dda3d4ddaf158328964dc2e |
7 files changed, 38 insertions(+), 38 deletions(-)
build.zig.zon+1-1| ... | @@ -12,5 +12,5 @@ | ... | @@ -12,5 +12,5 @@ |
| 12 | }, | 12 | }, |
| 13 | }, | 13 | }, |
| 14 | .paths = .{""}, | 14 | .paths = .{""}, |
| 15 | .nonce = 0xc1ce108124179e16, | 15 | .fingerprint = 0xc1ce108124179e16, |
| 16 | } | 16 | } |
doc/build.zig.zon.md+5-5| ... | @@ -22,24 +22,24 @@ Zig package namespace. | ... | @@ -22,24 +22,24 @@ Zig package namespace. |
| 22 | 22 | ||
| 23 | Must be a valid bare Zig identifier (don't `@` me), limited to 32 bytes. | 23 | Must be a valid bare Zig identifier (don't `@` me), limited to 32 bytes. |
| 24 | 24 | ||
| 25 | Together with `nonce`, this represents a globally unique package identifier. | 25 | Together with `fingerprint`, this represents a globally unique package identifier. |
| 26 | 26 | ||
| 27 | ### `nonce` | 27 | ### `fingerprint` |
| 28 | 28 | ||
| 29 | Together with `name`, this represents a globally unique package identifier. This | 29 | Together with `name`, this represents a globally unique package identifier. This |
| 30 | field is auto-initialized by the toolchain when the package is first created, | 30 | field is auto-initialized by the toolchain when the package is first created, |
| 31 | and then *never changes*. This allows Zig to unambiguously detect when one | 31 | and then *never changes*. This allows Zig to unambiguously detect when one |
| 32 | package is an updated version of another. | 32 | package is an updated version of another. |
| 33 | 33 | ||
| 34 | When forking a Zig project, this nonce should be regenerated if the upstream | 34 | When forking a Zig project, this fingerprint should be regenerated if the upstream |
| 35 | project is still maintained. Otherwise, the fork is *hostile*, attempting to | 35 | project is still maintained. Otherwise, the fork is *hostile*, attempting to |
| 36 | take control over the original project's identity. The nonce can be regenerated | 36 | take control over the original project's identity. The fingerprint can be regenerated |
| 37 | by deleting the field and running `zig build`. | 37 | by deleting the field and running `zig build`. |
| 38 | 38 | ||
| 39 | This 64-bit integer is the combination of a 32-bit id component and a 32-bit | 39 | This 64-bit integer is the combination of a 32-bit id component and a 32-bit |
| 40 | checksum. | 40 | checksum. |
| 41 | 41 | ||
| 42 | The id component within the nonce has these restrictions: | 42 | The id component within the fingerprint has these restrictions: |
| 43 | 43 | ||
| 44 | `0x00000000` is reserved for legacy packages. | 44 | `0x00000000` is reserved for legacy packages. |
| 45 | 45 |
lib/init/build.zig.zon+1-1| ... | @@ -24,7 +24,7 @@ | ... | @@ -24,7 +24,7 @@ |
| 24 | // original project's identity. Thus it is recommended to leave the comment | 24 | // original project's identity. Thus it is recommended to leave the comment |
| 25 | // on the following line intact, so that it shows up in code reviews that | 25 | // on the following line intact, so that it shows up in code reviews that |
| 26 | // modify the field. | 26 | // modify the field. |
| 27 | .nonce = .NONCE, // Changing this has security and trust implications. | 27 | .fingerprint = .FINGERPRINT, // Changing this has security and trust implications. |
| 28 | 28 | ||
| 29 | // Tracks the earliest Zig version that the package considers to be a | 29 | // Tracks the earliest Zig version that the package considers to be a |
| 30 | // supported use case. | 30 | // supported use case. |
src/Package.zig+4-4| ... | @@ -10,25 +10,25 @@ pub const multihash_len = 1 + 1 + Hash.Algo.digest_length; | ... | @@ -10,25 +10,25 @@ pub const multihash_len = 1 + 1 + Hash.Algo.digest_length; |
| 10 | pub const multihash_hex_digest_len = 2 * multihash_len; | 10 | pub const multihash_hex_digest_len = 2 * multihash_len; |
| 11 | pub const MultiHashHexDigest = [multihash_hex_digest_len]u8; | 11 | pub const MultiHashHexDigest = [multihash_hex_digest_len]u8; |
| 12 | 12 | ||
| 13 | pub const Nonce = packed struct(u64) { | 13 | pub const Fingerprint = packed struct(u64) { |
| 14 | id: u32, | 14 | id: u32, |
| 15 | checksum: u32, | 15 | checksum: u32, |
| 16 | 16 | ||
| 17 | pub fn generate(name: []const u8) Nonce { | 17 | pub fn generate(name: []const u8) Fingerprint { |
| 18 | return .{ | 18 | return .{ |
| 19 | .id = std.crypto.random.intRangeLessThan(u32, 1, 0xffffffff), | 19 | .id = std.crypto.random.intRangeLessThan(u32, 1, 0xffffffff), |
| 20 | .checksum = std.hash.Crc32.hash(name), | 20 | .checksum = std.hash.Crc32.hash(name), |
| 21 | }; | 21 | }; |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | pub fn validate(n: Nonce, name: []const u8) bool { | 24 | pub fn validate(n: Fingerprint, name: []const u8) bool { |
| 25 | switch (n.id) { | 25 | switch (n.id) { |
| 26 | 0x00000000, 0xffffffff => return false, | 26 | 0x00000000, 0xffffffff => return false, |
| 27 | else => return std.hash.Crc32.hash(name) == n.checksum, | 27 | else => return std.hash.Crc32.hash(name) == n.checksum, |
| 28 | } | 28 | } |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | pub fn int(n: Nonce) u64 { | 31 | pub fn int(n: Fingerprint) u64 { |
| 32 | return @bitCast(n); | 32 | return @bitCast(n); |
| 33 | } | 33 | } |
| 34 | }; | 34 | }; |
src/Package/Fetch.zig+4-4| ... | @@ -44,7 +44,7 @@ omit_missing_hash_error: bool, | ... | @@ -44,7 +44,7 @@ omit_missing_hash_error: bool, |
| 44 | /// which specifies inclusion rules. This is intended to be true for the first | 44 | /// which specifies inclusion rules. This is intended to be true for the first |
| 45 | /// fetch task and false for the recursive dependencies. | 45 | /// fetch task and false for the recursive dependencies. |
| 46 | allow_missing_paths_field: bool, | 46 | allow_missing_paths_field: bool, |
| 47 | allow_missing_nonce: bool, | 47 | allow_missing_fingerprint: bool, |
| 48 | allow_name_string: bool, | 48 | allow_name_string: bool, |
| 49 | /// If true and URL points to a Git repository, will use the latest commit. | 49 | /// If true and URL points to a Git repository, will use the latest commit. |
| 50 | use_latest_commit: bool, | 50 | use_latest_commit: bool, |
| ... | @@ -649,7 +649,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void { | ... | @@ -649,7 +649,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void { |
| 649 | 649 | ||
| 650 | f.manifest = try Manifest.parse(arena, ast.*, .{ | 650 | f.manifest = try Manifest.parse(arena, ast.*, .{ |
| 651 | .allow_missing_paths_field = f.allow_missing_paths_field, | 651 | .allow_missing_paths_field = f.allow_missing_paths_field, |
| 652 | .allow_missing_nonce = f.allow_missing_nonce, | 652 | .allow_missing_fingerprint = f.allow_missing_fingerprint, |
| 653 | .allow_name_string = f.allow_name_string, | 653 | .allow_name_string = f.allow_name_string, |
| 654 | }); | 654 | }); |
| 655 | const manifest = &f.manifest.?; | 655 | const manifest = &f.manifest.?; |
| ... | @@ -752,7 +752,7 @@ fn queueJobsForDeps(f: *Fetch) RunError!void { | ... | @@ -752,7 +752,7 @@ fn queueJobsForDeps(f: *Fetch) RunError!void { |
| 752 | .job_queue = f.job_queue, | 752 | .job_queue = f.job_queue, |
| 753 | .omit_missing_hash_error = false, | 753 | .omit_missing_hash_error = false, |
| 754 | .allow_missing_paths_field = true, | 754 | .allow_missing_paths_field = true, |
| 755 | .allow_missing_nonce = true, | 755 | .allow_missing_fingerprint = true, |
| 756 | .allow_name_string = true, | 756 | .allow_name_string = true, |
| 757 | .use_latest_commit = false, | 757 | .use_latest_commit = false, |
| 758 | 758 | ||
| ... | @@ -2323,7 +2323,7 @@ const TestFetchBuilder = struct { | ... | @@ -2323,7 +2323,7 @@ const TestFetchBuilder = struct { |
| 2323 | .job_queue = &self.job_queue, | 2323 | .job_queue = &self.job_queue, |
| 2324 | .omit_missing_hash_error = true, | 2324 | .omit_missing_hash_error = true, |
| 2325 | .allow_missing_paths_field = false, | 2325 | .allow_missing_paths_field = false, |
| 2326 | .allow_missing_nonce = true, // so we can keep using the old testdata .tar.gz | 2326 | .allow_missing_fingerprint = true, // so we can keep using the old testdata .tar.gz |
| 2327 | .allow_name_string = true, // so we can keep using the old testdata .tar.gz | 2327 | .allow_name_string = true, // so we can keep using the old testdata .tar.gz |
| 2328 | .use_latest_commit = true, | 2328 | .use_latest_commit = true, |
| 2329 | 2329 |
src/Package/Manifest.zig+13-13| ... | @@ -52,7 +52,7 @@ pub const ParseOptions = struct { | ... | @@ -52,7 +52,7 @@ pub const ParseOptions = struct { |
| 52 | /// Deprecated, to be removed after 0.14.0 is tagged. | 52 | /// Deprecated, to be removed after 0.14.0 is tagged. |
| 53 | allow_name_string: bool = true, | 53 | allow_name_string: bool = true, |
| 54 | /// Deprecated, to be removed after 0.14.0 is tagged. | 54 | /// Deprecated, to be removed after 0.14.0 is tagged. |
| 55 | allow_missing_nonce: bool = true, | 55 | allow_missing_fingerprint: bool = true, |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | pub const Error = Allocator.Error; | 58 | pub const Error = Allocator.Error; |
| ... | @@ -81,7 +81,7 @@ pub fn parse(gpa: Allocator, ast: Ast, options: ParseOptions) Error!Manifest { | ... | @@ -81,7 +81,7 @@ pub fn parse(gpa: Allocator, ast: Ast, options: ParseOptions) Error!Manifest { |
| 81 | .paths = .{}, | 81 | .paths = .{}, |
| 82 | .allow_missing_paths_field = options.allow_missing_paths_field, | 82 | .allow_missing_paths_field = options.allow_missing_paths_field, |
| 83 | .allow_name_string = options.allow_name_string, | 83 | .allow_name_string = options.allow_name_string, |
| 84 | .allow_missing_nonce = options.allow_missing_nonce, | 84 | .allow_missing_fingerprint = options.allow_missing_fingerprint, |
| 85 | .minimum_zig_version = null, | 85 | .minimum_zig_version = null, |
| 86 | .buf = .{}, | 86 | .buf = .{}, |
| 87 | }; | 87 | }; |
| ... | @@ -157,7 +157,7 @@ const Parse = struct { | ... | @@ -157,7 +157,7 @@ const Parse = struct { |
| 157 | paths: std.StringArrayHashMapUnmanaged(void), | 157 | paths: std.StringArrayHashMapUnmanaged(void), |
| 158 | allow_missing_paths_field: bool, | 158 | allow_missing_paths_field: bool, |
| 159 | allow_name_string: bool, | 159 | allow_name_string: bool, |
| 160 | allow_missing_nonce: bool, | 160 | allow_missing_fingerprint: bool, |
| 161 | minimum_zig_version: ?std.SemanticVersion, | 161 | minimum_zig_version: ?std.SemanticVersion, |
| 162 | 162 | ||
| 163 | const InnerError = error{ ParseFailure, OutOfMemory }; | 163 | const InnerError = error{ ParseFailure, OutOfMemory }; |
| ... | @@ -175,7 +175,7 @@ const Parse = struct { | ... | @@ -175,7 +175,7 @@ const Parse = struct { |
| 175 | var have_name = false; | 175 | var have_name = false; |
| 176 | var have_version = false; | 176 | var have_version = false; |
| 177 | var have_included_paths = false; | 177 | var have_included_paths = false; |
| 178 | var nonce: ?Package.Nonce = null; | 178 | var fingerprint: ?Package.Fingerprint = null; |
| 179 | 179 | ||
| 180 | for (struct_init.ast.fields) |field_init| { | 180 | for (struct_init.ast.fields) |field_init| { |
| 181 | const name_token = ast.firstToken(field_init) - 2; | 181 | const name_token = ast.firstToken(field_init) - 2; |
| ... | @@ -192,8 +192,8 @@ const Parse = struct { | ... | @@ -192,8 +192,8 @@ const Parse = struct { |
| 192 | } else if (mem.eql(u8, field_name, "name")) { | 192 | } else if (mem.eql(u8, field_name, "name")) { |
| 193 | p.name = try parseName(p, field_init); | 193 | p.name = try parseName(p, field_init); |
| 194 | have_name = true; | 194 | have_name = true; |
| 195 | } else if (mem.eql(u8, field_name, "nonce")) { | 195 | } else if (mem.eql(u8, field_name, "fingerprint")) { |
| 196 | nonce = try parseNonce(p, field_init); | 196 | fingerprint = try parseFingerprint(p, field_init); |
| 197 | } else if (mem.eql(u8, field_name, "version")) { | 197 | } else if (mem.eql(u8, field_name, "version")) { |
| 198 | p.version_node = field_init; | 198 | p.version_node = field_init; |
| 199 | const version_text = try parseString(p, field_init); | 199 | const version_text = try parseString(p, field_init); |
| ... | @@ -220,16 +220,16 @@ const Parse = struct { | ... | @@ -220,16 +220,16 @@ const Parse = struct { |
| 220 | if (!have_name) { | 220 | if (!have_name) { |
| 221 | try appendError(p, main_token, "missing top-level 'name' field", .{}); | 221 | try appendError(p, main_token, "missing top-level 'name' field", .{}); |
| 222 | } else { | 222 | } else { |
| 223 | if (nonce) |n| { | 223 | if (fingerprint) |n| { |
| 224 | if (!n.validate(p.name)) { | 224 | if (!n.validate(p.name)) { |
| 225 | return fail(p, main_token, "invalid nonce: 0x{x}; if this is a new or forked package, use this value: 0x{x}", .{ | 225 | return fail(p, main_token, "invalid fingerprint: 0x{x}; if this is a new or forked package, use this value: 0x{x}", .{ |
| 226 | n.int(), Package.Nonce.generate(p.name).int(), | 226 | n.int(), Package.Fingerprint.generate(p.name).int(), |
| 227 | }); | 227 | }); |
| 228 | } | 228 | } |
| 229 | p.id = n.id; | 229 | p.id = n.id; |
| 230 | } else if (!p.allow_missing_nonce) { | 230 | } else if (!p.allow_missing_fingerprint) { |
| 231 | try appendError(p, main_token, "missing top-level 'nonce' field; suggested value: 0x{x}", .{ | 231 | try appendError(p, main_token, "missing top-level 'fingerprint' field; suggested value: 0x{x}", .{ |
| 232 | Package.Nonce.generate(p.name).int(), | 232 | Package.Fingerprint.generate(p.name).int(), |
| 233 | }); | 233 | }); |
| 234 | } else { | 234 | } else { |
| 235 | p.id = 0; | 235 | p.id = 0; |
| ... | @@ -385,7 +385,7 @@ const Parse = struct { | ... | @@ -385,7 +385,7 @@ const Parse = struct { |
| 385 | } | 385 | } |
| 386 | } | 386 | } |
| 387 | 387 | ||
| 388 | fn parseNonce(p: *Parse, node: Ast.Node.Index) !Package.Nonce { | 388 | fn parseFingerprint(p: *Parse, node: Ast.Node.Index) !Package.Fingerprint { |
| 389 | const ast = p.ast; | 389 | const ast = p.ast; |
| 390 | const node_tags = ast.nodes.items(.tag); | 390 | const node_tags = ast.nodes.items(.tag); |
| 391 | const main_tokens = ast.nodes.items(.main_token); | 391 | const main_tokens = ast.nodes.items(.main_token); |
src/main.zig+10-10| ... | @@ -4752,10 +4752,10 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { | ... | @@ -4752,10 +4752,10 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 4752 | }; | 4752 | }; |
| 4753 | var ok_count: usize = 0; | 4753 | var ok_count: usize = 0; |
| 4754 | 4754 | ||
| 4755 | const nonce: Package.Nonce = .generate(sanitized_root_name); | 4755 | const fingerprint: Package.Fingerprint = .generate(sanitized_root_name); |
| 4756 | 4756 | ||
| 4757 | for (template_paths) |template_path| { | 4757 | for (template_paths) |template_path| { |
| 4758 | if (templates.write(arena, fs.cwd(), sanitized_root_name, template_path, nonce)) |_| { | 4758 | if (templates.write(arena, fs.cwd(), sanitized_root_name, template_path, fingerprint)) |_| { |
| 4759 | std.log.info("created {s}", .{template_path}); | 4759 | std.log.info("created {s}", .{template_path}); |
| 4760 | ok_count += 1; | 4760 | ok_count += 1; |
| 4761 | } else |err| switch (err) { | 4761 | } else |err| switch (err) { |
| ... | @@ -5225,7 +5225,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { | ... | @@ -5225,7 +5225,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 5225 | .job_queue = &job_queue, | 5225 | .job_queue = &job_queue, |
| 5226 | .omit_missing_hash_error = true, | 5226 | .omit_missing_hash_error = true, |
| 5227 | .allow_missing_paths_field = false, | 5227 | .allow_missing_paths_field = false, |
| 5228 | .allow_missing_nonce = false, | 5228 | .allow_missing_fingerprint = false, |
| 5229 | .allow_name_string = false, | 5229 | .allow_name_string = false, |
| 5230 | .use_latest_commit = false, | 5230 | .use_latest_commit = false, |
| 5231 | 5231 | ||
| ... | @@ -7127,7 +7127,7 @@ fn cmdFetch( | ... | @@ -7127,7 +7127,7 @@ fn cmdFetch( |
| 7127 | .job_queue = &job_queue, | 7127 | .job_queue = &job_queue, |
| 7128 | .omit_missing_hash_error = true, | 7128 | .omit_missing_hash_error = true, |
| 7129 | .allow_missing_paths_field = false, | 7129 | .allow_missing_paths_field = false, |
| 7130 | .allow_missing_nonce = true, | 7130 | .allow_missing_fingerprint = true, |
| 7131 | .allow_name_string = true, | 7131 | .allow_name_string = true, |
| 7132 | .use_latest_commit = true, | 7132 | .use_latest_commit = true, |
| 7133 | 7133 | ||
| ... | @@ -7468,10 +7468,10 @@ fn loadManifest( | ... | @@ -7468,10 +7468,10 @@ fn loadManifest( |
| 7468 | 0, | 7468 | 0, |
| 7469 | ) catch |err| switch (err) { | 7469 | ) catch |err| switch (err) { |
| 7470 | error.FileNotFound => { | 7470 | error.FileNotFound => { |
| 7471 | const nonce: Package.Nonce = .generate(options.root_name); | 7471 | const fingerprint: Package.Fingerprint = .generate(options.root_name); |
| 7472 | var templates = findTemplates(gpa, arena); | 7472 | var templates = findTemplates(gpa, arena); |
| 7473 | defer templates.deinit(); | 7473 | defer templates.deinit(); |
| 7474 | templates.write(arena, options.dir, options.root_name, Package.Manifest.basename, nonce) catch |e| { | 7474 | templates.write(arena, options.dir, options.root_name, Package.Manifest.basename, fingerprint) catch |e| { |
| 7475 | fatal("unable to write {s}: {s}", .{ | 7475 | fatal("unable to write {s}: {s}", .{ |
| 7476 | Package.Manifest.basename, @errorName(e), | 7476 | Package.Manifest.basename, @errorName(e), |
| 7477 | }); | 7477 | }); |
| ... | @@ -7529,7 +7529,7 @@ const Templates = struct { | ... | @@ -7529,7 +7529,7 @@ const Templates = struct { |
| 7529 | out_dir: fs.Dir, | 7529 | out_dir: fs.Dir, |
| 7530 | root_name: []const u8, | 7530 | root_name: []const u8, |
| 7531 | template_path: []const u8, | 7531 | template_path: []const u8, |
| 7532 | nonce: Package.Nonce, | 7532 | fingerprint: Package.Fingerprint, |
| 7533 | ) !void { | 7533 | ) !void { |
| 7534 | if (fs.path.dirname(template_path)) |dirname| { | 7534 | if (fs.path.dirname(template_path)) |dirname| { |
| 7535 | out_dir.makePath(dirname) catch |err| { | 7535 | out_dir.makePath(dirname) catch |err| { |
| ... | @@ -7555,9 +7555,9 @@ const Templates = struct { | ... | @@ -7555,9 +7555,9 @@ const Templates = struct { |
| 7555 | try templates.buffer.appendSlice(root_name); | 7555 | try templates.buffer.appendSlice(root_name); |
| 7556 | i += ".NAME".len; | 7556 | i += ".NAME".len; |
| 7557 | continue; | 7557 | continue; |
| 7558 | } else if (std.mem.startsWith(u8, contents[i..], ".NONCE")) { | 7558 | } else if (std.mem.startsWith(u8, contents[i..], ".FINGERPRINT")) { |
| 7559 | try templates.buffer.writer().print("0x{x}", .{nonce.int()}); | 7559 | try templates.buffer.writer().print("0x{x}", .{fingerprint.int()}); |
| 7560 | i += ".NONCE".len; | 7560 | i += ".FINGERPRINT".len; |
| 7561 | continue; | 7561 | continue; |
| 7562 | } else if (std.mem.startsWith(u8, contents[i..], ".ZIGVER")) { | 7562 | } else if (std.mem.startsWith(u8, contents[i..], ".ZIGVER")) { |
| 7563 | try templates.buffer.appendSlice(build_options.version); | 7563 | try templates.buffer.appendSlice(build_options.version); |