shithub: libgit

Download patch

ref: f12b2f1cd7cd26033457a54454456158e1572834
author: sirjofri <sirjofri@sirjofri.de>
date: Tue Jun 11 13:52:22 EDT 2024

working commit, add, rm

diff: cannot open b/test//null: file does not exist: 'b/test//null'
--- /dev/null
+++ b/git.c
@@ -1,0 +1,220 @@
+#include <u.h>
+#include <libc.h>
+#include "git.h"
+
+char *Enoinit = "not initialized";
+
+char *gitdir = "/mnt/git";
+int initialized = 0;
+char *repodir = nil;
+char *indexfile = nil;
+
+enum {
+	FAIL = 0,
+	SUCCESS = 1,
+};
+
+enum {
+	ADD,
+	BRANCH,
+	COMMIT,
+	DIFF,
+	LOG,
+	RM,
+};
+
+char *cmds[] = {
+	[ADD] nil,
+	[BRANCH] nil,
+	[COMMIT] "/bin/git/commit",
+	[DIFF] nil,
+	[LOG] nil,
+	[RM] nil,
+};
+
+char *cname[] = {
+	[ADD] nil,
+	[BRANCH] nil,
+	[COMMIT] "commit",
+	[DIFF] nil,
+	[LOG] nil,
+	[RM] nil,
+};
+
+static int
+isinitialized(void)
+{
+	return initialized;
+}
+#define checkinitialized() if (!isinitialized()){ werrstr(Enoinit); return FAIL; }
+
+int
+initgit(char *dir)
+{
+	if (initialized) {
+		werrstr("already initialized");
+		return FAIL;
+	}
+	
+	repodir = strdup(dir);
+	indexfile = smprint("%s/.git/INDEX9", dir);
+	if (!repodir || !indexfile) {
+		if (repodir) free(repodir);
+		if (indexfile) free(indexfile);
+		return FAIL;
+	}
+	
+	switch (fork()) {
+	case 0: /* child */
+		if (chdir(dir) < 0)
+			sysfatal("unable to chdir: %r");
+		execl("/bin/git/fs", "fs", "-m", gitdir, nil);
+		sysfatal("unable to exec: %r");
+		break;
+	case -1: /* error */
+		werrstr("unable to fork: %r");
+		return FAIL;
+		break;
+	default: /* parent */
+		break;
+	}
+	initialized = 1;
+	return SUCCESS;
+}
+
+/* args[0] reserved for argv0 */
+static int
+gitcmd(int cmd, char **args)
+{
+	int pid;
+	char *c;
+	Waitmsg *wmsg;
+	
+	c = cmds[cmd];
+	if (!c) {
+		werrstr("not implemented");
+		return FAIL;
+	}
+	args[0] = cname[cmd];
+	
+	fprint(2, "command: %s", c);
+	for (char **a = args; *a; a++)
+		fprint(2, " '%s'", *a);
+	fprint(2, "\n");
+	
+	switch (pid = fork()) {
+	case 0: /* child */
+		if (chdir(repodir) < 0)
+			sysfatal("%r");
+		exec(c, args);
+		break;
+	case -1: /* error */
+		werrstr("unable to fork: %r");
+		return FAIL;
+		break;
+	default: /* parent */
+		break;
+	}
+	
+	for (;;) {
+		wmsg = wait();
+		if (wmsg->pid == pid)
+			break;
+	}
+	
+	if (wmsg->msg && *wmsg->msg) {
+		werrstr("%s", wmsg->msg);
+		free(wmsg);
+		return FAIL;
+	}
+	if (wmsg) free(wmsg);
+	return SUCCESS;
+}
+
+int
+gitcommit(char *msg, char *file, ...)
+{
+	va_list args;
+	char *files[32];
+	char *f;
+	int nfile = 1;
+
+	checkinitialized();
+	
+	files[nfile++] = "-m";
+	files[nfile++] = msg;
+	
+	files[nfile++] = file;
+	
+	va_start(args, file);
+	while (f = va_arg(args, char*)) {
+		files[nfile++] = f;
+		if (nfile >= sizeof(files)) {
+			files[nfile] = nil;
+			if (!gitcmd(COMMIT, files))
+				return FAIL;
+			nfile = 3;
+		}
+	}
+	va_end(args);
+	
+	if (nfile > 3) {
+		files[nfile] = nil;
+		if (!gitcmd(COMMIT, files))
+			return FAIL;
+	}
+	
+	return SUCCESS;
+}
+
+static int
+gitaddrm(char *F, char *file, va_list args)
+{
+	char *ofile;
+	int fd;
+	
+	ofile = strdup(file);
+	file = cleanname(ofile);
+	
+	fd = open(indexfile, OWRITE);
+	if (fd < 0)
+		return FAIL;
+	seek(fd, 0, 2);
+	
+	fprint(fd, "%s NOQID 0 %s\n", F, file);
+	free(ofile);
+	
+	while ((ofile = va_arg(args, char*)) != nil) {
+		ofile = strdup(ofile);
+		file = cleanname(ofile);
+		
+		fprint(fd, "%s NOQID 0 %s\n", F, file);
+		free(ofile);
+	}
+	
+	va_end(args);
+	close(fd);
+	return SUCCESS;
+}
+
+int
+gitadd(char *file, ...)
+{
+	va_list args;
+
+	checkinitialized();
+	
+	va_start(args, file);
+	return gitaddrm("A", file, args);
+}
+
+int
+gitrm(char *file, ...)
+{
+	va_list args;
+
+	checkinitialized();
+	
+	va_start(args, file);
+	return gitaddrm("R", file, args);
+}
--- /dev/null
+++ b/git.h
@@ -1,0 +1,10 @@
+#pragma lib "libgit.a"
+#pragma src "/sys/src/libgit"
+
+/* initialize git system */
+int initgit(char*);
+
+/* git commands. files must be relative within repository */
+int gitcommit(char *msg, char* file, ...);
+int gitadd(char* file, ...);
+int gitrm(char* file, ...);
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,8 @@
+</$objtype/mkfile
+
+LIB=/$objtype/lib/libgit.a
+OFILES=git.$O
+
+HFILES=/sys/include/git.h
+
+</sys/src/cmd/mksyslib
--- /dev/null
+++ b/test/gtest.c
@@ -1,0 +1,31 @@
+#include <u.h>
+#include <libc.h>
+#include "../git.h"
+
+char *dir = "/tmp/repo";
+char *addfile = "test";
+
+#define test(A, B) if (!A) { sysfatal("%s: %r\n", B); }
+
+void
+main(void)
+{
+	int fd;
+	char buf[128];
+	
+	if (!initgit("/tmp/repo"))
+		sysfatal("gitinit: %r");
+	
+	snprint(buf, sizeof(buf), "%s/%s", dir, addfile);
+	
+	fd = create(buf, OWRITE, 0666);
+	if (fd < 0)
+		sysfatal("%r");
+	fprint(fd, "hello world\n");
+	close(fd);
+	
+	test(gitadd(addfile, nil), "add file");
+	test(gitcommit("add file", addfile, nil), "commit add");
+	test(gitrm(addfile, nil), "rm file");
+	test(gitcommit("remove file", addfile, nil), "commit rm");
+}
--- /dev/null
+++ b/test/mkfile
@@ -1,0 +1,6 @@
+</$objtype/mkfile
+
+TARG=gtest
+OFILES=gtest.$O
+
+</sys/src/cmd/mkone
--- /dev/null
+++ b/test/test.rc
@@ -1,0 +1,38 @@
+#!/bin/rc
+
+rfork en
+
+t=`{pwd}
+t=$t/6.out
+
+mk -a
+ramfs
+
+mkdir -p /tmp/repo
+cd /tmp/repo
+git/init .
+
+echo testfile > beforetest
+git/add beforetest
+git/commit -m init beforetest
+
+cat <<EOF >.git/config
+[user]
+	name = testuser
+	email = testmail
+EOF
+
+cat .git/INDEX9
+
+echo '========== run test ============'
+$t
+echo '========== end test ============'
+
+echo git/log: should contain "remove file" and "add file" commits
+git/log
+echo ''
+echo INDEX9: should contain "R NOQID 0 test" line
+cat .git/INDEX9
+echo walk
+walk
+rc -i