do not overwrite files in leading path
If the work tree contains an untracked file x, and unpack-trees wants to checkout a path x/*, the file x is removed unconditionally. Instead, apply the same checks that are normally used for untracked files, and abort if the file cannot be removed. Signed-off-by: Clemens Buchacher <drizzd@aon.at>maint
							parent
							
								
									4856ff2a19
								
							
						
					
					
						commit
						f66caaf9c8
					
				
							
								
								
									
										2
									
								
								cache.h
								
								
								
								
							
							
						
						
									
										2
									
								
								cache.h
								
								
								
								
							|  | @ -859,7 +859,7 @@ struct cache_def { | |||
|  | ||||
| extern int has_symlink_leading_path(const char *name, int len); | ||||
| extern int threaded_has_symlink_leading_path(struct cache_def *, const char *, int); | ||||
| extern int has_symlink_or_noent_leading_path(const char *name, int len); | ||||
| extern int check_leading_path(const char *name, int len); | ||||
| extern int has_dirs_only_path(const char *name, int len, int prefix_len); | ||||
| extern void schedule_dir_for_removal(const char *name, int len); | ||||
| extern void remove_scheduled_dirs(void); | ||||
|  |  | |||
							
								
								
									
										21
									
								
								symlinks.c
								
								
								
								
							
							
						
						
									
										21
									
								
								symlinks.c
								
								
								
								
							|  | @ -209,15 +209,26 @@ int has_symlink_leading_path(const char *name, int len) | |||
| } | ||||
|  | ||||
| /* | ||||
|  * Return non-zero if path 'name' has a leading symlink component or | ||||
|  * Return zero if path 'name' has a leading symlink component or | ||||
|  * if some leading path component does not exists. | ||||
|  * | ||||
|  * Return -1 if leading path exists and is a directory. | ||||
|  * | ||||
|  * Return path length if leading path exists and is neither a | ||||
|  * directory nor a symlink. | ||||
|  */ | ||||
| int has_symlink_or_noent_leading_path(const char *name, int len) | ||||
| int check_leading_path(const char *name, int len) | ||||
| { | ||||
| 	struct cache_def *cache = &default_cache;	/* FIXME */ | ||||
| 	return lstat_cache(cache, name, len, | ||||
| 			   FL_SYMLINK|FL_NOENT|FL_DIR, USE_ONLY_LSTAT) & | ||||
| 		(FL_SYMLINK|FL_NOENT); | ||||
| 	int flags; | ||||
| 	int match_len = lstat_cache_matchlen(cache, name, len, &flags, | ||||
| 			   FL_SYMLINK|FL_NOENT|FL_DIR, USE_ONLY_LSTAT); | ||||
| 	if (flags & (FL_SYMLINK|FL_NOENT)) | ||||
| 		return 0; | ||||
| 	else if (flags & FL_DIR) | ||||
| 		return -1; | ||||
| 	else | ||||
| 		return match_len; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  |  | |||
|  | @ -100,7 +100,7 @@ test_expect_success 'will not overwrite untracked subtree' ' | |||
| 	test_cmp important sub/f/important | ||||
| ' | ||||
|  | ||||
| test_expect_failure 'will not overwrite untracked file in leading path' ' | ||||
| test_expect_success 'will not overwrite untracked file in leading path' ' | ||||
| 	git reset --hard c0 && | ||||
| 	rm -rf sub && | ||||
| 	cp important sub && | ||||
|  |  | |||
|  | @ -182,7 +182,7 @@ static void display_error_msgs(struct unpack_trees_options *o) | |||
|  */ | ||||
| static void unlink_entry(struct cache_entry *ce) | ||||
| { | ||||
| 	if (has_symlink_or_noent_leading_path(ce->name, ce_namelen(ce))) | ||||
| 	if (!check_leading_path(ce->name, ce_namelen(ce))) | ||||
| 		return; | ||||
| 	if (remove_or_warn(ce->ce_mode, ce->name)) | ||||
| 		return; | ||||
|  | @ -1194,18 +1194,28 @@ static int verify_absent_1(struct cache_entry *ce, | |||
| 				 enum unpack_trees_error_types error_type, | ||||
| 				 struct unpack_trees_options *o) | ||||
| { | ||||
| 	int len; | ||||
| 	struct stat st; | ||||
|  | ||||
| 	if (o->index_only || o->reset || !o->update) | ||||
| 		return 0; | ||||
|  | ||||
| 	if (has_symlink_or_noent_leading_path(ce->name, ce_namelen(ce))) | ||||
| 	len = check_leading_path(ce->name, ce_namelen(ce)); | ||||
| 	if (!len) | ||||
| 		return 0; | ||||
| 	else if (len > 0) { | ||||
| 		char path[PATH_MAX + 1]; | ||||
| 		memcpy(path, ce->name, len); | ||||
| 		path[len] = 0; | ||||
| 		lstat(path, &st); | ||||
|  | ||||
| 	if (!lstat(ce->name, &st)) | ||||
| 		return check_ok_to_remove(path, len, DT_UNKNOWN, NULL, &st, | ||||
| 				error_type, o); | ||||
| 	} else if (!lstat(ce->name, &st)) | ||||
| 		return check_ok_to_remove(ce->name, ce_namelen(ce), | ||||
| 				ce_to_dtype(ce), ce, &st, | ||||
| 				error_type, o); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Clemens Buchacher
						Clemens Buchacher