{"thread":{"id":"51051","subject":"[PATCH 00/19] Convert revision.c to parseopt part 1/4","startedAt":"2019-05-08T11:13:25Z","lastAt":"2019-05-09T12:11:46Z","messageCount":25,"participants":["Nguyễn Thái Ngọc Duy","Derrick Stolee","Duy Nguyen"],"isPatch":true,"patchVersion":1,"patchTotal":19},"messages":[{"id":"375112","messageId":"20190508111249.15262-1-pclouds@gmail.com","threadId":"51051","inReplyTo":null,"subject":"[PATCH 00/19] Convert revision.c to parseopt part 1/4","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:30Z","receivedAt":"2019-05-08T11:13:25Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Following the conversion in diff.c to use parse_options, this time it's\nrevision.c. There are about 76 patches to convert all options, split in\n4 parts. After that there are about 10 more to convert rev users to use\nparse_options() directly.\n\nFull 76 patches are available here [1]. I'm not quite done with those\nlast \"10 more\" patches yet [2], still stuck at that ancient blame UI.\nBut I should be done by the 76 patches are merged.\n\n[1] https://gitlab.com/pclouds/git/commits/revision-opt-parse-options\n[2] https://gitlab.com/pclouds/git/commits/parse-options-step-no-more\n\n\nNguyễn Thái Ngọc Duy (19):\n  revision.h: avoid bit fields in struct rev_info\n  revision.h: move repo field down\n  revision.c: prepare to convert handle_revision_pseudo_opt()\n  rev-parseopt: convert --all\n  rev-parseopt: convert --branches\n  rev-parseopt: convert --bisect\n  rev-parseopt: convert --tags\n  rev-parseopt: convert --remotes\n  rev-parseopt: convert --glob\n  rev-parseopt: convert --exclude\n  rev-parseopt: convert --reflog\n  rev-parseopt: convert --indexed-objects\n  rev-parseopt: convert --not\n  rev-parseopt: convert --no-walk and --do-walk\n  rev-parseopt: convert --single-worktree\n  rev-parseopt: prepare to convert handle_revision_opt()\n  rev-parseopt: convert --max-count\n  rev-parseopt: convert --skip\n  rev-parseopt: convert --min-age and --max-age\n\n Documentation/technical/api-diff.txt |   6 +-\n diff.c                               |  16 -\n diff.h                               |   1 -\n parse-options-cb.c                   |   8 +\n parse-options.h                      |   4 +\n revision.c                           | 465 +++++++++++++++++++--------\n revision.h                           | 172 +++++-----\n 7 files changed, 441 insertions(+), 231 deletions(-)\n\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375113","messageId":"20190508111249.15262-2-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 01/19] revision.h: avoid bit fields in struct rev_info","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:31Z","receivedAt":"2019-05-08T11:13:29Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Bitfield addresses cannot be passed around in a pointer. This makes it\nhard to use parse-options to set/unset them. Turn this struct to\nnormal integers. This of course increases the size of this struct\nmultiple times, but since we only have a handful of rev_info variables\naround, memory consumption is not at all a concern.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n revision.h | 164 ++++++++++++++++++++++++++---------------------------\n 1 file changed, 82 insertions(+), 82 deletions(-)\n\ndiff --git a/revision.h b/revision.h\nindex 4134dc6029..01e4c42274 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -107,95 +107,95 @@ struct rev_info {\n \n \tunsigned int early_output;\n \n-\tunsigned int\tignore_missing:1,\n-\t\t\tignore_missing_links:1;\n+\tunsigned int ignore_missing;\n+\tunsigned int ignore_missing_links;\n \n \t/* Traversal flags */\n-\tunsigned int\tdense:1,\n-\t\t\tprune:1,\n-\t\t\tno_walk:2,\n-\t\t\tremove_empty_trees:1,\n-\t\t\tsimplify_history:1,\n-\t\t\ttopo_order:1,\n-\t\t\tsimplify_merges:1,\n-\t\t\tsimplify_by_decoration:1,\n-\t\t\tsingle_worktree:1,\n-\t\t\ttag_objects:1,\n-\t\t\ttree_objects:1,\n-\t\t\tblob_objects:1,\n-\t\t\tverify_objects:1,\n-\t\t\tedge_hint:1,\n-\t\t\tedge_hint_aggressive:1,\n-\t\t\tlimited:1,\n-\t\t\tunpacked:1,\n-\t\t\tboundary:2,\n-\t\t\tcount:1,\n-\t\t\tleft_right:1,\n-\t\t\tleft_only:1,\n-\t\t\tright_only:1,\n-\t\t\trewrite_parents:1,\n-\t\t\tprint_parents:1,\n-\t\t\tshow_decorations:1,\n-\t\t\treverse:1,\n-\t\t\treverse_output_stage:1,\n-\t\t\tcherry_pick:1,\n-\t\t\tcherry_mark:1,\n-\t\t\tbisect:1,\n-\t\t\tancestry_path:1,\n-\t\t\tfirst_parent_only:1,\n-\t\t\tline_level_traverse:1,\n-\t\t\ttree_blobs_in_commit_order:1,\n-\n-\t\t\t/*\n-\t\t\t * Blobs are shown without regard for their existence.\n-\t\t\t * But not so for trees: unless exclude_promisor_objects\n-\t\t\t * is set and the tree in question is a promisor object;\n-\t\t\t * OR ignore_missing_links is set, the revision walker\n-\t\t\t * dies with a \"bad tree object HASH\" message when\n-\t\t\t * encountering a missing tree. For callers that can\n-\t\t\t * handle missing trees and want them to be filterable\n-\t\t\t * and showable, set this to true. The revision walker\n-\t\t\t * will filter and show such a missing tree as usual,\n-\t\t\t * but will not attempt to recurse into this tree\n-\t\t\t * object.\n-\t\t\t */\n-\t\t\tdo_not_die_on_missing_tree:1,\n-\n-\t\t\t/* for internal use only */\n-\t\t\texclude_promisor_objects:1;\n+\tunsigned int dense;\n+\tunsigned int prune;\n+\tunsigned int no_walk;\n+\tunsigned int remove_empty_trees;\n+\tunsigned int simplify_history;\n+\tunsigned int topo_order;\n+\tunsigned int simplify_merges;\n+\tunsigned int simplify_by_decoration;\n+\tunsigned int single_worktree;\n+\tunsigned int tag_objects;\n+\tunsigned int tree_objects;\n+\tunsigned int blob_objects;\n+\tunsigned int verify_objects;\n+\tunsigned int edge_hint;\n+\tunsigned int edge_hint_aggressive;\n+\tunsigned int limited;\n+\tunsigned int unpacked;\n+\tunsigned int boundary;\n+\tunsigned int count;\n+\tunsigned int left_right;\n+\tunsigned int left_only;\n+\tunsigned int right_only;\n+\tunsigned int rewrite_parents;\n+\tunsigned int print_parents;\n+\tunsigned int show_decorations;\n+\tunsigned int reverse;\n+\tunsigned int reverse_output_stage;\n+\tunsigned int cherry_pick;\n+\tunsigned int cherry_mark;\n+\tunsigned int bisect;\n+\tunsigned int ancestry_path;\n+\tunsigned int first_parent_only;\n+\tunsigned int line_level_traverse;\n+\tunsigned int tree_blobs_in_commit_order;\n+\n+\t/*\n+\t * Blobs are shown without regard for their existence.\n+\t * But not so for trees: unless exclude_promisor_objects\n+\t * is set and the tree in question is a promisor object;\n+\t * OR ignore_missing_links is set, the revision walker\n+\t * dies with a \"bad tree object HASH\" message when\n+\t * encountering a missing tree. For callers that can\n+\t * handle missing trees and want them to be filterable\n+\t * and showable, set this to true. The revision walker\n+\t * will filter and show such a missing tree as usual,\n+\t * but will not attempt to recurse into this tree\n+\t * object.\n+\t */\n+\tunsigned int do_not_die_on_missing_tree;\n+\n+\t/* for internal use only */\n+\tunsigned int exclude_promisor_objects;\n \n \t/* Diff flags */\n-\tunsigned int\tdiff:1,\n-\t\t\tfull_diff:1,\n-\t\t\tshow_root_diff:1,\n-\t\t\tno_commit_id:1,\n-\t\t\tverbose_header:1,\n-\t\t\tignore_merges:1,\n-\t\t\tcombine_merges:1,\n-\t\t\tcombined_all_paths:1,\n-\t\t\tdense_combined_merges:1,\n-\t\t\talways_show_header:1;\n+\tunsigned int diff;\n+\tunsigned int full_diff;\n+\tunsigned int show_root_diff;\n+\tunsigned int no_commit_id;\n+\tunsigned int verbose_header;\n+\tunsigned int ignore_merges;\n+\tunsigned int combine_merges;\n+\tunsigned int combined_all_paths;\n+\tunsigned int dense_combined_merges;\n+\tunsigned int always_show_header;\n \n \t/* Format info */\n-\tunsigned int\tshown_one:1,\n-\t\t\tshown_dashes:1,\n-\t\t\tshow_merge:1,\n-\t\t\tshow_notes:1,\n-\t\t\tshow_notes_given:1,\n-\t\t\tshow_signature:1,\n-\t\t\tpretty_given:1,\n-\t\t\tabbrev_commit:1,\n-\t\t\tabbrev_commit_given:1,\n-\t\t\tzero_commit:1,\n-\t\t\tuse_terminator:1,\n-\t\t\tmissing_newline:1,\n-\t\t\tdate_mode_explicit:1,\n-\t\t\tpreserve_subject:1;\n-\tunsigned int\tdisable_stdin:1;\n+\tunsigned int shown_one;\n+\tunsigned int shown_dashes;\n+\tunsigned int show_merge;\n+\tunsigned int show_notes;\n+\tunsigned int show_notes_given;\n+\tunsigned int show_signature;\n+\tunsigned int pretty_given;\n+\tunsigned int abbrev_commit;\n+\tunsigned int abbrev_commit_given;\n+\tunsigned int zero_commit;\n+\tunsigned int use_terminator;\n+\tunsigned int missing_newline;\n+\tunsigned int date_mode_explicit;\n+\tunsigned int preserve_subject;\n+\tunsigned int disable_stdin;\n \t/* --show-linear-break */\n-\tunsigned int\ttrack_linear:1,\n-\t\t\ttrack_first_time:1,\n-\t\t\tlinear:1;\n+\tunsigned int track_linear;\n+\tunsigned int track_first_time;\n+\tunsigned int linear;\n \n \tstruct date_mode date_mode;\n \tint\t\texpand_tabs_in_log; /* unset if negative */\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375114","messageId":"20190508111249.15262-3-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 02/19] revision.h: move repo field down","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:32Z","receivedAt":"2019-05-08T11:13:33Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This block at the top of rev_info is \"Starting list\" and repo is\nobviously not one. Move it to the bottom since it's not that important\nto stay on top.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n revision.h | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/revision.h b/revision.h\nindex 01e4c42274..71e724c59c 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -74,7 +74,6 @@ struct rev_info {\n \t/* Starting list */\n \tstruct commit_list *commits;\n \tstruct object_array pending;\n-\tstruct repository *repo;\n \n \t/* Parents of shown commits */\n \tstruct object_array boundary_commits;\n@@ -278,6 +277,8 @@ struct rev_info {\n \tstruct revision_sources *sources;\n \n \tstruct topo_walk_info *topo_walk_info;\n+\n+\tstruct repository *repo;\n };\n \n int ref_excluded(struct string_list *, const char *path);\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375115","messageId":"20190508111249.15262-4-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 03/19] revision.c: prepare to convert handle_revision_pseudo_opt()","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:33Z","receivedAt":"2019-05-08T11:13:37Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This patch is essentially no-op. It allows to parse_options() to handle\nsome options. But the new option list remains empty. The option will be\nmoved one by one from the old manual parsing code to this list.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n revision.c | 44 ++++++++++++++++++++++++++++++++++----------\n revision.h |  2 ++\n 2 files changed, 36 insertions(+), 10 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex d4aaf0ef25..65d40c9255 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -26,6 +26,7 @@\n #include \"argv-array.h\"\n #include \"commit-reach.h\"\n #include \"commit-graph.h\"\n+#include \"parse-options.h\"\n #include \"prio-queue.h\"\n #include \"hashmap.h\"\n \n@@ -1598,6 +1599,8 @@ static int add_parents_only(struct rev_info *revs, const char *arg_, int flags,\n \treturn 1;\n }\n \n+static void make_pseudo_options(struct rev_info *revs);\n+\n void repo_init_revisions(struct repository *r,\n \t\t\t struct rev_info *revs,\n \t\t\t const char *prefix)\n@@ -1638,6 +1641,7 @@ void repo_init_revisions(struct repository *r,\n \t}\n \n \trevs->notes_opt.use_default_notes = -1;\n+\tmake_pseudo_options(revs);\n }\n \n static void add_pending_commit_list(struct rev_info *revs,\n@@ -2355,6 +2359,25 @@ static int for_each_good_bisect_ref(struct ref_store *refs, each_ref_fn fn, void\n \treturn for_each_bisect_ref(refs, fn, cb_data, term_good);\n }\n \n+static void make_pseudo_options(struct rev_info *revs)\n+{\n+\t/*\n+\t * NOTE!\n+\t *\n+\t * Commands like \"git shortlog\" will not accept the options below\n+\t * unless parse_revision_opt queues them (as opposed to erroring\n+\t * out).\n+\t *\n+\t * When implementing your new pseudo-option, remember to\n+\t * register it in the list at the top of handle_revision_opt.\n+\t */\n+\tstruct option options[] = {\n+\t\tOPT_END()\n+\t};\n+\tALLOC_ARRAY(revs->pseudo_options, ARRAY_SIZE(options));\n+\tmemcpy(revs->pseudo_options, options, sizeof(options));\n+}\n+\n static int handle_revision_pseudo_opt(const char *submodule,\n \t\t\t\tstruct rev_info *revs,\n \t\t\t\tint argc, const char **argv, int *flags)\n@@ -2377,16 +2400,16 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \t} else\n \t\trefs = get_main_ref_store(revs->repo);\n \n-\t/*\n-\t * NOTE!\n-\t *\n-\t * Commands like \"git shortlog\" will not accept the options below\n-\t * unless parse_revision_opt queues them (as opposed to erroring\n-\t * out).\n-\t *\n-\t * When implementing your new pseudo-option, remember to\n-\t * register it in the list at the top of handle_revision_opt.\n-\t */\n+\targc = parse_options(argc, argv, revs->prefix,\n+\t\t\t     revs->pseudo_options, NULL,\n+\t\t\t     PARSE_OPT_KEEP_DASHDASH |\n+\t\t\t     PARSE_OPT_KEEP_UNKNOWN |\n+\t\t\t     PARSE_OPT_NO_INTERNAL_HELP |\n+\t\t\t     PARSE_OPT_ONE_SHOT |\n+\t\t\t     PARSE_OPT_STOP_AT_NON_OPTION);\n+\tif (argc)\n+\t\treturn argc;\n+\n \tif (!strcmp(arg, \"--all\")) {\n \t\thandle_refs(refs, revs, *flags, refs_for_each_ref);\n \t\thandle_refs(refs, revs, *flags, refs_head_ref);\n@@ -2685,6 +2708,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s\n \tif (revs->expand_tabs_in_log < 0)\n \t\trevs->expand_tabs_in_log = revs->expand_tabs_in_log_default;\n \n+\tFREE_AND_NULL(revs->pseudo_options);\n \treturn left;\n }\n \ndiff --git a/revision.h b/revision.h\nindex 71e724c59c..0769c97dee 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -39,6 +39,7 @@\n #define DECORATE_FULL_REFS\t2\n \n struct log_info;\n+struct option;\n struct repository;\n struct rev_info;\n struct string_list;\n@@ -279,6 +280,7 @@ struct rev_info {\n \tstruct topo_walk_info *topo_walk_info;\n \n \tstruct repository *repo;\n+\tstruct option *pseudo_options;\n };\n \n int ref_excluded(struct string_list *, const char *path);\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375116","messageId":"20190508111249.15262-5-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 04/19] rev-parseopt: convert --all","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:34Z","receivedAt":"2019-05-08T11:13:42Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n revision.c | 41 ++++++++++++++++++++++++++++++-----------\n revision.h |  2 ++\n 2 files changed, 32 insertions(+), 11 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex 65d40c9255..9a346577f6 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -30,6 +30,10 @@\n #include \"prio-queue.h\"\n #include \"hashmap.h\"\n \n+#define OPT_REV_NOARG(s, l, h, cb) \\\n+\tOPT_CALLBACK_F(s, l, revs, NULL, h, \\\n+\t\t       PARSE_OPT_NONEG | PARSE_OPT_NOARG, cb)\n+\n volatile show_early_output_fn_t show_early_output;\n \n static const char *term_bad;\n@@ -2359,6 +2363,26 @@ static int for_each_good_bisect_ref(struct ref_store *refs, each_ref_fn fn, void\n \treturn for_each_bisect_ref(refs, fn, cb_data, term_good);\n }\n \n+static int rev_opt_all(const struct option *opt, const char *arg, int unset)\n+{\n+\tstruct rev_info\t\t*revs  = opt->value;\n+\tint\t\t\t flags = *revs->pseudo_flags;\n+\tstruct ref_store\t*refs  = revs->pseudo_refs;\n+\n+\tBUG_ON_OPT_NEG(unset);\n+\tBUG_ON_OPT_ARG(arg);\n+\thandle_refs(refs, revs, flags, refs_for_each_ref);\n+\thandle_refs(refs, revs, flags, refs_head_ref);\n+\tif (!revs->single_worktree) {\n+\t\tstruct all_refs_cb cb;\n+\n+\t\tinit_all_refs_cb(&cb, revs, flags);\n+\t\tother_head_refs(handle_one_ref, &cb);\n+\t}\n+\tclear_ref_exclusion(&revs->ref_excludes);\n+\treturn 0;\n+}\n+\n static void make_pseudo_options(struct rev_info *revs)\n {\n \t/*\n@@ -2372,6 +2396,9 @@ static void make_pseudo_options(struct rev_info *revs)\n \t * register it in the list at the top of handle_revision_opt.\n \t */\n \tstruct option options[] = {\n+\t\tOPT_REV_NOARG(0, \"all\",\n+\t\t\t      N_(\"include all refs in refs/ and HEAD\"),\n+\t\t\t      rev_opt_all),\n \t\tOPT_END()\n \t};\n \tALLOC_ARRAY(revs->pseudo_options, ARRAY_SIZE(options));\n@@ -2400,6 +2427,8 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \t} else\n \t\trefs = get_main_ref_store(revs->repo);\n \n+\trevs->pseudo_flags = flags;\n+\trevs->pseudo_refs = refs;\n \targc = parse_options(argc, argv, revs->prefix,\n \t\t\t     revs->pseudo_options, NULL,\n \t\t\t     PARSE_OPT_KEEP_DASHDASH |\n@@ -2410,17 +2439,7 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \tif (argc)\n \t\treturn argc;\n \n-\tif (!strcmp(arg, \"--all\")) {\n-\t\thandle_refs(refs, revs, *flags, refs_for_each_ref);\n-\t\thandle_refs(refs, revs, *flags, refs_head_ref);\n-\t\tif (!revs->single_worktree) {\n-\t\t\tstruct all_refs_cb cb;\n-\n-\t\t\tinit_all_refs_cb(&cb, revs, *flags);\n-\t\t\tother_head_refs(handle_one_ref, &cb);\n-\t\t}\n-\t\tclear_ref_exclusion(&revs->ref_excludes);\n-\t} else if (!strcmp(arg, \"--branches\")) {\n+\tif (!strcmp(arg, \"--branches\")) {\n \t\thandle_refs(refs, revs, *flags, refs_for_each_branch_ref);\n \t\tclear_ref_exclusion(&revs->ref_excludes);\n \t} else if (!strcmp(arg, \"--bisect\")) {\ndiff --git a/revision.h b/revision.h\nindex 0769c97dee..cec5215c04 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -281,6 +281,8 @@ struct rev_info {\n \n \tstruct repository *repo;\n \tstruct option *pseudo_options;\n+\tint *pseudo_flags;\n+\tstruct ref_store *pseudo_refs;\n };\n \n int ref_excluded(struct string_list *, const char *path);\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375117","messageId":"20190508111249.15262-6-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 05/19] rev-parseopt: convert --branches","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:35Z","receivedAt":"2019-05-08T11:13:46Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n revision.c | 38 +++++++++++++++++++++++++++++---------\n 1 file changed, 29 insertions(+), 9 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex 9a346577f6..7db1109b57 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -34,6 +34,10 @@\n \tOPT_CALLBACK_F(s, l, revs, NULL, h, \\\n \t\t       PARSE_OPT_NONEG | PARSE_OPT_NOARG, cb)\n \n+#define OPT_REV_OPTARG(s, l, a, h, cb) \\\n+\tOPT_CALLBACK_F(s, l, revs, a, h, \\\n+\t\t       PARSE_OPT_NONEG | PARSE_OPT_OPTARG, cb)\n+\n volatile show_early_output_fn_t show_early_output;\n \n static const char *term_bad;\n@@ -2383,6 +2387,27 @@ static int rev_opt_all(const struct option *opt, const char *arg, int unset)\n \treturn 0;\n }\n \n+static int rev_opt_branches(const struct option *opt,\n+\t\t\t    const char *arg, int unset)\n+{\n+\tstruct rev_info\t\t*revs  = opt->value;\n+\tint\t\t\t flags = *revs->pseudo_flags;\n+\tstruct ref_store\t*refs  = revs->pseudo_refs;\n+\n+\tBUG_ON_OPT_NEG(unset);\n+\tif (arg) {\n+\t\tstruct all_refs_cb cb;\n+\n+\t\tinit_all_refs_cb(&cb, revs, flags);\n+\t\tfor_each_glob_ref_in(handle_one_ref, arg, \"refs/heads/\", &cb);\n+\t\tclear_ref_exclusion(&revs->ref_excludes);\n+\t} else {\n+\t\thandle_refs(refs, revs, flags, refs_for_each_branch_ref);\n+\t\tclear_ref_exclusion(&revs->ref_excludes);\n+\t}\n+\treturn 0;\n+}\n+\n static void make_pseudo_options(struct rev_info *revs)\n {\n \t/*\n@@ -2399,6 +2424,9 @@ static void make_pseudo_options(struct rev_info *revs)\n \t\tOPT_REV_NOARG(0, \"all\",\n \t\t\t      N_(\"include all refs in refs/ and HEAD\"),\n \t\t\t      rev_opt_all),\n+\t\tOPT_REV_OPTARG(0, \"branches\", N_(\"<pattern>\"),\n+\t\t\t       N_(\"include all refs in refs/heads (optionally matches pattern)\"),\n+\t\t\t       rev_opt_branches),\n \t\tOPT_END()\n \t};\n \tALLOC_ARRAY(revs->pseudo_options, ARRAY_SIZE(options));\n@@ -2439,10 +2467,7 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \tif (argc)\n \t\treturn argc;\n \n-\tif (!strcmp(arg, \"--branches\")) {\n-\t\thandle_refs(refs, revs, *flags, refs_for_each_branch_ref);\n-\t\tclear_ref_exclusion(&revs->ref_excludes);\n-\t} else if (!strcmp(arg, \"--bisect\")) {\n+\tif (!strcmp(arg, \"--bisect\")) {\n \t\tread_bisect_terms(&term_bad, &term_good);\n \t\thandle_refs(refs, revs, *flags, for_each_bad_bisect_ref);\n \t\thandle_refs(refs, revs, *flags ^ (UNINTERESTING | BOTTOM),\n@@ -2463,11 +2488,6 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \t} else if ((argcount = parse_long_opt(\"exclude\", argv, &optarg))) {\n \t\tadd_ref_exclusion(&revs->ref_excludes, optarg);\n \t\treturn argcount;\n-\t} else if (skip_prefix(arg, \"--branches=\", &optarg)) {\n-\t\tstruct all_refs_cb cb;\n-\t\tinit_all_refs_cb(&cb, revs, *flags);\n-\t\tfor_each_glob_ref_in(handle_one_ref, optarg, \"refs/heads/\", &cb);\n-\t\tclear_ref_exclusion(&revs->ref_excludes);\n \t} else if (skip_prefix(arg, \"--tags=\", &optarg)) {\n \t\tstruct all_refs_cb cb;\n \t\tinit_all_refs_cb(&cb, revs, *flags);\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375118","messageId":"20190508111249.15262-7-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 06/19] rev-parseopt: convert --bisect","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:36Z","receivedAt":"2019-05-08T11:13:51Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n revision.c | 28 +++++++++++++++++++++-------\n 1 file changed, 21 insertions(+), 7 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex 7db1109b57..0d34f81716 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -2387,6 +2387,23 @@ static int rev_opt_all(const struct option *opt, const char *arg, int unset)\n \treturn 0;\n }\n \n+static int rev_opt_bisect(const struct option *opt,\n+\t\t\t  const char *arg, int unset)\n+{\n+\tstruct rev_info\t\t*revs  = opt->value;\n+\tint\t\t\t flags = *revs->pseudo_flags;\n+\tstruct ref_store\t*refs  = revs->pseudo_refs;\n+\n+\tBUG_ON_OPT_NEG(unset);\n+\tBUG_ON_OPT_ARG(arg);\n+\tread_bisect_terms(&term_bad, &term_good);\n+\thandle_refs(refs, revs, flags, for_each_bad_bisect_ref);\n+\thandle_refs(refs, revs, flags ^ (UNINTERESTING | BOTTOM),\n+\t\t    for_each_good_bisect_ref);\n+\trevs->bisect = 1;\n+\treturn 0;\n+}\n+\n static int rev_opt_branches(const struct option *opt,\n \t\t\t    const char *arg, int unset)\n {\n@@ -2427,6 +2444,9 @@ static void make_pseudo_options(struct rev_info *revs)\n \t\tOPT_REV_OPTARG(0, \"branches\", N_(\"<pattern>\"),\n \t\t\t       N_(\"include all refs in refs/heads (optionally matches pattern)\"),\n \t\t\t       rev_opt_branches),\n+\t\tOPT_REV_NOARG(0, \"bisect\",\n+\t\t\t      N_(\"synonym to refs/bisect/good-* --not refs/bisect/bad\"),\n+\t\t\t      rev_opt_bisect),\n \t\tOPT_END()\n \t};\n \tALLOC_ARRAY(revs->pseudo_options, ARRAY_SIZE(options));\n@@ -2467,13 +2487,7 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \tif (argc)\n \t\treturn argc;\n \n-\tif (!strcmp(arg, \"--bisect\")) {\n-\t\tread_bisect_terms(&term_bad, &term_good);\n-\t\thandle_refs(refs, revs, *flags, for_each_bad_bisect_ref);\n-\t\thandle_refs(refs, revs, *flags ^ (UNINTERESTING | BOTTOM),\n-\t\t\t    for_each_good_bisect_ref);\n-\t\trevs->bisect = 1;\n-\t} else if (!strcmp(arg, \"--tags\")) {\n+\tif (!strcmp(arg, \"--tags\")) {\n \t\thandle_refs(refs, revs, *flags, refs_for_each_tag_ref);\n \t\tclear_ref_exclusion(&revs->ref_excludes);\n \t} else if (!strcmp(arg, \"--remotes\")) {\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375119","messageId":"20190508111249.15262-8-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 07/19] rev-parseopt: convert --tags","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:37Z","receivedAt":"2019-05-08T11:13:55Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n revision.c | 34 +++++++++++++++++++++++++---------\n 1 file changed, 25 insertions(+), 9 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex 0d34f81716..5183cdf66d 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -2425,6 +2425,27 @@ static int rev_opt_branches(const struct option *opt,\n \treturn 0;\n }\n \n+static int rev_opt_tags(const struct option *opt,\n+\t\t\tconst char *arg, int unset)\n+{\n+\tstruct rev_info\t\t*revs  = opt->value;\n+\tint\t\t\t flags = *revs->pseudo_flags;\n+\tstruct ref_store\t*refs  = revs->pseudo_refs;\n+\n+\tBUG_ON_OPT_NEG(unset);\n+\tif (arg) {\n+\t\tstruct all_refs_cb cb;\n+\n+\t\tinit_all_refs_cb(&cb, revs, flags);\n+\t\tfor_each_glob_ref_in(handle_one_ref, arg, \"refs/tags/\", &cb);\n+\t\tclear_ref_exclusion(&revs->ref_excludes);\n+\t} else {\n+\t\thandle_refs(refs, revs, flags, refs_for_each_tag_ref);\n+\t\tclear_ref_exclusion(&revs->ref_excludes);\n+\t}\n+\treturn 0;\n+}\n+\n static void make_pseudo_options(struct rev_info *revs)\n {\n \t/*\n@@ -2447,6 +2468,9 @@ static void make_pseudo_options(struct rev_info *revs)\n \t\tOPT_REV_NOARG(0, \"bisect\",\n \t\t\t      N_(\"synonym to refs/bisect/good-* --not refs/bisect/bad\"),\n \t\t\t      rev_opt_bisect),\n+\t\tOPT_REV_OPTARG(0, \"tags\", N_(\"<pattern>\"),\n+\t\t\t       N_(\"include all refs in refs/tags (optionally matches pattern)\"),\n+\t\t\t       rev_opt_tags),\n \t\tOPT_END()\n \t};\n \tALLOC_ARRAY(revs->pseudo_options, ARRAY_SIZE(options));\n@@ -2487,10 +2511,7 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \tif (argc)\n \t\treturn argc;\n \n-\tif (!strcmp(arg, \"--tags\")) {\n-\t\thandle_refs(refs, revs, *flags, refs_for_each_tag_ref);\n-\t\tclear_ref_exclusion(&revs->ref_excludes);\n-\t} else if (!strcmp(arg, \"--remotes\")) {\n+\tif (!strcmp(arg, \"--remotes\")) {\n \t\thandle_refs(refs, revs, *flags, refs_for_each_remote_ref);\n \t\tclear_ref_exclusion(&revs->ref_excludes);\n \t} else if ((argcount = parse_long_opt(\"glob\", argv, &optarg))) {\n@@ -2502,11 +2523,6 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \t} else if ((argcount = parse_long_opt(\"exclude\", argv, &optarg))) {\n \t\tadd_ref_exclusion(&revs->ref_excludes, optarg);\n \t\treturn argcount;\n-\t} else if (skip_prefix(arg, \"--tags=\", &optarg)) {\n-\t\tstruct all_refs_cb cb;\n-\t\tinit_all_refs_cb(&cb, revs, *flags);\n-\t\tfor_each_glob_ref_in(handle_one_ref, optarg, \"refs/tags/\", &cb);\n-\t\tclear_ref_exclusion(&revs->ref_excludes);\n \t} else if (skip_prefix(arg, \"--remotes=\", &optarg)) {\n \t\tstruct all_refs_cb cb;\n \t\tinit_all_refs_cb(&cb, revs, *flags);\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375120","messageId":"20190508111249.15262-9-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 08/19] rev-parseopt: convert --remotes","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:38Z","receivedAt":"2019-05-08T11:13:59Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n revision.c | 34 +++++++++++++++++++++++++---------\n 1 file changed, 25 insertions(+), 9 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex 5183cdf66d..bcfca8856f 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -2425,6 +2425,27 @@ static int rev_opt_branches(const struct option *opt,\n \treturn 0;\n }\n \n+static int rev_opt_remotes(const struct option *opt,\n+\t\t\t   const char *arg, int unset)\n+{\n+\tstruct rev_info\t\t*revs  = opt->value;\n+\tint\t\t\t flags = *revs->pseudo_flags;\n+\tstruct ref_store\t*refs  = revs->pseudo_refs;\n+\n+\tBUG_ON_OPT_NEG(unset);\n+\tif (arg) {\n+\t\tstruct all_refs_cb cb;\n+\n+\t\tinit_all_refs_cb(&cb, revs, flags);\n+\t\tfor_each_glob_ref_in(handle_one_ref, arg, \"refs/remotes/\", &cb);\n+\t\tclear_ref_exclusion(&revs->ref_excludes);\n+\t} else {\n+\t\thandle_refs(refs, revs, flags, refs_for_each_remote_ref);\n+\t\tclear_ref_exclusion(&revs->ref_excludes);\n+\t}\n+\treturn 0;\n+}\n+\n static int rev_opt_tags(const struct option *opt,\n \t\t\tconst char *arg, int unset)\n {\n@@ -2471,6 +2492,9 @@ static void make_pseudo_options(struct rev_info *revs)\n \t\tOPT_REV_OPTARG(0, \"tags\", N_(\"<pattern>\"),\n \t\t\t       N_(\"include all refs in refs/tags (optionally matches pattern)\"),\n \t\t\t       rev_opt_tags),\n+\t\tOPT_REV_OPTARG(0, \"remotes\", N_(\"<pattern>\"),\n+\t\t\t       N_(\"include all refs in refs/remotes (optionally matches pattern)\"),\n+\t\t\t       rev_opt_remotes),\n \t\tOPT_END()\n \t};\n \tALLOC_ARRAY(revs->pseudo_options, ARRAY_SIZE(options));\n@@ -2511,10 +2535,7 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \tif (argc)\n \t\treturn argc;\n \n-\tif (!strcmp(arg, \"--remotes\")) {\n-\t\thandle_refs(refs, revs, *flags, refs_for_each_remote_ref);\n-\t\tclear_ref_exclusion(&revs->ref_excludes);\n-\t} else if ((argcount = parse_long_opt(\"glob\", argv, &optarg))) {\n+\tif ((argcount = parse_long_opt(\"glob\", argv, &optarg))) {\n \t\tstruct all_refs_cb cb;\n \t\tinit_all_refs_cb(&cb, revs, *flags);\n \t\tfor_each_glob_ref(handle_one_ref, optarg, &cb);\n@@ -2523,11 +2544,6 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \t} else if ((argcount = parse_long_opt(\"exclude\", argv, &optarg))) {\n \t\tadd_ref_exclusion(&revs->ref_excludes, optarg);\n \t\treturn argcount;\n-\t} else if (skip_prefix(arg, \"--remotes=\", &optarg)) {\n-\t\tstruct all_refs_cb cb;\n-\t\tinit_all_refs_cb(&cb, revs, *flags);\n-\t\tfor_each_glob_ref_in(handle_one_ref, optarg, \"refs/remotes/\", &cb);\n-\t\tclear_ref_exclusion(&revs->ref_excludes);\n \t} else if (!strcmp(arg, \"--reflog\")) {\n \t\tadd_reflogs_to_pending(revs, *flags);\n \t} else if (!strcmp(arg, \"--indexed-objects\")) {\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375121","messageId":"20190508111249.15262-10-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 09/19] rev-parseopt: convert --glob","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:39Z","receivedAt":"2019-05-08T11:14:04Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n revision.c | 28 +++++++++++++++++++++-------\n 1 file changed, 21 insertions(+), 7 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex bcfca8856f..013b8ec19f 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -30,6 +30,9 @@\n #include \"prio-queue.h\"\n #include \"hashmap.h\"\n \n+#define OPT_REV(s, l, a, h, cb)\t\t \\\n+\tOPT_CALLBACK_F(s, l, revs, a, h, PARSE_OPT_NONEG, cb)\n+\n #define OPT_REV_NOARG(s, l, h, cb) \\\n \tOPT_CALLBACK_F(s, l, revs, NULL, h, \\\n \t\t       PARSE_OPT_NONEG | PARSE_OPT_NOARG, cb)\n@@ -2425,6 +2428,20 @@ static int rev_opt_branches(const struct option *opt,\n \treturn 0;\n }\n \n+static int rev_opt_glob(const struct option *opt,\n+\t\t\tconst char *arg, int unset)\n+{\n+\tstruct rev_info\t*revs  = opt->value;\n+\tint flags = *revs->pseudo_flags;\n+\tstruct all_refs_cb cb;\n+\n+\tBUG_ON_OPT_NEG(unset);\n+\tinit_all_refs_cb(&cb, revs, flags);\n+\tfor_each_glob_ref(handle_one_ref, arg, &cb);\n+\tclear_ref_exclusion(&revs->ref_excludes);\n+\treturn 0;\n+}\n+\n static int rev_opt_remotes(const struct option *opt,\n \t\t\t   const char *arg, int unset)\n {\n@@ -2495,6 +2512,9 @@ static void make_pseudo_options(struct rev_info *revs)\n \t\tOPT_REV_OPTARG(0, \"remotes\", N_(\"<pattern>\"),\n \t\t\t       N_(\"include all refs in refs/remotes (optionally matches pattern)\"),\n \t\t\t       rev_opt_remotes),\n+\t\tOPT_REV(0, \"glob\", N_(\"<pattern>\"),\n+\t\t\tN_(\"include all refs matching shell glob\"),\n+\t\t\trev_opt_glob),\n \t\tOPT_END()\n \t};\n \tALLOC_ARRAY(revs->pseudo_options, ARRAY_SIZE(options));\n@@ -2535,13 +2555,7 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \tif (argc)\n \t\treturn argc;\n \n-\tif ((argcount = parse_long_opt(\"glob\", argv, &optarg))) {\n-\t\tstruct all_refs_cb cb;\n-\t\tinit_all_refs_cb(&cb, revs, *flags);\n-\t\tfor_each_glob_ref(handle_one_ref, optarg, &cb);\n-\t\tclear_ref_exclusion(&revs->ref_excludes);\n-\t\treturn argcount;\n-\t} else if ((argcount = parse_long_opt(\"exclude\", argv, &optarg))) {\n+\tif ((argcount = parse_long_opt(\"exclude\", argv, &optarg))) {\n \t\tadd_ref_exclusion(&revs->ref_excludes, optarg);\n \t\treturn argcount;\n \t} else if (!strcmp(arg, \"--reflog\")) {\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375122","messageId":"20190508111249.15262-11-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 10/19] rev-parseopt: convert --exclude","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:40Z","receivedAt":"2019-05-08T11:14:09Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n revision.c | 19 ++++++++++++++-----\n 1 file changed, 14 insertions(+), 5 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex 013b8ec19f..d34e17984d 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -2428,6 +2428,16 @@ static int rev_opt_branches(const struct option *opt,\n \treturn 0;\n }\n \n+static int rev_opt_exclude(const struct option *opt,\n+\t\t\t   const char *arg, int unset)\n+{\n+\tstruct rev_info\t*revs  = opt->value;\n+\n+\tBUG_ON_OPT_NEG(unset);\n+\tadd_ref_exclusion(&revs->ref_excludes, arg);\n+\treturn 0;\n+}\n+\n static int rev_opt_glob(const struct option *opt,\n \t\t\tconst char *arg, int unset)\n {\n@@ -2515,6 +2525,9 @@ static void make_pseudo_options(struct rev_info *revs)\n \t\tOPT_REV(0, \"glob\", N_(\"<pattern>\"),\n \t\t\tN_(\"include all refs matching shell glob\"),\n \t\t\trev_opt_glob),\n+\t\tOPT_REV(0, \"exclude\", N_(\"<pattern>\"),\n+\t\t\tN_(\"exclude refs matching glob pattern\"),\n+\t\t\trev_opt_exclude),\n \t\tOPT_END()\n \t};\n \tALLOC_ARRAY(revs->pseudo_options, ARRAY_SIZE(options));\n@@ -2528,7 +2541,6 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \tconst char *arg = argv[0];\n \tconst char *optarg;\n \tstruct ref_store *refs;\n-\tint argcount;\n \n \tif (submodule) {\n \t\t/*\n@@ -2555,10 +2567,7 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \tif (argc)\n \t\treturn argc;\n \n-\tif ((argcount = parse_long_opt(\"exclude\", argv, &optarg))) {\n-\t\tadd_ref_exclusion(&revs->ref_excludes, optarg);\n-\t\treturn argcount;\n-\t} else if (!strcmp(arg, \"--reflog\")) {\n+\tif (!strcmp(arg, \"--reflog\")) {\n \t\tadd_reflogs_to_pending(revs, *flags);\n \t} else if (!strcmp(arg, \"--indexed-objects\")) {\n \t\tadd_index_objects_to_pending(revs, *flags);\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375123","messageId":"20190508111249.15262-12-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 11/19] rev-parseopt: convert --reflog","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:41Z","receivedAt":"2019-05-08T11:14:13Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n revision.c | 19 ++++++++++++++++---\n 1 file changed, 16 insertions(+), 3 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex d34e17984d..6efa9bee1e 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -2452,6 +2452,18 @@ static int rev_opt_glob(const struct option *opt,\n \treturn 0;\n }\n \n+static int rev_opt_reflog(const struct option *opt,\n+\t\t\t  const char *arg, int unset)\n+{\n+\tstruct rev_info *revs  = opt->value;\n+\tint flags = *revs->pseudo_flags;\n+\n+\tBUG_ON_OPT_NEG(unset);\n+\tBUG_ON_OPT_ARG(arg);\n+\tadd_reflogs_to_pending(revs, flags);\n+\treturn 0;\n+}\n+\n static int rev_opt_remotes(const struct option *opt,\n \t\t\t   const char *arg, int unset)\n {\n@@ -2528,6 +2540,9 @@ static void make_pseudo_options(struct rev_info *revs)\n \t\tOPT_REV(0, \"exclude\", N_(\"<pattern>\"),\n \t\t\tN_(\"exclude refs matching glob pattern\"),\n \t\t\trev_opt_exclude),\n+\t\tOPT_REV_NOARG(0, \"reflog\",\n+\t\t\t      N_(\"include all refs from reflog\"),\n+\t\t\t      rev_opt_reflog),\n \t\tOPT_END()\n \t};\n \tALLOC_ARRAY(revs->pseudo_options, ARRAY_SIZE(options));\n@@ -2567,9 +2582,7 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \tif (argc)\n \t\treturn argc;\n \n-\tif (!strcmp(arg, \"--reflog\")) {\n-\t\tadd_reflogs_to_pending(revs, *flags);\n-\t} else if (!strcmp(arg, \"--indexed-objects\")) {\n+\tif (!strcmp(arg, \"--indexed-objects\")) {\n \t\tadd_index_objects_to_pending(revs, *flags);\n \t} else if (!strcmp(arg, \"--not\")) {\n \t\t*flags ^= UNINTERESTING | BOTTOM;\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375124","messageId":"20190508111249.15262-13-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 12/19] rev-parseopt: convert --indexed-objects","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:42Z","receivedAt":"2019-05-08T11:14:17Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n revision.c | 19 ++++++++++++++++---\n 1 file changed, 16 insertions(+), 3 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex 6efa9bee1e..9cfa4dc151 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -2438,6 +2438,18 @@ static int rev_opt_exclude(const struct option *opt,\n \treturn 0;\n }\n \n+static int rev_opt_indexed_objects(const struct option *opt,\n+\t\t\t\t   const char *arg, int unset)\n+{\n+\tstruct rev_info *revs  = opt->value;\n+\tint flags = *revs->pseudo_flags;\n+\n+\tBUG_ON_OPT_NEG(unset);\n+\tBUG_ON_OPT_ARG(arg);\n+\tadd_index_objects_to_pending(revs, flags);\n+\treturn 0;\n+}\n+\n static int rev_opt_glob(const struct option *opt,\n \t\t\tconst char *arg, int unset)\n {\n@@ -2543,6 +2555,9 @@ static void make_pseudo_options(struct rev_info *revs)\n \t\tOPT_REV_NOARG(0, \"reflog\",\n \t\t\t      N_(\"include all refs from reflog\"),\n \t\t\t      rev_opt_reflog),\n+\t\tOPT_REV_NOARG(0, \"indexed-objects\",\n+\t\t\t      N_(\"include all trees and blobs used by the index\"),\n+\t\t\t      rev_opt_indexed_objects),\n \t\tOPT_END()\n \t};\n \tALLOC_ARRAY(revs->pseudo_options, ARRAY_SIZE(options));\n@@ -2582,9 +2597,7 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \tif (argc)\n \t\treturn argc;\n \n-\tif (!strcmp(arg, \"--indexed-objects\")) {\n-\t\tadd_index_objects_to_pending(revs, *flags);\n-\t} else if (!strcmp(arg, \"--not\")) {\n+\tif (!strcmp(arg, \"--not\")) {\n \t\t*flags ^= UNINTERESTING | BOTTOM;\n \t} else if (!strcmp(arg, \"--no-walk\")) {\n \t\trevs->no_walk = REVISION_WALK_NO_WALK_SORTED;\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375125","messageId":"20190508111249.15262-14-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 13/19] rev-parseopt: convert --not","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:43Z","receivedAt":"2019-05-08T11:14:22Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n revision.c | 18 +++++++++++++++---\n 1 file changed, 15 insertions(+), 3 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex 9cfa4dc151..b02cb4660b 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -2464,6 +2464,17 @@ static int rev_opt_glob(const struct option *opt,\n \treturn 0;\n }\n \n+static int rev_opt_not(const struct option *opt,\n+\t\t       const char *arg, int unset)\n+{\n+\tstruct rev_info *revs  = opt->value;\n+\n+\tBUG_ON_OPT_NEG(unset);\n+\tBUG_ON_OPT_ARG(arg);\n+\t*revs->pseudo_flags ^= UNINTERESTING | BOTTOM;\n+\treturn 0;\n+}\n+\n static int rev_opt_reflog(const struct option *opt,\n \t\t\t  const char *arg, int unset)\n {\n@@ -2558,6 +2569,9 @@ static void make_pseudo_options(struct rev_info *revs)\n \t\tOPT_REV_NOARG(0, \"indexed-objects\",\n \t\t\t      N_(\"include all trees and blobs used by the index\"),\n \t\t\t      rev_opt_indexed_objects),\n+\t\tOPT_REV_NOARG(0, \"not\",\n+\t\t\t      N_(\"reverse the meaning of '^' for all following revisions\"),\n+\t\t\t      rev_opt_not),\n \t\tOPT_END()\n \t};\n \tALLOC_ARRAY(revs->pseudo_options, ARRAY_SIZE(options));\n@@ -2597,9 +2611,7 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \tif (argc)\n \t\treturn argc;\n \n-\tif (!strcmp(arg, \"--not\")) {\n-\t\t*flags ^= UNINTERESTING | BOTTOM;\n-\t} else if (!strcmp(arg, \"--no-walk\")) {\n+\tif (!strcmp(arg, \"--no-walk\")) {\n \t\trevs->no_walk = REVISION_WALK_NO_WALK_SORTED;\n \t} else if (skip_prefix(arg, \"--no-walk=\", &optarg)) {\n \t\t/*\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375126","messageId":"20190508111249.15262-15-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 14/19] rev-parseopt: convert --no-walk and --do-walk","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:44Z","receivedAt":"2019-05-08T11:14:27Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n revision.c | 47 ++++++++++++++++++++++++++++++-----------------\n 1 file changed, 30 insertions(+), 17 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex b02cb4660b..f04eb7f140 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -2464,6 +2464,29 @@ static int rev_opt_glob(const struct option *opt,\n \treturn 0;\n }\n \n+static int rev_opt_no_walk(const struct option *opt,\n+\t\t\t   const char *arg, int unset)\n+{\n+\tstruct rev_info *revs  = opt->value;\n+\n+\tBUG_ON_OPT_NEG(unset);\n+\tif (!arg) {\n+\t\trevs->no_walk = REVISION_WALK_NO_WALK_SORTED;\n+\t} else {\n+\t\t/*\n+\t\t * Detached form (\"--no-walk X\" as opposed to \"--no-walk=X\")\n+\t\t * not allowed, since the argument is optional.\n+\t\t */\n+\t\tif (!strcmp(arg, \"sorted\"))\n+\t\t\trevs->no_walk = REVISION_WALK_NO_WALK_SORTED;\n+\t\telse if (!strcmp(arg, \"unsorted\"))\n+\t\t\trevs->no_walk = REVISION_WALK_NO_WALK_UNSORTED;\n+\t\telse\n+\t\t\treturn error(_(\"invalid argument to --no-walk\"));\n+\t}\n+\treturn 0;\n+}\n+\n static int rev_opt_not(const struct option *opt,\n \t\t       const char *arg, int unset)\n {\n@@ -2572,6 +2595,12 @@ static void make_pseudo_options(struct rev_info *revs)\n \t\tOPT_REV_NOARG(0, \"not\",\n \t\t\t      N_(\"reverse the meaning of '^' for all following revisions\"),\n \t\t\t      rev_opt_not),\n+\t\tOPT_REV_OPTARG(0, \"no-walk\", N_(\"(sorted|unsorted)\"),\n+\t\t\t       N_(\"only show given commits but do not traverse their ancestors\"),\n+\t\t\t       rev_opt_no_walk),\n+\t\tOPT_SET_INT_F(0, \"do-walk\", &revs->no_walk,\n+\t\t\t      N_(\"override a previous --no-walk\"),\n+\t\t\t      0, PARSE_OPT_NONEG),\n \t\tOPT_END()\n \t};\n \tALLOC_ARRAY(revs->pseudo_options, ARRAY_SIZE(options));\n@@ -2583,7 +2612,6 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \t\t\t\tint argc, const char **argv, int *flags)\n {\n \tconst char *arg = argv[0];\n-\tconst char *optarg;\n \tstruct ref_store *refs;\n \n \tif (submodule) {\n@@ -2611,22 +2639,7 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \tif (argc)\n \t\treturn argc;\n \n-\tif (!strcmp(arg, \"--no-walk\")) {\n-\t\trevs->no_walk = REVISION_WALK_NO_WALK_SORTED;\n-\t} else if (skip_prefix(arg, \"--no-walk=\", &optarg)) {\n-\t\t/*\n-\t\t * Detached form (\"--no-walk X\" as opposed to \"--no-walk=X\")\n-\t\t * not allowed, since the argument is optional.\n-\t\t */\n-\t\tif (!strcmp(optarg, \"sorted\"))\n-\t\t\trevs->no_walk = REVISION_WALK_NO_WALK_SORTED;\n-\t\telse if (!strcmp(optarg, \"unsorted\"))\n-\t\t\trevs->no_walk = REVISION_WALK_NO_WALK_UNSORTED;\n-\t\telse\n-\t\t\treturn error(\"invalid argument to --no-walk\");\n-\t} else if (!strcmp(arg, \"--do-walk\")) {\n-\t\trevs->no_walk = 0;\n-\t} else if (!strcmp(arg, \"--single-worktree\")) {\n+\tif (!strcmp(arg, \"--single-worktree\")) {\n \t\trevs->single_worktree = 1;\n \t} else {\n \t\treturn 0;\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375127","messageId":"20190508111249.15262-16-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 15/19] rev-parseopt: convert --single-worktree","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:45Z","receivedAt":"2019-05-08T11:14:32Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n revision.c | 15 ++++-----------\n 1 file changed, 4 insertions(+), 11 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex f04eb7f140..dd22ac5c39 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -2601,6 +2601,9 @@ static void make_pseudo_options(struct rev_info *revs)\n \t\tOPT_SET_INT_F(0, \"do-walk\", &revs->no_walk,\n \t\t\t      N_(\"override a previous --no-walk\"),\n \t\t\t      0, PARSE_OPT_NONEG),\n+\t\tOPT_BOOL_F(0, \"single-worktree\", &revs->single_worktree,\n+\t\t\t   N_(\"only consider refs from the current worktree\"),\n+\t\t\t   PARSE_OPT_NONEG),\n \t\tOPT_END()\n \t};\n \tALLOC_ARRAY(revs->pseudo_options, ARRAY_SIZE(options));\n@@ -2611,7 +2614,6 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \t\t\t\tstruct rev_info *revs,\n \t\t\t\tint argc, const char **argv, int *flags)\n {\n-\tconst char *arg = argv[0];\n \tstruct ref_store *refs;\n \n \tif (submodule) {\n@@ -2636,16 +2638,7 @@ static int handle_revision_pseudo_opt(const char *submodule,\n \t\t\t     PARSE_OPT_NO_INTERNAL_HELP |\n \t\t\t     PARSE_OPT_ONE_SHOT |\n \t\t\t     PARSE_OPT_STOP_AT_NON_OPTION);\n-\tif (argc)\n-\t\treturn argc;\n-\n-\tif (!strcmp(arg, \"--single-worktree\")) {\n-\t\trevs->single_worktree = 1;\n-\t} else {\n-\t\treturn 0;\n-\t}\n-\n-\treturn 1;\n+\treturn argc;\n }\n \n static void NORETURN diagnose_missing_default(const char *def)\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375128","messageId":"20190508111249.15262-17-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 16/19] rev-parseopt: prepare to convert handle_revision_opt()","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:46Z","receivedAt":"2019-05-08T11:14:36Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Besides preparing an empty option table to be added in. The table is\nalso concatenated with diff option table so we don't need\ndiff_opt_parse() anymore. Merging with pseudo-opt table though will\nnot happen until we kill parse_revision_opt().\n\n--abbrev has to be converted right away to override the same one from\nthe diff option parser (which runs first now, if not overriden)\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/technical/api-diff.txt |  6 +--\n diff.c                               | 16 -------\n diff.h                               |  1 -\n revision.c                           | 64 +++++++++++++++++++++-------\n revision.h                           |  1 +\n 5 files changed, 53 insertions(+), 35 deletions(-)\n\ndiff --git a/Documentation/technical/api-diff.txt b/Documentation/technical/api-diff.txt\nindex 30fc0e9c93..1e4e6968f4 100644\n--- a/Documentation/technical/api-diff.txt\n+++ b/Documentation/technical/api-diff.txt\n@@ -22,9 +22,9 @@ Calling sequence\n   sets up the vanilla default.\n \n * Fill in the options structure to specify desired output format, rename\n-  detection, etc.  `diff_opt_parse()` can be used to parse options given\n-  from the command line in a way consistent with existing git-diff\n-  family of programs.\n+  detection, etc. `parseopts[]` can be used with parse_options() to\n+  parse options from the command line in a way consistent with\n+  existing git-diff family of programs.\n \n * Call `diff_setup_done()`; this inspects the options set up so far for\n   internal consistency and make necessary tweaking to it (e.g. if\ndiff --git a/diff.c b/diff.c\nindex 4d3cf83a27..ef0eb2a160 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -5522,22 +5522,6 @@ static void prep_parse_options(struct diff_options *options)\n \tmemcpy(options->parseopts, parseopts, sizeof(parseopts));\n }\n \n-int diff_opt_parse(struct diff_options *options,\n-\t\t   const char **av, int ac, const char *prefix)\n-{\n-\tif (!prefix)\n-\t\tprefix = \"\";\n-\n-\tac = parse_options(ac, av, prefix, options->parseopts, NULL,\n-\t\t\t   PARSE_OPT_KEEP_DASHDASH |\n-\t\t\t   PARSE_OPT_KEEP_UNKNOWN |\n-\t\t\t   PARSE_OPT_NO_INTERNAL_HELP |\n-\t\t\t   PARSE_OPT_ONE_SHOT |\n-\t\t\t   PARSE_OPT_STOP_AT_NON_OPTION);\n-\n-\treturn ac;\n-}\n-\n int parse_rename_score(const char **cp_p)\n {\n \tunsigned long num, scale;\ndiff --git a/diff.h b/diff.h\nindex b20cbcc091..c75480a998 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -351,7 +351,6 @@ int git_diff_ui_config(const char *var, const char *value, void *cb);\n #define diff_setup(diffopts) repo_diff_setup(the_repository, diffopts)\n #endif\n void repo_diff_setup(struct repository *, struct diff_options *);\n-int diff_opt_parse(struct diff_options *, const char **, int, const char *);\n void diff_setup_done(struct diff_options *);\n int git_config_rename(const char *var, const char *value);\n \ndiff --git a/revision.c b/revision.c\nindex dd22ac5c39..f15aa3e62d 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1611,6 +1611,7 @@ static int add_parents_only(struct rev_info *revs, const char *arg_, int flags,\n }\n \n static void make_pseudo_options(struct rev_info *revs);\n+static void make_rev_options(struct rev_info *revs);\n \n void repo_init_revisions(struct repository *r,\n \t\t\t struct rev_info *revs,\n@@ -1653,6 +1654,7 @@ void repo_init_revisions(struct repository *r,\n \n \trevs->notes_opt.use_default_notes = -1;\n \tmake_pseudo_options(revs);\n+\tmake_rev_options(revs);\n }\n \n static void add_pending_commit_list(struct rev_info *revs,\n@@ -1953,6 +1955,38 @@ static void add_message_grep(struct rev_info *revs, const char *pattern)\n \tadd_grep(revs, pattern, GREP_PATTERN_BODY);\n }\n \n+static int rev_opt_abbrev(const struct option *opt,\n+\t\t\t  const char *optarg, int unset)\n+{\n+\tstruct rev_info *revs = opt->value;\n+\n+\tif (unset) {\n+\t\trevs->abbrev = 0;\n+\t} else if (!optarg) {\n+\t\trevs->abbrev = DEFAULT_ABBREV;\n+\t} else {\n+\t\tconst unsigned hexsz = the_hash_algo->hexsz;\n+\n+\t\trevs->abbrev = strtoul(optarg, NULL, 10);\n+\t\tif (revs->abbrev < MINIMUM_ABBREV)\n+\t\t\trevs->abbrev = MINIMUM_ABBREV;\n+\t\telse if (revs->abbrev > hexsz)\n+\t\t\trevs->abbrev = hexsz;\n+\t}\n+\treturn 0;\n+}\n+\n+static void make_rev_options(struct rev_info *revs)\n+{\n+\tstruct option options[] = {\n+\t\tOPT_CALLBACK_F(0, \"abbrev\", revs, N_(\"n\"),\n+\t\t\t       N_(\"show the given source prefix instead of \\\"a/\\\"\"),\n+\t\t\t       PARSE_OPT_OPTARG, rev_opt_abbrev),\n+\t\tOPT_END(),\n+\t};\n+\trevs->options = parse_options_concat(options, revs->diffopt.parseopts);\n+}\n+\n static int handle_revision_opt(struct rev_info *revs, int argc, const char **argv,\n \t\t\t       int *unkc, const char **unkv,\n \t\t\t       const struct setup_revision_opt* opt)\n@@ -1960,7 +1994,6 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \tconst char *arg = argv[0];\n \tconst char *optarg;\n \tint argcount;\n-\tconst unsigned hexsz = the_hash_algo->hexsz;\n \n \t/* pseudo revision arguments */\n \tif (!strcmp(arg, \"--all\") || !strcmp(arg, \"--branches\") ||\n@@ -1977,6 +2010,18 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\treturn 1;\n \t}\n \n+\trevs->pseudo_flags = NULL;\n+\trevs->pseudo_refs = NULL;\n+\targc = parse_options(argc, argv, revs->prefix,\n+\t\t\t     revs->options, NULL,\n+\t\t\t     PARSE_OPT_KEEP_DASHDASH |\n+\t\t\t     PARSE_OPT_KEEP_UNKNOWN |\n+\t\t\t     PARSE_OPT_NO_INTERNAL_HELP |\n+\t\t\t     PARSE_OPT_ONE_SHOT |\n+\t\t\t     PARSE_OPT_STOP_AT_NON_OPTION);\n+\tif (argc)\n+\t\treturn argc;\n+\n \tif ((argcount = parse_long_opt(\"max-count\", argv, &optarg))) {\n \t\trevs->max_count = atoi(optarg);\n \t\trevs->no_walk = 0;\n@@ -2243,16 +2288,6 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\trevs->no_commit_id = 1;\n \t} else if (!strcmp(arg, \"--always\")) {\n \t\trevs->always_show_header = 1;\n-\t} else if (!strcmp(arg, \"--no-abbrev\")) {\n-\t\trevs->abbrev = 0;\n-\t} else if (!strcmp(arg, \"--abbrev\")) {\n-\t\trevs->abbrev = DEFAULT_ABBREV;\n-\t} else if (skip_prefix(arg, \"--abbrev=\", &optarg)) {\n-\t\trevs->abbrev = strtoul(optarg, NULL, 10);\n-\t\tif (revs->abbrev < MINIMUM_ABBREV)\n-\t\t\trevs->abbrev = MINIMUM_ABBREV;\n-\t\telse if (revs->abbrev > hexsz)\n-\t\t\trevs->abbrev = hexsz;\n \t} else if (!strcmp(arg, \"--abbrev-commit\")) {\n \t\trevs->abbrev_commit = 1;\n \t\trevs->abbrev_commit_given = 1;\n@@ -2324,10 +2359,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\t\tBUG(\"exclude_promisor_objects can only be used when fetch_if_missing is 0\");\n \t\trevs->exclude_promisor_objects = 1;\n \t} else {\n-\t\tint opts = diff_opt_parse(&revs->diffopt, argv, argc, revs->prefix);\n-\t\tif (!opts)\n-\t\t\tunkv[(*unkc)++] = arg;\n-\t\treturn opts;\n+\t\tunkv[(*unkc)++] = arg;\n+\t\treturn 0;\n \t}\n \tif (revs->graph && revs->track_linear)\n \t\tdie(\"--show-linear-break and --graph are incompatible\");\n@@ -2861,6 +2894,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s\n \t\trevs->expand_tabs_in_log = revs->expand_tabs_in_log_default;\n \n \tFREE_AND_NULL(revs->pseudo_options);\n+\tFREE_AND_NULL(revs->options);\n \treturn left;\n }\n \ndiff --git a/revision.h b/revision.h\nindex cec5215c04..4e840c8eb1 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -283,6 +283,7 @@ struct rev_info {\n \tstruct option *pseudo_options;\n \tint *pseudo_flags;\n \tstruct ref_store *pseudo_refs;\n+\tstruct option *options;\n };\n \n int ref_excluded(struct string_list *, const char *path);\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375129","messageId":"20190508111249.15262-18-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 17/19] rev-parseopt: convert --max-count","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:47Z","receivedAt":"2019-05-08T11:14:39Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n revision.c | 29 +++++++++++++++--------------\n 1 file changed, 15 insertions(+), 14 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex f15aa3e62d..c53347d362 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1976,12 +1976,26 @@ static int rev_opt_abbrev(const struct option *opt,\n \treturn 0;\n }\n \n+static int rev_opt_max_count(const struct option *opt,\n+\t\t\t     const char *arg, int unset)\n+{\n+\tstruct rev_info *revs  = opt->value;\n+\n+\tBUG_ON_OPT_NEG(unset);\n+\trevs->max_count = atoi(arg);\n+\trevs->no_walk = 0;\n+\treturn 0;\n+}\n+\n static void make_rev_options(struct rev_info *revs)\n {\n \tstruct option options[] = {\n \t\tOPT_CALLBACK_F(0, \"abbrev\", revs, N_(\"n\"),\n \t\t\t       N_(\"show the given source prefix instead of \\\"a/\\\"\"),\n \t\t\t       PARSE_OPT_OPTARG, rev_opt_abbrev),\n+\t\tOPT_REV('n', \"max-count\", N_(\"<n>\"),\n+\t\t\tN_(\"limit the number of commis to stdout\"),\n+\t\t\trev_opt_max_count),\n \t\tOPT_END(),\n \t};\n \trevs->options = parse_options_concat(options, revs->diffopt.parseopts);\n@@ -2022,11 +2036,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \tif (argc)\n \t\treturn argc;\n \n-\tif ((argcount = parse_long_opt(\"max-count\", argv, &optarg))) {\n-\t\trevs->max_count = atoi(optarg);\n-\t\trevs->no_walk = 0;\n-\t\treturn argcount;\n-\t} else if ((argcount = parse_long_opt(\"skip\", argv, &optarg))) {\n+\tif ((argcount = parse_long_opt(\"skip\", argv, &optarg))) {\n \t\trevs->skip_count = atoi(optarg);\n \t\treturn argcount;\n \t} else if ((*arg == '-') && isdigit(arg[1])) {\n@@ -2035,15 +2045,6 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\t    revs->max_count < 0)\n \t\t\tdie(\"'%s': not a non-negative integer\", arg + 1);\n \t\trevs->no_walk = 0;\n-\t} else if (!strcmp(arg, \"-n\")) {\n-\t\tif (argc <= 1)\n-\t\t\treturn error(\"-n requires an argument\");\n-\t\trevs->max_count = atoi(argv[1]);\n-\t\trevs->no_walk = 0;\n-\t\treturn 2;\n-\t} else if (skip_prefix(arg, \"-n\", &optarg)) {\n-\t\trevs->max_count = atoi(optarg);\n-\t\trevs->no_walk = 0;\n \t} else if ((argcount = parse_long_opt(\"max-age\", argv, &optarg))) {\n \t\trevs->max_age = atoi(optarg);\n \t\treturn argcount;\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375130","messageId":"20190508111249.15262-19-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 18/19] rev-parseopt: convert --skip","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:48Z","receivedAt":"2019-05-08T11:14:43Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n revision.c | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex c53347d362..42d466cd08 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1996,6 +1996,9 @@ static void make_rev_options(struct rev_info *revs)\n \t\tOPT_REV('n', \"max-count\", N_(\"<n>\"),\n \t\t\tN_(\"limit the number of commis to stdout\"),\n \t\t\trev_opt_max_count),\n+\t\tOPT_INTEGER_F(0, \"skip\", &revs->skip_count,\n+\t\t\t      N_(\"skip a number of commits before starting to show\"),\n+\t\t\t      PARSE_OPT_NONEG),\n \t\tOPT_END(),\n \t};\n \trevs->options = parse_options_concat(options, revs->diffopt.parseopts);\n@@ -2036,10 +2039,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \tif (argc)\n \t\treturn argc;\n \n-\tif ((argcount = parse_long_opt(\"skip\", argv, &optarg))) {\n-\t\trevs->skip_count = atoi(optarg);\n-\t\treturn argcount;\n-\t} else if ((*arg == '-') && isdigit(arg[1])) {\n+\tif ((*arg == '-') && isdigit(arg[1])) {\n \t\t/* accept -<digit>, like traditional \"head\" */\n \t\tif (strtol_i(arg + 1, 10, &revs->max_count) < 0 ||\n \t\t    revs->max_count < 0)\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375131","messageId":"20190508111249.15262-20-pclouds@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-1-pclouds@gmail.com","subject":"[PATCH 19/19] rev-parseopt: convert --min-age and --max-age","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T11:12:49Z","receivedAt":"2019-05-08T11:14:48Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n parse-options-cb.c |  8 ++++++++\n parse-options.h    |  4 ++++\n revision.c         | 10 ++++------\n 3 files changed, 16 insertions(+), 6 deletions(-)\n\ndiff --git a/parse-options-cb.c b/parse-options-cb.c\nindex 6e2e8d6273..7cdbbf5f6d 100644\n--- a/parse-options-cb.c\n+++ b/parse-options-cb.c\n@@ -39,6 +39,14 @@ int parse_opt_expiry_date_cb(const struct option *opt, const char *arg,\n \treturn 0;\n }\n \n+int parse_opt_timestamp_cb(const struct option *opt,\n+\t\t\t   const char *arg, int unset)\n+{\n+\tBUG_ON_OPT_NEG(unset);\n+\t*(timestamp_t *)opt->value = atoi(arg);\n+\treturn 0;\n+}\n+\n int parse_opt_color_flag_cb(const struct option *opt, const char *arg,\n \t\t\t    int unset)\n {\ndiff --git a/parse-options.h b/parse-options.h\nindex cc9230adac..7637864c41 100644\n--- a/parse-options.h\n+++ b/parse-options.h\n@@ -168,6 +168,9 @@ struct option {\n #define OPT_EXPIRY_DATE(s, l, v, h) \\\n \t{ OPTION_CALLBACK, (s), (l), (v), N_(\"expiry-date\"),(h), 0,\t\\\n \t  parse_opt_expiry_date_cb }\n+#define OPT_TIMESTAMP(s, l, v, h) \\\n+\t{ OPTION_CALLBACK, (s), (l), (v), N_(\"timestamp\"),(h), \\\n+\t  PARSE_OPT_NONEG, parse_opt_timestamp_cb }\n #define OPT_CALLBACK(s, l, v, a, h, f) OPT_CALLBACK_F(s, l, v, a, h, 0, f)\n #define OPT_NUMBER_CALLBACK(v, h, f) \\\n \t{ OPTION_NUMBER, 0, NULL, (v), NULL, (h), \\\n@@ -275,6 +278,7 @@ struct option *parse_options_concat(struct option *a, struct option *b);\n /*----- some often used options -----*/\n int parse_opt_abbrev_cb(const struct option *, const char *, int);\n int parse_opt_expiry_date_cb(const struct option *, const char *, int);\n+int parse_opt_timestamp_cb(const struct option *, const char *, int);\n int parse_opt_color_flag_cb(const struct option *, const char *, int);\n int parse_opt_verbosity_cb(const struct option *, const char *, int);\n int parse_opt_object_name(const struct option *, const char *, int);\ndiff --git a/revision.c b/revision.c\nindex 42d466cd08..0c28b67978 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1999,6 +1999,10 @@ static void make_rev_options(struct rev_info *revs)\n \t\tOPT_INTEGER_F(0, \"skip\", &revs->skip_count,\n \t\t\t      N_(\"skip a number of commits before starting to show\"),\n \t\t\t      PARSE_OPT_NONEG),\n+\t\tOPT_TIMESTAMP(0, \"min-age\", &revs->min_age,\n+\t\t\t      N_(\"limit the commits output to a specified time range\")),\n+\t\tOPT_TIMESTAMP(0, \"max-age\", &revs->max_age,\n+\t\t\t      N_(\"limit the commits output to a specified time range\")),\n \t\tOPT_END(),\n \t};\n \trevs->options = parse_options_concat(options, revs->diffopt.parseopts);\n@@ -2045,18 +2049,12 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\t    revs->max_count < 0)\n \t\t\tdie(\"'%s': not a non-negative integer\", arg + 1);\n \t\trevs->no_walk = 0;\n-\t} else if ((argcount = parse_long_opt(\"max-age\", argv, &optarg))) {\n-\t\trevs->max_age = atoi(optarg);\n-\t\treturn argcount;\n \t} else if ((argcount = parse_long_opt(\"since\", argv, &optarg))) {\n \t\trevs->max_age = approxidate(optarg);\n \t\treturn argcount;\n \t} else if ((argcount = parse_long_opt(\"after\", argv, &optarg))) {\n \t\trevs->max_age = approxidate(optarg);\n \t\treturn argcount;\n-\t} else if ((argcount = parse_long_opt(\"min-age\", argv, &optarg))) {\n-\t\trevs->min_age = atoi(optarg);\n-\t\treturn argcount;\n \t} else if ((argcount = parse_long_opt(\"before\", argv, &optarg))) {\n \t\trevs->min_age = approxidate(optarg);\n \t\treturn argcount;\n-- \n2.21.0.1141.gd54ac2cb17\n\n"},{"id":"375140","messageId":"0509589b-7a92-6c05-e404-65a9b2bf5666@gmail.com","threadId":"51051","inReplyTo":"20190508111249.15262-2-pclouds@gmail.com","subject":"Re: [PATCH 01/19] revision.h: avoid bit fields in struct rev_info","fromName":"Derrick Stolee","fromEmail":"stolee@gmail.com","sentAt":"2019-05-08T14:07:01Z","receivedAt":"2019-05-08T14:07:04Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 5/8/2019 7:12 AM, Nguyễn Thái Ngọc Duy wrote:\n> Bitfield addresses cannot be passed around in a pointer. This makes it\n> hard to use parse-options to set/unset them. Turn this struct to\n> normal integers. This of course increases the size of this struct\n> multiple times, but since we only have a handful of rev_info variables\n> around, memory consumption is not at all a concern.\n\nI think you are right that this memory trade-off shouldn't be a problem.\n\nWhat worries me instead is that we are using an \"internal\" data structure\nfor option parsing. Would it make more sense to create a struct for use\nin the parse_opts method and a method that translates those options into\nthe bitfield in struct rev_info?\n\nThanks,\n-Stolee\n"},{"id":"375143","messageId":"CACsJy8DEjBS-aiWqDe2AU56rJBVZ4Po6c-C7GxR4QDNiGSiZoQ@mail.gmail.com","threadId":"51051","inReplyTo":"0509589b-7a92-6c05-e404-65a9b2bf5666@gmail.com","subject":"Re: [PATCH 01/19] revision.h: avoid bit fields in struct rev_info","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-08T14:41:17Z","receivedAt":"2019-05-08T14:41:48Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, May 8, 2019 at 9:07 PM Derrick Stolee <stolee@gmail.com> wrote:\n>\n> On 5/8/2019 7:12 AM, Nguyễn Thái Ngọc Duy wrote:\n> > Bitfield addresses cannot be passed around in a pointer. This makes it\n> > hard to use parse-options to set/unset them. Turn this struct to\n> > normal integers. This of course increases the size of this struct\n> > multiple times, but since we only have a handful of rev_info variables\n> > around, memory consumption is not at all a concern.\n>\n> I think you are right that this memory trade-off shouldn't be a problem.\n>\n> What worries me instead is that we are using an \"internal\" data structure\n> for option parsing. Would it make more sense to create a struct for use\n> in the parse_opts method and a method that translates those options into\n> the bitfield in struct rev_info?\n\nBut we are doing that now (option parsing) using the same data\nstructure. Why would changing from a custom parser to parse_options()\naffect what fields it should or should not touch in rev_info? Genuine\nquestion. Maybe you could elaborate more about \"internal\". I probably\nmissed something. Or maybe this is a good opportunity to separate\nintermediate option parsing variables from the rest of rev_info?\n-- \nDuy\n"},{"id":"375147","messageId":"d018ea8c-6f7f-1587-d56b-af3225d6cf0b@gmail.com","threadId":"51051","inReplyTo":"CACsJy8DEjBS-aiWqDe2AU56rJBVZ4Po6c-C7GxR4QDNiGSiZoQ@mail.gmail.com","subject":"Re: [PATCH 01/19] revision.h: avoid bit fields in struct rev_info","fromName":"Derrick Stolee","fromEmail":"stolee@gmail.com","sentAt":"2019-05-08T15:52:47Z","receivedAt":"2019-05-08T15:52:51Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 5/8/2019 10:41 AM, Duy Nguyen wrote:\n> On Wed, May 8, 2019 at 9:07 PM Derrick Stolee <stolee@gmail.com> wrote:\n>>\n>> On 5/8/2019 7:12 AM, Nguyễn Thái Ngọc Duy wrote:\n>>> Bitfield addresses cannot be passed around in a pointer. This makes it\n>>> hard to use parse-options to set/unset them. Turn this struct to\n>>> normal integers. This of course increases the size of this struct\n>>> multiple times, but since we only have a handful of rev_info variables\n>>> around, memory consumption is not at all a concern.\n>>\n>> I think you are right that this memory trade-off shouldn't be a problem.\n>>\n>> What worries me instead is that we are using an \"internal\" data structure\n>> for option parsing. Would it make more sense to create a struct for use\n>> in the parse_opts method and a method that translates those options into\n>> the bitfield in struct rev_info?\n> \n> But we are doing that now (option parsing) using the same data\n> structure. Why would changing from a custom parser to parse_options()\n> affect what fields it should or should not touch in rev_info? Genuine\n> question. Maybe you could elaborate more about \"internal\". I probably\n> missed something. Or maybe this is a good opportunity to separate\n> intermediate option parsing variables from the rest of rev_info?\n\nYou're right. I was unclear.\n\nrev_info stores a lot of data. Some of the fields are important\nin-memory structures that are crucial to the workings of revision.c\nand are never used by builtin/rev-list.c. Combining this purpose\nwith the option parsing seems smelly to me.\n\nThinking more on it, I would prefer a more invasive change that may\npay off in the long term. These options, along with the \"starting list\"\nvalues, could be extracted to a 'struct rev_options' that contains these\nintegers and the commit list. Then your option parsing changes could be\nlimited to a rev_options struct, which is later inserted into a rev_info\nstruct during setup_revisions().\n\nGenerally, the rev_info struct has too many members and could be split\ninto smaller pieces according to purpose. I created the topo_walk_info\nstruct as a way to not make the situation worse, but doesn't fix existing\npain.\n\nMy ramblings are mostly complaining about old code that grew organically\nacross many many quality additions. It is definitely hard to understand\nthe revision-walking code, and perhaps it would be easier to understand\nwith a little more structure.\n\nThe biggest issue with my suggestion is that it requires changing the\nconsumers of the options, as they would no longer live directly on the\nrev_info struct. That would be a big change, even if it could be done\nwith string replacement.\n\nThanks,\n-Stolee \n"},{"id":"375210","messageId":"CACsJy8BR9XqEvQfnaBAjdgtp6J=FOhbUDpYCkMN4P4wOcw5Dmg@mail.gmail.com","threadId":"51051","inReplyTo":"d018ea8c-6f7f-1587-d56b-af3225d6cf0b@gmail.com","subject":"Re: [PATCH 01/19] revision.h: avoid bit fields in struct rev_info","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2019-05-09T09:56:27Z","receivedAt":"2019-05-09T09:56:56Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, May 8, 2019 at 10:52 PM Derrick Stolee <stolee@gmail.com> wrote:\n>\n> On 5/8/2019 10:41 AM, Duy Nguyen wrote:\n> > On Wed, May 8, 2019 at 9:07 PM Derrick Stolee <stolee@gmail.com> wrote:\n> >>\n> >> On 5/8/2019 7:12 AM, Nguyễn Thái Ngọc Duy wrote:\n> >>> Bitfield addresses cannot be passed around in a pointer. This makes it\n> >>> hard to use parse-options to set/unset them. Turn this struct to\n> >>> normal integers. This of course increases the size of this struct\n> >>> multiple times, but since we only have a handful of rev_info variables\n> >>> around, memory consumption is not at all a concern.\n> >>\n> >> I think you are right that this memory trade-off shouldn't be a problem.\n> >>\n> >> What worries me instead is that we are using an \"internal\" data structure\n> >> for option parsing. Would it make more sense to create a struct for use\n> >> in the parse_opts method and a method that translates those options into\n> >> the bitfield in struct rev_info?\n> >\n> > But we are doing that now (option parsing) using the same data\n> > structure. Why would changing from a custom parser to parse_options()\n> > affect what fields it should or should not touch in rev_info? Genuine\n> > question. Maybe you could elaborate more about \"internal\". I probably\n> > missed something. Or maybe this is a good opportunity to separate\n> > intermediate option parsing variables from the rest of rev_info?\n>\n> You're right. I was unclear.\n>\n> rev_info stores a lot of data. Some of the fields are important\n> in-memory structures that are crucial to the workings of revision.c\n> and are never used by builtin/rev-list.c. Combining this purpose\n> with the option parsing seems smelly to me.\n>\n> Thinking more on it, I would prefer a more invasive change that may\n> pay off in the long term. These options, along with the \"starting list\"\n> values, could be extracted to a 'struct rev_options' that contains these\n> integers and the commit list. Then your option parsing changes could be\n> limited to a rev_options struct, which is later inserted into a rev_info\n> struct during setup_revisions().\n>\n> Generally, the rev_info struct has too many members and could be split\n> into smaller pieces according to purpose. I created the topo_walk_info\n> struct as a way to not make the situation worse, but doesn't fix existing\n> pain.\n>\n> My ramblings are mostly complaining about old code that grew organically\n> across many many quality additions. It is definitely hard to understand\n> the revision-walking code, and perhaps it would be easier to understand\n> with a little more structure.\n\nThanks. This is much better.\n\n> The biggest issue with my suggestion is that it requires changing the\n> consumers of the options, as they would no longer live directly on the\n> rev_info struct. That would be a big change, even if it could be done\n> with string replacement.\n\nI agree rev_info has grown \"wild\". It's quite ancient code. As you\nnoted, it's a big change. And since my series is already long (76\npatches), I would rather focus on just one thing, rewriting the\nparsing code with minimum changes to anything else, preferably retain\nthe exact same old behavior.\n\nAfter that work is done (and no regression found), we could focus on\nreorganizing rev_info, which could be quite \"interesting\". Some fields\nmay be overloaded with different purposes, which I just can't spend\ntime investigating now. There's also the problem with freeing\nresources after rev-list is done, which I think we have ignored so\nfar.\n-- \nDuy\n"},{"id":"375220","messageId":"554a318d-117a-b223-ee45-7cdcac2054f9@gmail.com","threadId":"51051","inReplyTo":"CACsJy8BR9XqEvQfnaBAjdgtp6J=FOhbUDpYCkMN4P4wOcw5Dmg@mail.gmail.com","subject":"Re: [PATCH 01/19] revision.h: avoid bit fields in struct rev_info","fromName":"Derrick Stolee","fromEmail":"stolee@gmail.com","sentAt":"2019-05-09T12:11:43Z","receivedAt":"2019-05-09T12:11:46Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 5/9/2019 5:56 AM, Duy Nguyen wrote:\n> On Wed, May 8, 2019 at 10:52 PM Derrick Stolee <stolee@gmail.com> wrote:\n>>\n>> The biggest issue with my suggestion is that it requires changing the\n>> consumers of the options, as they would no longer live directly on the\n>> rev_info struct. That would be a big change, even if it could be done\n>> with string replacement.\n> \n> I agree rev_info has grown \"wild\". It's quite ancient code. As you\n> noted, it's a big change. And since my series is already long (76\n> patches), I would rather focus on just one thing, rewriting the\n> parsing code with minimum changes to anything else, preferably retain\n> the exact same old behavior.\n> \n> After that work is done (and no regression found), we could focus on\n> reorganizing rev_info, which could be quite \"interesting\". Some fields\n> may be overloaded with different purposes, which I just can't spend\n> time investigating now. There's also the problem with freeing\n> resources after rev-list is done, which I think we have ignored so\n> far.\n\nThanks for humoring me. I agree with your reasoning.\n\nThis series looks good to me.\n\nThanks,\n-Stolee\n\n"}]}