144
ATOM_BODY,
145
ATOM_TRAILERS,
146
ATOM_CONTENTS,
147
+ ATOM_RAW,
148
ATOM_UPSTREAM,
149
ATOM_PUSH,
150
ATOM_SYMREF,
190
struct process_trailer_options trailer_opts;
191
unsigned int nlines;
192
} contents;
193
+ struct {
194
+ enum { RAW_BARE, RAW_LENGTH } option;
195
+ } raw_data;
196
struct {
197
cmp_status cmp_status;
198
const char *str;
430
return 0;
431
}
432
433
+static int raw_atom_parser(const struct ref_format *format, struct used_atom *atom,
434
+ const char *arg, struct strbuf *err)
435
+{
436
+ if (!arg)
437
+ atom->u.raw_data.option = RAW_BARE;
438
+ else if (!strcmp(arg, "size"))
439
+ atom->u.raw_data.option = RAW_LENGTH;
440
+ else
441
+ return strbuf_addf_ret(err, -1, _("unrecognized %%(raw) argument: %s"), arg);
442
+ return 0;
443
+}
444
+
445
static int oid_atom_parser(const struct ref_format *format, struct used_atom *atom,
446
const char *arg, struct strbuf *err)
447
{
602
[ATOM_BODY] = { "body", SOURCE_OBJ, FIELD_STR, body_atom_parser },
603
[ATOM_TRAILERS] = { "trailers", SOURCE_OBJ, FIELD_STR, trailers_atom_parser },
604
[ATOM_CONTENTS] = { "contents", SOURCE_OBJ, FIELD_STR, contents_atom_parser },
605
+ [ATOM_RAW] = { "raw", SOURCE_OBJ, FIELD_STR, raw_atom_parser },
606
[ATOM_UPSTREAM] = { "upstream", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },
607
[ATOM_PUSH] = { "push", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },
608
[ATOM_SYMREF] = { "symref", SOURCE_NONE, FIELD_STR, refname_atom_parser },
637
638
struct atom_value {
639
const char *s;
640
+ ssize_t s_size;
641
int (*handler)(struct atom_value *atomv, struct ref_formatting_state *state,
642
struct strbuf *err);
643
uintmax_t value; /* used for sorting when not FIELD_STR */
644
struct used_atom *atom;
645
};
646
647
+#define ATOM_SIZE_UNSPECIFIED (-1)
648
+
649
+#define ATOM_VALUE_INIT { \
650
+ .s_size = ATOM_SIZE_UNSPECIFIED \
651
+}
652
+
653
/*
654
* Used to parse format string and sort specifiers
655
*/
668
return strbuf_addf_ret(err, -1, _("malformed field name: %.*s"),
669
(int)(ep-atom), atom);
670
647
- /* Do we have the atom already used elsewhere? */
648
- for (i = 0; i < used_atom_cnt; i++) {
649
- int len = strlen(used_atom[i].name);
650
- if (len == ep - atom && !memcmp(used_atom[i].name, atom, len))
651
- return i;
652
- }
653
-
671
/*
672
* If the atom name has a colon, strip it and everything after
673
* it off - it specifies the format for this entry, and
677
arg = memchr(sp, ':', ep - sp);
678
atom_len = (arg ? arg : ep) - sp;
679
680
+ /* Do we have the atom already used elsewhere? */
681
+ for (i = 0; i < used_atom_cnt; i++) {
682
+ int len = strlen(used_atom[i].name);
683
+ if (len == ep - atom && !memcmp(used_atom[i].name, atom, len))
684
+ return i;
685
+ }
686
+
687
/* Is the atom a valid one? */
688
for (i = 0; i < ARRAY_SIZE(valid_atom); i++) {
689
int len = strlen(valid_atom[i].name);
733
return at;
734
}
735
712
-static void quote_formatting(struct strbuf *s, const char *str, int quote_style)
736
+static void quote_formatting(struct strbuf *s, const char *str, ssize_t len, int quote_style)
737
{
738
switch (quote_style) {
739
case QUOTE_NONE:
716
- strbuf_addstr(s, str);
740
+ if (len < 0)
741
+ strbuf_addstr(s, str);
742
+ else
743
+ strbuf_add(s, str, len);
744
break;
745
case QUOTE_SHELL:
746
sq_quote_buf(s, str);
767
* encountered.
768
*/
769
if (!state->stack->prev)
743
- quote_formatting(&state->stack->output, v->s, state->quote_style);
744
- else
770
+ quote_formatting(&state->stack->output, v->s, v->s_size, state->quote_style);
771
+ else if (v->s_size < 0)
772
strbuf_addstr(&state->stack->output, v->s);
773
+ else
774
+ strbuf_add(&state->stack->output, v->s, v->s_size);
775
return 0;
776
}
777
871
return 0;
872
}
873
845
-static int is_empty(const char *s)
874
+static int is_empty(struct strbuf *buf)
875
{
847
- while (*s != '\0') {
848
- if (!isspace(*s))
849
- return 0;
850
- s++;
851
- }
852
- return 1;
853
-}
876
+ const char *cur = buf->buf;
877
+ const char *end = buf->buf + buf->len;
878
+
879
+ while (cur != end && (isspace(*cur)))
880
+ cur++;
881
+
882
+ return cur == end;
883
+ }
884
885
static int then_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state,
886
struct strbuf *err)
887
{
888
struct ref_formatting_stack *cur = state->stack;
889
struct if_then_else *if_then_else = NULL;
890
+ size_t str_len = 0;
891
892
if (cur->at_end == if_then_else_handler)
893
if_then_else = (struct if_then_else *)cur->at_end_data;
898
if (if_then_else->else_atom_seen)
899
return strbuf_addf_ret(err, -1, _("format: %%(then) atom used after %%(else)"));
900
if_then_else->then_atom_seen = 1;
901
+ if (if_then_else->str)
902
+ str_len = strlen(if_then_else->str);
903
/*
904
* If the 'equals' or 'notequals' attribute is used then
905
* perform the required comparison. If not, only non-empty
906
* strings satisfy the 'if' condition.
907
*/
908
if (if_then_else->cmp_status == COMPARE_EQUAL) {
876
- if (!strcmp(if_then_else->str, cur->output.buf))
909
+ if (str_len == cur->output.len &&
910
+ !memcmp(if_then_else->str, cur->output.buf, cur->output.len))
911
if_then_else->condition_satisfied = 1;
912
} else if (if_then_else->cmp_status == COMPARE_UNEQUAL) {
879
- if (strcmp(if_then_else->str, cur->output.buf))
913
+ if (str_len != cur->output.len ||
914
+ memcmp(if_then_else->str, cur->output.buf, cur->output.len))
915
if_then_else->condition_satisfied = 1;
881
- } else if (cur->output.len && !is_empty(cur->output.buf))
916
+ } else if (cur->output.len && !is_empty(&cur->output))
917
if_then_else->condition_satisfied = 1;
918
strbuf_reset(&cur->output);
919
return 0;
959
* only on the topmost supporting atom.
960
*/
961
if (!current->prev->prev) {
927
- quote_formatting(&s, current->output.buf, state->quote_style);
962
+ quote_formatting(&s, current->output.buf, current->output.len, state->quote_style);
963
strbuf_swap(¤t->output, &s);
964
}
965
strbuf_release(&s);
1009
at = parse_ref_filter_atom(format, sp + 2, ep, &err);
1010
if (at < 0)
1011
die("%s", err.buf);
1012
+ if (format->quote_style && used_atom[at].atom_type == ATOM_RAW &&
1013
+ used_atom[at].u.raw_data.option == RAW_BARE)
1014
+ die(_("--format=%.*s cannot be used with"
1015
+ "--python, --shell, --tcl, --perl"), (int)(ep - sp - 2), sp + 2);
1016
cp = ep + 1;
1017
1018
if (skip_prefix(used_atom[at].name, "color:", &color))
1406
struct used_atom *atom = &used_atom[i];
1407
const char *name = atom->name;
1408
struct atom_value *v = &val[i];
1409
+ enum atom_type atom_type = atom->atom_type;
1410
1411
if (!!deref != (*name == '*'))
1412
continue;
1413
if (deref)
1414
name++;
1415
1416
+ if (atom_type == ATOM_RAW) {
1417
+ unsigned long buf_size = data->size;
1418
+
1419
+ if (atom->u.raw_data.option == RAW_BARE) {
1420
+ v->s = xmemdupz(buf, buf_size);
1421
+ v->s_size = buf_size;
1422
+ } else if (atom->u.raw_data.option == RAW_LENGTH) {
1423
+ v->s = xstrfmt("%"PRIuMAX, (uintmax_t)buf_size);
1424
+ }
1425
+ continue;
1426
+ }
1427
+
1428
if ((data->type != OBJ_TAG &&
1429
data->type != OBJ_COMMIT) ||
1430
(strcmp(name, "body") &&
1512
break;
1513
case OBJ_TREE:
1514
/* grab_tree_values(val, deref, obj, buf, sz); */
1515
+ grab_sub_body_contents(val, deref, data);
1516
break;
1517
case OBJ_BLOB:
1518
/* grab_blob_values(val, deref, obj, buf, sz); */
1519
+ grab_sub_body_contents(val, deref, data);
1520
break;
1521
default:
1522
die("Eh? Object of type %d?", obj->type);
1820
const char *refname;
1821
struct branch *branch = NULL;
1822
1823
+ v->s_size = ATOM_SIZE_UNSPECIFIED;
1824
v->handler = append_atom;
1825
v->atom = atom;
1826
2424
return 0;
2425
}
2426
2427
+static int memcasecmp(const void *vs1, const void *vs2, size_t n)
2428
+{
2429
+ const char *s1 = vs1, *s2 = vs2;
2430
+ const char *end = s1 + n;
2431
+
2432
+ for (; s1 < end; s1++, s2++) {
2433
+ int diff = tolower(*s1) - tolower(*s2);
2434
+ if (diff)
2435
+ return diff;
2436
+ }
2437
+ return 0;
2438
+}
2439
+
2440
static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, struct ref_array_item *b)
2441
{
2442
struct atom_value *va, *vb;
2457
} else if (s->sort_flags & REF_SORTING_VERSION) {
2458
cmp = versioncmp(va->s, vb->s);
2459
} else if (cmp_type == FIELD_STR) {
2392
- int (*cmp_fn)(const char *, const char *);
2393
- cmp_fn = s->sort_flags & REF_SORTING_ICASE
2394
- ? strcasecmp : strcmp;
2395
- cmp = cmp_fn(va->s, vb->s);
2460
+ if (va->s_size < 0 && vb->s_size < 0) {
2461
+ int (*cmp_fn)(const char *, const char *);
2462
+ cmp_fn = s->sort_flags & REF_SORTING_ICASE
2463
+ ? strcasecmp : strcmp;
2464
+ cmp = cmp_fn(va->s, vb->s);
2465
+ } else {
2466
+ size_t a_size = va->s_size < 0 ?
2467
+ strlen(va->s) : va->s_size;
2468
+ size_t b_size = vb->s_size < 0 ?
2469
+ strlen(vb->s) : vb->s_size;
2470
+ int (*cmp_fn)(const void *, const void *, size_t);
2471
+ cmp_fn = s->sort_flags & REF_SORTING_ICASE
2472
+ ? memcasecmp : memcmp;
2473
+
2474
+ cmp = cmp_fn(va->s, vb->s, b_size > a_size ?
2475
+ a_size : b_size);
2476
+ if (!cmp) {
2477
+ if (a_size > b_size)
2478
+ cmp = 1;
2479
+ else if (a_size < b_size)
2480
+ cmp = -1;
2481
+ }
2482
+ }
2483
} else {
2484
if (va->value < vb->value)
2485
cmp = -1;
2578
append_literal(cp, sp, &state);
2579
}
2580
if (format->need_color_reset_at_eol) {
2494
- struct atom_value resetv;
2581
+ struct atom_value resetv = ATOM_VALUE_INIT;
2582
resetv.s = GIT_COLOR_RESET;
2583
if (append_atom(&resetv, &state, error_buf)) {
2584
pop_stack_element(&state.stack);