Skip to content

Commit

Permalink
Allow cloning to an existing empty directory
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
  • Loading branch information
aspotashev authored and gitster committed Jan 11, 2009
1 parent 8ca12c0 commit 55892d2
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 3 deletions.
9 changes: 6 additions & 3 deletions builtin-clone.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand All @@ -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);
Expand Down
19 changes: 19 additions & 0 deletions dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions dir.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
19 changes: 19 additions & 0 deletions t/t5601-clone.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 55892d2

Please sign in to comment.