Browse Source

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
Alexander Potashev 16 years ago committed by Junio C Hamano
parent
commit
55892d2398
  1. 9
      builtin-clone.c
  2. 19
      dir.c
  3. 2
      dir.h
  4. 19
      t/t5601-clone.sh

9
builtin-clone.c

@ -357,6 +357,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) @@ -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) @@ -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) @@ -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

@ -777,6 +777,25 @@ int is_inside_dir(const char *dir) @@ -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

@ -84,6 +84,8 @@ static inline int is_dot_or_dotdot(const char *name) @@ -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);


19
t/t5601-clone.sh

@ -125,4 +125,23 @@ test_expect_success 'clone to destination with extra trailing /' ' @@ -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…
Cancel
Save