Skip to content

Commit 8502a77

Browse files
committed
Merge branch 'tr/maint-bundle-long-subject' into maint-1.7.8
* tr/maint-bundle-long-subject: t5704: match tests to modern style strbuf: improve strbuf_get*line documentation bundle: use a strbuf to scan the log for boundary commits bundle: put strbuf_readline_fd in strbuf.c with adjustments
2 parents dbdc07f + 8a557bb commit 8502a77

File tree

5 files changed

+67
-51
lines changed

5 files changed

+67
-51
lines changed

Documentation/technical/api-strbuf.txt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,24 @@ same behaviour as well.
255255

256256
`strbuf_getline`::
257257

258-
Read a line from a FILE* pointer. The second argument specifies the line
258+
Read a line from a FILE *, overwriting the existing contents
259+
of the strbuf. The second argument specifies the line
259260
terminator character, typically `'\n'`.
261+
Reading stops after the terminator or at EOF. The terminator
262+
is removed from the buffer before returning. Returns 0 unless
263+
there was nothing left before EOF, in which case it returns `EOF`.
264+
265+
`strbuf_getwholeline`::
266+
267+
Like `strbuf_getline`, but keeps the trailing terminator (if
268+
any) in the buffer.
269+
270+
`strbuf_getwholeline_fd`::
271+
272+
Like `strbuf_getwholeline`, but operates on a file descriptor.
273+
It reads one character at a time, so it is very slow. Do not
274+
use it unless you need the correct position in the file
275+
descriptor.
260276

261277
`stripspace`::
262278

bundle.c

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,31 +23,14 @@ static void add_to_ref_list(const unsigned char *sha1, const char *name,
2323
list->nr++;
2424
}
2525

