Ref-filter: unification of 'tag -l', 'branch -l' and 'for-each-ref'
v2 cover Ref-filter: unification of 'tag -l', 'branch -l' and 'for-each-ref'
Hello,
After the 1st version of the WIP patch ($gmane/269461) this is a follow up.
Changes since 1st version :
* restructure to have 'struct ref_filter_data' which has a list of refs 'struct ref_list list', and the filters to apply 'struct ref_filter filter'
* reformat the commit to be better structured and easier to track
and more 'git blame' friendly.
* other small changes.
Also I'll be maintaining a repo on Github where I'll be pushing code more often. https://github.com/KarthikNayak/git
--
Regards,
Karthik
PATCH v2 1/2 for-each-ref: re-structure code for moving to 'ref-filter'
Re-factoring and renaming of code to make meaningful, targeted services available to other commands in efforts to change private scope of the code to public API by moving it to 'ref-filter'. Restructuring of code done to further modularize it to make API provisions simple and effective.
Rename 'refinfo' to 'ref_filter_item' and intoduce 'ref_filter_data' which will hold 'ref_filter' (Conditions to filter the refs on) and 'ref_list' (The list of ref_filter_items).
Modify the code to use 'ref_filter_data' and make some of the functions publically available by removind the static file scope.
--- builtin/for-each-ref.c | 212 ++++++++++++++++++++++++++++--------------------- 1 file changed, 121 insertions(+), 91 deletions(-)
builtin/for-each-ref.c +121 -91
@@ -31,12 +31,26 @@ struct ref_sort { unsigned reverse : 1; }; -struct refinfo { -char *refname; -unsigned char objectname[20 ]; -int flag; +struct ref_filter_item { +unsigned char sha1[20 ]; +int flags;const char *symref;struct atom_value *value; +char *name; +}; + +struct ref_list { +int nr, alloc; +struct ref_filter_item **items; +}; + +struct ref_filter { +const char **name_patterns; +}; + +struct ref_filter_data { +struct ref_list list; +struct ref_filter filter; }; static struct {
@@ -85,7 +99,7 @@ static struct {* a "*" to denote deref_tag(). * * We parse given format string and sort specifiers, and make a list -* of properties that we need to extract out of objects. refinfo +* of properties that we need to extract out of objects. ref_filter_item * structure will hold an array of values extracted that can be * indexed with the "atom number", which is an index into this * array.
@@ -98,7 +112,7 @@ static int need_color_reset_at_eol;/* * Used to parse format string and sort specifiers */ -static int parse_atom (const char *atom,const char *ep) +int parse_atom (const char *atom,const char *ep) {const char *sp;int i, at;
@@ -175,7 +189,7 @@ static const char *find_next(const char *cp)* Make sure the format string is well formed, and parse out * the used atoms. */ -static int verify_format (const char *format) +int verify_format (const char *format) {const char *cp, *sp;
@@ -622,7 +636,7 @@ static inline char *copy_advance(char *dst, const char *src)/* * Parse the object referred by ref, and grab needed value. */ -static void populate_value (struct refinfo *ref) +static void populate_value (struct ref_filter_item *ref) {void *buf;struct object *obj;
@@ -632,9 +646,9 @@ static void populate_value(struct refinfo *ref) ref->value =xcalloc (used_atom_cnt,sizeof (struct atom_value )); -if (need_symref && (ref->flag &REF_ISSYMREF ) && !ref->symref) { +if (need_symref && (ref->flags &REF_ISSYMREF ) && !ref->symref) {unsigned char unused1[20 ]; - ref->symref =resolve_refdup (ref->refname,RESOLVE_REF_READING , + ref->symref =resolve_refdup (ref->name,RESOLVE_REF_READING , unused1,NULL );if (!ref->symref) ref->symref ="" ;
@@ -655,14 +669,14 @@ static void populate_value(struct refinfo *ref) }if (starts_with (name,"refname" )) - refname = ref->refname; + refname = ref->name;else if (starts_with (name,"symref" )) refname = ref->symref ? ref->symref :"" ;else if (starts_with (name,"upstream" )) {/* only local branches may have an upstream */ -if (!starts_with (ref->refname,"refs/heads/" )) +if (!starts_with (ref->name,"refs/heads/" ))continue ; - branch =branch_get (ref->refname +11 ); + branch =branch_get (ref->name +11 );if (!branch || !branch->merge || !branch->merge[0 ] || !branch->merge[0 ]->dst)
@@ -677,9 +691,9 @@ static void populate_value(struct refinfo *ref)continue ; }else if (!strcmp (name,"flag" )) {char buf[256 ], *cp = buf; -if (ref->flag &REF_ISSYMREF ) +if (ref->flags &REF_ISSYMREF ) cp =copy_advance (cp,",symref" ); -if (ref->flag &REF_ISPACKED ) +if (ref->flags &REF_ISPACKED ) cp =copy_advance (cp,",packed" );if (cp == buf) v->s ="" ;
@@ -688,7 +702,7 @@ static void populate_value(struct refinfo *ref) v->s =xstrdup (buf +1 ); }continue ; - }else if (!deref &&grab_objectname (name, ref->objectname, v)) { + }else if (!deref &&grab_objectname (name, ref->sha1, v)) {continue ; }else if (!strcmp (name,"HEAD" )) {const char *head;
@@ -696,7 +710,7 @@ static void populate_value(struct refinfo *ref) head =resolve_ref_unsafe ("HEAD" ,RESOLVE_REF_READING , sha1,NULL ); -if (!strcmp (ref->refname, head)) +if (!strcmp (ref->name, head)) v->s ="*" ;else v->s =" " ;
@@ -774,13 +788,13 @@ static void populate_value(struct refinfo *ref)return ; need_obj: - buf =get_obj (ref->objectname, &obj, &size, &eaten); + buf =get_obj (ref->sha1, &obj, &size, &eaten);if (!buf)die ("missing object %s for %s" , -sha1_to_hex (ref->objectname), ref->refname); +sha1_to_hex (ref->sha1), ref->name);if (!obj)die ("parse_object_buffer failed on %s for %s" , -sha1_to_hex (ref->objectname), ref->refname); +sha1_to_hex (ref->sha1), ref->name);grab_values (ref->value,0 , obj, buf, size);if (!eaten)
@@ -808,10 +822,10 @@ static void populate_value(struct refinfo *ref) buf =get_obj (tagged, &obj, &size, &eaten);if (!buf)die ("missing object %s for %s" , -sha1_to_hex (tagged), ref->refname); +sha1_to_hex (tagged), ref->name);if (!obj)die ("parse_object_buffer failed on %s for %s" , -sha1_to_hex (tagged), ref->refname); +sha1_to_hex (tagged), ref->name);grab_values (ref->value,1 , obj, buf, size);if (!eaten)free (buf);
@@ -821,7 +835,7 @@ static void populate_value(struct refinfo *ref)* Given a ref, return the value for the atom. This lazily gets value * out of the object by calling populate value. */ -static void get_value (struct refinfo *ref,int atom,struct atom_value **v) +static void get_value (struct ref_filter_item *ref,int atom,struct atom_value **v) {if (!ref->value) {populate_value (ref);
@@ -830,65 +844,81 @@ static void get_value(struct refinfo *ref, int atom, struct atom_value **v) *v = &ref->value[atom]; } -struct grab_ref_cbdata { -struct refinfo **grab_array; -const char **grab_pattern; -int grab_cnt; -}; +/* +* Given a refname, return 1 if the refname matches with one of the patterns +* while the pattern is a pathname like 'refs/tags' or 'refs/heads/master' +* and so on, else return 0. Supports use of wild characters. +*/ +static int match_name_as_path (const char **pattern,const char *refname) +{ +int namelen =strlen (refname); +for (; *pattern; pattern++) { +const char *p = *pattern; +int plen =strlen (p); + +if ((plen <= namelen) && + !strncmp (refname, p, plen) && + (refname[plen] =='\0' || + refname[plen] =='/' || + p[plen-1 ] =='/' )) +return 1 ; +if (!wildmatch (p, refname,WM_PATHNAME ,NULL )) +return 1 ; + } +return 0 ; +} + +/* Allocate space for a new ref_filter_item and copy the sha1 and flags to it */ +static struct ref_filter_item *new_ref_filter_item (const char *refname, +const unsigned char *sha1, +int flag) +{ +struct ref_filter_item *ref =xcalloc (1 ,sizeof (struct ref_filter_item )); + ref->name =xstrdup (refname); +hashcpy (ref->sha1, sha1); + ref->flags = flag; + +return ref; +}/* -* A call-back given to for_each_ref(). Filter refs and keep them for -* later object processing. +* A call-back given to for_each_ref(). Process the refs and store only required refs +* into the ref_filter_data structure. */ -static int grab_single_ref (const char *refname,const unsigned char *sha1,int flag,void *cb_data) +int ref_filter_handler (const char *refname,const unsigned char *sha1,int flag,void *data) { -struct grab_ref_cbdata *cb = cb_data; -struct refinfo *ref; -int cnt; +struct ref_filter_data *ref_data = data; +struct ref_filter_item *ref;if (flag &REF_BAD_NAME ) { -warning ("ignoring ref with broken name %s" , refname); -return 0 ; +warning ("ignoring ref with broken name %s" , refname); +return 0 ; } -if (*cb->grab_pattern) { -const char **pattern; -int namelen =strlen (refname); -for (pattern = cb->grab_pattern; *pattern; pattern++) { -const char *p = *pattern; -int plen =strlen (p); - -if ((plen <= namelen) && - !strncmp (refname, p, plen) && - (refname[plen] =='\0' || - refname[plen] =='/' || - p[plen-1 ] =='/' )) -break ; -if (!wildmatch (p, refname,WM_PATHNAME ,NULL )) -break ; - } -if (!*pattern) -return 0 ; - } +if (*ref_data->filter.name_patterns && !match_name_as_path (ref_data->filter.name_patterns, refname)) +return 0 ; + + ref =new_ref_filter_item (refname, sha1, flag); + +REALLOC_ARRAY (ref_data->list.items, ref_data->list.nr +1 ); + ref_data->list.items[ref_data->list.nr++] = ref; -/* -* 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. -*/ - ref =xcalloc (1 ,sizeof (*ref)); - ref->refname =xstrdup (refname); -hashcpy (ref->objectname, sha1); - ref->flag = flag; - - cnt = cb->grab_cnt; -REALLOC_ARRAY (cb->grab_array, cnt +1 ); - cb->grab_array[cnt++] = ref; - cb->grab_cnt = cnt;return 0 ; } -static int cmp_ref_sort (struct ref_sort *s,struct refinfo *a,struct refinfo *b) +/* Free all memory allocated for ref_filter_data */ +void ref_filter_clear (struct ref_filter_data *ref_data) +{ +int i; + +for (i =0 ; i < ref_data->list.nr; i++) +free (ref_data->list.items[i]); +free (ref_data->list.items); + ref_data->list.items =NULL ; + ref_data->list.nr = ref_data->list.alloc =0 ; +} + +static int cmp_ref_sort (struct ref_sort *s,struct ref_filter_item *a,struct ref_filter_item *b) {struct atom_value *va, *vb;int cmp;
@@ -915,8 +945,8 @@ static int cmp_ref_sort(struct ref_sort *s, struct refinfo *a, struct refinfo *bstatic struct ref_sort *ref_sort;static int compare_refs (const void *a_,const void *b_) { -struct refinfo *a = *((struct refinfo **)a_); -struct refinfo *b = *((struct refinfo **)b_); +struct ref_filter_item *a = *((struct ref_filter_item **)a_); +struct ref_filter_item *b = *((struct ref_filter_item **)b_);struct ref_sort *s;for (s = ref_sort; s; s = s->next) {
@@ -927,10 +957,11 @@ static int compare_refs(const void *a_, const void *b_)return 0 ; } -static void sort_refs (struct ref_sort *sort,struct refinfo **refs,int num_refs) +void sort_refs (struct ref_sort *sort,struct ref_filter_data *ref_data) { ref_sort = sort; -qsort (refs, num_refs,sizeof (struct refinfo *), compare_refs); +qsort (ref_data->list.items, ref_data->list.nr, +sizeof (struct ref_filter_item *), compare_refs); }static void print_value (struct atom_value *v,int quote_style)
@@ -997,7 +1028,7 @@ static void emit(const char *cp, const char *ep) } } -static void show_ref (struct refinfo *info,const char *format,int quote_style) +void show_ref (struct ref_filter_item *info,const char *format,int quote_style) {const char *cp, *sp, *ep;
@@ -1026,7 +1057,8 @@ static void show_ref(struct refinfo *info, const char *format, int quote_style)putchar ('\n' ); } -static struct ref_sort *default_sort (void ) +/* If no sorting option is given, use refname to sort as default */ +struct ref_sort *ref_default_sort (void ) {static const char cstr_name[] ="refname" ;
@@ -1037,7 +1069,7 @@ static struct ref_sort *default_sort(void)return sort; } -static int opt_parse_sort (const struct option *opt,const char *arg,int unset) +int ref_opt_parse_sort (const struct option *opt,const char *arg,int unset) {struct ref_sort **sort_tail = opt->value;struct ref_sort *s;
@@ -1066,12 +1098,12 @@ static char const * const for_each_ref_usage[] = { int cmd_for_each_ref(int argc, const char **argv, const char *prefix) { - int i, num_refs; + int i; const char *format = "%(objectname) %(objecttype)\t%(refname)"; struct ref_sort *sort = NULL, **sort_tail = &sort; int maxcount = 0, quote_style = 0; - struct refinfo **refs; - struct grab_ref_cbdata cbdata; + struct ref_filter_data ref_data; + memset(&ref_data, 0, sizeof(ref_data)); struct option opts[] = { OPT_BIT('s', "shell", "e_style,
@@ -1087,7 +1119,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)OPT_INTEGER (0 ,"count" , &maxcount,N_ ("show only <n> matched refs" )),OPT_STRING (0 ,"format" , &format,N_ ("format" ),N_ ("format to use for the output" )),OPT_CALLBACK (0 ,"sort" , sort_tail,N_ ("key" ), -N_ ("field name to sort on" ), &opt_parse_sort), +N_ ("field name to sort on" ), &ref_opt_parse_sort), OPT_END(), };
@@ -1104,22 +1136,20 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)usage_with_options (for_each_ref_usage, opts);if (!sort) - sort =default_sort (); + sort =ref_default_sort ();/* for warn_ambiguous_refs */ git_config (git_default_config,NULL ); -memset (&cbdata,0 ,sizeof (cbdata)); - cbdata.grab_pattern = argv; -for_each_rawref (grab_single_ref, &cbdata); - refs = cbdata.grab_array; - num_refs = cbdata.grab_cnt; + ref_data.filter.name_patterns = argv; +for_each_rawref (ref_filter_handler, &ref_data); -sort_refs (sort, refs, num_refs); +sort_refs (sort, &ref_data); -if (!maxcount || num_refs < maxcount) - maxcount = num_refs; +if (!maxcount || ref_data.list.nr < maxcount) + maxcount = ref_data.list.nr;for (i =0 ; i < maxcount; i++) -show_ref (refs[i], format, quote_style); +show_ref (ref_data.list.items[i], format, quote_style); +ref_filter_clear (&ref_data);return 0 ; }
Signature · 1 line
2.4.1
Re: [PATCH v2 1/2] for-each-ref: re-structure code for moving to 'ref-filter'
builtin/for-each-ref.c struct ref_sort { · line 40
Quoted 11 lines · Karthik Nayak
builtin/for-each-ref.c +5
-4-struct refinfo { -char *refname; -unsigned char objectname[20 ]; -int flag; +struct ref_filter_item { +unsigned char sha1[20 ]; +int flags;const char *symref;struct atom_value *value; +char *name; +};
I do not see much point in renaming between these two. The latter makes it sound as if this is only for "filtering" and from that angle of view is probably a worse name. If you do not think of a better one, and if you are going to name the array that contains this thing "ref_list", calling "ref_list_item" would be following suit to what string-list did.
I somehow had an impression that we are trying to move away from calling the name of objects as "sha1[]" as a longer term goal? I do not think it is particularly a good idea to start using "struct object_id" in this series (it can be done after everything is done and you still have time left in GSoC), but I do not see how much value this interim renaming (because eventually we would change not just name but type, and the final name will _not_ be sha1[] but more closer to "object name") adds value.
You didn't explain why you reordered the fields, either. Were you planning to make the name[] field to flex-array to reduce need for one level of redirection or something?
Quoted 4 lines
builtin/for-each-ref.c +4
-0+ +struct ref_list { +int nr, alloc; +struct ref_filter_item **items;
builtin/for-each-ref.c struct ref_sort { · line 54
Quoted 10 lines
builtin/for-each-ref.c +9
-0+}; + +struct ref_filter { +const char **name_patterns; +}; + +struct ref_filter_data { +struct ref_list list; +struct ref_filter filter; };
I agree that "grab" part of "grab_ref_cbdata" sounds unprofessional, and using "ref_filter_" to signal that this callback data is about ref-filter API might be a good idea (I do not think the original is too bad, either, though). I do not think you would use this struct anywhere other than as the callback data; you would want to end its name with "_cbdata", not just "_data", to make it clear why these two unrelated things are in a single struct (the only time these two concepts, operation and operatee, meet is when they need to be passed to an "apply operation to operatee" function; there is no such "this set of operatee always are for this operation" association between them---which is what I mean by 'two unrelated things').
builtin/for-each-ref.c static int need_color_reset_at_eol; · line 115
Quoted 6 lines
builtin/for-each-ref.c +1
-1@@ -98,7 +112,7 @@ static int need_color_reset_at_eol;/* * Used to parse format string and sort specifiers */ -static int parse_atom (const char *atom,const char *ep) +int parse_atom (const char *atom,const char *ep)
It was perfectly good name as a file-scope static; within the context of 'for-each-ref' implementation, when every somebody says "atom", you would know it is those %(atomic-data-item) things, and parse_atom() would be a helper function to do so.
But it is *WAY* too generic a name to make public, where you are naming things in the whole context of Git implementation. If you used the word "atom" while discussing formatting done with "git for-each-ref" with somebody else, it would be unambiguously clear what you mean; you wouldn't say "I am writing a function to parse 'atoms' in Git"---that's too broad and you will get "'atom', in what sense?" in response.
builtin/for-each-ref.c static const char *find_next(const char *cp) · line 192
Quoted 6 lines
builtin/for-each-ref.c +1
-1@@ -175,7 +189,7 @@ static const char *find_next(const char *cp)* Make sure the format string is well formed, and parse out * the used atoms. */ -static int verify_format (const char *format) +int verify_format (const char *format)
Ditto.
builtin/for-each-ref.c static inline char *copy_advance(char *dst, const char *src) · line 640
Quoted 7 lines
builtin/for-each-ref.c +1
-1@@ -622,7 +636,7 @@ static inline char *copy_advance(char *dst, const char *src)/* * Parse the object referred by ref, and grab needed value. */ -static void populate_value (struct refinfo *ref) +static void populate_value (struct ref_filter_item *ref) {
As long as this will stay private within the new ref-filter.c after the move, this name is OK.
Quoted 20 lines
builtin/for-each-ref.c +3
-3@@ -655,14 +669,14 @@ static void populate_value(struct refinfo *ref) }if (starts_with (name,"refname" )) - refname = ref->refname; + refname = ref->name;else if (starts_with (name,"symref" )) refname = ref->symref ? ref->symref :"" ;else if (starts_with (name,"upstream" )) {/* only local branches may have an upstream */ -if (!starts_with (ref->refname,"refs/heads/" )) +if (!starts_with (ref->name,"refs/heads/" ))continue ; - branch =branch_get (ref->refname +11 ); + branch =branch_get (ref->name +11 );if (!branch || !branch->merge || !branch->merge[0 ] || !branch->merge[0 ]->dst)@@ -677,9 +691,9 @@ static void populate_value(struct refinfo *ref)continue ;
builtin/for-each-ref.c static void populate_value(struct refinfo *ref) · line 699
Quoted 10 lines
builtin/for-each-ref.c +2
-2}else if (!strcmp (name,"flag" )) {char buf[256 ], *cp = buf; -if (ref->flag &REF_ISSYMREF ) +if (ref->flags &REF_ISSYMREF ) cp =copy_advance (cp,",symref" ); -if (ref->flag &REF_ISPACKED ) +if (ref->flags &REF_ISPACKED ) cp =copy_advance (cp,",packed" );if (cp == buf) v->s ="" ;
I see fallouts from the two renamed fields in the above hunks. Was the rename necessary?
refinfo keeps two names (ref and object) and calling one "refname" made perfect sense (and calling other "objectname" did, too). Has anything around its use changed to invalidate that rationale after the structure was renamed?
When we say 'flag', it is obvious that it is a "flag word", i.e. a word that holds collection of flags. Otherwise, we would have named each "unsigned foo_flag : 1" with meaningful names. Was it necessary to make the field name longer?
builtin/for-each-ref.c static void populate_value(struct refinfo *ref) · line 706
Quoted 7 lines
builtin/for-each-ref.c +1
-1@@ -688,7 +702,7 @@ static void populate_value(struct refinfo *ref) v->s =xstrdup (buf +1 ); }continue ; - }else if (!deref &&grab_objectname (name, ref->objectname, v)) { + }else if (!deref &&grab_objectname (name, ref->sha1, v)) {continue ;
Mental note: grab_objectname() still remains, so I'd guess that it will not be moved from this file or it will stay private after it is moved.
Another mental note: it was a consistent naming for the function to grab objectname to store the result into objectname[] field. Now it stores into sha1[] field.
Quoted 13 lines
builtin/for-each-ref.c +13
-0+/* +* Given a refname, return 1 if the refname matches with one of the patterns +* while the pattern is a pathname like 'refs/tags' or 'refs/heads/master' +* and so on, else return 0. Supports use of wild characters. +*/ +static int match_name_as_path (const char **pattern,const char *refname) +{ +int namelen =strlen (refname); +for (; *pattern; pattern++) { +const char *p = *pattern; +int plen =strlen (p); + + if ((plen <= namelen) &&
builtin/for-each-ref.c static void get_value(struct refinfo *ref, int atom, struct atom_value **v) · line 869
Quoted 10 lines
builtin/for-each-ref.c +10
-0+ !strncmp (refname, p, plen) && + (refname[plen] =='\0' || + refname[plen] =='/' || + p[plen-1] == '/')) + return 1; +if (!wildmatch (p, refname,WM_PATHNAME ,NULL )) +return 1 ; + } +return 0 ; +}
Yuck; I can see what you are doing but can you imitate what the more experienced people (e.g. peff, mhagger) do when restructuring existing code and do things in smaller increments? For example, I think it should be a separate preparatory patch, even before these renames of structures, fields and functions, to extract this helper function out of grab_single_ref() function.
builtin/for-each-ref.c static void get_value(struct refinfo *ref, int atom, struct atom_value **v) · line 882
Quoted 13 lines
builtin/for-each-ref.c +13
-0+ +/* Allocate space for a new ref_filter_item and copy the sha1 and flags to it */ +static struct ref_filter_item *new_ref_filter_item (const char *refname, +const unsigned char *sha1, +int flag) +{ +struct ref_filter_item *ref =xcalloc (1 ,sizeof (struct ref_filter_item )); + ref->name =xstrdup (refname); +hashcpy (ref->sha1, sha1); + ref->flags = flag; + +return ref; +}
And extracting this could be another separate preparatory step before renames (but I didn't look too closely).
I won't be commenting on the remainder of the patch in this message, as I need to step out. I see quite a many instances of the same "overly generic public names" in your "s/static //".
Re: [PATCH v2 1/2] for-each-ref: re-structure code for moving to 'ref-filter'
Quoted 8 lines
I do not see much point in renaming between these two. The latter makes it sound as if this is only for "filtering" and from that angle of view is probably a worse name. If you do not think of a better one, and if you are going to name the array that contains this thing "
ref_list", calling "ref_list_item" would be following suit to what string-list did.
Well I just wanted to keep it related to 'ref-filter', I think 'ref_list_item'
sounds better after seeing your point of view.
Quoted 10 lines
I somehow had an impression that we are trying to move away from calling the name of objects as "sha1[]" as a longer term goal? I do not think it is particularly a good idea to start using "struct
object_id" in this series (it can be done after everything is done and you still have time left in GSoC), but I do not see how much value this interim renaming (because eventually we would change not just name but type, and the final name will _not_ be sha1[] but more closer to "object name") adds value.
I did that to resemble whats usually being used in similar structures,
a simple grep of "sha1[20];" resulted in 344 uses.
I didn't know about the "we are trying to move away from calling the name of objects as "sha1[]"". Will leave it as objectname then.
Quoted 5 lines
You didn't explain why you reordered the fields, either. Were you planning to make the name[] field to flex-array to reduce need for one level of redirection or something?
Yes! exactly why the re-order, was going to rebase it and squash it in, if the code seemed to be up and running.
Quoted 14 lines
I agree that "grab" part of "
grab_ref_cbdata" sounds unprofessional, and using "ref_filter_" to signal that this callback data is about ref-filter API might be a good idea (I do not think the original is too bad, either, though). I do not think you would use this struct anywhere other than as the callback data; you would want to end its name with "_cbdata", not just "_data", to make it clear why these two unrelated things are in a single struct (the only time these two concepts, operation and operatee, meet is when they need to be passed to an "apply operation to operatee" function; there is no such "this set of operatee always are for this operation" association between them---which is what I mean by 'two unrelated things').
sure, will do :) thanks for putting that out.
Quoted 16 lines
It was perfectly good name as a file-scope static; within the context of 'for-each-ref' implementation, when every somebody says "atom", you would know it is those %(atomic-data-item) things, and
parse_atom()would be a helper function to do so.But it is *WAY* too generic a name to make public, where you are naming things in the whole context of Git implementation. If you used the word "atom" while discussing formatting done with "git for-each-ref" with somebody else, it would be unambiguously clear what you mean; you wouldn't say "I am writing a function to parse 'atoms' in Git"---that's too broad and you will get "'atom', in what sense?" in response.
Quoted 2 lines
Ditto.
Yes, that does seem to be too vague for a public function name, will amend it.
Quoted 4 lines
As long as this will stay private within the new
ref-filter.cafter the move, this name is OK.
That'll mostly stay private, if required will change the name along.
Quoted 9 lines
I see fallouts from the two renamed fields in the above hunks. Was the rename necessary?
refinfo keeps two names (ref and object) and calling one "refname" made perfect sense (and calling other "objectname" did, too). Has anything around its use changed to invalidate that rationale after the structure was renamed?
I guess it was unnecessary, my bad.
Quoted 6 lines
When we say 'flag', it is obvious that it is a "flag word", i.e. a word that holds collection of flags. Otherwise, we would have named each "unsigned
foo_flag: 1" with meaningful names. Was it necessary to make the field name longer?
Just felt flags to be more descriptive, well "Otherwise, we would have named each "unsigned foo_flag : 1" with meaningful names. " makes sense.
Quoted 6 lines
builtin/for-each-ref.c static void populate_value(struct refinfo *ref) · line 691
Quoted 5 lines
builtin/for-each-ref.c +0
-1@@ -688,7 +702,7 @@ static void populate_value(struct refinfo *ref) v->s =xstrdup (buf +1 ); }continue ; - } else if (!deref && grab_objectname(name, ref->objectname,v)) {
Quoted 7 lines
builtin/for-each-ref.c static void populate_value(struct refinfo *ref) · line 706
Quoted 2 lines
builtin/for-each-ref.c +1
-0+ }else if (!deref &&grab_objectname (name, ref->sha1, v)) {continue ;Mental note:
grab_objectname()still remains, so I'd guess that it will not be moved from this file or it will stay private after it is moved.
It will be private.
Quoted 5 lines
Another mental note: it was a consistent naming for the function to grab objectname to store the result into objectname[] field. Now it stores into sha1[] field.
yes, seems a bit off.
Quoted 8 lines
Yuck; I can see what you are doing but can you imitate what the more experienced people (e.g. peff, mhagger) do when restructuring existing code and do things in smaller increments? For example, I think it should be a separate preparatory patch, even before these renames of structures, fields and functions, to extract this helper function out of
grab_single_ref()function.
Shall do so.
Quoted 4 lines
And extracting this could be another separate preparatory step before renames (but I didn't look too closely).
Sure.
Quoted 5 lines
I won't be commenting on the remainder of the patch in this message, as I need to step out. I see quite a many instances of the same "overly generic public names" in your "s/static //".
Will work on it, thanks for the suggestions.
Signature · 2 lines
Regards, Karthik
Re: [PATCH v2 1/2] for-each-ref: re-structure code for moving to 'ref-filter'
Quoted 11 lines · Karthik Nayak
Quoted 7 lines
I do not see much point in renaming between these two. The latter makes it sound as if this is only for "filtering" and from that angle of view is probably a worse name. If you do not think of a better one, and if you are going to name the array that contains this thing "
ref_list", calling "ref_list_item" would be following suit to what string-list did.Well I just wanted to keep it related to 'ref-filter', I think '
ref_list_item'
sounds better after seeing your point of view.
Also I think Matthieu already commented that "filter" was out of place for that struct. I still think your ref_list is better called ref_array, but that is a minor point. Use of "foo_list" in our codebase is predominantly (because we use "commit_list" very often in the core part of the system) for a linear linked list where you do not have a random access to the items. string-list is misnomer, I would think.
Quoted 2 lines
I didn't know about the "we are trying to move away from calling the name of objects as "sha1[]"". Will leave it as objectname then.
I think you now know after seeing that 56-patch series ;-)
Quoted 7 lines
Quoted 4 lines
You didn't explain why you reordered the fields, either. Were you planning to make the name[] field to flex-array to reduce need for one level of redirection or something?
Yes! exactly why the re-order, was going to rebase it and squash it in, if the code seemed to be up and running.
If that is the case, I would suggest making that "turn it flex array" a separate step.
Re: [PATCH v2 1/2] for-each-ref: re-structure code for moving to 'ref-filter'
Quoted 9 lines
Also I think Matthieu already commented that "filter" was out of place for that struct. I still think your
ref_listis better calledref_array, but that is a minor point. Use of "foo_list" in our codebase is predominantly (because we use "commit_list" very often in the core part of the system) for a linear linked list where you do not have a random access to the items. string-list is misnomer, I would think.
ref_array also sounds good, yes! there might be confusion and might be considered a linked list rather than an array. Will change.
Quoted 3 lines
I think you now know after seeing that 56-patch series ;-)
Haha, That definitely helped.
Quoted 4 lines
If that is the case, I would suggest making that "turn it flex array" a separate step.
Sure.
Signature · 2 lines
Regards, Karthik
Re: [PATCH v2 1/2] for-each-ref: re-structure code for moving to 'ref-filter'
In reply to Junio C HamanoQuoted 3 lines · Junio C Hamano
Yuck; I can see what you are doing but can you imitate what the more experienced people (e.g. peff, mhagger) do when restructuring existing code and do things in smaller increments?
Seconded. Some reasons/guide to split:
* Split trivial and non-trivial stuff. I can quickly review a "rename-only" patch even if it's a bit long (essentially, I'll check that you did find-and-replace properly), but reviewing a mix of renames and actual code change is hard.
* Split controversial and non-controversial stuff. For example, you changed the ordering of fields in a struct. Perhaps it was not a good idea. Perhaps it was a good idea, but then you want this reordering to be alone in its patch so that you can explain why it's a good idea in the commit message (you'll see me use the word "why" a lot when talking about commit messages; not a coincidence).
* Split code movement and other stuff. For example extraction of match_name_as_path() would be trivial if made in its own patch.
I'd also make a separate patch "introduce the ref_list data-structure" to introduce struct ref_list and basic helper functions (constructors, mutators, destructors).
It will take time and may appear to be counter-productive at first, but you'll get used to it, and you'll end up being actually more productive this way (well, maybe not "you" but the set "you + reviewers").
Signature · 2 lines
Matthieu Moy http://www-verimag.imag.fr/~moy/
Re: [PATCH v2 1/2] for-each-ref: re-structure code for moving to 'ref-filter'
Quoted 7 lines · Matthieu Moy
Seconded. Some reasons/guide to split:
* Split trivial and non-trivial stuff. I can quickly review a "rename-only" patch even if it's a bit long (essentially, I'll check that you did find-and-replace properly), but reviewing a mix of renames and actual code change is hard.
Quoted 6 lines
* Split controversial and non-controversial stuff. For example, you changed the ordering of fields in a struct. Perhaps it was not a good idea. Perhaps it was a good idea, but then you want this reordering to be alone in its patch so that you can explain why it's a good idea in the commit message (you'll see me use the word "why" a lot when talking about commit messages; not a coincidence).u
Since one of the patches is to restructure and rename 'for-each-ref', I thought It would be ideal to introduce the data structures within that patch, What do you think?
Quoted 4 lines
* Split code movement and other stuff. For example extraction of
match_name_as_path()would be trivial if made in its own patch.
Quoted 8 lines
I'd also make a separate patch "introduce the
ref_listdata-structure" to introduce structref_listand basic helper functions (constructors, mutators, destructors).It will take time and may appear to be counter-productive at first, but you'll get used to it, and you'll end up being actually more productive this way (well, maybe not "you" but the set "you + reviewers").
Thanks for this.
Signature · 2 lines
Regards, Karthik
Re: [PATCH v2 1/2] for-each-ref: re-structure code for moving to 'ref-filter'
Quoted 15 lines · Karthik Nayak
Quoted 7 lines · Matthieu Moy
Seconded. Some reasons/guide to split:
* Split trivial and non-trivial stuff. I can quickly review a "rename-only" patch even if it's a bit long (essentially, I'll check that you did find-and-replace properly), but reviewing a mix of renames and actual code change is hard.
Quoted 6 lines
* Split controversial and non-controversial stuff. For example, you changed the ordering of fields in a struct. Perhaps it was not a good idea. Perhaps it was a good idea, but then you want this reordering to be alone in its patch so that you can explain why it's a good idea in the commit message (you'll see me use the word "why" a lot when talking about commit messages; not a coincidence).
Quoted 3 lines
Since one of the patches is to restructure and rename 'for-each-ref', I thought It would be ideal to introduce the data structures within that patch, What do you think?
I don't have a universal answer: in general I prefer (let's say "this list prefers") splitting as much as possible. It may make sense to group "add data structure X" with "use data-structure X" to make sure that functions you introduce have a caller.
What's clear is that your PATCH 1/2 is not split enough. Just go through it, you'll see code movement (a pain to review in patch format), straigthforward renamings (easy to review as-is, but disturbs the reviewer when mixed with something else) and actual new code.
Signature · 2 lines
Matthieu Moy http://www-verimag.imag.fr/~moy/
PATCH v2 2/2 ref-filter: move code from 'for-each-ref'
In reply to Karthik NayakMove most of the code from 'for-each-ref' to 'ref-filter' to make it publically available to other commands, this is to unify the code of 'tag -l', 'branch -l' and 'for-each-ref' so that they can share their implementations with each other.
--- Makefile | 1 + builtin/for-each-ref.c | 1089 +----------------------------------------------- ref-filter.c | 1051 ++++++++++++++++++++++++++++++++++++++++++++++ ref-filter.h | 65 +++ 4 files changed, 1118 insertions(+), 1088 deletions(-) create mode 100644 ref-filter.c create mode 100644 ref-filter.h
Makefile +1 -0
@@ -761,6 +761,7 @@ LIB_OBJS += reachable.o LIB_OBJS += read-cache.o LIB_OBJS += reflog-walk.o LIB_OBJS += refs.o +LIB_OBJS += ref-filter.o LIB_OBJS += remote.o LIB_OBJS += replace_object.o LIB_OBJS += rerere.o
builtin/for-each-ref.c +1 -1088
1,096 lines not on this page · raw message
ref-filter.c new file +1051 -0
1,051 lines not on this page · raw message
ref-filter.h new file +65 -0
65 lines not on this page · raw message
Signature · 1 line
2.4.1