Skip to content

Commit f3a3214

Browse files
author
Linus Torvalds
committed
Make send/receive-pack be closer to doing something interesting
1 parent 6122147 commit f3a3214

File tree

5 files changed

+148
-126
lines changed

5 files changed

+148
-126
lines changed

Makefile

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
1010
# break unless your underlying filesystem supports those sub-second times
1111
# (my ext3 doesn't).
12-
COPTS=-O2
12+
COPTS=
1313
CFLAGS=-g $(COPTS) -Wall
1414

1515
prefix=$(HOME)
@@ -46,9 +46,10 @@ install: $(PROG) $(SCRIPTS)
4646

4747
LIB_OBJS=read-cache.o sha1_file.o usage.o object.o commit.o tree.o blob.o \
4848
tag.o date.o index.o diff-delta.o patch-delta.o entry.o \
49-
epoch.o refs.o csum-file.o verify_pack.o
49+
epoch.o refs.o csum-file.o verify_pack.o pkt-line.o
5050
LIB_FILE=libgit.a
51-
LIB_H=cache.h object.h blob.h tree.h commit.h tag.h delta.h epoch.h csum-file.h pack.h
51+
LIB_H=cache.h object.h blob.h tree.h commit.h tag.h delta.h epoch.h csum-file.h \
52+
pack.h pkt-line.h
5253

5354
LIB_H += strbuf.h
5455
LIB_OBJS += strbuf.o

pkt-line.c

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#include "cache.h"
2+
#include "pkt-line.h"
3+
4+
/*
5+
* Write a packetized stream, where each line is preceded by
6+
* its length (including the header) as a 4-byte hex number.
7+
* A length of 'zero' means end of stream (and a length of 1-3
8+
* would be an error).
9+
*
10+
* This is all pretty stupid, but we use this packetized line
11+
* format to make a streaming format possible without ever
12+
* over-running the read buffers. That way we'll never read
13+
* into what might be the pack data (which should go to another
14+
* process entirely).
15+
*
16+
* The writing side could use stdio, but since the reading
17+
* side can't, we stay with pure read/write interfaces.
18+
*/
19+
static void safe_write(int fd, const void *buf, unsigned n)
20+
{
21+
while (n) {
22+
int ret = write(fd, buf, n);
23+
if (ret > 0) {
24+
buf += ret;
25+
n -= ret;
26+
continue;
27+
}
28+
if (!ret)
29+
die("write error (disk full?)");
30+
if (errno == EAGAIN || errno == EINTR)
31+
continue;
32+
die("write error (%s)", strerror(errno));
33+
}
34+
}
35+
36+
/*
37+
* If we buffered things up above (we don't, but we should),
38+
* we'd flush it here
39+
*/
40+
void packet_flush(int fd)
41+
{
42+
safe_write(fd, "0000", 4);
43+
}
44+
45+
#define hex(a) (hexchar[(a) & 15])
46+
void packet_write(int fd, const char *fmt, ...)
47+
{
48+
static char buffer[1000];
49+
static char hexchar[] = "0123456789abcdef";
50+
va_list args;
51+
unsigned n;
52+
53+
va_start(args, fmt);
54+
n = vsnprintf(buffer + 4, sizeof(buffer) - 4, fmt, args);
55+
va_end(args);
56+
if (n >= sizeof(buffer)-4)
57+
die("protocol error: impossibly long line");
58+
n += 4;
59+
buffer[0] = hex(n >> 12);
60+
buffer[1] = hex(n >> 8);
61+
buffer[2] = hex(n >> 4);
62+
buffer[3] = hex(n);
63+
safe_write(fd, buffer, n);
64+
}
65+
66+
static void safe_read(int fd, void *buffer, unsigned size)
67+
{
68+
int n = 0;
69+
70+
while (n < size) {
71+
int ret = read(fd, buffer + n, size - n);
72+
if (ret < 0) {
73+
if (errno == EINTR || errno == EAGAIN)
74+
continue;
75+
die("read error (%s)", strerror(errno));
76+
}
77+
if (!ret)
78+
die("unexpected EOF");
79+
n += ret;
80+
}
81+
}
82+
83+
int packet_read_line(int fd, char *buffer, unsigned size)
84+
{
85+
int n;
86+
unsigned len;
87+
char linelen[4];
88+
89+
safe_read(fd, linelen, 4);
90+
91+
len = 0;
92+
for (n = 0; n < 4; n++) {
93+
unsigned char c = linelen[n];
94+
len <<= 4;
95+
if (c >= '0' && c <= '9') {
96+
len += c - '0';
97+
continue;
98+
}
99+
if (c >= 'a' && c <= 'f') {
100+
len += c - 'a' + 10;
101+
continue;
102+
}
103+
if (c >= 'A' && c <= 'F') {
104+
len += c - 'A' + 10;
105+
continue;
106+
}
107+
die("protocol error: bad line length character");
108+
}
109+
if (!len)
110+
return 0;
111+
len -= 4;
112+
if (len >= size)
113+
die("protocol error: bad line length %d", len);
114+
safe_read(fd, buffer, len);
115+
buffer[len] = 0;
116+
return len;
117+
}

