--- OLD/builtin-clone.c Thu Jan 1 00:00:00 1970 +++ NEW/builtin-clone.c Thu Jan 1 00:00:00 1970 @@ -33,12 +33,12 @@ * */ static const char * const builtin_clone_usage[] = { - "git clone [options] [--] []", + "git clone [options] [--] ", NULL }; static int option_quiet, option_no_checkout, option_bare, option_mirror; -static int option_local, option_no_hardlinks, option_shared; +static int option_local, option_no_hardlinks, option_shared, option_force; static char *option_template, *option_reference, *option_depth; static char *option_origin = NULL; static char *option_upload_pack = "git-upload-pack"; @@ -49,6 +49,8 @@ OPT__VERBOSE(&option_verbose), OPT_BOOLEAN('n', "no-checkout", &option_no_checkout, "don't create a checkout"), + OPT_BOOLEAN('f', "force", &option_force, + "force cloning into nonempty directory"), OPT_BOOLEAN(0, "bare", &option_bare, "create a bare repository"), OPT_BOOLEAN(0, "naked", &option_bare, "create a bare repository"), OPT_BOOLEAN(0, "mirror", &option_mirror, @@ -101,75 +103,6 @@ return NULL; } -static char *guess_dir_name(const char *repo, int is_bundle, int is_bare) -{ - const char *end = repo + strlen(repo), *start; - char *dir; - - /* - * Strip trailing spaces, slashes and /.git - */ - while (repo < end && (is_dir_sep(end[-1]) || isspace(end[-1]))) - end--; - if (end - repo > 5 && is_dir_sep(end[-5]) && - !strncmp(end - 4, ".git", 4)) { - end -= 5; - while (repo < end && is_dir_sep(end[-1])) - end--; - } - - /* - * Find last component, but be prepared that repo could have - * the form "remote.example.com:foo.git", i.e. no slash - * in the directory part. - */ - start = end; - while (repo < start && !is_dir_sep(start[-1]) && start[-1] != ':') - start--; - - /* - * Strip .{bundle,git}. - */ - if (is_bundle) { - if (end - start > 7 && !strncmp(end - 7, ".bundle", 7)) - end -= 7; - } else { - if (end - start > 4 && !strncmp(end - 4, ".git", 4)) - end -= 4; - } - - if (is_bare) { - struct strbuf result = STRBUF_INIT; - strbuf_addf(&result, "%.*s.git", (int)(end - start), start); - dir = strbuf_detach(&result, NULL); - } else - dir = xstrndup(start, end - start); - /* - * Replace sequences of 'control' characters and whitespace - * with one ascii space, remove leading and trailing spaces. - */ - if (*dir) { - char *out = dir; - int prev_space = 1 /* strip leading whitespace */; - for (end = dir; *end; ++end) { - char ch = *end; - if ((unsigned char)ch < '\x20') - ch = '\x20'; - if (isspace(ch)) { - if (prev_space) - continue; - prev_space = 1; - } else - prev_space = 0; - *out++ = ch; - } - *out = '\0'; - if (out > dir && prev_space) - out[-1] = '\0'; - } - return dir; -} - static void strip_trailing_slashes(char *dir) { char *end = dir + strlen(dir); @@ -306,7 +239,7 @@ remove_dir_recursively(&sb, 0); strbuf_reset(&sb); } - if (junk_work_tree) { + if (junk_work_tree && !option_force) { strbuf_addstr(&sb, junk_work_tree); remove_dir_recursively(&sb, 0); strbuf_reset(&sb); @@ -362,8 +295,8 @@ argc = parse_options(argc, argv, prefix, builtin_clone_options, builtin_clone_usage, 0); - if (argc == 0) - die("You must specify a repository to clone."); + if (argc != 2) + die("You must specify a repository and directory."); if (option_mirror) option_bare = 1; @@ -388,16 +321,21 @@ else repo = repo_name; - if (argc == 2) - dir = xstrdup(argv[1]); - else - dir = guess_dir_name(repo_name, is_bundle, option_bare); + dir = xstrdup(argv[1]); strip_trailing_slashes(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); + if (dest_exists) { + if (option_force) { + if (!is_directory(dir)) + die("destination path '%s' already exists and" + " is not a directory.", dir); + } else { + if (!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);