@@ -43,8 +43,42 @@ static void fix_filename(const char *prefix, const char **file)
4343 * file = xstrdup (prefix_filename (prefix , strlen (prefix ), * file ));
4444}
4545
46+ static int opt_command_mode_error (const struct option * opt ,
47+ const struct option * all_opts ,
48+ int flags )
49+ {
50+ const struct option * that ;
51+ struct strbuf message = STRBUF_INIT ;
52+ struct strbuf that_name = STRBUF_INIT ;
53+
54+ /*
55+ * Find the other option that was used to set the variable
56+ * already, and report that this is not compatible with it.
57+ */
58+ for (that = all_opts ; that -> type != OPTION_END ; that ++ ) {
59+ if (that == opt ||
60+ that -> type != OPTION_CMDMODE ||
61+ that -> value != opt -> value ||
62+ that -> defval != * (int * )opt -> value )
63+ continue ;
64+
65+ if (that -> long_name )
66+ strbuf_addf (& that_name , "--%s" , that -> long_name );
67+ else
68+ strbuf_addf (& that_name , "-%c" , that -> short_name );
69+ strbuf_addf (& message , ": incompatible with %s" , that_name .buf );
70+ strbuf_release (& that_name );
71+ opterror (opt , message .buf , flags );
72+ strbuf_release (& message );
73+ return -1 ;
74+ }
75+ return opterror (opt , ": incompatible with something else" , flags );
76+ }
77+
4678static int get_value (struct parse_opt_ctx_t * p ,
47- const struct option * opt , int flags )
79+ const struct option * opt ,
80+ const struct option * all_opts ,
81+ int flags )
4882{
4983 const char * s , * arg ;
5084 const int unset = flags & OPT_UNSET ;
@@ -83,6 +117,16 @@ static int get_value(struct parse_opt_ctx_t *p,
83117 * (int * )opt -> value = unset ? 0 : opt -> defval ;
84118 return 0 ;
85119
120+ case OPTION_CMDMODE :
121+ /*
122+ * Giving the same mode option twice, although is unnecessary,
123+ * is not a grave error, so let it pass.
124+ */
125+ if (* (int * )opt -> value && * (int * )opt -> value != opt -> defval )
126+ return opt_command_mode_error (opt , all_opts , flags );
127+ * (int * )opt -> value = opt -> defval ;
128+ return 0 ;
129+
86130 case OPTION_SET_PTR :
87131 * (void * * )opt -> value = unset ? NULL : (void * )opt -> defval ;
88132 return 0 ;
@@ -143,12 +187,13 @@ static int get_value(struct parse_opt_ctx_t *p,
143187
144188static int parse_short_opt (struct parse_opt_ctx_t * p , const struct option * options )
145189{
190+ const struct option * all_opts = options ;
146191 const struct option * numopt = NULL ;
147192
148193 for (; options -> type != OPTION_END ; options ++ ) {
149194 if (options -> short_name == * p -> opt ) {
150195 p -> opt = p -> opt [1 ] ? p -> opt + 1 : NULL ;
151- return get_value (p , options , OPT_SHORT );
196+ return get_value (p , options , all_opts , OPT_SHORT );
152197 }
153198
154199 /*
@@ -177,6 +222,7 @@ static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *optio
177222static int parse_long_opt (struct parse_opt_ctx_t * p , const char * arg ,
178223 const struct option * options )
179224{
225+ const struct option * all_opts = options ;
180226 const char * arg_end = strchr (arg , '=' );
181227 const struct option * abbrev_option = NULL , * ambiguous_option = NULL ;
182228 int abbrev_flags = 0 , ambiguous_flags = 0 ;
@@ -253,7 +299,7 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
253299 continue ;
254300 p -> opt = rest + 1 ;
255301 }
256- return get_value (p , options , flags ^ opt_flags );
302+ return get_value (p , options , all_opts , flags ^ opt_flags );
257303 }
258304
259305 if (ambiguous_option )
@@ -265,18 +311,20 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
265311 (abbrev_flags & OPT_UNSET ) ? "no-" : "" ,
266312 abbrev_option -> long_name );
267313 if (abbrev_option )
268- return get_value (p , abbrev_option , abbrev_flags );
314+ return get_value (p , abbrev_option , all_opts , abbrev_flags );
269315 return -2 ;
270316}
271317
272318static int parse_nodash_opt (struct parse_opt_ctx_t * p , const char * arg ,
273319 const struct option * options )
274320{
321+ const struct option * all_opts = options ;
322+
275323 for (; options -> type != OPTION_END ; options ++ ) {
276324 if (!(options -> flags & PARSE_OPT_NODASH ))
277325 continue ;
278326 if (options -> short_name == arg [0 ] && arg [1 ] == '\0' )
279- return get_value (p , options , OPT_SHORT );
327+ return get_value (p , options , all_opts , OPT_SHORT );
280328 }
281329 return -2 ;
282330}
0 commit comments