diff options
Diffstat (limited to 'strbuf.c')
-rw-r--r-- | strbuf.c | 286 |
1 files changed, 88 insertions, 198 deletions
@@ -1,7 +1,10 @@ -#include "cache.h" -#include "refs.h" +#include "git-compat-util.h" +#include "gettext.h" +#include "hex-ll.h" +#include "strbuf.h" #include "string-list.h" #include "utf8.h" +#include "date.h" int starts_with(const char *str, const char *prefix) { @@ -21,6 +24,17 @@ int istarts_with(const char *str, const char *prefix) return 0; } +int starts_with_mem(const char *str, size_t len, const char *prefix) +{ + const char *end = str + len; + for (; ; str++, prefix++) { + if (!*prefix) + return 1; + else if (str == end || *str != *prefix) + return 0; + } +} + int skip_to_optional_arg_default(const char *str, const char *prefix, const char **arg, const char *def) { @@ -337,18 +351,17 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...) } static void add_lines(struct strbuf *out, - const char *prefix1, - const char *prefix2, - const char *buf, size_t size) + const char *prefix, + const char *buf, size_t size, + int space_after_prefix) { while (size) { - const char *prefix; const char *next = memchr(buf, '\n', size); next = next ? (next + 1) : (buf + size); - prefix = ((prefix2 && (buf[0] == '\n' || buf[0] == '\t')) - ? prefix2 : prefix1); strbuf_addstr(out, prefix); + if (space_after_prefix && buf[0] != '\n' && buf[0] != '\t') + strbuf_addch(out, ' '); strbuf_add(out, buf, next - buf); size -= next - buf; buf = next; @@ -356,19 +369,14 @@ static void add_lines(struct strbuf *out, strbuf_complete_line(out); } -void strbuf_add_commented_lines(struct strbuf *out, const char *buf, size_t size) +void strbuf_add_commented_lines(struct strbuf *out, const char *buf, + size_t size, const char *comment_prefix) { - static char prefix1[3]; - static char prefix2[2]; - - if (prefix1[0] != comment_line_char) { - xsnprintf(prefix1, sizeof(prefix1), "%c ", comment_line_char); - xsnprintf(prefix2, sizeof(prefix2), "%c", comment_line_char); - } - add_lines(out, prefix1, prefix2, buf, size); + add_lines(out, comment_prefix, buf, size, 1); } -void strbuf_commented_addf(struct strbuf *sb, const char *fmt, ...) +void strbuf_commented_addf(struct strbuf *sb, const char *comment_prefix, + const char *fmt, ...) { va_list params; struct strbuf buf = STRBUF_INIT; @@ -378,7 +386,7 @@ void strbuf_commented_addf(struct strbuf *sb, const char *fmt, ...) strbuf_vaddf(&buf, fmt, params); va_end(params); - strbuf_add_commented_lines(sb, buf.buf, buf.len); + strbuf_add_commented_lines(sb, buf.buf, buf.len, comment_prefix); if (incomplete_line) sb->buf[--sb->len] = '\0'; @@ -406,36 +414,19 @@ void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap) strbuf_setlen(sb, sb->len + len); } -void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn, - void *context) +int strbuf_expand_step(struct strbuf *sb, const char **formatp) { - for (;;) { - const char *percent; - size_t consumed; + const char *format = *formatp; + const char *percent = strchrnul(format, '%'); - percent = strchrnul(format, '%'); - strbuf_add(sb, format, percent - format); - if (!*percent) - break; - format = percent + 1; - - if (*format == '%') { - strbuf_addch(sb, '%'); - format++; - continue; - } - - consumed = fn(sb, format, context); - if (consumed) - format += consumed; - else - strbuf_addch(sb, '%'); - } + strbuf_add(sb, format, percent - format); + if (!*percent) + return 0; + *formatp = percent + 1; + return 1; } -size_t strbuf_expand_literal_cb(struct strbuf *sb, - const char *placeholder, - void *context) +size_t strbuf_expand_literal(struct strbuf *sb, const char *placeholder) { int ch; @@ -454,20 +445,24 @@ size_t strbuf_expand_literal_cb(struct strbuf *sb, return 0; } -size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder, - void *context) +void strbuf_expand_bad_format(const char *format, const char *command) { - struct strbuf_expand_dict_entry *e = context; - size_t len; + const char *end; - for (; e->placeholder && (len = strlen(e->placeholder)); e++) { - if (!strncmp(placeholder, e->placeholder, len)) { - if (e->value) - strbuf_addstr(sb, e->value); - return len; - } - } - return 0; + if (*format != '(') + /* TRANSLATORS: The first %s is a command like "ls-tree". */ + die(_("bad %s format: element '%s' does not start with '('"), + command, format); + + end = strchr(format + 1, ')'); + if (!end) + /* TRANSLATORS: The first %s is a command like "ls-tree". */ + die(_("bad %s format: element '%s' does not end in ')'"), + command, format); + + /* TRANSLATORS: %s is a command like "ls-tree". */ + die(_("bad %s format: %%%.*s"), + command, (int)(end - format + 1), format); } void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src) @@ -712,11 +707,11 @@ static int strbuf_getdelim(struct strbuf *sb, FILE *fp, int term) return 0; } -int strbuf_getline(struct strbuf *sb, FILE *fp) +int strbuf_getdelim_strip_crlf(struct strbuf *sb, FILE *fp, int term) { - if (strbuf_getwholeline(sb, fp, '\n')) + if (strbuf_getwholeline(sb, fp, term)) return EOF; - if (sb->buf[sb->len - 1] == '\n') { + if (term == '\n' && 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); @@ -724,6 +719,11 @@ int strbuf_getline(struct strbuf *sb, FILE *fp) return 0; } +int strbuf_getline(struct strbuf *sb, FILE *fp) +{ + return strbuf_getdelim_strip_crlf(sb, fp, '\n'); +} + int strbuf_getline_lf(struct strbuf *sb, FILE *fp) { return strbuf_getdelim(sb, fp, '\n'); @@ -773,7 +773,7 @@ ssize_t strbuf_read_file(struct strbuf *sb, const char *path, size_t hint) void strbuf_add_lines(struct strbuf *out, const char *prefix, const char *buf, size_t size) { - add_lines(out, prefix, NULL, buf, size); + add_lines(out, prefix, buf, size, 0); } void strbuf_addstr_xml_quoted(struct strbuf *buf, const char *s) @@ -802,25 +802,6 @@ void strbuf_addstr_xml_quoted(struct strbuf *buf, const char *s) } } -int is_rfc3986_reserved_or_unreserved(char ch) -{ - if (is_rfc3986_unreserved(ch)) - return 1; - switch (ch) { - case '!': case '*': case '\'': case '(': case ')': case ';': - case ':': case '@': case '&': case '=': case '+': case '$': - case ',': case '/': case '?': case '#': case '[': case ']': - return 1; - } - return 0; -} - -int is_rfc3986_unreserved(char ch) -{ - return isalnum(ch) || - ch == '-' || ch == '_' || ch == '.' || ch == '~'; -} - static void strbuf_add_urlencode(struct strbuf *sb, const char *s, size_t len, char_predicate allow_unencoded_fn) { @@ -874,9 +855,9 @@ static void strbuf_humanise(struct strbuf *buf, off_t bytes, strbuf_addf(buf, humanise_rate == 0 ? /* TRANSLATORS: IEC 80000-13:2008 byte */ - Q_("%u byte", "%u bytes", (unsigned)bytes) : + Q_("%u byte", "%u bytes", bytes) : /* TRANSLATORS: IEC 80000-13:2008 byte/second */ - Q_("%u byte/s", "%u bytes/s", (unsigned)bytes), + Q_("%u byte/s", "%u bytes/s", bytes), (unsigned)bytes); } } @@ -891,42 +872,6 @@ void strbuf_humanise_rate(struct strbuf *buf, off_t bytes) strbuf_humanise(buf, bytes, 1); } -void strbuf_add_absolute_path(struct strbuf *sb, const char *path) -{ - if (!*path) - die("The empty string is not a valid path"); - if (!is_absolute_path(path)) { - struct stat cwd_stat, pwd_stat; - size_t orig_len = sb->len; - char *cwd = xgetcwd(); - char *pwd = getenv("PWD"); - if (pwd && strcmp(pwd, cwd) && - !stat(cwd, &cwd_stat) && - (cwd_stat.st_dev || cwd_stat.st_ino) && - !stat(pwd, &pwd_stat) && - pwd_stat.st_dev == cwd_stat.st_dev && - pwd_stat.st_ino == cwd_stat.st_ino) - strbuf_addstr(sb, pwd); - else - strbuf_addstr(sb, cwd); - if (sb->len > orig_len && !is_dir_sep(sb->buf[sb->len - 1])) - strbuf_addch(sb, '/'); - free(cwd); - } - strbuf_addstr(sb, path); -} - -void strbuf_add_real_path(struct strbuf *sb, const char *path) -{ - if (sb->len) { - struct strbuf resolved = STRBUF_INIT; - strbuf_realpath(&resolved, path, 1); - strbuf_addbuf(sb, &resolved); - strbuf_release(&resolved); - } else - strbuf_realpath(sb, path, 1); -} - int printf_ln(const char *fmt, ...) { int ret; @@ -1006,32 +951,27 @@ void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm, /* * There is no portable way to pass timezone information to - * strftime, so we handle %z and %Z here. + * strftime, so we handle %z and %Z here. Likewise '%s', because + * going back to an epoch time requires knowing the zone. + * + * Note that tz_offset is in the "[-+]HHMM" decimal form; this is what + * we want for %z, but the computation for %s has to convert to number + * of seconds. */ - for (;;) { - const char *percent = strchrnul(fmt, '%'); - strbuf_add(&munged_fmt, fmt, percent - fmt); - if (!*percent) - break; - fmt = percent + 1; - switch (*fmt) { - case '%': + while (strbuf_expand_step(&munged_fmt, &fmt)) { + if (skip_prefix(fmt, "%", &fmt)) strbuf_addstr(&munged_fmt, "%%"); - fmt++; - break; - case 'z': + else if (skip_prefix(fmt, "s", &fmt)) + strbuf_addf(&munged_fmt, "%"PRItime, + (timestamp_t)tm_to_time_t(tm) - + 3600 * (tz_offset / 100) - + 60 * (tz_offset % 100)); + else if (skip_prefix(fmt, "z", &fmt)) strbuf_addf(&munged_fmt, "%+05d", tz_offset); - fmt++; - break; - case 'Z': - if (suppress_tz_name) { - fmt++; - break; - } - /* FALLTHROUGH */ - default: + else if (suppress_tz_name && skip_prefix(fmt, "Z", &fmt)) + ; /* nothing */ + else strbuf_addch(&munged_fmt, '%'); - } } fmt = munged_fmt.buf; @@ -1059,15 +999,6 @@ void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm, strbuf_setlen(sb, sb->len + len); } -void strbuf_add_unique_abbrev(struct strbuf *sb, const struct object_id *oid, - int abbrev_len) -{ - int r; - strbuf_grow(sb, GIT_MAX_HEXSZ + 1); - r = find_unique_abbrev_r(sb->buf + sb->len, oid, abbrev_len); - strbuf_setlen(sb, sb->len + r); -} - /* * Returns the length of a line, without trailing spaces. * @@ -1097,10 +1028,10 @@ static size_t cleanup(char *line, size_t len) * * If last line does not have a newline at the end, one is added. * - * Enable skip_comments to skip every line starting with comment - * character. + * Pass a non-NULL comment_prefix to skip every line starting + * with it. */ -void strbuf_stripspace(struct strbuf *sb, int skip_comments) +void strbuf_stripspace(struct strbuf *sb, const char *comment_prefix) { size_t empties = 0; size_t i, j, len, newlen; @@ -1113,7 +1044,8 @@ void strbuf_stripspace(struct strbuf *sb, int skip_comments) eol = memchr(sb->buf + i, '\n', sb->len - i); len = eol ? eol - (sb->buf + i) + 1 : sb->len - i; - if (skip_comments && len && sb->buf[i] == comment_line_char) { + if (comment_prefix && len && + starts_with(sb->buf + i, comment_prefix)) { newlen = 0; continue; } @@ -1134,50 +1066,8 @@ void strbuf_stripspace(struct strbuf *sb, int skip_comments) strbuf_setlen(sb, j); } -int strbuf_normalize_path(struct strbuf *src) -{ - struct strbuf dst = STRBUF_INIT; - - strbuf_grow(&dst, src->len); - if (normalize_path_copy(dst.buf, src->buf) < 0) { - strbuf_release(&dst); - return -1; - } - - /* - * normalize_path does not tell us the new length, so we have to - * compute it by looking for the new NUL it placed - */ - strbuf_setlen(&dst, strlen(dst.buf)); - strbuf_swap(src, &dst); - strbuf_release(&dst); - return 0; -} - -int strbuf_edit_interactively(struct strbuf *buffer, const char *path, - const char *const *env) +void strbuf_strip_file_from_path(struct strbuf *sb) { - char *path2 = NULL; - int fd, res = 0; - - if (!is_absolute_path(path)) - path = path2 = xstrdup(git_path("%s", path)); - - fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666); - if (fd < 0) - res = error_errno(_("could not open '%s' for writing"), path); - else if (write_in_full(fd, buffer->buf, buffer->len) < 0) { - res = error_errno(_("could not write to '%s'"), path); - close(fd); - } else if (close(fd) < 0) - res = error_errno(_("could not close '%s'"), path); - else { - strbuf_reset(buffer); - if (launch_editor(path, buffer, env) < 0) - res = error_errno(_("could not edit '%s'"), path); - unlink(path); - } - - free(path2); - return res; + char *path_sep = find_last_dir_sep(sb->buf); + strbuf_setlen(sb, path_sep ? path_sep - sb->buf + 1 : 0); } |