parse-options-cb.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. #include "git-compat-util.h"
  2. #include "parse-options.h"
  3. #include "cache.h"
  4. #include "commit.h"
  5. #include "color.h"
  6. #include "string-list.h"
  7. #include "strvec.h"
  8. #include "oid-array.h"
  9. /*----- some often used options -----*/
  10. int parse_opt_abbrev_cb(const struct option *opt, const char *arg, int unset)
  11. {
  12. int v;
  13. if (!arg) {
  14. v = unset ? 0 : DEFAULT_ABBREV;
  15. } else {
  16. if (!*arg)
  17. return error(_("option `%s' expects a numerical value"),
  18. opt->long_name);
  19. v = strtol(arg, (char **)&arg, 10);
  20. if (*arg)
  21. return error(_("option `%s' expects a numerical value"),
  22. opt->long_name);
  23. if (v && v < MINIMUM_ABBREV)
  24. v = MINIMUM_ABBREV;
  25. else if (v > the_hash_algo->hexsz)
  26. v = the_hash_algo->hexsz;
  27. }
  28. *(int *)(opt->value) = v;
  29. return 0;
  30. }
  31. int parse_opt_expiry_date_cb(const struct option *opt, const char *arg,
  32. int unset)
  33. {
  34. if (unset)
  35. arg = "never";
  36. if (parse_expiry_date(arg, (timestamp_t *)opt->value))
  37. die(_("malformed expiration date '%s'"), arg);
  38. return 0;
  39. }
  40. int parse_opt_color_flag_cb(const struct option *opt, const char *arg,
  41. int unset)
  42. {
  43. int value;
  44. if (!arg)
  45. arg = unset ? "never" : (const char *)opt->defval;
  46. value = git_config_colorbool(NULL, arg);
  47. if (value < 0)
  48. return error(_("option `%s' expects \"always\", \"auto\", or \"never\""),
  49. opt->long_name);
  50. *(int *)opt->value = value;
  51. return 0;
  52. }
  53. int parse_opt_verbosity_cb(const struct option *opt, const char *arg,
  54. int unset)
  55. {
  56. int *target = opt->value;
  57. BUG_ON_OPT_ARG(arg);
  58. if (unset)
  59. /* --no-quiet, --no-verbose */
  60. *target = 0;
  61. else if (opt->short_name == 'v') {
  62. if (*target >= 0)
  63. (*target)++;
  64. else
  65. *target = 1;
  66. } else {
  67. if (*target <= 0)
  68. (*target)--;
  69. else
  70. *target = -1;
  71. }
  72. return 0;
  73. }
  74. int parse_opt_commits(const struct option *opt, const char *arg, int unset)
  75. {
  76. struct object_id oid;
  77. struct commit *commit;
  78. BUG_ON_OPT_NEG(unset);
  79. if (!arg)
  80. return -1;
  81. if (get_oid(arg, &oid))
  82. return error("malformed object name %s", arg);
  83. commit = lookup_commit_reference(the_repository, &oid);
  84. if (!commit)
  85. return error("no such commit %s", arg);
  86. commit_list_insert(commit, opt->value);
  87. return 0;
  88. }
  89. int parse_opt_commit(const struct option *opt, const char *arg, int unset)
  90. {
  91. struct object_id oid;
  92. struct commit *commit;
  93. struct commit **target = opt->value;
  94. BUG_ON_OPT_NEG(unset);
  95. if (!arg)
  96. return -1;
  97. if (get_oid(arg, &oid))
  98. return error("malformed object name %s", arg);
  99. commit = lookup_commit_reference(the_repository, &oid);
  100. if (!commit)
  101. return error("no such commit %s", arg);
  102. *target = commit;
  103. return 0;
  104. }
  105. int parse_opt_object_name(const struct option *opt, const char *arg, int unset)
  106. {
  107. struct object_id oid;
  108. if (unset) {
  109. oid_array_clear(opt->value);
  110. return 0;
  111. }
  112. if (!arg)
  113. return -1;
  114. if (get_oid(arg, &oid))
  115. return error(_("malformed object name '%s'"), arg);
  116. oid_array_append(opt->value, &oid);
  117. return 0;
  118. }
  119. int parse_opt_object_id(const struct option *opt, const char *arg, int unset)
  120. {
  121. struct object_id oid;
  122. struct object_id *target = opt->value;
  123. if (unset) {
  124. *target = null_oid;
  125. return 0;
  126. }
  127. if (!arg)
  128. return -1;
  129. if (get_oid(arg, &oid))
  130. return error(_("malformed object name '%s'"), arg);
  131. *target = oid;
  132. return 0;
  133. }
  134. int parse_opt_tertiary(const struct option *opt, const char *arg, int unset)
  135. {
  136. int *target = opt->value;
  137. BUG_ON_OPT_ARG(arg);
  138. *target = unset ? 2 : 1;
  139. return 0;
  140. }
  141. static size_t parse_options_count(const struct option *opt)
  142. {
  143. size_t n = 0;
  144. for (; opt && opt->type != OPTION_END; opt++)
  145. n++;
  146. return n;
  147. }
  148. struct option *parse_options_dup(const struct option *o)
  149. {
  150. struct option no_options[] = { OPT_END() };
  151. return parse_options_concat(o, no_options);
  152. }
  153. struct option *parse_options_concat(const struct option *a,
  154. const struct option *b)
  155. {
  156. struct option *ret;
  157. size_t a_len = parse_options_count(a);
  158. size_t b_len = parse_options_count(b);
  159. ALLOC_ARRAY(ret, st_add3(a_len, b_len, 1));
  160. COPY_ARRAY(ret, a, a_len);
  161. COPY_ARRAY(ret + a_len, b, b_len + 1); /* + 1 for final OPTION_END */
  162. return ret;
  163. }
  164. int parse_opt_string_list(const struct option *opt, const char *arg, int unset)
  165. {
  166. struct string_list *v = opt->value;
  167. if (unset) {
  168. string_list_clear(v, 0);
  169. return 0;
  170. }
  171. if (!arg)
  172. return -1;
  173. string_list_append(v, arg);
  174. return 0;
  175. }
  176. int parse_opt_noop_cb(const struct option *opt, const char *arg, int unset)
  177. {
  178. return 0;
  179. }
  180. /**
  181. * Report that the option is unknown, so that other code can handle
  182. * it. This can be used as a callback together with
  183. * OPTION_LOWLEVEL_CALLBACK to allow an option to be documented in the
  184. * "-h" output even if it's not being handled directly by
  185. * parse_options().
  186. */
  187. enum parse_opt_result parse_opt_unknown_cb(struct parse_opt_ctx_t *ctx,
  188. const struct option *opt,
  189. const char *arg, int unset)
  190. {
  191. BUG_ON_OPT_ARG(arg);
  192. return PARSE_OPT_UNKNOWN;
  193. }
  194. /**
  195. * Recreates the command-line option in the strbuf.
  196. */
  197. static int recreate_opt(struct strbuf *sb, const struct option *opt,
  198. const char *arg, int unset)
  199. {
  200. strbuf_reset(sb);
  201. if (opt->long_name) {
  202. strbuf_addstr(sb, unset ? "--no-" : "--");
  203. strbuf_addstr(sb, opt->long_name);
  204. if (arg) {
  205. strbuf_addch(sb, '=');
  206. strbuf_addstr(sb, arg);
  207. }
  208. } else if (opt->short_name && !unset) {
  209. strbuf_addch(sb, '-');
  210. strbuf_addch(sb, opt->short_name);
  211. if (arg)
  212. strbuf_addstr(sb, arg);
  213. } else
  214. return -1;
  215. return 0;
  216. }
  217. /**
  218. * For an option opt, recreates the command-line option in opt->value which
  219. * must be an char* initialized to NULL. This is useful when we need to pass
  220. * the command-line option to another command. Since any previous value will be
  221. * overwritten, this callback should only be used for options where the last
  222. * one wins.
  223. */
  224. int parse_opt_passthru(const struct option *opt, const char *arg, int unset)
  225. {
  226. static struct strbuf sb = STRBUF_INIT;
  227. char **opt_value = opt->value;
  228. if (recreate_opt(&sb, opt, arg, unset) < 0)
  229. return -1;
  230. free(*opt_value);
  231. *opt_value = strbuf_detach(&sb, NULL);
  232. return 0;
  233. }
  234. /**
  235. * For an option opt, recreate the command-line option, appending it to
  236. * opt->value which must be a strvec. This is useful when we need to pass
  237. * the command-line option, which can be specified multiple times, to another
  238. * command.
  239. */
  240. int parse_opt_passthru_argv(const struct option *opt, const char *arg, int unset)
  241. {
  242. static struct strbuf sb = STRBUF_INIT;
  243. struct strvec *opt_value = opt->value;
  244. if (recreate_opt(&sb, opt, arg, unset) < 0)
  245. return -1;
  246. strvec_push(opt_value, sb.buf);
  247. return 0;
  248. }