pkt-line.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef PKTLINE_H
2+
#define PKTLINE_H
3+
4+
/*
5+
* Silly packetized line writing interface
6+
*/
7+
void packet_flush(int fd);
8+
void packet_write(int fd, const char *fmt, ...);
9+
10+
int packet_read_line(int fd, char *buffer, unsigned size);
11+
12+
#endif

receive-pack.c

Lines changed: 7 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "cache.h"
2+
#include "pkt-line.h"
23
#include <sys/wait.h>
34

45
static const char receive_pack_usage[] = "git-receive-pack [--unpack=executable] <git-dir> [heads]";
@@ -26,61 +27,9 @@ static int path_match(const char *path, int nr, char **match)
2627
return 0;
2728
}
2829

29-
static void safe_write(int fd, const void *buf, unsigned n)
30-
{
31-
while (n) {
32-
int ret = write(fd, buf, n);
33-
if (ret > 0) {
34-
buf += ret;
35-
n -= ret;
36-
continue;
37-
}
38-
if (!ret)
39-
die("write error (disk full?)");
40-
if (errno == EAGAIN || errno == EINTR)
41-
continue;
42-
die("write error (%s)", strerror(errno));
43-
}
44-
}
45-
46-
/*
47-
* If we buffered things up above (we don't, but we should),
48-
* we'd flush it here
49-
*/
50-
static void flush_safe(int fd)
51-
{
52-
}
53-
54-
/*
55-
* Write a packetized stream, where each line is preceded by
56-
* its length (including the header) as a 4-byte hex number.
57-
* A length of 'zero' means end of stream (and a length of 1-3
58-
* would be an error).
59-
*/
60-
#define hex(a) (hexchar[(a) & 15])
61-
static void packet_write(const char *fmt, ...)
62-
{
63-
static char buffer[1000];
64-
static char hexchar[] = "0123456789abcdef";
65-
va_list args;
66-
unsigned n;
67-
68-
va_start(args, fmt);
69-
n = vsnprintf(buffer + 4, sizeof(buffer) - 4, fmt, args);
70-
va_end(args);
71-
if (n >= sizeof(buffer)-4)
72-
die("protocol error: impossibly long line");
73-
n += 4;
74-
buffer[0] = hex(n >> 12);
75-
buffer[1] = hex(n >> 8);
76-
buffer[2] = hex(n >> 4);
77-
buffer[3] = hex(n);
78-
safe_write(1, buffer, n);
79-
}
80-
8130
static void show_ref(const char *path, unsigned char *sha1)
8231
{
83-
packet_write("%s %s\n", sha1_to_hex(sha1), path);
32+
packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
8433
}
8534

8635
static int read_ref(const char *path, unsigned char *sha1)
@@ -137,66 +86,6 @@ static void write_head_info(const char *base, int nr, char **match)
13786
}
13887
}
13988

