BreakingChanges: early adopter option
[git/gitster.git] / alias.c
blob4daafd9bdae66ef9bd8cdf147699e4057cde89f7
1 #include "git-compat-util.h"
2 #include "alias.h"
3 #include "config.h"
4 #include "gettext.h"
5 #include "strbuf.h"
6 #include "string-list.h"
8 struct config_alias_data {
9 const char *alias;
10 char *v;
11 struct string_list *list;
14 static int config_alias_cb(const char *key, const char *value,
15 const struct config_context *ctx UNUSED, void *d)
17 struct config_alias_data *data = d;
18 const char *p;
20 if (!skip_prefix(key, "alias.", &p))
21 return 0;
23 if (data->alias) {
24 if (!strcasecmp(p, data->alias)) {
25 FREE_AND_NULL(data->v);
26 return git_config_string(&data->v,
27 key, value);
29 } else if (data->list) {
30 string_list_append(data->list, p);
33 return 0;
36 char *alias_lookup(const char *alias)
38 struct config_alias_data data = { alias, NULL };
40 read_early_config(config_alias_cb, &data);
42 return data.v;
45 void list_aliases(struct string_list *list)
47 struct config_alias_data data = { NULL, NULL, list };
49 read_early_config(config_alias_cb, &data);
52 void quote_cmdline(struct strbuf *buf, const char **argv)
54 for (const char **argp = argv; *argp; argp++) {
55 if (argp != argv)
56 strbuf_addch(buf, ' ');
57 strbuf_addch(buf, '"');
58 for (const char *p = *argp; *p; p++) {
59 const char c = *p;
61 if (c == '"' || c =='\\')
62 strbuf_addch(buf, '\\');
63 strbuf_addch(buf, c);
65 strbuf_addch(buf, '"');
69 #define SPLIT_CMDLINE_BAD_ENDING 1
70 #define SPLIT_CMDLINE_UNCLOSED_QUOTE 2
71 #define SPLIT_CMDLINE_ARGC_OVERFLOW 3
72 static const char *split_cmdline_errors[] = {
73 N_("cmdline ends with \\"),
74 N_("unclosed quote"),
75 N_("too many arguments"),
78 int split_cmdline(char *cmdline, const char ***argv)
80 size_t src, dst, count = 0, size = 16;
81 char quoted = 0;
83 ALLOC_ARRAY(*argv, size);
85 /* split alias_string */
86 (*argv)[count++] = cmdline;
87 for (src = dst = 0; cmdline[src];) {
88 char c = cmdline[src];
89 if (!quoted && isspace(c)) {
90 cmdline[dst++] = 0;
91 while (cmdline[++src]
92 && isspace(cmdline[src]))
93 ; /* skip */
94 ALLOC_GROW(*argv, count + 1, size);
95 (*argv)[count++] = cmdline + dst;
96 } else if (!quoted && (c == '\'' || c == '"')) {
97 quoted = c;
98 src++;
99 } else if (c == quoted) {
100 quoted = 0;
101 src++;
102 } else {
103 if (c == '\\' && quoted != '\'') {
104 src++;
105 c = cmdline[src];
106 if (!c) {
107 FREE_AND_NULL(*argv);
108 return -SPLIT_CMDLINE_BAD_ENDING;
111 cmdline[dst++] = c;
112 src++;
116 cmdline[dst] = 0;
118 if (quoted) {
119 FREE_AND_NULL(*argv);
120 return -SPLIT_CMDLINE_UNCLOSED_QUOTE;
123 if (count >= INT_MAX) {
124 FREE_AND_NULL(*argv);
125 return -SPLIT_CMDLINE_ARGC_OVERFLOW;
128 ALLOC_GROW(*argv, count + 1, size);
129 (*argv)[count] = NULL;
131 return count;
134 const char *split_cmdline_strerror(int split_cmdline_errno)
136 return split_cmdline_errors[-split_cmdline_errno - 1];