From: Junio C Hamano Date: Mon, 26 Jan 2009 01:13:34 +0000 (-0800) Subject: Merge branch 'kb/lstat-cache' X-Git-Tag: v1.6.2-rc0~88 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/0990e7aaaa63ca908dbdfc379af132068e4b066f?ds=inline;hp=-c Merge branch 'kb/lstat-cache' * kb/lstat-cache: lstat_cache(): introduce clear_lstat_cache() function lstat_cache(): introduce invalidate_lstat_cache() function lstat_cache(): introduce has_dirs_only_path() function lstat_cache(): introduce has_symlink_or_noent_leading_path() function lstat_cache(): more cache effective symlink/directory detection --- 0990e7aaaa63ca908dbdfc379af132068e4b066f diff --combined cache.h index c96854a0d6,468daf6a43..c17fbf58a7 --- a/cache.h +++ b/cache.h @@@ -18,10 -18,6 +18,10 @@@ #define deflateBound(c,s) ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11) #endif +void git_inflate_init(z_streamp strm); +void git_inflate_end(z_streamp strm); +int git_inflate(z_streamp strm, int flush); + #if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT) #define DTYPE(de) ((de)->d_type) #else @@@ -635,6 -631,9 +635,6 @@@ extern int write_sha1_file(void *buf, u extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *); extern int force_object_loose(const unsigned char *sha1, time_t mtime); -/* just like read_sha1_file(), but non fatal in presence of bad objects */ -extern void *read_object(const unsigned char *sha1, enum object_type *type, unsigned long *size); - /* global flag to enable extra checks when accessing packed objects */ extern int do_check_packed_object_crc; @@@ -721,6 -720,10 +721,10 @@@ struct checkout extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath); extern int has_symlink_leading_path(int len, const char *name); + extern int has_symlink_or_noent_leading_path(int len, const char *name); + extern int has_dirs_only_path(int len, const char *name, int prefix_len); + extern void invalidate_lstat_cache(int len, const char *name); + extern void clear_lstat_cache(void); extern struct alternate_object_database { struct alternate_object_database *next; @@@ -937,6 -940,7 +941,6 @@@ extern int ws_fix_copy(char *, const ch extern int ws_blank_line(const char *line, int len, unsigned ws_rule); /* ls-files */ -int pathspec_match(const char **spec, char *matched, const char *filename, int skiplen); int report_path_error(const char *ps_matched, const char **pathspec, int prefix_offset); void overlay_tree_on_cache(const char *tree_name, const char *prefix); diff --combined entry.c index 5f24816eb9,01a683ee5d..05aa58d348 --- a/entry.c +++ b/entry.c @@@ -1,6 -1,5 +1,6 @@@ #include "cache.h" #include "blob.h" +#include "dir.h" static void create_directories(const char *path, const struct checkout *state) { @@@ -9,35 -8,25 +9,25 @@@ const char *slash = path; while ((slash = strchr(slash+1, '/')) != NULL) { - struct stat st; - int stat_status; - len = slash - path; memcpy(buf, path, len); buf[len] = 0; - if (len <= state->base_dir_len) - /* - * checkout-index --prefix=; is - * allowed to be a symlink to an existing - * directory. - */ - stat_status = stat(buf, &st); - else - /* - * if there currently is a symlink, we would - * want to replace it with a real directory. - */ - stat_status = lstat(buf, &st); - - if (!stat_status && S_ISDIR(st.st_mode)) + /* + * For 'checkout-index --prefix=', is + * allowed to be a symlink to an existing directory, + * and we set 'state->base_dir_len' below, such that + * we test the path components of the prefix with the + * stat() function instead of the lstat() function. + */ + if (has_dirs_only_path(len, buf, state->base_dir_len)) continue; /* ok, it is already a directory. */ /* - * We know stat_status == 0 means something exists - * there and this mkdir would fail, but that is an - * error codepath; we do not care, as we unlink and - * mkdir again in such a case. + * If this mkdir() would fail, it could be that there + * is already a symlink or something else exists + * there, therefore we then try to unlink it and try + * one more time to create the directory. */ if (mkdir(buf, 0777)) { if (errno == EEXIST && state->force && @@@ -63,7 -52,9 +53,7 @@@ static void remove_subtree(const char * *name++ = '/'; while ((de = readdir(dir)) != NULL) { struct stat st; - if ((de->d_name[0] == '.') && - ((de->d_name[1] == 0) || - ((de->d_name[1] == '.') && de->d_name[2] == 0))) + if (is_dot_or_dotdot(de->d_name)) continue; strcpy(name, de->d_name); if (lstat(pathbuf, &st)) diff --combined unpack-trees.c index 15c9ef592b,a3fd383afb..16bc2ca9eb --- a/unpack-trees.c +++ b/unpack-trees.c @@@ -61,7 -61,7 +61,7 @@@ static void unlink_entry(struct cache_e char *cp, *prev; char *name = ce->name; - if (has_symlink_leading_path(ce_namelen(ce), ce->name)) + if (has_symlink_or_noent_leading_path(ce_namelen(ce), ce->name)) return; if (unlink(name)) return; @@@ -494,7 -494,7 +494,7 @@@ static int verify_clean_subdirectory(st * anything in the existing directory there. */ int namelen; - int pos, i; + int i; struct dir_struct d; char *pathbuf; int cnt = 0; @@@ -515,20 -515,24 +515,20 @@@ * in that directory. */ namelen = strlen(ce->name); - pos = index_name_pos(o->src_index, ce->name, namelen); - if (0 <= pos) - return cnt; /* we have it as nondirectory */ - pos = -pos - 1; - for (i = pos; i < o->src_index->cache_nr; i++) { - struct cache_entry *ce = o->src_index->cache[i]; - int len = ce_namelen(ce); + for (i = o->pos; i < o->src_index->cache_nr; i++) { + struct cache_entry *ce2 = o->src_index->cache[i]; + int len = ce_namelen(ce2); if (len < namelen || - strncmp(ce->name, ce->name, namelen) || - ce->name[namelen] != '/') + strncmp(ce->name, ce2->name, namelen) || + ce2->name[namelen] != '/') break; /* - * ce->name is an entry in the subdirectory. + * ce2->name is an entry in the subdirectory. */ - if (!ce_stage(ce)) { - if (verify_uptodate(ce, o)) + if (!ce_stage(ce2)) { + if (verify_uptodate(ce2, o)) return -1; - add_entry(o, ce, CE_REMOVE, 0); + add_entry(o, ce2, CE_REMOVE, 0); } cnt++; } @@@ -580,11 -584,11 +580,11 @@@ static int verify_absent(struct cache_e if (o->index_only || o->reset || !o->update) return 0; - if (has_symlink_leading_path(ce_namelen(ce), ce->name)) + if (has_symlink_or_noent_leading_path(ce_namelen(ce), ce->name)) return 0; if (!lstat(ce->name, &st)) { - int cnt; + int ret; int dtype = ce_to_dtype(ce); struct cache_entry *result; @@@ -612,15 -616,13 +612,15 @@@ * files that are in "foo/" we would lose * it. */ - cnt = verify_clean_subdirectory(ce, action, o); + ret = verify_clean_subdirectory(ce, action, o); + if (ret < 0) + return ret; /* * If this removed entries from the index, * what that means is: * - * (1) the caller unpack_trees_rec() saw path/foo + * (1) the caller unpack_callback() saw path/foo * in the index, and it has not removed it because * it thinks it is handling 'path' as blob with * D/F conflict; @@@ -633,7 -635,7 +633,7 @@@ * We need to increment it by the number of * deleted entries here. */ - o->pos += cnt; + o->pos += ret; return 0; }