From 86b9dbc12f61c24457f2979e9496c85e115a3799 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 17 Nov 2012 04:50:48 -0800 Subject: [PATCH 01/10] Fix MSVC compilation warnings --- src/pack-objects.h | 10 +++++----- tests-clar/object/raw/short.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pack-objects.h b/src/pack-objects.h index 8c01f7189..e34cc2754 100644 --- a/src/pack-objects.h +++ b/src/pack-objects.h @@ -71,11 +71,11 @@ struct git_packbuilder { git_cond progress_cond; /* configs */ - unsigned long delta_cache_size; - unsigned long max_delta_cache_size; - unsigned long cache_max_small_delta_size; - unsigned long big_file_threshold; - unsigned long window_memory_limit; + uint64_t delta_cache_size; + uint64_t max_delta_cache_size; + uint64_t cache_max_small_delta_size; + uint64_t big_file_threshold; + uint64_t window_memory_limit; int nr_threads; /* nr of threads to use */ diff --git a/tests-clar/object/raw/short.c b/tests-clar/object/raw/short.c index 14b1ae219..93c79b6a5 100644 --- a/tests-clar/object/raw/short.c +++ b/tests-clar/object/raw/short.c @@ -43,7 +43,7 @@ void test_object_raw_short__oid_shortener_stresstest_git_oid_shorten(void) for (i = 0; i < MAX_OIDS; ++i) { char *oid_text; - sprintf(number_buffer, "%u", (unsigned int)i); + p_snprintf(number_buffer, 16, "%u", (unsigned int)i); git_hash_buf(&oid, number_buffer, strlen(number_buffer)); oid_text = git__malloc(GIT_OID_HEXSZ + 1); From aa8a76eff9494e109c2c72c72ad687faaf05db3d Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 17 Nov 2012 05:12:14 -0800 Subject: [PATCH 02/10] tag: rename git_tag_type to git_tag_target_type --- examples/general.c | 2 +- include/git2/tag.h | 2 +- src/tag.c | 2 +- tests-clar/object/tag/read.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/general.c b/examples/general.c index d9467f5b5..9ccb4c56e 100644 --- a/examples/general.c +++ b/examples/general.c @@ -239,7 +239,7 @@ int main (int argc, char** argv) // the tagger (a git_signature - name, email, timestamp), and the tag message. git_tag_target((git_object **)&commit, tag); tname = git_tag_name(tag); // "test" - ttype = git_tag_type(tag); // GIT_OBJ_COMMIT (otype enum) + ttype = git_tag_target_type(tag); // GIT_OBJ_COMMIT (otype enum) tmessage = git_tag_message(tag); // "tag message\n" printf("Tag Message: %s\n", tmessage); diff --git a/include/git2/tag.h b/include/git2/tag.h index 5602914f7..a1b685f12 100644 --- a/include/git2/tag.h +++ b/include/git2/tag.h @@ -104,7 +104,7 @@ GIT_EXTERN(const git_oid *) git_tag_target_oid(git_tag *tag); * @param tag a previously loaded tag. * @return type of the tagged object */ -GIT_EXTERN(git_otype) git_tag_type(git_tag *tag); +GIT_EXTERN(git_otype) git_tag_target_type(git_tag *tag); /** * Get the name of a tag diff --git a/src/tag.c b/src/tag.c index 4c3d811eb..13369d9fb 100644 --- a/src/tag.c +++ b/src/tag.c @@ -39,7 +39,7 @@ const git_oid *git_tag_target_oid(git_tag *t) return &t->target; } -git_otype git_tag_type(git_tag *t) +git_otype git_tag_target_type(git_tag *t) { assert(t); return t->type; diff --git a/tests-clar/object/tag/read.c b/tests-clar/object/tag/read.c index 62dd4ca39..53272e91c 100644 --- a/tests-clar/object/tag/read.c +++ b/tests-clar/object/tag/read.c @@ -38,7 +38,7 @@ void test_object_tag_read__parse(void) cl_git_pass(git_tag_lookup(&tag1, g_repo, &id1)); cl_assert_equal_s(git_tag_name(tag1), "test"); - cl_assert(git_tag_type(tag1) == GIT_OBJ_TAG); + cl_assert(git_tag_target_type(tag1) == GIT_OBJ_TAG); cl_git_pass(git_tag_target((git_object **)&tag2, tag1)); cl_assert(tag2 != NULL); From 0e95e70a55b2c7af64370c0b886d4d00f8bea839 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 17 Nov 2012 05:22:39 -0800 Subject: [PATCH 03/10] env: ensure git_futils_find_xxx() returns ENOTFOUND --- tests-clar/core/env.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/tests-clar/core/env.c b/tests-clar/core/env.c index 288222d29..d849f76ed 100644 --- a/tests-clar/core/env.c +++ b/tests-clar/core/env.c @@ -84,13 +84,15 @@ void test_core_env__0(void) cl_git_mkfile(path.ptr, "find me"); git_buf_rtruncate_at_char(&path, '/'); - cl_git_fail(git_futils_find_global_file(&found, testfile)); + cl_assert_equal_i( + GIT_ENOTFOUND, git_futils_find_global_file(&found, testfile)); setenv_and_check("HOME", path.ptr); cl_git_pass(git_futils_find_global_file(&found, testfile)); cl_setenv("HOME", env_save[0]); - cl_git_fail(git_futils_find_global_file(&found, testfile)); + cl_assert_equal_i( + GIT_ENOTFOUND, git_futils_find_global_file(&found, testfile)); #ifdef GIT_WIN32 setenv_and_check("HOMEDRIVE", NULL); @@ -106,7 +108,8 @@ void test_core_env__0(void) if (root >= 0) { setenv_and_check("USERPROFILE", NULL); - cl_git_fail(git_futils_find_global_file(&found, testfile)); + cl_assert_equal_i( + GIT_ENOTFOUND, git_futils_find_global_file(&found, testfile)); old = path.ptr[root]; path.ptr[root] = '\0'; @@ -128,7 +131,8 @@ void test_core_env__1(void) { git_buf path = GIT_BUF_INIT; - cl_must_fail(git_futils_find_global_file(&path, "nonexistentfile")); + cl_assert_equal_i( + GIT_ENOTFOUND, git_futils_find_global_file(&path, "nonexistentfile")); cl_git_pass(cl_setenv("HOME", "doesnotexist")); #ifdef GIT_WIN32 @@ -136,7 +140,8 @@ void test_core_env__1(void) cl_git_pass(cl_setenv("USERPROFILE", "doesnotexist")); #endif - cl_must_fail(git_futils_find_global_file(&path, "nonexistentfile")); + cl_assert_equal_i( + GIT_ENOTFOUND, git_futils_find_global_file(&path, "nonexistentfile")); cl_git_pass(cl_setenv("HOME", NULL)); #ifdef GIT_WIN32 @@ -144,13 +149,16 @@ void test_core_env__1(void) cl_git_pass(cl_setenv("USERPROFILE", NULL)); #endif - cl_must_fail(git_futils_find_global_file(&path, "nonexistentfile")); + cl_assert_equal_i( + GIT_ENOTFOUND, git_futils_find_global_file(&path, "nonexistentfile")); - cl_must_fail(git_futils_find_system_file(&path, "nonexistentfile")); + cl_assert_equal_i( + GIT_ENOTFOUND, git_futils_find_system_file(&path, "nonexistentfile")); #ifdef GIT_WIN32 cl_git_pass(cl_setenv("PROGRAMFILES", NULL)); - cl_must_fail(git_futils_find_system_file(&path, "nonexistentfile")); + cl_assert_equal_i( + GIT_ENOTFOUND, git_futils_find_system_file(&path, "nonexistentfile")); #endif git_buf_free(&path); From 5df7207a674d1d4c41b300f6f0c5548d087f06b3 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 17 Nov 2012 06:56:19 -0800 Subject: [PATCH 04/10] repo: readonly tests don't need a sandboxed repo --- tests-clar/repo/getters.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/tests-clar/repo/getters.c b/tests-clar/repo/getters.c index ffcd171f2..299a2cb42 100644 --- a/tests-clar/repo/getters.c +++ b/tests-clar/repo/getters.c @@ -1,15 +1,5 @@ #include "clar_libgit2.h" -void test_repo_getters__initialize(void) -{ - cl_fixture_sandbox("testrepo.git"); -} - -void test_repo_getters__cleanup(void) -{ - cl_fixture_cleanup("testrepo.git"); -} - void test_repo_getters__empty(void) { git_repository *repo_empty, *repo_normal; @@ -28,7 +18,7 @@ void test_repo_getters__retrieving_the_odb_honors_the_refcount(void) git_odb *odb; git_repository *repo; - cl_git_pass(git_repository_open(&repo, "testrepo.git")); + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); cl_git_pass(git_repository_odb(&odb, repo)); cl_assert(((git_refcount *)odb)->refcount == 2); From f5a0e734bc440ca6c89d15a894fea0ea3bf38f36 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 17 Nov 2012 06:46:42 -0800 Subject: [PATCH 05/10] tests: introduce cl_git_remove_placeholders() --- tests-clar/clar_helpers.c | 49 +++++++++++++++++++++++++++++++++++++++ tests-clar/clar_libgit2.h | 3 +++ 2 files changed, 52 insertions(+) diff --git a/tests-clar/clar_helpers.c b/tests-clar/clar_helpers.c index 3d09bd489..b718d4305 100644 --- a/tests-clar/clar_helpers.c +++ b/tests-clar/clar_helpers.c @@ -271,3 +271,52 @@ const char* cl_git_path_url(const char *path) git_buf_free(&path_buf); return url; } + +typedef struct { + const char *filename; + size_t filename_len; +} remove_data; + +static int remove_placeholders_recurs(void *_data, git_buf *path) +{ + remove_data *data = (remove_data *)_data; + size_t pathlen; + + if (git_path_isdir(path->ptr) == true) + return git_path_direach(path, remove_placeholders_recurs, data); + + pathlen = path->size; + + if (pathlen < data->filename_len) + return 0; + + /* if path ends in '/'+filename (or equals filename) */ + if (!strcmp(data->filename, path->ptr + pathlen - data->filename_len) && + (pathlen == data->filename_len || + path->ptr[pathlen - data->filename_len - 1] == '/')) + return p_unlink(path->ptr); + + return 0; +} + +int cl_git_remove_placeholders(const char *directory_path, const char *filename) +{ + int error; + remove_data data; + git_buf buffer = GIT_BUF_INIT; + + if (git_path_isdir(directory_path) == false) + return -1; + + if (git_buf_sets(&buffer, directory_path) < 0) + return -1; + + data.filename = filename; + data.filename_len = strlen(filename); + + error = remove_placeholders_recurs(&data, &buffer); + + git_buf_free(&buffer); + + return error; +} diff --git a/tests-clar/clar_libgit2.h b/tests-clar/clar_libgit2.h index fd20c1259..91a542654 100644 --- a/tests-clar/clar_libgit2.h +++ b/tests-clar/clar_libgit2.h @@ -61,4 +61,7 @@ void cl_git_sandbox_cleanup(void); const char* cl_git_fixture_url(const char *fixturename); const char* cl_git_path_url(const char *path); +/* Test repository cleaner */ +int cl_git_remove_placeholders(const char *directory_path, const char *filename); + #endif From 6091457e76638503fec46de269bc158f63e4721a Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 17 Nov 2012 07:19:14 -0800 Subject: [PATCH 06/10] repo: ensure is_empty() checks there are no refs --- include/git2/repository.h | 2 +- src/repository.c | 51 ++++++++++++++++++++++++--------------- tests-clar/repo/getters.c | 26 ++++++++++++++------ 3 files changed, 50 insertions(+), 29 deletions(-) diff --git a/include/git2/repository.h b/include/git2/repository.h index d606cfa2a..f891e91e9 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -305,7 +305,7 @@ GIT_EXTERN(int) git_repository_head_orphan(git_repository *repo); * Check if a repository is empty * * An empty repository has just been initialized and contains - * no commits. + * no references. * * @param repo Repo to test * @return 1 if the repository is empty, 0 if it isn't, error code diff --git a/src/repository.c b/src/repository.c index 101497c4d..2d6ce4dbb 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1241,36 +1241,47 @@ int git_repository_head_orphan(git_repository *repo) return 0; } +int at_least_one_cb(const char *refname, void *payload) +{ + GIT_UNUSED(refname); + GIT_UNUSED(payload); + + return GIT_EUSER; +} + +static int repo_contains_no_reference(git_repository *repo) +{ + int error; + + error = git_reference_foreach(repo, GIT_REF_LISTALL, at_least_one_cb, NULL); + + if (error == GIT_EUSER) + return 0; + + return error == 0 ? 1 : error; +} + int git_repository_is_empty(git_repository *repo) { - git_reference *head = NULL, *branch = NULL; - int error; + git_reference *head = NULL; + int error, ref_count = 0; if (git_reference_lookup(&head, repo, GIT_HEAD_FILE) < 0) return -1; - if (git_reference_type(head) != GIT_REF_SYMBOLIC) { - git_reference_free(head); - return 0; - } + if (!(error = git_reference_type(head) == GIT_REF_SYMBOLIC)) + goto cleanup; - if (strcmp(git_reference_target(head), GIT_REFS_HEADS_DIR "master") != 0) { - git_reference_free(head); - return 0; - } + if (!(error = strcmp( + git_reference_target(head), + GIT_REFS_HEADS_DIR "master") == 0)) + goto cleanup; - error = git_reference_resolve(&branch, head); + error = repo_contains_no_reference(repo); +cleanup: git_reference_free(head); - git_reference_free(branch); - - if (error == GIT_ENOTFOUND) - return 1; - - if (error < 0) - return -1; - - return 0; + return error < 0 ? -1 : error; } const char *git_repository_path(git_repository *repo) diff --git a/tests-clar/repo/getters.c b/tests-clar/repo/getters.c index 299a2cb42..b372f5b70 100644 --- a/tests-clar/repo/getters.c +++ b/tests-clar/repo/getters.c @@ -1,16 +1,26 @@ #include "clar_libgit2.h" -void test_repo_getters__empty(void) +void test_repo_getters__is_empty_correctly_deals_with_pristine_looking_repos(void) { - git_repository *repo_empty, *repo_normal; + git_repository *repo; - cl_git_pass(git_repository_open(&repo_normal, cl_fixture("testrepo.git"))); - cl_assert(git_repository_is_empty(repo_normal) == 0); - git_repository_free(repo_normal); + repo = cl_git_sandbox_init("empty_bare.git"); + cl_git_remove_placeholders(git_repository_path(repo), "dummy-marker.txt"); - cl_git_pass(git_repository_open(&repo_empty, cl_fixture("empty_bare.git"))); - cl_assert(git_repository_is_empty(repo_empty) == 1); - git_repository_free(repo_empty); + cl_assert_equal_i(true, git_repository_is_empty(repo)); + + cl_git_sandbox_cleanup(); +} + +void test_repo_getters__is_empty_can_detect_used_repositories(void) +{ + git_repository *repo; + + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); + + cl_assert_equal_i(false, git_repository_is_empty(repo)); + + git_repository_free(repo); } void test_repo_getters__retrieving_the_odb_honors_the_refcount(void) From d36451c9d4ba071de07106371553bf93f2717fc4 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 17 Nov 2012 12:34:15 -0800 Subject: [PATCH 07/10] config: Make git_config_file__ondisk() internal --- include/git2/config.h | 13 ------------- src/config.h | 13 +++++++++++++ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/git2/config.h b/include/git2/config.h index b427b8598..8270aefa4 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -134,19 +134,6 @@ GIT_EXTERN(int) git_config_find_system(char *system_config_path, size_t length); */ GIT_EXTERN(int) git_config_open_default(git_config **out); -/** - * Create a configuration file backend for ondisk files - * - * These are the normal `.gitconfig` files that Core Git - * processes. Note that you first have to add this file to a - * configuration object before you can query it for configuration - * variables. - * - * @param out the new backend - * @param path where the config file is located - */ -GIT_EXTERN(int) git_config_file__ondisk(struct git_config_file **out, const char *path); - /** * Allocate a new configuration object * diff --git a/src/config.h b/src/config.h index a0569ec93..c7595ee79 100644 --- a/src/config.h +++ b/src/config.h @@ -32,4 +32,17 @@ extern int git_config_rename_section( const char *old_section_name, /* eg "branch.dummy" */ const char *new_section_name); /* NULL to drop the old section */ +/** + * Create a configuration file backend for ondisk files + * + * These are the normal `.gitconfig` files that Core Git + * processes. Note that you first have to add this file to a + * configuration object before you can query it for configuration + * variables. + * + * @param out the new backend + * @param path where the config file is located + */ +extern int git_config_file__ondisk(struct git_config_file **out, const char *path); + #endif From 270160b91a0e55486f2cb6a6238c39fcd1271809 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 17 Nov 2012 13:39:24 -0800 Subject: [PATCH 08/10] config: Opening a nonexistent file returns ENOTFOUND --- include/git2/config.h | 11 ++++++----- src/config.c | 26 +++++++++++++++++++------- src/repository.c | 23 +++++++++++++++++++++++ tests-clar/config/new.c | 1 + tests-clar/config/read.c | 20 ++++++++++++++++++++ 5 files changed, 69 insertions(+), 12 deletions(-) diff --git a/include/git2/config.h b/include/git2/config.h index 8270aefa4..8ec78e35c 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -189,7 +189,8 @@ GIT_EXTERN(int) git_config_add_file( * @param force if a config file already exists for the given * priority level, replace it * @return 0 on success, GIT_EEXISTS when adding more than one file - * for a given priority level (and force_replace set to 0), or error code + * for a given priority level (and force_replace set to 0), + * GIT_ENOTFOUND when the file doesn't exist or error code */ GIT_EXTERN(int) git_config_add_file_ondisk( git_config *cfg, @@ -197,7 +198,6 @@ GIT_EXTERN(int) git_config_add_file_ondisk( unsigned int level, int force); - /** * Create a new config instance containing a single on-disk file * @@ -206,11 +206,12 @@ GIT_EXTERN(int) git_config_add_file_ondisk( * - git_config_new * - git_config_add_file_ondisk * - * @param cfg The configuration instance to create + * @param out The configuration instance to create * @param path Path to the on-disk file to open - * @return 0 or an error code + * @return 0 on success, GIT_ENOTFOUND when the file doesn't exist + * or an error code */ -GIT_EXTERN(int) git_config_open_ondisk(git_config **cfg, const char *path); +GIT_EXTERN(int) git_config_open_ondisk(git_config **out, const char *path); /** * Build a single-level focused config object from a multi-level one. diff --git a/src/config.c b/src/config.c index 01a54ecf2..412965b73 100644 --- a/src/config.c +++ b/src/config.c @@ -90,6 +90,13 @@ int git_config_add_file_ondisk( git_config_file *file = NULL; int res; + assert(cfg && path); + + if (!git_path_isfile(path)) { + giterr_set(GITERR_CONFIG, "File '%s' doesn't exists.", path); + return GIT_ENOTFOUND; + } + if (git_config_file__ondisk(&file, path) < 0) return -1; @@ -105,17 +112,22 @@ int git_config_add_file_ondisk( return 0; } -int git_config_open_ondisk(git_config **cfg, const char *path) +int git_config_open_ondisk(git_config **out, const char *path) { - if (git_config_new(cfg) < 0) + int error; + git_config *config; + + *out = NULL; + + if (git_config_new(&config) < 0) return -1; - if (git_config_add_file_ondisk(*cfg, path, GIT_CONFIG_LEVEL_LOCAL, 0) < 0) { - git_config_free(*cfg); - return -1; - } + if ((error = git_config_add_file_ondisk(config, path, GIT_CONFIG_LEVEL_LOCAL, 0)) < 0) + git_config_free(config); + else + *out = config; - return 0; + return error; } static int find_internal_file_by_level( diff --git a/src/repository.c b/src/repository.c index 2d6ce4dbb..c1756b1bc 100644 --- a/src/repository.c +++ b/src/repository.c @@ -750,6 +750,23 @@ static bool are_symlinks_supported(const char *wd_path) return _symlinks_supported; } +static int create_empty_file(const char *path, mode_t mode) +{ + int fd; + + if ((fd = p_creat(path, mode)) < 0) { + giterr_set(GITERR_OS, "Error while creating '%s'", path); + return -1; + } + + if (p_close(fd) < 0) { + giterr_set(GITERR_OS, "Error while closing '%s'", path); + return -1; + } + + return 0; +} + static int repo_init_config( const char *repo_dir, const char *work_dir, @@ -766,6 +783,12 @@ static int repo_init_config( if (git_buf_joinpath(&cfg_path, repo_dir, GIT_CONFIG_FILENAME_INREPO) < 0) return -1; + if (!git_path_isfile(git_buf_cstr(&cfg_path)) && + create_empty_file(git_buf_cstr(&cfg_path), GIT_CONFIG_FILE_MODE) < 0) { + git_buf_free(&cfg_path); + return -1; + } + if (git_config_open_ondisk(&config, git_buf_cstr(&cfg_path)) < 0) { git_buf_free(&cfg_path); return -1; diff --git a/tests-clar/config/new.c b/tests-clar/config/new.c index 6bd719fba..dd6dbca9e 100644 --- a/tests-clar/config/new.c +++ b/tests-clar/config/new.c @@ -11,6 +11,7 @@ void test_config_new__write_new_config(void) const char *out; git_config *config; + cl_git_mkfile(TEST_CONFIG, ""); cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); cl_git_pass(git_config_set_string(config, "color.ui", "auto")); diff --git a/tests-clar/config/read.c b/tests-clar/config/read.c index 7b30b6e12..d63ef4c91 100644 --- a/tests-clar/config/read.c +++ b/tests-clar/config/read.c @@ -430,3 +430,23 @@ void test_config_read__simple_read_from_specific_level(void) git_config_free(cfg_specific); git_config_free(cfg); } + +void test_config_read__can_load_and_parse_an_empty_config_file(void) +{ + git_config *cfg; + int i; + + cl_git_mkfile("./empty", ""); + cl_git_pass(git_config_open_ondisk(&cfg, "./empty")); + cl_assert_equal_i(GIT_ENOTFOUND, git_config_get_int32(&i, cfg, "nope.neither")); + + git_config_free(cfg); +} + +void test_config_read__cannot_load_a_non_existing_config_file(void) +{ + git_config *cfg; + int i; + + cl_assert_equal_i(GIT_ENOTFOUND, git_config_open_ondisk(&cfg, "./no.config")); +} From 1a764476d27ac1861d1433b02bc7fbff733d8942 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 17 Nov 2012 18:24:10 -0800 Subject: [PATCH 09/10] reflog: Fix documentation --- include/git2/reflog.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/git2/reflog.h b/include/git2/reflog.h index d48a89725..20e0f3319 100644 --- a/include/git2/reflog.h +++ b/include/git2/reflog.h @@ -107,7 +107,8 @@ GIT_EXTERN(const git_reflog_entry *) git_reflog_entry_byindex(git_reflog *reflog * * @param rewrite_previous_entry 1 to rewrite the history; 0 otherwise. * - * @return 0 on success or an error code. + * @return 0 on success, GIT_ENOTFOUND if the entry doesn't exist + * or an error code. */ GIT_EXTERN(int) git_reflog_drop( git_reflog *reflog, From b15df1d937128bb7051ab35084195ff1980a7869 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 17 Nov 2012 18:29:51 -0800 Subject: [PATCH 10/10] reflog: make entry_byindex() and drop() git compliant Passing 0 as the index now retrieves the most recent entry instead of the oldest one. --- include/git2/reflog.h | 11 ++++++--- src/reflog.c | 41 ++++++++++++++++++--------------- src/revparse.c | 6 ++--- src/stash.c | 4 ++-- tests-clar/refs/reflog/drop.c | 22 ++++++++++-------- tests-clar/refs/reflog/reflog.c | 4 ++-- tests-clar/stash/drop.c | 2 +- 7 files changed, 51 insertions(+), 39 deletions(-) diff --git a/include/git2/reflog.h b/include/git2/reflog.h index 20e0f3319..72e1f1753 100644 --- a/include/git2/reflog.h +++ b/include/git2/reflog.h @@ -88,8 +88,12 @@ GIT_EXTERN(unsigned int) git_reflog_entrycount(git_reflog *reflog); /** * Lookup an entry by its index * + * Requesting the reflog entry with an index of 0 (zero) will + * return the most recently created entry. + * * @param reflog a previously loaded reflog - * @param idx the position to lookup + * @param idx the position of the entry to lookup. Should be greater than or + * equal to 0 (zero) and less than `git_reflog_entrycount()`. * @return the entry; NULL if not found */ GIT_EXTERN(const git_reflog_entry *) git_reflog_entry_byindex(git_reflog *reflog, size_t idx); @@ -103,7 +107,8 @@ GIT_EXTERN(const git_reflog_entry *) git_reflog_entry_byindex(git_reflog *reflog * * @param reflog a previously loaded reflog. * - * @param idx the position of the entry to remove. + * @param idx the position of the entry to remove. Should be greater than or + * equal to 0 (zero) and less than `git_reflog_entrycount()`. * * @param rewrite_previous_entry 1 to rewrite the history; 0 otherwise. * @@ -112,7 +117,7 @@ GIT_EXTERN(const git_reflog_entry *) git_reflog_entry_byindex(git_reflog *reflog */ GIT_EXTERN(int) git_reflog_drop( git_reflog *reflog, - unsigned int idx, + size_t idx, int rewrite_previous_entry); /** diff --git a/src/reflog.c b/src/reflog.c index 0e333aa6f..7b07c6a9f 100644 --- a/src/reflog.c +++ b/src/reflog.c @@ -291,8 +291,8 @@ success: int git_reflog_append(git_reflog *reflog, const git_oid *new_oid, const git_signature *committer, const char *msg) { - int count; git_reflog_entry *entry; + const git_reflog_entry *previous; const char *newline; assert(reflog && new_oid && committer); @@ -319,16 +319,12 @@ int git_reflog_append(git_reflog *reflog, const git_oid *new_oid, } } - count = git_reflog_entrycount(reflog); + previous = git_reflog_entry_byindex(reflog, 0); - if (count == 0) + if (previous == NULL) git_oid_fromstr(&entry->oid_old, GIT_OID_HEX_ZERO); - else { - const git_reflog_entry *previous; - - previous = git_reflog_entry_byindex(reflog, count -1); + else git_oid_cpy(&entry->oid_old, &previous->oid_cur); - } git_oid_cpy(&entry->oid_cur, new_oid); @@ -417,8 +413,16 @@ unsigned int git_reflog_entrycount(git_reflog *reflog) const git_reflog_entry * git_reflog_entry_byindex(git_reflog *reflog, size_t idx) { + int pos; + assert(reflog); - return git_vector_get(&reflog->entries, idx); + + pos = git_reflog_entrycount(reflog) - (idx + 1); + + if (pos < 0) + return NULL; + + return git_vector_get(&reflog->entries, pos); } const git_oid * git_reflog_entry_oidold(const git_reflog_entry *entry) @@ -447,7 +451,7 @@ char * git_reflog_entry_msg(const git_reflog_entry *entry) int git_reflog_drop( git_reflog *reflog, - unsigned int idx, + size_t idx, int rewrite_previous_entry) { unsigned int entrycount; @@ -457,30 +461,31 @@ int git_reflog_drop( entrycount = git_reflog_entrycount(reflog); - if (idx >= entrycount) + entry = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx); + + if (entry == NULL) return GIT_ENOTFOUND; - entry = git_vector_get(&reflog->entries, idx); reflog_entry_free(entry); - if (git_vector_remove(&reflog->entries, idx) < 0) + if (git_vector_remove(&reflog->entries, entrycount - (idx + 1)) < 0) return -1; if (!rewrite_previous_entry) return 0; /* No need to rewrite anything when removing the most recent entry */ - if (idx == entrycount - 1) + if (idx == 0) return 0; - /* There are no more entries in the log */ + /* Have the latest entry just been dropped? */ if (entrycount == 1) return 0; - entry = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx); + entry = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx - 1); /* If the oldest entry has just been removed... */ - if (idx == 0) { + if (idx == entrycount - 1) { /* ...clear the oid_old member of the "new" oldest entry */ if (git_oid_fromstr(&entry->oid_old, GIT_OID_HEX_ZERO) < 0) return -1; @@ -488,7 +493,7 @@ int git_reflog_drop( return 0; } - previous = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx - 1); + previous = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx); git_oid_cpy(&entry->oid_old, &previous->oid_cur); return 0; diff --git a/src/revparse.c b/src/revparse.c index 83eea7d3f..6a7587d6a 100644 --- a/src/revparse.c +++ b/src/revparse.c @@ -201,7 +201,7 @@ static int retrieve_previously_checked_out_branch_or_revision(git_object **out, numentries = git_reflog_entrycount(reflog); - for (i = numentries - 1; i >= 0; i--) { + for (i = 0; i < numentries; i++) { entry = git_reflog_entry_byindex(reflog, i); msg = git_reflog_entry_msg(entry); @@ -263,7 +263,7 @@ static int retrieve_oid_from_reflog(git_oid *oid, git_reference *ref, unsigned i } entry = git_reflog_entry_byindex(reflog, identifier); - git_oid_cpy(oid, git_reflog_entry_oidold(entry)); + git_oid_cpy(oid, git_reflog_entry_oidnew(entry)); error = 0; goto cleanup; @@ -271,7 +271,7 @@ static int retrieve_oid_from_reflog(git_oid *oid, git_reference *ref, unsigned i int i; git_time commit_time; - for (i = numentries - 1; i >= 0; i--) { + for (i = 0; i < numentries; i++) { entry = git_reflog_entry_byindex(reflog, i); commit_time = git_reflog_entry_committer(entry)->when; diff --git a/src/stash.c b/src/stash.c index 627d271f4..b74429aca 100644 --- a/src/stash.c +++ b/src/stash.c @@ -600,7 +600,7 @@ int git_stash_foreach( max = git_reflog_entrycount(reflog); for (i = 0; i < max; i++) { - entry = git_reflog_entry_byindex(reflog, max - i - 1); + entry = git_reflog_entry_byindex(reflog, i); if (callback(i, git_reflog_entry_msg(entry), @@ -642,7 +642,7 @@ int git_stash_drop( goto cleanup; } - if ((error = git_reflog_drop(reflog, max - index - 1, true)) < 0) + if ((error = git_reflog_drop(reflog, index, true)) < 0) goto cleanup; if ((error = git_reflog_write(reflog)) < 0) diff --git a/tests-clar/refs/reflog/drop.c b/tests-clar/refs/reflog/drop.c index 4be857b42..512e8ba02 100644 --- a/tests-clar/refs/reflog/drop.c +++ b/tests-clar/refs/reflog/drop.c @@ -49,14 +49,16 @@ void test_refs_reflog_drop__can_drop_an_entry_and_rewrite_the_log_history(void) cl_assert(entrycount > 4); - before_current = git_reflog_entry_byindex(g_reflog, 2); + before_current = git_reflog_entry_byindex(g_reflog, 1); + git_oid_cpy(&before_current_old_oid, &before_current->oid_old); git_oid_cpy(&before_current_cur_oid, &before_current->oid_cur); - cl_git_pass(git_reflog_drop(g_reflog, 2, 1)); + cl_git_pass(git_reflog_drop(g_reflog, 1, 1)); + cl_assert_equal_i(entrycount - 1, git_reflog_entrycount(g_reflog)); - after_current = git_reflog_entry_byindex(g_reflog, 2); + after_current = git_reflog_entry_byindex(g_reflog, 0); cl_assert_equal_i(0, git_oid_cmp(&before_current_old_oid, &after_current->oid_old)); cl_assert(0 != git_oid_cmp(&before_current_cur_oid, &after_current->oid_cur)); @@ -68,10 +70,10 @@ void test_refs_reflog_drop__can_drop_the_oldest_entry(void) cl_assert(entrycount > 2); - cl_git_pass(git_reflog_drop(g_reflog, 0, 0)); + cl_git_pass(git_reflog_drop(g_reflog, entrycount - 1, 0)); cl_assert_equal_i(entrycount - 1, git_reflog_entrycount(g_reflog)); - entry = git_reflog_entry_byindex(g_reflog, 0); + entry = git_reflog_entry_byindex(g_reflog, entrycount - 2); cl_assert(git_oid_streq(&entry->oid_old, GIT_OID_HEX_ZERO) != 0); } @@ -81,10 +83,10 @@ void test_refs_reflog_drop__can_drop_the_oldest_entry_and_rewrite_the_log_histor cl_assert(entrycount > 2); - cl_git_pass(git_reflog_drop(g_reflog, 0, 1)); + cl_git_pass(git_reflog_drop(g_reflog, entrycount - 1, 1)); cl_assert_equal_i(entrycount - 1, git_reflog_entrycount(g_reflog)); - entry = git_reflog_entry_byindex(g_reflog, 0); + entry = git_reflog_entry_byindex(g_reflog, entrycount - 2); cl_assert(git_oid_streq(&entry->oid_old, GIT_OID_HEX_ZERO) == 0); } @@ -93,8 +95,8 @@ void test_refs_reflog_drop__can_drop_all_the_entries(void) cl_assert(--entrycount > 0); do { - cl_git_pass(git_reflog_drop(g_reflog, --entrycount, 1)); - } while (entrycount > 0); + cl_git_pass(git_reflog_drop(g_reflog, 0, 1)); + } while (--entrycount > 0); cl_git_pass(git_reflog_drop(g_reflog, 0, 1)); @@ -108,7 +110,7 @@ void test_refs_reflog_drop__can_persist_deletion_on_disk(void) cl_assert(entrycount > 2); cl_git_pass(git_reference_lookup(&ref, g_repo, g_reflog->ref_name)); - cl_git_pass(git_reflog_drop(g_reflog, entrycount - 1, 1)); + cl_git_pass(git_reflog_drop(g_reflog, 0, 1)); cl_assert_equal_i(entrycount - 1, git_reflog_entrycount(g_reflog)); cl_git_pass(git_reflog_write(g_reflog)); diff --git a/tests-clar/refs/reflog/reflog.c b/tests-clar/refs/reflog/reflog.c index 20f08f523..09b935692 100644 --- a/tests-clar/refs/reflog/reflog.c +++ b/tests-clar/refs/reflog/reflog.c @@ -68,13 +68,13 @@ void test_refs_reflog_reflog__append_then_read(void) cl_git_pass(git_reflog_read(&reflog, lookedup_ref)); cl_assert_equal_i(2, git_reflog_entrycount(reflog)); - entry = git_reflog_entry_byindex(reflog, 0); + entry = git_reflog_entry_byindex(reflog, 1); assert_signature(committer, entry->committer); cl_assert(git_oid_streq(&entry->oid_old, GIT_OID_HEX_ZERO) == 0); cl_assert(git_oid_cmp(&oid, &entry->oid_cur) == 0); cl_assert(entry->msg == NULL); - entry = git_reflog_entry_byindex(reflog, 1); + entry = git_reflog_entry_byindex(reflog, 0); assert_signature(committer, entry->committer); cl_assert(git_oid_cmp(&oid, &entry->oid_old) == 0); cl_assert(git_oid_cmp(&oid, &entry->oid_cur) == 0); diff --git a/tests-clar/stash/drop.c b/tests-clar/stash/drop.c index 39139ccae..b4f73b995 100644 --- a/tests-clar/stash/drop.c +++ b/tests-clar/stash/drop.c @@ -99,7 +99,7 @@ void test_stash_drop__dropping_an_entry_rewrites_reflog_history(void) cl_git_pass(git_stash_drop(repo, 1)); cl_git_pass(git_reflog_read(&reflog, stash)); - entry = git_reflog_entry_byindex(reflog, 1); + entry = git_reflog_entry_byindex(reflog, 0); cl_assert_equal_i(0, git_oid_cmp(&oid, git_reflog_entry_oidold(entry))); cl_assert_equal_i(count - 1, git_reflog_entrycount(reflog));