ref: f12b2f1cd7cd26033457a54454456158e1572834
dir: /git.c/
#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); }