6
#include "list-objects.h"
7
#include "list-objects-filter.h"
8
#include "list-objects-filter-options.h"
9
+#include "trace.h"
10
#include "url.h"
11
12
static int parse_combine_filter(
179
return result;
180
}
181
181
-int parse_list_objects_filter(struct list_objects_filter_options *filter_options,
182
- const char *arg)
182
+static int allow_unencoded(char ch)
183
+{
184
+ if (ch <= ' ' || ch == '%' || ch == '+')
185
+ return 0;
186
+ return !strchr(RESERVED_NON_WS, ch);
187
+}
188
+
189
+static void filter_spec_append_urlencode(
190
+ struct list_objects_filter_options *filter, const char *raw)
191
{
192
struct strbuf buf = STRBUF_INIT;
193
+ strbuf_addstr_urlencode(&buf, raw, allow_unencoded);
194
+ trace_printf("Add to combine filter-spec: %s\n", buf.buf);
195
+ string_list_append(&filter->filter_spec, strbuf_detach(&buf, NULL));
196
+}
197
+
198
+/*
199
+ * Changes filter_options into an equivalent LOFC_COMBINE filter options
200
+ * instance. Does not do anything if filter_options is already LOFC_COMBINE.
201
+ */
202
+static void transform_to_combine_type(
203
+ struct list_objects_filter_options *filter_options)
204
+{
205
+ assert(filter_options->choice);
206
+ if (filter_options->choice == LOFC_COMBINE)
207
+ return;
208
+ {
209
+ const int initial_sub_alloc = 2;
210
+ struct list_objects_filter_options *sub_array =
211
+ xcalloc(initial_sub_alloc, sizeof(*sub_array));
212
+ sub_array[0] = *filter_options;
213
+ memset(filter_options, 0, sizeof(*filter_options));
214
+ filter_options->sub = sub_array;
215
+ filter_options->sub_alloc = initial_sub_alloc;
216
+ }
217
+ filter_options->sub_nr = 1;
218
+ filter_options->choice = LOFC_COMBINE;
219
+ string_list_append(&filter_options->filter_spec, xstrdup("combine:"));
220
+ filter_spec_append_urlencode(
221
+ filter_options,
222
+ list_objects_filter_spec(&filter_options->sub[0]));
223
+ /*
224
+ * We don't need the filter_spec strings for subfilter specs, only the
225
+ * top level.
226
+ */
227
+ string_list_clear(&filter_options->sub[0].filter_spec, /*free_util=*/0);
228
+}
229
+
230
+void list_objects_filter_die_if_populated(
231
+ struct list_objects_filter_options *filter_options)
232
+{
233
if (filter_options->choice)
234
die(_("multiple filter-specs cannot be combined"));
187
- string_list_append(&filter_options->filter_spec, xstrdup(arg));
188
- if (gently_parse_list_objects_filter(filter_options, arg, &buf))
189
- die("%s", buf.buf);
235
+}
236
+
237
+int parse_list_objects_filter(
238
+ struct list_objects_filter_options *filter_options,
239
+ const char *arg)
240
+{
241
+ struct strbuf errbuf = STRBUF_INIT;
242
+ int parse_error;
243
+
244
+ if (!filter_options->choice) {
245
+ string_list_append(&filter_options->filter_spec, xstrdup(arg));
246
+
247
+ parse_error = gently_parse_list_objects_filter(
248
+ filter_options, arg, &errbuf);
249
+ } else {
250
+ /*
251
+ * Make filter_options an LOFC_COMBINE spec so we can trivially
252
+ * add subspecs to it.
253
+ */
254
+ transform_to_combine_type(filter_options);
255
+
256
+ string_list_append(&filter_options->filter_spec, xstrdup("+"));
257
+ filter_spec_append_urlencode(filter_options, arg);
258
+ ALLOC_GROW(filter_options->sub, filter_options->sub_nr + 1,
259
+ filter_options->sub_alloc);
260
+ filter_options = &filter_options->sub[filter_options->sub_nr++];
261
+ memset(filter_options, 0, sizeof(*filter_options));
262
+
263
+ parse_error = gently_parse_list_objects_filter(
264
+ filter_options, arg, &errbuf);
265
+ }
266
+ if (parse_error)
267
+ die("%s", errbuf.buf);
268
return 0;
269
}
270