Browse Source

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 <gitster@pobox.com>
maint
Junio C Hamano 9 years ago
parent
commit
c8aa9fdf5d
  1. 15
      builtin/am.c
  2. 12
      strbuf.c
  3. 7
      strbuf.h

15
builtin/am.c

@ -45,21 +45,6 @@ static int is_empty_file(const char *filename) @@ -45,21 +45,6 @@ static int is_empty_file(const char *filename)
return !st.st_size;
}

/**
* Like strbuf_getline(), but treats both '\n' and "\r\n" as line terminators.
*/
static int strbuf_getline_crlf(struct strbuf *sb, FILE *fp)
{
if (strbuf_getwholeline(sb, fp, '\n'))
return EOF;
if (sb->buf[sb->len - 1] == '\n') {
strbuf_setlen(sb, sb->len - 1);
if (sb->len > 0 && sb->buf[sb->len - 1] == '\r')
strbuf_setlen(sb, sb->len - 1);
}
return 0;
}

/**
* Returns the length of the first line of msg.
*/

12
strbuf.c

@ -510,6 +510,18 @@ int strbuf_getline(struct strbuf *sb, FILE *fp, int term) @@ -510,6 +510,18 @@ int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
return 0;
}

int strbuf_getline_crlf(struct strbuf *sb, FILE *fp)
{
if (strbuf_getwholeline(sb, fp, '\n'))
return EOF;
if (sb->buf[sb->len - 1] == '\n') {
strbuf_setlen(sb, sb->len - 1);
if (sb->len && sb->buf[sb->len - 1] == '\r')
strbuf_setlen(sb, sb->len - 1);
}
return 0;
}

int strbuf_getwholeline_fd(struct strbuf *sb, int fd, int term)
{
strbuf_reset(sb);

7
strbuf.h

@ -388,6 +388,13 @@ extern int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint); @@ -388,6 +388,13 @@ extern int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint);
*/
extern int strbuf_getline(struct strbuf *, FILE *, int);

/*
* Similar to strbuf_getline(), but uses '\n' as the terminator,
* and additionally treats a '\r' that comes immediately before '\n'
* as part of the terminator.
*/
extern int strbuf_getline_crlf(struct strbuf *, FILE *);

/**
* Like `strbuf_getline`, but keeps the trailing terminator (if
* any) in the buffer.

Loading…
Cancel
Save