@@ 285,11 285,29 @@ dialssh(Conn *c, char *host, char *, char *path, char *direction)
snprint(cmd, sizeof(cmd), "git-%s-pack", direction);
dprint(1, "exec ssh '%s' '%s' %s\n", host, cmd, path);
execl("/bin/ssh", "ssh", host, cmd, path, nil);
- }else{
- close(pfd[0]);
- c->type = ConnSsh;
- c->rfd = pfd[1];
- c->wfd = dup(pfd[1], -1);
+ sysfatal("exec: %r");
+ }
+ close(pfd[0]);
+ c->type = ConnSsh;
+ c->rfd = pfd[1];
+ c->wfd = dup(pfd[1], -1);
+ return 0;
+}
+
+static int
+githandshake(Conn *c, char *host, char *path, char *direction)
+{
+ char *p, *e, cmd[512];
+
+ p = cmd;
+ e = cmd + sizeof(cmd);
+ p = seprint(p, e - 1, "git-%s-pack %s", direction, path);
+ if(host != nil)
+ p = seprint(p + 1, e, "host=%s", host);
+ if(writepkt(c, cmd, p - cmd + 1) == -1){
+ fprint(2, "failed to write message\n");
+ closeconn(c);
+ return -1;
}
return 0;
}
@@ 297,7 315,7 @@ dialssh(Conn *c, char *host, char *, char *path, char *direction)
static int
dialhjgit(Conn *c, char *host, char *port, char *path, char *direction, int auth)
{
- char *ds, *p, *e, cmd[512];
+ char *ds;
int pid, pfd[2];
if((ds = netmkaddr(host, "tcp", port)) == nil)
@@ 317,30 335,26 @@ dialhjgit(Conn *c, char *host, char *port, char *path, char *direction, int auth
else
execl("/bin/tlsclient", "tlsclient", ds, nil);
sysfatal("exec: %r");
- }else{
- close(pfd[0]);
- p = cmd;
- e = cmd + sizeof(cmd);
- p = seprint(p, e - 1, "git-%s-pack %s", direction, path);
- p = seprint(p + 1, e, "host=%s", host);
- c->type = ConnGit9;
- c->rfd = pfd[1];
- c->wfd = dup(pfd[1], -1);
- if(writepkt(c, cmd, p - cmd + 1) == -1){
- fprint(2, "failed to write message\n");
- close(c->rfd);
- close(c->wfd);
- return -1;
- }
}
- return 0;
+ close(pfd[0]);
+ c->type = ConnGit9;
+ c->rfd = pfd[1];
+ c->wfd = dup(pfd[1], -1);
+ return githandshake(c, host, path, direction);
}
+void
+initconn(Conn *c, int rd, int wr)
+{
+ c->type = ConnGit;
+ c->rfd = rd;
+ c->wfd = wr;
+}
static int
dialgit(Conn *c, char *host, char *port, char *path, char *direction)
{
- char *ds, *p, *e, cmd[512];
+ char *ds;
int fd;
if((ds = netmkaddr(host, "tcp", port)) == nil)
@@ 349,27 363,51 @@ dialgit(Conn *c, char *host, char *port, char *path, char *direction)
fd = dial(ds, nil, nil, nil);
if(fd == -1)
return -1;
- p = cmd;
- e = cmd + sizeof(cmd);
- p = seprint(p, e - 1, "git-%s-pack %s", direction, path);
- p = seprint(p + 1, e, "host=%s", host);
c->type = ConnGit;
c->rfd = fd;
c->wfd = dup(fd, -1);
- if(writepkt(c, cmd, p - cmd + 1) == -1){
- fprint(2, "failed to write message\n");
- close(fd);
- return -1;
- }
- return 0;
+ return githandshake(c, host, path, direction);
}
-void
-initconn(Conn *c, int rd, int wr)
+static int
+servelocal(Conn *c, char *path, char *direction)
{
+ int pid, pfd[2];
+
+ if(pipe(pfd) == -1)
+ sysfatal("unable to open pipe: %r");
+ pid = fork();
+ if(pid == -1)
+ sysfatal("unable to fork");
+ if(pid == 0){
+ close(pfd[1]);
+ dup(pfd[0], 0);
+ dup(pfd[0], 1);
+ execl("/bin/git/serve", "serve", "-w", nil);
+ sysfatal("exec: %r");
+ }
+ close(pfd[0]);
c->type = ConnGit;
- c->rfd = rd;
- c->wfd = wr;
+ c->rfd = pfd[1];
+ c->wfd = dup(pfd[1], -1);
+ return githandshake(c, nil, path, direction);
+}
+
+static int
+localrepo(char *uri, char *path, int npath)
+{
+ int fd;
+
+ snprint(path, npath, "%s/.git/../", uri);
+ fd = open(path, OREAD);
+ if(fd < 0)
+ return -1;
+ if(fd2path(fd, path, npath) != 0){
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ return 0;
}
int
@@ 378,12 416,16 @@ gitconnect(Conn *c, char *uri, char *direction)
char proto[Nproto], host[Nhost], port[Nport];
char repo[Nrepo], path[Npath];
+ memset(c, 0, sizeof(Conn));
+ c->rfd = c->wfd = c->cfd = -1;
+
+ if(localrepo(uri, path, sizeof(path)) == 0)
+ return servelocal(c, path, direction);
+
if(parseuri(uri, proto, host, port, path, repo) == -1){
werrstr("bad uri %s", uri);
return -1;
}
-
- memset(c, 0, sizeof(Conn));
if(strcmp(proto, "ssh") == 0)
return dialssh(c, host, port, path, direction);
else if(strcmp(proto, "git") == 0)
@@ 345,18 345,25 @@ void
main(int argc, char **argv)
{
Hash th, ch, parents[Maxparents];
- char *msg, *name, *email, *dstr;
- int i, r, nparents;
+ char *msg, *name, *email, *dstr, cwd[1024];
+ int i, r, ncwd, nparents;
vlong date;
Object *t;
+ gitinit();
+ gitinit();
+ if(access(".git", AEXIST) != 0)
+ sysfatal("could not find git repo: %r");
+ if(getwd(cwd, sizeof(cwd)) == nil)
+ sysfatal("getcwd: %r");
msg = nil;
name = nil;
email = nil;
dstr = nil;
date = time(nil);
nparents = 0;
- gitinit();
+ ncwd = strlen(cwd);
+
ARGBEGIN{
case 'm': msg = EARGF(usage()); break;
case 'n': name = EARGF(usage()); break;
@@ 385,12 392,14 @@ main(int argc, char **argv)
}
if(msg == nil || name == nil)
usage();
- for(i = 0; i < argc; i++)
+ for(i = 0; i < argc; i++){
cleanname(argv[i]);
+ if(*argv[i] == '/' && strncmp(argv[i], cwd, ncwd) == 0)
+ argv[i] += ncwd;
+ while(*argv[i] == '/')
+ argv[i]++;
+ }
- gitinit();
- if(access(".git", AEXIST) != 0)
- sysfatal("could not find git repo: %r");
t = findroot();
r = treeify(t, argv, argv + argc, 0, &th);
if(r == -1)