Something went wrong. Try again.
A Zig library that reads git repositories without running git, with log, show and diff output byte-identical to git's.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990// SPDX-FileCopyrightText: © 2026 Jeffrey C. Ollie <jeff@ocjtech.us>// SPDX-License-Identifier: MIT
//! Listing branches and tags, and the reachability filters `branch`, `tag`//! and `for-each-ref` share, compared with git over generated histories//! with tags of every kind and remote-tracking refs, attached and//! detached, under SHA-1 and SHA-256.
const std = @import("std");
const tool = @import("zig_git.zig");const Repo = tool.Repo;const walk_tests = @import("walk_tests.zig");
const testing = std.testing;
fn same(repo: *Repo, args: []const []const u8) !void { try tool.expectSameAsGitHow(repo, args, .{});}
const listings = [_][]const []const u8{ &.{"branch"}, &.{ "branch", "-a" }, &.{ "branch", "-r" }, &.{ "branch", "--list", "b*" }, &.{ "branch", "-a", "--list", "origin/*" }, &.{ "branch", "-r", "--list", "*b1" }, &.{ "branch", "--list", "b1", "main" }, &.{ "branch", "--show-current" }, &.{ "branch", "--contains", "main~5" }, &.{ "branch", "--no-contains", "main~5" }, &.{ "branch", "--merged", "main" }, &.{ "branch", "--no-merged", "main" }, &.{ "branch", "--merged" }, &.{ "branch", "--contains" }, &.{ "branch", "--points-at", "main" }, &.{ "branch", "-a", "--merged", "HEAD" }, &.{ "branch", "-a", "b*" }, &.{ "branch", "--contains", "bogus" }, &.{"tag"}, &.{ "tag", "-l", "t1*", "l2*" }, &.{ "tag", "--contains", "main~20" }, &.{ "tag", "-l", "t*", "--merged", "main" }, &.{ "tag", "--no-contains" }, &.{ "tag", "--points-at", "tag-of-tag" }, &.{ "tag", "--points-at", "main~2^{tree}" }, &.{ "tag", "--contains", "bogus" }, &.{ "tag", "--points-at", "bogus" }, &.{ "tag", "--contains", "main^{tree}" }, &.{ "for-each-ref", "--contains", "main~5" }, &.{ "for-each-ref", "--no-contains", "main~5" }, &.{ "for-each-ref", "--merged", "main" }, &.{ "for-each-ref", "--no-merged", "b1" }, &.{ "for-each-ref", "--points-at", "main" }, &.{ "for-each-ref", "--contains", "main~3", "--no-contains", "b2" }, &.{ "for-each-ref", "--merged", "main", "--merged", "b1", "--no-merged", "b3" }, &.{ "for-each-ref", "--count=3", "--contains", "main~9", "refs/tags" }, &.{ "for-each-ref", "--sort=-refname", "--merged", "main" },};
test "branches and tags are listed and filtered as git lists them" { var repo = try Repo.init(testing.allocator, testing.io); defer repo.deinit(); try walk_tests.makeHistory(&repo, 21, 70); const tags = try repo.output(&.{ "tag", "-l", "t*" }); defer testing.allocator.free(tags); var it = std.mem.tokenizeScalar(u8, tags, '\n'); try repo.git(&.{ "tag", "-a", "-m", "of a tag", "tag-of-tag", it.next().? }); try repo.git(&.{ "tag", "tree-tag", "main~2^{tree}" }); try repo.git(&.{ "update-ref", "refs/remotes/origin/HEAD", "main" }); try repo.git(&.{ "symbolic-ref", "refs/remotes/origin/HEAD", "refs/remotes/origin/main" }); try repo.git(&.{ "update-ref", "refs/remotes/origin/main", "main~1" }); for ([_]bool{ false, true }) |graph| { if (graph) try repo.git(&.{ "commit-graph", "write", "--reachable" }); for (listings) |args| try same(&repo, args); } // Detached where the checkout left it, and moved on from there. try repo.git(&.{ "checkout", "-q", "main~3" }); try same(&repo, &.{"branch"}); try same(&repo, &.{ "branch", "--show-current" }); try same(&repo, &.{ "branch", "--contains", "main~6" }); try repo.git(&.{ "checkout", "-q", "--detach", "origin/main" }); try same(&repo, &.{ "branch", "-a" }); try repo.commit("moved on"); try same(&repo, &.{"branch"}); try repo.git(&.{ "checkout", "-q", "main" }); try repo.git(&.{ "update-ref", "--no-deref", "HEAD", "b2" }); try same(&repo, &.{"branch"});}