Skip to content

Commit fa257b0

Browse files
dschoJunio C Hamano
authored andcommitted
git-bundle: assorted fixes
This patch fixes issues mentioned by Junio, Nico and Simon: - I forgot to convert the usage string when removing the "--" from the subcommands, - a style fix in the bundle_header, - use xread() instead of read(), - use write_or_die() instead of write(), - make the bundle header extensible, - fail if the whitespace after a sha1 of a reference is missing, - close() the fds passed to a subprocess, - in verify_bundle(), do not use "rev-list --stdin", but rather pass the revs directly (avoiding a fork()), - fix a corrupted comment in show_object(), and - fix the size check in index_pack. Signed-off-by: Johannes Schindelin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2e0afaf commit fa257b0

File tree

2 files changed

+63
-49
lines changed

2 files changed

+63
-49
lines changed

builtin-bundle.c

Lines changed: 60 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* bundle supporting git-fetch, git-pull, and git-ls-remote
1414
*/
1515

16-
static const char *bundle_usage="git-bundle (--create <bundle> <git-rev-list args> | --verify <bundle> | --list-heads <bundle> [refname]... | --unbundle <bundle> [refname]... )";
16+
static const char *bundle_usage="git-bundle (create <bundle> <git-rev-list args> | verify <bundle> | list-heads <bundle> [refname]... | unbundle <bundle> [refname]... )";
1717

1818
static const char bundle_signature[] = "# v2 git bundle\n";
1919

@@ -39,15 +39,16 @@ static void add_to_ref_list(const unsigned char *sha1, const char *name,
3939
}
4040

4141
struct bundle_header {
42-
struct ref_list prerequisites, references;
42+
struct ref_list prerequisites;
43+
struct ref_list references;
4344
};
4445

4546
/* this function returns the length of the string */
4647
static int read_string(int fd, char *buffer, int size)
4748
{
4849
int i;
4950
for (i = 0; i < size - 1; i++) {
50-
int count = read(fd, buffer + i, 1);
51+
int count = xread(fd, buffer + i, 1);
5152
if (count < 0)
5253
return error("Read error: %s", strerror(errno));
5354
if (count == 0) {
@@ -75,18 +76,25 @@ static int read_header(const char *path, struct bundle_header *header) {
7576
}
7677
while (read_string(fd, buffer, sizeof(buffer)) > 0
7778
&& buffer[0] != '\n') {
78-
int offset = buffer[0] == '-' ? 1 : 0;
79+
int is_prereq = buffer[0] == '-';
80+
int offset = is_prereq ? 1 : 0;
7981
int len = strlen(buffer);
8082
unsigned char sha1[20];
81-
struct ref_list *list = offset ? &header->prerequisites
83+
struct ref_list *list = is_prereq ? &header->prerequisites
8284
: &header->references;
83-
if (get_sha1_hex(buffer + offset, sha1)) {
84-
close(fd);
85-
return error("invalid SHA1: %s", buffer);
86-
}
85+
char delim;
86+
8787
if (buffer[len - 1] == '\n')
8888
buffer[len - 1] = '\0';
89-
add_to_ref_list(sha1, buffer + 41 + offset, list);
89+
if (get_sha1_hex(buffer + offset, sha1)) {
90+
warn("unrecognized header: %s", buffer);
91+
continue;
92+
}
93+
delim = buffer[40 + offset];
94+
if (!isspace(delim) && (delim != '\0' || !is_prereq))
95+
die ("invalid header: %s", buffer);
96+
add_to_ref_list(sha1, isspace(delim) ?
97+
buffer + 41 + offset : "", list);
9098
}
9199
return fd;
92100
}
@@ -127,20 +135,28 @@ static int fork_with_pipe(const char **argv, int *in, int *out)
127135
dup2(fdin[0], 0);
128136
close(fdin[0]);
129137
close(fdin[1]);
130-
} else if (in)
138+
} else if (in) {
131139
dup2(*in, 0);
140+
close(*in);
141+
}
132142
if (needs_out) {
133143
dup2(fdout[1], 1);
134144
close(fdout[0]);
135145
close(fdout[1]);
136-
} else if (out)
146+
} else if (out) {
137147
dup2(*out, 1);
148+
close(*out);
149+
}
138150
exit(execv_git_cmd(argv));
139151
}
140152
if (needs_in)
141153
close(fdin[0]);
154+
else if (in)
155+
close(*in);
142156
if (needs_out)
143157
close(fdout[1]);
158+
else if (out)
159+
close(*out);
144160
return pid;
145161
}
146162

@@ -151,29 +167,28 @@ static int verify_bundle(struct bundle_header *header)
151167
* to be verbose about the errors
152168
*/
153169
struct ref_list *p = &header->prerequisites;
154-
const char *argv[5] = {"rev-list", "--stdin", "--not", "--all", NULL};
155-
int pid, in, out, i, ret = 0;
170+
char **argv;
171+
int pid, out, i, ret = 0;
156172
char buffer[1024];
157173

