Skip to content

Commit c8aa9fd

Browse files
committed
strbuf: make strbuf_getline_crlf() global
Often we read "text" files that are supplied by the end user (e.g. commit log message that was edited with $GIT_EDITOR upon 'git commit -e'), and in some environments lines in a text file are terminated with CRLF. Existing strbuf_getline() knows to read a single line and then strip the terminating byte from the result, but it is handy to have a version that is more tailored for a "text" input that takes both '\n' and '\r\n' as line terminator (aka <newline> in POSIX lingo) and returns the body of the line after stripping <newline>. Recently reimplemented "git am" uses such a function implemented privately; move it to strbuf.[ch] and make it available for others. Note that we do not blindly replace calls to strbuf_getline() that uses LF as the line terminator with calls to strbuf_getline_crlf() and this is very much deliberate. Some callers may want to treat an incoming line that ends with CR (and terminated with LF) to have a payload that includes the final CR, and such a blind replacement will result in misconversion when done without code audit. Signed-off-by: Junio C Hamano <[email protected]>
1 parent dce80bd commit c8aa9fd

File tree

3 files changed

+19
-15
lines changed

3 files changed

+19
-15
lines changed

builtin/am.c

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,21 +45,6 @@ static int is_empty_file(const char *filename)
4545
return !st.st_size;
4646
}
4747

48-
/**
49-
* Like strbuf_getline(), but treats both '\n' and "\r\n" as line terminators.
50-
*/
51-
static int strbuf_getline_crlf(struct strbuf *sb, FILE *fp)
52-
{
53-
if (strbuf_getwholeline(sb, fp, '\n'))
54-
return EOF;
55-
if (sb->buf[sb->len - 1] == '\n') {
56-
strbuf_setlen(sb, sb->len - 1);
57-
if (sb->len > 0 && sb->buf[sb->len - 1] == '\r')
58-
strbuf_setlen(sb, sb->len - 1);
59-
}
60-
return 0;
61-
}
62-
6348
/**
6449
* Returns the length of the first line of msg.
6550
*/

strbuf.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,18 @@ int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
510510
return 0;
511511
}
512512

513+
int strbuf_getline_crlf(struct strbuf *sb, FILE *fp)
514+
{
515+
if (strbuf_getwholeline(sb, fp, '\n'))
516+
return EOF;
517+
if (sb->buf[sb->len - 1] == '\n') {
518+
strbuf_setlen(sb, sb->len - 1);
519+
if (sb->len && sb->buf[sb->len - 1] == '\r')
520+
strbuf_setlen(sb, sb->len - 1);
521+
}
522+
return 0;
523+
}
524+
513525
int strbuf_getwholeline_fd(struct strbuf *sb, int fd, int term)
514526
{
515527
strbuf_reset(sb);

strbuf.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,13 @@ extern int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint);
388388
*/
389389
extern int strbuf_getline(struct strbuf *, FILE *, int);
390390

391+
/*
392+
* Similar to strbuf_getline(), but uses '\n' as the terminator,
393+
* and additionally treats a '\r' that comes immediately before '\n'
394+
* as part of the terminator.
395+
*/
396+
extern int strbuf_getline_crlf(struct strbuf *, FILE *);
397+
391398
/**
392399
* Like `strbuf_getline`, but keeps the trailing terminator (if
393400
* any) in the buffer.

0 commit comments

Comments
 (0)