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