Re: AW: Understanding behavior of git blame -M
"Sokolov, Konstantin (ext)" writes: > Hi David, > > thank you very much for the exhaustive answer. The keyword "hunk" made > me try a little bit more. So I realized that -M works as expected when > at least three lines are moved. > > From your answer I discern that you find the current behavior > correct. I don't say any such thing and don't imply it. -- David Kastrup -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
You do not have permission to post to the ms...@lists.myitforum.com list
Sorry, you do not have permission to post to the ms...@lists.myitforum.com mailing list. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 2/2] convert: Stream from fd to required clean filter instead of mmap
On Wed, Aug 06, 2014 at 07:32:14AM +0200, Steffen Prohaska wrote: [...] > The expectation on the process size is tested using /usr/bin/time. An > alternative would have been tcsh, which could be used to print memory > information as follows: > > tcsh -c 'set time=(0 "%M"); ' > > Although the logic could perhaps be simplified with tcsh, I chose to use > 'time' to avoid a dependency on tcsh. [...] > @@ -190,6 +196,58 @@ test_expect_success 'required filter clean failure' ' > test_must_fail git add test.fc > ' > > +# Handle differences in /usr/bin/time. > +# > +# - Linux: call with '-v'. > +#output: : > +# > +# - Mac: call with '-l'. > +#output: > +#Strip three digits to get to KB (base 10 is good enough). > +# > +case $(uname -s) in > +Linux) > + test_set_prereq HAVE_MAX_MEM_USAGE > + max_mem_usage_KB () { > + /usr/bin/time -v "$@" 2>&1 | > + grep 'Maximum resident set size' | > + cut -d ':' -f 2 > + } > + ;; > +Darwin) > + test_set_prereq HAVE_MAX_MEM_USAGE > + max_mem_usage_KB () { > + /usr/bin/time -l "$@" 2>&1 | > + grep 'maximum resident set size' | > + sed -e 's/ */ /' | > + cut -d ' ' -f 2 | > + sed -e 's/...$//' > + } > + ;; > +esac > + > +max_mem_usage_is_lt_KB () { > + limit=$1 > + shift > + mem_usage=$(max_mem_usage_KB "$@") > + if [ $mem_usage -lt $limit ]; then > + true > + else > + printf 'Command used too much memory (expected limit %dKB, > actual usage %dKB).\n' \ > + $limit $mem_usage > + false > + fi > +} > + > +test_expect_success HAVE_MAX_MEM_USAGE \ > +'filtering large input to small output should use little memory' ' > + git config filter.devnull.clean "cat >/dev/null" && > + git config filter.devnull.required true && > + for i in $(test_seq 1 30); do printf "%1048576d" 1; done >30MB && > + echo "30MB filter=devnull" >.gitattributes && > + max_mem_usage_is_lt_KB 15000 git add 30MB > +' This test fails for me: -- 8< -- expecting success: git config filter.devnull.clean "cat >/dev/null" && git config filter.devnull.required true && for i in $(test_seq 1 30); do printf "%1048576d" 1; done >30MB && echo "30MB filter=devnull" >.gitattributes && max_mem_usage_is_lt_KB 15000 git add 30MB Command used too much memory (expected limit 15000KB, actual usage 15808KB). not ok 8 - filtering large input to small output should use little memory -- >8 -- This is on Linux 3.16 x86_64 with GCC 4.8.3 and glibc 2.19. My GCC also has "-fstack-protector" and "-D_FORTIFY_SOURCE=2" enabled by default; turning those off for Git decreased the memory usage by about 500KB but not enough to make the test pass. Of course, all of the libraries Git is linking are also compiled with those flags... Is the 15MB limit supposed to be imposed somewhere or is it just a guide of how much memory we expect Git to use in this scenario? -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[GIT PULL] l10n updates for 2.1.0 round 1
I'm sorry this pull request is late for git v2.1.0. I should send it out yesterday night using the network of my new house, but after 2 weeks' business travel and home moving, I'm a bit lazy. And German translation is still under review, so it is not included in this pull request. The following changes since commit 49f1cb93a2f11845cfa2723611a729d3d7f02f0d: Git 2.1.0-rc0 (2014-07-27 15:22:22 -0700) are available in the git repository at: git://github.com/git-l10n/git-po for you to fetch changes up to f7fbc357f863ecc5323f3fcf2fc9cbf2aa2a8587: l10n: fr.po (2257t) update for version 2.1.0 (2014-08-07 09:07:18 +0200) Alexander Shopov (3): l10n: Updated Bulgarian translation of git (2228t,0f,0u) l10n: Updated Bulgarian translation of git (2247t,0f,0u) l10n: Updated Bulgarian translation of git (2257t,0f,0u) Jean-Noel Avila (1): l10n: fr.po (2257t) update for version 2.1.0 Jiang Xin (6): l10n: git.pot: v2.1.0 round 1 (38 new, 9 removed) Merge remote-tracking branch 'sv/nafmo/master' Merge commit 'bg/alshopov/master' l10n: zh_CN: translations for git v2.1.0-rc0 Merge branch 'master' of github.com:alshopov/git-po Merge remote-tracking branch 'l10n/vi/vnwildman/master' Peter Krefting (2): l10n: Fix more typos in the Swedish translations l10n: sv.po: Update Swedish translation (2257t0f0u) Trần Ngọc Quân (1): l10n: vi.po (2257t): Update translation po/bg.po| 5134 +-- po/fr.po| 2871 + po/git.pot | 2804 po/sv.po| 2871 + po/vi.po| 2853 + po/zh_CN.po | 2822 6 files changed, 10320 insertions(+), 9035 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] clean: use f(void) instead of f() to declare a pointer to a function without arguments
Explicitly state that menu_item functions like clean_cmd don't take any arguments by using void instead of an empty parameter list. Found using gcc -Wstrict-prototypes. Signed-off-by: Rene Scharfe --- builtin/clean.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/clean.c b/builtin/clean.c index 1032563..3beeea6 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -67,7 +67,7 @@ struct menu_item { char hotkey; const char *title; int selected; - int (*fn)(); + int (*fn)(void); }; enum menu_stuff_type { -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] read-cache.c: Ensure unmerged entries are removed
I'd like to add some tests too for this, but I don't know how to reproduce this state with git commands only, is there any way to add entries to the index without checkings? Or maybe it could be done by creating a "test-" command that adds the entries to an index? Thanks. On Fri, Aug 15, 2014 at 11:45 PM, Junio C Hamano wrote: > Jaime Soriano Pastor writes: > >> On Thu, Aug 14, 2014 at 1:04 AM, Junio C Hamano wrote: >>> Being a conservative, I'd rather avoid doing any magic during >>> read_cache() time. "ls-files -s" for example should show the four >>> stages so that the "broken" state can be inspected. >>> >> Well, only read_cache_unmerged() is modified in the sent patch, so no >> magic is done in read_cache(), I'd also avoid changes there. > > Ahh, I must have overlooked that; changes being only in _unmerged() > variant makes me feel much better, and it probably would make much > of ... > >>> Yes, it would be more work,... > > ... moot, hopefully ;-) > >> git reset will clean the index anyway if the loop finishes, would it >> be ok? > > Surely. > >> git merge is also affected by the loop in read_cache_unmerged(), but >> any of the solutions would be enough for it as only by finishing the >> loop with unmerged entries it will die without commiting the cache to >> the index file. > > Again, true. The mergy operations want to start from a clean slate > and they call _unmerged() variant primarily to learn that there were > unmerged entries in the index, only to abort the operation in that > case, so a change to _unmerged() variant should be safe for them. > > I'll take another look at your patch later, but not before the 2.1 > final, and by that time you may already have sent a reroll ;-) > > Thanks. -- Jaime Soriano Pastor - Software Developer -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 2/2] convert: Stream from fd to required clean filter instead of mmap
On Aug 16, 2014, at 12:27 PM, John Keeping wrote: >> +test_expect_success HAVE_MAX_MEM_USAGE \ >> +'filtering large input to small output should use little memory' ' >> +git config filter.devnull.clean "cat >/dev/null" && >> +git config filter.devnull.required true && >> +for i in $(test_seq 1 30); do printf "%1048576d" 1; done >30MB && >> +echo "30MB filter=devnull" >.gitattributes && >> +max_mem_usage_is_lt_KB 15000 git add 30MB >> +' > > This test fails for me: > > -- 8< -- > expecting success: >git config filter.devnull.clean "cat >/dev/null" && >git config filter.devnull.required true && >for i in $(test_seq 1 30); do printf "%1048576d" 1; done >30MB && >echo "30MB filter=devnull" >.gitattributes && >max_mem_usage_is_lt_KB 15000 git add 30MB > > Command used too much memory (expected limit 15000KB, actual usage 15808KB). > not ok 8 - filtering large input to small output should use little memory > -- >8 -- > > This is on Linux 3.16 x86_64 with GCC 4.8.3 and glibc 2.19. My GCC also > has "-fstack-protector" and "-D_FORTIFY_SOURCE=2" enabled by default; > turning those off for Git decreased the memory usage by about 500KB but > not enough to make the test pass. Of course, all of the libraries Git > is linking are also compiled with those flags... > > Is the 15MB limit supposed to be imposed somewhere or is it just a guide > of how much memory we expect Git to use in this scenario? The test should confirm that the the file that is added is not mmapped to memory. The process size should be relatively small independently of the size of the file that is added. I wanted to keep the file size small. The chosen sizes worked for me on Mac and Linux. A simple solution could be to increase the size of the test file and the limit. I'd suggest to squash the diff below. The test should still run reasonably fast with a 50 MB test file. Junio, shall I send a whole updated patch series? Steffen diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh index 2cb2414..43de87d 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -243,9 +243,9 @@ test_expect_success HAVE_MAX_MEM_USAGE \ 'filtering large input to small output should use little memory' ' git config filter.devnull.clean "cat >/dev/null" && git config filter.devnull.required true && - for i in $(test_seq 1 30); do printf "%1048576d" 1; done >30MB && - echo "30MB filter=devnull" >.gitattributes && - max_mem_usage_is_lt_KB 15000 git add 30MB + for i in $(test_seq 1 50); do printf "%1048576d" 1; done >50MB && + echo "50MB filter=devnull" >.gitattributes && + max_mem_usage_is_lt_KB 35000 git add 50MB ' -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v13 03/11] trailer: read and process config information
Read the configuration to get trailer information, and then process it and store 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 Signed-off-by: Junio C Hamano --- trailer.c | 185 ++ 1 file changed, 185 insertions(+) diff --git a/trailer.c b/trailer.c index 4940e06..2d391f3 100644 --- a/trailer.c +++ b/trailer.c @@ -272,3 +272,188 @@ static void process_trailers_lists(struct trailer_item **in_tok_first, 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 if (!strcasecmp("end", value)) + item->where = WHERE_END; + else if (!strcasecmp("start", value)) + item->where = WHERE_START; + 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("replace", value)) + item->if_exists = EXISTS_REPLACE; + 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; +} + +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 *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); + duplicate_conf(&item->conf, &default_conf_info); + item->conf.name = xstrdup(name); + + if (!previous) + first_conf_item = item; + else { + previous->next = item; + item->previous = previous; + } + + return item; +} + +enum trailer_info_type { TRAILER_KEY, TRAILER_COMMAND, TRAILER_WHERE, +TRAILER_IF_EXISTS, TRAILER_IF_MISSING }; + +static struct { + const char *name; + enum trailer_info_type type; +} trailer_config_items[] = { + { "key", TRAILER_KEY }, + { "command", TRAILER_COMMAND }, + { "where", TRAILER_WHERE }, + { "ifexists", TRAILER_IF_EXISTS }, + { "ifmissing", TRAILER_IF_MISSING } +}; + +static int git_trailer_default_config(const char *conf_key, const char *value, void *cb) +{ + const char *trailer_item, *variable_name; + + if (!skip_prefix(conf_key, "trailer.", &trailer_item)) + return 0; + + variable_name = strrchr(trailer_item, '.'); + if (!variable_name) { + if (!strcmp(trailer_item, "where")) { + if (set_where(&default_conf_info, value) < 0) + warning(_("unknown value '%s' for key '%s'"), + value, conf_key); + } else if (!strcmp(trailer_item, "ifexists")) { + if (set_if_exists(&default_conf_info, value) < 0) + warning(_("unknown value '%s' for key '%s'"), + value, conf_key); + } else if (!strcmp(trailer_item, "ifmissing")) { + if (set_if_missing(&default_conf_info, value) < 0) + warning(_("unknown value '%s' for key '%s'"), + value, conf_key); + } else if (!strcmp(trailer_item, "separators")) { + separators = xstrdup(value); +
[PATCH v13 05/11] trailer: parse trailers from file or stdin
Read trailers from a file or from stdin, parse the trailers and then put the result into a doubly linked list. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- trailer.c | 123 ++ 1 file changed, 123 insertions(+) diff --git a/trailer.c b/trailer.c index b9d3ed4..46e2fcb 100644 --- a/trailer.c +++ b/trailer.c @@ -64,6 +64,14 @@ static int same_trailer(struct trailer_item *a, struct trailer_item *b) return same_token(a, b) && same_value(a, b); } +static inline int contains_only_spaces(const char *str) +{ + const char *s = str; + while (*s && isspace(*s)) + s++; + return !*s; +} + static void free_trailer_item(struct trailer_item *item) { free(item->conf.name); @@ -582,3 +590,118 @@ static struct trailer_item *process_command_line_args(struct string_list *traile return arg_tok_first; } + +static struct strbuf **read_input_file(const char *file) +{ + struct strbuf **lines; + struct strbuf sb = STRBUF_INIT; + + if (file) { + if (strbuf_read_file(&sb, file, 0) < 0) + die_errno(_("could not read input file '%s'"), file); + } else { + 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 (0 based) index of the start of the patch or the line + * count if there is no patch in the message. + */ +static int find_patch_start(struct strbuf **lines, int count) +{ + int i; + + /* Get the start of the patch part if any */ + for (i = 0; i < count; i++) { + if (starts_with(lines[i]->buf, "---")) + return i; + } + + return count; +} + +/* + * Return the (0 based) index of the first trailer line or count if + * there are no trailers. Trailers are searched only in the lines from + * index (count - 1) down to index 0. + */ +static int find_trailer_start(struct strbuf **lines, int count) +{ + int start, only_spaces = 1; + + /* +* Get the start of the trailers by looking starting from the end +* for a line with only spaces before lines with one separator. +*/ + for (start = count - 1; start >= 0; start--) { + if (lines[start]->buf[0] == comment_line_char) + continue; + if (contains_only_spaces(lines[start]->buf)) { + if (only_spaces) + continue; + return start + 1; + } + if (strcspn(lines[start]->buf, separators) < lines[start]->len) { + if (only_spaces) + only_spaces = 0; + continue; + } + return count; + } + + return only_spaces ? count : 0; +} + +static int has_blank_line_before(struct strbuf **lines, int start) +{ + for (;start >= 0; start--) { + if (lines[start]->buf[0] == comment_line_char) + continue; + return contains_only_spaces(lines[start]->buf); + } + return 0; +} + +static void print_lines(struct strbuf **lines, int start, int end) +{ + int i; + for (i = start; lines[i] && i < end; i++) + printf("%s", lines[i]->buf); +} + +static int process_input_file(struct strbuf **lines, + struct trailer_item **in_tok_first, + struct trailer_item **in_tok_last) +{ + int count = 0; + int patch_start, trailer_start, i; + + /* Get the line count */ + while (lines[count]) + count++; + + patch_start = find_patch_start(lines, count); + trailer_start = find_trailer_start(lines, patch_start); + + /* Print lines before the trailers as is */ + print_lines(lines, 0, trailer_start); + + if (!has_blank_line_before(lines, trailer_start - 1)) + printf("\n"); + + /* Parse trailer lines */ + for (i = trailer_start; i < patch_start; i++) { + struct trailer_item *new = create_trailer_item(lines[i]->buf); + add_trailer_item(in_tok_first, in_tok_last, new); + } + + return patch_start; +} -- 2.0.1.674.ga7f57b7 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v13 00/11] Add interpret-trailers builtin
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 keep builtin/commit.c uncontaminated by any more hard-wired logic, like what we have for the signed-off-by line. Any new things can and should be doable in hooks, and this filter would help writing these hooks. And that is why the design goal of the filter is to make it at least as powerful as the built-in logic we have for signed-off-by lines; that would allow us to later eject the hard-wired logic for signed-off-by line from the main codepath, if/when we wanted to. Alternatively, we could build a library-ish API around this filter code and replace the hard-wired logic for signed-off-by line with a call into that API, if/when we wanted to, but that requires (in addition to the "at least as powerful as the built-in logic") that the implementation of this stand-alone filter can be cleanly made into a reusable library, so that is a bit higher bar to cross than "everything can be doable with hooks" alternative. 2) Current state: Currently the usage string of this command is: git interpret-trailers [--trim-empty] [(--trailer [(=|:)])...] [...] The following features are implemented: - the result is printed on stdout - the --trailer arguments are interpreted - messages read from ... or stdin are interpreted - the "trailer.separators" option in the config is interpreted (new) - the "trailer.where" option is interpreted (new) - the "trailer.ifexists" option is interpreted (new) - the "trailer.ifmissing" option is interpreted (new) - the "trailer..key" options are interpreted - the "trailer..where" options are interpreted - the "trailer..ifexist" options are interpreted - the "trailer..ifmissing" options are interpreted - the "trailer..command" config works - $ARG can be used in commands - messages can contain a patch - lines in messages starting with a comment char are ignored - there are 49 tests - there is some documentation - there are examples in the documentation 3) Changes since version 12, thanks to Jakub, Michael, Johan and Junio: * "end" and "start" values for "trailer..where" have been implemented * "end" has been made the default value for "where", but this default value can be changed using the new "trailer.where" config variable * "addIfDifferentNeighbor" is now the default value for "ifexists", but this default can be changed using the new "trailer.ifexists" config variable * the new "trailer.ifmissing" can be used to change the default value for "ifmissing" (which is "add") * by default the only separator is ':', this can be changed by using the new "trailer.separators" config variable * only the configured separators (or just ':' by default) are used for both input parsing and output printing; the only exception is that '=' is always accepted as separator when parsing "--trailer ''" command line arguments, for compatibility with other git commands * 14 tests have been added Only patches 7/11, 9/11 and 10/11 have not been changed since v12. Christian Couder (11): trailer: add data structures and basic functions trailer: process trailers from input message and arguments trailer: read and process config information trailer: process command line trailer arguments trailer: parse trailers from file or 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..command' trailer: add tests for commands in config file Documentation: add documentation for 'git interpret-trailers' .gitignore | 1 + Documentation/git-interpret-trailers.txt | 308 +++ Makefile | 2 + builtin.h| 1 + builtin/interpret-trailers.c | 44 ++ command-list.txt | 1 + git.c| 1 + t/t7513-interpret-trailers.sh| 850 +++ trailer.c| 830 ++ trailer.h
[PATCH v13 04/11] trailer: process command line trailer arguments
Parse the trailer command line arguments and put the result into an arg_tok doubly linked list. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- trailer.c | 125 ++ 1 file changed, 125 insertions(+) diff --git a/trailer.c b/trailer.c index 2d391f3..b9d3ed4 100644 --- a/trailer.c +++ b/trailer.c @@ -1,4 +1,5 @@ #include "cache.h" +#include "string-list.h" /* * Copyright (c) 2013, 2014 Christian Couder */ @@ -457,3 +458,127 @@ static int git_trailer_config(const char *conf_key, const char *value, void *cb) } return 0; } + +static int parse_trailer(struct strbuf *tok, struct strbuf *val, const char *trailer) +{ + size_t len; + struct strbuf seps = STRBUF_INIT; + strbuf_addstr(&seps, separators); + strbuf_addch(&seps, '='); + len = strcspn(trailer, seps.buf); + strbuf_release(&seps); + if (len == 0) + return error(_("empty trailer token in trailer '%s'"), 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); + } + return 0; +} + + +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 const char *token_from_item(struct trailer_item *item) +{ + if (item->conf.key) + return item->conf.key; + + return item->conf.name; +} + +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(token_from_item(conf_item)); + free(tok); + } else { + duplicate_conf(&new->conf, &default_conf_info); + new->token = tok; + } + + return new; +} + +static int token_matches_item(const char *tok, struct trailer_item *item, int alnum_len) +{ + if (!strncasecmp(tok, item->conf.name, alnum_len)) + return 1; + return item->conf.key ? !strncasecmp(tok, item->conf.key, alnum_len) : 0; +} + +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; + + if (parse_trailer(&tok, &val, string)) + return NULL; + + 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 (token_matches_item(tok.buf, item, 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 (!new) + return; + if (!*last) { + *first = new; + *last = new; + } else { + (*last)->next = new; + new->previous = *last; + *last = new; + } +} + +static struct trailer_item *process_command_line_args(struct string_list *trailers) +{ + struct trailer_item *arg_tok_first = NULL; + struct trailer_item *arg_tok_last = NULL; + struct string_list_item *tr; + + for_each_string_list_item(tr, trailers) { + struct trailer_item *new = create_trailer_item(tr->string); + add_trailer_item(&arg_tok_first, &arg_tok_last, new); + } + + return arg_tok_first; +} -- 2.0.1.674.ga7f57b7 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v13 01/11] trailer: add data structures and basic functions
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 Signed-off-by: Junio C Hamano --- Makefile | 1 + trailer.c | 64 +++ 2 files changed, 65 insertions(+) create mode 100644 trailer.c diff --git a/Makefile b/Makefile index 63a210d..ef82972 100644 --- a/Makefile +++ b/Makefile @@ -888,6 +888,7 @@ LIB_OBJS += submodule-config.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 000..2adc1b7 --- /dev/null +++ b/trailer.c @@ -0,0 +1,64 @@ +#include "cache.h" +/* + * Copyright (c) 2013, 2014 Christian Couder + */ + +enum action_where { WHERE_END, WHERE_AFTER, WHERE_BEFORE, WHERE_START }; +enum action_if_exists { EXISTS_ADD_IF_DIFFERENT_NEIGHBOR, EXISTS_ADD_IF_DIFFERENT, + EXISTS_ADD, EXISTS_REPLACE, 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; +}; + +static struct conf_info default_conf_info; + +struct trailer_item { + struct trailer_item *previous; + struct trailer_item *next; + const char *token; + const char *value; + struct conf_info conf; +}; + +static struct trailer_item *first_conf_item; + +static char *separators = ":"; + +static int after_or_end(enum action_where where) +{ + return (where == WHERE_AFTER) || (where == WHERE_END); +} + +/* 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; +} + +static int same_token(struct trailer_item *a, struct trailer_item *b) +{ + size_t a_alnum_len = alnum_len(a->token, strlen(a->token)); + size_t b_alnum_len = alnum_len(b->token, strlen(b->token)); + size_t min_alnum_len = (a_alnum_len > b_alnum_len) ? b_alnum_len : a_alnum_len; + + return !strncasecmp(a->token, b->token, min_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) +{ + return same_token(a, b) && same_value(a, b); +} -- 2.0.1.674.ga7f57b7 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v13 02/11] trailer: process trailers from input message and arguments
Implement the logic to process trailers from the input message and from arguments. At the beginning trailers from the input message 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 Signed-off-by: Junio C Hamano --- trailer.c | 210 ++ 1 file changed, 210 insertions(+) diff --git a/trailer.c b/trailer.c index 2adc1b7..4940e06 100644 --- a/trailer.c +++ b/trailer.c @@ -62,3 +62,213 @@ static int same_trailer(struct trailer_item *a, struct trailer_item *b) { return same_token(a, b) && same_value(a, b); } + +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 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 add_arg_to_input_list(struct trailer_item *on_tok, + struct trailer_item *arg_tok, + struct trailer_item **first, + struct trailer_item **last) +{ + if (after_or_end(arg_tok->conf.where)) { + arg_tok->next = on_tok->next; + on_tok->next = arg_tok; + arg_tok->previous = on_tok; + if (arg_tok->next) + arg_tok->next->previous = arg_tok; + update_last(last); + } else { + arg_tok->previous = on_tok->previous; + on_tok->previous = arg_tok; + arg_tok->next = on_tok; + if (arg_tok->previous) + arg_tok->previous->next = arg_tok; + update_first(first); + } +} + +static int check_if_different(struct trailer_item *in_tok, + struct trailer_item *arg_tok, + int check_all) +{ + enum action_where where = arg_tok->conf.where; + do { + if (!in_tok) + return 1; + if (same_trailer(in_tok, arg_tok)) + return 0; + /* +* if we want to add a trailer after another one, +* we have to check those before this one +*/ + in_tok = after_or_end(where) ? in_tok->previous : in_tok->next; + } while (check_all); + return 1; +} + +static void remove_from_list(struct trailer_item *item, +struct trailer_item **first, +struct trailer_item **last) +{ + struct trailer_item *next = item->next; + struct trailer_item *previous = item->previous; + + if (next) { + item->next->previous = previous; + item->next = NULL; + } else if (last) + *last = previous; + + if (previous) { + item->previous->next = next; + item->previous = NULL; + } else if (first) + *first = 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 apply_arg_if_exists(struct trailer_item *in_tok, + struct trailer_item *arg_tok, + struct trailer_item *on_tok, + struct trailer_item **in_tok_first, + struct trailer_item **in_tok_last) +{ + switch (arg_tok->conf.if_exists) { + case EXISTS_DO_NOTHING: + free_trailer_item(arg_tok); + break; + case EXISTS_REPLACE: + add_arg_to_input_list(on_tok, arg_tok, + in_tok_first, in_tok_last); + remove_from_list(in_tok, in_tok_first, in_tok_last); + free_trailer_item(in_tok); + break; + case EXISTS_ADD: + add_arg_to_input_list(on_tok, arg_tok, + in_tok_first, in_tok_last); + break; + case EXISTS_ADD_IF_DIFFERENT: + if (check_if_different(in_tok, arg_tok, 1)) + add_arg_to_input_list(on_tok, arg_tok, +
[PATCH v13 06/11] trailer: put all the processing together and print
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 Signed-off-by: Junio C Hamano --- trailer.c | 81 +-- trailer.h | 6 + 2 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 trailer.h diff --git a/trailer.c b/trailer.c index 46e2fcb..8e41b8f 100644 --- a/trailer.c +++ b/trailer.c @@ -1,5 +1,6 @@ #include "cache.h" #include "string-list.h" +#include "trailer.h" /* * Copyright (c) 2013, 2014 Christian Couder */ @@ -82,6 +83,35 @@ static void free_trailer_item(struct trailer_item *item) free(item); } +static char last_non_space_char(const char *s) +{ + int i; + for (i = strlen(s) - 1; i >= 0; i--) + if (!isspace(s[i])) + return s[i]; + return '\0'; +} + +static void print_tok_val(const char *tok, const char *val) +{ + char c = last_non_space_char(tok); + if (!c) + return; + if (strchr(separators, c)) + printf("%s%s\n", tok, val); + else + printf("%s%c %s\n", tok, separators[0], 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 update_last(struct trailer_item **last) { if (*last) @@ -489,18 +519,6 @@ static int parse_trailer(struct strbuf *tok, struct strbuf *val, const char *tra return 0; } - -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 const char *token_from_item(struct trailer_item *item) { if (item->conf.key) @@ -705,3 +723,42 @@ static int process_input_file(struct strbuf **lines, return patch_start; } + +static void free_all(struct trailer_item **first) +{ + while (*first) { + struct trailer_item *item = remove_first(first); + free_trailer_item(item); + } +} + +void process_trailers(const char *file, int trim_empty, struct string_list *trailers) +{ + struct trailer_item *in_tok_first = NULL; + struct trailer_item *in_tok_last = NULL; + struct trailer_item *arg_tok_first; + struct strbuf **lines; + int patch_start; + + /* Default config must be setup first */ + git_config(git_trailer_default_config, NULL); + git_config(git_trailer_config, NULL); + + lines = read_input_file(file); + + /* Print the lines before the trailers */ + patch_start = process_input_file(lines, &in_tok_first, &in_tok_last); + + arg_tok_first = process_command_line_args(trailers); + + process_trailers_lists(&in_tok_first, &in_tok_last, &arg_tok_first); + + print_all(in_tok_first, trim_empty); + + free_all(&in_tok_first); + + /* Print the lines after the trailers as is */ + print_lines(lines, patch_start, INT_MAX); + + strbuf_list_free(lines); +} diff --git a/trailer.h b/trailer.h new file mode 100644 index 000..8eb25d5 --- /dev/null +++ b/trailer.h @@ -0,0 +1,6 @@ +#ifndef TRAILER_H +#define TRAILER_H + +void process_trailers(const char *file, int trim_empty, struct string_list *trailers); + +#endif /* TRAILER_H */ -- 2.0.1.674.ga7f57b7 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v13 08/11] trailer: add tests for "git interpret-trailers"
Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- t/t7513-interpret-trailers.sh | 726 ++ 1 file changed, 726 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 000..fa37565 --- /dev/null +++ b/t/t7513-interpret-trailers.sh @@ -0,0 +1,726 @@ +#!/bin/sh +# +# Copyright (c) 2013, 2014 Christian Couder +# + +test_description='git interpret-trailers' + +. ./test-lib.sh + +# When 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' ' + : >empty && + cat >basic_message <<-\EOF && + subject + + body + EOF + cat >complex_message_body <<-\EOF && + my subject + + my body which is long + and contains some special + chars like : = ? ! + + EOF + sed -e "s/ Z\$/ /" >complex_message_trailers <<-\EOF && + Fixes: Z + Acked-by: Z + Reviewed-by: Z + Signed-off-by: Z + EOF + cat >basic_patch <<-\EOF + --- +foo.txt | 2 +- +1 file changed, 1 insertion(+), 1 deletion(-) + + diff --git a/foo.txt b/foo.txt + index 0353767..1d91aa1 100644 + --- a/foo.txt + +++ b/foo.txt + @@ -1,3 +1,3 @@ + + -bar + +baz + + -- + 1.9.rc0.11.ga562ddc + + EOF +' + +test_expect_success 'without config' ' + sed -e "s/ Z\$/ /" >expected <<-\EOF && + + ack: Peff + Reviewed-by: Z + Acked-by: Johan + EOF + git interpret-trailers --trailer "ack = Peff" --trailer "Reviewed-by" \ + --trailer "Acked-by: Johan" empty >actual && + test_cmp expected actual +' + +test_expect_success 'without config in another order' ' + sed -e "s/ Z\$/ /" >expected <<-\EOF && + + Acked-by: Johan + Reviewed-by: Z + ack: Peff + EOF + git interpret-trailers --trailer "Acked-by: Johan" --trailer "Reviewed-by" \ + --trailer "ack = Peff" empty >actual && + test_cmp expected actual +' + +test_expect_success '--trim-empty without config' ' + cat >expected <<-\EOF && + + ack: Peff + Acked-by: Johan + EOF + git interpret-trailers --trim-empty --trailer ack=Peff \ + --trailer "Reviewed-by" --trailer "Acked-by: Johan" \ + --trailer "sob:" empty >actual && + test_cmp expected actual +' + +test_expect_success 'with config setup' ' + git config trailer.ack.key "Acked-by: " && + cat >expected <<-\EOF && + + Acked-by: Peff + EOF + git interpret-trailers --trim-empty --trailer "ack = Peff" empty >actual && + test_cmp expected actual && + git interpret-trailers --trim-empty --trailer "Acked-by = Peff" empty >actual && + test_cmp expected actual && + git interpret-trailers --trim-empty --trailer "Acked-by :Peff" empty >actual && + test_cmp expected actual +' + +test_expect_success 'with config setup and ":=" as separators' ' + git config trailer.separators ":=" && + git config trailer.ack.key "Acked-by= " && + cat >expected <<-\EOF && + + Acked-by= Peff + EOF + git interpret-trailers --trim-empty --trailer "ack = Peff" empty >actual && + test_cmp expected actual && + git interpret-trailers --trim-empty --trailer "Acked-by= Peff" empty >actual && + test_cmp expected actual && + git interpret-trailers --trim-empty --trailer "Acked-by : Peff" empty >actual && + test_cmp expected actual +' + +test_expect_success 'with config setup and "%" as separators' ' + git config trailer.separators "%" && + cat >expected <<-\EOF && + + bug% 42 + count% 10 + bug% 422 + EOF + git interpret-trailers --trim-empty --trailer "bug = 42" \ + --trailer count%10 --trailer "test: stuff" \ + --trailer "bug % 422" empty >actual && + test_cmp expected actual +' + +test_expect_success 'with "%" as separators and a message with trailers' ' + cat >special_message <<-\EOF && + Special Message + + bug% 42 + count% 10 + bug% 422 + EOF + cat >expected <<-\EOF && + Special Message + + bug% 42 + count% 10 + bug% 422 + count% 100 + EOF + git interpret-trailers --trailer count%100 \ + special_message >actual && + test_cmp expected actual +'
[PATCH v13 10/11] trailer: add tests for commands in config file
And add a few other tests for some special cases. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- t/t7513-interpret-trailers.sh | 124 ++ 1 file changed, 124 insertions(+) diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh index fa37565..562c00a 100755 --- a/t/t7513-interpret-trailers.sh +++ b/t/t7513-interpret-trailers.sh @@ -723,4 +723,128 @@ test_expect_success 'default "where" is now "after"' ' 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 \"" && + cat complex_message_body >expected && + sed -e "s/ Z\$/ /" >>expected <<-\EOF && + Fixes: Z + Acked-by= Z + Reviewed-by: + Signed-off-by: Z + Signed-off-by: A U Thor + EOF + git interpret-trailers --trailer "review:" --trailer "fix=22" \ + 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 && + sed -e "s/ Z\$/ /" >>expected <<-\EOF && + Fixes: Z + Acked-by= Z + Reviewed-by: + Signed-off-by: Z + Signed-off-by: C O Mitter + EOF + git interpret-trailers --trailer "review:" --trailer "fix=22" \ + 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 && + sed -e "s/ Z\$/ /" >>expected <<-\EOF && + Fixes: Z + Acked-by= Z + Reviewed-by: + Signed-off-by: Z + Signed-off-by: A U Thor + EOF + git interpret-trailers --trailer "review:" --trailer "fix=22" \ + 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 && + sed -e "s/ Z\$/ /" >>expected <<-EOF && + Fixes: $FIXED + Acked-by= Z + Reviewed-by: + Signed-off-by: Z + Signed-off-by: A U Thor + EOF + git interpret-trailers --trailer "review:" --trailer "fix=HEAD" \ + actual && + test_cmp expected actual +' + +test_expect_success 'with failing command using $ARG' ' + git config trailer.fix.ifExists "overwrite" && + git config trailer.fix.command "false \$ARG" && + cat complex_message_body >expected && + sed -e "s/ Z\$/ /" >>expected <<-EOF && + Fixes: Z + Acked-by= Z + Reviewed-by: + Signed-off-by: Z + Signed-off-by: A U Thor + EOF + git interpret-trailers --trailer "review:" --trailer "fix=HEAD" \ + actual && + test_cmp expected actual +' + +test_expect_success 'with empty tokens' ' + cat >expected <<-EOF && + + Signed-off-by: A U Thor + EOF + git interpret-trailers --trailer ":" --trailer ":test" >actual <<-EOF && + EOF + test_cmp expected actual +' + +test_expect_success 'with command but no key' ' + git config --unset trailer.sign.key && + cat >expected <<-EOF && + + sign: A U Thor + EOF + git interpret-trailers >actual <<-EOF && + EOF + test_cmp expected actual +' + +test_expect_success 'with no command and no key' ' + git config --unset trailer.review.key && + cat >expected <<-EOF && + + review: Junio + sign: A U Thor + EOF + git interpret-trailers --trailer "review:Junio" >actual <<-EOF && + EOF + test_cmp expected actual +' + test_done -- 2.0.1.674.ga7f57b7 -- To unsubscribe from this list: send the line "unsubscribe git" in th
[PATCH v13 11/11] Documentation: add documentation for 'git interpret-trailers'
While at it add git-interpret-trailers to "command-list.txt". Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- Documentation/git-interpret-trailers.txt | 308 +++ command-list.txt | 1 + 2 files changed, 309 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 000..cf5b194 --- /dev/null +++ b/Documentation/git-interpret-trailers.txt @@ -0,0 +1,308 @@ +git-interpret-trailers(1) += + +NAME + +git-interpret-trailers - help add stuctured information into commit messages + +SYNOPSIS + +[verse] +'git interpret-trailers' [--trim-empty] [(--trailer [(=|:)])...] [...] + +DESCRIPTION +--- +Help adding 'trailers' lines, that look similar to RFC 822 e-mail +headers, at the end of the otherwise free-form part of a commit +message. + +This command reads some patches or commit messages from either the + arguments or the standard input if no is specified. Then +this command applies the arguments passed using the `--trailer` +option, if any, to the commit message part of each input file. The +result is emitted on the standard output. + +Some configuration variables control the way the `--trailer` arguments +are applied to each commit message and the way any existing trailer in +the commit message is changed. They also make it possible to +automatically add some trailers. + +By default, a '=' or ':' argument given +using `--trailer` will be appended after the existing trailers only if +the last trailer has a different (, ) pair (or if there +is no existing trailer). The and parts will be trimmed +to remove starting and trailing whitespace, and the resulting trimmed + and will appear in the message like this: + + +token: value + + +This means that the trimmed and will be separated by +`': '` (one colon followed by one space). + +By default the new trailer will appear at the end of all the existing +trailers. If there is no existing trailer, the new trailer will appear +after the commit message part of the ouput, and, if there is no line +with only spaces at the end of the commit message part, one blank line +will be added before the new trailer. + +The trailers are recognized in the input message using the following +rules: + +* by default only lines that contains a ':' (colon) are considered + trailers, + +* the trailer lines must all be next to each other, + +* after them it's only possible to have some lines that contain only + spaces, and then a patch; the patch part is recognized using the + fact that its first line starts with '---' (three minus signs), + +* before them there must be at least one line with only spaces. + +Note that 'trailers' do not follow and are not intended to follow many +rules for RFC 822 headers. For example they do not follow the line +folding rules, the encoding rules and probably many other rules. + +OPTIONS +--- +--trim-empty:: + If the part of any trailer contains only whitespace, + the whole trailer will be removed from the resulting message. + This apply to existing trailers as well as new trailers. + +--trailer [(=|:)]:: + Specify a (, ) pair that should be applied as a + trailer to the input messages. See the description of this + command. + +CONFIGURATION VARIABLES +--- + +trailer.separators:: + This option tells which characters are recognized as trailer + separators. By default only ':' is recognized as a trailer + separator, except that '=' is always accepted on the command + line for compatibility with other git commands. ++ +The first character given by this option will be the default character +used when another separator is not specified in the config for this +trailer. ++ +For example, if the value for this option is "%=$", then only lines +using the format '' with containing '%', '=' +or '$' and then spaces will be considered trailers. And '%' will be +the default separator used, so by default trailers will appear like: +'% ' (one percent sign and one space will appear between +the token and the value). + +trailer.where:: + This option tells where a new trailer will be added. ++ +This can be `end`, which is the default, `start`, `after` or `before`. ++ +If it is `end`, then each new trailer will appear at the end of the +existing trailers. ++ +If it is `start`, then each new trailer will appear at the start, +instead of the end, of the existing trailers. ++ +If it is `after`, then each new trailer will appear just after the +last trailer with the same . ++ +If it is `before`, then each new trailer will appear just before the +last trailer with the same . + +trailer.ifexists:: + This option makes it possible to c
[PATCH v13 07/11] trailer: add interpret-trailers command
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 Signed-off-by: Junio C Hamano --- .gitignore | 1 + Makefile | 1 + builtin.h| 1 + builtin/interpret-trailers.c | 44 git.c| 1 + 5 files changed, 48 insertions(+) create mode 100644 builtin/interpret-trailers.c diff --git a/.gitignore b/.gitignore index cf0d191..85593de 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 ef82972..0b06ae0 100644 --- a/Makefile +++ b/Makefile @@ -953,6 +953,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 5d91f31..b87df70 100644 --- a/builtin.h +++ b/builtin.h @@ -73,6 +73,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 000..46838d2 --- /dev/null +++ b/builtin/interpret-trailers.c @@ -0,0 +1,44 @@ +/* + * Builtin "git interpret-trailers" + * + * Copyright (c) 2013, 2014 Christian Couder + * + */ + +#include "cache.h" +#include "builtin.h" +#include "parse-options.h" +#include "string-list.h" +#include "trailer.h" + +static const char * const git_interpret_trailers_usage[] = { + N_("git interpret-trailers [--trim-empty] [(--trailer [(=|:)])...] [...]"), + NULL +}; + +int cmd_interpret_trailers(int argc, const char **argv, const char *prefix) +{ + int trim_empty = 0; + struct string_list trailers = STRING_LIST_INIT_DUP; + + struct option options[] = { + OPT_BOOL(0, "trim-empty", &trim_empty, N_("trim empty trailers")), + OPT_STRING_LIST(0, "trailer", &trailers, N_("trailer"), + N_("trailer(s) to add")), + OPT_END() + }; + + argc = parse_options(argc, argv, prefix, options, +git_interpret_trailers_usage, 0); + + if (argc) { + int i; + for (i = 0; i < argc; i++) + process_trailers(argv[i], trim_empty, &trailers); + } else + process_trailers(NULL, trim_empty, &trailers); + + string_list_clear(&trailers, 0); + + return 0; +} diff --git a/git.c b/git.c index 5ebb32f..e327a90 100644 --- a/git.c +++ b/git.c @@ -417,6 +417,7 @@ static struct cmd_struct commands[] = { { "index-pack", cmd_index_pack, RUN_SETUP_GENTLY }, { "init", cmd_init_db, NO_SETUP }, { "init-db", cmd_init_db, NO_SETUP }, + { "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 }, -- 2.0.1.674.ga7f57b7 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v13 09/11] trailer: execute command from 'trailer..command'
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 Signed-off-by: Junio C Hamano --- trailer.c | 66 +++ 1 file changed, 66 insertions(+) diff --git a/trailer.c b/trailer.c index 8e41b8f..baef034 100644 --- a/trailer.c +++ b/trailer.c @@ -1,5 +1,7 @@ #include "cache.h" #include "string-list.h" +#include "run-command.h" +#include "string-list.h" #include "trailer.h" /* * Copyright (c) 2013, 2014 Christian Couder @@ -14,6 +16,7 @@ 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; @@ -33,6 +36,8 @@ static struct trailer_item *first_conf_item; static char *separators = ":"; +#define TRAILER_ARG_STRING "$ARG" + static int after_or_end(enum action_where where) { return (where == WHERE_AFTER) || (where == WHERE_END); @@ -73,6 +78,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); @@ -478,6 +490,7 @@ static int git_trailer_config(const char *conf_key, const char *value, void *cb) if (conf->command) warning(_("more than one %s"), 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)) @@ -519,6 +532,46 @@ static int parse_trailer(struct strbuf *tok, struct strbuf *val, const char *tra return 0; } +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); + result = xstrdup(""); + } else + result = strbuf_detach(&buf, NULL); + + strbuf_release(&cmd); + return result; +} + static const char *token_from_item(struct trailer_item *item) { if (item->conf.key) @@ -537,6 +590,10 @@ static struct trailer_item *new_trailer_item(struct trailer_item *conf_item, duplicate_conf(&new->conf, &conf_item->conf); new->token = xstrdup(token_from_item(conf_item)); free(tok); + if (conf_item->conf.command_uses_arg || !val) { + new->value = apply_command(conf_item->conf.command, val); + free(val); + } } else { duplicate_conf(&new->conf, &default_conf_info); new->token = tok; @@ -600,12 +657,21 @@ static struct trailer_item *process_command_line_args(struct string_list *traile struct trailer_item *arg_tok_first = NULL; struct trailer_item *arg_tok_last = NULL; struct string_list_item *tr; + struct trailer_item *item; for_each_string_list_item(tr, trailers) { struct trailer_item *new = create_trailer_item(tr->string); 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; } -- 2.0.1.674.ga7f57b7 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordo
Re: [PATCH v2 2/2] convert: Stream from fd to required clean filter instead of mmap
Steffen Prohaska writes: > The test should confirm that the the file that is added is not mmapped to > memory. RSS doesn't tell you that. You can mmap a big file without RSS getting bigger. Andreas. -- Andreas Schwab, sch...@linux-m68k.org GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different." -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 03/10] setup: convert setup_git_directory_gently_1 et al. to strbuf
On 2014-07-28 20.26, René Scharfe wrote: > Convert setup_git_directory_gently_1() and its helper functions > setup_explicit_git_dir(), setup_discovered_git_dir() and > setup_bare_git_dir() to use a struct strbuf to hold the current working > directory. Replacing the PATH_MAX-sized buffer used before removes a > path length limition on some file systems. The functions are converted > all in one go because they all read and write the variable cwd. > > Signed-off-by: Rene Scharfe > --- > setup.c | 85 > + > 1 file changed, 43 insertions(+), 42 deletions(-) > > diff --git a/setup.c b/setup.c > index 0a22f8b..c8b8a97 100644 > --- a/setup.c > +++ b/setup.c > @@ -387,7 +387,7 @@ const char *read_gitfile(const char *path) > } > > static const char *setup_explicit_git_dir(const char *gitdirenv, > - char *cwd, int len, > + struct strbuf *cwd, > int *nongit_ok) > { > const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT); > @@ -441,7 +441,7 @@ static const char *setup_explicit_git_dir(const char > *gitdirenv, > die_errno("Could not chdir to '%s'", > git_work_tree_cfg); > if (!getcwd(core_worktree, PATH_MAX)) > die_errno("Could not get directory '%s'", > git_work_tree_cfg); > - if (chdir(cwd)) > + if (chdir(cwd->buf)) > die_errno("Could not come back to cwd"); > set_git_work_tree(core_worktree); > } > @@ -459,21 +459,20 @@ static const char *setup_explicit_git_dir(const char > *gitdirenv, > worktree = get_git_work_tree(); > > /* both get_git_work_tree() and cwd are already normalized */ > - if (!strcmp(cwd, worktree)) { /* cwd == worktree */ > + if (!strcmp(cwd->buf, worktree)) { /* cwd == worktree */ > set_git_dir(gitdirenv); > free(gitfile); > return NULL; > } > > - offset = dir_inside_of(cwd, worktree); > + offset = dir_inside_of(cwd->buf, worktree); > if (offset >= 0) { /* cwd inside worktree? */ > set_git_dir(real_path(gitdirenv)); > if (chdir(worktree)) > die_errno("Could not chdir to '%s'", worktree); > - cwd[len++] = '/'; > - cwd[len] = '\0'; > + strbuf_addch(cwd, '/'); > free(gitfile); > - return cwd + offset; > + return cwd->buf + offset; > } > > /* cwd outside worktree */ > @@ -483,7 +482,7 @@ static const char *setup_explicit_git_dir(const char > *gitdirenv, > } > > static const char *setup_discovered_git_dir(const char *gitdir, > - char *cwd, int offset, int len, > + struct strbuf *cwd, int offset, > int *nongit_ok) > { > if (check_repository_format_gently(gitdir, nongit_ok)) > @@ -491,17 +490,17 @@ static const char *setup_discovered_git_dir(const char > *gitdir, > > /* --work-tree is set without --git-dir; use discovered one */ > if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) { > - if (offset != len && !is_absolute_path(gitdir)) > + if (offset != cwd->len && !is_absolute_path(gitdir)) > gitdir = xstrdup(real_path(gitdir)); > - if (chdir(cwd)) > + if (chdir(cwd->buf)) > die_errno("Could not come back to cwd"); > - return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok); > + return setup_explicit_git_dir(gitdir, cwd, nongit_ok); > } > > /* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */ > if (is_bare_repository_cfg > 0) { > - set_git_dir(offset == len ? gitdir : real_path(gitdir)); > - if (chdir(cwd)) > + set_git_dir(offset == cwd->len ? gitdir : real_path(gitdir)); > + if (chdir(cwd->buf)) > die_errno("Could not come back to cwd"); > return NULL; > } > @@ -512,18 +511,18 @@ static const char *setup_discovered_git_dir(const char > *gitdir, > set_git_dir(gitdir); > inside_git_dir = 0; > inside_work_tree = 1; > - if (offset == len) > + if (offset == cwd->len) > return NULL; > > /* Make "offset" point to past the '/', and add a '/' at the end */ > offset++; > - cwd[len++] = '/'; > - cwd[len] = 0; > - return cwd + offset; > + strbuf_addch(cwd, '/'); > + return cwd->buf + offset; > } > > /* #16.1, #17.1, #20.1, #21.1, #22.1 (see t1510) */ > -static const char *setup_bare_git_dir(char *cwd, int offset, int len, int
[PATCH 2/2] Push the Makefile variable NATIVE_CRLF to C
Re-do the fix in 757543ae0c5d8d: Propagate the Makefile variable NATIVE_CRLF to the C preprocessor Signed-off-by: Torsten Bögershausen --- Makefile | 4 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 63a210d..00ba537 100644 --- a/Makefile +++ b/Makefile @@ -1482,6 +1482,10 @@ ifdef NO_REGEX COMPAT_OBJS += compat/regex/regex.o endif +ifdef NATIVE_CRLF + BASIC_CFLAGS += -DNATIVE_CRLF +endif + ifdef USE_NED_ALLOCATOR COMPAT_CFLAGS += -Icompat/nedmalloc COMPAT_OBJS += compat/nedmalloc/nedmalloc.o -- 2.1.0.rc2.210.g636bceb -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] t0027: Tests for core.eol=native, eol=lf, eol=crlf
Add test cases for core.eol "native" and "" (unset). (MINGW uses CRLF, all other systems LF as native line endings) Add test cases for the attributes "eol=lf" and "eol=crlf" Other minor changes: - Use the more portable 'tr' instead of 'od -c' to convert '\n' into 'Q' and '\0' into 'N' - Style fixes for shell functions according to the coding guide lines - Replace "txtbin" with "attr" Signed-off-by: Torsten Bögershausen --- t/t0027-auto-crlf.sh | 220 --- 1 file changed, 120 insertions(+), 100 deletions(-) diff --git a/t/t0027-auto-crlf.sh b/t/t0027-auto-crlf.sh index 72dd3e8..2a4a6c1 100755 --- a/t/t0027-auto-crlf.sh +++ b/t/t0027-auto-crlf.sh @@ -10,30 +10,26 @@ then test_done fi - -compare_files() -{ - od -c <"$1" >"$1".expect && - od -c <"$2" >"$2".actual && +compare_files () { + tr '\015\000' QN <"$1" >"$1".expect && + tr '\015\000' QN <"$2" >"$2".actual && test_cmp "$1".expect "$2".actual && rm "$1".expect "$2".actual } -compare_ws_file() -{ +compare_ws_file () { pfx=$1 exp=$2.expect act=$pfx.actual.$3 - od -c <"$2" >"$exp" && - od -c <"$3" >"$act" && + tr '\015\000' QN <"$2" >"$exp" && + tr '\015\000' QN <"$3" >"$act" && test_cmp $exp $act && rm $exp $act } -create_gitattributes() -{ - txtbin=$1 - case "$txtbin" in +create_gitattributes () { + attr=$1 + case "$attr" in auto) echo "*.txt text=auto" >.gitattributes ;; @@ -43,35 +39,43 @@ create_gitattributes() -text) echo "*.txt -text" >.gitattributes ;; - *) + crlf) + echo "*.txt eol=crlf" >.gitattributes + ;; + lf) + echo "*.txt eol=lf" >.gitattributes + ;; + "") echo >.gitattributes ;; + *) + echo >&2 invalid attribute: $attr + exit 1 + ;; esac } -create_file_in_repo() -{ +create_file_in_repo () { crlf=$1 - txtbin=$2 - create_gitattributes "$txtbin" && + attr=$2 + create_gitattributes "$attr" && for f in LF CRLF LF_mix_CR CRLF_mix_LF CRLF_nul do - pfx=crlf_${crlf}_attr_${txtbin}_$f.txt && + pfx=crlf_${crlf}_attr_${attr}_$f.txt && cp $f $pfx && git -c core.autocrlf=$crlf add $pfx done && git commit -m "core.autocrlf $crlf" } -check_files_in_repo() -{ +check_files_in_repo () { crlf=$1 - txtbin=$2 + attr=$2 lfname=$3 crlfname=$4 lfmixcrlf=$5 lfmixcr=$6 crlfnul=$7 - pfx=crlf_${crlf}_attr_${txtbin}_ && + pfx=crlf_${crlf}_attr_${attr}_ && compare_files $lfname ${pfx}LF.txt && compare_files $crlfname ${pfx}CRLF.txt && compare_files $lfmixcrlf ${pfx}CRLF_mix_LF.txt && @@ -80,19 +84,18 @@ check_files_in_repo() } -check_files_in_ws() -{ +check_files_in_ws () { eol=$1 crlf=$2 - txtbin=$3 + attr=$3 lfname=$4 crlfname=$5 lfmixcrlf=$6 lfmixcr=$7 crlfnul=$8 - create_gitattributes $txtbin && + create_gitattributes $attr && git config core.autocrlf $crlf && - pfx=eol_${eol}_crlf_${crlf}_attr_${txtbin}_ && + pfx=eol_${eol}_crlf_${crlf}_attr_${attr}_ && src=crlf_false_attr__ && for f in LF CRLF LF_mix_CR CRLF_mix_LF CRLF_nul do @@ -104,42 +107,24 @@ check_files_in_ws() fi done - - test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$txtbin file=LF" " + test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$attr file=LF" " compare_ws_file $pfx $lfname${src}LF.txt " - test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$txtbin file=CRLF" " + test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$attr file=CRLF" " compare_ws_file $pfx $crlfname ${src}CRLF.txt " - test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$txtbin file=CRLF_mix_LF" " + test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$attr file=CRLF_mix_LF" " compare_ws_file $pfx $lfmixcrlf ${src}CRLF_mix_LF.txt " - test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$txtbin file=LF_mix_CR" " + test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$attr file=LF_mix_CR" " compare_ws_file $pfx $lfmixcr ${src}LF_mix_CR.txt " - test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattrib
t5534 broken when gpg not installed
(I couldn't find a post for this patch) The following is needed for systems without gpg to make t5534 pass: diff --git a/t/t5534-push-signed.sh b/t/t5534-push-signed.sh index 3acc864..ee5aaff 100755 --- a/t/t5534-push-signed.sh +++ b/t/t5534-push-signed.sh @@ -45,7 +45,7 @@ test_expect_success 'unsigned push does not send push certificate' ' ! test -s dst/push-cert ' -test_expect_success 'signed push sends push certificate' ' +test_expect_success GPG 'signed push sends push certificate' ' prepare_dst && mkdir -p dst/.git/hooks && write_script dst/.git/hooks/post-receive <<-\EOF && -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 03/10] setup: convert setup_git_directory_gently_1 et al. to strbuf
> Is there a chance to squueze this in: > > > $ git diff > diff --git a/setup.c b/setup.c > index 526cdf6..fb61860 100644 > --- a/setup.c > +++ b/setup.c > @@ -734,7 +734,7 @@ static const char *setup_git_directory_gently_1(int > *nongit_ok) > string_list_clear(&ceiling_dirs, 0); > } > > - if (ceil_offset < 0 && has_dos_drive_prefix(cwd)) > + if (ceil_offset < 0 && has_dos_drive_prefix(cwd.buf)) > ceil_offset = 1; > > Ouch, thanks for catching this. Perhaps the following patch should go in as well. -- >8 -- Subject: [PATCH] turn path macros into inline function Use static inline functions instead of macros for has_dos_drive_prefix, offset_1st_component, is_dir_sep and find_last_dir_sep in order to let the compiler do type checking. The definitions of offset_1st_component and is_dir_sep are switched around because the former uses the latter. Signed-off-by: Rene Scharfe --- git-compat-util.h | 28 ++-- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/git-compat-util.h b/git-compat-util.h index f587749..0b6c13a 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -264,19 +264,35 @@ extern char *gitbasename(char *); #endif #ifndef has_dos_drive_prefix -#define has_dos_drive_prefix(path) 0 +static inline int git_has_dos_drive_prefix(const char *path) +{ + return 0; +} +#define has_dos_drive_prefix git_has_dos_drive_prefix #endif -#ifndef offset_1st_component -#define offset_1st_component(path) (is_dir_sep((path)[0])) +#ifndef is_dir_sep +static inline int git_is_dir_sep(int c) +{ + return c == '/'; +} +#define is_dir_sep git_is_dir_sep #endif -#ifndef is_dir_sep -#define is_dir_sep(c) ((c) == '/') +#ifndef offset_1st_component +static inline int git_offset_1st_component(const char *path) +{ + return is_dir_sep(path[0]); +} +#define offset_1st_component git_offset_1st_component #endif #ifndef find_last_dir_sep -#define find_last_dir_sep(path) strrchr(path, '/') +static inline char *git_find_last_dir_sep(const char *path) +{ + return strrchr(path, '/'); +} +#define find_last_dir_sep git_find_last_dir_sep #endif #if defined(__HP_cc) && (__HP_cc >= 61000) -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v13 00/11] Add interpret-trailers builtin
On Sat, Aug 16, 2014 at 6:06 PM, Christian Couder wrote: > > 3) Changes since version 12, thanks to Jakub, Michael, Johan and Junio: > > * "end" and "start" values for "trailer..where" have been > implemented > * "end" has been made the default value for "where", but this default > value can be changed using the new "trailer.where" config > variable > * "addIfDifferentNeighbor" is now the default value for "ifexists", > but this default can be changed using the new "trailer.ifexists" > config variable > * the new "trailer.ifmissing" can be used to change the default value > for "ifmissing" (which is "add") > * by default the only separator is ':', this can be changed by using > the new "trailer.separators" config variable > * only the configured separators (or just ':' by default) are used for > both input parsing and output printing; the only exception is that > '=' is always accepted as separator when parsing > "--trailer ''" command line arguments, for > compatibility with other git commands > * 14 tests have been added I forgot the following change: * "overwrite" value for "ifexists" option has been replaced with "replace" value; when used with "where = after" or "where = before", "replace" does the same thing as "overwrite" did; but when used with "where = end" or "where = start", the new trailer appears at the end or the start of the existing trailers, instead of where the replaced trailer was -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] run-command: introduce CHILD_PROCESS_INIT
Most struct child_process variables are cleared using memset right after declaration. Provide a macro, CHILD_PROCESS_INIT, that can be used to initialize them statically instead. That's shorter, doesn't require a function call and is slightly more readable (especially given that we already have similar macros like STRBUF_INIT, ARGV_ARRAY_INIT etc.). Signed-off-by: Rene Scharfe --- Documentation/technical/api-run-command.txt | 4 ++-- archive-tar.c | 3 +-- builtin/add.c | 3 +-- builtin/commit.c| 3 +-- builtin/help.c | 3 +-- builtin/merge.c | 3 +-- builtin/notes.c | 3 +-- builtin/remote-ext.c| 3 +-- builtin/repack.c| 3 +-- builtin/replace.c | 4 ++-- builtin/verify-pack.c | 3 +-- bundle.c| 6 ++ connected.c | 3 +-- convert.c | 3 +-- credential-cache.c | 3 +-- credential.c| 3 +-- daemon.c| 8 +++- diff.c | 3 +-- editor.c| 3 +-- fetch-pack.c| 3 +-- gpg-interface.c | 6 ++ http-backend.c | 3 +-- http.c | 3 +-- imap-send.c | 2 +- prompt.c| 3 +-- remote-curl.c | 3 +-- remote-testsvn.c| 3 +-- run-command.h | 2 ++ send-pack.c | 3 +-- submodule.c | 21 +++-- test-run-command.c | 4 +--- test-subprocess.c | 3 +-- transport.c | 12 upload-pack.c | 3 +-- wt-status.c | 3 +-- 35 files changed, 51 insertions(+), 93 deletions(-) diff --git a/Documentation/technical/api-run-command.txt b/Documentation/technical/api-run-command.txt index 69510ae..ca066bf 100644 --- a/Documentation/technical/api-run-command.txt +++ b/Documentation/technical/api-run-command.txt @@ -96,8 +96,8 @@ command to run in a sub-process. The caller: -1. allocates and clears (memset(&chld, 0, sizeof(chld));) a - struct child_process variable; +1. allocates and clears (memset(&chld, 0, sizeof(chld)); or + using CHILD_PROCESS_INIT) a struct child_process variable; 2. initializes the members; 3. calls start_command(); 4. processes the data; diff --git a/archive-tar.c b/archive-tar.c index 719b629..0d1e6bd 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -395,7 +395,7 @@ static int write_tar_filter_archive(const struct archiver *ar, struct archiver_args *args) { struct strbuf cmd = STRBUF_INIT; - struct child_process filter; + struct child_process filter = CHILD_PROCESS_INIT; const char *argv[2]; int r; @@ -406,7 +406,6 @@ static int write_tar_filter_archive(const struct archiver *ar, if (args->compression_level >= 0) strbuf_addf(&cmd, " -%d", args->compression_level); - memset(&filter, 0, sizeof(filter)); argv[0] = cmd.buf; argv[1] = NULL; filter.argv = argv; diff --git a/builtin/add.c b/builtin/add.c index 4baf3a5..352b85e 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -180,7 +180,7 @@ static int edit_patch(int argc, const char **argv, const char *prefix) char *file = git_pathdup("ADD_EDIT.patch"); const char *apply_argv[] = { "apply", "--recount", "--cached", NULL, NULL }; - struct child_process child; + struct child_process child = CHILD_PROCESS_INIT; struct rev_info rev; int out; struct stat st; @@ -214,7 +214,6 @@ static int edit_patch(int argc, const char **argv, const char *prefix) if (!st.st_size) die(_("Empty patch. Aborted.")); - memset(&child, 0, sizeof(child)); child.git_cmd = 1; child.argv = apply_argv; if (run_command(&child)) diff --git a/builtin/commit.c b/builtin/commit.c index 5ed6036..b8b8663 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -1508,7 +1508,7 @@ static int run_rewrite_hook(const unsigned char *oldsha1, { /* oldsha1 SP newsha1 LF NUL */ static char buf[2*40 + 3]; - struct child_process proc; + struct child_process proc = CHILD_PROCESS_INIT; const char *argv[3]; int code; size_t n
Feature Request: `git remote prune --all`
I would like to propose the addition of a `git remote prune --all` command option or similar mechanism for pruning all remotes in a repository. For lack of such a feature, I've been using the following bash alias: alias git-remote-prune-all='for REMOTE in `git remote`; do echo "Pruning $REMOTE"; git remote prune $REMOTE; done;' -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Running make in contrib/subtree does not create executable
Running "make" in contrib/subtree no longer creates the git-subtree executable: $ git describe v2.1.0 $ make -C contrib/subtree /Library/Developer/CommandLineTools/usr/bin/make -C ../../ GIT-VERSION-FILE GIT_VERSION = 2.1.0 make[1]: `GIT-VERSION-FILE' is up to date. /Library/Developer/CommandLineTools/usr/bin/make -C ../../ GIT-VERSION-FILE make[1]: `GIT-VERSION-FILE' is up to date. make: `../../GIT-VERSION-FILE' is up to date. $ ls contrib/subtree/git-subtree ls: contrib/subtree/git-subtree: No such file or directory The change appears to be inadvertent. I bisected it to 8e2a5ccad11bc21eb72499133bc884024e299983 ("contrib/subtree/Makefile: use GIT-VERSION-FILE"). This was reproduced on OS X 10.9 with GNU make 3.81. -Jack -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html