26-
/* Eventually this should go to strbuf.[ch] */
27-
static int strbuf_readline_fd(struct strbuf *sb, int fd)
28-
{
29-
strbuf_reset(sb);
30-
31-
while (1) {
32-
char ch;
33-
ssize_t len = xread(fd, &ch, 1);
34-
if (len <= 0)
35-
return len;
36-
strbuf_addch(sb, ch);
37-
if (ch == '\n')
38-
break;
39-
}
40-
return 0;
41-
}
42-
4326
static int parse_bundle_header(int fd, struct bundle_header *header,
4427
const char *report_path)
4528
{
4629
struct strbuf buf = STRBUF_INIT;
4730
int status = 0;
4831

4932
/* The bundle header begins with the signature */
50-
if (strbuf_readline_fd(&buf, fd) ||
33+
if (strbuf_getwholeline_fd(&buf, fd, '\n') ||
5134
strcmp(buf.buf, bundle_signature)) {
5235
if (report_path)
5336
error("'%s' does not look like a v2 bundle file",
@@ -57,7 +40,7 @@ static int parse_bundle_header(int fd, struct bundle_header *header,
5740
}
5841

5942
/* The bundle header ends with an empty line */
60-
while (!strbuf_readline_fd(&buf, fd) &&
43+
while (!strbuf_getwholeline_fd(&buf, fd, '\n') &&
6144
buf.len && buf.buf[0] != '\n') {
6245
unsigned char sha1[20];
6346
int is_prereq = 0;
@@ -251,7 +234,7 @@ int create_bundle(struct bundle_header *header, const char *path,
251234
const char **argv_boundary = xmalloc((argc + 4) * sizeof(const char *));
252235
const char **argv_pack = xmalloc(6 * sizeof(const char *));
253236
int i, ref_count = 0;
254-
char buffer[1024];
237+
struct strbuf buf = STRBUF_INIT;
255238
struct rev_info revs;
256239
struct child_process rls;
257240
FILE *rls_fout;
@@ -283,20 +266,21 @@ int create_bundle(struct bundle_header *header, const char *path,
283266
if (start_command(&rls))
284267
return -1;
285268
rls_fout = xfdopen(rls.out, "r");
286-
while (fgets(buffer, sizeof(buffer), rls_fout)) {
269+
while (strbuf_getwholeline(&buf, rls_fout, '\n') != EOF) {
287270
unsigned char sha1[20];
288-
if (buffer[0] == '-') {
289-
write_or_die(bundle_fd, buffer, strlen(buffer));
290-
if (!get_sha1_hex(buffer + 1, sha1)) {
271+
if (buf.len > 0 && buf.buf[0] == '-') {
272+
write_or_die(bundle_fd, buf.buf, buf.len);
273+
if (!get_sha1_hex(buf.buf + 1, sha1)) {
291274
struct object *object = parse_object(sha1);
292275
object->flags |= UNINTERESTING;
293-
add_pending_object(&revs, object, buffer);
276+
add_pending_object(&revs, object, buf.buf);
294277
}
295-
} else if (!get_sha1_hex(buffer, sha1)) {
278+
} else if (!get_sha1_hex(buf.buf, sha1)) {
296279
struct object *object = parse_object(sha1);
297280
object->flags |= SHOWN;
298281
}
299282
}
283+
strbuf_release(&buf);
300284
fclose(rls_fout);
301285
if (finish_command(&rls))
302286
return error("rev-list died");

strbuf.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,22 @@ int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
383383
return 0;
384384
}
385385

386+
int strbuf_getwholeline_fd(struct strbuf *sb, int fd, int term)
387+
{
388+
strbuf_reset(sb);
389+
390+
while (1) {
391+
char ch;
392+
ssize_t len = xread(fd, &ch, 1);
393+
if (len <= 0)
394+
return EOF;
395+
strbuf_addch(sb, ch);
396+
if (ch == term)
397+
break;
398+
}
399+
return 0;
400+
}
401+
386402
int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
387403
{
388404
int fd, len;

strbuf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ extern int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint);
108108

109109
extern int strbuf_getwholeline(struct strbuf *, FILE *, int);
110110
extern int strbuf_getline(struct strbuf *, FILE *, int);
111+
extern int strbuf_getwholeline_fd(struct strbuf *, int, int);
111112

112113
extern void stripspace(struct strbuf *buf, int skip_comments);
113114
extern int launch_editor(const char *path, struct strbuf *buffer, const char *const *env);

t/t5704-bundle.sh

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,59 +4,58 @@ test_description='some bundle related tests'
44
. ./test-lib.sh
55

66
test_expect_success 'setup' '
7-
8-
: > file &&
9-
git add file &&
10-
test_tick &&
11-
git commit -m initial &&
7+
test_commit initial &&
128
test_tick &&
139
git tag -m tag tag &&
14-
: > file2 &&
15-
git add file2 &&
16-
: > file3 &&
17-
test_tick &&
18-
git commit -m second &&
19-
git add file3 &&
20-
test_tick &&
21-
git commit -m third
22-
10+
test_commit second &&
11+
test_commit third &&
12+
git tag -d initial &&
13+
git tag -d second &&
14+
git tag -d third
2315
'
2416

2517
test_expect_success 'tags can be excluded by rev-list options' '
26-
2718
git bundle create bundle --all --since=7.Apr.2005.15:16:00.-0700 &&
2819
git ls-remote bundle > output &&
2920
! grep tag output
30-
3121
'
3222

3323
test_expect_success 'die if bundle file cannot be created' '
34-
3524
mkdir adir &&
3625
test_must_fail git bundle create adir --all
37-
3826
'
3927

4028
test_expect_failure 'bundle --stdin' '
41-
4229
echo master | git bundle create stdin-bundle.bdl --stdin &&
4330
git ls-remote stdin-bundle.bdl >output &&
4431
grep master output
45-
4632
'
4733

4834
test_expect_failure 'bundle --stdin <rev-list options>' '
49-
5035
echo master | git bundle create hybrid-bundle.bdl --stdin tag &&
5136
git ls-remote hybrid-bundle.bdl >output &&
5237
grep master output
53-
5438
'
5539

5640
test_expect_success 'empty bundle file is rejected' '
41+
: >empty-bundle &&
42+
test_must_fail git fetch empty-bundle
43+
'
5744

58-
>empty-bundle && test_must_fail git fetch empty-bundle
59-
45+
# This triggers a bug in older versions where the resulting line (with
46+
# --pretty=oneline) was longer than a 1024-char buffer.
47+
test_expect_success 'ridiculously long subject in boundary' '
48+
: >file4 &&
49+
test_tick &&
50+
git add file4 &&
51+
printf "%01200d\n" 0 | git commit -F - &&
52+
test_commit fifth &&
53+
git bundle create long-subject-bundle.bdl HEAD^..HEAD &&
54+
git bundle list-heads long-subject-bundle.bdl >heads &&
55+
test -s heads &&
56+
git fetch long-subject-bundle.bdl &&
57+
sed -n "/^-/{p;q}" long-subject-bundle.bdl >boundary &&
58+
grep "^-$_x40 " boundary
6059
'
6160

6261
test_done

0 commit comments

Comments
 (0)