summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2013-11-07 16:30:14 -0800
committerJunio C Hamano <gitster@pobox.com>2013-11-11 09:36:05 -0800
commit4bc1ad32b176a1f70bd7dd11b522792a4a588a42 (patch)
treeff9bda5bf066b5283e39df1650e0b8bf1148167a
parent0ecd94d7d728606e0047a44e60a277ff4e7b3990 (diff)
downloadgit-jc/create-directories-microopt.tar.gz
checkout: most of the time we have good leading directoriesjc/create-directories-microopt
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 <gitster@pobox.com>
-rw-r--r--entry.c12
1 files changed, 10 insertions, 2 deletions
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];