* [PATCH v6 00/11] Add interpret-trailers builtin
@ 2014-03-04 19:47 Christian Couder
2014-03-04 19:47 ` [PATCH v6 01/11] Add data structures and basic functions for commit trailers Christian Couder
` (11 more replies)
0 siblings, 12 replies; 21+ messages in thread
From: Christian Couder @ 2014-03-04 19:47 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johan Herland, Josh Triplett, Thomas Rast, Michael Haggerty,
Dan Carpenter, Greg Kroah-Hartman, Jeff King, Eric Sunshine
This patch series implements a new command:
git interpret-trailers
and an infrastructure to process trailers that can be reused,
for example in "commit.c".
1) Rationale:
This command should help with RFC 822 style headers, called
"trailers", that are found at the end of commit messages.
(Note that these headers do not follow and are not intended to
follow many rules that are in RFC 822. For example they do not
follow the line breaking rules, the encoding rules and probably
many other rules.)
For a long time, these trailers have become a de facto standard
way to add helpful information into commit messages.
Until now git commit has only supported the well known
"Signed-off-by: " trailer, that is used by many projects like
the Linux kernel and Git.
It is better to implement features for these trailers first in a
new command rather than in builtin/commit.c, because this way the
prepare-commit-msg and commit-msg hooks can reuse this command.
2) Current state:
Currently the usage string of this command is:
git interpret-trailers [--trim-empty] [(<token>[(=|:)<value>])...]
The following features are implemented:
- the result is printed on stdout
- the [<token>[=<value>]>] arguments are interpreted
- a commit message read from stdin is interpreted
- the "trailer.<token>.key" options in the config are interpreted
- the "trailer.<token>.where" options are interpreted
- the "trailer.<token>.ifExist" options are interpreted
- the "trailer.<token>.ifMissing" options are interpreted
- the "trailer.<token>.command" config works
- $ARG can be used in commands
- there are some tests
- there is some documentation
The following features are planned but not yet implemented:
- add more tests related to commands
- add examples in documentation
- integration with "git commit"
Possible improvements:
- support GIT_COMMIT_PROTO env variable in commands
3) Changes since version 5, thanks to Junio and Eric:
* the --infile <file> option has been removed
* many small functions are back to just 'static' instead of 'static inline'
* alnum_len() has been adjust to have a "size_t len" parameter and a size_t
return value again
* strcspn() is used in void parse_trailer()
* some test setup commands have been moved in some proper tests
* some commit messages have been improved
* a patch to setup env variables for commands has been removed
* all the memory leaks should have been fixed
Christian Couder (11):
Add data structures and basic functions for commit trailers
trailer: process trailers from stdin and arguments
trailer: read and process config information
trailer: process command line trailer arguments
trailer: parse trailers from stdin
trailer: put all the processing together and print
trailer: add interpret-trailers command
trailer: add tests for "git interpret-trailers"
trailer: execute command from 'trailer.<name>.command'
trailer: add tests for commands in config file
Documentation: add documentation for 'git interpret-trailers'
.gitignore | 1 +
Documentation/git-interpret-trailers.txt | 123 ++++++
Makefile | 2 +
builtin.h | 1 +
builtin/interpret-trailers.c | 33 ++
git.c | 1 +
t/t7513-interpret-trailers.sh | 261 ++++++++++++
trailer.c | 661 +++++++++++++++++++++++++++++++
trailer.h | 6 +
9 files changed, 1089 insertions(+)
create mode 100644 Documentation/git-interpret-trailers.txt
create mode 100644 builtin/interpret-trailers.c
create mode 100755 t/t7513-interpret-trailers.sh
create mode 100644 trailer.c
create mode 100644 trailer.h
--
1.8.5.2.204.gcfe299d.dirty
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v6 01/11] Add data structures and basic functions for commit trailers
2014-03-04 19:47 [PATCH v6 00/11] Add interpret-trailers builtin Christian Couder
@ 2014-03-04 19:47 ` Christian Couder
2014-03-04 19:48 ` [PATCH v6 02/11] trailer: process trailers from stdin and arguments Christian Couder
` (10 subsequent siblings)
11 siblings, 0 replies; 21+ messages in thread
From: Christian Couder @ 2014-03-04 19:47 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johan Herland, Josh Triplett, Thomas Rast, Michael Haggerty,
Dan Carpenter, Greg Kroah-Hartman, Jeff King, Eric Sunshine
We will use a doubly linked list to store all information
about trailers and their configuration.
This way we can easily remove or add trailers to or from
trailer lists while traversing the lists in either direction.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
Makefile | 1 +
trailer.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 50 insertions(+)
create mode 100644 trailer.c
diff --git a/Makefile b/Makefile
index b4af1e2..ec90feb 100644
--- a/Makefile
+++ b/Makefile
@@ -871,6 +871,7 @@ LIB_OBJS += submodule.o
LIB_OBJS += symlinks.o
LIB_OBJS += tag.o
LIB_OBJS += trace.o
+LIB_OBJS += trailer.o
LIB_OBJS += transport.o
LIB_OBJS += transport-helper.o
LIB_OBJS += tree-diff.o
diff --git a/trailer.c b/trailer.c
new file mode 100644
index 0000000..db93a63
--- /dev/null
+++ b/trailer.c
@@ -0,0 +1,49 @@
+#include "cache.h"
+/*
+ * Copyright (c) 2013, 2014 Christian Couder <chriscool@tuxfamily.org>
+ */
+
+enum action_where { WHERE_AFTER, WHERE_BEFORE };
+enum action_if_exists { EXISTS_ADD_IF_DIFFERENT, EXISTS_ADD_IF_DIFFERENT_NEIGHBOR,
+ EXISTS_ADD, EXISTS_OVERWRITE, EXISTS_DO_NOTHING };
+enum action_if_missing { MISSING_ADD, MISSING_DO_NOTHING };
+
+struct conf_info {
+ char *name;
+ char *key;
+ char *command;
+ enum action_where where;
+ enum action_if_exists if_exists;
+ enum action_if_missing if_missing;
+};
+
+struct trailer_item {
+ struct trailer_item *previous;
+ struct trailer_item *next;
+ const char *token;
+ const char *value;
+ struct conf_info conf;
+};
+
+static int same_token(struct trailer_item *a, struct trailer_item *b, int alnum_len)
+{
+ return !strncasecmp(a->token, b->token, alnum_len);
+}
+
+static int same_value(struct trailer_item *a, struct trailer_item *b)
+{
+ return !strcasecmp(a->value, b->value);
+}
+
+static int same_trailer(struct trailer_item *a, struct trailer_item *b, int alnum_len)
+{
+ return same_token(a, b, alnum_len) && same_value(a, b);
+}
+
+/* Get the length of buf from its beginning until its last alphanumeric character */
+static size_t alnum_len(const char *buf, size_t len)
+{
+ while (len > 0 && !isalnum(buf[len - 1]))
+ len--;
+ return len;
+}
--
1.8.5.2.204.gcfe299d.dirty
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v6 02/11] trailer: process trailers from stdin and arguments
2014-03-04 19:47 [PATCH v6 00/11] Add interpret-trailers builtin Christian Couder
2014-03-04 19:47 ` [PATCH v6 01/11] Add data structures and basic functions for commit trailers Christian Couder
@ 2014-03-04 19:48 ` Christian Couder
2014-03-05 22:52 ` Junio C Hamano
2014-03-04 19:48 ` [PATCH v6 03/11] trailer: read and process config information Christian Couder
` (9 subsequent siblings)
11 siblings, 1 reply; 21+ messages in thread
From: Christian Couder @ 2014-03-04 19:48 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johan Herland, Josh Triplett, Thomas Rast, Michael Haggerty,
Dan Carpenter, Greg Kroah-Hartman, Jeff King, Eric Sunshine
Implement the logic to process trailers from stdin and arguments.
At the beginning trailers from stdin are in their own in_tok
doubly linked list, and trailers from arguments are in their own
arg_tok doubly linked list.
The lists are traversed and when an arg_tok should be "applied",
it is removed from its list and inserted into the in_tok list.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
trailer.c | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 197 insertions(+)
diff --git a/trailer.c b/trailer.c
index db93a63..a0124f2 100644
--- a/trailer.c
+++ b/trailer.c
@@ -47,3 +47,200 @@ static size_t alnum_len(const char *buf, size_t len)
len--;
return len;
}
+
+static void free_trailer_item(struct trailer_item *item)
+{
+ free(item->conf.name);
+ free(item->conf.key);
+ free(item->conf.command);
+ free((char *)item->token);
+ free((char *)item->value);
+ free(item);
+}
+
+static void add_arg_to_input_list(struct trailer_item *in_tok,
+ struct trailer_item *arg_tok)
+{
+ if (arg_tok->conf.where == WHERE_AFTER) {
+ arg_tok->next = in_tok->next;
+ in_tok->next = arg_tok;
+ arg_tok->previous = in_tok;
+ if (arg_tok->next)
+ arg_tok->next->previous = arg_tok;
+ } else {
+ arg_tok->previous = in_tok->previous;
+ in_tok->previous = arg_tok;
+ arg_tok->next = in_tok;
+ if (arg_tok->previous)
+ arg_tok->previous->next = arg_tok;
+ }
+}
+
+static int check_if_different(struct trailer_item *in_tok,
+ struct trailer_item *arg_tok,
+ int alnum_len, int check_all)
+{
+ enum action_where where = arg_tok->conf.where;
+ do {
+ if (!in_tok)
+ return 1;
+ if (same_trailer(in_tok, arg_tok, alnum_len))
+ return 0;
+ /*
+ * if we want to add a trailer after another one,
+ * we have to check those before this one
+ */
+ in_tok = (where == WHERE_AFTER) ? in_tok->previous : in_tok->next;
+ } while (check_all);
+ return 1;
+}
+
+static void apply_arg_if_exists(struct trailer_item *in_tok,
+ struct trailer_item *arg_tok,
+ int alnum_len)
+{
+ switch (arg_tok->conf.if_exists) {
+ case EXISTS_DO_NOTHING:
+ free_trailer_item(arg_tok);
+ break;
+ case EXISTS_OVERWRITE:
+ free((char *)in_tok->value);
+ in_tok->value = xstrdup(arg_tok->value);
+ free_trailer_item(arg_tok);
+ break;
+ case EXISTS_ADD:
+ add_arg_to_input_list(in_tok, arg_tok);
+ break;
+ case EXISTS_ADD_IF_DIFFERENT:
+ if (check_if_different(in_tok, arg_tok, alnum_len, 1))
+ add_arg_to_input_list(in_tok, arg_tok);
+ else
+ free_trailer_item(arg_tok);
+ break;
+ case EXISTS_ADD_IF_DIFFERENT_NEIGHBOR:
+ if (check_if_different(in_tok, arg_tok, alnum_len, 0))
+ add_arg_to_input_list(in_tok, arg_tok);
+ else
+ free_trailer_item(arg_tok);
+ break;
+ }
+}
+
+static void remove_from_list(struct trailer_item *item,
+ struct trailer_item **first)
+{
+ if (item->next)
+ item->next->previous = item->previous;
+ if (item->previous)
+ item->previous->next = item->next;
+ else
+ *first = item->next;
+}
+
+static struct trailer_item *remove_first(struct trailer_item **first)
+{
+ struct trailer_item *item = *first;
+ *first = item->next;
+ if (item->next) {
+ item->next->previous = NULL;
+ item->next = NULL;
+ }
+ return item;
+}
+
+static void process_input_token(struct trailer_item *in_tok,
+ struct trailer_item **arg_tok_first,
+ enum action_where where)
+{
+ struct trailer_item *arg_tok;
+ struct trailer_item *next_arg;
+
+ int tok_alnum_len = alnum_len(in_tok->token, strlen(in_tok->token));
+ for (arg_tok = *arg_tok_first; arg_tok; arg_tok = next_arg) {
+ next_arg = arg_tok->next;
+ if (same_token(in_tok, arg_tok, tok_alnum_len) &&
+ arg_tok->conf.where == where) {
+ remove_from_list(arg_tok, arg_tok_first);
+ apply_arg_if_exists(in_tok, arg_tok, tok_alnum_len);
+ /*
+ * If arg has been added to input,
+ * then we need to process it too now.
+ */
+ if ((where == WHERE_AFTER ? in_tok->next : in_tok->previous) == arg_tok)
+ in_tok = arg_tok;
+ }
+ }
+}
+
+static void update_last(struct trailer_item **last)
+{
+ if (*last)
+ while((*last)->next != NULL)
+ *last = (*last)->next;
+}
+
+static void update_first(struct trailer_item **first)
+{
+ if (*first)
+ while((*first)->previous != NULL)
+ *first = (*first)->previous;
+}
+
+static void apply_arg_if_missing(struct trailer_item **in_tok_first,
+ struct trailer_item **in_tok_last,
+ struct trailer_item *arg_tok)
+{
+ struct trailer_item **in_tok;
+ enum action_where where;
+
+ switch (arg_tok->conf.if_missing) {
+ case MISSING_DO_NOTHING:
+ free_trailer_item(arg_tok);
+ break;
+ case MISSING_ADD:
+ where = arg_tok->conf.where;
+ in_tok = (where == WHERE_AFTER) ? in_tok_last : in_tok_first;
+ if (*in_tok) {
+ add_arg_to_input_list(*in_tok, arg_tok);
+ *in_tok = arg_tok;
+ } else {
+ *in_tok_first = arg_tok;
+ *in_tok_last = arg_tok;
+ }
+ break;
+ }
+}
+
+static void process_trailers_lists(struct trailer_item **in_tok_first,
+ struct trailer_item **in_tok_last,
+ struct trailer_item **arg_tok_first)
+{
+ struct trailer_item *in_tok;
+ struct trailer_item *arg_tok;
+
+ if (!*arg_tok_first)
+ return;
+
+ /* Process input from end to start */
+ for (in_tok = *in_tok_last; in_tok; in_tok = in_tok->previous) {
+ process_input_token(in_tok, arg_tok_first, WHERE_AFTER);
+ }
+
+ update_last(in_tok_last);
+
+ if (!*arg_tok_first)
+ return;
+
+ /* Process input from start to end */
+ for (in_tok = *in_tok_first; in_tok; in_tok = in_tok->next) {
+ process_input_token(in_tok, arg_tok_first, WHERE_BEFORE);
+ }
+
+ update_first(in_tok_first);
+
+ /* Process args left */
+ while (*arg_tok_first) {
+ arg_tok = remove_first(arg_tok_first);
+ apply_arg_if_missing(in_tok_first, in_tok_last, arg_tok);
+ }
+}
--
1.8.5.2.204.gcfe299d.dirty
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v6 03/11] trailer: read and process config information
2014-03-04 19:47 [PATCH v6 00/11] Add interpret-trailers builtin Christian Couder
2014-03-04 19:47 ` [PATCH v6 01/11] Add data structures and basic functions for commit trailers Christian Couder
2014-03-04 19:48 ` [PATCH v6 02/11] trailer: process trailers from stdin and arguments Christian Couder
@ 2014-03-04 19:48 ` Christian Couder
2014-03-04 19:48 ` [PATCH v6 04/11] trailer: process command line trailer arguments Christian Couder
` (8 subsequent siblings)
11 siblings, 0 replies; 21+ messages in thread
From: Christian Couder @ 2014-03-04 19:48 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johan Herland, Josh Triplett, Thomas Rast, Michael Haggerty,
Dan Carpenter, Greg Kroah-Hartman, Jeff King, Eric Sunshine
This patch implements reading the configuration
to get trailer information, and then processing
it and storing it in a doubly linked list.
The config information is stored in the list
whose first item is pointed to by:
static struct trailer_item *first_conf_item;
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
trailer.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 134 insertions(+)
diff --git a/trailer.c b/trailer.c
index a0124f2..5b8e28b 100644
--- a/trailer.c
+++ b/trailer.c
@@ -25,6 +25,8 @@ struct trailer_item {
struct conf_info conf;
};
+static struct trailer_item *first_conf_item;
+
static int same_token(struct trailer_item *a, struct trailer_item *b, int alnum_len)
{
return !strncasecmp(a->token, b->token, alnum_len);
@@ -244,3 +246,135 @@ static void process_trailers_lists(struct trailer_item **in_tok_first,
apply_arg_if_missing(in_tok_first, in_tok_last, arg_tok);
}
}
+
+static int set_where(struct conf_info *item, const char *value)
+{
+ if (!strcasecmp("after", value))
+ item->where = WHERE_AFTER;
+ else if (!strcasecmp("before", value))
+ item->where = WHERE_BEFORE;
+ else
+ return 1;
+ return 0;
+}
+
+static int set_if_exists(struct conf_info *item, const char *value)
+{
+ if (!strcasecmp("addIfDifferent", value))
+ item->if_exists = EXISTS_ADD_IF_DIFFERENT;
+ else if (!strcasecmp("addIfDifferentNeighbor", value))
+ item->if_exists = EXISTS_ADD_IF_DIFFERENT_NEIGHBOR;
+ else if (!strcasecmp("add", value))
+ item->if_exists = EXISTS_ADD;
+ else if (!strcasecmp("overwrite", value))
+ item->if_exists = EXISTS_OVERWRITE;
+ else if (!strcasecmp("doNothing", value))
+ item->if_exists = EXISTS_DO_NOTHING;
+ else
+ return 1;
+ return 0;
+}
+
+static int set_if_missing(struct conf_info *item, const char *value)
+{
+ if (!strcasecmp("doNothing", value))
+ item->if_missing = MISSING_DO_NOTHING;
+ else if (!strcasecmp("add", value))
+ item->if_missing = MISSING_ADD;
+ else
+ return 1;
+ return 0;
+}
+
+enum trailer_info_type { TRAILER_KEY, TRAILER_COMMAND, TRAILER_WHERE,
+ TRAILER_IF_EXISTS, TRAILER_IF_MISSING };
+
+static int set_name_and_type(const char *conf_key, const char *suffix,
+ enum trailer_info_type type,
+ char **pname, enum trailer_info_type *ptype)
+{
+ int ret = ends_with(conf_key, suffix);
+ if (ret) {
+ *pname = xstrndup(conf_key, strlen(conf_key) - strlen(suffix));
+ *ptype = type;
+ }
+ return ret;
+}
+
+static struct trailer_item *get_conf_item(const char *name)
+{
+ struct trailer_item *item;
+ struct trailer_item *previous;
+
+ /* Look up item with same name */
+ for (previous = NULL, item = first_conf_item;
+ item;
+ previous = item, item = item->next) {
+ if (!strcasecmp(item->conf.name, name))
+ return item;
+ }
+
+ /* Item does not already exists, create it */
+ item = xcalloc(sizeof(struct trailer_item), 1);
+ item->conf.name = xstrdup(name);
+
+ if (!previous)
+ first_conf_item = item;
+ else {
+ previous->next = item;
+ item->previous = previous;
+ }
+
+ return item;
+}
+
+static int git_trailer_config(const char *conf_key, const char *value, void *cb)
+{
+ if (starts_with(conf_key, "trailer.")) {
+ const char *orig_conf_key = conf_key;
+ struct trailer_item *item;
+ struct conf_info *conf;
+ char *name;
+ enum trailer_info_type type;
+
+ conf_key += 8;
+ if (!set_name_and_type(conf_key, ".key", TRAILER_KEY, &name, &type) &&
+ !set_name_and_type(conf_key, ".command", TRAILER_COMMAND, &name, &type) &&
+ !set_name_and_type(conf_key, ".where", TRAILER_WHERE, &name, &type) &&
+ !set_name_and_type(conf_key, ".ifexists", TRAILER_IF_EXISTS, &name, &type) &&
+ !set_name_and_type(conf_key, ".ifmissing", TRAILER_IF_MISSING, &name, &type))
+ return 0;
+
+ item = get_conf_item(name);
+ conf = &item->conf;
+ free(name);
+
+ switch (type) {
+ case TRAILER_KEY:
+ if (conf->key)
+ warning(_("more than one %s"), orig_conf_key);
+ conf->key = xstrdup(value);
+ break;
+ case TRAILER_COMMAND:
+ if (conf->command)
+ warning(_("more than one %s"), orig_conf_key);
+ conf->command = xstrdup(value);
+ break;
+ case TRAILER_WHERE:
+ if (set_where(conf, value))
+ warning(_("unknown value '%s' for key '%s'"), value, orig_conf_key);
+ break;
+ case TRAILER_IF_EXISTS:
+ if (set_if_exists(conf, value))
+ warning(_("unknown value '%s' for key '%s'"), value, orig_conf_key);
+ break;
+ case TRAILER_IF_MISSING:
+ if (set_if_missing(conf, value))
+ warning(_("unknown value '%s' for key '%s'"), value, orig_conf_key);
+ break;
+ default:
+ die("internal bug in trailer.c");
+ }
+ }
+ return 0;
+}
--
1.8.5.2.204.gcfe299d.dirty
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v6 04/11] trailer: process command line trailer arguments
2014-03-04 19:47 [PATCH v6 00/11] Add interpret-trailers builtin Christian Couder
` (2 preceding siblings ...)
2014-03-04 19:48 ` [PATCH v6 03/11] trailer: read and process config information Christian Couder
@ 2014-03-04 19:48 ` Christian Couder
2014-03-05 22:55 ` Junio C Hamano
2014-03-04 19:48 ` [PATCH v6 05/11] trailer: parse trailers from stdin Christian Couder
` (7 subsequent siblings)
11 siblings, 1 reply; 21+ messages in thread
From: Christian Couder @ 2014-03-04 19:48 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johan Herland, Josh Triplett, Thomas Rast, Michael Haggerty,
Dan Carpenter, Greg Kroah-Hartman, Jeff King, Eric Sunshine
Parse the trailer command line arguments and put
the result into an arg_tok doubly linked list.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
trailer.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 93 insertions(+)
diff --git a/trailer.c b/trailer.c
index 5b8e28b..5d69c00 100644
--- a/trailer.c
+++ b/trailer.c
@@ -378,3 +378,96 @@ static int git_trailer_config(const char *conf_key, const char *value, void *cb)
}
return 0;
}
+
+static void parse_trailer(struct strbuf *tok, struct strbuf *val, const char *trailer)
+{
+ size_t len = strcspn(trailer, "=:");
+ if (len < strlen(trailer)) {
+ strbuf_add(tok, trailer, len);
+ strbuf_trim(tok);
+ strbuf_addstr(val, trailer + len + 1);
+ strbuf_trim(val);
+ } else {
+ strbuf_addstr(tok, trailer);
+ strbuf_trim(tok);
+ }
+}
+
+
+static void duplicate_conf(struct conf_info *dst, struct conf_info *src)
+{
+ *dst = *src;
+ if (src->name)
+ dst->name = xstrdup(src->name);
+ if (src->key)
+ dst->key = xstrdup(src->key);
+ if (src->command)
+ dst->command = xstrdup(src->command);
+}
+
+static struct trailer_item *new_trailer_item(struct trailer_item *conf_item,
+ char* tok, char* val)
+{
+ struct trailer_item *new = xcalloc(sizeof(*new), 1);
+ new->value = val;
+
+ if (conf_item) {
+ duplicate_conf(&new->conf, &conf_item->conf);
+ new->token = xstrdup(conf_item->conf.key);
+ free(tok);
+ } else
+ new->token = tok;
+
+ return new;
+}
+
+static struct trailer_item *create_trailer_item(const char *string)
+{
+ struct strbuf tok = STRBUF_INIT;
+ struct strbuf val = STRBUF_INIT;
+ struct trailer_item *item;
+ int tok_alnum_len;
+
+ parse_trailer(&tok, &val, string);
+
+ tok_alnum_len = alnum_len(tok.buf, tok.len);
+
+ /* Lookup if the token matches something in the config */
+ for (item = first_conf_item; item; item = item->next) {
+ if (!strncasecmp(tok.buf, item->conf.key, tok_alnum_len) ||
+ !strncasecmp(tok.buf, item->conf.name, tok_alnum_len)) {
+ strbuf_release(&tok);
+ return new_trailer_item(item, NULL, strbuf_detach(&val, NULL));
+ }
+ }
+
+ return new_trailer_item(NULL, strbuf_detach(&tok, NULL), strbuf_detach(&val, NULL));;
+}
+
+static void add_trailer_item(struct trailer_item **first,
+ struct trailer_item **last,
+ struct trailer_item *new)
+{
+ if (!*last) {
+ *first = new;
+ *last = new;
+ } else {
+ (*last)->next = new;
+ new->previous = *last;
+ *last = new;
+ }
+}
+
+static struct trailer_item *process_command_line_args(int argc, const char **argv)
+{
+ int i;
+ struct trailer_item *arg_tok_first = NULL;
+ struct trailer_item *arg_tok_last = NULL;
+
+ for (i = 0; i < argc; i++) {
+ struct trailer_item *new = create_trailer_item(argv[i]);
+ add_trailer_item(&arg_tok_first, &arg_tok_last, new);
+ }
+
+ return arg_tok_first;
+}
--
1.8.5.2.204.gcfe299d.dirty
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v6 05/11] trailer: parse trailers from stdin
2014-03-04 19:47 [PATCH v6 00/11] Add interpret-trailers builtin Christian Couder
` (3 preceding siblings ...)
2014-03-04 19:48 ` [PATCH v6 04/11] trailer: process command line trailer arguments Christian Couder
@ 2014-03-04 19:48 ` Christian Couder
2014-03-05 22:56 ` Junio C Hamano
2014-03-04 19:48 ` [PATCH v6 06/11] trailer: put all the processing together and print Christian Couder
` (6 subsequent siblings)
11 siblings, 1 reply; 21+ messages in thread
From: Christian Couder @ 2014-03-04 19:48 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johan Herland, Josh Triplett, Thomas Rast, Michael Haggerty,
Dan Carpenter, Greg Kroah-Hartman, Jeff King, Eric Sunshine
Read trailers from stdin, parse them and put the result into a doubly linked
list.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
trailer.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 76 insertions(+)
diff --git a/trailer.c b/trailer.c
index 5d69c00..e0e066f 100644
--- a/trailer.c
+++ b/trailer.c
@@ -50,6 +50,13 @@ static size_t alnum_len(const char *buf, size_t len)
return len;
}
+static inline int contains_only_spaces(const char *str)
+{
+ const char *s;
+ for (s = str; *s && isspace(*s); s++);
+ return !*s;
+}
+
static void free_trailer_item(struct trailer_item *item)
{
free(item->conf.name);
@@ -471,3 +478,72 @@ static struct trailer_item *process_command_line_args(int argc, const char **arg
return arg_tok_first;
}
+
+static struct strbuf **read_stdin(void)
+{
+ struct strbuf **lines;
+ struct strbuf sb = STRBUF_INIT;
+
+ if (strbuf_read(&sb, fileno(stdin), 0) < 0)
+ die_errno(_("could not read from stdin"));
+
+ lines = strbuf_split(&sb, '\n');
+
+ strbuf_release(&sb);
+
+ return lines;
+}
+
+/*
+ * Return the the (0 based) index of the first trailer line
+ * or the line count if there are no trailers.
+ */
+static int find_trailer_start(struct strbuf **lines)
+{
+ int count, start, empty = 1;
+
+ /* Get the line count */
+ for (count = 0; lines[count]; count++)
+ ; /* Nothing to do */
+
+ /*
+ * Get the start of the trailers by looking starting from the end
+ * for a line with only spaces before lines with one ':'.
+ */
+ for (start = count - 1; start >= 0; start--) {
+ if (contains_only_spaces(lines[start]->buf)) {
+ if (empty)
+ continue;
+ return start + 1;
+ }
+ if (strchr(lines[start]->buf, ':')) {
+ if (empty)
+ empty = 0;
+ continue;
+ }
+ return count;
+ }
+
+ return empty ? count : start + 1;
+}
+
+static void process_stdin(struct trailer_item **in_tok_first,
+ struct trailer_item **in_tok_last)
+{
+ struct strbuf **lines = read_stdin();
+ int start = find_trailer_start(lines);
+ int i;
+
+ /* Print non trailer lines as is */
+ for (i = 0; lines[i] && i < start; i++) {
+ printf("%s", lines[i]->buf);
+ }
+
+ /* Parse trailer lines */
+ for (i = start; lines[i]; i++) {
+ struct trailer_item *new = create_trailer_item(lines[i]->buf);
+ add_trailer_item(in_tok_first, in_tok_last, new);
+ }
+
+ strbuf_list_free(lines);
+}
--
1.8.5.2.204.gcfe299d.dirty
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v6 06/11] trailer: put all the processing together and print
2014-03-04 19:47 [PATCH v6 00/11] Add interpret-trailers builtin Christian Couder
` (4 preceding siblings ...)
2014-03-04 19:48 ` [PATCH v6 05/11] trailer: parse trailers from stdin Christian Couder
@ 2014-03-04 19:48 ` Christian Couder
2014-03-04 19:48 ` [PATCH v6 07/11] trailer: add interpret-trailers command Christian Couder
` (5 subsequent siblings)
11 siblings, 0 replies; 21+ messages in thread
From: Christian Couder @ 2014-03-04 19:48 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johan Herland, Josh Triplett, Thomas Rast, Michael Haggerty,
Dan Carpenter, Greg Kroah-Hartman, Jeff King, Eric Sunshine
This patch adds the process_trailers() function that
calls all the previously added processing functions
and then prints the results on the standard output.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
trailer.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/trailer.c b/trailer.c
index e0e066f..ab93c16 100644
--- a/trailer.c
+++ b/trailer.c
@@ -67,6 +67,26 @@ static void free_trailer_item(struct trailer_item *item)
free(item);
}
+static void print_tok_val(const char *tok, const char *val)
+{
+ char c = tok[strlen(tok) - 1];
+ if (isalnum(c))
+ printf("%s: %s\n", tok, val);
+ else if (isspace(c) || c == '#')
+ printf("%s%s\n", tok, val);
+ else
+ printf("%s %s\n", tok, val);
+}
+
+static void print_all(struct trailer_item *first, int trim_empty)
+{
+ struct trailer_item *item;
+ for (item = first; item; item = item->next) {
+ if (!trim_empty || strlen(item->value) > 0)
+ print_tok_val(item->token, item->value);
+ }
+}
+
static void add_arg_to_input_list(struct trailer_item *in_tok,
struct trailer_item *arg_tok)
{
@@ -547,3 +567,31 @@ static void process_stdin(struct trailer_item **in_tok_first,
strbuf_list_free(lines);
}
+
+static void free_all(struct trailer_item **first)
+{
+ while (*first) {
+ struct trailer_item *item = remove_first(first);
+ free_trailer_item(item);
+ }
+}
+
+void process_trailers(int trim_empty, int argc, const char **argv)
+{
+ struct trailer_item *in_tok_first = NULL;
+ struct trailer_item *in_tok_last = NULL;
+ struct trailer_item *arg_tok_first;
+
+ git_config(git_trailer_config, NULL);
+
+ /* Print the non trailer part of stdin */
+ process_stdin(&in_tok_first, &in_tok_last);
+
+ arg_tok_first = process_command_line_args(argc, argv);
+
+ process_trailers_lists(&in_tok_first, &in_tok_last, &arg_tok_first);
+
+ print_all(in_tok_first, trim_empty);
+
+ free_all(&in_tok_first);
+}
--
1.8.5.2.204.gcfe299d.dirty
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v6 07/11] trailer: add interpret-trailers command
2014-03-04 19:47 [PATCH v6 00/11] Add interpret-trailers builtin Christian Couder
` (5 preceding siblings ...)
2014-03-04 19:48 ` [PATCH v6 06/11] trailer: put all the processing together and print Christian Couder
@ 2014-03-04 19:48 ` Christian Couder
2014-03-04 19:48 ` [PATCH v6 08/11] trailer: add tests for "git interpret-trailers" Christian Couder
` (4 subsequent siblings)
11 siblings, 0 replies; 21+ messages in thread
From: Christian Couder @ 2014-03-04 19:48 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johan Herland, Josh Triplett, Thomas Rast, Michael Haggerty,
Dan Carpenter, Greg Kroah-Hartman, Jeff King, Eric Sunshine
This patch adds the "git interpret-trailers" command.
This command uses the previously added process_trailers()
function in trailer.c.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
.gitignore | 1 +
Makefile | 1 +
builtin.h | 1 +
builtin/interpret-trailers.c | 33 +++++++++++++++++++++++++++++++++
git.c | 1 +
trailer.h | 6 ++++++
6 files changed, 43 insertions(+)
create mode 100644 builtin/interpret-trailers.c
create mode 100644 trailer.h
diff --git a/.gitignore b/.gitignore
index b5f9def..c870ada 100644
--- a/.gitignore
+++ b/.gitignore
@@ -74,6 +74,7 @@
/git-index-pack
/git-init
/git-init-db
+/git-interpret-trailers
/git-instaweb
/git-log
/git-ls-files
diff --git a/Makefile b/Makefile
index ec90feb..a91465e 100644
--- a/Makefile
+++ b/Makefile
@@ -935,6 +935,7 @@ BUILTIN_OBJS += builtin/hash-object.o
BUILTIN_OBJS += builtin/help.o
BUILTIN_OBJS += builtin/index-pack.o
BUILTIN_OBJS += builtin/init-db.o
+BUILTIN_OBJS += builtin/interpret-trailers.o
BUILTIN_OBJS += builtin/log.o
BUILTIN_OBJS += builtin/ls-files.o
BUILTIN_OBJS += builtin/ls-remote.o
diff --git a/builtin.h b/builtin.h
index d4afbfe..30f4c30 100644
--- a/builtin.h
+++ b/builtin.h
@@ -71,6 +71,7 @@ extern int cmd_hash_object(int argc, const char **argv, const char *prefix);
extern int cmd_help(int argc, const char **argv, const char *prefix);
extern int cmd_index_pack(int argc, const char **argv, const char *prefix);
extern int cmd_init_db(int argc, const char **argv, const char *prefix);
+extern int cmd_interpret_trailers(int argc, const char **argv, const char *prefix);
extern int cmd_log(int argc, const char **argv, const char *prefix);
extern int cmd_log_reflog(int argc, const char **argv, const char *prefix);
extern int cmd_ls_files(int argc, const char **argv, const char *prefix);
diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c
new file mode 100644
index 0000000..0c8ca72
--- /dev/null
+++ b/builtin/interpret-trailers.c
@@ -0,0 +1,33 @@
+/*
+ * Builtin "git interpret-trailers"
+ *
+ * Copyright (c) 2013, 2014 Christian Couder <chriscool@tuxfamily.org>
+ *
+ */
+
+#include "cache.h"
+#include "builtin.h"
+#include "parse-options.h"
+#include "trailer.h"
+
+static const char * const git_interpret_trailers_usage[] = {
+ N_("git interpret-trailers [--trim-empty] [(<token>[(=|:)<value>])...]"),
+ NULL
+};
+
+int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
+{
+ int trim_empty = 0;
+
+ struct option options[] = {
+ OPT_BOOL(0, "trim-empty", &trim_empty, N_("trim empty trailers")),
+ OPT_END()
+ };
+
+ argc = parse_options(argc, argv, prefix, options,
+ git_interpret_trailers_usage, 0);
+
+ process_trailers(trim_empty, argc, argv);
+
+ return 0;
+}
diff --git a/git.c b/git.c
index 3799514..1420b58 100644
--- a/git.c
+++ b/git.c
@@ -383,6 +383,7 @@ static void handle_internal_command(int argc, const char **argv)
{ "index-pack", cmd_index_pack, RUN_SETUP_GENTLY },
{ "init", cmd_init_db },
{ "init-db", cmd_init_db },
+ { "interpret-trailers", cmd_interpret_trailers, RUN_SETUP },
{ "log", cmd_log, RUN_SETUP },
{ "ls-files", cmd_ls_files, RUN_SETUP },
{ "ls-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
diff --git a/trailer.h b/trailer.h
new file mode 100644
index 0000000..9323b1e
--- /dev/null
+++ b/trailer.h
@@ -0,0 +1,6 @@
+#ifndef TRAILER_H
+#define TRAILER_H
+
+void process_trailers(int trim_empty, int argc, const char **argv);
+
+#endif /* TRAILER_H */
--
1.8.5.2.204.gcfe299d.dirty
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v6 08/11] trailer: add tests for "git interpret-trailers"
2014-03-04 19:47 [PATCH v6 00/11] Add interpret-trailers builtin Christian Couder
` (6 preceding siblings ...)
2014-03-04 19:48 ` [PATCH v6 07/11] trailer: add interpret-trailers command Christian Couder
@ 2014-03-04 19:48 ` Christian Couder
2014-03-05 22:59 ` Junio C Hamano
2014-03-04 19:48 ` [PATCH v6 09/11] trailer: execute command from 'trailer.<name>.command' Christian Couder
` (3 subsequent siblings)
11 siblings, 1 reply; 21+ messages in thread
From: Christian Couder @ 2014-03-04 19:48 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johan Herland, Josh Triplett, Thomas Rast, Michael Haggerty,
Dan Carpenter, Greg Kroah-Hartman, Jeff King, Eric Sunshine
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
t/t7513-interpret-trailers.sh | 214 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 214 insertions(+)
create mode 100755 t/t7513-interpret-trailers.sh
diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh
new file mode 100755
index 0000000..3223b12
--- /dev/null
+++ b/t/t7513-interpret-trailers.sh
@@ -0,0 +1,214 @@
+#!/bin/sh
+#
+# Copyright (c) 2013 Christian Couder
+#
+
+test_description='git interpret-trailers'
+
+. ./test-lib.sh
+
+test_expect_success 'setup 1' '
+ cat >basic_message <<"EOF"
+subject
+
+body
+EOF
+'
+
+test_expect_success 'setup 2' '
+ cat >complex_message_body <<"EOF"
+my subject
+
+my body which is long
+and contains some special
+chars like : = ? !
+
+EOF
+'
+
+# We want one trailing space at the end of each line.
+# Let's use sed to make sure that these spaces are not removed
+# by any automatic tool.
+test_expect_success 'setup 3' '
+ sed -e "s/ Z\$/ /" >complex_message_trailers <<-\EOF
+Fixes: Z
+Acked-by: Z
+Reviewed-by: Z
+Signed-off-by: Z
+EOF
+'
+
+test_expect_success 'without config' '
+ printf "ack: Peff\nReviewed-by: \nAcked-by: Johan\n" >expected &&
+ git interpret-trailers "ack = Peff" "Reviewed-by" "Acked-by: Johan" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success '--trim-empty without config' '
+ printf "ack: Peff\nAcked-by: Johan\n" >expected &&
+ git interpret-trailers --trim-empty "ack = Peff" "Reviewed-by" "Acked-by: Johan" "sob:" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with config setup' '
+ git config trailer.ack.key "Acked-by: " &&
+ printf "Acked-by: Peff\n" >expected &&
+ git interpret-trailers --trim-empty "ack = Peff" >actual &&
+ test_cmp expected actual &&
+ git interpret-trailers --trim-empty "Acked-by = Peff" >actual &&
+ test_cmp expected actual &&
+ git interpret-trailers --trim-empty "Acked-by :Peff" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with config setup and = sign' '
+ git config trailer.ack.key "Acked-by= " &&
+ printf "Acked-by= Peff\n" >expected &&
+ git interpret-trailers --trim-empty "ack = Peff" >actual &&
+ test_cmp expected actual &&
+ git interpret-trailers --trim-empty "Acked-by= Peff" >actual &&
+ test_cmp expected actual &&
+ git interpret-trailers --trim-empty "Acked-by : Peff" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with config setup and # sign' '
+ git config trailer.bug.key "Bug #" &&
+ printf "Bug #42\n" >expected &&
+ git interpret-trailers --trim-empty "bug = 42" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with commit basic message' '
+ git interpret-trailers <basic_message >actual &&
+ test_cmp basic_message actual
+'
+
+test_expect_success 'with commit complex message' '
+ cat complex_message_body complex_message_trailers >complex_message &&
+ cat complex_message_body >expected &&
+ printf "Fixes: \nAcked-by= \nReviewed-by: \nSigned-off-by: \n" >>expected &&
+ git interpret-trailers <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with commit complex message and args' '
+ cat complex_message_body >expected &&
+ printf "Fixes: \nAcked-by= \nAcked-by= Peff\nReviewed-by: \nSigned-off-by: \nBug #42\n" >>expected &&
+ git interpret-trailers "ack: Peff" "bug: 42" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with commit complex message, args and --trim-empty' '
+ cat complex_message_body >expected &&
+ printf "Acked-by= Peff\nBug #42\n" >>expected &&
+ git interpret-trailers --trim-empty "ack: Peff" "bug: 42" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "where = before"' '
+ git config trailer.bug.where "before" &&
+ cat complex_message_body >expected &&
+ printf "Bug #42\nFixes: \nAcked-by= \nAcked-by= Peff\nReviewed-by: \nSigned-off-by: \n" >>expected &&
+ git interpret-trailers "ack: Peff" "bug: 42" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "where = before" for a token in the middle of the message' '
+ git config trailer.review.key "Reviewed-by:" &&
+ git config trailer.review.where "before" &&
+ cat complex_message_body >expected &&
+ printf "Bug #42\nFixes: \nAcked-by= \nAcked-by= Peff\nReviewed-by: Johan\nReviewed-by: \nSigned-off-by: \n" >>expected &&
+ git interpret-trailers "ack: Peff" "bug: 42" "review: Johan" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "where = before" and --trim-empty' '
+ cat complex_message_body >expected &&
+ printf "Bug #46\nBug #42\nAcked-by= Peff\nReviewed-by: Johan\n" >>expected &&
+ git interpret-trailers --trim-empty "ack: Peff" "bug: 42" "review: Johan" "Bug: 46" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'the default is "ifExists = addIfDifferent"' '
+ cat complex_message_body >expected &&
+ printf "Bug #42\nFixes: \nAcked-by= \nAcked-by= Peff\nReviewed-by: \nSigned-off-by: \n" >>expected &&
+ git interpret-trailers "ack: Peff" "review:" "bug: 42" "ack: Peff" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifExists = addIfDifferent"' '
+ git config trailer.review.ifExists "addIfDifferent" &&
+ cat complex_message_body >expected &&
+ printf "Bug #42\nFixes: \nAcked-by= \nAcked-by= Peff\nReviewed-by: \nSigned-off-by: \n" >>expected &&
+ git interpret-trailers "ack: Peff" "review:" "bug: 42" "ack: Peff" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifExists = addIfDifferentNeighbor"' '
+ git config trailer.ack.ifExists "addIfDifferentNeighbor" &&
+ cat complex_message_body >expected &&
+ printf "Bug #42\nFixes: \nAcked-by= \nAcked-by= Peff\nAcked-by= Junio\nAcked-by= Peff\nReviewed-by: \nSigned-off-by: \n" >>expected &&
+ git interpret-trailers "ack: Peff" "review:" "ack: Junio" "bug: 42" "ack: Peff" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifExists = addIfDifferentNeighbor" and --trim-empty' '
+ git config trailer.ack.ifExists "addIfDifferentNeighbor" &&
+ cat complex_message_body >expected &&
+ printf "Bug #42\nAcked-by= Peff\nAcked-by= Junio\nAcked-by= Peff\n" >>expected &&
+ git interpret-trailers --trim-empty "ack: Peff" "Acked-by= Peff" "review:" "ack: Junio" "bug: 42" "ack: Peff" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifExists = add"' '
+ git config trailer.ack.ifExists "add" &&
+ cat complex_message_body >expected &&
+ printf "Bug #42\nFixes: \nAcked-by= \nAcked-by= Peff\nAcked-by= Peff\nAcked-by= Junio\nAcked-by= Peff\nReviewed-by: \nSigned-off-by: \n" >>expected &&
+ git interpret-trailers "ack: Peff" "Acked-by= Peff" "review:" "ack: Junio" "bug: 42" "ack: Peff" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifExists = overwrite"' '
+ git config trailer.fix.key "Fixes:" &&
+ git config trailer.fix.ifExists "overwrite" &&
+ cat complex_message_body >expected &&
+ printf "Bug #42\nFixes: 22\nAcked-by= \nAcked-by= Junio\nAcked-by= Peff\nReviewed-by: \nSigned-off-by: \n" >>expected &&
+ git interpret-trailers "review:" "fix=53" "ack: Junio" "fix=22" "bug: 42" "ack: Peff" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifExists = doNothing"' '
+ git config trailer.fix.ifExists "doNothing" &&
+ cat complex_message_body >expected &&
+ printf "Bug #42\nFixes: \nAcked-by= \nAcked-by= Junio\nAcked-by= Peff\nReviewed-by: \nSigned-off-by: \n" >>expected &&
+ git interpret-trailers "review:" "fix=53" "ack: Junio" "fix=22" "bug: 42" "ack: Peff" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'the default is "ifMissing = add"' '
+ git config trailer.cc.key "Cc: " &&
+ git config trailer.Cc.where "before" &&
+ cat complex_message_body >expected &&
+ printf "Bug #42\nCc: Linus\nFixes: \nAcked-by= \nAcked-by= Junio\nAcked-by= Peff\nReviewed-by: \nSigned-off-by: \n" >>expected &&
+ git interpret-trailers "review:" "fix=53" "cc=Linus" "ack: Junio" "fix=22" "bug: 42" "ack: Peff" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifMissing = add"' '
+ git config trailer.Cc.ifMissing "add" &&
+ cat complex_message_body >expected &&
+ printf "Cc: Linus\nBug #42\nFixes: \nAcked-by= \nAcked-by= Junio\nAcked-by= Peff\nReviewed-by: \nSigned-off-by: \n" >>expected &&
+ git interpret-trailers "review:" "fix=53" "ack: Junio" "fix=22" "bug: 42" "cc=Linus" "ack: Peff" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifMissing = doNothing"' '
+ git config trailer.Cc.ifMissing "doNothing" &&
+ cat complex_message_body >expected &&
+ printf "Bug #42\nFixes: \nAcked-by= \nAcked-by= Junio\nAcked-by= Peff\nReviewed-by: \nSigned-off-by: \n" >>expected &&
+ git interpret-trailers "review:" "fix=53" "cc=Linus" "ack: Junio" "fix=22" "bug: 42" "ack: Peff" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_done
--
1.8.5.2.204.gcfe299d.dirty
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v6 09/11] trailer: execute command from 'trailer.<name>.command'
2014-03-04 19:47 [PATCH v6 00/11] Add interpret-trailers builtin Christian Couder
` (7 preceding siblings ...)
2014-03-04 19:48 ` [PATCH v6 08/11] trailer: add tests for "git interpret-trailers" Christian Couder
@ 2014-03-04 19:48 ` Christian Couder
2014-03-05 22:57 ` Junio C Hamano
2014-03-04 19:48 ` [PATCH v6 10/11] trailer: add tests for commands in config file Christian Couder
` (2 subsequent siblings)
11 siblings, 1 reply; 21+ messages in thread
From: Christian Couder @ 2014-03-04 19:48 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johan Herland, Josh Triplett, Thomas Rast, Michael Haggerty,
Dan Carpenter, Greg Kroah-Hartman, Jeff King, Eric Sunshine
Let the user specify a command that will give on its standard output
the value to use for the specified trailer.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
trailer.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/trailer.c b/trailer.c
index ab93c16..67e7baf 100644
--- a/trailer.c
+++ b/trailer.c
@@ -1,4 +1,5 @@
#include "cache.h"
+#include "run-command.h"
/*
* Copyright (c) 2013, 2014 Christian Couder <chriscool@tuxfamily.org>
*/
@@ -12,11 +13,14 @@ struct conf_info {
char *name;
char *key;
char *command;
+ unsigned command_uses_arg : 1;
enum action_where where;
enum action_if_exists if_exists;
enum action_if_missing if_missing;
};
+#define TRAILER_ARG_STRING "$ARG"
+
struct trailer_item {
struct trailer_item *previous;
struct trailer_item *next;
@@ -57,6 +61,13 @@ static inline int contains_only_spaces(const char *str)
return !*s;
}
+static inline void strbuf_replace(struct strbuf *sb, const char *a, const char *b)
+{
+ const char *ptr = strstr(sb->buf, a);
+ if (ptr)
+ strbuf_splice(sb, ptr - sb->buf, strlen(a), b, strlen(b));
+}
+
static void free_trailer_item(struct trailer_item *item)
{
free(item->conf.name);
@@ -386,6 +397,7 @@ static int git_trailer_config(const char *conf_key, const char *value, void *cb)
if (conf->command)
warning(_("more than one %s"), orig_conf_key);
conf->command = xstrdup(value);
+ conf->command_uses_arg = !!strstr(conf->command, TRAILER_ARG_STRING);
break;
case TRAILER_WHERE:
if (set_where(conf, value))
@@ -420,6 +432,44 @@ static void parse_trailer(struct strbuf *tok, struct strbuf *val, const char *tr
}
}
+static int read_from_command(struct child_process *cp, struct strbuf *buf)
+{
+ if (run_command(cp))
+ return error("running trailer command '%s' failed", cp->argv[0]);
+ if (strbuf_read(buf, cp->out, 1024) < 1)
+ return error("reading from trailer command '%s' failed", cp->argv[0]);
+ strbuf_trim(buf);
+ return 0;
+}
+
+static const char *apply_command(const char *command, const char *arg)
+{
+ struct strbuf cmd = STRBUF_INIT;
+ struct strbuf buf = STRBUF_INIT;
+ struct child_process cp;
+ const char *argv[] = {NULL, NULL};
+ const char *result = "";
+
+ strbuf_addstr(&cmd, command);
+ if (arg)
+ strbuf_replace(&cmd, TRAILER_ARG_STRING, arg);
+
+ argv[0] = cmd.buf;
+ memset(&cp, 0, sizeof(cp));
+ cp.argv = argv;
+ cp.env = local_repo_env;
+ cp.no_stdin = 1;
+ cp.out = -1;
+ cp.use_shell = 1;
+
+ if (read_from_command(&cp, &buf))
+ strbuf_release(&buf);
+ else
+ result = strbuf_detach(&buf, NULL);
+
+ strbuf_release(&cmd);
+ return result;
+}
static void duplicate_conf(struct conf_info *dst, struct conf_info *src)
{
@@ -442,6 +492,10 @@ static struct trailer_item *new_trailer_item(struct trailer_item *conf_item,
duplicate_conf(&new->conf, &conf_item->conf);
new->token = xstrdup(conf_item->conf.key);
free(tok);
+ if (conf_item->conf.command_uses_arg || !val) {
+ new->value = apply_command(conf_item->conf.command, val);
+ free(val);
+ }
} else
new->token = tok;
@@ -490,12 +544,22 @@ static struct trailer_item *process_command_line_args(int argc, const char **arg
int i;
struct trailer_item *arg_tok_first = NULL;
struct trailer_item *arg_tok_last = NULL;
+ struct trailer_item *item;
for (i = 0; i < argc; i++) {
struct trailer_item *new = create_trailer_item(argv[i]);
add_trailer_item(&arg_tok_first, &arg_tok_last, new);
}
+ /* Add conf commands that don't use $ARG */
+ for (item = first_conf_item; item; item = item->next) {
+ if (item->conf.command && !item->conf.command_uses_arg)
+ {
+ struct trailer_item *new = new_trailer_item(item, NULL, NULL);
+ add_trailer_item(&arg_tok_first, &arg_tok_last, new);
+ }
+ }
+
return arg_tok_first;
}
--
1.8.5.2.204.gcfe299d.dirty
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v6 10/11] trailer: add tests for commands in config file
2014-03-04 19:47 [PATCH v6 00/11] Add interpret-trailers builtin Christian Couder
` (8 preceding siblings ...)
2014-03-04 19:48 ` [PATCH v6 09/11] trailer: execute command from 'trailer.<name>.command' Christian Couder
@ 2014-03-04 19:48 ` Christian Couder
2014-03-04 19:48 ` [PATCH v6 11/11] Documentation: add documentation for 'git interpret-trailers' Christian Couder
2014-03-06 1:18 ` [PATCH v6 00/11] Add interpret-trailers builtin Ramsay Jones
11 siblings, 0 replies; 21+ messages in thread
From: Christian Couder @ 2014-03-04 19:48 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johan Herland, Josh Triplett, Thomas Rast, Michael Haggerty,
Dan Carpenter, Greg Kroah-Hartman, Jeff King, Eric Sunshine
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
t/t7513-interpret-trailers.sh | 47 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh
index 3223b12..0badd0e 100755
--- a/t/t7513-interpret-trailers.sh
+++ b/t/t7513-interpret-trailers.sh
@@ -211,4 +211,51 @@ test_expect_success 'using "ifMissing = doNothing"' '
test_cmp expected actual
'
+test_expect_success 'with simple command' '
+ git config trailer.sign.key "Signed-off-by: " &&
+ git config trailer.sign.where "after" &&
+ git config trailer.sign.ifExists "addIfDifferentNeighbor" &&
+ git config trailer.sign.command "echo \"A U Thor <author@example.com>\"" &&
+ cat complex_message_body >expected &&
+ printf "Fixes: \nAcked-by= \nReviewed-by: \nSigned-off-by: \nSigned-off-by: A U Thor <author@example.com>\n" >>expected &&
+ git interpret-trailers "review:" "fix=22" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with command using commiter information' '
+ git config trailer.sign.ifExists "addIfDifferent" &&
+ git config trailer.sign.command "echo \"\$GIT_COMMITTER_NAME <\$GIT_COMMITTER_EMAIL>\"" &&
+ cat complex_message_body >expected &&
+ printf "Fixes: \nAcked-by= \nReviewed-by: \nSigned-off-by: \nSigned-off-by: C O Mitter <committer@example.com>\n" >>expected &&
+ git interpret-trailers "review:" "fix=22" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with command using author information' '
+ git config trailer.sign.key "Signed-off-by: " &&
+ git config trailer.sign.where "after" &&
+ git config trailer.sign.ifExists "addIfDifferentNeighbor" &&
+ git config trailer.sign.command "echo \"\$GIT_AUTHOR_NAME <\$GIT_AUTHOR_EMAIL>\"" &&
+ cat complex_message_body >expected &&
+ printf "Fixes: \nAcked-by= \nReviewed-by: \nSigned-off-by: \nSigned-off-by: A U Thor <author@example.com>\n" >>expected &&
+ git interpret-trailers "review:" "fix=22" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'setup a commit' '
+ echo "Content of the first commit." > a.txt &&
+ git add a.txt &&
+ git commit -m "Add file a.txt"
+'
+
+test_expect_success 'with command using $ARG' '
+ git config trailer.fix.ifExists "overwrite" &&
+ git config trailer.fix.command "git log -1 --oneline --format=\"%h (%s)\" --abbrev-commit --abbrev=14 \$ARG" &&
+ FIXED=$(git log -1 --oneline --format="%h (%s)" --abbrev-commit --abbrev=14 HEAD) &&
+ cat complex_message_body >expected &&
+ printf "Fixes: $FIXED\nAcked-by= \nReviewed-by: \nSigned-off-by: \nSigned-off-by: A U Thor <author@example.com>\n" >>expected &&
+ git interpret-trailers "review:" "fix=HEAD" <complex_message >actual &&
+ test_cmp expected actual
+'
+
test_done
--
1.8.5.2.204.gcfe299d.dirty
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v6 11/11] Documentation: add documentation for 'git interpret-trailers'
2014-03-04 19:47 [PATCH v6 00/11] Add interpret-trailers builtin Christian Couder
` (9 preceding siblings ...)
2014-03-04 19:48 ` [PATCH v6 10/11] trailer: add tests for commands in config file Christian Couder
@ 2014-03-04 19:48 ` Christian Couder
2014-03-06 1:18 ` [PATCH v6 00/11] Add interpret-trailers builtin Ramsay Jones
11 siblings, 0 replies; 21+ messages in thread
From: Christian Couder @ 2014-03-04 19:48 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johan Herland, Josh Triplett, Thomas Rast, Michael Haggerty,
Dan Carpenter, Greg Kroah-Hartman, Jeff King, Eric Sunshine
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
Documentation/git-interpret-trailers.txt | 123 +++++++++++++++++++++++++++++++
1 file changed, 123 insertions(+)
create mode 100644 Documentation/git-interpret-trailers.txt
diff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt
new file mode 100644
index 0000000..75ae386
--- /dev/null
+++ b/Documentation/git-interpret-trailers.txt
@@ -0,0 +1,123 @@
+git-interpret-trailers(1)
+=========================
+
+NAME
+----
+git-interpret-trailers - help add stuctured information into commit messages
+
+SYNOPSIS
+--------
+[verse]
+'git interpret-trailers' [--trim-empty] [(<token>[(=|:)<value>])...]
+
+DESCRIPTION
+-----------
+Help add RFC 822-like headers, called 'trailers', at the end of the
+otherwise free-form part of a commit message.
+
+This command is a filter. It reads the standard input for a commit
+message and applies the `token` arguments, if any, to this
+message. The resulting message is emited on the standard output.
+
+Some configuration variables control the way the `token` arguments are
+applied to the message and the way any existing trailer in the message
+is changed. They also make it possible to automatically add some
+trailers.
+
+By default, a 'token=value' or 'token:value' argument will be added
+only if no trailer with the same (token, value) pair is already in the
+message. The 'token' and 'value' parts will be trimmed to remove
+starting and trailing whitespace, and the resulting trimmed 'token'
+and 'value' will appear in the message like this:
+
+------------------------------------------------
+token: value
+------------------------------------------------
+
+By default, if there are already trailers with the same 'token', the
+new trailer will appear just after the last trailer with the same
+'token'. Otherwise it will appear at the end of the message.
+
+Note that 'trailers' do not follow and are not intended to follow many
+rules that are in RFC 822. For example they do not follow the line
+breaking rules, the encoding rules and probably many other rules.
+
+OPTIONS
+-------
+--trim-empty::
+ If the 'value' part of any trailer contains only whitespace,
+ the whole trailer will be removed from the resulting message.
+
+CONFIGURATION VARIABLES
+-----------------------
+
+trailer.<token>.key::
+ This 'key' will be used instead of 'token' in the
+ trailer. After some alphanumeric characters, it can contain
+ some non alphanumeric characters like ':', '=' or '#' that will
+ be used instead of ':' to separate the token from the value in
+ the trailer, though the default ':' is more standard.
+
+trailer.<token>.where::
+ This can be either `after`, which is the default, or
+ `before`. If it is `before`, then a trailer with the specified
+ token, will appear before, instead of after, other trailers
+ with the same token, or otherwise at the beginning, instead of
+ at the end, of all the trailers.
+
+trailer.<token>.ifexist::
+ This option makes it possible to choose what action will be
+ performed when there is already at least one trailer with the
+ same token in the message.
++
+The valid values for this option are: `addIfDifferent` (this is the
+default), `addIfDifferentNeighbor`, `add`, `overwrite` or `doNothing`.
++
+With `addIfDifferent`, a new trailer will be added only if no trailer
+with the same (token, value) pair is already in the message.
++
+With `addIfDifferentNeighbor`, a new trailer will be added only if no
+trailer with the same (token, value) pair is above or below the line
+where the new trailer will be added.
++
+With `add`, a new trailer will be added, even if some trailers with
+the same (token, value) pair are already in the message.
++
+With `overwrite`, the new trailer will overwrite an existing trailer
+with the same token.
++
+With `doNothing`, nothing will be done, that is no new trailer will be
+added if there is already one with the same token in the message.
+
+trailer.<token>.ifmissing::
+ This option makes it possible to choose what action will be
+ performed when there is not yet any trailer with the same
+ token in the message.
++
+The valid values for this option are: `add` (this is the default) and
+`doNothing`.
++
+With `add`, a new trailer will be added.
++
+With `doNothing`, nothing will be done.
+
+trailer.<token>.command::
+ This option can be used to specify a shell command that will
+ be used to automatically add or modify a trailer with the
+ specified 'token'.
++
+When this option is specified, it is like if a special 'token=value'
+argument is added at the end of the command line, where 'value' will
+be given by the standard output of the specified command.
++
+If the command contains the `$ARG` string, this string will be
+replaced with the 'value' part of an existing trailer with the same
+token, if any, before the command is launched.
+
+SEE ALSO
+--------
+linkgit:git-commit[1]
+
+GIT
+---
+Part of the linkgit:git[1] suite
--
1.8.5.2.204.gcfe299d.dirty
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v6 02/11] trailer: process trailers from stdin and arguments
2014-03-04 19:48 ` [PATCH v6 02/11] trailer: process trailers from stdin and arguments Christian Couder
@ 2014-03-05 22:52 ` Junio C Hamano
2014-03-07 6:19 ` Christian Couder
0 siblings, 1 reply; 21+ messages in thread
From: Junio C Hamano @ 2014-03-05 22:52 UTC (permalink / raw)
To: Christian Couder
Cc: git, Johan Herland, Josh Triplett, Thomas Rast, Michael Haggerty,
Dan Carpenter, Greg Kroah-Hartman, Jeff King, Eric Sunshine
Christian Couder <chriscool@tuxfamily.org> writes:
> Implement the logic to process trailers from stdin and arguments.
>
> At the beginning trailers from stdin are in their own in_tok
> doubly linked list, and trailers from arguments are in their own
> arg_tok doubly linked list.
>
> The lists are traversed and when an arg_tok should be "applied",
> it is removed from its list and inserted into the in_tok list.
>
> Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
> ---
Thanks.
This round is marked as the sixth, but I still see quite a many
style issues, which I expect not to see from long timers without
being told. Somewhat disappointing...
> trailer.c | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 197 insertions(+)
>
> diff --git a/trailer.c b/trailer.c
> index db93a63..a0124f2 100644
> --- a/trailer.c
> +++ b/trailer.c
> @@ -47,3 +47,200 @@ static size_t alnum_len(const char *buf, size_t len)
> ...
> + if ((where == WHERE_AFTER ? in_tok->next : in_tok->previous) == arg_tok)
Overlong line that does not have to be.
if ((where == WHERE_AFTER
? in_tok->next : in_tok->previous) == arg_tok)
or something?
> +static void update_last(struct trailer_item **last)
> +{
> + if (*last)
> + while((*last)->next != NULL)
Style. SP between control keyword and the expression.
> + *last = (*last)->next;
> +}
> +
> +static void update_first(struct trailer_item **first)
> +{
> + if (*first)
> + while((*first)->previous != NULL)
Ditto.
> +static void process_trailers_lists(struct trailer_item **in_tok_first,
> ...
> + /* Process input from end to start */
> + for (in_tok = *in_tok_last; in_tok; in_tok = in_tok->previous) {
> + process_input_token(in_tok, arg_tok_first, WHERE_AFTER);
> + }
Needless brace pair.
> + /* Process input from start to end */
> + for (in_tok = *in_tok_first; in_tok; in_tok = in_tok->next) {
> + process_input_token(in_tok, arg_tok_first, WHERE_BEFORE);
> + }
Ditto.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v6 04/11] trailer: process command line trailer arguments
2014-03-04 19:48 ` [PATCH v6 04/11] trailer: process command line trailer arguments Christian Couder
@ 2014-03-05 22:55 ` Junio C Hamano
0 siblings, 0 replies; 21+ messages in thread
From: Junio C Hamano @ 2014-03-05 22:55 UTC (permalink / raw)
To: Christian Couder
Cc: git, Johan Herland, Josh Triplett, Thomas Rast, Michael Haggerty,
Dan Carpenter, Greg Kroah-Hartman, Jeff King, Eric Sunshine
Christian Couder <chriscool@tuxfamily.org> writes:
> diff --git a/trailer.c b/trailer.c
> index 5b8e28b..5d69c00 100644
> --- a/trailer.c
> +++ b/trailer.c
> @@ -378,3 +378,96 @@ static int git_trailer_config(const char *conf_key, const char *value, void *cb)
> ...
> +static struct trailer_item *new_trailer_item(struct trailer_item *conf_item,
> + char* tok, char* val)
Asterisk sticks to the variable, not the type.
> +static struct trailer_item *create_trailer_item(const char *string)
> +{
> ...
> + return new_trailer_item(NULL, strbuf_detach(&tok, NULL), strbuf_detach(&val, NULL));;
Overlong line. Perhaps that helped you to miss the double-semicolon
at the end.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v6 05/11] trailer: parse trailers from stdin
2014-03-04 19:48 ` [PATCH v6 05/11] trailer: parse trailers from stdin Christian Couder
@ 2014-03-05 22:56 ` Junio C Hamano
0 siblings, 0 replies; 21+ messages in thread
From: Junio C Hamano @ 2014-03-05 22:56 UTC (permalink / raw)
To: Christian Couder
Cc: git, Johan Herland, Josh Triplett, Thomas Rast, Michael Haggerty,
Dan Carpenter, Greg Kroah-Hartman, Jeff King, Eric Sunshine
Christian Couder <chriscool@tuxfamily.org> writes:
> diff --git a/trailer.c b/trailer.c
> index 5d69c00..e0e066f 100644
> --- a/trailer.c
> +++ b/trailer.c
> @@ -50,6 +50,13 @@ static size_t alnum_len(const char *buf, size_t len)
> return len;
> }
>
> +static inline int contains_only_spaces(const char *str)
> +{
> + const char *s;
> + for (s = str; *s && isspace(*s); s++);
Have an empty statement on a separate line for readability. I.e.
for (...)
; /* keep skipping */
> @@ -471,3 +478,72 @@ static struct trailer_item *process_command_line_args(int argc, const char **arg
> ...
> +static void process_stdin(struct trailer_item **in_tok_first,
> + struct trailer_item **in_tok_last)
> +{
> ...
> + /* Print non trailer lines as is */
> + for (i = 0; lines[i] && i < start; i++) {
> + printf("%s", lines[i]->buf);
> + }
Needless brace pair.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v6 09/11] trailer: execute command from 'trailer.<name>.command'
2014-03-04 19:48 ` [PATCH v6 09/11] trailer: execute command from 'trailer.<name>.command' Christian Couder
@ 2014-03-05 22:57 ` Junio C Hamano
0 siblings, 0 replies; 21+ messages in thread
From: Junio C Hamano @ 2014-03-05 22:57 UTC (permalink / raw)
To: Christian Couder
Cc: git, Johan Herland, Josh Triplett, Thomas Rast, Michael Haggerty,
Dan Carpenter, Greg Kroah-Hartman, Jeff King, Eric Sunshine
Christian Couder <chriscool@tuxfamily.org> writes:
> diff --git a/trailer.c b/trailer.c
> index ab93c16..67e7baf 100644
> --- a/trailer.c
> +++ b/trailer.c
> @@ -490,12 +544,22 @@ static struct trailer_item *process_command_line_args(int argc, const char **arg
> ...
> + /* Add conf commands that don't use $ARG */
> + for (item = first_conf_item; item; item = item->next) {
> + if (item->conf.command && !item->conf.command_uses_arg)
> + {
Opening brace of a block sits on the same line as the closing
condition of the control. I.e.
if (...) {
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v6 08/11] trailer: add tests for "git interpret-trailers"
2014-03-04 19:48 ` [PATCH v6 08/11] trailer: add tests for "git interpret-trailers" Christian Couder
@ 2014-03-05 22:59 ` Junio C Hamano
0 siblings, 0 replies; 21+ messages in thread
From: Junio C Hamano @ 2014-03-05 22:59 UTC (permalink / raw)
To: Christian Couder
Cc: git, Johan Herland, Josh Triplett, Thomas Rast, Michael Haggerty,
Dan Carpenter, Greg Kroah-Hartman, Jeff King, Eric Sunshine
Christian Couder <chriscool@tuxfamily.org> writes:
> +# We want one trailing space at the end of each line.
> +# Let's use sed to make sure that these spaces are not removed
> +# by any automatic tool.
> +test_expect_success 'setup 3' '
> + sed -e "s/ Z\$/ /" >complex_message_trailers <<-\EOF
> +Fixes: Z
> +Acked-by: Z
> +Reviewed-by: Z
> +Signed-off-by: Z
> +EOF
> +'
It is a bit disappointing to see that these are flushed to the left,
when the here-doc redirection uses "<<-\EOF" (not "<<\EOF") to allow
you to indent, i.e.
sed ... <<-\EOF
foo
bar
EOF
or even more readable:
sed ... <<-\EOF
foo
bar
EOF
no?
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v6 00/11] Add interpret-trailers builtin
2014-03-04 19:47 [PATCH v6 00/11] Add interpret-trailers builtin Christian Couder
` (10 preceding siblings ...)
2014-03-04 19:48 ` [PATCH v6 11/11] Documentation: add documentation for 'git interpret-trailers' Christian Couder
@ 2014-03-06 1:18 ` Ramsay Jones
11 siblings, 0 replies; 21+ messages in thread
From: Ramsay Jones @ 2014-03-06 1:18 UTC (permalink / raw)
To: Christian Couder, Junio C Hamano
Cc: git, Johan Herland, Josh Triplett, Thomas Rast, Michael Haggerty,
Dan Carpenter, Greg Kroah-Hartman, Jeff King, Eric Sunshine
On 04/03/14 19:47, Christian Couder wrote:
> This patch series implements a new command:
>
> git interpret-trailers
>
[snip]
Minor problem: this series causes sparse to complain, thus:
trailer.c:642:6: warning: symbol 'process_trailers' was not \
declared. Should it be static?
The following patch, on top of the 'pu' branch, fixes it:
--- >8 ---
Subject: [PATCH] trailer.c: suppress sparse warning
Check that the public interface, as declared in the trailer.h header
file, is consistent with the actual implementation. Add an #include
of the header file into the implementation file.
Noticed by sparse ("'process_trailers' was not declared. Should it
be static?").
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
---
trailer.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/trailer.c b/trailer.c
index b5de616..95d5874 100644
--- a/trailer.c
+++ b/trailer.c
@@ -1,6 +1,7 @@
#include "cache.h"
#include "run-command.h"
#include "argv-array.h"
+#include "trailer.h"
/*
* Copyright (c) 2013 Christian Couder <chriscool@tuxfamily.org>
*/
--
1.9.0
--- 8< ---
However, for this to work, in addition to squashing the above patch into
your patch #6, you would need to move the creation of the trailer.h header
file from patch 07/11 ("trailer: add interpret-trailers command") to patch
06/11 ("trailer: put all the processing together and print"), where it should
have been anyway! :-D
HTH
ATB,
Ramsay Jones
> Christian Couder (11):
> Add data structures and basic functions for commit trailers
> trailer: process trailers from stdin and arguments
> trailer: read and process config information
> trailer: process command line trailer arguments
> trailer: parse trailers from stdin
> trailer: put all the processing together and print
> trailer: add interpret-trailers command
> trailer: add tests for "git interpret-trailers"
> trailer: execute command from 'trailer.<name>.command'
> trailer: add tests for commands in config file
> Documentation: add documentation for 'git interpret-trailers'
>
> .gitignore | 1 +
> Documentation/git-interpret-trailers.txt | 123 ++++++
> Makefile | 2 +
> builtin.h | 1 +
> builtin/interpret-trailers.c | 33 ++
> git.c | 1 +
> t/t7513-interpret-trailers.sh | 261 ++++++++++++
> trailer.c | 661 +++++++++++++++++++++++++++++++
> trailer.h | 6 +
> 9 files changed, 1089 insertions(+)
> create mode 100644 Documentation/git-interpret-trailers.txt
> create mode 100644 builtin/interpret-trailers.c
> create mode 100755 t/t7513-interpret-trailers.sh
> create mode 100644 trailer.c
> create mode 100644 trailer.h
>
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v6 02/11] trailer: process trailers from stdin and arguments
2014-03-05 22:52 ` Junio C Hamano
@ 2014-03-07 6:19 ` Christian Couder
2014-03-07 8:08 ` Dan Carpenter
0 siblings, 1 reply; 21+ messages in thread
From: Christian Couder @ 2014-03-07 6:19 UTC (permalink / raw)
To: Junio C Hamano
Cc: Christian Couder, git, Johan Herland, Josh Triplett, Thomas Rast,
Michael Haggerty, Dan Carpenter, Greg Kroah-Hartman, Jeff King,
Eric Sunshine
On Wed, Mar 5, 2014 at 11:52 PM, Junio C Hamano <gitster@pobox.com> wrote:
>
> This round is marked as the sixth, but I still see quite a many
> style issues, which I expect not to see from long timers without
> being told. Somewhat disappointing...
Yeah, I don't know why, but these days I find it very hard to review
style issues in my own code without being distracted.
And by the way is there a good script to check them?
Thanks,
Christian.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v6 02/11] trailer: process trailers from stdin and arguments
2014-03-07 6:19 ` Christian Couder
@ 2014-03-07 8:08 ` Dan Carpenter
2014-03-07 12:41 ` Christian Couder
0 siblings, 1 reply; 21+ messages in thread
From: Dan Carpenter @ 2014-03-07 8:08 UTC (permalink / raw)
To: Christian Couder
Cc: Junio C Hamano, Christian Couder, git, Johan Herland,
Josh Triplett, Thomas Rast, Michael Haggerty, Greg Kroah-Hartman,
Jeff King, Eric Sunshine
On Fri, Mar 07, 2014 at 07:19:15AM +0100, Christian Couder wrote:
> On Wed, Mar 5, 2014 at 11:52 PM, Junio C Hamano <gitster@pobox.com> wrote:
> >
> > This round is marked as the sixth, but I still see quite a many
> > style issues, which I expect not to see from long timers without
> > being told. Somewhat disappointing...
>
> Yeah, I don't know why, but these days I find it very hard to review
> style issues in my own code without being distracted.
> And by the way is there a good script to check them?
Many of these would have been caught with kernel.org's checkpatch.pl
script.
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/scripts/checkpatch.pl
regards,
dan carpenter
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v6 02/11] trailer: process trailers from stdin and arguments
2014-03-07 8:08 ` Dan Carpenter
@ 2014-03-07 12:41 ` Christian Couder
0 siblings, 0 replies; 21+ messages in thread
From: Christian Couder @ 2014-03-07 12:41 UTC (permalink / raw)
To: Dan Carpenter
Cc: Junio C Hamano, Christian Couder, git, Johan Herland,
Josh Triplett, Thomas Rast, Michael Haggerty, Greg Kroah-Hartman,
Jeff King, Eric Sunshine
On Fri, Mar 7, 2014 at 9:08 AM, Dan Carpenter <dan.carpenter@oracle.com> wrote:
> On Fri, Mar 07, 2014 at 07:19:15AM +0100, Christian Couder wrote:
>>
>> Yeah, I don't know why, but these days I find it very hard to review
>> style issues in my own code without being distracted.
>> And by the way is there a good script to check them?
>
> Many of these would have been caught with kernel.org's checkpatch.pl
> script.
>
> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/scripts/checkpatch.pl
Yeah, I already thought about using it in the past, but I was not sure
about its status regarding the git source code because it's use is not
suggested in CodingGuidelines, and the discussions about adding it
there went nowhere:
http://thread.gmane.org/gmane.comp.version-control.git/223698/focus=224653
Thanks,
Christian.
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2014-03-07 12:41 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-04 19:47 [PATCH v6 00/11] Add interpret-trailers builtin Christian Couder
2014-03-04 19:47 ` [PATCH v6 01/11] Add data structures and basic functions for commit trailers Christian Couder
2014-03-04 19:48 ` [PATCH v6 02/11] trailer: process trailers from stdin and arguments Christian Couder
2014-03-05 22:52 ` Junio C Hamano
2014-03-07 6:19 ` Christian Couder
2014-03-07 8:08 ` Dan Carpenter
2014-03-07 12:41 ` Christian Couder
2014-03-04 19:48 ` [PATCH v6 03/11] trailer: read and process config information Christian Couder
2014-03-04 19:48 ` [PATCH v6 04/11] trailer: process command line trailer arguments Christian Couder
2014-03-05 22:55 ` Junio C Hamano
2014-03-04 19:48 ` [PATCH v6 05/11] trailer: parse trailers from stdin Christian Couder
2014-03-05 22:56 ` Junio C Hamano
2014-03-04 19:48 ` [PATCH v6 06/11] trailer: put all the processing together and print Christian Couder
2014-03-04 19:48 ` [PATCH v6 07/11] trailer: add interpret-trailers command Christian Couder
2014-03-04 19:48 ` [PATCH v6 08/11] trailer: add tests for "git interpret-trailers" Christian Couder
2014-03-05 22:59 ` Junio C Hamano
2014-03-04 19:48 ` [PATCH v6 09/11] trailer: execute command from 'trailer.<name>.command' Christian Couder
2014-03-05 22:57 ` Junio C Hamano
2014-03-04 19:48 ` [PATCH v6 10/11] trailer: add tests for commands in config file Christian Couder
2014-03-04 19:48 ` [PATCH v6 11/11] Documentation: add documentation for 'git interpret-trailers' Christian Couder
2014-03-06 1:18 ` [PATCH v6 00/11] Add interpret-trailers builtin Ramsay Jones
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).