Coverage Report

Created: 2024-09-08 06:23

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