{"thread":{"id":"686","subject":"[PATCH 3/3] - Convert git-checkout-cache to argp","startedAt":"2005-05-21T18:33:28Z","lastAt":"2005-05-21T21:39:31Z","messageCount":5,"participants":["Sean","Junio C Hamano","Jeff Garzik"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"3708","messageId":"2242.10.10.10.24.1116700408.squirrel@linux1","threadId":"686","inReplyTo":null,"subject":"[PATCH 3/3] - Convert git-checkout-cache to argp","fromName":"Sean","fromEmail":"seanlkml@sympatico.ca","sentAt":"2005-05-21T18:33:28Z","receivedAt":"2005-05-21T18:33:28Z","isPatch":true,"sender":{"key":"seanlkml@sympatico.ca","avatar":"https://gravatar.com/avatar/f92923f54fc08c401fc59b71829d4b89e9b8087fbba45ff87c82e6a83aee02ae?d=mp&s=160"},"body":"\nUse argp to process command line arguments for git-checkout-cache.  Also,\nfix things up so that the order of options on the command line no longer\nmatters.  To this end, the \"-f\" (--force) switch only applies to the\nindividual files given on the command line.   A new forcing version of the\n\"-a\" (--all) switch is added as \"-A\" (--forceall).\n\nSigned-off-by: Sean Estabrooks <seanlkml@sympatico.ca>\n\n\n Documentation/git-checkout-cache.txt |   17 +++--\n checkout-cache.c                     |  113\n+++++++++++++++++------------------\n 2 files changed, 68 insertions(+), 62 deletions(-)\n\n\n\n\nIndex: checkout-cache.c\n===================================================================\n--- 4708925e3e3b955ffcb417fc4acdbb0aafdf8dc0/checkout-cache.c  (mode:100644)\n+++ uncommitted/checkout-cache.c  (mode:100644)\n@@ -3,8 +3,6 @@\n  *\n  * Copyright (C) 2005 Linus Torvalds\n  *\n- * Careful: order of argument flags does matter. For example,\n- *\n  *\tgit-checkout-cache -a -f file.c\n  *\n  * Will first check out all files listed in the cache (but not\n@@ -14,7 +12,7 @@\n  *\n  * Also, just doing \"git-checkout-cache\" does nothing. You probably\n  * meant \"git-checkout-cache -a\". And if you want to force it, you\n- * want \"git-checkout-cache -f -a\".\n+ * want \"git-checkout-cache -A\".\n  *\n  * Intuitiveness is not the goal here. Repeatability is. The\n  * reason for the \"no arguments means no work\" thing is that\n@@ -25,7 +23,7 @@\n  * which will force all existing *.h files to be replaced with\n  * their cached copies. If an empty command line implied \"all\",\n  * then this would force-refresh everything in the cache, which\n- * was not the point.\n+ * was not the point.  However, please note the -r option of xargs.\n  *\n  * Oh, and the \"--\" is just a good idea when you know the rest\n  * will be filenames. Just so that you wouldn't have a filename\n@@ -35,8 +33,12 @@\n #include <sys/types.h>\n #include <dirent.h>\n #include \"cache.h\"\n+#include <argp.h>\n+const char *argp_program_version = VERSION;\n \n static int force = 0, quiet = 0, not_new = 0, refresh_cache = 0;\n+static int force_opt = 0, force_all = 0, all = 0;\n+static const char *base_opt = \"\";\n \n static void create_directories(const char *path)\n {\n@@ -226,68 +228,67 @@\n \treturn 0;\n }\n \n+static const char doc[] = \"Populate working tree with files from cache\";\n+\n+static struct argp_option options[] = {\n+ {\"prefix\", 1, \"base\", 0, \"Prepend base to each file before checkout\"},\n+ {\"all\", 'a', 0, 0, \"Checkout entire cache, will NOT overwrite\"},\n+ {\"forceall\", 'A', 0, 0, \"Checkout entire cache, with overwrite\"},\n+ {\"force\", 'f', 0, 0, \"Checkout files listed on command line, with overwrite\"},\n+ {\"quiet\", 'q', 0, 0, \"Suppress warnings\"},\n+ {\"not-new\", 'n', 0, 0, \"Checkout existing files only\"},\n+ {\"update\", 'u', 0, 0, \"Update cache with new stat info\"},\n+ { }\n+};\n+\n+static error_t parse_opt (int key, char *arg, struct argp_state *state)\n+{\n+        switch (key) {\n+        case 'a':\t\tall = 1; break;\n+        case 'q':\t\tquiet = 1; break;\n+        case 'n':\t\tnot_new = 1; break;\n+        case 'f':\t\tforce_opt = 1; break;\n+        case   1:\t\tbase_opt = arg; break;\n+        case 'u':\t\trefresh_cache = 1; break;\n+        case 'A':\t\tforce_all = 1; all = 1; break;\n+        default:\t\treturn ARGP_ERR_UNKNOWN;\n+        }\n+        return 0;\n+}\n+\n+static const struct argp argp = { options, parse_opt, \"[FILES...]\", doc };\n+\n int main(int argc, char **argv)\n {\n-\tint i, force_filename = 0;\n-\tconst char *base_dir = \"\";\n \tstruct cache_file cache_file;\n-\tint newfd = -1;\n+\tint i, idx, newfd = -1;\n \n \tif (read_cache() < 0) {\n \t\tdie(\"invalid cache\");\n \t}\n \n-\tfor (i = 1; i < argc; i++) {\n-\t\tconst char *arg = argv[i];\n-\t\tif (!force_filename) {\n-\t\t\tif (!strcmp(arg, \"-a\")) {\n-\t\t\t\tcheckout_all(base_dir);\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(arg, \"--\")) {\n-\t\t\t\tforce_filename = 1;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(arg, \"-f\")) {\n-\t\t\t\tforce = 1;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(arg, \"-q\")) {\n-\t\t\t\tquiet = 1;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(arg, \"-n\")) {\n-\t\t\t\tnot_new = 1;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(arg, \"-u\")) {\n-\t\t\t\trefresh_cache = 1;\n-\t\t\t\tif (newfd < 0)\n-\t\t\t\t\tnewfd = hold_index_file_for_update\n-\t\t\t\t\t\t(&cache_file,\n-\t\t\t\t\t\t get_index_file());\n-\t\t\t\tif (newfd < 0)\n-\t\t\t\t\tdie(\"cannot open index.lock file.\");\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!memcmp(arg, \"--prefix=\", 9)) {\n-\t\t\t\tbase_dir = arg+9;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t}\n-\t\tif (base_dir[0]) {\n-\t\t\t/* when --prefix is specified we do not\n-\t\t\t * want to update cache.\n-\t\t\t */\n-\t\t\tif (refresh_cache) {\n-\t\t\t\tclose(newfd); newfd = -1;\n-\t\t\t\trollback_index_file(&cache_file);\n-\t\t\t}\n-\t\t\trefresh_cache = 0;\n-\t\t}\n-\t\tcheckout_file(arg, base_dir);\n+\terror_t rc = argp_parse(&argp, argc, argv, 0, &idx, NULL);\n+\tif (rc) {\n+\t\tfprintf(stderr, \"argument failed: %s\\n\", strerror(rc));\n+\t\treturn 1;\n \t}\n \n+\tif (refresh_cache) {\n+\t\tif (base_opt[0])\n+\t\t\tdie(\"cannot update cache when --prefix option is used\");\n+\t\tnewfd = hold_index_file_for_update(&cache_file, get_index_file());\n+\t\tif (newfd < 0)\n+\t\t\tdie(\"cannot open index.lock file.\");\n+\t}\n+\n+\tforce = force_all;\n+\tif (all)\n+\t\tcheckout_all(base_opt); \n+\n+\tforce = force_opt;\n+\tfor (i = idx; i < argc; i++) \n+\t\tcheckout_file(argv[i], base_opt);\n+\n \tif (0 <= newfd &&\n \t    (write_cache(newfd, active_cache, active_nr) ||\n \t     commit_index_file(&cache_file)))\nIndex: Documentation/git-checkout-cache.txt\n===================================================================\n--- 4708925e3e3b955ffcb417fc4acdbb0aafdf8dc0/Documentation/git-checkout-cache.txt  (mode:100644)\n+++ uncommitted/Documentation/git-checkout-cache.txt  (mode:100644)\n@@ -9,8 +9,8 @@\n \n SYNOPSIS\n --------\n-'git-checkout-cache' [-u] [-q] [-a] [-f] [-n] [--prefix=<string>]\n-\t           [--] <file>...\n+'git-checkout-cache' [-u] [-q] [-a] [-A] [-f] [-n] [--prefix=<string>]\n+\t           [--] [file]...\n \n DESCRIPTION\n -----------\n@@ -24,15 +24,20 @@\n \tthe cache file.\n \n -q::\n-\tbe quiet if files exist or are not in the cache\n+\tbe quiet if files exist or are not in the cache.\n \n -f::\n-\tforces overwrite of existing files\n+\tforces overwrite when checking out files listed on the\n+\tcommand line (does not apply to -a option).\n \n -a::\n \tchecks out all files in the cache (will then continue to\n \tprocess listed files).\n \n+-A::\n+\tchecks out all files in the cache, forces overwrite of \n+\texisting files.\n+\n -n::\n \tDon't checkout new files, only refresh files already checked\n \tout.\n@@ -44,7 +49,7 @@\n --::\n \tDo not interpret any more arguments as options.\n \n-Note that the order of the flags matters:\n+Example:\n \n      git-checkout-cache -a -f file.c\n \n@@ -54,7 +59,7 @@\n \n Also, just doing \"git-checkout-cache\" does nothing. You probably meant\n \"git-checkout-cache -a\". And if you want to force it, you want\n-\"git-checkout-cache -f -a\".\n+\"git-checkout-cache -A\".\n \n Intuitiveness is not the goal here. Repeatability is. The reason for\n the \"no arguments means no work\" thing is that from scripts you are\n"},{"id":"3715","messageId":"7voeb4gxnt.fsf@assigned-by-dhcp.cox.net","threadId":"686","inReplyTo":"2242.10.10.10.24.1116700408.squirrel@linux1","subject":"Re: [PATCH 3/3] - Convert git-checkout-cache to argp","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-21T19:57:10Z","receivedAt":"2005-05-21T19:57:10Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"S\" == Sean  <seanlkml@sympatico.ca> writes:\n\nS> Use argp to process command line arguments for git-checkout-cache.  Also,\nS> fix things up so that the order of options on the command line no longer\nS> matters.  To this end, the \"-f\" (--force) switch only applies to the\nS> individual files given on the command line.   A new forcing version of the\nS> \"-a\" (--all) switch is added as \"-A\" (--forceall).\n\nI do not like that change at all.  That would break existing\nscripts.\n\nWhy not just say --force forces checkout even when it is used\nwith -a?  I do not think anybody sane uses \"-a -f\" in their\nexisting scripts nor from the command line.\n\n\n\n"},{"id":"3719","messageId":"428FA5C3.6010900@pobox.com","threadId":"686","inReplyTo":"2242.10.10.10.24.1116700408.squirrel@linux1","subject":"Re: [PATCH 3/3] - Convert git-checkout-cache to argp","fromName":"Jeff Garzik","fromEmail":"jgarzik@pobox.com","sentAt":"2005-05-21T21:18:59Z","receivedAt":"2005-05-21T21:18:59Z","isPatch":true,"sender":{"key":"jgarzik@pobox.com","avatar":null},"body":"Sean wrote:\n> Use argp to process command line arguments for git-checkout-cache.  Also,\n> fix things up so that the order of options on the command line no longer\n> matters.  To this end, the \"-f\" (--force) switch only applies to the\n> individual files given on the command line.   A new forcing version of the\n> \"-a\" (--all) switch is added as \"-A\" (--forceall).\n\nI agree with Junio -- this patch breaks stuff.\n\n\tJeff\n\n\n\n"},{"id":"3720","messageId":"7v7jhsgtlg.fsf@assigned-by-dhcp.cox.net","threadId":"686","inReplyTo":"428FA5C3.6010900@pobox.com","subject":"Re: [PATCH 3/3] - Convert git-checkout-cache to argp","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-21T21:24:59Z","receivedAt":"2005-05-21T21:24:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"JG\" == Jeff Garzik <jgarzik@pobox.com> writes:\n\nJG> Sean wrote:\n>> Use argp to process command line arguments for git-checkout-cache.  Also,\n>> fix things up so that the order of options on the command line no longer\n>> matters.  To this end, the \"-f\" (--force) switch only applies to the\n>> individual files given on the command line.   A new forcing version of the\n>> \"-a\" (--all) switch is added as \"-A\" (--forceall).\n\nJG> I agree with Junio -- this patch breaks stuff.\n\nYes, and that is exactly why I wanted to see the documentation\nchanges first before the code.\n\n"},{"id":"3721","messageId":"2669.10.10.10.24.1116711571.squirrel@linux1","threadId":"686","inReplyTo":"7v7jhsgtlg.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 3/3] - Convert git-checkout-cache to argp","fromName":"Sean","fromEmail":"seanlkml@sympatico.ca","sentAt":"2005-05-21T21:39:31Z","receivedAt":"2005-05-21T21:39:31Z","isPatch":true,"sender":{"key":"seanlkml@sympatico.ca","avatar":"https://gravatar.com/avatar/f92923f54fc08c401fc59b71829d4b89e9b8087fbba45ff87c82e6a83aee02ae?d=mp&s=160"},"body":"On Sat, May 21, 2005 5:24 pm, Junio C Hamano said:\n>>>>>> \"JG\" == Jeff Garzik <jgarzik@pobox.com> writes:\n>\n> JG> Sean wrote:\n>>> Use argp to process command line arguments for git-checkout-cache.\n>>> Also,\n>>> fix things up so that the order of options on the command line no\n>>> longer\n>>> matters.  To this end, the \"-f\" (--force) switch only applies to the\n>>> individual files given on the command line.   A new forcing version of\n>>> the\n>>> \"-a\" (--all) switch is added as \"-A\" (--forceall).\n>\n> JG> I agree with Junio -- this patch breaks stuff.\n>\n> Yes, and that is exactly why I wanted to see the documentation\n> changes first before the code.\n>\n\nOkay.  Attached no longer tries to maintain the feature of unforced -a in\ncombination with forced file list.  So:\n\n\nUse argp to process command line arguments for git-checkout-cache.  Also,\nfix things up so that the order of options on the command line no longer\nmatters.  To this end, the \"-f\" (--force) option always affects the -a\n(--all) option no matter where it appears on the command line.\n\nSigned-off-by: Sean Estabrooks <seanlkml@sympatico.ca>\n\n\n Documentation/git-checkout-cache.txt |   16 ++--\n checkout-cache.c                     |  120\n++++++++++++++++-------------------\n 2 files changed, 64 insertions(+), 72 deletions(-)\n\n\n\nIndex: Documentation/git-checkout-cache.txt\n===================================================================\n--- 3abc6a8ee0f27eaba8d0a7d091413eb390447386/Documentation/git-checkout-cache.txt  (mode:100644)\n+++ uncommitted/Documentation/git-checkout-cache.txt  (mode:100644)\n@@ -24,7 +24,7 @@\n \tthe cache file.\n \n -q::\n-\tbe quiet if files exist or are not in the cache\n+\tbe quiet if files exist or are not in the cache.\n \n -f::\n \tforces overwrite of existing files\n@@ -44,17 +44,15 @@\n --::\n \tDo not interpret any more arguments as options.\n \n-Note that the order of the flags matters:\n+Example:\n \n-     git-checkout-cache -a -f file.c\n+     git-checkout-cache -a\n \n-will first check out all files listed in the cache (but not overwrite\n-any old ones), and then force-checkout `file.c` a second time (ie that\n-one *will* overwrite any old contents with the same filename).\n+Will check out all files listed in the cache.\n \n-Also, just doing \"git-checkout-cache\" does nothing. You probably meant\n+Just doing \"git-checkout-cache\" does nothing. You probably meant\n \"git-checkout-cache -a\". And if you want to force it, you want\n-\"git-checkout-cache -f -a\".\n+\"git-checkout-cache -a -f\".\n \n Intuitiveness is not the goal here. Repeatability is. The reason for\n the \"no arguments means no work\" thing is that from scripts you are\n@@ -68,7 +66,7 @@\n \n To update and refresh only the files already checked out:\n \n-        git-checkout-cache -n -f -a && git-update-cache --ignore-missing --refresh\n+        git-checkout-cache -n -a -f && git-update-cache --ignore-missing --refresh\n \n Oh, and the \"--\" is just a good idea when you know the rest will be\n filenames. Just so that you wouldn't have a filename of \"-a\" causing\nIndex: checkout-cache.c\n===================================================================\n--- 3abc6a8ee0f27eaba8d0a7d091413eb390447386/checkout-cache.c  (mode:100644)\n+++ uncommitted/checkout-cache.c  (mode:100644)\n@@ -3,18 +3,14 @@\n  *\n  * Copyright (C) 2005 Linus Torvalds\n  *\n- * Careful: order of argument flags does matter. For example,\n+ *\tgit-checkout-cache -a\n  *\n- *\tgit-checkout-cache -a -f file.c\n+ * Will check out all files listed in the cache, but not\n+ * overwrite any existing files. \n  *\n- * Will first check out all files listed in the cache (but not\n- * overwrite any old ones), and then force-checkout \"file.c\" a\n- * second time (ie that one _will_ overwrite any old contents\n- * with the same filename).\n- *\n- * Also, just doing \"git-checkout-cache\" does nothing. You probably\n- * meant \"git-checkout-cache -a\". And if you want to force it, you\n- * want \"git-checkout-cache -f -a\".\n+ * Just doing \"git-checkout-cache\" does nothing. You probably\n+ * meant \"git-checkout-cache -a\". And if you want to force it,\n+ * you want \"git-checkout-cache -f -a\".\n  *\n  * Intuitiveness is not the goal here. Repeatability is. The\n  * reason for the \"no arguments means no work\" thing is that\n@@ -35,8 +31,11 @@\n #include <sys/types.h>\n #include <dirent.h>\n #include \"cache.h\"\n+#include <argp.h>\n+const char *argp_program_version = VERSION;\n \n-static int force = 0, quiet = 0, not_new = 0, refresh_cache = 0;\n+static int force = 0, quiet = 0, not_new = 0, refresh_cache = 0, all = 0;\n+static const char *base_opt = \"\";\n \n static void create_directories(const char *path)\n {\n@@ -226,68 +225,63 @@\n \treturn 0;\n }\n \n+static const char doc[] = \"Populate working tree with files from cache\";\n+\n+static struct argp_option options[] = {\n+ {\"prefix\", 1, \"base\", 0, \"Prepend base to each file before checkout\"},\n+ {\"all\", 'a', 0, 0, \"Checkout entire cache\"},\n+ {\"force\", 'f', 0, 0, \"Allow checkout to overwrite existing files\"},\n+ {\"quiet\", 'q', 0, 0, \"Suppress warnings\"},\n+ {\"not-new\", 'n', 0, 0, \"Checkout existing files only\"},\n+ {\"update\", 'u', 0, 0, \"Update cache with new stat info\"},\n+ { }\n+};\n+\n+static error_t parse_opt (int key, char *arg, struct argp_state *state)\n+{\n+        switch (key) {\n+        case 'a':\t\tall = 1; break;\n+        case 'q':\t\tquiet = 1; break;\n+        case 'n':\t\tnot_new = 1; break;\n+        case 'f':\t\tforce = 1; break;\n+        case   1:\t\tbase_opt = arg; break;\n+        case 'u':\t\trefresh_cache = 1; break;\n+        default:\t\treturn ARGP_ERR_UNKNOWN;\n+        }\n+        return 0;\n+}\n+\n+static const struct argp argp = { options, parse_opt, \"[FILES...]\", doc };\n+\n int main(int argc, char **argv)\n {\n-\tint i, force_filename = 0;\n-\tconst char *base_dir = \"\";\n \tstruct cache_file cache_file;\n-\tint newfd = -1;\n+\tint i, idx, newfd = -1;\n \n \tif (read_cache() < 0) {\n \t\tdie(\"invalid cache\");\n \t}\n \n-\tfor (i = 1; i < argc; i++) {\n-\t\tconst char *arg = argv[i];\n-\t\tif (!force_filename) {\n-\t\t\tif (!strcmp(arg, \"-a\")) {\n-\t\t\t\tcheckout_all(base_dir);\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(arg, \"--\")) {\n-\t\t\t\tforce_filename = 1;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(arg, \"-f\")) {\n-\t\t\t\tforce = 1;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(arg, \"-q\")) {\n-\t\t\t\tquiet = 1;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(arg, \"-n\")) {\n-\t\t\t\tnot_new = 1;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(arg, \"-u\")) {\n-\t\t\t\trefresh_cache = 1;\n-\t\t\t\tif (newfd < 0)\n-\t\t\t\t\tnewfd = hold_index_file_for_update\n-\t\t\t\t\t\t(&cache_file,\n-\t\t\t\t\t\t get_index_file());\n-\t\t\t\tif (newfd < 0)\n-\t\t\t\t\tdie(\"cannot open index.lock file.\");\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!memcmp(arg, \"--prefix=\", 9)) {\n-\t\t\t\tbase_dir = arg+9;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t}\n-\t\tif (base_dir[0]) {\n-\t\t\t/* when --prefix is specified we do not\n-\t\t\t * want to update cache.\n-\t\t\t */\n-\t\t\tif (refresh_cache) {\n-\t\t\t\tclose(newfd); newfd = -1;\n-\t\t\t\trollback_index_file(&cache_file);\n-\t\t\t}\n-\t\t\trefresh_cache = 0;\n-\t\t}\n-\t\tcheckout_file(arg, base_dir);\n+\terror_t rc = argp_parse(&argp, argc, argv, 0, &idx, NULL);\n+\tif (rc) {\n+\t\tfprintf(stderr, \"argument failed: %s\\n\", strerror(rc));\n+\t\treturn 1;\n \t}\n \n+\tif (refresh_cache) {\n+\t\tif (base_opt[0])\n+\t\t\tdie(\"cannot update cache when --prefix option is used\");\n+\t\tnewfd = hold_index_file_for_update(&cache_file, get_index_file());\n+\t\tif (newfd < 0)\n+\t\t\tdie(\"cannot open index.lock file.\");\n+\t}\n+\n+\tif (all)\n+\t\tcheckout_all(base_opt); \n+\n+\tfor (i = idx; i < argc; i++) \n+\t\tcheckout_file(argv[i], base_opt);\n+\n \tif (0 <= newfd &&\n \t    (write_cache(newfd, active_cache, active_nr) ||\n \t     commit_index_file(&cache_file)))"}]}