name-hash: refactor polymorphic index_name_exists()
Depending upon the absence or presence of a trailing '/' on the incoming pathname, index_name_exists() checks either if a file is present in the index or if a directory is represented within the index. Each caller explicitly chooses the mode of operation by adding or removing a trailing '/' before invoking index_name_exists(). Since these two modes of operations are disjoint and have no code in common (one searches index_state.name_hash; the other dir_hash), they can be represented more naturally as distinct functions: one to search for a file, and one for a directory. Splitting index searching into two functions relieves callers of the artificial burden of having to add or remove a slash to select the mode of operation; instead they just call the desired function. A subsequent patch will take advantage of this benefit in order to eliminate the requirement that the incoming pathname for a directory search must have a trailing slash. (In order to avoid disturbing in-flight topics, index_name_exists() is retained as a thin wrapper dispatching either to index_dir_exists() or index_file_exists().) Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
b3e7d24ca1
commit
db5360f3f4
4
cache.h
4
cache.h
@ -314,6 +314,8 @@ extern void free_name_hash(struct index_state *istate);
|
|||||||
#define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL, NULL)
|
#define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL, NULL)
|
||||||
#define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))
|
#define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))
|
||||||
#define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))
|
#define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))
|
||||||
|
#define cache_dir_exists(name, namelen) index_dir_exists(&the_index, (name), (namelen))
|
||||||
|
#define cache_file_exists(name, namelen, igncase) index_file_exists(&the_index, (name), (namelen), (igncase))
|
||||||
#define cache_name_exists(name, namelen, igncase) index_name_exists(&the_index, (name), (namelen), (igncase))
|
#define cache_name_exists(name, namelen, igncase) index_name_exists(&the_index, (name), (namelen), (igncase))
|
||||||
#define cache_name_is_other(name, namelen) index_name_is_other(&the_index, (name), (namelen))
|
#define cache_name_is_other(name, namelen) index_name_is_other(&the_index, (name), (namelen))
|
||||||
#define resolve_undo_clear() resolve_undo_clear_index(&the_index)
|
#define resolve_undo_clear() resolve_undo_clear_index(&the_index)
|
||||||
@ -463,6 +465,8 @@ extern int write_index(struct index_state *, int newfd);
|
|||||||
extern int discard_index(struct index_state *);
|
extern int discard_index(struct index_state *);
|
||||||
extern int unmerged_index(const struct index_state *);
|
extern int unmerged_index(const struct index_state *);
|
||||||
extern int verify_path(const char *path);
|
extern int verify_path(const char *path);
|
||||||
|
extern struct cache_entry *index_dir_exists(struct index_state *istate, const char *name, int namelen);
|
||||||
|
extern struct cache_entry *index_file_exists(struct index_state *istate, const char *name, int namelen, int igncase);
|
||||||
extern struct cache_entry *index_name_exists(struct index_state *istate, const char *name, int namelen, int igncase);
|
extern struct cache_entry *index_name_exists(struct index_state *istate, const char *name, int namelen, int igncase);
|
||||||
extern int index_name_pos(const struct index_state *, const char *name, int namelen);
|
extern int index_name_pos(const struct index_state *, const char *name, int namelen);
|
||||||
#define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */
|
#define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */
|
||||||
|
54
name-hash.c
54
name-hash.c
@ -222,7 +222,29 @@ static int same_name(const struct cache_entry *ce, const char *name, int namelen
|
|||||||
return slow_same_name(name, namelen, ce->name, len);
|
return slow_same_name(name, namelen, ce->name, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cache_entry *index_name_exists(struct index_state *istate, const char *name, int namelen, int icase)
|
struct cache_entry *index_dir_exists(struct index_state *istate, const char *name, int namelen)
|
||||||
|
{
|
||||||
|
struct cache_entry *ce;
|
||||||
|
struct dir_entry *dir;
|
||||||
|
|
||||||
|
lazy_init_name_hash(istate);
|
||||||
|
dir = find_dir_entry(istate, name, namelen);
|
||||||
|
if (dir && dir->nr)
|
||||||
|
return dir->ce;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It might be a submodule. Unlike plain directories, which are stored
|
||||||
|
* in the dir-hash, submodules are stored in the name-hash, so check
|
||||||
|
* there, as well.
|
||||||
|
*/
|
||||||
|
ce = index_file_exists(istate, name, namelen - 1, 1);
|
||||||
|
if (ce && S_ISGITLINK(ce->ce_mode))
|
||||||
|
return ce;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cache_entry *index_file_exists(struct index_state *istate, const char *name, int namelen, int icase)
|
||||||
{
|
{
|
||||||
unsigned int hash = hash_name(name, namelen);
|
unsigned int hash = hash_name(name, namelen);
|
||||||
struct cache_entry *ce;
|
struct cache_entry *ce;
|
||||||
@ -237,32 +259,16 @@ struct cache_entry *index_name_exists(struct index_state *istate, const char *na
|
|||||||
}
|
}
|
||||||
ce = ce->next;
|
ce = ce->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* When looking for a directory (trailing '/'), it might be a
|
|
||||||
* submodule or a directory. Despite submodules being directories,
|
|
||||||
* they are stored in the name hash without a closing slash.
|
|
||||||
* When ignore_case is 1, directories are stored in a separate hash
|
|
||||||
* table *with* their closing slash.
|
|
||||||
*
|
|
||||||
* The side effect of this storage technique is we have need to
|
|
||||||
* lookup the directory in a separate hash table, and if not found
|
|
||||||
* remove the slash from name and perform the lookup again without
|
|
||||||
* the slash. If a match is made, S_ISGITLINK(ce->mode) will be
|
|
||||||
* true.
|
|
||||||
*/
|
|
||||||
if (icase && name[namelen - 1] == '/') {
|
|
||||||
struct dir_entry *dir = find_dir_entry(istate, name, namelen);
|
|
||||||
if (dir && dir->nr)
|
|
||||||
return dir->ce;
|
|
||||||
|
|
||||||
ce = index_name_exists(istate, name, namelen - 1, icase);
|
|
||||||
if (ce && S_ISGITLINK(ce->ce_mode))
|
|
||||||
return ce;
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct cache_entry *index_name_exists(struct index_state *istate, const char *name, int namelen, int icase)
|
||||||
|
{
|
||||||
|
if (namelen > 0 && name[namelen - 1] == '/')
|
||||||
|
return index_dir_exists(istate, name, namelen);
|
||||||
|
return index_file_exists(istate, name, namelen, icase);
|
||||||
|
}
|
||||||
|
|
||||||
static int free_dir_entry(void *entry, void *unused)
|
static int free_dir_entry(void *entry, void *unused)
|
||||||
{
|
{
|
||||||
struct dir_entry *dir = entry;
|
struct dir_entry *dir = entry;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user