{"thread":{"id":"39547","subject":"[RFC/PATCH 0/9] add options to ref-filter","startedAt":"2015-06-06T20:03:22Z","lastAt":"2015-06-10T11:31:16Z","messageCount":37,"participants":["Karthik Nayak","Christian Couder","Matthieu Moy","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":9},"messages":[{"id":"263122","messageId":"5573520A.90603@gmail.com","threadId":"39547","inReplyTo":null,"subject":"[RFC/PATCH 0/9] add options to ref-filter","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-06T20:03:22Z","receivedAt":"2015-06-06T20:03:22Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"This is a follow up series to the one posted here\nhttp://thread.gmane.org/gmane.comp.version-control.git/270922\n\nThis patch series adds '--ponints-at', '--merged', '--no-merged' and\n'--contain' options to 'ref-filter' and uses these options in \n'for-each-ref'.\n\n-- \nRegards,\nKarthik\n"},{"id":"263123","messageId":"1433621052-5588-1-git-send-email-karthik.188@gmail.com","threadId":"39547","inReplyTo":"5573520A.90603@gmail.com","subject":"[RFC/PATCH 1/9] tag: libify parse_opt_points_at()","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-06T20:04:04Z","receivedAt":"2015-06-06T20:04:04Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Moving 'parse_opt_points_at()' from 'tag.c' to a common location,\nin preparation for using it in 'ref-filter'.\n\nBased-on-patch-by: Jeff King <peff@peff.net>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n builtin/tag.c      | 19 +------------------\n parse-options-cb.c | 17 +++++++++++++++++\n parse-options.h    |  1 +\n 3 files changed, 19 insertions(+), 18 deletions(-)\n\ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex 5f6cdc5..eda76ba 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -546,23 +546,6 @@ static int strbuf_check_tag_ref(struct strbuf *sb, const char *name)\n \treturn check_refname_format(sb->buf, 0);\n }\n \n-static int parse_opt_points_at(const struct option *opt __attribute__((unused)),\n-\t\t\tconst char *arg, int unset)\n-{\n-\tunsigned char sha1[20];\n-\n-\tif (unset) {\n-\t\tsha1_array_clear(&points_at);\n-\t\treturn 0;\n-\t}\n-\tif (!arg)\n-\t\treturn error(_(\"switch 'points-at' requires an object\"));\n-\tif (get_sha1(arg, sha1))\n-\t\treturn error(_(\"malformed object name '%s'\"), arg);\n-\tsha1_array_append(&points_at, sha1);\n-\treturn 0;\n-}\n-\n static int parse_opt_sort(const struct option *opt, const char *arg, int unset)\n {\n \tint *sort = opt->value;\n@@ -625,7 +608,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \t\t\tparse_opt_with_commit, (intptr_t)\"HEAD\",\n \t\t},\n \t\t{\n-\t\t\tOPTION_CALLBACK, 0, \"points-at\", NULL, N_(\"object\"),\n+\t\t\tOPTION_CALLBACK, 0, \"points-at\", &points_at, N_(\"object\"),\n \t\t\tN_(\"print only tags of the object\"), 0, parse_opt_points_at\n \t\t},\n \t\tOPT_END()\ndiff --git a/parse-options-cb.c b/parse-options-cb.c\nindex be8c413..a4d294d 100644\n--- a/parse-options-cb.c\n+++ b/parse-options-cb.c\n@@ -4,6 +4,7 @@\n #include \"commit.h\"\n #include \"color.h\"\n #include \"string-list.h\"\n+#include \"sha1-array.h\"\n \n /*----- some often used options -----*/\n \n@@ -92,6 +93,22 @@ int parse_opt_with_commit(const struct option *opt, const char *arg, int unset)\n \treturn 0;\n }\n \n+int parse_opt_points_at(const struct option *opt, const char *arg, int unset)\n+{\n+\tunsigned char sha1[20];\n+\n+\tif (unset) {\n+\t\tsha1_array_clear(opt->value);\n+\t\treturn 0;\n+\t}\n+\tif (!arg)\n+\t\treturn -1;\n+\tif (get_sha1(arg, sha1))\n+\t\treturn error(_(\"malformed object name '%s'\"), arg);\n+\tsha1_array_append(opt->value, sha1);\n+\treturn 0;\n+}\n+\n int parse_opt_tertiary(const struct option *opt, const char *arg, int unset)\n {\n \tint *target = opt->value;\ndiff --git a/parse-options.h b/parse-options.h\nindex c71e9da..3ae16a1 100644\n--- a/parse-options.h\n+++ b/parse-options.h\n@@ -220,6 +220,7 @@ extern int parse_opt_approxidate_cb(const struct option *, const char *, int);\n extern int parse_opt_expiry_date_cb(const struct option *, const char *, int);\n extern int parse_opt_color_flag_cb(const struct option *, const char *, int);\n extern int parse_opt_verbosity_cb(const struct option *, const char *, int);\n+extern int parse_opt_points_at(const struct option *, const char *, int);\n extern int parse_opt_with_commit(const struct option *, const char *, int);\n extern int parse_opt_tertiary(const struct option *, const char *, int);\n extern int parse_opt_string_list(const struct option *, const char *, int);\n-- \n2.4.2\n"},{"id":"263125","messageId":"1433621052-5588-2-git-send-email-karthik.188@gmail.com","threadId":"39547","inReplyTo":"1433621052-5588-1-git-send-email-karthik.188@gmail.com","subject":"[RFC/PATCH 2/9] ref-filter: implement '--points-at' option","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-06T20:04:05Z","receivedAt":"2015-06-06T20:04:05Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"In 'tag -l' we have '--points-at' option which lets users\nlist only tags which point to a particular commit, Implement\nthis option in 'ref-filter.{c,h}' so that the other commands\ncan benefit from this.\n\nBased-on-patch-by: Jeff King <peff@peff.net>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n ref-filter.c | 26 ++++++++++++++++++++++++++\n ref-filter.h |  1 +\n 2 files changed, 27 insertions(+)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 745d3b3..456b0fa 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -841,6 +841,29 @@ static int match_name_as_path(const char **pattern, const char *refname)\n \treturn 0;\n }\n \n+/*\n+ * Given a ref (sha1, refname) see if it points to a one of the sha1s\n+ * in a sha1_array.\n+ */\n+static int match_points_at(struct sha1_array *points_at, const unsigned char *sha1,\n+\t\t\t   const char *refname)\n+{\n+\tstruct object *obj;\n+\n+\tif (!points_at || !points_at->nr)\n+\t\treturn 1;\n+\n+\tif (sha1_array_lookup(points_at, sha1) >= 0)\n+\t\treturn 1;\n+\n+\tobj = parse_object_or_die(sha1, refname);\n+\tif (obj->type == OBJ_TAG &&\n+\t    sha1_array_lookup(points_at, ((struct tag *)obj)->tagged->sha1) >= 0)\n+\t\treturn 1;\n+\n+\treturn 0;\n+}\n+\n /* Allocate space for a new ref_array_item and copy the objectname and flag to it */\n static struct ref_array_item *new_ref_array_item(const char *refname,\n \t\t\t\t\t\t const unsigned char *objectname,\n@@ -874,6 +897,9 @@ int ref_filter_handler(const char *refname, const struct object_id *oid, int fla\n \tif (*filter->name_patterns && !match_name_as_path(filter->name_patterns, refname))\n \t\treturn 0;\n \n+\tif (!match_points_at(&filter->points_at, oid->hash, refname))\n+\t\treturn 0;\n+\n \t/*\n \t * We do not open the object yet; sort may only need refname\n \t * to do its job and the resulting list may yet to be pruned\ndiff --git a/ref-filter.h b/ref-filter.h\nindex 041a39a..a8980e7 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -39,6 +39,7 @@ struct ref_array {\n \n struct ref_filter {\n \tconst char **name_patterns;\n+\tstruct sha1_array points_at;\n };\n \n struct ref_filter_cbdata {\n-- \n2.4.2\n"},{"id":"263124","messageId":"1433621052-5588-3-git-send-email-karthik.188@gmail.com","threadId":"39547","inReplyTo":"1433621052-5588-1-git-send-email-karthik.188@gmail.com","subject":"[RFC/PATCH 3/9] for-each-ref: add '--points-at' option","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-06T20:04:06Z","receivedAt":"2015-06-06T20:04:06Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Add the '--points-at' option provided by 'ref-filter'. The\noption lets the user to pick only refs which point to a particular\ncommit.\n\nAdd Documentation for the same.\n\nBased-on-patch-by: Jeff King <peff@peff.net>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n Documentation/git-for-each-ref.txt | 3 +++\n builtin/for-each-ref.c             | 6 +++++-\n 2 files changed, 8 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt\nindex 7f8d9a5..e9f6a8a 100644\n--- a/Documentation/git-for-each-ref.txt\n+++ b/Documentation/git-for-each-ref.txt\n@@ -10,6 +10,7 @@ SYNOPSIS\n [verse]\n 'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]\n \t\t   [(--sort=<key>)...] [--format=<format>] [<pattern>...]\n+\t\t   [--points-at <object>]\n \n DESCRIPTION\n -----------\n@@ -62,6 +63,8 @@ OPTIONS\n \tthe specified host language.  This is meant to produce\n \ta scriptlet that can directly be `eval`ed.\n \n+--points-at <object>::\n+\tOnly list tags of the given object.\n \n FIELD NAMES\n -----------\ndiff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c\nindex 4d2d024..b9d180a 100644\n--- a/builtin/for-each-ref.c\n+++ b/builtin/for-each-ref.c\n@@ -7,6 +7,7 @@\n \n static char const * const for_each_ref_usage[] = {\n \tN_(\"git for-each-ref [<options>] [<pattern>]\"),\n+\tN_(\"git for-each-ref [--points-at <object>]\"),\n \tNULL\n };\n \n@@ -17,6 +18,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n \tstruct ref_sorting *sorting = NULL, **sorting_tail = &sorting;\n \tint maxcount = 0, quote_style = 0;\n \tstruct ref_filter_cbdata ref_cbdata;\n+\tmemset(&ref_cbdata, 0, sizeof(ref_cbdata));\n \n \tstruct option opts[] = {\n \t\tOPT_BIT('s', \"shell\", &quote_style,\n@@ -33,6 +35,9 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n \t\tOPT_STRING(  0 , \"format\", &format, N_(\"format\"), N_(\"format to use for the output\")),\n \t\tOPT_CALLBACK(0 , \"sort\", sorting_tail, N_(\"key\"),\n \t\t\t    N_(\"field name to sort on\"), &parse_opt_ref_sorting),\n+\t\tOPT_CALLBACK(0, \"points-at\", &ref_cbdata.filter.points_at,\n+\t\t\t     N_(\"object\"), N_(\"print only tags of the object\"),\n+\t\t\t     parse_opt_points_at),\n \t\tOPT_END(),\n \t};\n \n@@ -54,7 +59,6 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n \t/* for warn_ambiguous_refs */\n \tgit_config(git_default_config, NULL);\n \n-\tmemset(&ref_cbdata, 0, sizeof(ref_cbdata));\n \tref_cbdata.filter.name_patterns = argv;\n \tfilter_refs(for_each_rawref, &ref_cbdata);\n \n-- \n2.4.2\n"},{"id":"263129","messageId":"1433621052-5588-4-git-send-email-karthik.188@gmail.com","threadId":"39547","inReplyTo":"1433621052-5588-1-git-send-email-karthik.188@gmail.com","subject":"[RFC/PATCH 4/9] parse-options: add parse_opt_merge_filter()","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-06T20:04:07Z","receivedAt":"2015-06-06T20:04:07Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Add 'parse_opt_merge_filter()' to parse '--merged' and '--no-merged'\noptions and write MACROS for the same.\n\nBased-on-patch-by: Jeff King <peff@peff.net>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n parse-options-cb.c | 22 ++++++++++++++++++++++\n parse-options.h    | 11 +++++++++++\n 2 files changed, 33 insertions(+)\n\ndiff --git a/parse-options-cb.c b/parse-options-cb.c\nindex a4d294d..1969803 100644\n--- a/parse-options-cb.c\n+++ b/parse-options-cb.c\n@@ -4,6 +4,7 @@\n #include \"commit.h\"\n #include \"color.h\"\n #include \"string-list.h\"\n+#include \"ref-filter.h\"\n #include \"sha1-array.h\"\n \n /*----- some often used options -----*/\n@@ -109,6 +110,27 @@ int parse_opt_points_at(const struct option *opt, const char *arg, int unset)\n \treturn 0;\n }\n \n+int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)\n+{\n+\tstruct ref_filter *rf = opt->value;\n+\tunsigned char sha1[20];\n+\n+\trf->merge = opt->long_name[0] == 'n'\n+\t\t? REF_FILTER_MERGED_OMIT\n+\t\t: REF_FILTER_MERGED_INCLUDE;\n+\n+\tif (!arg)\n+\t\targ = \"HEAD\";\n+\tif (get_sha1(arg, sha1))\n+\t\tdie(_(\"malformed object name %s\"), arg);\n+\n+\trf->merge_commit = lookup_commit_reference_gently(sha1, 0);\n+\tif (!rf->merge_commit)\n+\t\treturn opterror(opt, \"must point to a commit\", 0);\n+\n+\treturn 0;\n+}\n+\n int parse_opt_tertiary(const struct option *opt, const char *arg, int unset)\n {\n \tint *target = opt->value;\ndiff --git a/parse-options.h b/parse-options.h\nindex 3ae16a1..7bcf0f3 100644\n--- a/parse-options.h\n+++ b/parse-options.h\n@@ -221,6 +221,7 @@ extern int parse_opt_expiry_date_cb(const struct option *, const char *, int);\n extern int parse_opt_color_flag_cb(const struct option *, const char *, int);\n extern int parse_opt_verbosity_cb(const struct option *, const char *, int);\n extern int parse_opt_points_at(const struct option *, const char *, int);\n+extern int parse_opt_merge_filter(const struct option *, const char *, int);\n extern int parse_opt_with_commit(const struct option *, const char *, int);\n extern int parse_opt_tertiary(const struct option *, const char *, int);\n extern int parse_opt_string_list(const struct option *, const char *, int);\n@@ -243,5 +244,15 @@ extern int parse_opt_noop_cb(const struct option *, const char *, int);\n \tOPT_COLOR_FLAG(0, \"color\", (var), (h))\n #define OPT_COLUMN(s, l, v, h) \\\n \t{ OPTION_CALLBACK, (s), (l), (v), N_(\"style\"), (h), PARSE_OPT_OPTARG, parseopt_column_callback }\n+#define OPT_NO_MERGED(filter, h) \\\n+\t{ OPTION_CALLBACK, 0, \"no-merged\", (filter), N_(\"commit\"), (h), \\\n+\t  PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \\\n+\t  parse_opt_merge_filter, (intptr_t) \"HEAD\" \\\n+\t}\n+#define OPT_MERGED(filter, h) \\\n+\t{ OPTION_CALLBACK, 0, \"merged\", (filter), N_(\"commit\"), (h), \\\n+\t  PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \\\n+\t  parse_opt_merge_filter, (intptr_t) \"HEAD\" \\\n+\t}\n \n #endif\n-- \n2.4.2\n"},{"id":"263128","messageId":"1433621052-5588-5-git-send-email-karthik.188@gmail.com","threadId":"39547","inReplyTo":"1433621052-5588-1-git-send-email-karthik.188@gmail.com","subject":"[RFC/PATCH 5/9] ref-filter: implement '--merged' and '--no-merged' options","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-06T20:04:08Z","receivedAt":"2015-06-06T20:04:08Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"In 'branch -l' we have '--merged' option which only lists refs (branches)\nmerged into the named commit and '--no-merged' option which only lists\nrefs (branches) not merged into the named commit will be listed. Implement\nthese two options in ref-filter.{c,h} so that other commands can benefit\nfrom this.\n\nBased-on-patch-by: Jeff King <peff@peff.net>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n ref-filter.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-\n ref-filter.h |  8 ++++++++\n 2 files changed, 68 insertions(+), 1 deletion(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 456b0fa..2be9df2 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -9,6 +9,7 @@\n #include \"tag.h\"\n #include \"quote.h\"\n #include \"ref-filter.h\"\n+#include \"revision.h\"\n \n typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type;\n \n@@ -888,6 +889,7 @@ int ref_filter_handler(const char *refname, const struct object_id *oid, int fla\n \tstruct ref_filter_cbdata *ref_cbdata = cb_data;\n \tstruct ref_filter *filter = &ref_cbdata->filter;\n \tstruct ref_array_item *ref;\n+\tstruct commit *commit = NULL;\n \n \tif (flag & REF_BAD_NAME) {\n \t\t  warning(\"ignoring ref with broken name %s\", refname);\n@@ -900,12 +902,19 @@ int ref_filter_handler(const char *refname, const struct object_id *oid, int fla\n \tif (!match_points_at(&filter->points_at, oid->hash, refname))\n \t\treturn 0;\n \n+\tif(filter->merge_commit) {\n+\t\tcommit = lookup_commit_reference_gently(sha1, 1);\n+\t\tif (!commit)\n+\t\t\treturn 0;\n+\t}\n+\n \t/*\n \t * We do not open the object yet; sort may only need refname\n \t * to do its job and the resulting list may yet to be pruned\n \t * by maxcount logic.\n \t */\n \tref = new_ref_array_item(refname, oid->hash, flag);\n+\tref->commit = commit;\n \n \tREALLOC_ARRAY(ref_cbdata->array.items, ref_cbdata->array.nr + 1);\n \tref_cbdata->array.items[ref_cbdata->array.nr++] = ref;\n@@ -931,6 +940,50 @@ void ref_array_clear(struct ref_array *array)\n \tarray->nr = array->alloc = 0;\n }\n \n+static void do_merge_filter(struct ref_filter_cbdata *ref_cbdata)\n+{\n+\tstruct rev_info revs;\n+\tint i, old_nr;\n+\tstruct ref_filter *filter = &ref_cbdata->filter;\n+\tstruct ref_array *array = &ref_cbdata->array;\n+\tstruct commit_list *p, *to_clear = NULL;\n+\n+\tinit_revisions(&revs, NULL);\n+\n+\tfor (i = 0; i < array->nr; i++) {\n+\t\tstruct ref_array_item *item = array->items[i];\n+\t\tadd_pending_object(&revs, &item->commit->object, item->refname);\n+\t\tcommit_list_insert(item->commit, &to_clear);\n+\t}\n+\n+\tfilter->merge_commit->object.flags |= UNINTERESTING;\n+\tadd_pending_object(&revs, &filter->merge_commit->object, \"\");\n+\n+\trevs.limited = 1;\n+\tif (prepare_revision_walk(&revs))\n+\t\tdie(_(\"revision walk setup failed\"));\n+\n+\told_nr = array->nr;\n+\tarray->nr = 0;\n+\n+\tfor (i = 0; i < old_nr; i++) {\n+\t\tstruct ref_array_item *item = array->items[i];\n+\t\tstruct commit *commit = item->commit;\n+\n+\t\tint is_merged = !!(commit->object.flags & UNINTERESTING);\n+\n+\t\tif (is_merged == (filter->merge == REF_FILTER_MERGED_INCLUDE))\n+\t\t\tarray->items[array->nr++] = array->items[i];\n+\t\telse\n+\t\t\tfree_array_item(item);\n+\t}\n+\n+\tfor (p = to_clear; p; p = p->next)\n+\t\tclear_commit_marks(p->item, ALL_REV_FLAGS);\n+\tclear_commit_marks(filter->merge_commit, ALL_REV_FLAGS);\n+\tfree_commit_list(to_clear);\n+}\n+\n /*\n  * API for filtering a set of refs. The refs are provided and iterated\n  * over using the for_each_ref_fn(). The refs are stored into and filtered\n@@ -938,7 +991,13 @@ void ref_array_clear(struct ref_array *array)\n  */\n int filter_refs(int (for_each_ref_fn)(each_ref_fn, void *), struct ref_filter_cbdata *data)\n {\n-\treturn for_each_ref_fn(ref_filter_handler, data);\n+\tint ret;\n+\n+\tret = for_each_ref_fn(ref_filter_handler, data);\n+\tif (data->filter.merge_commit)\n+\t\tdo_merge_filter(data);\n+\n+\treturn ret;\n }\n \n static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, struct ref_array_item *b)\ndiff --git a/ref-filter.h b/ref-filter.h\nindex a8980e7..622b942 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -28,6 +28,7 @@ struct ref_array_item {\n \tunsigned char objectname[20];\n \tint flag;\n \tchar *symref;\n+\tstruct commit *commit;\n \tstruct atom_value *value;\n \tchar refname[FLEX_ARRAY];\n };\n@@ -40,6 +41,13 @@ struct ref_array {\n struct ref_filter {\n \tconst char **name_patterns;\n \tstruct sha1_array points_at;\n+\n+\tenum {\n+\t\tREF_FILTER_MERGED_NONE = 0,\n+\t\tREF_FILTER_MERGED_INCLUDE,\n+\t\tREF_FILTER_MERGED_OMIT\n+\t} merge;\n+\tstruct commit *merge_commit;\n };\n \n struct ref_filter_cbdata {\n-- \n2.4.2\n"},{"id":"263130","messageId":"1433621052-5588-6-git-send-email-karthik.188@gmail.com","threadId":"39547","inReplyTo":"1433621052-5588-1-git-send-email-karthik.188@gmail.com","subject":"[RFC/PATCH 6/9] for-each-ref: add '--merged' and '--no-merged' options","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-06T20:04:09Z","receivedAt":"2015-06-06T20:04:09Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Add the '--merged' and '--no-merged' options provided by 'ref-filter'.\nThe '--merged' option lets the user to only list refs merged into the\nnamed commit. The '--no-merged' option lets the user to only list refs\nnot merged into the named commit.\n\nAdd documentation for the same.\n\nBased-on-patch-by: Jeff King <peff@peff.net>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n Documentation/git-for-each-ref.txt | 10 +++++++++-\n builtin/for-each-ref.c             |  3 +++\n 2 files changed, 12 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt\nindex e9f6a8a..74f24f4 100644\n--- a/Documentation/git-for-each-ref.txt\n+++ b/Documentation/git-for-each-ref.txt\n@@ -10,7 +10,7 @@ SYNOPSIS\n [verse]\n 'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]\n \t\t   [(--sort=<key>)...] [--format=<format>] [<pattern>...]\n-\t\t   [--points-at <object>]\n+\t\t   [--points-at <object>] [(--merged | --no-merged) <object>]\n \n DESCRIPTION\n -----------\n@@ -66,6 +66,14 @@ OPTIONS\n --points-at <object>::\n \tOnly list tags of the given object.\n \n+--merged [<commit>]::\n+\tOnly list refs whose tips are reachable from the\n+\tspecified commit (HEAD if not specified).\n+\n+--no-merged [<commit>]::\n+\tOnly list refs whose tips are not reachable from the\n+\tspecified commit (HEAD if not specified).\n+\n FIELD NAMES\n -----------\n \ndiff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c\nindex b9d180a..82605ed 100644\n--- a/builtin/for-each-ref.c\n+++ b/builtin/for-each-ref.c\n@@ -8,6 +8,7 @@\n static char const * const for_each_ref_usage[] = {\n \tN_(\"git for-each-ref [<options>] [<pattern>]\"),\n \tN_(\"git for-each-ref [--points-at <object>]\"),\n+\tN_(\"git for-each-ref [(--merged | --no-merged) <object>]\"),\n \tNULL\n };\n \n@@ -38,6 +39,8 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n \t\tOPT_CALLBACK(0, \"points-at\", &ref_cbdata.filter.points_at,\n \t\t\t     N_(\"object\"), N_(\"print only tags of the object\"),\n \t\t\t     parse_opt_points_at),\n+\t\tOPT_MERGED(&ref_cbdata.filter, N_(\"print only merged refs\")),\n+\t\tOPT_NO_MERGED(&ref_cbdata.filter, N_(\"print only not merged refs\")),\n \t\tOPT_END(),\n \t};\n \n-- \n2.4.2\n"},{"id":"263131","messageId":"1433621052-5588-7-git-send-email-karthik.188@gmail.com","threadId":"39547","inReplyTo":"1433621052-5588-1-git-send-email-karthik.188@gmail.com","subject":"[RFC/PATCH 7/9] parse-options.h: add macros for '--contains' option","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-06T20:04:10Z","receivedAt":"2015-06-06T20:04:10Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Add a macro for using the '--contains' option in parse-options.h\nalso include an optional '--with' option macro which performs the\nsame action as '--contains'.\n\nMake tag.c use this new macro\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n builtin/tag.c   | 14 ++------------\n parse-options.h | 10 ++++++++++\n 2 files changed, 12 insertions(+), 12 deletions(-)\n\ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex eda76ba..e16668b 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -591,23 +591,13 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \n \t\tOPT_GROUP(N_(\"Tag listing options\")),\n \t\tOPT_COLUMN(0, \"column\", &colopts, N_(\"show tag list in columns\")),\n+\t\tOPT_CONTAINS(&with_commit, N_(\"print only tags that contain the commit\")),\n+\t\tOPT_WITH(&with_commit, N_(\"print only tags that contain the commit\")),\n \t\t{\n \t\t\tOPTION_CALLBACK, 0, \"sort\", &tag_sort, N_(\"type\"), N_(\"sort tags\"),\n \t\t\tPARSE_OPT_NONEG, parse_opt_sort\n \t\t},\n \t\t{\n-\t\t\tOPTION_CALLBACK, 0, \"contains\", &with_commit, N_(\"commit\"),\n-\t\t\tN_(\"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\t{\n-\t\t\tOPTION_CALLBACK, 0, \"with\", &with_commit, N_(\"commit\"),\n-\t\t\tN_(\"print only tags that contain the commit\"),\n-\t\t\tPARSE_OPT_HIDDEN | PARSE_OPT_LASTARG_DEFAULT,\n-\t\t\tparse_opt_with_commit, (intptr_t)\"HEAD\",\n-\t\t},\n-\t\t{\n \t\t\tOPTION_CALLBACK, 0, \"points-at\", &points_at, N_(\"object\"),\n \t\t\tN_(\"print only tags of the object\"), 0, parse_opt_points_at\n \t\t},\ndiff --git a/parse-options.h b/parse-options.h\nindex 7bcf0f3..d8389ad 100644\n--- a/parse-options.h\n+++ b/parse-options.h\n@@ -254,5 +254,15 @@ extern int parse_opt_noop_cb(const struct option *, const char *, int);\n \t  PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \\\n \t  parse_opt_merge_filter, (intptr_t) \"HEAD\" \\\n \t}\n+#define OPT_CONTAINS(filter, h) \\\n+\t{ OPTION_CALLBACK, 0, \"contains\", (filter), N_(\"commit\"), (h), \\\n+\t  PARSE_OPT_LASTARG_DEFAULT, \\\n+\t  parse_opt_with_commit, (intptr_t) \"HEAD\" \\\n+\t}\n+#define OPT_WITH(filter, h) \\\n+\t{ OPTION_CALLBACK, 0, \"with\", (filter), N_(\"commit\"), (h), \\\n+\t  PARSE_OPT_LASTARG_DEFAULT, \\\n+\t  parse_opt_with_commit, (intptr_t) \"HEAD\" \\\n+\t}\n \n #endif\n-- \n2.4.2\n"},{"id":"263126","messageId":"1433621052-5588-8-git-send-email-karthik.188@gmail.com","threadId":"39547","inReplyTo":"1433621052-5588-1-git-send-email-karthik.188@gmail.com","subject":"[RFC/PATCH 8/9] ref-filter: add '--contains' option","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-06T20:04:11Z","receivedAt":"2015-06-06T20:04:11Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"'tag -l' and 'branch -l' have two different ways of finding\nout if a certain ref contains a commit. Implement both these\nmethods in ref-filter and give the caller of ref-filter API\nthe option to pick which implementation to be used.\n\n'branch -l' uses 'is_descendant_of()' from commit.c which is\nleft as the default implementation to be used.\n\n'tag -l' uses a more specific algorithm since ffc4b80. This\nimplementation is used whenever the 'with_commit_tag_algo' bit\nis set in 'struct ref_filter'.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n ref-filter.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--\n ref-filter.h |   3 ++\n 2 files changed, 115 insertions(+), 2 deletions(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 2be9df2..6c5f5c2 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -818,6 +818,113 @@ static void get_ref_atom_value(struct ref_array_item *ref, int atom, struct atom\n \t*v = &ref->value[atom];\n }\n \n+enum contains_result {\n+\tCONTAINS_UNKNOWN = -1,\n+\tCONTAINS_NO = 0,\n+\tCONTAINS_YES = 1\n+};\n+\n+/*\n+ * Mimicking the real stack, this stack lives on the heap, avoiding stack\n+ * overflows.\n+ *\n+ * At each recursion step, the stack items points to the commits whose\n+ * ancestors are to be inspected.\n+ */\n+struct stack {\n+\tint nr, alloc;\n+\tstruct stack_entry {\n+\t\tstruct commit *commit;\n+\t\tstruct commit_list *parents;\n+\t} *stack;\n+};\n+\n+static int in_commit_list(const struct commit_list *want, struct commit *c)\n+{\n+\tfor (; want; want = want->next)\n+\t\tif (!hashcmp(want->item->object.sha1, c->object.sha1))\n+\t\t\treturn 1;\n+\treturn 0;\n+}\n+\n+/*\n+ * Test whether the candidate or one of its parents is contained in the list.\n+ * Do not recurse to find out, though, but return -1 if inconclusive.\n+ */\n+static enum contains_result contains_test(struct commit *candidate,\n+\t\t\t    const struct commit_list *want)\n+{\n+\t/* was it previously marked as containing a want commit? */\n+\tif (candidate->object.flags & TMP_MARK)\n+\t\treturn 1;\n+\t/* or marked as not possibly containing a want commit? */\n+\tif (candidate->object.flags & UNINTERESTING)\n+\t\treturn 0;\n+\t/* or are we it? */\n+\tif (in_commit_list(want, candidate)) {\n+\t\tcandidate->object.flags |= TMP_MARK;\n+\t\treturn 1;\n+\t}\n+\n+\tif (parse_commit(candidate) < 0)\n+\t\treturn 0;\n+\n+\treturn -1;\n+}\n+\n+static void push_to_stack(struct commit *candidate, struct stack *stack)\n+{\n+\tALLOC_GROW(stack->stack, stack->nr + 1, stack->alloc);\n+\tstack->stack[stack->nr].commit = candidate;\n+\tstack->stack[stack->nr++].parents = candidate->parents;\n+}\n+\n+static enum contains_result contains_tag_algo(struct commit *candidate,\n+\t\tconst struct commit_list *want)\n+{\n+\tstruct stack stack = { 0, 0, NULL };\n+\tint result = contains_test(candidate, want);\n+\n+\tif (result != CONTAINS_UNKNOWN)\n+\t\treturn result;\n+\n+\tpush_to_stack(candidate, &stack);\n+\twhile (stack.nr) {\n+\t\tstruct stack_entry *entry = &stack.stack[stack.nr - 1];\n+\t\tstruct commit *commit = entry->commit;\n+\t\tstruct commit_list *parents = entry->parents;\n+\n+\t\tif (!parents) {\n+\t\t\tcommit->object.flags |= UNINTERESTING;\n+\t\t\tstack.nr--;\n+\t\t}\n+\t\t/*\n+\t\t * If we just popped the stack, parents->item has been marked,\n+\t\t * therefore contains_test will return a meaningful 0 or 1.\n+\t\t */\n+\t\telse switch (contains_test(parents->item, want)) {\n+\t\tcase CONTAINS_YES:\n+\t\t\tcommit->object.flags |= TMP_MARK;\n+\t\t\tstack.nr--;\n+\t\t\tbreak;\n+\t\tcase CONTAINS_NO:\n+\t\t\tentry->parents = parents->next;\n+\t\t\tbreak;\n+\t\tcase CONTAINS_UNKNOWN:\n+\t\t\tpush_to_stack(parents->item, &stack);\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tfree(stack.stack);\n+\treturn contains_test(candidate, want);\n+}\n+\n+static int commit_contains(struct ref_filter *filter, struct commit *commit)\n+{\n+\tif (filter->with_commit_tag_algo)\n+\t\treturn contains_tag_algo(commit, filter->with_commit);\n+\treturn is_descendant_of(commit, filter->with_commit);\n+}\n /*\n  * Given a refname, return 1 if the refname matches with one of the patterns\n  * while the pattern is a pathname like 'refs/tags' or 'refs/heads/master'\n@@ -902,10 +1009,13 @@ int ref_filter_handler(const char *refname, const struct object_id *oid, int fla\n \tif (!match_points_at(&filter->points_at, oid->hash, refname))\n \t\treturn 0;\n \n-\tif(filter->merge_commit) {\n-\t\tcommit = lookup_commit_reference_gently(sha1, 1);\n+\tif(filter->merge_commit || filter->with_commit) {\n+\t\tcommit = lookup_commit_reference_gently(oid->hash, 1);\n \t\tif (!commit)\n \t\t\treturn 0;\n+\t\tif(filter->with_commit &&\n+\t\t   !commit_contains(filter, commit))\n+\t\t\treturn 0;\n \t}\n \n \t/*\ndiff --git a/ref-filter.h b/ref-filter.h\nindex 622b942..c71704e 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -41,6 +41,7 @@ struct ref_array {\n struct ref_filter {\n \tconst char **name_patterns;\n \tstruct sha1_array points_at;\n+\tstruct commit_list *with_commit;\n \n \tenum {\n \t\tREF_FILTER_MERGED_NONE = 0,\n@@ -48,6 +49,8 @@ struct ref_filter {\n \t\tREF_FILTER_MERGED_OMIT\n \t} merge;\n \tstruct commit *merge_commit;\n+\n+\tunsigned int with_commit_tag_algo: 1;\n };\n \n struct ref_filter_cbdata {\n-- \n2.4.2\n"},{"id":"263127","messageId":"1433621052-5588-9-git-send-email-karthik.188@gmail.com","threadId":"39547","inReplyTo":"1433621052-5588-1-git-send-email-karthik.188@gmail.com","subject":"[RFC/PATCH 9/9] for-each-ref: add '--contains' option","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-06T20:04:12Z","receivedAt":"2015-06-06T20:04:12Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Add the '--contains' option provided by 'ref-filter'. The '--contains'\nlists only refs which are contain the specific commit (HEAD of the\nbranch if no commit give).\n\nAdd documentation for the same.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n Documentation/git-for-each-ref.txt | 5 +++++\n builtin/for-each-ref.c             | 2 ++\n 2 files changed, 7 insertions(+)\n\ndiff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt\nindex 74f24f4..7ac64ea 100644\n--- a/Documentation/git-for-each-ref.txt\n+++ b/Documentation/git-for-each-ref.txt\n@@ -11,6 +11,7 @@ SYNOPSIS\n 'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]\n \t\t   [(--sort=<key>)...] [--format=<format>] [<pattern>...]\n \t\t   [--points-at <object>] [(--merged | --no-merged) <object>]\n+\t\t   [--contains <object>]\n \n DESCRIPTION\n -----------\n@@ -74,6 +75,10 @@ OPTIONS\n \tOnly list refs whose tips are not reachable from the\n \tspecified commit (HEAD if not specified).\n \n+--contains [<commit>]::\n+\tOnly list tags which contain the specified commit (HEAD if not\n+\tspecified).\n+\n FIELD NAMES\n -----------\n \ndiff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c\nindex 82605ed..44e1467 100644\n--- a/builtin/for-each-ref.c\n+++ b/builtin/for-each-ref.c\n@@ -9,6 +9,7 @@ static char const * const for_each_ref_usage[] = {\n \tN_(\"git for-each-ref [<options>] [<pattern>]\"),\n \tN_(\"git for-each-ref [--points-at <object>]\"),\n \tN_(\"git for-each-ref [(--merged | --no-merged) <object>]\"),\n+\tN_(\"git for-each-ref [--contains <object>]\"),\n \tNULL\n };\n \n@@ -41,6 +42,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n \t\t\t     parse_opt_points_at),\n \t\tOPT_MERGED(&ref_cbdata.filter, N_(\"print only merged refs\")),\n \t\tOPT_NO_MERGED(&ref_cbdata.filter, N_(\"print only not merged refs\")),\n+\t\tOPT_CONTAINS(&ref_cbdata.filter.with_commit, N_(\"print only refs which contain the commit\")),\n \t\tOPT_END(),\n \t};\n \n-- \n2.4.2\n"},{"id":"263150","messageId":"CAP8UFD2FCKTbfzRtNWdwimR93-k3WWoQPOWEKsSPrVpdcEmkDg@mail.gmail.com","threadId":"39547","inReplyTo":"5573520A.90603@gmail.com","subject":"Re: [RFC/PATCH 0/9] add options to ref-filter","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2015-06-07T13:10:04Z","receivedAt":"2015-06-07T13:10:04Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Sat, Jun 6, 2015 at 10:03 PM, Karthik Nayak <karthik.188@gmail.com> wrote:\n> This is a follow up series to the one posted here\n> http://thread.gmane.org/gmane.comp.version-control.git/270922\n>\n> This patch series adds '--ponints-at', '--merged', '--no-merged' and\n\ns/--ponints-at/--points-at/\n\n> '--contain' options to 'ref-filter' and uses these options in\n> 'for-each-ref'.\n"},{"id":"263218","messageId":"5575AE06.5020302@gmail.com","threadId":"39547","inReplyTo":"CAP8UFD2FCKTbfzRtNWdwimR93-k3WWoQPOWEKsSPrVpdcEmkDg@mail.gmail.com","subject":"Re: [RFC/PATCH 0/9] add options to ref-filter","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-08T15:00:22Z","receivedAt":"2015-06-08T15:00:22Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On 06/07/2015 06:40 PM, Christian Couder wrote:\n> On Sat, Jun 6, 2015 at 10:03 PM, Karthik Nayak <karthik.188@gmail.com> wrote:\n> > This is a follow up series to the one posted here\n> > http://thread.gmane.org/gmane.comp.version-control.git/270922\n> >\n> > This patch series adds '--ponints-at', '--merged', '--no-merged' and\n>\n> s/--ponints-at/--points-at/\n>\n> > '--contain' options to 'ref-filter' and uses these options in\n> > 'for-each-ref'.\n\nThanks!\n\n-- \nRegards,\nKarthik\n"},{"id":"263268","messageId":"vpqwpzertst.fsf@anie.imag.fr","threadId":"39547","inReplyTo":"1433621052-5588-2-git-send-email-karthik.188@gmail.com","subject":"Re: [RFC/PATCH 2/9] ref-filter: implement '--points-at' option","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2015-06-08T17:31:14Z","receivedAt":"2015-06-08T17:31:14Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> +/*\n> + * Given a ref (sha1, refname) see if it points to a one of the sha1s\n> + * in a sha1_array.\n> + */\n> +static int match_points_at(struct sha1_array *points_at, const unsigned char *sha1,\n> +\t\t\t   const char *refname)\n> +{\n> +\tstruct object *obj;\n> +\n> +\tif (!points_at || !points_at->nr)\n> +\t\treturn 1;\n> +\n> +\tif (sha1_array_lookup(points_at, sha1) >= 0)\n> +\t\treturn 1;\n> +\n> +\tobj = parse_object_or_die(sha1, refname);\n> +\tif (obj->type == OBJ_TAG &&\n> +\t    sha1_array_lookup(points_at, ((struct tag *)obj)->tagged->sha1) >= 0)\n> +\t\treturn 1;\n> +\n> +\treturn 0;\n> +}\n\nThere's a similar function in builtin/tag.c that you are not removing.\nYou should justify why you are doing this code duplication in the commit\nmessage (or not do code duplication). It might make sense to add a\ncomment next to match_points_at in tag.c saying stg like \"this is\nduplicated from ..., will be removed later\".\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"263269","messageId":"vpqlhfurtlb.fsf@anie.imag.fr","threadId":"39547","inReplyTo":"1433621052-5588-3-git-send-email-karthik.188@gmail.com","subject":"Re: [RFC/PATCH 3/9] for-each-ref: add '--points-at' option","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2015-06-08T17:35:44Z","receivedAt":"2015-06-08T17:35:44Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> Add the '--points-at' option provided by 'ref-filter'. The\n> option lets the user to pick only refs which point to a particular\n> commit.\n>\n> Add Documentation for the same.\n\n... but no test?\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"263272","messageId":"vpqeglmrsut.fsf@anie.imag.fr","threadId":"39547","inReplyTo":"1433621052-5588-5-git-send-email-karthik.188@gmail.com","subject":"Re: [RFC/PATCH 5/9] ref-filter: implement '--merged' and '--no-merged' options","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2015-06-08T17:51:38Z","receivedAt":"2015-06-08T17:51:38Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> +\tif(filter->merge_commit) {\n\nspace after if.\n\n> @@ -938,7 +991,13 @@ void ref_array_clear(struct ref_array *array)\n>   */\n>  int filter_refs(int (for_each_ref_fn)(each_ref_fn, void *), struct ref_filter_cbdata *data)\n>  {\n> -\treturn for_each_ref_fn(ref_filter_handler, data);\n> +\tint ret;\n> +\n> +\tret = for_each_ref_fn(ref_filter_handler, data);\n> +\tif (data->filter.merge_commit)\n> +\t\tdo_merge_filter(data);\n\nReading this, I first wondered why you did not do the merge_filter as\npart of ref_filter_handler. It seems weird to fill-in an array and then\nre-filter it. I think it would make sense to add a few comments, like\n\n/* Simple per-ref filtering */\nret = for_each_ref_fn(ref_filter_handler, data);\n\n/* Filters that need revision walking */\nif (data->filter.merge_commit)\n...\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"263273","messageId":"vpq8ubursrh.fsf@anie.imag.fr","threadId":"39547","inReplyTo":"1433621052-5588-6-git-send-email-karthik.188@gmail.com","subject":"Re: [RFC/PATCH 6/9] for-each-ref: add '--merged' and '--no-merged' options","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2015-06-08T17:53:38Z","receivedAt":"2015-06-08T17:53:38Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> Add the '--merged' and '--no-merged' options provided by 'ref-filter'.\n> The '--merged' option lets the user to only list refs merged into the\n> named commit. The '--no-merged' option lets the user to only list refs\n> not merged into the named commit.\n>\n> Add documentation for the same.\n\nThis also requires some tests. The algorithmic part will be validated by\n'git tag --merged' using this library, but you need to check the\ncodepath from the command-line to the lib in for-each-ref.\n\n> @@ -38,6 +39,8 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n>  \t\tOPT_CALLBACK(0, \"points-at\", &ref_cbdata.filter.points_at,\n>  \t\t\t     N_(\"object\"), N_(\"print only tags of the object\"),\n>  \t\t\t     parse_opt_points_at),\n> +\t\tOPT_MERGED(&ref_cbdata.filter, N_(\"print only merged refs\")),\n> +\t\tOPT_NO_MERGED(&ref_cbdata.filter, N_(\"print only not merged refs\")),\n\nI'd spell that \"only refs that are not merged\".\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"263274","messageId":"vpqoakqozdr.fsf@anie.imag.fr","threadId":"39547","inReplyTo":"1433621052-5588-4-git-send-email-karthik.188@gmail.com","subject":"Re: [RFC/PATCH 4/9] parse-options: add parse_opt_merge_filter()","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2015-06-08T17:58:56Z","receivedAt":"2015-06-08T17:58:56Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> +int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)\n> +{\n> +\tstruct ref_filter *rf = opt->value;\n> +\tunsigned char sha1[20];\n> +\n> +\trf->merge = opt->long_name[0] == 'n'\n> +\t\t? REF_FILTER_MERGED_OMIT\n> +\t\t: REF_FILTER_MERGED_INCLUDE;\n\nI would use starts_with(\"no-\", opt->long_name) instead. I had a hard\ntime understanding why the letter 'n' was special while the\nstarts_with() version is self-explanatory.\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"263275","messageId":"vpqmw0aozbr.fsf@anie.imag.fr","threadId":"39547","inReplyTo":"1433621052-5588-2-git-send-email-karthik.188@gmail.com","subject":"Re: [RFC/PATCH 2/9] ref-filter: implement '--points-at' option","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2015-06-08T18:00:08Z","receivedAt":"2015-06-08T18:00:08Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> In 'tag -l' we have '--points-at' option which lets users\n> list only tags which point to a particular commit, Implement\n\ns/,/./ ?\n\n> this option in 'ref-filter.{c,h}' so that the other commands\n\ns/the//\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"263283","messageId":"5575E40E.3000500@gmail.com","threadId":"39547","inReplyTo":"vpqwpzertst.fsf@anie.imag.fr","subject":"Re: [RFC/PATCH 2/9] ref-filter: implement '--points-at' option","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-08T18:50:54Z","receivedAt":"2015-06-08T18:50:54Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On 06/08/2015 11:01 PM, Matthieu Moy wrote:\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> +/*\n>> + * Given a ref (sha1, refname) see if it points to a one of the sha1s\n>> + * in a sha1_array.\n>> + */\n>> +static int match_points_at(struct sha1_array *points_at, const unsigned char *sha1,\n>> +\t\t\t   const char *refname)\n>> +{\n>> +\tstruct object *obj;\n>> +\n>> +\tif (!points_at || !points_at->nr)\n>> +\t\treturn 1;\n>> +\n>> +\tif (sha1_array_lookup(points_at, sha1) >= 0)\n>> +\t\treturn 1;\n>> +\n>> +\tobj = parse_object_or_die(sha1, refname);\n>> +\tif (obj->type == OBJ_TAG &&\n>> +\t    sha1_array_lookup(points_at, ((struct tag *)obj)->tagged->sha1) >= 0)\n>> +\t\treturn 1;\n>> +\n>> +\treturn 0;\n>> +}\n>\n> There's a similar function in builtin/tag.c that you are not removing.\n> You should justify why you are doing this code duplication in the commit\n> message (or not do code duplication). It might make sense to add a\n> comment next to match_points_at in tag.c saying stg like \"this is\n> duplicated from ..., will be removed later\".\n>\n\nOk will add this :)\n\n-- \nRegards,\nKarthik\n"},{"id":"263284","messageId":"5575E43E.4030708@gmail.com","threadId":"39547","inReplyTo":"vpqlhfurtlb.fsf@anie.imag.fr","subject":"Re: [RFC/PATCH 3/9] for-each-ref: add '--points-at' option","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-08T18:51:42Z","receivedAt":"2015-06-08T18:51:42Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On 06/08/2015 11:05 PM, Matthieu Moy wrote:\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> Add the '--points-at' option provided by 'ref-filter'. The\n>> option lets the user to pick only refs which point to a particular\n>> commit.\n>>\n>> Add Documentation for the same.\n>\n> ... but no test?\n>\n\nNo haven't written tests, this was just to ensure if the way this is \nmoving forth is correct.\n\n-- \nRegards,\nKarthik\n"},{"id":"263285","messageId":"5575E496.9030102@gmail.com","threadId":"39547","inReplyTo":"vpqeglmrsut.fsf@anie.imag.fr","subject":"Re: [RFC/PATCH 5/9] ref-filter: implement '--merged' and '--no-merged' options","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-08T18:53:10Z","receivedAt":"2015-06-08T18:53:10Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On 06/08/2015 11:21 PM, Matthieu Moy wrote:\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> +\tif(filter->merge_commit) {\n>\n> space after if.\n>\n>> @@ -938,7 +991,13 @@ void ref_array_clear(struct ref_array *array)\n>>    */\n>>   int filter_refs(int (for_each_ref_fn)(each_ref_fn, void *), struct ref_filter_cbdata *data)\n>>   {\n>> -\treturn for_each_ref_fn(ref_filter_handler, data);\n>> +\tint ret;\n>> +\n>> +\tret = for_each_ref_fn(ref_filter_handler, data);\n>> +\tif (data->filter.merge_commit)\n>> +\t\tdo_merge_filter(data);\n>\n> Reading this, I first wondered why you did not do the merge_filter as\n> part of ref_filter_handler. It seems weird to fill-in an array and then\n> re-filter it. I think it would make sense to add a few comments, like\n>\n> /* Simple per-ref filtering */\n> ret = for_each_ref_fn(ref_filter_handler, data);\n>\n> /* Filters that need revision walking */\n> if (data->filter.merge_commit)\n> ...\n>\n\nThanks! will add the space and comments as suggested.\n\n-- \nRegards,\nKarthik\n"},{"id":"263286","messageId":"5575E4C8.70101@gmail.com","threadId":"39547","inReplyTo":"vpq8ubursrh.fsf@anie.imag.fr","subject":"Re: [RFC/PATCH 6/9] for-each-ref: add '--merged' and '--no-merged' options","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-08T18:54:00Z","receivedAt":"2015-06-08T18:54:00Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On 06/08/2015 11:23 PM, Matthieu Moy wrote:\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> Add the '--merged' and '--no-merged' options provided by 'ref-filter'.\n>> The '--merged' option lets the user to only list refs merged into the\n>> named commit. The '--no-merged' option lets the user to only list refs\n>> not merged into the named commit.\n>>\n>> Add documentation for the same.\n>\n> This also requires some tests. The algorithmic part will be validated by\n> 'git tag --merged' using this library, but you need to check the\n> codepath from the command-line to the lib in for-each-ref.\n>\n>> @@ -38,6 +39,8 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n>>   \t\tOPT_CALLBACK(0, \"points-at\", &ref_cbdata.filter.points_at,\n>>   \t\t\t     N_(\"object\"), N_(\"print only tags of the object\"),\n>>   \t\t\t     parse_opt_points_at),\n>> +\t\tOPT_MERGED(&ref_cbdata.filter, N_(\"print only merged refs\")),\n>> +\t\tOPT_NO_MERGED(&ref_cbdata.filter, N_(\"print only not merged refs\")),\n>\n> I'd spell that \"only refs that are not merged\".\n>\n\nLike I mentioned, no tests were written.\nWill change that.\n\n-- \nRegards,\nKarthik\n"},{"id":"263287","messageId":"5575E4E4.4080403@gmail.com","threadId":"39547","inReplyTo":"vpqoakqozdr.fsf@anie.imag.fr","subject":"Re: [RFC/PATCH 4/9] parse-options: add parse_opt_merge_filter()","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-08T18:54:28Z","receivedAt":"2015-06-08T18:54:28Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On 06/08/2015 11:28 PM, Matthieu Moy wrote:\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> +int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)\n>> +{\n>> +\tstruct ref_filter *rf = opt->value;\n>> +\tunsigned char sha1[20];\n>> +\n>> +\trf->merge = opt->long_name[0] == 'n'\n>> +\t\t? REF_FILTER_MERGED_OMIT\n>> +\t\t: REF_FILTER_MERGED_INCLUDE;\n>\n> I would use starts_with(\"no-\", opt->long_name) instead. I had a hard\n> time understanding why the letter 'n' was special while the\n> starts_with() version is self-explanatory.\n>\n\nCan do that also :)\n\n-- \nRegards,\nKarthik\n"},{"id":"263288","messageId":"5575E4F5.8050808@gmail.com","threadId":"39547","inReplyTo":"vpqmw0aozbr.fsf@anie.imag.fr","subject":"Re: [RFC/PATCH 2/9] ref-filter: implement '--points-at' option","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-08T18:54:45Z","receivedAt":"2015-06-08T18:54:45Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On 06/08/2015 11:30 PM, Matthieu Moy wrote:\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> In 'tag -l' we have '--points-at' option which lets users\n>> list only tags which point to a particular commit, Implement\n>\n> s/,/./ ?\n>\n>> this option in 'ref-filter.{c,h}' so that the other commands\n>\n> s/the//\n>\n\nNoted! thanks\n\n-- \nRegards,\nKarthik\n"},{"id":"263289","messageId":"xmqq4mmiauu0.fsf@gitster.dls.corp.google.com","threadId":"39547","inReplyTo":"1433621052-5588-1-git-send-email-karthik.188@gmail.com","subject":"Re: [RFC/PATCH 1/9] tag: libify parse_opt_points_at()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-06-08T19:00:55Z","receivedAt":"2015-06-08T19:00:55Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> diff --git a/parse-options-cb.c b/parse-options-cb.c\n> index be8c413..a4d294d 100644\n> --- a/parse-options-cb.c\n> +++ b/parse-options-cb.c\n> @@ -4,6 +4,7 @@\n>  #include \"commit.h\"\n>  #include \"color.h\"\n>  #include \"string-list.h\"\n> +#include \"sha1-array.h\"\n>  ...\n> +int parse_opt_points_at(const struct option *opt, const char *arg, int unset)\n> +{\n> +\tunsigned char sha1[20];\n> +\n> +\tif (unset) {\n> +\t\tsha1_array_clear(opt->value);\n> +\t\treturn 0;\n> +\t}\n> +\tif (!arg)\n> +\t\treturn -1;\n> +\tif (get_sha1(arg, sha1))\n> +\t\treturn error(_(\"malformed object name '%s'\"), arg);\n> +\tsha1_array_append(opt->value, sha1);\n> +\treturn 0;\n> +}\n> +\n\nThis feels way too specialized to live as part of parse_options\ninfrastructure.\n\nThe existing caller(s) may want to use this callback for parsing\n\"points-at\" option they have, but is that the only plausible use of\nthis callback?  It looks to be usable by any future caller that\nwants to take and accumulate any object names into an sha1-array, so\nperhaps rename it to be a bit more generic to represent its nature\nbetter?\n\n\tparse_opt_object_name()\n\nor something?\n\nI also wonder if we can (and want to) refactor the users of\nwith-commit callback.  Have them use this to obtain an sha1-array\nand then convert what they received into a commit-list themselves.\n\n>  int parse_opt_tertiary(const struct option *opt, const char *arg, int unset)\n>  {\n>  \tint *target = opt->value;\n> diff --git a/parse-options.h b/parse-options.h\n> index c71e9da..3ae16a1 100644\n> --- a/parse-options.h\n> +++ b/parse-options.h\n> @@ -220,6 +220,7 @@ extern int parse_opt_approxidate_cb(const struct option *, const char *, int);\n>  extern int parse_opt_expiry_date_cb(const struct option *, const char *, int);\n>  extern int parse_opt_color_flag_cb(const struct option *, const char *, int);\n>  extern int parse_opt_verbosity_cb(const struct option *, const char *, int);\n> +extern int parse_opt_points_at(const struct option *, const char *, int);\n>  extern int parse_opt_with_commit(const struct option *, const char *, int);\n>  extern int parse_opt_tertiary(const struct option *, const char *, int);\n>  extern int parse_opt_string_list(const struct option *, const char *, int);\n"},{"id":"263290","messageId":"xmqqzj4a9fpn.fsf@gitster.dls.corp.google.com","threadId":"39547","inReplyTo":"1433621052-5588-3-git-send-email-karthik.188@gmail.com","subject":"Re: [RFC/PATCH 3/9] for-each-ref: add '--points-at' option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-06-08T19:12:52Z","receivedAt":"2015-06-08T19:12:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> Add the '--points-at' option provided by 'ref-filter'. The\n> option lets the user to pick only refs which point to a particular\n> commit.\n>\n> Add Documentation for the same.\n>\n> Based-on-patch-by: Jeff King <peff@peff.net>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>\n> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n> ---\n>  Documentation/git-for-each-ref.txt | 3 +++\n>  builtin/for-each-ref.c             | 6 +++++-\n>  2 files changed, 8 insertions(+), 1 deletion(-)\n>\n> diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt\n> index 7f8d9a5..e9f6a8a 100644\n> --- a/Documentation/git-for-each-ref.txt\n> +++ b/Documentation/git-for-each-ref.txt\n> @@ -10,6 +10,7 @@ SYNOPSIS\n>  [verse]\n>  'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]\n>  \t\t   [(--sort=<key>)...] [--format=<format>] [<pattern>...]\n> +\t\t   [--points-at <object>]\n>  \n>  DESCRIPTION\n>  -----------\n> @@ -62,6 +63,8 @@ OPTIONS\n>  \tthe specified host language.  This is meant to produce\n>  \ta scriptlet that can directly be `eval`ed.\n>  \n> +--points-at <object>::\n> +\tOnly list tags of the given object.\n\nIs this intended?  I would have expected if I did\n\n\tgit for-each-ref --points-at master\n\nI would get refs/heads/master and any other refs that exactly points\nat that commit.\n\n>  \n>  FIELD NAMES\n>  -----------\n> diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c\n> index 4d2d024..b9d180a 100644\n> --- a/builtin/for-each-ref.c\n> +++ b/builtin/for-each-ref.c\n> @@ -7,6 +7,7 @@\n>  \n>  static char const * const for_each_ref_usage[] = {\n>  \tN_(\"git for-each-ref [<options>] [<pattern>]\"),\n> +\tN_(\"git for-each-ref [--points-at <object>]\"),\n>  \tNULL\n>  };\n>  \n> @@ -17,6 +18,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n>  \tstruct ref_sorting *sorting = NULL, **sorting_tail = &sorting;\n>  \tint maxcount = 0, quote_style = 0;\n>  \tstruct ref_filter_cbdata ref_cbdata;\n> +\tmemset(&ref_cbdata, 0, sizeof(ref_cbdata));\n>  \n>  \tstruct option opts[] = {\n>  \t\tOPT_BIT('s', \"shell\", &quote_style,\n> @@ -33,6 +35,9 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n>  \t\tOPT_STRING(  0 , \"format\", &format, N_(\"format\"), N_(\"format to use for the output\")),\n>  \t\tOPT_CALLBACK(0 , \"sort\", sorting_tail, N_(\"key\"),\n>  \t\t\t    N_(\"field name to sort on\"), &parse_opt_ref_sorting),\n> +\t\tOPT_CALLBACK(0, \"points-at\", &ref_cbdata.filter.points_at,\n> +\t\t\t     N_(\"object\"), N_(\"print only tags of the object\"),\n> +\t\t\t     parse_opt_points_at),\n>  \t\tOPT_END(),\n>  \t};\n>  \n> @@ -54,7 +59,6 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n>  \t/* for warn_ambiguous_refs */\n>  \tgit_config(git_default_config, NULL);\n>  \n> -\tmemset(&ref_cbdata, 0, sizeof(ref_cbdata));\n\nI cannot quite see how this change relates to the addition of the\nnew option.\n\n>  \tref_cbdata.filter.name_patterns = argv;\n>  \tfilter_refs(for_each_rawref, &ref_cbdata);\n"},{"id":"263291","messageId":"xmqqvbey9fcx.fsf@gitster.dls.corp.google.com","threadId":"39547","inReplyTo":"1433621052-5588-4-git-send-email-karthik.188@gmail.com","subject":"Re: [RFC/PATCH 4/9] parse-options: add parse_opt_merge_filter()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-06-08T19:20:30Z","receivedAt":"2015-06-08T19:20:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> +int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)\n> +{\n> +\tstruct ref_filter *rf = opt->value;\n> +\tunsigned char sha1[20];\n> +\n> +\trf->merge = opt->long_name[0] == 'n'\n> +\t\t? REF_FILTER_MERGED_OMIT\n> +\t\t: REF_FILTER_MERGED_INCLUDE;\n> +\n> +\tif (!arg)\n> +\t\targ = \"HEAD\";\n> +\tif (get_sha1(arg, sha1))\n> +\t\tdie(_(\"malformed object name %s\"), arg);\n> +\n> +\trf->merge_commit = lookup_commit_reference_gently(sha1, 0);\n> +\tif (!rf->merge_commit)\n> +\t\treturn opterror(opt, \"must point to a commit\", 0);\n> +\n> +\treturn 0;\n> +}\n\nAgain, this smells too specific to live as a part of parse-options\ninfrastructure.  If we want to have two helper callbacks, one that\ngives the results in an sha1-array (because there is no guarantee\nthat you want only commits) and in a commit-list, I am fine with\nhaving parse_opt_object_name() and parse_opt_with_commit().  Perhaps\nrename the latter which was named too specifically to something more\nsensible (e.g. parse_opt_commit_object_name()) and use it from the\ncaller you wanted to use parse_opt_merge_filter()?  The caller, if\nit is not prepared to see more than one commits specified, may have\nto check if (!list || !list->next) { die(\"I want one and only one\") }\nor something, though.\n\nHaving it in ref-filter.h as parse_opt_merge_filter() is fine,\nthough.  After all, you would be sharing it with for-each-ref,\nbranch and tag and nobody else anyway.\n\n> diff --git a/parse-options.h b/parse-options.h\n> index 3ae16a1..7bcf0f3 100644\n> --- a/parse-options.h\n> +++ b/parse-options.h\n> @@ -221,6 +221,7 @@ extern int parse_opt_expiry_date_cb(const struct option *, const char *, int);\n>  extern int parse_opt_color_flag_cb(const struct option *, const char *, int);\n>  extern int parse_opt_verbosity_cb(const struct option *, const char *, int);\n>  extern int parse_opt_points_at(const struct option *, const char *, int);\n> +extern int parse_opt_merge_filter(const struct option *, const char *, int);\n>  extern int parse_opt_with_commit(const struct option *, const char *, int);\n>  extern int parse_opt_tertiary(const struct option *, const char *, int);\n>  extern int parse_opt_string_list(const struct option *, const char *, int);\n> @@ -243,5 +244,15 @@ extern int parse_opt_noop_cb(const struct option *, const char *, int);\n>  \tOPT_COLOR_FLAG(0, \"color\", (var), (h))\n>  #define OPT_COLUMN(s, l, v, h) \\\n>  \t{ OPTION_CALLBACK, (s), (l), (v), N_(\"style\"), (h), PARSE_OPT_OPTARG, parseopt_column_callback }\n> +#define OPT_NO_MERGED(filter, h) \\\n> +\t{ OPTION_CALLBACK, 0, \"no-merged\", (filter), N_(\"commit\"), (h), \\\n> +\t  PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \\\n> +\t  parse_opt_merge_filter, (intptr_t) \"HEAD\" \\\n> +\t}\n> +#define OPT_MERGED(filter, h) \\\n> +\t{ OPTION_CALLBACK, 0, \"merged\", (filter), N_(\"commit\"), (h), \\\n> +\t  PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \\\n> +\t  parse_opt_merge_filter, (intptr_t) \"HEAD\" \\\n> +\t}\n\nLikewise.\n"},{"id":"263293","messageId":"xmqqr3pm9et4.fsf@gitster.dls.corp.google.com","threadId":"39547","inReplyTo":"1433621052-5588-7-git-send-email-karthik.188@gmail.com","subject":"Re: [RFC/PATCH 7/9] parse-options.h: add macros for '--contains' option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-06-08T19:32:23Z","receivedAt":"2015-06-08T19:32:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> +#define OPT_CONTAINS(filter, h) \\\n> +\t{ OPTION_CALLBACK, 0, \"contains\", (filter), N_(\"commit\"), (h), \\\n> +\t  PARSE_OPT_LASTARG_DEFAULT, \\\n> +\t  parse_opt_with_commit, (intptr_t) \"HEAD\" \\\n> +\t}\n> +#define OPT_WITH(filter, h) \\\n> +\t{ OPTION_CALLBACK, 0, \"with\", (filter), N_(\"commit\"), (h), \\\n> +\t  PARSE_OPT_LASTARG_DEFAULT, \\\n> +\t  parse_opt_with_commit, (intptr_t) \"HEAD\" \\\n> +\t}\n\nThe redundancy bothers me.  Can't we do a bit better than that,\nperhaps like this?\n\n#define _OPT_CONTAINS_OR_WITH(name, variable, help) \\\n\t{ OPTION_CALLBACK, 0, name, (variable), N_(\"commit\"), (help), \\\n\t  PARSE_OPT_LASTARG_DEFAULT, \\\n\t  parse_opt_with_commit, (intptr_t) \"HEAD\" \\\n\t}\n#define OPT_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH(\"contains\", v, h)\n"},{"id":"263294","messageId":"xmqqmw0a9eq7.fsf@gitster.dls.corp.google.com","threadId":"39547","inReplyTo":"5573520A.90603@gmail.com","subject":"Re: [RFC/PATCH 0/9] add options to ref-filter","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-06-08T19:34:08Z","receivedAt":"2015-06-08T19:34:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> This is a follow up series to the one posted here\n> http://thread.gmane.org/gmane.comp.version-control.git/270922\n>\n> This patch series adds '--ponints-at', '--merged', '--no-merged' and\n> '--contain' options to 'ref-filter' and uses these options in\n> for-each-ref'.\n\nThe structure of the series looked sensible (I stopped at around\n7/9, though, for now); even though a few style violations were\nsomewhat irritating, overall it was a pleasant read.\n\nThanks.\n"},{"id":"263342","messageId":"5576D31F.90603@gmail.com","threadId":"39547","inReplyTo":"xmqq4mmiauu0.fsf@gitster.dls.corp.google.com","subject":"Re: [RFC/PATCH 1/9] tag: libify parse_opt_points_at()","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-09T11:50:55Z","receivedAt":"2015-06-09T11:50:55Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On 06/09/2015 12:30 AM, Junio C Hamano wrote:\n>\n> This feels way too specialized to live as part of parse_options\n> infrastructure.\n>\n> The existing caller(s) may want to use this callback for parsing\n> \"points-at\" option they have, but is that the only plausible use of\n> this callback?  It looks to be usable by any future caller that\n> wants to take and accumulate any object names into an sha1-array, so\n> perhaps rename it to be a bit more generic to represent its nature\n> better?\n>\n> \tparse_opt_object_name()\n>\n> or something?\n\nThis makes sense! Will change.\n\n>\n> I also wonder if we can (and want to) refactor the users of\n> with-commit callback.  Have them use this to obtain an sha1-array\n> and then convert what they received into a commit-list themselves.\n>\n\nBut wouldn't that be too much of an overhead to iterate through the\nsha1-array and convert it to a commit-list?\n\n-- \nRegards,\nKarthik\n"},{"id":"263344","messageId":"5576D591.6030704@gmail.com","threadId":"39547","inReplyTo":"xmqqzj4a9fpn.fsf@gitster.dls.corp.google.com","subject":"Re: [RFC/PATCH 3/9] for-each-ref: add '--points-at' option","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-09T12:01:21Z","receivedAt":"2015-06-09T12:01:21Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On 06/09/2015 12:42 AM, Junio C Hamano wrote:\n>\n> Is this intended?  I would have expected if I did\n>\n> \tgit for-each-ref --points-at master\n>\n> I would get refs/heads/master and any other refs that exactly points\n> at that commit.\n>\n\nThats to be changed, thanks!\n\n>>\n>>   FIELD NAMES\n>>   -----------\n>> diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c\n>> index 4d2d024..b9d180a 100644\n>> --- a/builtin/for-each-ref.c\n>> +++ b/builtin/for-each-ref.c\n>> @@ -7,6 +7,7 @@\n>>\n>>   static char const * const for_each_ref_usage[] = {\n>>   \tN_(\"git for-each-ref [<options>] [<pattern>]\"),\n>> +\tN_(\"git for-each-ref [--points-at <object>]\"),\n>>   \tNULL\n>>   };\n>>\n>> @@ -17,6 +18,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n>>   \tstruct ref_sorting *sorting = NULL, **sorting_tail = &sorting;\n>>   \tint maxcount = 0, quote_style = 0;\n>>   \tstruct ref_filter_cbdata ref_cbdata;\n>> +\tmemset(&ref_cbdata, 0, sizeof(ref_cbdata));\n>>\n>>   \tstruct option opts[] = {\n>>   \t\tOPT_BIT('s', \"shell\", &quote_style,\n>> @@ -33,6 +35,9 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n>>   \t\tOPT_STRING(  0 , \"format\", &format, N_(\"format\"), N_(\"format to use for the output\")),\n>>   \t\tOPT_CALLBACK(0 , \"sort\", sorting_tail, N_(\"key\"),\n>>   \t\t\t    N_(\"field name to sort on\"), &parse_opt_ref_sorting),\n>> +\t\tOPT_CALLBACK(0, \"points-at\", &ref_cbdata.filter.points_at,\n>> +\t\t\t     N_(\"object\"), N_(\"print only tags of the object\"),\n>> +\t\t\t     parse_opt_points_at),\n>>   \t\tOPT_END(),\n>>   \t};\n>>\n>> @@ -54,7 +59,6 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n>>   \t/* for warn_ambiguous_refs */\n>>   \tgit_config(git_default_config, NULL);\n>>\n>> -\tmemset(&ref_cbdata, 0, sizeof(ref_cbdata));\n>\n> I cannot quite see how this change relates to the addition of the\n> new option.\n>\n\nWell if we memset() after calling parse_opt_points_at(), we loose all \nthe information we would have obtained.\nSo the memset() is moved to an earlier location.\n\n-- \nRegards,\nKarthik\n"},{"id":"263348","messageId":"5576DDD6.3020205@gmail.com","threadId":"39547","inReplyTo":"xmqqvbey9fcx.fsf@gitster.dls.corp.google.com","subject":"Re: [RFC/PATCH 4/9] parse-options: add parse_opt_merge_filter()","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-09T12:36:38Z","receivedAt":"2015-06-09T12:36:38Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On 06/09/2015 12:50 AM, Junio C Hamano wrote:\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> +int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)\n>> +{\n>> +\tstruct ref_filter *rf = opt->value;\n>> +\tunsigned char sha1[20];\n>> +\n>> +\trf->merge = opt->long_name[0] == 'n'\n>> +\t\t? REF_FILTER_MERGED_OMIT\n>> +\t\t: REF_FILTER_MERGED_INCLUDE;\n>> +\n>> +\tif (!arg)\n>> +\t\targ = \"HEAD\";\n>> +\tif (get_sha1(arg, sha1))\n>> +\t\tdie(_(\"malformed object name %s\"), arg);\n>> +\n>> +\trf->merge_commit = lookup_commit_reference_gently(sha1, 0);\n>> +\tif (!rf->merge_commit)\n>> +\t\treturn opterror(opt, \"must point to a commit\", 0);\n>> +\n>> +\treturn 0;\n>> +}\n>\n> Again, this smells too specific to live as a part of parse-options\n> infrastructure.  If we want to have two helper callbacks, one that\n> gives the results in an sha1-array (because there is no guarantee\n> that you want only commits) and in a commit-list, I am fine with\n> having parse_opt_object_name() and parse_opt_with_commit().  Perhaps\n> rename the latter which was named too specifically to something more\n> sensible (e.g. parse_opt_commit_object_name()) and use it from the\n> caller you wanted to use parse_opt_merge_filter()?  The caller, if\n> it is not prepared to see more than one commits specified, may have\n> to check if (!list || !list->next) { die(\"I want one and only one\") }\n> or something, though.\n>\n> Having it in ref-filter.h as parse_opt_merge_filter() is fine,\n> though.  After all, you would be sharing it with for-each-ref,\n> branch and tag and nobody else anyway.\n >\n\nI guess it's better left in ref-filter.h. We could like you said make\nit depend on parse_opt_with_commit() but that again means we need to \ncheck if more than one commits are specified. So I think it would be \nbetter to have it in ref-filter.h\n>\n>> diff --git a/parse-options.h b/parse-options.h\n>> index 3ae16a1..7bcf0f3 100644\n>> --- a/parse-options.h\n>> +++ b/parse-options.h\n>> @@ -221,6 +221,7 @@ extern int parse_opt_expiry_date_cb(const struct option *, const char *, int);\n>>   extern int parse_opt_color_flag_cb(const struct option *, const char *, int);\n>>   extern int parse_opt_verbosity_cb(const struct option *, const char *, int);\n>>   extern int parse_opt_points_at(const struct option *, const char *, int);\n>> +extern int parse_opt_merge_filter(const struct option *, const char *, int);\n>>   extern int parse_opt_with_commit(const struct option *, const char *, int);\n>>   extern int parse_opt_tertiary(const struct option *, const char *, int);\n>>   extern int parse_opt_string_list(const struct option *, const char *, int);\n>> @@ -243,5 +244,15 @@ extern int parse_opt_noop_cb(const struct option *, const char *, int);\n>>   \tOPT_COLOR_FLAG(0, \"color\", (var), (h))\n>>   #define OPT_COLUMN(s, l, v, h) \\\n>>   \t{ OPTION_CALLBACK, (s), (l), (v), N_(\"style\"), (h), PARSE_OPT_OPTARG, parseopt_column_callback }\n>> +#define OPT_NO_MERGED(filter, h) \\\n>> +\t{ OPTION_CALLBACK, 0, \"no-merged\", (filter), N_(\"commit\"), (h), \\\n>> +\t  PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \\\n>> +\t  parse_opt_merge_filter, (intptr_t) \"HEAD\" \\\n>> +\t}\n>> +#define OPT_MERGED(filter, h) \\\n>> +\t{ OPTION_CALLBACK, 0, \"merged\", (filter), N_(\"commit\"), (h), \\\n>> +\t  PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \\\n>> +\t  parse_opt_merge_filter, (intptr_t) \"HEAD\" \\\n>> +\t}\n>\n> Likewise.\n>\n\nThis too would be better off in ref-filter.h\n\n-- \nRegards,\nKarthik\n"},{"id":"263350","messageId":"5576E0EF.3080301@gmail.com","threadId":"39547","inReplyTo":"xmqqr3pm9et4.fsf@gitster.dls.corp.google.com","subject":"Re: [RFC/PATCH 7/9] parse-options.h: add macros for '--contains' option","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-09T12:49:51Z","receivedAt":"2015-06-09T12:49:51Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On 06/09/2015 01:02 AM, Junio C Hamano wrote:\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> +#define OPT_CONTAINS(filter, h) \\\n>> +\t{ OPTION_CALLBACK, 0, \"contains\", (filter), N_(\"commit\"), (h), \\\n>> +\t  PARSE_OPT_LASTARG_DEFAULT, \\\n>> +\t  parse_opt_with_commit, (intptr_t) \"HEAD\" \\\n>> +\t}\n>> +#define OPT_WITH(filter, h) \\\n>> +\t{ OPTION_CALLBACK, 0, \"with\", (filter), N_(\"commit\"), (h), \\\n>> +\t  PARSE_OPT_LASTARG_DEFAULT, \\\n>> +\t  parse_opt_with_commit, (intptr_t) \"HEAD\" \\\n>> +\t}\n>\n> The redundancy bothers me.  Can't we do a bit better than that,\n> perhaps like this?\n>\n> #define _OPT_CONTAINS_OR_WITH(name, variable, help) \\\n> \t{ OPTION_CALLBACK, 0, name, (variable), N_(\"commit\"), (help), \\\n> \t  PARSE_OPT_LASTARG_DEFAULT, \\\n> \t  parse_opt_with_commit, (intptr_t) \"HEAD\" \\\n> \t}\n> #define OPT_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH(\"contains\", v, h)\n>\n\nThis seems better, thanks!\n\n-- \nRegards,\nKarthik\n"},{"id":"263409","messageId":"xmqqvbew66q9.fsf@gitster.dls.corp.google.com","threadId":"39547","inReplyTo":"5576D591.6030704@gmail.com","subject":"Re: [RFC/PATCH 3/9] for-each-ref: add '--points-at' option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-06-09T19:07:26Z","receivedAt":"2015-06-09T19:07:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n>>> @@ -54,7 +59,6 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n>>>   \t/* for warn_ambiguous_refs */\n>>>   \tgit_config(git_default_config, NULL);\n>>>\n>>> -\tmemset(&ref_cbdata, 0, sizeof(ref_cbdata));\n>>\n>> I cannot quite see how this change relates to the addition of the\n>> new option.\n>>\n>\n> Well if we memset() after calling parse_opt_points_at(), we loose all\n> the information we would have obtained.\n> So the memset() is moved to an earlier location.\n\nwhich I did not see, because I expected the code to follow the usual\n\"no decl-after-statement\" pattern.  IOW\n\n>>   \tint maxcount = 0, quote_style = 0;\n>>   \tstruct ref_filter_cbdata ref_cbdata;\n>> +\tmemset(&ref_cbdata, 0, sizeof(ref_cbdata));\n>>\n>>   \tstruct option opts[] = {\n>>   \t\tOPT_BIT('s', \"shell\", &quote_style,\n\nDon't do that.  Always start your function like so:\n\n\ttype funcname(args)\n        {\n        \tdeclarations;\n\n                first statement;\n\t\t...\n\nwith no blank line within declarations block and a blank line after\nthe declarations block.\n"},{"id":"263433","messageId":"5577DF57.2020607@gmail.com","threadId":"39547","inReplyTo":"xmqqvbew66q9.fsf@gitster.dls.corp.google.com","subject":"Re: [RFC/PATCH 3/9] for-each-ref: add '--points-at' option","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-10T06:55:19Z","receivedAt":"2015-06-10T06:55:19Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On 06/10/2015 12:37 AM, Junio C Hamano wrote:\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n> >>> @@ -54,7 +59,6 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n> >>>        /* for warn_ambiguous_refs */\n> >>>        git_config(git_default_config, NULL);\n> >>>\n> >>> -    memset(&ref_cbdata, 0, sizeof(ref_cbdata));\n> >>\n> >> I cannot quite see how this change relates to the addition of the\n> >> new option.\n> >>\n> >\n> > Well if we memset() after calling parse_opt_points_at(), we loose all\n> > the information we would have obtained.\n> > So the memset() is moved to an earlier location.\n>\n> which I did not see, because I expected the code to follow the usual\n> \"no decl-after-statement\" pattern.  IOW\n>\n> >>        int maxcount = 0, quote_style = 0;\n> >>        struct ref_filter_cbdata ref_cbdata;\n> >> +    memset(&ref_cbdata, 0, sizeof(ref_cbdata));\n> >>\n> >>        struct option opts[] = {\n> >>            OPT_BIT('s', \"shell\", &quote_style,\n>\n> Don't do that.  Always start your function like so:\n>\n>     type funcname(args)\n>          {\n>              declarations;\n>\n>                  first statement;\n>         ...\n>\n> with no blank line within declarations block and a blank line after\n> the declarations block.\n>\nWill do, thanks!\n\n-- \nRegards,\nKarthik\n"},{"id":"263444","messageId":"vpqeglkc8qh.fsf@anie.imag.fr","threadId":"39547","inReplyTo":"xmqqvbew66q9.fsf@gitster.dls.corp.google.com","subject":"Re: [RFC/PATCH 3/9] for-each-ref: add '--points-at' option","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2015-06-10T07:39:50Z","receivedAt":"2015-06-10T07:39:50Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Don't do that.  Always start your function like so:\n>\n> \ttype funcname(args)\n>         {\n>         \tdeclarations;\n>\n>                 first statement;\n> \t\t...\n\nHint: create a file config.mak with this content:\n\n$ cat config.mak\nCFLAGS += -Wdeclaration-after-statement -Wall -Werror\n\nand gcc will prevent you from doing this mistake again.\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"263461","messageId":"55782004.3080600@gmail.com","threadId":"39547","inReplyTo":"vpqeglkc8qh.fsf@anie.imag.fr","subject":"Re: [RFC/PATCH 3/9] for-each-ref: add '--points-at' option","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-06-10T11:31:16Z","receivedAt":"2015-06-10T11:31:16Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"On 06/10/2015 01:09 PM, Matthieu Moy wrote:\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n> > Don't do that.  Always start your function like so:\n> >\n> >     type funcname(args)\n> >          {\n> >              declarations;\n> >\n> >                  first statement;\n> >         ...\n>\n> Hint: create a file config.mak with this content:\n>\n> $ cat config.mak\n> CFLAGS += -Wdeclaration-after-statement -Wall -Werror\n>\n> and gcc will prevent you from doing this mistake again.\n>\n\nThanks a lot!\nYour tips are brilliant.\n\n-- \nRegards,\nKarthik\n"}]}