Subject: [PATCH v2 0/2] [GSOC] ref-filter: add %(raw) atom

From: "ZheNing Hu via GitGitGadget" <[email-masked]>
Date: Fri, 04 Jun 2021 12:12:28 +0000

In order to make git cat-file --batch use ref-filter logic, %(raw) atom is
adding to ref-filter.

Change from last version:

 1. Change --<lang> and --format=%(raw) checkpoint to verify_ref_format(),
    which make it more scalable.
 2. Change grab_sub_body_contents() use struct expand_data *data instread of
    using obj,buf,buf_size to pass object info which can reduce the delivery
    of function parameters.

ZheNing Hu (2):
  [GSOC] ref-filter: add obj-type check in grab contents
  [GSOC] ref-filter: add %(raw) atom

 Documentation/git-for-each-ref.txt |   9 ++
 ref-filter.c                       | 164 +++++++++++++++++------
 t/t6300-for-each-ref.sh            | 207 +++++++++++++++++++++++++++++
 3 files changed, 343 insertions(+), 37 deletions(-)

base-commit: 1197f1a46360d3ae96bd9c15908a3a6f8e562207
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-966%2Fadlternative%2Fref-filter-raw-atom-v4-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-966/adlternative/ref-filter-raw-atom-v4-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/966

Range-diff vs v1:

 1:  97955705c22e ! 1:  48d256db5c34 [GSOC] ref-filter: add obj-type check in grab contents
     @@ ref-filter.c: static void append_lines(struct strbuf *out, const char *buf, unsi
       
       /* See grab_values */
      -static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf)
     -+static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf,
     -+				   struct object *obj)
     ++static void grab_sub_body_contents(struct atom_value *val, int deref, struct expand_data *data)
       {
       	int i;
       	const char *subpos = NULL, *bodypos = NULL, *sigpos = NULL;
     + 	size_t sublen = 0, bodylen = 0, nonsiglen = 0, siglen = 0;
     ++	void *buf = data->content;
     + 
     + 	for (i = 0; i < used_atom_cnt; i++) {
     + 		struct used_atom *atom = &used_atom[i];
      @@ ref-filter.c: static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf)
       			continue;
       		if (deref)
     @@ ref-filter.c: static void grab_sub_body_contents(struct atom_value *val, int der
      -		    !starts_with(name, "trailers") &&
      -		    !starts_with(name, "contents"))
      +
     -+		if ((obj->type != OBJ_TAG &&
     -+		     obj->type != OBJ_COMMIT) ||
     ++		if ((data->type != OBJ_TAG &&
     ++		     data->type != OBJ_COMMIT) ||
      +		    (strcmp(name, "body") &&
      +		     !starts_with(name, "subject") &&
      +		     !starts_with(name, "trailers") &&
     @@ ref-filter.c: static void grab_sub_body_contents(struct atom_value *val, int der
       			continue;
       		if (!subpos)
       			find_subpos(buf,
     -@@ ref-filter.c: static void grab_values(struct atom_value *val, int deref, struct object *obj, v
     +@@ ref-filter.c: static void fill_missing_values(struct atom_value *val)
     +  * pointed at by the ref itself; otherwise it is the object the
     +  * ref (which is a tag) refers to.
     +  */
     +-static void grab_values(struct atom_value *val, int deref, struct object *obj, void *buf)
     ++static void grab_values(struct atom_value *val, int deref, struct object *obj, struct expand_data *data)
     + {
     ++	void *buf = data->content;
     ++
       	switch (obj->type) {
       	case OBJ_TAG:
       		grab_tag_values(val, deref, obj);
      -		grab_sub_body_contents(val, deref, buf);
     -+		grab_sub_body_contents(val, deref, buf, obj);
     ++		grab_sub_body_contents(val, deref, data);
       		grab_person("tagger", val, deref, buf);
       		break;
       	case OBJ_COMMIT:
       		grab_commit_values(val, deref, obj);
      -		grab_sub_body_contents(val, deref, buf);
     -+		grab_sub_body_contents(val, deref, buf, obj);
     ++		grab_sub_body_contents(val, deref, data);
       		grab_person("author", val, deref, buf);
       		grab_person("committer", val, deref, buf);
       		break;
     +@@ ref-filter.c: static int get_object(struct ref_array_item *ref, int deref, struct object **obj
     + 			return strbuf_addf_ret(err, -1, _("parse_object_buffer failed on %s for %s"),
     + 					       oid_to_hex(&oi->oid), ref->refname);
     + 		}
     +-		grab_values(ref->value, deref, *obj, oi->content);
     ++		grab_values(ref->value, deref, *obj, oi);
     + 	}
     + 
     + 	grab_common_values(ref->value, deref, oi);
 2:  5a94705cdbc1 ! 2:  0efed9435b59 [GSOC] ref-filter: add %(raw) atom
     @@ ref-filter.c: static int parse_ref_filter_atom(const struct ref_format *format,
       	arg = memchr(sp, ':', ep - sp);
       	atom_len = (arg ? arg : ep) - sp;
       
     -+	if (format->quote_style && !strncmp(sp, "raw", 3) && !arg)
     -+		return strbuf_addf_ret(err, -1, _("--format=%.*s cannot be used with"
     -+				"--python, --shell, --tcl, --perl"), (int)(ep-atom), atom);
     -+
      +	/* Do we have the atom already used elsewhere? */
      +	for (i = 0; i < used_atom_cnt; i++) {
      +		int len = strlen(used_atom[i].name);
     @@ ref-filter.c: static int end_atom_handler(struct atom_value *atomv, struct ref_f
       		strbuf_swap(&current->output, &s);
       	}
       	strbuf_release(&s);
     -@@ ref-filter.c: static void append_lines(struct strbuf *out, const char *buf, unsigned long size
     +@@ ref-filter.c: int verify_ref_format(struct ref_format *format)
     + 		at = parse_ref_filter_atom(format, sp + 2, ep, &err);
     + 		if (at < 0)
     + 			die("%s", err.buf);
     ++		if (format->quote_style && used_atom[at].atom_type == ATOM_RAW &&
     ++		    used_atom[at].u.raw_data.option == RAW_BARE)
     ++			die(_("--format=%.*s cannot be used with"
     ++			      "--python, --shell, --tcl, --perl"), (int)(ep - sp - 2), sp + 2);
     + 		cp = ep + 1;
       
     - /* See grab_values */
     - static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf,
     --				   struct object *obj)
     -+				   unsigned long buf_size, struct object *obj)
     - {
     - 	int i;
     + 		if (skip_prefix(used_atom[at].name, "color:", &color))
     +@@ ref-filter.c: static void grab_sub_body_contents(struct atom_value *val, int deref, struct exp
       	const char *subpos = NULL, *bodypos = NULL, *sigpos = NULL;
     -@@ ref-filter.c: static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf,
     + 	size_t sublen = 0, bodylen = 0, nonsiglen = 0, siglen = 0;
     + 	void *buf = data->content;
     ++	unsigned long buf_size = data->size;
     + 
     + 	for (i = 0; i < used_atom_cnt; i++) {
       		struct used_atom *atom = &used_atom[i];
       		const char *name = atom->name;
       		struct atom_value *v = &val[i];
     @@ ref-filter.c: static void grab_sub_body_contents(struct atom_value *val, int der
      +			continue;
      +		}
      +
     - 		if ((obj->type != OBJ_TAG &&
     - 		     obj->type != OBJ_COMMIT) ||
     + 		if ((data->type != OBJ_TAG &&
     + 		     data->type != OBJ_COMMIT) ||
       		    (strcmp(name, "body") &&
     -@@ ref-filter.c: static void fill_missing_values(struct atom_value *val)
     -  * pointed at by the ref itself; otherwise it is the object the
     -  * ref (which is a tag) refers to.
     -  */
     --static void grab_values(struct atom_value *val, int deref, struct object *obj, void *buf)
     -+static void grab_values(struct atom_value *val, int deref, struct object *obj, struct expand_data *data)
     - {
     -+	void *buf = data->content;
     -+	unsigned long buf_size = data->size;
     -+
     - 	switch (obj->type) {
     - 	case OBJ_TAG:
     - 		grab_tag_values(val, deref, obj);
     --		grab_sub_body_contents(val, deref, buf, obj);
     -+		grab_sub_body_contents(val, deref, buf, buf_size, obj);
     - 		grab_person("tagger", val, deref, buf);
     - 		break;
     - 	case OBJ_COMMIT:
     - 		grab_commit_values(val, deref, obj);
     --		grab_sub_body_contents(val, deref, buf, obj);
     -+		grab_sub_body_contents(val, deref, buf, buf_size, obj);
     - 		grab_person("author", val, deref, buf);
     - 		grab_person("committer", val, deref, buf);
     +@@ ref-filter.c: static void grab_values(struct atom_value *val, int deref, struct object *obj, s
       		break;
       	case OBJ_TREE:
       		/* grab_tree_values(val, deref, obj, buf, sz); */
     -+		grab_sub_body_contents(val, deref, buf, buf_size, obj);
     ++		grab_sub_body_contents(val, deref, data);
       		break;
       	case OBJ_BLOB:
       		/* grab_blob_values(val, deref, obj, buf, sz); */
     -+		grab_sub_body_contents(val, deref, buf, buf_size, obj);
     ++		grab_sub_body_contents(val, deref, data);
       		break;
       	default:
       		die("Eh?  Object of type %d?", obj->type);
     -@@ ref-filter.c: static int get_object(struct ref_array_item *ref, int deref, struct object **obj
     - 			return strbuf_addf_ret(err, -1, _("parse_object_buffer failed on %s for %s"),
     - 					       oid_to_hex(&oi->oid), ref->refname);
     - 		}
     --		grab_values(ref->value, deref, *obj, oi->content);
     -+		grab_values(ref->value, deref, *obj, oi);
     - 	}
     - 
     - 	grab_common_values(ref->value, deref, oi);
      @@ ref-filter.c: static int populate_value(struct ref_array_item *ref, struct strbuf *err)
       		int deref = 0;
       		const char *refname;

-- 
gitgitgadget