tiny.smg.context.source
Defined in context.
API (1)
Actions
Public operations.
Source
Source: tools/smg/src/context/root.zig:8
zig
pub const source = @import("source.zig");Source: tools/smg/src/context/source.zig
zig
const std = @import("std");const repo = @import("repo");const sys = @import("sys");const smg = @import("../root.zig");const context = @import("root.zig");const model = context.model;const io = std.Options.debug_io;pub fn inspect(builder: *model.Builder, entry: *model.Entry, node: smg.Node) !void { std.debug.assert(builder.entry_count != 0); std.debug.assert(std.mem.eql(u8, entry.name, node.name)); const evidence = smg.api.declarationSource(node) catch { builder.report.coverage.unverified_spans += 1; return; }; entry.source_span = evidence.span; entry.source_sha256 = try builder.allocator.dupe( u8, &std.fmt.bytesToHex(evidence.digest, .lower), ); entry.basis = verify(builder, evidence) catch |err| switch (err) { error.OutOfMemory => return err, else => .unavailable, }; if (entry.basis == .verified_span) { builder.report.coverage.verified_spans += 1; } else { builder.report.coverage.unverified_spans += 1; } if (entry.basis == .stale and builder.report.state == .ready) builder.report.state = .stale;}fn verify(builder: *model.Builder, evidence: smg.api.DeclarationSource) !model.Basis { if (!builder.active()) return .unverified; const count = evidence.span.end_byte - evidence.span.start_byte; std.debug.assert(count != 0); const remaining = builder.options.limits.source_bytes - builder.report.coverage.source_bytes; if (count > remaining) { builder.report.omissions.source = true; builder.exhausted(); return .oversized; } const path = try sourcePath(builder.allocator, builder.root, evidence.file); defer builder.allocator.free(path); if ((try sys.fs.statFile(path)).kind != .file) return .unavailable; var file = try std.Io.Dir.openFileAbsolute(io, path, .{ .follow_symlinks = false }); defer file.close(io); const before = try file.stat(io); if (before.kind != .file) return .unavailable; if (evidence.span.end_byte > before.size) return .stale; const bytes = try builder.allocator.alloc(u8, count); defer builder.allocator.free(bytes); const read = try file.readPositionalAll(io, bytes, evidence.span.start_byte); std.debug.assert(read <= count); builder.report.coverage.source_bytes += @intCast(read); if (!builder.active()) return .unverified; if (read != bytes.len) return .stale; const after = try file.stat(io); if (before.size != after.size or before.mtime.nanoseconds != after.mtime.nanoseconds) { return .stale; } const digest = smg.api.sourceDigest(bytes); return if (std.mem.eql(u8, &digest, &evidence.digest)) .verified_span else .stale;}fn sourcePath(allocator: std.mem.Allocator, root: []const u8, path: []const u8) ![]u8 { std.debug.assert(std.fs.path.isAbsolute(root)); std.debug.assert(path.len != 0); const relative = try repo.work.resolvedPathAlloc(allocator, root, path); defer allocator.free(relative); const absolute = try std.fs.path.join(allocator, &.{ root, relative }); defer allocator.free(absolute); const real = try std.Io.Dir.cwd().realPathFileAlloc(io, absolute, allocator); errdefer allocator.free(real); const checked = try repo.work.resolvedPathAlloc(allocator, root, real); allocator.free(checked); return real;}Audit
| Definitions | 2 |
|---|---|
| Public names | 2 |
| Members | 0 |
| Version | 26.7.0 |
| Revision | daab053ee433 |