/* * Determine if the path is a Windows prefix and, if so, returns * its actual lentgh. If it is not a prefix, returns -1. */ static int win32_prefix_length(const char *path, int len) { #ifndef GIT_WIN32 GIT_UNUSED(path); GIT_UNUSED(len); #else /* * Mimic unix behavior where '/.git' returns '/': 'C:/.git' will return * 'C:/' here */ if (len == 2 && LOOKS_LIKE_DRIVE_PREFIX(path)) return 2; /* * Similarly checks if we're dealing with a network computer name * '//computername/.git' will return '//computername/' */ if (looks_like_network_computer_name(path, len)) return len; #endif return -1; }
/* * Based on the Android implementation, BSD licensed. * Check http://android.git.kernel.org/ */ int git_path_dirname_r(git_buf *buffer, const char *path) { const char *endp; int result, len; /* Empty or NULL string gets treated as "." */ if (path == NULL || *path == '\0') { path = "."; len = 1; goto Exit; } /* Strip trailing slashes */ endp = path + strlen(path) - 1; while (endp > path && *endp == '/') endp--; /* Find the start of the dir */ while (endp > path && *endp != '/') endp--; /* Either the dir is "/" or there are no slashes */ if (endp == path) { path = (*endp == '/') ? "/" : "."; len = 1; goto Exit; } do { endp--; } while (endp > path && *endp == '/'); /* Cast is safe because max path < max int */ len = (int)(endp - path + 1); #ifdef GIT_WIN32 /* Mimic unix behavior where '/.git' returns '/': 'C:/.git' will return 'C:/' here */ if (len == 2 && LOOKS_LIKE_DRIVE_PREFIX(path)) { len = 3; goto Exit; } /* Similarly checks if we're dealing with a network computer name '//computername/.git' will return '//computername/' */ if (looks_like_network_computer_name(path, len)) { len++; goto Exit; } #endif Exit: result = len; if (buffer != NULL && git_buf_set(buffer, path, len) < 0) return -1; return result; }