{"thread":{"id":"6021","subject":"[PATCH] Built-in cherry","startedAt":"2006-10-23T23:01:57Z","lastAt":"2006-10-23T23:01:57Z","messageCount":1,"participants":["Rene Scharfe"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"29780","messageId":"453D49E5.3050902@lsrfire.ath.cx","threadId":"6021","inReplyTo":null,"subject":"[PATCH] Built-in cherry","fromName":"Rene Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2006-10-23T23:01:57Z","receivedAt":"2006-10-23T23:01:57Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"This replaces the shell script git-cherry with a version written in C.\n\nThe behaviour of the new version differs from the original in two\npoints: it has no long help any more, and it is handling the (optional)\nthird parameter a bit differently.  Basically, it does the equivalent\nof\n\n   ours=`git-rev-list $ours ^$limit ^$upstream`\n\ninstead of\n\n   ours=`git-rev-list $ours ^$limit`\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n---\n\nI'm not really sure if the limit behaviour change matches the original\nintent of this feature; Yann, please holler if it doesn't.\n\n Makefile      |    4 +-\n builtin-log.c |  106 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n builtin.h     |    1 +\n git-cherry.sh |   91 -------------------------------------------------\n git.c         |    1 +\n 5 files changed, 110 insertions(+), 93 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 66c8b4b..2b53747 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -157,7 +157,7 @@ BASIC_LDFLAGS =\n \n SCRIPT_SH = \\\n \tgit-bisect.sh git-branch.sh git-checkout.sh \\\n-\tgit-cherry.sh git-clean.sh git-clone.sh git-commit.sh \\\n+\tgit-clean.sh git-clone.sh git-commit.sh \\\n \tgit-fetch.sh \\\n \tgit-ls-remote.sh \\\n \tgit-merge-one-file.sh git-parse-remote.sh \\\n@@ -210,7 +210,7 @@ # Empty...\n EXTRA_PROGRAMS =\n \n BUILT_INS = \\\n-\tgit-format-patch$X git-show$X git-whatchanged$X \\\n+\tgit-format-patch$X git-show$X git-whatchanged$X git-cherry$X \\\n \tgit-get-tar-commit-id$X \\\n \t$(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS))\n \ndiff --git a/builtin-log.c b/builtin-log.c\nindex 9d1ceae..840c742 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -437,3 +437,109 @@ int cmd_format_patch(int argc, const cha\n \treturn 0;\n }\n \n+static int add_pending_commit(const char *arg, struct rev_info *revs, int flags)\n+{\n+\tunsigned char sha1[20];\n+\tif (get_sha1(arg, sha1) == 0) {\n+\t\tstruct commit *commit = lookup_commit_reference(sha1);\n+\t\tif (commit) {\n+\t\t\tcommit->object.flags |= flags;\n+\t\t\tadd_pending_object(revs, &commit->object, arg);\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\treturn -1;\n+}\n+\n+static const char cherry_usage[] =\n+\"git-cherry [-v] <upstream> [<head>] [<limit>]\";\n+int cmd_cherry(int argc, const char **argv, const char *prefix)\n+{\n+\tstruct rev_info revs;\n+\tstruct diff_options patch_id_opts;\n+\tstruct commit *commit;\n+\tstruct commit_list *list = NULL;\n+\tconst char *upstream;\n+\tconst char *head = \"HEAD\";\n+\tconst char *limit = NULL;\n+\tint verbose = 0;\n+\n+\tif (argc > 1 && !strcmp(argv[1], \"-v\")) {\n+\t\tverbose = 1;\n+\t\targc--;\n+\t\targv++;\n+\t}\n+\n+\tswitch (argc) {\n+\tcase 4:\n+\t\tlimit = argv[3];\n+\t\t/* FALLTHROUGH */\n+\tcase 3:\n+\t\thead = argv[2];\n+\t\t/* FALLTHROUGH */\n+\tcase 2:\n+\t\tupstream = argv[1];\n+\t\tbreak;\n+\tdefault:\n+\t\tusage(cherry_usage);\n+\t}\n+\n+\tinit_revisions(&revs, prefix);\n+\trevs.diff = 1;\n+\trevs.combine_merges = 0;\n+\trevs.ignore_merges = 1;\n+\trevs.diffopt.recursive = 1;\n+\n+\tif (add_pending_commit(head, &revs, 0))\n+\t\tdie(\"Unknown commit %s\", head);\n+\tif (add_pending_commit(upstream, &revs, UNINTERESTING))\n+\t\tdie(\"Unknown commit %s\", upstream);\n+\n+\t/* Don't say anything if head and upstream are the same. */\n+\tif (revs.pending.nr == 2) {\n+\t\tstruct object_array_entry *o = revs.pending.objects;\n+\t\tif (hashcmp(o[0].item->sha1, o[1].item->sha1) == 0)\n+\t\t\treturn 0;\n+\t}\n+\n+\tget_patch_ids(&revs, &patch_id_opts, prefix);\n+\n+\tif (limit && add_pending_commit(limit, &revs, UNINTERESTING))\n+\t\tdie(\"Unknown commit %s\", limit);\n+\n+\t/* reverse the list of commits */\n+\tprepare_revision_walk(&revs);\n+\twhile ((commit = get_revision(&revs)) != NULL) {\n+\t\t/* ignore merges */\n+\t\tif (commit->parents && commit->parents->next)\n+\t\t\tcontinue;\n+\n+\t\tcommit_list_insert(commit, &list);\n+\t}\n+\n+\twhile (list) {\n+\t\tunsigned char sha1[20];\n+\t\tchar sign = '+';\n+\n+\t\tcommit = list->item;\n+\t\tif (!get_patch_id(commit, &patch_id_opts, sha1) &&\n+\t\t    lookup_object(sha1))\n+\t\t\tsign = '-';\n+\n+\t\tif (verbose) {\n+\t\t\tstatic char buf[16384];\n+\t\t\tpretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,\n+\t\t\t                    buf, sizeof(buf), 0, NULL, NULL, 0);\n+\t\t\tprintf(\"%c %s %s\\n\", sign, \n+\t\t\t       sha1_to_hex(commit->object.sha1), buf);\n+\t\t}\n+\t\telse {\n+\t\t\tprintf(\"%c %s\\n\", sign,\n+\t\t\t       sha1_to_hex(commit->object.sha1));\n+\t\t}\n+\n+\t\tlist = list->next;\n+\t}\n+\n+\treturn 0;\n+}\ndiff --git a/builtin.h b/builtin.h\nindex f71b962..285d98f 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -19,6 +19,7 @@ extern int cmd_archive(int argc, const c\n extern int cmd_cat_file(int argc, const char **argv, const char *prefix);\n extern int cmd_checkout_index(int argc, const char **argv, const char *prefix);\n extern int cmd_check_ref_format(int argc, const char **argv, const char *prefix);\n+extern int cmd_cherry(int argc, const char **argv, const char *prefix);\n extern int cmd_commit_tree(int argc, const char **argv, const char *prefix);\n extern int cmd_count_objects(int argc, const char **argv, const char *prefix);\n extern int cmd_diff_files(int argc, const char **argv, const char *prefix);\ndiff --git a/git-cherry.sh b/git-cherry.sh\ndeleted file mode 100755\nindex 8832573..0000000\n--- a/git-cherry.sh\n+++ /dev/null\n@@ -1,91 +0,0 @@\n-#!/bin/sh\n-#\n-# Copyright (c) 2005 Junio C Hamano.\n-#\n-\n-USAGE='[-v] <upstream> [<head>] [<limit>]'\n-LONG_USAGE='             __*__*__*__*__> <upstream>\n-            /\n-  fork-point\n-            \\__+__+__+__+__+__+__+__> <head>\n-\n-Each commit between the fork-point (or <limit> if given) and <head> is\n-examined, and compared against the change each commit between the\n-fork-point and <upstream> introduces.  If the change seems to be in\n-the upstream, it is shown on the standard output with prefix \"+\".\n-Otherwise it is shown with prefix \"-\".'\n-. git-sh-setup\n-\n-case \"$1\" in -v) verbose=t; shift ;; esac \n-\n-case \"$#,$1\" in\n-1,*..*)\n-    upstream=$(expr \"z$1\" : 'z\\(.*\\)\\.\\.') ours=$(expr \"z$1\" : '.*\\.\\.\\(.*\\)$')\n-    set x \"$upstream\" \"$ours\"\n-    shift ;;\n-esac\n-\n-case \"$#\" in\n-1) upstream=`git-rev-parse --verify \"$1\"` &&\n-   ours=`git-rev-parse --verify HEAD` || exit\n-   limit=\"$upstream\"\n-   ;;\n-2) upstream=`git-rev-parse --verify \"$1\"` &&\n-   ours=`git-rev-parse --verify \"$2\"` || exit\n-   limit=\"$upstream\"\n-   ;;\n-3) upstream=`git-rev-parse --verify \"$1\"` &&\n-   ours=`git-rev-parse --verify \"$2\"` &&\n-   limit=`git-rev-parse --verify \"$3\"` || exit\n-   ;;\n-*) usage ;;\n-esac\n-\n-# Note that these list commits in reverse order;\n-# not that the order in inup matters...\n-inup=`git-rev-list ^$ours $upstream` &&\n-ours=`git-rev-list $ours ^$limit` || exit\n-\n-tmp=.cherry-tmp$$\n-patch=$tmp-patch\n-mkdir $patch\n-trap \"rm -rf $tmp-*\" 0 1 2 3 15\n-\n-for c in $inup\n-do\n-\tgit-diff-tree -p $c\n-done | git-patch-id |\n-while read id name\n-do\n-\techo $name >>$patch/$id\n-done\n-\n-LF='\n-'\n-\n-O=\n-for c in $ours\n-do\n-\tset x `git-diff-tree -p $c | git-patch-id`\n-\tif test \"$2\" != \"\"\n-\tthen\n-\t\tif test -f \"$patch/$2\"\n-\t\tthen\n-\t\t\tsign=-\n-\t\telse\n-\t\t\tsign=+\n-\t\tfi\n-\t\tcase \"$verbose\" in\n-\t\tt)\n-\t\t\tc=$(git-rev-list --pretty=oneline --max-count=1 $c)\n-\t\tesac\n-\t\tcase \"$O\" in\n-\t\t'')\tO=\"$sign $c\" ;;\n-\t\t*)\tO=\"$sign $c$LF$O\" ;;\n-\t\tesac\n-\tfi\n-done\n-case \"$O\" in\n-'') ;;\n-*)  echo \"$O\" ;;\n-esac\ndiff --git a/git.c b/git.c\nindex e089b53..f8c991f 100644\n--- a/git.c\n+++ b/git.c\n@@ -224,6 +224,7 @@ static void handle_internal_command(int \n \t\t{ \"cat-file\", cmd_cat_file, RUN_SETUP },\n \t\t{ \"checkout-index\", cmd_checkout_index, RUN_SETUP },\n \t\t{ \"check-ref-format\", cmd_check_ref_format },\n+\t\t{ \"cherry\", cmd_cherry, RUN_SETUP },\n \t\t{ \"commit-tree\", cmd_commit_tree, RUN_SETUP },\n \t\t{ \"count-objects\", cmd_count_objects, RUN_SETUP },\n \t\t{ \"diff\", cmd_diff, RUN_SETUP | USE_PAGER },\n"}]}