[PATCH 0/2] add format specifiers to display trailers
From: Jacob Keller This is based off of jt/use-trailer-api-in-commands so that we can make use of the public trailer API that will parse a string for trailers. I use trailers as a way to store extra commit metadata, and would like a convenient way to obtain the trailers of a commit message easily. This adds format specifiers to both the ref-filter API and the pretty format specifiers, using %(trailers) for both (and also contents:trailers for ref-filter). Additionally, I am somewhat not a fan of the way that if you have a series of trailers which are trailer format, but not recognized, such as the following: My-tag: my value My-other-tag: my other value [non-trailer line] My-tag: my third value Git interpret-trailers will not recognize this as a trailer block because it doesn't have any standard git tags within it. Junio suggested that we should treat all the configured trailer prefixes as recognized so that it would work as well, but it doesn't appear to do this at least for jt/use-trailer-api-in-commands I think that's the right solution, since it's extensible, though it would mean that interpret-trailers would behave differently on different systems... not really sure it's all bad though. interdiff v1: diff --git c/Documentation/pretty-formats.txt w/Documentation/pretty-formats.txt index 9ee68a4cb64a..47b286b33e4e 100644 --- c/Documentation/pretty-formats.txt +++ w/Documentation/pretty-formats.txt @@ -138,7 +138,6 @@ The placeholders are: - '%s': subject - '%f': sanitized subject line, suitable for a filename - '%b': body -- '%bT': trailers of body as interpreted by linkgit:git-interpret-trailers[1] - '%B': raw body (unwrapped subject and body) ifndef::git-rev-list[] - '%N': commit notes @@ -200,6 +199,8 @@ endif::git-rev-list[] than given and there are spaces on its left, use those spaces - '%><()', '%><|()': similar to '% <()', '%<|()' respectively, but padding both sides (i.e. the text is centered) +-%(trailers): display the trailers of the body as interpreted by + linkgit:git-interpret-trailers[1] NOTE: Some placeholders may depend on other options given to the revision traversal engine. For example, the `%g*` reflog options will diff --git c/pretty.c w/pretty.c index ea8764334865..5e683830d9d6 100644 --- c/pretty.c +++ w/pretty.c @@ -1300,16 +1300,15 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ format_sanitized_subject(sb, msg + c->subject_off); return 1; case 'b': /* body */ - switch (placeholder[1]) { - case 'T': - format_trailers(sb, msg + c->subject_off); - return 2; - default: - break; - } strbuf_addstr(sb, msg + c->body_off); return 1; } + + if (starts_with(placeholder, "(trailers)")) { + format_trailers(sb, msg + c->subject_off); + return strlen("(trailers)"); + } + return 0; /* unknown placeholder */ } diff --git c/t/t4205-log-pretty-formats.sh w/t/t4205-log-pretty-formats.sh index 7a35941ddcbd..21eb8c8587f2 100755 --- c/t/t4205-log-pretty-formats.sh +++ w/t/t4205-log-pretty-formats.sh @@ -542,7 +542,7 @@ Acked-by: A U Thor Signed-off-by: A U Thor EOF -test_expect_success 'pretty format %bT shows trailers' ' +test_expect_success 'pretty format %(trailers) shows trailers' ' echo "Some contents" >trailerfile && git add trailerfile && git commit -F - <<-EOF && @@ -553,7 +553,7 @@ test_expect_success 'pretty format %bT shows trailers' ' $(cat trailers) EOF - git log --no-walk --pretty="%bT" >actual && + git log --no-walk --pretty="%(trailers)" >actual && cat >expect <<-EOF && $(cat trailers) Jacob Keller (2): pretty: add %bT format for displaying trailers of a commit message ref-filter: add support to display trailers as part of contents Documentation/git-for-each-ref.txt | 2 ++ Documentation/pretty-formats.txt | 1 + pretty.c | 18 ++ ref-filter.c | 22 +- t/t4205-log-pretty-formats.sh | 26 ++ t/t6300-for-each-ref.sh| 26 ++ 6 files changed, 94 insertions(+), 1 deletion(-) -- 2.11.0.rc2.152.g4d04e67
[PATCH v2 2/2] ref-filter: add support to display trailers as part of contents
From: Jacob Keller Add %(trailers) and %(contents:trailers) to display the trailers as interpreted by trailer_info_get. Update documentation and add a test for the new feature. Signed-off-by: Jacob Keller --- Documentation/git-for-each-ref.txt | 2 ++ ref-filter.c | 22 +- t/t6300-for-each-ref.sh| 26 ++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt index f57e69bc83e3..e5807eede787 100644 --- a/Documentation/git-for-each-ref.txt +++ b/Documentation/git-for-each-ref.txt @@ -165,6 +165,8 @@ of all lines of the commit message up to the first blank line. The next line is 'contents:body', where body is all of the lines after the first blank line. The optional GPG signature is `contents:signature`. The first `N` lines of the message is obtained using `contents:lines=N`. +Additionally, the trailers as interpreted by linkgit:git-interpret-trailers[1] +are obtained as 'contents:trailers'. For sorting purposes, fields with numeric values sort in numeric order (`objectsize`, `authordate`, `committerdate`, `creatordate`, `taggerdate`). diff --git a/ref-filter.c b/ref-filter.c index d4c2931f3aab..b6f1bb73ed37 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -13,6 +13,7 @@ #include "utf8.h" #include "git-compat-util.h" #include "version.h" +#include "trailer.h" typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type; @@ -40,7 +41,7 @@ static struct used_atom { enum { RR_NORMAL, RR_SHORTEN, RR_TRACK, RR_TRACKSHORT } remote_ref; struct { - enum { C_BARE, C_BODY, C_BODY_DEP, C_LINES, C_SIG, C_SUB } option; + enum { C_BARE, C_BODY, C_BODY_DEP, C_LINES, C_SIG, C_SUB, C_TRAILERS } option; unsigned int nlines; } contents; enum { O_FULL, O_SHORT } objectname; @@ -85,6 +86,13 @@ static void subject_atom_parser(struct used_atom *atom, const char *arg) atom->u.contents.option = C_SUB; } +static void trailers_atom_parser(struct used_atom *atom, const char *arg) +{ + if (arg) + die(_("%%(trailers) does not take arguments")); + atom->u.contents.option = C_TRAILERS; +} + static void contents_atom_parser(struct used_atom *atom, const char *arg) { if (!arg) @@ -95,6 +103,8 @@ static void contents_atom_parser(struct used_atom *atom, const char *arg) atom->u.contents.option = C_SIG; else if (!strcmp(arg, "subject")) atom->u.contents.option = C_SUB; + else if (!strcmp(arg, "trailers")) + atom->u.contents.option = C_TRAILERS; else if (skip_prefix(arg, "lines=", &arg)) { atom->u.contents.option = C_LINES; if (strtoul_ui(arg, 10, &atom->u.contents.nlines)) @@ -194,6 +204,7 @@ static struct { { "creatordate", FIELD_TIME }, { "subject", FIELD_STR, subject_atom_parser }, { "body", FIELD_STR, body_atom_parser }, + { "trailers", FIELD_STR, trailers_atom_parser }, { "contents", FIELD_STR, contents_atom_parser }, { "upstream", FIELD_STR, remote_ref_atom_parser }, { "push", FIELD_STR, remote_ref_atom_parser }, @@ -785,6 +796,7 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct obj name++; if (strcmp(name, "subject") && strcmp(name, "body") && + strcmp(name, "trailers") && !starts_with(name, "contents")) continue; if (!subpos) @@ -808,6 +820,14 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct obj /* Size is the length of the message after removing the signature */ append_lines(&s, subpos, contents_end - subpos, atom->u.contents.nlines); v->s = strbuf_detach(&s, NULL); + } else if (atom->u.contents.option == C_TRAILERS) { + struct trailer_info info; + + /* Search for trailer info */ + trailer_info_get(&info, subpos); + v->s = xmemdupz(info.trailer_start, + info.trailer_end - info.trailer_start); + trailer_info_release(&info); } else if (atom->u.contents.option == C_BARE) v->s = xstrdup(subpos); } diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index 19a2823025e7..eb4bac0fe477 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -553,4 +553,30 @@ test_expect_success 'Verify sort with multiple keys' ' refs/tags/bogo refs/tags/master > actual && test_cmp expected actual ' + +c
[PATCH v2 1/2] pretty: add %(trailers) format for displaying trailers of a commit message
From: Jacob Keller Recent patches have expanded on the trailers.c code and we have the builtin commant git-interpret-trailers which can be used to add or modify trailer lines. However, there is no easy way to simply display the trailers of a commit message. Add support for %(trailers) format modifier which will use the trailer_info_get() calls to read trailers in an identical way as git interpret-trailers does. Use a long format option instead of a short name so that future work can more easily unify ref-filter and pretty formats. Add documentation and tests for the same. Signed-off-by: Jacob Keller --- Documentation/pretty-formats.txt | 2 ++ pretty.c | 17 + t/t4205-log-pretty-formats.sh| 26 ++ 3 files changed, 45 insertions(+) diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt index 3bcee2ddb124..47b286b33e4e 100644 --- a/Documentation/pretty-formats.txt +++ b/Documentation/pretty-formats.txt @@ -199,6 +199,8 @@ endif::git-rev-list[] than given and there are spaces on its left, use those spaces - '%><()', '%><|()': similar to '% <()', '%<|()' respectively, but padding both sides (i.e. the text is centered) +-%(trailers): display the trailers of the body as interpreted by + linkgit:git-interpret-trailers[1] NOTE: Some placeholders may depend on other options given to the revision traversal engine. For example, the `%g*` reflog options will diff --git a/pretty.c b/pretty.c index 37b2c3b1f995..5e683830d9d6 100644 --- a/pretty.c +++ b/pretty.c @@ -10,6 +10,7 @@ #include "color.h" #include "reflog-walk.h" #include "gpg-interface.h" +#include "trailer.h" static char *user_format; static struct cmt_fmt_map { @@ -889,6 +890,16 @@ const char *format_subject(struct strbuf *sb, const char *msg, return msg; } +static void format_trailers(struct strbuf *sb, const char *msg) +{ + struct trailer_info info; + + trailer_info_get(&info, msg); + strbuf_add(sb, info.trailer_start, + info.trailer_end - info.trailer_start); + trailer_info_release(&info); +} + static void parse_commit_message(struct format_commit_context *c) { const char *msg = c->message + c->message_off; @@ -1292,6 +1303,12 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ strbuf_addstr(sb, msg + c->body_off); return 1; } + + if (starts_with(placeholder, "(trailers)")) { + format_trailers(sb, msg + c->subject_off); + return strlen("(trailers)"); + } + return 0; /* unknown placeholder */ } diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh index f5435fd250ba..21eb8c8587f2 100755 --- a/t/t4205-log-pretty-formats.sh +++ b/t/t4205-log-pretty-formats.sh @@ -535,4 +535,30 @@ test_expect_success 'clean log decoration' ' test_cmp expected actual1 ' +cat >trailers < +Acked-by: A U Thor +[ v2 updated patch description ] +Signed-off-by: A U Thor +EOF + +test_expect_success 'pretty format %(trailers) shows trailers' ' + echo "Some contents" >trailerfile && + git add trailerfile && + git commit -F - <<-EOF && + trailers: this commit message has trailers + + This commit is a test commit with trailers at the end. We parse this + message and display the trailers using %bT + + $(cat trailers) + EOF + git log --no-walk --pretty="%(trailers)" >actual && + cat >expect <<-EOF && + $(cat trailers) + + EOF + test_cmp expect actual +' + test_done -- 2.11.0.rc2.152.g4d04e67
Re: [PATCH 0/2] add format specifiers to display trailers
On Fri, Nov 18, 2016 at 3:38 PM, Junio C Hamano wrote: > Jacob Keller writes: > >> Git interpret-trailers will not recognize this as a trailer block >> because it doesn't have any standard git tags within it. Would it be ok >> to augment the trailer interpretation to say that if we have over 75% >> trailers in the block that we accept it even if it doesn't have any real >> recognized tags? > > I thought the documented way to do this is to configure one of your > custom trailer as such. Jonathan? > That would be fine then, if that works. >> pretty: add %bT format for displaying trailers of a commit message > > Are %(...) taken already? In longer term, it would be nice if we > can unify the --pretty formats and for-each-ref formats, so it is > probably better if we avoid adding any new short ones to the former. > Oh, I hadn't considered adding a longer one. I'll rework this to use longer ones. > We have %s and %b so that we can reconstruct the whole thing by > using both. It is unclear how %bT fits in this picture. I wonder > if we also need another placeholder that expands to the body of the > message without the trailer---otherwise the whole set would become > incoherent, no? > I'm not entirely sure what to do here. I just wanted a way to easily format "just the trailers" of a message. We could add something that formats just the non-trailers, that's not too difficult. Not really sure what I'd call it though. Thanks, Jake
Fwd: git diff with “--word-diff-regex” extremely slow compared to “--word-diff”?
Hi When giving a custom regex to git diff --word-diff-regex= instead of using the default --word-diff (which splits words on whitespace), git slows down very considerably... I don't understand why such a speed difference? (this question was asked on stack overflow, but after two month without answer, I'm asking it here instead. Post: http://stackoverflow.com/questions/39027864/git-diff-with-word-diff-regex-extremely-slow-compared-to-word-diff). Example (sorry, UNIX specific code): create two one-line files, and two 20-lines files: echo aaa,bbb ,12,12,15 >file1.txt echo aaa,bbb ,12,12,16 >file2.txt awk '{for(i=0;i<20;i++)print}' file1.txt > file1BIG.txt awk '{for(i=0;i<20;i++)print}' file2.txt > file2BIG.txt Default --word-diff has no issues with the BIG files (cannot see time difference): git diff --word-diff file1.txt file2.txt git diff --word-diff file1BIG.txt file2BIG.txt Now use instead --word-diff-regex= argument (with regex from post: http://stackoverflow.com/questions/10482773/also-use-comma-as-a-word-separator-in-diff ) git diff --word-diff-regex=[^[:space:],] file1.txt file2.txt git diff --word-diff-regex=[^[:space:],] file1BIG.txt file2BIG.txt Why is the speed so different if one uses --word-diff instead of --word-diff-regex= ? Is it just because my expression is (slightly) more complex than the default one (split on period instead of only whitespace) ? Or is it that the default word-diff is implemented differently/more efficiently? How can I overcome this speed slowdown? Thanks!! Matthieu PS: using git 2.7.4 on Ubuntu 16.04
Re: [PATCH 13/16] submodule: teach unpack_trees() to update submodules
On Tue, Nov 15, 2016 at 4:25 PM, Brandon Williams wrote: > On 11/15, Stefan Beller wrote: >> + int flags = >> CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE; > > For readability you may want to have spaces between the two flags done > >> + if (o->index_only >> + || (!((old->ce_flags & CE_VALID) || ce_skip_worktree(old)) >> + && (o->reset || ce_uptodate(old >> + return 0; > > The coding guidelines say that git prefers to have the logical operators > on the right side like this: fixed all the coding style issues.
Re: [PATCH 0/2] add format specifiers to display trailers
Jacob Keller writes: > Git interpret-trailers will not recognize this as a trailer block > because it doesn't have any standard git tags within it. Would it be ok > to augment the trailer interpretation to say that if we have over 75% > trailers in the block that we accept it even if it doesn't have any real > recognized tags? I thought the documented way to do this is to configure one of your custom trailer as such. Jonathan? > pretty: add %bT format for displaying trailers of a commit message Are %(...) taken already? In longer term, it would be nice if we can unify the --pretty formats and for-each-ref formats, so it is probably better if we avoid adding any new short ones to the former. We have %s and %b so that we can reconstruct the whole thing by using both. It is unclear how %bT fits in this picture. I wonder if we also need another placeholder that expands to the body of the message without the trailer---otherwise the whole set would become incoherent, no?
Re: [PATCH 13/16] submodule: teach unpack_trees() to update submodules
On Tue, Nov 15, 2016 at 4:22 PM, David Turner wrote: >> msgs[ERROR_NOT_UPTODATE_DIR] = >> _("Updating the following directories would lose untracked >> files in it:\n%s"); >> + msgs[ERROR_NOT_UPTODATE_SUBMODULE] = >> + _("Updating the following submodules would lose modifications >> in >> +it:\n%s"); > > s/it/them/ done, also fixed the existing ERROR_NOT_UPTODATE_DIR. >> + if (!S_ISGITLINK(ce->ce_mode)) { > > I generally prefer to avoid if (!x) { A } else { B } -- I would rather just > see if (x) { B } else { A }. done. >> + if (submodule_is_interesting(old->name, >> null_sha1) >> + && ok_to_remove_submodule(old->name)) >> + return 0; >> + } > > Do we need a return 1 in here somewhere? Because otherwise, we fall through > and return 0 later. Otherwise we would fall through and run if (errno == ENOENT) return 0; return o->gently ? -1 : add_rejected_path(o, error_type, ce->name); which produces different results than 0?
Re: [PATCH v7 00/17] port branch.c to use ref-filter's printing options
Karthik Nayak writes: > Thanks, will add it in. OK, here is a reroll of what I sent earlier in http://public-inbox.org/git/ but rebased so that it can happen as a preparatory bugfix before your series. The bug dates back to the very original implementation of %(HEAD) in 7a48b83219 ("for-each-ref: introduce %(HEAD) asterisk marker", 2013-11-18) and was moved to the current location in the v2.6 days at c95b758587 ("ref-filter: move code from 'for-each-ref'", 2015-06-14). -- >8 -- Subject: [PATCH] for-each-ref: do not segv with %(HEAD) on an unborn branch The code to flip between "*" and " " prefixes depending on what branch is checked out used in --format='%(HEAD)' did not consider that HEAD may resolve to an unborn branch and dereferenced a NULL. This will become a lot easier to trigger as the codepath will be used to reimplement "git branch [--list]" in the future. Signed-off-by: Junio C Hamano --- ref-filter.c| 2 +- t/t6300-for-each-ref.sh | 10 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ref-filter.c b/ref-filter.c index bc551a752c..d7e91a78da 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -1017,7 +1017,7 @@ static void populate_value(struct ref_array_item *ref) head = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, sha1, NULL); - if (!strcmp(ref->refname, head)) + if (head && !strcmp(ref->refname, head)) v->s = "*"; else v->s = " "; diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index 19a2823025..039509a9cb 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -553,4 +553,14 @@ test_expect_success 'Verify sort with multiple keys' ' refs/tags/bogo refs/tags/master > actual && test_cmp expected actual ' + +test_expect_success 'do not dereference NULL upon %(HEAD) on unborn branch' ' + test_when_finished "git checkout master" && + git for-each-ref --format="%(HEAD) %(refname:short)" refs/heads/ >actual && + sed -e "s/^\* / /" actual >expect && + git checkout --orphan HEAD && + git for-each-ref --format="%(HEAD) %(refname:short)" refs/heads/ >actual && + test_cmp expect actual +' + test_done -- 2.11.0-rc2-152-gc9ad1dc38a
[PATCH 2/2] ref-filter: add support to display trailers as part of contents
From: Jacob Keller Add %(trailers) and %(contents:trailers) to display the trailers as interpreted by trailer_info_get. Update documentation and add a test for the new feature. Signed-off-by: Jacob Keller --- Documentation/git-for-each-ref.txt | 2 ++ ref-filter.c | 22 +- t/t6300-for-each-ref.sh| 26 ++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt index f57e69bc83e3..e5807eede787 100644 --- a/Documentation/git-for-each-ref.txt +++ b/Documentation/git-for-each-ref.txt @@ -165,6 +165,8 @@ of all lines of the commit message up to the first blank line. The next line is 'contents:body', where body is all of the lines after the first blank line. The optional GPG signature is `contents:signature`. The first `N` lines of the message is obtained using `contents:lines=N`. +Additionally, the trailers as interpreted by linkgit:git-interpret-trailers[1] +are obtained as 'contents:trailers'. For sorting purposes, fields with numeric values sort in numeric order (`objectsize`, `authordate`, `committerdate`, `creatordate`, `taggerdate`). diff --git a/ref-filter.c b/ref-filter.c index d4c2931f3aab..b6f1bb73ed37 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -13,6 +13,7 @@ #include "utf8.h" #include "git-compat-util.h" #include "version.h" +#include "trailer.h" typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type; @@ -40,7 +41,7 @@ static struct used_atom { enum { RR_NORMAL, RR_SHORTEN, RR_TRACK, RR_TRACKSHORT } remote_ref; struct { - enum { C_BARE, C_BODY, C_BODY_DEP, C_LINES, C_SIG, C_SUB } option; + enum { C_BARE, C_BODY, C_BODY_DEP, C_LINES, C_SIG, C_SUB, C_TRAILERS } option; unsigned int nlines; } contents; enum { O_FULL, O_SHORT } objectname; @@ -85,6 +86,13 @@ static void subject_atom_parser(struct used_atom *atom, const char *arg) atom->u.contents.option = C_SUB; } +static void trailers_atom_parser(struct used_atom *atom, const char *arg) +{ + if (arg) + die(_("%%(trailers) does not take arguments")); + atom->u.contents.option = C_TRAILERS; +} + static void contents_atom_parser(struct used_atom *atom, const char *arg) { if (!arg) @@ -95,6 +103,8 @@ static void contents_atom_parser(struct used_atom *atom, const char *arg) atom->u.contents.option = C_SIG; else if (!strcmp(arg, "subject")) atom->u.contents.option = C_SUB; + else if (!strcmp(arg, "trailers")) + atom->u.contents.option = C_TRAILERS; else if (skip_prefix(arg, "lines=", &arg)) { atom->u.contents.option = C_LINES; if (strtoul_ui(arg, 10, &atom->u.contents.nlines)) @@ -194,6 +204,7 @@ static struct { { "creatordate", FIELD_TIME }, { "subject", FIELD_STR, subject_atom_parser }, { "body", FIELD_STR, body_atom_parser }, + { "trailers", FIELD_STR, trailers_atom_parser }, { "contents", FIELD_STR, contents_atom_parser }, { "upstream", FIELD_STR, remote_ref_atom_parser }, { "push", FIELD_STR, remote_ref_atom_parser }, @@ -785,6 +796,7 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct obj name++; if (strcmp(name, "subject") && strcmp(name, "body") && + strcmp(name, "trailers") && !starts_with(name, "contents")) continue; if (!subpos) @@ -808,6 +820,14 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct obj /* Size is the length of the message after removing the signature */ append_lines(&s, subpos, contents_end - subpos, atom->u.contents.nlines); v->s = strbuf_detach(&s, NULL); + } else if (atom->u.contents.option == C_TRAILERS) { + struct trailer_info info; + + /* Search for trailer info */ + trailer_info_get(&info, subpos); + v->s = xmemdupz(info.trailer_start, + info.trailer_end - info.trailer_start); + trailer_info_release(&info); } else if (atom->u.contents.option == C_BARE) v->s = xstrdup(subpos); } diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index 19a2823025e7..eb4bac0fe477 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -553,4 +553,30 @@ test_expect_success 'Verify sort with multiple keys' ' refs/tags/bogo refs/tags/master > actual && test_cmp expected actual ' + +c
[PATCH 0/2] add format specifiers to display trailers
From: Jacob Keller This is based off of jt/use-trailer-api-in-commands so that we can make use of the public trailer API that will parse a string for trailers. I use trailers as a way to store extra commit metadata, and would like a convenient way to obtain the trailers of a commit message easily. This adds format specifiers to both the ref-filter API and the pretty formats. I am not a fan of %bT but %t and %T were already taken. I don't really know if it's ok to use %bT, since I think we used to allow "%bT" format, though i don't think this is likely used much in practice. I am open to suggestions for the pretty format specifier. Additionally, I am somewhat not a fan of the way that if you have a series of trailers which are trailer format, but not recognized, such as the following: My-tag: my value My-other-tag: my other value [non-trailer line] My-tag: my third value --- Git interpret-trailers will not recognize this as a trailer block because it doesn't have any standard git tags within it. Would it be ok to augment the trailer interpretation to say that if we have over 75% trailers in the block that we accept it even if it doesn't have any real recognized tags? I say this because I regularly use extra tags in my git projects to represent change metadata, and it would be nice if the tag block could be recognized even if it has 1-2 lines of non-trailer formatting in it... Thoughts? Jacob Keller (2): pretty: add %bT format for displaying trailers of a commit message ref-filter: add support to display trailers as part of contents Documentation/git-for-each-ref.txt | 2 ++ Documentation/pretty-formats.txt | 1 + pretty.c | 18 ++ ref-filter.c | 22 +- t/t4205-log-pretty-formats.sh | 26 ++ t/t6300-for-each-ref.sh| 26 ++ 6 files changed, 94 insertions(+), 1 deletion(-) -- 2.11.0.rc2.152.g4d04e67
[PATCH 1/2] pretty: add %bT format for displaying trailers of a commit message
From: Jacob Keller Recent patches have expanded on the trailers.c code and we have the builtin commant git-interpret-trailers which can be used to add or modify trailer lines. However, there is no easy way to simply display the trailers of a commit message. Add support for %bT format modifier which will use the trailer_info_get() calls to read trailers in an identical way as git interpret-trailers does. Add documentation and tests for the same. Signed-off-by: Jacob Keller --- Documentation/pretty-formats.txt | 1 + pretty.c | 18 ++ t/t4205-log-pretty-formats.sh| 26 ++ 3 files changed, 45 insertions(+) diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt index 3bcee2ddb124..9ee68a4cb64a 100644 --- a/Documentation/pretty-formats.txt +++ b/Documentation/pretty-formats.txt @@ -138,6 +138,7 @@ The placeholders are: - '%s': subject - '%f': sanitized subject line, suitable for a filename - '%b': body +- '%bT': trailers of body as interpreted by linkgit:git-interpret-trailers[1] - '%B': raw body (unwrapped subject and body) ifndef::git-rev-list[] - '%N': commit notes diff --git a/pretty.c b/pretty.c index 37b2c3b1f995..ea8764334865 100644 --- a/pretty.c +++ b/pretty.c @@ -10,6 +10,7 @@ #include "color.h" #include "reflog-walk.h" #include "gpg-interface.h" +#include "trailer.h" static char *user_format; static struct cmt_fmt_map { @@ -889,6 +890,16 @@ const char *format_subject(struct strbuf *sb, const char *msg, return msg; } +static void format_trailers(struct strbuf *sb, const char *msg) +{ + struct trailer_info info; + + trailer_info_get(&info, msg); + strbuf_add(sb, info.trailer_start, + info.trailer_end - info.trailer_start); + trailer_info_release(&info); +} + static void parse_commit_message(struct format_commit_context *c) { const char *msg = c->message + c->message_off; @@ -1289,6 +1300,13 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ format_sanitized_subject(sb, msg + c->subject_off); return 1; case 'b': /* body */ + switch (placeholder[1]) { + case 'T': + format_trailers(sb, msg + c->subject_off); + return 2; + default: + break; + } strbuf_addstr(sb, msg + c->body_off); return 1; } diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh index f5435fd250ba..7a35941ddcbd 100755 --- a/t/t4205-log-pretty-formats.sh +++ b/t/t4205-log-pretty-formats.sh @@ -535,4 +535,30 @@ test_expect_success 'clean log decoration' ' test_cmp expected actual1 ' +cat >trailers < +Acked-by: A U Thor +[ v2 updated patch description ] +Signed-off-by: A U Thor +EOF + +test_expect_success 'pretty format %bT shows trailers' ' + echo "Some contents" >trailerfile && + git add trailerfile && + git commit -F - <<-EOF && + trailers: this commit message has trailers + + This commit is a test commit with trailers at the end. We parse this + message and display the trailers using %bT + + $(cat trailers) + EOF + git log --no-walk --pretty="%bT" >actual && + cat >expect <<-EOF && + $(cat trailers) + + EOF + test_cmp expect actual +' + test_done -- 2.11.0.rc2.152.g4d04e67
Re: [PATCH v4 4/6] grep: optionally recurse into submodules
On 11/18, Junio C Hamano wrote: > Brandon Williams writes: > > > +static int grep_cache(struct grep_opt *opt, const struct pathspec > > *pathspec, > > + int cached) > > { > > int hit = 0; > > int nr; > > + struct strbuf name = STRBUF_INIT; > > + int name_base_len = 0; > > + if (super_prefix) { > > + name_base_len = strlen(super_prefix); > > + strbuf_addstr(&name, super_prefix); > > + } > > + > > read_cache(); > > > > for (nr = 0; nr < active_nr; nr++) { > > const struct cache_entry *ce = active_cache[nr]; > > - if (!S_ISREG(ce->ce_mode)) > > - continue; > > - if (!ce_path_match(ce, pathspec, NULL)) > > - continue; > > - /* > > -* If CE_VALID is on, we assume worktree file and its cache > > entry > > -* are identical, even if worktree file has been modified, so > > use > > -* cache version instead > > -*/ > > - if (cached || (ce->ce_flags & CE_VALID) || > > ce_skip_worktree(ce)) { > > - if (ce_stage(ce) || ce_intent_to_add(ce)) > > - continue; > > - hit |= grep_sha1(opt, ce->oid.hash, ce->name, 0, > > -ce->name); > > + strbuf_setlen(&name, name_base_len); > > + strbuf_addstr(&name, ce->name); > > + > > + if (S_ISREG(ce->ce_mode) && > > + match_pathspec(pathspec, name.buf, name.len, 0, NULL, > > + S_ISDIR(ce->ce_mode) || > > + S_ISGITLINK(ce->ce_mode))) { > > + /* > > +* If CE_VALID is on, we assume worktree file and its > > +* cache entry are identical, even if worktree file has > > +* been modified, so use cache version instead > > +*/ > > + if (cached || (ce->ce_flags & CE_VALID) || > > + ce_skip_worktree(ce)) { > > + if (ce_stage(ce) || ce_intent_to_add(ce)) > > + continue; > > + hit |= grep_sha1(opt, ce->oid.hash, ce->name, > > +0, ce->name); > > + } else { > > + hit |= grep_file(opt, ce->name); > > + } > > + } else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) && > > + submodule_path_match(pathspec, name.buf, NULL)) { > > + hit |= grep_submodule(opt, NULL, ce->name, ce->name); > > } > > - else > > - hit |= grep_file(opt, ce->name); > > We used to reject anything other than S_ISREG() upfront in the loop, > and then either did grep_sha1() from the cache or from grep_file() > from the working tree. > > Now, the guard upfront is removed, and we do the same in the first > part of this if/elseif. The elseif part deals with a submodule that > could match the pathspec. > > Don't we need a final else clause that would skip the remainder of > this loop? What would happen to a S_ISREG() path that does *NOT* > match the given pathspec? We used to just "continue", but it seems > to me that such a path will fall through the above if/elseif in the > new code. Would that be a problem? It may be (Though I didn't see any issues when running tests). It would be easy enough to add an 'else continue;' at the end though. -- Brandon Williams
Re: [PATCH v4 3/6] grep: add submodules as a grep source type
On 11/18, Junio C Hamano wrote: > Brandon Williams writes: > > > diff --git a/grep.h b/grep.h > > index 5856a23..267534c 100644 > > --- a/grep.h > > +++ b/grep.h > > @@ -161,6 +161,7 @@ struct grep_source { > > GREP_SOURCE_SHA1, > > GREP_SOURCE_FILE, > > GREP_SOURCE_BUF, > > + GREP_SOURCE_SUBMODULE, > > } type; > > void *identifier; > > Hmph, interesting. We have avoided ending enum definition with a > comma, because it is only valid in more recent C than what we aim to > support. This patch is not introducing a new problem, but just > doing the same thing that would have broken older compilers as the > existing code. Perhaps those older compilers have died out? Perhaps it is time to move to a new C standard! :P -- Brandon Williams
Re: [PATCH v4 5/6] grep: enable recurse-submodules to work on objects
On 11/18, Junio C Hamano wrote: > Brandon Williams writes: > > > @@ -671,12 +707,29 @@ static int grep_tree(struct grep_opt *opt, const > > struct pathspec *pathspec, > > enum interesting match = entry_not_interesting; > > struct name_entry entry; > > int old_baselen = base->len; > > + struct strbuf name = STRBUF_INIT; > > + int name_base_len = 0; > > + if (super_prefix) { > > + strbuf_addstr(&name, super_prefix); > > + name_base_len = name.len; > > + } > > > > while (tree_entry(tree, &entry)) { > > int te_len = tree_entry_len(&entry); > > > > if (match != all_entries_interesting) { > > - match = tree_entry_interesting(&entry, base, tn_len, > > pathspec); > > + strbuf_setlen(&name, name_base_len); > > + strbuf_addstr(&name, base->buf + tn_len); > > + > > + if (recurse_submodules && S_ISGITLINK(entry.mode)) { > > + strbuf_addstr(&name, entry.path); > > + match = submodule_path_match(pathspec, name.buf, > > +NULL); > > The vocabulary from submodule_path_match() returns is the same as > that of do_match_pathspec() and match_pathspec_item() which is > MATCHED_{EXACTLY,FNMATCH,RECURSIVELY}, which is different from the > vocabulary of the variable "match" which is "enum interesting" that > is used by the tree-walk infrastructure. > > I doubt they are compatible to be usable like this. Am I missing > something? I think i initially must have thought it would work out, but looking back at this I can clearly see that they aren't 100% compatible... It slightly feels odd to me that we have so many different means for checking pathspecs, all of which pretty much duplicate some of the functionality of the other. Is there any reason there are these two different code paths? Do we want them to remain separate or have them be unified at some point? Also, in order to use the tree_entry_interesting code it looks like I'll either have to pipe through a flag saying 'yes i want to match against submodules' like I did for the other pathspec codepath. Either that or add functionality to perform wildmatching against partial matches (ie directories and submodules) since currently the tree_entry_interesting code path just punts and says 'well say it matches for now and check again later' whenever it runs into a directory (I can't really make it do that for submodules without a flag of somesort as tests could break). Or maybe both? -- Brandon Williams
Re: [PATCH v7 14/17] ref-filter: allow porcelain to translate messages in the output
W dniu 08.11.2016 o 21:12, Karthik Nayak pisze: > From: Karthik Nayak > > Introduce setup_ref_filter_porcelain_msg() so that the messages used in > the atom %(upstream:track) can be translated if needed. This is needed > as we port branch.c to use ref-filter's printing API's. > > Written-by: Matthieu Moy > Mentored-by: Christian Couder > Mentored-by: Matthieu Moy > Signed-off-by: Karthik Nayak > --- > ref-filter.c | 28 > ref-filter.h | 2 ++ > 2 files changed, 26 insertions(+), 4 deletions(-) > > diff --git a/ref-filter.c b/ref-filter.c > index b47b900..944671a 100644 > --- a/ref-filter.c > +++ b/ref-filter.c > @@ -15,6 +15,26 @@ > #include "version.h" > #include "wt-status.h" > > +static struct ref_msg { > + const char *gone; > + const char *ahead; > + const char *behind; > + const char *ahead_behind; > +} msgs = { > + "gone", > + "ahead %d", > + "behind %d", > + "ahead %d, behind %d" > +}; > + > +void setup_ref_filter_porcelain_msg(void) > +{ > + msgs.gone = _("gone"); > + msgs.ahead = _("ahead %d"); > + msgs.behind = _("behind %d"); > + msgs.ahead_behind = _("ahead %d, behind %d"); > +} Do I understand it correctly that this mechanism is here to avoid repeated calls into gettext, as those messages would get repeated over and over; otherwise one would use foo = N_("...") and _(foo), isn't it? I wonder if there is some way to avoid duplication here, but I don't see anything easy and safe (e.g. against running setup_*() twice). Best, -- Jakub Narębski
Re: [PATCH v4 5/6] grep: enable recurse-submodules to work on objects
Brandon Williams writes: > @@ -671,12 +707,29 @@ static int grep_tree(struct grep_opt *opt, const struct > pathspec *pathspec, > enum interesting match = entry_not_interesting; > struct name_entry entry; > int old_baselen = base->len; > + struct strbuf name = STRBUF_INIT; > + int name_base_len = 0; > + if (super_prefix) { > + strbuf_addstr(&name, super_prefix); > + name_base_len = name.len; > + } > > while (tree_entry(tree, &entry)) { > int te_len = tree_entry_len(&entry); > > if (match != all_entries_interesting) { > - match = tree_entry_interesting(&entry, base, tn_len, > pathspec); > + strbuf_setlen(&name, name_base_len); > + strbuf_addstr(&name, base->buf + tn_len); > + > + if (recurse_submodules && S_ISGITLINK(entry.mode)) { > + strbuf_addstr(&name, entry.path); > + match = submodule_path_match(pathspec, name.buf, > + NULL); The vocabulary from submodule_path_match() returns is the same as that of do_match_pathspec() and match_pathspec_item() which is MATCHED_{EXACTLY,FNMATCH,RECURSIVELY}, which is different from the vocabulary of the variable "match" which is "enum interesting" that is used by the tree-walk infrastructure. I doubt they are compatible to be usable like this. Am I missing something? > + } else { > + match = tree_entry_interesting(&entry, &name, > +0, pathspec); > + } > + > if (match == all_entries_not_interesting) > break; > if (match == entry_not_interesting)
Re: [PATCH v4 4/6] grep: optionally recurse into submodules
Brandon Williams writes: > +static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, > + int cached) > { > int hit = 0; > int nr; > + struct strbuf name = STRBUF_INIT; > + int name_base_len = 0; > + if (super_prefix) { > + name_base_len = strlen(super_prefix); > + strbuf_addstr(&name, super_prefix); > + } > + > read_cache(); > > for (nr = 0; nr < active_nr; nr++) { > const struct cache_entry *ce = active_cache[nr]; > - if (!S_ISREG(ce->ce_mode)) > - continue; > - if (!ce_path_match(ce, pathspec, NULL)) > - continue; > - /* > - * If CE_VALID is on, we assume worktree file and its cache > entry > - * are identical, even if worktree file has been modified, so > use > - * cache version instead > - */ > - if (cached || (ce->ce_flags & CE_VALID) || > ce_skip_worktree(ce)) { > - if (ce_stage(ce) || ce_intent_to_add(ce)) > - continue; > - hit |= grep_sha1(opt, ce->oid.hash, ce->name, 0, > - ce->name); > + strbuf_setlen(&name, name_base_len); > + strbuf_addstr(&name, ce->name); > + > + if (S_ISREG(ce->ce_mode) && > + match_pathspec(pathspec, name.buf, name.len, 0, NULL, > +S_ISDIR(ce->ce_mode) || > +S_ISGITLINK(ce->ce_mode))) { > + /* > + * If CE_VALID is on, we assume worktree file and its > + * cache entry are identical, even if worktree file has > + * been modified, so use cache version instead > + */ > + if (cached || (ce->ce_flags & CE_VALID) || > + ce_skip_worktree(ce)) { > + if (ce_stage(ce) || ce_intent_to_add(ce)) > + continue; > + hit |= grep_sha1(opt, ce->oid.hash, ce->name, > + 0, ce->name); > + } else { > + hit |= grep_file(opt, ce->name); > + } > + } else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) && > +submodule_path_match(pathspec, name.buf, NULL)) { > + hit |= grep_submodule(opt, NULL, ce->name, ce->name); > } > - else > - hit |= grep_file(opt, ce->name); We used to reject anything other than S_ISREG() upfront in the loop, and then either did grep_sha1() from the cache or from grep_file() from the working tree. Now, the guard upfront is removed, and we do the same in the first part of this if/elseif. The elseif part deals with a submodule that could match the pathspec. Don't we need a final else clause that would skip the remainder of this loop? What would happen to a S_ISREG() path that does *NOT* match the given pathspec? We used to just "continue", but it seems to me that such a path will fall through the above if/elseif in the new code. Would that be a problem?
Re: [PATCH v4 4/6] grep: optionally recurse into submodules
Brandon Williams writes: > @@ -300,6 +311,10 @@ static int grep_sha1(struct grep_opt *opt, const > unsigned char *sha1, > if (opt->relative && opt->prefix_length) { > quote_path_relative(filename + tree_name_len, opt->prefix, > &pathbuf); > strbuf_insert(&pathbuf, 0, filename, tree_name_len); > + } else if (super_prefix) { > + strbuf_add(&pathbuf, filename, tree_name_len); > + strbuf_addstr(&pathbuf, super_prefix); > + strbuf_addstr(&pathbuf, filename + tree_name_len); > } else { > strbuf_addstr(&pathbuf, filename); > } > @@ -328,10 +343,13 @@ static int grep_file(struct grep_opt *opt, const char > *filename) > { > struct strbuf buf = STRBUF_INIT; > > - if (opt->relative && opt->prefix_length) > + if (opt->relative && opt->prefix_length) { > quote_path_relative(filename, opt->prefix, &buf); > - else > + } else { > + if (super_prefix) > + strbuf_addstr(&buf, super_prefix); > strbuf_addstr(&buf, filename); > + } The above two hunks both assume that the super_prefix option is usable only from the top-level (i.e. opt->prefix_length == 0) and also "--no-full-name" (which is the default) cannot be used. The only invoker that runs "grep" with "--super-prefix" is the "grep" that runs in the superproject, and it will only run us from the top-level of the working tree, so the former assumption is OK. It is a bit unclear to me how the "relative" and "--recurse-submodules" would interact with each other, though.
Re: [PATCH v7 13/17] ref-filter: add `:dir` and `:base` options for ref printing atoms
W dniu 15.11.2016 o 18:42, Junio C Hamano pisze: > Jacob Keller writes: > >> dirname makes sense. What about implementing a reverse variant of >> strip, which you could perform stripping of right-most components and >> instead of stripping by a number, strip "to" a number, ie: keep the >> left N most components, and then you could use something like >> ... >> I think that would be more general purpose than basename, and less confusing? > > I think you are going in the right direction. I had a similar > thought but built around a different axis. I.e. if strip=1 strips > one from the left, perhaps we want to have rstrip=1 that strips one > from the right, and also strip=-1 to mean strip everything except > one from the left and so on?. I think this and your keep (and > perhaps you'll have rkeep for completeness) have the same expressive > power. I do not offhand have a preference one over the other. > > Somehow it sounds a bit strange to me to treat 'remotes' as the same > class of token as 'heads' and 'tags' (I'd expect 'heads' and > 'remotes/origin' would be at the same level in end-user's mind), but > that is probably an unrelated tangent. The reason this series wants > to introduce :base must be to emulate an existing feature, so that > existing feature is a concrete counter-example that argues against > my "it sounds a bit strange" reaction. If it is to implement the feature where we select if to display only local branches (refs/heads/**), only remote-tracking branches (refs/remotes/**/**), or only tags (refs/tags/**), then perhaps ':category' or ':type' would make sense? As in '%(refname:category)', e.g. %(if:equals=heads)%(refname:category)%(then)...%(end) -- Jakub Narębski
Re: [PATCH v4 4/6] grep: optionally recurse into submodules
Brandon Williams writes: > +static void compile_submodule_options(const struct grep_opt *opt, > + const struct pathspec *pathspec, > + int cached, int untracked, > + int opt_exclude, int use_index, > + int pattern_type_arg) > +{ > + struct grep_pat *pattern; > + int i; > + > + if (recurse_submodules) > + argv_array_push(&submodule_options, "--recurse-submodules"); > + > + if (cached) > + argv_array_push(&submodule_options, "--cached"); > +... > + > + /* Add Pathspecs */ > + argv_array_push(&submodule_options, "--"); > + for (i = 0; i < pathspec->nr; i++) > + argv_array_push(&submodule_options, > + pathspec->items[i].original); > +} When I do $ git grep --recurse-submodules pattern submodules/ lib/ where I have bunch of submodules in "submodules/" directory in the top-level project, the top-level grep would try to find the pattern in its own files in its "lib/" directory and then invoke sub-greps in the submodule/a, submodule/b, etc. working trees. This passes the "submodules/" and "lib/" pathspec down to these sub-greps. These sub-greps in turn learn via --super-prefix where they are in the super-project's context (e.g. "submodules/a/") to adjust the given pathspec patterns, so everything cancels out (e.g. they know "lib/" is totally outside of their area and their files do not match with the pathspec element "lib/" at all). Looking good.
Re: [PATCH v4 3/6] grep: add submodules as a grep source type
Brandon Williams writes: > diff --git a/grep.h b/grep.h > index 5856a23..267534c 100644 > --- a/grep.h > +++ b/grep.h > @@ -161,6 +161,7 @@ struct grep_source { > GREP_SOURCE_SHA1, > GREP_SOURCE_FILE, > GREP_SOURCE_BUF, > + GREP_SOURCE_SUBMODULE, > } type; > void *identifier; Hmph, interesting. We have avoided ending enum definition with a comma, because it is only valid in more recent C than what we aim to support. This patch is not introducing a new problem, but just doing the same thing that would have broken older compilers as the existing code. Perhaps those older compilers have died out?
Re: [PATCH v7 10/17] ref-filter: introduce refname_atom_parser_internal()
W dniu 08.11.2016 o 21:12, Karthik Nayak pisze: > From: Karthik Nayak > > Since there are multiple atoms which print refs ('%(refname)', > '%(symref)', '%(push)', '%upstream'), it makes sense to have a common Minor typo; it should be: "%(upstream)" > ground for parsing them. This would allow us to share implementations of > the atom modifiers between these atoms. > > Introduce refname_atom_parser_internal() to act as a common parsing > function for ref printing atoms. This would eventually be used to > introduce refname_atom_parser() and symref_atom_parser() and also be > internally used in remote_ref_atom_parser(). > > Helped-by: Jeff King > Signed-off-by: Karthik Nayak > --- [...] > +static void refname_atom_parser_internal(struct refname_atom *atom, > + const char *arg, const char *name) > +{ > + if (!arg) > + atom->option = R_NORMAL; > + else if (!strcmp(arg, "short")) > + atom->option = R_SHORT; > + else if (skip_prefix(arg, "strip=", &arg)) { > + atom->option = R_STRIP; > + if (strtoul_ui(arg, 10, &atom->strip) || atom->strip <= 0) > + die(_("positive value expected refname:strip=%s"), arg); > + } else ^^ It looks like you have spurious tab here. > + die(_("unrecognized %%(%s) argument: %s"), name, arg); > +} > + > static void remote_ref_atom_parser(struct used_atom *atom, const char *arg) > { > struct string_list params = STRING_LIST_INIT_DUP; >
Re: [PATCH v7 09/17] ref-filter: make "%(symref)" atom work with the ':short' modifier
W dniu 08.11.2016 o 21:12, Karthik Nayak pisze: [...] > Add tests for %(symref) and %(symref:short) while we're here. That's nice. > > Helped-by: Junio C Hamano > Signed-off-by: Karthik Nayak > --- [...] > +test_expect_success 'Add symbolic ref for the following tests' ' > + git symbolic-ref refs/heads/sym refs/heads/master > +' > + > +cat >expected < +refs/heads/master > +EOF This should be inside the relevant test, not outside. In other patches in this series you are putting setup together with the rest of test, by using "cat >expected <<-\EOF". > + > +test_expect_success 'Verify usage of %(symref) atom' ' > + git for-each-ref --format="%(symref)" refs/heads/sym > actual && This should be spelled " >actual", rather than " > actual"; there should be no space between redirection and file name. > + test_cmp expected actual > +' > + > +cat >expected < +heads/master > +EOF > + > +test_expect_success 'Verify usage of %(symref:short) atom' ' > + git for-each-ref --format="%(symref:short)" refs/heads/sym > actual && > + test_cmp expected actual > +' Same here. > + > test_done > -- Jakub Narębski
Re: [PATCH v3] remote-curl: don't hang when a server dies before any output
David Turner writes: > In the event that a HTTP server closes the connection after giving a > 200 but before giving any packets, we don't want to hang forever > waiting for a response that will never come. Instead, we should die > immediately. > > One case where this happens is when attempting to fetch a dangling > object by SHA. In this case, the server dies before sending any data. > Prior to this patch, fetch-pack would wait for data from the server, > and remote-curl would wait for fetch-pack, causing a deadlock. > ... > Still to do: it would be good to give a better error message > than "fatal: The remote end hung up unexpectedly". > > Signed-off-by: David Turner > Signed-off-by: Junio C Hamano > --- Thanks.
[PATCH v3] remote-curl: don't hang when a server dies before any output
In the event that a HTTP server closes the connection after giving a 200 but before giving any packets, we don't want to hang forever waiting for a response that will never come. Instead, we should die immediately. One case where this happens is when attempting to fetch a dangling object by SHA. In this case, the server dies before sending any data. Prior to this patch, fetch-pack would wait for data from the server, and remote-curl would wait for fetch-pack, causing a deadlock. Despite this patch, there is other possible malformed input that could cause the same deadlock (e.g. a half-finished pktline, or a pktline but no trailing flush). There are a few possible solutions to this: 1. Allowing remote-curl to tell fetch-pack about the EOF (so that fetch-pack could know that no more data is coming until it says something else). This is tricky because an out-of-band signal would be required, or the http response would have to be re-framed inside another layer of pkt-line or something. 2. Make remote-curl understand some of the protocol. It turns out that in addition to understanding pkt-line, it would need to watch for ack/nak. This is somewhat fragile, as information about the protocol would end up in two places. Also, pkt-lines which are already at the length limit would need special handling. Both of these solutions would require a fair amount of work, whereas this hack is easy and solves at least some of the problem. Still to do: it would be good to give a better error message than "fatal: The remote end hung up unexpectedly". Signed-off-by: David Turner Signed-off-by: Junio C Hamano --- remote-curl.c | 8 t/t5551-http-fetch-smart.sh | 30 ++ 2 files changed, 38 insertions(+) diff --git a/remote-curl.c b/remote-curl.c index f14c41f..ee44236 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -400,6 +400,7 @@ struct rpc_state { size_t pos; int in; int out; + int any_written; struct strbuf result; unsigned gzip_request : 1; unsigned initial_buffer : 1; @@ -456,6 +457,8 @@ static size_t rpc_in(char *ptr, size_t eltsize, { size_t size = eltsize * nmemb; struct rpc_state *rpc = buffer_; + if (size) + rpc->any_written = 1; write_or_die(rpc->in, ptr, size); return size; } @@ -659,6 +662,8 @@ static int post_rpc(struct rpc_state *rpc) curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, rpc_in); curl_easy_setopt(slot->curl, CURLOPT_FILE, rpc); + + rpc->any_written = 0; err = run_slot(slot, NULL); if (err == HTTP_REAUTH && !large_request) { credential_fill(&http_auth); @@ -667,6 +672,9 @@ static int post_rpc(struct rpc_state *rpc) if (err != HTTP_OK) err = -1; + if (!rpc->any_written) + err = -1; + curl_slist_free_all(headers); free(gzip_body); return err; diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh index 1ec5b27..43665ab 100755 --- a/t/t5551-http-fetch-smart.sh +++ b/t/t5551-http-fetch-smart.sh @@ -276,6 +276,36 @@ test_expect_success 'large fetch-pack requests can be split across POSTs' ' test_line_count = 2 posts ' +test_expect_success 'test allowreachablesha1inwant' ' + test_when_finished "rm -rf test_reachable.git" && + server="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + master_sha=$(git -C "$server" rev-parse refs/heads/master) && + git -C "$server" config uploadpack.allowreachablesha1inwant 1 && + + git init --bare test_reachable.git && + git -C test_reachable.git remote add origin "$HTTPD_URL/smart/repo.git" && + git -C test_reachable.git fetch origin "$master_sha" +' + +test_expect_success 'test allowreachablesha1inwant with unreachable' ' + test_when_finished "rm -rf test_reachable.git; git reset --hard $(git rev-parse HEAD)" && + + #create unreachable sha + echo content >file2 && + git add file2 && + git commit -m two && + git push public HEAD:refs/heads/doomed && + git push public :refs/heads/doomed && + + server="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + master_sha=$(git -C "$server" rev-parse refs/heads/master) && + git -C "$server" config uploadpack.allowreachablesha1inwant 1 && + + git init --bare test_reachable.git && + git -C test_reachable.git remote add origin "$HTTPD_URL/smart/repo.git" && + test_must_fail git -C test_reachable.git fetch origin "$(git rev-parse HEAD)" +' + test_expect_success EXPENSIVE 'http can handle enormous ref negotiation' ' ( cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && -- 2.8.0.rc4.22.g8ae061a
Re: [PATCH v4 0/6] recursively grep across submodules
On Fri, Nov 18, 2016 at 11:58 AM, Brandon Williams wrote: > This revision of this series should address all of the problems brought up > with > v3. > > * indent output example in patch 5/6. > * fix ':' in submodule names and add a test to verify. > * cleanup some comments. > * fixed tests to test the case where a submodule isn't at the root of a > repository. > * always pass --threads=%d in order to limit threads to child proccess. > > > -- interdiff based on 'bw/grep-recurse-submodules' Thanks for interdiff! I only skimmed the patches, but rather reviewed this interdiff in detail. The series looks good to me, no nits! Thanks, Stefan
Re: gitweb html validation
2016-11-15 19:26 GMT+01:00 Ralf Thielow : Finally I've found the time to actually try this out and there are some problems with it. > > diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl > index 7cf68f07b..33d7c154f 100755 > --- a/gitweb/gitweb.perl > +++ b/gitweb/gitweb.perl > @@ -5531,8 +5531,8 @@ sub git_project_search_form { > $limit = " in '$project_filter/'"; > } > > - print "\n"; > print $cgi->start_form(-method => 'get', -action => $my_uri) . > + "\n" . > $cgi->hidden(-name => 'a', -value => 'project_list') . "\n"; > print $cgi->hidden(-name => 'pf', -value => $project_filter). "\n" > if (defined $project_filter); > @@ -5544,11 +5544,11 @@ sub git_project_search_form { > -checked => $search_use_regexp) . > "\n" . > $cgi->submit(-name => 'btnS', -value => 'Search') . > - $cgi->end_form() . "\n" . > $cgi->a({-href => href(project => undef, searchtext => undef, > project_filter => $project_filter)}, > esc_html("List all projects$limit")) . "\n"; > - print "\n"; > + print "\n" . > + $cgi->end_form() . "\n"; > } > The anchor is now inside the form-tag, which means there is no visual line-break anymore that comes automatically after as the form-tag is a block level element. Could be solved by adding a "", which is not very nice, but OK. > # entry for given @keys needs filling if at least one of keys in list > diff --git a/gitweb/static/gitweb.css b/gitweb/static/gitweb.css > index 321260103..507740b6a 100644 > --- a/gitweb/static/gitweb.css > +++ b/gitweb/static/gitweb.css > @@ -539,7 +539,7 @@ div.projsearch { > margin: 20px 0px; > } > > -div.projsearch form { > +form div.projsearch { > margin-bottom: 2px; > } > This is wrong as it overwrites the setting above, 20px at the bottom went to 2px. The problem is how to apply the 2px now. Before this, we had the , a block element, which we can give the 2px margin at the bottom. Now this element is gone and we have a set of inline elements where we use "" to emulate the line break. There are two css rules which can solve this, but I'm not really happy with both of them. 1) As we know we need the two pixel below an input element, we can say div.projsearch input { margin-bottom: 2px; } 2) Make the a-Tag inside div.projsearch being displayed as a block element to make a margin-top setting working. This has the benefit that we don't care about the element above. div.projsearch a { display: inline-block; margin-top: 2px; } If I have to choose I'd prefer the second one. So I can't think of a way to solve this nicely with this change.
Re: [PATCH v2] remote-curl: don't hang when a server dies before any output
David Turner writes: > In the event that a HTTP server closes the connection after giving a > 200 but before giving any packets, we don't want to hang forever > waiting for a response that will never come. Instead, we should die > immediately. > > One case where this happens is when attempting to fetch a dangling > object by SHA. > > Prior to this patch, fetch-pack would wait for more data from the > server, and remote-curl would wait for fetch-pack, causing a deadlock. > > Despite this patch, there is other possible malformed input that could > cause the same deadlock (e.g. a half-finished pktline, or a pktline but > no trailing flush). There are a few possible solutions to this: > > 1. Allowing remote-curl to tell fetch-pack about the EOF (so that > fetch-pack could know that no more data is coming until it says > something else). This is tricky because an out-of-band signal would > be required, or the http response would have to be re-framed inside > another layer of pkt-line or something. > > 2. Make remote-curl understand some of the protocol. It turns out > that in addition to understanding pkt-line, it would need to watch for > ack/nak. This is somewhat fragile, as information about the protocol > would end up in two places. Also, pkt-lines which are already at the > length limit would need special handling. > > Both of these solutions would require a fair amount of work, whereas > this hack is easy and solves at least some of the problem. > > Still to do: it would be good to give a better error message > than "fatal: The remote end hung up unexpectedly". It seems to me that there is some gap/leap in the description between the second and third paragraph above (i.e. the client asks for an object, the server tries to see if the object is reachable from the refs, and then what? who waits for more data without asking?), but other than that, including the future direction, the proposed log message is very nicely described. Thanks, will queue.
[PATCH v4 3/6] grep: add submodules as a grep source type
Add `GREP_SOURCE_SUBMODULE` as a grep_source type and cases for this new type in the various switch statements in grep.c. When initializing a grep_source with type `GREP_SOURCE_SUBMODULE` the identifier can either be NULL (to indicate that the working tree will be used) or a SHA1 (the REV of the submodule to be grep'd). If the identifier is a SHA1 then we want to fall through to the `GREP_SOURCE_SHA1` case to handle the copying of the SHA1. Signed-off-by: Brandon Williams --- grep.c | 16 +++- grep.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/grep.c b/grep.c index 1194d35..0dbdc1d 100644 --- a/grep.c +++ b/grep.c @@ -1735,12 +1735,23 @@ void grep_source_init(struct grep_source *gs, enum grep_source_type type, case GREP_SOURCE_FILE: gs->identifier = xstrdup(identifier); break; + case GREP_SOURCE_SUBMODULE: + if (!identifier) { + gs->identifier = NULL; + break; + } + /* +* FALL THROUGH +* If the identifier is non-NULL (in the submodule case) it +* will be a SHA1 that needs to be copied. +*/ case GREP_SOURCE_SHA1: gs->identifier = xmalloc(20); hashcpy(gs->identifier, identifier); break; case GREP_SOURCE_BUF: gs->identifier = NULL; + break; } } @@ -1760,6 +1771,7 @@ void grep_source_clear_data(struct grep_source *gs) switch (gs->type) { case GREP_SOURCE_FILE: case GREP_SOURCE_SHA1: + case GREP_SOURCE_SUBMODULE: free(gs->buf); gs->buf = NULL; gs->size = 0; @@ -1831,8 +1843,10 @@ static int grep_source_load(struct grep_source *gs) return grep_source_load_sha1(gs); case GREP_SOURCE_BUF: return gs->buf ? 0 : -1; + case GREP_SOURCE_SUBMODULE: + break; } - die("BUG: invalid grep_source type"); + die("BUG: invalid grep_source type to load"); } void grep_source_load_driver(struct grep_source *gs) diff --git a/grep.h b/grep.h index 5856a23..267534c 100644 --- a/grep.h +++ b/grep.h @@ -161,6 +161,7 @@ struct grep_source { GREP_SOURCE_SHA1, GREP_SOURCE_FILE, GREP_SOURCE_BUF, + GREP_SOURCE_SUBMODULE, } type; void *identifier; -- 2.8.0.rc3.226.g39d4020
[PATCH v4 4/6] grep: optionally recurse into submodules
Allow grep to recognize submodules and recursively search for patterns in each submodule. This is done by forking off a process to recursively call grep on each submodule. The top level --super-prefix option is used to pass a path to the submodule which can in turn be used to prepend to output or in pathspec matching logic. Recursion only occurs for submodules which have been initialized and checked out by the parent project. If a submodule hasn't been initialized and checked out it is simply skipped. In order to support the existing multi-threading infrastructure in grep, output from each child process is captured in a strbuf so that it can be later printed to the console in an ordered fashion. To limit the number of theads that are created, each child process has half the number of threads as its parents (minimum of 1), otherwise we potentailly have a fork-bomb. Signed-off-by: Brandon Williams --- Documentation/git-grep.txt | 5 + builtin/grep.c | 300 ++--- git.c | 2 +- t/t7814-grep-recurse-submodules.sh | 99 4 files changed, 385 insertions(+), 21 deletions(-) create mode 100755 t/t7814-grep-recurse-submodules.sh diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt index 0ecea6e..17aa1ba 100644 --- a/Documentation/git-grep.txt +++ b/Documentation/git-grep.txt @@ -26,6 +26,7 @@ SYNOPSIS [--threads ] [-f ] [-e] [--and|--or|--not|(|)|-e ...] + [--recurse-submodules] [ [--[no-]exclude-standard] [--cached | --no-index | --untracked] | ...] [--] [...] @@ -88,6 +89,10 @@ OPTIONS mechanism. Only useful when searching files in the current directory with `--no-index`. +--recurse-submodules:: + Recursively search in each submodule that has been initialized and + checked out in the repository. + -a:: --text:: Process binary files as if they were text. diff --git a/builtin/grep.c b/builtin/grep.c index 8887b6a..cfafa15 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -18,12 +18,20 @@ #include "quote.h" #include "dir.h" #include "pathspec.h" +#include "submodule.h" static char const * const grep_usage[] = { N_("git grep [] [-e] [...] [[--] ...]"), NULL }; +static const char *super_prefix; +static int recurse_submodules; +static struct argv_array submodule_options = ARGV_ARRAY_INIT; + +static int grep_submodule_launch(struct grep_opt *opt, +const struct grep_source *gs); + #define GREP_NUM_THREADS_DEFAULT 8 static int num_threads; @@ -174,7 +182,10 @@ static void *run(void *arg) break; opt->output_priv = w; - hit |= grep_source(opt, &w->source); + if (w->source.type == GREP_SOURCE_SUBMODULE) + hit |= grep_submodule_launch(opt, &w->source); + else + hit |= grep_source(opt, &w->source); grep_source_clear_data(&w->source); work_done(w); } @@ -300,6 +311,10 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1, if (opt->relative && opt->prefix_length) { quote_path_relative(filename + tree_name_len, opt->prefix, &pathbuf); strbuf_insert(&pathbuf, 0, filename, tree_name_len); + } else if (super_prefix) { + strbuf_add(&pathbuf, filename, tree_name_len); + strbuf_addstr(&pathbuf, super_prefix); + strbuf_addstr(&pathbuf, filename + tree_name_len); } else { strbuf_addstr(&pathbuf, filename); } @@ -328,10 +343,13 @@ static int grep_file(struct grep_opt *opt, const char *filename) { struct strbuf buf = STRBUF_INIT; - if (opt->relative && opt->prefix_length) + if (opt->relative && opt->prefix_length) { quote_path_relative(filename, opt->prefix, &buf); - else + } else { + if (super_prefix) + strbuf_addstr(&buf, super_prefix); strbuf_addstr(&buf, filename); + } #ifndef NO_PTHREADS if (num_threads) { @@ -378,31 +396,258 @@ static void run_pager(struct grep_opt *opt, const char *prefix) exit(status); } -static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int cached) +static void compile_submodule_options(const struct grep_opt *opt, + const struct pathspec *pathspec, + int cached, int untracked, + int opt_exclude, int use_index, + int pattern_type_arg) +{ + struct grep_pat *pattern; + int i; + + if (recurse_submodules) + argv_array_push(&submodule_options, "--recurse-submodules"); + + if
[PATCH v4 2/6] submodules: load gitmodules file from commit sha1
teach submodules to load a '.gitmodules' file from a commit sha1. This enables the population of the submodule_cache to be based on the state of the '.gitmodules' file from a particular commit. Signed-off-by: Brandon Williams --- cache.h| 2 ++ config.c | 8 submodule-config.c | 6 +++--- submodule-config.h | 3 +++ submodule.c| 12 submodule.h| 1 + 6 files changed, 25 insertions(+), 7 deletions(-) diff --git a/cache.h b/cache.h index 1be6526..559a461 100644 --- a/cache.h +++ b/cache.h @@ -1690,6 +1690,8 @@ extern int git_default_config(const char *, const char *, void *); extern int git_config_from_file(config_fn_t fn, const char *, void *); extern int git_config_from_mem(config_fn_t fn, const enum config_origin_type, const char *name, const char *buf, size_t len, void *data); +extern int git_config_from_blob_sha1(config_fn_t fn, const char *name, +const unsigned char *sha1, void *data); extern void git_config_push_parameter(const char *text); extern int git_config_from_parameters(config_fn_t fn, void *data); extern void git_config(config_fn_t fn, void *); diff --git a/config.c b/config.c index 83fdecb..4d78e72 100644 --- a/config.c +++ b/config.c @@ -1214,10 +1214,10 @@ int git_config_from_mem(config_fn_t fn, const enum config_origin_type origin_typ return do_config_from(&top, fn, data); } -static int git_config_from_blob_sha1(config_fn_t fn, -const char *name, -const unsigned char *sha1, -void *data) +int git_config_from_blob_sha1(config_fn_t fn, + const char *name, + const unsigned char *sha1, + void *data) { enum object_type type; char *buf; diff --git a/submodule-config.c b/submodule-config.c index 098085b..8b9a2ef 100644 --- a/submodule-config.c +++ b/submodule-config.c @@ -379,9 +379,9 @@ static int parse_config(const char *var, const char *value, void *data) return ret; } -static int gitmodule_sha1_from_commit(const unsigned char *commit_sha1, - unsigned char *gitmodules_sha1, - struct strbuf *rev) +int gitmodule_sha1_from_commit(const unsigned char *commit_sha1, + unsigned char *gitmodules_sha1, + struct strbuf *rev) { int ret = 0; diff --git a/submodule-config.h b/submodule-config.h index d05c542..78584ba 100644 --- a/submodule-config.h +++ b/submodule-config.h @@ -29,6 +29,9 @@ const struct submodule *submodule_from_name(const unsigned char *commit_sha1, const char *name); const struct submodule *submodule_from_path(const unsigned char *commit_sha1, const char *path); +extern int gitmodule_sha1_from_commit(const unsigned char *commit_sha1, + unsigned char *gitmodules_sha1, + struct strbuf *rev); void submodule_free(void); #endif /* SUBMODULE_CONFIG_H */ diff --git a/submodule.c b/submodule.c index f5107f0..062e58b 100644 --- a/submodule.c +++ b/submodule.c @@ -198,6 +198,18 @@ void gitmodules_config(void) } } +void gitmodules_config_sha1(const unsigned char *commit_sha1) +{ + struct strbuf rev = STRBUF_INIT; + unsigned char sha1[20]; + + if (gitmodule_sha1_from_commit(commit_sha1, sha1, &rev)) { + git_config_from_blob_sha1(submodule_config, rev.buf, + sha1, NULL); + } + strbuf_release(&rev); +} + /* * Determine if a submodule has been initialized at a given 'path' */ diff --git a/submodule.h b/submodule.h index 6ec5f2f..9203d89 100644 --- a/submodule.h +++ b/submodule.h @@ -37,6 +37,7 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt, const char *path); int submodule_config(const char *var, const char *value, void *cb); void gitmodules_config(void); +extern void gitmodules_config_sha1(const unsigned char *commit_sha1); extern int is_submodule_initialized(const char *path); extern int is_submodule_populated(const char *path); int parse_submodule_update_strategy(const char *value, -- 2.8.0.rc3.226.g39d4020
[PATCH v4 6/6] grep: search history of moved submodules
If a submodule was renamed at any point since it's inception then if you were to try and grep on a commit prior to the submodule being moved, you wouldn't be able to find a working directory for the submodule since the path in the past is different from the current path. This patch teaches grep to find the .git directory for a submodule in the parents .git/modules/ directory in the event the path to the submodule in the commit that is being searched differs from the state of the currently checked out commit. If found, the child process that is spawned to grep the submodule will chdir into its gitdir instead of a working directory. In order to override the explicit setting of submodule child process's gitdir environment variable (which was introduced in '10f5c526') `GIT_DIR_ENVIORMENT` needs to be pushed onto child process's env_array. This allows the searching of history from a submodule's gitdir, rather than from a working directory. Signed-off-by: Brandon Williams --- builtin/grep.c | 20 +-- t/t7814-grep-recurse-submodules.sh | 41 ++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/builtin/grep.c b/builtin/grep.c index 9b795ee..747b0c3 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -547,6 +547,7 @@ static int grep_submodule_launch(struct grep_opt *opt, name = gs->name; prepare_submodule_repo_env(&cp.env_array); + argv_array_push(&cp.env_array, GIT_DIR_ENVIRONMENT); /* Add super prefix */ argv_array_pushf(&cp.args, "--super-prefix=%s%s/", @@ -615,8 +616,23 @@ static int grep_submodule(struct grep_opt *opt, const unsigned char *sha1, { if (!is_submodule_initialized(path)) return 0; - if (!is_submodule_populated(path)) - return 0; + if (!is_submodule_populated(path)) { + /* +* If searching history, check for the presense of the +* submodule's gitdir before skipping the submodule. +*/ + if (sha1) { + const struct submodule *sub = + submodule_from_path(null_sha1, path); + if (sub) + path = git_path("modules/%s", sub->name); + + if(!(is_directory(path) && is_git_directory(path))) + return 0; + } else { + return 0; + } + } #ifndef NO_PTHREADS if (num_threads) { diff --git a/t/t7814-grep-recurse-submodules.sh b/t/t7814-grep-recurse-submodules.sh index d1fd7ed..7d66716 100755 --- a/t/t7814-grep-recurse-submodules.sh +++ b/t/t7814-grep-recurse-submodules.sh @@ -158,6 +158,47 @@ test_expect_success 'grep recurse submodule colon in name' ' test_cmp expect actual ' +test_expect_success 'grep history with moved submoules' ' + git init parent && + test_when_finished "rm -rf parent" && + echo "foobar" >parent/file && + git -C parent add file && + git -C parent commit -m "add file" && + + git init sub && + test_when_finished "rm -rf sub" && + echo "foobar" >sub/file && + git -C sub add file && + git -C sub commit -m "add file" && + + git -C parent submodule add ../sub dir/sub && + git -C parent commit -m "add submodule" && + + cat >expect <<-\EOF && + dir/sub/file:foobar + file:foobar + EOF + git -C parent grep -e "foobar" --recurse-submodules >actual && + test_cmp expect actual && + + git -C parent mv dir/sub sub-moved && + git -C parent commit -m "moved submodule" && + + cat >expect <<-\EOF && + file:foobar + sub-moved/file:foobar + EOF + git -C parent grep -e "foobar" --recurse-submodules >actual && + test_cmp expect actual && + + cat >expect <<-\EOF && + HEAD^:dir/sub/file:foobar + HEAD^:file:foobar + EOF + git -C parent grep -e "foobar" --recurse-submodules HEAD^ >actual && + test_cmp expect actual +' + test_incompatible_with_recurse_submodules () { test_expect_success "--recurse-submodules and $1 are incompatible" " -- 2.8.0.rc3.226.g39d4020
[PATCH v4 5/6] grep: enable recurse-submodules to work on objects
Teach grep to recursively search in submodules when provided with a object. This allows grep to search a submodule based on the state of the submodule that is present in a commit of the super project. When grep is provided with a object, the name of the object is prefixed to all output. In order to provide uniformity of output between the parent and child processes the option `--parent-basename` has been added so that the child can preface all of it's output with the name of the parent's object instead of the name of the commit SHA1 of the submodule. This changes output from the command `git grep -e. -l --recurse-submodules HEAD` from: HEAD:file :sub/file to: HEAD:file HEAD:sub/file Signed-off-by: Brandon Williams --- Documentation/git-grep.txt | 13 +- builtin/grep.c | 83 +++--- t/t7814-grep-recurse-submodules.sh | 75 +- 3 files changed, 162 insertions(+), 9 deletions(-) diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt index 17aa1ba..71f32f3 100644 --- a/Documentation/git-grep.txt +++ b/Documentation/git-grep.txt @@ -26,7 +26,7 @@ SYNOPSIS [--threads ] [-f ] [-e] [--and|--or|--not|(|)|-e ...] - [--recurse-submodules] + [--recurse-submodules] [--parent-basename ] [ [--[no-]exclude-standard] [--cached | --no-index | --untracked] | ...] [--] [...] @@ -91,7 +91,16 @@ OPTIONS --recurse-submodules:: Recursively search in each submodule that has been initialized and - checked out in the repository. + checked out in the repository. When used in combination with the +option the prefix of all submodule output will be the name of + the parent project's object. + +--parent-basename :: + For internal use only. In order to produce uniform output with the + --recurse-submodules option, this option can be used to provide the + basename of a parent's object to a submodule so the submodule + can prefix its output with the parent's name rather than the SHA1 of + the submodule. -a:: --text:: diff --git a/builtin/grep.c b/builtin/grep.c index cfafa15..9b795ee 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -19,6 +19,7 @@ #include "dir.h" #include "pathspec.h" #include "submodule.h" +#include "submodule-config.h" static char const * const grep_usage[] = { N_("git grep [] [-e] [...] [[--] ...]"), @@ -28,6 +29,7 @@ static char const * const grep_usage[] = { static const char *super_prefix; static int recurse_submodules; static struct argv_array submodule_options = ARGV_ARRAY_INIT; +static const char *parent_basename; static int grep_submodule_launch(struct grep_opt *opt, const struct grep_source *gs); @@ -534,19 +536,53 @@ static int grep_submodule_launch(struct grep_opt *opt, { struct child_process cp = CHILD_PROCESS_INIT; int status, i; + const char *end_of_base; + const char *name; struct work_item *w = opt->output_priv; + end_of_base = strchr(gs->name, ':'); + if (gs->identifier && end_of_base) + name = end_of_base + 1; + else + name = gs->name; + prepare_submodule_repo_env(&cp.env_array); /* Add super prefix */ argv_array_pushf(&cp.args, "--super-prefix=%s%s/", super_prefix ? super_prefix : "", -gs->name); +name); argv_array_push(&cp.args, "grep"); + /* +* Add basename of parent project +* When performing grep on a tree object the filename is prefixed +* with the object's name: 'tree-name:filename'. In order to +* provide uniformity of output we want to pass the name of the +* parent project's object name to the submodule so the submodule can +* prefix its output with the parent's name and not its own SHA1. +*/ + if (gs->identifier && end_of_base) + argv_array_pushf(&cp.args, "--parent-basename=%.*s", +(int) (end_of_base - gs->name), +gs->name); + /* Add options */ - for (i = 0; i < submodule_options.argc; i++) + for (i = 0; i < submodule_options.argc; i++) { + /* +* If there is a tree identifier for the submodule, add the +* rev after adding the submodule options but before the +* pathspecs. To do this we listen for the '--' and insert the +* sha1 before pushing the '--' onto the child process argv +* array. +*/ + if (gs->identifier && + !strcmp("--", submodule_options.argv[i])) { + argv_array_push(&cp.args, sha1_to_hex(gs->identifier)); + } +
[PATCH v4 1/6] submodules: add helper functions to determine presence of submodules
Add two helper functions to submodules.c. `is_submodule_initialized()` checks if a submodule has been initialized at a given path and `is_submodule_populated()` check if a submodule has been checked out at a given path. Signed-off-by: Brandon Williams --- submodule.c | 38 ++ submodule.h | 2 ++ 2 files changed, 40 insertions(+) diff --git a/submodule.c b/submodule.c index 6f7d883..f5107f0 100644 --- a/submodule.c +++ b/submodule.c @@ -198,6 +198,44 @@ void gitmodules_config(void) } } +/* + * Determine if a submodule has been initialized at a given 'path' + */ +int is_submodule_initialized(const char *path) +{ + int ret = 0; + const struct submodule *module = NULL; + + module = submodule_from_path(null_sha1, path); + + if (module) { + char *key = xstrfmt("submodule.%s.url", module->name); + char *value = NULL; + + ret = !git_config_get_string(key, &value); + + free(value); + free(key); + } + + return ret; +} + +/* + * Determine if a submodule has been populated at a given 'path' + */ +int is_submodule_populated(const char *path) +{ + int ret = 0; + char *gitdir = xstrfmt("%s/.git", path); + + if (resolve_gitdir(gitdir)) + ret = 1; + + free(gitdir); + return ret; +} + int parse_submodule_update_strategy(const char *value, struct submodule_update_strategy *dst) { diff --git a/submodule.h b/submodule.h index d9e197a..6ec5f2f 100644 --- a/submodule.h +++ b/submodule.h @@ -37,6 +37,8 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt, const char *path); int submodule_config(const char *var, const char *value, void *cb); void gitmodules_config(void); +extern int is_submodule_initialized(const char *path); +extern int is_submodule_populated(const char *path); int parse_submodule_update_strategy(const char *value, struct submodule_update_strategy *dst); const char *submodule_strategy_to_string(const struct submodule_update_strategy *s); -- 2.8.0.rc3.226.g39d4020
[PATCH v4 0/6] recursively grep across submodules
This revision of this series should address all of the problems brought up with v3. * indent output example in patch 5/6. * fix ':' in submodule names and add a test to verify. * cleanup some comments. * fixed tests to test the case where a submodule isn't at the root of a repository. * always pass --threads=%d in order to limit threads to child proccess. Brandon Williams (6): submodules: add helper functions to determine presence of submodules submodules: load gitmodules file from commit sha1 grep: add submodules as a grep source type grep: optionally recurse into submodules grep: enable recurse-submodules to work on objects grep: search history of moved submodules Documentation/git-grep.txt | 14 ++ builtin/grep.c | 393 ++--- cache.h| 2 + config.c | 8 +- git.c | 2 +- grep.c | 16 +- grep.h | 1 + submodule-config.c | 6 +- submodule-config.h | 3 + submodule.c| 50 + submodule.h| 3 + t/t7814-grep-recurse-submodules.sh | 213 12 files changed, 679 insertions(+), 32 deletions(-) create mode 100755 t/t7814-grep-recurse-submodules.sh -- interdiff based on 'bw/grep-recurse-submodules' diff --git a/builtin/grep.c b/builtin/grep.c index 1cd2be9..747b0c3 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -518,9 +518,8 @@ static void compile_submodule_options(const struct grep_opt *opt, * This is to prevent potential fork-bomb behavior of git-grep as each * submodule process has its own thread pool. */ - if (num_threads) - argv_array_pushf(&submodule_options, "--threads=%d", -(num_threads + 1) / 2); + argv_array_pushf(&submodule_options, "--threads=%d", +(num_threads + 1) / 2); /* Add Pathspecs */ argv_array_push(&submodule_options, "--"); @@ -542,7 +541,7 @@ static int grep_submodule_launch(struct grep_opt *opt, struct work_item *w = opt->output_priv; end_of_base = strchr(gs->name, ':'); - if (end_of_base) + if (gs->identifier && end_of_base) name = end_of_base + 1; else name = gs->name; @@ -558,13 +557,13 @@ static int grep_submodule_launch(struct grep_opt *opt, /* * Add basename of parent project -* When performing grep on a object the filename is prefixed -* with the object's name: ':filename'. In order to +* When performing grep on a tree object the filename is prefixed +* with the object's name: 'tree-name:filename'. In order to * provide uniformity of output we want to pass the name of the * parent project's object name to the submodule so the submodule can * prefix its output with the parent's name and not its own SHA1. */ - if (end_of_base) + if (gs->identifier && end_of_base) argv_array_pushf(&cp.args, "--parent-basename=%.*s", (int) (end_of_base - gs->name), gs->name); @@ -572,7 +571,7 @@ static int grep_submodule_launch(struct grep_opt *opt, /* Add options */ for (i = 0; i < submodule_options.argc; i++) { /* -* If there is a identifier for the submodule, add the +* If there is a tree identifier for the submodule, add the * rev after adding the submodule options but before the * pathspecs. To do this we listen for the '--' and insert the * sha1 before pushing the '--' onto the child process argv @@ -615,17 +614,20 @@ static int grep_submodule_launch(struct grep_opt *opt, static int grep_submodule(struct grep_opt *opt, const unsigned char *sha1, const char *filename, const char *path) { - if (!(is_submodule_initialized(path) && - is_submodule_populated(path))) { + if (!is_submodule_initialized(path)) + return 0; + if (!is_submodule_populated(path)) { /* * If searching history, check for the presense of the * submodule's gitdir before skipping the submodule. */ if (sha1) { - path = git_path("modules/%s", - submodule_from_path(null_sha1, path)->name); + const struct submodule *sub = + submodule_from_path(null_sha1, path); + if (sub) + path = git_path("modules/%s", sub->name); - if (!(is_directory(path) && is_git_directory(path))
Re: [PATCH v7 03/17] ref-filter: implement %(if:equals=) and %(if:notequals=)
W dniu 08.11.2016 o 21:11, Karthik Nayak pisze: > From: Karthik Nayak > > Implement %(if:equals=) wherein the if condition is only > satisfied if the value obtained between the %(if:...) and %(then) atom > is the same as the given ''. > > Similarly, implement (if:notequals=) wherein the if condition > is only satisfied if the value obtained between the %(if:...) and > %(then) atom is differnt from the given ''. s/differnt/different/ <-- typo > > This is done by introducing 'if_atom_parser()' which parses the given > %(if) atom and then stores the data in used_atom which is later passed > on to the used_atom of the %(then) atom, so that it can do the required > comparisons. Nb. the syntax reminds me a bit of RPM SPEC language. > > Add tests and Documentation for the same. > > Mentored-by: Christian Couder > Mentored-by: Matthieu Moy > Signed-off-by: Karthik Nayak > --- > Documentation/git-for-each-ref.txt | 3 +++ > ref-filter.c | 43 > +- > t/t6302-for-each-ref-filter.sh | 18 > 3 files changed, 59 insertions(+), 5 deletions(-) > > diff --git a/Documentation/git-for-each-ref.txt > b/Documentation/git-for-each-ref.txt > index fed8126..b7b8560 100644 > --- a/Documentation/git-for-each-ref.txt > +++ b/Documentation/git-for-each-ref.txt > @@ -155,6 +155,9 @@ if:: > evaluating the string before %(then), this is useful when we > use the %(HEAD) atom which prints either "*" or " " and we > want to apply the 'if' condition only on the 'HEAD' ref. So %(if) is actually %(if:notempty) ? Just kidding. > + Append ":equals=" or ":notequals=" to compare > + the value between the %(if:...) and %(then) atoms with the > + given string. > > In addition to the above, for commit and tag objects, the header > field names (`tree`, `parent`, `object`, `type`, and `tag`) can > diff --git a/ref-filter.c b/ref-filter.c > index 8392303..44481c3 100644 > --- a/ref-filter.c > +++ b/ref-filter.c > @@ -22,6 +22,8 @@ struct align { > }; > > struct if_then_else { > + const char *if_equals, > + *not_equals; I guess using anonymous structs from C11 here... > unsigned int then_atom_seen : 1, > else_atom_seen : 1, > condition_satisfied : 1; > @@ -49,6 +51,10 @@ static struct used_atom { > enum { C_BARE, C_BODY, C_BODY_DEP, C_LINES, C_SIG, > C_SUB } option; > unsigned int nlines; > } contents; > + struct { > + const char *if_equals, > + *not_equals; > + } if_then_else; ...to avoid code duplication there is rather out of question? > enum { O_FULL, O_SHORT } objectname; > } u; > } *used_atom; > @@ -169,6 +175,19 @@ static void align_atom_parser(struct used_atom *atom, > const char *arg) > string_list_clear(¶ms, 0); > } > > +static void if_atom_parser(struct used_atom *atom, const char *arg) > +{ > + if (!arg) > + return; > + else if (skip_prefix(arg, "equals=", &atom->u.if_then_else.if_equals)) > + ; > + else if (skip_prefix(arg, "notequals=", > &atom->u.if_then_else.not_equals)) > + ; Those ';' should be perfectly aligned, isn't it? [...] > +test_expect_success 'check %(if:equals=)' ' > + git for-each-ref > --format="%(if:equals=master)%(refname:short)%(then)Found master%(else)Not > master%(end)" refs/heads/ >actual && > + cat >expect <<-\EOF && > + Found master > + Not master > + EOF > + test_cmp expect actual > +' > + > +test_expect_success 'check %(if:notequals=)' ' > + git for-each-ref > --format="%(if:notequals=master)%(refname:short)%(then)Not master%(else)Found > master%(end)" refs/heads/ >actual && > + cat >expect <<-\EOF && > + Found master > + Not master > + EOF > + test_cmp expect actual > +' Nice! -- Jakub Narębski
Re: [PATCH 11/16] teach unpack_trees() to remove submodule contents
On Thu, Nov 17, 2016 at 5:35 AM, Heiko Voigt wrote: > On Tue, Nov 15, 2016 at 03:06:46PM -0800, Stefan Beller wrote: >> Extend rmdir_or_warn() to remove the directories of those submodules which >> are scheduled for removal. Also teach verify_clean_submodule() to check >> that a submodule configured to be removed is not modified before scheduling >> it for removal. >> >> Signed-off-by: Stefan Beller >> --- > [...] >> --- a/wrapper.c >> +++ b/wrapper.c >> @@ -2,6 +2,7 @@ >> * Various trivial helper wrappers around standard functions >> */ >> #include "cache.h" >> +#include "submodule.h" >> >> static void do_nothing(size_t size) >> { >> @@ -592,6 +593,9 @@ int unlink_or_warn(const char *file) >> >> int rmdir_or_warn(const char *file) >> { >> + if (submodule_is_interesting(file, null_sha1) >> + && depopulate_submodule(file)) >> + return -1; > > How about untracked files inside submodules? Should we not care about > them? With this code the entire directory will be removed. In general > git would not remove a directory with untracked files in it even though > it is removed in the database. I wonder if we should imitate that here > and just remove files that are tracked by git so that users do not loose > files that might be precious to them. Well from the superprojects perspective a submodule looks like a file, so if the checkout involved removing a file it had to either be clean or the checkout failed. So I though we'd go with a similar way here? We need to stop when untracked files are present, I am not sure if we need to care if the files are ignored, though. In this version of the series, the test added in patch 14, testing for treating untracked files properly is a failing test. So I agree that we should not just delete them; I'll fix that in the next version of the series. Thanks, Stefan
Re: [PATCH] remote-curl: don't hang when a server dies before any output
Jeff King writes: > So I don't feel like we have a good patch for the general case yet, and > I'm probably not going to get around to implementing it anytime soon. So > I'd suggest taking David's original patch (to punt when the response is > empty) in the meantime. Yup, we are on the same page; the above matches what I wrote in the draft of the next issue of What's cooking report last night. > I do think the commit message could be improved based on the discussion > here, though (at the very least to describe the nature of the deadlock, > and that we are choosing only one of the possible solutions, and why). Thanks. That sounds sensible.
Re: [PATCH 08/16] update submodules: add depopulate_submodule
On Fri, Nov 18, 2016 at 9:46 AM, Brandon Williams wrote: >> + >> + sub = submodule_from_path(null_sha1, path); > > This should probably be checked to see if sub not NULL before > dereferencing it right? yeah, will fix.
Re: [PATCH v7 13/17] ref-filter: add `:dir` and `:base` options for ref printing atoms
Jacob Keller writes: to get remotes from /refs/foo/abc/xyz we'd need to do strip=1,strip=-1, which could be done but ... >>> >>> ... would be unnecessary if this is the only use case: >>> strbuf_addf(&fmt, "%%(if:notequals=remotes)%%(refname:base)%%(then)%s%%(else)%s%%(end)", local.buf, remote.buf); >>> >>> You can "strip to leave only 2 components" and compare the result >>> with refs/remotes instead, no? >>> >> >> Of course, my only objective was that someone would find it useful to >> have these two additional >> atoms. So if you think it's unnecessary we could drop it entirely :D >> >> -- >> Regards, >> Karthik Nayak > > I think having strip and rstrip make sense, (along with support for > negative numbers) I don't think we need to make them work together > unless someone is interested, since we can use strip=-2 to get the > behavior we need today. I am OK with multiple strips Karthik suggests, e.g. %(refname:strip=1,rstrip=-1) if it is cleanly implemented. I have a bit of trouble with these names, though. If we call one strip and the other rstrip, to only those who know about rstrip it would be clear that strip is about stripping from the left. Perhaps we should call it lstrip for symmetry and ease-of-remembering? refs/heads/master:lstrip=-1 => master (strip all but one level from the left) refs/heads/master:rstrip=-2 => refs/heads (strip all but two levels from the right) refs/heads/master:lstrip=1,rstrip=-1 => heads (strip one level from the left and then strip all but one level from the right) I dunno.
lening bieden
Goede dag, Dit is Lloyd's TSB Bank plc leningen aan te bieden. Lloyds TSB biedt flexibele en betaalbare leningen voor welk doel u te helpen uw doelen te bereiken. we lening tegen lage rente van 3%. Hier zijn een aantal belangrijke kenmerken van de persoonlijke lening aangeboden door Lloyd's TSB. Hier zijn de Loan Factoren we werken met de toonaangevende Britse makelaars die toegang hebben tot de top kredietverstrekkers hebben en in staat zijn om de beste financiële oplossing tegen een betaalbare price.Please vinden als u geïnteresseerd bent vriendelijk contact met ons op via deze e-mail: lloyds26...@gmail.com Na de reactie, zal u een aanvraag voor een lening te vullen ontvangen. Geen sociale zekerheid en geen credit check, 100% gegarandeerd. Het zal ons een eer zijn als u ons toelaten om u van dienst zijn. INFORMATIE NODIG Jullie namen Adres: ... Telefoon: ... Benodigd Duur: ... Bezetting: ... Maandelijks Inkomen Level: Geslacht: ... Geboortedatum: Staat: .. Land: .. Doel: . Ontmoeting uw financiële behoeften is onze trots. Dr.John Mahama.
[PATCH v2] remote-curl: don't hang when a server dies before any output
In the event that a HTTP server closes the connection after giving a 200 but before giving any packets, we don't want to hang forever waiting for a response that will never come. Instead, we should die immediately. One case where this happens is when attempting to fetch a dangling object by SHA. Prior to this patch, fetch-pack would wait for more data from the server, and remote-curl would wait for fetch-pack, causing a deadlock. Despite this patch, there is other possible malformed input that could cause the same deadlock (e.g. a half-finished pktline, or a pktline but no trailing flush). There are a few possible solutions to this: 1. Allowing remote-curl to tell fetch-pack about the EOF (so that fetch-pack could know that no more data is coming until it says something else). This is tricky because an out-of-band signal would be required, or the http response would have to be re-framed inside another layer of pkt-line or something. 2. Make remote-curl understand some of the protocol. It turns out that in addition to understanding pkt-line, it would need to watch for ack/nak. This is somewhat fragile, as information about the protocol would end up in two places. Also, pkt-lines which are already at the length limit would need special handling. Both of these solutions would require a fair amount of work, whereas this hack is easy and solves at least some of the problem. Still to do: it would be good to give a better error message than "fatal: The remote end hung up unexpectedly". Signed-off-by: David Turner Signed-off-by: Junio C Hamano --- remote-curl.c | 8 t/t5551-http-fetch-smart.sh | 30 ++ 2 files changed, 38 insertions(+) diff --git a/remote-curl.c b/remote-curl.c index f14c41f..ee44236 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -400,6 +400,7 @@ struct rpc_state { size_t pos; int in; int out; + int any_written; struct strbuf result; unsigned gzip_request : 1; unsigned initial_buffer : 1; @@ -456,6 +457,8 @@ static size_t rpc_in(char *ptr, size_t eltsize, { size_t size = eltsize * nmemb; struct rpc_state *rpc = buffer_; + if (size) + rpc->any_written = 1; write_or_die(rpc->in, ptr, size); return size; } @@ -659,6 +662,8 @@ static int post_rpc(struct rpc_state *rpc) curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, rpc_in); curl_easy_setopt(slot->curl, CURLOPT_FILE, rpc); + + rpc->any_written = 0; err = run_slot(slot, NULL); if (err == HTTP_REAUTH && !large_request) { credential_fill(&http_auth); @@ -667,6 +672,9 @@ static int post_rpc(struct rpc_state *rpc) if (err != HTTP_OK) err = -1; + if (!rpc->any_written) + err = -1; + curl_slist_free_all(headers); free(gzip_body); return err; diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh index 1ec5b27..43665ab 100755 --- a/t/t5551-http-fetch-smart.sh +++ b/t/t5551-http-fetch-smart.sh @@ -276,6 +276,36 @@ test_expect_success 'large fetch-pack requests can be split across POSTs' ' test_line_count = 2 posts ' +test_expect_success 'test allowreachablesha1inwant' ' + test_when_finished "rm -rf test_reachable.git" && + server="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + master_sha=$(git -C "$server" rev-parse refs/heads/master) && + git -C "$server" config uploadpack.allowreachablesha1inwant 1 && + + git init --bare test_reachable.git && + git -C test_reachable.git remote add origin "$HTTPD_URL/smart/repo.git" && + git -C test_reachable.git fetch origin "$master_sha" +' + +test_expect_success 'test allowreachablesha1inwant with unreachable' ' + test_when_finished "rm -rf test_reachable.git; git reset --hard $(git rev-parse HEAD)" && + + #create unreachable sha + echo content >file2 && + git add file2 && + git commit -m two && + git push public HEAD:refs/heads/doomed && + git push public :refs/heads/doomed && + + server="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + master_sha=$(git -C "$server" rev-parse refs/heads/master) && + git -C "$server" config uploadpack.allowreachablesha1inwant 1 && + + git init --bare test_reachable.git && + git -C test_reachable.git remote add origin "$HTTPD_URL/smart/repo.git" && + test_must_fail git -C test_reachable.git fetch origin "$(git rev-parse HEAD)" +' + test_expect_success EXPENSIVE 'http can handle enormous ref negotiation' ' ( cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && -- 2.8.0.rc4.22.g8ae061a
Re: [PATCH 08/16] update submodules: add depopulate_submodule
On 11/17, Stefan Beller wrote: > On Thu, Nov 17, 2016 at 2:42 PM, Stefan Beller wrote: > > > > I think I'll just write this functionality in C and optionally expose > > it via the submodule--helper, > > such that the user facing git-submodule.sh only has to call that helper. > > I think it will roughly look like this: > (white space mangled) > > > commit e72ef244c667920c874247aa32aa55845500aac8 > Author: Stefan Beller > Date: Thu Nov 17 16:14:46 2016 -0800 > > submodule--helper: add intern-git-dir function > > When a submodule has its git dir inside the working dir, the submodule > support for checkout that we plan to add in a later patch will fail. > > Add functionality to migrate the git directory to be embedded > into the superprojects git directory. > > Signed-off-by: Stefan Beller > > diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c > index 4beeda5..4f31100 100644 > --- a/builtin/submodule--helper.c > +++ b/builtin/submodule--helper.c > @@ -1076,6 +1076,21 @@ static int resolve_remote_submodule_branch(int > argc, const char **argv, > return 0; > } > > +static int intern_git_dir(int argc, const char **argv, const char *prefix) > +{ > + int i; > + struct pathspec pathspec; > + struct module_list list = MODULE_LIST_INIT; > + > + if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0) > + return 1; > + > + for (i = 0; i < list.nr; i++) > + migrate_submodule_gitdir(list.entries[i]->name); > + > + return 0; > +} > + > struct cmd_struct { > const char *cmd; > int (*fn)(int, const char **, const char *); > @@ -1090,7 +1105,8 @@ static struct cmd_struct commands[] = { > {"resolve-relative-url", resolve_relative_url}, > {"resolve-relative-url-test", resolve_relative_url_test}, > {"init", module_init}, > - {"remote-branch", resolve_remote_submodule_branch} > + {"remote-branch", resolve_remote_submodule_branch}, > + {"intern-git-dir", intern_git_dir} > }; > > int cmd_submodule__helper(int argc, const char **argv, const char *prefix) > diff --git a/submodule.c b/submodule.c > index 45b9060..e513bba 100644 > --- a/submodule.c > +++ b/submodule.c > @@ -1335,3 +1335,42 @@ void prepare_submodule_repo_env(struct argv_array *out) > } > argv_array_push(out, "GIT_DIR=.git"); > } > + > +/* > + * Migrate the given submodule (and all its submodules recursively) from > + * having its git directory within the working tree to the git dir nested > + * in its superprojects git dir under modules/. > + */ > +void migrate_submodule_gitdir(const char *path) > +{ > + char *old_git_dir; > + const char *new_git_dir; > + const struct submodule *sub; > + > + struct child_process cp = CHILD_PROCESS_INIT; > + cp.git_cmd = 1; > + cp.no_stdin = 1; > + cp.dir = path; > + argv_array_pushl(&cp.args, "submodule", "foreach", "--recursive", > + "git", "submodule--helper" "intern-git-dir", NULL); > + > + if (run_command(&cp)) > + die(_("Could not migrate git directory in submodule '%s'"), > + path); > + > + old_git_dir = xstrfmt("%s/.git", path); > + if (read_gitfile(old_git_dir)) > + /* If it is an actual gitfile, it doesn't need migration. */ > + goto out; > + > + sub = submodule_from_path(null_sha1, path); This should probably be checked to see if sub not NULL before dereferencing it right? > + new_git_dir = git_common_path("modules/%s", sub->name); > + > + if (rename(old_git_dir, new_git_dir) < 0) > + die_errno(_("Could not migrate git directory from %s to %s"), > + old_git_dir, new_git_dir); > + > + connect_work_tree_and_git_dir(path, new_git_dir); > +out: > + free(old_git_dir); > +} > diff --git a/submodule.h b/submodule.h > index aac202c..143ec18 100644 > --- a/submodule.h > +++ b/submodule.h > @@ -90,5 +90,6 @@ extern int parallel_submodules(void); > * retaining any config in the environment. > */ > extern void prepare_submodule_repo_env(struct argv_array *out); > +extern void migrate_submodule_gitdir(const char *path); > > #endif -- Brandon Williams
RE: [PATCH] remote-curl: don't hang when a server dies before any output
> -Original Message- > From: Jeff King [mailto:p...@peff.net] > Sent: Friday, November 18, 2016 12:09 PM > To: David Turner > Cc: Junio C Hamano; git@vger.kernel.org; spea...@spearce.org > Subject: Re: [PATCH] remote-curl: don't hang when a server dies before any > output > > On Fri, Nov 18, 2016 at 05:04:59PM +, David Turner wrote: > > > > So I don't feel like we have a good patch for the general case yet, > > > and I'm probably not going to get around to implementing it anytime > > > soon. > > > > I'm confused -- it sounds like your patch actually does work (that is, > > that Junio's failure was not caused by your patch but by the absence > > of our patches). And your patch handles more cases than mine. So we > > should probably use it instead of mine. > > No, mine passes the vanilla test suite, but fails with GIT_TEST_LONG. > If the want/have negotiation takes multiple rounds, the intermediate > rounds don't end on a flush packet, and my patch causes remote-curl to > complain that the response was truncated. > > I think you could fix it by teaching remote-curl that the final packet > must be a flush _or_ contain an ACK/NAK, but I didn't try it. That's > getting a bit invasive and brittle. OK, I'll re-roll mine with a better message.
Re: [PATCH] remote-curl: don't hang when a server dies before any output
On Fri, Nov 18, 2016 at 05:04:59PM +, David Turner wrote: > > So I don't feel like we have a good patch for the general case yet, > > and I'm probably not going to get around to implementing it anytime > > soon. > > I'm confused -- it sounds like your patch actually does work (that is, > that Junio's failure was not caused by your patch but by the absence > of our patches). And your patch handles more cases than mine. So we > should probably use it instead of mine. No, mine passes the vanilla test suite, but fails with GIT_TEST_LONG. If the want/have negotiation takes multiple rounds, the intermediate rounds don't end on a flush packet, and my patch causes remote-curl to complain that the response was truncated. I think you could fix it by teaching remote-curl that the final packet must be a flush _or_ contain an ACK/NAK, but I didn't try it. That's getting a bit invasive and brittle. -Peff
RE: [PATCH] remote-curl: don't hang when a server dies before any output
> -Original Message- > From: Jeff King [mailto:p...@peff.net] > Sent: Friday, November 18, 2016 12:02 PM > To: Junio C Hamano > Cc: David Turner; git@vger.kernel.org; spea...@spearce.org > Subject: Re: [PATCH] remote-curl: don't hang when a server dies before any > output > > On Tue, Nov 15, 2016 at 09:42:57AM -0800, Junio C Hamano wrote: > > > >> Hmph. I think I tried David's original under GIT_TEST_LONG and saw > > >> it got stuck; could be the same issue, I guess. > > > > > > It works OK here. I think it is just that the test is really slow > > > (by design). > > > > Yeah, I think what I recalled was my old attempt to run the follow-up > > "any SHA-1" patch without this one. > > Right, that makes sense. > > So I don't feel like we have a good patch for the general case yet, and > I'm probably not going to get around to implementing it anytime soon. I'm confused -- it sounds like your patch actually does work (that is, that Junio's failure was not caused by your patch but by the absence of our patches). And your patch handles more cases than mine. So we should probably use it instead of mine.
Re: [PATCH] remote-curl: don't hang when a server dies before any output
On Tue, Nov 15, 2016 at 09:42:57AM -0800, Junio C Hamano wrote: > >> Hmph. I think I tried David's original under GIT_TEST_LONG and saw > >> it got stuck; could be the same issue, I guess. > > > > It works OK here. I think it is just that the test is really slow (by > > design). > > Yeah, I think what I recalled was my old attempt to run the > follow-up "any SHA-1" patch without this one. Right, that makes sense. So I don't feel like we have a good patch for the general case yet, and I'm probably not going to get around to implementing it anytime soon. So I'd suggest taking David's original patch (to punt when the response is empty) in the meantime. It doesn't fix all cases, but if fixes _a_ case, and probably one of the most likely one in practice. I don't think it can cause any regressions. It's a "snooping" solution like mine, but it makes many fewer assumptions about the protocol. We know that an empty response cannot possibly advance fetch-pack further because we won't have sent it any bytes. :) I do think the commit message could be improved based on the discussion here, though (at the very least to describe the nature of the deadlock, and that we are choosing only one of the possible solutions, and why). -Peff
RE: merge --no-ff is NOT mentioned in help
> On Thu, Nov 17, 2016 at 09:10:22AM -0800, Junio C Hamano wrote: > > > People interested may want to try the attached single-liner patch to > > see how the output from _ALL_ commands that use parse-options API > > looks when given "-h". It could be that the result may not be too > > bad. > > The output is less ugly than I expected, but still a bit cluttered IMHO. > I was surprised that the column-adjustment did not need tweaked, but the code > correctly increments "pos" from the return value of fprintf, which just works. > > Looking at the output for --ff, though: > >--[no-]ff allow fast-forward (default) > > I do not think it's improving the situation nearly as much as if we made the > primary option "--no-ff" with a NONEG flga, and then added back in a HIDDEN > "--ff". I thought we had done that in other cases, but I can't seem to find > any. But it would make "--no-ff" the primary form, which makes sense, as > "--ff" is already the default. > > Another option would be to teach parse-options to somehow treat the negated > form as primary in the help text. That's a bit more code, but might be usable > in other places. > > -Peff > What about leaving the help as is, but adding a sentence at the end (or beginning?) like: "The following options may be negated by adding 'no-' after the double dashes"? This e-mail, including attachments, may include confidential and/or proprietary information, and may be used only by the person or entity to which it is addressed. If the reader of this e-mail is not the intended recipient or his or her authorized agent, the reader is hereby notified that any dissemination, distribution or copying of this e-mail is prohibited. If you have received this e-mail in error, please notify the sender by replying to this message and delete this e-mail immediately.
Re: [PATCH v1 12/19] Documentation/config: add splitIndex.maxPercentChange
On Mon, Nov 7, 2016 at 10:38 AM, Duy Nguyen wrote: > (sorry I got sick in the last few weeks and could not respond to this earlier) (Yeah, I have also been sick during the last few weeks.) > On Mon, Nov 7, 2016 at 4:44 AM, Christian Couder > wrote: >> Le 6 nov. 2016 09:16, "Junio C Hamano" a écrit : >>> >>> Christian Couder writes: >>> >>> > I think it is easier for user to be able to just set core.splitIndex >>> > to true to enable split-index. >>> >>> You can have that exact benefit by making core.splitIndex to >>> bool-or-more. If your default is 20%, take 'true' as if the user >>> specified 20% and take 'false' as if the user specified 100% (or is >>> it 0%? I do not care about the details but you get the point). > >> Then if we ever add 'auto' and the user wants for example 10% instead of the >> default 20%, we will have to make it accept things like "auto,10". (Sorry for writing the above on my phone which added HTML, so that it didn't reach the list.) > In my opinion, "true" _is_ auto, which is a way to say "I trust you to > do the right thing, just re-split the index when it makes sense", "no" > is disabled of course. If the user wants to be specific, just write > "10" or some other percentage.(and either 0 or 100 would mean enable > split-index but do not re-split automatically, let _me_ do it when I > want it) The meaning of a future "auto" option for "core.splitIndex" could be "use the split-index feature only if the number of entries in whole index is greater than 1 (by default)". If there is no difference between "true" and "auto" then, when users who have "core.splitIndex=true" will migrate to the git version that adds the "auto" feature, their repos with under 1 entires will not use the split-index feature anymore. These users may then be annoyed that the behavior has been switched under them, and that the split-index feature is not always used despite having "core.splitIndex=true" in their config.
Staging chunks can get confused
Tonight I was staging changes with `git add -p` and noticed they got applied at the *wrong* location. My guess is that when you stage a hunk it doesn't do a line number fix-up for earlier unstaged hunks in the file. Screencast: https://asciinema.org/a/7y9qhr0837a7t96m8w14mupnk Alternatively, an example follows: $ git add -p diff --git a/unistring/unistring.c b/unistring/unistring.c index 62bbc8a..45ced5d 100644 --- a/unistring/unistring.c +++ b/unistring/unistring.c @@ -17,6 +17,27 @@ static const char *const uninormnames[] = {"NFD", "NFC", "NFKD", "NFKC", NULL}; #define lunistring_optuninorm(L, arg) (lua_isnoneornil(L,(arg))?NULL:lunistring_checkuninorm((L), (arg))) +const uint8_t * u8_check (const uint8_t *s, size_t n); +int u8_mblen (const uint8_t *s, size_t n); +int u8_mbtouc_unsafe (ucs4_t *puc, const uint8_t *s, size_t n); +int u8_mbtouc (ucs4_t *puc, const uint8_t *s, size_t n); +int u8_mbtoucr (ucs4_t *puc, const uint8_t *s, size_t n); +int u8_uctomb (uint8_t *s, ucs4_t uc, int n); +size_t u8_mbsnlen (const uint8_t *s, size_t n); + +int u8_strmblen (const uint8_t *s); +int u8_strmbtouc (ucs4_t *puc, const uint8_t *s); +const uint8_t * u8_next (ucs4_t *puc, const uint8_t *s); +const uint8_t * u8_prev (ucs4_t *puc, const uint8_t *s, const uint8_t *start); + +uint8_t * u8_conv_from_encoding (const char *fromcode, enum iconv_ilseq_handler handler, const char *src, size_t srclen, size_t *offsets, uint8_t *resultbuf, size_t *lengthp); +char * u8_conv_to_encoding (const char *tocode, enum iconv_ilseq_handler handler, const uint8_t *src, size_t srclen, size_t *offsets, char *resultbuf, size_t *lengthp); +uint8_t * u8_strconv_from_encoding (const char *string, const char *fromcode, enum iconv_ilseq_handler handler); +char * u8_strconv_to_encoding (const uint8_t *string, const char *tocode, enum iconv_ilseq_handler handler); +uint8_t * u8_strconv_from_locale (const char *string); +char * u8_strconv_to_locale (const uint8_t *string); + + static int lunistring_width(lua_State *L) { size_t n; const uint8_t *s = (const uint8_t*)luaL_checklstring(L, 1, &n); Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? n @@ -27,6 +48,17 @@ static int lunistring_width(lua_State *L) { } +int u8_strwidth (const uint8_t *s, const char *encoding); +void u8_wordbreaks (const uint8_t *s, size_t n, char *p); +void u8_possible_linebreaks (const uint8_t *s, size_t n, const char *encoding, char *p); +int u8_width_linebreaks (const uint8_t *s, size_t n, int width, int start_column, int at_end_columns, const char *override, const char *encoding, char *p); + + +int uc_decomposition (ucs4_t uc, int *decomp_tag, ucs4_t *decomposition); +int uc_canonical_decomposition (ucs4_t uc, ucs4_t *decomposition); +ucs4_t uc_composition (ucs4_t uc1, ucs4_t uc2); + + static int lunistring_normalize(lua_State *L) { uninorm_t nf = lunistring_optuninorm(L, 1); size_t n; Stage this hunk [y,n,q,a,d,/,K,j,J,g,e,?]? n @@ -54,6 +86,9 @@ static int lunistring_normalize(lua_State *L) { } +int u8_normcmp (const uint8_t *s1, size_t n1, const uint8_t *s2, size_t n2, uninorm_t nf, int *resultp); + + static int lunistring_normxfrm(lua_State *L) { size_t n; const uint8_t *s = (const uint8_t*)luaL_checklstring(L, 1, &n); Stage this hunk [y,n,q,a,d,/,K,j,J,g,e,?]? n @@ -83,6 +118,9 @@ static int lunistring_normxfrm(lua_State *L) { } +int u8_normcoll (const uint8_t *s1, size_t n1, const uint8_t *s2, size_t n2, uninorm_t nf, int *resultp); + + static int lunistring_uc_locale_language(lua_State *L) { lua_pushstring(L, uc_locale_language()); return 1; Stage this hunk [y,n,q,a,d,/,K,j,J,g,e,?]? n @@ -173,6 +211,15 @@ static int lunistring_totitle(lua_State *L) { } +casing_prefix_context_t u8_casing_prefix_context (const uint8_t *s, size_t n); +casing_prefix_context_t u8_casing_prefixes_context (const uint8_t *s, size_t n, casing_prefix_context_t a_context); +casing_suffix_context_t u8_casing_suffix_context (const uint8_t *s, size_t n); +casing_suffix_context_t u8_casing_suffixes_context (const uint8_t *s, size_t n, casing_suffix_context_t a_context); +uint8_t * u8_ct_toupper (const uint8_t *s, size_t n, casing_prefix_context_t prefix_context, casing_suffix_context_t suffix_context, const char *iso639_language, uninorm_t nf, uint8_t *resultbuf, size_t *lengthp); +uint8_t * u8_ct_tolower (const uint8_t *s, size_t n, casing_prefix_context_t prefix_context, casing_suffix_context_t suffix_context, const char *iso639_language, uninorm_t nf, uint8_t *resultbuf, size_t *lengthp); +uint8_t * u8_ct_totitle (const uint8_t *s, size_t n, casing_prefix_context_t prefix_context, casing_suffix_context_t suffix_context, const char *iso639_language, uninorm_t nf, uint8_t *resultbuf, size_t *lengthp); + + static int lunistring_casefold(lua_State *L) { size_t n; const uint8_t *s = (const uint8_t*)luaL_checklstring(L, 1, &n); Stage this hunk [y,n,q,a,d,/,K,j,J,g,e,?]? n @@ -201,6 +248,10 @@ static int lunistring_casefold(lua_State *L) { } +uint8_t * u8_ct_casefo
Re: [PATCH v7 13/17] ref-filter: add `:dir` and `:base` options for ref printing atoms
On Thu, Nov 17, 2016 at 11:33 PM, Karthik Nayak wrote: > Hey, > > On Fri, Nov 18, 2016 at 12:05 AM, Junio C Hamano wrote: >> Karthik Nayak writes: >> >>> On Tue, Nov 15, 2016 at 11:12 PM, Junio C Hamano wrote: Jacob Keller writes: ... I think you are going in the right direction. I had a similar thought but built around a different axis. I.e. if strip=1 strips one from the left, perhaps we want to have rstrip=1 that strips one from the right, and also strip=-1 to mean strip everything except one from the left and so on? >>> ... >> >>> If we do implement strip with negative numbers, it definitely >>> would be neat, but to get the desired feature which I've mentioned >>> below, we'd need to call strip twice, i.e >>> to get remotes from /refs/foo/abc/xyz we'd need to do >>> strip=1,strip=-1, which could be >>> done but ... >> >> ... would be unnecessary if this is the only use case: >> >>> strbuf_addf(&fmt, >>> "%%(if:notequals=remotes)%%(refname:base)%%(then)%s%%(else)%s%%(end)", >>> local.buf, remote.buf); >> >> You can "strip to leave only 2 components" and compare the result >> with refs/remotes instead, no? >> > > Of course, my only objective was that someone would find it useful to > have these two additional > atoms. So if you think it's unnecessary we could drop it entirely :D > > -- > Regards, > Karthik Nayak I think having strip and rstrip make sense, (along with support for negative numbers) I don't think we need to make them work together unless someone is interested, since we can use strip=-2 to get the behavior we need today. Thanks, Jake
Did You Get My Message This Time?
-- This is the second time i am sending you this mail.I, Friedrich Mayrhofer Donate $ 1,000,000.00 to You, Email Me personally for more details. Regards. Friedrich Mayrhofer