login

<     >

2022-02-26 17:17:22 (UTC-03:00)

Marcel Rodrigues <marcelgmr@gmail.com>

first commit: basic libgit2 wrapper

diff --git a/git.lua b/git.lua
new file mode 100644
index 0000000..9b4b38a
--- /dev/null
+++ b/git.lua
@@ -0,0 +1,154 @@
+local ffi = require "ffi"
+
+ffi.cdef[[
+typedef int64_t git_time_t;
+typedef struct git_repository git_repository;
+typedef struct git_object git_object;
+typedef struct git_commit git_commit;
+typedef struct git_tree git_tree;
+typedef struct git_tree_entry git_tree_entry;
+typedef struct git_diff git_diff;
+typedef struct git_blob git_blob;
+typedef struct git_tag git_tag;
+typedef struct git_revwalk git_revwalk;
+typedef enum {
+	GIT_OBJECT_ANY =      -2, /**< Object can be any of the following */
+	GIT_OBJECT_INVALID =  -1, /**< Object is invalid. */
+	GIT_OBJECT_COMMIT =    1, /**< A commit object. */
+	GIT_OBJECT_TREE =      2, /**< A tree (directory listing) object. */
+	GIT_OBJECT_BLOB =      3, /**< A file revision object. */
+	GIT_OBJECT_TAG =       4, /**< An annotated tag object. */
+	GIT_OBJECT_OFS_DELTA = 6, /**< A delta, base is given by an offset. */
+	GIT_OBJECT_REF_DELTA = 7  /**< A delta, base is given by object id. */
+} git_object_t;
+typedef struct git_oid {
+	/** raw binary formatted id */
+	unsigned char id[20];
+} git_oid;
+typedef struct git_strarray {
+	char **strings;
+	size_t count;
+} git_strarray;
+typedef struct git_time {
+	git_time_t time; /**< time in seconds from epoch */
+	int offset; /**< timezone offset, in minutes */
+	char sign; /**< indicator for questionable '-0000' offsets in signature */
+} git_time;
+typedef struct git_signature {
+	char *name; /**< full name of the author */
+	char *email; /**< email of the author */
+	git_time when; /**< time when the action happened */
+} git_signature;
+typedef struct git_diff_options git_diff_options;
+
+int git_libgit2_init();
+int git_libgit2_shutdown();
+int git_libgit2_version(int *major, int *minor, int *rev);
+
+const git_oid * git_object_id(const git_object *obj);
+void git_object_free(git_object *object);
+
+int git_repository_open_ext(git_repository **out, const char *path, unsigned int flags, const char *ceiling_dirs);
+int git_repository_open_bare(git_repository **out, const char *bare_path);
+
+int git_oid_fromstr(git_oid *out, const char *str);
+char * git_oid_tostr(char *out, size_t n, const git_oid *id);
+
+int git_reference_list(git_strarray *array, git_repository *repo);
+void git_strarray_free(git_strarray *array);
+
+int git_tag_list(git_strarray *tag_names, git_repository *repo);
+
+int git_revparse_single(git_object **out, git_repository *repo, const char *spec);
+
+int git_commit_lookup(git_commit **commit, git_repository *repo, const git_oid *id);
+int git_commit_parent(git_commit **out, const git_commit *commit, unsigned int n);
+const char * git_commit_message(const git_commit *commit);
+const char * git_commit_summary(git_commit *commit);
+git_time_t git_commit_time(const git_commit *commit);
+const git_signature * git_commit_author(const git_commit *commit);
+
+int git_revwalk_new(git_revwalk **out, git_repository *repo);
+int git_revwalk_push_range(git_revwalk *walk, const char *range);
+int git_revwalk_next(git_oid *out, git_revwalk *walk);
+
+int git_commit_tree(git_tree **tree_out, const git_commit *commit);
+size_t git_tree_entrycount(const git_tree *tree);
+const git_tree_entry * git_tree_entry_byindex(const git_tree *tree, size_t idx);
+git_object_t git_tree_entry_type(const git_tree_entry *entry);
+
+int git_diff_tree_to_tree(git_diff **diff, git_repository *repo, git_tree *old_tree, git_tree *new_tree, const git_diff_options *opts);
+]]
+local C = ffi.load("git2")
+
+local function strarr_to_table(strarr)
+    local tab = {}
+    for i = 1, tonumber(strarr[0].count) do
+        local str = ffi.string(strarr[0].strings[i-1])
+        table.insert(tab, str)
+    end
+    return tab
+end
+
+local Commit = {}
+Commit.__index = Commit
+
+local function get_commit(commit)
+    return setmetatable({commit=commit}, Commit)
+end
+
+function Commit:message()
+    return ffi.string(C.git_commit_message(self.commit))
+end
+
+function Commit:summary()
+    return ffi.string(C.git_commit_summary(self.commit))
+end
+
+function Commit:parent(n)
+    n = n or 1
+    local pcommit = ffi.new("git_commit *[1]")
+    C.git_commit_parent(pcommit, self.commit, n-1)
+    return get_commit(pcommit[0])
+end
+
+local Repo = {}
+Repo.__index = Repo
+
+function Repo:refs()
+    local strarr = ffi.new("git_strarray[1]")
+    C.git_reference_list(strarr, self.repo)
+    local refs = strarr_to_table(strarr)
+    C.git_strarray_free(strarr);
+    return refs
+end
+
+function Repo:tags()
+    local strarr = ffi.new("git_strarray[1]")
+    C.git_tag_list(strarr, self.repo)
+    local tags = strarr_to_table(strarr)
+    C.git_strarray_free(strarr);
+    return tags
+end
+
+function Repo:commit(rev)
+    local pobj = ffi.new("git_object *[1]")
+    C.git_revparse_single(pobj, self.repo, rev)
+    local obj = pobj[0]
+    local oid = C.git_object_id(obj)
+    local pcommit = ffi.new("git_commit *[1]")
+    C.git_commit_lookup(pcommit, self.repo, oid)
+    local commit = pcommit[0]
+    C.git_object_free(obj)
+    return get_commit(commit)
+end
+
+local function open(path)
+    local self = setmetatable({}, Repo)
+    local prepo = ffi.new("git_repository *[1]")
+    assert(C.git_repository_open_bare(prepo, path) == 0)
+    self.repo = prepo[0]
+    return self
+end
+
+return {init=C.git_libgit2_init, shutdown=C.git_libgit2_shutdown, open=open}