Artifact 0cbb3eba0d56a9d4fb26b74f20565532372c4fbace16742d6943d04b13bdcdec:
- File src/git/git_import_cli_pipe_helper.zig — part of check-in [49c08bb191] at 2026-08-13 13:08:34 on branch sub-manifest — git: gather every interop root into src/git/ — cli.zig joins the zit module (nine importers rerouted), moved roots take parent deps through the module; ~986 duplicate test executions eliminated (user: dmestas, size: 1949) [annotate] [blame] [check-ins using] [more...]
- File
src/git_import_cli_pipe_helper.zig
— part of check-in
[dc0aa2f858]
at
2026-07-31 02:56:07
on branch sub-manifest
— git-import: translate a Git fast-export stream into a zit history
`zit import-git SOURCE DEST` reads a Git repository through `git fast- export` and builds a zit repository from it. The destination appears only after the export, artifact creation and publication have all completed, so a failure anywhere leaves no half-published repository behind; this is the first caller of the logstore artifact batch added earlier on this branch, which is what makes a check-in's blobs arrive as a unit.
Mode 160000 now parses as a gitlink instead of error.UnsupportedMode. That completes the split begun in the previous check-in: reporting what the stream said is the parser's job, and deciding that zit has no submodule concept is the importer's. The refusal still happens, but it now explains itself instead of failing as a parse error on input git legitimately emits.
Signed commits are refused by default rather than imported with the signature silently dropped. Fossil has no signature card, so importing one is a loss the operator should choose; --drop-signatures accepts it explicitly.
The sub-manifest parameter is analyzed, not guessed. Preflight measures the source's own name set and pins its measured optimum, and --submanifest-k overrides that only to match another repository's existing pin, which is what lets two repositories share sub-manifests by content address. On a 100,000 file corpus the analyzed value cuts the objective by roughly 3.4x against the fixed default it replaces.
Correctness is checked differentially against real Git rather than against fixtures we wrote: every materialized tree is compared to `git ls-tree` for the corresponding commit, refs and annotated tags are compared to the source, and both comparators now assert that a gitlink is absent rather than merely tolerating it, so the omission is a contract instead of an accident.
The rest is wiring. extras learns the import provenance names, root.zig exports the importer modules across the executable and library boundary, tidy and the CI step guard learn the new test roots and build steps, and the e2e help check learns that a verb spelled import_git in Zig is import-git on the command line. (user: dmestas, size: 1949) [annotate] [blame] [check-ins using]
const std = @import("std"); const Io = std.Io; const valid_export = "feature done\n" ++ "blob\n" ++ "mark :1\n" ++ "data 5\n" ++ "hello\n" ++ "commit refs/heads/main\n" ++ "mark :2\n" ++ "author A <[email protected]> 0 +0000\n" ++ "committer A <[email protected]> 0 +0000\n" ++ "data 4\n" ++ "init\n" ++ "M 100644 :1 README\n" ++ "\n" ++ "done\n"; pub fn main(init: std.process.Init) !void { const io = init.io; const args = try init.minimal.args.toSlice(init.arena.allocator()); const mode = if (args.len > 1) args[1] else "success"; var out_buffer: [1024]u8 = undefined; var out = Io.File.Writer.initStreaming(.stdout(), io, &out_buffer); var err_buffer: [1024]u8 = undefined; var err = Io.File.Writer.initStreaming(.stderr(), io, &err_buffer); // 8 MiB exceeds ordinary pipe capacity. Writing it before stdout makes a // non-concurrent stderr drain deadlock, exactly what the parent test needs // to detect, while this direct executable remains shell-free and local. const chunk = "x" ** 8192; if (!std.mem.eql(u8, mode, "truncated-nonzero")) { for (0..1024) |_| try err.interface.writeAll(chunk); try err.interface.flush(); } if (std.mem.eql(u8, mode, "hold")) { try out.interface.writeAll("feature done\nblob\nmark :1\ndata 1\nx\nbogus\n"); try out.interface.flush(); try std.Io.sleep(io, .fromSeconds(60), .awake); return; } if (std.mem.eql(u8, mode, "truncated-nonzero")) { try out.interface.writeAll("feature done\nblob\nmark :1\ndata 1\nx\n"); try out.interface.flush(); try err.interface.writeAll("fatal: signed commit rejected\n"); try err.interface.flush(); std.process.exit(23); } try out.interface.writeAll(valid_export); try out.interface.flush(); if (std.mem.eql(u8, mode, "nonzero")) std.process.exit(23); }