From 9d9bab5c384fd5d2f2832f6a68b36ce6848e0552 Mon Sep 17 00:00:00 2001 From: Romain Geissler Date: Sat, 4 Jun 2011 16:28:39 +0200 Subject: [PATCH 1/7] Repository: Fixed some errors with ceiling_dirs in git_repository_discover. Now the ceiling_dirs are compared with their symbolic free version (like base_path). The ceiling dirs check is now performed after getting the parent directory. --- src/repository.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/repository.c b/src/repository.c index 0b67d144c..cae43dc3b 100644 --- a/src/repository.c +++ b/src/repository.c @@ -369,8 +369,7 @@ static int retrieve_ceiling_directories_offset(const char *path, const char *cei strncpy(buf, ceil, len); buf[len] = '\0'; - gitfo_posixify_path(buf); - if (gitfo_prettify_dir_path(buf2, sizeof(buf2), buf, NULL) < GIT_SUCCESS) + if (abspath(buf2, sizeof(buf2), buf) < GIT_SUCCESS) continue; len = strlen(buf2); @@ -521,12 +520,6 @@ int git_repository_discover(char *repository_path, size_t size, const char *star git_repository__free_dirs(&repo); - //nothing has been found, lets try the parent directory - if (bare_path[ceiling_offset] == '\0') { - error = git__throw(GIT_ENOTAREPO,"Not a git repository (or any of the parent directories): %s", start_path); - goto cleanup; - } - if (git__dirname_r(normal_path, sizeof(normal_path), bare_path) < GIT_SUCCESS) goto cleanup; @@ -547,6 +540,13 @@ int git_repository_discover(char *repository_path, size_t size, const char *star strcpy(bare_path, normal_path); git__joinpath(normal_path, bare_path, DOT_GIT); + + //nothing has been found, lets try the parent directory + if (bare_path[ceiling_offset] == '\0') { + error = git__throw(GIT_ENOTAREPO,"Not a git repository (or any of the parent directories): %s", start_path); + goto cleanup; + } + } if (size < (strlen(found_path) + 1) * sizeof(char)) { From 8b05e780180072d1fab525ec29100d63beb104a6 Mon Sep 17 00:00:00 2001 From: Romain Geissler Date: Sun, 5 Jun 2011 00:17:26 +0200 Subject: [PATCH 2/7] Repository: Fixed a bug in read_gitfile (proprely remove trailings newlines) --- src/repository.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/repository.c b/src/repository.c index cae43dc3b..91f27d406 100644 --- a/src/repository.c +++ b/src/repository.c @@ -409,8 +409,8 @@ static int read_gitfile(char *path_out, size_t size, const char *file_path, cons end_offset = strlen(data) - 1; - for (;data[end_offset] != '\r' && data[end_offset] != '\n'; --end_offset); - data[end_offset] = '\0'; + for (;data[end_offset] == '\r' || data[end_offset] == '\n'; --end_offset); + data[end_offset + 1] = '\0'; if (GIT_FILE_CONTENT_PREFIX_LENGTH == end_offset) { gitfo_free_buf(&file); From f2a60854cd174006fc2fa9b9f2af4c3e54672e96 Mon Sep 17 00:00:00 2001 From: Romain Geissler Date: Sun, 5 Jun 2011 00:18:34 +0200 Subject: [PATCH 3/7] Repository: Fixed the path returned by read_gitfile (remove trailing slashes) --- src/repository.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/repository.c b/src/repository.c index 91f27d406..47d58e4eb 100644 --- a/src/repository.c +++ b/src/repository.c @@ -418,6 +418,13 @@ static int read_gitfile(char *path_out, size_t size, const char *file_path, cons } error = gitfo_prettify_dir_path(path_out, size, data + GIT_FILE_CONTENT_PREFIX_LENGTH, base_path); + if (error == GIT_SUCCESS) { + end_offset = strlen(path_out); + + if (end_offset > 0 && path_out[end_offset - 1] == '/') + path_out[end_offset - 1 ] = '\0'; + } + gitfo_free_buf(&file); return error; From a993e4fe0612b2f08885fff283175fd1238a1be6 Mon Sep 17 00:00:00 2001 From: Romain Geissler Date: Sun, 5 Jun 2011 00:20:35 +0200 Subject: [PATCH 4/7] Fileops: Fixed gitfo_mkdir_recurs so that it proprely works with a path without trailing slash. It used to discard the last directory if the path didn't have a trailing slash. --- src/fileops.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index 56bf2927f..b1a6bb8b1 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -380,7 +380,7 @@ int gitfo_mkdir_recurs(const char *path, int mode) if (root_path_offset > 0) pp += root_path_offset; /* On Windows, will skip the drive name (eg. C: or D:) */ - while (error == GIT_SUCCESS && (sp = strchr(pp, '/')) != 0) { + while (error == GIT_SUCCESS && (sp = strchr(pp, '/')) != NULL) { if (sp != pp && gitfo_isdir(path_copy) < GIT_SUCCESS) { *sp = 0; error = gitfo_mkdir(path_copy, mode); @@ -395,8 +395,11 @@ int gitfo_mkdir_recurs(const char *path, int mode) pp = sp + 1; } - if (*(pp - 1) != '/' && error == GIT_SUCCESS) + if (*pp != '\0' && error == GIT_SUCCESS) { error = gitfo_mkdir(path, mode); + if (errno == EEXIST) + error = GIT_SUCCESS; + } free(path_copy); From 76e9e3b763e9848971950c25399748762865ee10 Mon Sep 17 00:00:00 2001 From: Romain Geissler Date: Sun, 5 Jun 2011 00:23:24 +0200 Subject: [PATCH 5/7] Tests: Added tests for git_repository_discover. Unfortunately, the across_fs flag can't be tested automaticly, as we can't create a temporary new filesystem. --- tests/resources/.gitignore | Bin 0 -> 13 bytes tests/t12-repo.c | 139 +++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 tests/resources/.gitignore diff --git a/tests/resources/.gitignore b/tests/resources/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..43a19cc9d37efba0c46b59ff17c9fd94ad20af59 GIT binary patch literal 13 UcmYevEKbfZOD)n%&n)2r03?wF+yDRo literal 0 HcmV?d00001 diff --git a/tests/t12-repo.c b/tests/t12-repo.c index 4e51f1b15..055fb46dc 100644 --- a/tests/t12-repo.c +++ b/tests/t12-repo.c @@ -268,6 +268,144 @@ BEGIN_TEST(empty0, "test if a repository is empty or not") git_repository_free(repo_empty); END_TEST +#define DISCOVER_FOLDER TEST_RESOURCES "/discover.git" + +#define SUB_REPOSITORY_FOLDER_NAME "sub_repo" +#define SUB_REPOSITORY_FOLDER DISCOVER_FOLDER "/" SUB_REPOSITORY_FOLDER_NAME +#define SUB_REPOSITORY_FOLDER_SUB SUB_REPOSITORY_FOLDER "/sub" +#define SUB_REPOSITORY_FOLDER_SUB_SUB SUB_REPOSITORY_FOLDER_SUB "/subsub" +#define SUB_REPOSITORY_FOLDER_SUB_SUB_SUB SUB_REPOSITORY_FOLDER_SUB_SUB "/subsubsub" + +#define REPOSITORY_ALTERNATE_FOLDER DISCOVER_FOLDER "/alternate_sub_repo" +#define REPOSITORY_ALTERNATE_FOLDER_SUB REPOSITORY_ALTERNATE_FOLDER "/sub" +#define REPOSITORY_ALTERNATE_FOLDER_SUB_SUB REPOSITORY_ALTERNATE_FOLDER_SUB "/subsub" +#define REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB REPOSITORY_ALTERNATE_FOLDER_SUB_SUB "/subsubsub" + +#define ALTERNATE_MALFORMED_FOLDER1 DISCOVER_FOLDER "/alternate_malformed_repo1" +#define ALTERNATE_MALFORMED_FOLDER2 DISCOVER_FOLDER "/alternate_malformed_repo2" +#define ALTERNATE_MALFORMED_FOLDER3 DISCOVER_FOLDER "/alternate_malformed_repo3" +#define ALTERNATE_NOT_FOUND_FOLDER DISCOVER_FOLDER "/alternate_not_found_repo" + +static int ensure_repository_discover(const char *start_path, const char *ceiling_dirs, const char *expected_path) +{ + int error; + char found_path[GIT_PATH_MAX]; + + error = git_repository_discover(found_path, sizeof(found_path), start_path, 0, ceiling_dirs); + //across_fs is always 0 as we can't automate the filesystem change tests + + if (error < GIT_SUCCESS) + return error; + + return strcmp(found_path, expected_path) ? GIT_ERROR : GIT_SUCCESS; +} + +static int write_file(const char *path, const char *content) +{ + int error; + git_file file; + + if (gitfo_exists(path) == GIT_SUCCESS) { + error = gitfo_unlink(path); + + if (error < GIT_SUCCESS) + return error; + } + + file = gitfo_creat_force(path, 0644); + if (file < GIT_SUCCESS) + return file; + + error = gitfo_write(file, (void*)content, strlen(content) * sizeof(char)); + + gitfo_close(file); + + return error; +} + +//no check is performed on ceiling_dirs length, so be sure it's long enough +static int append_ceiling_dir(char *ceiling_dirs, const char *path) +{ + int len = strlen(ceiling_dirs); + int error; + + error = gitfo_prettify_dir_path(ceiling_dirs + len + (len ? 1 : 0), GIT_PATH_MAX, path, NULL); + if (error < GIT_SUCCESS) + return git__rethrow(error, "Failed to append ceiling directory."); + + if (len) + ceiling_dirs[len] = ':'; + + return GIT_SUCCESS; +} + +BEGIN_TEST(discover0, "test discover") + git_repository *repo; + char ceiling_dirs[GIT_PATH_MAX * 2] = ""; + char repository_path[GIT_PATH_MAX]; + char sub_repository_path[GIT_PATH_MAX]; + char found_path[GIT_PATH_MAX]; + int error; + int mode = 0755; + + rmdir_recurs(DISCOVER_FOLDER); + must_pass(append_ceiling_dir(ceiling_dirs,TEST_RESOURCES)); + gitfo_mkdir_recurs(DISCOVER_FOLDER, mode); + + must_fail(error = git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs)); + must_be_true(error == GIT_ENOTAREPO); + + must_pass(git_repository_init(&repo, DISCOVER_FOLDER, 1)); + must_pass(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs)); + + must_pass(git_repository_init(&repo, SUB_REPOSITORY_FOLDER, 0)); + must_pass(gitfo_mkdir_recurs(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, mode)); + must_pass(git_repository_discover(sub_repository_path, sizeof(sub_repository_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs)); + + must_pass(gitfo_mkdir_recurs(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, mode)); + must_pass(ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs, sub_repository_path)); + must_pass(ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path)); + must_pass(ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, ceiling_dirs, sub_repository_path)); + + must_pass(gitfo_mkdir_recurs(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, mode)); + must_pass(write_file(REPOSITORY_ALTERNATE_FOLDER "/" DOT_GIT, "gitdir: ../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT)); + must_pass(write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB "/" DOT_GIT, "gitdir: ../../../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT)); + must_pass(write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB "/" DOT_GIT, "gitdir: ../../../../")); + must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path)); + must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, sub_repository_path)); + must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path)); + must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, repository_path)); + + must_pass(gitfo_mkdir_recurs(ALTERNATE_MALFORMED_FOLDER1, mode)); + must_pass(write_file(ALTERNATE_MALFORMED_FOLDER1 "/" DOT_GIT, "Anything but not gitdir:")); + must_pass(gitfo_mkdir_recurs(ALTERNATE_MALFORMED_FOLDER2, mode)); + must_pass(write_file(ALTERNATE_MALFORMED_FOLDER2 "/" DOT_GIT, "gitdir:")); + must_pass(gitfo_mkdir_recurs(ALTERNATE_MALFORMED_FOLDER3, mode)); + must_pass(write_file(ALTERNATE_MALFORMED_FOLDER3 "/" DOT_GIT, "gitdir: \n\n\n")); + must_pass(gitfo_mkdir_recurs(ALTERNATE_NOT_FOUND_FOLDER, mode)); + must_pass(write_file(ALTERNATE_NOT_FOUND_FOLDER "/" DOT_GIT, "gitdir: a_repository_that_surely_does_not_exist")); + must_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER1, 0, ceiling_dirs)); + must_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER2, 0, ceiling_dirs)); + must_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs)); + must_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs)); + + must_pass(append_ceiling_dir(ceiling_dirs, SUB_REPOSITORY_FOLDER)); + //this must pass as ceiling_directories cannot predent the current + //working directory to be checked + must_pass(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs)); + must_fail(error = git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs)); + must_fail(error = git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs)); + must_fail(error = git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs)); + + //.gitfile redirection should not be affected by ceiling directories + must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path)); + must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, sub_repository_path)); + must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path)); + must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, repository_path)); + + rmdir_recurs(DISCOVER_FOLDER); +END_TEST + BEGIN_SUITE(repository) ADD_TEST(odb0); ADD_TEST(odb1); @@ -278,5 +416,6 @@ BEGIN_SUITE(repository) ADD_TEST(open1); ADD_TEST(open2); ADD_TEST(empty0); + ADD_TEST(discover0); END_SUITE From 5ec05d0748094b0e7fd1920bd960a24826435cac Mon Sep 17 00:00:00 2001 From: Romain Geissler Date: Mon, 6 Jun 2011 01:26:01 +0200 Subject: [PATCH 6/7] Repository: Fixed retrieve_device return type. --- src/repository.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repository.c b/src/repository.c index 47d58e4eb..b721af8b8 100644 --- a/src/repository.c +++ b/src/repository.c @@ -330,7 +330,7 @@ static int abspath(char *buffer_out, size_t size, const char *path) return GIT_SUCCESS; } -static dev_t retrieve_device(dev_t *device_out, const char *path) +static int retrieve_device(dev_t *device_out, const char *path) { struct stat path_info; From efcc87c9d95a0b156c657c0e5c11580e7f071efd Mon Sep 17 00:00:00 2001 From: Romain Geissler Date: Mon, 6 Jun 2011 10:02:07 +0200 Subject: [PATCH 7/7] Repository: A little fix in error code. GIT_ENOTFOUND is returned when a gitfile is malformed and GIT_ENOTAREPO when the pointed dir is not a repo. Fixed tests so that it check the right error code. --- src/repository.c | 2 +- tests/t12-repo.c | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/repository.c b/src/repository.c index b721af8b8..2f4a0d3e9 100644 --- a/src/repository.c +++ b/src/repository.c @@ -412,7 +412,7 @@ static int read_gitfile(char *path_out, size_t size, const char *file_path, cons for (;data[end_offset] == '\r' || data[end_offset] == '\n'; --end_offset); data[end_offset + 1] = '\0'; - if (GIT_FILE_CONTENT_PREFIX_LENGTH == end_offset) { + if (GIT_FILE_CONTENT_PREFIX_LENGTH == end_offset + 1) { gitfo_free_buf(&file); return git__throw(GIT_ENOTFOUND, "No path in git file `%s`", file_path); } diff --git a/tests/t12-repo.c b/tests/t12-repo.c index 055fb46dc..47a48b28d 100644 --- a/tests/t12-repo.c +++ b/tests/t12-repo.c @@ -345,15 +345,13 @@ BEGIN_TEST(discover0, "test discover") char repository_path[GIT_PATH_MAX]; char sub_repository_path[GIT_PATH_MAX]; char found_path[GIT_PATH_MAX]; - int error; int mode = 0755; rmdir_recurs(DISCOVER_FOLDER); must_pass(append_ceiling_dir(ceiling_dirs,TEST_RESOURCES)); gitfo_mkdir_recurs(DISCOVER_FOLDER, mode); - must_fail(error = git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs)); - must_be_true(error == GIT_ENOTAREPO); + must_be_true(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs) == GIT_ENOTAREPO); must_pass(git_repository_init(&repo, DISCOVER_FOLDER, 1)); must_pass(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs)); @@ -387,15 +385,15 @@ BEGIN_TEST(discover0, "test discover") must_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER1, 0, ceiling_dirs)); must_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER2, 0, ceiling_dirs)); must_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs)); - must_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs)); + must_be_true(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs) == GIT_ENOTAREPO); must_pass(append_ceiling_dir(ceiling_dirs, SUB_REPOSITORY_FOLDER)); //this must pass as ceiling_directories cannot predent the current //working directory to be checked must_pass(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs)); - must_fail(error = git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs)); - must_fail(error = git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs)); - must_fail(error = git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs)); + must_be_true(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs) == GIT_ENOTAREPO); + must_be_true(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs) == GIT_ENOTAREPO); + must_be_true(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs) == GIT_ENOTAREPO); //.gitfile redirection should not be affected by ceiling directories must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path));