{"thread":{"id":"17314","subject":"[PATCH 2/3] Make has_commit non-static","startedAt":"2009-01-23T00:48:36Z","lastAt":"2009-01-23T22:41:17Z","messageCount":5,"participants":["Jake Goulding","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"101590","messageId":"497913E4.6050806@vivisimo.com","threadId":"17314","inReplyTo":"1232671630-19683-1-git-send-email-goulding@vivisimo.com","subject":"[PATCH 2/3] Make has_commit non-static","fromName":"Jake Goulding","fromEmail":"goulding@vivisimo.com","sentAt":"2009-01-23T00:48:36Z","receivedAt":"2009-01-23T00:48:36Z","isPatch":true,"sender":{"key":"goulding@vivisimo.com","avatar":"https://gravatar.com/avatar/d8938ff226c618b80857e27f7e0a2d4335215bfb9733c321b8dd30c660b7f1e9?d=mp&s=160"},"body":"Moving has_commit from branch to a common location in preparation for\nusing it in tag.\n\nSigned-off-by: Jake Goulding <goulding@vivisimo.com>\n---\n builtin-branch.c |   15 ---------------\n commit.c         |   15 +++++++++++++++\n commit.h         |    1 +\n 3 files changed, 16 insertions(+), 15 deletions(-)\n\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 82d6fb2..bb42911 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -193,21 +193,6 @@ struct ref_list {\n \tint kinds;\n };\n\n-static int has_commit(struct commit *commit, struct commit_list\n*with_commit)\n-{\n-\tif (!with_commit)\n-\t\treturn 1;\n-\twhile (with_commit) {\n-\t\tstruct commit *other;\n-\n-\t\tother = with_commit->item;\n-\t\twith_commit = with_commit->next;\n-\t\tif (in_merge_bases(other, &commit, 1))\n-\t\t\treturn 1;\n-\t}\n-\treturn 0;\n-}\n-\n static int append_ref(const char *refname, const unsigned char *sha1,\nint flags, void *cb_data)\n {\n \tstruct ref_list *ref_list = (struct ref_list*)(cb_data);\ndiff --git a/commit.c b/commit.c\nindex c99db16..5ccb338 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -705,6 +705,21 @@ struct commit_list *get_merge_bases(struct commit\n*one, struct commit *two,\n \treturn get_merge_bases_many(one, 1, &two, cleanup);\n }\n\n+int has_commit(struct commit *commit, struct commit_list *with_commit)\n+{\n+\tif (!with_commit)\n+\t\treturn 1;\n+\twhile (with_commit) {\n+\t\tstruct commit *other;\n+\n+\t\tother = with_commit->item;\n+\t\twith_commit = with_commit->next;\n+\t\tif (in_merge_bases(other, &commit, 1))\n+\t\t\treturn 1;\n+\t}\n+\treturn 0;\n+}\n+\n int in_merge_bases(struct commit *commit, struct commit **reference,\nint num)\n {\n \tstruct commit_list *bases, *b;\ndiff --git a/commit.h b/commit.h\nindex 3a7b06a..1b8444f 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -133,6 +133,7 @@ extern int is_repository_shallow(void);\n extern struct commit_list *get_shallow_commits(struct object_array *heads,\n \t\tint depth, int shallow_flag, int not_shallow_flag);\n\n+int has_commit(struct commit *, struct commit_list *);\n int in_merge_bases(struct commit *, struct commit **, int);\n\n extern int interactive_add(int argc, const char **argv, const char\n*prefix);\n-- \n1.6.0.4\n"},{"id":"101591","messageId":"497913EE.9040608@vivisimo.com","threadId":"17314","inReplyTo":"1232671630-19683-2-git-send-email-goulding@vivisimo.com","subject":"[PATCH 3/3] Add --contains flag to git tag","fromName":"Jake Goulding","fromEmail":"goulding@vivisimo.com","sentAt":"2009-01-23T00:48:46Z","receivedAt":"2009-01-23T00:48:46Z","isPatch":true,"sender":{"key":"goulding@vivisimo.com","avatar":"https://gravatar.com/avatar/d8938ff226c618b80857e27f7e0a2d4335215bfb9733c321b8dd30c660b7f1e9?d=mp&s=160"},"body":"This functions similar to git branch --contains - it will show all\ntags that contain the specified commit. Indeed, it uses the same\nlookup mechanisms as git branch.\n\nAlso adding documentation and tests for new option.\n\nSigned-off-by: Jake Goulding <goulding@vivisimo.com>\n---\n\nReworked with feedback from the list.\n\nMoved commit testing inside of the regex match, instead of before.\nMoved test cases into existing test.\nSquashed code / doc / test into one commit.\n\n Documentation/git-tag.txt |    5 ++-\n builtin-tag.c             |   32 +++++++++++-\n t/t7004-tag.sh            |  115\n+++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 148 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt\nindex e44f543..533d18b 100644\n--- a/Documentation/git-tag.txt\n+++ b/Documentation/git-tag.txt\n@@ -12,7 +12,7 @@ SYNOPSIS\n 'git tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]\n \t<name> [<commit> | <object>]\n 'git tag' -d <name>...\n-'git tag' [-n[<num>]] -l [<pattern>]\n+'git tag' [-n[<num>]] -l [--contains <commit>] [<pattern>]\n 'git tag' -v <name>...\n\n DESCRIPTION\n@@ -68,6 +68,9 @@ OPTIONS\n \tList tags with names that match the given pattern (or all if no\npattern is given).\n \tTyping \"git tag\" without arguments, also lists all tags.\n\n+--contains <commit>::\n+\tOnly list tags which contain the specified commit.\n+\n -m <msg>::\n \tUse the given tag message (instead of prompting).\n \tIf multiple `-m` options are given, their values are\ndiff --git a/builtin-tag.c b/builtin-tag.c\nindex a398499..33424c0 100644\n--- a/builtin-tag.c\n+++ b/builtin-tag.c\n@@ -26,6 +26,7 @@ static char signingkey[1000];\n struct tag_filter {\n \tconst char *pattern;\n \tint lines;\n+\tstruct commit_list *with_commit;\n };\n\n #define PGP_SIGNATURE \"-----BEGIN PGP SIGNATURE-----\"\n@@ -34,7 +35,6 @@ static int show_reference(const char *refname, const\nunsigned char *sha1,\n \t\t\t  int flag, void *cb_data)\n {\n \tstruct tag_filter *filter = cb_data;\n-\n \tif (!fnmatch(filter->pattern, refname, 0)) {\n \t\tint i;\n \t\tunsigned long size;\n@@ -42,6 +42,18 @@ static int show_reference(const char *refname, const\nunsigned char *sha1,\n \t\tchar *buf, *sp, *eol;\n \t\tsize_t len;\n\n+\t\tif (filter->with_commit) {\n+\t\t\tstruct commit *commit;\n+\n+\t\t\tcommit = lookup_commit_reference_gently(sha1, 1);\n+\t\t\tif (!commit) {\n+\t\t\t\terror(\"tag '%s' does not point at a commit\", refname);\n+\t\t\t\treturn 0;\n+\t\t\t}\n+\t\t\tif (!has_commit(commit, filter->with_commit))\n+\t\t\t\treturn 0;\n+\t\t}\n+\n \t\tif (!filter->lines) {\n \t\t\tprintf(\"%s\\n\", refname);\n \t\t\treturn 0;\n@@ -79,7 +91,8 @@ static int show_reference(const char *refname, const\nunsigned char *sha1,\n \treturn 0;\n }\n\n-static int list_tags(const char *pattern, int lines)\n+static int list_tags(const char *pattern, int lines,\n+\t\t\tstruct commit_list *with_commit)\n {\n \tstruct tag_filter filter;\n\n@@ -88,6 +101,7 @@ static int list_tags(const char *pattern, int lines)\n\n \tfilter.pattern = pattern;\n \tfilter.lines = lines;\n+\tfilter.with_commit = with_commit;\n\n \tfor_each_tag_ref(show_reference, (void *) &filter);\n\n@@ -360,6 +374,7 @@ int cmd_tag(int argc, const char **argv, const char\n*prefix)\n \t\tlist = 0, delete = 0, verify = 0;\n \tconst char *msgfile = NULL, *keyid = NULL;\n \tstruct msg_arg msg = { 0, STRBUF_INIT };\n+\tstruct commit_list *with_commit = NULL;\n \tstruct option options[] = {\n \t\tOPT_BOOLEAN('l', NULL, &list, \"list tag names\"),\n \t\t{ OPTION_INTEGER, 'n', NULL, &lines, NULL,\n@@ -378,6 +393,14 @@ int cmd_tag(int argc, const char **argv, const char\n*prefix)\n \t\tOPT_STRING('u', NULL, &keyid, \"key-id\",\n \t\t\t\t\t\"use another key to sign the tag\"),\n \t\tOPT_BOOLEAN('f', NULL, &force, \"replace the tag if exists\"),\n+\n+\t\tOPT_GROUP(\"Tag listing options\"),\n+\t\t{\n+\t\t\tOPTION_CALLBACK, 0, \"contains\", &with_commit, \"commit\",\n+\t\t\t\"print only tags that contain the commit\",\n+\t\t\tPARSE_OPT_LASTARG_DEFAULT,\n+\t\t\tparse_opt_with_commit, (intptr_t)\"HEAD\",\n+\t\t},\n \t\tOPT_END()\n \t};\n\n@@ -402,9 +425,12 @@ int cmd_tag(int argc, const char **argv, const char\n*prefix)\n \tif (list + delete + verify > 1)\n \t\tusage_with_options(git_tag_usage, options);\n \tif (list)\n-\t\treturn list_tags(argv[0], lines == -1 ? 0 : lines);\n+\t\treturn list_tags(argv[0], lines == -1 ? 0 : lines,\n+\t\t\t\t with_commit);\n \tif (lines != -1)\n \t\tdie(\"-n option is only allowed with -l.\");\n+\tif (with_commit)\n+\t\tdie(\"--contains option is only allowed with -l.\");\n \tif (delete)\n \t\treturn for_each_tag_name(argv, delete_tag);\n \tif (verify)\ndiff --git a/t/t7004-tag.sh b/t/t7004-tag.sh\nindex f377fea..69501e2 100755\n--- a/t/t7004-tag.sh\n+++ b/t/t7004-tag.sh\n@@ -1090,6 +1090,121 @@ test_expect_success 'filename for the message is\nrelative to cwd' '\n \tgit cat-file tag tag-from-subdir-2 | grep \"in sub directory\"\n '\n\n+# create a few more commits to test --contains\n+\n+hash1=$(git rev-parse HEAD)\n+\n+test_expect_success 'creating second commit and tag' '\n+\techo foo-2.0 >foo &&\n+\tgit add foo &&\n+\tgit commit -m second\n+\tgit tag v2.0\n+'\n+\n+hash2=$(git rev-parse HEAD)\n+\n+test_expect_success 'creating third commit without tag' '\n+\techo foo-dev >foo &&\n+\tgit add foo &&\n+\tgit commit -m third\n+'\n+\n+hash3=$(git rev-parse HEAD)\n+\n+# simple linear checks of --continue\n+\n+cat > expected <<EOF\n+v0.2.1\n+v1.0\n+v1.0.1\n+v1.1.3\n+v2.0\n+EOF\n+\n+test_expect_success 'checking that first commit is in all tags (hash)' \"\n+\tgit tag -l --contains $hash1 v* >actual\n+\ttest_cmp expected actual\n+\"\n+\n+# other ways of specifying the commit\n+test_expect_success 'checking that first commit is in all tags (tag)' \"\n+\tgit tag -l --contains v1.0 v* >actual\n+\ttest_cmp expected actual\n+\"\n+\n+test_expect_success 'checking that first commit is in all tags\n(relative)' \"\n+\tgit tag -l --contains HEAD~2 v* >actual\n+\ttest_cmp expected actual\n+\"\n+\n+cat > expected <<EOF\n+v2.0\n+EOF\n+\n+test_expect_success 'checking that second commit only has one tag' \"\n+\tgit tag -l --contains $hash2 v* >actual\n+\ttest_cmp expected actual\n+\"\n+\n+\n+cat > expected <<EOF\n+EOF\n+\n+test_expect_success 'checking that third commit has no tags' \"\n+\tgit tag -l --contains $hash3 v* >actual\n+\ttest_cmp expected actual\n+\"\n+\n+# how about a simple merge?\n+\n+test_expect_success 'creating simple branch' '\n+\tgit branch stable v2.0 &&\n+        git checkout stable &&\n+\techo foo-3.0 > foo &&\n+\tgit commit foo -m fourth\n+\tgit tag v3.0\n+'\n+\n+hash4=$(git rev-parse HEAD)\n+\n+cat > expected <<EOF\n+v3.0\n+EOF\n+\n+test_expect_success 'checking that branch head only has one tag' \"\n+\tgit tag -l --contains $hash4 v* >actual\n+\ttest_cmp expected actual\n+\"\n+\n+test_expect_success 'merging original branch into this branch' '\n+\tgit merge --strategy=ours master &&\n+        git tag v4.0\n+'\n+\n+cat > expected <<EOF\n+v4.0\n+EOF\n+\n+test_expect_success 'checking that original branch head has one tag now' \"\n+\tgit tag -l --contains $hash3 v* >actual\n+\ttest_cmp expected actual\n+\"\n+\n+cat > expected <<EOF\n+v0.2.1\n+v1.0\n+v1.0.1\n+v1.1.3\n+v2.0\n+v3.0\n+v4.0\n+EOF\n+\n+test_expect_success 'checking that initial commit is in all tags' \"\n+\tgit tag -l --contains $hash1 v* >actual\n+\ttest_cmp expected actual\n+\"\n+\n # mixing modes and options:\n\n test_expect_success 'mixing incompatibles modes and options is forbidden' '\n-- \n1.6.0.4\n"},{"id":"101593","messageId":"7v7i4m6cz0.fsf@gitster.siamese.dyndns.org","threadId":"17314","inReplyTo":"497913E4.6050806@vivisimo.com","subject":"Re: [PATCH 2/3] Make has_commit non-static","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-01-23T01:13:55Z","receivedAt":"2009-01-23T01:13:55Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jake Goulding <goulding@vivisimo.com> writes:\n\n> Moving has_commit from branch to a common location in preparation for\n> using it in tag.\n\nhas_commit() may have been a good enough name when it was a static in\nbuiltin-branch.c but with much wider visibility, it is not specific\nenough.\n\nPerhaps you would want to rename it to something more descriptive.\n\nAlso it seems that your patch is garbled and won't apply.  A blank\ncontext line lost the leading (and only) SP, and long lines are wrapped.\n\n> Signed-off-by: Jake Goulding <goulding@vivisimo.com>\n> ---\n>  builtin-branch.c |   15 ---------------\n>  commit.c         |   15 +++++++++++++++\n>  commit.h         |    1 +\n>  3 files changed, 16 insertions(+), 15 deletions(-)\n>\n> diff --git a/builtin-branch.c b/builtin-branch.c\n> index 82d6fb2..bb42911 100644\n> --- a/builtin-branch.c\n> +++ b/builtin-branch.c\n> @@ -193,21 +193,6 @@ struct ref_list {\n>  \tint kinds;\n>  };\n>\n> -static int has_commit(struct commit *commit, struct commit_list\n> *with_commit)\n> -{\n> -\tif (!with_commit)\n> -\t\treturn 1;\n> -\twhile (with_commit) {\n> -\t\tstruct commit *other;\n> -\n> -\t\tother = with_commit->item;\n> -\t\twith_commit = with_commit->next;\n> -\t\tif (in_merge_bases(other, &commit, 1))\n> -\t\t\treturn 1;\n> -\t}\n> -\treturn 0;\n> -}\n> -\n>  static int append_ref(const char *refname, const unsigned char *sha1,\n> int flags, void *cb_data)\n>  {\n>  \tstruct ref_list *ref_list = (struct ref_list*)(cb_data);\n> diff --git a/commit.c b/commit.c\n> index c99db16..5ccb338 100644\n> --- a/commit.c\n> +++ b/commit.c\n> @@ -705,6 +705,21 @@ struct commit_list *get_merge_bases(struct commit\n> *one, struct commit *two,\n>  \treturn get_merge_bases_many(one, 1, &two, cleanup);\n>  }\n>\n> +int has_commit(struct commit *commit, struct commit_list *with_commit)\n> +{\n> +\tif (!with_commit)\n> +\t\treturn 1;\n> +\twhile (with_commit) {\n> +\t\tstruct commit *other;\n> +\n> +\t\tother = with_commit->item;\n> +\t\twith_commit = with_commit->next;\n> +\t\tif (in_merge_bases(other, &commit, 1))\n> +\t\t\treturn 1;\n> +\t}\n> +\treturn 0;\n> +}\n> +\n>  int in_merge_bases(struct commit *commit, struct commit **reference,\n> int num)\n>  {\n>  \tstruct commit_list *bases, *b;\n> diff --git a/commit.h b/commit.h\n> index 3a7b06a..1b8444f 100644\n> --- a/commit.h\n> +++ b/commit.h\n> @@ -133,6 +133,7 @@ extern int is_repository_shallow(void);\n>  extern struct commit_list *get_shallow_commits(struct object_array *heads,\n>  \t\tint depth, int shallow_flag, int not_shallow_flag);\n>\n> +int has_commit(struct commit *, struct commit_list *);\n>  int in_merge_bases(struct commit *, struct commit **, int);\n>\n>  extern int interactive_add(int argc, const char **argv, const char\n> *prefix);\n> -- \n> 1.6.0.4\n"},{"id":"101594","messageId":"7v1vuu6cr6.fsf@gitster.siamese.dyndns.org","threadId":"17314","inReplyTo":"497913EE.9040608@vivisimo.com","subject":"Re: [PATCH 3/3] Add --contains flag to git tag","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-01-23T01:18:37Z","receivedAt":"2009-01-23T01:18:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jake Goulding <goulding@vivisimo.com> writes:\n\n> @@ -34,7 +35,6 @@ static int show_reference(const char *refname, const\n> unsigned char *sha1,\n>  \t\t\t  int flag, void *cb_data)\n>  {\n>  \tstruct tag_filter *filter = cb_data;\n> -\n>  \tif (!fnmatch(filter->pattern, refname, 0)) {\n>  \t\tint i;\n>  \t\tunsigned long size;\n\nHere you can see a long line wrapped.\n\nWhat does this hunk have to do with adding --contains option anyway?\n\n> @@ -42,6 +42,18 @@ static int show_reference(const char *refname, const\n> unsigned char *sha1,\n>  \t\tchar *buf, *sp, *eol;\n>  \t\tsize_t len;\n>\n> +\t\tif (filter->with_commit) {\n> +\t\t\tstruct commit *commit;\n> +\n> +\t\t\tcommit = lookup_commit_reference_gently(sha1, 1);\n> +\t\t\tif (!commit) {\n> +\t\t\t\terror(\"tag '%s' does not point at a commit\", refname);\n> +\t\t\t\treturn 0;\n\nDrop this error() call, and just return silently.  A tag that does not\npoint at a commit is not an error at all.\n"},{"id":"101704","messageId":"497A478D.2030707@vivisimo.com","threadId":"17314","inReplyTo":"7v7i4m6cz0.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 2/3] Make has_commit non-static","fromName":"Jake Goulding","fromEmail":"goulding@vivisimo.com","sentAt":"2009-01-23T22:41:17Z","receivedAt":"2009-01-23T22:41:17Z","isPatch":true,"sender":{"key":"goulding@vivisimo.com","avatar":"https://gravatar.com/avatar/d8938ff226c618b80857e27f7e0a2d4335215bfb9733c321b8dd30c660b7f1e9?d=mp&s=160"},"body":"Junio C Hamano wrote:\n> Jake Goulding <goulding@vivisimo.com> writes:\n> \n>> Moving has_commit from branch to a common location in preparation for\n>> using it in tag.\n> \n> has_commit() may have been a good enough name when it was a static in\n> builtin-branch.c but with much wider visibility, it is not specific\n> enough.\n> \n> Perhaps you would want to rename it to something more descriptive.\n\nSure - any suggestions?\n\nThe best I could come up with was \"commit_has_any_in_commit_list\"\n\n> Also it seems that your patch is garbled and won't apply.  A blank\n> context line lost the leading (and only) SP, and long lines are wrapped.\n\nYes - adventures in sending patches. Hopefully I'll have it fixed by the\nnext round of patches. :-)\n\n> \n>> Signed-off-by: Jake Goulding <goulding@vivisimo.com>\n>> ---\n>>  builtin-branch.c |   15 ---------------\n>>  commit.c         |   15 +++++++++++++++\n>>  commit.h         |    1 +\n>>  3 files changed, 16 insertions(+), 15 deletions(-)\n>>\n>> diff --git a/builtin-branch.c b/builtin-branch.c\n>> index 82d6fb2..bb42911 100644\n>> --- a/builtin-branch.c\n>> +++ b/builtin-branch.c\n>> @@ -193,21 +193,6 @@ struct ref_list {\n>>  \tint kinds;\n>>  };\n>>\n>> -static int has_commit(struct commit *commit, struct commit_list\n>> *with_commit)\n>> -{\n>> -\tif (!with_commit)\n>> -\t\treturn 1;\n>> -\twhile (with_commit) {\n>> -\t\tstruct commit *other;\n>> -\n>> -\t\tother = with_commit->item;\n>> -\t\twith_commit = with_commit->next;\n>> -\t\tif (in_merge_bases(other, &commit, 1))\n>> -\t\t\treturn 1;\n>> -\t}\n>> -\treturn 0;\n>> -}\n>> -\n>>  static int append_ref(const char *refname, const unsigned char *sha1,\n>> int flags, void *cb_data)\n>>  {\n>>  \tstruct ref_list *ref_list = (struct ref_list*)(cb_data);\n>> diff --git a/commit.c b/commit.c\n>> index c99db16..5ccb338 100644\n>> --- a/commit.c\n>> +++ b/commit.c\n>> @@ -705,6 +705,21 @@ struct commit_list *get_merge_bases(struct commit\n>> *one, struct commit *two,\n>>  \treturn get_merge_bases_many(one, 1, &two, cleanup);\n>>  }\n>>\n>> +int has_commit(struct commit *commit, struct commit_list *with_commit)\n>> +{\n>> +\tif (!with_commit)\n>> +\t\treturn 1;\n>> +\twhile (with_commit) {\n>> +\t\tstruct commit *other;\n>> +\n>> +\t\tother = with_commit->item;\n>> +\t\twith_commit = with_commit->next;\n>> +\t\tif (in_merge_bases(other, &commit, 1))\n>> +\t\t\treturn 1;\n>> +\t}\n>> +\treturn 0;\n>> +}\n>> +\n>>  int in_merge_bases(struct commit *commit, struct commit **reference,\n>> int num)\n>>  {\n>>  \tstruct commit_list *bases, *b;\n>> diff --git a/commit.h b/commit.h\n>> index 3a7b06a..1b8444f 100644\n>> --- a/commit.h\n>> +++ b/commit.h\n>> @@ -133,6 +133,7 @@ extern int is_repository_shallow(void);\n>>  extern struct commit_list *get_shallow_commits(struct object_array *heads,\n>>  \t\tint depth, int shallow_flag, int not_shallow_flag);\n>>\n>> +int has_commit(struct commit *, struct commit_list *);\n>>  int in_merge_bases(struct commit *, struct commit **, int);\n>>\n>>  extern int interactive_add(int argc, const char **argv, const char\n>> *prefix);\n>> -- \n>> 1.6.0.4\n"}]}