Allow cloning to an existing empty directory
The die() message updated accordingly. The previous behaviour was to only allow cloning when the destination directory doesn't exist. [jc: added trivial tests] Signed-off-by: Alexander Potashev <aspotashev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									8ca12c0d62
								
							
						
					
					
						commit
						55892d2398
					
				|  | @ -357,6 +357,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) | |||
| 	struct stat buf; | ||||
| 	const char *repo_name, *repo, *work_tree, *git_dir; | ||||
| 	char *path, *dir; | ||||
| 	int dest_exists; | ||||
| 	const struct ref *refs, *head_points_at, *remote_head, *mapped_refs; | ||||
| 	struct strbuf key = STRBUF_INIT, value = STRBUF_INIT; | ||||
| 	struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT; | ||||
|  | @ -406,8 +407,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix) | |||
| 		dir = guess_dir_name(repo_name, is_bundle, option_bare); | ||||
| 	strip_trailing_slashes(dir); | ||||
|  | ||||
| 	if (!stat(dir, &buf)) | ||||
| 		die("destination directory '%s' already exists.", dir); | ||||
| 	dest_exists = !stat(dir, &buf); | ||||
| 	if (dest_exists && !is_empty_dir(dir)) | ||||
| 		die("destination path '%s' already exists and is not " | ||||
| 			"an empty directory.", dir); | ||||
|  | ||||
| 	strbuf_addf(&reflog_msg, "clone: from %s", repo); | ||||
|  | ||||
|  | @ -431,7 +434,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) | |||
| 		if (safe_create_leading_directories_const(work_tree) < 0) | ||||
| 			die("could not create leading directories of '%s': %s", | ||||
| 					work_tree, strerror(errno)); | ||||
| 		if (mkdir(work_tree, 0755)) | ||||
| 		if (!dest_exists && mkdir(work_tree, 0755)) | ||||
| 			die("could not create work tree dir '%s': %s.", | ||||
| 					work_tree, strerror(errno)); | ||||
| 		set_git_work_tree(work_tree); | ||||
|  |  | |||
							
								
								
									
										19
									
								
								dir.c
								
								
								
								
							
							
						
						
									
										19
									
								
								dir.c
								
								
								
								
							|  | @ -777,6 +777,25 @@ int is_inside_dir(const char *dir) | |||
| 	return get_relative_cwd(buffer, sizeof(buffer), dir) != NULL; | ||||
| } | ||||
|  | ||||
| int is_empty_dir(const char *path) | ||||
| { | ||||
| 	DIR *dir = opendir(path); | ||||
| 	struct dirent *e; | ||||
| 	int ret = 1; | ||||
|  | ||||
| 	if (!dir) | ||||
| 		return 0; | ||||
|  | ||||
| 	while ((e = readdir(dir)) != NULL) | ||||
| 		if (!is_dot_or_dotdot(e->d_name)) { | ||||
| 			ret = 0; | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 	closedir(dir); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| int remove_dir_recursively(struct strbuf *path, int only_empty) | ||||
| { | ||||
| 	DIR *dir = opendir(path->buf); | ||||
|  |  | |||
							
								
								
									
										2
									
								
								dir.h
								
								
								
								
							
							
						
						
									
										2
									
								
								dir.h
								
								
								
								
							|  | @ -84,6 +84,8 @@ static inline int is_dot_or_dotdot(const char *name) | |||
| 		 (name[1] == '.' && name[2] == '\0'))); | ||||
| } | ||||
|  | ||||
| extern int is_empty_dir(const char *dir); | ||||
|  | ||||
| extern void setup_standard_excludes(struct dir_struct *dir); | ||||
| extern int remove_dir_recursively(struct strbuf *path, int only_empty); | ||||
|  | ||||
|  |  | |||
|  | @ -125,4 +125,23 @@ test_expect_success 'clone to destination with extra trailing /' ' | |||
|  | ||||
| ' | ||||
|  | ||||
| test_expect_success 'clone to an existing empty directory' ' | ||||
| 	mkdir target-3 && | ||||
| 	git clone src target-3 && | ||||
| 	T=$( cd target-3 && git rev-parse HEAD ) && | ||||
| 	S=$( cd src && git rev-parse HEAD ) && | ||||
| 	test "$T" = "$S" | ||||
| ' | ||||
|  | ||||
| test_expect_success 'clone to an existing non-empty directory' ' | ||||
| 	mkdir target-4 && | ||||
| 	>target-4/Fakefile && | ||||
| 	test_must_fail git clone src target-4 | ||||
| ' | ||||
|  | ||||
| test_expect_success 'clone to an existing path' ' | ||||
| 	>target-5 && | ||||
| 	test_must_fail git clone src target-5 | ||||
| ' | ||||
|  | ||||
| test_done | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Alexander Potashev
						Alexander Potashev