On Mon, Jun 23, 2008 at 03:56:41PM -0400, Daniel Barkalow wrote: > > Switching to the 1.5.6 release from 1.5.5.1, I found out that the > > rewritten git-clone command changed its behaviour wrt cloning to a > > non-existing destination directory structure. In the shell version the > > destination (work tree) is created with 'mkdir -p' but in the C > > version with just the mkdir() call which doesn't create the parent > > directories. > > > > I can't find any indication that this would be intended in the repo > > history nor in the mailing list, so I'm left thinking that this is an > > unwanted regression. Could someone confirm this? > > It wasn't an intentional change, anyway. Here is a partial fix. For --bare repo creation, we follow a different codepath, and I think the fix is likely to be a bit tricky. We actually fail in make_absolute_path, before we try creating the directory. But I suspect we can't just create the directory ourselves because init_db expects it not to exist. -- >8 -- clone: create intermediate directories of repo destination The shell version used to use "mkdir -p" to create the repo path, but the C version just calls "mkdir". Let's replicate the old behavior. --- builtin-clone.c | 40 +++++++++++++++++++++++++++++++++++++++- t/t5601-clone.sh | 14 ++++++++++++++ 2 files changed, 53 insertions(+), 1 deletions(-) diff --git a/builtin-clone.c b/builtin-clone.c index 5c5acb4..758d02c 100644 --- a/builtin-clone.c +++ b/builtin-clone.c @@ -168,6 +168,44 @@ static void setup_reference(const char *repo) free(ref_git_copy); } +static int mkdirp_recurse(char *path, int mode) +{ + int n; + char tmp; + int r; + + if (mkdir(path, mode) == 0) + return 0; + if (errno != ENOENT) + return -1; + + for (n = strlen(path); n > 0 && path[n] != '/'; n--) + ; + if (n == 0) + return -1; + tmp = path[n]; + path[n] = '\0'; + r = mkdirp_recurse(path, mode); + path[n] = tmp; + if (r < 0) + return -1; + return mkdir(path, mode); +} + +static int mkdirp(const char *path, int mode) +{ + char buf[PATH_MAX]; + int n; + + n = strlen(path); + if (n >= PATH_MAX) { + errno = ENAMETOOLONG; + return -1; + } + memcpy(buf, path, n+1); + return mkdirp_recurse(buf, mode); +} + static void copy_or_link_directory(char *src, char *dest) { struct dirent *de; @@ -404,7 +442,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) if (!option_bare) { junk_work_tree = work_tree; - if (mkdir(work_tree, 0755)) + if (mkdirp(work_tree, 0755)) die("could not create work tree dir '%s'.", work_tree); set_git_work_tree(work_tree); } diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index 593d1a3..c2c83f0 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -30,4 +30,18 @@ test_expect_success 'clone checks out files' ' ' +test_expect_success 'clone creates intermediate directories' ' + + git clone src long/path/to/dst && + test -f long/path/to/dst/file + +' + +test_expect_failure 'clone creates intermediate directories for bare repo' ' + + git clone --bare src long/path/to/bare/dst && + test -f long/path/to/bare/dst/config + +' + test_done -- 1.5.6.105.gceec6.dirty -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html