5 #include <sys/socket.h>
6 #include <netinet/in.h>
11 * Read all the refs from the other end
13 struct ref
**get_remote_heads(int in
, struct ref
**list
, int nr_match
, char **match
)
18 unsigned char old_sha1
[20];
19 static char buffer
[1000];
23 len
= packet_read_line(in
, buffer
, sizeof(buffer
));
26 if (buffer
[len
-1] == '\n')
29 if (len
< 42 || get_sha1_hex(buffer
, old_sha1
) || buffer
[40] != ' ')
30 die("protocol error: expected sha/ref, got '%s'", buffer
);
32 if (nr_match
&& !path_match(name
, nr_match
, match
))
34 ref
= xmalloc(sizeof(*ref
) + len
- 40);
35 memcpy(ref
->old_sha1
, old_sha1
, 20);
36 memset(ref
->new_sha1
, 0, 20);
37 memcpy(ref
->name
, buffer
+ 41, len
- 40);
45 int get_ack(int fd
, unsigned char *result_sha1
)
47 static char line
[1000];
48 int len
= packet_read_line(fd
, line
, sizeof(line
));
51 die("git-fetch-pack: expected ACK/NAK, got EOF");
52 if (line
[len
-1] == '\n')
54 if (!strcmp(line
, "NAK"))
56 if (!strncmp(line
, "ACK ", 3)) {
57 if (!get_sha1_hex(line
+4, result_sha1
))
60 die("git-fetch_pack: expected ACK/NAK, got '%s'", line
);
63 int path_match(const char *path
, int nr
, char **match
)
66 int pathlen
= strlen(path
);
68 for (i
= 0; i
< nr
; i
++) {
72 if (!len
|| len
> pathlen
)
74 if (memcmp(path
+ pathlen
- len
, s
, len
))
76 if (pathlen
> len
&& path
[pathlen
- len
- 1] != '/')
90 static enum protocol
get_protocol(const char *name
)
92 if (!strcmp(name
, "ssh"))
94 if (!strcmp(name
, "git"))
96 die("I don't handle protocol '%s'", name
);
99 static void lookup_host(const char *host
, struct sockaddr
*in
)
101 struct addrinfo
*res
;
104 ret
= getaddrinfo(host
, NULL
, NULL
, &res
);
106 die("Unable to look up %s (%s)", host
, gai_strerror(ret
));
111 static int git_tcp_connect(int fd
[2], const char *prog
, char *host
, char *path
)
113 struct sockaddr addr
;
114 int port
= DEFAULT_GIT_PORT
, sockfd
;
117 colon
= strchr(host
, ':');
120 unsigned long n
= strtoul(colon
+1, &end
, 0);
121 if (colon
[1] && !*end
) {
127 lookup_host(host
, &addr
);
128 ((struct sockaddr_in
*)&addr
)->sin_port
= htons(port
);
130 sockfd
= socket(PF_INET
, SOCK_STREAM
, IPPROTO_IP
);
132 die("unable to create socket (%s)", strerror(errno
));
133 if (connect(sockfd
, (void *)&addr
, sizeof(addr
)) < 0)
134 die("unable to connect (%s)", strerror(errno
));
137 packet_write(sockfd
, "%s %s\n", prog
, path
);
142 * Yeah, yeah, fixme. Need to pass in the heads etc.
144 int git_connect(int fd
[2], char *url
, const char *prog
)
151 enum protocol protocol
;
155 colon
= strchr(url
, ':');
156 protocol
= PROTO_LOCAL
;
161 protocol
= PROTO_SSH
;
162 if (!memcmp(path
, "//", 2)) {
163 char *slash
= strchr(path
+ 2, '/');
165 int nr
= slash
- path
- 2;
166 memmove(path
, path
+2, nr
);
168 protocol
= get_protocol(url
);
175 if (protocol
== PROTO_GIT
)
176 return git_tcp_connect(fd
, prog
, host
, path
);
178 if (pipe(pipefd
[0]) < 0 || pipe(pipefd
[1]) < 0)
179 die("unable to create pipe pair for communication");
182 snprintf(command
, sizeof(command
), "%s %s", prog
,
184 dup2(pipefd
[1][0], 0);
185 dup2(pipefd
[0][1], 1);
190 if (protocol
== PROTO_SSH
)
191 execlp("ssh", "ssh", host
, command
, NULL
);
193 execlp("sh", "sh", "-c", command
, NULL
);
196 fd
[0] = pipefd
[0][0];
197 fd
[1] = pipefd
[1][1];
203 int finish_connect(pid_t pid
)
208 ret
= waitpid(pid
, NULL
, 0);