5 static const char fetch_pack_usage
[] = "git-fetch-pack [host:]directory [heads]* < mycommitlist";
6 static const char *exec
= "git-upload-pack";
8 static int get_ack(int fd
, unsigned char *result_sha1
)
10 static char line
[1000];
11 int len
= packet_read_line(fd
, line
, sizeof(line
));
14 die("git-fetch-pack: expected ACK/NAK, got EOF");
15 if (line
[len
-1] == '\n')
17 if (!strcmp(line
, "NAK"))
19 if (!strncmp(line
, "ACK ", 3)) {
20 if (!get_sha1_hex(line
+4, result_sha1
))
23 die("git-fetch_pack: expected ACK/NAK, got '%s'", line
);
26 static int find_common(int fd
[2], unsigned char *result_sha1
, unsigned char *remote
)
28 static char line
[1000];
29 int count
= 0, flushes
= 0;
31 packet_write(fd
[1], "want %s\n", sha1_to_hex(remote
));
33 while (fgets(line
, sizeof(line
), stdin
) != NULL
) {
34 unsigned char sha1
[20];
35 if (get_sha1_hex(line
, sha1
))
36 die("git-fetch-pack: expected object name, got crud");
37 packet_write(fd
[1], "have %s\n", sha1_to_hex(sha1
));
38 if (!(31 & ++count
)) {
43 * We keep one window "ahead" of the other side, and
44 * will wait for an ACK only on the next one
48 if (get_ack(fd
[0], result_sha1
))
57 if (get_ack(fd
[0], result_sha1
))
63 static int get_old_sha1(const char *refname
, unsigned char *sha1
)
65 static char pathname
[PATH_MAX
];
69 git_dir
= gitenv(GIT_DIR_ENVIRONMENT
) ? : DEFAULT_GIT_DIR_ENVIRONMENT
;
70 snprintf(pathname
, sizeof(pathname
), "%s/%s", git_dir
, refname
);
71 fd
= open(pathname
, O_RDONLY
);
75 if (read(fd
, buffer
, sizeof(buffer
)) >= 40)
76 ret
= get_sha1_hex(buffer
, sha1
);
82 static int check_ref(const char *refname
, const unsigned char *sha1
)
84 unsigned char mysha1
[20];
87 if (get_old_sha1(refname
, mysha1
) < 0)
88 memset(mysha1
, 0, 20);
90 if (!memcmp(sha1
, mysha1
, 20)) {
91 printf("%s: unchanged\n", refname
);
95 memcpy(oldhex
, sha1_to_hex(mysha1
), 41);
96 printf("%s: %s (%s)\n", refname
, sha1_to_hex(sha1
), oldhex
);
100 static int get_remote_heads(int fd
, int nr_match
, char **match
, unsigned char *result
)
105 static char line
[1000];
106 unsigned char sha1
[20];
110 len
= packet_read_line(fd
, line
, sizeof(line
));
113 if (line
[len
-1] == '\n')
115 if (len
< 42 || get_sha1_hex(line
, sha1
))
116 die("git-fetch-pack: protocol error - expected ref descriptor, got '%sä'", line
);
118 if (nr_match
&& !path_match(refname
, nr_match
, match
))
120 if (check_ref(refname
, sha1
)) {
122 memcpy(result
, sha1
, 20);
128 static int fetch_pack(int fd
[2], int nr_match
, char **match
)
130 unsigned char sha1
[20], remote
[20];
133 heads
= get_remote_heads(fd
[0], nr_match
, match
, remote
);
136 die(heads
? "multiple remote heads" : "no matching remote head");
138 if (find_common(fd
, sha1
, remote
) < 0)
139 die("git-fetch-pack: no common commits");
143 execlp("git-unpack-objects", "git-unpack-objects", NULL
);
144 die("git-unpack-objects exec failed");
147 int main(int argc
, char **argv
)
149 int i
, ret
, nr_heads
;
150 char *dest
= NULL
, **heads
;
156 for (i
= 1; i
< argc
; i
++) {
160 /* Arguments go here */
161 usage(fetch_pack_usage
);
164 heads
= argv
+ i
+ 1;
165 nr_heads
= argc
- i
- 1;
169 usage(fetch_pack_usage
);
170 pid
= git_connect(fd
, dest
, exec
);
173 ret
= fetch_pack(fd
, nr_heads
, heads
);