From 4bc1ad32b176a1f70bd7dd11b522792a4a588a42 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 7 Nov 2013 16:30:14 -0800 Subject: checkout: most of the time we have good leading directories When "git checkout" wants to create a path, e.g. a/b/c/d/e, after seeing if the entire thing already exists (in which case we check if that is up-to-date and do not bother to check it out, or we unlink and recreate it) and find it missing, we validate that the leading directory path is without funny symlinks by seeing that a/, a/b/, a/b/c/ and then a/b/c/d/ are all without funny symlinks, by calling has_dirs_only_path() in this order. When we are checking out many files (imagine: initial checkout), however, it is likely that an earlier checkout would have already made sure that the leading directory a/b/c/d/ is in good order, and has_dirs_only_path() caches this information. We can often bypass calls to has_dirs_only_path() for leading part by first checking the whole path a/b/c/d/ first (imagine we just checked out a/b/c/d/e0 and are about to check out a/b/c/d/e). This cuts down the number of calls to has_dirs_only_path() for checking out Linux kernel sources afresh from 190k down to 98k. Signed-off-by: Junio C Hamano --- entry.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'entry.c') diff --git a/entry.c b/entry.c index 7b7aa8167a..e2c0ac6230 100644 --- a/entry.c +++ b/entry.c @@ -6,9 +6,17 @@ static void create_directories(const char *path, int path_len, const struct checkout *state) { - char *buf = xmalloc(path_len + 1); - int len = 0; + char *buf; + int len; + + for (len = path_len - 1; 0 <= len; len--) + if (path[len] == '/') + break; + if (has_dirs_only_path(path, len, state->base_dir_len)) + return; /* ok, we have the whole leading directory */ + buf = xmalloc(path_len + 1); + len = 0; while (len < path_len) { do { buf[len] = path[len]; -- cgit v1.2.1