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>
Jonathan Tan committed
Nov 2, 2016 at 10:29 UTC
e8c352c316f31a3869f3ad1dae0e8b33042cbaf4
2 files changed
+107
-36
trailer.c
+82
-36
@@ -46,6 +46,8 @@ static LIST_HEAD(conf_head);
46
47
static char *separators = ":";
48
49
+static int configured;
50
+
51
#define TRAILER_ARG_STRING "$ARG"
52
53
static const char *git_generated_prefixes[] = {
@@ -546,6 +548,17 @@ static int git_trailer_config(const char *conf_key, const char *value, void *cb)
548
return 0;
549
}
550
551
+static void ensure_configured(void)
552
+{
553
+ if (configured)
554
+ return;
555
+
556
+ /* Default config must be setup first */
557
+ git_config(git_trailer_default_config, NULL);
558
+ git_config(git_trailer_config, NULL);
559
+ configured = 1;
560
+}
561
+
562
static const char *token_from_item(struct arg_item *item, char *tok)
563
{
564
if (item->conf.key)
@@ -875,59 +888,43 @@ static int process_input_file(FILE *outfile,
888
const char *str,
889
struct list_head *head)
890
{
878
- int patch_start, trailer_start, trailer_end;
891
+ struct trailer_info info;
892
struct strbuf tok = STRBUF_INIT;
893
struct strbuf val = STRBUF_INIT;
881
- struct trailer_item *last = NULL;
882
- struct strbuf *trailer, **trailer_lines, **ptr;
894
+ int i;
895
884
- patch_start = find_patch_start(str);
885
- trailer_end = find_trailer_end(str, patch_start);
886
- trailer_start = find_trailer_start(str, trailer_end);
896
+ trailer_info_get(&info, str);
897
898
/* Print lines before the trailers as is */
889
- fwrite(str, 1, trailer_start, outfile);
899
+ fwrite(str, 1, info.trailer_start - str, outfile);
900
891
- if (!ends_with_blank_line(str, trailer_start))
901
+ if (!info.blank_line_before_trailer)
902
fprintf(outfile, "\n");
903
894
- /* Parse trailer lines */
895
- trailer_lines = strbuf_split_buf(str + trailer_start,
896
- trailer_end - trailer_start,
897
- '\n',
898
- 0);
899
- for (ptr = trailer_lines; *ptr; ptr++) {
904
+ for (i = 0; i < info.trailer_nr; i++) {
905
int separator_pos;
901
- trailer = *ptr;
902
- if (trailer->buf[0] == comment_line_char)
903
- continue;
904
- if (last && isspace(trailer->buf[0])) {
905
- struct strbuf sb = STRBUF_INIT;
906
- strbuf_addf(&sb, "%s\n%s", last->value, trailer->buf);
907
- strbuf_strip_suffix(&sb, "\n");
908
- free(last->value);
909
- last->value = strbuf_detach(&sb, NULL);
906
+ char *trailer = info.trailers[i];
907
+ if (trailer[0] == comment_line_char)
908
continue;
911
- }
912
- separator_pos = find_separator(trailer->buf, separators);
909
+ separator_pos = find_separator(trailer, separators);
910
if (separator_pos >= 1) {
914
- parse_trailer(&tok, &val, NULL, trailer->buf,
911
+ parse_trailer(&tok, &val, NULL, trailer,
912
separator_pos);
916
- last = add_trailer_item(head,
917
- strbuf_detach(&tok, NULL),
918
- strbuf_detach(&val, NULL));
913
+ add_trailer_item(head,
914
+ strbuf_detach(&tok, NULL),
915
+ strbuf_detach(&val, NULL));
916
} else {
920
- strbuf_addbuf(&val, trailer);
917
+ strbuf_addstr(&val, trailer);
918
strbuf_strip_suffix(&val, "\n");
919
add_trailer_item(head,
920
NULL,
921
strbuf_detach(&val, NULL));
925
- last = NULL;
922
}
923
}
928
- strbuf_list_free(trailer_lines);
924
930
- return trailer_end;
925
+ trailer_info_release(&info);
926
+
927
+ return info.trailer_end - str;
928
}
929
930
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
975
int trailer_end;
976
FILE *outfile = stdout;
977
981
- /* Default config must be setup first */
982
- git_config(git_trailer_default_config, NULL);
983
- git_config(git_trailer_config, NULL);
978
+ ensure_configured();
979
980
read_input_file(&sb, file);
981
@@ -1007,3 +1002,54 @@ void process_trailers(const char *file, int in_place, int trim_empty, struct str
1002
1003
strbuf_release(&sb);
1004
}
1005
+
1006
+void trailer_info_get(struct trailer_info *info, const char *str)
1007
+{
1008
+ int patch_start, trailer_end, trailer_start;
1009
+ struct strbuf **trailer_lines, **ptr;
1010
+ char **trailer_strings = NULL;
1011
+ size_t nr = 0, alloc = 0;
1012
+ char **last = NULL;
1013
+
1014
+ ensure_configured();
1015
+
1016
+ patch_start = find_patch_start(str);
1017
+ trailer_end = find_trailer_end(str, patch_start);
1018
+ trailer_start = find_trailer_start(str, trailer_end);
1019
+
1020
+ trailer_lines = strbuf_split_buf(str + trailer_start,
1021
+ trailer_end - trailer_start,
1022
+ '\n',
1023
+ 0);
1024
+ for (ptr = trailer_lines; *ptr; ptr++) {
1025
+ if (last && isspace((*ptr)->buf[0])) {
1026
+ struct strbuf sb = STRBUF_INIT;
1027
+ strbuf_attach(&sb, *last, strlen(*last), strlen(*last));
1028
+ strbuf_addbuf(&sb, *ptr);
1029
+ *last = strbuf_detach(&sb, NULL);
1030
+ continue;
1031
+ }
1032
+ ALLOC_GROW(trailer_strings, nr + 1, alloc);
1033
+ trailer_strings[nr] = strbuf_detach(*ptr, NULL);
1034
+ last = find_separator(trailer_strings[nr], separators) >= 1
1035
+ ? &trailer_strings[nr]
1036
+ : NULL;
1037
+ nr++;
1038
+ }
1039
+ strbuf_list_free(trailer_lines);
1040
+
1041
+ info->blank_line_before_trailer = ends_with_blank_line(str,
1042
+ trailer_start);
1043
+ info->trailer_start = str + trailer_start;
1044
+ info->trailer_end = str + trailer_end;
1045
+ info->trailers = trailer_strings;
1046
+ info->trailer_nr = nr;
1047
+}
1048
+
1049
+void trailer_info_release(struct trailer_info *info)
1050
+{
1051
+ int i;
1052
+ for (i = 0; i < info->trailer_nr; i++)
1053
+ free(info->trailers[i]);
1054
+ free(info->trailers);
1055
+}
trailer.h
+25
@@ -1,7 +1,32 @@
1
#ifndef TRAILER_H
2
#define TRAILER_H
3
4
+struct trailer_info {
5
+ /*
6
+ * True if there is a blank line before the location pointed to by
7
+ * trailer_start.
8
+ */
9
+ int blank_line_before_trailer;
10
+
11
+ /*
12
+ * Pointers to the start and end of the trailer block found. If there
13
+ * is no trailer block found, these 2 pointers point to the end of the
14
+ * input string.
15
+ */
16
+ const char *trailer_start, *trailer_end;
17
+
18
+ /*
19
+ * Array of trailers found.
20
+ */
21
+ char **trailers;
22
+ size_t trailer_nr;
23
+};
24
+
25
void process_trailers(const char *file, int in_place, int trim_empty,
26
struct string_list *trailers);
27
28
+void trailer_info_get(struct trailer_info *info, const char *str);
29
+
30
+void trailer_info_release(struct trailer_info *info);
31
+
32
#endif /* TRAILER_H */