diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d2e663f..c55649e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false matrix: - zig-version: ["0.14.0"] + zig-version: ["0.15.2"] os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} @@ -23,7 +23,7 @@ jobs: uses: actions/checkout@v4 - name: Setup Zig - uses: mlugg/setup-zig@v1 + uses: mlugg/setup-zig@v2 with: version: ${{ matrix.zig-version }} diff --git a/build.zig b/build.zig index e78f9a4..bcaf370 100644 --- a/build.zig +++ b/build.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const builtin = @import("builtin"); pub fn build(b: *std.Build) !void { const target = b.standardTargetOptions(.{}); @@ -430,34 +429,19 @@ pub fn build(b: *std.Build) !void { const test_step = b.step("test", "Run core unit tests (requires python)"); { - if (builtin.os.tag != .windows) { - // Fix the test fixture file permissions. This is necessary because Zig does - // not respect the execute permission on arbitrary files it extracts from dependencies. - // Since we need those files to have the execute permission set for tests to - // run successfully, we need to patch them before we bake them into the - // test executable. While modifying the global cache is hacky, it wont break - // hashes for the same reason above. -blurrycat 3/31/25 - for ([_]std.Build.LazyPath{ - libgit_root.path(b, "tests/resources/filemodes/exec_on"), - libgit_root.path(b, "tests/resources/filemodes/exec_off2on_staged"), - libgit_root.path(b, "tests/resources/filemodes/exec_off2on_workdir"), - libgit_root.path(b, "tests/resources/filemodes/exec_on_untracked"), - }) |lazy| { - const path = lazy.getPath2(b, null); - const file = try std.fs.cwd().openFile(path, .{ - .mode = .read_write, - }); - defer file.close(); - try file.setPermissions(.{ .inner = .{ .mode = 0o755 } }); - } - } - const gen_cmd = b.addSystemCommand(&.{"python3"}); gen_cmd.addFileArg(libgit_src.path("tests/clar/generate.py")); const clar_suite = gen_cmd.addPrefixedOutputDirectoryArg("-o", "clar_suite"); gen_cmd.addArgs(&.{ "-f", "-xonline", "-xstress", "-xperf" }); gen_cmd.addDirectoryArg(libgit_src.path("tests/libgit2")); + // Copy the clar source so it can be modified below. + const clar_src = b.addWriteFiles().addCopyDirectory( + libgit_src.path("tests/clar"), + "clar_src", + .{}, + ); + const runner = b.addExecutable(.{ .name = "libgit2_tests", .root_module = b.createModule(.{ @@ -467,7 +451,7 @@ pub fn build(b: *std.Build) !void { }), }); runner.addIncludePath(clar_suite); - runner.addIncludePath(libgit_src.path("tests/clar")); + runner.addIncludePath(clar_src); runner.addIncludePath(libgit_src.path("tests/libgit2")); runner.addConfigHeader(features); @@ -481,28 +465,79 @@ pub fn build(b: *std.Build) !void { runner.linkLibrary(lib); + const runner_flags = &.{ + "-DCLAR_FIXTURE_PATH", // See clar_fix step below + "-DCLAR_TMPDIR=\"libgit2_tests\"", + "-DCLAR_WIN32_LONGPATHS", + "-DGIT_DEPRECATE_HARD", + }; runner.addCSourceFiles(.{ - .root = libgit_src.path("tests/"), - .files = &(clar_sources ++ libgit2_test_sources), - .flags = &.{ - b.fmt( - "-DCLAR_FIXTURE_PATH=\"{s}\"", - // clar expects the fixture path to only have posix seperators or else some tests will break on windows - .{try getNormalizedPath(libgit_src.path("tests/resources"), b, &runner.step)}, - ), - "-DCLAR_TMPDIR=\"libgit2_tests\"", - "-DCLAR_WIN32_LONGPATHS", - "-D_FILE_OFFSET_BITS=64", - "-DGIT_DEPRECATE_HARD", - }, + .root = libgit_src.path("tests/libgit2/"), + .files = &libgit2_test_sources, + .flags = runner_flags, + }); + runner.addCSourceFiles(.{ + .root = clar_src, + .files = &clar_sources, + .flags = runner_flags, }); + const resources_dir = switch (@import("builtin").os.tag) { + .windows => libgit_src.path("tests/resources/"), + else => dir: { + // Fix the test fixture file permissions. This is necessary because Zig does + // not respect the execute permission on arbitrary files it extracts from dependencies. + // Since we need those files to have the execute permission set for tests to + // run successfully, we need to patch them before we bake them into the + // test executable. + const resources_dir = b.addWriteFiles().addCopyDirectory( + libgit_root.path(b, "tests/resources/"), + "test_resources", + .{}, + ); + const chmod = b.addExecutable(.{ + .name = "chmod", + .root_module = b.createModule(.{ + .root_source_file = b.path("build/chmod.zig"), + .target = b.graph.host, + }), + }); + const run_chmod = b.addRunArtifact(chmod); + run_chmod.addFileArg(resources_dir.path(b, "filemodes/exec_on")); + run_chmod.addFileArg(resources_dir.path(b, "filemodes/exec_off2on_staged")); + run_chmod.addFileArg(resources_dir.path(b, "filemodes/exec_off2on_workdir")); + run_chmod.addFileArg(resources_dir.path(b, "filemodes/exec_on_untracked")); + runner.step.dependOn(&run_chmod.step); + + break :dir resources_dir; + }, + }; + { + // Clar hardcodes the path to resources_dir via the `-DCLAR_FIXTURE_PATH="..."` flag. + // This path isn't known at configure-time, so we have to create a dedicated build step. + // This step replaces *reads* of the `CLAR_FIXTURE_PATH` macro in a local-cache copy of the source code + // (see clar_src). Thankfully the macro is only read by `tests/clar/clar/fixture.h` once. + const clar_fix = b.addExecutable(.{ + .name = "clar_fix", + .root_module = b.createModule(.{ + .root_source_file = b.path("build/clar_fix.zig"), + .target = b.graph.host, + }), + }); + + const run_fix = b.addRunArtifact(clar_fix); + // run_fix.has_side_effects = true; // @Todo is this necessary? What are the rules for cache invalidation with Run steps? + run_fix.addFileArg(clar_src.path(b, "clar/fixtures.h")); + run_fix.addDirectoryArg(resources_dir); + runner.step.dependOn(&run_fix.step); + } + const TestHelper = struct { b: *std.Build, top_level_step: *std.Build.Step, runner: *std.Build.Step.Compile, - const ClarStep = @import("ClarTestStep.zig"); + const ClarStep = @import("build/ClarTestStep.zig"); fn addTest( self: @This(), @@ -553,18 +588,6 @@ pub fn build(b: *std.Build) !void { } } -/// Returns the absolute lazy path with posix seperators -fn getNormalizedPath(lp: std.Build.LazyPath, b: *std.Build, asking_step: *std.Build.Step) ![]const u8 { - const p = lp.getPath3(b, asking_step); - const result = b.pathResolve(&.{ p.root_dir.path orelse ".", p.sub_path }); - if (builtin.os.tag == .windows) { - for (result) |*c| { - if (c.* == '\\') c.* = '/'; - } - } - return result; -} - pub const TlsBackend = enum { openssl, mbedtls, securetransport }; fn maybeAddTlsIncludes( @@ -888,414 +911,414 @@ const example_sources = [_][]const u8{ }; const clar_sources = [_][]const u8{ - "clar/clar.c", - "clar/clar_libgit2.c", - "clar/clar_libgit2_alloc.c", - "clar/clar_libgit2_timer.c", - "clar/clar_libgit2_trace.c", - "clar/main.c", + "clar.c", + "clar_libgit2.c", + "clar_libgit2_alloc.c", + "clar_libgit2_timer.c", + "clar_libgit2_trace.c", + "main.c", }; const libgit2_test_sources = [_][]const u8{ - "libgit2/apply/apply_helpers.c", - "libgit2/apply/both.c", - "libgit2/apply/callbacks.c", - "libgit2/apply/check.c", - "libgit2/apply/fromdiff.c", - "libgit2/apply/fromfile.c", - "libgit2/apply/index.c", - "libgit2/apply/partial.c", - "libgit2/apply/tree.c", - "libgit2/apply/workdir.c", - "libgit2/attr/file.c", - "libgit2/attr/flags.c", - "libgit2/attr/lookup.c", - "libgit2/attr/macro.c", - "libgit2/attr/repo.c", - "libgit2/blame/blame_helpers.c", - "libgit2/blame/buffer.c", - "libgit2/blame/getters.c", - "libgit2/blame/harder.c", - "libgit2/blame/simple.c", - "libgit2/checkout/binaryunicode.c", - "libgit2/checkout/checkout_helpers.c", - "libgit2/checkout/conflict.c", - "libgit2/checkout/crlf.c", - "libgit2/checkout/head.c", - "libgit2/checkout/icase.c", - "libgit2/checkout/index.c", - "libgit2/checkout/nasty.c", - "libgit2/checkout/tree.c", - "libgit2/checkout/typechange.c", - "libgit2/cherrypick/bare.c", - "libgit2/cherrypick/workdir.c", - "libgit2/clone/empty.c", - "libgit2/clone/local.c", - "libgit2/clone/nonetwork.c", - "libgit2/clone/transport.c", - "libgit2/commit/commit.c", - "libgit2/commit/create.c", - "libgit2/commit/parent.c", - "libgit2/commit/parse.c", - "libgit2/commit/signature.c", - "libgit2/commit/write.c", - "libgit2/config/add.c", - "libgit2/config/backend.c", - "libgit2/config/conditionals.c", - "libgit2/config/config_helpers.c", - "libgit2/config/configlevel.c", - "libgit2/config/find.c", - "libgit2/config/global.c", - "libgit2/config/include.c", - "libgit2/config/memory.c", - "libgit2/config/multivar.c", - "libgit2/config/new.c", - "libgit2/config/read.c", - "libgit2/config/readonly.c", - "libgit2/config/rename.c", - "libgit2/config/snapshot.c", - "libgit2/config/stress.c", - "libgit2/config/validkeyname.c", - "libgit2/config/write.c", - "libgit2/core/buf.c", - "libgit2/core/env.c", - "libgit2/core/features.c", - "libgit2/core/hashsig.c", - "libgit2/core/oid.c", - "libgit2/core/oidarray.c", - "libgit2/core/opts.c", - "libgit2/core/pool.c", - "libgit2/core/structinit.c", - "libgit2/core/useragent.c", - "libgit2/core/version.c", - "libgit2/date/date.c", - "libgit2/date/rfc2822.c", - "libgit2/delta/apply.c", - "libgit2/describe/describe.c", - "libgit2/describe/describe_helpers.c", - "libgit2/describe/t6120.c", - "libgit2/diff/binary.c", - "libgit2/diff/blob.c", - "libgit2/diff/diff_helpers.c", - "libgit2/diff/diffiter.c", - "libgit2/diff/drivers.c", - "libgit2/diff/externalmodifications.c", - "libgit2/diff/format_email.c", - "libgit2/diff/header.c", - "libgit2/diff/index.c", - "libgit2/diff/notify.c", - "libgit2/diff/parse.c", - "libgit2/diff/patch.c", - "libgit2/diff/patchid.c", - "libgit2/diff/pathspec.c", - "libgit2/diff/racediffiter.c", - "libgit2/diff/rename.c", - "libgit2/diff/stats.c", - "libgit2/diff/submodules.c", - "libgit2/diff/tree.c", - "libgit2/diff/userdiff.c", - "libgit2/diff/workdir.c", - "libgit2/email/create.c", - "libgit2/fetch/local.c", - "libgit2/fetchhead/nonetwork.c", - "libgit2/filter/bare.c", - "libgit2/filter/blob.c", - "libgit2/filter/crlf.c", - "libgit2/filter/custom.c", - "libgit2/filter/custom_helpers.c", - "libgit2/filter/file.c", - "libgit2/filter/ident.c", - "libgit2/filter/query.c", - "libgit2/filter/stream.c", - "libgit2/filter/systemattrs.c", - "libgit2/filter/wildcard.c", - "libgit2/grafts/basic.c", - "libgit2/grafts/parse.c", - "libgit2/grafts/shallow.c", - "libgit2/graph/ahead_behind.c", - "libgit2/graph/commitgraph.c", - "libgit2/graph/descendant_of.c", - "libgit2/graph/reachable_from_any.c", - "libgit2/ignore/path.c", - "libgit2/ignore/status.c", - "libgit2/index/add.c", - "libgit2/index/addall.c", - "libgit2/index/bypath.c", - "libgit2/index/cache.c", - "libgit2/index/collision.c", - "libgit2/index/conflicts.c", - "libgit2/index/crlf.c", - "libgit2/index/filemodes.c", - "libgit2/index/inmemory.c", - "libgit2/index/names.c", - "libgit2/index/nsec.c", - "libgit2/index/racy.c", - "libgit2/index/read_index.c", - "libgit2/index/read_tree.c", - "libgit2/index/rename.c", - "libgit2/index/reuc.c", - "libgit2/index/splitindex.c", - "libgit2/index/stage.c", - "libgit2/index/tests.c", - "libgit2/index/tests256.c", - "libgit2/index/version.c", - "libgit2/iterator/index.c", - "libgit2/iterator/iterator_helpers.c", - "libgit2/iterator/tree.c", - "libgit2/iterator/workdir.c", - "libgit2/mailmap/basic.c", - "libgit2/mailmap/blame.c", - "libgit2/mailmap/parsing.c", - "libgit2/merge/analysis.c", - "libgit2/merge/annotated_commit.c", - "libgit2/merge/driver.c", - "libgit2/merge/files.c", - "libgit2/merge/merge_helpers.c", - "libgit2/merge/trees/automerge.c", - "libgit2/merge/trees/commits.c", - "libgit2/merge/trees/modeconflict.c", - "libgit2/merge/trees/recursive.c", - "libgit2/merge/trees/renames.c", - "libgit2/merge/trees/treediff.c", - "libgit2/merge/trees/trivial.c", - "libgit2/merge/trees/whitespace.c", - "libgit2/merge/workdir/dirty.c", - "libgit2/merge/workdir/recursive.c", - "libgit2/merge/workdir/renames.c", - "libgit2/merge/workdir/setup.c", - "libgit2/merge/workdir/simple.c", - "libgit2/merge/workdir/submodules.c", - "libgit2/merge/workdir/trivial.c", - "libgit2/message/trailer.c", - "libgit2/network/cred.c", - "libgit2/network/fetchlocal.c", - "libgit2/network/refspecs.c", - "libgit2/network/remote/defaultbranch.c", - "libgit2/network/remote/delete.c", - "libgit2/network/remote/isvalidname.c", - "libgit2/network/remote/local.c", - "libgit2/network/remote/push.c", - "libgit2/network/remote/remotes.c", - "libgit2/network/remote/rename.c", - "libgit2/network/remote/tag.c", - "libgit2/notes/notes.c", - "libgit2/notes/notesref.c", - "libgit2/object/blob/filter.c", - "libgit2/object/blob/fromstream.c", - "libgit2/object/blob/write.c", - "libgit2/object/cache.c", - "libgit2/object/commit/commitstagedfile.c", - "libgit2/object/commit/parse.c", - "libgit2/object/lookup.c", - "libgit2/object/lookup256.c", - "libgit2/object/lookupbypath.c", - "libgit2/object/message.c", - "libgit2/object/peel.c", - "libgit2/object/raw/chars.c", - "libgit2/object/raw/compare.c", - "libgit2/object/raw/convert.c", - "libgit2/object/raw/fromstr.c", - "libgit2/object/raw/hash.c", - "libgit2/object/raw/short.c", - "libgit2/object/raw/size.c", - "libgit2/object/raw/type2string.c", - "libgit2/object/raw/write.c", - "libgit2/object/shortid.c", - "libgit2/object/tag/list.c", - "libgit2/object/tag/parse.c", - "libgit2/object/tag/peel.c", - "libgit2/object/tag/read.c", - "libgit2/object/tag/write.c", - "libgit2/object/tree/attributes.c", - "libgit2/object/tree/duplicateentries.c", - "libgit2/object/tree/frompath.c", - "libgit2/object/tree/parse.c", - "libgit2/object/tree/read.c", - "libgit2/object/tree/update.c", - "libgit2/object/tree/walk.c", - "libgit2/object/tree/write.c", - "libgit2/object/validate.c", - "libgit2/odb/alternates.c", - "libgit2/odb/backend/backend_helpers.c", - "libgit2/odb/backend/loose.c", - "libgit2/odb/backend/mempack.c", - "libgit2/odb/backend/multiple.c", - "libgit2/odb/backend/nobackend.c", - "libgit2/odb/backend/nonrefreshing.c", - "libgit2/odb/backend/refreshing.c", - "libgit2/odb/backend/simple.c", - "libgit2/odb/emptyobjects.c", - "libgit2/odb/foreach.c", - "libgit2/odb/freshen.c", - "libgit2/odb/largefiles.c", - "libgit2/odb/loose.c", - "libgit2/odb/mixed.c", - "libgit2/odb/open.c", - "libgit2/odb/packed.c", - "libgit2/odb/packed256.c", - "libgit2/odb/packedone.c", - "libgit2/odb/packedone256.c", - "libgit2/odb/sorting.c", - "libgit2/odb/streamwrite.c", - "libgit2/online/badssl.c", - "libgit2/online/clone.c", - "libgit2/online/customcert.c", - "libgit2/online/fetch.c", - "libgit2/online/fetchhead.c", - "libgit2/online/push.c", - "libgit2/online/push_util.c", - "libgit2/online/remotes.c", - "libgit2/online/shallow.c", - "libgit2/pack/filelimit.c", - "libgit2/pack/indexer.c", - "libgit2/pack/midx.c", - "libgit2/pack/packbuilder.c", - "libgit2/pack/sharing.c", - "libgit2/pack/threadsafety.c", - "libgit2/patch/parse.c", - "libgit2/patch/print.c", - "libgit2/path/validate.c", - "libgit2/perf/helper__perf__do_merge.c", - "libgit2/perf/helper__perf__timer.c", - "libgit2/perf/merge.c", - "libgit2/precompiled.c", - "libgit2/rebase/abort.c", - "libgit2/rebase/inmemory.c", - "libgit2/rebase/iterator.c", - "libgit2/rebase/merge.c", - "libgit2/rebase/setup.c", - "libgit2/rebase/sign.c", - "libgit2/rebase/submodule.c", - "libgit2/refs/basic.c", - "libgit2/refs/branches/checkedout.c", - "libgit2/refs/branches/create.c", - "libgit2/refs/branches/delete.c", - "libgit2/refs/branches/ishead.c", - "libgit2/refs/branches/iterator.c", - "libgit2/refs/branches/lookup.c", - "libgit2/refs/branches/move.c", - "libgit2/refs/branches/name.c", - "libgit2/refs/branches/remote.c", - "libgit2/refs/branches/upstream.c", - "libgit2/refs/branches/upstreamname.c", - "libgit2/refs/crashes.c", - "libgit2/refs/create.c", - "libgit2/refs/delete.c", - "libgit2/refs/dup.c", - "libgit2/refs/foreachglob.c", - "libgit2/refs/isvalidname.c", - "libgit2/refs/iterator.c", - "libgit2/refs/list.c", - "libgit2/refs/listall.c", - "libgit2/refs/lookup.c", - "libgit2/refs/namespaces.c", - "libgit2/refs/normalize.c", - "libgit2/refs/overwrite.c", - "libgit2/refs/pack.c", - "libgit2/refs/peel.c", - "libgit2/refs/races.c", - "libgit2/refs/read.c", - "libgit2/refs/ref_helpers.c", - "libgit2/refs/reflog/drop.c", - "libgit2/refs/reflog/messages.c", - "libgit2/refs/reflog/reflog.c", - "libgit2/refs/reflog/reflog_helpers.c", - "libgit2/refs/rename.c", - "libgit2/refs/revparse.c", - "libgit2/refs/setter.c", - "libgit2/refs/shorthand.c", - "libgit2/refs/tags/name.c", - "libgit2/refs/transactions.c", - "libgit2/refs/unicode.c", - "libgit2/refs/update.c", - "libgit2/remote/create.c", - "libgit2/remote/fetch.c", - "libgit2/remote/httpproxy.c", - "libgit2/remote/insteadof.c", - "libgit2/remote/list.c", - "libgit2/repo/config.c", - "libgit2/repo/discover.c", - "libgit2/repo/env.c", - "libgit2/repo/extensions.c", - "libgit2/repo/getters.c", - "libgit2/repo/hashfile.c", - "libgit2/repo/head.c", - "libgit2/repo/headtree.c", - "libgit2/repo/init.c", - "libgit2/repo/message.c", - "libgit2/repo/new.c", - "libgit2/repo/objectformat.c", - "libgit2/repo/open.c", - "libgit2/repo/pathspec.c", - "libgit2/repo/repo_helpers.c", - "libgit2/repo/reservedname.c", - "libgit2/repo/setters.c", - "libgit2/repo/shallow.c", - "libgit2/repo/state.c", - "libgit2/repo/template.c", - "libgit2/reset/default.c", - "libgit2/reset/hard.c", - "libgit2/reset/mixed.c", - "libgit2/reset/reset_helpers.c", - "libgit2/reset/soft.c", - "libgit2/revert/bare.c", - "libgit2/revert/rename.c", - "libgit2/revert/workdir.c", - "libgit2/revwalk/basic.c", - "libgit2/revwalk/hidecb.c", - "libgit2/revwalk/mergebase.c", - "libgit2/revwalk/signatureparsing.c", - "libgit2/revwalk/simplify.c", - "libgit2/stash/apply.c", - "libgit2/stash/drop.c", - "libgit2/stash/foreach.c", - "libgit2/stash/save.c", - "libgit2/stash/stash_helpers.c", - "libgit2/stash/submodules.c", - "libgit2/status/renames.c", - "libgit2/status/single.c", - "libgit2/status/status_helpers.c", - "libgit2/status/submodules.c", - "libgit2/status/worktree.c", - "libgit2/status/worktree_init.c", - "libgit2/stream/deprecated.c", - "libgit2/stream/registration.c", - "libgit2/stress/diff.c", - "libgit2/submodule/add.c", - "libgit2/submodule/escape.c", - "libgit2/submodule/init.c", - "libgit2/submodule/inject_option.c", - "libgit2/submodule/lookup.c", - "libgit2/submodule/modify.c", - "libgit2/submodule/nosubs.c", - "libgit2/submodule/open.c", - "libgit2/submodule/repository_init.c", - "libgit2/submodule/status.c", - "libgit2/submodule/submodule_helpers.c", - "libgit2/submodule/update.c", - "libgit2/threads/atomic.c", - "libgit2/threads/basic.c", - "libgit2/threads/diff.c", - "libgit2/threads/iterator.c", - "libgit2/threads/refdb.c", - "libgit2/threads/thread_helpers.c", - "libgit2/threads/tlsdata.c", - "libgit2/trace/trace.c", - "libgit2/trace/windows/stacktrace.c", - "libgit2/transport/register.c", - "libgit2/transport/ssh_exec.c", - "libgit2/transports/smart/packet.c", - "libgit2/win32/forbidden.c", - "libgit2/win32/longpath.c", - "libgit2/win32/systemdir.c", - "libgit2/worktree/bare.c", - "libgit2/worktree/config.c", - "libgit2/worktree/merge.c", - "libgit2/worktree/open.c", - "libgit2/worktree/reflog.c", - "libgit2/worktree/refs.c", - "libgit2/worktree/repository.c", - "libgit2/worktree/submodule.c", - "libgit2/worktree/worktree.c", - "libgit2/worktree/worktree_helpers.c", + "apply/apply_helpers.c", + "apply/both.c", + "apply/callbacks.c", + "apply/check.c", + "apply/fromdiff.c", + "apply/fromfile.c", + "apply/index.c", + "apply/partial.c", + "apply/tree.c", + "apply/workdir.c", + "attr/file.c", + "attr/flags.c", + "attr/lookup.c", + "attr/macro.c", + "attr/repo.c", + "blame/blame_helpers.c", + "blame/buffer.c", + "blame/getters.c", + "blame/harder.c", + "blame/simple.c", + "checkout/binaryunicode.c", + "checkout/checkout_helpers.c", + "checkout/conflict.c", + "checkout/crlf.c", + "checkout/head.c", + "checkout/icase.c", + "checkout/index.c", + "checkout/nasty.c", + "checkout/tree.c", + "checkout/typechange.c", + "cherrypick/bare.c", + "cherrypick/workdir.c", + "clone/empty.c", + "clone/local.c", + "clone/nonetwork.c", + "clone/transport.c", + "commit/commit.c", + "commit/create.c", + "commit/parent.c", + "commit/parse.c", + "commit/signature.c", + "commit/write.c", + "config/add.c", + "config/backend.c", + "config/conditionals.c", + "config/config_helpers.c", + "config/configlevel.c", + "config/find.c", + "config/global.c", + "config/include.c", + "config/memory.c", + "config/multivar.c", + "config/new.c", + "config/read.c", + "config/readonly.c", + "config/rename.c", + "config/snapshot.c", + "config/stress.c", + "config/validkeyname.c", + "config/write.c", + "core/buf.c", + "core/env.c", + "core/features.c", + "core/hashsig.c", + "core/oid.c", + "core/oidarray.c", + "core/opts.c", + "core/pool.c", + "core/structinit.c", + "core/useragent.c", + "core/version.c", + "date/date.c", + "date/rfc2822.c", + "delta/apply.c", + "describe/describe.c", + "describe/describe_helpers.c", + "describe/t6120.c", + "diff/binary.c", + "diff/blob.c", + "diff/diff_helpers.c", + "diff/diffiter.c", + "diff/drivers.c", + "diff/externalmodifications.c", + "diff/format_email.c", + "diff/header.c", + "diff/index.c", + "diff/notify.c", + "diff/parse.c", + "diff/patch.c", + "diff/patchid.c", + "diff/pathspec.c", + "diff/racediffiter.c", + "diff/rename.c", + "diff/stats.c", + "diff/submodules.c", + "diff/tree.c", + "diff/userdiff.c", + "diff/workdir.c", + "email/create.c", + "fetch/local.c", + "fetchhead/nonetwork.c", + "filter/bare.c", + "filter/blob.c", + "filter/crlf.c", + "filter/custom.c", + "filter/custom_helpers.c", + "filter/file.c", + "filter/ident.c", + "filter/query.c", + "filter/stream.c", + "filter/systemattrs.c", + "filter/wildcard.c", + "grafts/basic.c", + "grafts/parse.c", + "grafts/shallow.c", + "graph/ahead_behind.c", + "graph/commitgraph.c", + "graph/descendant_of.c", + "graph/reachable_from_any.c", + "ignore/path.c", + "ignore/status.c", + "index/add.c", + "index/addall.c", + "index/bypath.c", + "index/cache.c", + "index/collision.c", + "index/conflicts.c", + "index/crlf.c", + "index/filemodes.c", + "index/inmemory.c", + "index/names.c", + "index/nsec.c", + "index/racy.c", + "index/read_index.c", + "index/read_tree.c", + "index/rename.c", + "index/reuc.c", + "index/splitindex.c", + "index/stage.c", + "index/tests.c", + "index/tests256.c", + "index/version.c", + "iterator/index.c", + "iterator/iterator_helpers.c", + "iterator/tree.c", + "iterator/workdir.c", + "mailmap/basic.c", + "mailmap/blame.c", + "mailmap/parsing.c", + "merge/analysis.c", + "merge/annotated_commit.c", + "merge/driver.c", + "merge/files.c", + "merge/merge_helpers.c", + "merge/trees/automerge.c", + "merge/trees/commits.c", + "merge/trees/modeconflict.c", + "merge/trees/recursive.c", + "merge/trees/renames.c", + "merge/trees/treediff.c", + "merge/trees/trivial.c", + "merge/trees/whitespace.c", + "merge/workdir/dirty.c", + "merge/workdir/recursive.c", + "merge/workdir/renames.c", + "merge/workdir/setup.c", + "merge/workdir/simple.c", + "merge/workdir/submodules.c", + "merge/workdir/trivial.c", + "message/trailer.c", + "network/cred.c", + "network/fetchlocal.c", + "network/refspecs.c", + "network/remote/defaultbranch.c", + "network/remote/delete.c", + "network/remote/isvalidname.c", + "network/remote/local.c", + "network/remote/push.c", + "network/remote/remotes.c", + "network/remote/rename.c", + "network/remote/tag.c", + "notes/notes.c", + "notes/notesref.c", + "object/blob/filter.c", + "object/blob/fromstream.c", + "object/blob/write.c", + "object/cache.c", + "object/commit/commitstagedfile.c", + "object/commit/parse.c", + "object/lookup.c", + "object/lookup256.c", + "object/lookupbypath.c", + "object/message.c", + "object/peel.c", + "object/raw/chars.c", + "object/raw/compare.c", + "object/raw/convert.c", + "object/raw/fromstr.c", + "object/raw/hash.c", + "object/raw/short.c", + "object/raw/size.c", + "object/raw/type2string.c", + "object/raw/write.c", + "object/shortid.c", + "object/tag/list.c", + "object/tag/parse.c", + "object/tag/peel.c", + "object/tag/read.c", + "object/tag/write.c", + "object/tree/attributes.c", + "object/tree/duplicateentries.c", + "object/tree/frompath.c", + "object/tree/parse.c", + "object/tree/read.c", + "object/tree/update.c", + "object/tree/walk.c", + "object/tree/write.c", + "object/validate.c", + "odb/alternates.c", + "odb/backend/backend_helpers.c", + "odb/backend/loose.c", + "odb/backend/mempack.c", + "odb/backend/multiple.c", + "odb/backend/nobackend.c", + "odb/backend/nonrefreshing.c", + "odb/backend/refreshing.c", + "odb/backend/simple.c", + "odb/emptyobjects.c", + "odb/foreach.c", + "odb/freshen.c", + "odb/largefiles.c", + "odb/loose.c", + "odb/mixed.c", + "odb/open.c", + "odb/packed.c", + "odb/packed256.c", + "odb/packedone.c", + "odb/packedone256.c", + "odb/sorting.c", + "odb/streamwrite.c", + "online/badssl.c", + "online/clone.c", + "online/customcert.c", + "online/fetch.c", + "online/fetchhead.c", + "online/push.c", + "online/push_util.c", + "online/remotes.c", + "online/shallow.c", + "pack/filelimit.c", + "pack/indexer.c", + "pack/midx.c", + "pack/packbuilder.c", + "pack/sharing.c", + "pack/threadsafety.c", + "patch/parse.c", + "patch/print.c", + "path/validate.c", + "perf/helper__perf__do_merge.c", + "perf/helper__perf__timer.c", + "perf/merge.c", + "precompiled.c", + "rebase/abort.c", + "rebase/inmemory.c", + "rebase/iterator.c", + "rebase/merge.c", + "rebase/setup.c", + "rebase/sign.c", + "rebase/submodule.c", + "refs/basic.c", + "refs/branches/checkedout.c", + "refs/branches/create.c", + "refs/branches/delete.c", + "refs/branches/ishead.c", + "refs/branches/iterator.c", + "refs/branches/lookup.c", + "refs/branches/move.c", + "refs/branches/name.c", + "refs/branches/remote.c", + "refs/branches/upstream.c", + "refs/branches/upstreamname.c", + "refs/crashes.c", + "refs/create.c", + "refs/delete.c", + "refs/dup.c", + "refs/foreachglob.c", + "refs/isvalidname.c", + "refs/iterator.c", + "refs/list.c", + "refs/listall.c", + "refs/lookup.c", + "refs/namespaces.c", + "refs/normalize.c", + "refs/overwrite.c", + "refs/pack.c", + "refs/peel.c", + "refs/races.c", + "refs/read.c", + "refs/ref_helpers.c", + "refs/reflog/drop.c", + "refs/reflog/messages.c", + "refs/reflog/reflog.c", + "refs/reflog/reflog_helpers.c", + "refs/rename.c", + "refs/revparse.c", + "refs/setter.c", + "refs/shorthand.c", + "refs/tags/name.c", + "refs/transactions.c", + "refs/unicode.c", + "refs/update.c", + "remote/create.c", + "remote/fetch.c", + "remote/httpproxy.c", + "remote/insteadof.c", + "remote/list.c", + "repo/config.c", + "repo/discover.c", + "repo/env.c", + "repo/extensions.c", + "repo/getters.c", + "repo/hashfile.c", + "repo/head.c", + "repo/headtree.c", + "repo/init.c", + "repo/message.c", + "repo/new.c", + "repo/objectformat.c", + "repo/open.c", + "repo/pathspec.c", + "repo/repo_helpers.c", + "repo/reservedname.c", + "repo/setters.c", + "repo/shallow.c", + "repo/state.c", + "repo/template.c", + "reset/default.c", + "reset/hard.c", + "reset/mixed.c", + "reset/reset_helpers.c", + "reset/soft.c", + "revert/bare.c", + "revert/rename.c", + "revert/workdir.c", + "revwalk/basic.c", + "revwalk/hidecb.c", + "revwalk/mergebase.c", + "revwalk/signatureparsing.c", + "revwalk/simplify.c", + "stash/apply.c", + "stash/drop.c", + "stash/foreach.c", + "stash/save.c", + "stash/stash_helpers.c", + "stash/submodules.c", + "status/renames.c", + "status/single.c", + "status/status_helpers.c", + "status/submodules.c", + "status/worktree.c", + "status/worktree_init.c", + "stream/deprecated.c", + "stream/registration.c", + "stress/diff.c", + "submodule/add.c", + "submodule/escape.c", + "submodule/init.c", + "submodule/inject_option.c", + "submodule/lookup.c", + "submodule/modify.c", + "submodule/nosubs.c", + "submodule/open.c", + "submodule/repository_init.c", + "submodule/status.c", + "submodule/submodule_helpers.c", + "submodule/update.c", + "threads/atomic.c", + "threads/basic.c", + "threads/diff.c", + "threads/iterator.c", + "threads/refdb.c", + "threads/thread_helpers.c", + "threads/tlsdata.c", + "trace/trace.c", + "trace/windows/stacktrace.c", + "transport/register.c", + "transport/ssh_exec.c", + "transports/smart/packet.c", + "win32/forbidden.c", + "win32/longpath.c", + "win32/systemdir.c", + "worktree/bare.c", + "worktree/config.c", + "worktree/merge.c", + "worktree/open.c", + "worktree/reflog.c", + "worktree/refs.c", + "worktree/repository.c", + "worktree/submodule.c", + "worktree/worktree.c", + "worktree/worktree_helpers.c", }; diff --git a/build.zig.zon b/build.zig.zon index b528ae6..86a41cf 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,7 +1,7 @@ .{ .name = .libgit2, .version = "1.9.0", - .minimum_zig_version = "0.14.0", + .minimum_zig_version = "0.15.2", .fingerprint = 0x7f0051374dea2cba, .dependencies = .{ .libgit2 = .{ @@ -9,19 +9,19 @@ .hash = "N-V-__8AAJbmLwHHxHDWkz0i6WIR6FpNe6tXSLzaPuWtvBBg", }, .openssl = .{ - .url = "git+https://github.com/allyourcodebase/openssl.git#f348124c5382bcc377f1b3277357cbf2ed2fb8db", - .hash = "openssl-3.3.1-2-TC9C3Se3ZACF5WO_CjoD7Bt_X94oCsAAbbwhOp1rTZBe", + .url = "git+https://github.com/allyourcodebase/openssl.git#cad7ccba47e42fa608ca655ec14ae33202df86e1", + .hash = "openssl-3.3.2-TC9C3Wa3ZACgB1hZbrLOQCK9XccIBaW_F3imFfIeYP06", .lazy = true, }, .mbedtls = .{ - .url = "git+https://github.com/allyourcodebase/mbedtls#7d862fe61ff2eac37ee54e1e017fc287bed1cd7a", - .hash = "mbedtls-3.6.2-E4NURzYUAABWLBwHJWx_ppb_j2kDSoGfCfR2rI2zs9dz", + .url = "git+https://github.com/allyourcodebase/mbedtls.git#68d5872dca0faa3e2a09d3329c73bd8779cc34e6", + .hash = "mbedtls-3.6.4-E4NUR24VAADBF5pt-No-Z90DjozkzySYAgq6eDFy9Xdy", .lazy = true, }, }, .paths = .{ "build.zig", - "ClarTestStep.zig", + "build", "build.zig.zon", "README.md", "LICENSE", diff --git a/ClarTestStep.zig b/build/ClarTestStep.zig similarity index 87% rename from ClarTestStep.zig rename to build/ClarTestStep.zig index 3679cf5..91cc013 100644 --- a/ClarTestStep.zig +++ b/build/ClarTestStep.zig @@ -41,15 +41,15 @@ fn make(step: *Step, options: Step.MakeOptions) !void { var man = b.graph.cache.obtain(); defer man.deinit(); - var argv_list: std.ArrayList([]const u8) = .init(arena); + var argv_list: std.ArrayList([]const u8) = .empty; { const file_path = clar.runner.installed_path orelse clar.runner.generated_bin.?.path.?; - try argv_list.append(file_path); + try argv_list.append(arena, file_path); _ = try man.addFile(file_path, null); } - try argv_list.append("-t"); // force TAP output + try argv_list.append(arena, "-t"); // force TAP output for (clar.args.items) |arg| { - try argv_list.append(arg); + try argv_list.append(arena, arg); man.hash.addBytes(arg); } @@ -67,33 +67,16 @@ fn make(step: *Step, options: Step.MakeOptions) !void { try child.spawn(); - var poller = std.io.poll( - b.allocator, - enum { stdout }, - .{ .stdout = child.stdout.? }, - ); - defer poller.deinit(); - - const fifo = poller.fifo(.stdout); - const r = fifo.reader(); - - var buf: std.BoundedArray(u8, 1024) = .{}; - const w = buf.writer(); + var reader_buf: [1024]u8 = undefined; + var file_reader = child.stdout.?.readerStreaming(&reader_buf); + const r = &file_reader.interface; var parser: TapParser = .default; var node: ?std.Progress.Node = null; defer if (node) |n| n.end(); - while (true) { - r.streamUntilDelimiter(w, '\n', null) catch |err| switch (err) { - error.EndOfStream => if (try poller.poll()) continue else break, - else => return err, - }; - - const line = buf.constSlice(); - defer buf.resize(0) catch unreachable; - - switch (try parser.parseLine(arena, line)) { + while (r.takeDelimiter('\n')) |line| { + switch (try parser.parseLine(arena, line orelse break)) { .start_suite => |suite| { if (node) |n| n.end(); node = options.progress_node.start(suite, 0); @@ -111,6 +94,9 @@ fn make(step: *Step, options: Step.MakeOptions) !void { }, .feed_line => {}, } + } else |err| switch (err) { + error.ReadFailed => return file_reader.err.?, + error.StreamTooLong => return error.TapLineTooLong, } const term = try child.wait(); @@ -131,8 +117,8 @@ const TapParser = struct { feed_line, const Failure = struct { - description: std.ArrayListUnmanaged(u8), - reasons: std.ArrayListUnmanaged([]const u8), + description: std.ArrayList(u8), + reasons: std.ArrayList([]const u8), }; }; diff --git a/build/chmod.zig b/build/chmod.zig new file mode 100644 index 0000000..7a07480 --- /dev/null +++ b/build/chmod.zig @@ -0,0 +1,22 @@ +//! Usage: chmod [file-path...] +//! Accepts a list of file paths as input and changes their permission bits to `0o755`. +//! POSIX only. + +pub fn main() !void { + var args = std.process.args(); + _ = args.skip(); + while (args.next()) |path| { + const file = std.fs.cwd().openFile(path, .{ .mode = .read_write }) catch |err| + fatal("unable to open file '{s}': {t}", .{ path, err }); + defer file.close(); + file.setPermissions(.{ .inner = .{ .mode = 0o755 } }) catch |err| + fatal("unable to set permissions on file '{s}': {t}", .{ path, err }); + } +} + +fn fatal(comptime fmt: []const u8, args: anytype) noreturn { + std.log.err(fmt, args); + std.process.exit(1); +} + +const std = @import("std"); diff --git a/build/clar_fix.zig b/build/clar_fix.zig new file mode 100644 index 0000000..8126e67 --- /dev/null +++ b/build/clar_fix.zig @@ -0,0 +1,67 @@ +//! Usage: clar_fix +//! Replaces *reads* of the CLAR_FIXTURE_PATH macro definition in `src-file` with +//! the absolute path of `fixtures-dir`. `#ifdef`s are not affected. + +const std = @import("std"); + +const fixture_var_name = "CLAR_FIXTURE_PATH"; + +pub fn main() !void { + var arena_inst: std.heap.ArenaAllocator = .init(std.heap.page_allocator); + defer arena_inst.deinit(); + const arena = arena_inst.allocator(); + + var args = try std.process.argsWithAllocator(arena); + _ = args.skip(); + + const clar_fixture_h = args.next() orelse fatal("expected path to 'clar/fixtures.h' file", .{}); + const fixture_path: []const u8 = blk: { + const path_arg = args.next() orelse fatal("expected path to test resources directory", .{}); + + var cleaned_path: std.ArrayList(u8) = try .initCapacity(arena, std.fs.max_path_bytes + 2); + cleaned_path.appendAssumeCapacity('"'); // add string quotes + const abs_path = try std.fs.cwd().realpath(path_arg, cleaned_path.unusedCapacitySlice()); + cleaned_path.items.len += abs_path.len; + cleaned_path.appendAssumeCapacity('"'); + + // clar expects the fixture path to only have posix seperators or else some tests will break + for (cleaned_path.items) |*c| { + if (c.* == '\\') c.* = '/'; + } + break :blk cleaned_path.items; + }; + + const file = try std.fs.cwd().openFile(clar_fixture_h, .{ .mode = .read_write }); + defer file.close(); + + var buf: [1024]u8 = undefined; + var src: std.ArrayList(u8) = src: { + var file_reader = file.reader(&buf); + + const file_size = try file_reader.getSize(); + const to_add = fixture_path.len -| fixture_var_name.len; + var src: std.Io.Writer.Allocating = try .initCapacity(arena, file_size + to_add); + + _ = try file_reader.interface.streamRemaining(&src.writer); + break :src src.toArrayList(); + }; + + const i = std.mem.indexOf( + u8, + src.items, + "return fixture_path(CLAR_FIXTURE_PATH, fixture_name);", + ) orelse return; + + const start = i + "return fixture_path(".len; + src.replaceRangeAssumeCapacity(start, fixture_var_name.len, fixture_path); + + try file.seekTo(0); + var writer = file.writer(&buf); // buf is safe to reuse since file_reader is out of scope + try writer.interface.writeAll(src.items); + try writer.interface.flush(); +} + +fn fatal(comptime fmt: []const u8, args: anytype) noreturn { + std.log.err(fmt, args); + std.process.exit(1); +}