1
0
mirror of https://github.com/git/git.git synced 2024-11-18 02:14:03 +01:00

trailer: have function to describe trailer layout

Create a function that, taking a string, describes the position of its
trailer block (if available) and the contents thereof, and make trailer
use it. This makes it easier for other Git components, in the future, to
interpret trailer blocks in the same way as trailer.

In a subsequent patch, another component will be made to use this.

Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jonathan Tan 2016-11-02 10:29:19 -07:00 committed by Junio C Hamano
parent 022349c3b0
commit e8c352c316
2 changed files with 107 additions and 36 deletions

118
trailer.c

@ -46,6 +46,8 @@ static LIST_HEAD(conf_head);
static char *separators = ":";
static int configured;
#define TRAILER_ARG_STRING "$ARG"
static const char *git_generated_prefixes[] = {
@ -546,6 +548,17 @@ static int git_trailer_config(const char *conf_key, const char *value, void *cb)
return 0;
}
static void ensure_configured(void)
{
if (configured)
return;
/* Default config must be setup first */
git_config(git_trailer_default_config, NULL);
git_config(git_trailer_config, NULL);
configured = 1;
}
static const char *token_from_item(struct arg_item *item, char *tok)
{
if (item->conf.key)
@ -875,59 +888,43 @@ static int process_input_file(FILE *outfile,
const char *str,
struct list_head *head)
{
int patch_start, trailer_start, trailer_end;
struct trailer_info info;
struct strbuf tok = STRBUF_INIT;
struct strbuf val = STRBUF_INIT;
struct trailer_item *last = NULL;
struct strbuf *trailer, **trailer_lines, **ptr;
int i;
patch_start = find_patch_start(str);
trailer_end = find_trailer_end(str, patch_start);
trailer_start = find_trailer_start(str, trailer_end);
trailer_info_get(&info, str);
/* Print lines before the trailers as is */
fwrite(str, 1, trailer_start, outfile);
fwrite(str, 1, info.trailer_start - str, outfile);
if (!ends_with_blank_line(str, trailer_start))
if (!info.blank_line_before_trailer)
fprintf(outfile, "\n");
/* Parse trailer lines */
trailer_lines = strbuf_split_buf(str + trailer_start,
trailer_end - trailer_start,
'\n',
0);
for (ptr = trailer_lines; *ptr; ptr++) {
for (i = 0; i < info.trailer_nr; i++) {
int separator_pos;
trailer = *ptr;
if (trailer->buf[0] == comment_line_char)
char *trailer = info.trailers[i];
if (trailer[0] == comment_line_char)
continue;
if (last && isspace(trailer->buf[0])) {
struct strbuf sb = STRBUF_INIT;
strbuf_addf(&sb, "%s\n%s", last->value, trailer->buf);
strbuf_strip_suffix(&sb, "\n");
free(last->value);
last->value = strbuf_detach(&sb, NULL);
continue;
}
separator_pos = find_separator(trailer->buf, separators);
separator_pos = find_separator(trailer, separators);
if (separator_pos >= 1) {
parse_trailer(&tok, &val, NULL, trailer->buf,
parse_trailer(&tok, &val, NULL, trailer,
separator_pos);
last = add_trailer_item(head,
strbuf_detach(&tok, NULL),
strbuf_detach(&val, NULL));
add_trailer_item(head,
strbuf_detach(&tok, NULL),
strbuf_detach(&val, NULL));
} else {
strbuf_addbuf(&val, trailer);
strbuf_addstr(&val, trailer);
strbuf_strip_suffix(&val, "\n");
add_trailer_item(head,
NULL,
strbuf_detach(&val, NULL));
last = NULL;
}
}
strbuf_list_free(trailer_lines);
return trailer_end;
trailer_info_release(&info);
return info.trailer_end - str;
}
static void free_all(struct list_head *head)
@ -978,9 +975,7 @@ void process_trailers(const char *file, int in_place, int trim_empty, struct str
int trailer_end;
FILE *outfile = stdout;
/* Default config must be setup first */
git_config(git_trailer_default_config, NULL);
git_config(git_trailer_config, NULL);
ensure_configured();
read_input_file(&sb, file);
@ -1007,3 +1002,54 @@ void process_trailers(const char *file, int in_place, int trim_empty, struct str
strbuf_release(&sb);
}
void trailer_info_get(struct trailer_info *info, const char *str)
{
int patch_start, trailer_end, trailer_start;
struct strbuf **trailer_lines, **ptr;
char **trailer_strings = NULL;
size_t nr = 0, alloc = 0;
char **last = NULL;
ensure_configured();
patch_start = find_patch_start(str);
trailer_end = find_trailer_end(str, patch_start);
trailer_start = find_trailer_start(str, trailer_end);
trailer_lines = strbuf_split_buf(str + trailer_start,
trailer_end - trailer_start,
'\n',
0);
for (ptr = trailer_lines; *ptr; ptr++) {
if (last && isspace((*ptr)->buf[0])) {
struct strbuf sb = STRBUF_INIT;
strbuf_attach(&sb, *last, strlen(*last), strlen(*last));
strbuf_addbuf(&sb, *ptr);
*last = strbuf_detach(&sb, NULL);
continue;
}
ALLOC_GROW(trailer_strings, nr + 1, alloc);
trailer_strings[nr] = strbuf_detach(*ptr, NULL);
last = find_separator(trailer_strings[nr], separators) >= 1
? &trailer_strings[nr]
: NULL;
nr++;
}
strbuf_list_free(trailer_lines);
info->blank_line_before_trailer = ends_with_blank_line(str,
trailer_start);
info->trailer_start = str + trailer_start;
info->trailer_end = str + trailer_end;
info->trailers = trailer_strings;
info->trailer_nr = nr;
}
void trailer_info_release(struct trailer_info *info)
{
int i;
for (i = 0; i < info->trailer_nr; i++)
free(info->trailers[i]);
free(info->trailers);
}

@ -1,7 +1,32 @@
#ifndef TRAILER_H
#define TRAILER_H
struct trailer_info {
/*
* True if there is a blank line before the location pointed to by
* trailer_start.
*/
int blank_line_before_trailer;
/*
* Pointers to the start and end of the trailer block found. If there
* is no trailer block found, these 2 pointers point to the end of the
* input string.
*/
const char *trailer_start, *trailer_end;
/*
* Array of trailers found.
*/
char **trailers;
size_t trailer_nr;
};
void process_trailers(const char *file, int in_place, int trim_empty,
struct string_list *trailers);
void trailer_info_get(struct trailer_info *info, const char *str);
void trailer_info_release(struct trailer_info *info);
#endif /* TRAILER_H */