diff options
Diffstat (limited to 'tree-walk.c')
-rw-r--r-- | tree-walk.c | 60 |
1 files changed, 51 insertions, 9 deletions
diff --git a/tree-walk.c b/tree-walk.c index bea819d826..3a94959d64 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -1,10 +1,10 @@ #include "cache.h" #include "tree-walk.h" -#include "unpack-trees.h" #include "dir.h" #include "object-store.h" #include "tree.h" #include "pathspec.h" +#include "json-writer.h" static const char *get_mode(const char *str, unsigned int *modep) { @@ -49,7 +49,7 @@ static int decode_tree_entry(struct tree_desc *desc, const char *buf, unsigned l desc->entry.path = path; desc->entry.mode = canon_mode(mode); desc->entry.pathlen = len - 1; - hashcpy(desc->entry.oid.hash, (const unsigned char *)path + len); + oidread(&desc->entry.oid, (const unsigned char *)path + len); return 0; } @@ -168,6 +168,25 @@ int tree_entry_gently(struct tree_desc *desc, struct name_entry *entry) return 1; } +static int traverse_trees_atexit_registered; +static int traverse_trees_count; +static int traverse_trees_cur_depth; +static int traverse_trees_max_depth; + +static void trace2_traverse_trees_statistics_atexit(void) +{ + struct json_writer jw = JSON_WRITER_INIT; + + jw_object_begin(&jw, 0); + jw_object_intmax(&jw, "traverse_trees_count", traverse_trees_count); + jw_object_intmax(&jw, "traverse_trees_max_depth", traverse_trees_max_depth); + jw_end(&jw); + + trace2_data_json("traverse_trees", the_repository, "statistics", &jw); + + jw_release(&jw); +} + void setup_traverse_info(struct traverse_info *info, const char *base) { size_t pathlen = strlen(base); @@ -181,6 +200,11 @@ void setup_traverse_info(struct traverse_info *info, const char *base) info->namelen = pathlen; if (pathlen) info->prev = &dummy; + + if (trace2_is_enabled() && !traverse_trees_atexit_registered) { + atexit(trace2_traverse_trees_statistics_atexit); + traverse_trees_atexit_registered = 1; + } } char *make_traverse_path(char *path, size_t pathlen, @@ -410,15 +434,26 @@ int traverse_trees(struct index_state *istate, struct traverse_info *info) { int error = 0; - struct name_entry *entry = xmalloc(n*sizeof(*entry)); + struct name_entry entry[MAX_TRAVERSE_TREES]; int i; - struct tree_desc_x *tx = xcalloc(n, sizeof(*tx)); + struct tree_desc_x tx[ARRAY_SIZE(entry)]; struct strbuf base = STRBUF_INIT; int interesting = 1; char *traverse_path; - for (i = 0; i < n; i++) + traverse_trees_count++; + traverse_trees_cur_depth++; + + if (traverse_trees_cur_depth > traverse_trees_max_depth) + traverse_trees_max_depth = traverse_trees_cur_depth; + + if (n >= ARRAY_SIZE(entry)) + BUG("traverse_trees() called with too many trees (%d)", n); + + for (i = 0; i < n; i++) { tx[i].d = t[i]; + tx[i].skip = NULL; + } if (info->prev) { strbuf_make_traverse_path(&base, info->prev, @@ -506,13 +541,13 @@ int traverse_trees(struct index_state *istate, if (mask & (1ul << i)) update_extended_entry(tx + i, entry + i); } - free(entry); for (i = 0; i < n; i++) free_extended_entry(tx + i); - free(tx); free(traverse_path); info->traverse_path = NULL; strbuf_release(&base); + + traverse_trees_cur_depth--; return error; } @@ -849,7 +884,14 @@ static int match_entry(const struct pathspec_item *item, if (matchlen > pathlen) { if (match[pathlen] != '/') return 0; - if (!S_ISDIR(entry->mode) && !S_ISGITLINK(entry->mode)) + /* + * Reject non-directories as partial pathnames, except + * when match is a submodule with a trailing slash and + * nothing else (to handle 'submod/' and 'submod' + * uniformly). + */ + if (!S_ISDIR(entry->mode) && + (!S_ISGITLINK(entry->mode) || matchlen > pathlen + 1)) return 0; } @@ -1124,7 +1166,7 @@ match_wildcards: * later on. * max_depth is ignored but we may consider support it * in future, see - * https://public-inbox.org/git/7vmxo5l2g4.fsf@alter.siamese.dyndns.org/ + * https://lore.kernel.org/git/7vmxo5l2g4.fsf@alter.siamese.dyndns.org/ */ if (ps->recursive && S_ISDIR(entry->mode)) return entry_interesting; |