{"thread":{"id":"16999","subject":"[PATCH] parse-opt: migrate builtin-ls-files.","startedAt":"2009-01-06T00:11:09Z","lastAt":"2009-02-17T14:27:11Z","messageCount":19,"participants":["Miklos Vajna","Pierre Habouzit","Johannes Schindelin","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"99390","messageId":"1231200669-30684-1-git-send-email-vmiklos@frugalware.org","threadId":"16999","inReplyTo":null,"subject":"[PATCH] parse-opt: migrate builtin-ls-files.","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2009-01-06T00:11:09Z","receivedAt":"2009-01-06T00:11:09Z","isPatch":true,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>\n---\n\noption_parse_ignored(), option_parse_directory() and\noption_parse_no_empty() callbacks are necessary because\ndir->show_ignored, dir->show_other_directories and\ndir->hide_empty_directories are bitfields in struct dir_struct. Maybe it\nwould worth just removing them, but I did not want to touch dir.h just\nbecause of parseopt.\n\n builtin-ls-files.c |  294 ++++++++++++++++++++++++++++------------------------\n 1 files changed, 159 insertions(+), 135 deletions(-)\n\ndiff --git a/builtin-ls-files.c b/builtin-ls-files.c\nindex f72eb85..a2f3de4 100644\n--- a/builtin-ls-files.c\n+++ b/builtin-ls-files.c\n@@ -10,6 +10,7 @@\n #include \"dir.h\"\n #include \"builtin.h\"\n #include \"tree.h\"\n+#include \"parse-options.h\"\n \n static int abbrev;\n static int show_deleted;\n@@ -28,6 +29,7 @@ static const char **pathspec;\n static int error_unmatch;\n static char *ps_matched;\n static const char *with_tree;\n+static int exc_given;\n \n static const char *tag_cached = \"\";\n static const char *tag_unmerged = \"\";\n@@ -395,156 +397,178 @@ int report_path_error(const char *ps_matched, const char **pathspec, int prefix_\n \treturn errors;\n }\n \n-static const char ls_files_usage[] =\n-\t\"git ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* \"\n-\t\"[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] \"\n-\t\"[ --exclude-per-directory=<filename> ] [--exclude-standard] \"\n-\t\"[--full-name] [--abbrev] [--] [<file>]*\";\n+static const char * const ls_files_usage[] = {\n+\t\"git ls-files [options] [<file>]*\",\n+\tNULL\n+};\n+\n+static int option_parse_z(const struct option *opt,\n+\t\t\t  const char *arg, int unset)\n+{\n+\tif (unset)\n+\t\tline_terminator = '\\n';\n+\telse\n+\t\tline_terminator = 0;\n+\treturn 0;\n+}\n+\n+static int option_parse_exclude(const struct option *opt,\n+\t\t\t\tconst char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\texc_given = 1;\n+\tadd_exclude(arg, \"\", 0, &dir->exclude_list[EXC_CMDL]);\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_exclude_from(const struct option *opt,\n+\t\t\t\t     const char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\texc_given = 1;\n+\tadd_excludes_from_file(dir, arg);\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_exclude_standard(const struct option *opt,\n+\t\t\t\t\t const char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\texc_given = 1;\n+\tsetup_standard_excludes(dir);\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_ignored(const struct option *opt,\n+\t\t\t\tconst char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\tdir->show_ignored = 1;\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_directory(const struct option *opt,\n+\t\t\t\t  const char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\tdir->show_other_directories = 1;\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_no_empty(const struct option *opt,\n+\t\t\t\t const char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\tdir->hide_empty_directories = 1;\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_full_name(const struct option *opt,\n+\t\t\t\t  const char *arg, int unset)\n+{\n+\tprefix_offset = 0;\n+\n+\treturn 0;\n+}\n \n int cmd_ls_files(int argc, const char **argv, const char *prefix)\n {\n-\tint i;\n-\tint exc_given = 0, require_work_tree = 0;\n+\tint require_work_tree = 0, show_tag = 0;\n \tstruct dir_struct dir;\n+\tstruct option builtin_ls_files_options[] = {\n+\t\t{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,\n+\t\t\t\"paths are separated with NUL character\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_z },\n+\t\tOPT_BOOLEAN('t', NULL, &show_tag,\n+\t\t\t\"identify the file status with tags\"),\n+\t\tOPT_BOOLEAN('v', NULL, &show_valid_bit,\n+\t\t\t\"use lowercase letters for 'assume unchanged' files\"),\n+\t\tOPT_BOOLEAN('c', \"cached\", &show_cached,\n+\t\t\t\t\"show cached files in the output (default)\"),\n+\t\tOPT_BOOLEAN('d', \"deleted\", &show_deleted,\n+\t\t\t\t\"show deleted files in the output\"),\n+\t\tOPT_BOOLEAN('m', \"modified\", &show_modified,\n+\t\t\t\t\"show modified files in the output\"),\n+\t\tOPT_BOOLEAN('o', \"others\", &show_others,\n+\t\t\t\t\"show other files in the output\"),\n+\t\t{ OPTION_CALLBACK, 'i', \"ignored\", &dir, NULL,\n+\t\t\t\"show ignored files in the output\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_ignored },\n+\t\tOPT_BOOLEAN('s', \"stage\", &show_stage,\n+\t\t\t\"show staged contents' object name in the output\"),\n+\t\tOPT_BOOLEAN('k', \"killed\", &show_killed,\n+\t\t\t\"show files on the filesystem that need to be removed\"),\n+\t\t{ OPTION_CALLBACK, 0, \"directory\", &dir, NULL,\n+\t\t\t\"show 'other' directories' name only\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_directory },\n+\t\t{ OPTION_CALLBACK, 0, \"no-empty-directory\", &dir, NULL,\n+\t\t\t\"do not list empty directories\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_no_empty },\n+\t\tOPT_BOOLEAN('u', \"unmerged\", &show_unmerged,\n+\t\t\t\"show unmerged files in the output\"),\n+\t\t{ OPTION_CALLBACK, 'x', \"exclude\", &dir, \"pattern\",\n+\t\t\t\"skip files matching pattern\",\n+\t\t\t0, option_parse_exclude },\n+\t\t{ OPTION_CALLBACK, 'X', \"exclude-from\", &dir, \"file\",\n+\t\t\t\"exclude patterns are read from <file>\",\n+\t\t\t0, option_parse_exclude_from },\n+\t\tOPT_STRING(0, \"exclude-per-directory\", &dir.exclude_per_dir, \"file\",\n+\t\t\t\"read additional per-directory exclude patterns in <file>\"),\n+\t\t{ OPTION_CALLBACK, 0, \"exclude-standard\", &dir, NULL,\n+\t\t\t\"add the standard git exclusions\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_exclude_standard },\n+\t\t{ OPTION_CALLBACK, 0, \"full-name\", NULL, NULL,\n+\t\t\t\"make the output relative to the project top directory\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_full_name },\n+\t\tOPT_BOOLEAN(0, \"error-unmatch\", &error_unmatch,\n+\t\t\t\"if any <file> is not in the index, treat this as an error\"),\n+\t\tOPT_STRING(0, \"with-tree\", &with_tree, \"tree-ish\",\n+\t\t\t\"pretend that paths removed since <tree-ish> are still present\"),\n+\t\tOPT__ABBREV(&abbrev),\n+\t\tOPT_END()\n+\t};\n \n \tmemset(&dir, 0, sizeof(dir));\n \tif (prefix)\n \t\tprefix_offset = strlen(prefix);\n \tgit_config(git_default_config, NULL);\n \n-\tfor (i = 1; i < argc; i++) {\n-\t\tconst char *arg = argv[i];\n-\n-\t\tif (!strcmp(arg, \"--\")) {\n-\t\t\ti++;\n-\t\t\tbreak;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-z\")) {\n-\t\t\tline_terminator = 0;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-t\") || !strcmp(arg, \"-v\")) {\n-\t\t\ttag_cached = \"H \";\n-\t\t\ttag_unmerged = \"M \";\n-\t\t\ttag_removed = \"R \";\n-\t\t\ttag_modified = \"C \";\n-\t\t\ttag_other = \"? \";\n-\t\t\ttag_killed = \"K \";\n-\t\t\tif (arg[1] == 'v')\n-\t\t\t\tshow_valid_bit = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-c\") || !strcmp(arg, \"--cached\")) {\n-\t\t\tshow_cached = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-d\") || !strcmp(arg, \"--deleted\")) {\n-\t\t\tshow_deleted = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-m\") || !strcmp(arg, \"--modified\")) {\n-\t\t\tshow_modified = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-o\") || !strcmp(arg, \"--others\")) {\n-\t\t\tshow_others = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-i\") || !strcmp(arg, \"--ignored\")) {\n-\t\t\tdir.show_ignored = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-s\") || !strcmp(arg, \"--stage\")) {\n-\t\t\tshow_stage = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-k\") || !strcmp(arg, \"--killed\")) {\n-\t\t\tshow_killed = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--directory\")) {\n-\t\t\tdir.show_other_directories = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--no-empty-directory\")) {\n-\t\t\tdir.hide_empty_directories = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-u\") || !strcmp(arg, \"--unmerged\")) {\n-\t\t\t/* There's no point in showing unmerged unless\n-\t\t\t * you also show the stage information.\n-\t\t\t */\n-\t\t\tshow_stage = 1;\n-\t\t\tshow_unmerged = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-x\") && i+1 < argc) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_exclude(argv[++i], \"\", 0, &dir.exclude_list[EXC_CMDL]);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--exclude=\")) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_exclude(arg+10, \"\", 0, &dir.exclude_list[EXC_CMDL]);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-X\") && i+1 < argc) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_excludes_from_file(&dir, argv[++i]);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--exclude-from=\")) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_excludes_from_file(&dir, arg+15);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--exclude-per-directory=\")) {\n-\t\t\texc_given = 1;\n-\t\t\tdir.exclude_per_dir = arg + 24;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--exclude-standard\")) {\n-\t\t\texc_given = 1;\n-\t\t\tsetup_standard_excludes(&dir);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--full-name\")) {\n-\t\t\tprefix_offset = 0;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--error-unmatch\")) {\n-\t\t\terror_unmatch = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--with-tree=\")) {\n-\t\t\twith_tree = arg + 12;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--abbrev=\")) {\n-\t\t\tabbrev = strtoul(arg+9, NULL, 10);\n-\t\t\tif (abbrev && abbrev < MINIMUM_ABBREV)\n-\t\t\t\tabbrev = MINIMUM_ABBREV;\n-\t\t\telse if (abbrev > 40)\n-\t\t\t\tabbrev = 40;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--abbrev\")) {\n-\t\t\tabbrev = DEFAULT_ABBREV;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (*arg == '-')\n-\t\t\tusage(ls_files_usage);\n-\t\tbreak;\n+\targc = parse_options(argc, argv, builtin_ls_files_options,\n+\t\t\tls_files_usage, 0);\n+\tif (show_tag || show_valid_bit) {\n+\t\ttag_cached = \"H \";\n+\t\ttag_unmerged = \"M \";\n+\t\ttag_removed = \"R \";\n+\t\ttag_modified = \"C \";\n+\t\ttag_other = \"? \";\n+\t\ttag_killed = \"K \";\n \t}\n+\tif (show_modified || show_others || dir.show_ignored || show_killed)\n+\t\trequire_work_tree = 1;\n+\tif (show_unmerged)\n+\t\t/* There's no point in showing unmerged unless\n+\t\t * you also show the stage information.\n+\t\t */\n+\t\tshow_stage = 1;\n+\tif (dir.exclude_per_dir)\n+\t\texc_given = 1;\n \n \tif (require_work_tree && !is_inside_work_tree())\n \t\tsetup_work_tree();\n \n-\tpathspec = get_pathspec(prefix, argv + i);\n+\tpathspec = get_pathspec(prefix, argv);\n \n \t/* Verify that the pathspec matches the prefix */\n \tif (pathspec)\n-- \n1.6.1\n"},{"id":"99459","messageId":"20090106102202.GA30766@artemis.corp","threadId":"16999","inReplyTo":"1231200669-30684-1-git-send-email-vmiklos@frugalware.org","subject":"Re: [PATCH] parse-opt: migrate builtin-ls-files.","fromName":"Pierre Habouzit","fromEmail":"madcoder@debian.org","sentAt":"2009-01-06T10:22:02Z","receivedAt":"2009-01-06T10:22:02Z","isPatch":true,"sender":{"key":"madcoder@debian.org","avatar":"https://avatars.githubusercontent.com/u/44708?v=4"},"body":"On Tue, Jan 06, 2009 at 12:11:09AM +0000, Miklos Vajna wrote:\n\n> +static int option_parse_no_empty(const struct option *opt,\n> +\t\t\t\t const char *arg, int unset)\n> +{\n> +\tstruct dir_struct *dir = opt->value;\n> +\n> +\tdir->hide_empty_directories = 1;\n> +\n> +\treturn 0;\n> +}\n\nShould be option_parse_empty and deal with \"unset\" to know if `no-` was\nprefixed to it or not.\n\n\n> +\t\t{ OPTION_CALLBACK, 0, \"no-empty-directory\", &dir, NULL,\n> +\t\t\t\"do not list empty directories\",\n\nThis should be \"empty-directory\" and \"list empty directories as well\"\n\n\nI've not checked if you could also check more of the \"unsets\" things in\nyour callbacks as well btw, but it looks like it could.\n\n\n-- \n·O·  Pierre Habouzit\n··O                                                madcoder@debian.org\nOOO                                                http://www.madism.org\n"},{"id":"99532","messageId":"1231297894-31809-1-git-send-email-vmiklos@frugalware.org","threadId":"16999","inReplyTo":"20090106102202.GA30766@artemis.corp","subject":"[PATCH v2] parse-opt: migrate builtin-ls-files.","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2009-01-07T03:11:34Z","receivedAt":"2009-01-07T03:11:34Z","isPatch":true,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>\n---\n\nOn Tue, Jan 06, 2009 at 11:22:02AM +0100, Pierre Habouzit <madcoder@debian.org> wrote:\n> > +static int option_parse_no_empty(const struct option *opt,\n> > +                            const char *arg, int unset)\n> > +{\n> > +   struct dir_struct *dir = opt->value;\n> > +\n> > +   dir->hide_empty_directories = 1;\n> > +\n> > +   return 0;\n> > +}\n>\n> Should be option_parse_empty and deal with \"unset\" to know if `no-`\n> was\n> prefixed to it or not.\n>\n>\n> > +           { OPTION_CALLBACK, 0, \"no-empty-directory\", &dir, NULL,\n> > +                   \"do not list empty directories\",\n>\n> This should be \"empty-directory\" and \"list empty directories as well\"\n\nAh, sure.\n\n> I've not checked if you could also check more of the \"unsets\" things\n> in\n> your callbacks as well btw, but it looks like it could.\n\nRight, added to option_parse_ignored() and option_parse_directory() as\nwell.\n\nInterdiff: b3b6ad0..a44941c in git://repo.or.cz/git/vmiklos.git.\n\n builtin-ls-files.c |  303 +++++++++++++++++++++++++++++-----------------------\n 1 files changed, 168 insertions(+), 135 deletions(-)\n\ndiff --git a/builtin-ls-files.c b/builtin-ls-files.c\nindex f72eb85..8a946ef 100644\n--- a/builtin-ls-files.c\n+++ b/builtin-ls-files.c\n@@ -10,6 +10,7 @@\n #include \"dir.h\"\n #include \"builtin.h\"\n #include \"tree.h\"\n+#include \"parse-options.h\"\n \n static int abbrev;\n static int show_deleted;\n@@ -28,6 +29,7 @@ static const char **pathspec;\n static int error_unmatch;\n static char *ps_matched;\n static const char *with_tree;\n+static int exc_given;\n \n static const char *tag_cached = \"\";\n static const char *tag_unmerged = \"\";\n@@ -395,156 +397,187 @@ int report_path_error(const char *ps_matched, const char **pathspec, int prefix_\n \treturn errors;\n }\n \n-static const char ls_files_usage[] =\n-\t\"git ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* \"\n-\t\"[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] \"\n-\t\"[ --exclude-per-directory=<filename> ] [--exclude-standard] \"\n-\t\"[--full-name] [--abbrev] [--] [<file>]*\";\n+static const char * const ls_files_usage[] = {\n+\t\"git ls-files [options] [<file>]*\",\n+\tNULL\n+};\n+\n+static int option_parse_z(const struct option *opt,\n+\t\t\t  const char *arg, int unset)\n+{\n+\tif (unset)\n+\t\tline_terminator = '\\n';\n+\telse\n+\t\tline_terminator = 0;\n+\treturn 0;\n+}\n+\n+static int option_parse_exclude(const struct option *opt,\n+\t\t\t\tconst char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\texc_given = 1;\n+\tadd_exclude(arg, \"\", 0, &dir->exclude_list[EXC_CMDL]);\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_exclude_from(const struct option *opt,\n+\t\t\t\t     const char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\texc_given = 1;\n+\tadd_excludes_from_file(dir, arg);\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_exclude_standard(const struct option *opt,\n+\t\t\t\t\t const char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\texc_given = 1;\n+\tsetup_standard_excludes(dir);\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_ignored(const struct option *opt,\n+\t\t\t\tconst char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\tif (unset)\n+\t\tdir->show_ignored = 0;\n+\telse\n+\t\tdir->show_ignored = 1;\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_directory(const struct option *opt,\n+\t\t\t\t  const char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\tif (unset)\n+\t\tdir->show_other_directories = 0;\n+\telse\n+\t\tdir->show_other_directories = 1;\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_empty(const struct option *opt,\n+\t\t\t\t const char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\tif (unset)\n+\t\tdir->hide_empty_directories = 1;\n+\telse\n+\t\tdir->hide_empty_directories = 0;\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_full_name(const struct option *opt,\n+\t\t\t\t  const char *arg, int unset)\n+{\n+\tprefix_offset = 0;\n+\n+\treturn 0;\n+}\n \n int cmd_ls_files(int argc, const char **argv, const char *prefix)\n {\n-\tint i;\n-\tint exc_given = 0, require_work_tree = 0;\n+\tint require_work_tree = 0, show_tag = 0;\n \tstruct dir_struct dir;\n+\tstruct option builtin_ls_files_options[] = {\n+\t\t{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,\n+\t\t\t\"paths are separated with NUL character\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_z },\n+\t\tOPT_BOOLEAN('t', NULL, &show_tag,\n+\t\t\t\"identify the file status with tags\"),\n+\t\tOPT_BOOLEAN('v', NULL, &show_valid_bit,\n+\t\t\t\"use lowercase letters for 'assume unchanged' files\"),\n+\t\tOPT_BOOLEAN('c', \"cached\", &show_cached,\n+\t\t\t\t\"show cached files in the output (default)\"),\n+\t\tOPT_BOOLEAN('d', \"deleted\", &show_deleted,\n+\t\t\t\t\"show deleted files in the output\"),\n+\t\tOPT_BOOLEAN('m', \"modified\", &show_modified,\n+\t\t\t\t\"show modified files in the output\"),\n+\t\tOPT_BOOLEAN('o', \"others\", &show_others,\n+\t\t\t\t\"show other files in the output\"),\n+\t\t{ OPTION_CALLBACK, 'i', \"ignored\", &dir, NULL,\n+\t\t\t\"show ignored files in the output\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_ignored },\n+\t\tOPT_BOOLEAN('s', \"stage\", &show_stage,\n+\t\t\t\"show staged contents' object name in the output\"),\n+\t\tOPT_BOOLEAN('k', \"killed\", &show_killed,\n+\t\t\t\"show files on the filesystem that need to be removed\"),\n+\t\t{ OPTION_CALLBACK, 0, \"directory\", &dir, NULL,\n+\t\t\t\"show 'other' directories' name only\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_directory },\n+\t\t{ OPTION_CALLBACK, 0, \"empty-directory\", &dir, NULL,\n+\t\t\t\"list empty directories\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_empty },\n+\t\tOPT_BOOLEAN('u', \"unmerged\", &show_unmerged,\n+\t\t\t\"show unmerged files in the output\"),\n+\t\t{ OPTION_CALLBACK, 'x', \"exclude\", &dir, \"pattern\",\n+\t\t\t\"skip files matching pattern\",\n+\t\t\t0, option_parse_exclude },\n+\t\t{ OPTION_CALLBACK, 'X', \"exclude-from\", &dir, \"file\",\n+\t\t\t\"exclude patterns are read from <file>\",\n+\t\t\t0, option_parse_exclude_from },\n+\t\tOPT_STRING(0, \"exclude-per-directory\", &dir.exclude_per_dir, \"file\",\n+\t\t\t\"read additional per-directory exclude patterns in <file>\"),\n+\t\t{ OPTION_CALLBACK, 0, \"exclude-standard\", &dir, NULL,\n+\t\t\t\"add the standard git exclusions\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_exclude_standard },\n+\t\t{ OPTION_CALLBACK, 0, \"full-name\", NULL, NULL,\n+\t\t\t\"make the output relative to the project top directory\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_full_name },\n+\t\tOPT_BOOLEAN(0, \"error-unmatch\", &error_unmatch,\n+\t\t\t\"if any <file> is not in the index, treat this as an error\"),\n+\t\tOPT_STRING(0, \"with-tree\", &with_tree, \"tree-ish\",\n+\t\t\t\"pretend that paths removed since <tree-ish> are still present\"),\n+\t\tOPT__ABBREV(&abbrev),\n+\t\tOPT_END()\n+\t};\n \n \tmemset(&dir, 0, sizeof(dir));\n \tif (prefix)\n \t\tprefix_offset = strlen(prefix);\n \tgit_config(git_default_config, NULL);\n \n-\tfor (i = 1; i < argc; i++) {\n-\t\tconst char *arg = argv[i];\n-\n-\t\tif (!strcmp(arg, \"--\")) {\n-\t\t\ti++;\n-\t\t\tbreak;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-z\")) {\n-\t\t\tline_terminator = 0;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-t\") || !strcmp(arg, \"-v\")) {\n-\t\t\ttag_cached = \"H \";\n-\t\t\ttag_unmerged = \"M \";\n-\t\t\ttag_removed = \"R \";\n-\t\t\ttag_modified = \"C \";\n-\t\t\ttag_other = \"? \";\n-\t\t\ttag_killed = \"K \";\n-\t\t\tif (arg[1] == 'v')\n-\t\t\t\tshow_valid_bit = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-c\") || !strcmp(arg, \"--cached\")) {\n-\t\t\tshow_cached = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-d\") || !strcmp(arg, \"--deleted\")) {\n-\t\t\tshow_deleted = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-m\") || !strcmp(arg, \"--modified\")) {\n-\t\t\tshow_modified = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-o\") || !strcmp(arg, \"--others\")) {\n-\t\t\tshow_others = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-i\") || !strcmp(arg, \"--ignored\")) {\n-\t\t\tdir.show_ignored = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-s\") || !strcmp(arg, \"--stage\")) {\n-\t\t\tshow_stage = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-k\") || !strcmp(arg, \"--killed\")) {\n-\t\t\tshow_killed = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--directory\")) {\n-\t\t\tdir.show_other_directories = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--no-empty-directory\")) {\n-\t\t\tdir.hide_empty_directories = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-u\") || !strcmp(arg, \"--unmerged\")) {\n-\t\t\t/* There's no point in showing unmerged unless\n-\t\t\t * you also show the stage information.\n-\t\t\t */\n-\t\t\tshow_stage = 1;\n-\t\t\tshow_unmerged = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-x\") && i+1 < argc) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_exclude(argv[++i], \"\", 0, &dir.exclude_list[EXC_CMDL]);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--exclude=\")) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_exclude(arg+10, \"\", 0, &dir.exclude_list[EXC_CMDL]);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-X\") && i+1 < argc) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_excludes_from_file(&dir, argv[++i]);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--exclude-from=\")) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_excludes_from_file(&dir, arg+15);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--exclude-per-directory=\")) {\n-\t\t\texc_given = 1;\n-\t\t\tdir.exclude_per_dir = arg + 24;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--exclude-standard\")) {\n-\t\t\texc_given = 1;\n-\t\t\tsetup_standard_excludes(&dir);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--full-name\")) {\n-\t\t\tprefix_offset = 0;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--error-unmatch\")) {\n-\t\t\terror_unmatch = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--with-tree=\")) {\n-\t\t\twith_tree = arg + 12;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--abbrev=\")) {\n-\t\t\tabbrev = strtoul(arg+9, NULL, 10);\n-\t\t\tif (abbrev && abbrev < MINIMUM_ABBREV)\n-\t\t\t\tabbrev = MINIMUM_ABBREV;\n-\t\t\telse if (abbrev > 40)\n-\t\t\t\tabbrev = 40;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--abbrev\")) {\n-\t\t\tabbrev = DEFAULT_ABBREV;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (*arg == '-')\n-\t\t\tusage(ls_files_usage);\n-\t\tbreak;\n+\targc = parse_options(argc, argv, builtin_ls_files_options,\n+\t\t\tls_files_usage, 0);\n+\tif (show_tag || show_valid_bit) {\n+\t\ttag_cached = \"H \";\n+\t\ttag_unmerged = \"M \";\n+\t\ttag_removed = \"R \";\n+\t\ttag_modified = \"C \";\n+\t\ttag_other = \"? \";\n+\t\ttag_killed = \"K \";\n \t}\n+\tif (show_modified || show_others || dir.show_ignored || show_killed)\n+\t\trequire_work_tree = 1;\n+\tif (show_unmerged)\n+\t\t/* There's no point in showing unmerged unless\n+\t\t * you also show the stage information.\n+\t\t */\n+\t\tshow_stage = 1;\n+\tif (dir.exclude_per_dir)\n+\t\texc_given = 1;\n \n \tif (require_work_tree && !is_inside_work_tree())\n \t\tsetup_work_tree();\n \n-\tpathspec = get_pathspec(prefix, argv + i);\n+\tpathspec = get_pathspec(prefix, argv);\n \n \t/* Verify that the pathspec matches the prefix */\n \tif (pathspec)\n-- \n1.6.1\n"},{"id":"99583","messageId":"20090107144640.GD831@artemis.corp","threadId":"16999","inReplyTo":"1231297894-31809-1-git-send-email-vmiklos@frugalware.org","subject":"Re: [PATCH v2] parse-opt: migrate builtin-ls-files.","fromName":"Pierre Habouzit","fromEmail":"madcoder@debian.org","sentAt":"2009-01-07T14:46:40Z","receivedAt":"2009-01-07T14:46:40Z","isPatch":true,"sender":{"key":"madcoder@debian.org","avatar":"https://avatars.githubusercontent.com/u/44708?v=4"},"body":"On Wed, Jan 07, 2009 at 03:11:34AM +0000, Miklos Vajna wrote:\n\n> +static int option_parse_ignored(const struct option *opt,\n> +\t\t\t\tconst char *arg, int unset)\n> +{\n> +\tstruct dir_struct *dir = opt->value;\n> +\n> +\tif (unset)\n> +\t\tdir->show_ignored = 0;\n> +\telse\n> +\t\tdir->show_ignored = 1;\n\ndir->show_ignored = !unset ?\n\n> +static int option_parse_directory(const struct option *opt,\n> +\t\t\t\t  const char *arg, int unset)\n> +{\n\nditto\n\n> +static int option_parse_empty(const struct option *opt,\n> +\t\t\t\t const char *arg, int unset)\n> +{\n\nditto\n\n\n-- \n·O·  Pierre Habouzit\n··O                                                madcoder@debian.org\nOOO                                                http://www.madism.org\n"},{"id":"99645","messageId":"1231376145-32331-1-git-send-email-vmiklos@frugalware.org","threadId":"16999","inReplyTo":"20090107144640.GD831@artemis.corp","subject":"[PATCH v3] parse-opt: migrate builtin-ls-files.","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2009-01-08T00:55:45Z","receivedAt":"2009-01-08T00:55:45Z","isPatch":true,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>\n---\n\nOn Wed, Jan 07, 2009 at 03:46:40PM +0100, Pierre Habouzit <madcoder@debian.org> wrote:\n> > +   if (unset)\n> > +           dir->show_ignored = 0;\n> > +   else\n> > +           dir->show_ignored = 1;\n>\n> dir->show_ignored = !unset ?\n\nTrue, cleaned up all 3 occurrences.\n\nInterdiff: git diff b2a38d9..ee34fcc in my repo.\n\n builtin-ls-files.c |  294 ++++++++++++++++++++++++++++------------------------\n 1 files changed, 159 insertions(+), 135 deletions(-)\n\ndiff --git a/builtin-ls-files.c b/builtin-ls-files.c\nindex f72eb85..ffa8210 100644\n--- a/builtin-ls-files.c\n+++ b/builtin-ls-files.c\n@@ -10,6 +10,7 @@\n #include \"dir.h\"\n #include \"builtin.h\"\n #include \"tree.h\"\n+#include \"parse-options.h\"\n \n static int abbrev;\n static int show_deleted;\n@@ -28,6 +29,7 @@ static const char **pathspec;\n static int error_unmatch;\n static char *ps_matched;\n static const char *with_tree;\n+static int exc_given;\n \n static const char *tag_cached = \"\";\n static const char *tag_unmerged = \"\";\n@@ -395,156 +397,178 @@ int report_path_error(const char *ps_matched, const char **pathspec, int prefix_\n \treturn errors;\n }\n \n-static const char ls_files_usage[] =\n-\t\"git ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* \"\n-\t\"[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] \"\n-\t\"[ --exclude-per-directory=<filename> ] [--exclude-standard] \"\n-\t\"[--full-name] [--abbrev] [--] [<file>]*\";\n+static const char * const ls_files_usage[] = {\n+\t\"git ls-files [options] [<file>]*\",\n+\tNULL\n+};\n+\n+static int option_parse_z(const struct option *opt,\n+\t\t\t  const char *arg, int unset)\n+{\n+\tif (unset)\n+\t\tline_terminator = '\\n';\n+\telse\n+\t\tline_terminator = 0;\n+\treturn 0;\n+}\n+\n+static int option_parse_exclude(const struct option *opt,\n+\t\t\t\tconst char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\texc_given = 1;\n+\tadd_exclude(arg, \"\", 0, &dir->exclude_list[EXC_CMDL]);\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_exclude_from(const struct option *opt,\n+\t\t\t\t     const char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\texc_given = 1;\n+\tadd_excludes_from_file(dir, arg);\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_exclude_standard(const struct option *opt,\n+\t\t\t\t\t const char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\texc_given = 1;\n+\tsetup_standard_excludes(dir);\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_ignored(const struct option *opt,\n+\t\t\t\tconst char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\tdir->show_ignored = !unset;\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_directory(const struct option *opt,\n+\t\t\t\t  const char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\tdir->show_other_directories = !unset;\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_empty(const struct option *opt,\n+\t\t\t\t const char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\tdir->hide_empty_directories = unset;\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_full_name(const struct option *opt,\n+\t\t\t\t  const char *arg, int unset)\n+{\n+\tprefix_offset = 0;\n+\n+\treturn 0;\n+}\n \n int cmd_ls_files(int argc, const char **argv, const char *prefix)\n {\n-\tint i;\n-\tint exc_given = 0, require_work_tree = 0;\n+\tint require_work_tree = 0, show_tag = 0;\n \tstruct dir_struct dir;\n+\tstruct option builtin_ls_files_options[] = {\n+\t\t{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,\n+\t\t\t\"paths are separated with NUL character\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_z },\n+\t\tOPT_BOOLEAN('t', NULL, &show_tag,\n+\t\t\t\"identify the file status with tags\"),\n+\t\tOPT_BOOLEAN('v', NULL, &show_valid_bit,\n+\t\t\t\"use lowercase letters for 'assume unchanged' files\"),\n+\t\tOPT_BOOLEAN('c', \"cached\", &show_cached,\n+\t\t\t\t\"show cached files in the output (default)\"),\n+\t\tOPT_BOOLEAN('d', \"deleted\", &show_deleted,\n+\t\t\t\t\"show deleted files in the output\"),\n+\t\tOPT_BOOLEAN('m', \"modified\", &show_modified,\n+\t\t\t\t\"show modified files in the output\"),\n+\t\tOPT_BOOLEAN('o', \"others\", &show_others,\n+\t\t\t\t\"show other files in the output\"),\n+\t\t{ OPTION_CALLBACK, 'i', \"ignored\", &dir, NULL,\n+\t\t\t\"show ignored files in the output\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_ignored },\n+\t\tOPT_BOOLEAN('s', \"stage\", &show_stage,\n+\t\t\t\"show staged contents' object name in the output\"),\n+\t\tOPT_BOOLEAN('k', \"killed\", &show_killed,\n+\t\t\t\"show files on the filesystem that need to be removed\"),\n+\t\t{ OPTION_CALLBACK, 0, \"directory\", &dir, NULL,\n+\t\t\t\"show 'other' directories' name only\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_directory },\n+\t\t{ OPTION_CALLBACK, 0, \"empty-directory\", &dir, NULL,\n+\t\t\t\"list empty directories\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_empty },\n+\t\tOPT_BOOLEAN('u', \"unmerged\", &show_unmerged,\n+\t\t\t\"show unmerged files in the output\"),\n+\t\t{ OPTION_CALLBACK, 'x', \"exclude\", &dir, \"pattern\",\n+\t\t\t\"skip files matching pattern\",\n+\t\t\t0, option_parse_exclude },\n+\t\t{ OPTION_CALLBACK, 'X', \"exclude-from\", &dir, \"file\",\n+\t\t\t\"exclude patterns are read from <file>\",\n+\t\t\t0, option_parse_exclude_from },\n+\t\tOPT_STRING(0, \"exclude-per-directory\", &dir.exclude_per_dir, \"file\",\n+\t\t\t\"read additional per-directory exclude patterns in <file>\"),\n+\t\t{ OPTION_CALLBACK, 0, \"exclude-standard\", &dir, NULL,\n+\t\t\t\"add the standard git exclusions\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_exclude_standard },\n+\t\t{ OPTION_CALLBACK, 0, \"full-name\", NULL, NULL,\n+\t\t\t\"make the output relative to the project top directory\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_full_name },\n+\t\tOPT_BOOLEAN(0, \"error-unmatch\", &error_unmatch,\n+\t\t\t\"if any <file> is not in the index, treat this as an error\"),\n+\t\tOPT_STRING(0, \"with-tree\", &with_tree, \"tree-ish\",\n+\t\t\t\"pretend that paths removed since <tree-ish> are still present\"),\n+\t\tOPT__ABBREV(&abbrev),\n+\t\tOPT_END()\n+\t};\n \n \tmemset(&dir, 0, sizeof(dir));\n \tif (prefix)\n \t\tprefix_offset = strlen(prefix);\n \tgit_config(git_default_config, NULL);\n \n-\tfor (i = 1; i < argc; i++) {\n-\t\tconst char *arg = argv[i];\n-\n-\t\tif (!strcmp(arg, \"--\")) {\n-\t\t\ti++;\n-\t\t\tbreak;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-z\")) {\n-\t\t\tline_terminator = 0;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-t\") || !strcmp(arg, \"-v\")) {\n-\t\t\ttag_cached = \"H \";\n-\t\t\ttag_unmerged = \"M \";\n-\t\t\ttag_removed = \"R \";\n-\t\t\ttag_modified = \"C \";\n-\t\t\ttag_other = \"? \";\n-\t\t\ttag_killed = \"K \";\n-\t\t\tif (arg[1] == 'v')\n-\t\t\t\tshow_valid_bit = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-c\") || !strcmp(arg, \"--cached\")) {\n-\t\t\tshow_cached = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-d\") || !strcmp(arg, \"--deleted\")) {\n-\t\t\tshow_deleted = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-m\") || !strcmp(arg, \"--modified\")) {\n-\t\t\tshow_modified = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-o\") || !strcmp(arg, \"--others\")) {\n-\t\t\tshow_others = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-i\") || !strcmp(arg, \"--ignored\")) {\n-\t\t\tdir.show_ignored = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-s\") || !strcmp(arg, \"--stage\")) {\n-\t\t\tshow_stage = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-k\") || !strcmp(arg, \"--killed\")) {\n-\t\t\tshow_killed = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--directory\")) {\n-\t\t\tdir.show_other_directories = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--no-empty-directory\")) {\n-\t\t\tdir.hide_empty_directories = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-u\") || !strcmp(arg, \"--unmerged\")) {\n-\t\t\t/* There's no point in showing unmerged unless\n-\t\t\t * you also show the stage information.\n-\t\t\t */\n-\t\t\tshow_stage = 1;\n-\t\t\tshow_unmerged = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-x\") && i+1 < argc) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_exclude(argv[++i], \"\", 0, &dir.exclude_list[EXC_CMDL]);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--exclude=\")) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_exclude(arg+10, \"\", 0, &dir.exclude_list[EXC_CMDL]);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-X\") && i+1 < argc) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_excludes_from_file(&dir, argv[++i]);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--exclude-from=\")) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_excludes_from_file(&dir, arg+15);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--exclude-per-directory=\")) {\n-\t\t\texc_given = 1;\n-\t\t\tdir.exclude_per_dir = arg + 24;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--exclude-standard\")) {\n-\t\t\texc_given = 1;\n-\t\t\tsetup_standard_excludes(&dir);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--full-name\")) {\n-\t\t\tprefix_offset = 0;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--error-unmatch\")) {\n-\t\t\terror_unmatch = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--with-tree=\")) {\n-\t\t\twith_tree = arg + 12;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--abbrev=\")) {\n-\t\t\tabbrev = strtoul(arg+9, NULL, 10);\n-\t\t\tif (abbrev && abbrev < MINIMUM_ABBREV)\n-\t\t\t\tabbrev = MINIMUM_ABBREV;\n-\t\t\telse if (abbrev > 40)\n-\t\t\t\tabbrev = 40;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--abbrev\")) {\n-\t\t\tabbrev = DEFAULT_ABBREV;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (*arg == '-')\n-\t\t\tusage(ls_files_usage);\n-\t\tbreak;\n+\targc = parse_options(argc, argv, builtin_ls_files_options,\n+\t\t\tls_files_usage, 0);\n+\tif (show_tag || show_valid_bit) {\n+\t\ttag_cached = \"H \";\n+\t\ttag_unmerged = \"M \";\n+\t\ttag_removed = \"R \";\n+\t\ttag_modified = \"C \";\n+\t\ttag_other = \"? \";\n+\t\ttag_killed = \"K \";\n \t}\n+\tif (show_modified || show_others || dir.show_ignored || show_killed)\n+\t\trequire_work_tree = 1;\n+\tif (show_unmerged)\n+\t\t/* There's no point in showing unmerged unless\n+\t\t * you also show the stage information.\n+\t\t */\n+\t\tshow_stage = 1;\n+\tif (dir.exclude_per_dir)\n+\t\texc_given = 1;\n \n \tif (require_work_tree && !is_inside_work_tree())\n \t\tsetup_work_tree();\n \n-\tpathspec = get_pathspec(prefix, argv + i);\n+\tpathspec = get_pathspec(prefix, argv);\n \n \t/* Verify that the pathspec matches the prefix */\n \tif (pathspec)\n-- \n1.6.1\n"},{"id":"99650","messageId":"alpine.DEB.1.00.0901080207520.30769@pacific.mpi-cbg.de","threadId":"16999","inReplyTo":"1231376145-32331-1-git-send-email-vmiklos@frugalware.org","subject":"Re: [PATCH v3] parse-opt: migrate builtin-ls-files.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-01-08T01:10:15Z","receivedAt":"2009-01-08T01:10:15Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 8 Jan 2009, Miklos Vajna wrote:\n\n> Interdiff: git diff b2a38d9..ee34fcc in my repo.\n\n... or on repo.or.cz:\n\nhttp://repo.or.cz/w/git/vmiklos.git?a=treediff;hpb=b2a38d9;hb=ee34fcc\n\nCiao,\nDscho\n"},{"id":"99653","messageId":"20090108015407.GS21154@genesis.frugalware.org","threadId":"16999","inReplyTo":"alpine.DEB.1.00.0901080207520.30769@pacific.mpi-cbg.de","subject":"Re: [PATCH v3] parse-opt: migrate builtin-ls-files.","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2009-01-08T01:54:07Z","receivedAt":"2009-01-08T01:54:07Z","isPatch":true,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"On Thu, Jan 08, 2009 at 02:10:15AM +0100, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> > Interdiff: git diff b2a38d9..ee34fcc in my repo.\n> \n> ... or on repo.or.cz:\n> \n> http://repo.or.cz/w/git/vmiklos.git?a=treediff;hpb=b2a38d9;hb=ee34fcc\n\nThat *is* what I meant by 'my repo'. ;-)\n\nBTW thanks for the link, I didn't know about it - AFAIK stock gitweb\ndoes not have a treediff view.\n"},{"id":"100514","messageId":"20090115001410.GE30710@genesis.frugalware.org","threadId":"16999","inReplyTo":"1231376145-32331-1-git-send-email-vmiklos@frugalware.org","subject":"Re: [PATCH v3] parse-opt: migrate builtin-ls-files.","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2009-01-15T00:14:10Z","receivedAt":"2009-01-15T00:14:10Z","isPatch":true,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"On Thu, Jan 08, 2009 at 01:55:45AM +0100, Miklos Vajna <vmiklos@frugalware.org> wrote:\n>  builtin-ls-files.c |  294 ++++++++++++++++++++++++++++------------------------\n>  1 files changed, 159 insertions(+), 135 deletions(-)\n\nHi Junio,\n\nWas this dropped on the floor by accident?\n\nThanks.\n"},{"id":"100537","messageId":"7vljtdw961.fsf@gitster.siamese.dyndns.org","threadId":"16999","inReplyTo":"20090115001410.GE30710@genesis.frugalware.org","subject":"Re: [PATCH v3] parse-opt: migrate builtin-ls-files.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-01-15T03:16:38Z","receivedAt":"2009-01-15T03:16:38Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Miklos Vajna <vmiklos@frugalware.org> writes:\n\n> Was this dropped on the floor by accident?\n\nI am not fundamentally opposed to the parseopt conversion, but I was\nsomewhat discouraged from taking another one, after we got burned by the\none that converted git-apply without much visible gain but with a new bug.\n\nBecause ls-files is a plumbing, it has somewhat lower priority for user\nfriendliness than any other patches currently in-flight on the list; hence\nit has been backburnered.  It still is kept in my Inbox.\n"},{"id":"100541","messageId":"20090115034834.GH30710@genesis.frugalware.org","threadId":"16999","inReplyTo":"7vljtdw961.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH v3] parse-opt: migrate builtin-ls-files.","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2009-01-15T03:48:34Z","receivedAt":"2009-01-15T03:48:34Z","isPatch":true,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"On Wed, Jan 14, 2009 at 07:16:38PM -0800, Junio C Hamano <gitster@pobox.com> wrote:\n> I am not fundamentally opposed to the parseopt conversion, but I was\n> somewhat discouraged from taking another one, after we got burned by the\n> one that converted git-apply without much visible gain but with a new bug.\n> \n> Because ls-files is a plumbing, it has somewhat lower priority for user\n> friendliness than any other patches currently in-flight on the list; hence\n> it has been backburnered.  It still is kept in my Inbox.\n\nMakes sense, thanks for the answer.\n"},{"id":"104634","messageId":"20090214121631.GG4371@genesis.frugalware.org","threadId":"16999","inReplyTo":"7vljtdw961.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH v3] parse-opt: migrate builtin-ls-files.","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2009-02-14T12:16:31Z","receivedAt":"2009-02-14T12:16:31Z","isPatch":true,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"On Wed, Jan 14, 2009 at 07:16:38PM -0800, Junio C Hamano <gitster@pobox.com> wrote:\n> Miklos Vajna <vmiklos@frugalware.org> writes:\n> \n> > Was this dropped on the floor by accident?\n> \n> I am not fundamentally opposed to the parseopt conversion, but I was\n> somewhat discouraged from taking another one, after we got burned by the\n> one that converted git-apply without much visible gain but with a new bug.\n> \n> Because ls-files is a plumbing, it has somewhat lower priority for user\n> friendliness than any other patches currently in-flight on the list; hence\n> it has been backburnered.  It still is kept in my Inbox.\n\nI'm just asking again as I see the parseopt patch for builtin-config now\non the list.\n\nShould I just resend this patch after v1.6.2?\n"},{"id":"104680","messageId":"7vmycoss2r.fsf@gitster.siamese.dyndns.org","threadId":"16999","inReplyTo":"20090214121631.GG4371@genesis.frugalware.org","subject":"Re: [PATCH v3] parse-opt: migrate builtin-ls-files.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-14T20:04:44Z","receivedAt":"2009-02-14T20:04:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Miklos Vajna <vmiklos@frugalware.org> writes:\n\n> On Wed, Jan 14, 2009 at 07:16:38PM -0800, Junio C Hamano <gitster@pobox.com> wrote:\n>> Miklos Vajna <vmiklos@frugalware.org> writes:\n>> \n>> > Was this dropped on the floor by accident?\n>> \n>> I am not fundamentally opposed to the parseopt conversion, but I was\n>> somewhat discouraged from taking another one, after we got burned by the\n>> one that converted git-apply without much visible gain but with a new bug.\n>> \n>> Because ls-files is a plumbing, it has somewhat lower priority for user\n>> friendliness than any other patches currently in-flight on the list; hence\n>> it has been backburnered.  It still is kept in my Inbox.\n>\n> I'm just asking again as I see the parseopt patch for builtin-config now\n> on the list.\n>\n> Should I just resend this patch after v1.6.2?\n\nYou can do it either way, and a resend after v1.6.2 is certainly\nappreciated,\n\nAs I said earlier in \"What's cooking\", 'pu' and 'next' are open during\nthis freeze cycle as an experiment.\n\nI limit my bandwidth for handing anything non-fix during the rc freeze\nperiod as always.  The only difference from previous cycles is that the\ncap used to be set to near-absolute-zero, but in this cycle it is not.\n\nIt still is capped and updates to 'pu' and 'next' are \"as time permits\"\nbasis.\n"},{"id":"104691","messageId":"alpine.DEB.1.00.0902142127040.10279@pacific.mpi-cbg.de","threadId":"16999","inReplyTo":"1231376145-32331-1-git-send-email-vmiklos@frugalware.org","subject":"Re: [PATCH v3] parse-opt: migrate builtin-ls-files.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-02-14T20:56:04Z","receivedAt":"2009-02-14T20:56:04Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 8 Jan 2009, Miklos Vajna wrote:\n\n> +static int option_parse_z(const struct option *opt,\n> +\t\t\t  const char *arg, int unset)\n> +{\n> +\tif (unset)\n> +\t\tline_terminator = '\\n';\n> +\telse\n> +\t\tline_terminator = 0;\n> +\treturn 0;\n> +}\n\n\tline_terminator = unset ? '\\0' : '\\n';\n\nHmm?\n\n> +static int option_parse_exclude(const struct option *opt,\n> +\t\t\t\tconst char *arg, int unset)\n> +{\n> +\tstruct dir_struct *dir = opt->value;\n> +\n> +\texc_given = 1;\n> +\tadd_exclude(arg, \"\", 0, &dir->exclude_list[EXC_CMDL]);\n\nWhy is &dir->exclude_list[EXC_CMDL] not stored in opt->value directly?\n\n> +static int option_parse_ignored(const struct option *opt,\n> +\t\t\t\tconst char *arg, int unset)\n> +{\n> +\tstruct dir_struct *dir = opt->value;\n> +\n> +\tdir->show_ignored = !unset;\n> +\n> +\treturn 0;\n> +}\n\nMaybe this wants to be converted into an OPTION_BIT compatible data type?\n\n> +static int option_parse_directory(const struct option *opt,\n> +\t\t\t\t  const char *arg, int unset)\n> +{\n> +\tstruct dir_struct *dir = opt->value;\n> +\n> +\tdir->show_other_directories = !unset;\n> +\n> +\treturn 0;\n> +}\n\nLikewise?\n\n> +static int option_parse_empty(const struct option *opt,\n> +\t\t\t\t const char *arg, int unset)\n> +{\n> +\tstruct dir_struct *dir = opt->value;\n> +\n> +\tdir->hide_empty_directories = unset;\n> +\n> +\treturn 0;\n> +}\n\nMaybe we need an OPT_BIT_NEG?\n\n> +static int option_parse_full_name(const struct option *opt,\n> +\t\t\t\t  const char *arg, int unset)\n> +{\n> +\tprefix_offset = 0;\n> +\n> +\treturn 0;\n> +}\n\nNot that it matters much, but maybe you can guard this with an\n\"if (!unset)\"?\n\n> +\t\t{ OPTION_CALLBACK, 0, \"full-name\", NULL, NULL,\n> +\t\t\t\"make the output relative to the project top directory\",\n> +\t\t\tPARSE_OPT_NOARG, option_parse_full_name },\n\nMaybe OPT_NONEG, and maybe SET_INT?\n\n> +\tif (dir.exclude_per_dir)\n> +\t\texc_given = 1;\n\nYou could use a boolean to handle --exclude-standard, too... But you did \nnot do that so that there is no regression with specific ordering of the \nexclude options, right?\n\nCiao,\nDscho\n"},{"id":"104814","messageId":"1234727647-18523-1-git-send-email-vmiklos@frugalware.org","threadId":"16999","inReplyTo":"alpine.DEB.1.00.0902142127040.10279@pacific.mpi-cbg.de","subject":"[PATCH] parse-opt: migrate builtin-ls-files.","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2009-02-15T19:54:07Z","receivedAt":"2009-02-15T19:54:07Z","isPatch":true,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>\n---\n\nOn Sat, Feb 14, 2009 at 09:56:04PM +0100, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> Hi,\n>\n> On Thu, 8 Jan 2009, Miklos Vajna wrote:\n>\n> > +static int option_parse_z(const struct option *opt,\n> > +                     const char *arg, int unset)\n> > +{\n> > +   if (unset)\n> > +           line_terminator = '\\n';\n> > +   else\n> > +           line_terminator = 0;\n> > +   return 0;\n> > +}\n>\n>       line_terminator = unset ? '\\0' : '\\n';\n>\n> Hmm?\n\nThe opposite:\n\n        line_terminator = unset ? '\\n' : '\\0';\n\n> > +static int option_parse_exclude(const struct option *opt,\n> > +                           const char *arg, int unset)\n> > +{\n> > +   struct dir_struct *dir = opt->value;\n> > +\n> > +   exc_given = 1;\n> > +   add_exclude(arg, \"\", 0, &dir->exclude_list[EXC_CMDL]);\n>\n> Why is &dir->exclude_list[EXC_CMDL] not stored in opt->value directly?\n\nChanged.\n\n> > +static int option_parse_ignored(const struct option *opt,\n> > +                           const char *arg, int unset)\n> > +{\n> > +   struct dir_struct *dir = opt->value;\n> > +\n> > +   dir->show_ignored = !unset;\n> > +\n> > +   return 0;\n> > +}\n>\n> Maybe this wants to be converted into an OPTION_BIT compatible data\n> type?\n\nI think that's not possible, as show_ignored is a bitfield.\n\n> > +static int option_parse_directory(const struct option *opt,\n> > +                             const char *arg, int unset)\n> > +{\n> > +   struct dir_struct *dir = opt->value;\n> > +\n> > +   dir->show_other_directories = !unset;\n> > +\n> > +   return 0;\n> > +}\n>\n> Likewise?\n\nSame, show_other_directories can't be passed as a pointer, either.\n\n> > +static int option_parse_empty(const struct option *opt,\n> > +                            const char *arg, int unset)\n> > +{\n> > +   struct dir_struct *dir = opt->value;\n> > +\n> > +   dir->hide_empty_directories = unset;\n> > +\n> > +   return 0;\n> > +}\n>\n> Maybe we need an OPT_BIT_NEG?\n\nI can do it, but hide_empty_directories is a bitfield as well.\n\n> > +           { OPTION_CALLBACK, 0, \"full-name\", NULL, NULL,\n> > +                   \"make the output relative to the project top\n> > directory\",\n> > +                   PARSE_OPT_NOARG, option_parse_full_name },\n>\n> Maybe OPT_NONEG, and maybe SET_INT?\n\nAh yes, that makes option_parse_full_name useless, great. :-)\n\n> > +   if (dir.exclude_per_dir)\n> > +           exc_given = 1;\n>\n> You could use a boolean to handle --exclude-standard, too... But you\n> did\n> not do that so that there is no regression with specific ordering of\n> the\n> exclude options, right?\n\nYes, exactly.\n\n builtin-ls-files.c |  284 +++++++++++++++++++++++++++-------------------------\n 1 files changed, 149 insertions(+), 135 deletions(-)\n\ndiff --git a/builtin-ls-files.c b/builtin-ls-files.c\nindex 9dec282..0070669 100644\n--- a/builtin-ls-files.c\n+++ b/builtin-ls-files.c\n@@ -10,6 +10,7 @@\n #include \"dir.h\"\n #include \"builtin.h\"\n #include \"tree.h\"\n+#include \"parse-options.h\"\n \n static int abbrev;\n static int show_deleted;\n@@ -28,6 +29,7 @@ static const char **pathspec;\n static int error_unmatch;\n static char *ps_matched;\n static const char *with_tree;\n+static int exc_given;\n \n static const char *tag_cached = \"\";\n static const char *tag_unmerged = \"\";\n@@ -374,156 +376,168 @@ int report_path_error(const char *ps_matched, const char **pathspec, int prefix_\n \treturn errors;\n }\n \n-static const char ls_files_usage[] =\n-\t\"git ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* \"\n-\t\"[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] \"\n-\t\"[ --exclude-per-directory=<filename> ] [--exclude-standard] \"\n-\t\"[--full-name] [--abbrev] [--] [<file>]*\";\n+static const char * const ls_files_usage[] = {\n+\t\"git ls-files [options] [<file>]*\",\n+\tNULL\n+};\n+\n+static int option_parse_z(const struct option *opt,\n+\t\t\t  const char *arg, int unset)\n+{\n+\tline_terminator = unset ? '\\n' : '\\0';\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_exclude(const struct option *opt,\n+\t\t\t\tconst char *arg, int unset)\n+{\n+\tstruct exclude_list *list = opt->value;\n+\n+\texc_given = 1;\n+\tadd_exclude(arg, \"\", 0, list);\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_exclude_from(const struct option *opt,\n+\t\t\t\t     const char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\texc_given = 1;\n+\tadd_excludes_from_file(dir, arg);\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_exclude_standard(const struct option *opt,\n+\t\t\t\t\t const char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\texc_given = 1;\n+\tsetup_standard_excludes(dir);\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_ignored(const struct option *opt,\n+\t\t\t\tconst char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\tdir->show_ignored = !unset;\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_directory(const struct option *opt,\n+\t\t\t\t  const char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\tdir->show_other_directories = !unset;\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_empty(const struct option *opt,\n+\t\t\t\t const char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\tdir->hide_empty_directories = unset;\n+\n+\treturn 0;\n+}\n \n int cmd_ls_files(int argc, const char **argv, const char *prefix)\n {\n-\tint i;\n-\tint exc_given = 0, require_work_tree = 0;\n+\tint require_work_tree = 0, show_tag = 0;\n \tstruct dir_struct dir;\n+\tstruct option builtin_ls_files_options[] = {\n+\t\t{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,\n+\t\t\t\"paths are separated with NUL character\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_z },\n+\t\tOPT_BOOLEAN('t', NULL, &show_tag,\n+\t\t\t\"identify the file status with tags\"),\n+\t\tOPT_BOOLEAN('v', NULL, &show_valid_bit,\n+\t\t\t\"use lowercase letters for 'assume unchanged' files\"),\n+\t\tOPT_BOOLEAN('c', \"cached\", &show_cached,\n+\t\t\t\t\"show cached files in the output (default)\"),\n+\t\tOPT_BOOLEAN('d', \"deleted\", &show_deleted,\n+\t\t\t\t\"show deleted files in the output\"),\n+\t\tOPT_BOOLEAN('m', \"modified\", &show_modified,\n+\t\t\t\t\"show modified files in the output\"),\n+\t\tOPT_BOOLEAN('o', \"others\", &show_others,\n+\t\t\t\t\"show other files in the output\"),\n+\t\t{ OPTION_CALLBACK, 'i', \"ignored\", &dir, NULL,\n+\t\t\t\"show ignored files in the output\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_ignored },\n+\t\tOPT_BOOLEAN('s', \"stage\", &show_stage,\n+\t\t\t\"show staged contents' object name in the output\"),\n+\t\tOPT_BOOLEAN('k', \"killed\", &show_killed,\n+\t\t\t\"show files on the filesystem that need to be removed\"),\n+\t\t{ OPTION_CALLBACK, 0, \"directory\", &dir, NULL,\n+\t\t\t\"show 'other' directories' name only\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_directory },\n+\t\t{ OPTION_CALLBACK, 0, \"empty-directory\", &dir, NULL,\n+\t\t\t\"list empty directories\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_empty },\n+\t\tOPT_BOOLEAN('u', \"unmerged\", &show_unmerged,\n+\t\t\t\"show unmerged files in the output\"),\n+\t\t{ OPTION_CALLBACK, 'x', \"exclude\", &dir.exclude_list[EXC_CMDL], \"pattern\",\n+\t\t\t\"skip files matching pattern\",\n+\t\t\t0, option_parse_exclude },\n+\t\t{ OPTION_CALLBACK, 'X', \"exclude-from\", &dir, \"file\",\n+\t\t\t\"exclude patterns are read from <file>\",\n+\t\t\t0, option_parse_exclude_from },\n+\t\tOPT_STRING(0, \"exclude-per-directory\", &dir.exclude_per_dir, \"file\",\n+\t\t\t\"read additional per-directory exclude patterns in <file>\"),\n+\t\t{ OPTION_CALLBACK, 0, \"exclude-standard\", &dir, NULL,\n+\t\t\t\"add the standard git exclusions\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_exclude_standard },\n+\t\t{ OPTION_SET_INT, 0, \"full-name\", &prefix_offset, NULL,\n+\t\t\t\"make the output relative to the project top directory\",\n+\t\t\tPARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL },\n+\t\tOPT_BOOLEAN(0, \"error-unmatch\", &error_unmatch,\n+\t\t\t\"if any <file> is not in the index, treat this as an error\"),\n+\t\tOPT_STRING(0, \"with-tree\", &with_tree, \"tree-ish\",\n+\t\t\t\"pretend that paths removed since <tree-ish> are still present\"),\n+\t\tOPT__ABBREV(&abbrev),\n+\t\tOPT_END()\n+\t};\n \n \tmemset(&dir, 0, sizeof(dir));\n \tif (prefix)\n \t\tprefix_offset = strlen(prefix);\n \tgit_config(git_default_config, NULL);\n \n-\tfor (i = 1; i < argc; i++) {\n-\t\tconst char *arg = argv[i];\n-\n-\t\tif (!strcmp(arg, \"--\")) {\n-\t\t\ti++;\n-\t\t\tbreak;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-z\")) {\n-\t\t\tline_terminator = 0;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-t\") || !strcmp(arg, \"-v\")) {\n-\t\t\ttag_cached = \"H \";\n-\t\t\ttag_unmerged = \"M \";\n-\t\t\ttag_removed = \"R \";\n-\t\t\ttag_modified = \"C \";\n-\t\t\ttag_other = \"? \";\n-\t\t\ttag_killed = \"K \";\n-\t\t\tif (arg[1] == 'v')\n-\t\t\t\tshow_valid_bit = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-c\") || !strcmp(arg, \"--cached\")) {\n-\t\t\tshow_cached = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-d\") || !strcmp(arg, \"--deleted\")) {\n-\t\t\tshow_deleted = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-m\") || !strcmp(arg, \"--modified\")) {\n-\t\t\tshow_modified = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-o\") || !strcmp(arg, \"--others\")) {\n-\t\t\tshow_others = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-i\") || !strcmp(arg, \"--ignored\")) {\n-\t\t\tdir.show_ignored = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-s\") || !strcmp(arg, \"--stage\")) {\n-\t\t\tshow_stage = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-k\") || !strcmp(arg, \"--killed\")) {\n-\t\t\tshow_killed = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--directory\")) {\n-\t\t\tdir.show_other_directories = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--no-empty-directory\")) {\n-\t\t\tdir.hide_empty_directories = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-u\") || !strcmp(arg, \"--unmerged\")) {\n-\t\t\t/* There's no point in showing unmerged unless\n-\t\t\t * you also show the stage information.\n-\t\t\t */\n-\t\t\tshow_stage = 1;\n-\t\t\tshow_unmerged = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-x\") && i+1 < argc) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_exclude(argv[++i], \"\", 0, &dir.exclude_list[EXC_CMDL]);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--exclude=\")) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_exclude(arg+10, \"\", 0, &dir.exclude_list[EXC_CMDL]);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-X\") && i+1 < argc) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_excludes_from_file(&dir, argv[++i]);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--exclude-from=\")) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_excludes_from_file(&dir, arg+15);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--exclude-per-directory=\")) {\n-\t\t\texc_given = 1;\n-\t\t\tdir.exclude_per_dir = arg + 24;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--exclude-standard\")) {\n-\t\t\texc_given = 1;\n-\t\t\tsetup_standard_excludes(&dir);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--full-name\")) {\n-\t\t\tprefix_offset = 0;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--error-unmatch\")) {\n-\t\t\terror_unmatch = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--with-tree=\")) {\n-\t\t\twith_tree = arg + 12;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--abbrev=\")) {\n-\t\t\tabbrev = strtoul(arg+9, NULL, 10);\n-\t\t\tif (abbrev && abbrev < MINIMUM_ABBREV)\n-\t\t\t\tabbrev = MINIMUM_ABBREV;\n-\t\t\telse if (abbrev > 40)\n-\t\t\t\tabbrev = 40;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--abbrev\")) {\n-\t\t\tabbrev = DEFAULT_ABBREV;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (*arg == '-')\n-\t\t\tusage(ls_files_usage);\n-\t\tbreak;\n+\targc = parse_options(argc, argv, builtin_ls_files_options,\n+\t\t\tls_files_usage, 0);\n+\tif (show_tag || show_valid_bit) {\n+\t\ttag_cached = \"H \";\n+\t\ttag_unmerged = \"M \";\n+\t\ttag_removed = \"R \";\n+\t\ttag_modified = \"C \";\n+\t\ttag_other = \"? \";\n+\t\ttag_killed = \"K \";\n \t}\n+\tif (show_modified || show_others || dir.show_ignored || show_killed)\n+\t\trequire_work_tree = 1;\n+\tif (show_unmerged)\n+\t\t/* There's no point in showing unmerged unless\n+\t\t * you also show the stage information.\n+\t\t */\n+\t\tshow_stage = 1;\n+\tif (dir.exclude_per_dir)\n+\t\texc_given = 1;\n \n \tif (require_work_tree && !is_inside_work_tree())\n \t\tsetup_work_tree();\n \n-\tpathspec = get_pathspec(prefix, argv + i);\n+\tpathspec = get_pathspec(prefix, argv);\n \n \t/* be nice with submodule patsh ending in a slash */\n \tread_cache();\n-- \n1.6.1.3\n"},{"id":"104819","messageId":"alpine.DEB.1.00.0902152108370.10279@pacific.mpi-cbg.de","threadId":"16999","inReplyTo":"1234727647-18523-1-git-send-email-vmiklos@frugalware.org","subject":"Re: [PATCH] parse-opt: migrate builtin-ls-files.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-02-15T20:13:42Z","receivedAt":"2009-02-15T20:13:42Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 15 Feb 2009, Miklos Vajna wrote:\n\n> On Sat, Feb 14, 2009 at 09:56:04PM +0100, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> >\n> > On Thu, 8 Jan 2009, Miklos Vajna wrote:\n> >\n> > > +static int option_parse_ignored(const struct option *opt,\n> > > +                           const char *arg, int unset)\n> > > +{\n> > > +   struct dir_struct *dir = opt->value;\n> > > +\n> > > +   dir->show_ignored = !unset;\n> > > +\n> > > +   return 0;\n> > > +}\n> >\n> > Maybe this wants to be converted into an OPTION_BIT compatible data \n> > type?\n> \n> I think that's not possible, as show_ignored is a bitfield.\n\nWell, in my juvenile folly I dreamt of turning this into a proper \nbitfield...\n\nCiao,\nDscho\n"},{"id":"104832","messageId":"20090215220706.GB4371@genesis.frugalware.org","threadId":"16999","inReplyTo":"alpine.DEB.1.00.0902152108370.10279@pacific.mpi-cbg.de","subject":"Re: [PATCH] parse-opt: migrate builtin-ls-files.","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2009-02-15T22:07:06Z","receivedAt":"2009-02-15T22:07:06Z","isPatch":true,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"On Sun, Feb 15, 2009 at 09:13:42PM +0100, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> > > > +   dir->show_ignored = !unset;\n> > > > +\n> > > > +   return 0;\n> > > > +}\n> > >\n> > > Maybe this wants to be converted into an OPTION_BIT compatible data \n> > > type?\n> > \n> > I think that's not possible, as show_ignored is a bitfield.\n> \n> Well, in my juvenile folly I dreamt of turning this into a proper \n> bitfield...\n\nUhm, I think I haven't got what you mean. ;-)\n\nPersonally I would just remove all problematic bitfields in struct\ndir_struct as I think it does not worth using them, but getting rid of\nthem just because of parseopt sounds insane as well - so I sended up\nwriting callback functions, as you saw in the patch.\n"},{"id":"104940","messageId":"alpine.DEB.1.00.0902161317570.10279@pacific.mpi-cbg.de","threadId":"16999","inReplyTo":"20090215220706.GB4371@genesis.frugalware.org","subject":"[PATCH] Turn the flags in struct dir_struct into a single variable","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-02-16T12:20:25Z","receivedAt":"2009-02-16T12:20:25Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"By having flags represented as bits in the new member variable 'flags',\nit will be easier to use parse_options when dir_struct is involved.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\tOn Sun, 15 Feb 2009, Miklos Vajna wrote:\n\n\t> On Sun, Feb 15, 2009 at 09:13:42PM +0100, Johannes Schindelin\n\t> <Johannes.Schindelin@gmx.de> wrote:\n\t>\n\t> > Well, in my juvenile folly I dreamt of turning this into a proper \n\t> > bitfield...\n\t> \n\t> Uhm, I think I haven't got what you mean. ;-)\n\n\tI meant this...\n\n builtin-add.c       |    2 +-\n builtin-checkout.c  |    2 +-\n builtin-clean.c     |    4 ++--\n builtin-ls-files.c  |   14 ++++++++------\n builtin-merge.c     |    2 +-\n builtin-read-tree.c |    2 +-\n dir.c               |   17 +++++++++--------\n dir.h               |   12 +++++++-----\n wt-status.c         |    7 +++----\n 9 files changed, 33 insertions(+), 29 deletions(-)\n\ndiff --git a/builtin-add.c b/builtin-add.c\nindex 7a5a8c7..f2066a1 100644\n--- a/builtin-add.c\n+++ b/builtin-add.c\n@@ -106,7 +106,7 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec,\n \t/* Set up the default git porcelain excludes */\n \tmemset(dir, 0, sizeof(*dir));\n \tif (!ignored_too) {\n-\t\tdir->collect_ignored = 1;\n+\t\tdir->flags |= DIR_COLLECT_IGNORED;\n \t\tsetup_standard_excludes(dir);\n \t}\n \ndiff --git a/builtin-checkout.c b/builtin-checkout.c\nindex 20b34ce..5b4921d 100644\n--- a/builtin-checkout.c\n+++ b/builtin-checkout.c\n@@ -405,7 +405,7 @@ static int merge_working_tree(struct checkout_opts *opts,\n \t\ttopts.verbose_update = !opts->quiet;\n \t\ttopts.fn = twoway_merge;\n \t\ttopts.dir = xcalloc(1, sizeof(*topts.dir));\n-\t\ttopts.dir->show_ignored = 1;\n+\t\ttopts.dir->flags |= DIR_SHOW_IGNORED;\n \t\ttopts.dir->exclude_per_dir = \".gitignore\";\n \t\ttree = parse_tree_indirect(old->commit->object.sha1);\n \t\tinit_tree_desc(&trees[0], tree->buffer, tree->size);\ndiff --git a/builtin-clean.c b/builtin-clean.c\nindex f78c2fb..c5ad33d 100644\n--- a/builtin-clean.c\n+++ b/builtin-clean.c\n@@ -60,7 +60,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)\n \n \tmemset(&dir, 0, sizeof(dir));\n \tif (ignored_only)\n-\t\tdir.show_ignored = 1;\n+\t\tdir.flags |= DIR_SHOW_IGNORED;\n \n \tif (ignored && ignored_only)\n \t\tdie(\"-x and -X cannot be used together\");\n@@ -69,7 +69,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)\n \t\tdie(\"clean.requireForce%s set and -n or -f not given; \"\n \t\t    \"refusing to clean\", config_set ? \"\" : \" not\");\n \n-\tdir.show_other_directories = 1;\n+\tdir.flags |= DIR_SHOW_OTHER_DIRECTORIES;\n \n \tif (!ignored)\n \t\tsetup_standard_excludes(&dir);\ndiff --git a/builtin-ls-files.c b/builtin-ls-files.c\nindex 15f4e97..beb66b7 100644\n--- a/builtin-ls-files.c\n+++ b/builtin-ls-files.c\n@@ -179,7 +179,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)\n \t\tfor (i = 0; i < active_nr; i++) {\n \t\t\tstruct cache_entry *ce = active_cache[i];\n \t\t\tint dtype = ce_to_dtype(ce);\n-\t\t\tif (excluded(dir, ce->name, &dtype) != dir->show_ignored)\n+\t\t\tif (excluded(dir, ce->name, &dtype) !=\n+\t\t\t\t\t!!(dir->flags & DIR_SHOW_IGNORED))\n \t\t\t\tcontinue;\n \t\t\tif (show_unmerged && !ce_stage(ce))\n \t\t\t\tcontinue;\n@@ -194,7 +195,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)\n \t\t\tstruct stat st;\n \t\t\tint err;\n \t\t\tint dtype = ce_to_dtype(ce);\n-\t\t\tif (excluded(dir, ce->name, &dtype) != dir->show_ignored)\n+\t\t\tif (excluded(dir, ce->name, &dtype) !=\n+\t\t\t\t\t!!(dir->flags & DIR_SHOW_IGNORED))\n \t\t\t\tcontinue;\n \t\t\tif (ce->ce_flags & CE_UPDATE)\n \t\t\t\tcontinue;\n@@ -437,7 +439,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)\n \t\t\tcontinue;\n \t\t}\n \t\tif (!strcmp(arg, \"-i\") || !strcmp(arg, \"--ignored\")) {\n-\t\t\tdir.show_ignored = 1;\n+\t\t\tdir.flags |= DIR_SHOW_IGNORED;\n \t\t\trequire_work_tree = 1;\n \t\t\tcontinue;\n \t\t}\n@@ -455,11 +457,11 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)\n \t\t\tcontinue;\n \t\t}\n \t\tif (!strcmp(arg, \"--directory\")) {\n-\t\t\tdir.show_other_directories = 1;\n+\t\t\tdir.flags |= DIR_SHOW_OTHER_DIRECTORIES;\n \t\t\tcontinue;\n \t\t}\n \t\tif (!strcmp(arg, \"--no-empty-directory\")) {\n-\t\t\tdir.hide_empty_directories = 1;\n+\t\t\tdir.flags |= DIR_HIDE_EMPTY_DIRECTORIES;\n \t\t\tcontinue;\n \t\t}\n \t\tif (!strcmp(arg, \"-u\") || !strcmp(arg, \"--unmerged\")) {\n@@ -551,7 +553,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)\n \t\tps_matched = xcalloc(1, num);\n \t}\n \n-\tif (dir.show_ignored && !exc_given) {\n+\tif ((dir.flags & DIR_SHOW_IGNORED) && !exc_given) {\n \t\tfprintf(stderr, \"%s: --ignored needs some exclude pattern\\n\",\n \t\t\targv[0]);\n \t\texit(1);\ndiff --git a/builtin-merge.c b/builtin-merge.c\nindex 6d2160d..4c11935 100644\n--- a/builtin-merge.c\n+++ b/builtin-merge.c\n@@ -636,7 +636,7 @@ static int checkout_fast_forward(unsigned char *head, unsigned char *remote)\n \tmemset(&opts, 0, sizeof(opts));\n \tmemset(&t, 0, sizeof(t));\n \tmemset(&dir, 0, sizeof(dir));\n-\tdir.show_ignored = 1;\n+\tdir.flags |= DIR_SHOW_IGNORED;\n \tdir.exclude_per_dir = \".gitignore\";\n \topts.dir = &dir;\n \ndiff --git a/builtin-read-tree.c b/builtin-read-tree.c\nindex 38fef34..8e02738 100644\n--- a/builtin-read-tree.c\n+++ b/builtin-read-tree.c\n@@ -170,7 +170,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n \t\t\t\tdie(\"more than one --exclude-per-directory are given.\");\n \n \t\t\tdir = xcalloc(1, sizeof(*opts.dir));\n-\t\t\tdir->show_ignored = 1;\n+\t\t\tdir->flags |= DIR_SHOW_IGNORED;\n \t\t\tdir->exclude_per_dir = arg + 24;\n \t\t\topts.dir = dir;\n \t\t\t/* We do not need to nor want to do read-directory\ndiff --git a/dir.c b/dir.c\nindex b9230c4..56e386b 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -487,14 +487,14 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,\n \t\treturn recurse_into_directory;\n \n \tcase index_gitdir:\n-\t\tif (dir->show_other_directories)\n+\t\tif (dir->flags & DIR_SHOW_OTHER_DIRECTORIES)\n \t\t\treturn ignore_directory;\n \t\treturn show_directory;\n \n \tcase index_nonexistent:\n-\t\tif (dir->show_other_directories)\n+\t\tif (dir->flags & DIR_SHOW_OTHER_DIRECTORIES)\n \t\t\tbreak;\n-\t\tif (!dir->no_gitlinks) {\n+\t\tif (!(dir->flags & DIR_NO_GITLINKS)) {\n \t\t\tunsigned char sha1[20];\n \t\t\tif (resolve_gitlink_ref(dirname, \"HEAD\", sha1) == 0)\n \t\t\t\treturn show_directory;\n@@ -503,7 +503,7 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,\n \t}\n \n \t/* This is the \"show_other_directories\" case */\n-\tif (!dir->hide_empty_directories)\n+\tif (!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))\n \t\treturn show_directory;\n \tif (!read_directory_recursive(dir, dirname, dirname, len, 1, simplify))\n \t\treturn ignore_directory;\n@@ -601,7 +601,7 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co\n \n \t\t\tdtype = DTYPE(de);\n \t\t\texclude = excluded(dir, fullname, &dtype);\n-\t\t\tif (exclude && dir->collect_ignored\n+\t\t\tif (exclude && (dir->flags & DIR_COLLECT_IGNORED)\n \t\t\t    && in_pathspec(fullname, baselen + len, simplify))\n \t\t\t\tdir_add_ignored(dir, fullname, baselen + len);\n \n@@ -609,7 +609,7 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co\n \t\t\t * Excluded? If we don't explicitly want to show\n \t\t\t * ignored files, ignore it\n \t\t\t */\n-\t\t\tif (exclude && !dir->show_ignored)\n+\t\t\tif (exclude && !(dir->flags & DIR_SHOW_IGNORED))\n \t\t\t\tcontinue;\n \n \t\t\tif (dtype == DT_UNKNOWN)\n@@ -621,7 +621,7 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co\n \t\t\t * even if we don't ignore them, since the\n \t\t\t * directory may contain files that we do..\n \t\t\t */\n-\t\t\tif (!exclude && dir->show_ignored) {\n+\t\t\tif (!exclude && (dir->flags & DIR_SHOW_IGNORED)) {\n \t\t\t\tif (dtype != DT_DIR)\n \t\t\t\t\tcontinue;\n \t\t\t}\n@@ -634,7 +634,8 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co\n \t\t\t\tlen++;\n \t\t\t\tswitch (treat_directory(dir, fullname, baselen + len, simplify)) {\n \t\t\t\tcase show_directory:\n-\t\t\t\t\tif (exclude != dir->show_ignored)\n+\t\t\t\t\tif (exclude != !!(dir->flags\n+\t\t\t\t\t\t\t& DIR_SHOW_IGNORED))\n \t\t\t\t\t\tcontinue;\n \t\t\t\t\tbreak;\n \t\t\t\tcase recurse_into_directory:\ndiff --git a/dir.h b/dir.h\nindex 8009877..811e865 100644\n--- a/dir.h\n+++ b/dir.h\n@@ -34,11 +34,13 @@ struct exclude_stack {\n struct dir_struct {\n \tint nr, alloc;\n \tint ignored_nr, ignored_alloc;\n-\tunsigned int show_ignored:1,\n-\t\t     show_other_directories:1,\n-\t\t     hide_empty_directories:1,\n-\t\t     no_gitlinks:1,\n-\t\t     collect_ignored:1;\n+\tenum {\n+\t\tDIR_SHOW_IGNORED = 1<<0,\n+\t\tDIR_SHOW_OTHER_DIRECTORIES = 1<<1,\n+\t\tDIR_HIDE_EMPTY_DIRECTORIES = 1<<2,\n+\t\tDIR_NO_GITLINKS = 1<<3,\n+\t\tDIR_COLLECT_IGNORED = 1<<4\n+\t} flags;\n \tstruct dir_entry **entries;\n \tstruct dir_entry **ignored;\n \ndiff --git a/wt-status.c b/wt-status.c\nindex 96ff2f8..f2eae20 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -250,10 +250,9 @@ static void wt_status_print_untracked(struct wt_status *s)\n \n \tmemset(&dir, 0, sizeof(dir));\n \n-\tif (!s->untracked) {\n-\t\tdir.show_other_directories = 1;\n-\t\tdir.hide_empty_directories = 1;\n-\t}\n+\tif (!s->untracked)\n+\t\tdir.flags |=\n+\t\t\tDIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;\n \tsetup_standard_excludes(&dir);\n \n \tread_directory(&dir, \".\", \"\", 0, NULL);\n-- \n1.6.2.rc0.392.g7c2ec\n"},{"id":"105015","messageId":"20090216214756.GG4371@genesis.frugalware.org","threadId":"16999","inReplyTo":"alpine.DEB.1.00.0902161317570.10279@pacific.mpi-cbg.de","subject":"Re: [PATCH] Turn the flags in struct dir_struct into a single variable","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2009-02-16T21:47:56Z","receivedAt":"2009-02-16T21:47:56Z","isPatch":true,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"On Mon, Feb 16, 2009 at 01:20:25PM +0100, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> By having flags represented as bits in the new member variable 'flags',\n> it will be easier to use parse_options when dir_struct is involved.\n> \n> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n> ---\n> \n> \tOn Sun, 15 Feb 2009, Miklos Vajna wrote:\n> \n> \t> On Sun, Feb 15, 2009 at 09:13:42PM +0100, Johannes Schindelin\n> \t> <Johannes.Schindelin@gmx.de> wrote:\n> \t>\n> \t> > Well, in my juvenile folly I dreamt of turning this into a proper \n> \t> > bitfield...\n> \t> \n> \t> Uhm, I think I haven't got what you mean. ;-)\n> \n> \tI meant this...\n\nAah. That definitely makes the parseopt code shorter, thanks. :-)\n"},{"id":"105154","messageId":"20090217142711.GT4371@genesis.frugalware.org","threadId":"16999","inReplyTo":"alpine.DEB.1.00.0902161317570.10279@pacific.mpi-cbg.de","subject":"[PATCH] parse-opt: migrate builtin-ls-files.","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2009-02-17T14:27:11Z","receivedAt":"2009-02-17T14:27:11Z","isPatch":true,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>\n---\n builtin-ls-files.c |  255 ++++++++++++++++++++++++---------------------------\n 1 files changed, 120 insertions(+), 135 deletions(-)\n\nOn Mon, Feb 16, 2009 at 01:20:25PM +0100, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> \tI meant this...\n\nAnd here is my patch on top of this one.\ndiff --git a/builtin-ls-files.c b/builtin-ls-files.c\nindex d36f80b..1742c0f 100644\n--- a/builtin-ls-files.c\n+++ b/builtin-ls-files.c\n@@ -10,6 +10,7 @@\n #include \"dir.h\"\n #include \"builtin.h\"\n #include \"tree.h\"\n+#include \"parse-options.h\"\n \n static int abbrev;\n static int show_deleted;\n@@ -28,6 +29,7 @@ static const char **pathspec;\n static int error_unmatch;\n static char *ps_matched;\n static const char *with_tree;\n+static int exc_given;\n \n static const char *tag_cached = \"\";\n static const char *tag_unmerged = \"\";\n@@ -376,156 +378,139 @@ int report_path_error(const char *ps_matched, const char **pathspec, int prefix_\n \treturn errors;\n }\n \n-static const char ls_files_usage[] =\n-\t\"git ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* \"\n-\t\"[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] \"\n-\t\"[ --exclude-per-directory=<filename> ] [--exclude-standard] \"\n-\t\"[--full-name] [--abbrev] [--] [<file>]*\";\n+static const char * const ls_files_usage[] = {\n+\t\"git ls-files [options] [<file>]*\",\n+\tNULL\n+};\n+\n+static int option_parse_z(const struct option *opt,\n+\t\t\t  const char *arg, int unset)\n+{\n+\tline_terminator = unset ? '\\n' : '\\0';\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_exclude(const struct option *opt,\n+\t\t\t\tconst char *arg, int unset)\n+{\n+\tstruct exclude_list *list = opt->value;\n+\n+\texc_given = 1;\n+\tadd_exclude(arg, \"\", 0, list);\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_exclude_from(const struct option *opt,\n+\t\t\t\t     const char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\texc_given = 1;\n+\tadd_excludes_from_file(dir, arg);\n+\n+\treturn 0;\n+}\n+\n+static int option_parse_exclude_standard(const struct option *opt,\n+\t\t\t\t\t const char *arg, int unset)\n+{\n+\tstruct dir_struct *dir = opt->value;\n+\n+\texc_given = 1;\n+\tsetup_standard_excludes(dir);\n+\n+\treturn 0;\n+}\n \n int cmd_ls_files(int argc, const char **argv, const char *prefix)\n {\n-\tint i;\n-\tint exc_given = 0, require_work_tree = 0;\n+\tint require_work_tree = 0, show_tag = 0;\n \tstruct dir_struct dir;\n+\tstruct option builtin_ls_files_options[] = {\n+\t\t{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,\n+\t\t\t\"paths are separated with NUL character\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_z },\n+\t\tOPT_BOOLEAN('t', NULL, &show_tag,\n+\t\t\t\"identify the file status with tags\"),\n+\t\tOPT_BOOLEAN('v', NULL, &show_valid_bit,\n+\t\t\t\"use lowercase letters for 'assume unchanged' files\"),\n+\t\tOPT_BOOLEAN('c', \"cached\", &show_cached,\n+\t\t\t\"show cached files in the output (default)\"),\n+\t\tOPT_BOOLEAN('d', \"deleted\", &show_deleted,\n+\t\t\t\"show deleted files in the output\"),\n+\t\tOPT_BOOLEAN('m', \"modified\", &show_modified,\n+\t\t\t\"show modified files in the output\"),\n+\t\tOPT_BOOLEAN('o', \"others\", &show_others,\n+\t\t\t\"show other files in the output\"),\n+\t\tOPT_BIT('i', \"ignored\", &dir.flags,\n+\t\t\t\"show ignored files in the output\",\n+\t\t\tDIR_SHOW_IGNORED),\n+\t\tOPT_BOOLEAN('s', \"stage\", &show_stage,\n+\t\t\t\"show staged contents' object name in the output\"),\n+\t\tOPT_BOOLEAN('k', \"killed\", &show_killed,\n+\t\t\t\"show files on the filesystem that need to be removed\"),\n+\t\tOPT_BIT(0, \"directory\", &dir.flags,\n+\t\t\t\"show 'other' directories' name only\",\n+\t\t\tDIR_SHOW_OTHER_DIRECTORIES),\n+\t\tOPT_BIT(0, \"empty-directory\", &dir.flags,\n+\t\t\t\"list empty directories\",\n+\t\t\tDIR_HIDE_EMPTY_DIRECTORIES),\n+\t\tOPT_BOOLEAN('u', \"unmerged\", &show_unmerged,\n+\t\t\t\"show unmerged files in the output\"),\n+\t\t{ OPTION_CALLBACK, 'x', \"exclude\", &dir.exclude_list[EXC_CMDL], \"pattern\",\n+\t\t\t\"skip files matching pattern\",\n+\t\t\t0, option_parse_exclude },\n+\t\t{ OPTION_CALLBACK, 'X', \"exclude-from\", &dir, \"file\",\n+\t\t\t\"exclude patterns are read from <file>\",\n+\t\t\t0, option_parse_exclude_from },\n+\t\tOPT_STRING(0, \"exclude-per-directory\", &dir.exclude_per_dir, \"file\",\n+\t\t\t\"read additional per-directory exclude patterns in <file>\"),\n+\t\t{ OPTION_CALLBACK, 0, \"exclude-standard\", &dir, NULL,\n+\t\t\t\"add the standard git exclusions\",\n+\t\t\tPARSE_OPT_NOARG, option_parse_exclude_standard },\n+\t\t{ OPTION_SET_INT, 0, \"full-name\", &prefix_offset, NULL,\n+\t\t\t\"make the output relative to the project top directory\",\n+\t\t\tPARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL },\n+\t\tOPT_BOOLEAN(0, \"error-unmatch\", &error_unmatch,\n+\t\t\t\"if any <file> is not in the index, treat this as an error\"),\n+\t\tOPT_STRING(0, \"with-tree\", &with_tree, \"tree-ish\",\n+\t\t\t\"pretend that paths removed since <tree-ish> are still present\"),\n+\t\tOPT__ABBREV(&abbrev),\n+\t\tOPT_END()\n+\t};\n \n \tmemset(&dir, 0, sizeof(dir));\n \tif (prefix)\n \t\tprefix_offset = strlen(prefix);\n \tgit_config(git_default_config, NULL);\n \n-\tfor (i = 1; i < argc; i++) {\n-\t\tconst char *arg = argv[i];\n-\n-\t\tif (!strcmp(arg, \"--\")) {\n-\t\t\ti++;\n-\t\t\tbreak;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-z\")) {\n-\t\t\tline_terminator = 0;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-t\") || !strcmp(arg, \"-v\")) {\n-\t\t\ttag_cached = \"H \";\n-\t\t\ttag_unmerged = \"M \";\n-\t\t\ttag_removed = \"R \";\n-\t\t\ttag_modified = \"C \";\n-\t\t\ttag_other = \"? \";\n-\t\t\ttag_killed = \"K \";\n-\t\t\tif (arg[1] == 'v')\n-\t\t\t\tshow_valid_bit = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-c\") || !strcmp(arg, \"--cached\")) {\n-\t\t\tshow_cached = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-d\") || !strcmp(arg, \"--deleted\")) {\n-\t\t\tshow_deleted = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-m\") || !strcmp(arg, \"--modified\")) {\n-\t\t\tshow_modified = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-o\") || !strcmp(arg, \"--others\")) {\n-\t\t\tshow_others = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-i\") || !strcmp(arg, \"--ignored\")) {\n-\t\t\tdir.flags |= DIR_SHOW_IGNORED;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-s\") || !strcmp(arg, \"--stage\")) {\n-\t\t\tshow_stage = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-k\") || !strcmp(arg, \"--killed\")) {\n-\t\t\tshow_killed = 1;\n-\t\t\trequire_work_tree = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--directory\")) {\n-\t\t\tdir.flags |= DIR_SHOW_OTHER_DIRECTORIES;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--no-empty-directory\")) {\n-\t\t\tdir.flags |= DIR_HIDE_EMPTY_DIRECTORIES;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-u\") || !strcmp(arg, \"--unmerged\")) {\n-\t\t\t/* There's no point in showing unmerged unless\n-\t\t\t * you also show the stage information.\n-\t\t\t */\n-\t\t\tshow_stage = 1;\n-\t\t\tshow_unmerged = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-x\") && i+1 < argc) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_exclude(argv[++i], \"\", 0, &dir.exclude_list[EXC_CMDL]);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--exclude=\")) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_exclude(arg+10, \"\", 0, &dir.exclude_list[EXC_CMDL]);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-X\") && i+1 < argc) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_excludes_from_file(&dir, argv[++i]);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--exclude-from=\")) {\n-\t\t\texc_given = 1;\n-\t\t\tadd_excludes_from_file(&dir, arg+15);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--exclude-per-directory=\")) {\n-\t\t\texc_given = 1;\n-\t\t\tdir.exclude_per_dir = arg + 24;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--exclude-standard\")) {\n-\t\t\texc_given = 1;\n-\t\t\tsetup_standard_excludes(&dir);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--full-name\")) {\n-\t\t\tprefix_offset = 0;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--error-unmatch\")) {\n-\t\t\terror_unmatch = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--with-tree=\")) {\n-\t\t\twith_tree = arg + 12;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--abbrev=\")) {\n-\t\t\tabbrev = strtoul(arg+9, NULL, 10);\n-\t\t\tif (abbrev && abbrev < MINIMUM_ABBREV)\n-\t\t\t\tabbrev = MINIMUM_ABBREV;\n-\t\t\telse if (abbrev > 40)\n-\t\t\t\tabbrev = 40;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--abbrev\")) {\n-\t\t\tabbrev = DEFAULT_ABBREV;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (*arg == '-')\n-\t\t\tusage(ls_files_usage);\n-\t\tbreak;\n+\targc = parse_options(argc, argv, builtin_ls_files_options,\n+\t\t\tls_files_usage, 0);\n+\tif (show_tag || show_valid_bit) {\n+\t\ttag_cached = \"H \";\n+\t\ttag_unmerged = \"M \";\n+\t\ttag_removed = \"R \";\n+\t\ttag_modified = \"C \";\n+\t\ttag_other = \"? \";\n+\t\ttag_killed = \"K \";\n \t}\n+\tif (show_modified || show_others || (dir.flags & DIR_SHOW_IGNORED) || show_killed)\n+\t\trequire_work_tree = 1;\n+\tif (show_unmerged)\n+\t\t/*\n+\t\t * There's no point in showing unmerged unless\n+\t\t * you also show the stage information.\n+\t\t */\n+\t\tshow_stage = 1;\n+\tif (dir.exclude_per_dir)\n+\t\texc_given = 1;\n \n \tif (require_work_tree && !is_inside_work_tree())\n \t\tsetup_work_tree();\n \n-\tpathspec = get_pathspec(prefix, argv + i);\n+\tpathspec = get_pathspec(prefix, argv);\n \n \t/* be nice with submodule patsh ending in a slash */\n \tread_cache();\n-- \n1.6.1\n"}]}