/* * Search for a directory entry directly within dir (without * recursing). Sort dir if necessary. subdirname must be a directory * name (i.e., end in '/'). If mkdir is set, then create the * directory if it is missing; otherwise, return NULL if the desired * directory cannot be found. dir must already be complete. */ static struct ref_dir *search_for_subdir(struct ref_dir *dir, const char *subdirname, size_t len, int mkdir) { int entry_index = search_ref_dir(dir, subdirname, len); struct ref_entry *entry; if (entry_index == -1) { if (!mkdir) return NULL; /* * Since dir is complete, the absence of a subdir * means that the subdir really doesn't exist; * therefore, create an empty record for it but mark * the record complete. */ entry = create_dir_entry(dir->cache, subdirname, len, 0); add_entry_to_dir(dir, entry); } else { entry = dir->entries[entry_index]; } return get_ref_dir(entry); }
struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache, const char *prefix, int prime_dir) { struct ref_dir *dir; struct cache_ref_iterator *iter; struct ref_iterator *ref_iterator; struct cache_ref_iterator_level *level; dir = get_ref_dir(cache->root); if (prefix && *prefix) dir = find_containing_dir(dir, prefix, 0); if (!dir) /* There's nothing to iterate over. */ return empty_ref_iterator_begin(); if (prime_dir) prime_ref_dir(dir, prefix); iter = xcalloc(1, sizeof(*iter)); ref_iterator = &iter->base; base_ref_iterator_init(ref_iterator, &cache_ref_iterator_vtable, 1); ALLOC_GROW(iter->levels, 10, iter->levels_alloc); iter->levels_nr = 1; level = &iter->levels[0]; level->index = -1; level->dir = dir; if (prefix && *prefix) { iter->prefix = xstrdup(prefix); level->prefix_state = PREFIX_WITHIN_DIR; } else { level->prefix_state = PREFIX_CONTAINS_DIR; } return ref_iterator; }
static struct ref_list *get_ref_dir(const char *submodule, const char *base, struct ref_list *list) { DIR *dir; const char *path; if (submodule) path = git_path_submodule(submodule, "%s", base); else path = git_path("%s", base); dir = opendir(path); if (dir) { struct dirent *de; int baselen = strlen(base); char *ref = xmalloc(baselen + 257); memcpy(ref, base, baselen); if (baselen && base[baselen-1] != '/') ref[baselen++] = '/'; while ((de = readdir(dir)) != NULL) { unsigned char sha1[20]; struct stat st; int flag; int namelen; const char *refdir; if (de->d_name[0] == '.') continue; namelen = strlen(de->d_name); if (namelen > 255) continue; if (has_extension(de->d_name, ".lock")) continue; memcpy(ref + baselen, de->d_name, namelen+1); refdir = submodule ? git_path_submodule(submodule, "%s", ref) : git_path("%s", ref); if (stat(refdir, &st) < 0) continue; if (S_ISDIR(st.st_mode)) { list = get_ref_dir(submodule, ref, list); continue; } if (submodule) { hashclr(sha1); flag = 0; if (resolve_gitlink_ref(submodule, ref, sha1) < 0) { hashclr(sha1); flag |= REF_BROKEN; } } else if (!resolve_ref(ref, sha1, 1, &flag)) { hashclr(sha1); flag |= REF_BROKEN; } list = add_ref(ref, sha1, flag, list, NULL); } free(ref); closedir(dir); } return sort_ref_list(list); }