1 #include "builtin.h" 2 #include "cache.h" 3 #include "parse-options.h" 4 #include "refs.h" 5 #include "wildmatch.h" 6 #include "object-store.h" 7 #include "repository.h" 8 #include "commit.h" 9 #include "remote.h" 10 #include "color.h" 11 #include "tag.h" 12 #include "quote.h" 13 #include "ref-filter.h" 14 #include "revision.h" 15 #include "utf8.h" 16 #include "git-compat-util.h" 17 #include "version.h" 18 #include "trailer.h" 19 #include "wt-status.h" 20 #include "commit-slab.h" 21 #include "commit-graph.h" 22 #include "commit-reach.h" 23 #include "worktree.h" 24 #include "hashmap.h" 25 #include "strvec.h" 26 27 static struct ref_msg { 28 const char *gone; 29 const char *ahead; 30 const char *behind; 31 const char *ahead_behind; 32 } msgs = { 33 /* Untranslated plumbing messages: */ 34 "gone", 35 "ahead %d", 36 "behind %d", 37 "ahead %d, behind %d" 38 }; 39 40 void setup_ref_filter_porcelain_msg(void) 41 { 42 msgs.gone = _("gone"); 43 msgs.ahead = _("ahead %d"); 44 msgs.behind = _("behind %d"); 45 msgs.ahead_behind = _("ahead %d, behind %d"); 46 } 47 48 typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type; 49 typedef enum { COMPARE_EQUAL, COMPARE_UNEQUAL, COMPARE_NONE } cmp_status; 50 typedef enum { SOURCE_NONE = 0, SOURCE_OBJ, SOURCE_OTHER } info_source; 51 52 struct align { 53 align_type position; 54 unsigned int width; 55 }; 56 57 struct if_then_else { 58 cmp_status cmp_status; 59 const char *str; 60 unsigned int then_atom_seen : 1, 61 else_atom_seen : 1, 62 condition_satisfied : 1; 63 }; 64 65 struct refname_atom { 66 enum { R_NORMAL, R_SHORT, R_LSTRIP, R_RSTRIP } option; 67 int lstrip, rstrip; 68 }; 69 70 static struct ref_trailer_buf { 71 struct string_list filter_list; 72 struct strbuf sepbuf; 73 struct strbuf kvsepbuf; 74 } ref_trailer_buf = {STRING_LIST_INIT_NODUP, STRBUF_INIT, STRBUF_INIT}; 75 76 static struct expand_data { 77 struct object_id oid; 78 enum object_type type; 79 unsigned long size; 80 off_t disk_size; 81 struct object_id delta_base_oid; 82 void *content; 83 84 struct object_info info; 85 } oi, oi_deref; 86 87 struct ref_to_worktree_entry { 88 struct hashmap_entry ent; 89 struct worktree *wt; /* key is wt->head_ref */ 90 }; 91 92 static int ref_to_worktree_map_cmpfnc(const void *unused_lookupdata, 93 const struct hashmap_entry *eptr, 94 const struct hashmap_entry *kptr, 95 const void *keydata_aka_refname) 96 { 97 const struct ref_to_worktree_entry *e, *k; 98 99 e = container_of(eptr, const struct ref_to_worktree_entry, ent); 100 k = container_of(kptr, const struct ref_to_worktree_entry, ent); 101 102 return strcmp(e->wt->head_ref, 103 keydata_aka_refname ? keydata_aka_refname : k->wt->head_ref); 104 } 105 106 static struct ref_to_worktree_map { 107 struct hashmap map; 108 struct worktree **worktrees; 109 } ref_to_worktree_map; 110 111 /* 112 * The enum atom_type is used as the index of valid_atom array. 113 * In the atom parsing stage, it will be passed to used_atom.atom_type 114 * as the identifier of the atom type. We can check the type of used_atom 115 * entry by `if (used_atom[i].atom_type == ATOM_*)`. 116 */ 117 enum atom_type { 118 ATOM_REFNAME, 119 ATOM_OBJECTTYPE, 120 ATOM_OBJECTSIZE, 121 ATOM_OBJECTNAME, 122 ATOM_DELTABASE, 123 ATOM_TREE, 124 ATOM_PARENT, 125 ATOM_NUMPARENT, 126 ATOM_OBJECT, 127 ATOM_TYPE, 128 ATOM_TAG, 129 ATOM_AUTHOR, 130 ATOM_AUTHORNAME, 131 ATOM_AUTHOREMAIL, 132 ATOM_AUTHORDATE, 133 ATOM_COMMITTER, 134 ATOM_COMMITTERNAME, 135 ATOM_COMMITTEREMAIL, 136 ATOM_COMMITTERDATE, 137 ATOM_TAGGER, 138 ATOM_TAGGERNAME, 139 ATOM_TAGGEREMAIL, 140 ATOM_TAGGERDATE, 141 ATOM_CREATOR, 142 ATOM_CREATORDATE, 143 ATOM_SUBJECT, 144 ATOM_BODY, 145 ATOM_TRAILERS, 146 ATOM_CONTENTS, 147 ATOM_RAW, 148 ATOM_UPSTREAM, 149 ATOM_PUSH, 150 ATOM_SYMREF, 151 ATOM_FLAG, 152 ATOM_HEAD, 153 ATOM_COLOR, 154 ATOM_WORKTREEPATH, 155 ATOM_ALIGN, 156 ATOM_END, 157 ATOM_IF, 158 ATOM_THEN, 159 ATOM_ELSE, 160 ATOM_REST, 161 }; 162 163 /* 164 * An atom is a valid field atom listed below, possibly prefixed with 165 * a "*" to denote deref_tag(). 166 * 167 * We parse given format string and sort specifiers, and make a list 168 * of properties that we need to extract out of objects. ref_array_item 169 * structure will hold an array of values extracted that can be 170 * indexed with the "atom number", which is an index into this 171 * array. 172 */ 173 static struct used_atom { 174 enum atom_type atom_type; 175 const char *name; 176 cmp_type type; 177 info_source source; 178 union { 179 char color[COLOR_MAXLEN]; 180 struct align align; 181 struct { 182 enum { 183 RR_REF, RR_TRACK, RR_TRACKSHORT, RR_REMOTE_NAME, RR_REMOTE_REF 184 } option; 185 struct refname_atom refname; 186 unsigned int nobracket : 1, push : 1, push_remote : 1; 187 } remote_ref; 188 struct { 189 enum { C_BARE, C_BODY, C_BODY_DEP, C_LENGTH, C_LINES, 190 C_SIG, C_SUB, C_SUB_SANITIZE, C_TRAILERS } option; 191 struct process_trailer_options trailer_opts; 192 unsigned int nlines; 193 } contents; 194 struct { 195 enum { RAW_BARE, RAW_LENGTH } option; 196 } raw_data; 197 struct { 198 cmp_status cmp_status; 199 const char *str; 200 } if_then_else; 201 struct { 202 enum { O_FULL, O_LENGTH, O_SHORT } option; 203 unsigned int length; 204 } oid; 205 struct { 206 enum { O_SIZE, O_SIZE_DISK } option; 207 } objectsize; 208 struct email_option { 209 enum { EO_RAW, EO_TRIM, EO_LOCALPART } option; 210 } email_option; 211 struct refname_atom refname; 212 char *head; 213 } u; 214 } *used_atom; 215 static int used_atom_cnt, need_tagged, need_symref; 216 217 /* 218 * Expand string, append it to strbuf *sb, then return error code ret. 219 * Allow to save few lines of code. 220 */ 221 __attribute__((format (printf, 3, 4))) 222 static int strbuf_addf_ret(struct strbuf *sb, int ret, const char *fmt, ...) 223 { 224 va_list ap; 225 va_start(ap, fmt); 226 strbuf_vaddf(sb, fmt, ap); 227 va_end(ap); 228 return ret; 229 } 230 231 static int color_atom_parser(struct ref_format *format, struct used_atom *atom, 232 const char *color_value, struct strbuf *err) 233 { 234 if (!color_value) 235 return strbuf_addf_ret(err, -1, _("expected format: %%(color:<color>)")); 236 if (color_parse(color_value, atom->u.color) < 0) 237 return strbuf_addf_ret(err, -1, _("unrecognized color: %%(color:%s)"), 238 color_value); 239 /* 240 * We check this after we've parsed the color, which lets us complain 241 * about syntactically bogus color names even if they won't be used. 242 */ 243 if (!want_color(format->use_color)) 244 color_parse("", atom->u.color); 245 return 0; 246 } 247 248 static int refname_atom_parser_internal(struct refname_atom *atom, const char *arg, 249 const char *name, struct strbuf *err) 250 { 251 if (!arg) 252 atom->option = R_NORMAL; 253 else if (!strcmp(arg, "short")) 254 atom->option = R_SHORT; 255 else if (skip_prefix(arg, "lstrip=", &arg) || 256 skip_prefix(arg, "strip=", &arg)) { 257 atom->option = R_LSTRIP; 258 if (strtol_i(arg, 10, &atom->lstrip)) 259 return strbuf_addf_ret(err, -1, _("Integer value expected refname:lstrip=%s"), arg); 260 } else if (skip_prefix(arg, "rstrip=", &arg)) { 261 atom->option = R_RSTRIP; 262 if (strtol_i(arg, 10, &atom->rstrip)) 263 return strbuf_addf_ret(err, -1, _("Integer value expected refname:rstrip=%s"), arg); 264 } else 265 return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), name, arg); 266 return 0; 267 } 268 269 static int remote_ref_atom_parser(struct ref_format *format, struct used_atom *atom, 270 const char *arg, struct strbuf *err) 271 { 272 struct string_list params = STRING_LIST_INIT_DUP; 273 int i; 274 275 if (!strcmp(atom->name, "push") || starts_with(atom->name, "push:")) 276 atom->u.remote_ref.push = 1; 277 278 if (!arg) { 279 atom->u.remote_ref.option = RR_REF; 280 return refname_atom_parser_internal(&atom->u.remote_ref.refname, 281 arg, atom->name, err); 282 } 283 284 atom->u.remote_ref.nobracket = 0; 285 string_list_split(¶ms, arg, ',', -1); 286 287 for (i = 0; i < params.nr; i++) { 288 const char *s = params.items[i].string; 289 290 if (!strcmp(s, "track")) 291 atom->u.remote_ref.option = RR_TRACK; 292 else if (!strcmp(s, "trackshort")) 293 atom->u.remote_ref.option = RR_TRACKSHORT; 294 else if (!strcmp(s, "nobracket")) 295 atom->u.remote_ref.nobracket = 1; 296 else if (!strcmp(s, "remotename")) { 297 atom->u.remote_ref.option = RR_REMOTE_NAME; 298 atom->u.remote_ref.push_remote = 1; 299 } else if (!strcmp(s, "remoteref")) { 300 atom->u.remote_ref.option = RR_REMOTE_REF; 301 atom->u.remote_ref.push_remote = 1; 302 } else { 303 atom->u.remote_ref.option = RR_REF; 304 if (refname_atom_parser_internal(&atom->u.remote_ref.refname, 305 arg, atom->name, err)) { 306 string_list_clear(¶ms, 0); 307 return -1; 308 } 309 } 310 } 311 312 string_list_clear(¶ms, 0); 313 return 0; 314 } 315 316 static int objecttype_atom_parser(struct ref_format *format, struct used_atom *atom, 317 const char *arg, struct strbuf *err) 318 { 319 if (arg) 320 return strbuf_addf_ret(err, -1, _("%%(objecttype) does not take arguments")); 321 if (*atom->name == '*') 322 oi_deref.info.typep = &oi_deref.type; 323 else 324 oi.info.typep = &oi.type; 325 return 0; 326 } 327 328 static int objectsize_atom_parser(struct ref_format *format, struct used_atom *atom, 329 const char *arg, struct strbuf *err) 330 { 331 if (!arg) { 332 atom->u.objectsize.option = O_SIZE; 333 if (*atom->name == '*') 334 oi_deref.info.sizep = &oi_deref.size; 335 else 336 oi.info.sizep = &oi.size; 337 } else if (!strcmp(arg, "disk")) { 338 atom->u.objectsize.option = O_SIZE_DISK; 339 if (*atom->name == '*') 340 oi_deref.info.disk_sizep = &oi_deref.disk_size; 341 else 342 oi.info.disk_sizep = &oi.disk_size; 343 } else 344 return strbuf_addf_ret(err, -1, _("unrecognized %%(objectsize) argument: %s"), arg); 345 return 0; 346 } 347 348 static int deltabase_atom_parser(struct ref_format *format, struct used_atom *atom, 349 const char *arg, struct strbuf *err) 350 { 351 if (arg) 352 return strbuf_addf_ret(err, -1, _("%%(deltabase) does not take arguments")); 353 if (*atom->name == '*') 354 oi_deref.info.delta_base_oid = &oi_deref.delta_base_oid; 355 else 356 oi.info.delta_base_oid = &oi.delta_base_oid; 357 return 0; 358 } 359 360 static int body_atom_parser(struct ref_format *format, struct used_atom *atom, 361 const char *arg, struct strbuf *err) 362 { 363 if (arg) 364 return strbuf_addf_ret(err, -1, _("%%(body) does not take arguments")); 365 atom->u.contents.option = C_BODY_DEP; 366 return 0; 367 } 368 369 static int subject_atom_parser(struct ref_format *format, struct used_atom *atom, 370 const char *arg, struct strbuf *err) 371 { 372 if (!arg) 373 atom->u.contents.option = C_SUB; 374 else if (!strcmp(arg, "sanitize")) 375 atom->u.contents.option = C_SUB_SANITIZE; 376 else 377 return strbuf_addf_ret(err, -1, _("unrecognized %%(subject) argument: %s"), arg); 378 return 0; 379 } 380 381 static int trailers_atom_parser(struct ref_format *format, struct used_atom *atom, 382 const char *arg, struct strbuf *err) 383 { 384 atom->u.contents.trailer_opts.no_divider = 1; 385 386 if (arg) { 387 const char *argbuf = xstrfmt("%s)", arg); 388 char *invalid_arg = NULL; 389 390 if (format_set_trailers_options(&atom->u.contents.trailer_opts, 391 &ref_trailer_buf.filter_list, 392 &ref_trailer_buf.sepbuf, 393 &ref_trailer_buf.kvsepbuf, 394 &argbuf, &invalid_arg)) { 395 if (!invalid_arg) 396 strbuf_addf(err, _("expected %%(trailers:key=<value>)")); 397 else 398 strbuf_addf(err, _("unknown %%(trailers) argument: %s"), invalid_arg); 399 free((char *)invalid_arg); 400 return -1; 401 } 402 } 403 atom->u.contents.option = C_TRAILERS; 404 return 0; 405 } 406 407 static int contents_atom_parser(struct ref_format *format, struct used_atom *atom, 408 const char *arg, struct strbuf *err) 409 { 410 if (!arg) 411 atom->u.contents.option = C_BARE; 412 else if (!strcmp(arg, "body")) 413 atom->u.contents.option = C_BODY; 414 else if (!strcmp(arg, "size")) 415 atom->u.contents.option = C_LENGTH; 416 else if (!strcmp(arg, "signature")) 417 atom->u.contents.option = C_SIG; 418 else if (!strcmp(arg, "subject")) 419 atom->u.contents.option = C_SUB; 420 else if (!strcmp(arg, "trailers")) { 421 if (trailers_atom_parser(format, atom, NULL, err)) 422 return -1; 423 } else if (skip_prefix(arg, "trailers:", &arg)) { 424 if (trailers_atom_parser(format, atom, arg, err)) 425 return -1; 426 } else if (skip_prefix(arg, "lines=", &arg)) { 427 atom->u.contents.option = C_LINES; 428 if (strtoul_ui(arg, 10, &atom->u.contents.nlines)) 429 return strbuf_addf_ret(err, -1, _("positive value expected contents:lines=%s"), arg); 430 } else 431 return strbuf_addf_ret(err, -1, _("unrecognized %%(contents) argument: %s"), arg); 432 return 0; 433 } 434 435 static int raw_atom_parser(struct ref_format *format, struct used_atom *atom, 436 const char *arg, struct strbuf *err) 437 { 438 if (!arg) 439 atom->u.raw_data.option = RAW_BARE; 440 else if (!strcmp(arg, "size")) 441 atom->u.raw_data.option = RAW_LENGTH; 442 else 443 return strbuf_addf_ret(err, -1, _("unrecognized %%(raw) argument: %s"), arg); 444 return 0; 445 } 446 447 static int oid_atom_parser(struct ref_format *format, struct used_atom *atom, 448 const char *arg, struct strbuf *err) 449 { 450 if (!arg) 451 atom->u.oid.option = O_FULL; 452 else if (!strcmp(arg, "short")) 453 atom->u.oid.option = O_SHORT; 454 else if (skip_prefix(arg, "short=", &arg)) { 455 atom->u.oid.option = O_LENGTH; 456 if (strtoul_ui(arg, 10, &atom->u.oid.length) || 457 atom->u.oid.length == 0) 458 return strbuf_addf_ret(err, -1, _("positive value expected '%s' in %%(%s)"), arg, atom->name); 459 if (atom->u.oid.length < MINIMUM_ABBREV) 460 atom->u.oid.length = MINIMUM_ABBREV; 461 } else 462 return strbuf_addf_ret(err, -1, _("unrecognized argument '%s' in %%(%s)"), arg, atom->name); 463 return 0; 464 } 465 466 static int person_email_atom_parser(struct ref_format *format, struct used_atom *atom, 467 const char *arg, struct strbuf *err) 468 { 469 if (!arg) 470 atom->u.email_option.option = EO_RAW; 471 else if (!strcmp(arg, "trim")) 472 atom->u.email_option.option = EO_TRIM; 473 else if (!strcmp(arg, "localpart")) 474 atom->u.email_option.option = EO_LOCALPART; 475 else 476 return strbuf_addf_ret(err, -1, _("unrecognized email option: %s"), arg); 477 return 0; 478 } 479 480 static int refname_atom_parser(struct ref_format *format, struct used_atom *atom, 481 const char *arg, struct strbuf *err) 482 { 483 return refname_atom_parser_internal(&atom->u.refname, arg, atom->name, err); 484 } 485 486 static align_type parse_align_position(const char *s) 487 { 488 if (!strcmp(s, "right")) 489 return ALIGN_RIGHT; 490 else if (!strcmp(s, "middle")) 491 return ALIGN_MIDDLE; 492 else if (!strcmp(s, "left")) 493 return ALIGN_LEFT; 494 return -1; 495 } 496 497 static int align_atom_parser(struct ref_format *format, struct used_atom *atom, 498 const char *arg, struct strbuf *err) 499 { 500 struct align *align = &atom->u.align; 501 struct string_list params = STRING_LIST_INIT_DUP; 502 int i; 503 unsigned int width = ~0U; 504 505 if (!arg) 506 return strbuf_addf_ret(err, -1, _("expected format: %%(align:<width>,<position>)")); 507 508 align->position = ALIGN_LEFT; 509 510 string_list_split(¶ms, arg, ',', -1); 511 for (i = 0; i < params.nr; i++) { 512 const char *s = params.items[i].string; 513 int position; 514 515 if (skip_prefix(s, "position=", &s)) { 516 position = parse_align_position(s); 517 if (position < 0) { 518 strbuf_addf(err, _("unrecognized position:%s"), s); 519 string_list_clear(¶ms, 0); 520 return -1; 521 } 522 align->position = position; 523 } else if (skip_prefix(s, "width=", &s)) { 524 if (strtoul_ui(s, 10, &width)) { 525 strbuf_addf(err, _("unrecognized width:%s"), s); 526 string_list_clear(¶ms, 0); 527 return -1; 528 } 529 } else if (!strtoul_ui(s, 10, &width)) 530 ; 531 else if ((position = parse_align_position(s)) >= 0) 532 align->position = position; 533 else { 534 strbuf_addf(err, _("unrecognized %%(align) argument: %s"), s); 535 string_list_clear(¶ms, 0); 536 return -1; 537 } 538 } 539 540 if (width == ~0U) { 541 string_list_clear(¶ms, 0); 542 return strbuf_addf_ret(err, -1, _("positive width expected with the %%(align) atom")); 543 } 544 align->width = width; 545 string_list_clear(¶ms, 0); 546 return 0; 547 } 548 549 static int if_atom_parser(struct ref_format *format, struct used_atom *atom, 550 const char *arg, struct strbuf *err) 551 { 552 if (!arg) { 553 atom->u.if_then_else.cmp_status = COMPARE_NONE; 554 return 0; 555 } else if (skip_prefix(arg, "equals=", &atom->u.if_then_else.str)) { 556 atom->u.if_then_else.cmp_status = COMPARE_EQUAL; 557 } else if (skip_prefix(arg, "notequals=", &atom->u.if_then_else.str)) { 558 atom->u.if_then_else.cmp_status = COMPARE_UNEQUAL; 559 } else 560 return strbuf_addf_ret(err, -1, _("unrecognized %%(if) argument: %s"), arg); 561 return 0; 562 } 563 564 static int rest_atom_parser(struct ref_format *format, struct used_atom *atom, 565 const char *arg, struct strbuf *err) 566 { 567 if (arg) 568 return strbuf_addf_ret(err, -1, _("%%(rest) does not take arguments")); 569 format->use_rest = 1; 570 return 0; 571 } 572 573 static int head_atom_parser(struct ref_format *format, struct used_atom *atom, 574 const char *arg, struct strbuf *unused_err) 575 { 576 atom->u.head = resolve_refdup("HEAD", RESOLVE_REF_READING, NULL, NULL); 577 return 0; 578 } 579 580 static struct { 581 const char *name; 582 info_source source; 583 cmp_type cmp_type; 584 int (*parser)(struct ref_format *format, struct used_atom *atom, 585 const char *arg, struct strbuf *err); 586 } valid_atom[] = { 587 [ATOM_REFNAME] = { "refname", SOURCE_NONE, FIELD_STR, refname_atom_parser }, 588 [ATOM_OBJECTTYPE] = { "objecttype", SOURCE_OTHER, FIELD_STR, objecttype_atom_parser }, 589 [ATOM_OBJECTSIZE] = { "objectsize", SOURCE_OTHER, FIELD_ULONG, objectsize_atom_parser }, 590 [ATOM_OBJECTNAME] = { "objectname", SOURCE_OTHER, FIELD_STR, oid_atom_parser }, 591 [ATOM_DELTABASE] = { "deltabase", SOURCE_OTHER, FIELD_STR, deltabase_atom_parser }, 592 [ATOM_TREE] = { "tree", SOURCE_OBJ, FIELD_STR, oid_atom_parser }, 593 [ATOM_PARENT] = { "parent", SOURCE_OBJ, FIELD_STR, oid_atom_parser }, 594 [ATOM_NUMPARENT] = { "numparent", SOURCE_OBJ, FIELD_ULONG }, 595 [ATOM_OBJECT] = { "object", SOURCE_OBJ }, 596 [ATOM_TYPE] = { "type", SOURCE_OBJ }, 597 [ATOM_TAG] = { "tag", SOURCE_OBJ }, 598 [ATOM_AUTHOR] = { "author", SOURCE_OBJ }, 599 [ATOM_AUTHORNAME] = { "authorname", SOURCE_OBJ }, 600 [ATOM_AUTHOREMAIL] = { "authoremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser }, 601 [ATOM_AUTHORDATE] = { "authordate", SOURCE_OBJ, FIELD_TIME }, 602 [ATOM_COMMITTER] = { "committer", SOURCE_OBJ }, 603 [ATOM_COMMITTERNAME] = { "committername", SOURCE_OBJ }, 604 [ATOM_COMMITTEREMAIL] = { "committeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser }, 605 [ATOM_COMMITTERDATE] = { "committerdate", SOURCE_OBJ, FIELD_TIME }, 606 [ATOM_TAGGER] = { "tagger", SOURCE_OBJ }, 607 [ATOM_TAGGERNAME] = { "taggername", SOURCE_OBJ }, 608 [ATOM_TAGGEREMAIL] = { "taggeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser }, 609 [ATOM_TAGGERDATE] = { "taggerdate", SOURCE_OBJ, FIELD_TIME }, 610 [ATOM_CREATOR] = { "creator", SOURCE_OBJ }, 611 [ATOM_CREATORDATE] = { "creatordate", SOURCE_OBJ, FIELD_TIME }, 612 [ATOM_SUBJECT] = { "subject", SOURCE_OBJ, FIELD_STR, subject_atom_parser }, 613 [ATOM_BODY] = { "body", SOURCE_OBJ, FIELD_STR, body_atom_parser }, 614 [ATOM_TRAILERS] = { "trailers", SOURCE_OBJ, FIELD_STR, trailers_atom_parser }, 615 [ATOM_CONTENTS] = { "contents", SOURCE_OBJ, FIELD_STR, contents_atom_parser }, 616 [ATOM_RAW] = { "raw", SOURCE_OBJ, FIELD_STR, raw_atom_parser }, 617 [ATOM_UPSTREAM] = { "upstream", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser }, 618 [ATOM_PUSH] = { "push", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser }, 619 [ATOM_SYMREF] = { "symref", SOURCE_NONE, FIELD_STR, refname_atom_parser }, 620 [ATOM_FLAG] = { "flag", SOURCE_NONE }, 621 [ATOM_HEAD] = { "HEAD", SOURCE_NONE, FIELD_STR, head_atom_parser }, 622 [ATOM_COLOR] = { "color", SOURCE_NONE, FIELD_STR, color_atom_parser }, 623 [ATOM_WORKTREEPATH] = { "worktreepath", SOURCE_NONE }, 624 [ATOM_ALIGN] = { "align", SOURCE_NONE, FIELD_STR, align_atom_parser }, 625 [ATOM_END] = { "end", SOURCE_NONE }, 626 [ATOM_IF] = { "if", SOURCE_NONE, FIELD_STR, if_atom_parser }, 627 [ATOM_THEN] = { "then", SOURCE_NONE }, 628 [ATOM_ELSE] = { "else", SOURCE_NONE }, 629 [ATOM_REST] = { "rest", SOURCE_NONE, FIELD_STR, rest_atom_parser }, 630 /* 631 * Please update $__git_ref_fieldlist in git-completion.bash 632 * when you add new atoms 633 */ 634 }; 635 636 #define REF_FORMATTING_STATE_INIT { 0 } 637 638 struct ref_formatting_stack { 639 struct ref_formatting_stack *prev; 640 struct strbuf output; 641 void (*at_end)(struct ref_formatting_stack **stack); 642 void *at_end_data; 643 }; 644 645 struct ref_formatting_state { 646 int quote_style; 647 struct ref_formatting_stack *stack; 648 }; 649 650 struct atom_value { 651 const char *s; 652 ssize_t s_size; 653 int (*handler)(struct atom_value *atomv, struct ref_formatting_state *state, 654 struct strbuf *err); 655 uintmax_t value; /* used for sorting when not FIELD_STR */ 656 struct used_atom *atom; 657 }; 658 659 #define ATOM_SIZE_UNSPECIFIED (-1) 660 661 #define ATOM_VALUE_INIT { \ 662 .s_size = ATOM_SIZE_UNSPECIFIED \ 663 } 664 665 /* 666 * Used to parse format string and sort specifiers 667 */ 668 static int parse_ref_filter_atom(struct ref_format *format, 669 const char *atom, const char *ep, 670 struct strbuf *err) 671 { 672 const char *sp; 673 const char *arg; 674 int i, at, atom_len; 675 676 sp = atom; 677 if (*sp == '*' && sp < ep) 678 sp++; /* deref */ 679 if (ep <= sp) 680 return strbuf_addf_ret(err, -1, _("malformed field name: %.*s"), 681 (int)(ep-atom), atom); 682 683 /* 684 * If the atom name has a colon, strip it and everything after 685 * it off - it specifies the format for this entry, and 686 * shouldn't be used for checking against the valid_atom 687 * table. 688 */ 689 arg = memchr(sp, ':', ep - sp); 690 atom_len = (arg ? arg : ep) - sp; 691 692 /* Do we have the atom already used elsewhere? */ 693 for (i = 0; i < used_atom_cnt; i++) { 694 int len = strlen(used_atom[i].name); 695 if (len == ep - atom && !memcmp(used_atom[i].name, atom, len)) 696 return i; 697 } 698 699 /* Is the atom a valid one? */ 700 for (i = 0; i < ARRAY_SIZE(valid_atom); i++) { 701 int len = strlen(valid_atom[i].name); 702 if (len == atom_len && !memcmp(valid_atom[i].name, sp, len)) 703 break; 704 } 705 706 if (ARRAY_SIZE(valid_atom) <= i) 707 return strbuf_addf_ret(err, -1, _("unknown field name: %.*s"), 708 (int)(ep-atom), atom); 709 if (valid_atom[i].source != SOURCE_NONE && !have_git_dir()) 710 return strbuf_addf_ret(err, -1, 711 _("not a git repository, but the field '%.*s' requires access to object data"), 712 (int)(ep-atom), atom); 713 714 /* Add it in, including the deref prefix */ 715 at = used_atom_cnt; 716 used_atom_cnt++; 717 REALLOC_ARRAY(used_atom, used_atom_cnt); 718 used_atom[at].atom_type = i; 719 used_atom[at].name = xmemdupz(atom, ep - atom); 720 used_atom[at].type = valid_atom[i].cmp_type; 721 used_atom[at].source = valid_atom[i].source; 722 if (used_atom[at].source == SOURCE_OBJ) { 723 if (*atom == '*') 724 oi_deref.info.contentp = &oi_deref.content; 725 else 726 oi.info.contentp = &oi.content; 727 } 728 if (arg) { 729 arg = used_atom[at].name + (arg - atom) + 1; 730 if (!*arg) { 731 /* 732 * Treat empty sub-arguments list as NULL (i.e., 733 * "%(atom:)" is equivalent to "%(atom)"). 734 */ 735 arg = NULL; 736 } 737 } 738 memset(&used_atom[at].u, 0, sizeof(used_atom[at].u)); 739 if (valid_atom[i].parser && valid_atom[i].parser(format, &used_atom[at], arg, err)) 740 return -1; 741 if (*atom == '*') 742 need_tagged = 1; 743 if (i == ATOM_SYMREF) 744 need_symref = 1; 745 return at; 746 } 747 748 static void quote_formatting(struct strbuf *s, const char *str, ssize_t len, int quote_style) 749 { 750 switch (quote_style) { 751 case QUOTE_NONE: 752 if (len < 0) 753 strbuf_addstr(s, str); 754 else 755 strbuf_add(s, str, len); 756 break; 757 case QUOTE_SHELL: 758 sq_quote_buf(s, str); 759 break; 760 case QUOTE_PERL: 761 if (len < 0) 762 perl_quote_buf(s, str); 763 else 764 perl_quote_buf_with_len(s, str, len); 765 break; 766 case QUOTE_PYTHON: 767 python_quote_buf(s, str); 768 break; 769 case QUOTE_TCL: 770 tcl_quote_buf(s, str); 771 break; 772 } 773 } 774 775 static int append_atom(struct atom_value *v, struct ref_formatting_state *state, 776 struct strbuf *unused_err) 777 { 778 /* 779 * Quote formatting is only done when the stack has a single 780 * element. Otherwise quote formatting is done on the 781 * element's entire output strbuf when the %(end) atom is 782 * encountered. 783 */ 784 if (!state->stack->prev) 785 quote_formatting(&state->stack->output, v->s, v->s_size, state->quote_style); 786 else if (v->s_size < 0) 787 strbuf_addstr(&state->stack->output, v->s); 788 else 789 strbuf_add(&state->stack->output, v->s, v->s_size); 790 return 0; 791 } 792 793 static void push_stack_element(struct ref_formatting_stack **stack) 794 { 795 struct ref_formatting_stack *s = xcalloc(1, sizeof(struct ref_formatting_stack)); 796 797 strbuf_init(&s->output, 0); 798 s->prev = *stack; 799 *stack = s; 800 } 801 802 static void pop_stack_element(struct ref_formatting_stack **stack) 803 { 804 struct ref_formatting_stack *current = *stack; 805 struct ref_formatting_stack *prev = current->prev; 806 807 if (prev) 808 strbuf_addbuf(&prev->output, ¤t->output); 809 strbuf_release(¤t->output); 810 free(current); 811 *stack = prev; 812 } 813 814 static void end_align_handler(struct ref_formatting_stack **stack) 815 { 816 struct ref_formatting_stack *cur = *stack; 817 struct align *align = (struct align *)cur->at_end_data; 818 struct strbuf s = STRBUF_INIT; 819 820 strbuf_utf8_align(&s, align->position, align->width, cur->output.buf); 821 strbuf_swap(&cur->output, &s); 822 strbuf_release(&s); 823 } 824 825 static int align_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state, 826 struct strbuf *unused_err) 827 { 828 struct ref_formatting_stack *new_stack; 829 830 push_stack_element(&state->stack); 831 new_stack = state->stack; 832 new_stack->at_end = end_align_handler; 833 new_stack->at_end_data = &atomv->atom->u.align; 834 return 0; 835 } 836 837 static void if_then_else_handler(struct ref_formatting_stack **stack) 838 { 839 struct ref_formatting_stack *cur = *stack; 840 struct ref_formatting_stack *prev = cur->prev; 841 struct if_then_else *if_then_else = (struct if_then_else *)cur->at_end_data; 842 843 if (!if_then_else->then_atom_seen) 844 die(_("format: %%(if) atom used without a %%(then) atom")); 845 846 if (if_then_else->else_atom_seen) { 847 /* 848 * There is an %(else) atom: we need to drop one state from the 849 * stack, either the %(else) branch if the condition is satisfied, or 850 * the %(then) branch if it isn't. 851 */ 852 if (if_then_else->condition_satisfied) { 853 strbuf_reset(&cur->output); 854 pop_stack_element(&cur); 855 } else { 856 strbuf_swap(&cur->output, &prev->output); 857 strbuf_reset(&cur->output); 858 pop_stack_element(&cur); 859 } 860 } else if (!if_then_else->condition_satisfied) { 861 /* 862 * No %(else) atom: just drop the %(then) branch if the 863 * condition is not satisfied. 864 */ 865 strbuf_reset(&cur->output); 866 } 867 868 *stack = cur; 869 free(if_then_else); 870 } 871 872 static int if_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state, 873 struct strbuf *unused_err) 874 { 875 struct ref_formatting_stack *new_stack; 876 struct if_then_else *if_then_else = xcalloc(1, 877 sizeof(struct if_then_else)); 878 879 if_then_else->str = atomv->atom->u.if_then_else.str; 880 if_then_else->cmp_status = atomv->atom->u.if_then_else.cmp_status; 881 882 push_stack_element(&state->stack); 883 new_stack = state->stack; 884 new_stack->at_end = if_then_else_handler; 885 new_stack->at_end_data = if_then_else; 886 return 0; 887 } 888 889 static int is_empty(struct strbuf *buf) 890 { 891 const char *cur = buf->buf; 892 const char *end = buf->buf + buf->len; 893 894 while (cur != end && (isspace(*cur))) 895 cur++; 896 897 return cur == end; 898 } 899 900 static int then_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state, 901 struct strbuf *err) 902 { 903 struct ref_formatting_stack *cur = state->stack; 904 struct if_then_else *if_then_else = NULL; 905 size_t str_len = 0; 906 907 if (cur->at_end == if_then_else_handler) 908 if_then_else = (struct if_then_else *)cur->at_end_data; 909 if (!if_then_else) 910 return strbuf_addf_ret(err, -1, _("format: %%(then) atom used without an %%(if) atom")); 911 if (if_then_else->then_atom_seen) 912 return strbuf_addf_ret(err, -1, _("format: %%(then) atom used more than once")); 913 if (if_then_else->else_atom_seen) 914 return strbuf_addf_ret(err, -1, _("format: %%(then) atom used after %%(else)")); 915 if_then_else->then_atom_seen = 1; 916 if (if_then_else->str) 917 str_len = strlen(if_then_else->str); 918 /* 919 * If the 'equals' or 'notequals' attribute is used then 920 * perform the required comparison. If not, only non-empty 921 * strings satisfy the 'if' condition. 922 */ 923 if (if_then_else->cmp_status == COMPARE_EQUAL) { 924 if (str_len == cur->output.len && 925 !memcmp(if_then_else->str, cur->output.buf, cur->output.len)) 926 if_then_else->condition_satisfied = 1; 927 } else if (if_then_else->cmp_status == COMPARE_UNEQUAL) { 928 if (str_len != cur->output.len || 929 memcmp(if_then_else->str, cur->output.buf, cur->output.len)) 930 if_then_else->condition_satisfied = 1; 931 } else if (cur->output.len && !is_empty(&cur->output)) 932 if_then_else->condition_satisfied = 1; 933 strbuf_reset(&cur->output); 934 return 0; 935 } 936 937 static int else_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state, 938 struct strbuf *err) 939 { 940 struct ref_formatting_stack *prev = state->stack; 941 struct if_then_else *if_then_else = NULL; 942 943 if (prev->at_end == if_then_else_handler) 944 if_then_else = (struct if_then_else *)prev->at_end_data; 945 if (!if_then_else) 946 return strbuf_addf_ret(err, -1, _("format: %%(else) atom used without an %%(if) atom")); 947 if (!if_then_else->then_atom_seen) 948 return strbuf_addf_ret(err, -1, _("format: %%(else) atom used without a %%(then) atom")); 949 if (if_then_else->else_atom_seen) 950 return strbuf_addf_ret(err, -1, _("format: %%(else) atom used more than once")); 951 if_then_else->else_atom_seen = 1; 952 push_stack_element(&state->stack); 953 state->stack->at_end_data = prev->at_end_data; 954 state->stack->at_end = prev->at_end; 955 return 0; 956 } 957 958 static int end_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state, 959 struct strbuf *err) 960 { 961 struct ref_formatting_stack *current = state->stack; 962 struct strbuf s = STRBUF_INIT; 963 964 if (!current->at_end) 965 return strbuf_addf_ret(err, -1, _("format: %%(end) atom used without corresponding atom")); 966 current->at_end(&state->stack); 967 968 /* Stack may have been popped within at_end(), hence reset the current pointer */ 969 current = state->stack; 970 971 /* 972 * Perform quote formatting when the stack element is that of 973 * a supporting atom. If nested then perform quote formatting 974 * only on the topmost supporting atom. 975 */ 976 if (!current->prev->prev) { 977 quote_formatting(&s, current->output.buf, current->output.len, state->quote_style); 978 strbuf_swap(¤t->output, &s); 979 } 980 strbuf_release(&s); 981 pop_stack_element(&state->stack); 982 return 0; 983 } 984 985 /* 986 * In a format string, find the next occurrence of %(atom). 987 */ 988 static const char *find_next(const char *cp) 989 { 990 while (*cp) { 991 if (*cp == '%') { 992 /* 993 * %( is the start of an atom; 994 * %% is a quoted per-cent. 995 */ 996 if (cp[1] == '(') 997 return cp; 998 else if (cp[1] == '%') 999 cp++; /* skip over two % */ 1000 /* otherwise this is a singleton, literal % */ 1001 } 1002 cp++; 1003 } 1004 return NULL; 1005 } 1006 1007 static int reject_atom(enum atom_type atom_type) 1008 { 1009 return atom_type == ATOM_REST; 1010 } 1011 1012 /* 1013 * Make sure the format string is well formed, and parse out 1014 * the used atoms. 1015 */ 1016 int verify_ref_format(struct ref_format *format) 1017 { 1018 const char *cp, *sp; 1019 1020 format->need_color_reset_at_eol = 0; 1021 for (cp = format->format; *cp && (sp = find_next(cp)); ) { 1022 struct strbuf err = STRBUF_INIT; 1023 const char *color, *ep = strchr(sp, ')'); 1024 int at; 1025 1026 if (!ep) 1027 return error(_("malformed format string %s"), sp); 1028 /* sp points at "%(" and ep points at the closing ")" */ 1029 at = parse_ref_filter_atom(format, sp + 2, ep, &err); 1030 if (at < 0) 1031 die("%s", err.buf); 1032 if (reject_atom(used_atom[at].atom_type)) 1033 die(_("this command reject atom %%(%.*s)"), (int)(ep - sp - 2), sp + 2); 1034 1035 if ((format->quote_style == QUOTE_PYTHON || 1036 format->quote_style == QUOTE_SHELL || 1037 format->quote_style == QUOTE_TCL) && 1038 used_atom[at].atom_type == ATOM_RAW && 1039 used_atom[at].u.raw_data.option == RAW_BARE) 1040 die(_("--format=%.*s cannot be used with " 1041 "--python, --shell, --tcl"), (int)(ep - sp - 2), sp + 2); 1042 cp = ep + 1; 1043 1044 if (skip_prefix(used_atom[at].name, "color:", &color)) 1045 format->need_color_reset_at_eol = !!strcmp(color, "reset"); 1046 strbuf_release(&err); 1047 } 1048 if (format->need_color_reset_at_eol && !want_color(format->use_color)) 1049 format->need_color_reset_at_eol = 0; 1050 return 0; 1051 } 1052 1053 static const char *do_grab_oid(const char *field, const struct object_id *oid, 1054 struct used_atom *atom) 1055 { 1056 switch (atom->u.oid.option) { 1057 case O_FULL: 1058 return oid_to_hex(oid); 1059 case O_LENGTH: 1060 return find_unique_abbrev(oid, atom->u.oid.length); 1061 case O_SHORT: 1062 return find_unique_abbrev(oid, DEFAULT_ABBREV); 1063 default: 1064 BUG("unknown %%(%s) option", field); 1065 } 1066 } 1067 1068 static int grab_oid(const char *name, const char *field, const struct object_id *oid, 1069 struct atom_value *v, struct used_atom *atom) 1070 { 1071 if (starts_with(name, field)) { 1072 v->s = xstrdup(do_grab_oid(field, oid, atom)); 1073 return 1; 1074 } 1075 return 0; 1076 } 1077 1078 /* See grab_values */ 1079 static void grab_common_values(struct atom_value *val, int deref, struct expand_data *oi) 1080 { 1081 int i; 1082 1083 for (i = 0; i < used_atom_cnt; i++) { 1084 const char *name = used_atom[i].name; 1085 enum atom_type atom_type = used_atom[i].atom_type; 1086 struct atom_value *v = &val[i]; 1087 if (!!deref != (*name == '*')) 1088 continue; 1089 if (deref) 1090 name++; 1091 if (atom_type == ATOM_OBJECTTYPE) 1092 v->s = xstrdup(type_name(oi->type)); 1093 else if (atom_type == ATOM_OBJECTSIZE) { 1094 if (used_atom[i].u.objectsize.option == O_SIZE_DISK) { 1095 v->value = oi->disk_size; 1096 v->s = xstrfmt("%"PRIuMAX, (uintmax_t)oi->disk_size); 1097 } else if (used_atom[i].u.objectsize.option == O_SIZE) { 1098 v->value = oi->size; 1099 v->s = xstrfmt("%"PRIuMAX , (uintmax_t)oi->size); 1100 } 1101 } else if (atom_type == ATOM_DELTABASE) 1102 v->s = xstrdup(oid_to_hex(&oi->delta_base_oid)); 1103 else if (atom_type == ATOM_OBJECTNAME && deref) 1104 grab_oid(name, "objectname", &oi->oid, v, &used_atom[i]); 1105 } 1106 } 1107 1108 /* See grab_values */ 1109 static void grab_tag_values(struct atom_value *val, int deref, struct object *obj) 1110 { 1111 int i; 1112 struct tag *tag = (struct tag *) obj; 1113 1114 for (i = 0; i < used_atom_cnt; i++) { 1115 const char *name = used_atom[i].name; 1116 enum atom_type atom_type = used_atom[i].atom_type; 1117 struct atom_value *v = &val[i]; 1118 if (!!deref != (*name == '*')) 1119 continue; 1120 if (deref) 1121 name++; 1122 if (atom_type == ATOM_TAG) 1123 v->s = xstrdup(tag->tag); 1124 else if (atom_type == ATOM_TYPE && tag->tagged) 1125 v->s = xstrdup(type_name(tag->tagged->type)); 1126 else if (atom_type == ATOM_OBJECT && tag->tagged) 1127 v->s = xstrdup(oid_to_hex(&tag->tagged->oid)); 1128 } 1129 } 1130 1131 /* See grab_values */ 1132 static void grab_commit_values(struct atom_value *val, int deref, struct object *obj) 1133 { 1134 int i; 1135 struct commit *commit = (struct commit *) obj; 1136 1137 for (i = 0; i < used_atom_cnt; i++) { 1138 const char *name = used_atom[i].name; 1139 enum atom_type atom_type = used_atom[i].atom_type; 1140 struct atom_value *v = &val[i]; 1141 if (!!deref != (*name == '*')) 1142 continue; 1143 if (deref) 1144 name++; 1145 if (atom_type == ATOM_TREE && 1146 grab_oid(name, "tree", get_commit_tree_oid(commit), v, &used_atom[i])) 1147 continue; 1148 if (atom_type == ATOM_NUMPARENT) { 1149 v->value = commit_list_count(commit->parents); 1150 v->s = xstrfmt("%lu", (unsigned long)v->value); 1151 } 1152 else if (atom_type == ATOM_PARENT) { 1153 struct commit_list *parents; 1154 struct strbuf s = STRBUF_INIT; 1155 for (parents = commit->parents; parents; parents = parents->next) { 1156 struct object_id *oid = &parents->item->object.oid; 1157 if (parents != commit->parents) 1158 strbuf_addch(&s, ' '); 1159 strbuf_addstr(&s, do_grab_oid("parent", oid, &used_atom[i])); 1160 } 1161 v->s = strbuf_detach(&s, NULL); 1162 } 1163 } 1164 } 1165 1166 static const char *find_wholine(const char *who, int wholen, const char *buf) 1167 { 1168 const char *eol; 1169 while (*buf) { 1170 if (!strncmp(buf, who, wholen) && 1171 buf[wholen] == ' ') 1172 return buf + wholen + 1; 1173 eol = strchr(buf, '\n'); 1174 if (!eol) 1175 return ""; 1176 eol++; 1177 if (*eol == '\n') 1178 return ""; /* end of header */ 1179 buf = eol; 1180 } 1181 return ""; 1182 } 1183 1184 static const char *copy_line(const char *buf) 1185 { 1186 const char *eol = strchrnul(buf, '\n'); 1187 return xmemdupz(buf, eol - buf); 1188 } 1189 1190 static const char *copy_name(const char *buf) 1191 { 1192 const char *cp; 1193 for (cp = buf; *cp && *cp != '\n'; cp++) { 1194 if (!strncmp(cp, " <", 2)) 1195 return xmemdupz(buf, cp - buf); 1196 } 1197 return xstrdup(""); 1198 } 1199 1200 static const char *copy_email(const char *buf, struct used_atom *atom) 1201 { 1202 const char *email = strchr(buf, '<'); 1203 const char *eoemail; 1204 if (!email) 1205 return xstrdup(""); 1206 switch (atom->u.email_option.option) { 1207 case EO_RAW: 1208 eoemail = strchr(email, '>'); 1209 if (eoemail) 1210 eoemail++; 1211 break; 1212 case EO_TRIM: 1213 email++; 1214 eoemail = strchr(email, '>'); 1215 break; 1216 case EO_LOCALPART: 1217 email++; 1218 eoemail = strchr(email, '@'); 1219 if (!eoemail) 1220 eoemail = strchr(email, '>'); 1221 break; 1222 default: 1223 BUG("unknown email option"); 1224 } 1225 1226 if (!eoemail) 1227 return xstrdup(""); 1228 return xmemdupz(email, eoemail - email); 1229 } 1230 1231 static char *copy_subject(const char *buf, unsigned long len) 1232 { 1233 struct strbuf sb = STRBUF_INIT; 1234 int i; 1235 1236 for (i = 0; i < len; i++) { 1237 if (buf[i] == '\r' && i + 1 < len && buf[i + 1] == '\n') 1238 continue; /* ignore CR in CRLF */ 1239 1240 if (buf[i] == '\n') 1241 strbuf_addch(&sb, ' '); 1242 else 1243 strbuf_addch(&sb, buf[i]); 1244 } 1245 return strbuf_detach(&sb, NULL); 1246 } 1247 1248 static void grab_date(const char *buf, struct atom_value *v, const char *atomname) 1249 { 1250 const char *eoemail = strstr(buf, "> "); 1251 char *zone; 1252 timestamp_t timestamp; 1253 long tz; 1254 struct date_mode date_mode = { DATE_NORMAL }; 1255 const char *formatp; 1256 1257 /* 1258 * We got here because atomname ends in "date" or "date<something>"; 1259 * it's not possible that <something> is not ":<format>" because 1260 * parse_ref_filter_atom() wouldn't have allowed it, so we can assume that no 1261 * ":" means no format is specified, and use the default. 1262 */ 1263 formatp = strchr(atomname, ':'); 1264 if (formatp != NULL) { 1265 formatp++; 1266 parse_date_format(formatp, &date_mode); 1267 } 1268 1269 if (!eoemail) 1270 goto bad; 1271 timestamp = parse_timestamp(eoemail + 2, &zone, 10); 1272 if (timestamp == TIME_MAX) 1273 goto bad; 1274 tz = strtol(zone, NULL, 10); 1275 if ((tz == LONG_MIN || tz == LONG_MAX) && errno == ERANGE) 1276 goto bad; 1277 v->s = xstrdup(show_date(timestamp, tz, &date_mode)); 1278 v->value = timestamp; 1279 return; 1280 bad: 1281 v->s = xstrdup(""); 1282 v->value = 0; 1283 } 1284 1285 /* See grab_values */ 1286 static void grab_person(const char *who, struct atom_value *val, int deref, void *buf) 1287 { 1288 int i; 1289 int wholen = strlen(who); 1290 const char *wholine = NULL; 1291 1292 for (i = 0; i < used_atom_cnt; i++) { 1293 const char *name = used_atom[i].name; 1294 struct atom_value *v = &val[i]; 1295 if (!!deref != (*name == '*')) 1296 continue; 1297 if (deref) 1298 name++; 1299 if (strncmp(who, name, wholen)) 1300 continue; 1301 if (name[wholen] != 0 && 1302 strcmp(name + wholen, "name") && 1303 !starts_with(name + wholen, "email") && 1304 !starts_with(name + wholen, "date")) 1305 continue; 1306 if (!wholine) 1307 wholine = find_wholine(who, wholen, buf); 1308 if (!wholine) 1309 return; /* no point looking for it */ 1310 if (name[wholen] == 0) 1311 v->s = copy_line(wholine); 1312 else if (!strcmp(name + wholen, "name")) 1313 v->s = copy_name(wholine); 1314 else if (starts_with(name + wholen, "email")) 1315 v->s = copy_email(wholine, &used_atom[i]); 1316 else if (starts_with(name + wholen, "date")) 1317 grab_date(wholine, v, name); 1318 } 1319 1320 /* 1321 * For a tag or a commit object, if "creator" or "creatordate" is 1322 * requested, do something special. 1323 */ 1324 if (strcmp(who, "tagger") && strcmp(who, "committer")) 1325 return; /* "author" for commit object is not wanted */ 1326 if (!wholine) 1327 wholine = find_wholine(who, wholen, buf); 1328 if (!wholine) 1329 return; 1330 for (i = 0; i < used_atom_cnt; i++) { 1331 const char *name = used_atom[i].name; 1332 enum atom_type atom_type = used_atom[i].atom_type; 1333 struct atom_value *v = &val[i]; 1334 if (!!deref != (*name == '*')) 1335 continue; 1336 if (deref) 1337 name++; 1338 1339 if (atom_type == ATOM_CREATORDATE) 1340 grab_date(wholine, v, name); 1341 else if (atom_type == ATOM_CREATOR) 1342 v->s = copy_line(wholine); 1343 } 1344 } 1345 1346 static void find_subpos(const char *buf, 1347 const char **sub, size_t *sublen, 1348 const char **body, size_t *bodylen, 1349 size_t *nonsiglen, 1350 const char **sig, size_t *siglen) 1351 { 1352 struct strbuf payload = STRBUF_INIT; 1353 struct strbuf signature = STRBUF_INIT; 1354 const char *eol; 1355 const char *end = buf + strlen(buf); 1356 const char *sigstart; 1357 1358 /* parse signature first; we might not even have a subject line */ 1359 parse_signature(buf, end - buf, &payload, &signature); 1360 1361 /* skip past header until we hit empty line */ 1362 while (*buf && *buf != '\n') { 1363 eol = strchrnul(buf, '\n'); 1364 if (*eol) 1365 eol++; 1366 buf = eol; 1367 } 1368 /* skip any empty lines */ 1369 while (*buf == '\n') 1370 buf++; 1371 *sig = strbuf_detach(&signature, siglen); 1372 sigstart = buf + parse_signed_buffer(buf, strlen(buf)); 1373 1374 /* subject is first non-empty line */ 1375 *sub = buf; 1376 /* subject goes to first empty line before signature begins */ 1377 if ((eol = strstr(*sub, "\n\n"))) { 1378 eol = eol < sigstart ? eol : sigstart; 1379 /* check if message uses CRLF */ 1380 } else if (! (eol = strstr(*sub, "\r\n\r\n"))) { 1381 /* treat whole message as subject */ 1382 eol = strrchr(*sub, '\0'); 1383 } 1384 buf = eol; 1385 *sublen = buf - *sub; 1386 /* drop trailing newline, if present */ 1387 while (*sublen && ((*sub)[*sublen - 1] == '\n' || 1388 (*sub)[*sublen - 1] == '\r')) 1389 *sublen -= 1; 1390 1391 /* skip any empty lines */ 1392 while (*buf == '\n' || *buf == '\r') 1393 buf++; 1394 *body = buf; 1395 *bodylen = strlen(buf); 1396 *nonsiglen = sigstart - buf; 1397 } 1398 1399 /* 1400 * If 'lines' is greater than 0, append that many lines from the given 1401 * 'buf' of length 'size' to the given strbuf. 1402 */ 1403 static void append_lines(struct strbuf *out, const char *buf, unsigned long size, int lines) 1404 { 1405 int i; 1406 const char *sp, *eol; 1407 size_t len; 1408 1409 sp = buf; 1410 1411 for (i = 0; i < lines && sp < buf + size; i++) { 1412 if (i) 1413 strbuf_addstr(out, "\n "); 1414 eol = memchr(sp, '\n', size - (sp - buf)); 1415 len = eol ? eol - sp : size - (sp - buf); 1416 strbuf_add(out, sp, len); 1417 if (!eol) 1418 break; 1419 sp = eol + 1; 1420 } 1421 } 1422 1423 /* See grab_values */ 1424 static void grab_sub_body_contents(struct atom_value *val, int deref, struct expand_data *data) 1425 { 1426 int i; 1427 const char *subpos = NULL, *bodypos = NULL, *sigpos = NULL; 1428 size_t sublen = 0, bodylen = 0, nonsiglen = 0, siglen = 0; 1429 void *buf = data->content; 1430 1431 for (i = 0; i < used_atom_cnt; i++) { 1432 struct used_atom *atom = &used_atom[i]; 1433 const char *name = atom->name; 1434 struct atom_value *v = &val[i]; 1435 enum atom_type atom_type = atom->atom_type; 1436 1437 if (!!deref != (*name == '*')) 1438 continue; 1439 if (deref) 1440 name++; 1441 1442 if (atom_type == ATOM_RAW) { 1443 unsigned long buf_size = data->size; 1444 1445 if (atom->u.raw_data.option == RAW_BARE) { 1446 v->s = xmemdupz(buf, buf_size); 1447 v->s_size = buf_size; 1448 } else if (atom->u.raw_data.option == RAW_LENGTH) { 1449 v->s = xstrfmt("%"PRIuMAX, (uintmax_t)buf_size); 1450 } 1451 continue; 1452 } 1453 1454 if ((data->type != OBJ_TAG && 1455 data->type != OBJ_COMMIT) || 1456 (strcmp(name, "body") && 1457 !starts_with(name, "subject") && 1458 !starts_with(name, "trailers") && 1459 !starts_with(name, "contents"))) 1460 continue; 1461 if (!subpos) 1462 find_subpos(buf, 1463 &subpos, &sublen, 1464 &bodypos, &bodylen, &nonsiglen, 1465 &sigpos, &siglen); 1466 1467 if (atom->u.contents.option == C_SUB) 1468 v->s = copy_subject(subpos, sublen); 1469 else if (atom->u.contents.option == C_SUB_SANITIZE) { 1470 struct strbuf sb = STRBUF_INIT; 1471 format_sanitized_subject(&sb, subpos, sublen); 1472 v->s = strbuf_detach(&sb, NULL); 1473 } else if (atom->u.contents.option == C_BODY_DEP) 1474 v->s = xmemdupz(bodypos, bodylen); 1475 else if (atom->u.contents.option == C_LENGTH) 1476 v->s = xstrfmt("%"PRIuMAX, (uintmax_t)strlen(subpos)); 1477 else if (atom->u.contents.option == C_BODY) 1478 v->s = xmemdupz(bodypos, nonsiglen); 1479 else if (atom->u.contents.option == C_SIG) 1480 v->s = xmemdupz(sigpos, siglen); 1481 else if (atom->u.contents.option == C_LINES) { 1482 struct strbuf s = STRBUF_INIT; 1483 const char *contents_end = bodypos + nonsiglen; 1484 1485 /* Size is the length of the message after removing the signature */ 1486 append_lines(&s, subpos, contents_end - subpos, atom->u.contents.nlines); 1487 v->s = strbuf_detach(&s, NULL); 1488 } else if (atom->u.contents.option == C_TRAILERS) { 1489 struct strbuf s = STRBUF_INIT; 1490 1491 /* Format the trailer info according to the trailer_opts given */ 1492 format_trailers_from_commit(&s, subpos, &atom->u.contents.trailer_opts); 1493 1494 v->s = strbuf_detach(&s, NULL); 1495 } else if (atom->u.contents.option == C_BARE) 1496 v->s = xstrdup(subpos); 1497 1498 } 1499 free((void *)sigpos); 1500 } 1501 1502 /* 1503 * We want to have empty print-string for field requests 1504 * that do not apply (e.g. "authordate" for a tag object) 1505 */ 1506 static void fill_missing_values(struct atom_value *val) 1507 { 1508 int i; 1509 for (i = 0; i < used_atom_cnt; i++) { 1510 struct atom_value *v = &val[i]; 1511 if (v->s == NULL) 1512 v->s = xstrdup(""); 1513 } 1514 } 1515 1516 /* 1517 * val is a list of atom_value to hold returned values. Extract 1518 * the values for atoms in used_atom array out of (obj, buf, sz). 1519 * when deref is false, (obj, buf, sz) is the object that is 1520 * pointed at by the ref itself; otherwise it is the object the 1521 * ref (which is a tag) refers to. 1522 */ 1523 static void grab_values(struct atom_value *val, int deref, struct object *obj, struct expand_data *data) 1524 { 1525 void *buf = data->content; 1526 1527 switch (obj->type) { 1528 case OBJ_TAG: 1529 grab_tag_values(val, deref, obj); 1530 grab_sub_body_contents(val, deref, data); 1531 grab_person("tagger", val, deref, buf); 1532 break; 1533 case OBJ_COMMIT: 1534 grab_commit_values(val, deref, obj); 1535 grab_sub_body_contents(val, deref, data); 1536 grab_person("author", val, deref, buf); 1537 grab_person("committer", val, deref, buf); 1538 break; 1539 case OBJ_TREE: 1540 /* grab_tree_values(val, deref, obj, buf, sz); */ 1541 grab_sub_body_contents(val, deref, data); 1542 break; 1543 case OBJ_BLOB: 1544 /* grab_blob_values(val, deref, obj, buf, sz); */ 1545 grab_sub_body_contents(val, deref, data); 1546 break; 1547 default: 1548 die("Eh? Object of type %d?", obj->type); 1549 } 1550 } 1551 1552 static inline char *copy_advance(char *dst, const char *src) 1553 { 1554 while (*src) 1555 *dst++ = *src++; 1556 return dst; 1557 } 1558 1559 static const char *lstrip_ref_components(const char *refname, int len) 1560 { 1561 long remaining = len; 1562 const char *start = xstrdup(refname); 1563 const char *to_free = start; 1564 1565 if (len < 0) { 1566 int i; 1567 const char *p = refname; 1568 1569 /* Find total no of '/' separated path-components */ 1570 for (i = 0; p[i]; p[i] == '/' ? i++ : *p++) 1571 ; 1572 /* 1573 * The number of components we need to strip is now 1574 * the total minus the components to be left (Plus one 1575 * because we count the number of '/', but the number 1576 * of components is one more than the no of '/'). 1577 */ 1578 remaining = i + len + 1; 1579 } 1580 1581 while (remaining > 0) { 1582 switch (*start++) { 1583 case '\0': 1584 free((char *)to_free); 1585 return xstrdup(""); 1586 case '/': 1587 remaining--; 1588 break; 1589 } 1590 } 1591 1592 start = xstrdup(start); 1593 free((char *)to_free); 1594 return start; 1595 } 1596 1597 static const char *rstrip_ref_components(const char *refname, int len) 1598 { 1599 long remaining = len; 1600 const char *start = xstrdup(refname); 1601 const char *to_free = start; 1602 1603 if (len < 0) { 1604 int i; 1605 const char *p = refname; 1606 1607 /* Find total no of '/' separated path-components */ 1608 for (i = 0; p[i]; p[i] == '/' ? i++ : *p++) 1609 ; 1610 /* 1611 * The number of components we need to strip is now 1612 * the total minus the components to be left (Plus one 1613 * because we count the number of '/', but the number 1614 * of components is one more than the no of '/'). 1615 */ 1616 remaining = i + len + 1; 1617 } 1618 1619 while (remaining-- > 0) { 1620 char *p = strrchr(start, '/'); 1621 if (p == NULL) { 1622 free((char *)to_free); 1623 return xstrdup(""); 1624 } else 1625 p[0] = '\0'; 1626 } 1627 return start; 1628 } 1629 1630 static const char *show_ref(struct refname_atom *atom, const char *refname) 1631 { 1632 if (atom->option == R_SHORT) 1633 return shorten_unambiguous_ref(refname, warn_ambiguous_refs); 1634 else if (atom->option == R_LSTRIP) 1635 return lstrip_ref_components(refname, atom->lstrip); 1636 else if (atom->option == R_RSTRIP) 1637 return rstrip_ref_components(refname, atom->rstrip); 1638 else 1639 return xstrdup(refname); 1640 } 1641 1642 static void fill_remote_ref_details(struct used_atom *atom, const char *refname, 1643 struct branch *branch, const char **s) 1644 { 1645 int num_ours, num_theirs; 1646 if (atom->u.remote_ref.option == RR_REF) 1647 *s = show_ref(&atom->u.remote_ref.refname, refname); 1648 else if (atom->u.remote_ref.option == RR_TRACK) { 1649 if (stat_tracking_info(branch, &num_ours, &num_theirs, 1650 NULL, atom->u.remote_ref.push, 1651 AHEAD_BEHIND_FULL) < 0) { 1652 *s = xstrdup(msgs.gone); 1653 } else if (!num_ours && !num_theirs) 1654 *s = xstrdup(""); 1655 else if (!num_ours) 1656 *s = xstrfmt(msgs.behind, num_theirs); 1657 else if (!num_theirs) 1658 *s = xstrfmt(msgs.ahead, num_ours); 1659 else 1660 *s = xstrfmt(msgs.ahead_behind, 1661 num_ours, num_theirs); 1662 if (!atom->u.remote_ref.nobracket && *s[0]) { 1663 const char *to_free = *s; 1664 *s = xstrfmt("[%s]", *s); 1665 free((void *)to_free); 1666 } 1667 } else if (atom->u.remote_ref.option == RR_TRACKSHORT) { 1668 if (stat_tracking_info(branch, &num_ours, &num_theirs, 1669 NULL, atom->u.remote_ref.push, 1670 AHEAD_BEHIND_FULL) < 0) { 1671 *s = xstrdup(""); 1672 return; 1673 } 1674 if (!num_ours && !num_theirs) 1675 *s = xstrdup("="); 1676 else if (!num_ours) 1677 *s = xstrdup("<"); 1678 else if (!num_theirs) 1679 *s = xstrdup(">"); 1680 else 1681 *s = xstrdup("<>"); 1682 } else if (atom->u.remote_ref.option == RR_REMOTE_NAME) { 1683 int explicit; 1684 const char *remote = atom->u.remote_ref.push ? 1685 pushremote_for_branch(branch, &explicit) : 1686 remote_for_branch(branch, &explicit); 1687 *s = xstrdup(explicit ? remote : ""); 1688 } else if (atom->u.remote_ref.option == RR_REMOTE_REF) { 1689 const char *merge; 1690 1691 merge = remote_ref_for_branch(branch, atom->u.remote_ref.push); 1692 *s = xstrdup(merge ? merge : ""); 1693 } else 1694 BUG("unhandled RR_* enum"); 1695 } 1696 1697 char *get_head_description(void) 1698 { 1699 struct strbuf desc = STRBUF_INIT; 1700 struct wt_status_state state; 1701 memset(&state, 0, sizeof(state)); 1702 wt_status_get_state(the_repository, &state, 1); 1703 if (state.rebase_in_progress || 1704 state.rebase_interactive_in_progress) { 1705 if (state.branch) 1706 strbuf_addf(&desc, _("(no branch, rebasing %s)"), 1707 state.branch); 1708 else 1709 strbuf_addf(&desc, _("(no branch, rebasing detached HEAD %s)"), 1710 state.detached_from); 1711 } else if (state.bisect_in_progress) 1712 strbuf_addf(&desc, _("(no branch, bisect started on %s)"), 1713 state.branch); 1714 else if (state.detached_from) { 1715 if (state.detached_at) 1716 strbuf_addf(&desc, _("(HEAD detached at %s)"), 1717 state.detached_from); 1718 else 1719 strbuf_addf(&desc, _("(HEAD detached from %s)"), 1720 state.detached_from); 1721 } else 1722 strbuf_addstr(&desc, _("(no branch)")); 1723 1724 return strbuf_detach(&desc, NULL); 1725 } 1726 1727 static const char *get_symref(struct used_atom *atom, struct ref_array_item *ref) 1728 { 1729 if (!ref->symref) 1730 return xstrdup(""); 1731 else 1732 return show_ref(&atom->u.refname, ref->symref); 1733 } 1734 1735 static const char *get_refname(struct used_atom *atom, struct ref_array_item *ref) 1736 { 1737 if (ref->kind & FILTER_REFS_DETACHED_HEAD) 1738 return get_head_description(); 1739 return show_ref(&atom->u.refname, ref->refname); 1740 } 1741 1742 static int get_object(struct ref_array_item *ref, int deref, struct object **obj, 1743 struct expand_data *oi, struct strbuf *err) 1744 { 1745 /* parse_object_buffer() will set eaten to 0 if free() will be needed */ 1746 int eaten = 1; 1747 if (oi->info.contentp) { 1748 /* We need to know that to use parse_object_buffer properly */ 1749 oi->info.sizep = &oi->size; 1750 oi->info.typep = &oi->type; 1751 } 1752 if (oid_object_info_extended(the_repository, &oi->oid, &oi->info, 1753 OBJECT_INFO_LOOKUP_REPLACE)) 1754 return strbuf_addf_ret(err, -1, _("missing object %s for %s"), 1755 oid_to_hex(&oi->oid), ref->refname); 1756 if (oi->info.disk_sizep && oi->disk_size < 0) 1757 BUG("Object size is less than zero."); 1758 1759 if (oi->info.contentp) { 1760 *obj = parse_object_buffer(the_repository, &oi->oid, oi->type, oi->size, oi->content, &eaten); 1761 if (!*obj) { 1762 if (!eaten) 1763 free(oi->content); 1764 return strbuf_addf_ret(err, -1, _("parse_object_buffer failed on %s for %s"), 1765 oid_to_hex(&oi->oid), ref->refname); 1766 } 1767 grab_values(ref->value, deref, *obj, oi); 1768 } 1769 1770 grab_common_values(ref->value, deref, oi); 1771 if (!eaten) 1772 free(oi->content); 1773 return 0; 1774 } 1775 1776 static void populate_worktree_map(struct hashmap *map, struct worktree **worktrees) 1777 { 1778 int i; 1779 1780 for (i = 0; worktrees[i]; i++) { 1781 if (worktrees[i]->head_ref) { 1782 struct ref_to_worktree_entry *entry; 1783 entry = xmalloc(sizeof(*entry)); 1784 entry->wt = worktrees[i]; 1785 hashmap_entry_init(&entry->ent, 1786 strhash(worktrees[i]->head_ref)); 1787 1788 hashmap_add(map, &entry->ent); 1789 } 1790 } 1791 } 1792 1793 static void lazy_init_worktree_map(void) 1794 { 1795 if (ref_to_worktree_map.worktrees) 1796 return; 1797 1798 ref_to_worktree_map.worktrees = get_worktrees(); 1799 hashmap_init(&(ref_to_worktree_map.map), ref_to_worktree_map_cmpfnc, NULL, 0); 1800 populate_worktree_map(&(ref_to_worktree_map.map), ref_to_worktree_map.worktrees); 1801 } 1802 1803 static char *get_worktree_path(const struct used_atom *atom, const struct ref_array_item *ref) 1804 { 1805 struct hashmap_entry entry, *e; 1806 struct ref_to_worktree_entry *lookup_result; 1807 1808 lazy_init_worktree_map(); 1809 1810 hashmap_entry_init(&entry, strhash(ref->refname)); 1811 e = hashmap_get(&(ref_to_worktree_map.map), &entry, ref->refname); 1812 1813 if (!e) 1814 return xstrdup(""); 1815 1816 lookup_result = container_of(e, struct ref_to_worktree_entry, ent); 1817 1818 return xstrdup(lookup_result->wt->path); 1819 } 1820 1821 /* 1822 * Parse the object referred by ref, and grab needed value. 1823 */ 1824 static int populate_value(struct ref_array_item *ref, struct strbuf *err) 1825 { 1826 struct object *obj; 1827 int i; 1828 struct object_info empty = OBJECT_INFO_INIT; 1829 1830 CALLOC_ARRAY(ref->value, used_atom_cnt); 1831 1832 if (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) { 1833 ref->symref = resolve_refdup(ref->refname, RESOLVE_REF_READING, 1834 NULL, NULL); 1835 if (!ref->symref) 1836 ref->symref = xstrdup(""); 1837 } 1838 1839 /* Fill in specials first */ 1840 for (i = 0; i < used_atom_cnt; i++) { 1841 struct used_atom *atom = &used_atom[i]; 1842 enum atom_type atom_type = atom->atom_type; 1843 const char *name = used_atom[i].name; 1844 struct atom_value *v = &ref->value[i]; 1845 int deref = 0; 1846 const char *refname; 1847 struct branch *branch = NULL; 1848 1849 v->s_size = ATOM_SIZE_UNSPECIFIED; 1850 v->handler = append_atom; 1851 v->atom = atom; 1852 1853 if (*name == '*') { 1854 deref = 1; 1855 name++; 1856 } 1857 1858 if (atom_type == ATOM_REFNAME) 1859 refname = get_refname(atom, ref); 1860 else if (atom_type == ATOM_WORKTREEPATH) { 1861 if (ref->kind == FILTER_REFS_BRANCHES) 1862 v->s = get_worktree_path(atom, ref); 1863 else 1864 v->s = xstrdup(""); 1865 continue; 1866 } 1867 else if (atom_type == ATOM_SYMREF) 1868 refname = get_symref(atom, ref); 1869 else if (atom_type == ATOM_UPSTREAM) { 1870 const char *branch_name; 1871 /* only local branches may have an upstream */ 1872 if (!skip_prefix(ref->refname, "refs/heads/", 1873 &branch_name)) { 1874 v->s = xstrdup(""); 1875 continue; 1876 } 1877 branch = branch_get(branch_name); 1878 1879 refname = branch_get_upstream(branch, NULL); 1880 if (refname) 1881 fill_remote_ref_details(atom, refname, branch, &v->s); 1882 else 1883 v->s = xstrdup(""); 1884 continue; 1885 } else if (atom_type == ATOM_PUSH && atom->u.remote_ref.push) { 1886 const char *branch_name; 1887 v->s = xstrdup(""); 1888 if (!skip_prefix(ref->refname, "refs/heads/", 1889 &branch_name)) 1890 continue; 1891 branch = branch_get(branch_name); 1892 1893 if (atom->u.remote_ref.push_remote) 1894 refname = NULL; 1895 else { 1896 refname = branch_get_push(branch, NULL); 1897 if (!refname) 1898 continue; 1899 } 1900 /* We will definitely re-init v->s on the next line. */ 1901 free((char *)v->s); 1902 fill_remote_ref_details(atom, refname, branch, &v->s); 1903 continue; 1904 } else if (atom_type == ATOM_COLOR) { 1905 v->s = xstrdup(atom->u.color); 1906 continue; 1907 } else if (atom_type == ATOM_FLAG) { 1908 char buf[256], *cp = buf; 1909 if (ref->flag & REF_ISSYMREF) 1910 cp = copy_advance(cp, ",symref"); 1911 if (ref->flag & REF_ISPACKED) 1912 cp = copy_advance(cp, ",packed"); 1913 if (cp == buf) 1914 v->s = xstrdup(""); 1915 else { 1916 *cp = '\0'; 1917 v->s = xstrdup(buf + 1); 1918 } 1919 continue; 1920 } else if (!deref && atom_type == ATOM_OBJECTNAME && 1921 grab_oid(name, "objectname", &ref->objectname, v, atom)) { 1922 continue; 1923 } else if (atom_type == ATOM_HEAD) { 1924 if (atom->u.head && !strcmp(ref->refname, atom->u.head)) 1925 v->s = xstrdup("*"); 1926 else 1927 v->s = xstrdup(" "); 1928 continue; 1929 } else if (atom_type == ATOM_ALIGN) { 1930 v->handler = align_atom_handler; 1931 v->s = xstrdup(""); 1932 continue; 1933 } else if (atom_type == ATOM_END) { 1934 v->handler = end_atom_handler; 1935 v->s = xstrdup(""); 1936 continue; 1937 } else if (atom_type == ATOM_IF) { 1938 const char *s; 1939 if (skip_prefix(name, "if:", &s)) 1940 v->s = xstrdup(s); 1941 else 1942 v->s = xstrdup(""); 1943 v->handler = if_atom_handler; 1944 continue; 1945 } else if (atom_type == ATOM_THEN) { 1946 v->handler = then_atom_handler; 1947 v->s = xstrdup(""); 1948 continue; 1949 } else if (atom_type == ATOM_ELSE) { 1950 v->handler = else_atom_handler; 1951 v->s = xstrdup(""); 1952 continue; 1953 } else if (atom_type == ATOM_REST) { 1954 if (ref->rest) 1955 v->s = xstrdup(ref->rest); 1956 else 1957 v->s = xstrdup(""); 1958 continue; 1959 } else 1960 continue; 1961 1962 if (!deref) 1963 v->s = xstrdup(refname); 1964 else 1965 v->s = xstrfmt("%s^{}", refname); 1966 free((char *)refname); 1967 } 1968 1969 for (i = 0; i < used_atom_cnt; i++) { 1970 struct atom_value *v = &ref->value[i]; 1971 if (v->s == NULL && used_atom[i].source == SOURCE_NONE) 1972 return strbuf_addf_ret(err, -1, _("missing object %s for %s"), 1973 oid_to_hex(&ref->objectname), ref->refname); 1974 } 1975 1976 if (need_tagged) 1977 oi.info.contentp = &oi.content; 1978 if (!memcmp(&oi.info, &empty, sizeof(empty)) && 1979 !memcmp(&oi_deref.info, &empty, sizeof(empty))) 1980 return 0; 1981 1982 1983 oi.oid = ref->objectname; 1984 if (get_object(ref, 0, &obj, &oi, err)) 1985 return -1; 1986 1987 /* 1988 * If there is no atom that wants to know about tagged 1989 * object, we are done. 1990 */ 1991 if (!need_tagged || (obj->type != OBJ_TAG)) 1992 return 0; 1993 1994 /* 1995 * If it is a tag object, see if we use a value that derefs 1996 * the object, and if we do grab the object it refers to. 1997 */ 1998 oi_deref.oid = *get_tagged_oid((struct tag *)obj); 1999 2000 /* 2001 * NEEDSWORK: This derefs tag only once, which 2002 * is good to deal with chains of trust, but 2003 * is not consistent with what deref_tag() does 2004 * which peels the onion to the core. 2005 */ 2006 return get_object(ref, 1, &obj, &oi_deref, err); 2007 } 2008 2009 /* 2010 * Given a ref, return the value for the atom. This lazily gets value 2011 * out of the object by calling populate value. 2012 */ 2013 static int get_ref_atom_value(struct ref_array_item *ref, int atom, 2014 struct atom_value **v, struct strbuf *err) 2015 { 2016 if (!ref->value) { 2017 if (populate_value(ref, err)) 2018 return -1; 2019 fill_missing_values(ref->value); 2020 } 2021 *v = &ref->value[atom]; 2022 return 0; 2023 } 2024 2025 /* 2026 * Return 1 if the refname matches one of the patterns, otherwise 0. 2027 * A pattern can be a literal prefix (e.g. a refname "refs/heads/master" 2028 * matches a pattern "refs/heads/mas") or a wildcard (e.g. the same ref 2029 * matches "refs/heads/mas*", too). 2030 */ 2031 static int match_pattern(const struct ref_filter *filter, const char *refname) 2032 { 2033 const char **patterns = filter->name_patterns; 2034 unsigned flags = 0; 2035 2036 if (filter->ignore_case) 2037 flags |= WM_CASEFOLD; 2038 2039 /* 2040 * When no '--format' option is given we need to skip the prefix 2041 * for matching refs of tags and branches. 2042 */ 2043 (void)(skip_prefix(refname, "refs/tags/", &refname) || 2044 skip_prefix(refname, "refs/heads/", &refname) || 2045 skip_prefix(refname, "refs/remotes/", &refname) || 2046 skip_prefix(refname, "refs/", &refname)); 2047 2048 for (; *patterns; patterns++) { 2049 if (!wildmatch(*patterns, refname, flags)) 2050 return 1; 2051 } 2052 return 0; 2053 } 2054 2055 /* 2056 * Return 1 if the refname matches one of the patterns, otherwise 0. 2057 * A pattern can be path prefix (e.g. a refname "refs/heads/master" 2058 * matches a pattern "refs/heads/" but not "refs/heads/m") or a 2059 * wildcard (e.g. the same ref matches "refs/heads/m*", too). 2060 */ 2061 static int match_name_as_path(const struct ref_filter *filter, const char *refname) 2062 { 2063 const char **pattern = filter->name_patterns; 2064 int namelen = strlen(refname); 2065 unsigned flags = WM_PATHNAME; 2066 2067 if (filter->ignore_case) 2068 flags |= WM_CASEFOLD; 2069 2070 for (; *pattern; pattern++) { 2071 const char *p = *pattern; 2072 int plen = strlen(p); 2073 2074 if ((plen <= namelen) && 2075 !strncmp(refname, p, plen) && 2076 (refname[plen] == '\0' || 2077 refname[plen] == '/' || 2078 p[plen-1] == '/')) 2079 return 1; 2080 if (!wildmatch(p, refname, flags)) 2081 return 1; 2082 } 2083 return 0; 2084 } 2085 2086 /* Return 1 if the refname matches one of the patterns, otherwise 0. */ 2087 static int filter_pattern_match(struct ref_filter *filter, const char *refname) 2088 { 2089 if (!*filter->name_patterns) 2090 return 1; /* No pattern always matches */ 2091 if (filter->match_as_path) 2092 return match_name_as_path(filter, refname); 2093 return match_pattern(filter, refname); 2094 } 2095 2096 /* 2097 * This is the same as for_each_fullref_in(), but it tries to iterate 2098 * only over the patterns we'll care about. Note that it _doesn't_ do a full 2099 * pattern match, so the callback still has to match each ref individually. 2100 */ 2101 static int for_each_fullref_in_pattern(struct ref_filter *filter, 2102 each_ref_fn cb, 2103 void *cb_data) 2104 { 2105 if (!filter->match_as_path) { 2106 /* 2107 * in this case, the patterns are applied after 2108 * prefixes like "refs/heads/" etc. are stripped off, 2109 * so we have to look at everything: 2110 */ 2111 return for_each_fullref_in("", cb, cb_data); 2112 } 2113 2114 if (filter->ignore_case) { 2115 /* 2116 * we can't handle case-insensitive comparisons, 2117 * so just return everything and let the caller 2118 * sort it out. 2119 */ 2120 return for_each_fullref_in("", cb, cb_data); 2121 } 2122 2123 if (!filter->name_patterns[0]) { 2124 /* no patterns; we have to look at everything */ 2125 return for_each_fullref_in("", cb, cb_data); 2126 } 2127 2128 return for_each_fullref_in_prefixes(NULL, filter->name_patterns, 2129 cb, cb_data); 2130 } 2131 2132 /* 2133 * Given a ref (oid, refname), check if the ref belongs to the array 2134 * of oids. If the given ref is a tag, check if the given tag points 2135 * at one of the oids in the given oid array. 2136 * NEEDSWORK: 2137 * 1. Only a single level of indirection is obtained, we might want to 2138 * change this to account for multiple levels (e.g. annotated tags 2139 * pointing to annotated tags pointing to a commit.) 2140 * 2. As the refs are cached we might know what refname peels to without 2141 * the need to parse the object via parse_object(). peel_ref() might be a 2142 * more efficient alternative to obtain the pointee. 2143 */ 2144 static const struct object_id *match_points_at(struct oid_array *points_at, 2145 const struct object_id *oid, 2146 const char *refname) 2147 { 2148 const struct object_id *tagged_oid = NULL; 2149 struct object *obj; 2150 2151 if (oid_array_lookup(points_at, oid) >= 0) 2152 return oid; 2153 obj = parse_object(the_repository, oid); 2154 if (!obj) 2155 die(_("malformed object at '%s'"), refname); 2156 if (obj->type == OBJ_TAG) 2157 tagged_oid = get_tagged_oid((struct tag *)obj); 2158 if (tagged_oid && oid_array_lookup(points_at, tagged_oid) >= 0) 2159 return tagged_oid; 2160 return NULL; 2161 } 2162 2163 /* 2164 * Allocate space for a new ref_array_item and copy the name and oid to it. 2165 * 2166 * Callers can then fill in other struct members at their leisure. 2167 */ 2168 static struct ref_array_item *new_ref_array_item(const char *refname, 2169 const struct object_id *oid) 2170 { 2171 struct ref_array_item *ref; 2172 2173 FLEX_ALLOC_STR(ref, refname, refname); 2174 oidcpy(&ref->objectname, oid); 2175 ref->rest = NULL; 2176 2177 return ref; 2178 } 2179 2180 struct ref_array_item *ref_array_push(struct ref_array *array, 2181 const char *refname, 2182 const struct object_id *oid) 2183 { 2184 struct ref_array_item *ref = new_ref_array_item(refname, oid); 2185 2186 ALLOC_GROW(array->items, array->nr + 1, array->alloc); 2187 array->items[array->nr++] = ref; 2188 2189 return ref; 2190 } 2191 2192 static int ref_kind_from_refname(const char *refname) 2193 { 2194 unsigned int i; 2195 2196 static struct { 2197 const char *prefix; 2198 unsigned int kind; 2199 } ref_kind[] = { 2200 { "refs/heads/" , FILTER_REFS_BRANCHES }, 2201 { "refs/remotes/" , FILTER_REFS_REMOTES }, 2202 { "refs/tags/", FILTER_REFS_TAGS} 2203 }; 2204 2205 if (!strcmp(refname, "HEAD")) 2206 return FILTER_REFS_DETACHED_HEAD; 2207 2208 for (i = 0; i < ARRAY_SIZE(ref_kind); i++) { 2209 if (starts_with(refname, ref_kind[i].prefix)) 2210 return ref_kind[i].kind; 2211 } 2212 2213 return FILTER_REFS_OTHERS; 2214 } 2215 2216 static int filter_ref_kind(struct ref_filter *filter, const char *refname) 2217 { 2218 if (filter->kind == FILTER_REFS_BRANCHES || 2219 filter->kind == FILTER_REFS_REMOTES || 2220 filter->kind == FILTER_REFS_TAGS) 2221 return filter->kind; 2222 return ref_kind_from_refname(refname); 2223 } 2224 2225 struct ref_filter_cbdata { 2226 struct ref_array *array; 2227 struct ref_filter *filter; 2228 struct contains_cache contains_cache; 2229 struct contains_cache no_contains_cache; 2230 }; 2231 2232 /* 2233 * A call-back given to for_each_ref(). Filter refs and keep them for 2234 * later object processing. 2235 */ 2236 static int ref_filter_handler(const char *refname, const struct object_id *oid, int flag, void *cb_data) 2237 { 2238 struct ref_filter_cbdata *ref_cbdata = cb_data; 2239 struct ref_filter *filter = ref_cbdata->filter; 2240 struct ref_array_item *ref; 2241 struct commit *commit = NULL; 2242 unsigned int kind; 2243 2244 if (flag & REF_BAD_NAME) { 2245 warning(_("ignoring ref with broken name %s"), refname); 2246 return 0; 2247 } 2248 2249 if (flag & REF_ISBROKEN) { 2250 warning(_("ignoring broken ref %s"), refname); 2251 return 0; 2252 } 2253 2254 /* Obtain the current ref kind from filter_ref_kind() and ignore unwanted refs. */ 2255 kind = filter_ref_kind(filter, refname); 2256 if (!(kind & filter->kind)) 2257 return 0; 2258 2259 if (!filter_pattern_match(filter, refname)) 2260 return 0; 2261 2262 if (filter->points_at.nr && !match_points_at(&filter->points_at, oid, refname)) 2263 return 0; 2264 2265 /* 2266 * A merge filter is applied on refs pointing to commits. Hence 2267 * obtain the commit using the 'oid' available and discard all 2268 * non-commits early. The actual filtering is done later. 2269 */ 2270 if (filter->reachable_from || filter->unreachable_from || 2271 filter->with_commit || filter->no_commit || filter->verbose) { 2272 commit = lookup_commit_reference_gently(the_repository, oid, 1); 2273 if (!commit) 2274 return 0; 2275 /* We perform the filtering for the '--contains' option... */ 2276 if (filter->with_commit && 2277 !commit_contains(filter, commit, filter->with_commit, &ref_cbdata->contains_cache)) 2278 return 0; 2279 /* ...or for the `--no-contains' option */ 2280 if (filter->no_commit && 2281 commit_contains(filter, commit, filter->no_commit, &ref_cbdata->no_contains_cache)) 2282 return 0; 2283 } 2284 2285 /* 2286 * We do not open the object yet; sort may only need refname 2287 * to do its job and the resulting list may yet to be pruned 2288 * by maxcount logic. 2289 */ 2290 ref = ref_array_push(ref_cbdata->array, refname, oid); 2291 ref->commit = commit; 2292 ref->flag = flag; 2293 ref->kind = kind; 2294 2295 return 0; 2296 } 2297 2298 /* Free memory allocated for a ref_array_item */ 2299 static void free_array_item(struct ref_array_item *item) 2300 { 2301 free((char *)item->symref); 2302 if (item->value) { 2303 int i; 2304 for (i = 0; i < used_atom_cnt; i++) 2305 free((char *)item->value[i].s); 2306 free(item->value); 2307 } 2308 free(item); 2309 } 2310 2311 /* Free all memory allocated for ref_array */ 2312 void ref_array_clear(struct ref_array *array) 2313 { 2314 int i; 2315 2316 for (i = 0; i < array->nr; i++) 2317 free_array_item(array->items[i]); 2318 FREE_AND_NULL(array->items); 2319 array->nr = array->alloc = 0; 2320 2321 for (i = 0; i < used_atom_cnt; i++) { 2322 struct used_atom *atom = &used_atom[i]; 2323 if (atom->atom_type == ATOM_HEAD) 2324 free(atom->u.head); 2325 free((char *)atom->name); 2326 } 2327 FREE_AND_NULL(used_atom); 2328 used_atom_cnt = 0; 2329 2330 if (ref_to_worktree_map.worktrees) { 2331 hashmap_clear_and_free(&(ref_to_worktree_map.map), 2332 struct ref_to_worktree_entry, ent); 2333 free_worktrees(ref_to_worktree_map.worktrees); 2334 ref_to_worktree_map.worktrees = NULL; 2335 } 2336 } 2337 2338 #define EXCLUDE_REACHED 0 2339 #define INCLUDE_REACHED 1 2340 static void reach_filter(struct ref_array *array, 2341 struct commit_list *check_reachable, 2342 int include_reached) 2343 { 2344 struct rev_info revs; 2345 int i, old_nr; 2346 struct commit **to_clear; 2347 struct commit_list *cr; 2348 2349 if (!check_reachable) 2350 return; 2351 2352 CALLOC_ARRAY(to_clear, array->nr); 2353 2354 repo_init_revisions(the_repository, &revs, NULL); 2355 2356 for (i = 0; i < array->nr; i++) { 2357 struct ref_array_item *item = array->items[i]; 2358 add_pending_object(&revs, &item->commit->object, item->refname); 2359 to_clear[i] = item->commit; 2360 } 2361 2362 for (cr = check_reachable; cr; cr = cr->next) { 2363 struct commit *merge_commit = cr->item; 2364 merge_commit->object.flags |= UNINTERESTING; 2365 add_pending_object(&revs, &merge_commit->object, ""); 2366 } 2367 2368 revs.limited = 1; 2369 if (prepare_revision_walk(&revs)) 2370 die(_("revision walk setup failed")); 2371 2372 old_nr = array->nr; 2373 array->nr = 0; 2374 2375 for (i = 0; i < old_nr; i++) { 2376 struct ref_array_item *item = array->items[i]; 2377 struct commit *commit = item->commit; 2378 2379 int is_merged = !!(commit->object.flags & UNINTERESTING); 2380 2381 if (is_merged == include_reached) 2382 array->items[array->nr++] = array->items[i]; 2383 else 2384 free_array_item(item); 2385 } 2386 2387 clear_commit_marks_many(old_nr, to_clear, ALL_REV_FLAGS); 2388 2389 while (check_reachable) { 2390 struct commit *merge_commit = pop_commit(&check_reachable); 2391 clear_commit_marks(merge_commit, ALL_REV_FLAGS); 2392 } 2393 2394 free(to_clear); 2395 } 2396 2397 /* 2398 * API for filtering a set of refs. Based on the type of refs the user 2399 * has requested, we iterate through those refs and apply filters 2400 * as per the given ref_filter structure and finally store the 2401 * filtered refs in the ref_array structure. 2402 */ 2403 int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int type) 2404 { 2405 struct ref_filter_cbdata ref_cbdata; 2406 int ret = 0; 2407 2408 ref_cbdata.array = array; 2409 ref_cbdata.filter = filter; 2410 2411 filter->kind = type & FILTER_REFS_KIND_MASK; 2412 2413 init_contains_cache(&ref_cbdata.contains_cache); 2414 init_contains_cache(&ref_cbdata.no_contains_cache); 2415 2416 /* Simple per-ref filtering */ 2417 if (!filter->kind) 2418 die("filter_refs: invalid type"); 2419 else { 2420 /* 2421 * For common cases where we need only branches or remotes or tags, 2422 * we only iterate through those refs. If a mix of refs is needed, 2423 * we iterate over all refs and filter out required refs with the help 2424 * of filter_ref_kind(). 2425 */ 2426 if (filter->kind == FILTER_REFS_BRANCHES) 2427 ret = for_each_fullref_in("refs/heads/", ref_filter_handler, &ref_cbdata); 2428 else if (filter->kind == FILTER_REFS_REMOTES) 2429 ret = for_each_fullref_in("refs/remotes/", ref_filter_handler, &ref_cbdata); 2430 else if (filter->kind == FILTER_REFS_TAGS) 2431 ret = for_each_fullref_in("refs/tags/", ref_filter_handler, &ref_cbdata); 2432 else if (filter->kind & FILTER_REFS_ALL) 2433 ret = for_each_fullref_in_pattern(filter, ref_filter_handler, &ref_cbdata); 2434 if (!ret && (filter->kind & FILTER_REFS_DETACHED_HEAD)) 2435 head_ref(ref_filter_handler, &ref_cbdata); 2436 } 2437 2438 clear_contains_cache(&ref_cbdata.contains_cache); 2439 clear_contains_cache(&ref_cbdata.no_contains_cache); 2440 2441 /* Filters that need revision walking */ 2442 reach_filter(array, filter->reachable_from, INCLUDE_REACHED); 2443 reach_filter(array, filter->unreachable_from, EXCLUDE_REACHED); 2444 2445 return ret; 2446 } 2447 2448 static int compare_detached_head(struct ref_array_item *a, struct ref_array_item *b) 2449 { 2450 if (!(a->kind ^ b->kind)) 2451 BUG("ref_kind_from_refname() should only mark one ref as HEAD"); 2452 if (a->kind & FILTER_REFS_DETACHED_HEAD) 2453 return -1; 2454 else if (b->kind & FILTER_REFS_DETACHED_HEAD) 2455 return 1; 2456 BUG("should have died in the xor check above"); 2457 return 0; 2458 } 2459 2460 static int memcasecmp(const void *vs1, const void *vs2, size_t n) 2461 { 2462 const char *s1 = vs1, *s2 = vs2; 2463 const char *end = s1 + n; 2464 2465 for (; s1 < end; s1++, s2++) { 2466 int diff = tolower(*s1) - tolower(*s2); 2467 if (diff) 2468 return diff; 2469 } 2470 return 0; 2471 } 2472 2473 static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, struct ref_array_item *b) 2474 { 2475 struct atom_value *va, *vb; 2476 int cmp; 2477 int cmp_detached_head = 0; 2478 cmp_type cmp_type = used_atom[s->atom].type; 2479 struct strbuf err = STRBUF_INIT; 2480 2481 if (get_ref_atom_value(a, s->atom, &va, &err)) 2482 die("%s", err.buf); 2483 if (get_ref_atom_value(b, s->atom, &vb, &err)) 2484 die("%s", err.buf); 2485 strbuf_release(&err); 2486 if (s->sort_flags & REF_SORTING_DETACHED_HEAD_FIRST && 2487 ((a->kind | b->kind) & FILTER_REFS_DETACHED_HEAD)) { 2488 cmp = compare_detached_head(a, b); 2489 cmp_detached_head = 1; 2490 } else if (s->sort_flags & REF_SORTING_VERSION) { 2491 cmp = versioncmp(va->s, vb->s); 2492 } else if (cmp_type == FIELD_STR) { 2493 if (va->s_size < 0 && vb->s_size < 0) { 2494 int (*cmp_fn)(const char *, const char *); 2495 cmp_fn = s->sort_flags & REF_SORTING_ICASE 2496 ? strcasecmp : strcmp; 2497 cmp = cmp_fn(va->s, vb->s); 2498 } else { 2499 size_t a_size = va->s_size < 0 ? 2500 strlen(va->s) : va->s_size; 2501 size_t b_size = vb->s_size < 0 ? 2502 strlen(vb->s) : vb->s_size; 2503 int (*cmp_fn)(const void *, const void *, size_t); 2504 cmp_fn = s->sort_flags & REF_SORTING_ICASE 2505 ? memcasecmp : memcmp; 2506 2507 cmp = cmp_fn(va->s, vb->s, b_size > a_size ? 2508 a_size : b_size); 2509 if (!cmp) { 2510 if (a_size > b_size) 2511 cmp = 1; 2512 else if (a_size < b_size) 2513 cmp = -1; 2514 } 2515 } 2516 } else { 2517 if (va->value < vb->value) 2518 cmp = -1; 2519 else if (va->value == vb->value) 2520 cmp = 0; 2521 else 2522 cmp = 1; 2523 } 2524 2525 return (s->sort_flags & REF_SORTING_REVERSE && !cmp_detached_head) 2526 ? -cmp : cmp; 2527 } 2528 2529 static int compare_refs(const void *a_, const void *b_, void *ref_sorting) 2530 { 2531 struct ref_array_item *a = *((struct ref_array_item **)a_); 2532 struct ref_array_item *b = *((struct ref_array_item **)b_); 2533 struct ref_sorting *s; 2534 2535 for (s = ref_sorting; s; s = s->next) { 2536 int cmp = cmp_ref_sorting(s, a, b); 2537 if (cmp) 2538 return cmp; 2539 } 2540 s = ref_sorting; 2541 return s && s->sort_flags & REF_SORTING_ICASE ? 2542 strcasecmp(a->refname, b->refname) : 2543 strcmp(a->refname, b->refname); 2544 } 2545 2546 void ref_sorting_set_sort_flags_all(struct ref_sorting *sorting, 2547 unsigned int mask, int on) 2548 { 2549 for (; sorting; sorting = sorting->next) { 2550 if (on) 2551 sorting->sort_flags |= mask; 2552 else 2553 sorting->sort_flags &= ~mask; 2554 } 2555 } 2556 2557 void ref_array_sort(struct ref_sorting *sorting, struct ref_array *array) 2558 { 2559 QSORT_S(array->items, array->nr, compare_refs, sorting); 2560 } 2561 2562 static void append_literal(const char *cp, const char *ep, struct ref_formatting_state *state) 2563 { 2564 struct strbuf *s = &state->stack->output; 2565 2566 while (*cp && (!ep || cp < ep)) { 2567 if (*cp == '%') { 2568 if (cp[1] == '%') 2569 cp++; 2570 else { 2571 int ch = hex2chr(cp + 1); 2572 if (0 <= ch) { 2573 strbuf_addch(s, ch); 2574 cp += 3; 2575 continue; 2576 } 2577 } 2578 } 2579 strbuf_addch(s, *cp); 2580 cp++; 2581 } 2582 } 2583 2584 int format_ref_array_item(struct ref_array_item *info, 2585 struct ref_format *format, 2586 struct strbuf *final_buf, 2587 struct strbuf *error_buf) 2588 { 2589 const char *cp, *sp, *ep; 2590 struct ref_formatting_state state = REF_FORMATTING_STATE_INIT; 2591 2592 state.quote_style = format->quote_style; 2593 push_stack_element(&state.stack); 2594 2595 for (cp = format->format; *cp && (sp = find_next(cp)); cp = ep + 1) { 2596 struct atom_value *atomv; 2597 int pos; 2598 2599 ep = strchr(sp, ')'); 2600 if (cp < sp) 2601 append_literal(cp, sp, &state); 2602 pos = parse_ref_filter_atom(format, sp + 2, ep, error_buf); 2603 if (pos < 0 || get_ref_atom_value(info, pos, &atomv, error_buf) || 2604 atomv->handler(atomv, &state, error_buf)) { 2605 pop_stack_element(&state.stack); 2606 return -1; 2607 } 2608 } 2609 if (*cp) { 2610 sp = cp + strlen(cp); 2611 append_literal(cp, sp, &state); 2612 } 2613 if (format->need_color_reset_at_eol) { 2614 struct atom_value resetv = ATOM_VALUE_INIT; 2615 resetv.s = GIT_COLOR_RESET; 2616 if (append_atom(&resetv, &state, error_buf)) { 2617 pop_stack_element(&state.stack); 2618 return -1; 2619 } 2620 } 2621 if (state.stack->prev) { 2622 pop_stack_element(&state.stack); 2623 return strbuf_addf_ret(error_buf, -1, _("format: %%(end) atom missing")); 2624 } 2625 strbuf_addbuf(final_buf, &state.stack->output); 2626 pop_stack_element(&state.stack); 2627 return 0; 2628 } 2629 2630 void pretty_print_ref(const char *name, const struct object_id *oid, 2631 struct ref_format *format) 2632 { 2633 struct ref_array_item *ref_item; 2634 struct strbuf output = STRBUF_INIT; 2635 struct strbuf err = STRBUF_INIT; 2636 2637 ref_item = new_ref_array_item(name, oid); 2638 ref_item->kind = ref_kind_from_refname(name); 2639 if (format_ref_array_item(ref_item, format, &output, &err)) 2640 die("%s", err.buf); 2641 fwrite(output.buf, 1, output.len, stdout); 2642 putchar('\n'); 2643 2644 strbuf_release(&err); 2645 strbuf_release(&output); 2646 free_array_item(ref_item); 2647 } 2648 2649 static int parse_sorting_atom(const char *atom) 2650 { 2651 /* 2652 * This parses an atom using a dummy ref_format, since we don't 2653 * actually care about the formatting details. 2654 */ 2655 struct ref_format dummy = REF_FORMAT_INIT; 2656 const char *end = atom + strlen(atom); 2657 struct strbuf err = STRBUF_INIT; 2658 int res = parse_ref_filter_atom(&dummy, atom, end, &err); 2659 if (res < 0) 2660 die("%s", err.buf); 2661 strbuf_release(&err); 2662 return res; 2663 } 2664 2665 /* If no sorting option is given, use refname to sort as default */ 2666 struct ref_sorting *ref_default_sorting(void) 2667 { 2668 static const char cstr_name[] = "refname"; 2669 2670 struct ref_sorting *sorting = xcalloc(1, sizeof(*sorting)); 2671 2672 sorting->next = NULL; 2673 sorting->atom = parse_sorting_atom(cstr_name); 2674 return sorting; 2675 } 2676 2677 void parse_ref_sorting(struct ref_sorting **sorting_tail, const char *arg) 2678 { 2679 struct ref_sorting *s; 2680 2681 CALLOC_ARRAY(s, 1); 2682 s->next = *sorting_tail; 2683 *sorting_tail = s; 2684 2685 if (*arg == '-') { 2686 s->sort_flags |= REF_SORTING_REVERSE; 2687 arg++; 2688 } 2689 if (skip_prefix(arg, "version:", &arg) || 2690 skip_prefix(arg, "v:", &arg)) 2691 s->sort_flags |= REF_SORTING_VERSION; 2692 s->atom = parse_sorting_atom(arg); 2693 } 2694 2695 int parse_opt_ref_sorting(const struct option *opt, const char *arg, int unset) 2696 { 2697 /* 2698 * NEEDSWORK: We should probably clear the list in this case, but we've 2699 * already munged the global used_atoms list, which would need to be 2700 * undone. 2701 */ 2702 BUG_ON_OPT_NEG(unset); 2703 2704 parse_ref_sorting(opt->value, arg); 2705 return 0; 2706 } 2707 2708 void ref_sorting_release(struct ref_sorting *sorting) 2709 { 2710 while (sorting) { 2711 struct ref_sorting *next = sorting->next; 2712 free(sorting); 2713 sorting = next; 2714 } 2715 } 2716 2717 int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset) 2718 { 2719 struct ref_filter *rf = opt->value; 2720 struct object_id oid; 2721 struct commit *merge_commit; 2722 2723 BUG_ON_OPT_NEG(unset); 2724 2725 if (get_oid(arg, &oid)) 2726 die(_("malformed object name %s"), arg); 2727 2728 merge_commit = lookup_commit_reference_gently(the_repository, &oid, 0); 2729 2730 if (!merge_commit) 2731 return error(_("option `%s' must point to a commit"), opt->long_name); 2732 2733 if (starts_with(opt->long_name, "no")) 2734 commit_list_insert(merge_commit, &rf->unreachable_from); 2735 else 2736 commit_list_insert(merge_commit, &rf->reachable_from); 2737 2738 return 0; 2739 } 2740