Extract helper bits from c-merge-recursive work
This backports the pieces that are not uncooked from the merge-recursive WIP we have seen earlier, to be used in git-mv rewritten in C. Signed-off-by: Junio C Hamano <junkio@cox.net>maint
							parent
							
								
									24cf6e5847
								
							
						
					
					
						commit
						8fd2cb4069
					
				
							
								
								
									
										3
									
								
								cache.h
								
								
								
								
							
							
						
						
									
										3
									
								
								cache.h
								
								
								
								
							|  | @ -115,6 +115,7 @@ static inline unsigned int create_ce_mode(unsigned int mode) | |||
| extern struct cache_entry **active_cache; | ||||
| extern unsigned int active_nr, active_alloc, active_cache_changed; | ||||
| extern struct cache_tree *active_cache_tree; | ||||
| extern int cache_errno; | ||||
|  | ||||
| #define GIT_DIR_ENVIRONMENT "GIT_DIR" | ||||
| #define DEFAULT_GIT_DIR_ENVIRONMENT ".git" | ||||
|  | @ -142,6 +143,7 @@ extern void verify_non_filename(const char *prefix, const char *name); | |||
|  | ||||
| /* Initialize and use the cache information */ | ||||
| extern int read_cache(void); | ||||
| extern int read_cache_from(const char *path); | ||||
| extern int write_cache(int newfd, struct cache_entry **cache, int entries); | ||||
| extern int verify_path(const char *path); | ||||
| extern int cache_name_pos(const char *name, int namelen); | ||||
|  | @ -149,6 +151,7 @@ extern int cache_name_pos(const char *name, int namelen); | |||
| #define ADD_CACHE_OK_TO_REPLACE 2	/* Ok to replace file/directory */ | ||||
| #define ADD_CACHE_SKIP_DFCHECK 4	/* Ok to skip DF conflict checks */ | ||||
| extern int add_cache_entry(struct cache_entry *ce, int option); | ||||
| extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really); | ||||
| extern int remove_cache_entry_at(int pos); | ||||
| extern int remove_file_from_cache(const char *path); | ||||
| extern int ce_same_name(struct cache_entry *a, struct cache_entry *b); | ||||
|  |  | |||
|  | @ -0,0 +1,105 @@ | |||
| #include <stdio.h> | ||||
| #include "cache.h" | ||||
| #include "path-list.h" | ||||
|  | ||||
| /* if there is no exact match, point to the index where the entry could be | ||||
|  * inserted */ | ||||
| static int get_entry_index(const struct path_list *list, const char *path, | ||||
| 		int *exact_match) | ||||
| { | ||||
| 	int left = -1, right = list->nr; | ||||
|  | ||||
| 	while (left + 1 < right) { | ||||
| 		int middle = (left + right) / 2; | ||||
| 		int compare = strcmp(path, list->items[middle].path); | ||||
| 		if (compare < 0) | ||||
| 			right = middle; | ||||
| 		else if (compare > 0) | ||||
| 			left = middle; | ||||
| 		else { | ||||
| 			*exact_match = 1; | ||||
| 			return middle; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	*exact_match = 0; | ||||
| 	return right; | ||||
| } | ||||
|  | ||||
| /* returns -1-index if already exists */ | ||||
| static int add_entry(struct path_list *list, const char *path) | ||||
| { | ||||
| 	int exact_match; | ||||
| 	int index = get_entry_index(list, path, &exact_match); | ||||
|  | ||||
| 	if (exact_match) | ||||
| 		return -1 - index; | ||||
|  | ||||
| 	if (list->nr + 1 >= list->alloc) { | ||||
| 		list->alloc += 32; | ||||
| 		list->items = xrealloc(list->items, list->alloc | ||||
| 				* sizeof(struct path_list_item)); | ||||
| 	} | ||||
| 	if (index < list->nr) | ||||
| 		memmove(list->items + index + 1, list->items + index, | ||||
| 				(list->nr - index) | ||||
| 				* sizeof(struct path_list_item)); | ||||
| 	list->items[index].path = list->strdup_paths ? | ||||
| 		strdup(path) : (char *)path; | ||||
| 	list->items[index].util = NULL; | ||||
| 	list->nr++; | ||||
|  | ||||
| 	return index; | ||||
| } | ||||
|  | ||||
| struct path_list_item *path_list_insert(const char *path, struct path_list *list) | ||||
| { | ||||
| 	int index = add_entry(list, path); | ||||
|  | ||||
| 	if (index < 0) | ||||
| 		index = 1 - index; | ||||
|  | ||||
| 	return list->items + index; | ||||
| } | ||||
|  | ||||
| int path_list_has_path(const struct path_list *list, const char *path) | ||||
| { | ||||
| 	int exact_match; | ||||
| 	get_entry_index(list, path, &exact_match); | ||||
| 	return exact_match; | ||||
| } | ||||
|  | ||||
| struct path_list_item *path_list_lookup(const char *path, struct path_list *list) | ||||
| { | ||||
| 	int exact_match, i = get_entry_index(list, path, &exact_match); | ||||
| 	if (!exact_match) | ||||
| 		return NULL; | ||||
| 	return list->items + i; | ||||
| } | ||||
|  | ||||
| void path_list_clear(struct path_list *list, int free_items) | ||||
| { | ||||
| 	if (list->items) { | ||||
| 		int i; | ||||
| 		if (free_items) | ||||
| 			for (i = 0; i < list->nr; i++) { | ||||
| 				if (list->strdup_paths) | ||||
| 					free(list->items[i].path); | ||||
| 				if (list->items[i].util) | ||||
| 					free(list->items[i].util); | ||||
| 			} | ||||
| 		free(list->items); | ||||
| 	} | ||||
| 	list->items = NULL; | ||||
| 	list->nr = list->alloc = 0; | ||||
| } | ||||
|  | ||||
| void print_path_list(const char *text, const struct path_list *p) | ||||
| { | ||||
| 	int i; | ||||
| 	if ( text ) | ||||
| 		printf("%s\n", text); | ||||
| 	for (i = 0; i < p->nr; i++) | ||||
| 		printf("%s:%p\n", p->items[i].path, p->items[i].util); | ||||
| } | ||||
|  | ||||
|  | @ -0,0 +1,22 @@ | |||
| #ifndef _PATH_LIST_H_ | ||||
| #define _PATH_LIST_H_ | ||||
|  | ||||
| struct path_list_item { | ||||
| 	char *path; | ||||
| 	void *util; | ||||
| }; | ||||
| struct path_list | ||||
| { | ||||
| 	struct path_list_item *items; | ||||
| 	unsigned int nr, alloc; | ||||
| 	unsigned int strdup_paths:1; | ||||
| }; | ||||
|  | ||||
| void print_path_list(const char *text, const struct path_list *p); | ||||
|  | ||||
| int path_list_has_path(const struct path_list *list, const char *path); | ||||
| void path_list_clear(struct path_list *list, int free_items); | ||||
| struct path_list_item *path_list_insert(const char *path, struct path_list *list); | ||||
| struct path_list_item *path_list_lookup(const char *path, struct path_list *list); | ||||
|  | ||||
| #endif /* _PATH_LIST_H_ */ | ||||
							
								
								
									
										87
									
								
								read-cache.c
								
								
								
								
							
							
						
						
									
										87
									
								
								read-cache.c
								
								
								
								
							|  | @ -24,6 +24,11 @@ unsigned int active_nr = 0, active_alloc = 0, active_cache_changed = 0; | |||
|  | ||||
| struct cache_tree *active_cache_tree = NULL; | ||||
|  | ||||
| int cache_errno = 0; | ||||
|  | ||||
| static void *cache_mmap = NULL; | ||||
| static size_t cache_mmap_size = 0; | ||||
|  | ||||
| /* | ||||
|  * This only updates the "non-critical" parts of the directory | ||||
|  * cache, ie the parts that aren't tracked by GIT, and only used | ||||
|  | @ -577,22 +582,6 @@ int add_cache_entry(struct cache_entry *ce, int option) | |||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* Three functions to allow overloaded pointer return; see linux/err.h */ | ||||
| static inline void *ERR_PTR(long error) | ||||
| { | ||||
| 	return (void *) error; | ||||
| } | ||||
|  | ||||
| static inline long PTR_ERR(const void *ptr) | ||||
| { | ||||
| 	return (long) ptr; | ||||
| } | ||||
|  | ||||
| static inline long IS_ERR(const void *ptr) | ||||
| { | ||||
| 	return (unsigned long)ptr > (unsigned long)-1000L; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * "refresh" does not calculate a new sha1 file or bring the | ||||
|  * cache up-to-date for mode/content changes. But what it | ||||
|  | @ -604,14 +593,16 @@ static inline long IS_ERR(const void *ptr) | |||
|  * For example, you'd want to do this after doing a "git-read-tree", | ||||
|  * to link up the stat cache details with the proper files. | ||||
|  */ | ||||
| static struct cache_entry *refresh_entry(struct cache_entry *ce, int really) | ||||
| struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really) | ||||
| { | ||||
| 	struct stat st; | ||||
| 	struct cache_entry *updated; | ||||
| 	int changed, size; | ||||
|  | ||||
| 	if (lstat(ce->name, &st) < 0) | ||||
| 		return ERR_PTR(-errno); | ||||
| 	if (lstat(ce->name, &st) < 0) { | ||||
| 		cache_errno = errno; | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	changed = ce_match_stat(ce, &st, really); | ||||
| 	if (!changed) { | ||||
|  | @ -619,11 +610,13 @@ static struct cache_entry *refresh_entry(struct cache_entry *ce, int really) | |||
| 		    !(ce->ce_flags & htons(CE_VALID))) | ||||
| 			; /* mark this one VALID again */ | ||||
| 		else | ||||
| 			return NULL; | ||||
| 			return ce; | ||||
| 	} | ||||
|  | ||||
| 	if (ce_modified(ce, &st, really)) | ||||
| 		return ERR_PTR(-EINVAL); | ||||
| 	if (ce_modified(ce, &st, really)) { | ||||
| 		cache_errno = EINVAL; | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	size = ce_size(ce); | ||||
| 	updated = xmalloc(size); | ||||
|  | @ -666,13 +659,13 @@ int refresh_cache(unsigned int flags) | |||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		new = refresh_entry(ce, really); | ||||
| 		if (!new) | ||||
| 		new = refresh_cache_entry(ce, really); | ||||
| 		if (new == ce) | ||||
| 			continue; | ||||
| 		if (IS_ERR(new)) { | ||||
| 			if (not_new && PTR_ERR(new) == -ENOENT) | ||||
| 		if (!new) { | ||||
| 			if (not_new && cache_errno == ENOENT) | ||||
| 				continue; | ||||
| 			if (really && PTR_ERR(new) == -EINVAL) { | ||||
| 			if (really && cache_errno == EINVAL) { | ||||
| 				/* If we are doing --really-refresh that | ||||
| 				 * means the index is not valid anymore. | ||||
| 				 */ | ||||
|  | @ -728,40 +721,44 @@ static int read_index_extension(const char *ext, void *data, unsigned long sz) | |||
| } | ||||
|  | ||||
| int read_cache(void) | ||||
| { | ||||
| 	return read_cache_from(get_index_file()); | ||||
| } | ||||
|  | ||||
| /* remember to discard_cache() before reading a different cache! */ | ||||
| int read_cache_from(const char *path) | ||||
| { | ||||
| 	int fd, i; | ||||
| 	struct stat st; | ||||
| 	unsigned long size, offset; | ||||
| 	void *map; | ||||
| 	unsigned long offset; | ||||
| 	struct cache_header *hdr; | ||||
|  | ||||
| 	errno = EBUSY; | ||||
| 	if (active_cache) | ||||
| 	if (cache_mmap) | ||||
| 		return active_nr; | ||||
|  | ||||
| 	errno = ENOENT; | ||||
| 	index_file_timestamp = 0; | ||||
| 	fd = open(get_index_file(), O_RDONLY); | ||||
| 	fd = open(path, O_RDONLY); | ||||
| 	if (fd < 0) { | ||||
| 		if (errno == ENOENT) | ||||
| 			return 0; | ||||
| 		die("index file open failed (%s)", strerror(errno)); | ||||
| 	} | ||||
|  | ||||
| 	size = 0; /* avoid gcc warning */ | ||||
| 	map = MAP_FAILED; | ||||
| 	cache_mmap = MAP_FAILED; | ||||
| 	if (!fstat(fd, &st)) { | ||||
| 		size = st.st_size; | ||||
| 		cache_mmap_size = st.st_size; | ||||
| 		errno = EINVAL; | ||||
| 		if (size >= sizeof(struct cache_header) + 20) | ||||
| 			map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); | ||||
| 		if (cache_mmap_size >= sizeof(struct cache_header) + 20) | ||||
| 			cache_mmap = mmap(NULL, cache_mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); | ||||
| 	} | ||||
| 	close(fd); | ||||
| 	if (map == MAP_FAILED) | ||||
| 	if (cache_mmap == MAP_FAILED) | ||||
| 		die("index file mmap failed (%s)", strerror(errno)); | ||||
|  | ||||
| 	hdr = map; | ||||
| 	if (verify_hdr(hdr, size) < 0) | ||||
| 	hdr = cache_mmap; | ||||
| 	if (verify_hdr(hdr, cache_mmap_size) < 0) | ||||
| 		goto unmap; | ||||
|  | ||||
| 	active_nr = ntohl(hdr->hdr_entries); | ||||
|  | @ -770,12 +767,12 @@ int read_cache(void) | |||
|  | ||||
| 	offset = sizeof(*hdr); | ||||
| 	for (i = 0; i < active_nr; i++) { | ||||
| 		struct cache_entry *ce = (struct cache_entry *) ((char *) map + offset); | ||||
| 		struct cache_entry *ce = (struct cache_entry *) ((char *) cache_mmap + offset); | ||||
| 		offset = offset + ce_size(ce); | ||||
| 		active_cache[i] = ce; | ||||
| 	} | ||||
| 	index_file_timestamp = st.st_mtime; | ||||
| 	while (offset <= size - 20 - 8) { | ||||
| 	while (offset <= cache_mmap_size - 20 - 8) { | ||||
| 		/* After an array of active_nr index entries, | ||||
| 		 * there can be arbitrary number of extended | ||||
| 		 * sections, each of which is prefixed with | ||||
|  | @ -783,10 +780,10 @@ int read_cache(void) | |||
| 		 * in 4-byte network byte order. | ||||
| 		 */ | ||||
| 		unsigned long extsize; | ||||
| 		memcpy(&extsize, (char *) map + offset + 4, 4); | ||||
| 		memcpy(&extsize, (char *) cache_mmap + offset + 4, 4); | ||||
| 		extsize = ntohl(extsize); | ||||
| 		if (read_index_extension(((const char *) map) + offset, | ||||
| 					 (char *) map + offset + 8, | ||||
| 		if (read_index_extension(((const char *) cache_mmap) + offset, | ||||
| 					 (char *) cache_mmap + offset + 8, | ||||
| 					 extsize) < 0) | ||||
| 			goto unmap; | ||||
| 		offset += 8; | ||||
|  | @ -795,7 +792,7 @@ int read_cache(void) | |||
| 	return active_nr; | ||||
|  | ||||
| unmap: | ||||
| 	munmap(map, size); | ||||
| 	munmap(cache_mmap, cache_mmap_size); | ||||
| 	errno = EINVAL; | ||||
| 	die("index file corrupt"); | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Johannes Schindelin
						Johannes Schindelin