ref: 073882f6a2a8c065375b94dc77c59eb7d8b2091f
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);
}