140-
/*
141-
* This is all pretty stupid, but we use this packetized line
142-
* format to make a streaming format possible without ever
143-
* over-running the read buffers. That way we'll never read
144-
* into what might be the pack data (which should go to another
145-
* process entirely).
146-
*
147-
* The writing side could use stdio, but since the reading
148-
* side can't, we stay with pure read/write interfaces.
149-
*/
150-
static void safe_read(int fd, void *buffer, unsigned size)
151-
{
152-
int n = 0;
153-
154-
while (n < size) {
155-
int ret = read(0, buffer + n, size - n);
156-
if (ret < 0) {
157-
if (errno == EINTR || errno == EAGAIN)
158-
continue;
159-
die("read error (%s)", strerror(errno));
160-
}
161-
if (!ret)
162-
die("unexpected EOF");
163-
n += ret;
164-
}
165-
}
166-
167-
static int safe_read_line(char *buffer, unsigned size)
168-
{
169-
int n, len;
170-
171-
safe_read(0, buffer, 4);
172-
173-
len = 0;
174-
for (n = 0; n < 4; n++) {
175-
unsigned char c = buffer[n];
176-
len <<= 4;
177-
if (c >= '0' && c <= '9') {
178-
len += c - '0';
179-
continue;
180-
}
181-
if (c >= 'a' && c <= 'f') {
182-
len += c - 'a' + 10;
183-
continue;
184-
}
185-
if (c >= 'A' && c <= 'F') {
186-
len += c - 'A' + 10;
187-
continue;
188-
}
189-
die("protocol error: bad line length character");
190-
}
191-
if (!len)
192-
return 0;
193-
if (len < 4 || len >= size)
194-
die("protocol error: bad line length %d", len);
195-
safe_read(0, buffer + 4, len - 4);
196-
buffer[len] = 0;
197-
return len;
198-
}
199-
20089
struct line {
20190
struct line *next;
20291
char data[0];
@@ -213,7 +102,7 @@ static void execute_commands(void)
213102
struct line *line = commands;
214103

215104
while (line) {
216-
printf("%s", line->data);
105+
fprintf(stderr, "%s", line->data);
217106
line = line->next;
218107
}
219108
}
@@ -223,7 +112,7 @@ static void read_head_info(void)
223112
struct line **p = &commands;
224113
for (;;) {
225114
static char line[1000];
226-
int len = safe_read_line(line, sizeof(line));
115+
int len = packet_read_line(0, line, sizeof(line));
227116
struct line *n;
228117
if (!len)
229118
break;
@@ -242,8 +131,8 @@ static void unpack(void)
242131
if (pid < 0)
243132
die("unpack fork failed");
244133
if (!pid) {
245-
char *const envp[] = { "GIT_DIR=.", NULL };
246-
execle(unpacker, unpacker, NULL, envp);
134+
setenv("GIT_DIR", ".", 1);
135+
execlp(unpacker, unpacker, NULL);
247136
die("unpack execute failed");
248137
}
249138

@@ -311,8 +200,7 @@ int main(int argc, char **argv)
311200
write_head_info("refs/", nr_heads, heads);
312201

313202
/* EOF */
314-
safe_write(1, "0000", 4);
315-
flush_safe(1);
203+
packet_flush(1);
316204

317205
read_head_info();
318206
unpack();

send-pack.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "cache.h"
2+
#include "pkt-line.h"
23

34
static const char send_pack_usage[] = "git-send-pack [--exec=other] destination [heads]*";
45

@@ -8,13 +9,16 @@ static int send_pack(int in, int out)
89
{
910
for (;;) {
1011
static char buffer[1000];
11-
int ret = read(in, buffer, sizeof(buffer));
12-
if (ret > 0) {
13-
write(1, buffer, ret);
12+
int len;
13+
14+
len = packet_read_line(in, buffer, sizeof(buffer));
15+
if (len > 0) {
16+
write(2, buffer, len);
1417
continue;
1518
}
1619
break;
1720
}
21+
packet_flush(out);
1822
close(out);
1923
return 0;
2024
}
@@ -77,7 +81,7 @@ static int setup_connection(int fd[2], char *url, char **heads)
7781
if (host)
7882
execlp("ssh", "ssh", host, command, NULL);
7983
else
80-
execlp(host, command, NULL);
84+
execlp("sh", "sh", "-c", command, NULL);
8185
die("exec failed");
8286
}
8387
fd[0] = pipefd[0][0];

0 commit comments

Comments
 (0)