{"thread":{"id":"25296","subject":"[WIP PATCH] revision-walk: --parent option to find children of a parent","startedAt":"2010-09-30T10:30:46Z","lastAt":"2010-09-30T15:12:51Z","messageCount":3,"participants":["Michael J Gruber","Jonathan Nieder"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"152120","messageId":"99aa4cd5a60b2b2d3eae962acb8a49c2a62a8f77.1285842569.git.git@drmicha.warpmail.net","threadId":"25296","inReplyTo":null,"subject":"[WIP PATCH] revision-walk: --parent option to find children of a parent","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2010-09-30T10:30:46Z","receivedAt":"2010-09-30T10:30:46Z","isPatch":true,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Introduce a new --parent=<commit> option for the revision walker which\nlimits the commits to those which have <commit> as one of their parents.\n\nThis allows to check, e.g., whether <commit> is a fork point.\n\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\nThis is heavily WIP/RFC for the obvious reasons, but also these:\n\nCurrently, multiple --parent options are ORed. I'm still unsure whether that or ANDing\nis more useful. ANDing can always be done cheaply by rev-listing with one\n--parent and then checking the result commits. ORing, otoh can be achieved only\nby doing multiple rev-list runs (unless it is implemented as it is, of course)..\n\nAs a consequence (of the decision for ORing), I don't limit automatically by\n^<commit>. I should probably do that automatically for the single --parent\noption case, it's a huge speed-up.\n\n revision.c |   18 ++++++++++++++++++\n revision.h |    3 +++\n 2 files changed, 21 insertions(+), 0 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex b1c1890..db56cf6 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1149,6 +1149,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n {\n \tconst char *arg = argv[0];\n \tconst char *optarg;\n+\tunsigned char sha1[20];\n \tint argcount;\n \n \t/* pseudo revision arguments */\n@@ -1247,6 +1248,15 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t} else if (!strcmp(arg, \"--parents\")) {\n \t\trevs->rewrite_parents = 1;\n \t\trevs->print_parents = 1;\n+\t} else if ((argcount = parse_long_opt(\"parent\", argv, &optarg))) {\n+\t\tstruct commit *a;\n+\t\tif (get_sha1(optarg, sha1))\n+\t\t\treturn error(\"Not a valid object name: %s\", optarg);\n+\t\ta = lookup_commit_reference(sha1);\n+\t\tif (!a)\n+\t\t\treturn error(\"Couldn't look up commit object for '%s'\", optarg);\n+\t\tcommit_list_insert(a, &(revs->parent_list));\n+\t\treturn argcount;\n \t} else if (!strcmp(arg, \"--dense\")) {\n \t\trevs->dense = 1;\n \t} else if (!strcmp(arg, \"--sparse\")) {\n@@ -1989,6 +1999,14 @@ enum commit_action get_commit_action(struct rev_info *revs, struct commit *commi\n \t\treturn commit_ignore;\n \tif (revs->merges_only && !(commit->parents && commit->parents->next))\n \t\treturn commit_ignore;\n+\tif (revs->parent_list) {\n+\t\tstruct commit_list *a, *b;\n+\t\tfor (b = revs->parent_list; b; b = b->next)\n+\t\t\tfor (a = commit->parents; a; a = a->next)\n+\t\t\t\tif (!hashcmp(b->item->object.sha1, a->item->object.sha1))\n+\t\t\t\t\treturn commit_show;\n+\t\treturn commit_ignore;\n+\t}\n \tif (!commit_match(commit, revs))\n \t\treturn commit_ignore;\n \tif (revs->prune && revs->dense) {\ndiff --git a/revision.h b/revision.h\nindex 05659c6..e424a53 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -111,6 +111,9 @@ struct rev_info {\n \tint\t\tno_inline;\n \tint\t\tshow_log_size;\n \n+\t/* Filter by parents */\n+\tstruct commit_list *parent_list;\n+\n \t/* Filter by commit log message */\n \tstruct grep_opt\tgrep_filter;\n \n-- \n1.7.3.98.g5ad7d\n"},{"id":"152158","messageId":"20100930143234.GH4850@burratino","threadId":"25296","inReplyTo":"99aa4cd5a60b2b2d3eae962acb8a49c2a62a8f77.1285842569.git.git@drmicha.warpmail.net","subject":"Re: [WIP PATCH] revision-walk: --parent option to find children of a parent","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-09-30T14:32:34Z","receivedAt":"2010-09-30T14:32:34Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Hi,\n\nMichael J Gruber wrote:\n\n> Introduce a new --parent=<commit> option for the revision walker which\n> limits the commits to those which have <commit> as one of their parents.\n\nSo this lists the direct children for a given commit.  Could you\nmention a use case?  Why would one want to use this instead of\n\n the_commit=$(git rev-parse --verify <commit>) &&\n git rev-list --parents ... ^<commit> |\n grep -F \" $the_commit\"\n\n?\n \n> --- a/revision.c\n> +++ b/revision.c\n> @@ -1149,6 +1149,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n>  {\n>  \tconst char *arg = argv[0];\n>  \tconst char *optarg;\n> +\tunsigned char sha1[20];\n\nCould this be given narrower scope?\n\n> @@ -1989,6 +1999,14 @@ enum commit_action get_commit_action(struct rev_info *revs, struct commit *commi\n>  \t\treturn commit_ignore;\n>  \tif (revs->merges_only && !(commit->parents && commit->parents->next))\n>  \t\treturn commit_ignore;\n> +\tif (revs->parent_list) {\n> +\t\tstruct commit_list *a, *b;\n> +\t\tfor (b = revs->parent_list; b; b = b->next)\n> +\t\t\tfor (a = commit->parents; a; a = a->next)\n> +\t\t\t\tif (!hashcmp(b->item->object.sha1, a->item->object.sha1))\n> +\t\t\t\t\treturn commit_show;\n> +\t\treturn commit_ignore;\n> +\t}\n\nThe implementation looks good.\n"},{"id":"152163","messageId":"4CA4A8F3.3010805@drmicha.warpmail.net","threadId":"25296","inReplyTo":"20100930143234.GH4850@burratino","subject":"Re: [WIP PATCH] revision-walk: --parent option to find children of a parent","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2010-09-30T15:12:51Z","receivedAt":"2010-09-30T15:12:51Z","isPatch":true,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Jonathan Nieder venit, vidit, dixit 09/30/2010 04:32 PM:\n> Hi,\n> \n> Michael J Gruber wrote:\n> \n>> Introduce a new --parent=<commit> option for the revision walker which\n>> limits the commits to those which have <commit> as one of their parents.\n> \n> So this lists the direct children for a given commit.  Could you\n> mention a use case?  Why would one want to use this instead of\n> \n>  the_commit=$(git rev-parse --verify <commit>) &&\n>  git rev-list --parents ... ^<commit> |\n>  grep -F \" $the_commit\"\n\n| cut -d' ' -f1 # or such :)\n\n> \n> ?\n\nFull disclosure: I didn't see that it can be scripted that easily,\nsimply because the description of \"--parents\" does not indicate at all\nthat it lists the commit along with its parents. I had the impression\nthat it outputs the parents only (same goes for --children.) so that\nlooping over the rev-list output would be required, which would have\nbeen much slower.\n\nAs a use case, it not only tells you whether a specific commit is a fork\npoint, it's also a reverse of \"rev-parse commit^@\", so to say.\n\nPersonally, this was some exercise with the revision walker before\napproaching something else there.\n\n[It also helps with \"Heck, I committed on top of a detached origin/next\nyesterday, how did I tag that commit.\", but there are other solutions,\nof course...]\n\nSpeaking of that: It helps you \"going forward(!)\" from a commit that you\nchecked out (maybe for inspection). Just imagine trying to understand a\nhistory by checking out versions iteratively. Say, you want to review\nthe last 10 revs, do a \"checkout HEAD~10\", then a \"checkout HEAD~9\" and\nnotice that's not quite the way to do it... (Again, there are\nalternatives, of course.)\n\n>> --- a/revision.c\n>> +++ b/revision.c\n>> @@ -1149,6 +1149,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n>>  {\n>>  \tconst char *arg = argv[0];\n>>  \tconst char *optarg;\n>> +\tunsigned char sha1[20];\n> \n> Could this be given narrower scope?\n\nSure! I expected more rough edges (and some resistance) which is why I\nsent a WIP first.\n\nMichael\n"}]}