From 40dae3094db123be664c69b356b6e4f4e33d80e6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 13 Feb 2010 11:29:27 -0800 Subject: [PATCH 1/4] builtin-for-each-ref.c: comment fixes The primary purpose of this is to get rid of stale comments that lamented the lack of callback parameter from for_each_ref() which we have already fixed. While at it we adjust the multi-line comment style to match the style convention. Signed-off-by: Junio C Hamano --- builtin-for-each-ref.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c index a5a83f1469..3698e822c8 100644 --- a/builtin-for-each-ref.c +++ b/builtin-for-each-ref.c @@ -143,7 +143,8 @@ static const char *find_next(const char *cp) { while (*cp) { if (*cp == '%') { - /* %( is the start of an atom; + /* + * %( is the start of an atom; * %% is a quoted per-cent. */ if (cp[1] == '(') @@ -420,7 +421,8 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru grab_date(wholine, v, name); } - /* For a tag or a commit object, if "creator" or "creatordate" is + /* + * For a tag or a commit object, if "creator" or "creatordate" is * requested, do something special. */ if (strcmp(who, "tagger") && strcmp(who, "committer")) @@ -502,7 +504,8 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct obj } } -/* We want to have empty print-string for field requests +/* + * We want to have empty print-string for field requests * that do not apply (e.g. "authordate" for a tag object) */ static void fill_missing_values(struct atom_value *val) @@ -633,18 +636,21 @@ static void populate_value(struct refinfo *ref) if (!eaten) free(buf); - /* If there is no atom that wants to know about tagged + /* + * If there is no atom that wants to know about tagged * object, we are done. */ if (!need_tagged || (obj->type != OBJ_TAG)) return; - /* If it is a tag object, see if we use a value that derefs + /* + * If it is a tag object, see if we use a value that derefs * the object, and if we do grab the object it refers to. */ tagged = ((struct tag *)obj)->tagged->sha1; - /* NEEDSWORK: This derefs tag only once, which + /* + * NEEDSWORK: This derefs tag only once, which * is good to deal with chains of trust, but * is not consistent with what deref_tag() does * which peels the onion to the core. @@ -681,9 +687,8 @@ struct grab_ref_cbdata { }; /* - * A call-back given to for_each_ref(). It is unfortunate that we - * need to use global variables to pass extra information to this - * function. + * A call-back given to for_each_ref(). Filter refs and keep them for + * later object processing. */ static int grab_single_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data) { @@ -711,7 +716,8 @@ static int grab_single_ref(const char *refname, const unsigned char *sha1, int f return 0; } - /* We do not open the object yet; sort may only need refname + /* + * We do not open the object yet; sort may only need refname * to do its job and the resulting list may yet to be pruned * by maxcount logic. */ From 20322e0b552b9860377c162675ce5c49bfd32e83 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 13 Feb 2010 11:38:42 -0800 Subject: [PATCH 2/4] builtin-for-each-ref.c: check if we need to peel onion while parsing the format Instead of iterating over the parsed atoms that are used in the output format after all the parsing is done, check it while parsing the format string. --- builtin-for-each-ref.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c index 3698e822c8..d68977ee63 100644 --- a/builtin-for-each-ref.c +++ b/builtin-for-each-ref.c @@ -133,6 +133,8 @@ static int parse_atom(const char *atom, const char *ep) (sizeof(*used_atom_type) * used_atom_cnt)); used_atom[at] = xmemdupz(atom, ep - atom); used_atom_type[at] = valid_atom[i].cmp_type; + if (*atom == '*') + need_tagged = 1; return at; } @@ -944,13 +946,6 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix) refs = cbdata.grab_array; num_refs = cbdata.grab_cnt; - for (i = 0; i < used_atom_cnt; i++) { - if (used_atom[i][0] == '*') { - need_tagged = 1; - break; - } - } - sort_refs(sort, refs, num_refs); if (!maxcount || num_refs < maxcount) From 5cdd628c84d808feb6ec407b2ecd74dfea63f865 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 13 Feb 2010 11:57:08 -0800 Subject: [PATCH 3/4] for-each-ref --format='%(symref) %(symref:short)' New %(symref) output atom expands to the name of the ref a symbolic ref points at, or an empty string if the ref being shown is not a symref. This may help scripted Porcelain writers. Signed-off-by: Junio C Hamano --- builtin-for-each-ref.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c index d68977ee63..b9b03e14d3 100644 --- a/builtin-for-each-ref.c +++ b/builtin-for-each-ref.c @@ -33,6 +33,8 @@ struct ref_sort { struct refinfo { char *refname; unsigned char objectname[20]; + int flag; + const char *symref; struct atom_value *value; }; @@ -68,6 +70,7 @@ static struct { { "body" }, { "contents" }, { "upstream" }, + { "symref" }, }; /* @@ -82,7 +85,7 @@ static struct { */ static const char **used_atom; static cmp_type *used_atom_type; -static int used_atom_cnt, sort_atom_limit, need_tagged; +static int used_atom_cnt, sort_atom_limit, need_tagged, need_symref; /* * Used to parse format string and sort specifiers @@ -135,6 +138,8 @@ static int parse_atom(const char *atom, const char *ep) used_atom_type[at] = valid_atom[i].cmp_type; if (*atom == '*') need_tagged = 1; + if (!strcmp(used_atom[at], "symref")) + need_symref = 1; return at; } @@ -566,6 +571,16 @@ static void populate_value(struct refinfo *ref) ref->value = xcalloc(sizeof(struct atom_value), used_atom_cnt); + if (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) { + unsigned char unused1[20]; + const char *symref; + symref = resolve_ref(ref->refname, unused1, 1, NULL); + if (symref) + ref->symref = xstrdup(symref); + else + ref->symref = ""; + } + /* Fill in specials first */ for (i = 0; i < used_atom_cnt; i++) { const char *name = used_atom[i]; @@ -581,6 +596,8 @@ static void populate_value(struct refinfo *ref) if (!prefixcmp(name, "refname")) refname = ref->refname; + else if (!prefixcmp(name, "symref")) + refname = ref->symref ? ref->symref : ""; else if (!prefixcmp(name, "upstream")) { struct branch *branch; /* only local branches may have an upstream */ @@ -726,6 +743,7 @@ static int grab_single_ref(const char *refname, const unsigned char *sha1, int f ref = xcalloc(1, sizeof(*ref)); ref->refname = xstrdup(refname); hashcpy(ref->objectname, sha1); + ref->flag = flag; cnt = cb->grab_cnt; cb->grab_array = xrealloc(cb->grab_array, From 88fb7f27f6036028b3470e0e2a0efed1d9c7ee78 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 13 Feb 2010 12:05:44 -0800 Subject: [PATCH 4/4] for-each-ref --format='%(flag)' This expands to "symref" or "packed" or an empty string, exposing the internal "flag" the for_each_ref() callback functions are called with. Signed-off-by: Junio C Hamano --- builtin-for-each-ref.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c index b9b03e14d3..62be1bbfd6 100644 --- a/builtin-for-each-ref.c +++ b/builtin-for-each-ref.c @@ -71,6 +71,7 @@ static struct { { "contents" }, { "upstream" }, { "symref" }, + { "flag" }, }; /* @@ -558,6 +559,13 @@ static void grab_values(struct atom_value *val, int deref, struct object *obj, v } } +static inline char *copy_advance(char *dst, const char *src) +{ + while (*src) + *dst++ = *src++; + return dst; +} + /* * Parse the object referred by ref, and grab needed value. */ @@ -610,6 +618,20 @@ static void populate_value(struct refinfo *ref) continue; refname = branch->merge[0]->dst; } + else if (!strcmp(name, "flag")) { + char buf[256], *cp = buf; + if (ref->flag & REF_ISSYMREF) + cp = copy_advance(cp, ",symref"); + if (ref->flag & REF_ISPACKED) + cp = copy_advance(cp, ",packed"); + if (cp == buf) + v->s = ""; + else { + *cp = '\0'; + v->s = xstrdup(buf + 1); + } + continue; + } else continue;