diff --git a/src/fileops.c b/src/fileops.c index 5d7e92978..68f45c25a 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -1,5 +1,6 @@ #include "common.h" #include "fileops.h" +#include int gitfo_open(const char *path, int flags) { @@ -311,6 +312,19 @@ int gitfo_dirent( return GIT_SUCCESS; } +#ifdef GIT_WIN32 + +static int is_windows_rooted_path(const char *path) +{ + /* Does the root of the path look like a windows drive ? */ + if (isalpha(path[0]) && (path[1] == ':')) + return GIT_SUCCESS; + + return GIT_ERROR; +} + +#endif + int gitfo_mkdir_recurs(const char *path, int mode) { int error; @@ -320,23 +334,35 @@ int gitfo_mkdir_recurs(const char *path, int mode) if (path_copy == NULL) return GIT_ENOMEM; - error = GIT_SUCCESS; - pp = path_copy; + error = GIT_SUCCESS; + pp = path_copy; - while (error == 0 && (sp = strchr(pp, '/')) != 0) { - if (sp != pp && gitfo_isdir(path_copy) < GIT_SUCCESS) { - *sp = 0; - error = gitfo_mkdir(path_copy, mode); - *sp = '/'; - } +#ifdef GIT_WIN32 - pp = sp + 1; - } + if (!is_windows_rooted_path(pp)) + pp += 2; /* Skip the drive name (eg. C: or D:) */ - if (*(pp - 1) != '/' && error == GIT_SUCCESS) - error = gitfo_mkdir(path, mode); +#endif - free(path_copy); - return error; + while (error == GIT_SUCCESS && (sp = strchr(pp, '/')) != 0) { + if (sp != pp && gitfo_isdir(path_copy) < GIT_SUCCESS) { + *sp = 0; + error = gitfo_mkdir(path_copy, mode); + + /* Do not choke while trying to recreate an existing directory */ + if (errno == EEXIST) + error = GIT_SUCCESS; + + *sp = '/'; + } + + pp = sp + 1; + } + + if (*(pp - 1) != '/' && error == GIT_SUCCESS) + error = gitfo_mkdir(path, mode); + + free(path_copy); + return error; } diff --git a/src/repository.c b/src/repository.c index 3551b8796..6af75f7d0 100644 --- a/src/repository.c +++ b/src/repository.c @@ -35,9 +35,11 @@ #define GIT_DIR "/.git/" #define GIT_OBJECTS_DIR "objects/" +#define GIT_OBJECTS_INFO_DIR GIT_OBJECTS_DIR "info/" +#define GIT_OBJECTS_PACK_DIR GIT_OBJECTS_DIR "pack/" #define GIT_REFS_DIR "refs/" -#define GIT_REFS_HEADS_DIR "refs/heads/" -#define GIT_REFS_TAGS_DIR "refs/tags/" +#define GIT_REFS_HEADS_DIR GIT_REFS_DIR "heads/" +#define GIT_REFS_TAGS_DIR GIT_REFS_DIR "tags/" #define GIT_INDEX_FILE "index" #define GIT_HEAD_FILE "HEAD" @@ -786,19 +788,19 @@ int repo_init_structure(repo_init *results) if (repo_init_createhead(temp_path) < GIT_SUCCESS) return GIT_ERROR; - /* Creates the '/objects/' directory */ - strcpy(temp_path + path_len, GIT_OBJECTS_DIR); - if (gitfo_mkdir(temp_path, mode)) + /* Creates the '/objects/info/' directory */ + strcpy(temp_path + path_len, GIT_OBJECTS_INFO_DIR); + if (gitfo_mkdir_recurs(temp_path, mode)) return GIT_ERROR; - /* Creates the '/refs/' directory */ - strcpy(temp_path + path_len, GIT_REFS_DIR); + /* Creates the '/objects/pack/' directory */ + strcpy(temp_path + path_len, GIT_OBJECTS_PACK_DIR); if (gitfo_mkdir(temp_path, mode)) return GIT_ERROR; /* Creates the '/refs/heads/' directory */ strcpy(temp_path + path_len, GIT_REFS_HEADS_DIR); - if (gitfo_mkdir(temp_path, mode)) + if (gitfo_mkdir_recurs(temp_path, mode)) return GIT_ERROR; /* Creates the '/refs/tags/' directory */