From d98ffcfd85e65d8e3a1f3018faa6f6050e20f4f6 Mon Sep 17 00:00:00 2001 From: "Gabriel A. Giovanini" Date: Wed, 26 Feb 2025 21:26:07 +0100 Subject: ref: Give struct to the files --- src/git.zig | 209 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/root.zig | 102 ++--------------------------- 2 files changed, 214 insertions(+), 97 deletions(-) create mode 100644 src/git.zig (limited to 'src') diff --git a/src/git.zig b/src/git.zig new file mode 100644 index 0000000..4803103 --- /dev/null +++ b/src/git.zig @@ -0,0 +1,209 @@ +const std = @import("std"); +const testing = std.testing; +const Allocator = std.mem.Allocator; +const galloc = @import("galloc.zig"); + +const git = @cImport({ + @cInclude("git2.h"); +}); + +const GitError = error{ + RepositoryAlreadyInitialized, + Unkown, + + //libgit specific error + GitError, + GitNotfound, + GitExists, + GitAmbiguous, + GitBufs, + GitUser, + GitUnbornBranch, + GitUnmerged, + GitNonFastForward, + GitInvalidSpec, + GitConflict, + GitLocked, + GitModified, + GitAuth, + GitCertificate, + GitApplied, + GitPeel, + GitEof, + GitInvalid, + GitUncommitted, + GitDirectory, + GitMergeConflict, + GitPassthrough, + GitIterOver, + GitRetry, + GitMismatch, + GitIndexDirty, + GitApplyFail, + GitOwner, + GitTimeout, + GitUnchanged, + GitNotSupported, + GitReadonly, +}; + +var alloc: galloc.GitAllocator = undefined; + +fn malloc(size: usize, _: ?*anyopaque) callconv(.C) ?*anyopaque { + return alloc.malloc(size); +} + +fn relloc(ptr: ?*anyopaque, size: usize, _: ?*anyopaque) callconv(.C) ?*anyopaque { + const new_ptr = alloc.realloc(ptr, size); + return new_ptr; +} + +fn free(ptr: ?*anyopaque) callconv(.C) void { + alloc.free(ptr); +} + +fn err(code: c_int) GitError!void { + if (code >= 0) return; + + return switch (code) { + git.GIT_ERROR => GitError.GitError, + git.GIT_ENOTFOUND => GitError.GitNotfound, + git.GIT_EEXISTS => GitError.GitExists, + git.GIT_EAMBIGUOUS => GitError.GitAmbiguous, + git.GIT_EBUFS => GitError.GitBufs, + git.GIT_EUSER => GitError.GitUser, + git.GIT_EUNBORNBRANCH => GitError.GitUnbornBranch, + git.GIT_EUNMERGED => GitError.GitUnmerged, + git.GIT_ENONFASTFORWARD => GitError.GitNonFastForward, + git.GIT_EINVALIDSPEC => GitError.GitInvalidSpec, + git.GIT_ECONFLICT => GitError.GitConflict, + git.GIT_ELOCKED => GitError.GitLocked, + git.GIT_EMODIFIED => GitError.GitModified, + git.GIT_EAUTH => GitError.GitAuth, + git.GIT_ECERTIFICATE => GitError.GitCertificate, + git.GIT_EAPPLIED => GitError.GitApplied, + git.GIT_EPEEL => GitError.GitPeel, + git.GIT_EEOF => GitError.GitEof, + git.GIT_EINVALID => GitError.GitInvalid, + git.GIT_EUNCOMMITTED => GitError.GitUncommitted, + git.GIT_EDIRECTORY => GitError.GitDirectory, + git.GIT_EMERGECONFLICT => GitError.GitMergeConflict, + git.GIT_PASSTHROUGH => GitError.GitPassthrough, + git.GIT_ITEROVER => GitError.GitIterOver, + git.GIT_RETRY => GitError.GitRetry, + git.GIT_EMISMATCH => GitError.GitMismatch, + git.GIT_EINDEXDIRTY => GitError.GitIndexDirty, + git.GIT_EAPPLYFAIL => GitError.GitApplyFail, + git.GIT_EOWNER => GitError.GitOwner, + git.GIT_TIMEOUT => GitError.GitTimeout, + git.GIT_EUNCHANGED => GitError.GitUnchanged, + git.GIT_ENOTSUPPORTED => GitError.GitNotSupported, + git.GIT_EREADONLY => GitError.GitReadonly, + else => GitError.Unkown, + }; +} + +const git_allocator = extern struct { + gmalloc: ?*const fn (size: usize, payload: ?*anyopaque) callconv(.C) ?*anyopaque, + grealloc: ?*const fn (ptr: ?*anyopaque, size: usize, payload: ?*anyopaque) callconv(.C) ?*anyopaque, + gfree: ?*const fn (ptr: ?*anyopaque) callconv(.C) void, +}; + +pub fn init(a: std.mem.Allocator) GitError!void { + alloc = galloc.GitAllocator.init(a); + + const cAlloc = git_allocator{ + .gmalloc = malloc, + .grealloc = relloc, + .gfree = free, + }; + + var code = git.git_libgit2_opts(git.GIT_OPT_SET_ALLOCATOR, &cAlloc); + try err(code); + + code = git.git_libgit2_init(); + try err(code); +} + +pub fn deinit() !void { + defer alloc.deinit(); + try err(git.git_libgit2_shutdown()); +} + +pub const Repository = struct { + repository: ?*git.git_repository = null, + + fn validateInit(self: *Repository) GitError!void { + if (self.repository != null) + return GitError.RepositoryAlreadyInitialized; + } + + pub fn open(self: *Repository, path: []const u8) GitError!void { + try self.validateInit(); + try err(git.git_repository_open(@ptrCast(&self.repository), path.ptr)); + } + + pub fn init(self: *Repository, path: []const u8, bare: bool) GitError!void { + try self.validateInit(); + try err(git.git_repository_init(@ptrCast(&self.repository), path.ptr, if (bare) 1 else 0)); + } + + pub fn deinit(self: *Repository) void { + if (self.repository) |repo| { + git.git_repository_free(repo); + } + } +}; + +test "init deinit" { + try init(testing.allocator); + try deinit(); +} + +test "open repository" { + try init(testing.allocator); + defer deinit() catch {}; + + var repository = Repository{}; + defer repository.deinit(); + + try repository.open("."); +} + +test "init repository" { + var tmp_dir = testing.tmpDir(.{}); + defer tmp_dir.cleanup(); + + const full_path = try tmp_dir.dir.realpathAlloc(testing.allocator, "."); + defer testing.allocator.free(full_path); + + try init(testing.allocator); + defer deinit() catch {}; + + var repository = Repository{}; + defer repository.deinit(); + + try repository.init(full_path, false); +} + +test "init repository bare" { + var tmp_dir = testing.tmpDir(.{}); + defer tmp_dir.cleanup(); + + const full_path = try tmp_dir.dir.realpathAlloc(testing.allocator, "."); + defer testing.allocator.free(full_path); + + try init(testing.allocator); + defer deinit() catch {}; + + var repository = Repository{}; + defer repository.deinit(); + + try repository.init(full_path, false); + + // try opening the repository to test if it is properly created. + var tmp = Repository{}; + defer tmp.deinit(); + + try tmp.open(full_path); +} diff --git a/src/root.zig b/src/root.zig index 9552bc5..43b3598 100644 --- a/src/root.zig +++ b/src/root.zig @@ -1,102 +1,10 @@ const std = @import("std"); const testing = std.testing; -const Allocator = std.mem.Allocator; -const galloc = @import("galloc.zig"); +const git = @import("git.zig"); -const git = @cImport({ - @cInclude("git2.h"); -}); +pub const Git = git; +pub const Repository = git.Repository; -const GitError = error{ - InitError, - DeinitError, - OpenError, -}; - -const git_allocator = extern struct { - gmalloc: ?*const fn (size: usize, payload: ?*anyopaque) callconv(.C) ?*anyopaque, - grealloc: ?*const fn (ptr: ?*anyopaque, size: usize, payload: ?*anyopaque) callconv(.C) ?*anyopaque, - gfree: ?*const fn (ptr: ?*anyopaque) callconv(.C) void, -}; - -pub var alloc: galloc.GitAllocator = undefined; - -fn malloc(size: usize, _: ?*anyopaque) callconv(.C) ?*anyopaque { - std.debug.print("MALLOC {}\n", .{size}); - return alloc.malloc(size); -} - -fn relloc(ptr: ?*anyopaque, size: usize, _: ?*anyopaque) callconv(.C) ?*anyopaque { - std.debug.print("REALLOC {} {?}\n", .{ size, ptr }); - const new_ptr = alloc.realloc(ptr, size); - return new_ptr; -} - -fn free(ptr: ?*anyopaque) callconv(.C) void { - std.debug.print("FREE\n", .{}); - alloc.free(ptr); -} - -pub fn initGit(a: std.mem.Allocator) GitError!void { - alloc = galloc.GitAllocator.init(a); - - const cAlloc = git_allocator{ - .gmalloc = malloc, - .grealloc = relloc, - .gfree = free, - }; - - _ = git.git_libgit2_opts(git.GIT_OPT_SET_ALLOCATOR, &cAlloc); - - const code = git.git_libgit2_init(); - if (code < 0) { - return GitError.InitError; - } -} - -pub fn deInitGit() !void { - defer alloc.deinit(); - const code = git.git_libgit2_shutdown(); - if (code < 0) { - return GitError.DeinitError; - } -} - -pub const Repository = struct { - allocator: Allocator = undefined, - repository: ?*git.git_repository = null, - - pub fn init(a: Allocator) !Repository { - return Repository{ - .allocator = a, - }; - } - - pub fn open(self: *Repository, path: []const u8) GitError!void { - const code = git.git_repository_open(@ptrCast(&self.repository), path.ptr); - if (code < 0) { - return GitError.OpenError; - } - } - - pub fn deinit(self: *Repository) void { - if (self.repository) |repo| { - git.git_repository_free(repo); - } - } -}; - -test "init deinit" { - try initGit(testing.allocator); - try deInitGit(); -} - -test "open repository" { - try initGit(testing.allocator); - - var repository = try Repository.init(std.testing.allocator); - try repository.open("."); - - repository.deinit(); - try deInitGit(); +test { + std.testing.refAllDecls(@This()); } -- cgit v1.2.3