158-
in = out = -1;
159-
pid = fork_with_pipe(argv, &in, &out);
174+
argv = xmalloc((p->nr + 4) * sizeof(const char *));
175+
argv[0] = "rev-list";
176+
argv[1] = "--not";
177+
argv[2] = "--all";
178+
for (i = 0; i < p->nr; i++)
179+
argv[i + 3] = xstrdup(sha1_to_hex(p->list[i].sha1));
180+
argv[p->nr + 3] = NULL;
181+
out = -1;
182+
pid = fork_with_pipe((const char **)argv, NULL, &out);
160183
if (pid < 0)
161184
return error("Could not fork rev-list");
162-
if (!fork()) {
163-
for (i = 0; i < p->nr; i++) {
164-
write(in, sha1_to_hex(p->list[i].sha1), 40);
165-
write(in, "\n", 1);
166-
}
167-
close(in);
168-
exit(0);
169-
}
170-
close(in);
171-
while (read_string(out, buffer, sizeof(buffer)) > 0) {
172-
if (ret++ == 0)
173-
error ("The bundle requires the following commits you lack:");
174-
fprintf(stderr, "%s", buffer);
175-
}
185+
while (read_string(out, buffer, sizeof(buffer)) > 0)
186+
; /* do nothing */
176187
close(out);
188+
for (i = 0; i < p->nr; i++)
189+
free(argv[i + 3]);
190+
free(argv);
191+
177192
while (waitpid(pid, &i, 0) < 0)
178193
if (errno != EINTR)
179194
return -1;
@@ -205,8 +220,8 @@ static int list_heads(struct bundle_header *header, int argc, const char **argv)
205220

206221
static void show_commit(struct commit *commit)
207222
{
208-
write(1, sha1_to_hex(commit->object.sha1), 40);
209-
write(1, "\n", 1);
223+
write_or_die(1, sha1_to_hex(commit->object.sha1), 40);
224+
write_or_die(1, "\n", 1);
210225
if (commit->parents) {
211226
free_commit_list(commit->parents);
212227
commit->parents = NULL;
@@ -216,15 +231,15 @@ static void show_commit(struct commit *commit)
216231
static void show_object(struct object_array_entry *p)
217232
{
218233
/* An object with name "foo\n0000000..." can be used to
219-
* * confuse downstream git-pack-objects very badly.
220-
* */
234+
* confuse downstream git-pack-objects very badly.
235+
*/
221236
const char *ep = strchr(p->name, '\n');
222237
int len = ep ? ep - p->name : strlen(p->name);
223-
write(1, sha1_to_hex(p->item->sha1), 40);
224-
write(1, " ", 1);
238+
write_or_die(1, sha1_to_hex(p->item->sha1), 40);
239+
write_or_die(1, " ", 1);
225240
if (len)
226-
write(1, p->name, len);
227-
write(1, "\n", 1);
241+
write_or_die(1, p->name, len);
242+
write_or_die(1, "\n", 1);
228243
}
229244

230245
static int create_bundle(struct bundle_header *header, const char *path,
@@ -243,7 +258,7 @@ static int create_bundle(struct bundle_header *header, const char *path,
243258
return error("Could not write to '%s'", path);
244259

245260
/* write signature */
246-
write(bundle_fd, bundle_signature, strlen(bundle_signature));
261+
write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature));
247262

248263
/* write prerequisites */
249264
memcpy(argv_boundary + 2, argv + 1, argc * sizeof(const char *));
@@ -256,7 +271,7 @@ static int create_bundle(struct bundle_header *header, const char *path,
256271
return -1;
257272
while ((i = read_string(out, buffer, sizeof(buffer))) > 0)
258273
if (buffer[0] == '-')
259-
write(bundle_fd, buffer, i);
274+
write_or_die(bundle_fd, buffer, i);
260275
while ((i = waitpid(pid, &status, 0)) < 0)
261276
if (errno != EINTR)
262277
return error("rev-list died");
@@ -279,16 +294,16 @@ static int create_bundle(struct bundle_header *header, const char *path,
279294
char *ref;
280295
if (dwim_ref(e->name, strlen(e->name), sha1, &ref) != 1)
281296
continue;
282-
write(bundle_fd, sha1_to_hex(e->item->sha1), 40);
283-
write(bundle_fd, " ", 1);
284-
write(bundle_fd, ref, strlen(ref));
285-
write(bundle_fd, "\n", 1);
297+
write_or_die(bundle_fd, sha1_to_hex(e->item->sha1), 40);
298+
write_or_die(bundle_fd, " ", 1);
299+
write_or_die(bundle_fd, ref, strlen(ref));
300+
write_or_die(bundle_fd, "\n", 1);
286301
free(ref);
287302
}
288303
}
289304

290305
/* end header */
291-
write(bundle_fd, "\n", 1);
306+
write_or_die(bundle_fd, "\n", 1);
292307

293308
/* write pack */
294309
argv_pack[0] = "pack-objects";
@@ -301,7 +316,6 @@ static int create_bundle(struct bundle_header *header, const char *path,
301316
if (pid < 0)
302317
return error("Could not spawn pack-objects");
303318
close(1);
304-
close(bundle_fd);
305319
dup2(in, 1);
306320
close(in);
307321
prepare_revision_walk(&revs);
@@ -327,7 +341,6 @@ static int unbundle(struct bundle_header *header, int bundle_fd,
327341
pid = fork_with_pipe(argv_index_pack, &bundle_fd, &dev_null);
328342
if (pid < 0)
329343
return error("Could not spawn index-pack");
330-
close(bundle_fd);
331344
while (waitpid(pid, &status, 0) < 0)
332345
if (errno != EINTR)
333346
return error("index-pack died");

index-pack.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,9 @@ static void parse_pack_objects(unsigned char *sha1)
457457
/* If input_fd is a file, we should have reached its end now. */
458458
if (fstat(input_fd, &st))
459459
die("cannot fstat packfile: %s", strerror(errno));
460-
if (input_fd && S_ISREG(st.st_mode) && st.st_size != consumed_bytes)
461-
die("pack has junk at the end: 0%o, %d, %d %d", st.st_mode, (int)st.st_size, (int)consumed_bytes, input_fd);
460+
if (S_ISREG(st.st_mode) &&
461+
lseek(input_fd, 0, SEEK_CUR) - input_len != st.st_size)
462+
die("pack has junk at the end");
462463

463464
if (!nr_deltas)
464465
return;

0 commit comments

Comments
 (0)