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