ref: 5a34cc86a807c4629491b38f0f401e885956edc0
parent: 4dd461e4400b20fbb218304e53a84d3704ae8304
author: cinap_lenrek <[email protected]>
date: Fri Jun 4 13:47:26 EDT 2021
git: allow local repository directories as remote uri's This is implemented by checking first if the uri is a directory containing the .git/ subdirectory. If this is the case, we fork git/serve serving the repository on a pipe.
--- a/sys/src/cmd/git/proto.c
+++ b/sys/src/cmd/git/proto.c
@@ -285,19 +285,37 @@
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;
+}
+
+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 @@
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,29 +363,53 @@
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
gitconnect(Conn *c, char *uri, char *direction)
{
@@ -378,12 +416,16 @@
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)